blob: 553e4ae49cafcc30ae6796e23cc840387b3ec382 [file] [log] [blame]
Lorenz Brun52f7f292020-06-24 16:42:02 +02001// Copyright 2020 The Monogon Project Authors.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17package main
18
19import (
20 "context"
Serge Bazanski686444e2020-12-21 14:21:14 +010021 "fmt"
22 "io"
Lorenz Brun52f7f292020-06-24 16:42:02 +020023 "log"
24 "os"
25 "os/signal"
26 "syscall"
27 "time"
28
29 grpcretry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
30 "google.golang.org/grpc"
31
Serge Bazanski77cb6c52020-12-19 00:09:22 +010032 common "git.monogon.dev/source/nexantic.git/metropolis/node"
Serge Bazanski549b72b2021-01-07 14:54:19 +010033 "git.monogon.dev/source/nexantic.git/metropolis/pkg/logbuffer"
Serge Bazanski77cb6c52020-12-19 00:09:22 +010034 apb "git.monogon.dev/source/nexantic.git/metropolis/proto/api"
35 "git.monogon.dev/source/nexantic.git/metropolis/test/launch"
Lorenz Brun52f7f292020-06-24 16:42:02 +020036)
37
Serge Bazanski686444e2020-12-21 14:21:14 +010038// prefixedStdout is a os.Stdout proxy that prefixes every line with a constant
39// prefix. This is used to show logs from two Metropolis nodes without getting
40// them confused.
41// TODO(q3k): move to logging API instead of relying on qemu stdout, and remove
42// this function.
43func prefixedStdout(prefix string) io.ReadWriter {
44 lb := logbuffer.NewLineBuffer(2048, func(l *logbuffer.Line) {
45 fmt.Fprintf(os.Stdout, "%s%s\n", prefix, l.Data)
46 })
47 // Make a ReaderWriter from LineBuffer (a Reader), by combining into an
48 // anonymous struct with a io.MultiReader() (which will always return EOF
49 // on every Read if given no underlying readers).
50 return struct {
51 io.Reader
52 io.Writer
53 }{
54 Reader: io.MultiReader(),
55 Writer: lb,
56 }
57}
58
Lorenz Brun52f7f292020-06-24 16:42:02 +020059func main() {
60 sigs := make(chan os.Signal, 1)
61 signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
62 ctx, cancel := context.WithCancel(context.Background())
63 go func() {
64 <-sigs
65 cancel()
66 }()
67 sw0, vm0, err := launch.NewSocketPair()
68 if err != nil {
69 log.Fatalf("Failed to create network pipe: %v\n", err)
70 }
71 sw1, vm1, err := launch.NewSocketPair()
72 if err != nil {
73 log.Fatalf("Failed to create network pipe: %v\n", err)
74 }
75
76 go func() {
Serge Bazanski686444e2020-12-21 14:21:14 +010077 if err := launch.Launch(ctx, launch.Options{
78 ConnectToSocket: vm0,
79 SerialPort: prefixedStdout("1| "),
80 }); err != nil {
Lorenz Brun52f7f292020-06-24 16:42:02 +020081 log.Fatalf("Failed to launch vm0: %v", err)
82 }
83 }()
84 nanoswitchPortMap := make(launch.PortMap)
85 identityPorts := []uint16{
86 common.ExternalServicePort,
87 common.DebugServicePort,
88 common.KubernetesAPIPort,
89 }
90 for _, port := range identityPorts {
91 nanoswitchPortMap[port] = port
92 }
93 go func() {
94 opts := []grpcretry.CallOption{
95 grpcretry.WithBackoff(grpcretry.BackoffExponential(100 * time.Millisecond)),
96 }
Serge Bazanski57b43752020-07-13 19:17:48 +020097 conn, err := nanoswitchPortMap.DialGRPC(common.DebugServicePort, grpc.WithInsecure(),
Lorenz Brun52f7f292020-06-24 16:42:02 +020098 grpc.WithUnaryInterceptor(grpcretry.UnaryClientInterceptor(opts...)))
99 if err != nil {
100 panic(err)
101 }
102 defer conn.Close()
Serge Bazanski57b43752020-07-13 19:17:48 +0200103 debug := apb.NewNodeDebugServiceClient(conn)
104 res, err := debug.GetGoldenTicket(ctx, &apb.GetGoldenTicketRequest{
105 // HACK: this is assigned by DHCP, and we assume that everything goes well.
106 ExternalIp: "10.1.0.3",
107 }, grpcretry.WithMax(10))
108 if err != nil {
109 log.Fatalf("Failed to get golden ticket: %v", err)
110 }
111
112 ec := &apb.EnrolmentConfig{
113 GoldenTicket: res.Ticket,
114 }
115
Serge Bazanski686444e2020-12-21 14:21:14 +0100116 if err := launch.Launch(ctx, launch.Options{
117 ConnectToSocket: vm1,
118 EnrolmentConfig: ec,
119 SerialPort: prefixedStdout("2| "),
120 }); err != nil {
Serge Bazanski57b43752020-07-13 19:17:48 +0200121 log.Fatalf("Failed to launch vm1: %v", err)
122 }
Lorenz Brun52f7f292020-06-24 16:42:02 +0200123 }()
124 if err := launch.RunMicroVM(ctx, &launch.MicroVMOptions{
125 SerialPort: os.Stdout,
Serge Bazanski77cb6c52020-12-19 00:09:22 +0100126 KernelPath: "metropolis/test/ktest/linux-testing.elf",
127 InitramfsPath: "metropolis/test/nanoswitch/initramfs.lz4",
Lorenz Brun52f7f292020-06-24 16:42:02 +0200128 ExtraNetworkInterfaces: []*os.File{sw0, sw1},
129 PortMap: nanoswitchPortMap,
130 }); err != nil {
131 log.Fatalf("Failed to launch nanoswitch: %v", err)
132 }
133}