diff --git a/mantle/platform/metal.go b/mantle/platform/metal.go index 6acf1a0a71..b6e7e5a45f 100644 --- a/mantle/platform/metal.go +++ b/mantle/platform/metal.go @@ -36,6 +36,8 @@ const ( // defaultQemuHostIPv4 is documented in `man qemu-kvm`, under the `-netdev` option defaultQemuHostIPv4 = "10.0.2.2" + targetDevice = "/dev/vda" + // rebootUnit is a copy of the system one without the ConditionPathExists rebootUnit = `[Unit] Description=Reboot after CoreOS Installer @@ -562,13 +564,6 @@ func (inst *Install) InstallViaISOEmbed(kargs []string, liveIgnition, targetIgni } pointerIgnitionPath := "/var/opt/pointer.ign" - targetDevice := "/dev/vda" - // For aarch64, the cdrom is a pci blk device /dev/vda - // TBD: use the serial identifier and use /dev/disk/by-id to install - if system.RpmArch() == "aarch64" { - targetDevice = "/dev/vdb" - } - installerUnit := fmt.Sprintf(` [Unit] After=network-online.target diff --git a/mantle/platform/qemu.go b/mantle/platform/qemu.go index 7c2c0fa263..31ed7354f6 100644 --- a/mantle/platform/qemu.go +++ b/mantle/platform/qemu.go @@ -245,31 +245,48 @@ func (inst *QemuInstance) SwitchBootOrder() error { //Not applicable for other arches return nil } - monitor, devs, err := listQMPDevices(inst.tempdir) - if monitor != nil { - defer monitor.Disconnect() + monitor, err := newQMPMonitor(inst.tempdir) + if err != nil { + return errors.Wrapf(err, "Could not connect to QMP device") + } + monitor.Connect() + defer monitor.Disconnect() + devs, err := listQMPDevices(monitor, inst.tempdir) + if err != nil { + return errors.Wrapf(err, "Could not list devices through qmp") } + blkdevs, err := listQMPBlkDevices(monitor, inst.tempdir) if err != nil { - return errors.Wrapf(err, "Could not list devices") + return errors.Wrapf(err, "Could not list blk devices through qmp") } + var blkdev string var bootdev string + // Get bootdevice for pxe boot for _, dev := range devs.Return { switch dev.Type { - // Boot device used for first boot - for aarch64 the cdrom is a pci blk device (used for ISO installs) - case "child", "child", "child": + case "child", "child": bootdev = filepath.Join("/machine/peripheral-anon", dev.Name) + default: break - case "child", "child": - blkdev = filepath.Join("/machine/peripheral-anon", dev.Name) - break + } + } + // Get boot device (for iso-installs) and block device + for _, dev := range blkdevs.Return { + devpath := filepath.Clean(strings.Trim(dev.DevicePath, "virtio-backend")) + switch dev.Device { + case "installiso": + bootdev = devpath + case "d1": + blkdev = devpath default: break } } - // unset bootindex for the network device + + // unset bootindex for the boot device if err := setBootIndexForDevice(monitor, bootdev, -1); err != nil { - return errors.Wrapf(err, "Could not set bootindex for netdev") + return errors.Wrapf(err, "Could not set bootindex for bootdev") } // set bootindex to 1 to boot from disk if err := setBootIndexForDevice(monitor, blkdev, 1); err != nil { @@ -1045,7 +1062,7 @@ func (builder *QemuBuilder) setupIso() error { // both UEFI and BIOS (`-boot once=d` OTOH doesn't work with OVMF). switch system.RpmArch() { case "s390x", "ppc64le", "aarch64": - builder.Append("-cdrom", builder.iso.path) + builder.Append("-drive", "file="+builder.iso.path+",id=installiso,index=2,media=cdrom") default: bootindexStr := "" if builder.iso.bootindex != "" { diff --git a/mantle/platform/qmp_util.go b/mantle/platform/qmp_util.go index ca90475da3..706ef98781 100644 --- a/mantle/platform/qmp_util.go +++ b/mantle/platform/qmp_util.go @@ -36,6 +36,13 @@ type QOMDev struct { } `json:"return"` } +type QOMBlkDev struct { + Return []struct { + Device string `json:"device"` + DevicePath string `json:"qdev"` + } `json:"return"` +} + // Create a new QMP socket connection func newQMPMonitor(sockaddr string) (*qmp.SocketMonitor, error) { qmpPath := filepath.Join(sockaddr, "qmp.sock") @@ -54,24 +61,33 @@ func newQMPMonitor(sockaddr string) (*qmp.SocketMonitor, error) { } // Executes a query which provides the list of devices and their names -func listQMPDevices(sockaddr string) (*qmp.SocketMonitor, *QOMDev, error) { - monitor, err := newQMPMonitor(sockaddr) +func listQMPDevices(monitor *qmp.SocketMonitor, sockaddr string) (*QOMDev, error) { + listcmd := []byte(`{ "execute": "qom-list", "arguments": { "path": "/machine/peripheral-anon" } }`) + out, err := monitor.Run(listcmd) if err != nil { - return nil, nil, errors.Wrapf(err, "Could not open monitor") + return nil, errors.Wrapf(err, "Running QMP list command") } - monitor.Connect() - listcmd := []byte(`{ "execute": "qom-list", "arguments": { "path": "/machine/peripheral-anon" } }`) + var devs QOMDev + if err = json.Unmarshal(out, &devs); err != nil { + return nil, errors.Wrapf(err, "De-serializing QMP output") + } + return &devs, nil +} + +// Executes a query which provides the list of block devices and their names +func listQMPBlkDevices(monitor *qmp.SocketMonitor, sockaddr string) (*QOMBlkDev, error) { + listcmd := []byte(`{ "execute": "query-block" }`) out, err := monitor.Run(listcmd) if err != nil { - return monitor, nil, errors.Wrapf(err, "Running QMP list command") + return nil, errors.Wrapf(err, "Running QMP list command") } - var devs QOMDev + var devs QOMBlkDev if err = json.Unmarshal(out, &devs); err != nil { - return monitor, nil, errors.Wrapf(err, "De-serializing QMP output") + return nil, errors.Wrapf(err, "De-serializing QMP output") } - return monitor, &devs, nil + return &devs, nil } // Set the bootindex for the particular device