]> xenbits.xensource.com Git - libvirt.git/commitdiff
Support Xenner bootloader
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 15 May 2008 16:21:11 +0000 (16:21 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Thu, 15 May 2008 16:21:11 +0000 (16:21 +0000)
ChangeLog
src/qemu_conf.c
src/qemu_conf.h
tests/qemuxml2argvdata/qemuxml2argv-bootloader.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml [new file with mode: 0644]
tests/qemuxml2argvtest.c
tests/qemuxml2xmltest.c

index d20f1708ec225b31767c200345bd53296e86d817..df07dd29946b9aa6be5937747c8040a727fdae1b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Thu May 15 12:16:08 EST 2008 Daniel P. Berrange <berrange@redhat.com>
+
+       Support xenner bootloader capability
+       * src/qemu_conf.c, src/qemu_conf.h: Add support for specifying a
+       bootloader for paravirt xen guests
+       * tests/qemuxml2argv-bootloader.{args,xml}: Test case data
+       files for xen bootloader
+       * tests/qemuxml2argvtest.c, tests/qemuxml2xmltest.c: Add
+       test case for xen bootloader
+
 Thu May 15 12:11:08 EST 2008 Daniel P. Berrange <berrange@redhat.com>
 
        * src/qemu_conf.c, src/qemu_conf.h: Pass the -name flag to QEMU
index b17d0c816f03225665f0dc6d54f587864a198f35..4cb3f78c2aaac75378c588767776d239dd567ff1 100644 (file)
@@ -1702,22 +1702,37 @@ static struct qemud_vm_def *qemudParseXML(virConnectPtr conn,
     xmlXPathFreeObject(obj);
 
 
+    /* Extract bootloader */
+    obj = xmlXPathEval(BAD_CAST "string(/domain/bootloader)", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        strncpy(def->os.bootloader, (const char*)obj->stringval, sizeof(def->os.bootloader));
+        NUL_TERMINATE(def->os.bootloader);
+        xmlXPathFreeObject(obj);
+
+        /* Set a default OS type, since <type> is optional with bootloader */
+        strcpy(def->os.type, "xen");
+    }
+
     /* Extract OS type info */
     obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1])", ctxt);
     if ((obj == NULL) || (obj->type != XPATH_STRING) ||
         (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE,
-                         "%s", _("no OS type"));
-        goto error;
+        if (!def->os.type[0]) {
+            qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE,
+                             "%s", _("no OS type"));
+            goto error;
+        }
+    } else {
+        strcpy(def->os.type, (const char *)obj->stringval);
+        xmlXPathFreeObject(obj);
     }
-    if (!virCapabilitiesSupportsGuestOSType(driver->caps, (const char*)obj->stringval)) {
+
+    if (!virCapabilitiesSupportsGuestOSType(driver->caps, def->os.type)) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE,
-                         "%s", obj->stringval);
+                         "%s", def->os.type);
         goto error;
     }
-    strcpy(def->os.type, (const char *)obj->stringval);
-    xmlXPathFreeObject(obj);
-
 
     obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1]/@arch)", ctxt);
     if ((obj == NULL) || (obj->type != XPATH_STRING) ||
@@ -1772,75 +1787,76 @@ static struct qemud_vm_def *qemudParseXML(virConnectPtr conn,
     xmlXPathFreeObject(obj);
 
 
-    obj = xmlXPathEval(BAD_CAST "string(/domain/os/kernel[1])", ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-        if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("kernel path too long"));
-            goto error;
+    if (!def->os.bootloader[0]) {
+        obj = xmlXPathEval(BAD_CAST "string(/domain/os/kernel[1])", ctxt);
+        if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+            (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+            if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
+                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("kernel path too long"));
+                goto error;
+            }
+            strcpy(def->os.kernel, (const char *)obj->stringval);
         }
-        strcpy(def->os.kernel, (const char *)obj->stringval);
-    }
-    xmlXPathFreeObject(obj);
+        xmlXPathFreeObject(obj);
 
 
-    obj = xmlXPathEval(BAD_CAST "string(/domain/os/initrd[1])", ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-        if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("initrd path too long"));
-            goto error;
+        obj = xmlXPathEval(BAD_CAST "string(/domain/os/initrd[1])", ctxt);
+        if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+            (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+            if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
+                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("initrd path too long"));
+                goto error;
+            }
+            strcpy(def->os.initrd, (const char *)obj->stringval);
         }
