From 1da0d51c531295f304aaf741f67029a2e4938214 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 19 Mar 2020 21:48:20 +0000 Subject: [PATCH] Support `cosa run --kargs` For the use case of enabling systemd debugging, etc. https://github.com/coreos/coreos-assembler/pull/1263#issuecomment-601419408 --- mantle/cmd/kola/qemuexec.go | 3 +++ mantle/platform/qemu.go | 41 ++++++++++++++++++++++++++++++++----- src/cmd-run | 8 ++++++++ 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/mantle/cmd/kola/qemuexec.go b/mantle/cmd/kola/qemuexec.go index dcbe47dcdb..d09fbce383 100644 --- a/mantle/cmd/kola/qemuexec.go +++ b/mantle/cmd/kola/qemuexec.go @@ -39,6 +39,7 @@ var ( hostname string ignition string + kargs string knetargs string forceConfigInjection bool @@ -47,6 +48,7 @@ var ( func init() { root.AddCommand(cmdQemuExec) cmdQemuExec.Flags().StringVarP(&knetargs, "knetargs", "", "", "Arguments for Ignition networking on kernel commandline") + cmdQemuExec.Flags().StringVarP(&kargs, "kargs", "", "", "Additional kernel arguments applied (ephemerally) to the first boot") cmdQemuExec.Flags().BoolVarP(&usernet, "usernet", "U", false, "Enable usermode networking") cmdQemuExec.Flags().StringVarP(&hostname, "hostname", "", "", "Set hostname via DHCP") cmdQemuExec.Flags().IntVarP(&memory, "memory", "m", 0, "Memory in MB") @@ -61,6 +63,7 @@ func runQemuExec(cmd *cobra.Command, args []string) error { if len(knetargs) > 0 { builder.IgnitionNetworkKargs = knetargs } + builder.EphemeralKernelArguments = kargs defer builder.Close() builder.Firmware = kola.QEMUOptions.Firmware if kola.QEMUOptions.DiskImage != "" { diff --git a/mantle/platform/qemu.go b/mantle/platform/qemu.go index 5a59fc08ed..aa566643ff 100644 --- a/mantle/platform/qemu.go +++ b/mantle/platform/qemu.go @@ -149,6 +149,9 @@ type QemuBuilder struct { Pdeathsig bool Argv []string + // EphemeralKernelArguments are appended to the bootloader config + EphemeralKernelArguments string + // IgnitionNetworkKargs are written to /boot/ignition IgnitionNetworkKargs string @@ -356,9 +359,8 @@ func (gf *coreosGuestfish) destroy() { } } -// setupIgnition copies the ignition file inside the disk image and/or sets -// networking kernel arguments -func setupIgnition(confPath string, knetargs string, diskImagePath string, diskSectorSize int) error { +// setupPreboot performs changes necessary before the disk is booted +func setupPreboot(confPath, knetargs, kargs string, diskImagePath string, diskSectorSize int) error { gf, err := newGuestfish(diskImagePath, diskSectorSize) if err != nil { return err @@ -383,6 +385,34 @@ func setupIgnition(confPath string, knetargs string, diskImagePath string, diskS } } + if kargs != "" { + confpathout, err := exec.Command("guestfish", gf.remote, "glob-expand", "/loader/entries/ostree*conf").Output() + if err != nil { + return errors.Wrapf(err, "finding bootloader config path") + } + confs := strings.Split(strings.TrimSpace(string(confpathout)), "\n") + if len(confs) != 1 { + return fmt.Errorf("Multiple values for bootloader config: %v", confpathout) + } + confpath := confs[0] + + origconf, err := exec.Command("guestfish", gf.remote, "read-file", confpath).Output() + if err != nil { + return errors.Wrapf(err, "reading bootloader config") + } + var buf strings.Builder + for _, line := range strings.Split(string(origconf), "\n") { + if strings.HasPrefix(line, "options ") { + line += " " + kargs + } + buf.Write([]byte(line)) + buf.Write([]byte("\n")) + } + if err := exec.Command("guestfish", gf.remote, "write", confpath, buf.String()).Run(); err != nil { + return errors.Wrapf(err, "writing bootloader config") + } + } + if err := exec.Command("guestfish", gf.remote, "umount-all").Run(); err != nil { return errors.Wrapf(err, "guestfish umount failed") } @@ -443,8 +473,9 @@ func (builder *QemuBuilder) addDiskImpl(disk *Disk, primary bool) error { // If the board doesn't support -fw_cfg or we were explicitly // requested, inject via libguestfs on the primary disk. requiresInjection := builder.Config != "" && (builder.ForceConfigInjection || !builder.supportsFwCfg()) - if requiresInjection || builder.IgnitionNetworkKargs != "" { - if err = setupIgnition(builder.Config, builder.IgnitionNetworkKargs, dstFileName, disk.SectorSize); err != nil { + if requiresInjection || builder.IgnitionNetworkKargs != "" || builder.EphemeralKernelArguments != "" { + if err = setupPreboot(builder.Config, builder.IgnitionNetworkKargs, builder.EphemeralKernelArguments, + dstFileName, disk.SectorSize); err != nil { return errors.Wrapf(err, "ignition injection with guestfs failed") } } diff --git a/src/cmd-run b/src/cmd-run index 6f4b261d5d..7716a1a914 100755 --- a/src/cmd-run +++ b/src/cmd-run @@ -17,6 +17,7 @@ BUILDID=latest IMAGE_TYPE=qemu HOSTNAME= VM_DISK= +KARGS= DISK_CHANNEL=virtio VM_MEMORY=2048 VM_NCPUS="${VM_NCPUS:-${QEMU_PROCS}}" @@ -36,6 +37,7 @@ Options: --size GB Disk size in GB (matches base by default) --user USERNAME Create user USERNAME via Ignition (if not already extant) and log in as that user -h this ;-) + --kargs Append kernel arguments to first boot (ephemeral) --uefi Boot using uefi (x86_64 only, implied on arm) --uefi-secure Boot using uefi with secure boot enabled (x86_64/arm only) @@ -91,6 +93,9 @@ while [ $# -ge 1 ]; do --uefi-secure) FIRMWARE=uefi-secure shift ;; + --kargs) + KARGS="$2" + shift 2;; -h|--help) echo "$USAGE" exit ;; @@ -275,6 +280,9 @@ esac if [ -n "${HOSTNAME}" ]; then kola_args+=("--hostname=${HOSTNAME}") fi +if [ -n "${KARGS}" ]; then + kola_args+=("--kargs=${KARGS}") +fi # for the metal images, there's no other way but to inject into /boot case "${IMAGE_TYPE}" in