metropolis/cli/metroctl: implement install ssh
This implements another way of installing metropolis via ssh. It does
this by uploading the files to the target machine and then doing a kexec
into the install environment. If it fails at any point it will print the
error and reboot.
Change-Id: I1ac6538896709c386b053a84903fa04940c1f012
Reviewed-on: https://review.monogon.dev/c/monogon/+/2079
Tested-by: Jenkins CI
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/metropolis/cli/takeover/boot.go b/metropolis/cli/takeover/boot.go
new file mode 100644
index 0000000..eb71694
--- /dev/null
+++ b/metropolis/cli/takeover/boot.go
@@ -0,0 +1,47 @@
+package main
+
+import (
+ "context"
+ "os"
+ "path/filepath"
+ "time"
+
+ "golang.org/x/sys/unix"
+
+ "source.monogon.dev/metropolis/node/core/devmgr"
+ "source.monogon.dev/osbase/supervisor"
+)
+
+// Main runnable for the installer.
+func takeoverRunnable(ctx context.Context) error {
+ l := supervisor.Logger(ctx)
+
+ devmgrSvc := devmgr.New()
+ supervisor.Run(ctx, "devmgr", devmgrSvc.Run)
+ supervisor.Signal(ctx, supervisor.SignalHealthy)
+
+ for {
+ devicePath := filepath.Join("/dev", os.Getenv(EnvInstallTarget))
+ l.Infof("Waiting for device: %s", devicePath)
+ _, err := os.Stat(devicePath)
+ if os.IsNotExist(err) {
+ time.Sleep(1 * time.Second)
+ continue
+ } else if err != nil {
+ return err
+ }
+ break
+ }
+
+ if err := installMetropolis(l); err != nil {
+ l.Errorf("Installation failed: %v", err)
+ } else {
+ l.Info("Installation succeeded")
+ }
+
+ time.Sleep(1 * time.Second)
+ unix.Sync()
+ unix.Reboot(unix.LINUX_REBOOT_CMD_RESTART)
+
+ return nil
+}