diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index f9672558bf..1f0a3c2027 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -431,6 +431,7 @@ qemuCapsInitGuest(virCapsPtr caps, int nmachines = 0; struct stat st; unsigned int ncpus; + unsigned long long qemuCmdFlags; int ret = -1; /* Check for existance of base emulator, or alternate base @@ -546,6 +547,11 @@ qemuCapsInitGuest(virCapsPtr caps, !virCapabilitiesAddGuestFeature(guest, "cpuselection", 1, 0)) goto error; + if (qemuCapsExtractVersionInfo(binary, NULL, &qemuCmdFlags) < 0 || + ((qemuCmdFlags & QEMUD_CMD_FLAG_BOOTINDEX) && + !virCapabilitiesAddGuestFeature(guest, "deviceboot", 1, 0))) + goto error; + if (hvm) { if (virCapabilitiesAddGuestDomain(guest, "qemu", @@ -1047,6 +1053,7 @@ qemuCapsExtractDeviceStr(const char *qemu, * '-device ?'. */ cmd = virCommandNewArgList(qemu, "-device", "pci-assign,?", + "-device", "virtio-blk-pci,?", NULL); virCommandAddEnvPassCommon(cmd); /* qemu -help goes to stdout, but qemu -device ? goes to stderr. */ @@ -1070,6 +1077,8 @@ qemuCapsParseDeviceStr(const char *str, unsigned long long *flags) { if (strstr(str, "pci-assign.configfd")) *flags |= QEMUD_CMD_FLAG_PCI_CONFIGFD; + if (strstr(str, "virtio-blk-pci.bootindex")) + *flags |= QEMUD_CMD_FLAG_BOOTINDEX; return 0; } diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 8057479f2d..e9e2da0d42 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -83,6 +83,7 @@ enum qemuCapsFlags { QEMUD_CMD_FLAG_SPICE = (1LL << 46), /* Is -spice avail */ QEMUD_CMD_FLAG_VGA_NONE = (1LL << 47), /* The 'none' arg for '-vga' */ QEMUD_CMD_FLAG_MIGRATE_QEMU_FD = (1LL << 48), /* -incoming fd:n */ + QEMUD_CMD_FLAG_BOOTINDEX = (1LL << 49), /* -device bootindex property */ }; virCapsPtr qemuCapsInit(virCapsPtr old_caps); diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index fff1f74400..d36a30a7c2 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1342,7 +1342,8 @@ error: char * -qemuBuildDriveDevStr(virDomainDiskDefPtr disk) +qemuBuildDriveDevStr(virDomainDiskDefPtr disk, + unsigned long long qemuCmdFlags) { virBuffer opt = VIR_BUFFER_INITIALIZER; const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus); @@ -1382,6 +1383,8 @@ qemuBuildDriveDevStr(virDomainDiskDefPtr disk) } virBufferVSprintf(&opt, ",drive=%s%s", QEMU_DRIVE_HOST_PREFIX, disk->info.alias); virBufferVSprintf(&opt, ",id=%s", disk->info.alias); + if (disk->bootIndex && (qemuCmdFlags & QEMUD_CMD_FLAG_BOOTINDEX)) + virBufferVSprintf(&opt, ",bootindex=%d", disk->bootIndex); if (virBufferError(&opt)) { virReportOOMError(); @@ -1538,7 +1541,9 @@ qemuBuildNicStr(virDomainNetDefPtr net, char * -qemuBuildNicDevStr(virDomainNetDefPtr net, int vlan) +qemuBuildNicDevStr(virDomainNetDefPtr net, + int vlan, + unsigned long long qemuCmdFlags) { virBuffer buf = VIR_BUFFER_INITIALIZER; const char *nic; @@ -1563,6 +1568,8 @@ qemuBuildNicDevStr(virDomainNetDefPtr net, int vlan) net->mac[4], net->mac[5]); if (qemuBuildDeviceAddressStr(&buf, &net->info) < 0) goto error; + if (net->bootIndex && (qemuCmdFlags & QEMUD_CMD_FLAG_BOOTINDEX)) + virBufferVSprintf(&buf, ",bootindex=%d", net->bootIndex); if (virBufferError(&buf)) { virReportOOMError(); @@ -3125,10 +3132,19 @@ qemuBuildCommandLine(virConnectPtr conn, disk->info.addr.drive.unit ? 'B' : 'A', disk->info.alias); + + if (disk->bootIndex && + (qemuCmdFlags & QEMUD_CMD_FLAG_BOOTINDEX)) { + virCommandAddArg(cmd, "-global"); + virCommandAddArgFormat(cmd, "isa-fdc.bootindex%c=%d", + disk->info.addr.drive.unit + ? 'B' : 'A', + disk->bootIndex); + } } else { virCommandAddArg(cmd, "-device"); - if (!(optstr = qemuBuildDriveDevStr(disk))) + if (!(optstr = qemuBuildDriveDevStr(disk, qemuCmdFlags))) goto error; virCommandAddArg(cmd, optstr); VIR_FREE(optstr); @@ -3352,7 +3368,7 @@ qemuBuildCommandLine(virConnectPtr conn, } if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { virCommandAddArg(cmd, "-device"); - if (!(nic = qemuBuildNicDevStr(net, vlan))) + if (!(nic = qemuBuildNicDevStr(net, vlan, qemuCmdFlags))) goto error; virCommandAddArg(cmd, nic); VIR_FREE(nic); diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 5b24539035..9c07aca496 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -62,7 +62,8 @@ char * qemuBuildNicStr(virDomainNetDefPtr net, /* Current, best practice */ char * qemuBuildNicDevStr(virDomainNetDefPtr net, - int vlan); + int vlan, + unsigned long long qemuCmdFlags); char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk, unsigned long long qemuCmdFlags); @@ -75,7 +76,8 @@ char *qemuBuildFSStr(virDomainFSDefPtr fs, unsigned long long qemuCmdFlags); /* Current, best practice */ -char * qemuBuildDriveDevStr(virDomainDiskDefPtr disk); +char * qemuBuildDriveDevStr(virDomainDiskDefPtr disk, + unsigned long long qemuCmdFlags); char * qemuBuildFSDevStr(virDomainFSDefPtr fs); /* Current, best practice */ char * qemuBuildControllerDevStr(virDomainControllerDefPtr def); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 395f72f236..2beb268264 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6050,6 +6050,7 @@ static char *qemuDomainXMLToNative(virConnectPtr conn, */ for (i = 0 ; i < def->nnets ; i++) { virDomainNetDefPtr net = def->nets[i]; + int bootIndex = net->bootIndex; if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK || net->type == VIR_DOMAIN_NET_TYPE_DIRECT) { VIR_FREE(net->data.network.name); @@ -6072,6 +6073,7 @@ static char *qemuDomainXMLToNative(virConnectPtr conn, net->data.ethernet.script = script; net->data.ethernet.ipaddr = ipaddr; } + net->bootIndex = bootIndex; } for (i = 0 ; i < def->ngraphics ; i++) { if (def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index b4088acb6d..a4227dd5af 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -169,7 +169,7 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver, if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags))) goto error; - if (!(devstr = qemuBuildDriveDevStr(disk))) + if (!(devstr = qemuBuildDriveDevStr(disk, qemuCmdFlags))) goto error; } @@ -380,7 +380,7 @@ int qemuDomainAttachSCSIDisk(struct qemud_driver *driver, if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { if (qemuAssignDeviceDiskAlias(disk, qemuCmdFlags) < 0) goto error; - if (!(devstr = qemuBuildDriveDevStr(disk))) + if (!(devstr = qemuBuildDriveDevStr(disk, qemuCmdFlags))) goto error; } @@ -493,7 +493,7 @@ int qemuDomainAttachUsbMassstorageDevice(struct qemud_driver *driver, goto error; if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags))) goto error; - if (!(devstr = qemuBuildDriveDevStr(disk))) + if (!(devstr = qemuBuildDriveDevStr(disk, qemuCmdFlags))) goto error; } @@ -675,7 +675,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, } if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { - if (!(nicstr = qemuBuildNicDevStr(net, vlan))) + if (!(nicstr = qemuBuildNicDevStr(net, vlan, qemuCmdFlags))) goto try_remove; } else { if (!(nicstr = qemuBuildNicStr(net, NULL, vlan)))