From e1ec9651a2e15384cf6cfcb3b49879a9adec945c Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 11 Aug 2006 14:40:04 +0000 Subject: [PATCH] Fixup handling of HVM boot preference, and include HVM cdrom/floppy in main device list --- ChangeLog | 31 +++++++++--- src/libvirt.c | 24 +++------ src/xend_internal.c | 67 ++++++++++++++++++------- src/xml.c | 117 +++++++++++++++++++++++++++++++++++++------- 4 files changed, 182 insertions(+), 57 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7986349aaf..fcd5014a33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +Fri Aug 11 09:37:02 EDT 2006 Daniel Berrange + + * src/libvirt.c: Avoid duplicated attempts to shutdown or + pause a domain if the first attempt succeeded. + * src/xend_internal.c, src/xml.c: When parsing UUID from + SEXPR also allow for format without any embedded '-'. The + ioemu: prefix is no longer required for HVM domains. It is + added when generating SEXPR, and removing when parsing SEXPR + never appearing in XML. CDROM & floppy devices for HVM domains + are now included in XML under tag. The + tag now has a 'device' attribute allowing one of 'floppy', + 'cdrom', 'disk' to be specified. If the tag is present + in XML, HVM domains get a serial console activated. + tag now expects one of 'fd' 'hd' or 'cdrom' when specifying + boot device preference. Increased size of XML doc buffer from + 1k to 4k to deal with large numbers of devices + Fri Aug 11 13:08:01 CEST 2006 Daniel Veillard * configure.in: updated python detection code from latest libxml2 one @@ -25,9 +42,9 @@ Wed Aug 9 10:17:03 EDT 2006 Daniel Berrange * src/test.c, src/xen_internal.c: Added NULL entry for new driver method for fetching XML * src/proxy_internal.c, src/proxy_internal.h, proxy/libvirt_proxy.c: - Added implmentation of virDomainGetXMLDesc driver method which + Added implmentation of virDomainGetXMLDesc driver method which goes via proxy. - + Tue Aug 8 23:24:51 CEST 2006 Daniel Veillard * src/driver.h src/libvirt.c src/proxy_internal.c src/test.c @@ -38,14 +55,14 @@ Tue Aug 8 23:24:51 CEST 2006 Daniel Veillard Mon Aug 7 18:33:45 EDT 2006 Daniel Berrange - * src/xend_internal.c: Added details of serial console TTY to XML + * src/xend_internal.c: Added details of serial console TTY to XML representation of domain. Fetch VNC port from xenstore if it is available (only in xen 3.0.3 or later). * src/xs_internal.c, src/xs_internal.h: Added APIs for retrieving the serial console TTY and VNC server port from xenstore. * docs/libvir.html: Document 'port' attribute for VNC graphics, and '' element for serial console. - + Mon Aug 7 21:57:41 CEST 2006 Daniel Veillard * TODO: updated with new items @@ -60,7 +77,7 @@ Mon Aug 7 11:06:20 EDT 2006 Daniel Berrange * src/xend_internal.c: Added a 'port' attribute to the '' tag when display type is VNC, providing the port number on which the VNC server is listening. - + Mon Aug 7 18:47:48 CEST 2006 Daniel Veillard * include/libvirt/libvirt.h.in: previous change to libvirt.h should @@ -70,10 +87,10 @@ Fri Aug 4 20:19:23 EDT 2006 Daniel Berrange * src/libvirt.c: Fix off-by-one in validated VCPU number (it is zero based, not one based). - * include/libvirt/libvirt.h: Add some convenience macros for + * include/libvirt/libvirt.h: Add some convenience macros for calculating neccessary CPU map lengths & total host CPUs * src/virsh.c: Add 'vcpuinfo' and 'vcpumap' commands - + Fri Aug 4 14:45:25 CEST 2006 Daniel Veillard * python/generator.py: fix the generator when handling long integers diff --git a/src/libvirt.c b/src/libvirt.c index 47b3267902..4c4a997afd 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -720,7 +720,7 @@ virDomainLookupByName(virConnectPtr conn, const char *name) int virDomainDestroy(virDomainPtr domain) { - int ret = -1, i; + int i; virConnectPtr conn; if (!VIR_IS_CONNECTED_DOMAIN(domain)) { @@ -743,7 +743,7 @@ virDomainDestroy(virDomainPtr domain) (conn->drivers[i]->no != VIR_DRV_XEN_HYPERVISOR) && (conn->drivers[i]->domainDestroy != NULL)) { if (conn->drivers[i]->domainDestroy(domain) == 0) - ret = 0; + return (0); } } for (i = 0;i < conn->nb_drivers;i++) { @@ -751,16 +751,12 @@ virDomainDestroy(virDomainPtr domain) (conn->drivers[i]->no == VIR_DRV_XEN_HYPERVISOR) && (conn->drivers[i]->domainDestroy != NULL)) { if (conn->drivers[i]->domainDestroy(domain) == 0) - ret = 0; + return (0); } } - if (ret != 0) { virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__); - return (ret); - } - - return (ret); + return (-1); } /** @@ -799,7 +795,7 @@ virDomainFree(virDomainPtr domain) int virDomainSuspend(virDomainPtr domain) { - int ret = -1, i; + int i; virConnectPtr conn; if (!VIR_IS_CONNECTED_DOMAIN(domain)) { @@ -822,7 +818,7 @@ virDomainSuspend(virDomainPtr domain) (conn->drivers[i]->no != VIR_DRV_XEN_HYPERVISOR) && (conn->drivers[i]->domainSuspend != NULL)) { if (conn->drivers[i]->domainSuspend(domain) == 0) - ret = 0; + return (0); } } for (i = 0;i < conn->nb_drivers;i++) { @@ -830,16 +826,12 @@ virDomainSuspend(virDomainPtr domain) (conn->drivers[i]->no == VIR_DRV_XEN_HYPERVISOR) && (conn->drivers[i]->domainSuspend != NULL)) { if (conn->drivers[i]->domainSuspend(domain) == 0) - ret = 0; + return (0); } } - if (ret != 0) { virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__); - return (ret); - } - - return (ret); + return (-1); } /** diff --git a/src/xend_internal.c b/src/xend_internal.c index bfe8f22636..810162a01c 100644 --- a/src/xend_internal.c +++ b/src/xend_internal.c @@ -790,6 +790,18 @@ sexpr_uuid(char **ptr, struct sexpr *node, const char *path) if (r == NULL) goto error; + ret = sscanf(r, + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x", + uuid + 0, uuid + 1, uuid + 2, uuid + 3, + uuid + 4, uuid + 5, uuid + 6, uuid + 7, + uuid + 8, uuid + 9, uuid + 10, uuid + 11, + uuid + 12, uuid + 13, uuid + 14, uuid + 15); + if (ret == 16) + goto done; + ret = sscanf(r, "%02x%02x%02x%02x-" "%02x%02x-" @@ -1416,21 +1428,19 @@ xend_parse_sexp_desc_os(struct sexpr *node, virBufferPtr buf, int hvm) virBufferVSprintf(buf, " %s\n", tmp); tmp = sexpr_node(node, "domain/image/hvm/boot"); if ((tmp != NULL) && (tmp[0] != 0)) { - /* - * FIXME: - * Figure out how to map the 'a', 'b', 'c' nonsense to a - * device. - */ if (tmp[0] == 'a') - virBufferAdd(buf, " \n", 25 ); + /* XXX no way to deal with boot from 2nd floppy */ + virBufferAdd(buf, " \n", 21 ); else if (tmp[0] == 'c') /* * Don't know what to put here. Say the vm has been given 3 * disks - hda, hdb, hdc. How does one identify the boot disk? + * We're going to assume that first disk is the boot disk since + * this is most common practice */ - virBufferAdd(buf, " \n", 22 ); + virBufferAdd(buf, " \n", 21 ); else if (strcmp(tmp, "d") == 0) - virBufferAdd(buf, " \n", 29 ); + virBufferAdd(buf, " \n", 24 ); } } else { virBufferVSprintf(buf, " linux\n"); @@ -1482,11 +1492,11 @@ xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root) /* ERROR */ return (NULL); } - ret = malloc(1000); + ret = malloc(4000); if (ret == NULL) return (NULL); buf.content = ret; - buf.size = 1000; + buf.size = 4000; buf.use = 0; domid = sexpr_int(root, "domain/domid"); @@ -1552,7 +1562,7 @@ xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root) continue; if (!memcmp(tmp, "file:", 5)) { tmp += 5; - virBufferVSprintf(&buf, " \n"); + virBufferVSprintf(&buf, " \n"); virBufferVSprintf(&buf, " \n", tmp); tmp = sexpr_node(node, "device/vbd/dev"); @@ -1561,6 +1571,8 @@ xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root) "domain information incomplete, vbd has no dev"); goto error; } + if (!strncmp(tmp, "ioemu:", 6)) + tmp += 6; virBufferVSprintf(&buf, " \n", tmp); tmp = sexpr_node(node, "device/vbd/mode"); if ((tmp != NULL) && (!strcmp(tmp, "r"))) @@ -1568,7 +1580,7 @@ xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root) virBufferAdd(&buf, " \n", 12); } else if (!memcmp(tmp, "phy:", 4)) { tmp += 4; - virBufferVSprintf(&buf, " \n"); + virBufferVSprintf(&buf, " \n"); virBufferVSprintf(&buf, " \n", tmp); tmp = sexpr_node(node, "device/vbd/dev"); if (tmp == NULL) { @@ -1576,6 +1588,8 @@ xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root) "domain information incomplete, vbd has no dev"); goto error; } + if (!strncmp(tmp, "ioemu:", 6)) + tmp += 6; virBufferVSprintf(&buf, " \n", tmp); tmp = sexpr_node(node, "device/vbd/mode"); if ((tmp != NULL) && (!strcmp(tmp, "r"))) @@ -1625,6 +1639,30 @@ xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root) } if (hvm) { + tmp = sexpr_node(root, "domain/image/hvm/fda"); + if ((tmp != NULL) && (tmp[0] != 0)) { + virBufferAdd(&buf, " \n", 39); + virBufferVSprintf(&buf, " \n", tmp); + virBufferAdd(&buf, " \n", 26); + virBufferAdd(&buf, " \n", 12); + } + tmp = sexpr_node(root, "domain/image/hvm/fdb"); + if ((tmp != NULL) && (tmp[0] != 0)) { + virBufferAdd(&buf, " \n", 39); + virBufferVSprintf(&buf, " \n", tmp); + virBufferAdd(&buf, " \n", 26); + virBufferAdd(&buf, " \n", 12); + } + /* XXX new (3.0.3) Xend puts cdrom devs in usual (devices) block */ + tmp = sexpr_node(root, "domain/image/hvm/cdrom"); + if ((tmp != NULL) && (tmp[0] != 0)) { + virBufferAdd(&buf, " \n", 38); + virBufferVSprintf(&buf, " \n", tmp); + virBufferAdd(&buf, " \n", 26); + virBufferAdd(&buf, " \n", 18); + virBufferAdd(&buf, " \n", 12); + } + /* Graphics device */ tmp = sexpr_node(root, "domain/image/hvm/vnc"); if (tmp != NULL) { @@ -1641,11 +1679,6 @@ xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root) if (tmp[0] == '1') virBufferAdd(&buf, " \n", 27 ); } - - /* - * TODO: - * Device for cdrom - */ } tty = xenStoreDomainGetConsolePath(conn, domid); diff --git a/src/xml.c b/src/xml.c index 619f5127e6..255a642417 100644 --- a/src/xml.c +++ b/src/xml.c @@ -268,7 +268,10 @@ virDomainGetXMLDevice(virDomainPtr domain, virBufferPtr buf, long dev) } val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "dev"); if (val != NULL) { - virBufferVSprintf(buf, " \n", val); + char *tmp = val; + if (!strncmp(tmp, "ioemu:", 6)) + tmp += 6; + virBufferVSprintf(buf, " \n", tmp); free(val); } val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "read-only"); @@ -286,7 +289,10 @@ virDomainGetXMLDevice(virDomainPtr domain, virBufferPtr buf, long dev) } val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "dev"); if (val != NULL) { - virBufferVSprintf(buf, " \n", val); + char *tmp = val; + if (!strncmp(tmp, "ioemu:", 6)) + tmp += 6; + virBufferVSprintf(buf, " \n", tmp); free(val); } val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "read-only"); @@ -635,22 +641,72 @@ virDomainParseXMLOSDescHVM(xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr obj = NULL; if (boot_dev) { - /* TODO: - * Have to figure out the naming used here. - */ - if (xmlStrEqual(type, BAD_CAST "hda")) { + if (xmlStrEqual(boot_dev, BAD_CAST "fd")) { virBufferVSprintf(buf, "(boot a)", (const char *) boot_dev); - } else if (xmlStrEqual(type, BAD_CAST "hdd")) { + } else if (xmlStrEqual(boot_dev, BAD_CAST "cdrom")) { virBufferVSprintf(buf, "(boot d)", (const char *) boot_dev); - } else { - /* Force hd[b|c] if boot_dev specified but not floppy or cdrom? */ + } else if (xmlStrEqual(boot_dev, BAD_CAST "hd")) { virBufferVSprintf(buf, "(boot c)", (const char *) boot_dev); + } else { + /* Any other type of boot dev is unsupported right now */ + virXMLError(VIR_ERR_XML_ERROR, NULL, 0); + } + + /* get the 1st floppy device file */ + obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='floppy' and target/@dev='fda']/source", ctxt); + if ((obj != NULL) && (obj->type == XPATH_NODESET) && + (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) { + cur = obj->nodesetval->nodeTab[0]; + virBufferVSprintf(buf, "(fda '%s')", + (const char *) xmlGetProp(cur, BAD_CAST "file")); + cur = NULL; + } + if (obj) { + xmlXPathFreeObject(obj); + obj = NULL; + } + + /* get the 2nd floppy device file */ + obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source", ctxt); + if ((obj != NULL) && (obj->type == XPATH_NODESET) && + (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) { + cur = obj->nodesetval->nodeTab[0]; + virBufferVSprintf(buf, "(fdb '%s')", + (const char *) xmlGetProp(cur, BAD_CAST "file")); + cur = NULL; + } + if (obj) { + xmlXPathFreeObject(obj); + obj = NULL; + } + + + /* get the cdrom device file */ + /* XXX new (3.0.3) Xend puts cdrom devs in usual (devices) block */ + obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source", ctxt); + if ((obj != NULL) && (obj->type == XPATH_NODESET) && + (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) { + cur = obj->nodesetval->nodeTab[0]; + virBufferVSprintf(buf, "(cdrom '%s')", + (const char *) xmlGetProp(cur, BAD_CAST "file")); + cur = NULL; + } + if (obj) { + xmlXPathFreeObject(obj); + obj = NULL; } } - /* TODO: - * Is a cdrom disk device specified? - * Kind of ugly since it is buried in the devices/diskk node. - */ + + obj = xmlXPathEval(BAD_CAST "count(domain/devices/console) > 0", ctxt); + if ((obj == NULL) || (obj->type != XPATH_BOOLEAN)) { + virXMLError(VIR_ERR_XML_ERROR, NULL, 0); + goto error; + } + if (obj->boolval) { + virBufferAdd(buf, "(serial pty)", 12); + } + xmlXPathFreeObject(obj); + obj = NULL; /* Is a graphics device specified? */ obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics[1]", ctxt); @@ -779,10 +835,11 @@ virDomainParseXMLOSDescPV(xmlNodePtr node, virBufferPtr buf) * Returns 0 in case of success, -1 in case of error. */ static int -virDomainParseXMLDiskDesc(xmlNodePtr node, virBufferPtr buf) +virDomainParseXMLDiskDesc(xmlNodePtr node, virBufferPtr buf, int hvm) { xmlNodePtr cur; xmlChar *type = NULL; + xmlChar *device = NULL; xmlChar *source = NULL; xmlChar *target = NULL; int ro = 0; @@ -796,6 +853,8 @@ virDomainParseXMLDiskDesc(xmlNodePtr node, virBufferPtr buf) typ = 1; xmlFree(type); } + device = xmlGetProp(node, BAD_CAST "device"); + cur = node->children; while (cur != NULL) { if (cur->type == XML_ELEMENT_NODE) { @@ -829,7 +888,29 @@ virDomainParseXMLDiskDesc(xmlNodePtr node, virBufferPtr buf) xmlFree(source); return (-1); } + + /* Skip floppy/cdrom disk used as the boot device + * since that's incorporated into the HVM kernel + * (image (hvm..)) part of the sexpr, rather than + * the (devices...) bit. Odd Xend HVM config :-( + * XXX This will have to change in Xen 3.0.3 + */ + if (hvm && device && + (!strcmp((const char *)device, "floppy") || + !strcmp((const char *)device, "cdrom"))) { + return 0; + } + + + virBufferAdd(buf, "(device ", 8); virBufferAdd(buf, "(vbd ", 5); + /* XXX ioemu prefix is going away in Xen 3.0.3 */ + if (hvm) { + char *tmp = (char *)target; + if (!strncmp((const char *) tmp, "ioemu:", 6)) + tmp += 6; + virBufferVSprintf(buf, "(dev 'ioemu:%s')", (const char *) tmp); + } else virBufferVSprintf(buf, "(dev '%s')", (const char *) target); if (typ == 0) virBufferVSprintf(buf, "(uname 'file:%s')", source); @@ -844,6 +925,7 @@ virDomainParseXMLDiskDesc(xmlNodePtr node, virBufferPtr buf) else if (ro == 1) virBufferVSprintf(buf, "(mode 'r')"); + virBufferAdd(buf, ")", 1); virBufferAdd(buf, ")", 1); xmlFree(target); xmlFree(source); @@ -912,6 +994,7 @@ virDomainParseXMLIfDesc(xmlNodePtr node, virBufferPtr buf) } if (script != NULL) virBufferVSprintf(buf, "(script '%s')", script); + virBufferAdd(buf, "(type ioemu)", 12); virBufferAdd(buf, ")", 1); if (mac != NULL) @@ -948,6 +1031,7 @@ virDomainParseXMLDesc(const char *xmldesc, char **name) xmlXPathContextPtr ctxt = NULL; int i, res; int bootloader = 0; + int hvm = 0; if (name != NULL) *name = NULL; @@ -1072,6 +1156,7 @@ virDomainParseXMLDesc(const char *xmldesc, char **name) if ((tmpobj == NULL) || !xmlStrEqual(tmpobj->stringval, BAD_CAST "hvm")) { res = virDomainParseXMLOSDescPV(obj->nodesetval->nodeTab[0], &buf); } else { + hvm = 1; res = virDomainParseXMLOSDescHVM(obj->nodesetval->nodeTab[0], &buf, ctxt); } @@ -1090,12 +1175,10 @@ virDomainParseXMLDesc(const char *xmldesc, char **name) if ((obj != NULL) && (obj->type == XPATH_NODESET) && (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { for (i = 0; i < obj->nodesetval->nodeNr; i++) { - virBufferAdd(&buf, "(device ", 8); - res = virDomainParseXMLDiskDesc(obj->nodesetval->nodeTab[i], &buf); + res = virDomainParseXMLDiskDesc(obj->nodesetval->nodeTab[i], &buf, hvm); if (res != 0) { goto error; } - virBufferAdd(&buf, ")", 1); } } xmlXPathFreeObject(obj);