[libvirt] [PATCH] qemu: Translate boot config into bootindex if possible

Jiri Denemark jdenemar at redhat.com
Mon Jun 6 13:32:57 UTC 2011


Prefer bootindex=N option for -device over the old way -boot ORDER
possibly accompanied with boot=on option for -drive. This gives us full
control over which device will actually be used for booting guest OS.
Moreover, if qemu doesn't support boot=on, this is the only way to boot
of certain disks in some configurations (such as virtio disks when used
together IDE disks) without transforming domain XML to use per device
boot elements.
---
 src/qemu/qemu_command.c                            |  141 +++++++++++++-------
 src/qemu/qemu_command.h                            |    4 +-
 src/qemu/qemu_hotplug.c                            |   14 +-
 .../qemuxml2argv-boot-complex-bootindex.args       |   30 ++++
 .../qemuxml2argv-boot-complex-bootindex.xml        |   65 +++++++++
 .../qemuxml2argv-boot-complex.args                 |   30 ++++
 .../qemuxml2argvdata/qemuxml2argv-boot-complex.xml |   65 +++++++++
 ...xml2argv-boot-menu-disable-drive-bootindex.args |   13 ++
 ...uxml2argv-boot-menu-disable-drive-bootindex.xml |   27 ++++
 .../qemuxml2argv-boot-menu-disable-drive.args      |   14 ++
 .../qemuxml2argv-boot-menu-disable-drive.xml       |   27 ++++
 .../qemuxml2argv-boot-menu-enable.args             |   14 ++
 .../qemuxml2argv-boot-menu-enable.xml              |   27 ++++
 .../qemuxml2argv-disk-drive-no-boot.args           |   18 +++
 .../qemuxml2argv-disk-drive-no-boot.xml            |   38 ++++++
 tests/qemuxml2argvtest.c                           |   17 +++
 16 files changed, 489 insertions(+), 55 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.xml
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-complex.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-complex.xml
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.xml
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.xml
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.xml
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.xml

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index ef2d002..277fa99 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1189,7 +1189,7 @@ qemuSafeSerialParamValue(const char *value)
 
 char *
 qemuBuildDriveStr(virDomainDiskDefPtr disk,
-                  int bootable,
+                  bool bootable,
                   virBitmapPtr qemuCaps)
 {
     virBuffer opt = VIR_BUFFER_INITIALIZER;
@@ -1343,6 +1343,7 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
         }
     }
     if (bootable &&
+        qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE_BOOT) &&
         disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
         disk->bus != VIR_DOMAIN_DISK_BUS_IDE)
         virBufferAddLit(&opt, ",boot=on");