-        strcpy(def->os.initrd, (const char *)obj->stringval);
-    }
-    xmlXPathFreeObject(obj);
+        xmlXPathFreeObject(obj);
 
 
-    obj = xmlXPathEval(BAD_CAST "string(/domain/os/cmdline[1])", ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
-        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
-        if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("cmdline arguments too long"));
-            goto error;
+        obj = xmlXPathEval(BAD_CAST "string(/domain/os/cmdline[1])", ctxt);
+        if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+            (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+            if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
+                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("cmdline arguments too long"));
+                goto error;
+            }
+            strcpy(def->os.cmdline, (const char *)obj->stringval);
         }
-        strcpy(def->os.cmdline, (const char *)obj->stringval);
-    }
-    xmlXPathFreeObject(obj);
+        xmlXPathFreeObject(obj);
 
 
-    /* analysis of the disk devices */
-    obj = xmlXPathEval(BAD_CAST "/domain/os/boot", ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
-        (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
-        for (i = 0; i < obj->nodesetval->nodeNr && i < QEMUD_MAX_BOOT_DEVS ; i++) {
-            if (!(prop = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "dev")))
-                continue;
-            if (STREQ((char *)prop, "hd")) {
-                def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_DISK;
-            } else if (STREQ((char *)prop, "fd")) {
-                def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_FLOPPY;
-            } else if (STREQ((char *)prop, "cdrom")) {
-                def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_CDROM;
-            } else if (STREQ((char *)prop, "network")) {
-                def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_NET;
-            } else {
-                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                             _("unknown boot device \'%s\'"), (char*)prop);
-                goto error;
+        /* analysis of the disk devices */
+        obj = xmlXPathEval(BAD_CAST "/domain/os/boot", ctxt);
+        if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
+            (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
+            for (i = 0; i < obj->nodesetval->nodeNr && i < QEMUD_MAX_BOOT_DEVS ; i++) {
+                if (!(prop = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "dev")))
+                    continue;
+                if (STREQ((char *)prop, "hd")) {
+                    def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_DISK;
+                } else if (STREQ((char *)prop, "fd")) {
+                    def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_FLOPPY;
+                } else if (STREQ((char *)prop, "cdrom")) {
+                    def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_CDROM;
+                } else if (STREQ((char *)prop, "network")) {
+                    def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_NET;
+                } else {
+                    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                                     _("unknown boot device \'%s\'"), (char*)prop);
+                    goto error;
+                }
+                xmlFree(prop);
+                prop = NULL;
             }
-            xmlFree(prop);
-            prop = NULL;
+        }
+        xmlXPathFreeObject(obj);
+        if (def->os.nBootDevs == 0) {
+            def->os.nBootDevs = 1;
+            def->os.bootDevs[0] = QEMUD_BOOT_DISK;
         }
     }
