diff --git a/mantle/cmd/kola/devshell.go b/mantle/cmd/kola/devshell.go index 665cc64c97..72e9054ab9 100644 --- a/mantle/cmd/kola/devshell.go +++ b/mantle/cmd/kola/devshell.go @@ -113,32 +113,13 @@ func runDevShellSSH(builder *platform.QemuBuilder, conf *v3types.Config) error { } sshPubKey := v3types.SSHAuthorizedKey(strings.TrimSpace(string(sshPubKeyBuf))) - readinessSignalChan := "coreos.devshellready" - signalReadyUnit := fmt.Sprintf(`[Unit] -Requires=dev-virtio\\x2dports-%s.device -OnFailure=emergency.target -OnFailureJobMode=isolate -After=systemd-user-sessions.service -After=sshd.service -[Service] -Type=oneshot -RemainAfterExit=yes -ExecStart=/bin/echo ready -StandardOutput=file:/dev/virtio-ports/%[1]s -[Install] -RequiredBy=multi-user.target`, readinessSignalChan) - signalPoweroffUnit := fmt.Sprintf(`[Unit] -Requires=dev-virtio\\x2dports-%s.device -OnFailure=emergency.target -OnFailureJobMode=isolate -Conflicts=reboot.target -[Service] -Type=oneshot -RemainAfterExit=yes -ExecStop=/bin/echo poweroff -StandardOutput=file:/dev/virtio-ports/%[1]s -[Install] -WantedBy=multi-user.target`, readinessSignalChan) + // Await sshd startup + journalConf, journalPipe, err := builder.VirtioJournal("-u sshd MESSAGE_ID=7d4958e842da4a758f6c1cdc7b36dcc5") + if err != nil { + return err + } + confm := v3.Merge(*conf, *journalConf) + conf = &confm devshellConfig := v3types.Config{ Ignition: v3types.Ignition{ @@ -154,29 +135,11 @@ WantedBy=multi-user.target`, readinessSignalChan) }, }, }, - Systemd: v3types.Systemd{ - Units: []v3types.Unit{ - { - Name: "coreos-devshell-signal-ready.service", - Contents: &signalReadyUnit, - Enabled: util.BoolToPtr(true), - }, - { - Name: "coreos-devshell-signal-poweroff.service", - Contents: &signalPoweroffUnit, - Enabled: util.BoolToPtr(true), - }, - }, - }, } - confm := v3.Merge(*conf, devshellConfig) + confm = v3.Merge(*conf, devshellConfig) conf = &confm - readyChan, err := builder.VirtioChannelRead(readinessSignalChan) - if err != nil { - return err - } - readyReader := bufio.NewReader(readyChan) + readyReader := bufio.NewReader(journalPipe) builder.SetConfig(*conf, kola.Options.IgnitionVersion == "v2") @@ -230,8 +193,8 @@ WantedBy=multi-user.target`, readinessSignalChan) if err != nil { errchan <- err } - if readyMsg != "ready" { - errchan <- fmt.Errorf("Unexpected ready message: %s", readyMsg) + if !strings.Contains(readyMsg, "Starting OpenSSH server daemon") { + errchan <- fmt.Errorf("Unexpected journal message: %s", readyMsg) } var s struct{} readychan <- s @@ -263,7 +226,7 @@ loop: // Caught SIGINT, we're done return fmt.Errorf("Caught SIGINT before successful login") case _ = <-readychan: - fmt.Printf("\033[2K\rvirtio: connected\n") + fmt.Printf("\033[2K\rvirtio journal connected - sshd started\n") break loop } } diff --git a/mantle/platform/qemu.go b/mantle/platform/qemu.go index 5c03306262..fdad5bc2a5 100644 --- a/mantle/platform/qemu.go +++ b/mantle/platform/qemu.go @@ -900,6 +900,43 @@ func (builder *QemuBuilder) SerialPipe() (*os.File, error) { return r, nil } +// VirtioJournal configures the OS and VM to stream the systemd journal +// (post-switchroot) over a virtio-serial channel. The first return value +// is an Ignition fragment that should be included in the target config, +// and the file stream will be newline-separated JSON. The optional +// queryArguments filters the stream - see `man journalctl` for more information. +func (builder *QemuBuilder) VirtioJournal(queryArguments string) (*v3types.Config, *os.File, error) { + stream, err := builder.VirtioChannelRead("mantlejournal") + if err != nil { + return nil, nil, err + } + var streamJournalUnit = fmt.Sprintf(`[Unit] + Requires=dev-virtio\\x2dports-mantlejournal.device + [Service] + Type=simple + StandardOutput=file:/dev/virtio-ports/mantlejournal + ExecStart=/usr/bin/journalctl -q -b -f -o json --no-tail %s + [Install] + RequiredBy=multi-user.target + `, queryArguments) + + conf := v3types.Config{ + Ignition: v3types.Ignition{ + Version: "3.0.0", + }, + Systemd: v3types.Systemd{ + Units: []v3types.Unit{ + { + Name: "mantle-virtio-journal-stream.service", + Contents: &streamJournalUnit, + Enabled: util.BoolToPtr(true), + }, + }, + }, + } + return &conf, stream, nil +} + func (builder *QemuBuilder) Exec() (*QemuInstance, error) { builder.finalize() var err error