@@ -1406,6 +1407,7 @@ error:
 
 char *
 qemuBuildDriveDevStr(virDomainDiskDefPtr disk,
+                     int bootindex,
                      virBitmapPtr qemuCaps)
 {
     virBuffer opt = VIR_BUFFER_INITIALIZER;
@@ -1446,8 +1448,8 @@ qemuBuildDriveDevStr(virDomainDiskDefPtr disk,
     }
     virBufferAsprintf(&opt, ",drive=%s%s", QEMU_DRIVE_HOST_PREFIX, disk->info.alias);
     virBufferAsprintf(&opt, ",id=%s", disk->info.alias);
-    if (disk->bootIndex && qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX))
-        virBufferAsprintf(&opt, ",bootindex=%d", disk->bootIndex);
+    if (bootindex && qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX))
+        virBufferAsprintf(&opt, ",bootindex=%d", bootindex);
 
     if (virBufferError(&opt)) {
         virReportOOMError();
@@ -1615,6 +1617,7 @@ qemuBuildNicStr(virDomainNetDefPtr net,
 char *
 qemuBuildNicDevStr(virDomainNetDefPtr net,
                    int vlan,
+                   int bootindex,
                    virBitmapPtr qemuCaps)
 {
     virBuffer buf = VIR_BUFFER_INITIALIZER;
@@ -1667,8 +1670,8 @@ qemuBuildNicDevStr(virDomainNetDefPtr net,
                       net->mac[4], net->mac[5]);
     if (qemuBuildDeviceAddressStr(&buf, &net->info, qemuCaps) < 0)
         goto error;
-    if (net->bootIndex && qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX))
-        virBufferAsprintf(&buf, ",bootindex=%d", net->bootIndex);
+    if (bootindex && qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX))
+        virBufferAsprintf(&buf, ",bootindex=%d", bootindex);
 
     if (virBufferError(&buf)) {
         virReportOOMError();
@@ -2684,7 +2687,6 @@ qemuBuildCommandLine(virConnectPtr conn,
                      enum virVMOperationType vmop)
 {
     int i;
-    char boot[VIR_DOMAIN_BOOT_LAST+1];
     struct utsname ut;
     int disableKQEMU = 0;
     int enableKQEMU = 0;
@@ -2699,6 +2701,7 @@ qemuBuildCommandLine(virConnectPtr conn,
     virCommandPtr cmd;
     bool has_rbd_hosts = false;
     virBuffer rbd_hosts = VIR_BUFFER_INITIALIZER;
+    bool emitBootindex = false;
 
     uname_normalize(&ut);
 
@@ -3090,31 +3093,54 @@ qemuBuildCommandLine(virConnectPtr conn,
         virCommandAddArg(cmd, "-no-acpi");
 
     if (!def->os.bootloader) {
-        for (i = 0 ; i < def->os.nBootDevs ; i++) {
-            switch (def->os.bootDevs[i]) {
-            case VIR_DOMAIN_BOOT_CDROM:
-                boot[i] = 'd';
-                break;
-            case VIR_DOMAIN_BOOT_FLOPPY:
-                boot[i] = 'a';
-                break;
-            case VIR_DOMAIN_BOOT_DISK:
-                boot[i] = 'c';
-                break;
-            case VIR_DOMAIN_BOOT_NET:
-                boot[i] = 'n';
-                break;
-            default:
-                boot[i] = 'c';
-                break;
+        /*
+         * We prefer using explicit bootindex=N parameters for predictable
+         * results even though domain XML doesn't use per device boot elements.
+         * However, we can't use bootindex if boot menu was requested.
+         */
+        if (!def->os.nBootDevs) {
+            /* def->os.nBootDevs is guaranteed to be > 0 unless per-device boot
+             * configuration is used
+             */
+            if (!qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX)) {
+                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                                _("hypervisor lacks deviceboot feature"));
+                goto error;
             }
+            emitBootindex = true;
+        } else if (qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX) &&
+                   (def->os.bootmenu != VIR_DOMAIN_BOOT_MENU_ENABLED ||
+                    !qemuCapsGet(qemuCaps, QEMU_CAPS_BOOT_MENU))) {
+            emitBootindex = true;
         }
-        if (def->os.nBootDevs) {
+
+        if (!emitBootindex) {
             virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
-            virCommandAddArg(cmd, "-boot");
+            char boot[VIR_DOMAIN_BOOT_LAST+1];
 
+            for (i = 0 ; i < def->os.nBootDevs ; i++) {
+                switch (def->os.bootDevs[i]) {
+                case VIR_DOMAIN_BOOT_CDROM:
+                    boot[i] = 'd';
+                    break;
+                case VIR_DOMAIN_BOOT_FLOPPY:
+                    boot[i] = 'a';
+                    break;
+                case VIR_DOMAIN_BOOT_DISK:
+                    boot[i] = 'c';
+                    break;
+                case VIR_DOMAIN_BOOT_NET:
+                    boot[i] = 'n';
+                    break;
+                default:
+                    boot[i] = 'c';
+                    break;
+                }
+            }
             boot[def->os.nBootDevs] = '\0';
 
+            virCommandAddArg(cmd, "-boot");
+
             if (qemuCapsGet(qemuCaps, QEMU_CAPS_BOOT_MENU) &&
                 def->os.bootmenu != VIR_DOMAIN_BOOT_MENU_DEFAULT) {
                 if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_ENABLED)
@@ -3126,13 +3152,6 @@ qemuBuildCommandLine(virConnectPtr conn,
             }
 
             virCommandAddArgBuffer(cmd, &boot_buf);
-        } else if (!qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX)) {
-            /* def->os.nBootDevs is guaranteed to be > 0 unless per-device boot
-             * configuration is used
-             */
-            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                            _("hypervisor lacks deviceboot feature"));
-            goto error;
         }
 
         if (def->os.kernel)
@@ -3190,19 +3209,20 @@ qemuBuildCommandLine(virConnectPtr conn,
     if (qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE)) {
         int bootCD = 0, bootFloppy = 0, bootDisk = 0;
 
-        /* If QEMU supports boot=on for -drive param... */
-        if (qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE_BOOT) &&
+        if ((qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE_BOOT) || emitBootindex) &&
             !def->os.kernel) {
+            /* bootDevs will get translated into either bootindex=N or boot=on
+             * depending on what qemu supports */
             for (i = 0 ; i < def->os.nBootDevs ; i++) {
                 switch (def->os.bootDevs[i]) {
                 case VIR_DOMAIN_BOOT_CDROM:
-                    bootCD = 1;
+                    bootCD = i + 1;
                     break;
                 case VIR_DOMAIN_BOOT_FLOPPY:
-                    bootFloppy = 1;
+                    bootFloppy = i + 1;
                     break;
                 case VIR_DOMAIN_BOOT_DISK:
-                    bootDisk = 1;
+                    bootDisk = i + 1;
                     break;
                 }
             }
@@ -3210,7 +3230,7 @@ qemuBuildCommandLine(virConnectPtr conn,
 
         for (i = 0 ; i < def->ndisks ; i++) {
             char *optstr;
-            int bootable = 0;
+            int bootindex = 0;
             virDomainDiskDefPtr disk = def->disks[i];
             int withDeviceArg = 0;
             bool deviceFlagMasked = false;
@@ -3234,15 +3254,15 @@ qemuBuildCommandLine(virConnectPtr conn,
 
             switch (disk->device) {
             case VIR_DOMAIN_DISK_DEVICE_CDROM:
-                bootable = bootCD;
+                bootindex = bootCD;
                 bootCD = 0;
                 break;
             case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
-                bootable = bootFloppy;
+                bootindex = bootFloppy;
                 bootFloppy = 0;
                 break;
             case VIR_DOMAIN_DISK_DEVICE_DISK:
-                bootable = bootDisk;
+                bootindex = bootDisk;
                 bootDisk = 0;
                 break;
             }
@@ -3262,7 +3282,9 @@ qemuBuildCommandLine(virConnectPtr conn,
                     deviceFlagMasked = true;
                 }
             }
-            optstr = qemuBuildDriveStr(disk, bootable, qemuCaps);
+            optstr = qemuBuildDriveStr(disk,
+                                       emitBootindex ? false : !!bootindex,
+                                       qemuCaps);
             if (deviceFlagMasked)
                 qemuCapsSet(qemuCaps, QEMU_CAPS_DEVICE);
             if (!optstr)
@@ -3290,6 +3312,11 @@ qemuBuildCommandLine(virConnectPtr conn,
                 }
             }
 
+            if (!emitBootindex)
+                bootindex = 0;
+            else if (disk->bootIndex)
+                bootindex = disk->bootIndex;
+
             if (withDeviceArg) {
                 if (disk->bus == VIR_DOMAIN_DISK_BUS_FDC) {
                     virCommandAddArg(cmd, "-global");
@@ -3298,18 +3325,18 @@ qemuBuildCommandLine(virConnectPtr conn,
                                            ? 'B' : 'A',
                                            disk->info.alias);
 
-                    if (disk->bootIndex &&
-                        qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX)) {
+                    if (bootindex) {
                         virCommandAddArg(cmd, "-global");
                         virCommandAddArgFormat(cmd, "isa-fdc.bootindex%c=%d",
                                                disk->info.addr.drive.unit
                                                ? 'B' : 'A',
-                                               disk->bootIndex);
+                                               bootindex);
                     }
                 } else {
                     virCommandAddArg(cmd, "-device");
 
-                    if (!(optstr = qemuBuildDriveDevStr(disk, qemuCaps)))
+                    if (!(optstr = qemuBuildDriveDevStr(disk, bootindex,
+                                                        qemuCaps)))
                         goto error;
                     virCommandAddArg(cmd, optstr);
                     VIR_FREE(optstr);
@@ -3470,12 +3497,31 @@ qemuBuildCommandLine(virConnectPtr conn,
         if (!qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE))
             virCommandAddArgList(cmd, "-net", "none", NULL);
     } else {
+        int bootNet = 0;
+
+        if (emitBootindex) {
+            /* convert <boot dev='network'/> to bootindex since we didn't emit
+             * -boot n
+             */
+            for (i = 0 ; i < def->os.nBootDevs ; i++) {
+                if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_NET) {
+                    bootNet = i + 1;
+                    break;
+                }
+            }
+        }
+
         for (i = 0 ; i < def->nnets ; i++) {
             virDomainNetDefPtr net = def->nets[i];
             char *nic, *host;
             char tapfd_name[50];
             char vhostfd_name[50] = "";
             int vlan;
+            int bootindex = bootNet;
+
+            bootNet = 0;
+            if (!bootindex)
+                bootindex = net->bootIndex;
 
             /* VLANs are not used with -netdev, so don't record them */
             if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) &&
@@ -3547,7 +3593,8 @@ qemuBuildCommandLine(virConnectPtr conn,
             }
             if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
                 virCommandAddArg(cmd, "-device");
-                if (!(nic = qemuBuildNicDevStr(net, vlan, qemuCaps)))
+                nic = qemuBuildNicDevStr(net, vlan, bootindex, qemuCaps);
+                if (!nic)
                     goto error;
                 virCommandAddArg(cmd, nic);
                 VIR_FREE(nic);
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 528031d..d6e5dcb 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -68,6 +68,7 @@ char * qemuBuildNicStr(virDomainNetDefPtr net,
 /* Current, best practice */
 char * qemuBuildNicDevStr(virDomainNetDefPtr net,
                           int vlan,
+                          int bootindex,
                           virBitmapPtr qemuCaps);
 
 char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk,
@@ -75,13 +76,14 @@ char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk,
 
 /* Both legacy & current support */
 char *qemuBuildDriveStr(virDomainDiskDefPtr disk,
-                        int bootable,
+                        bool bootable,
                         virBitmapPtr qemuCaps);
 char *qemuBuildFSStr(virDomainFSDefPtr fs,
                      virBitmapPtr qemuCaps);
 
 /* Current, best practice */
 char * qemuBuildDriveDevStr(virDomainDiskDefPtr disk,
+                            int bootindex,
                             virBitmapPtr qemuCaps);
 char * qemuBuildFSDevStr(virDomainFSDefPtr fs,
                          virBitmapPtr qemuCaps);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index fe47896..b605b3a 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -186,10 +186,10 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver,
         if (qemuAssignDeviceDiskAlias(disk, priv->qemuCaps) < 0)
             goto error;
 
-        if (!(drivestr = qemuBuildDriveStr(disk, 0, priv->qemuCaps)))
+        if (!(drivestr = qemuBuildDriveStr(disk, false, priv->qemuCaps)))
             goto error;
 
-        if (!(devstr = qemuBuildDriveDevStr(disk, priv->qemuCaps)))
+        if (!(devstr = qemuBuildDriveDevStr(disk, 0, priv->qemuCaps)))
             goto error;
     }
 
@@ -409,11 +409,11 @@ int qemuDomainAttachSCSIDisk(struct qemud_driver *driver,
     if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
         if (qemuAssignDeviceDiskAlias(disk, priv->qemuCaps) < 0)
             goto error;
-        if (!(devstr = qemuBuildDriveDevStr(disk, priv->qemuCaps)))
+        if (!(devstr = qemuBuildDriveDevStr(disk, 0, priv->qemuCaps)))
             goto error;
     }
 
-    if (!(drivestr = qemuBuildDriveStr(disk, 0, priv->qemuCaps)))
+    if (!(drivestr = qemuBuildDriveStr(disk, false, priv->qemuCaps)))
         goto error;
 
     for (i = 0 ; i <= disk->info.addr.drive.controller ; i++) {
@@ -529,9 +529,9 @@ int qemuDomainAttachUsbMassstorageDevice(struct qemud_driver *driver,
     if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
         if (qemuAssignDeviceDiskAlias(disk, priv->qemuCaps) < 0)
             goto error;
-        if (!(drivestr = qemuBuildDriveStr(disk, 0, priv->qemuCaps)))
+        if (!(drivestr = qemuBuildDriveStr(disk, false, priv->qemuCaps)))
             goto error;
-        if (!(devstr = qemuBuildDriveDevStr(disk, priv->qemuCaps)))
+        if (!(devstr = qemuBuildDriveDevStr(disk, 0, priv->qemuCaps)))
             goto error;
     }
 
@@ -702,7 +702,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
     }
 
     if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
-        if (!(nicstr = qemuBuildNicDevStr(net, vlan, priv->qemuCaps)))
+        if (!(nicstr = qemuBuildNicDevStr(net, vlan, 0, priv->qemuCaps)))
             goto try_remove;
     } else {
         if (!(nicstr = qemuBuildNicStr(net, NULL, vlan)))
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.args
new file mode 100644
index 0000000..ae0b2b1
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.args
@@ -0,0 +1,30 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-drive file=/tmp/vda.img,if=none,id=drive-virtio-disk0 \
+-device virtio-blk-pci,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=3 \
+-drive file=/tmp/vdb.img,if=none,id=drive-virtio-disk1 \
+-device virtio-blk-pci,bus=pci.0,addr=0x6,drive=drive-virtio-disk1,id=virtio-disk1 \
+-drive file=/dev/HostVG/hda,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-drive file=/dev/HostVG/hdb,if=none,id=drive-ide0-0-1 \
+-device ide-drive,bus=ide.0,unit=1,drive=drive-ide0-0-1,id=ide0-0-1 \
+-drive file=/dev/HostVG/hdc,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0,bootindex=1 \
+-drive file=/dev/fd0,if=none,id=drive-fdc0-0-0 \
+-global isa-fdc.driveA=drive-fdc0-0-0 \
+-global isa-fdc.bootindexA=4 \
+-drive file=/dev/fd1,if=none,id=drive-fdc0-0-1 \
+-global isa-fdc.driveB=drive-fdc0-0-1 \
+-device virtio-net-pci,vlan=0,id=net0,mac=00:11:22:33:44:11,bus=pci.0,addr=0x3,bootindex=2 \
+-net user,vlan=0,name=hostnet0 \
+-device virtio-net-pci,vlan=1,id=net1,mac=00:11:22:33:44:22,bus=pci.0,addr=0x4 \
+-net user,vlan=1,name=hostnet1 \
+-usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.xml b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.xml
new file mode 100644
index 0000000..b4d6f4f
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.xml
@@ -0,0 +1,65 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219100</memory>
+  <currentMemory>219100</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='cdrom'/>
+    <boot dev='network'/>
+    <boot dev='hd'/>
+    <boot dev='fd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='file' device='disk'>
+      <source file='/tmp/vdb.img'/>
+      <target dev='vdb' bus='virtio'/>
+    </disk>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/hdb'/>
+      <target dev='hdb' bus='ide'/>
+      <address type='drive' controller='0' bus='0' unit='1'/>
+    </disk>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/hda'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <disk type='file' device='disk'>
+      <source file='/tmp/vda.img'/>
+      <target dev='vda' bus='virtio'/>
+    </disk>
+    <disk type='block' device='cdrom'>
+      <source dev='/dev/HostVG/hdc'/>
+      <target dev='hdc' bus='ide'/>
+      <address type='drive' controller='0' bus='1' unit='0'/>
+    </disk>
+    <disk type='block' device='floppy'>
+      <source dev='/dev/fd1'/>
+      <target dev='fdb' bus='fdc'/>
+      <address type='drive' controller='0' bus='0' unit='1'/>
+    </disk>
+    <disk type='block' device='floppy'>
+      <source dev='/dev/fd0'/>
+      <target dev='fda' bus='fdc'/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <controller type='fdc' index='0'/>
+    <controller type='ide' index='0'/>
+    <interface type='user'>
+      <mac address='00:11:22:33:44:11'/>
+      <model type='virtio'/>
+    </interface>
+    <interface type='user'>
+      <mac address='00:11:22:33:44:22'/>
+      <model type='virtio'/>
+    </interface>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-complex.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex.args
new file mode 100644
index 0000000..c8d32ec
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex.args
@@ -0,0 +1,30 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-boot dnca \
+-drive file=/tmp/vda.img,if=none,id=drive-virtio-disk0,boot=on \
+-device virtio-blk-pci,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0 \
+-drive file=/tmp/vdb.img,if=none,id=drive-virtio-disk1 \
+-device virtio-blk-pci,bus=pci.0,addr=0x6,drive=drive-virtio-disk1,id=virtio-disk1 \
+-drive file=/dev/HostVG/hda,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-drive file=/dev/HostVG/hdb,if=none,id=drive-ide0-0-1 \
+-device ide-drive,bus=ide.0,unit=1,drive=drive-ide0-0-1,id=ide0-0-1 \
+-drive file=/dev/HostVG/hdc,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 \
+-drive file=/dev/fd0,if=none,id=drive-fdc0-0-0 \
+-global isa-fdc.driveA=drive-fdc0-0-0 \
+-drive file=/dev/fd1,if=none,id=drive-fdc0-0-1 \
+-global isa-fdc.driveB=drive-fdc0-0-1 \
+-device virtio-net-pci,vlan=0,id=net0,mac=00:11:22:33:44:11,bus=pci.0,addr=0x3 \
+-net user,vlan=0,name=hostnet0 \
+-device virtio-net-pci,vlan=1,id=net1,mac=00:11:22:33:44:22,bus=pci.0,addr=0x4 \
+-net user,vlan=1,name=hostnet1 \
+-usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-complex.xml b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex.xml
new file mode 100644
index 0000000..b4d6f4f
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex.xml
@@ -0,0 +1,65 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219100</memory>
+  <currentMemory>219100</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='cdrom'/>
+    <boot dev='network'/>
+    <boot dev='hd'/>
+    <boot dev='fd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='file' device='disk'>
+      <source file='/tmp/vdb.img'/>
+      <target dev='vdb' bus='virtio'/>
+    </disk>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/hdb'/>
+      <target dev='hdb' bus='ide'/>
+      <address type='drive' controller='0' bus='0' unit='1'/>
+    </disk>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/hda'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <disk type='file' device='disk'>
+      <source file='/tmp/vda.img'/>
+      <target dev='vda' bus='virtio'/>
+    </disk>
+    <disk type='block' device='cdrom'>
+      <source dev='/dev/HostVG/hdc'/>
+      <target dev='hdc' bus='ide'/>
+      <address type='drive' controller='0' bus='1' unit='0'/>
+    </disk>
+    <disk type='block' device='floppy'>
+      <source dev='/dev/fd1'/>
+      <target dev='fdb' bus='fdc'/>
+      <address type='drive' controller='0' bus='0' unit='1'/>
+    </disk>
+    <disk type='block' device='floppy'>
+      <source dev='/dev/fd0'/>
+      <target dev='fda' bus='fdc'/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <controller type='fdc' index='0'/>
+    <controller type='ide' index='0'/>
+    <interface type='user'>
+      <mac address='00:11:22:33:44:11'/>
+      <model type='virtio'/>
+    </interface>
+    <interface type='user'>
+      <mac address='00:11:22:33:44:22'/>
+      <model type='virtio'/>
+    </interface>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.args
new file mode 100644
index 0000000..5074e32
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.args
@@ -0,0 +1,13 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-drive file=/dev/cdrom,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0,bootindex=1 \
+-usb \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.xml b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.xml
new file mode 100644
index 0000000..bc1da8a
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.xml
@@ -0,0 +1,27 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219100</memory>
+  <currentMemory>219100</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='cdrom'/>
+    <bootmenu enable='no'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='cdrom'>
+      <source dev='/dev/cdrom'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.args
new file mode 100644
index 0000000..42b48e5
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.args
@@ -0,0 +1,14 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-boot order=d,menu=off \
+-drive file=/dev/cdrom,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 \
+-usb \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.xml b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.xml
new file mode 100644
index 0000000..bc1da8a
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.xml
@@ -0,0 +1,27 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219100</memory>
+  <currentMemory>219100</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='cdrom'/>
+    <bootmenu enable='no'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='cdrom'>
+      <source dev='/dev/cdrom'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.args
new file mode 100644
index 0000000..5d7c4a4
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.args
@@ -0,0 +1,14 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-boot order=d,menu=on \
+-drive file=/dev/cdrom,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 \
+-usb \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.xml b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.xml
new file mode 100644
index 0000000..c35b2bd
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.xml
@@ -0,0 +1,27 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219100</memory>
+  <currentMemory>219100</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='cdrom'/>
+    <bootmenu enable='yes'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='cdrom'>
+      <source dev='/dev/cdrom'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.args
new file mode 100644
index 0000000..357723f
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.args
@@ -0,0 +1,18 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=2 \
+-drive file=/dev/HostVG/QEMUGuest2,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0,bootindex=1 \
+-drive file=/dev/fd0,if=none,id=drive-fdc0-0-0 \
+-global isa-fdc.driveA=drive-fdc0-0-0 \
+-global isa-fdc.bootindexA=3 \
+-usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.xml
new file mode 100644
index 0000000..a7e08fd
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.xml
@@ -0,0 +1,38 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219100</memory>
+  <currentMemory>219100</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='cdrom'/>
+    <boot dev='hd'/>
+    <boot dev='fd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <disk type='block' device='cdrom'>
+      <source dev='/dev/HostVG/QEMUGuest2'/>
+      <target dev='hdc' bus='ide'/>
+      <address type='drive' controller='0' bus='1' unit='0'/>
+    </disk>
+    <disk type='block' device='floppy'>
+      <source dev='/dev/fd0'/>
+      <target dev='fda' bus='fdc'/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <controller type='fdc' index='0'/>
+    <controller type='ide' index='0'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index cbd9a5f..a0f3354 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -265,9 +265,24 @@ mymain(void)
     DO_TEST("boot-network", false, NONE);
     DO_TEST("boot-floppy", false, NONE);
     DO_TEST("boot-multi", false, QEMU_CAPS_BOOT_MENU);
+    DO_TEST("boot-menu-enable", false,
+            QEMU_CAPS_BOOT_MENU, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE);
+    DO_TEST("boot-menu-enable", false,
+            QEMU_CAPS_BOOT_MENU, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
+            QEMU_CAPS_BOOTINDEX);
     DO_TEST("boot-menu-disable", false, QEMU_CAPS_BOOT_MENU);
+    DO_TEST("boot-menu-disable-drive", false,
+            QEMU_CAPS_BOOT_MENU, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE);
+    DO_TEST("boot-menu-disable-drive-bootindex", false,
+            QEMU_CAPS_BOOT_MENU, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
+            QEMU_CAPS_BOOTINDEX);
     DO_TEST("boot-order", false,
             QEMU_CAPS_BOOTINDEX, QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE);
+    DO_TEST("boot-complex", false,
+            QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_BOOT);
+    DO_TEST("boot-complex-bootindex", false,
+            QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_BOOT,
+            QEMU_CAPS_BOOTINDEX);
     DO_TEST("bootloader", true, QEMU_CAPS_DOMID);
     DO_TEST("clock-utc", false, NONE);
     DO_TEST("clock-localtime", false, NONE);
@@ -323,6 +338,8 @@ mymain(void)
             QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT);
     DO_TEST("disk-drive-network-sheepdog", false,
             QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT);
+    DO_TEST("disk-drive-no-boot", false,
+            QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_BOOTINDEX);
     DO_TEST("disk-usb", false, NONE);
     DO_TEST("disk-usb-device", false,
             QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
-- 
1.7.5.3




More information about the libvir-list mailing list