-    xmlXPathFreeObject(obj);
-    if (def->os.nBootDevs == 0) {
-        def->os.nBootDevs = 1;
-        def->os.bootDevs[0] = QEMUD_BOOT_DISK;
-    }
-
 
     obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt);
     if ((obj == NULL) || (obj->type != XPATH_STRING) ||
@@ -2371,6 +2387,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
         (vm->def->os.kernel[0] ? 2 : 0) + /* kernel */
         (vm->def->os.initrd[0] ? 2 : 0) + /* initrd */
         (vm->def->os.cmdline[0] ? 2 : 0) + /* cmdline */
+        (vm->def->os.bootloader[0] ? 2 : 0) + /* bootloader */
         (vm->def->graphicsType == QEMUD_GRAPHICS_VNC ? 2 :
          (vm->def->graphicsType == QEMUD_GRAPHICS_SDL ? 0 : 1)) + /* graphics */
         (vm->migrateFrom[0] ? 3 : 0); /* migrateFrom */
@@ -2438,47 +2455,54 @@ int qemudBuildCommandLine(virConnectPtr conn,
             goto no_memory;
     }
 
-    for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
-        switch (vm->def->os.bootDevs[i]) {
-        case QEMUD_BOOT_CDROM:
-            boot[i] = 'd';
-            break;
-        case QEMUD_BOOT_FLOPPY:
-            boot[i] = 'a';
-            break;
-        case QEMUD_BOOT_DISK:
-            boot[i] = 'c';
-            break;
-        case QEMUD_BOOT_NET:
-            boot[i] = 'n';
-            break;
-        default:
-            boot[i] = 'c';
-            break;
+    if (!vm->def->os.bootloader[0]) {
+        for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
+            switch (vm->def->os.bootDevs[i]) {
+            case QEMUD_BOOT_CDROM:
+                boot[i] = 'd';
+                break;
+            case QEMUD_BOOT_FLOPPY:
+                boot[i] = 'a';
+                break;
+            case QEMUD_BOOT_DISK:
+                boot[i] = 'c';
+                break;
+            case QEMUD_BOOT_NET:
+                boot[i] = 'n';
+                break;
+            default:
+                boot[i] = 'c';
+                break;
+            }
         }
-    }
-    boot[vm->def->os.nBootDevs] = '\0';
-    if (!((*argv)[++n] = strdup("-boot")))
-        goto no_memory;
-    if (!((*argv)[++n] = strdup(boot)))
-        goto no_memory;
-
-    if (vm->def->os.kernel[0]) {
-        if (!((*argv)[++n] = strdup("-kernel")))
+        boot[vm->def->os.nBootDevs] = '\0';
+        if (!((*argv)[++n] = strdup("-boot")))
             goto no_memory;
-        if (!((*argv)[++n] = strdup(vm->def->os.kernel)))
-            goto no_memory;
-    }
-    if (vm->def->os.initrd[0]) {
-        if (!((*argv)[++n] = strdup("-initrd")))
+        if (!((*argv)[++n] = strdup(boot)))
             goto no_memory;
-        if (!((*argv)[++n] = strdup(vm->def->os.initrd)))
-            goto no_memory;
-    }
-    if (vm->def->os.cmdline[0]) {
-        if (!((*argv)[++n] = strdup("-append")))
+
+        if (vm->def->os.kernel[0]) {
+            if (!((*argv)[++n] = strdup("-kernel")))
+                goto no_memory;
+            if (!((*argv)[++n] = strdup(vm->def->os.kernel)))
+                goto no_memory;
+        }
+        if (vm->def->os.initrd[0]) {
+            if (!((*argv)[++n] = strdup("-initrd")))
+                goto no_memory;
+            if (!((*argv)[++n] = strdup(vm->def->os.initrd)))
+                goto no_memory;
+        }
+        if (vm->def->os.cmdline[0]) {
+            if (!((*argv)[++n] = strdup("-append")))
+                goto no_memory;
+            if (!((*argv)[++n] = strdup(vm->def->os.cmdline)))
+                goto no_memory;
+        }
+    } else {
+        if (!((*argv)[++n] = strdup("-bootloader")))
             goto no_memory;
-        if (!((*argv)[++n] = strdup(vm->def->os.cmdline)))
+        if (!((*argv)[++n] = strdup(vm->def->os.bootloader)))
             goto no_memory;
     }
 
@@ -3809,6 +3833,8 @@ char *qemudGenerateXML(virConnectPtr conn,
     virBufferVSprintf(&buf, "  <memory>%lu</memory>\n", def->maxmem);
     virBufferVSprintf(&buf, "  <currentMemory>%lu</currentMemory>\n", def->memory);
     virBufferVSprintf(&buf, "  <vcpu>%d</vcpu>\n", def->vcpus);
+    if (def->os.bootloader[0])
+        virBufferVSprintf(&buf, "  <bootloader>%s</bootloader>\n", def->os.bootloader);
     virBufferAddLit(&buf, "  <os>\n");
 
     if (def->virtType == QEMUD_VIRT_QEMU)
@@ -3817,30 +3843,32 @@ char *qemudGenerateXML(virConnectPtr conn,
     else
         virBufferVSprintf(&buf, "    <type>%s</type>\n", def->os.type);
 
-    if (def->os.kernel[0])
-        virBufferVSprintf(&buf, "    <kernel>%s</kernel>\n", def->os.kernel);
-    if (def->os.initrd[0])
-        virBufferVSprintf(&buf, "    <initrd>%s</initrd>\n", def->os.initrd);
-    if (def->os.cmdline[0])
-        virBufferVSprintf(&buf, "    <cmdline>%s</cmdline>\n", def->os.cmdline);
-
-    for (n = 0 ; n < def->os.nBootDevs ; n++) {
-        const char *boottype = "hd";
-        switch (def->os.bootDevs[n]) {
-        case QEMUD_BOOT_FLOPPY:
-            boottype = "fd";
-            break;
-        case QEMUD_BOOT_DISK:
-            boottype = "hd";
-            break;
-        case QEMUD_BOOT_CDROM:
-            boottype = "cdrom";
-            break;
-        case QEMUD_BOOT_NET:
-            boottype = "network";
-            break;
+    if (!def->os.bootloader[0]) {
+        if (def->os.kernel[0])
+            virBufferVSprintf(&buf, "    <kernel>%s</kernel>\n", def->os.kernel);
+        if (def->os.initrd[0])
+            virBufferVSprintf(&buf, "    <initrd>%s</initrd>\n", def->os.initrd);
+        if (def->os.cmdline[0])
+            virBufferVSprintf(&buf, "    <cmdline>%s</cmdline>\n", def->os.cmdline);
+
+        for (n = 0 ; n < def->os.nBootDevs ; n++) {
+            const char *boottype = "hd";
+            switch (def->os.bootDevs[n]) {
+            case QEMUD_BOOT_FLOPPY:
+                boottype = "fd";
+                break;
+            case QEMUD_BOOT_DISK:
+                boottype = "hd";
+                break;
+            case QEMUD_BOOT_CDROM:
+                boottype = "cdrom";
+                break;
+            case QEMUD_BOOT_NET:
+                boottype = "network";
+                break;
+            }
+            virBufferVSprintf(&buf, "    <boot dev='%s'/>\n", boottype);
         }
-        virBufferVSprintf(&buf, "    <boot dev='%s'/>\n", boottype);
     }
 
     virBufferAddLit(&buf, "  </os>\n");
index 5d07c89b9fedce6c725b4966c7471c2497ce9bff..70452034781e311977afa04ccf2ee4628816d942 100644 (file)
@@ -270,6 +270,7 @@ struct qemud_vm_os_def {
     char initrd[PATH_MAX];
     char cmdline[PATH_MAX];
     char binary[PATH_MAX];
+    char bootloader[PATH_MAX];
 };
 
 /* Guest VM main configuration */
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-bootloader.args b/tests/qemuxml2argvdata/qemuxml2argv-bootloader.args
new file mode 100644 (file)
index 0000000..c0a2cea
--- /dev/null
@@ -0,0 +1 @@
+/usr/bin/qemu-kvm -M xenner -m 214 -smp 1 -nographic -monitor pty -no-acpi -bootloader /usr/bin/pygrub -cdrom /dev/cdrom -net none -serial none -parallel none -usb
\ No newline at end of file
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml b/tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml
new file mode 100644 (file)
index 0000000..9de5d12
--- /dev/null
@@ -0,0 +1,23 @@
+<domain type='kvm'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219200</memory>
+  <currentMemory>219200</currentMemory>
+  <vcpu>1</vcpu>
+  <bootloader>/usr/bin/pygrub</bootloader>
+  <os>
+    <type>xen</type>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-kvm</emulator>
+    <disk type='block' device='cdrom'>
+      <source dev='/dev/cdrom'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+    </disk>
+  </devices>
+</domain>
index befe76a27f3594a824c362793d1d62b22a3e1a7f..91af71fcd750cdcd5a78f73a9d164009cdf4b1ba 100644 (file)
@@ -144,6 +144,7 @@ main(int argc, char **argv)
     DO_TEST("boot-cdrom", 0);
     DO_TEST("boot-network", 0);
     DO_TEST("boot-floppy", 0);
+    DO_TEST("bootloader", 0);
     DO_TEST("clock-utc", 0);
     DO_TEST("clock-localtime", 0);
     DO_TEST("disk-cdrom", 0);
index 6dfc66f67fdf0b72dab4c2d8761747595c8fcdd6..eaff0975794c9762db233a10cbb73ad352db274a 100644 (file)
@@ -97,6 +97,7 @@ main(int argc, char **argv)
     DO_TEST("boot-cdrom");
     DO_TEST("boot-network");
     DO_TEST("boot-floppy");
+    DO_TEST("bootloader");
     DO_TEST("clock-utc");
     DO_TEST("clock-localtime");
     DO_TEST("disk-cdrom");