]> xenbits.xensource.com Git - libvirt.git/commitdiff
xen: fix PyGrub boot device order
authorPhilipp Hahn <hahn@univention.de>
Wed, 12 Oct 2011 08:26:46 +0000 (10:26 +0200)
committerEric Blake <eblake@redhat.com>
Wed, 12 Oct 2011 18:52:20 +0000 (12:52 -0600)
When PyGrub is used as the bootloader in Xen, it gets passed the first
bootable disk. Xend supports a "bootable"-flag for this, which isn't
explicitly supported by libvirt.
When converting libvirt-xml to xen-sxpr the "bootable"-flag gets
implicitly set by xen.xend.XenConfig.device_add() for the first disk
(marked as "Compat hack -- mark first disk bootable").
When converting back xen-sxpr to libvirt-xml, the disks are returned in
the internal order used by Xend ignoring the "bootable"-flag, which
loses the original order. When the domain is then re-defined, the order
of disks is changed, which breaks PyGrub, since a different disk gets
passed.

When converting xen-sxpr to libvirt-xml, use the "bootable"-flag to
determine the first disk.

This isn't perfect, since several disks can be marked as bootable using
the Xend-API, but that is not supported by libvirt. In all known cases
relevant to libvirt exactly one disk is marked as bootable.

Signed-off-by: Philipp Hahn <hahn@univention.de>
src/xenxs/xen_sxpr.c

index 15eaf1863bff5cf61331c1104c526d827189c327..c172e61facf9726508f36d28799eae3a12e430ed 100644 (file)
@@ -348,20 +348,24 @@ xenParseSxprDisks(virDomainDefPtr def,
             const char *src = NULL;
             const char *dst = NULL;
             const char *mode = NULL;
+            const char *bootable = NULL;
 
             /* Again dealing with (vbd...) vs (tap ...) differences */
             if (sexpr_lookup(node, "device/vbd")) {
                 src = sexpr_node(node, "device/vbd/uname");
                 dst = sexpr_node(node, "device/vbd/dev");
                 mode = sexpr_node(node, "device/vbd/mode");
+                bootable = sexpr_node(node, "device/vbd/bootable");
             } else if (sexpr_lookup(node, "device/tap2")) {
                 src = sexpr_node(node, "device/tap2/uname");
                 dst = sexpr_node(node, "device/tap2/dev");
                 mode = sexpr_node(node, "device/tap2/mode");
+                bootable = sexpr_node(node, "device/tap2/bootable");
             } else {
                 src = sexpr_node(node, "device/tap/uname");
                 dst = sexpr_node(node, "device/tap/dev");
                 mode = sexpr_node(node, "device/tap/mode");
+                bootable = sexpr_node(node, "device/tap/bootable");
             }
 
             if (VIR_ALLOC(disk) < 0)
@@ -487,7 +491,13 @@ xenParseSxprDisks(virDomainDefPtr def,
             if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
                 goto no_memory;
 
-            def->disks[def->ndisks++] = disk;
+            /* re-order disks if there is a bootable device */
+            if (STREQ_NULLABLE(bootable, "1")) {
+                def->disks[def->ndisks++] = def->disks[0];
+                def->disks[0] = disk;
+            } else {
+                def->disks[def->ndisks++] = disk;
+            }
             disk = NULL;
         }
     }