From 419fe88d38145973ef9aa387e877be402c5e7e28 Mon Sep 17 00:00:00 2001
From: xengineering <me@xengineering.eu>
Date: Sun, 28 Jul 2024 13:18:23 +0200
Subject: Wait for VM to boot

This waits for a little delay and then tries to run `true` via SSH on
the virtual machine. If this does not work for a maximum amount of
attempts a fatal error is raised and an appropriate log message is
written.
---
 main.go | 48 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 44 insertions(+), 4 deletions(-)

diff --git a/main.go b/main.go
index da2284d..df9857c 100644
--- a/main.go
+++ b/main.go
@@ -9,17 +9,20 @@ import (
 	"os/exec"
 	"path/filepath"
 	"strings"
+	"time"
 )
 
 var (
-	repo = ""
+	key    = ""
+	repo   = ""
 	commit = ""
-	task = ""
-	image = ""
-	port = ""
+	task   = ""
+	image  = ""
+	port   = ""
 )
 
 func init() {
+	flag.StringVar(&key, "key", "", "Path to SSH private key")
 	flag.StringVar(&repo, "repo", "", "Source code as valid Git URL")
 	flag.StringVar(&commit, "commit", "", "Commit or commit-ish reference for checkout")
 	flag.StringVar(&task, "task", "", "Shell code to execute for the build")
@@ -47,6 +50,8 @@ func main() {
 		}
 	}()
 
+	waitBoot()
+
 	workbench := prepareWorkbench(repo, commit)
 	defer os.RemoveAll(workbench)
 	craft(workbench)
@@ -88,6 +93,41 @@ func qemu() *exec.Cmd {
 	)
 }
 
+func sshCommand(name string, arg ...string) *exec.Cmd {
+	return exec.Command(
+		"ssh",
+		append([]string{
+			"-p",
+			port,
+			"-o",
+			"UserKnownHostsFile=/dev/null",
+			"-o",
+			"StrictHostKeyChecking=no",
+			"-i",
+			key,
+			"root@localhost",
+			name,
+		}, arg...)...,
+	)
+}
+
+func waitBoot() {
+	retries := 5
+	initialDelay := 1 * time.Second
+
+	log.Println("Waiting for VM to boot")
+	time.Sleep(initialDelay) // without that `ssh` returns too quickly
+	for range retries {
+		cmd := sshCommand("true")
+		err := cmd.Run()
+		if err == nil {
+			log.Println("VM booted")
+			return
+		}
+	}
+	log.Fatalf("Could not reach VM %d times - giving up", retries)
+}
+
 func craft(workbench string) {
 	script := fmt.Sprintf(`#!/bin/sh
 
-- 
cgit v1.2.3-70-g09d2