Support Xenner bootloader

This commit is contained in:
Daniel P. Berrange 2008-05-15 16:21:11 +00:00
parent 0f1b6dd06a
commit 763a59d84d
7 changed files with 199 additions and 134 deletions

View File

@ -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

View 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)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE,
"%s", obj->stringval);
goto error;
}
strcpy(def->os.type, (const char *)obj->stringval);
xmlXPathFreeObject(obj);
if (!virCapabilitiesSupportsGuestOSType(driver->caps, def->os.type)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE,
"%s", def->os.type);
goto error;
}
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;
}
strcpy(def->os.kernel, (const char *)obj->stringval);
}
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;
}
strcpy(def->os.initrd, (const char *)obj->stringval);
}
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;
}
strcpy(def->os.cmdline, (const char *)obj->stringval);
}
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 {
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,
_("unknown boot device \'%s\'"), (char*)prop);
"%s", _("kernel path too long"));
goto error;
}
xmlFree(prop);
prop = NULL;
strcpy(def->os.kernel, (const char *)obj->stringval);
}
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;
}
strcpy(def->os.initrd, (const char *)obj->stringval);
}
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;
}
strcpy(def->os.cmdline, (const char *)obj->stringval);
}
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;
}
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;
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")))
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.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)))
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);
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;
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");

View 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 */

View File

@ -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

View File

@ -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>

View 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);

View 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");