Skip to content

Commit

Permalink
qemu: differentiate blk devices when switching boot order
Browse files Browse the repository at this point in the history
With coreos#1714 landing, needed a better way to differentiate blk devices as the cdrom is also a pci
device in aarch64. Used the `query-block` qmp query to detect blk devices and identify them that way.
  • Loading branch information
Prashanth684 authored and openshift-merge-robot committed Sep 17, 2020
1 parent b1b6463 commit db85a3c
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 28 deletions.
9 changes: 2 additions & 7 deletions mantle/platform/metal.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
41 changes: 29 additions & 12 deletions mantle/platform/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -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<virtio-net-pci>", "child<virtio-blk-pci>", "child<virtio-net-ccw>":
case "child<virtio-net-pci>", "child<virtio-net-ccw>":
bootdev = filepath.Join("/machine/peripheral-anon", dev.Name)
default:
break
case "child<virtio-blk-device>", "child<virtio-blk-ccw>":
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 {
Expand Down Expand Up @@ -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 != "" {
Expand Down
34 changes: 25 additions & 9 deletions mantle/platform/qmp_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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
Expand Down

0 comments on commit db85a3c

Please sign in to comment.