Skip to content

Commit

Permalink
Add qemu API to stream journal, use it in devshell
Browse files Browse the repository at this point in the history
This came up in coreos/ignition-dracut#146
and since then we've been doing more "ad hoc unit writing to virtio"
in mantle, but let's add a general API that streams the journal.

This is just better for what devshell wants - we can more precisely
watch for sshd starting.  And more code in e.g. `testiso.go` could
use it too which can come later.

The immediate motivation here is I may add another kola test
which could use this.
  • Loading branch information
cgwalters committed Apr 29, 2020
1 parent e89b75d commit c102739
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 49 deletions.
61 changes: 12 additions & 49 deletions mantle/cmd/kola/devshell.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand All @@ -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")

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
}
Expand Down
37 changes: 37 additions & 0 deletions mantle/platform/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit c102739

Please sign in to comment.