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 looses 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-sxpt 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@xxxxxxxxxxxxx> --- valgrind might complain about an uninitialized read access when copying disks[0] to disks[0], but that is overwritten again with the following assignment. <https://forge.univention.org/bugzilla/show_bug.cgi?id=21938> src/xenxs/xen_sxpr.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c index 72322a7..038c6bb 100644 --- a/src/xenxs/xen_sxpr.c +++ b/src/xenxs/xen_sxpr.c @@ -342,20 +342,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) @@ -481,7 +485,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; } } -- 1.7.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list