[libvirt] PATCH: 0/14: Generic XML parsers/formatters for all drivers

The following series of patchs provide a generic XML parser and formatter for the network and domain XML config formats. They then switch over the test, qemu, Xend and XM drivers to these APIs. The LXC driver is work in progress. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This change adjusts the XML parsing routines so that they will preserve the context node when evaluating XPath expressions. This allows us to use relative XPath expressions reliably in the parsers. Needed one tiny fix to a typo in the Xen driver to work xml.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) Daniel diff -r e72258d9d0d1 src/xml.c --- a/src/xml.c Mon Jul 07 11:13:21 2008 +0100 +++ b/src/xml.c Mon Jul 07 11:37:50 2008 +0100 @@ -386,6 +386,7 @@ virXPathString(const char *xpath, xmlXPathContextPtr ctxt) { xmlXPathObjectPtr obj; + xmlNodePtr relnode; char *ret; if ((ctxt == NULL) || (xpath == NULL)) { @@ -393,6 +394,7 @@ _("Invalid parameter to virXPathString()"), 0); return (NULL); } + relnode = ctxt->node; obj = xmlXPathEval(BAD_CAST xpath, ctxt); if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) || (obj->stringval[0] == 0)) { @@ -404,6 +406,7 @@ if (ret == NULL) { virXMLError(NULL, VIR_ERR_NO_MEMORY, _("strdup failed"), 0); } + ctxt->node = relnode; return (ret); } @@ -422,21 +425,25 @@ virXPathNumber(const char *xpath, xmlXPathContextPtr ctxt, double *value) { xmlXPathObjectPtr obj; + xmlNodePtr relnode; if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) { virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, _("Invalid parameter to virXPathNumber()"), 0); return (-1); } + relnode = ctxt->node; obj = xmlXPathEval(BAD_CAST xpath, ctxt); if ((obj == NULL) || (obj->type != XPATH_NUMBER) || (isnan(obj->floatval))) { xmlXPathFreeObject(obj); + ctxt->node = relnode; return (-1); } *value = obj->floatval; xmlXPathFreeObject(obj); + ctxt->node = relnode; return (0); } @@ -456,6 +463,7 @@ virXPathLong(const char *xpath, xmlXPathContextPtr ctxt, long *value) { xmlXPathObjectPtr obj; + xmlNodePtr relnode; int ret = 0; if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) { @@ -463,6 +471,7 @@ _("Invalid parameter to virXPathNumber()"), 0); return (-1); } + relnode = ctxt->node; obj = xmlXPathEval(BAD_CAST xpath, ctxt); if ((obj != NULL) && (obj->type == XPATH_STRING) && (obj->stringval != NULL) && (obj->stringval[0] != 0)) { @@ -486,6 +495,7 @@ } xmlXPathFreeObject(obj); + ctxt->node = relnode; return (ret); } @@ -502,6 +512,7 @@ virXPathBoolean(const char *xpath, xmlXPathContextPtr ctxt) { xmlXPathObjectPtr obj; + xmlNodePtr relnode; int ret; if ((ctxt == NULL) || (xpath == NULL)) { @@ -509,6 +520,7 @@ _("Invalid parameter to virXPathBoolean()"), 0); return (-1); } + relnode = ctxt->node; obj = xmlXPathEval(BAD_CAST xpath, ctxt); if ((obj == NULL) || (obj->type != XPATH_BOOLEAN) || (obj->boolval < 0) || (obj->boolval > 1)) { @@ -518,6 +530,7 @@ ret = obj->boolval; xmlXPathFreeObject(obj); + ctxt->node = relnode; return (ret); } @@ -535,6 +548,7 @@ virXPathNode(const char *xpath, xmlXPathContextPtr ctxt) { xmlXPathObjectPtr obj; + xmlNodePtr relnode; xmlNodePtr ret; if ((ctxt == NULL) || (xpath == NULL)) { @@ -542,16 +556,19 @@ _("Invalid parameter to virXPathNode()"), 0); return (NULL); } + relnode = ctxt->node; obj = xmlXPathEval(BAD_CAST xpath, ctxt); if ((obj == NULL) || (obj->type != XPATH_NODESET) || (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) || (obj->nodesetval->nodeTab == NULL)) { xmlXPathFreeObject(obj); + ctxt->node = relnode; return (NULL); } ret = obj->nodesetval->nodeTab[0]; xmlXPathFreeObject(obj); + ctxt->node = relnode; return (ret); } @@ -571,6 +588,7 @@ xmlNodePtr ** list) { xmlXPathObjectPtr obj; + xmlNodePtr relnode; int ret; if ((ctxt == NULL) || (xpath == NULL)) { @@ -578,6 +596,7 @@ _("Invalid parameter to virXPathNodeSet()"), 0); return (-1); } + relnode = ctxt->node; obj = xmlXPathEval(BAD_CAST xpath, ctxt); if ((obj == NULL) || (obj->type != XPATH_NODESET) || (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) || @@ -585,6 +604,7 @@ xmlXPathFreeObject(obj); if (list != NULL) *list = NULL; + ctxt->node = relnode; return (-1); } @@ -601,6 +621,7 @@ } } xmlXPathFreeObject(obj); + ctxt->node = relnode; return (ret); } @@ -1139,7 +1160,7 @@ goto error; virBufferVSprintf(buf, "(serial %s)", scratch); } else { - res = virXPathBoolean("count(domain/devices/console) > 0", ctxt); + res = virXPathBoolean("count(/domain/devices/console) > 0", ctxt); if (res < 0) { virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0); goto error; -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Tue, Jul 08, 2008 at 05:32:45PM +0100, Daniel P. Berrange wrote:
This change adjusts the XML parsing routines so that they will preserve the context node when evaluating XPath expressions. This allows us to use relative XPath expressions reliably in the parsers. Needed one tiny fix to a typo in the Xen driver to work
+1 that's needed for Relative XPath expression evaluations, Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

On Tue, Jul 08, 2008 at 12:49:12PM -0400, Daniel Veillard wrote:
On Tue, Jul 08, 2008 at 05:32:45PM +0100, Daniel P. Berrange wrote:
This change adjusts the XML parsing routines so that they will preserve the context node when evaluating XPath expressions. This allows us to use relative XPath expressions reliably in the parsers. Needed one tiny fix to a typo in the Xen driver to work
+1 that's needed for Relative XPath expression evaluations,
Ok, I've committed this one since its trivial. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

We currently have two drivers which handle the networking XML containing duplicated parsers and formatters for the XML, and very similar structs. This patch introduces a new general purpose internal API for parsing and formatting network XML, and representing it as a series of structs. This code is derived from the current equivalent code in the QEMU driver for networks. The naming conventions I'm adopting in this patch follow those in the storage driver: - virNetworkPtr - the public opaque object in libvirt.h - virNetworkObjPtr - the primary internal object for network state - virNetworkDefPtr - the configuration data for a network A virNetworkObjPtr contains a reference to one or two virNetworkDefPtr objects - the current live config, and potentially a secondary inactive config which will become live at the next restart. The structs are defined in network_conf.h, along with a bunch of APIs for dealing with them. These APIs are the same as similarly named ones from the current qemu driver, but I'll go over them again for a reminder: virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjPtr nets, const unsigned char *uuid); virNetworkObjPtr virNetworkFindByName(const virNetworkObjPtr nets, const char *name); Allow lookup of a virNetworkObjPtr object based on its name or UUID, as typically obtained from the public virNetworkPtr object. The 'nets' parameter to both of thse is a linked list of networks which are currently known to the driver using this API. void virNetworkDefFree(virNetworkDefPtr def); void virNetworkObjFree(virNetworkObjPtr net); Convenience APIs to totally free the memory associated with these objects. virNetworkObjPtr virNetworkAssignDef(virConnectPtr conn, virNetworkObjPtr *nets, const virNetworkDefPtr def); Given a virNetworkDefPtr object, it'll search for a pre-existing virNetworkObjPtr object with matching config. If one is found, its config will be updated, otherwise a new object will be allocated. void virNetworkRemoveInactive(virNetworkObjPtr *nets, const virNetworkObjPtr net); Convenience for removing and free'ing a virNetworkObjPtr object in the current list of active networks. virNetworkDefPtr virNetworkDefParseString(virConnectPtr conn, const char *xmlStr); virNetworkDefPtr virNetworkDefParseFile(virConnectPtr conn, const char *filename); virNetworkDefPtr virNetworkDefParseNode(virConnectPtr conn, xmlDocPtr xml, xmlNodePtr root); Based on DV's suggestion the parsing methods have changed slightly so instead of only allowing a string to be parsed, we can directly parse a file, or a XML node object. char *virNetworkDefFormat(virConnectPtr conn, const virNetworkDefPtr def); Given a virNetworkDefPtr object, generate a XML document describing the network. For drivers which no other persistent storage native to their virt type, there are helper methods for loading and saving the XML configs to files. This is primarily for QEMU and LXC drivers int virNetworkSaveConfig(virConnectPtr conn, const char *configDir, const char *autostartDir, virNetworkObjPtr net); virNetworkObjPtr virNetworkLoadConfig(virConnectPtr conn, virNetworkObjPtr *nets, const char *configDir, const char *autostartDir, const char *file); int virNetworkLoadAllConfigs(virConnectPtr conn, virNetworkObjPtr *nets, const char *configDir, const char *autostartDir); int virNetworkDeleteConfig(virConnectPtr conn, virNetworkObjPtr net); As a mentioned earlier, the impl of these APIs is just copied from the QEMU driver, but instead of using pre-declared char[PATH_MAX] fields, we allocate memory for strings as required. Other misc changes from last time - we introduce a VIR_FROM_NETWORK class for reporting errors against b/src/network_conf.c | 688 ++++++++++++++++++++++++++++++++++++++++++++ b/src/network_conf.h | 137 ++++++++ include/libvirt/virterror.h | 1 po/POTFILES.in | 1 src/Makefile.am | 1 src/virterror.c | 3 src/xml.c | 52 +++ src/xml.h | 3 8 files changed, 886 insertions(+) Daniel diff -r 097ed9d9ae46 include/libvirt/virterror.h --- a/include/libvirt/virterror.h Mon Jul 07 12:06:49 2008 +0100 +++ b/include/libvirt/virterror.h Tue Jul 08 15:26:26 2008 +0100 @@ -56,6 +56,7 @@ VIR_FROM_STATS_LINUX, /* Error in the Linux Stats code */ VIR_FROM_LXC, /* Error from Linux Container driver */ VIR_FROM_STORAGE, /* Error from storage driver */ + VIR_FROM_NETWORK, /* Error from network config */ } virErrorDomain; diff -r 097ed9d9ae46 po/POTFILES.in --- a/po/POTFILES.in Mon Jul 07 12:06:49 2008 +0100 +++ b/po/POTFILES.in Tue Jul 08 15:26:26 2008 +0100 @@ -9,6 +9,7 @@ src/lxc_conf.c src/lxc_container.c src/lxc_driver.c +src/network_conf.c src/openvz_conf.c src/openvz_driver.c src/proxy_internal.c diff -r 097ed9d9ae46 src/Makefile.am --- a/src/Makefile.am Mon Jul 07 12:06:49 2008 +0100 +++ b/src/Makefile.am Tue Jul 08 15:26:26 2008 +0100 @@ -52,6 +52,7 @@ driver.h \ proxy_internal.c proxy_internal.h \ conf.c conf.h \ + network_conf.c network_conf.h \ xm_internal.c xm_internal.h \ remote_internal.c remote_internal.h \ bridge.c bridge.h \ diff -r 097ed9d9ae46 src/network_conf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/network_conf.c Tue Jul 08 15:26:26 2008 +0100 @@ -0,0 +1,688 @@ +/* + * network_conf.c: network XML handling + * + * Copyright (C) 2006-2008 Red Hat, Inc. + * Copyright (C) 2006-2008 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange <berrange@redhat.com> + */ + + + +#include <config.h> + +#include <arpa/inet.h> +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#include <dirent.h> + +#include "internal.h" + +#include "network_conf.h" +#include "memory.h" +#include "xml.h" +#include "uuid.h" +#include "util.h" +#include "buf.h" + +VIR_ENUM_DECL(virNetworkForward) + +VIR_ENUM_IMPL(virNetworkForward, + VIR_NETWORK_FORWARD_LAST, + "none", "nat", "route" ) + +static void virNetworkReportError(virConnectPtr conn, + int code, const char *fmt, ...) +{ + va_list args; + char errorMessage[1024]; + const char *virerr; + + if (fmt) { + va_start(args, fmt); + vsnprintf(errorMessage, sizeof(errorMessage)-1, fmt, args); + va_end(args); + } else { + errorMessage[0] = '\0'; + } + + virerr = __virErrorMsg(code, (errorMessage[0] ? errorMessage : NULL)); + __virRaiseError(conn, NULL, NULL, VIR_FROM_NETWORK, code, VIR_ERR_ERROR, + virerr, errorMessage, NULL, -1, -1, virerr, errorMessage); +} + + +virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjPtr nets, + const unsigned char *uuid) +{ + virNetworkObjPtr net = nets; + while (net) { + if (!memcmp(net->def->uuid, uuid, VIR_UUID_BUFLEN)) + return net; + net = net->next; + } + + return NULL; +} + +virNetworkObjPtr virNetworkFindByName(const virNetworkObjPtr nets, + const char *name) +{ + virNetworkObjPtr net = nets; + while (net) { + if (STREQ(net->def->name, name)) + return net; + net = net->next; + } + + return NULL; +} + + +void virNetworkDefFree(virNetworkDefPtr def) +{ + int i; + + if (!def) + return; + + VIR_FREE(def->name); + VIR_FREE(def->bridge); + VIR_FREE(def->forwardDev); + VIR_FREE(def->ipAddress); + VIR_FREE(def->network); + VIR_FREE(def->netmask); + + for (i = 0 ; i < def->nranges && def->ranges ; i++) { + VIR_FREE(def->ranges[i].start); + VIR_FREE(def->ranges[i].end); + } + VIR_FREE(def->ranges); + + VIR_FREE(def); +} + +void virNetworkObjFree(virNetworkObjPtr net) +{ + if (!net) + return; + + virNetworkDefFree(net->def); + virNetworkDefFree(net->newDef); + + VIR_FREE(net->configFile); + VIR_FREE(net->autostartLink); + + VIR_FREE(net); +} + +virNetworkObjPtr virNetworkAssignDef(virConnectPtr conn, + virNetworkObjPtr *nets, + const virNetworkDefPtr def) +{ + virNetworkObjPtr network; + + if ((network = virNetworkFindByName(*nets, def->name))) { + if (!virNetworkIsActive(network)) { + virNetworkDefFree(network->def); + network->def = def; + } else { + if (network->newDef) + virNetworkDefFree(network->newDef); + network->newDef = def; + } + + return network; + } + + if (VIR_ALLOC(network) < 0) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + network->def = def; + network->next = *nets; + + *nets = network; + + return network; + +} + +void virNetworkRemoveInactive(virNetworkObjPtr *nets, + const virNetworkObjPtr net) +{ + virNetworkObjPtr prev = NULL; + virNetworkObjPtr curr = *nets; + + while (curr && + curr != net) { + prev = curr; + curr = curr->next; + } + + if (curr) { + if (prev) + prev->next = curr->next; + else + *nets = curr->next; + } + + virNetworkObjFree(net); +} + + +static int +virNetworkDHCPRangeDefParseXML(virConnectPtr conn, + virNetworkDefPtr def, + xmlNodePtr node) { + + xmlNodePtr cur; + + cur = node->children; + while (cur != NULL) { + xmlChar *start, *end; + + if (cur->type != XML_ELEMENT_NODE || + !xmlStrEqual(cur->name, BAD_CAST "range")) { + cur = cur->next; + continue; + } + + if (!(start = xmlGetProp(cur, BAD_CAST "start"))) { + cur = cur->next; + continue; + } + if (!(end = xmlGetProp(cur, BAD_CAST "end"))) { + cur = cur->next; + xmlFree(start); + continue; + } + + if (VIR_REALLOC_N(def->ranges, def->nranges + 1) < 0) { + xmlFree(start); + xmlFree(end); + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return -1; + } + def->ranges[def->nranges].start = (char *)start; + def->ranges[def->nranges].end = (char *)end; + def->nranges++; + + cur = cur->next; + } + + return 0; +} + +static virNetworkDefPtr +virNetworkDefParseXML(virConnectPtr conn, + xmlXPathContextPtr ctxt) +{ + virNetworkDefPtr def; + char *tmp; + + if (VIR_ALLOC(def) < 0) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + /* Extract network name */ + def->name = virXPathString("string(./name[1])", ctxt); + if (!def->name) { + virNetworkReportError(conn, VIR_ERR_NO_NAME, NULL); + goto error; + } + + /* Extract network uuid */ + tmp = virXPathString("string(./uuid[1])", ctxt); + if (!tmp) { + int err; + if ((err = virUUIDGenerate(def->uuid))) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Failed to generate UUID: %s"), strerror(err)); + goto error; + } + } else { + if (virUUIDParse(tmp, def->uuid) < 0) { + VIR_FREE(tmp); + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("malformed uuid element")); + goto error; + } + VIR_FREE(tmp); + } + + /* Parse bridge information */ + def->bridge = virXPathString("string(./bridge[1]/@name)", ctxt); + tmp = virXPathString("string(./bridge[1]/@stp)", ctxt); + def->stp = (tmp && STREQ(tmp, "off")) ? 0 : 1; + VIR_FREE(tmp); + + if (virXPathULong("string(./bridge[1]/@delay)", ctxt, &def->delay) < 0) + def->delay = 0; + + def->ipAddress = virXPathString("string(./ip[1]/@address)", ctxt); + def->netmask = virXPathString("string(./ip[1]/@netmask)", ctxt); + if (def->ipAddress && + def->netmask) { + /* XXX someday we want IPv6 too, so inet_aton won't work there */ + struct in_addr inaddress, innetmask; + char *netaddr; + xmlNodePtr dhcp; + + if (!inet_aton(def->ipAddress, &inaddress)) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot parse IP address '%s'"), + def->ipAddress); + goto error; + } + if (!inet_aton(def->netmask, &innetmask)) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot parse netmask '%s'"), + def->netmask); + goto error; + } + + inaddress.s_addr &= innetmask.s_addr; + netaddr = inet_ntoa(inaddress); + + if (asprintf(&def->network, "%s/%s", netaddr, def->netmask) < 0) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + + if ((dhcp = virXPathNode("./ip[1]/dhcp[1]", ctxt)) && + virNetworkDHCPRangeDefParseXML(conn, def, dhcp) < 0) + goto error; + } + + + /* IPv4 forwarding setup */ + if (virXPathBoolean("count(./forward) > 0", ctxt)) { + if (!def->ipAddress || + !def->netmask) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Forwarding requested, but no IPv4 address/netmask provided")); + goto error; + } + + tmp = virXPathString("string(./forward[1]/@mode)", ctxt); + if (tmp) { + if ((def->forwardType = virNetworkForwardTypeFromString(tmp)) < 0) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown forwarding type '%s'"), tmp); + VIR_FREE(tmp); + goto error; + } + VIR_FREE(tmp); + } else { + def->forwardType = VIR_NETWORK_FORWARD_NAT; + } + + + def->forwardDev = virXPathString("string(./forward[1]/@dev)", ctxt); + } else { + def->forwardType = VIR_NETWORK_FORWARD_NONE; + } + + return def; + + error: + virNetworkDefFree(def); + return NULL; +} + +virNetworkDefPtr virNetworkDefParseString(virConnectPtr conn, + const char *xmlStr) +{ + xmlDocPtr xml; + xmlNodePtr root; + virNetworkDefPtr def; + + if (!(xml = xmlReadDoc(BAD_CAST xmlStr, "network.xml", NULL, + XML_PARSE_NOENT | XML_PARSE_NONET | + XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { + virNetworkReportError(conn, VIR_ERR_XML_ERROR, NULL); + return NULL; + } + + if ((root = xmlDocGetRootElement(xml)) == NULL) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("missing root element")); + xmlFreeDoc(xml); + return NULL; + } + + def = virNetworkDefParseNode(conn, xml, root); + + xmlFreeDoc(xml); + return def; +} + +virNetworkDefPtr virNetworkDefParseFile(virConnectPtr conn, + const char *filename) +{ + xmlDocPtr xml; + xmlNodePtr root; + virNetworkDefPtr def; + + if (!(xml = xmlReadFile(filename, NULL, + XML_PARSE_NOENT | XML_PARSE_NONET | + XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { + virNetworkReportError(conn, VIR_ERR_XML_ERROR, NULL); + return NULL; + } + + if ((root = xmlDocGetRootElement(xml)) == NULL) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("missing root element")); + xmlFreeDoc(xml); + return NULL; + } + + def = virNetworkDefParseNode(conn, xml, root); + + xmlFreeDoc(xml); + return def; +} + + +virNetworkDefPtr virNetworkDefParseNode(virConnectPtr conn, + xmlDocPtr xml, + xmlNodePtr root) +{ + xmlXPathContextPtr ctxt = NULL; + virNetworkDefPtr def = NULL; + + if (!xmlStrEqual(root->name, BAD_CAST "network")) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("incorrect root element")); + goto cleanup; + } + + ctxt = xmlXPathNewContext(xml); + if (ctxt == NULL) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto cleanup; + } + + ctxt->node = root; + def = virNetworkDefParseXML(conn, ctxt); + +cleanup: + xmlXPathFreeContext(ctxt); + return def; +} + +char *virNetworkDefFormat(virConnectPtr conn, + const virNetworkDefPtr def) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + unsigned char *uuid; + char *tmp; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + virBufferAddLit(&buf, "<network>\n"); + virBufferEscapeString(&buf, " <name>%s</name>\n", def->name); + + uuid = def->uuid; + virUUIDFormat(uuid, uuidstr); + virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr); + + if (def->forwardType != VIR_NETWORK_FORWARD_NONE) { + const char *mode = virNetworkForwardTypeToString(def->forwardType); + if (mode) { + if (def->forwardDev) { + virBufferEscapeString(&buf, " <forward dev='%s'", + def->forwardDev); + } else { + virBufferAddLit(&buf, " <forward"); + } + virBufferVSprintf(&buf, " mode='%s'/>\n", mode); + } + } + + virBufferAddLit(&buf, " <bridge"); + if (def->bridge) + virBufferEscapeString(&buf, " name='%s'", def->bridge); + virBufferVSprintf(&buf, " stp='%s' forwardDelay='%ld' />\n", + def->stp ? "on" : "off", + def->delay); + + if (def->ipAddress || def->netmask) { + virBufferAddLit(&buf, " <ip"); + + if (def->ipAddress) + virBufferVSprintf(&buf, " address='%s'", def->ipAddress); + + if (def->netmask) + virBufferVSprintf(&buf, " netmask='%s'", def->netmask); + + virBufferAddLit(&buf, ">\n"); + + if (def->nranges) { + int i; + virBufferAddLit(&buf, " <dhcp>\n"); + for (i = 0 ; i < def->nranges ; i++) + virBufferVSprintf(&buf, " <range start='%s' end='%s' />\n", + def->ranges[i].start, def->ranges[i].end); + virBufferAddLit(&buf, " </dhcp>\n"); + } + + virBufferAddLit(&buf, " </ip>\n"); + } + + virBufferAddLit(&buf, "</network>\n"); + + if (virBufferError(&buf)) + goto no_memory; + + return virBufferContentAndReset(&buf); + + no_memory: + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + tmp = virBufferContentAndReset(&buf); + VIR_FREE(tmp); + return NULL; +} + +int virNetworkSaveConfig(virConnectPtr conn, + const char *configDir, + const char *autostartDir, + virNetworkObjPtr net) +{ + char *xml; + int fd = -1, ret = -1; + int towrite; + int err; + + if (!net->configFile && + asprintf(&net->configFile, "%s/%s.xml", + configDir, net->def->name) < 0) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto cleanup; + } + if (!net->autostartLink && + asprintf(&net->autostartLink, "%s/%s.xml", + autostartDir, net->def->name) < 0) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto cleanup; + } + + if (!(xml = virNetworkDefFormat(conn, + net->newDef ? net->newDef : net->def))) + return -1; + + if ((err = virFileMakePath(configDir))) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot create config directory %s: %s"), + configDir, strerror(err)); + goto cleanup; + } + + if ((err = virFileMakePath(autostartDir))) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot create autostart directory %s: %s"), + autostartDir, strerror(err)); + goto cleanup; + } + + if ((fd = open(net->configFile, + O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR )) < 0) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot create config file %s: %s"), + net->configFile, strerror(errno)); + goto cleanup; + } + + towrite = strlen(xml); + if (safewrite(fd, xml, towrite) < 0) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot write config file %s: %s"), + net->configFile, strerror(errno)); + goto cleanup; + } + + if (close(fd) < 0) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot save config file %s: %s"), + net->configFile, strerror(errno)); + goto cleanup; + } + + ret = 0; + + cleanup: + VIR_FREE(xml); + close(fd); + + return ret; +} + +virNetworkObjPtr virNetworkLoadConfig(virConnectPtr conn, + virNetworkObjPtr *nets, + const char *configDir, + const char *autostartDir, + const char *file) +{ + char *configFile, *autostartLink; + virNetworkDefPtr def = NULL; + virNetworkObjPtr net; + int autostart; + + if (asprintf(&configFile, "%s/%s", + configDir, file) < 0) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + if (asprintf(&autostartLink, "%s/%s", + autostartDir, file) < 0) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + + if ((autostart = virFileLinkPointsTo(autostartLink, configFile)) < 0) + goto error; + + if (!(def = virNetworkDefParseFile(conn, file))) + goto error; + + if (!virFileMatchesNameSuffix(file, def->name, ".xml")) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Network config filename '%s'" + " does not match network name '%s'"), + configFile, def->name); + goto error; + } + + if (!(net = virNetworkAssignDef(conn, nets, def))) + goto error; + + net->configFile = configFile; + net->autostartLink = autostartLink; + net->autostart = autostart; + + return net; + +error: + VIR_FREE(configFile); + VIR_FREE(autostartLink); + virNetworkDefFree(def); + return NULL; +} + +int virNetworkLoadAllConfigs(virConnectPtr conn, + virNetworkObjPtr *nets, + const char *configDir, + const char *autostartDir) +{ + DIR *dir; + struct dirent *entry; + + if (!(dir = opendir(configDir))) { + if (errno == ENOENT) + return 0; + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Failed to open dir '%s': %s"), + configDir, strerror(errno)); + return -1; + } + + while ((entry = readdir(dir))) { + if (entry->d_name[0] == '.') + continue; + + if (!virFileHasSuffix(entry->d_name, ".xml")) + continue; + + /* NB: ignoring errors, so one malformed config doesn't + kill the whole process */ + virNetworkLoadConfig(conn, + nets, + configDir, + autostartDir, + entry->d_name); + } + + closedir(dir); + + return 0; +} + +int virNetworkDeleteConfig(virConnectPtr conn, + virNetworkObjPtr net) +{ + if (!net->configFile || !net->autostartLink) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("no config file for %s"), net->def->name); + return -1; + } + + /* Not fatal if this doesn't work */ + unlink(net->autostartLink); + + if (unlink(net->configFile) < 0) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot remove config for %s"), net->def->name); + return -1; + } + + return 0; +} diff -r 097ed9d9ae46 src/network_conf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/network_conf.h Tue Jul 08 15:26:26 2008 +0100 @@ -0,0 +1,137 @@ +/* + * network_conf.h: network XML handling + * + * Copyright (C) 2006-2008 Red Hat, Inc. + * Copyright (C) 2006-2008 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange <berrange@redhat.com> + */ + +#ifndef __NETWORK_CONF_H__ +#define __NETWORK_CONF_H__ + +#include "internal.h" + +/* 2 possible types of forwarding */ +enum virNetworkForwardType { + VIR_NETWORK_FORWARD_NONE = 0, + VIR_NETWORK_FORWARD_NAT, + VIR_NETWORK_FORWARD_ROUTE, + + VIR_NETWORK_FORWARD_LAST, +}; + +typedef struct _virNetworkDHCPRangeDef virNetworkDHCPRangeDef; +typedef virNetworkDHCPRangeDef *virNetworkDHCPRangeDefPtr; +struct _virNetworkDHCPRangeDef { + char *start; + char *end; +}; + +typedef struct _virNetworkDef virNetworkDef; +typedef virNetworkDef *virNetworkDefPtr; +struct _virNetworkDef { + unsigned char uuid[VIR_UUID_BUFLEN]; + char *name; + + char *bridge; /* Name of bridge device */ + int stp : 1; /* Spanning tree protocol */ + unsigned long delay; /* Bridge forward delay (ms) */ + + int forwardType; /* One of virNetworkForwardType constants */ + char *forwardDev; /* Destination device for forwarding */ + + char *ipAddress; /* Bridge IP address */ + char *netmask; + char *network; + + unsigned int nranges; /* Zero or more dhcp ranges */ + virNetworkDHCPRangeDefPtr ranges; +}; + +typedef struct _virNetworkObj virNetworkObj; +typedef virNetworkObj *virNetworkObjPtr; +struct _virNetworkObj { + pid_t dnsmasqPid; + unsigned int active : 1; + unsigned int autostart : 1; + unsigned int persistent : 1; + + char *configFile; /* Persistent config file path */ + char *autostartLink; /* Symlink path for autostart */ + + virNetworkDefPtr def; /* The current definition */ + virNetworkDefPtr newDef; /* New definition to activate at shutdown */ + + virNetworkObjPtr next; +}; + +static inline int +virNetworkIsActive(const virNetworkObjPtr net) +{ + return net->active; +} + + +virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjPtr nets, + const unsigned char *uuid); +virNetworkObjPtr virNetworkFindByName(const virNetworkObjPtr nets, + const char *name); + + +void virNetworkDefFree(virNetworkDefPtr def); +void virNetworkObjFree(virNetworkObjPtr net); + +virNetworkObjPtr virNetworkAssignDef(virConnectPtr conn, + virNetworkObjPtr *nets, + const virNetworkDefPtr def); +void virNetworkRemoveInactive(virNetworkObjPtr *nets, + const virNetworkObjPtr net); + +virNetworkDefPtr virNetworkDefParseString(virConnectPtr conn, + const char *xmlStr); +virNetworkDefPtr virNetworkDefParseFile(virConnectPtr conn, + const char *filename); +virNetworkDefPtr virNetworkDefParseNode(virConnectPtr conn, + xmlDocPtr xml, + xmlNodePtr root); + +char *virNetworkDefFormat(virConnectPtr conn, + const virNetworkDefPtr def); + + +int virNetworkSaveConfig(virConnectPtr conn, + const char *configDir, + const char *autostartDir, + virNetworkObjPtr net); + +virNetworkObjPtr virNetworkLoadConfig(virConnectPtr conn, + virNetworkObjPtr *nets, + const char *configDir, + const char *autostartDir, + const char *file); + +int virNetworkLoadAllConfigs(virConnectPtr conn, + virNetworkObjPtr *nets, + const char *configDir, + const char *autostartDir); + +int virNetworkDeleteConfig(virConnectPtr conn, + virNetworkObjPtr net); + +#endif /* __NETWORK_CONF_H__ */ + diff -r 097ed9d9ae46 src/virterror.c --- a/src/virterror.c Mon Jul 07 12:06:49 2008 +0100 +++ b/src/virterror.c Tue Jul 08 15:26:26 2008 +0100 @@ -303,6 +303,9 @@ break; case VIR_FROM_STORAGE: dom = "Storage "; + break; + case VIR_FROM_NETWORK: + dom = "Network Config "; break; } diff -r 097ed9d9ae46 src/xml.c --- a/src/xml.c Mon Jul 07 12:06:49 2008 +0100 +++ b/src/xml.c Tue Jul 08 15:26:26 2008 +0100 @@ -500,6 +500,58 @@ } /** + * virXPathULong: + * @xpath: the XPath string to evaluate + * @ctxt: an XPath context + * @value: the returned long value + * + * Convenience function to evaluate an XPath number + * + * Returns 0 in case of success in which case @value is set, + * or -1 if the XPath evaluation failed or -2 if the + * value doesn't have a long format. + */ +int +virXPathULong(const char *xpath, xmlXPathContextPtr ctxt, unsigned long *value) +{ + xmlXPathObjectPtr obj; + xmlNodePtr relnode; + int ret = 0; + + if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) { + virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, + _("Invalid parameter to virXPathNumber()"), 0); + return (-1); + } + relnode = ctxt->node; + obj = xmlXPathEval(BAD_CAST xpath, ctxt); + if ((obj != NULL) && (obj->type == XPATH_STRING) && + (obj->stringval != NULL) && (obj->stringval[0] != 0)) { + char *conv = NULL; + long val; + + val = strtoul((const char *) obj->stringval, &conv, 10); + if (conv == (const char *) obj->stringval) { + ret = -2; + } else { + *value = val; + } + } else if ((obj != NULL) && (obj->type == XPATH_NUMBER) && + (!(isnan(obj->floatval)))) { + *value = (unsigned long) obj->floatval; + if (*value != obj->floatval) { + ret = -2; + } + } else { + ret = -1; + } + + xmlXPathFreeObject(obj); + ctxt->node = relnode; + return (ret); +} + +/** * virXPathBoolean: * @xpath: the XPath string to evaluate * @ctxt: an XPath context diff -r 097ed9d9ae46 src/xml.h --- a/src/xml.h Mon Jul 07 12:06:49 2008 +0100 +++ b/src/xml.h Tue Jul 08 15:26:26 2008 +0100 @@ -26,6 +26,9 @@ int virXPathLong (const char *xpath, xmlXPathContextPtr ctxt, long *value); +int virXPathULong (const char *xpath, + xmlXPathContextPtr ctxt, + unsigned long *value); xmlNodePtr virXPathNode (const char *xpath, xmlXPathContextPtr ctxt); int virXPathNodeSet (const char *xpath, -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Modulo some minor problems, ACK. Even though I reviewed only the incremental diffs, there was a bit of new material. BTW, nice catch, with the new uses of virBufferEscapeString.
+virNetworkDefPtr virNetworkDefParseNode(virConnectPtr conn, + xmlDocPtr xml, + xmlNodePtr root) +{ + xmlXPathContextPtr ctxt = NULL; + virNetworkDefPtr def = NULL; + + if (!xmlStrEqual(root->name, BAD_CAST "network")) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("incorrect root element")); + goto cleanup; + }
No big deal, but the above goto could be "return NULL;".
+ ctxt = xmlXPathNewContext(xml); + if (ctxt == NULL) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto cleanup; + } + + ctxt->node = root; + def = virNetworkDefParseXML(conn, ctxt); + +cleanup: + xmlXPathFreeContext(ctxt); + return def; +} ... +int virNetworkSaveConfig(virConnectPtr conn, + const char *configDir, + const char *autostartDir, + virNetworkObjPtr net) +{ + char *xml; + int fd = -1, ret = -1; + int towrite;
Use size_t, not int.
+ int err; + + if (!net->configFile && + asprintf(&net->configFile, "%s/%s.xml", + configDir, net->def->name) < 0) {
Upon failure, set net->autostartFile to NULL. Otherwise, when the caller frees "net", it will free a potentially undefined pointer.
+ virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto cleanup; + } + if (!net->autostartLink && + asprintf(&net->autostartLink, "%s/%s.xml", + autostartDir, net->def->name) < 0) {
Likewise for net->autostartLink.
+ virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto cleanup; + } + + if (!(xml = virNetworkDefFormat(conn, + net->newDef ? net->newDef : net->def))) + return -1;
No real problem, but each of the above two goto statements could be "return -1;", or maybe just change this return -1 to "goto cleanup;". Otherwise, the inconsistency looks suspicious.
+ if ((err = virFileMakePath(configDir))) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot create config directory %s: %s"), + configDir, strerror(err)); + goto cleanup; + } + + if ((err = virFileMakePath(autostartDir))) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot create autostart directory %s: %s"), + autostartDir, strerror(err)); + goto cleanup; + } + + if ((fd = open(net->configFile, + O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR )) < 0) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot create config file %s: %s"), + net->configFile, strerror(errno)); + goto cleanup; + } + + towrite = strlen(xml); + if (safewrite(fd, xml, towrite) < 0) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot write config file %s: %s"), + net->configFile, strerror(errno)); + goto cleanup; + } + + if (close(fd) < 0) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot save config file %s: %s"), + net->configFile, strerror(errno)); + goto cleanup; + } + + ret = 0; + + cleanup: + VIR_FREE(xml); + close(fd);
It's better not to close(-1), so as not to raise flags via tools like valgrind or strace: if (fd >= 0) close(fd);
+ return ret; +} + +virNetworkObjPtr virNetworkLoadConfig(virConnectPtr conn, + virNetworkObjPtr *nets, + const char *configDir, + const char *autostartDir, + const char *file) +{ + char *configFile, *autostartLink; + virNetworkDefPtr def = NULL; + virNetworkObjPtr net; + int autostart; + + if (asprintf(&configFile, "%s/%s", + configDir, file) < 0) {
Upon failed asprintf, here, you need to set configFile = NULL. Otherwise, the VIR_FREE(configFile) below will free a potentially undefined pointer.
+ virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + if (asprintf(&autostartLink, "%s/%s", + autostartDir, file) < 0) {
Same for autostartLink.
+ virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } ... +error: + VIR_FREE(configFile); + VIR_FREE(autostartLink); + virNetworkDefFree(def); + return NULL; +} ... +int virNetworkDeleteConfig(virConnectPtr conn, + virNetworkObjPtr net) +{ + if (!net->configFile || !net->autostartLink) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("no config file for %s"), net->def->name); + return -1; + } + + /* Not fatal if this doesn't work */ + unlink(net->autostartLink); + + if (unlink(net->configFile) < 0) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot remove config for %s"), net->def->name);
Please include strerror(errno), so people know why it fails.
+ return -1; + } + + return 0; +} diff -r 097ed9d9ae46 src/network_conf.h ... +typedef struct _virNetworkDef virNetworkDef; +typedef virNetworkDef *virNetworkDefPtr; +struct _virNetworkDef { + unsigned char uuid[VIR_UUID_BUFLEN]; + char *name; + + char *bridge; /* Name of bridge device */ + int stp : 1; /* Spanning tree protocol */ + unsigned long delay; /* Bridge forward delay (ms) */
Not that it matters, but... Swapping the two preceding lines should decrease the size of this struct by 8 bytes on a system with 8-byte pointers and longs.
+ + int forwardType; /* One of virNetworkForwardType constants */ + char *forwardDev; /* Destination device for forwarding */ + + char *ipAddress; /* Bridge IP address */ + char *netmask; + char *network; + + unsigned int nranges; /* Zero or more dhcp ranges */ + virNetworkDHCPRangeDefPtr ranges; +};

On Wed, Jul 09, 2008 at 04:34:39PM +0200, Jim Meyering wrote:
Modulo some minor problems, ACK. Even though I reviewed only the incremental diffs, there was a bit of new material. BTW, nice catch, with the new uses of virBufferEscapeString.
+virNetworkDefPtr virNetworkDefParseNode(virConnectPtr conn, + xmlDocPtr xml, + xmlNodePtr root) +{ + xmlXPathContextPtr ctxt = NULL; + virNetworkDefPtr def = NULL; + + if (!xmlStrEqual(root->name, BAD_CAST "network")) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("incorrect root element")); + goto cleanup; + }
No big deal, but the above goto could be "return NULL;".
I've made this change, and all the others suggested, and committed this patch. I've also made the equivalent changes to the domain XML patch. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

We currently have five drivers which handle the domain XML containing duplicated parsers and formatters for the XML with varying degrees of buginess, and often very similar structs. This patch introduces a new general purpose internal API for parsing and formatting network XML, and representing it as a series of structs. This code is derived from the current equivalent code in the QEMU driver for domains, but with alot of extra config parsing added for stuff needed by the Xen drivers. I have not yet added the extra bits needed by the container based drivers, LXC and OpenVZ, but don't anticipate any problems in this regard. Again the naming conventions I'm adopting in this patch follow those in the storage and network drivers: - virDomainPtr - the public opaque object in libvirt.h - virDomainObjPtr - the primary internal object for domain state - virDomainDefPtr - the configuration data for a domain A virDomainObjPtr contains a reference to one or two virDomainDefPtr objects - the current live config, and potentially a secondary inactive config which will become live at the next restart. The structs are defined in domain_conf.h, along with a bunch of APIs for dealing with them. These APIs are the same as similarly named ones from the current qemu driver, but I'll go over them again for a reminder: virDomainObjPtr virDomainFindByUUID(const virDomainObjPtr doms, const unsigned char *uuid); virDomainObjPtr virDomainFindByName(const virDomainObjPtr doms, const char *name); virDomainObjPtr virDomainFindByID(const virDomainObjPtr doms, const char *id); Allow lookup of a virDomainObjPtr object based on its name, ID or UUID, as typically obtained from the public virDomainPtr object. The 'doms' parameter to both of thse is a linked list of domains which are currently known to the driver using this API. Not all drivers will use these APIs - the Xen driver will just query XenD - these are only for drivers which maintain state internally with the libvirt daemon. void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def); void virDomainInputDefFree(virDomainInputDefPtr def); void virDomainDiskDefFree(virDomainDiskDefPtr def); void virDomainNetDefFree(virDomainNetDefPtr def); void virDomainChrDefFree(virDomainChrDefPtr def); void virDomainSoundDefFree(virDomainSoundDefPtr def); void virDomainDefFree(virDomainDefPtr def); void virDomainObjFree(virDomainObjPtr net); Convenience APIs to totally free the memory associated with these objects. virDomainObjPtr virDomainAssignDef(virConnectPtr conn, virDomainObjPtr *doms, const virDomainDefPtr def); Given a virDomainDefPtr object, it'll search for a pre-existing virDomainObjPtr object with matching config. If one is found, its config will be updated, otherwise a new object will be allocated. void virDomainRemoveInactive(virDomainObjPtr *doms, const virDomainObjPtr dom); Convenience for removing and free'ing a virDomainObjPtr object in the current list of active domains. virDomainDefPtr virDomainDefParseString(virConnectPtr conn, virCapsPtr caps, const char *xmlStr); virDomainDefPtr virDomainDefParseFile(virConnectPtr conn, virCapsPtr caps, const char *filename); virDomainDefPtr virDomainDefParseNode(virConnectPtr conn, virCapsPtr caps, xmlDocPtr doc, xmlNodePtr root); Based on DV's suggestion the parsing methods have changed slightly so instead of only allowing a string to be parsed, we can directly parse a file, or a XML node object. This is a little more advanced than the network parser because the various hypervisor drivers have slightly varying capabilities. So we pass a virCapsPtr object in so the parser can validate against the actual driver's capabilities. I'd like to extend the capabilities format to cover things like the boot parameters supported - eg PXE vs kernel+initrd vs bootloader vs BIOS, so we can further validate at time of parsing, instead of time of use. char *virDomainDefFormat(virConnectPtr conn, const virDomainDefPtr def, int secure); Given a virDomainDefPtr object, generate a XML document describing the domain. The secure flag controls whether passwords are included in the XML output. int virDomainCpuSetParse(virConnectPtr conn, const char **str, char sep, char *cpuset, int maxcpu); char *virDomainCpuSetFormat(virConnectPtr conn, char *cpuset, int maxcpu); These are just the APIs for dealing with CPU ranges moved from the xml.c file so they are in the expected place. A future patch will remove them from xml.c when the Xen driver is ported to this API. VIR_ENUM_DECL(virDomainVirt) VIR_ENUM_DECL(virDomainBoot) VIR_ENUM_DECL(virDomainFeature) VIR_ENUM_DECL(virDomainLifecycle) VIR_ENUM_DECL(virDomainDisk) VIR_ENUM_DECL(virDomainDiskDevice) VIR_ENUM_DECL(virDomainDiskBus) VIR_ENUM_DECL(virDomainNet) VIR_ENUM_DECL(virDomainChr) VIR_ENUM_DECL(virDomainSoundModel) VIR_ENUM_DECL(virDomainInput) VIR_ENUM_DECL(virDomainInputBus) VIR_ENUM_DECL(virDomainGraphics) This provides prototypes for all the enumerations useful to drivers using this API and struct definitions. For drivers which no other persistent storage native to their virt type, there are helper methods for loading and saving the XML configs to files. This is primarily for QEMU and LXC drivers int virDomainSaveConfig(virConnectPtr conn, const char *configDir, const char *autostartDir, virDomainObjPtr dom); virDomainObjPtr virDomainLoadConfig(virConnectPtr conn, virCapsPtr caps, virDomainObjPtr *doms, const char *configDir, const char *autostartDir, const char *file); int virDomainLoadAllConfigs(virConnectPtr conn, virCapsPtr caps, virDomainObjPtr *doms, const char *configDir, const char *autostartDir); int virDomainDeleteConfig(virConnectPtr conn, virDomainObjPtr dom); As a mentioned earlier, the impl of these APIs is just copied from the QEMU driver, but instead of using pre-declared char[PATH_MAX] fields, we allocate memory for strings as required. This dramatically reduces the memory needs of the QEMU driver (when ported to this API). It also switches to use the xml.c convenience routines instead of the regular libxml2 APIs, and in doing so I added a couple more convenience routines. There is no test suite explicitly against these parsers because when the QEMU and Xen drivers are ported to this API their existing test suites exercise nearly all the code. b/src/domain_conf.c | 2884 ++++++++++++++++++++++++++++++++++++++++++++ b/src/domain_conf.h | 489 +++++++ include/libvirt/virterror.h | 1 po/POTFILES.in | 1 src/Makefile.am | 1 src/util.h | 2 src/virterror.c | 3 src/xml.c | 18 src/xml.h | 10 9 files changed, 3403 insertions(+), 6 deletions(-) Daniel diff -r a77ea50ba693 include/libvirt/virterror.h --- a/include/libvirt/virterror.h Tue Jul 08 15:26:26 2008 +0100 +++ b/include/libvirt/virterror.h Tue Jul 08 15:26:51 2008 +0100 @@ -57,6 +57,7 @@ VIR_FROM_LXC, /* Error from Linux Container driver */ VIR_FROM_STORAGE, /* Error from storage driver */ VIR_FROM_NETWORK, /* Error from network config */ + VIR_FROM_DOMAIN, /* Error from domain config */ } virErrorDomain; diff -r a77ea50ba693 po/POTFILES.in --- a/po/POTFILES.in Tue Jul 08 15:26:26 2008 +0100 +++ b/po/POTFILES.in Tue Jul 08 15:26:51 2008 +0100 @@ -3,6 +3,7 @@ qemud/remote.c src/conf.c src/console.c +src/domain_conf.c src/hash.c src/iptables.c src/libvirt.c diff -r a77ea50ba693 src/Makefile.am --- a/src/Makefile.am Tue Jul 08 15:26:26 2008 +0100 +++ b/src/Makefile.am Tue Jul 08 15:26:51 2008 +0100 @@ -39,6 +39,7 @@ test.c test.h \ buf.c buf.h \ qparams.c qparams.h \ + domain_conf.c domain_conf.h \ capabilities.c capabilities.h \ xml.c xml.h \ event.c event.h \ diff -r a77ea50ba693 src/domain_conf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/domain_conf.c Tue Jul 08 15:26:51 2008 +0100 @@ -0,0 +1,2884 @@ +/* + * domain_conf.c: domain XML processing + * + * Copyright (C) 2006-2008 Red Hat, Inc. + * Copyright (C) 2006-2008 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange <berrange@redhat.com> + */ + +#include <config.h> + +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#include <dirent.h> + +#include "internal.h" + +#include "domain_conf.h" +#include "memory.h" +#include "verify.h" +#include "xml.h" +#include "uuid.h" +#include "util.h" +#include "buf.h" +#include "c-ctype.h" + +VIR_ENUM_IMPL(virDomainVirt, VIR_DOMAIN_VIRT_LAST, + "qemu", + "kqemu", + "kvm", + "xen", + "lxc", + "uml", + "openvz", + "vserver", + "ldom", + "test", + "vmware", + "hyperv") + +VIR_ENUM_IMPL(virDomainBoot, VIR_DOMAIN_BOOT_LAST, + "fd", + "cdrom", + "hd", + "network") + +VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST, + "acpi", + "apic", + "pae") + +VIR_ENUM_IMPL(virDomainLifecycle, VIR_DOMAIN_LIFECYCLE_LAST, + "destroy", + "restart", + "rename-restart", + "preserve") + +VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST, + "block", + "file") + +VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST, + "disk", + "cdrom", + "floppy") + +VIR_ENUM_IMPL(virDomainDiskBus, VIR_DOMAIN_DISK_BUS_LAST, + "ide", + "fdc", + "scsi", + "virtio", + "xen") + +VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST, + "user", + "ethernet", + "server", + "client", + "mcast", + "network", + "bridge") + +VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST, + "null", + "vc", + "pty", + "dev", + "file", + "pipe", + "stdio", + "udp", + "tcp", + "unix") + +VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST, + "sb16", + "es1370", + "pcspk"); + +VIR_ENUM_IMPL(virDomainInput, VIR_DOMAIN_INPUT_TYPE_LAST, + "mouse", + "tablet") + +VIR_ENUM_IMPL(virDomainInputBus, VIR_DOMAIN_INPUT_BUS_LAST, + "ps2", + "usb", + "xen") + +VIR_ENUM_IMPL(virDomainGraphics, VIR_DOMAIN_GRAPHICS_TYPE_LAST, + "sdl", + "vnc") + + +static void virDomainReportError(virConnectPtr conn, + int code, const char *fmt, ...) +{ + va_list args; + char errorMessage[1024]; + const char *virerr; + + if (fmt) { + va_start(args, fmt); + vsnprintf(errorMessage, sizeof(errorMessage)-1, fmt, args); + va_end(args); + } else { + errorMessage[0] = '\0'; + } + + virerr = __virErrorMsg(code, (errorMessage[0] ? errorMessage : NULL)); + __virRaiseError(conn, NULL, NULL, VIR_FROM_DOMAIN, code, VIR_ERR_ERROR, + virerr, errorMessage, NULL, -1, -1, virerr, errorMessage); +} + + +virDomainObjPtr virDomainFindByID(const virDomainObjPtr doms, + int id) +{ + virDomainObjPtr dom = doms; + while (dom) { + if (virDomainIsActive(dom) && dom->def->id == id) + return dom; + dom = dom->next; + } + + return NULL; +} + + +virDomainObjPtr virDomainFindByUUID(const virDomainObjPtr doms, + const unsigned char *uuid) +{ + virDomainObjPtr dom = doms; + + while (dom) { + if (!memcmp(dom->def->uuid, uuid, VIR_UUID_BUFLEN)) + return dom; + dom = dom->next; + } + + return NULL; +} + +virDomainObjPtr virDomainFindByName(const virDomainObjPtr doms, + const char *name) +{ + virDomainObjPtr dom = doms; + + while (dom) { + if (STREQ(dom->def->name, name)) + return dom; + dom = dom->next; + } + + return NULL; +} + +void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def) +{ + if (!def) + return; + + switch (def->type) { + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + VIR_FREE(def->data.vnc.listenAddr); + VIR_FREE(def->data.vnc.keymap); + VIR_FREE(def->data.vnc.passwd); + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + VIR_FREE(def->data.sdl.display); + VIR_FREE(def->data.sdl.xauth); + break; + } + + VIR_FREE(def); +} + +void virDomainInputDefFree(virDomainInputDefPtr def) +{ + if (!def) + return; + + virDomainInputDefFree(def->next); + VIR_FREE(def); +} + +void virDomainDiskDefFree(virDomainDiskDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def->src); + VIR_FREE(def->dst); + VIR_FREE(def->driverName); + VIR_FREE(def->driverType); + + virDomainDiskDefFree(def->next); + VIR_FREE(def); +} + +void virDomainNetDefFree(virDomainNetDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def->model); + + switch (def->type) { + case VIR_DOMAIN_NET_TYPE_ETHERNET: + VIR_FREE(def->data.ethernet.dev); + VIR_FREE(def->data.ethernet.script); + VIR_FREE(def->data.ethernet.ipaddr); + break; + + case VIR_DOMAIN_NET_TYPE_SERVER: + case VIR_DOMAIN_NET_TYPE_CLIENT: + case VIR_DOMAIN_NET_TYPE_MCAST: + VIR_FREE(def->data.socket.address); + break; + + case VIR_DOMAIN_NET_TYPE_NETWORK: + VIR_FREE(def->data.network.name); + break; + + case VIR_DOMAIN_NET_TYPE_BRIDGE: + VIR_FREE(def->data.bridge.brname); + break; + } + + VIR_FREE(def->ifname); + virDomainNetDefFree(def->next); + VIR_FREE(def); +} + +void virDomainChrDefFree(virDomainChrDefPtr def) +{ + if (!def) + return; + + switch (def->type) { + case VIR_DOMAIN_CHR_TYPE_PTY: + case VIR_DOMAIN_CHR_TYPE_DEV: + case VIR_DOMAIN_CHR_TYPE_FILE: + case VIR_DOMAIN_CHR_TYPE_PIPE: + VIR_FREE(def->data.file.path); + break; + + case VIR_DOMAIN_CHR_TYPE_UDP: + VIR_FREE(def->data.udp.bindHost); + VIR_FREE(def->data.udp.bindService); + VIR_FREE(def->data.udp.connectHost); + VIR_FREE(def->data.udp.connectService); + break; + + case VIR_DOMAIN_CHR_TYPE_TCP: + VIR_FREE(def->data.tcp.host); + VIR_FREE(def->data.tcp.service); + break; + + case VIR_DOMAIN_CHR_TYPE_UNIX: + VIR_FREE(def->data.nix.path); + break; + } + + virDomainChrDefFree(def->next); + VIR_FREE(def); +} + +void virDomainSoundDefFree(virDomainSoundDefPtr def) +{ + if (!def) + return; + + virDomainSoundDefFree(def->next); + VIR_FREE(def); +} + +void virDomainDeviceDefFree(virDomainDeviceDefPtr def) +{ + if (!def) + return; + + switch (def->type) { + case VIR_DOMAIN_DEVICE_DISK: + virDomainDiskDefFree(def->data.disk); + break; + case VIR_DOMAIN_DEVICE_NET: + virDomainNetDefFree(def->data.net); + break; + case VIR_DOMAIN_DEVICE_INPUT: + virDomainInputDefFree(def->data.input); + break; + case VIR_DOMAIN_DEVICE_SOUND: + virDomainSoundDefFree(def->data.sound); + break; + } + + VIR_FREE(def); +} + +void virDomainDefFree(virDomainDefPtr def) +{ + if (!def) + return; + + virDomainGraphicsDefFree(def->graphics); + virDomainInputDefFree(def->inputs); + virDomainDiskDefFree(def->disks); + virDomainNetDefFree(def->nets); + virDomainChrDefFree(def->serials); + virDomainChrDefFree(def->parallels); + virDomainChrDefFree(def->console); + virDomainSoundDefFree(def->sounds); + + + VIR_FREE(def->os.type); + VIR_FREE(def->os.arch); + VIR_FREE(def->os.machine); + VIR_FREE(def->os.kernel); + VIR_FREE(def->os.initrd); + VIR_FREE(def->os.cmdline); + VIR_FREE(def->os.root); + VIR_FREE(def->os.loader); + VIR_FREE(def->os.bootloader); + VIR_FREE(def->os.bootloaderArgs); + + VIR_FREE(def->name); + VIR_FREE(def->cpumask); + VIR_FREE(def->emulator); + + VIR_FREE(def); +} + +void virDomainObjFree(virDomainObjPtr dom) +{ + if (!dom) + return; + + virDomainDefFree(dom->def); + virDomainDefFree(dom->newDef); + + VIR_FREE(dom->vcpupids); + VIR_FREE(dom->configFile); + VIR_FREE(dom->autostartLink); + + VIR_FREE(dom); +} + +virDomainObjPtr virDomainAssignDef(virConnectPtr conn, + virDomainObjPtr *doms, + const virDomainDefPtr def) +{ + virDomainObjPtr domain; + + if ((domain = virDomainFindByName(*doms, def->name))) { + if (!virDomainIsActive(domain)) { + virDomainDefFree(domain->def); + domain->def = def; + } else { + if (domain->newDef) + virDomainDefFree(domain->newDef); + domain->newDef = def; + } + + return domain; + } + + if (VIR_ALLOC(domain) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + domain->def = def; + domain->next = *doms; + + *doms = domain; + + return domain; +} + +void virDomainRemoveInactive(virDomainObjPtr *doms, + virDomainObjPtr dom) +{ + virDomainObjPtr prev = NULL; + virDomainObjPtr curr = *doms; + + while (curr && + curr != dom) { + prev = curr; + curr = curr->next; + } + + if (curr) { + if (prev) + prev->next = curr->next; + else + *doms = curr->next; + } + + virDomainObjFree(dom); +} + +static int virDomainDiskCompare(virDomainDiskDefPtr a, + virDomainDiskDefPtr b) { + if (a->bus == b->bus) + return virDiskNameToIndex(a->dst) - virDiskNameToIndex(b->dst); + else + return a->bus - b->bus; +} + + +/* Parse the XML definition for a disk + * @param node XML nodeset to parse for disk definition + */ +static virDomainDiskDefPtr +virDomainDiskDefParseXML(virConnectPtr conn, + xmlNodePtr node) { + virDomainDiskDefPtr def; + xmlNodePtr cur; + char *type = NULL; + char *device = NULL; + char *driverName = NULL; + char *driverType = NULL; + char *source = NULL; + char *target = NULL; + char *bus = NULL; + + if (VIR_ALLOC(def) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + type = virXMLPropString(node, "type"); + if (type) { + if ((def->type = virDomainDiskTypeFromString(type)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown disk type '%s'"), type); + goto error; + } + } else { + def->type = VIR_DOMAIN_DISK_TYPE_FILE; + } + + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + if ((source == NULL) && + (xmlStrEqual(cur->name, BAD_CAST "source"))) { + + if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) + source = virXMLPropString(cur, "file"); + else + source = virXMLPropString(cur, "dev"); + } else if ((target == NULL) && + (xmlStrEqual(cur->name, BAD_CAST "target"))) { + target = virXMLPropString(cur, "dev"); + bus = virXMLPropString(cur, "bus"); + } else if ((driverName == NULL) && + (xmlStrEqual(cur->name, BAD_CAST "driver"))) { + driverName = virXMLPropString(cur, "name"); + driverType = virXMLPropString(cur, "type"); + } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) { + def->readonly = 1; + } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) { + def->shared = 1; + } + } + cur = cur->next; + } + + device = virXMLPropString(node, "device"); + if (device) { + if ((def->device = virDomainDiskDeviceTypeFromString(device)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown disk device '%s'"), device); + goto error; + } + } else { + def->device = VIR_DOMAIN_DISK_DEVICE_DISK; + } + + /* Only CDROM and Floppy devices are allowed missing source path + * to indicate no media present */ + if (source == NULL && + def->device != VIR_DOMAIN_DISK_DEVICE_CDROM && + def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) { + virDomainReportError(conn, VIR_ERR_NO_SOURCE, + target ? "%s" : NULL, target); + goto error; + } + + if (target == NULL) { + virDomainReportError(conn, VIR_ERR_NO_TARGET, + source ? "%s" : NULL, source); + goto error; + } + + if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY && + !STRPREFIX(target, "fd")) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Invalid floppy device name: %s"), target); + goto error; + } + + /* Force CDROM to be listed as read only */ + if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) + def->readonly = 1; + + if (def->device == VIR_DOMAIN_DISK_DEVICE_DISK && + !STRPREFIX((const char *)target, "hd") && + !STRPREFIX((const char *)target, "sd") && + !STRPREFIX((const char *)target, "vd") && + !STRPREFIX((const char *)target, "xvd")) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Invalid harddisk device name: %s"), target); + goto error; + } + + if (bus) { + if ((def->bus = virDomainDiskBusTypeFromString(bus)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown disk bus type '%s'"), bus); + goto error; + } + } else { + if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { + def->bus = VIR_DOMAIN_DISK_BUS_FDC; + } else { + if (STRPREFIX(target, "hd")) + def->bus = VIR_DOMAIN_DISK_BUS_IDE; + else if (STRPREFIX(target, "sd")) + def->bus = VIR_DOMAIN_DISK_BUS_SCSI; + else if (STRPREFIX(target, "vd")) + def->bus = VIR_DOMAIN_DISK_BUS_VIRTIO; + else if (STRPREFIX(target, "xvd")) + def->bus = VIR_DOMAIN_DISK_BUS_XEN; + else + def->bus = VIR_DOMAIN_DISK_BUS_IDE; + } + } + + if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY && + def->bus != VIR_DOMAIN_DISK_BUS_FDC) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Invalid bus type '%s' for floppy disk"), bus); + goto error; + } + if (def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY && + def->bus == VIR_DOMAIN_DISK_BUS_FDC) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Invalid bus type '%s' for disk"), bus); + goto error; + } + + def->src = source; + source = NULL; + def->dst = target; + target = NULL; + def->driverName = driverName; + driverName = NULL; + def->driverType = driverType; + driverType = NULL; + +cleanup: + VIR_FREE(bus); + VIR_FREE(type); + VIR_FREE(target); + VIR_FREE(source); + VIR_FREE(device); + VIR_FREE(driverType); + VIR_FREE(driverName); + + return def; + + error: + virDomainDiskDefFree(def); + def = NULL; + goto cleanup; +} + + +static void virDomainNetRandomMAC(virDomainNetDefPtr def) { + /* XXX there different vendor prefixes per hypervisor */ + def->mac[0] = 0x52; + def->mac[1] = 0x54; + def->mac[2] = 0x00; + def->mac[3] = 1 + (int)(256*(rand()/(RAND_MAX+1.0))); + def->mac[4] = 1 + (int)(256*(rand()/(RAND_MAX+1.0))); + def->mac[5] = 1 + (int)(256*(rand()/(RAND_MAX+1.0))); +} + + +/* Parse the XML definition for a network interface + * @param node XML nodeset to parse for net definition + * @return 0 on success, -1 on failure + */ +static virDomainNetDefPtr +virDomainNetDefParseXML(virConnectPtr conn, + xmlNodePtr node) { + virDomainNetDefPtr def; + xmlNodePtr cur; + char *macaddr = NULL; + char *type = NULL; + char *network = NULL; + char *bridge = NULL; + char *dev = NULL; + char *ifname = NULL; + char *script = NULL; + char *address = NULL; + char *port = NULL; + char *model = NULL; + + if (VIR_ALLOC(def) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + type = virXMLPropString(node, "type"); + if (type != NULL) { + if ((def->type = virDomainNetTypeFromString(type)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown interface type '%s'"), type); + goto error; + } + } else { + def->type = VIR_DOMAIN_NET_TYPE_USER; + } + + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + if ((macaddr == NULL) && + (xmlStrEqual(cur->name, BAD_CAST "mac"))) { + macaddr = virXMLPropString(cur, "address"); + } else if ((network == NULL) && + (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) && + (xmlStrEqual(cur->name, BAD_CAST "source"))) { + network = virXMLPropString(cur, "network"); + } else if ((network == NULL) && + (def->type == VIR_DOMAIN_NET_TYPE_BRIDGE) && + (xmlStrEqual(cur->name, BAD_CAST "source"))) { + bridge = virXMLPropString(cur, "bridge"); + } else if ((dev == NULL) && + (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET) && + xmlStrEqual(cur->name, BAD_CAST "source")) { + dev = virXMLPropString(cur, "dev"); + } else if ((network == NULL) && + ((def->type == VIR_DOMAIN_NET_TYPE_SERVER) || + (def->type == VIR_DOMAIN_NET_TYPE_CLIENT) || + (def->type == VIR_DOMAIN_NET_TYPE_MCAST)) && + (xmlStrEqual(cur->name, BAD_CAST "source"))) { + address = virXMLPropString(cur, "address"); + port = virXMLPropString(cur, "port"); + } else if ((address == NULL) && + (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET) && + (xmlStrEqual(cur->name, BAD_CAST "ip"))) { + address = virXMLPropString(cur, "address"); + } else if ((ifname == NULL) && + xmlStrEqual(cur->name, BAD_CAST "target")) { + ifname = virXMLPropString(cur, "dev"); + if (STRPREFIX((const char*)ifname, "vnet")) { + /* An auto-generated target name, blank it out */ + VIR_FREE(ifname); + ifname = NULL; + } + } else if ((script == NULL) && + (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET) && + xmlStrEqual(cur->name, BAD_CAST "script")) { + script = virXMLPropString(cur, "path"); + } else if (xmlStrEqual (cur->name, BAD_CAST "model")) { + model = virXMLPropString(cur, "type"); + } + } + cur = cur->next; + } + + if (macaddr) { + unsigned int mac[6]; + sscanf((const char *)macaddr, "%02x:%02x:%02x:%02x:%02x:%02x", + (unsigned int*)&mac[0], + (unsigned int*)&mac[1], + (unsigned int*)&mac[2], + (unsigned int*)&mac[3], + (unsigned int*)&mac[4], + (unsigned int*)&mac[5]); + def->mac[0] = mac[0]; + def->mac[1] = mac[1]; + def->mac[2] = mac[2]; + def->mac[3] = mac[3]; + def->mac[4] = mac[4]; + def->mac[5] = mac[5]; + } else { + virDomainNetRandomMAC(def); + } + + switch (def->type) { + case VIR_DOMAIN_NET_TYPE_NETWORK: + if (network == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("No <source> 'network' attribute specified with <interface type='network'/>")); + goto error; + } + def->data.network.name = network; + network = NULL; + break; + + case VIR_DOMAIN_NET_TYPE_ETHERNET: + + if (script != NULL) { + def->data.ethernet.script = script; + script = NULL; + } + if (dev != NULL) { + def->data.ethernet.dev = dev; + dev = NULL; + } + if (address != NULL) { + def->data.ethernet.ipaddr = address; + address = NULL; + } + break; + + case VIR_DOMAIN_NET_TYPE_BRIDGE: + if (bridge == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("No <source> 'dev' attribute specified with <interface type='bridge'/>")); + goto error; + } + def->data.bridge.brname = bridge; + bridge = NULL; + break; + + case VIR_DOMAIN_NET_TYPE_CLIENT: + case VIR_DOMAIN_NET_TYPE_SERVER: + case VIR_DOMAIN_NET_TYPE_MCAST: + if (port == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("No <source> 'port' attribute specified with socket interface")); + goto error; + } + if (virStrToLong_i(port, NULL, 10, &def->data.socket.port) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Cannot parse <source> 'port' attribute with socket interface")); + goto error; + } + + if (address == NULL) { + if (def->type == VIR_DOMAIN_NET_TYPE_CLIENT || + def->type == VIR_DOMAIN_NET_TYPE_MCAST) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("No <source> 'address' attribute specified with socket interface")); + goto error; + } + } else { + def->data.socket.address = address; + address = NULL; + } + } + + if (ifname != NULL) { + def->ifname = ifname; + ifname = NULL; + } + + /* NIC model (see -net nic,model=?). We only check that it looks + * reasonable, not that it is a supported NIC type. FWIW kvm + * supports these types as of April 2008: + * i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio + */ + if (model != NULL) { + int i; + for (i = 0 ; i < strlen(model) ; i++) { + int char_ok = c_isalnum(model[i]) || model[i] == '_'; + if (!char_ok) { + virDomainReportError (conn, VIR_ERR_INVALID_ARG, "%s", + _("Model name contains invalid characters")); + goto error; + } + } + def->model = model; + model = NULL; + } + +cleanup: + VIR_FREE(macaddr); + VIR_FREE(network); + VIR_FREE(address); + VIR_FREE(port); + VIR_FREE(ifname); + VIR_FREE(dev); + VIR_FREE(script); + VIR_FREE(bridge); + VIR_FREE(model); + VIR_FREE(type); + + return def; + +error: + virDomainNetDefFree(def); + def = NULL; + goto cleanup; +} + + +/* Parse the XML definition for a character device + * @param node XML nodeset to parse for net definition + * + * The XML we're dealing with looks like + * + * <serial type="pty"> + * <source path="/dev/pts/3"/> + * <target port="1"/> + * </serial> + * + * <serial type="dev"> + * <source path="/dev/ttyS0"/> + * <target port="1"/> + * </serial> + * + * <serial type="tcp"> + * <source mode="connect" host="0.0.0.0" service="2445"/> + * <target port="1"/> + * </serial> + * + * <serial type="tcp"> + * <source mode="bind" host="0.0.0.0" service="2445"/> + * <target port="1"/> + * </serial> + * + * <serial type="udp"> + * <source mode="bind" host="0.0.0.0" service="2445"/> + * <source mode="connect" host="0.0.0.0" service="2445"/> + * <target port="1"/> + * </serial> + * + * <serial type="unix"> + * <source mode="bind" path="/tmp/foo"/> + * <target port="1"/> + * </serial> + * + */ +static virDomainChrDefPtr +virDomainChrDefParseXML(virConnectPtr conn, + xmlNodePtr node) { + xmlNodePtr cur; + char *type = NULL; + char *bindHost = NULL; + char *bindService = NULL; + char *connectHost = NULL; + char *connectService = NULL; + char *path = NULL; + char *mode = NULL; + char *protocol = NULL; + virDomainChrDefPtr def; + + if (VIR_ALLOC(def) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + def->type = VIR_DOMAIN_CHR_TYPE_PTY; + type = virXMLPropString(node, "type"); + if (type != NULL) { + if (STREQ(type, "null")) + def->type = VIR_DOMAIN_CHR_TYPE_NULL; + else if (STREQ(type, "vc")) + def->type = VIR_DOMAIN_CHR_TYPE_VC; + else if (STREQ(type, "pty")) + def->type = VIR_DOMAIN_CHR_TYPE_PTY; + else if (STREQ(type, "dev")) + def->type = VIR_DOMAIN_CHR_TYPE_DEV; + else if (STREQ(type, "file")) + def->type = VIR_DOMAIN_CHR_TYPE_FILE; + else if (STREQ(type, "pipe")) + def->type = VIR_DOMAIN_CHR_TYPE_PIPE; + else if (STREQ(type, "stdio")) + def->type = VIR_DOMAIN_CHR_TYPE_STDIO; + else if (STREQ(type, "udp")) + def->type = VIR_DOMAIN_CHR_TYPE_UDP; + else if (STREQ(type, "tcp")) + def->type = VIR_DOMAIN_CHR_TYPE_TCP; + else if (STREQ(type, "unix")) + def->type = VIR_DOMAIN_CHR_TYPE_UNIX; + else + def->type = VIR_DOMAIN_CHR_TYPE_NULL; + } + + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + if (xmlStrEqual(cur->name, BAD_CAST "source")) { + if (mode == NULL) + mode = virXMLPropString(cur, "mode"); + + switch (def->type) { + case VIR_DOMAIN_CHR_TYPE_PTY: + case VIR_DOMAIN_CHR_TYPE_DEV: + case VIR_DOMAIN_CHR_TYPE_FILE: + case VIR_DOMAIN_CHR_TYPE_PIPE: + case VIR_DOMAIN_CHR_TYPE_UNIX: + if (path == NULL) + path = virXMLPropString(cur, "path"); + + break; + + case VIR_DOMAIN_CHR_TYPE_UDP: + case VIR_DOMAIN_CHR_TYPE_TCP: + if (mode == NULL || + STREQ((const char *)mode, "connect")) { + + if (connectHost == NULL) + connectHost = virXMLPropString(cur, "host"); + if (connectService == NULL) + connectService = virXMLPropString(cur, "service"); + } else { + if (bindHost == NULL) + bindHost = virXMLPropString(cur, "host"); + if (bindService == NULL) + bindService = virXMLPropString(cur, "service"); + } + + if (def->type == VIR_DOMAIN_CHR_TYPE_UDP) { + VIR_FREE(mode); + mode = NULL; + } + } + } else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) { + if (protocol == NULL) + protocol = virXMLPropString(cur, "type"); + } + } + cur = cur->next; + } + + + switch (def->type) { + case VIR_DOMAIN_CHR_TYPE_NULL: + /* Nada */ + break; + + case VIR_DOMAIN_CHR_TYPE_VC: + break; + + case VIR_DOMAIN_CHR_TYPE_PTY: + /* @path attribute is an output only property - pty is auto-allocted */ + break; + + case VIR_DOMAIN_CHR_TYPE_DEV: + case VIR_DOMAIN_CHR_TYPE_FILE: + case VIR_DOMAIN_CHR_TYPE_PIPE: + if (path == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Missing source path attribute for char device")); + goto error; + } + + def->data.file.path = path; + path = NULL; + break; + + case VIR_DOMAIN_CHR_TYPE_STDIO: + /* Nada */ + break; + + case VIR_DOMAIN_CHR_TYPE_TCP: + if (mode == NULL || + STREQ(mode, "connect")) { + if (connectHost == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Missing source host attribute for char device")); + goto error; + } + if (connectService == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Missing source service attribute for char device")); + goto error; + } + + def->data.tcp.host = connectHost; + connectHost = NULL; + def->data.tcp.service = connectService; + connectService = NULL; + def->data.tcp.listen = 0; + } else { + if (bindHost == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Missing source host attribute for char device")); + goto error; + } + if (bindService == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Missing source service attribute for char device")); + goto error; + } + + def->data.tcp.host = bindHost; + bindHost = NULL; + def->data.tcp.service = bindService; + bindService = NULL; + def->data.tcp.listen = 1; + } + if (protocol != NULL && + STREQ(protocol, "telnet")) + def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET; + else + def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW; + break; + + case VIR_DOMAIN_CHR_TYPE_UDP: + if (connectService == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Missing source service attribute for char device")); + goto error; + } + + def->data.udp.connectHost = connectHost; + connectHost = NULL; + def->data.udp.connectService = connectService; + connectService = NULL; + + def->data.udp.bindHost = bindHost; + bindHost = NULL; + def->data.udp.bindService = bindService; + bindService = NULL; + break; + + case VIR_DOMAIN_CHR_TYPE_UNIX: + if (path == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Missing source path attribute for char device")); + goto error; + } + + if (mode != NULL && + STRNEQ(mode, "connect")) + def->data.nix.listen = 1; + else + def->data.nix.listen = 0; + + def->data.nix.path = path; + path = NULL; + break; + } + +cleanup: + VIR_FREE(mode); + VIR_FREE(protocol); + VIR_FREE(type); + VIR_FREE(bindHost); + VIR_FREE(bindService); + VIR_FREE(connectHost); + VIR_FREE(connectService); + VIR_FREE(path); + + return def; + +error: + virDomainChrDefFree(def); + def = NULL; + goto cleanup; +} + +/* Parse the XML definition for a network interface */ +static virDomainInputDefPtr +virDomainInputDefParseXML(virConnectPtr conn, + const char *ostype, + xmlNodePtr node) { + virDomainInputDefPtr def; + char *type = NULL; + char *bus = NULL; + + if (VIR_ALLOC(def) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + type = virXMLPropString(node, "type"); + bus = virXMLPropString(node, "bus"); + + if (!type) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("missing input device type")); + goto error; + } + + if ((def->type = virDomainInputTypeFromString(type)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown input device type '%s'"), type); + goto error; + } + + if (bus) { + if ((def->bus = virDomainInputBusTypeFromString(bus)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown input bus type '%s'"), bus); + goto error; + } + + if (STREQ(ostype, "hvm")) { + if (def->bus == VIR_DOMAIN_INPUT_BUS_PS2 && /* Only allow mouse for ps2 */ + def->type != VIR_DOMAIN_INPUT_TYPE_MOUSE) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("ps2 bus does not support %s input device"), + type); + goto error; + } + if (def->bus == VIR_DOMAIN_INPUT_BUS_XEN) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unsupported input bus %s"), + bus); + goto error; + } + } else { + if (def->bus != VIR_DOMAIN_INPUT_BUS_XEN) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unsupported input bus %s"), + bus); + } + if (def->type != VIR_DOMAIN_INPUT_TYPE_MOUSE) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("xen bus does not support %s input device"), + type); + goto error; + } + } + } else { + if (STREQ(ostype, "hvm")) { + if (def->type == VIR_DOMAIN_INPUT_TYPE_MOUSE) + def->bus = VIR_DOMAIN_INPUT_BUS_PS2; + else + def->bus = VIR_DOMAIN_INPUT_BUS_USB; + } else { + def->bus = VIR_DOMAIN_INPUT_BUS_XEN; + } + } + +cleanup: + VIR_FREE(type); + VIR_FREE(bus); + + return def; + +error: + virDomainInputDefFree(def); + def = NULL; + goto cleanup; +} + + +/* Parse the XML definition for a graphics device */ +static virDomainGraphicsDefPtr +virDomainGraphicsDefParseXML(virConnectPtr conn, + xmlNodePtr node) { + virDomainGraphicsDefPtr def; + char *type = NULL; + + if (VIR_ALLOC(def) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + type = virXMLPropString(node, "type"); + + if (!type) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("missing graphics device type")); + goto error; + } + + if ((def->type = virDomainGraphicsTypeFromString(type)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown graphics device type '%s'"), type); + goto error; + } + + if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { + char *port = virXMLPropString(node, "port"); + char *autoport; + + if (port) { + if (virStrToLong_i(port, NULL, 10, &def->data.vnc.port) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot parse vnc port %s"), port); + VIR_FREE(port); + goto error; + } + VIR_FREE(port); + /* Legacy compat syntax, used -1 for auto-port */ + if (def->data.vnc.port == -1) { + def->data.vnc.port = 0; + def->data.vnc.autoport = 1; + } + } else { + def->data.vnc.port = 0; + def->data.vnc.autoport = 1; + } + + if ((autoport = virXMLPropString(node, "autoport")) != NULL) { + if (STREQ(autoport, "yes")) { + def->data.vnc.port = 0; + def->data.vnc.autoport = 1; + } + VIR_FREE(autoport); + } + + def->data.vnc.listenAddr = virXMLPropString(node, "listen"); + def->data.vnc.passwd = virXMLPropString(node, "passwd"); + def->data.vnc.keymap = virXMLPropString(node, "keymap"); + } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) { + def->data.sdl.xauth = virXMLPropString(node, "xauth"); + def->data.sdl.display = virXMLPropString(node, "display"); + } + +cleanup: + VIR_FREE(type); + + return def; + +error: + virDomainGraphicsDefFree(def); + def = NULL; + goto cleanup; +} + + +static virDomainSoundDefPtr +virDomainSoundDefParseXML(virConnectPtr conn, + const xmlNodePtr node) { + + char *model; + virDomainSoundDefPtr def; + + if (VIR_ALLOC(def) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + model = virXMLPropString(node, "model"); + if ((def->model = virDomainSoundModelTypeFromString(model)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown sound model '%s'"), model); + goto error; + } + +cleanup: + VIR_FREE(model); + + return def; + +error: + virDomainSoundDefFree(def); + def = NULL; + goto cleanup; +} + + +static int virDomainLifecycleParseXML(virConnectPtr conn, + xmlXPathContextPtr ctxt, + const char *xpath, + int *val, + int defaultVal) +{ + char *tmp = virXPathString(xpath, ctxt); + if (tmp == NULL) { + *val = defaultVal; + } else { + *val = virDomainLifecycleTypeFromString(tmp); + if (*val < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown lifecycle action %s"), tmp); + VIR_FREE(tmp); + return -1; + } + VIR_FREE(tmp); + } + return 0; +} + + +virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn, + const virDomainDefPtr def, + const char *xmlStr) +{ + xmlDocPtr xml; + xmlNodePtr node; + virDomainDeviceDefPtr dev = NULL; + + if (!(xml = xmlReadDoc(BAD_CAST xmlStr, "device.xml", NULL, + XML_PARSE_NOENT | XML_PARSE_NONET | + XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { + virDomainReportError(conn, VIR_ERR_XML_ERROR, NULL); + goto error; + } + + node = xmlDocGetRootElement(xml); + if (node == NULL) { + virDomainReportError(conn, VIR_ERR_XML_ERROR, + "%s", _("missing root element")); + goto error; + } + + if (VIR_ALLOC(dev) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + + if (xmlStrEqual(node->name, BAD_CAST "disk")) { + dev->type = VIR_DOMAIN_DEVICE_DISK; + if (!(dev->data.disk = virDomainDiskDefParseXML(conn, node))) + goto error; + } else if (xmlStrEqual(node->name, BAD_CAST "interface")) { + dev->type = VIR_DOMAIN_DEVICE_NET; + if (!(dev->data.net = virDomainNetDefParseXML(conn, node))) + goto error; + } else if (xmlStrEqual(node->name, BAD_CAST "input")) { + dev->type = VIR_DOMAIN_DEVICE_DISK; + if (!(dev->data.input = virDomainInputDefParseXML(conn, def->os.type, node))) + goto error; + } else if (xmlStrEqual(node->name, BAD_CAST "sound")) { + dev->type = VIR_DOMAIN_DEVICE_SOUND; + if (!(dev->data.sound = virDomainSoundDefParseXML(conn, node))) + goto error; + } else { + virDomainReportError(conn, VIR_ERR_XML_ERROR, + "%s", _("unknown device type")); + goto error; + } + + xmlFreeDoc(xml); + + return dev; + + error: + xmlFreeDoc(xml); + VIR_FREE(dev); + return NULL; +} + + +static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn, + virCapsPtr caps, + xmlXPathContextPtr ctxt) +{ + xmlNodePtr *nodes = NULL, node = NULL; + char *tmp = NULL; + int i, n; + virDomainDefPtr def; + + if (VIR_ALLOC(def) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, + "%s", _("failed to allocate space for xmlXPathContext")); + return NULL; + } + def->id = -1; + + /* Find out what type of QEMU virtualization to use */ + if (!(tmp = virXPathString("string(./@type)", ctxt))) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("missing domain type attribute")); + goto error; + } + + if ((def->virtType = virDomainVirtTypeFromString(tmp)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("invalid domain type %s"), tmp); + goto error; + } + VIR_FREE(tmp); + + /* Extract domain name */ + if (!(def->name = virXPathString("string(./name[1])", ctxt))) { + virDomainReportError(conn, VIR_ERR_NO_NAME, NULL); + goto error; + } + + /* Extract domain uuid */ + tmp = virXPathString("string(./uuid[1])", ctxt); + if (!tmp) { + int err; + if ((err = virUUIDGenerate(def->uuid))) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Failed to generate UUID: %s"), + strerror(err)); + goto error; + } + } else { + if (virUUIDParse(tmp, def->uuid) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("malformed uuid element")); + goto error; + } + VIR_FREE(tmp); + } + + /* Extract domain memory */ + if (virXPathULong("string(./memory[1])", ctxt, &def->maxmem) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("missing memory element")); + goto error; + } + + if (virXPathULong("string(./currentMemory[1])", ctxt, &def->memory) < 0) + def->memory = def->maxmem; + + if (virXPathULong("string(./vcpu[1])", ctxt, &def->vcpus) < 0) + def->vcpus = 1; + + tmp = virXPathString("string(./vcpu[1]/@cpuset)", ctxt); + if (tmp) { + char *set = tmp; + def->cpumasklen = VIR_DOMAIN_CPUMASK_LEN; + if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + if (virDomainCpuSetParse(conn, (const char **)&set, + 0, def->cpumask, + def->cpumasklen) < 0) + goto error; + VIR_FREE(tmp); + } + + if ((n = virXPathNodeSet("./features/*", ctxt, &nodes)) > 0) { + for (i = 0 ; i < n ; i++) { + int val = virDomainFeatureTypeFromString((const char *)nodes[i]->name); + if (val < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected feature %s"), + nodes[i]->name); + goto error; + } + def->features |= (1 << val); + } + } + VIR_FREE(nodes); + + if (virDomainLifecycleParseXML(conn, ctxt, "string(./on_reboot[1])", + &def->onReboot, VIR_DOMAIN_LIFECYCLE_RESTART) < 0) + goto error; + + if (virDomainLifecycleParseXML(conn, ctxt, "string(./on_poweroff[1])", + &def->onPoweroff, VIR_DOMAIN_LIFECYCLE_DESTROY) < 0) + goto error; + + if (virDomainLifecycleParseXML(conn, ctxt, "string(./on_crash[1])", + &def->onCrash, VIR_DOMAIN_LIFECYCLE_DESTROY) < 0) + goto error; + + + tmp = virXPathString("string(./clock/@offset)", ctxt); + if (tmp && STREQ(tmp, "localtime")) + def->localtime = 1; + VIR_FREE(tmp); + + def->os.bootloader = virXPathString("string(./bootloader)", ctxt); + def->os.bootloaderArgs = virXPathString("string(./bootloader_args)", ctxt); + + def->os.type = virXPathString("string(./os/type[1])", ctxt); + if (!def->os.type) { + if (def->os.bootloader) { + def->os.type = strdup("xen"); + if (!def->os.type) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + } else { + virDomainReportError(conn, VIR_ERR_OS_TYPE, + "%s", _("no OS type")); + goto error; + } + } + /* + * HACK: For xen driver we previously used bogus 'linux' as the + * os type for paravirt, whereas capabilities declare it to + * be 'xen'. So we accept the former and convert + */ + if (STREQ(def->os.type, "linux") && + def->virtType == VIR_DOMAIN_VIRT_XEN) { + VIR_FREE(def->os.type); + if (!(def->os.type = strdup("xen"))) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + } + + if (!virCapabilitiesSupportsGuestOSType(caps, def->os.type)) { + virDomainReportError(conn, VIR_ERR_OS_TYPE, + "%s", def->os.type); + goto error; + } + + def->os.arch = virXPathString("string(./os/type[1]/@arch)", ctxt); + if (!def->os.arch) { + const char *defaultArch = virCapabilitiesDefaultGuestArch(caps, def->os.type); + if (defaultArch == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("no supported architecture for os type '%s'"), + def->os.type); + goto error; + } + if (!(def->os.arch = strdup(defaultArch))) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + } + + def->os.machine = virXPathString("string(./os/type[1]/@machine)", ctxt); + if (!def->os.machine) { + const char *defaultMachine = virCapabilitiesDefaultGuestMachine(caps, + def->os.type, + def->os.arch); + if (defaultMachine != NULL) { + if (!(def->os.machine = strdup(defaultMachine))) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + } + } + + if (!def->os.bootloader) { + def->os.kernel = virXPathString("string(./os/kernel[1])", ctxt); + def->os.initrd = virXPathString("string(./os/initrd[1])", ctxt); + def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt); + def->os.root = virXPathString("string(./os/root[1])", ctxt); + def->os.loader = virXPathString("string(./os/loader[1])", ctxt); + + /* analysis of the boot devices */ + if ((n = virXPathNodeSet("./os/boot", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract boot device")); + goto error; + } + for (i = 0 ; i < n && i < VIR_DOMAIN_BOOT_LAST ; i++) { + int val; + char *dev = virXMLPropString(nodes[i], "dev"); + if (!dev) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("missing boot device")); + goto error; + } + if ((val = virDomainBootTypeFromString(dev)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown boot device '%s'"), + dev); + VIR_FREE(dev); + goto error; + } + VIR_FREE(dev); + def->os.bootDevs[def->os.nBootDevs++] = val; + } + if (def->os.nBootDevs == 0) { + def->os.nBootDevs = 1; + def->os.bootDevs[0] = VIR_DOMAIN_BOOT_DISK; + } + VIR_FREE(nodes); + } + + def->emulator = virXPathString("string(./devices/emulator[1])", ctxt); + if (!def->emulator) { + const char *type = virDomainVirtTypeToString(def->virtType); + if (!type) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("unknown virt type")); + goto error; + } + const char *emulator = virCapabilitiesDefaultGuestEmulator(caps, + def->os.type, + def->os.arch, + type); + if (!emulator) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("unsupported guest type")); + goto error; + } + if (!(def->emulator = strdup(emulator))) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + } + + /* analysis of the disk devices */ + if ((n = virXPathNodeSet("./devices/disk", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract disk devices")); + goto error; + } + for (i = 0 ; i < n ; i++) { + virDomainDiskDefPtr disk = virDomainDiskDefParseXML(conn, + nodes[i]); + if (!disk) + goto error; + + /* Maintain list in sorted order according to target device name */ + if (def->disks == NULL) { + disk->next = def->disks; + def->disks = disk; + } else { + virDomainDiskDefPtr ptr = def->disks; + while (ptr) { + if (!ptr->next || virDomainDiskCompare(disk, ptr->next) < 0) { + disk->next = ptr->next; + ptr->next = disk; + break; + } + ptr = ptr->next; + } + } + } + VIR_FREE(nodes); + + /* analysis of the network devices */ + if ((n = virXPathNodeSet("./devices/interface", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract network devices")); + goto error; + } + for (i = n - 1 ; i >= 0 ; i--) { + virDomainNetDefPtr net = virDomainNetDefParseXML(conn, + nodes[i]); + if (!net) + goto error; + + net->next = def->nets; + def->nets = net; + } + VIR_FREE(nodes); + + + /* analysis of the character devices */ + if ((n = virXPathNodeSet("./devices/parallel", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract parallel devices")); + goto error; + } + for (i = n - 1 ; i >= 0 ; i--) { + virDomainChrDefPtr chr = virDomainChrDefParseXML(conn, + nodes[i]); + if (!chr) + goto error; + + chr->dstPort = i; + chr->next = def->parallels; + def->parallels = chr; + } + VIR_FREE(nodes); + + if ((n = virXPathNodeSet("./devices/serial", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract serial devices")); + goto error; + } + for (i = n - 1 ; i >= 0 ; i--) { + virDomainChrDefPtr chr = virDomainChrDefParseXML(conn, + nodes[i]); + if (!chr) + goto error; + + chr->dstPort = i; + chr->next = def->serials; + def->serials = chr; + } + VIR_FREE(nodes); + + /* + * If no serial devices were listed, then look for console + * devices which is the legacy syntax for the same thing + */ + if (def->serials == NULL) { + if ((node = virXPathNode("./devices/console[1]", ctxt)) != NULL) { + virDomainChrDefPtr chr = virDomainChrDefParseXML(conn, + node); + if (!chr) + goto error; + + chr->dstPort = 0; + /* + * For HVM console actually created a serial device + * while for non-HVM it was a parvirt console + */ + if (STREQ(def->os.type, "hvm")) { + chr->next = def->serials; + def->serials = chr; + } else { + def->console = chr; + } + } + } + + + /* analysis of the input devices */ + if ((n = virXPathNodeSet("./devices/input", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract input devices")); + goto error; + } + for (i = n - 1 ; i >= 0 ; i--) { + virDomainInputDefPtr input = virDomainInputDefParseXML(conn, + def->os.type, + nodes[i]); + if (!input) + goto error; + + + /* With QEMU / KVM / Xen graphics, mouse + PS/2 is implicit + * with graphics, so don't store it. + * XXX will this be true for other virt types ? */ + if ((STREQ(def->os.type, "hvm") && + input->bus == VIR_DOMAIN_INPUT_BUS_PS2 && + input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE) || + (STRNEQ(def->os.type, "hvm") && + input->bus == VIR_DOMAIN_INPUT_BUS_XEN && + input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE)) { + virDomainInputDefFree(input); + continue; + } + + input->next = def->inputs; + def->inputs = input; + } + VIR_FREE(nodes); + + /* analysis of the input devices */ + if ((n = virXPathNodeSet("./devices/graphics", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract graphics devices")); + goto error; + } + if (n > 0) { + virDomainGraphicsDefPtr graphics = virDomainGraphicsDefParseXML(conn, + nodes[0]); + if (!graphics) + goto error; + + def->graphics = graphics; + } + VIR_FREE(nodes); + + /* If graphics are enabled, there's an implicit PS2 mouse */ + if (def->graphics != NULL) { + virDomainInputDefPtr input; + + if (VIR_ALLOC(input) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + if (STREQ(def->os.type, "hvm")) { + input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE; + input->bus = VIR_DOMAIN_INPUT_BUS_PS2; + } else { + input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE; + input->bus = VIR_DOMAIN_INPUT_BUS_XEN; + } + input->next = def->inputs; + def->inputs = input; + } + + + /* analysis of the sound devices */ + if ((n = virXPathNodeSet("./devices/sound", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract sound devices")); + goto error; + } + for (i = n - 1 ; i >= 0 ; i--) { + int collision = 0; + virDomainSoundDefPtr check; + virDomainSoundDefPtr sound = virDomainSoundDefParseXML(conn, + nodes[i]); + if (!sound) + goto error; + + /* Verify there's no duplicated sound card */ + check = def->sounds; + while (check) { + if (check->model == sound->model) + collision = 1; + check = check->next; + } + if (collision) { + virDomainSoundDefFree(sound); + continue; + } + + sound->next = def->sounds; + def->sounds = sound; + } + VIR_FREE(nodes); + + return def; + + error: + VIR_FREE(tmp); + VIR_FREE(nodes); + virDomainDefFree(def); + return NULL; +} + + +virDomainDefPtr virDomainDefParseString(virConnectPtr conn, + virCapsPtr caps, + const char *xmlStr) +{ + xmlDocPtr xml; + xmlNodePtr root; + virDomainDefPtr def = NULL; + + if (!(xml = xmlReadDoc(BAD_CAST xmlStr, "network.xml", NULL, + XML_PARSE_NOENT | XML_PARSE_NONET | + XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { + virDomainReportError(conn, VIR_ERR_XML_ERROR, NULL); + return NULL; + } + + if ((root = xmlDocGetRootElement(xml)) == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("missing root element")); + xmlFreeDoc(xml); + return NULL; + } + + def = virDomainDefParseNode(conn, caps, xml, root); + + xmlFreeDoc(xml); + return def; +} + +virDomainDefPtr virDomainDefParseFile(virConnectPtr conn, + virCapsPtr caps, + const char *filename) +{ + xmlDocPtr xml; + xmlNodePtr root; + virDomainDefPtr def = NULL; + + if (!(xml = xmlReadFile(filename, NULL, + XML_PARSE_NOENT | XML_PARSE_NONET | + XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { + virDomainReportError(conn, VIR_ERR_XML_ERROR, NULL); + return NULL; + } + + if ((root = xmlDocGetRootElement(xml)) == NULL) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("missing root element")); + xmlFreeDoc(xml); + return NULL; + } + + def = virDomainDefParseNode(conn, caps, xml, root); + + xmlFreeDoc(xml); + return def; +} + + +virDomainDefPtr virDomainDefParseNode(virConnectPtr conn, + virCapsPtr caps, + xmlDocPtr xml, + xmlNodePtr root) +{ + xmlXPathContextPtr ctxt = NULL; + virDomainDefPtr def = NULL; + + if (!xmlStrEqual(root->name, BAD_CAST "domain")) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("incorrect root element")); + goto cleanup; + } + + ctxt = xmlXPathNewContext(xml); + if (ctxt == NULL) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto cleanup; + } + + ctxt->node = root; + def = virDomainDefParseXML(conn, caps, ctxt); + +cleanup: + xmlXPathFreeContext(ctxt); + return def; +} + + +/************************************************************************ + * * + * Parser and converter for the CPUset strings used in libvirt * + * * + ************************************************************************/ +/** + * virDomainCpuNumberParse + * @str: pointer to the char pointer used + * @maxcpu: maximum CPU number allowed + * + * Parse a CPU number + * + * Returns the CPU number or -1 in case of error. @str will be + * updated to skip the number. + */ +static int +virDomainCpuNumberParse(const char **str, int maxcpu) +{ + int ret = 0; + const char *cur = *str; + + if (!c_isdigit(*cur)) + return (-1); + + while (c_isdigit(*cur)) { + ret = ret * 10 + (*cur - '0'); + if (ret >= maxcpu) + return (-1); + cur++; + } + *str = cur; + return (ret); +} + +/** + * virDomainCpuSetFormat: + * @conn: connection + * @cpuset: pointer to a char array for the CPU set + * @maxcpu: number of elements available in @cpuset + * + * Serialize the cpuset to a string + * + * Returns the new string NULL in case of error. The string need to be + * freed by the caller. + */ +char * +virDomainCpuSetFormat(virConnectPtr conn, char *cpuset, int maxcpu) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + int start, cur; + int first = 1; + + if ((cpuset == NULL) || (maxcpu <= 0) || (maxcpu > 100000)) + return (NULL); + + cur = 0; + start = -1; + while (cur < maxcpu) { + if (cpuset[cur]) { + if (start == -1) + start = cur; + } else if (start != -1) { + if (!first) + virBufferAddLit(&buf, ","); + else + first = 0; + if (cur == start + 1) + virBufferVSprintf(&buf, "%d", start); + else + virBufferVSprintf(&buf, "%d-%d", start, cur - 1); + start = -1; + } + cur++; + } + if (start != -1) { + if (!first) + virBufferAddLit(&buf, ","); + if (maxcpu == start + 1) + virBufferVSprintf(&buf, "%d", start); + else + virBufferVSprintf(&buf, "%d-%d", start, maxcpu - 1); + } + + if (virBufferError(&buf)) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + return virBufferContentAndReset(&buf); +} + +/** + * virDomainCpuSetParse: + * @conn: connection + * @str: pointer to a CPU set string pointer + * @sep: potential character used to mark the end of string if not 0 + * @cpuset: pointer to a char array for the CPU set + * @maxcpu: number of elements available in @cpuset + * + * Parse the cpu set, it will set the value for enabled CPUs in the @cpuset + * to 1, and 0 otherwise. The syntax allows coma separated entries each + * can be either a CPU number, ^N to unset that CPU or N-M for ranges. + * + * Returns the number of CPU found in that set, or -1 in case of error. + * @cpuset is modified accordingly to the value parsed. + * @str is updated to the end of the part parsed + */ +int +virDomainCpuSetParse(virConnectPtr conn, const char **str, char sep, + char *cpuset, int maxcpu) +{ + const char *cur; + int ret = 0; + int i, start, last; + int neg = 0; + + if ((str == NULL) || (cpuset == NULL) || (maxcpu <= 0) || + (maxcpu > 100000)) + return (-1); + + cur = *str; + virSkipSpaces(&cur); + if (*cur == 0) + goto parse_error; + + /* initialize cpumap to all 0s */ + for (i = 0; i < maxcpu; i++) + cpuset[i] = 0; + ret = 0; + + while ((*cur != 0) && (*cur != sep)) { + /* + * 3 constructs are allowed: + * - N : a single CPU number + * - N-M : a range of CPU numbers with N < M + * - ^N : remove a single CPU number from the current set + */ + if (*cur == '^') { + cur++; + neg = 1; + } + + if (!c_isdigit(*cur)) + goto parse_error; + start = virDomainCpuNumberParse(&cur, maxcpu); + if (start < 0) + goto parse_error; + virSkipSpaces(&cur); + if ((*cur == ',') || (*cur == 0) || (*cur == sep)) { + if (neg) { + if (cpuset[start] == 1) { + cpuset[start] = 0; + ret--; + } + } else { + if (cpuset[start] == 0) { + cpuset[start] = 1; + ret++; + } + } + } else if (*cur == '-') { + if (neg) + goto parse_error; + cur++; + virSkipSpaces(&cur); + last = virDomainCpuNumberParse(&cur, maxcpu); + if (last < start) + goto parse_error; + for (i = start; i <= last; i++) { + if (cpuset[i] == 0) { + cpuset[i] = 1; + ret++; + } + } + virSkipSpaces(&cur); + } + if (*cur == ',') { + cur++; + virSkipSpaces(&cur); + neg = 0; + } else if ((*cur == 0) || (*cur == sep)) { + break; + } else + goto parse_error; + } + *str = cur; + return (ret); + + parse_error: + virDomainReportError(conn, VIR_ERR_XEN_CALL, + "%s", _("topology cpuset syntax error")); + return (-1); +} + + +static int +virDomainLifecycleDefFormat(virConnectPtr conn, + virBufferPtr buf, + int type, + const char *name) +{ + const char *typeStr = virDomainLifecycleTypeToString(type); + if (!typeStr) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected lifecycle type %d"), type); + return -1; + } + + virBufferVSprintf(buf, " <%s>%s</%s>\n", name, typeStr, name); + + return 0; +} + + +static int +virDomainDiskDefFormat(virConnectPtr conn, + virBufferPtr buf, + virDomainDiskDefPtr def) +{ + const char *type = virDomainDiskTypeToString(def->type); + const char *device = virDomainDiskDeviceTypeToString(def->device); + const char *bus = virDomainDiskBusTypeToString(def->bus); + + if (!type) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected disk type %d"), def->type); + return -1; + } + if (!device) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected disk device %d"), def->device); + return -1; + } + if (!bus) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected disk bus %d"), def->bus); + return -1; + } + + virBufferVSprintf(buf, + " <disk type='%s' device='%s'>\n", + type, device); + + if (def->driverName) { + if (def->driverType) + virBufferVSprintf(buf, + " <driver name='%s' type='%s'/>\n", + def->driverName, def->driverType); + else + virBufferVSprintf(buf, + " <driver name='%s'/>\n", + def->driverName); + } + + if (def->src) { + if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) + virBufferEscapeString(buf, " <source file='%s'/>\n", + def->src); + else + virBufferEscapeString(buf, " <source dev='%s'/>\n", + def->src); + } + + virBufferVSprintf(buf, " <target dev='%s' bus='%s'/>\n", + def->dst, bus); + + if (def->readonly) + virBufferAddLit(buf, " <readonly/>\n"); + if (def->shared) + virBufferAddLit(buf, " <shareable/>\n"); + + virBufferAddLit(buf, " </disk>\n"); + + return 0; +} + +static int +virDomainNetDefFormat(virConnectPtr conn, + virBufferPtr buf, + virDomainNetDefPtr def) +{ + const char *type = virDomainNetTypeToString(def->type); + + if (!type) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected net type %d"), def->type); + return -1; + } + + virBufferVSprintf(buf, " <interface type='%s'>\n", type); + + virBufferVSprintf(buf, + " <mac address='%02x:%02x:%02x:%02x:%02x:%02x'/>\n", + def->mac[0], def->mac[1], def->mac[2], + def->mac[3], def->mac[4], def->mac[5]); + + switch (def->type) { + case VIR_DOMAIN_NET_TYPE_NETWORK: + virBufferEscapeString(buf, " <source network='%s'/>\n", + def->data.network.name); + break; + + case VIR_DOMAIN_NET_TYPE_ETHERNET: + if (def->data.ethernet.dev) + virBufferEscapeString(buf, " <source dev='%s'/>\n", + def->data.ethernet.dev); + if (def->data.ethernet.ipaddr) + virBufferVSprintf(buf, " <ip address='%s'/>\n", + def->data.ethernet.ipaddr); + if (def->data.ethernet.script) + virBufferEscapeString(buf, " <script path='%s'/>\n", + def->data.ethernet.script); + break; + + case VIR_DOMAIN_NET_TYPE_BRIDGE: + virBufferEscapeString(buf, " <source bridge='%s'/>\n", + def->data.bridge.brname); + break; + + case VIR_DOMAIN_NET_TYPE_SERVER: + case VIR_DOMAIN_NET_TYPE_CLIENT: + case VIR_DOMAIN_NET_TYPE_MCAST: + if (def->data.socket.address) + virBufferVSprintf(buf, " <source address='%s' port='%d'/>\n", + def->data.socket.address, def->data.socket.port); + else + virBufferVSprintf(buf, " <source port='%d'/>\n", + def->data.socket.port); + } + + if (def->ifname) + virBufferEscapeString(buf, " <target dev='%s'/>\n", + def->ifname); + if (def->model) + virBufferEscapeString(buf, " <model type='%s'/>\n", + def->model); + + virBufferAddLit(buf, " </interface>\n"); + + return 0; +} + + +static int +virDomainChrDefFormat(virConnectPtr conn, + virBufferPtr buf, + virDomainChrDefPtr def, + const char *name) +{ + const char *type = virDomainChrTypeToString(def->type); + + if (!type) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected char type %d"), def->type); + return -1; + } + + /* Compat with legacy <console tty='/dev/pts/5'/> syntax */ + virBufferVSprintf(buf, " <%s type='%s'", + name, type); + if (STREQ(name, "console") && + def->type == VIR_DOMAIN_CHR_TYPE_PTY && + def->data.file.path) { + virBufferEscapeString(buf, " tty='%s'>\n", + def->data.file.path); + } else { + virBufferAddLit(buf, ">\n"); + } + + switch (def->type) { + case VIR_DOMAIN_CHR_TYPE_NULL: + case VIR_DOMAIN_CHR_TYPE_VC: + case VIR_DOMAIN_CHR_TYPE_STDIO: + /* nada */ + break; + + case VIR_DOMAIN_CHR_TYPE_PTY: + case VIR_DOMAIN_CHR_TYPE_DEV: + case VIR_DOMAIN_CHR_TYPE_FILE: + case VIR_DOMAIN_CHR_TYPE_PIPE: + if (def->type != VIR_DOMAIN_CHR_TYPE_PTY || + def->data.file.path) { + virBufferEscapeString(buf, " <source path='%s'/>\n", + def->data.file.path); + } + break; + + case VIR_DOMAIN_CHR_TYPE_UDP: + if (def->data.udp.bindService && + def->data.udp.bindHost) { + virBufferVSprintf(buf, " <source mode='bind' host='%s' service='%s'/>\n", + def->data.udp.bindHost, + def->data.udp.bindService); + } else if (def->data.udp.bindHost) { + virBufferVSprintf(buf, " <source mode='bind' host='%s'/>\n", + def->data.udp.bindHost); + } else if (def->data.udp.bindService) { + virBufferVSprintf(buf, " <source mode='bind' service='%s'/>\n", + def->data.udp.bindService); + } + + if (def->data.udp.connectService && + def->data.udp.connectHost) { + virBufferVSprintf(buf, " <source mode='connect' host='%s' service='%s'/>\n", + def->data.udp.connectHost, + def->data.udp.connectService); + } else if (def->data.udp.connectHost) { + virBufferVSprintf(buf, " <source mode='connect' host='%s'/>\n", + def->data.udp.connectHost); + } else if (def->data.udp.connectService) { + virBufferVSprintf(buf, " <source mode='connect' service='%s'/>\n", + def->data.udp.connectService); + } + break; + + case VIR_DOMAIN_CHR_TYPE_TCP: + virBufferVSprintf(buf, " <source mode='%s' host='%s' service='%s'/>\n", + def->data.tcp.listen ? "bind" : "connect", + def->data.tcp.host, + def->data.tcp.service); + virBufferVSprintf(buf, " <protocol type='%s'/>\n", + def->data.tcp.protocol == + VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET + ? "telnet" : "raw"); + break; + + case VIR_DOMAIN_CHR_TYPE_UNIX: + virBufferVSprintf(buf, " <source mode='%s'", + def->data.nix.listen ? "bind" : "connect"); + virBufferEscapeString(buf, " path='%s'/>\n", + def->data.nix.path); + break; + } + + virBufferVSprintf(buf, " <target port='%d'/>\n", + def->dstPort); + + virBufferVSprintf(buf, " </%s>\n", + name); + + return 0; +} + +static int +virDomainSoundDefFormat(virConnectPtr conn, + virBufferPtr buf, + virDomainSoundDefPtr def) +{ + const char *model = virDomainSoundModelTypeToString(def->model); + + if (!model) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected sound model %d"), def->model); + return -1; + } + + virBufferVSprintf(buf, " <sound model='%s'/>\n", + model); + + return 0; +} + +static int +virDomainInputDefFormat(virConnectPtr conn, + virBufferPtr buf, + virDomainInputDefPtr def) +{ + const char *type = virDomainInputTypeToString(def->type); + const char *bus = virDomainInputBusTypeToString(def->bus); + + if (!type) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected input type %d"), def->type); + return -1; + } + if (!bus) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected input bus type %d"), def->bus); + return -1; + } + + virBufferVSprintf(buf, " <input type='%s' bus='%s'/>\n", + type, bus); + + return 0; +} + + +static int +virDomainGraphicsDefFormat(virConnectPtr conn, + virBufferPtr buf, + virDomainGraphicsDefPtr def, + int flags) +{ + const char *type = virDomainGraphicsTypeToString(def->type); + + if (!type) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected net type %d"), def->type); + return -1; + } + + virBufferVSprintf(buf, " <graphics type='%s'", type); + + switch (def->type) { + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + if (def->data.vnc.autoport) + virBufferAddLit(buf, " port='-1'"); + else if (def->data.vnc.port) + virBufferVSprintf(buf, " port='%d'", + def->data.vnc.port); + + virBufferVSprintf(buf, " autoport='%s'", + def->data.vnc.autoport ? "yes" : "no"); + + if (def->data.vnc.listenAddr) + virBufferVSprintf(buf, " listen='%s'", + def->data.vnc.listenAddr); + + if (def->data.vnc.keymap) + virBufferEscapeString(buf, " keymap='%s'", + def->data.vnc.keymap); + + if (def->data.vnc.passwd && + (flags & VIR_DOMAIN_XML_SECURE)) + virBufferEscapeString(buf, " passwd='%s'", + def->data.vnc.passwd); + + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + if (def->data.sdl.display) + virBufferEscapeString(buf, " display='%s'", + def->data.sdl.display); + + if (def->data.sdl.xauth) + virBufferEscapeString(buf, " xauth='%s'", + def->data.sdl.xauth); + break; + } + + virBufferAddLit(buf, "/>\n"); + + return 0; +} + +char *virDomainDefFormat(virConnectPtr conn, + virDomainDefPtr def, + int flags) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + unsigned char *uuid; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virDomainDiskDefPtr disk; + virDomainNetDefPtr net; + virDomainSoundDefPtr sound; + virDomainInputDefPtr input; + virDomainChrDefPtr chr; + const char *type = NULL, *tmp; + int n, allones = 1; + + if (!(type = virDomainVirtTypeToString(def->virtType))) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected domain type %d"), def->virtType); + goto cleanup; + } + + if (def->id >= 0) + virBufferVSprintf(&buf, "<domain type='%s' id='%d'>\n", type, def->id); + else + virBufferVSprintf(&buf, "<domain type='%s'>\n", type); + + virBufferEscapeString(&buf, " <name>%s</name>\n", def->name); + + uuid = def->uuid; + virUUIDFormat(uuid, uuidstr); + virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr); + + virBufferVSprintf(&buf, " <memory>%lu</memory>\n", def->maxmem); + virBufferVSprintf(&buf, " <currentMemory>%lu</currentMemory>\n", + def->memory); + + for (n = 0 ; n < def->cpumasklen ; n++) + if (def->cpumask[n] != 1) + allones = 0; + + if (allones) { + virBufferVSprintf(&buf, " <vcpu>%lu</vcpu>\n", def->vcpus); + } else { + char *cpumask = NULL; + if ((cpumask = + virDomainCpuSetFormat(conn, def->cpumask, def->cpumasklen)) == NULL) + goto cleanup; + virBufferVSprintf(&buf, " <vcpu cpuset='%s'>%lu</vcpu>\n", + cpumask, def->vcpus); + VIR_FREE(cpumask); + } + + if (def->os.bootloader) { + virBufferEscapeString(&buf, " <bootloader>%s</bootloader>\n", + def->os.bootloader); + if (def->os.bootloaderArgs) + virBufferEscapeString(&buf, " <bootloader_args>%s</bootloader_args>\n", + def->os.bootloaderArgs); + } + virBufferAddLit(&buf, " <os>\n"); + + virBufferAddLit(&buf, " <type"); + if (def->os.arch) + virBufferVSprintf(&buf, " arch='%s'", def->os.arch); + if (def->os.machine) + virBufferVSprintf(&buf, " machine='%s'", def->os.machine); + /* + * HACK: For xen driver we previously used bogus 'linux' as the + * os type for paravirt, whereas capabilities declare it to + * be 'xen'. So we convert to the former for backcompat + */ + if (def->virtType == VIR_DOMAIN_VIRT_XEN && + STREQ(def->os.type, "xen")) + virBufferVSprintf(&buf, ">%s</type>\n", "linux"); + else + virBufferVSprintf(&buf, ">%s</type>\n", def->os.type); + + if (def->os.loader) + virBufferEscapeString(&buf, " <loader>%s</loader>\n", + def->os.loader); + if (def->os.kernel) + virBufferEscapeString(&buf, " <kernel>%s</kernel>\n", + def->os.kernel); + if (def->os.initrd) + virBufferEscapeString(&buf, " <initrd>%s</initrd>\n", + def->os.initrd); + if (def->os.cmdline) + virBufferEscapeString(&buf, " <cmdline>%s</cmdline>\n", + def->os.cmdline); + if (def->os.root) + virBufferEscapeString(&buf, " <root>%s</root>\n", + def->os.root); + + if (!def->os.bootloader) { + for (n = 0 ; n < def->os.nBootDevs ; n++) { + const char *boottype = + virDomainBootTypeToString(def->os.bootDevs[n]); + if (!boottype) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected boot device type %d"), + def->os.bootDevs[n]); + goto cleanup; + } + virBufferVSprintf(&buf, " <boot dev='%s'/>\n", boottype); + } + } + + virBufferAddLit(&buf, " </os>\n"); + + if (def->features) { + int i; + virBufferAddLit(&buf, " <features>\n"); + for (i = 0 ; i < VIR_DOMAIN_FEATURE_LAST ; i++) { + if (def->features & (1 << i)) { + const char *name = virDomainFeatureTypeToString(i); + if (!name) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected feature %d"), i); + goto cleanup; + } + virBufferVSprintf(&buf, " <%s/>\n", name); + } + } + virBufferAddLit(&buf, " </features>\n"); + } + + virBufferVSprintf(&buf, " <clock offset='%s'/>\n", + def->localtime ? "localtime" : "utc"); + + if (virDomainLifecycleDefFormat(conn, &buf, def->onPoweroff, + "on_poweroff") < 0) + goto cleanup; + if (virDomainLifecycleDefFormat(conn, &buf, def->onReboot, + "on_reboot") < 0) + goto cleanup; + if (virDomainLifecycleDefFormat(conn, &buf, def->onCrash, + "on_crash") < 0) + goto cleanup; + + virBufferAddLit(&buf, " <devices>\n"); + + if (def->emulator) + virBufferEscapeString(&buf, " <emulator>%s</emulator>\n", + def->emulator); + + disk = def->disks; + while (disk) { + if (virDomainDiskDefFormat(conn, &buf, disk) < 0) + goto cleanup; + disk = disk->next; + } + + net = def->nets; + while (net) { + if (virDomainNetDefFormat(conn, &buf, net) < 0) + goto cleanup; + net = net->next; + } + + + chr = def->serials; + while (chr) { + if (virDomainChrDefFormat(conn, &buf, chr, "serial") < 0) + goto cleanup; + chr = chr->next; + } + + chr = def->parallels; + while (chr) { + if (virDomainChrDefFormat(conn, &buf, chr, "parallel") < 0) + goto cleanup; + chr = chr->next; + } + + /* If there's a PV console that's preferred.. */ + if (def->console) { + if (virDomainChrDefFormat(conn, &buf, def->console, "console") < 0) + goto cleanup; + } else if (def->serials != NULL) { + /* ..else for legacy compat duplicate the serial device as a console */ + if (virDomainChrDefFormat(conn, &buf, def->serials, "console") < 0) + goto cleanup; + } + + input = def->inputs; + while (input) { + if (input->bus == VIR_DOMAIN_INPUT_BUS_USB && + virDomainInputDefFormat(conn, &buf, input) < 0) + goto cleanup; + input = input->next; + } + + if (def->graphics) { + /* If graphics is enabled, add the implicit mouse */ + virDomainInputDef autoInput = { + VIR_DOMAIN_INPUT_TYPE_MOUSE, + STREQ(def->os.type, "hvm") ? + VIR_DOMAIN_INPUT_BUS_PS2 : VIR_DOMAIN_INPUT_BUS_XEN, + NULL }; + + if (virDomainInputDefFormat(conn, &buf, &autoInput) < 0) + goto cleanup; + + if (virDomainGraphicsDefFormat(conn, &buf, def->graphics, flags) < 0) + goto cleanup; + } + + sound = def->sounds; + while(sound) { + if (virDomainSoundDefFormat(conn, &buf, sound) < 0) + goto cleanup; + sound = sound->next; + } + + virBufferAddLit(&buf, " </devices>\n"); + virBufferAddLit(&buf, "</domain>\n"); + + if (virBufferError(&buf)) + goto no_memory; + + return virBufferContentAndReset(&buf); + + no_memory: + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + cleanup: + tmp = virBufferContentAndReset(&buf); + VIR_FREE(tmp); + return NULL; +} + + +int virDomainSaveConfig(virConnectPtr conn, + const char *configDir, + const char *autostartDir, + virDomainObjPtr dom) +{ + char *xml; + int fd = -1, ret = -1; + int towrite; + int err; + + if (!dom->configFile && + asprintf(&dom->configFile, "%s/%s.xml", + configDir, dom->def->name) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto cleanup; + } + if (!dom->autostartLink && + asprintf(&dom->autostartLink, "%s/%s.xml", + autostartDir, dom->def->name) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto cleanup; + } + + if (!(xml = virDomainDefFormat(conn, + dom->newDef ? dom->newDef : dom->def, + VIR_DOMAIN_XML_SECURE))) + return -1; + + if ((err = virFileMakePath(configDir))) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot create config directory %s: %s"), + configDir, strerror(err)); + goto cleanup; + } + + if ((err = virFileMakePath(autostartDir))) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot create autostart directory %s: %s"), + autostartDir, strerror(err)); + goto cleanup; + } + + if ((fd = open(dom->configFile, + O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR )) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot create config file %s: %s"), + dom->configFile, strerror(errno)); + goto cleanup; + } + + towrite = strlen(xml); + if (safewrite(fd, xml, towrite) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot write config file %s: %s"), + dom->configFile, strerror(errno)); + goto cleanup; + } + + if (close(fd) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot save config file %s: %s"), + dom->configFile, strerror(errno)); + goto cleanup; + } + + ret = 0; + + cleanup: + VIR_FREE(xml); + close(fd); + + return ret; +} + +virDomainObjPtr virDomainLoadConfig(virConnectPtr conn, + virCapsPtr caps, + virDomainObjPtr *doms, + const char *configDir, + const char *autostartDir, + const char *file) +{ + char *configFile, *autostartLink; + virDomainDefPtr def = NULL; + virDomainObjPtr dom; + int autostart; + + if (asprintf(&configFile, "%s/%s", + configDir, file) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + if (asprintf(&autostartLink, "%s/%s", + autostartDir, file) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + + if ((autostart = virFileLinkPointsTo(autostartLink, configFile)) < 0) + goto error; + + if (!(def = virDomainDefParseFile(conn, caps, file))) + goto error; + + if (!virFileMatchesNameSuffix(file, def->name, ".xml")) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Domain config filename '%s'" + " does not match domain name '%s'"), + configFile, def->name); + goto error; + } + + if (!(dom = virDomainAssignDef(conn, doms, def))) + goto error; + + dom->configFile = configFile; + dom->autostartLink = autostartLink; + dom->autostart = autostart; + + return dom; + +error: + VIR_FREE(configFile); + VIR_FREE(autostartLink); + virDomainDefFree(def); + return NULL; +} + +int virDomainLoadAllConfigs(virConnectPtr conn, + virCapsPtr caps, + virDomainObjPtr *doms, + const char *configDir, + const char *autostartDir) +{ + DIR *dir; + struct dirent *entry; + + if (!(dir = opendir(configDir))) { + if (errno == ENOENT) + return 0; + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Failed to open dir '%s': %s"), + configDir, strerror(errno)); + return -1; + } + + while ((entry = readdir(dir))) { + if (entry->d_name[0] == '.') + continue; + + if (!virFileHasSuffix(entry->d_name, ".xml")) + continue; + + /* NB: ignoring errors, so one malformed config doesn't + kill the whole process */ + virDomainLoadConfig(conn, + caps, + doms, + configDir, + autostartDir, + entry->d_name); + } + + closedir(dir); + + return 0; +} + +int virDomainDeleteConfig(virConnectPtr conn, + virDomainObjPtr dom) +{ + if (!dom->configFile || !dom->autostartLink) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("no config file for %s"), dom->def->name); + return -1; + } + + /* Not fatal if this doesn't work */ + unlink(dom->autostartLink); + + if (unlink(dom->configFile) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot remove config for %s"), dom->def->name); + return -1; + } + + return 0; +} diff -r a77ea50ba693 src/domain_conf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/domain_conf.h Tue Jul 08 15:26:51 2008 +0100 @@ -0,0 +1,489 @@ +/* + * domain_conf.h: domain XML processing + * + * Copyright (C) 2006-2008 Red Hat, Inc. + * Copyright (C) 2006-2008 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange <berrange@redhat.com> + */ + +#ifndef __DOMAIN_CONF_H +#define __DOMAIN_CONF_H + +#include <config.h> + +#include "internal.h" +#include "capabilities.h" +#include "util.h" + +/* Different types of hypervisor */ +/* NB: Keep in sync with virDomainVirtTypeToString impl */ +enum virDomainVirtType { + VIR_DOMAIN_VIRT_QEMU, + VIR_DOMAIN_VIRT_KQEMU, + VIR_DOMAIN_VIRT_KVM, + VIR_DOMAIN_VIRT_XEN, + VIR_DOMAIN_VIRT_LXC, + VIR_DOMAIN_VIRT_UML, + VIR_DOMAIN_VIRT_OPENVZ, + VIR_DOMAIN_VIRT_VSERVER, + VIR_DOMAIN_VIRT_LDOM, + VIR_DOMAIN_VIRT_TEST, + VIR_DOMAIN_VIRT_VMWARE, + VIR_DOMAIN_VIRT_HYPERV, + + VIR_DOMAIN_VIRT_LAST, +}; + +/* Two types of disk backends */ +enum virDomainDiskType { + VIR_DOMAIN_DISK_TYPE_BLOCK, + VIR_DOMAIN_DISK_TYPE_FILE, + + VIR_DOMAIN_DISK_TYPE_LAST +}; + +/* Three types of disk frontend */ +enum virDomainDiskDevice { + VIR_DOMAIN_DISK_DEVICE_DISK, + VIR_DOMAIN_DISK_DEVICE_CDROM, + VIR_DOMAIN_DISK_DEVICE_FLOPPY, + + VIR_DOMAIN_DISK_DEVICE_LAST +}; + +enum virDomainDiskBus { + VIR_DOMAIN_DISK_BUS_IDE, + VIR_DOMAIN_DISK_BUS_FDC, + VIR_DOMAIN_DISK_BUS_SCSI, + VIR_DOMAIN_DISK_BUS_VIRTIO, + VIR_DOMAIN_DISK_BUS_XEN, + + VIR_DOMAIN_DISK_BUS_LAST +}; + +/* Stores the virtual disk configuration */ +typedef struct _virDomainDiskDef virDomainDiskDef; +typedef virDomainDiskDef *virDomainDiskDefPtr; +struct _virDomainDiskDef { + int type; + int device; + int bus; + char *src; + char *dst; + char *driverName; + char *driverType; + unsigned int readonly : 1; + unsigned int shared : 1; + + virDomainDiskDefPtr next; +}; + + +/* 5 different types of networking config */ +enum virDomainNetType { + VIR_DOMAIN_NET_TYPE_USER, + VIR_DOMAIN_NET_TYPE_ETHERNET, + VIR_DOMAIN_NET_TYPE_SERVER, + VIR_DOMAIN_NET_TYPE_CLIENT, + VIR_DOMAIN_NET_TYPE_MCAST, + VIR_DOMAIN_NET_TYPE_NETWORK, + VIR_DOMAIN_NET_TYPE_BRIDGE, + + VIR_DOMAIN_NET_TYPE_LAST, +}; + + +#define VIR_DOMAIN_NET_MAC_SIZE 6 + +/* Stores the virtual network interface configuration */ +typedef struct _virDomainNetDef virDomainNetDef; +typedef virDomainNetDef *virDomainNetDefPtr; +struct _virDomainNetDef { + int type; + unsigned char mac[VIR_DOMAIN_NET_MAC_SIZE]; + char *model; + union { + struct { + char *dev; + char *script; + char *ipaddr; + } ethernet; + struct { + char *address; + int port; + } socket; /* any of NET_CLIENT or NET_SERVER or NET_MCAST */ + struct { + char *name; + } network; + struct { + char *brname; + } bridge; + } data; + char *ifname; + + virDomainNetDefPtr next; +}; + +enum virDomainChrSrcType { + VIR_DOMAIN_CHR_TYPE_NULL, + VIR_DOMAIN_CHR_TYPE_VC, + VIR_DOMAIN_CHR_TYPE_PTY, + VIR_DOMAIN_CHR_TYPE_DEV, + VIR_DOMAIN_CHR_TYPE_FILE, + VIR_DOMAIN_CHR_TYPE_PIPE, + VIR_DOMAIN_CHR_TYPE_STDIO, + VIR_DOMAIN_CHR_TYPE_UDP, + VIR_DOMAIN_CHR_TYPE_TCP, + VIR_DOMAIN_CHR_TYPE_UNIX, + + VIR_DOMAIN_CHR_TYPE_LAST, +}; + +enum virDomainChrTcpProtocol { + VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW, + VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET, + + VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST, +}; + +typedef struct _virDomainChrDef virDomainChrDef; +typedef virDomainChrDef *virDomainChrDefPtr; +struct _virDomainChrDef { + int dstPort; + + int type; + union { + struct { + char *path; + } file; /* pty, file, pipe, or device */ + struct { + char *host; + char *service; + int listen; + int protocol; + } tcp; + struct { + char *bindHost; + char *bindService; + char *connectHost; + char *connectService; + } udp; + struct { + char *path; + int listen; + } nix; + } data; + + virDomainChrDefPtr next; +}; + +enum virDomainInputType { + VIR_DOMAIN_INPUT_TYPE_MOUSE, + VIR_DOMAIN_INPUT_TYPE_TABLET, + + VIR_DOMAIN_INPUT_TYPE_LAST, +}; + +enum virDomainInputBus { + VIR_DOMAIN_INPUT_BUS_PS2, + VIR_DOMAIN_INPUT_BUS_USB, + VIR_DOMAIN_INPUT_BUS_XEN, + + VIR_DOMAIN_INPUT_BUS_LAST +}; + +typedef struct _virDomainInputDef virDomainInputDef; +typedef virDomainInputDef *virDomainInputDefPtr; +struct _virDomainInputDef { + int type; + int bus; + virDomainInputDefPtr next; +}; + +enum virDomainSoundModel { + VIR_DOMAIN_SOUND_MODEL_SB16, + VIR_DOMAIN_SOUND_MODEL_ES1370, + VIR_DOMAIN_SOUND_MODEL_PCSPK, + + VIR_DOMAIN_SOUND_MODEL_LAST +}; + +typedef struct _virDomainSoundDef virDomainSoundDef; +typedef virDomainSoundDef *virDomainSoundDefPtr; +struct _virDomainSoundDef { + int model; + virDomainSoundDefPtr next; +}; + +/* 3 possible graphics console modes */ +enum virDomainGraphicsType { + VIR_DOMAIN_GRAPHICS_TYPE_SDL, + VIR_DOMAIN_GRAPHICS_TYPE_VNC, + + VIR_DOMAIN_GRAPHICS_TYPE_LAST, +}; + +typedef struct _virDomainGraphicsDef virDomainGraphicsDef; +typedef virDomainGraphicsDef *virDomainGraphicsDefPtr; +struct _virDomainGraphicsDef { + int type; + union { + struct { + int port; + int autoport : 1; + char *listenAddr; + char *keymap; + char *passwd; + } vnc; + struct { + char *display; + char *xauth; + } sdl; + } data; +}; + + + +/* Flags for the 'type' field in next struct */ +enum virDomainDeviceType { + VIR_DOMAIN_DEVICE_DISK, + VIR_DOMAIN_DEVICE_NET, + VIR_DOMAIN_DEVICE_INPUT, + VIR_DOMAIN_DEVICE_SOUND, +}; + +typedef struct _virDomainDeviceDef virDomainDeviceDef; +typedef virDomainDeviceDef *virDomainDeviceDefPtr; +struct _virDomainDeviceDef { + int type; + union { + virDomainDiskDefPtr disk; + virDomainNetDefPtr net; + virDomainInputDefPtr input; + virDomainSoundDefPtr sound; + } data; +}; + + +#define VIR_DOMAIN_MAX_BOOT_DEVS 4 + +/* 3 possible boot devices */ +enum virDomainBootOrder { + VIR_DOMAIN_BOOT_FLOPPY, + VIR_DOMAIN_BOOT_CDROM, + VIR_DOMAIN_BOOT_DISK, + VIR_DOMAIN_BOOT_NET, + + VIR_DOMAIN_BOOT_LAST, +}; + +enum virDomainFeature { + VIR_DOMAIN_FEATURE_ACPI, + VIR_DOMAIN_FEATURE_APIC, + VIR_DOMAIN_FEATURE_PAE, + + VIR_DOMAIN_FEATURE_LAST +}; + +enum virDomainLifecycleAction { + VIR_DOMAIN_LIFECYCLE_DESTROY, + VIR_DOMAIN_LIFECYCLE_RESTART, + VIR_DOMAIN_LIFECYCLE_RESTART_RENAME, + VIR_DOMAIN_LIFECYCLE_PRESERVE, + + VIR_DOMAIN_LIFECYCLE_LAST +}; + +/* Operating system configuration data & machine / arch */ +typedef struct _virDomainOSDef virDomainOSDef; +typedef virDomainOSDef *virDomainOSDefPtr; +struct _virDomainOSDef { + char *type; + char *arch; + char *machine; + int nBootDevs; + int bootDevs[VIR_DOMAIN_BOOT_LAST]; + char *kernel; + char *initrd; + char *cmdline; + char *root; + char *loader; + char *bootloader; + char *bootloaderArgs; +}; + +#define VIR_DOMAIN_CPUMASK_LEN 1024 + +/* Guest VM main configuration */ +typedef struct _virDomainDef virDomainDef; +typedef virDomainDef *virDomainDefPtr; +struct _virDomainDef { + int virtType; + int id; + unsigned char uuid[VIR_UUID_BUFLEN]; + char *name; + + unsigned long memory; + unsigned long maxmem; + unsigned long vcpus; + int cpumasklen; + char *cpumask; + + /* These 3 are based on virDomainLifeCycleAction enum flags */ + int onReboot; + int onPoweroff; + int onCrash; + + virDomainOSDef os; + char *emulator; + int features; + + int localtime; + + virDomainGraphicsDefPtr graphics; + virDomainDiskDefPtr disks; + virDomainNetDefPtr nets; + virDomainInputDefPtr inputs; + virDomainSoundDefPtr sounds; + virDomainChrDefPtr serials; + virDomainChrDefPtr parallels; + virDomainChrDefPtr console; +}; + +/* Guest VM runtime state */ +typedef struct _virDomainObj virDomainObj; +typedef virDomainObj *virDomainObjPtr; +struct _virDomainObj { + int stdin; + int stdout; + int stderr; + int monitor; + int logfile; + int pid; + int state; + + int nvcpupids; + int *vcpupids; + + unsigned int autostart : 1; + unsigned int persistent : 1; + + char *configFile; + char *autostartLink; + + virDomainDefPtr def; /* The current definition */ + virDomainDefPtr newDef; /* New definition to activate at shutdown */ + + virDomainObjPtr next; +}; + + +static inline int +virDomainIsActive(virDomainObjPtr dom) +{ + return dom->def->id != -1; +} + + +virDomainObjPtr virDomainFindByID(const virDomainObjPtr doms, + int id); +virDomainObjPtr virDomainFindByUUID(const virDomainObjPtr doms, + const unsigned char *uuid); +virDomainObjPtr virDomainFindByName(const virDomainObjPtr doms, + const char *name); + + +void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def); +void virDomainInputDefFree(virDomainInputDefPtr def); +void virDomainDiskDefFree(virDomainDiskDefPtr def); +void virDomainNetDefFree(virDomainNetDefPtr def); +void virDomainChrDefFree(virDomainChrDefPtr def); +void virDomainSoundDefFree(virDomainSoundDefPtr def); +void virDomainDeviceDefFree(virDomainDeviceDefPtr def); +void virDomainDefFree(virDomainDefPtr vm); +void virDomainObjFree(virDomainObjPtr vm); + +virDomainObjPtr virDomainAssignDef(virConnectPtr conn, + virDomainObjPtr *doms, + const virDomainDefPtr def); +void virDomainRemoveInactive(virDomainObjPtr *doms, + virDomainObjPtr dom); + +virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn, + const virDomainDefPtr def, + const char *xmlStr); +virDomainDefPtr virDomainDefParseString(virConnectPtr conn, + virCapsPtr caps, + const char *xmlStr); +virDomainDefPtr virDomainDefParseFile(virConnectPtr conn, + virCapsPtr caps, + const char *filename); +virDomainDefPtr virDomainDefParseNode(virConnectPtr conn, + virCapsPtr caps, + xmlDocPtr doc, + xmlNodePtr root); +char *virDomainDefFormat(virConnectPtr conn, + virDomainDefPtr def, + int flags); + +int virDomainCpuSetParse(virConnectPtr conn, + const char **str, + char sep, + char *cpuset, + int maxcpu); +char *virDomainCpuSetFormat(virConnectPtr conn, + char *cpuset, + int maxcpu); + + +int virDomainSaveConfig(virConnectPtr conn, + const char *configDir, + const char *autostartDir, + virDomainObjPtr dom); + +virDomainObjPtr virDomainLoadConfig(virConnectPtr conn, + virCapsPtr caps, + virDomainObjPtr *doms, + const char *configDir, + const char *autostartDir, + const char *file); + +int virDomainLoadAllConfigs(virConnectPtr conn, + virCapsPtr caps, + virDomainObjPtr *doms, + const char *configDir, + const char *autostartDir); + +int virDomainDeleteConfig(virConnectPtr conn, + virDomainObjPtr dom); + +VIR_ENUM_DECL(virDomainVirt) +VIR_ENUM_DECL(virDomainBoot) +VIR_ENUM_DECL(virDomainFeature) +VIR_ENUM_DECL(virDomainLifecycle) +VIR_ENUM_DECL(virDomainDisk) +VIR_ENUM_DECL(virDomainDiskDevice) +VIR_ENUM_DECL(virDomainDiskBus) +VIR_ENUM_DECL(virDomainNet) +VIR_ENUM_DECL(virDomainChr) +VIR_ENUM_DECL(virDomainSoundModel) +VIR_ENUM_DECL(virDomainInput) +VIR_ENUM_DECL(virDomainInputBus) +VIR_ENUM_DECL(virDomainGraphics) + +#endif /* __DOMAIN_CONF_H */ diff -r a77ea50ba693 src/util.h --- a/src/util.h Tue Jul 08 15:26:26 2008 +0100 +++ b/src/util.h Tue Jul 08 15:26:51 2008 +0100 @@ -100,7 +100,7 @@ #define VIR_ENUM_IMPL(name, lastVal, ...) \ static const char const *name ## TypeList[] = { __VA_ARGS__ }; \ - verify(ARRAY_CARDINALITY(name ## TypeList) == lastVal); \ + extern int (* name ## Verify (void)) [verify_true (ARRAY_CARDINALITY(name ## TypeList) == lastVal)]; \ const char *name ## TypeToString(int type) { \ return virEnumToString(name ## TypeList, \ ARRAY_CARDINALITY(name ## TypeList), \ diff -r a77ea50ba693 src/virterror.c --- a/src/virterror.c Tue Jul 08 15:26:26 2008 +0100 +++ b/src/virterror.c Tue Jul 08 15:26:51 2008 +0100 @@ -306,6 +306,9 @@ break; case VIR_FROM_NETWORK: dom = "Network Config "; + break; + case VIR_FROM_DOMAIN: + dom = "Domain Config "; break; } diff -r a77ea50ba693 src/xml.c --- a/src/xml.c Tue Jul 08 15:26:26 2008 +0100 +++ b/src/xml.c Tue Jul 08 15:26:51 2008 +0100 @@ -551,6 +551,13 @@ return (ret); } +char * +virXMLPropString(xmlNodePtr node, + const char *name) +{ + return (char *)xmlGetProp(node, BAD_CAST name); +} + /** * virXPathBoolean: * @xpath: the XPath string to evaluate @@ -648,20 +655,21 @@ _("Invalid parameter to virXPathNodeSet()"), 0); return (-1); } + + if (list != NULL) + *list = NULL; + relnode = ctxt->node; obj = xmlXPathEval(BAD_CAST xpath, ctxt); if ((obj == NULL) || (obj->type != XPATH_NODESET) || - (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) || - (obj->nodesetval->nodeTab == NULL)) { + (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr < 0)) { xmlXPathFreeObject(obj); - if (list != NULL) - *list = NULL; ctxt->node = relnode; return (-1); } ret = obj->nodesetval->nodeNr; - if (list != NULL) { + if (list != NULL && ret) { if (VIR_ALLOC_N(*list, ret) < 0) { virXMLError(NULL, VIR_ERR_NO_MEMORY, _("allocate string array"), diff -r a77ea50ba693 src/xml.h --- a/src/xml.h Tue Jul 08 15:26:26 2008 +0100 +++ b/src/xml.h Tue Jul 08 15:26:51 2008 +0100 @@ -23,6 +23,12 @@ int virXPathNumber (const char *xpath, xmlXPathContextPtr ctxt, double *value); +int virXPathInt (const char *xpath, + xmlXPathContextPtr ctxt, + int *value); +int virXPathUInt (const char *xpath, + xmlXPathContextPtr ctxt, + unsigned int *value); int virXPathLong (const char *xpath, xmlXPathContextPtr ctxt, long *value); @@ -34,6 +40,10 @@ int virXPathNodeSet (const char *xpath, xmlXPathContextPtr ctxt, xmlNodePtr **list); + +char * virXMLPropString(xmlNodePtr node, + const char *name); + #if WITH_XEN || WITH_QEMU int virParseCpuSet (virConnectPtr conn, -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

...
+static virDomainChrDefPtr +virDomainChrDefParseXML(virConnectPtr conn, + xmlNodePtr node) { + xmlNodePtr cur; + char *type = NULL; + char *bindHost = NULL; + char *bindService = NULL; + char *connectHost = NULL; + char *connectService = NULL; + char *path = NULL; + char *mode = NULL; + char *protocol = NULL; + virDomainChrDefPtr def; + + if (VIR_ALLOC(def) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + def->type = VIR_DOMAIN_CHR_TYPE_PTY; + type = virXMLPropString(node, "type"); + if (type != NULL) {
Looks like this can be replaced with virDomainChrTypeFromString.
+ if (STREQ(type, "null")) + def->type = VIR_DOMAIN_CHR_TYPE_NULL; + else if (STREQ(type, "vc")) + def->type = VIR_DOMAIN_CHR_TYPE_VC; + else if (STREQ(type, "pty")) + def->type = VIR_DOMAIN_CHR_TYPE_PTY; + else if (STREQ(type, "dev")) + def->type = VIR_DOMAIN_CHR_TYPE_DEV; + else if (STREQ(type, "file")) + def->type = VIR_DOMAIN_CHR_TYPE_FILE; + else if (STREQ(type, "pipe")) + def->type = VIR_DOMAIN_CHR_TYPE_PIPE; + else if (STREQ(type, "stdio")) + def->type = VIR_DOMAIN_CHR_TYPE_STDIO; + else if (STREQ(type, "udp")) + def->type = VIR_DOMAIN_CHR_TYPE_UDP; + else if (STREQ(type, "tcp")) + def->type = VIR_DOMAIN_CHR_TYPE_TCP; + else if (STREQ(type, "unix")) + def->type = VIR_DOMAIN_CHR_TYPE_UNIX; + else + def->type = VIR_DOMAIN_CHR_TYPE_NULL; + }
Otherwise, all looks good. ACK

On Fri, Jul 18, 2008 at 06:29:15PM +0200, Jim Meyering wrote:
Looks like this can be replaced with virDomainChrTypeFromString.
+ if (STREQ(type, "null")) + def->type = VIR_DOMAIN_CHR_TYPE_NULL; + else if (STREQ(type, "vc")) + def->type = VIR_DOMAIN_CHR_TYPE_VC; + else if (STREQ(type, "pty")) + def->type = VIR_DOMAIN_CHR_TYPE_PTY; + else if (STREQ(type, "dev")) + def->type = VIR_DOMAIN_CHR_TYPE_DEV; + else if (STREQ(type, "file")) + def->type = VIR_DOMAIN_CHR_TYPE_FILE; + else if (STREQ(type, "pipe")) + def->type = VIR_DOMAIN_CHR_TYPE_PIPE; + else if (STREQ(type, "stdio")) + def->type = VIR_DOMAIN_CHR_TYPE_STDIO; + else if (STREQ(type, "udp")) + def->type = VIR_DOMAIN_CHR_TYPE_UDP; + else if (STREQ(type, "tcp")) + def->type = VIR_DOMAIN_CHR_TYPE_TCP; + else if (STREQ(type, "unix")) + def->type = VIR_DOMAIN_CHR_TYPE_UNIX; + else + def->type = VIR_DOMAIN_CHR_TYPE_NULL; + }
Good point, i'll fix this in CVS Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch ports the Test driver to use the network XML apis. Basically the 'struct _testNet' is removed, and replaced by usage of the generic virNetworkObjPtr and virNetworkDefPtr objects. The XML parser and formatters are ripped out and replaced by calls to the generic APIs in network_conf.h. Finally there is just alot of cleanup of all the individual network driver implementations to adjust to the style of the new APIs used. Plenty of bug fixes since the last time I posted this. test.c | 527 ++++++++++++++++++----------------------------------------------- 1 file changed, 151 insertions(+), 376 deletions(-) Daniel diff -r 467b420d4082 src/test.c --- a/src/test.c Mon Jul 07 11:15:51 2008 +0100 +++ b/src/test.c Mon Jul 07 11:30:00 2008 +0100 @@ -46,6 +46,7 @@ #include "uuid.h" #include "capabilities.h" #include "memory.h" +#include "network_conf.h" /* Flags that determine the action to take on a shutdown or crash of a domain */ @@ -85,26 +86,6 @@ typedef struct _testDom testDom; typedef struct _testDom *testDomPtr; -struct _testNet { - int active; - int config; - int running; - char name[20]; - char bridge[20]; - unsigned char uuid[VIR_UUID_BUFLEN]; - int forward; - char forwardDev[IF_NAMESIZE]; - char ipAddress[INET_ADDRSTRLEN]; - char ipNetmask[INET_ADDRSTRLEN]; - - char dhcpStart[INET_ADDRSTRLEN]; - char dhcpEnd[INET_ADDRSTRLEN]; - - int autostart; -}; -typedef struct _testNet testNet; -typedef struct _testNet *testNetPtr; - #define MAX_DOMAINS 20 #define MAX_NETWORKS 20 #define MAX_CPUS 128 @@ -125,8 +106,7 @@ virNodeInfo nodeInfo; int numDomains; testDom domains[MAX_DOMAINS]; - int numNetworks; - testNet networks[MAX_NETWORKS]; + virNetworkObjPtr networks; int numCells; testCell cells[MAX_CELLS]; }; @@ -161,17 +141,18 @@ privdom = &privconn->domains[domidx]; #define GET_NETWORK(net, ret) \ - int netidx; \ testConnPtr privconn; \ - testNetPtr privnet; \ + virNetworkObjPtr privnet; \ \ privconn = (testConnPtr)net->conn->privateData; \ - if ((netidx = getNetworkIndex(net)) < 0) { \ - testError((net)->conn, NULL, (net), VIR_ERR_INVALID_ARG, \ - __FUNCTION__); \ - return (ret); \ - } \ - privnet = &privconn->networks[netidx]; + do { \ + if ((privnet = virNetworkFindByName(privconn->networks, \ + (net)->name)) == NULL) { \ + testError((net)->conn, NULL, (net), VIR_ERR_INVALID_ARG, \ + __FUNCTION__); \ + return (ret); \ + } \ + } while (0) #define GET_CONNECTION(conn, ret) \ testConnPtr privconn; \ @@ -423,191 +404,30 @@ } -static int testLoadNetwork(virConnectPtr conn, - xmlDocPtr xml) { - xmlNodePtr root = NULL; - xmlXPathContextPtr ctxt = NULL; - char *name = NULL, *bridge = NULL; - unsigned char uuid[VIR_UUID_BUFLEN]; - char *str; - char *ipaddress = NULL, *ipnetmask = NULL, *dhcpstart = NULL, *dhcpend = NULL; - int forward; - char *forwardDev = NULL; - int handle = -1, i; - GET_CONNECTION(conn, -1); - - root = xmlDocGetRootElement(xml); - if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "network"))) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("network")); - goto error; - } - - ctxt = xmlXPathNewContext(xml); - if (ctxt == NULL) { - testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("creating xpath context")); - goto error; - } - - name = virXPathString("string(/network/name[1])", ctxt); - if (name == NULL) { - testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("network name")); - goto error; - } - - bridge = virXPathString("string(/network/bridge[1]/@name)", ctxt); - - str = virXPathString("string(/network/uuid[1])", ctxt); - if (str == NULL) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("network uuid")); - goto error; - } - if (virUUIDParse(str, uuid) < 0) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("network uuid")); - goto error; - } - VIR_FREE(str); - - - forward = virXPathBoolean("count(/network/forward) != 0", ctxt); - if (forward < 0) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("network forward")); - goto error; - } - - forwardDev = virXPathString("string(/network/forward/@dev)", ctxt); - - - ipaddress = virXPathString("string(/network/ip/@address)", ctxt); - if (ipaddress == NULL) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("ip address")); - goto error; - } - ipnetmask = virXPathString("string(/network/ip/@netmask)", ctxt); - if (ipnetmask == NULL) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("ip netmask")); - goto error; - } - dhcpstart = virXPathString("string(/network/ip/dhcp/range[1]/@start)", ctxt); - if (dhcpstart == NULL) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("ip address")); - goto error; - } - dhcpend = virXPathString("string(/network/ip/dhcp/range[1]/@end)", ctxt); - if (dhcpend == NULL) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("ip address")); - goto error; - } - - for (i = 0 ; i < MAX_NETWORKS ; i++) { - if (!privconn->networks[i].active) { - handle = i; - break; - } - } - if (handle < 0) - return (-1); - - privconn->networks[handle].active = 1; - privconn->networks[handle].running = 1; - strncpy(privconn->networks[handle].name, name, sizeof(privconn->networks[handle].name)-1); - privconn->networks[handle].name[sizeof(privconn->networks[handle].name)-1] = '\0'; - strncpy(privconn->networks[handle].bridge, bridge ? bridge : name, sizeof(privconn->networks[handle].bridge)-1); - privconn->networks[handle].bridge[sizeof(privconn->networks[handle].bridge)-1] = '\0'; - VIR_FREE(name); - name = NULL; - if (bridge) { - VIR_FREE(bridge); - bridge = NULL; - } - - memmove(privconn->networks[handle].uuid, uuid, VIR_UUID_BUFLEN); - privconn->networks[handle].forward = forward; - if (forwardDev) { - strncpy(privconn->networks[handle].forwardDev, forwardDev, sizeof(privconn->networks[handle].forwardDev)-1); - privconn->networks[handle].forwardDev[sizeof(privconn->networks[handle].forwardDev)-1] = '\0'; - VIR_FREE(forwardDev); - } - - strncpy(privconn->networks[handle].ipAddress, ipaddress, sizeof(privconn->networks[handle].ipAddress)-1); - privconn->networks[handle].ipAddress[sizeof(privconn->networks[handle].ipAddress)-1] = '\0'; - VIR_FREE(ipaddress); - strncpy(privconn->networks[handle].ipNetmask, ipnetmask, sizeof(privconn->networks[handle].ipNetmask)-1); - privconn->networks[handle].ipNetmask[sizeof(privconn->networks[handle].ipNetmask)-1] = '\0'; - VIR_FREE(ipnetmask); - strncpy(privconn->networks[handle].dhcpStart, dhcpstart, sizeof(privconn->networks[handle].dhcpStart)-1); - privconn->networks[handle].dhcpStart[sizeof(privconn->networks[handle].dhcpStart)-1] = '\0'; - VIR_FREE(dhcpstart); - strncpy(privconn->networks[handle].dhcpEnd, dhcpend, sizeof(privconn->networks[handle].dhcpEnd)-1); - privconn->networks[handle].dhcpEnd[sizeof(privconn->networks[handle].dhcpEnd)-1] = '\0'; - VIR_FREE(dhcpend); - xmlXPathFreeContext(ctxt); - return (handle); - - error: - xmlXPathFreeContext(ctxt); - VIR_FREE (forwardDev); - VIR_FREE(ipaddress); - VIR_FREE(ipnetmask); - VIR_FREE(dhcpstart); - VIR_FREE(dhcpend); - VIR_FREE(name); - return (-1); -} - -static int testLoadNetworkFromDoc(virConnectPtr conn, - const char *doc) { - int ret; - xmlDocPtr xml; - if (!(xml = xmlReadDoc(BAD_CAST doc, "network.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("network")); - return (-1); - } - - ret = testLoadNetwork(conn, xml); - - xmlFreeDoc(xml); - - return (ret); -} - - -static int testLoadNetworkFromFile(virConnectPtr conn, - const char *filename) { - int ret, fd; - xmlDocPtr xml; - - if ((fd = open(filename, O_RDONLY)) < 0) { - testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("load network definition file")); - return (-1); - } - - if (!(xml = xmlReadFd(fd, filename, NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("network")); - return (-1); - } - - ret = testLoadNetwork(conn, xml); - - xmlFreeDoc(xml); - close(fd); - - return (ret); -} +static const char *defaultNetworkXML = +"<network>" +" <name>default</name>" +" <bridge name='virbr0' />" +" <forward/>" +" <ip address='192.168.122.1' netmask='255.255.255.0'>" +" <dhcp>" +" <range start='192.168.122.2' end='192.168.122.254' />" +" </dhcp>" +" </ip>" +"</network>"; static int testOpenDefault(virConnectPtr conn) { int u; struct timeval tv; testConnPtr privconn; + virNetworkDefPtr netdef; + virNetworkObjPtr netobj; + if (VIR_ALLOC(privconn) < 0) { testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "testConn"); return VIR_DRV_OPEN_ERROR; } - memset(privconn, 0, sizeof(testConn)); if (gettimeofday(&tv, NULL) < 0) { testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day")); @@ -636,21 +456,15 @@ privconn->domains[0].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll)); - privconn->numNetworks = 1; - privconn->networks[0].active = 1; - privconn->networks[0].config = 1; - privconn->networks[0].running = 1; - strcpy(privconn->networks[0].name, "default"); - strcpy(privconn->networks[0].bridge, "default"); - for (u = 0 ; u < VIR_UUID_BUFLEN ; u++) { - privconn->networks[0].uuid[u] = (u * 75)%255; + if (!(netdef = virNetworkDefParseString(conn, defaultNetworkXML))) { + return VIR_DRV_OPEN_ERROR; } - privconn->networks[0].forward = 1; - strcpy(privconn->networks[0].forwardDev, "eth0"); - strcpy(privconn->networks[0].ipAddress, "192.168.122.1"); - strcpy(privconn->networks[0].ipNetmask, "255.255.255.0"); - strcpy(privconn->networks[0].dhcpStart, "192.168.122.128"); - strcpy(privconn->networks[0].dhcpEnd, "192.168.122.253"); + if (!(netobj = virNetworkAssignDef(conn, &privconn->networks, netdef))) { + virNetworkDefFree(netdef); + return VIR_DRV_OPEN_ERROR; + } + netobj->active = 1; + netobj->persistent = 1; // Numa setup privconn->numCells = 2; @@ -736,7 +550,6 @@ conn->privateData = privconn; privconn->nextDomID = 1; privconn->numDomains = 0; - privconn->numNetworks = 0; privconn->numCells = 0; strncpy(privconn->path, file, PATH_MAX-1); privconn->path[PATH_MAX-1] = '\0'; @@ -838,28 +651,41 @@ ret = virXPathNodeSet("/node/network", ctxt, &networks); - if (ret > 0) { - for (i = 0 ; i < ret ; i++) { - xmlChar *netFile = xmlGetProp(networks[i], BAD_CAST "file"); - char *absFile = testBuildFilename(file, (const char *)netFile); - int handle; - VIR_FREE(netFile); + if (ret < 0) { + testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node network list")); + goto error; + } + for (i = 0 ; i < ret ; i++) { + virNetworkDefPtr def; + virNetworkObjPtr net; + char *relFile = virXMLPropString(networks[i], "file"); + if (relFile != NULL) { + char *absFile = testBuildFilename(file, relFile); + VIR_FREE(relFile); if (!absFile) { testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("resolving network filename")); goto error; } - if ((handle = testLoadNetworkFromFile(conn, absFile)) < 0) { - VIR_FREE(absFile); + + def = virNetworkDefParseFile(conn, absFile); + VIR_FREE(absFile); + if (!def) goto error; - } - privconn->networks[handle].config = 1; - VIR_FREE(absFile); - privconn->numNetworks++; + } else { + if ((def = virNetworkDefParseNode(conn, xml, networks[i])) == NULL) + goto error; } - if (networks != NULL) { - VIR_FREE(networks); - networks = NULL; + if (!(net = virNetworkAssignDef(conn, &privconn->networks, + def))) { + virNetworkDefFree(def); + goto error; } + + net->persistent = 1; + } + if (networks != NULL) { + VIR_FREE(networks); + networks = NULL; } xmlXPathFreeContext(ctxt); @@ -892,17 +718,6 @@ if (STREQ(domain->name, privconn->domains[i].name)) return (i); } - } - return (-1); -} - -static int getNetworkIndex(virNetworkPtr network) { - int i; - GET_CONNECTION(network->conn, -1); - - for (i = 0 ; i < MAX_NETWORKS ; i++) { - if (STREQ(network->name, privconn->networks[i].name)) - return (i); } return (-1); } @@ -1742,160 +1557,151 @@ static virNetworkPtr testLookupNetworkByUUID(virConnectPtr conn, const unsigned char *uuid) { - int i, idx = -1; + virNetworkObjPtr net = NULL; GET_CONNECTION(conn, NULL); - for (i = 0 ; i < MAX_NETWORKS ; i++) { - if (privconn->networks[i].active && - memcmp(uuid, privconn->networks[i].uuid, VIR_UUID_BUFLEN) == 0) { - idx = i; - break; - } - } - - if (idx < 0) { + if ((net = virNetworkFindByUUID(privconn->networks, uuid)) == NULL) { testError (conn, NULL, NULL, VIR_ERR_NO_NETWORK, NULL); return NULL; } - return virGetNetwork(conn, privconn->networks[idx].name, privconn->networks[idx].uuid); + return virGetNetwork(conn, net->def->name, net->def->uuid); } static virNetworkPtr testLookupNetworkByName(virConnectPtr conn, - const char *name) + const char *name) { - int i, idx = -1; + virNetworkObjPtr net = NULL; GET_CONNECTION(conn, NULL); - for (i = 0 ; i < MAX_NETWORKS ; i++) { - if (privconn->networks[i].active && - STREQ(name, privconn->networks[i].name)) { - idx = i; - break; - } - } - - if (idx < 0) { + if ((net = virNetworkFindByName(privconn->networks, name)) == NULL) { testError (conn, NULL, NULL, VIR_ERR_NO_NETWORK, NULL); return NULL; } - return virGetNetwork(conn, privconn->networks[idx].name, privconn->networks[idx].uuid); + return virGetNetwork(conn, net->def->name, net->def->uuid); } static int testNumNetworks(virConnectPtr conn) { - int numInactive = 0, i; + int numActive = 0; + virNetworkObjPtr net; GET_CONNECTION(conn, -1); - for (i = 0 ; i < MAX_NETWORKS ; i++) { - if (!privconn->networks[i].active || - !privconn->networks[i].running) - continue; - numInactive++; + net = privconn->networks; + while (net) { + if (virNetworkIsActive(net)) + numActive++; + net = net->next; } - return (numInactive); + return numActive; } static int testListNetworks(virConnectPtr conn, char **const names, int nnames) { - int n = 0, i; + int n = 0; + virNetworkObjPtr net; GET_CONNECTION(conn, -1); - for (i = 0, n = 0 ; i < MAX_NETWORKS && n < nnames ; i++) { - if (privconn->networks[i].active && - privconn->networks[i].running) { - names[n++] = strdup(privconn->networks[i].name); - } + net = privconn->networks; + memset(names, 0, sizeof(*names)*nnames); + while (net && n < nnames) { + if (virNetworkIsActive(net) && + !(names[n++] = strdup(net->def->name))) + goto no_memory; + net = net->next; } - return (n); + return n; + +no_memory: + testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + for (n = 0 ; n < nnames ; n++) + VIR_FREE(names[n]); + return (-1); } static int testNumDefinedNetworks(virConnectPtr conn) { - int numInactive = 0, i; + int numInactive = 0; + virNetworkObjPtr net; GET_CONNECTION(conn, -1); - for (i = 0 ; i < MAX_NETWORKS ; i++) { - if (!privconn->networks[i].active || - privconn->networks[i].running) - continue; - numInactive++; + net = privconn->networks; + while (net) { + if (!virNetworkIsActive(net)) + numInactive++; + net = net->next; } - return (numInactive); + return numInactive; } static int testListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) { - int n = 0, i; + int n = 0; + virNetworkObjPtr net; GET_CONNECTION(conn, -1); - for (i = 0, n = 0 ; i < MAX_NETWORKS && n < nnames ; i++) { - if (privconn->networks[i].active && - !privconn->networks[i].running) { - names[n++] = strdup(privconn->networks[i].name); - } + net = privconn->networks; + memset(names, 0, sizeof(*names)*nnames); + while (net && n < nnames) { + if (!virNetworkIsActive(net) && + !(names[n++] = strdup(net->def->name))) + goto no_memory; + net = net->next; } - return (n); + return n; + +no_memory: + testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + for (n = 0 ; n < nnames ; n++) + VIR_FREE(names[n]); + return (-1); } static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) { - int handle = -1; - virNetworkPtr net; + virNetworkDefPtr def; + virNetworkObjPtr net; GET_CONNECTION(conn, NULL); - if (xml == NULL) { - testError(conn, NULL, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); + if ((def = virNetworkDefParseString(conn, xml)) == NULL) + return NULL; + + if ((net = virNetworkAssignDef(conn, &privconn->networks, + def)) == NULL) { + virNetworkDefFree(def); + return NULL; } + net->active = 1; - if (privconn->numNetworks == MAX_NETWORKS) { - testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("too many networks")); - return (NULL); - } - - if ((handle = testLoadNetworkFromDoc(conn, xml)) < 0) - return (NULL); - privconn->networks[handle].config = 0; - - net = virGetNetwork(conn, privconn->networks[handle].name, privconn->networks[handle].uuid); - if (net == NULL) return NULL; - privconn->numNetworks++; - return (net); + return virGetNetwork(conn, def->name, def->uuid); } static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) { - int handle = -1; - virNetworkPtr net; + virNetworkDefPtr def; + virNetworkObjPtr net; GET_CONNECTION(conn, NULL); - if (xml == NULL) { - testError(conn, NULL, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); + if ((def = virNetworkDefParseString(conn, xml)) == NULL) + return NULL; + + if ((net = virNetworkAssignDef(conn, &privconn->networks, + def)) == NULL) { + virNetworkDefFree(def); + return NULL; } + net->persistent = 1; - if (privconn->numNetworks == MAX_NETWORKS) { - testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("too many networks")); - return (NULL); - } - - if ((handle = testLoadNetworkFromDoc(conn, xml)) < 0) - return (NULL); - - net = virGetNetwork(conn, privconn->networks[handle].name, privconn->networks[handle].uuid); - privconn->networks[handle].config = 1; - if (net == NULL) return NULL; - privconn->numNetworks++; - return (net); + return virGetNetwork(conn, def->name, def->uuid); } static int testNetworkUndefine(virNetworkPtr network) { GET_NETWORK(network, -1); - if (privnet->running) { + if (virNetworkIsActive(privnet)) { testError(network->conn, NULL, network, VIR_ERR_INTERNAL_ERROR, _("Network is still running")); return (-1); } - privnet->active = 0; + virNetworkRemoveInactive(&privconn->networks, + privnet); return (0); } @@ -1903,13 +1709,13 @@ static int testNetworkStart(virNetworkPtr network) { GET_NETWORK(network, -1); - if (privnet->running) { + if (virNetworkIsActive(privnet)) { testError(network->conn, NULL, network, VIR_ERR_INTERNAL_ERROR, _("Network is already running")); return (-1); } - privnet->running = 1; + privnet->active = 1; return (0); } @@ -1917,56 +1723,25 @@ static int testNetworkDestroy(virNetworkPtr network) { GET_NETWORK(network, -1); - if (privnet->config) { - privnet->running = 0; - } else { - privnet->active = 0; + privnet->active = 0; + if (!privnet->persistent) { + virNetworkRemoveInactive(&privconn->networks, + privnet); } return (0); } static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - unsigned char *uuid; - char uuidstr[VIR_UUID_STRING_BUFLEN]; GET_NETWORK(network, NULL); - virBufferAddLit(&buf, "<network>\n"); - virBufferVSprintf(&buf, " <name>%s</name>\n", network->name); - uuid = network->uuid; - virUUIDFormat(uuid, uuidstr); - virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr); - virBufferVSprintf(&buf, " <bridge name='%s'/>\n", privnet->bridge); - if (privnet->forward) { - if (privnet->forwardDev[0]) - virBufferVSprintf(&buf, " <forward dev='%s'/>\n", privnet->forwardDev); - else - virBufferAddLit(&buf, " <forward/>\n"); - } - - virBufferVSprintf(&buf, " <ip address='%s' netmask='%s'>\n", - privnet->ipAddress, privnet->ipNetmask); - virBufferAddLit(&buf, " <dhcp>\n"); - virBufferVSprintf(&buf, " <range start='%s' end='%s'/>\n", - privnet->dhcpStart, privnet->dhcpEnd); - virBufferAddLit(&buf, " </dhcp>\n"); - virBufferAddLit(&buf, " </ip>\n"); - - virBufferAddLit(&buf, "</network>\n"); - - if (virBufferError(&buf)) { - testError(network->conn, NULL, network, VIR_ERR_NO_MEMORY, __FUNCTION__); - return NULL; - } - - return virBufferContentAndReset(&buf); + return virNetworkDefFormat(network->conn, privnet->def); } static char *testNetworkGetBridgeName(virNetworkPtr network) { - char *bridge; + char *bridge = NULL; GET_NETWORK(network, NULL); - bridge = strdup(privnet->bridge); - if (!bridge) { + if (privnet->def->bridge && + !(bridge = strdup(privnet->def->bridge))) { testError(network->conn, NULL, network, VIR_ERR_NO_MEMORY, "network"); return NULL; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch ports the Test driver over to the domain XML apis. Basically the 'struct _testDom' is removed, and replaced by usage of the generic virDomainObjPtr and virDomainDefPtr objects. The XML parser and formatters are ripped out and replaced by calls to the generic APIs in domain_conf.h. Finally there is just alot of cleanup of all the individual domain driver implementations to adjust to the style of the new APIs used. This actually dramatically increases the functionality of the test driver - previously its XML parser didn't support any of the <device> section in the XML. This should make it much more useful for advanced apps like virt-manager Plenty of bug fixes since last time around. I've also implemented DV's suggestion of allowing the entire config to be loaded from a single XML file instead of having to reference external files for each domain. The 'docs/testnodeinline.xml' file illustrates this in practice. The old syntax is also supported of course. b/docs/testnodeinline.xml | 110 ++++ docs/testdomfc4.xml | 2 src/test.c | 1026 +++++++++++++++++----------------------------- src/test.h | 2 tests/read-non-seekable | 3 tests/virshtest.c | 4 6 files changed, 509 insertions(+), 638 deletions(-) Daniel diff -r 3c038ace4e38 docs/testdomfc4.xml --- a/docs/testdomfc4.xml Mon Jul 07 11:39:43 2008 +0100 +++ b/docs/testdomfc4.xml Mon Jul 07 11:39:51 2008 +0100 @@ -2,7 +2,7 @@ <name>fc4</name> <uuid>EF86180145B911CB88E3AFBFE5370493</uuid> <os> - <type>linux</type> + <type>xen</type> <kernel>/boot/vmlinuz-2.6.15-1.43_FC5guest</kernel> <initrd>/boot/initrd-2.6.15-1.43_FC5guest.img</initrd> <root>/dev/sda1</root> diff -r 3c038ace4e38 docs/testnodeinline.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/testnodeinline.xml Mon Jul 07 11:39:51 2008 +0100 @@ -0,0 +1,110 @@ +<?xml version="1.0"?> +<node> + <!-- This file gives an example config for the mock 'test' backend + driver to libvirt. This is intended to allow relible unit testing + of applications using libvirt. To use this with virsh, run something + like: + + virsh -connect test:////path/to/this/dir/testnode.xml nodeinfo + + --> + <domain type="test"> + <name>fv0</name> + <uuid>4dea22b31d52d8f32516782e98ab3fa0</uuid> + <os> + <type>hvm</type> + <loader>/usr/lib/xen/boot/hvmloader</loader> + <boot dev="hd"/> + </os> + <memory>524288</memory> + <maxMemory>1524288</maxMemory> + <vcpu>4</vcpu> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <features> + <pae/> + <acpi/> + <apic/> + </features> + <devices> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <interface type="bridge"> + <source bridge="xenbr0"/> + <mac address="00:16:3e:5d:c7:9e"/> + <script path="vif-bridge"/> + </interface> + <disk type="file"> + <source file="/root/fv0"/> + <target dev="hda"/> + </disk> + <disk type="file" device="cdrom"> + <source file="/root/fc5-x86_64-boot.iso"/> + <target dev="hdc"/> + <readonly/> + </disk> + <disk type="file" device="floppy"> + <source file="/root/fd.img"/> + <target dev="fda"/> + </disk> + <graphics type="vnc" port="5904"/> + </devices> + </domain> + <domain type="test"> + <name>fc4</name> + <uuid>EF86180145B911CB88E3AFBFE5370493</uuid> + <os> + <type>xen</type> + <kernel>/boot/vmlinuz-2.6.15-1.43_FC5guest</kernel> + <initrd>/boot/initrd-2.6.15-1.43_FC5guest.img</initrd> + <root>/dev/sda1</root> + <cmdline> ro selinux=0 3</cmdline> + </os> + <memory>261072</memory> + <currentMemory>131072</currentMemory> + <vcpu>1</vcpu> + <devices> + <disk type="file"> + <source file="/u/fc4.img"/> + <target dev="sda1"/> + </disk> + <interface type="bridge"> + <source bridge="xenbr0"/> + <mac address="aa:00:00:00:00:11"/> + <script path="/etc/xen/scripts/vif-bridge"/> + </interface> + <console tty="/dev/pts/5"/> + </devices> + </domain> + <network> + <name>private</name> + <uuid>004b22212d78c30f5aa5f03c87d21e69</uuid> + <bridge name="brpriv"/> + <ip address="192.168.124.1" netmask="255.255.255.0"> + <dhcp> + <range start="192.168.124.128" end="192.168.124.253"/> + </dhcp> + </ip> + </network> + <network> + <name>default</name> + <uuid>004b96e12d78c30f5aa5f03c87d21e69</uuid> + <bridge name="brdefault"/> + <forward dev="eth0"/> + <ip address="192.168.122.1" netmask="255.255.255.0"> + <dhcp> + <range start="192.168.122.128" end="192.168.122.253"/> + </dhcp> + </ip> + </network> + <cpu> + <mhz>6000</mhz> + <model>i986</model> + <active>50</active> + <nodes>4</nodes> + <sockets>4</sockets> + <cores>4</cores> + <threads>2</threads> + </cpu> + <memory>8192000</memory> +</node> diff -r 3c038ace4e38 src/test.c --- a/src/test.c Mon Jul 07 11:39:43 2008 +0100 +++ b/src/test.c Mon Jul 07 11:39:51 2008 +0100 @@ -28,66 +28,22 @@ #include <stdio.h> #include <string.h> #include <sys/time.h> -#include <libxml/parser.h> -#include <libxml/tree.h> -#include <libxml/xpath.h> -#include <libxml/uri.h> #include <fcntl.h> #include <unistd.h> #include <sys/stat.h> #include "socketcompat.h" -#include "internal.h" #include "test.h" -#include "xml.h" #include "buf.h" #include "util.h" #include "uuid.h" #include "capabilities.h" #include "memory.h" #include "network_conf.h" +#include "domain_conf.h" +#include "xml.h" -/* Flags that determine the action to take on a shutdown or crash of a domain - */ -typedef enum { - VIR_DOMAIN_DESTROY = 1, /* destroy the domain */ - VIR_DOMAIN_RESTART = 2, /* restart the domain */ - VIR_DOMAIN_PRESERVE= 3, /* keep as is, need manual destroy, for debug */ - VIR_DOMAIN_RENAME_RESTART= 4/* restart under an new unique name */ -} virDomainRestart; - -struct _testDev { - char name[20]; - int mode; -}; -typedef struct _testDev testDev; -typedef struct _testDev *testDevPtr; - -#define MAX_DEVICES 10 - -struct _testDom { - int active; - int config; - int id; - char name[20]; - unsigned char uuid[VIR_UUID_BUFLEN]; - virDomainInfo info; - unsigned int maxVCPUs; - virDomainRestart onRestart; /* What to do at end of current shutdown procedure */ - virDomainRestart onReboot; - virDomainRestart onPoweroff; - virDomainRestart onCrash; - int numDevices; - testDev devices[MAX_DEVICES]; - int autostart; - unsigned int weight; -}; -typedef struct _testDom testDom; -typedef struct _testDom *testDomPtr; - -#define MAX_DOMAINS 20 -#define MAX_NETWORKS 20 #define MAX_CPUS 128 struct _testCell { @@ -103,9 +59,9 @@ struct _testConn { char path[PATH_MAX]; int nextDomID; + virCapsPtr caps; virNodeInfo nodeInfo; - int numDomains; - testDom domains[MAX_DOMAINS]; + virDomainObjPtr domains; virNetworkObjPtr networks; int numCells; testCell cells[MAX_CELLS]; @@ -115,6 +71,7 @@ #define TEST_MODEL "i686" #define TEST_MODEL_WORDSIZE 32 +#define TEST_EMULATOR "/usr/bin/test-hv" static const virNodeInfo defaultNodeInfo = { TEST_MODEL, @@ -128,17 +85,18 @@ }; #define GET_DOMAIN(dom, ret) \ - int domidx; \ testConnPtr privconn; \ - testDomPtr privdom; \ + virDomainObjPtr privdom; \ \ privconn = (testConnPtr)dom->conn->privateData; \ - if ((domidx = getDomainIndex(dom)) < 0) { \ - testError((dom)->conn, (dom), NULL, VIR_ERR_INVALID_ARG, \ - __FUNCTION__); \ - return (ret); \ - } \ - privdom = &privconn->domains[domidx]; + do { \ + if ((privdom = virDomainFindByName(privconn->domains, \ + (dom)->name)) == NULL) { \ + testError((dom)->conn, (dom), NULL, VIR_ERR_INVALID_ARG, \ + __FUNCTION__); \ + return (ret); \ + } \ + } while (0) #define GET_NETWORK(net, ret) \ testConnPtr privconn; \ @@ -154,7 +112,7 @@ } \ } while (0) -#define GET_CONNECTION(conn, ret) \ +#define GET_CONNECTION(conn) \ testConnPtr privconn; \ \ privconn = (testConnPtr)conn->privateData; @@ -177,231 +135,72 @@ errmsg, info, NULL, 0, 0, errmsg, info, 0); } -static int testRestartStringToFlag(const char *str) { - if (STREQ(str, "restart")) { - return VIR_DOMAIN_RESTART; - } else if (STREQ(str, "destroy")) { - return VIR_DOMAIN_DESTROY; - } else if (STREQ(str, "preserve")) { - return VIR_DOMAIN_PRESERVE; - } else if (STREQ(str, "rename-restart")) { - return VIR_DOMAIN_RENAME_RESTART; - } else { - return (0); +static virCapsPtr +testBuildCapabilities(virConnectPtr conn) { + virCapsPtr caps; + virCapsGuestPtr guest; + const char *const guest_types[] = { "hvm", "xen" }; + int i; + GET_CONNECTION(conn); + + if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL) + goto no_memory; + + if (virCapabilitiesAddHostFeature(caps, "pae") < 0) + goto no_memory; + if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0) + goto no_memory; + + for (i = 0; i < privconn->numCells; i++) { + if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus, + privconn->cells[i].cpus) < 0) + goto no_memory; } + + for (i = 0; i < ARRAY_CARDINALITY(guest_types) ; i++) { + if ((guest = virCapabilitiesAddGuest(caps, + guest_types[i], + TEST_MODEL, + TEST_MODEL_WORDSIZE, + TEST_EMULATOR, + NULL, + 0, + NULL)) == NULL) + goto no_memory; + + if (virCapabilitiesAddGuestDomain(guest, + "test", + NULL, + NULL, + 0, + NULL) == NULL) + goto no_memory; + + if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL) + goto no_memory; + if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL) + goto no_memory; + } + + return caps; + +no_memory: + testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + virCapabilitiesFree(caps); + return NULL; } -static const char *testRestartFlagToString(int flag) { - switch (flag) { - case VIR_DOMAIN_RESTART: - return "restart"; - case VIR_DOMAIN_DESTROY: - return "destroy"; - case VIR_DOMAIN_PRESERVE: - return "preserve"; - case VIR_DOMAIN_RENAME_RESTART: - return "rename-restart"; - } - return (NULL); -} - -static int testLoadDomain(virConnectPtr conn, - int domid, - xmlDocPtr xml) { - xmlNodePtr root = NULL; - xmlXPathContextPtr ctxt = NULL; - char *name = NULL; - unsigned char uuid[VIR_UUID_BUFLEN]; - struct timeval tv; - unsigned long memory = 0; - unsigned long maxMem = 0; - int nrVirtCpu; - char *str; - int handle = -1, i, ret; - long l; - virDomainRestart onReboot = VIR_DOMAIN_RESTART; - virDomainRestart onPoweroff = VIR_DOMAIN_DESTROY; - virDomainRestart onCrash = VIR_DOMAIN_RENAME_RESTART; - GET_CONNECTION(conn, -1); - - if (gettimeofday(&tv, NULL) < 0) { - testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day")); - return (-1); - } - - root = xmlDocGetRootElement(xml); - if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "domain"))) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain")); - goto error; - } - - ctxt = xmlXPathNewContext(xml); - if (ctxt == NULL) { - testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("creating xpath context")); - goto error; - } - - name = virXPathString("string(/domain/name[1])", ctxt); - if (name == NULL) { - testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("domain name")); - goto error; - } - - str = virXPathString("string(/domain/uuid[1])", ctxt); - if (str == NULL) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain uuid")); - goto error; - } - if (virUUIDParse(str, uuid) < 0) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain uuid")); - goto error; - } - VIR_FREE(str); - - - ret = virXPathLong("string(/domain/memory[1])", ctxt, &l); - if (ret != 0) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain memory")); - goto error; - } - maxMem = l; - - ret = virXPathLong("string(/domain/currentMemory[1])", ctxt, &l); - if (ret == -1) { - memory = maxMem; - } else if (ret == -2) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain current memory")); - goto error; - } else { - memory = l; - } - - ret = virXPathLong("string(/domain/vcpu[1])", ctxt, &l); - if (ret == -1) { - nrVirtCpu = 1; - } else if (ret == -2) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain vcpus")); - goto error; - } else { - nrVirtCpu = l; - } - - str = virXPathString("string(/domain/on_reboot[1])", ctxt); - if (str != NULL) { - if (!(onReboot = testRestartStringToFlag(str))) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain reboot behaviour")); - VIR_FREE(str); - goto error; - } - VIR_FREE(str); - } - - str = virXPathString("string(/domain/on_poweroff[1])", ctxt); - if (str != NULL) { - if (!(onPoweroff = testRestartStringToFlag(str))) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain poweroff behaviour")); - VIR_FREE(str); - goto error; - } - VIR_FREE(str); - } - - str = virXPathString("string(/domain/on_crash[1])", ctxt); - if (str != NULL) { - if (!(onCrash = testRestartStringToFlag(str))) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain crash behaviour")); - VIR_FREE(str); - goto error; - } - VIR_FREE(str); - } - - for (i = 0 ; i < MAX_DOMAINS ; i++) { - if (!privconn->domains[i].active) { - handle = i; - break; - } - } - if (handle < 0) - goto error; - - privconn->domains[handle].active = 1; - privconn->domains[handle].id = domid; - strncpy(privconn->domains[handle].name, name, sizeof(privconn->domains[handle].name)-1); - privconn->domains[handle].name[sizeof(privconn->domains[handle].name)-1] = '\0'; - VIR_FREE(name); - name = NULL; - - if (memory > maxMem) - memory = maxMem; - - memmove(privconn->domains[handle].uuid, uuid, VIR_UUID_BUFLEN); - privconn->domains[handle].info.maxMem = maxMem; - privconn->domains[handle].info.memory = memory; - privconn->domains[handle].info.state = domid < 0 ? VIR_DOMAIN_SHUTOFF : VIR_DOMAIN_RUNNING; - privconn->domains[handle].info.nrVirtCpu = nrVirtCpu; - privconn->domains[handle].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll)); - privconn->domains[handle].maxVCPUs = nrVirtCpu; - - privconn->domains[handle].onReboot = onReboot; - privconn->domains[handle].onPoweroff = onPoweroff; - privconn->domains[handle].onCrash = onCrash; - - xmlXPathFreeContext(ctxt); - return (handle); - - error: - xmlXPathFreeContext(ctxt); - VIR_FREE(name); - return (-1); -} - -static int testLoadDomainFromDoc(virConnectPtr conn, - int domid, - const char *doc) { - int ret; - xmlDocPtr xml; - if (!(xml = xmlReadDoc(BAD_CAST doc, "domain.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain")); - return (-1); - } - - ret = testLoadDomain(conn, domid, xml); - - xmlFreeDoc(xml); - - return (ret); -} - - -static int testLoadDomainFromFile(virConnectPtr conn, - int domid, - const char *filename) { - int ret, fd; - xmlDocPtr xml; - - if ((fd = open(filename, O_RDONLY)) < 0) { - testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("load domain definition file")); - return (-1); - } - - if (!(xml = xmlReadFd(fd, filename, NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain")); - return (-1); - } - - ret = testLoadDomain(conn, domid, xml); - - xmlFreeDoc(xml); - close(fd); - - return (ret); -} +static const char *defaultDomainXML = +"<domain type='test'>" +" <name>test</name>" +" <memory>8388608</memory>" +" <currentMemory>2097152</currentMemory>" +" <vcpu>2</vcpu>" +" <os>" +" <type>hvm</type>" +" </os>" +"</domain>"; static const char *defaultNetworkXML = @@ -421,50 +220,23 @@ int u; struct timeval tv; testConnPtr privconn; - virNetworkDefPtr netdef; - virNetworkObjPtr netobj; + virDomainDefPtr domdef = NULL; + virDomainObjPtr domobj = NULL; + virNetworkDefPtr netdef = NULL; + virNetworkObjPtr netobj = NULL; if (VIR_ALLOC(privconn) < 0) { testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "testConn"); return VIR_DRV_OPEN_ERROR; } + conn->privateData = privconn; if (gettimeofday(&tv, NULL) < 0) { testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("getting time of day")); - return VIR_DRV_OPEN_ERROR; + goto error; } memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo)); - - strcpy(privconn->path, "/default"); - privconn->nextDomID = 1; - privconn->numDomains = 1; - privconn->domains[0].active = 1; - privconn->domains[0].config = 1; - privconn->domains[0].id = privconn->nextDomID++; - privconn->domains[0].onReboot = VIR_DOMAIN_RESTART; - privconn->domains[0].onCrash = VIR_DOMAIN_RESTART; - privconn->domains[0].onPoweroff = VIR_DOMAIN_DESTROY; - strcpy(privconn->domains[0].name, "test"); - for (u = 0 ; u < VIR_UUID_BUFLEN ; u++) { - privconn->domains[0].uuid[u] = (u * 75)%255; - } - privconn->domains[0].info.maxMem = 8192 * 1024; - privconn->domains[0].info.memory = 2048 * 1024; - privconn->domains[0].info.state = VIR_DOMAIN_RUNNING; - privconn->domains[0].info.nrVirtCpu = 2; - privconn->domains[0].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll)); - - - if (!(netdef = virNetworkDefParseString(conn, defaultNetworkXML))) { - return VIR_DRV_OPEN_ERROR; - } - if (!(netobj = virNetworkAssignDef(conn, &privconn->networks, netdef))) { - virNetworkDefFree(netdef); - return VIR_DRV_OPEN_ERROR; - } - netobj->active = 1; - netobj->persistent = 1; // Numa setup privconn->numCells = 2; @@ -476,8 +248,39 @@ privconn->cells[u % 2].cpus[(u / 2)] = u; } - conn->privateData = privconn; - return (VIR_DRV_OPEN_SUCCESS); + if (!(privconn->caps = testBuildCapabilities(conn))) + goto error; + + privconn->nextDomID = 1; + + if (!(domdef = virDomainDefParseString(conn, privconn->caps, defaultDomainXML))) + goto error; + if (!(domobj = virDomainAssignDef(conn, &privconn->domains, domdef))) { + virDomainDefFree(domdef); + goto error; + } + domobj->def->id = 1; + domobj->state = VIR_DOMAIN_RUNNING; + domobj->persistent = 1; + + if (!(netdef = virNetworkDefParseString(conn, defaultNetworkXML))) + goto error; + if (!(netobj = virNetworkAssignDef(conn, &privconn->networks, netdef))) { + virNetworkDefFree(netdef); + goto error; + } + + netobj->active = 1; + netobj->persistent = 1; + + return VIR_DRV_OPEN_SUCCESS; + +error: + virDomainObjFree(privconn->domains); + virNetworkObjFree(privconn->networks); + virCapabilitiesFree(privconn->caps); + VIR_FREE(privconn); + return VIR_DRV_OPEN_ERROR; } @@ -514,11 +317,17 @@ xmlNodePtr *domains, *networks = NULL; xmlXPathContextPtr ctxt = NULL; virNodeInfoPtr nodeInfo; + virNetworkObjPtr net; + virDomainObjPtr dom; testConnPtr privconn; if (VIR_ALLOC(privconn) < 0) { testError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY, "testConn"); return VIR_DRV_OPEN_ERROR; } + conn->privateData = privconn; + + if (!(privconn->caps = testBuildCapabilities(conn))) + goto error; if ((fd = open(file, O_RDONLY)) < 0) { testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("loading host definition file")); @@ -546,10 +355,7 @@ goto error; } - - conn->privateData = privconn; privconn->nextDomID = 1; - privconn->numDomains = 0; privconn->numCells = 0; strncpy(privconn->path, file, PATH_MAX-1); privconn->path[PATH_MAX-1] = '\0'; @@ -628,27 +434,37 @@ } for (i = 0 ; i < ret ; i++) { - xmlChar *domFile = xmlGetProp(domains[i], BAD_CAST "file"); - char *absFile = testBuildFilename(file, (const char *)domFile); - int domid = privconn->nextDomID++, handle; - VIR_FREE(domFile); - if (!absFile) { - testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("resolving domain filename")); + virDomainDefPtr def; + char *relFile = virXMLPropString(domains[i], "file"); + if (relFile != NULL) { + char *absFile = testBuildFilename(file, relFile); + VIR_FREE(relFile); + if (!absFile) { + testError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("resolving domain filename")); + goto error; + } + def = virDomainDefParseFile(conn, privconn->caps, absFile); + VIR_FREE(absFile); + if (!def) + goto error; + } else { + if ((def = virDomainDefParseNode(conn, privconn->caps, xml, domains[i])) == NULL) + goto error; + } + + if (!(dom = virDomainAssignDef(conn, &privconn->domains, def))) { + virDomainDefFree(def); goto error; } - if ((handle = testLoadDomainFromFile(conn, domid, absFile)) < 0) { - VIR_FREE(absFile); - goto error; - } - privconn->domains[handle].config = 1; - VIR_FREE(absFile); - privconn->numDomains++; + + dom->state = VIR_DOMAIN_RUNNING; + dom->def->id = privconn->nextDomID++; + dom->persistent = 1; } if (domains != NULL) { VIR_FREE(domains); domains = NULL; } - ret = virXPathNodeSet("/node/network", ctxt, &networks); if (ret < 0) { @@ -657,7 +473,6 @@ } for (i = 0 ; i < ret ; i++) { virNetworkDefPtr def; - virNetworkObjPtr net; char *relFile = virXMLPropString(networks[i], "file"); if (relFile != NULL) { char *absFile = testBuildFilename(file, relFile); @@ -695,32 +510,28 @@ error: xmlXPathFreeContext(ctxt); + xmlFreeDoc(xml); VIR_FREE(domains); VIR_FREE(networks); - if (xml) - xmlFreeDoc(xml); if (fd != -1) close(fd); + dom = privconn->domains; + while (dom) { + virDomainObjPtr tmp = dom->next; + virDomainObjFree(dom); + dom = tmp; + } + net = privconn->networks; + while (net) { + virNetworkObjPtr tmp = net->next; + virNetworkObjFree(net); + net = tmp; + } VIR_FREE(privconn); conn->privateData = NULL; return VIR_DRV_OPEN_ERROR; } -static int getDomainIndex(virDomainPtr domain) { - int i; - GET_CONNECTION(domain->conn, -1); - - for (i = 0 ; i < MAX_DOMAINS ; i++) { - if (domain->id >= 0) { - if (domain->id == privconn->domains[i].id) - return (i); - } else { - if (STREQ(domain->name, privconn->domains[i].name)) - return (i); - } - } - return (-1); -} static int testOpen(virConnectPtr conn, xmlURIPtr uri, @@ -762,7 +573,22 @@ static int testClose(virConnectPtr conn) { - GET_CONNECTION(conn, -1); + virDomainObjPtr dom; + virNetworkObjPtr net; + GET_CONNECTION(conn); + virCapabilitiesFree(privconn->caps); + dom = privconn->domains; + while (dom) { + virDomainObjPtr tmp = dom->next; + virDomainObjFree(dom); + dom = tmp; + } + net = privconn->networks; + while (net) { + virNetworkObjPtr tmp = net->next; + virNetworkObjFree(net); + net = tmp; + } VIR_FREE (privconn); conn->privateData = conn; return 0; @@ -796,7 +622,7 @@ static char * testGetURI (virConnectPtr conn) { char *uri; - GET_CONNECTION(conn, NULL); + GET_CONNECTION(conn); if (asprintf (&uri, "test://%s", privconn->path) == -1) { testError (conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno)); @@ -814,224 +640,149 @@ static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) { - GET_CONNECTION(conn, -1); + GET_CONNECTION(conn); memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo)); return (0); } static char *testGetCapabilities (virConnectPtr conn) { - virCapsPtr caps; - virCapsGuestPtr guest; char *xml; - const char *guest_types[] = { "hvm", "xen" }; - int i; + GET_CONNECTION(conn); - GET_CONNECTION(conn, -1); - - if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL) - goto no_memory; - - if (virCapabilitiesAddHostFeature(caps, "pae") < 0) - goto no_memory; - if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0) - goto no_memory; - - for (i = 0; i < privconn->numCells; ++i) { - if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus, - privconn->cells[i].cpus) < 0) - goto no_memory; + if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL) { + testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + return NULL; } - for (i = 0; i < (sizeof(guest_types)/sizeof(guest_types[0])); ++i) { - - if ((guest = virCapabilitiesAddGuest(caps, - guest_types[i], - TEST_MODEL, - TEST_MODEL_WORDSIZE, - NULL, - NULL, - 0, - NULL)) == NULL) - goto no_memory; - - if (virCapabilitiesAddGuestDomain(guest, - "test", - NULL, - NULL, - 0, - NULL) == NULL) - goto no_memory; - - if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL) - goto no_memory; - if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL) - goto no_memory; - } - - if ((xml = virCapabilitiesFormatXML(caps)) == NULL) - goto no_memory; - - virCapabilitiesFree(caps); - return xml; - - no_memory: - virCapabilitiesFree(caps); - testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__); - return NULL; } static int testNumOfDomains(virConnectPtr conn) { - int numActive = 0, i; - GET_CONNECTION(conn, -1); + int numActive = 0; + virDomainObjPtr dom; + GET_CONNECTION(conn); - for (i = 0 ; i < MAX_DOMAINS ; i++) { - if (!privconn->domains[i].active || - privconn->domains[i].info.state == VIR_DOMAIN_SHUTOFF) - continue; - numActive++; + dom = privconn->domains; + while (dom) { + if (virDomainIsActive(dom)) + numActive++; + dom = dom->next; } - return (numActive); + return numActive; } static virDomainPtr -testDomainCreateLinux(virConnectPtr conn, const char *xmlDesc, +testDomainCreateLinux(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { - int domid, handle = -1; - virDomainPtr dom; - GET_CONNECTION(conn, NULL); + virDomainPtr ret; + virDomainDefPtr def; + virDomainObjPtr dom; + GET_CONNECTION(conn); - if (xmlDesc == NULL) { - testError(conn, NULL, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); + if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL) + return NULL; + + if ((dom = virDomainAssignDef(conn, &privconn->domains, + def)) == NULL) { + virDomainDefFree(def); + return NULL; } + dom->state = VIR_DOMAIN_RUNNING; + dom->def->id = privconn->nextDomID++; - if (privconn->numDomains == MAX_DOMAINS) { - testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("too many domains")); - return (NULL); - } - - domid = privconn->nextDomID++; - if ((handle = testLoadDomainFromDoc(conn, domid, xmlDesc)) < 0) - return (NULL); - privconn->domains[handle].config = 0; - - dom = virGetDomain(conn, privconn->domains[handle].name, privconn->domains[handle].uuid); - if (dom == NULL) return NULL; - privconn->numDomains++; - return (dom); + ret = virGetDomain(conn, def->name, def->uuid); + if (!ret) + return NULL; + ret->id = def->id; + return ret; } static virDomainPtr testLookupDomainByID(virConnectPtr conn, int id) { - virDomainPtr dom; - int i, idx = -1; - GET_CONNECTION(conn, NULL); + virDomainObjPtr dom = NULL; + virDomainPtr ret; + GET_CONNECTION(conn); - for (i = 0 ; i < MAX_DOMAINS ; i++) { - if (privconn->domains[i].active && - privconn->domains[i].id == id) { - idx = i; - break; - } + if ((dom = virDomainFindByID(privconn->domains, id)) == NULL) { + testError (conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); + return NULL; } - if (idx < 0) { - testError (conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); - return(NULL); - } - - dom = virGetDomain(conn, privconn->domains[idx].name, privconn->domains[idx].uuid); - if (dom == NULL) return NULL; - dom->id = id; - return (dom); + ret = virGetDomain(conn, dom->def->name, dom->def->uuid); + if (!ret) + return NULL; + ret->id = dom->def->id; + return ret; } static virDomainPtr testLookupDomainByUUID(virConnectPtr conn, const unsigned char *uuid) { - virDomainPtr dom; - int i, idx = -1; - GET_CONNECTION(conn, NULL); + virDomainPtr ret; + virDomainObjPtr dom = NULL; + GET_CONNECTION(conn); - for (i = 0 ; i < MAX_DOMAINS ; i++) { - if (privconn->domains[i].active && - memcmp(uuid, privconn->domains[i].uuid, VIR_UUID_BUFLEN) == 0) { - idx = i; - break; - } - } - - if (idx < 0) { + if ((dom = virDomainFindByUUID(privconn->domains, uuid)) == NULL) { testError (conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); return NULL; } - dom = virGetDomain(conn, privconn->domains[idx].name, privconn->domains[idx].uuid); - if (dom == NULL) return NULL; - dom->id = privconn->domains[idx].id; - - return dom; + ret = virGetDomain(conn, dom->def->name, dom->def->uuid); + if (!ret) + return NULL; + ret->id = dom->def->id; + return ret; } static virDomainPtr testLookupDomainByName(virConnectPtr conn, const char *name) { - virDomainPtr dom; - int i, idx = -1; - GET_CONNECTION(conn, NULL); + virDomainPtr ret; + virDomainObjPtr dom = NULL; + GET_CONNECTION(conn); - for (i = 0 ; i < MAX_DOMAINS ; i++) { - if (privconn->domains[i].active && - STREQ(name, privconn->domains[i].name)) { - idx = i; - break; - } - } - - if (idx < 0) { + if ((dom = virDomainFindByName(privconn->domains, name)) == NULL) { testError (conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); return NULL; } - dom = virGetDomain(conn, privconn->domains[idx].name, privconn->domains[idx].uuid); - if (dom == NULL) return NULL; - dom->id = privconn->domains[idx].id; - - return dom; + ret = virGetDomain(conn, dom->def->name, dom->def->uuid); + if (!ret) + return NULL; + ret->id = dom->def->id; + return ret; } static int testListDomains (virConnectPtr conn, int *ids, int maxids) { - int n, i; - GET_CONNECTION(conn, -1); + int n = 0; + virDomainObjPtr dom; + GET_CONNECTION(conn); - for (i = 0, n = 0 ; i < MAX_DOMAINS && n < maxids ; i++) { - if (privconn->domains[i].active && - privconn->domains[i].info.state != VIR_DOMAIN_SHUTOFF) { - ids[n++] = privconn->domains[i].id; - } + dom = privconn->domains; + while (dom && n < maxids) { + if (virDomainIsActive(dom)) + ids[n++] = dom->def->id; + dom = dom->next; } - return (n); + return n; } static int testDestroyDomain (virDomainPtr domain) { GET_DOMAIN(domain, -1); - if (privdom->config) { - privdom->info.state = VIR_DOMAIN_SHUTOFF; - privdom->id = -1; - domain->id = -1; - } else { - privdom->active = 0; + privdom->state = VIR_DOMAIN_SHUTOFF; + if (!privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); } return (0); } @@ -1040,12 +791,13 @@ { GET_DOMAIN(domain, -1); - if (privdom->info.state != VIR_DOMAIN_PAUSED) { - testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, "domain not paused"); + if (privdom->state != VIR_DOMAIN_PAUSED) { + testError(domain->conn, domain, NULL, + VIR_ERR_INTERNAL_ERROR, _("domain not paused")); return -1; } - privdom->info.state = VIR_DOMAIN_RUNNING; + privdom->state = VIR_DOMAIN_RUNNING; return (0); } @@ -1053,13 +805,14 @@ { GET_DOMAIN(domain, -1); - if (privdom->info.state == VIR_DOMAIN_SHUTOFF || - privdom->info.state == VIR_DOMAIN_PAUSED) { - testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, "domain not running"); + if (privdom->state == VIR_DOMAIN_SHUTOFF || + privdom->state == VIR_DOMAIN_PAUSED) { + testError(domain->conn, domain, NULL, + VIR_ERR_INTERNAL_ERROR, _("domain not running")); return -1; } - privdom->info.state = VIR_DOMAIN_PAUSED; + privdom->state = VIR_DOMAIN_PAUSED; return (0); } @@ -1067,52 +820,50 @@ { GET_DOMAIN(domain, -1); - if (privdom->info.state == VIR_DOMAIN_SHUTOFF) { + if (privdom->state == VIR_DOMAIN_SHUTOFF) { testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, "domain not running"); return -1; } - privdom->info.state = VIR_DOMAIN_SHUTOFF; + privdom->state = VIR_DOMAIN_SHUTOFF; domain->id = -1; - privdom->id = -1; + privdom->def->id = -1; return (0); } /* Similar behaviour as shutdown */ -static int testRebootDomain (virDomainPtr domain, virDomainRestart action) +static int testRebootDomain (virDomainPtr domain, + unsigned int action ATTRIBUTE_UNUSED) { GET_DOMAIN(domain, -1); - if (!action) - action = VIR_DOMAIN_RESTART; - - privdom->info.state = VIR_DOMAIN_SHUTDOWN; - switch (action) { - case VIR_DOMAIN_DESTROY: - privdom->info.state = VIR_DOMAIN_SHUTOFF; + privdom->state = VIR_DOMAIN_SHUTDOWN; + switch (privdom->def->onReboot) { + case VIR_DOMAIN_LIFECYCLE_DESTROY: + privdom->state = VIR_DOMAIN_SHUTOFF; domain->id = -1; - privdom->id = -1; + privdom->def->id = -1; break; - case VIR_DOMAIN_RESTART: - privdom->info.state = VIR_DOMAIN_RUNNING; + case VIR_DOMAIN_LIFECYCLE_RESTART: + privdom->state = VIR_DOMAIN_RUNNING; break; - case VIR_DOMAIN_PRESERVE: - privdom->info.state = VIR_DOMAIN_SHUTOFF; + case VIR_DOMAIN_LIFECYCLE_PRESERVE: + privdom->state = VIR_DOMAIN_SHUTOFF; domain->id = -1; - privdom->id = -1; + privdom->def->id = -1; break; - case VIR_DOMAIN_RENAME_RESTART: - privdom->info.state = VIR_DOMAIN_RUNNING; + case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME: + privdom->state = VIR_DOMAIN_RUNNING; break; default: - privdom->info.state = VIR_DOMAIN_SHUTOFF; + privdom->state = VIR_DOMAIN_SHUTOFF; domain->id = -1; - privdom->id = -1; + privdom->def->id = -1; break; } @@ -1130,13 +881,11 @@ return (-1); } - if (privdom->info.state == VIR_DOMAIN_SHUTOFF) { - privdom->info.cpuTime = 0; - privdom->info.memory = 0; - } else { - privdom->info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll)); - } - memcpy(info, &privdom->info, sizeof(virDomainInfo)); + info->state = privdom->state; + info->memory = privdom->def->memory; + info->maxMem = privdom->def->maxmem; + info->nrVirtCpu = privdom->def->vcpus; + info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll)); return (0); } @@ -1190,12 +939,10 @@ close(fd); return (-1); } - if (privdom->config) { - privdom->info.state = VIR_DOMAIN_SHUTOFF; - privdom->id = -1; - domain->id = -1; - } else { - privdom->active = 0; + privdom->state = VIR_DOMAIN_SHUTOFF; + if (!privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); } return 0; } @@ -1205,8 +952,10 @@ { char *xml; char magic[15]; - int fd, len, ret, domid; - GET_CONNECTION(conn, -1); + int fd, len; + virDomainDefPtr def; + virDomainObjPtr dom; + GET_CONNECTION(conn); if ((fd = open(path, O_RDONLY)) < 0) { testError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, @@ -1250,10 +999,20 @@ } xml[len] = '\0'; close(fd); - domid = privconn->nextDomID++; - ret = testLoadDomainFromDoc(conn, domid, xml); + + def = virDomainDefParseString(conn, privconn->caps, xml); VIR_FREE(xml); - return ret < 0 ? -1 : 0; + if (!def) + return -1; + + if ((dom = virDomainAssignDef(conn, &privconn->domains, + def)) == NULL) { + virDomainDefFree(def); + return -1; + } + dom->state = VIR_DOMAIN_RUNNING; + dom->def->id = privconn->nextDomID++; + return dom->def->id; } static int testDomainCoreDump(virDomainPtr domain, @@ -1280,24 +1039,25 @@ close(fd); return (-1); } - if (privdom->config) { - privdom->info.state = VIR_DOMAIN_SHUTOFF; - privdom->id = -1; - domain->id = -1; - } else { - privdom->active = 0; + privdom->state = VIR_DOMAIN_SHUTOFF; + if (!privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); } return 0; } -static char *testGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) { - return strdup("linux"); +static char *testGetOSType(virDomainPtr dom) { + char *ret = strdup("linux"); + if (!ret) + testError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL); + return ret; } static unsigned long testGetMaxMemory(virDomainPtr domain) { GET_DOMAIN(domain, -1); - return privdom->info.maxMem; + return privdom->def->maxmem; } static int testSetMaxMemory(virDomainPtr domain, @@ -1306,7 +1066,7 @@ GET_DOMAIN(domain, -1); /* XXX validate not over host memory wrt to other domains */ - privdom->info.maxMem = memory; + privdom->def->maxmem = memory; return (0); } @@ -1315,12 +1075,13 @@ { GET_DOMAIN(domain, -1); - if (memory > privdom->info.maxMem) { - testError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + if (memory > privdom->def->maxmem) { + testError(domain->conn, domain, NULL, + VIR_ERR_INVALID_ARG, __FUNCTION__); return (-1); } - privdom->info.memory = memory; + privdom->def->memory = memory; return (0); } @@ -1334,88 +1095,84 @@ return (-1); } - privdom->info.nrVirtCpu = nrCpus; + privdom->def->vcpus = nrCpus; return (0); } -static char *testDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED) +static char *testDomainDumpXML(virDomainPtr domain, int flags) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - unsigned char *uuid; - char uuidstr[VIR_UUID_STRING_BUFLEN]; + virDomainDefPtr def; GET_DOMAIN(domain, NULL); - virBufferVSprintf(&buf, "<domain type='test' id='%d'>\n", domain->id); - virBufferVSprintf(&buf, " <name>%s</name>\n", domain->name); - uuid = domain->uuid; - virUUIDFormat(uuid, uuidstr); - virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr); - virBufferVSprintf(&buf, " <memory>%lu</memory>\n", privdom->info.maxMem); - virBufferVSprintf(&buf, " <vcpu>%d</vcpu>\n", privdom->info.nrVirtCpu); - virBufferVSprintf(&buf, " <on_reboot>%s</on_reboot>\n", testRestartFlagToString(privdom->onReboot)); - virBufferVSprintf(&buf, " <on_poweroff>%s</on_poweroff>\n", testRestartFlagToString(privdom->onPoweroff)); - virBufferVSprintf(&buf, " <on_crash>%s</on_crash>\n", testRestartFlagToString(privdom->onCrash)); + def = (flags & VIR_DOMAIN_XML_INACTIVE) && + privdom->newDef ? privdom->newDef : privdom->def; - virBufferAddLit(&buf, "</domain>\n"); - - if (virBufferError(&buf)) { - testError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__); - return NULL; - } - - return virBufferContentAndReset(&buf); + return virDomainDefFormat(domain->conn, + def, + flags); } static int testNumOfDefinedDomains(virConnectPtr conn) { - int numInactive = 0, i; - GET_CONNECTION(conn, -1); + int numInactive = 0; + virDomainObjPtr dom; + GET_CONNECTION(conn); - for (i = 0 ; i < MAX_DOMAINS ; i++) { - if (!privconn->domains[i].active || - privconn->domains[i].info.state != VIR_DOMAIN_SHUTOFF) - continue; - numInactive++; + dom = privconn->domains; + while (dom) { + if (!virDomainIsActive(dom)) + numInactive++; + dom = dom->next; } - return (numInactive); + return numInactive; } static int testListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) { - int n = 0, i; - GET_CONNECTION(conn, -1); + int n = 0; + virDomainObjPtr dom; + GET_CONNECTION(conn); - for (i = 0, n = 0 ; i < MAX_DOMAINS && n < maxnames ; i++) { - if (privconn->domains[i].active && - privconn->domains[i].info.state == VIR_DOMAIN_SHUTOFF) { - names[n++] = strdup(privconn->domains[i].name); - } + dom = privconn->domains; + memset(names, 0, sizeof(*names)*maxnames); + while (dom && n < maxnames) { + if (virDomainIsActive(dom) && + !(names[n++] = strdup(dom->def->name))) + goto no_memory; + dom = dom->next; } - return (n); + return n; + +no_memory: + testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + for (n = 0 ; n < maxnames ; n++) + VIR_FREE(names[n]); + return -1; } static virDomainPtr testDomainDefineXML(virConnectPtr conn, - const char *doc) { - int handle; - xmlDocPtr xml; - GET_CONNECTION(conn, NULL); + const char *xml) { + virDomainPtr ret; + virDomainDefPtr def; + virDomainObjPtr dom; + GET_CONNECTION(conn); - if (!(xml = xmlReadDoc(BAD_CAST doc, "domain.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { - testError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain")); - return (NULL); + if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL) + return NULL; + + if ((dom = virDomainAssignDef(conn, &privconn->domains, + def)) == NULL) { + virDomainDefFree(def); + return NULL; } + dom->persistent = 1; + dom->def->id = -1; - handle = testLoadDomain(conn, -1, xml); - privconn->domains[handle].config = 1; - - xmlFreeDoc(xml); - - if (handle < 0) - return (NULL); - - return virGetDomain(conn, privconn->domains[handle].name, privconn->domains[handle].uuid); + ret = virGetDomain(conn, def->name, def->uuid); + if (!ret) + return NULL; + ret->id = -1; + return ret; } static int testNodeGetCellsFreeMemory(virConnectPtr conn, @@ -1423,7 +1180,7 @@ int startCell, int maxCells) { int i, j; - GET_CONNECTION(conn, -1); + GET_CONNECTION(conn); if (startCell > privconn->numCells) { testError(conn, NULL, NULL, VIR_ERR_INVALID_ARG, @@ -1444,14 +1201,14 @@ static int testDomainCreate(virDomainPtr domain) { GET_DOMAIN(domain, -1); - if (privdom->info.state != VIR_DOMAIN_SHUTOFF) { + if (privdom->state != VIR_DOMAIN_SHUTOFF) { testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, _("Domain is already running")); return (-1); } - domain->id = privdom->id = privconn->nextDomID++; - privdom->info.state = VIR_DOMAIN_RUNNING; + domain->id = privdom->def->id = privconn->nextDomID++; + privdom->state = VIR_DOMAIN_RUNNING; return (0); } @@ -1459,13 +1216,15 @@ static int testDomainUndefine(virDomainPtr domain) { GET_DOMAIN(domain, -1); - if (privdom->info.state != VIR_DOMAIN_SHUTOFF) { + if (privdom->state != VIR_DOMAIN_SHUTOFF) { testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, _("Domain is still running")); return (-1); } - privdom->active = 0; + privdom->state = VIR_DOMAIN_SHUTOFF; + virDomainRemoveInactive(&privconn->domains, + privdom); return (0); } @@ -1511,7 +1270,9 @@ } strcpy(params[0].field, "weight"); params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT; - params[0].value.ui = privdom->weight; + /* XXX */ + /*params[0].value.ui = privdom->weight;*/ + params[0].value.ui = 50; return 0; } @@ -1533,7 +1294,8 @@ testError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, "type"); return (-1); } - privdom->weight = params[0].value.ui; + /* XXX */ + /*privdom->weight = params[0].value.ui;*/ return 0; } @@ -1558,7 +1320,7 @@ const unsigned char *uuid) { virNetworkObjPtr net = NULL; - GET_CONNECTION(conn, NULL); + GET_CONNECTION(conn); if ((net = virNetworkFindByUUID(privconn->networks, uuid)) == NULL) { testError (conn, NULL, NULL, VIR_ERR_NO_NETWORK, NULL); @@ -1572,7 +1334,7 @@ const char *name) { virNetworkObjPtr net = NULL; - GET_CONNECTION(conn, NULL); + GET_CONNECTION(conn); if ((net = virNetworkFindByName(privconn->networks, name)) == NULL) { testError (conn, NULL, NULL, VIR_ERR_NO_NETWORK, NULL); @@ -1586,7 +1348,7 @@ static int testNumNetworks(virConnectPtr conn) { int numActive = 0; virNetworkObjPtr net; - GET_CONNECTION(conn, -1); + GET_CONNECTION(conn); net = privconn->networks; while (net) { @@ -1600,7 +1362,7 @@ static int testListNetworks(virConnectPtr conn, char **const names, int nnames) { int n = 0; virNetworkObjPtr net; - GET_CONNECTION(conn, -1); + GET_CONNECTION(conn); net = privconn->networks; memset(names, 0, sizeof(*names)*nnames); @@ -1622,7 +1384,7 @@ static int testNumDefinedNetworks(virConnectPtr conn) { int numInactive = 0; virNetworkObjPtr net; - GET_CONNECTION(conn, -1); + GET_CONNECTION(conn); net = privconn->networks; while (net) { @@ -1636,7 +1398,7 @@ static int testListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) { int n = 0; virNetworkObjPtr net; - GET_CONNECTION(conn, -1); + GET_CONNECTION(conn); net = privconn->networks; memset(names, 0, sizeof(*names)*nnames); @@ -1658,7 +1420,7 @@ static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) { virNetworkDefPtr def; virNetworkObjPtr net; - GET_CONNECTION(conn, NULL); + GET_CONNECTION(conn); if ((def = virNetworkDefParseString(conn, xml)) == NULL) return NULL; @@ -1676,7 +1438,7 @@ static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) { virNetworkDefPtr def; virNetworkObjPtr net; - GET_CONNECTION(conn, NULL); + GET_CONNECTION(conn); if ((def = virNetworkDefParseString(conn, xml)) == NULL) return NULL; diff -r 3c038ace4e38 src/test.h --- a/src/test.h Mon Jul 07 11:39:43 2008 +0100 +++ b/src/test.h Mon Jul 07 11:39:51 2008 +0100 @@ -24,7 +24,7 @@ #ifndef __VIR_TEST_INTERNAL_H__ #define __VIR_TEST_INTERNAL_H__ -#include "libvirt/virterror.h" +#include "internal.h" #ifdef __cplusplus extern "C" { diff -r 3c038ace4e38 tests/read-non-seekable --- a/tests/read-non-seekable Mon Jul 07 11:39:43 2008 +0100 +++ b/tests/read-non-seekable Mon Jul 07 11:39:51 2008 +0100 @@ -31,6 +31,9 @@ <uuid>004b96e1-2d78-c30f-5aa5-000000000000</uuid> <memory>8388608</memory> <vcpu>2</vcpu> + <os> + <type>xen</type> + </os> <on_reboot>restart</on_reboot> <on_poweroff>destroy</on_poweroff> <on_crash>restart</on_crash> diff -r 3c038ace4e38 tests/virshtest.c --- a/tests/virshtest.c Mon Jul 07 11:39:43 2008 +0100 +++ b/tests/virshtest.c Mon Jul 07 11:39:51 2008 +0100 @@ -48,10 +48,6 @@ if (testFilterLine(actualData, filter) < 0) return -1; - if (getenv("DEBUG_TESTS")) { - printf("Expect %d '%s'\n", (int)strlen(expectData), expectData); - printf("Actual %d '%s'\n", (int)strlen(actualData), actualData); - } if (STRNEQ(expectData, actualData)) { virtTestDifference(stderr, expectData, actualData); return -1; -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Tue, Jul 08, 2008 at 05:35:31PM +0100, Daniel P. Berrange wrote:
This patch ports the Test driver over to the domain XML apis.
diff -r 3c038ace4e38 tests/virshtest.c --- a/tests/virshtest.c Mon Jul 07 11:39:43 2008 +0100 +++ b/tests/virshtest.c Mon Jul 07 11:39:51 2008 +0100 @@ -48,10 +48,6 @@ if (testFilterLine(actualData, filter) < 0) return -1;
- if (getenv("DEBUG_TESTS")) { - printf("Expect %d '%s'\n", (int)strlen(expectData), expectData); - printf("Actual %d '%s'\n", (int)strlen(actualData), actualData); - } if (STRNEQ(expectData, actualData)) { virtTestDifference(stderr, expectData, actualData); return -1;
This chunk of patch is obviously completely unrelated to the porting of the test driver to new APIs. Its just a cleanup of legacy debug output so I've just comitted this chunk now. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch ports the networking part of the QEMU driver to the new network APIs. Obviously we delete alot of the struct defintions and all the code used for parsing and formatting XML. Then there follows alot of fixup to deal with API name changes. The other notable point is that the char * arrays are no longer pre-declared as PATH_MAX in size, instead being allocated on the heap. So we change alot of conditionals from looking like foo[0] == '\0' over to foo == NULL Really this networking code doesn't belong in the QEMU driver at all. We really ought to move it out into a network_driver.c file as its nothing todo with QEMU at all. Its just here from historical days when it had to run inside the libvirt_qemud daemon. Since the last version of the patch lots of bugs fixed, and also al the code for saving/loading the persistent config files has been moved into the generic network_conf.c module too. bridge.c | 63 ++--- bridge.h | 4 qemu_conf.c | 626 ---------------------------------------------------------- qemu_conf.h | 95 -------- qemu_driver.c | 377 ++++++++++++++++++---------------- 5 files changed, 230 insertions(+), 935 deletions(-) Daniel diff -r 86abc19320a1 src/bridge.c --- a/src/bridge.c Tue Jul 08 15:06:51 2008 +0100 +++ b/src/bridge.c Tue Jul 08 15:26:10 2008 +0100 @@ -116,60 +116,41 @@ /** * brAddBridge: * @ctl: bridge control pointer - * @nameOrFmt: the bridge name (or name template) - * @name: pointer to @maxlen bytes to store the bridge name - * @maxlen: size of @name array + * @name: the bridge name * - * This function register a new bridge, @nameOrFmt can be either - * a fixed name or a name template with '%d' for dynamic name allocation. - * in either case the final name for the bridge will be stored in @name. + * This function register a new bridge * * Returns 0 in case of success or an errno code in case of failure. */ #ifdef SIOCBRADDBR int brAddBridge(brControl *ctl, - const char *nameOrFmt, - char *name, - int maxlen) + char **name) { - int id, subst; - - if (!ctl || !ctl->fd || !nameOrFmt || !name) + if (!ctl || !ctl->fd || !name) return EINVAL; - if (maxlen >= BR_IFNAME_MAXLEN) - maxlen = BR_IFNAME_MAXLEN; + if (*name) { + if (ioctl(ctl->fd, SIOCBRADDBR, *name) == 0) + return 0; + } else { + int id = 0; + do { + char try[50]; - subst = id = 0; + snprintf(try, sizeof(try), "virbr%d", id); - if (strstr(nameOrFmt, "%d")) - subst = 1; + if (ioctl(ctl->fd, SIOCBRADDBR, try) == 0) { + if (!(*name = strdup(try))) { + ioctl(ctl->fd, SIOCBRDELBR, name); + return ENOMEM; + } + return 0; + } - do { - char try[BR_IFNAME_MAXLEN]; - int len; - - if (subst) { - len = snprintf(try, maxlen, nameOrFmt, id); - if (len >= maxlen) - return EADDRINUSE; - } else { - len = strlen(nameOrFmt); - if (len >= maxlen - 1) - return EINVAL; - - strncpy(try, nameOrFmt, len); - try[len] = '\0'; - } - - if (ioctl(ctl->fd, SIOCBRADDBR, try) == 0) { - strncpy(name, try, maxlen); - return 0; - } - - id++; - } while (subst && id <= MAX_BRIDGE_ID); + id++; + } while (id < MAX_BRIDGE_ID); + } return errno; } diff -r 86abc19320a1 src/bridge.h --- a/src/bridge.h Tue Jul 08 15:06:51 2008 +0100 +++ b/src/bridge.h Tue Jul 08 15:26:10 2008 +0100 @@ -47,9 +47,7 @@ void brShutdown (brControl *ctl); int brAddBridge (brControl *ctl, - const char *nameOrFmt, - char *name, - int maxlen); + char **name); int brDeleteBridge (brControl *ctl, const char *name); diff -r 86abc19320a1 src/qemu_conf.c --- a/src/qemu_conf.c Tue Jul 08 15:06:51 2008 +0100 +++ b/src/qemu_conf.c Tue Jul 08 15:26:10 2008 +0100 @@ -175,32 +175,6 @@ if (STREQ(vm->def->name, name)) return vm; vm = vm->next; - } - - return NULL; -} - -struct qemud_network *qemudFindNetworkByUUID(const struct qemud_driver *driver, - const unsigned char *uuid) { - struct qemud_network *network = driver->networks; - - while (network) { - if (!memcmp(network->def->uuid, uuid, VIR_UUID_BUFLEN)) - return network; - network = network->next; - } - - return NULL; -} - -struct qemud_network *qemudFindNetworkByName(const struct qemud_driver *driver, - const char *name) { - struct qemud_network *network = driver->networks; - - while (network) { - if (STREQ(network->def->name, name)) - return network; - network = network->next; } return NULL; @@ -2254,7 +2228,7 @@ struct qemud_vm_net_def *net, int vlan) { - struct qemud_network *network = NULL; + virNetworkObjPtr network = NULL; char *brname; char *ifname; char tapfdstr[4+3+32+7]; @@ -2263,18 +2237,18 @@ int tapfd = -1; if (net->type == QEMUD_NET_NETWORK) { - if (!(network = qemudFindNetworkByName(driver, net->dst.network.name))) { + if (!(network = virNetworkFindByName(driver->networks, net->dst.network.name))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("Network '%s' not found"), net->dst.network.name); goto error; - } else if (network->bridge[0] == '\0') { + } else if (network->def->bridge == NULL) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("Network '%s' not active"), net->dst.network.name); goto error; } - brname = network->bridge; + brname = network->def->bridge; if (net->dst.network.ifname[0] == '\0' || STRPREFIX(net->dst.network.ifname, "vnet") || strchr(net->dst.network.ifname, '%')) { @@ -3113,465 +3087,6 @@ return qemudSaveConfig(conn, driver, vm, def); } -static int qemudSaveNetworkConfig(virConnectPtr conn, - struct qemud_driver *driver, - struct qemud_network *network, - struct qemud_network_def *def) { - char *xml; - int fd, ret = -1; - int towrite; - int err; - - if (!(xml = qemudGenerateNetworkXML(conn, driver, network, def))) { - return -1; - } - - if ((err = virFileMakePath(driver->networkConfigDir))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot create config directory %s: %s"), - driver->networkConfigDir, strerror(err)); - goto cleanup; - } - - if ((fd = open(network->configFile, - O_WRONLY | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR )) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot create config file %s: %s"), - network->configFile, strerror(errno)); - goto cleanup; - } - - towrite = strlen(xml); - if (safewrite(fd, xml, towrite) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot write config file %s: %s"), - network->configFile, strerror(errno)); - goto cleanup; - } - - if (close(fd) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot save config file %s: %s"), - network->configFile, strerror(errno)); - goto cleanup; - } - - ret = 0; - - cleanup: - - VIR_FREE(xml); - - return ret; -} - -void qemudFreeNetworkDef(struct qemud_network_def *def) { - struct qemud_dhcp_range_def *range = def->ranges; - while (range) { - struct qemud_dhcp_range_def *next = range->next; - VIR_FREE(range); - range = next; - } - VIR_FREE(def); -} - -void qemudFreeNetwork(struct qemud_network *network) { - qemudFreeNetworkDef(network->def); - if (network->newDef) - qemudFreeNetworkDef(network->newDef); - VIR_FREE(network); -} - -static int qemudParseBridgeXML(struct qemud_driver *driver ATTRIBUTE_UNUSED, - struct qemud_network_def *def, - xmlNodePtr node) { - xmlChar *name, *stp, *delay; - - name = xmlGetProp(node, BAD_CAST "name"); - if (name != NULL) { - strncpy(def->bridge, (const char *)name, IF_NAMESIZE-1); - def->bridge[IF_NAMESIZE-1] = '\0'; - xmlFree(name); - name = NULL; - } - - stp = xmlGetProp(node, BAD_CAST "stp"); - if (stp != NULL) { - if (xmlStrEqual(stp, BAD_CAST "off")) { - def->disableSTP = 1; - } - xmlFree(stp); - stp = NULL; - } - - delay = xmlGetProp(node, BAD_CAST "delay"); - if (delay != NULL) { - def->forwardDelay = strtol((const char *)delay, NULL, 10); - xmlFree(delay); - delay = NULL; - } - - return 1; -} - -static int qemudParseDhcpRangesXML(virConnectPtr conn, - struct qemud_driver *driver ATTRIBUTE_UNUSED, - struct qemud_network_def *def, - xmlNodePtr node) { - - xmlNodePtr cur; - - cur = node->children; - while (cur != NULL) { - struct qemud_dhcp_range_def *range; - xmlChar *start, *end; - - if (cur->type != XML_ELEMENT_NODE || - !xmlStrEqual(cur->name, BAD_CAST "range")) { - cur = cur->next; - continue; - } - - if (VIR_ALLOC(range) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for range string")); - return 0; - } - - start = xmlGetProp(cur, BAD_CAST "start"); - end = xmlGetProp(cur, BAD_CAST "end"); - - if (start && start[0] && end && end[0]) { - strncpy(range->start, (const char *)start, BR_INET_ADDR_MAXLEN-1); - range->start[BR_INET_ADDR_MAXLEN-1] = '\0'; - - strncpy(range->end, (const char *)end, BR_INET_ADDR_MAXLEN-1); - range->end[BR_INET_ADDR_MAXLEN-1] = '\0'; - - range->next = def->ranges; - def->ranges = range; - def->nranges++; - } else { - VIR_FREE(range); - } - - xmlFree(start); - xmlFree(end); - - cur = cur->next; - } - - return 1; -} - -static int qemudParseInetXML(virConnectPtr conn, - struct qemud_driver *driver ATTRIBUTE_UNUSED, - struct qemud_network_def *def, - xmlNodePtr node) { - xmlChar *address, *netmask; - xmlNodePtr cur; - - address = xmlGetProp(node, BAD_CAST "address"); - if (address != NULL) { - strncpy(def->ipAddress, (const char *)address, BR_INET_ADDR_MAXLEN-1); - def->ipAddress[BR_INET_ADDR_MAXLEN-1] = '\0'; - xmlFree(address); - address = NULL; - } - - netmask = xmlGetProp(node, BAD_CAST "netmask"); - if (netmask != NULL) { - strncpy(def->netmask, (const char *)netmask, BR_INET_ADDR_MAXLEN-1); - def->netmask[BR_INET_ADDR_MAXLEN-1] = '\0'; - xmlFree(netmask); - netmask = NULL; - } - - if (def->ipAddress[0] && def->netmask[0]) { - struct in_addr inaddress, innetmask; - char *netaddr; - - inet_aton((const char*)def->ipAddress, &inaddress); - inet_aton((const char*)def->netmask, &innetmask); - - inaddress.s_addr &= innetmask.s_addr; - - netaddr = inet_ntoa(inaddress); - - snprintf(def->network,sizeof(def->network)-1, - "%s/%s", netaddr, (const char *)def->netmask); - } - - cur = node->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE && - xmlStrEqual(cur->name, BAD_CAST "dhcp") && - !qemudParseDhcpRangesXML(conn, driver, def, cur)) - return 0; - cur = cur->next; - } - - return 1; -} - - -static struct qemud_network_def *qemudParseNetworkXML(virConnectPtr conn, - struct qemud_driver *driver, - xmlDocPtr xml) { - xmlNodePtr root = NULL; - xmlXPathContextPtr ctxt = NULL; - xmlXPathObjectPtr obj = NULL, tmp = NULL; - struct qemud_network_def *def; - - if (VIR_ALLOC(def) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for network_def string")); - return NULL; - } - - /* Prepare parser / xpath context */ - root = xmlDocGetRootElement(xml); - if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "network"))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("incorrect root element")); - goto error; - } - - ctxt = xmlXPathNewContext(xml); - if (ctxt == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for xmlXPathContext string")); - goto error; - } - - - /* Extract network name */ - obj = xmlXPathEval(BAD_CAST "string(/network/name[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_NAME, NULL); - goto error; - } - if (strlen((const char *)obj->stringval) >= (QEMUD_MAX_NAME_LEN-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("network name length too long")); - goto error; - } - strcpy(def->name, (const char *)obj->stringval); - xmlXPathFreeObject(obj); - - - /* Extract network uuid */ - obj = xmlXPathEval(BAD_CAST "string(/network/uuid[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - int err; - if ((err = virUUIDGenerate(def->uuid))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("Failed to generate UUID: %s"), strerror(err)); - goto error; - } - } else if (virUUIDParse((const char *)obj->stringval, def->uuid) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("malformed uuid element")); - goto error; - } - xmlXPathFreeObject(obj); - - /* Parse bridge information */ - obj = xmlXPathEval(BAD_CAST "/network/bridge[1]", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) { - if (!qemudParseBridgeXML(driver, def, obj->nodesetval->nodeTab[0])) { - goto error; - } - } - xmlXPathFreeObject(obj); - - /* Parse IP information */ - obj = xmlXPathEval(BAD_CAST "/network/ip[1]", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) { - if (!qemudParseInetXML(conn, driver, def, obj->nodesetval->nodeTab[0])) { - goto error; - } - } - xmlXPathFreeObject(obj); - - /* IPv4 forwarding setup */ - obj = xmlXPathEval(BAD_CAST "count(/network/forward) > 0", ctxt); - if ((obj != NULL) && (obj->type == XPATH_BOOLEAN) && - obj->boolval) { - if (!def->ipAddress[0] || - !def->netmask[0]) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("Forwarding requested, but no IPv4 address/netmask provided")); - goto error; - } - - def->forward = 1; - - tmp = xmlXPathEval(BAD_CAST "string(/network/forward[1]/@mode)", ctxt); - if ((tmp != NULL) && (tmp->type == XPATH_STRING) && - (tmp->stringval != NULL) && (xmlStrEqual(tmp->stringval, BAD_CAST "route"))) { - def->forwardMode = QEMUD_NET_FORWARD_ROUTE; - } else { - def->forwardMode = QEMUD_NET_FORWARD_NAT; - } - xmlXPathFreeObject(tmp); - tmp = NULL; - - tmp = xmlXPathEval(BAD_CAST "string(/network/forward[1]/@dev)", ctxt); - if ((tmp != NULL) && (tmp->type == XPATH_STRING) && - (tmp->stringval != NULL) && (tmp->stringval[0] != 0)) { - int len; - if ((len = xmlStrlen(tmp->stringval)) >= (BR_IFNAME_MAXLEN-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("forward device name '%s' is too long"), - (char*)tmp->stringval); - goto error; - } - strcpy(def->forwardDev, (char*)tmp->stringval); - } else { - def->forwardDev[0] = '\0'; - } - xmlXPathFreeObject(tmp); - tmp = NULL; - } else { - def->forward = 0; - } - xmlXPathFreeObject(obj); - - xmlXPathFreeContext(ctxt); - - return def; - - error: - /* XXX free all the stuff in the qemud_network struct, or leave it upto - the caller ? */ - xmlXPathFreeObject(obj); - xmlXPathFreeObject(tmp); - xmlXPathFreeContext(ctxt); - qemudFreeNetworkDef(def); - return NULL; -} - -struct qemud_network_def * -qemudParseNetworkDef(virConnectPtr conn, - struct qemud_driver *driver, - const char *xmlStr, - const char *displayName) { - xmlDocPtr xml; - struct qemud_network_def *def; - - if (!(xml = xmlReadDoc(BAD_CAST xmlStr, displayName ? displayName : "network.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, NULL); - return NULL; - } - - def = qemudParseNetworkXML(conn, driver, xml); - - xmlFreeDoc(xml); - - return def; -} - -struct qemud_network * -qemudAssignNetworkDef(virConnectPtr conn, - struct qemud_driver *driver, - struct qemud_network_def *def) { - struct qemud_network *network; - - if ((network = qemudFindNetworkByName(driver, def->name))) { - if (!qemudIsActiveNetwork(network)) { - qemudFreeNetworkDef(network->def); - network->def = def; - } else { - if (network->newDef) - qemudFreeNetworkDef(network->newDef); - network->newDef = def; - } - - return network; - } - - if (VIR_ALLOC(network) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for network string")); - return NULL; - } - - network->def = def; - network->next = driver->networks; - - driver->networks = network; - driver->ninactivenetworks++; - - return network; -} - -void -qemudRemoveInactiveNetwork(struct qemud_driver *driver, - struct qemud_network *network) -{ - struct qemud_network *prev = NULL, *curr; - - curr = driver->networks; - while (curr != network) { - prev = curr; - curr = curr->next; - } - - if (curr) { - if (prev) - prev->next = curr->next; - else - driver->networks = curr->next; - - driver->ninactivenetworks--; - } - - qemudFreeNetwork(network); -} - -int -qemudSaveNetworkDef(virConnectPtr conn, - struct qemud_driver *driver, - struct qemud_network *network, - struct qemud_network_def *def) { - - if (network->configFile[0] == '\0') { - int err; - - if ((err = virFileMakePath(driver->networkConfigDir))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot create config directory %s: %s"), - driver->networkConfigDir, strerror(err)); - return -1; - } - - if (virFileBuildPath(driver->networkConfigDir, def->name, ".xml", - network->configFile, PATH_MAX) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot construct config file path")); - return -1; - } - - if (virFileBuildPath(driver->networkAutostartDir, def->name, ".xml", - network->autostartLink, PATH_MAX) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot construct autostart link path")); - network->configFile[0] = '\0'; - return -1; - } - } - - return qemudSaveNetworkConfig(conn, driver, network, def); -} - static struct qemud_vm * qemudLoadConfig(struct qemud_driver *driver, @@ -3618,54 +3133,10 @@ return vm; } -static struct qemud_network * -qemudLoadNetworkConfig(struct qemud_driver *driver, - const char *file, - const char *path, - const char *xml, - const char *autostartLink) { - struct qemud_network_def *def; - struct qemud_network *network; - - if (!(def = qemudParseNetworkDef(NULL, driver, xml, file))) { - virErrorPtr err = virGetLastError(); - qemudLog(QEMUD_WARN, _("Error parsing network config '%s' : %s"), - path, err->message); - return NULL; - } - - if (!virFileMatchesNameSuffix(file, def->name, ".xml")) { - qemudLog(QEMUD_WARN, - _("Network config filename '%s'" - " does not match network name '%s'"), - path, def->name); - qemudFreeNetworkDef(def); - return NULL; - } - - if (!(network = qemudAssignNetworkDef(NULL, driver, def))) { - qemudLog(QEMUD_WARN, - _("Failed to load network config '%s': out of memory"), path); - qemudFreeNetworkDef(def); - return NULL; - } - - strncpy(network->configFile, path, PATH_MAX); - network->configFile[PATH_MAX-1] = '\0'; - - strncpy(network->autostartLink, autostartLink, PATH_MAX); - network->autostartLink[PATH_MAX-1] = '\0'; - - network->autostart = virFileLinkPointsTo(network->autostartLink, network->configFile); - - return network; -} - static int qemudScanConfigDir(struct qemud_driver *driver, const char *configDir, - const char *autostartDir, - int isGuest) { + const char *autostartDir) { DIR *dir; struct dirent *entry; @@ -3704,10 +3175,7 @@ if (virFileReadAll(path, QEMUD_MAX_XML_LEN, &xml) < 0) continue; - if (isGuest) - qemudLoadConfig(driver, entry->d_name, path, xml, autostartLink); - else - qemudLoadNetworkConfig(driver, entry->d_name, path, xml, autostartLink); + qemudLoadConfig(driver, entry->d_name, path, xml, autostartLink); VIR_FREE(xml); } @@ -3719,10 +3187,7 @@ /* Scan for all guest and network config files */ int qemudScanConfigs(struct qemud_driver *driver) { - if (qemudScanConfigDir(driver, driver->configDir, driver->autostartDir, 1) < 0) - return -1; - - if (qemudScanConfigDir(driver, driver->networkConfigDir, driver->networkAutostartDir, 0) < 0) + if (qemudScanConfigDir(driver, driver->configDir, driver->autostartDir) < 0) return -1; return 0; @@ -4128,83 +3593,6 @@ } -char *qemudGenerateNetworkXML(virConnectPtr conn, - struct qemud_driver *driver ATTRIBUTE_UNUSED, - struct qemud_network *network, - struct qemud_network_def *def) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - unsigned char *uuid; - char *tmp; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - - virBufferAddLit(&buf, "<network>\n"); - - virBufferVSprintf(&buf, " <name>%s</name>\n", def->name); - - uuid = def->uuid; - virUUIDFormat(uuid, uuidstr); - virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr); - - if (def->forward) { - if (def->forwardDev[0]) { - virBufferVSprintf(&buf, " <forward dev='%s' mode='%s'/>\n", - def->forwardDev, (def->forwardMode == QEMUD_NET_FORWARD_ROUTE ? "route" : "nat")); - } else { - virBufferVSprintf(&buf, " <forward mode='%s'/>\n", (def->forwardMode == QEMUD_NET_FORWARD_ROUTE ? "route" : "nat")); - } - } - - virBufferAddLit(&buf, " <bridge"); - if (qemudIsActiveNetwork(network)) { - virBufferVSprintf(&buf, " name='%s'", network->bridge); - } else if (def->bridge[0]) { - virBufferVSprintf(&buf, " name='%s'", def->bridge); - } - virBufferVSprintf(&buf, " stp='%s' forwardDelay='%d' />\n", - def->disableSTP ? "off" : "on", - def->forwardDelay); - - if (def->ipAddress[0] || def->netmask[0]) { - virBufferAddLit(&buf, " <ip"); - - if (def->ipAddress[0]) - virBufferVSprintf(&buf, " address='%s'", def->ipAddress); - - if (def->netmask[0]) - virBufferVSprintf(&buf, " netmask='%s'", def->netmask); - - virBufferAddLit(&buf, ">\n"); - - if (def->ranges) { - struct qemud_dhcp_range_def *range = def->ranges; - virBufferAddLit(&buf, " <dhcp>\n"); - while (range) { - virBufferVSprintf(&buf, " <range start='%s' end='%s' />\n", - range->start, range->end); - range = range->next; - } - virBufferAddLit(&buf, " </dhcp>\n"); - } - - virBufferAddLit(&buf, " </ip>\n"); - } - - virBufferAddLit(&buf, "</network>\n"); - - if (virBufferError(&buf)) - goto no_memory; - - return virBufferContentAndReset(&buf); - - no_memory: - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to generate XML: out of memory")); - tmp = virBufferContentAndReset(&buf); - VIR_FREE(tmp); - return NULL; -} - - int qemudDeleteConfig(virConnectPtr conn, struct qemud_driver *driver ATTRIBUTE_UNUSED, const char *configFile, diff -r 86abc19320a1 src/qemu_conf.h --- a/src/qemu_conf.h Tue Jul 08 15:06:51 2008 +0100 +++ b/src/qemu_conf.h Tue Jul 08 15:26:10 2008 +0100 @@ -32,6 +32,7 @@ #include "bridge.h" #include "iptables.h" #include "capabilities.h" +#include "network_conf.h" #include <netinet/in.h> #include <sched.h> @@ -94,12 +95,6 @@ QEMUD_NET_MCAST, QEMUD_NET_NETWORK, QEMUD_NET_BRIDGE, -}; - -/* 2 possible types of forwarding */ -enum qemud_vm_net_forward_type { - QEMUD_NET_FORWARD_NAT, - QEMUD_NET_FORWARD_ROUTE, }; #define QEMUD_MAX_NAME_LEN 50 @@ -349,53 +344,6 @@ struct qemud_vm *next; }; -/* Store start and end addresses of a dhcp range */ -struct qemud_dhcp_range_def { - char start[BR_INET_ADDR_MAXLEN]; - char end[BR_INET_ADDR_MAXLEN]; - - struct qemud_dhcp_range_def *next; -}; - -/* Virtual Network main configuration */ -struct qemud_network_def { - unsigned char uuid[VIR_UUID_BUFLEN]; - char name[QEMUD_MAX_NAME_LEN]; - - char bridge[BR_IFNAME_MAXLEN]; - int disableSTP; - int forwardDelay; - - int forward; - int forwardMode; /* From qemud_vm_net_forward_type */ - char forwardDev[BR_IFNAME_MAXLEN]; - - char ipAddress[BR_INET_ADDR_MAXLEN]; - char netmask[BR_INET_ADDR_MAXLEN]; - char network[BR_INET_ADDR_MAXLEN+BR_INET_ADDR_MAXLEN+1]; - - int nranges; - struct qemud_dhcp_range_def *ranges; -}; - -/* Virtual Network runtime state */ -struct qemud_network { - char configFile[PATH_MAX]; - char autostartLink[PATH_MAX]; - - struct qemud_network_def *def; /* The current definition */ - struct qemud_network_def *newDef; /* New definition to activate at shutdown */ - - char bridge[BR_IFNAME_MAXLEN]; - int dnsmasqPid; - - unsigned int active : 1; - unsigned int autostart : 1; - - struct qemud_network *next; -}; - - /* Main driver state */ struct qemud_driver { int qemuVersion; @@ -403,9 +351,9 @@ int ninactivevms; struct qemud_vm *vms; int nextvmid; - int nactivenetworks; - int ninactivenetworks; - struct qemud_network *networks; + + virNetworkObjPtr networks; + brControl *brctl; iptablesContext *iptables; char *configDir; @@ -428,12 +376,6 @@ return vm->id != -1; } -static inline int -qemudIsActiveNetwork(const struct qemud_network *network) -{ - return network->active; -} - void qemudReportError(virConnectPtr conn, virDomainPtr dom, virNetworkPtr net, @@ -450,11 +392,6 @@ const unsigned char *uuid); struct qemud_vm *qemudFindVMByName(const struct qemud_driver *driver, const char *name); - -struct qemud_network *qemudFindNetworkByUUID(const struct qemud_driver *driver, - const unsigned char *uuid); -struct qemud_network *qemudFindNetworkByName(const struct qemud_driver *driver, - const char *name); virCapsPtr qemudCapsInit (void); @@ -501,30 +438,6 @@ struct qemud_vm_def *def, int live); -void qemudFreeNetworkDef (struct qemud_network_def *def); -void qemudFreeNetwork (struct qemud_network *network); - -struct qemud_network * - qemudAssignNetworkDef (virConnectPtr conn, - struct qemud_driver *driver, - struct qemud_network_def *def); -void qemudRemoveInactiveNetwork (struct qemud_driver *driver, - struct qemud_network *network); - -struct qemud_network_def * - qemudParseNetworkDef (virConnectPtr conn, - struct qemud_driver *driver, - const char *xmlStr, - const char *displayName); -int qemudSaveNetworkDef (virConnectPtr conn, - struct qemud_driver *driver, - struct qemud_network *network, - struct qemud_network_def *def); -char * qemudGenerateNetworkXML (virConnectPtr conn, - struct qemud_driver *driver, - struct qemud_network *network, - struct qemud_network_def *def); - const char *qemudVirtTypeToString (int type); #endif /* WITH_QEMU */ diff -r 86abc19320a1 src/qemu_driver.c --- a/src/qemu_driver.c Tue Jul 08 15:06:51 2008 +0100 +++ b/src/qemu_driver.c Tue Jul 08 15:26:10 2008 +0100 @@ -120,11 +120,11 @@ static int qemudStartNetworkDaemon(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_network *network); + virNetworkObjPtr network); static int qemudShutdownNetworkDaemon(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_network *network); + virNetworkObjPtr network); static int qemudDomainGetMaxVcpus(virDomainPtr dom); static int qemudMonitorCommand (const struct qemud_driver *driver, @@ -137,15 +137,15 @@ static void qemudAutostartConfigs(struct qemud_driver *driver) { - struct qemud_network *network; + virNetworkObjPtr network; struct qemud_vm *vm; network = driver->networks; while (network != NULL) { - struct qemud_network *next = network->next; + virNetworkObjPtr next = network->next; if (network->autostart && - !qemudIsActiveNetwork(network) && + !virNetworkIsActive(network) && qemudStartNetworkDaemon(NULL, driver, network) < 0) { virErrorPtr err = virGetLastError(); qemudLog(QEMUD_ERR, _("Failed to autostart network '%s': %s"), @@ -247,6 +247,13 @@ qemudShutdown(); return -1; } + if (virNetworkLoadAllConfigs(NULL, + &qemu_driver->networks, + qemu_driver->networkConfigDir, + qemu_driver->networkAutostartDir) < 0) { + qemudShutdown(); + return -1; + } qemudAutostartConfigs(qemu_driver); return 0; @@ -273,6 +280,10 @@ static int qemudReload(void) { qemudScanConfigs(qemu_driver); + virNetworkLoadAllConfigs(NULL, + &qemu_driver->networks, + qemu_driver->networkConfigDir, + qemu_driver->networkAutostartDir); if (qemu_driver->iptables) { qemudLog(QEMUD_INFO, @@ -295,11 +306,14 @@ */ static int qemudActive(void) { - /* If we've any active networks or guests, then we - * mark this driver as active - */ - if (qemu_driver->nactivenetworks && - qemu_driver->nactivevms) + virNetworkObjPtr net = qemu_driver->networks; + while (net) { + if (net->active) + return 1; + net = net->next; + } + + if (qemu_driver->nactivevms) return 1; /* Otherwise we're happy to deal with a shutdown */ @@ -314,7 +328,7 @@ static int qemudShutdown(void) { struct qemud_vm *vm; - struct qemud_network *network; + virNetworkObjPtr network; if (!qemu_driver) return -1; @@ -346,8 +360,8 @@ /* shutdown active networks */ network = qemu_driver->networks; while (network) { - struct qemud_network *next = network->next; - if (qemudIsActiveNetwork(network)) + virNetworkObjPtr next = network->next; + if (virNetworkIsActive(network)) qemudShutdownNetworkDaemon(NULL, qemu_driver, network); network = next; } @@ -355,13 +369,11 @@ /* free inactive networks */ network = qemu_driver->networks; while (network) { - struct qemud_network *next = network->next; - qemudFreeNetwork(network); + virNetworkObjPtr next = network->next; + virNetworkObjFree(network); network = next; } qemu_driver->networks = NULL; - qemu_driver->nactivenetworks = 0; - qemu_driver->ninactivenetworks = 0; VIR_FREE(qemu_driver->configDir); VIR_FREE(qemu_driver->autostartDir); @@ -1039,11 +1051,10 @@ static int qemudBuildDnsmasqArgv(virConnectPtr conn, - struct qemud_network *network, + virNetworkObjPtr network, char ***argv) { - int i, len; + int i, len, r; char buf[PATH_MAX]; - struct qemud_dhcp_range_def *range; len = 1 + /* dnsmasq */ @@ -1109,15 +1120,13 @@ LOCAL_STATE_DIR, network->def->name); APPEND_ARG(*argv, i++, buf); - range = network->def->ranges; - while (range) { + for (r = 0 ; r < network->def->nranges ; r++) { snprintf(buf, sizeof(buf), "%s,%s", - range->start, range->end); + network->def->ranges[r].start, + network->def->ranges[r].end); APPEND_ARG(*argv, i++, "--dhcp-range"); APPEND_ARG(*argv, i++, buf); - - range = range->next; } #undef APPEND_ARG @@ -1138,12 +1147,12 @@ static int dhcpStartDhcpDaemon(virConnectPtr conn, - struct qemud_network *network) + virNetworkObjPtr network) { char **argv; int ret, i; - if (network->def->ipAddress[0] == '\0') { + if (network->def->ipAddress == NULL) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot start dhcp daemon without IP address for server")); return -1; @@ -1165,27 +1174,27 @@ static int qemudAddMasqueradingIptablesRules(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_network *network) { + virNetworkObjPtr network) { int err; /* allow forwarding packets from the bridge interface */ if ((err = iptablesAddForwardAllowOut(driver->iptables, network->def->network, - network->bridge, + network->def->bridge, network->def->forwardDev))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to add iptables rule to allow forwarding from '%s' : %s\n"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); goto masqerr1; } /* allow forwarding packets to the bridge interface if they are part of an existing connection */ if ((err = iptablesAddForwardAllowRelatedIn(driver->iptables, network->def->network, - network->bridge, + network->def->bridge, network->def->forwardDev))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to add iptables rule to allow forwarding to '%s' : %s\n"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); goto masqerr2; } @@ -1204,12 +1213,12 @@ masqerr3: iptablesRemoveForwardAllowRelatedIn(driver->iptables, network->def->network, - network->bridge, + network->def->bridge, network->def->forwardDev); masqerr2: iptablesRemoveForwardAllowOut(driver->iptables, network->def->network, - network->bridge, + network->def->bridge, network->def->forwardDev); masqerr1: return 0; @@ -1218,27 +1227,27 @@ static int qemudAddRoutingIptablesRules(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_network *network) { + virNetworkObjPtr network) { int err; /* allow routing packets from the bridge interface */ if ((err = iptablesAddForwardAllowOut(driver->iptables, network->def->network, - network->bridge, + network->def->bridge, network->def->forwardDev))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to add iptables rule to allow routing from '%s' : %s\n"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); goto routeerr1; } /* allow routing packets to the bridge interface */ if ((err = iptablesAddForwardAllowIn(driver->iptables, network->def->network, - network->bridge, + network->def->bridge, network->def->forwardDev))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to add iptables rule to allow routing to '%s' : %s\n"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); goto routeerr2; } @@ -1248,7 +1257,7 @@ routeerr2: iptablesRemoveForwardAllowOut(driver->iptables, network->def->network, - network->bridge, + network->def->bridge, network->def->forwardDev); routeerr1: return 0; @@ -1257,7 +1266,7 @@ static int qemudAddIptablesRules(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_network *network) { + virNetworkObjPtr network) { int err; if (!driver->iptables && !(driver->iptables = iptablesContextNew())) { @@ -1268,71 +1277,69 @@ /* allow DHCP requests through to dnsmasq */ - if ((err = iptablesAddTcpInput(driver->iptables, network->bridge, 67))) { + if ((err = iptablesAddTcpInput(driver->iptables, network->def->bridge, 67))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to add iptables rule to allow DHCP requests from '%s' : %s"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); goto err1; } - if ((err = iptablesAddUdpInput(driver->iptables, network->bridge, 67))) { + if ((err = iptablesAddUdpInput(driver->iptables, network->def->bridge, 67))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to add iptables rule to allow DHCP requests from '%s' : %s"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); goto err2; } /* allow DNS requests through to dnsmasq */ - if ((err = iptablesAddTcpInput(driver->iptables, network->bridge, 53))) { + if ((err = iptablesAddTcpInput(driver->iptables, network->def->bridge, 53))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to add iptables rule to allow DNS requests from '%s' : %s"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); goto err3; } - if ((err = iptablesAddUdpInput(driver->iptables, network->bridge, 53))) { + if ((err = iptablesAddUdpInput(driver->iptables, network->def->bridge, 53))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to add iptables rule to allow DNS requests from '%s' : %s"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); goto err4; } /* Catch all rules to block forwarding to/from bridges */ - if ((err = iptablesAddForwardRejectOut(driver->iptables, network->bridge))) { + if ((err = iptablesAddForwardRejectOut(driver->iptables, network->def->bridge))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to add iptables rule to block outbound traffic from '%s' : %s"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); goto err5; } - if ((err = iptablesAddForwardRejectIn(driver->iptables, network->bridge))) { + if ((err = iptablesAddForwardRejectIn(driver->iptables, network->def->bridge))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to add iptables rule to block inbound traffic to '%s' : %s"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); goto err6; } /* Allow traffic between guests on the same bridge */ - if ((err = iptablesAddForwardAllowCross(driver->iptables, network->bridge))) { + if ((err = iptablesAddForwardAllowCross(driver->iptables, network->def->bridge))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to add iptables rule to allow cross bridge traffic on '%s' : %s"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); goto err7; } - if (network->def->forward) { - /* If masquerading is enabled, set up the rules*/ - if (network->def->forwardMode == QEMUD_NET_FORWARD_NAT && - !qemudAddMasqueradingIptablesRules(conn, driver, network)) - goto err8; - /* else if routing is enabled, set up the rules*/ - else if (network->def->forwardMode == QEMUD_NET_FORWARD_ROUTE && - !qemudAddRoutingIptablesRules(conn, driver, network)) - goto err8; - } + /* If masquerading is enabled, set up the rules*/ + if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT && + !qemudAddMasqueradingIptablesRules(conn, driver, network)) + goto err8; + /* else if routing is enabled, set up the rules*/ + else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE && + !qemudAddRoutingIptablesRules(conn, driver, network)) + goto err8; iptablesSaveRules(driver->iptables); @@ -1340,56 +1347,56 @@ err8: iptablesRemoveForwardAllowCross(driver->iptables, - network->bridge); + network->def->bridge); err7: iptablesRemoveForwardRejectIn(driver->iptables, - network->bridge); + network->def->bridge); err6: iptablesRemoveForwardRejectOut(driver->iptables, - network->bridge); + network->def->bridge); err5: - iptablesRemoveUdpInput(driver->iptables, network->bridge, 53); + iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 53); err4: - iptablesRemoveTcpInput(driver->iptables, network->bridge, 53); + iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 53); err3: - iptablesRemoveUdpInput(driver->iptables, network->bridge, 67); + iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 67); err2: - iptablesRemoveTcpInput(driver->iptables, network->bridge, 67); + iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 67); err1: return 0; } static void qemudRemoveIptablesRules(struct qemud_driver *driver, - struct qemud_network *network) { - if (network->def->forward) { + virNetworkObjPtr network) { + if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE) { iptablesRemoveForwardMasquerade(driver->iptables, network->def->network, network->def->forwardDev); - if (network->def->forwardMode == QEMUD_NET_FORWARD_NAT) + if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) iptablesRemoveForwardAllowRelatedIn(driver->iptables, network->def->network, - network->bridge, + network->def->bridge, network->def->forwardDev); - else if (network->def->forwardMode == QEMUD_NET_FORWARD_ROUTE) + else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE) iptablesRemoveForwardAllowIn(driver->iptables, network->def->network, - network->bridge, + network->def->bridge, network->def->forwardDev); iptablesRemoveForwardAllowOut(driver->iptables, network->def->network, - network->bridge, + network->def->bridge, network->def->forwardDev); } - iptablesRemoveForwardAllowCross(driver->iptables, network->bridge); - iptablesRemoveForwardRejectIn(driver->iptables, network->bridge); - iptablesRemoveForwardRejectOut(driver->iptables, network->bridge); - iptablesRemoveUdpInput(driver->iptables, network->bridge, 53); - iptablesRemoveTcpInput(driver->iptables, network->bridge, 53); - iptablesRemoveUdpInput(driver->iptables, network->bridge, 67); - iptablesRemoveTcpInput(driver->iptables, network->bridge, 67); + iptablesRemoveForwardAllowCross(driver->iptables, network->def->bridge); + iptablesRemoveForwardRejectIn(driver->iptables, network->def->bridge); + iptablesRemoveForwardRejectOut(driver->iptables, network->def->bridge); + iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 53); + iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 53); + iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 67); + iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 67); iptablesSaveRules(driver->iptables); } @@ -1415,11 +1422,10 @@ static int qemudStartNetworkDaemon(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_network *network) { - const char *name; + virNetworkObjPtr network) { int err; - if (qemudIsActiveNetwork(network)) { + if (virNetworkIsActive(network)) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("network is already active")); return -1; @@ -1431,77 +1437,68 @@ return -1; } - if (network->def->bridge[0] == '\0' || - strchr(network->def->bridge, '%')) { - name = "vnet%d"; - } else { - name = network->def->bridge; - } - - if ((err = brAddBridge(driver->brctl, name, network->bridge, sizeof(network->bridge)))) { + if ((err = brAddBridge(driver->brctl, &network->def->bridge))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot create bridge '%s' : %s"), name, strerror(err)); + _("cannot create bridge '%s' : %s"), + network->def->bridge, strerror(err)); return -1; } - if (network->def->forwardDelay && - (err = brSetForwardDelay(driver->brctl, network->bridge, network->def->forwardDelay))) { + if (network->def->delay && + (err = brSetForwardDelay(driver->brctl, network->def->bridge, network->def->delay))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("failed to set bridge forward delay to %d"), - network->def->forwardDelay); + _("failed to set bridge forward delay to %ld"), + network->def->delay); goto err_delbr; } - if ((err = brSetEnableSTP(driver->brctl, network->bridge, network->def->disableSTP ? 0 : 1))) { + if ((err = brSetEnableSTP(driver->brctl, network->def->bridge, network->def->stp ? 1 : 0))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to set bridge STP to %s"), - network->def->disableSTP ? "off" : "on"); + network->def->stp ? "on" : "off"); goto err_delbr; } - if (network->def->ipAddress[0] && - (err = brSetInetAddress(driver->brctl, network->bridge, network->def->ipAddress))) { + if (network->def->ipAddress && + (err = brSetInetAddress(driver->brctl, network->def->bridge, network->def->ipAddress))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("cannot set IP address on bridge '%s' to '%s' : %s"), - network->bridge, network->def->ipAddress, strerror(err)); + network->def->bridge, network->def->ipAddress, strerror(err)); goto err_delbr; } - if (network->def->netmask[0] && - (err = brSetInetNetmask(driver->brctl, network->bridge, network->def->netmask))) { + if (network->def->netmask && + (err = brSetInetNetmask(driver->brctl, network->def->bridge, network->def->netmask))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("cannot set netmask on bridge '%s' to '%s' : %s"), - network->bridge, network->def->netmask, strerror(err)); + network->def->bridge, network->def->netmask, strerror(err)); goto err_delbr; } - if (network->def->ipAddress[0] && - (err = brSetInterfaceUp(driver->brctl, network->bridge, 1))) { + if (network->def->ipAddress && + (err = brSetInterfaceUp(driver->brctl, network->def->bridge, 1))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to bring the bridge '%s' up : %s"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); goto err_delbr; } if (!qemudAddIptablesRules(conn, driver, network)) goto err_delbr1; - if (network->def->forward && + if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE && !qemudEnableIpForwarding()) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to enable IP forwarding : %s"), strerror(err)); goto err_delbr2; } - if (network->def->ranges && + if (network->def->nranges && dhcpStartDhcpDaemon(conn, network) < 0) goto err_delbr2; network->active = 1; - - driver->ninactivenetworks--; - driver->nactivenetworks++; return 0; @@ -1509,16 +1506,16 @@ qemudRemoveIptablesRules(driver, network); err_delbr1: - if (network->def->ipAddress[0] && - (err = brSetInterfaceUp(driver->brctl, network->bridge, 0))) { + if (network->def->ipAddress && + (err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) { qemudLog(QEMUD_WARN, _("Failed to bring down bridge '%s' : %s"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); } err_delbr: - if ((err = brDeleteBridge(driver->brctl, network->bridge))) { + if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) { qemudLog(QEMUD_WARN, _("Failed to delete bridge '%s' : %s"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); } return -1; @@ -1527,12 +1524,12 @@ static int qemudShutdownNetworkDaemon(virConnectPtr conn ATTRIBUTE_UNUSED, struct qemud_driver *driver, - struct qemud_network *network) { + virNetworkObjPtr network) { int err; qemudLog(QEMUD_INFO, _("Shutting down network '%s'"), network->def->name); - if (!qemudIsActiveNetwork(network)) + if (!virNetworkIsActive(network)) return 0; if (network->dnsmasqPid > 0) @@ -1540,15 +1537,15 @@ qemudRemoveIptablesRules(driver, network); - if (network->def->ipAddress[0] && - (err = brSetInterfaceUp(driver->brctl, network->bridge, 0))) { + if (network->def->ipAddress && + (err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) { qemudLog(QEMUD_WARN, _("Failed to bring down bridge '%s' : %s"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); } - if ((err = brDeleteBridge(driver->brctl, network->bridge))) { + if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) { qemudLog(QEMUD_WARN, _("Failed to delete bridge '%s' : %s"), - network->bridge, strerror(err)); + network->def->bridge, strerror(err)); } if (network->dnsmasqPid > 0 && @@ -1559,21 +1556,18 @@ "%s", _("Got unexpected pid for dnsmasq")); } - network->bridge[0] = '\0'; network->dnsmasqPid = -1; network->active = 0; if (network->newDef) { - qemudFreeNetworkDef(network->def); + virNetworkDefFree(network->def); network->def = network->newDef; network->newDef = NULL; } - driver->nactivenetworks--; - driver->ninactivenetworks++; - - if (!network->configFile[0]) - qemudRemoveInactiveNetwork(driver, network); + if (!network->configFile) + virNetworkRemoveInactive(&driver->networks, + network); return 0; } @@ -3290,9 +3284,9 @@ } static virNetworkPtr qemudNetworkLookupByUUID(virConnectPtr conn ATTRIBUTE_UNUSED, - const unsigned char *uuid) { + const unsigned char *uuid) { struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData; - struct qemud_network *network = qemudFindNetworkByUUID(driver, uuid); + virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, uuid); virNetworkPtr net; if (!network) { @@ -3305,9 +3299,9 @@ return net; } static virNetworkPtr qemudNetworkLookupByName(virConnectPtr conn ATTRIBUTE_UNUSED, - const char *name) { + const char *name) { struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData; - struct qemud_network *network = qemudFindNetworkByName(driver, name); + virNetworkObjPtr network = virNetworkFindByName(driver->networks, name); virNetworkPtr net; if (!network) { @@ -3337,16 +3331,23 @@ } static int qemudNumNetworks(virConnectPtr conn) { + int nactive = 0; struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData; - return driver->nactivenetworks; + virNetworkObjPtr net = driver->networks; + while (net) { + if (virNetworkIsActive(net)) + nactive++; + net = net->next; + } + return nactive; } static int qemudListNetworks(virConnectPtr conn, char **const names, int nnames) { struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData; - struct qemud_network *network = driver->networks; + virNetworkObjPtr network = driver->networks; int got = 0, i; while (network && got < nnames) { - if (qemudIsActiveNetwork(network)) { + if (virNetworkIsActive(network)) { if (!(names[got] = strdup(network->def->name))) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for VM name string")); @@ -3365,16 +3366,23 @@ } static int qemudNumDefinedNetworks(virConnectPtr conn) { + int ninactive = 0; struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData; - return driver->ninactivenetworks; + virNetworkObjPtr net = driver->networks; + while (net) { + if (!virNetworkIsActive(net)) + ninactive++; + net = net->next; + } + return ninactive; } static int qemudListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) { struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData; - struct qemud_network *network = driver->networks; + virNetworkObjPtr network = driver->networks; int got = 0, i; while (network && got < nnames) { - if (!qemudIsActiveNetwork(network)) { + if (!virNetworkIsActive(network)) { if (!(names[got] = strdup(network->def->name))) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for VM name string")); @@ -3394,20 +3402,23 @@ static virNetworkPtr qemudNetworkCreate(virConnectPtr conn, const char *xml) { struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData; - struct qemud_network_def *def; - struct qemud_network *network; + virNetworkDefPtr def; + virNetworkObjPtr network; virNetworkPtr net; - if (!(def = qemudParseNetworkDef(conn, driver, xml, NULL))) + if (!(def = virNetworkDefParseString(conn, xml))) return NULL; - if (!(network = qemudAssignNetworkDef(conn, driver, def))) { - qemudFreeNetworkDef(def); + if (!(network = virNetworkAssignDef(conn, + &driver->networks, + def))) { + virNetworkDefFree(def); return NULL; } if (qemudStartNetworkDaemon(conn, driver, network) < 0) { - qemudRemoveInactiveNetwork(driver, network); + virNetworkRemoveInactive(&driver->networks, + network); return NULL; } @@ -3417,30 +3428,34 @@ static virNetworkPtr qemudNetworkDefine(virConnectPtr conn, const char *xml) { struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData; - struct qemud_network_def *def; - struct qemud_network *network; - virNetworkPtr net; + virNetworkDefPtr def; + virNetworkObjPtr network; - if (!(def = qemudParseNetworkDef(conn, driver, xml, NULL))) + if (!(def = virNetworkDefParseString(conn, xml))) return NULL; - if (!(network = qemudAssignNetworkDef(conn, driver, def))) { - qemudFreeNetworkDef(def); + if (!(network = virNetworkAssignDef(conn, + &driver->networks, + def))) { + virNetworkDefFree(def); return NULL; } - if (qemudSaveNetworkDef(conn, driver, network, def) < 0) { - qemudRemoveInactiveNetwork(driver, network); + if (virNetworkSaveConfig(conn, + driver->networkConfigDir, + driver->networkAutostartDir, + network) < 0) { + virNetworkRemoveInactive(&driver->networks, + network); return NULL; } - net = virGetNetwork(conn, network->def->name, network->def->uuid); - return net; + return virGetNetwork(conn, network->def->name, network->def->uuid); } static int qemudNetworkUndefine(virNetworkPtr net) { struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData; - struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid); + virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid); if (!network) { qemudReportError(net->conn, NULL, net, VIR_ERR_INVALID_DOMAIN, @@ -3448,24 +3463,24 @@ return -1; } - if (qemudDeleteConfig(net->conn, driver, network->configFile, network->def->name) < 0) + if (virNetworkIsActive(network)) { + qemudReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR, + "%s", _("network is still active")); + return -1; + } + + if (virNetworkDeleteConfig(net->conn, network) < 0) return -1; - if (unlink(network->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) - qemudLog(QEMUD_WARN, _("Failed to delete autostart link '%s': %s"), - network->autostartLink, strerror(errno)); - - network->configFile[0] = '\0'; - network->autostartLink[0] = '\0'; - - qemudRemoveInactiveNetwork(driver, network); + virNetworkRemoveInactive(&driver->networks, + network); return 0; } static int qemudNetworkStart(virNetworkPtr net) { struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData; - struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid); + virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid); if (!network) { qemudReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, @@ -3478,7 +3493,7 @@ static int qemudNetworkDestroy(virNetworkPtr net) { struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData; - struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid); + virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid); int ret; if (!network) { @@ -3494,7 +3509,7 @@ static char *qemudNetworkDumpXML(virNetworkPtr net, int flags ATTRIBUTE_UNUSED) { struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData; - struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid); + virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid); if (!network) { qemudReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, @@ -3502,12 +3517,12 @@ return NULL; } - return qemudGenerateNetworkXML(net->conn, driver, network, network->def); + return virNetworkDefFormat(net->conn, network->def); } static char *qemudNetworkGetBridgeName(virNetworkPtr net) { struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData; - struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid); + virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid); char *bridge; if (!network) { qemudReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, @@ -3515,7 +3530,7 @@ return NULL; } - bridge = strdup(network->bridge); + bridge = strdup(network->def->bridge); if (!bridge) { qemudReportError(net->conn, NULL, net, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for network bridge string")); @@ -3527,7 +3542,7 @@ static int qemudNetworkGetAutostart(virNetworkPtr net, int *autostart) { struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData; - struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid); + virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid); if (!network) { qemudReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, @@ -3543,7 +3558,7 @@ static int qemudNetworkSetAutostart(virNetworkPtr net, int autostart) { struct qemud_driver *driver = (struct qemud_driver *)net->conn->networkPrivateData; - struct qemud_network *network = qemudFindNetworkByUUID(driver, net->uuid); + virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid); if (!network) { qemudReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch ports the QEMU driver to the domain XML apis. Obviously we delete alot of the struct defintions and all the code used for parsing and formatting XML. Then there follows alot of fixup to deal with API name changes. The other notable point is that the char * arrays are no longer pre-declared as PATH_MAX in size, instead being allocated on the heap. So we change alot of conditionals from looking like foo[0] == '\0' over to foo == NULL The qemudBuildCommandLine() functions gains a whole lot of extra args since we no longer pass our QEMU specific state in via the domain's config object (as that's shared between all drivers). Since the last version of the patch lots of bugs fixed, and also al the code for saving/loading the persistent config files has been moved into the generic network_conf.c module too. src/qemu_conf.c | 2781 +------------------ src/qemu_conf.h | 368 -- src/qemu_driver.c | 481 +-- tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml | 2 tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc.xml | 2 tests/qemuxml2argvdata/qemuxml2argv-input-xen.args | 2 tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml | 4 tests/qemuxml2argvdata/qemuxml2argv-sound.xml | 7 tests/qemuxml2argvtest.c | 31 tests/qemuxml2xmltest.c | 20 10 files changed, 468 insertions(+), 3230 deletions(-) Daniel diff -r 8b6e9b6cbaa5 src/qemu_conf.c --- a/src/qemu_conf.c Tue Jul 08 15:26:54 2008 +0100 +++ b/src/qemu_conf.c Tue Jul 08 15:29:16 2008 +0100 @@ -37,16 +37,10 @@ #include <arpa/inet.h> #include <sys/utsname.h> -#include <libxml/parser.h> -#include <libxml/tree.h> -#include <libxml/xpath.h> -#include <libxml/uri.h> - #if HAVE_NUMACTL #include <numa.h> #endif -#include "internal.h" #include "qemu_conf.h" #include "uuid.h" #include "buf.h" @@ -55,7 +49,15 @@ #include "memory.h" #include "verify.h" #include "c-ctype.h" -#include "xml.h" + +VIR_ENUM_DECL(virDomainDiskQEMUBus) +VIR_ENUM_IMPL(virDomainDiskQEMUBus, VIR_DOMAIN_DISK_BUS_LAST, + "ide", + "floppy", + "scsi", + "virtio", + "xen") + #define qemudLog(level, msg...) fprintf(stderr, msg) @@ -64,12 +66,12 @@ virNetworkPtr net, int code, const char *fmt, ...) { va_list args; - char errorMessage[QEMUD_MAX_ERROR_LEN]; + char errorMessage[1024]; const char *virerr; if (fmt) { va_start(args, fmt); - vsnprintf(errorMessage, QEMUD_MAX_ERROR_LEN-1, fmt, args); + vsnprintf(errorMessage, sizeof(errorMessage)-1, fmt, args); va_end(args); } else { errorMessage[0] = '\0'; @@ -86,7 +88,11 @@ virConfValuePtr p; /* Setup 2 critical defaults */ - strcpy(driver->vncListen, "127.0.0.1"); + if (!(driver->vncListen = strdup("127.0.0.1"))) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY, + "%s", _("failed to allocate vncListen")); + return -1; + } if (!(driver->vncTLSx509certdir = strdup(SYSCONF_DIR "/pki/libvirt-vnc"))) { qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate vncTLSx509certdir")); @@ -133,104 +139,17 @@ p = virConfGetValue (conf, "vnc_listen"); CHECK_TYPE ("vnc_listen", VIR_CONF_STRING); if (p && p->str) { - strncpy(driver->vncListen, p->str, sizeof(driver->vncListen)); - driver->vncListen[sizeof(driver->vncListen)-1] = '\0'; + if (!(driver->vncListen = strdup(p->str))) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY, + "%s", _("failed to allocate vncTLSx509certdir")); + virConfFree(conf); + return -1; + } } virConfFree (conf); return 0; } - - -struct qemud_vm *qemudFindVMByID(const struct qemud_driver *driver, int id) { - struct qemud_vm *vm = driver->vms; - - while (vm) { - if (qemudIsActiveVM(vm) && vm->id == id) - return vm; - vm = vm->next; - } - - return NULL; -} - -struct qemud_vm *qemudFindVMByUUID(const struct qemud_driver *driver, - const unsigned char *uuid) { - struct qemud_vm *vm = driver->vms; - - while (vm) { - if (!memcmp(vm->def->uuid, uuid, VIR_UUID_BUFLEN)) - return vm; - vm = vm->next; - } - - return NULL; -} - -struct qemud_vm *qemudFindVMByName(const struct qemud_driver *driver, - const char *name) { - struct qemud_vm *vm = driver->vms; - - while (vm) { - if (STREQ(vm->def->name, name)) - return vm; - vm = vm->next; - } - - return NULL; -} - - -/* Free all memory associated with a struct qemud_vm object */ -void qemudFreeVMDef(struct qemud_vm_def *def) { - struct qemud_vm_disk_def *disk = def->disks; - struct qemud_vm_net_def *net = def->nets; - struct qemud_vm_input_def *input = def->inputs; - struct qemud_vm_chr_def *serial = def->serials; - struct qemud_vm_chr_def *parallel = def->parallels; - struct qemud_vm_sound_def *sound = def->sounds; - - while (disk) { - struct qemud_vm_disk_def *prev = disk; - disk = disk->next; - VIR_FREE(prev); - } - while (net) { - struct qemud_vm_net_def *prev = net; - net = net->next; - VIR_FREE(prev); - } - while (input) { - struct qemud_vm_input_def *prev = input; - input = input->next; - VIR_FREE(prev); - } - while (serial) { - struct qemud_vm_chr_def *prev = serial; - serial = serial->next; - VIR_FREE(prev); - } - while (parallel) { - struct qemud_vm_chr_def *prev = parallel; - parallel = parallel->next; - VIR_FREE(prev); - } - while (sound) { - struct qemud_vm_sound_def *prev = sound; - sound = sound->next; - VIR_FREE(prev); - } - xmlFree(def->keymap); - VIR_FREE(def); -} - -void qemudFreeVM(struct qemud_vm *vm) { - qemudFreeVMDef(vm->def); - if (vm->newDef) - qemudFreeVMDef(vm->newDef); - VIR_FREE(vm); -} - /* The list of possible machine types for various architectures, as supported by QEMU - taken from 'qemu -M ?' for each arch */ @@ -477,12 +396,14 @@ } -static int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) { +int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) { pid_t child; int newstdout[2]; - *flags = 0; - *version = 0; + if (flags) + *flags = 0; + if (version) + *version = 0; if (pipe(newstdout) < 0) { return -1; @@ -538,19 +459,22 @@ goto cleanup2; } - *version = (major * 1000 * 1000) + (minor * 1000) + micro; - if (strstr(help, "-no-kqemu")) - *flags |= QEMUD_CMD_FLAG_KQEMU; - if (strstr(help, "-no-reboot")) - *flags |= QEMUD_CMD_FLAG_NO_REBOOT; - if (strstr(help, "-name")) - *flags |= QEMUD_CMD_FLAG_NAME; - if (strstr(help, "-drive")) - *flags |= QEMUD_CMD_FLAG_DRIVE; - if (strstr(help, "boot=on")) - *flags |= QEMUD_CMD_FLAG_DRIVE_BOOT; - if (*version >= 9000) - *flags |= QEMUD_CMD_FLAG_VNC_COLON; + if (version) + *version = (major * 1000 * 1000) + (minor * 1000) + micro; + if (flags) { + if (strstr(help, "-no-kqemu")) + *flags |= QEMUD_CMD_FLAG_KQEMU; + if (strstr(help, "-no-reboot")) + *flags |= QEMUD_CMD_FLAG_NO_REBOOT; + if (strstr(help, "-name")) + *flags |= QEMUD_CMD_FLAG_NAME; + if (strstr(help, "-drive")) + *flags |= QEMUD_CMD_FLAG_DRIVE; + if (strstr(help, "boot=on")) + *flags |= QEMUD_CMD_FLAG_DRIVE_BOOT; + if (*version >= 9000) + *flags |= QEMUD_CMD_FLAG_VNC_COLON; + } ret = 0; qemudDebug("Version %d %d %d Cooked version: %d, with flags ? %d", @@ -612,1620 +536,13 @@ return 0; } -/* Converts def->virtType to applicable string type - * @param type integer virt type - * @return string type on success, NULL on fail - */ -const char * qemudVirtTypeToString(int type) { - switch (type) { - case QEMUD_VIRT_QEMU: - return "qemu"; - case QEMUD_VIRT_KQEMU: - return "kqemu"; - case QEMUD_VIRT_KVM: - return "kvm"; - } - return NULL; -} - -/* Parse the XML definition for a disk - * @param disk pre-allocated & zero'd disk record - * @param node XML nodeset to parse for disk definition - * @return 0 on success, -1 on failure - */ -static int qemudParseDiskXML(virConnectPtr conn, - struct qemud_vm_disk_def *disk, - xmlNodePtr node) { - xmlNodePtr cur; - xmlChar *device = NULL; - xmlChar *source = NULL; - xmlChar *target = NULL; - xmlChar *type = NULL; - xmlChar *bus = NULL; - int typ = 0; - - type = xmlGetProp(node, BAD_CAST "type"); - if (type != NULL) { - if (xmlStrEqual(type, BAD_CAST "file")) - typ = QEMUD_DISK_FILE; - else if (xmlStrEqual(type, BAD_CAST "block")) - typ = QEMUD_DISK_BLOCK; - else { - typ = QEMUD_DISK_FILE; - } - xmlFree(type); - type = NULL; - } - - device = xmlGetProp(node, BAD_CAST "device"); - - cur = node->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE) { - if ((source == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "source"))) { - - if (typ == QEMUD_DISK_FILE) - source = xmlGetProp(cur, BAD_CAST "file"); - else - source = xmlGetProp(cur, BAD_CAST "dev"); - } else if ((target == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "target"))) { - target = xmlGetProp(cur, BAD_CAST "dev"); - bus = xmlGetProp(cur, BAD_CAST "bus"); - } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) { - disk->readonly = 1; - } - } - cur = cur->next; - } - - if (source == NULL) { - /* There is a case without the source - * to the CD-ROM device - */ - if (!device || STRNEQ((const char *) device, "cdrom")) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SOURCE, - target ? "%s" : NULL, target); - goto error; - } - } - - if (target == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_TARGET, source ? "%s" : NULL, source); - goto error; - } - - if (device && - STREQ((const char *)device, "floppy") && - STRNEQ((const char *)target, "fda") && - STRNEQ((const char *)target, "fdb")) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("Invalid floppy device name: %s"), target); - goto error; - } - - if (device && - STREQ((const char *)device, "cdrom") && - STRNEQ((const char *)target, "hdc")) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("Invalid cdrom device name: %s"), target); - goto error; - } - - if (device && - STREQ((const char *)device, "cdrom")) - disk->readonly = 1; - - if ((!device || STREQ((const char *)device, "disk")) && - !STRPREFIX((const char *)target, "hd") && - !STRPREFIX((const char *)target, "sd") && - !STRPREFIX((const char *)target, "vd") && - !STRPREFIX((const char *)target, "xvd")) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("Invalid harddisk device name: %s"), target); - goto error; - } - - strncpy(disk->src, (source ? (const char *) source : "\0"), NAME_MAX-1); - disk->src[NAME_MAX-1] = '\0'; - - strncpy(disk->dst, (const char *)target, NAME_MAX-1); - disk->dst[NAME_MAX-1] = '\0'; - disk->type = typ; - - if (!device) - disk->device = QEMUD_DISK_DISK; - else if (STREQ((const char *)device, "disk")) - disk->device = QEMUD_DISK_DISK; - else if (STREQ((const char *)device, "cdrom")) - disk->device = QEMUD_DISK_CDROM; - else if (STREQ((const char *)device, "floppy")) - disk->device = QEMUD_DISK_FLOPPY; - else { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("Invalid device type: %s"), device); - goto error; - } - - if (!bus) { - if (disk->device == QEMUD_DISK_FLOPPY) { - disk->bus = QEMUD_DISK_BUS_FDC; - } else { - if (STRPREFIX((const char *)target, "hd")) - disk->bus = QEMUD_DISK_BUS_IDE; - else if (STRPREFIX((const char *)target, "sd")) - disk->bus = QEMUD_DISK_BUS_SCSI; - else if (STRPREFIX((const char *)target, "vd")) - disk->bus = QEMUD_DISK_BUS_VIRTIO; - else if (STRPREFIX((const char *)target, "xvd")) - disk->bus = QEMUD_DISK_BUS_XEN; - else - disk->bus = QEMUD_DISK_BUS_IDE; - } - } else if (STREQ((const char *)bus, "ide")) - disk->bus = QEMUD_DISK_BUS_IDE; - else if (STREQ((const char *)bus, "fdc")) - disk->bus = QEMUD_DISK_BUS_FDC; - else if (STREQ((const char *)bus, "scsi")) - disk->bus = QEMUD_DISK_BUS_SCSI; - else if (STREQ((const char *)bus, "virtio")) - disk->bus = QEMUD_DISK_BUS_VIRTIO; - else if (STREQ((const char *)bus, "xen")) - disk->bus = QEMUD_DISK_BUS_XEN; - else { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("Invalid bus type: %s"), bus); - goto error; - } - - if (disk->device == QEMUD_DISK_FLOPPY && - disk->bus != QEMUD_DISK_BUS_FDC) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("Invalid bus type '%s' for floppy disk"), bus); - goto error; - } - - xmlFree(device); - xmlFree(target); - xmlFree(source); - xmlFree(bus); - - return 0; - - error: - xmlFree(bus); - xmlFree(type); - xmlFree(target); - xmlFree(source); - xmlFree(device); - return -1; -} - -static void qemudRandomMAC(struct qemud_vm_net_def *net) { - net->mac[0] = 0x52; - net->mac[1] = 0x54; - net->mac[2] = 0x00; - net->mac[3] = 1 + (int)(256*(rand()/(RAND_MAX+1.0))); - net->mac[4] = 1 + (int)(256*(rand()/(RAND_MAX+1.0))); - net->mac[5] = 1 + (int)(256*(rand()/(RAND_MAX+1.0))); -} - - -/* Parse the XML definition for a network interface - * @param net pre-allocated & zero'd net record - * @param node XML nodeset to parse for net definition - * @return 0 on success, -1 on failure - */ -static int qemudParseInterfaceXML(virConnectPtr conn, - struct qemud_vm_net_def *net, - xmlNodePtr node) { - xmlNodePtr cur; - xmlChar *macaddr = NULL; - xmlChar *type = NULL; - xmlChar *network = NULL; - xmlChar *bridge = NULL; - xmlChar *ifname = NULL; - xmlChar *script = NULL; - xmlChar *address = NULL; - xmlChar *port = NULL; - xmlChar *model = NULL; - - net->type = QEMUD_NET_USER; - - type = xmlGetProp(node, BAD_CAST "type"); - if (type != NULL) { - if (xmlStrEqual(type, BAD_CAST "user")) - net->type = QEMUD_NET_USER; - else if (xmlStrEqual(type, BAD_CAST "ethernet")) - net->type = QEMUD_NET_ETHERNET; - else if (xmlStrEqual(type, BAD_CAST "server")) - net->type = QEMUD_NET_SERVER; - else if (xmlStrEqual(type, BAD_CAST "client")) - net->type = QEMUD_NET_CLIENT; - else if (xmlStrEqual(type, BAD_CAST "mcast")) - net->type = QEMUD_NET_MCAST; - else if (xmlStrEqual(type, BAD_CAST "network")) - net->type = QEMUD_NET_NETWORK; - else if (xmlStrEqual(type, BAD_CAST "bridge")) - net->type = QEMUD_NET_BRIDGE; - else - net->type = QEMUD_NET_USER; - xmlFree(type); - type = NULL; - } - - cur = node->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE) { - if ((macaddr == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "mac"))) { - macaddr = xmlGetProp(cur, BAD_CAST "address"); - } else if ((network == NULL) && - (net->type == QEMUD_NET_NETWORK) && - (xmlStrEqual(cur->name, BAD_CAST "source"))) { - network = xmlGetProp(cur, BAD_CAST "network"); - } else if ((network == NULL) && - (net->type == QEMUD_NET_BRIDGE) && - (xmlStrEqual(cur->name, BAD_CAST "source"))) { - bridge = xmlGetProp(cur, BAD_CAST "bridge"); - } else if ((network == NULL) && - ((net->type == QEMUD_NET_SERVER) || - (net->type == QEMUD_NET_CLIENT) || - (net->type == QEMUD_NET_MCAST)) && - (xmlStrEqual(cur->name, BAD_CAST "source"))) { - address = xmlGetProp(cur, BAD_CAST "address"); - port = xmlGetProp(cur, BAD_CAST "port"); - } else if ((ifname == NULL) && - ((net->type == QEMUD_NET_NETWORK) || - (net->type == QEMUD_NET_ETHERNET) || - (net->type == QEMUD_NET_BRIDGE)) && - xmlStrEqual(cur->name, BAD_CAST "target")) { - ifname = xmlGetProp(cur, BAD_CAST "dev"); - if (STRPREFIX((const char*)ifname, "vnet")) { - /* An auto-generated target name, blank it out */ - xmlFree(ifname); - ifname = NULL; - } - } else if ((script == NULL) && - (net->type == QEMUD_NET_ETHERNET) && - xmlStrEqual(cur->name, BAD_CAST "script")) { - script = xmlGetProp(cur, BAD_CAST "path"); - } else if (xmlStrEqual (cur->name, BAD_CAST "model")) { - model = xmlGetProp (cur, BAD_CAST "type"); - } - } - cur = cur->next; - } - - if (macaddr) { - unsigned int mac[6]; - sscanf((const char *)macaddr, "%02x:%02x:%02x:%02x:%02x:%02x", - (unsigned int*)&mac[0], - (unsigned int*)&mac[1], - (unsigned int*)&mac[2], - (unsigned int*)&mac[3], - (unsigned int*)&mac[4], - (unsigned int*)&mac[5]); - net->mac[0] = mac[0]; - net->mac[1] = mac[1]; - net->mac[2] = mac[2]; - net->mac[3] = mac[3]; - net->mac[4] = mac[4]; - net->mac[5] = mac[5]; - - xmlFree(macaddr); - macaddr = NULL; - } else { - qemudRandomMAC(net); - } - - if (net->type == QEMUD_NET_NETWORK) { - int len; - - if (network == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("No <source> 'network' attribute specified with <interface type='network'/>")); - goto error; - } else if ((len = xmlStrlen(network)) >= (QEMUD_MAX_NAME_LEN-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("Network name '%s' too long"), network); - goto error; - } else { - strncpy(net->dst.network.name, (char *)network, len); - net->dst.network.name[len] = '\0'; - } - - if (network) { - xmlFree(network); - network = NULL; - } - - if (ifname != NULL) { - if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("TAP interface name '%s' is too long"), - ifname); - goto error; - } else { - strncpy(net->dst.network.ifname, (char *)ifname, len); - net->dst.network.ifname[len] = '\0'; - } - xmlFree(ifname); - ifname = NULL; - } - } else if (net->type == QEMUD_NET_ETHERNET) { - int len; - - if (script != NULL) { - if ((len = xmlStrlen(script)) >= (PATH_MAX-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("TAP script path '%s' is too long"), script); - goto error; - } else { - strncpy(net->dst.ethernet.script, (char *)script, len); - net->dst.ethernet.script[len] = '\0'; - } - xmlFree(script); - script = NULL; - } - if (ifname != NULL) { - if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("TAP interface name '%s' is too long"), - ifname); - goto error; - } else { - strncpy(net->dst.ethernet.ifname, (char *)ifname, len); - net->dst.ethernet.ifname[len] = '\0'; - } - xmlFree(ifname); - } - } else if (net->type == QEMUD_NET_BRIDGE) { - int len; - - if (bridge == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("No <source> 'dev' attribute specified with <interface type='bridge'/>")); - goto error; - } else if ((len = xmlStrlen(bridge)) >= (BR_IFNAME_MAXLEN-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("TAP bridge path '%s' is too long"), bridge); - goto error; - } else { - strncpy(net->dst.bridge.brname, (char *)bridge, len); - net->dst.bridge.brname[len] = '\0'; - } - - xmlFree(bridge); - bridge = NULL; - - if (ifname != NULL) { - if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("TAP interface name '%s' is too long"), ifname); - goto error; - } else { - strncpy(net->dst.bridge.ifname, (char *)ifname, len); - net->dst.bridge.ifname[len] = '\0'; - } - xmlFree(ifname); - } - } else if (net->type == QEMUD_NET_CLIENT || - net->type == QEMUD_NET_SERVER || - net->type == QEMUD_NET_MCAST) { - int len = 0; - char *ret; - - if (port == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("No <source> 'port' attribute specified with socket interface")); - goto error; - } - if (!(net->dst.socket.port = strtol((char*)port, &ret, 10)) && - ret == (char*)port) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("Cannot parse <source> 'port' attribute with socket interface")); - goto error; - } - xmlFree(port); - port = NULL; - - if (address == NULL) { - if (net->type == QEMUD_NET_CLIENT || - net->type == QEMUD_NET_MCAST) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("No <source> 'address' attribute specified with socket interface")); - goto error; - } - } else if ((len = xmlStrlen(address)) >= (BR_INET_ADDR_MAXLEN)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("IP address '%s' is too long"), address); - goto error; - } - if (address == NULL) { - net->dst.socket.address[0] = '\0'; - } else { - strncpy(net->dst.socket.address, (char*)address,len); - net->dst.socket.address[len] = '\0'; - } - xmlFree(address); - } - - /* NIC model (see -net nic,model=?). We only check that it looks - * reasonable, not that it is a supported NIC type. FWIW kvm - * supports these types as of April 2008: - * i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio - */ - if (model != NULL) { - int i, len; - - len = xmlStrlen (model); - if (len >= QEMUD_MODEL_MAX_LEN) { - qemudReportError (conn, NULL, NULL, VIR_ERR_INVALID_ARG, - _("Model name '%s' is too long"), model); - goto error; - } - for (i = 0; i < len; ++i) { - int char_ok = c_isalnum(model[i]) || model[i] == '_'; - if (!char_ok) { - qemudReportError (conn, NULL, NULL, VIR_ERR_INVALID_ARG, "%s", - _("Model name contains invalid characters")); - goto error; - } - } - strncpy (net->model, (const char*) model, len); - net->model[len] = '\0'; - - xmlFree (model); - model = NULL; - } else - net->model[0] = '\0'; - - return 0; - - error: - xmlFree(network); - xmlFree(address); - xmlFree(port); - xmlFree(ifname); - xmlFree(script); - xmlFree(bridge); - xmlFree(model); - return -1; -} - - -/* Parse the XML definition for a character device - * @param net pre-allocated & zero'd net record - * @param node XML nodeset to parse for net definition - * @return 0 on success, -1 on failure - * - * The XML we're dealing with looks like - * - * <serial type="pty"> - * <source path="/dev/pts/3"/> - * <target port="1"/> - * </serial> - * - * <serial type="dev"> - * <source path="/dev/ttyS0"/> - * <target port="1"/> - * </serial> - * - * <serial type="tcp"> - * <source mode="connect" host="0.0.0.0" service="2445"/> - * <target port="1"/> - * </serial> - * - * <serial type="tcp"> - * <source mode="bind" host="0.0.0.0" service="2445"/> - * <target port="1"/> - * </serial> - * - * <serial type="udp"> - * <source mode="bind" host="0.0.0.0" service="2445"/> - * <source mode="connect" host="0.0.0.0" service="2445"/> - * <target port="1"/> - * </serial> - * - * <serial type="unix"> - * <source mode="bind" path="/tmp/foo"/> - * <target port="1"/> - * </serial> - * - */ -static int qemudParseCharXML(virConnectPtr conn, - struct qemud_vm_chr_def *chr, - int portNum, - xmlNodePtr node) { - xmlNodePtr cur; - xmlChar *type = NULL; - xmlChar *bindHost = NULL; - xmlChar *bindService = NULL; - xmlChar *connectHost = NULL; - xmlChar *connectService = NULL; - xmlChar *path = NULL; - xmlChar *mode = NULL; - xmlChar *protocol = NULL; - int ret = -1; - - chr->srcType = QEMUD_CHR_SRC_TYPE_PTY; - type = xmlGetProp(node, BAD_CAST "type"); - if (type != NULL) { - if (xmlStrEqual(type, BAD_CAST "null")) - chr->srcType = QEMUD_CHR_SRC_TYPE_NULL; - else if (xmlStrEqual(type, BAD_CAST "vc")) - chr->srcType = QEMUD_CHR_SRC_TYPE_VC; - else if (xmlStrEqual(type, BAD_CAST "pty")) - chr->srcType = QEMUD_CHR_SRC_TYPE_PTY; - else if (xmlStrEqual(type, BAD_CAST "dev")) - chr->srcType = QEMUD_CHR_SRC_TYPE_DEV; - else if (xmlStrEqual(type, BAD_CAST "file")) - chr->srcType = QEMUD_CHR_SRC_TYPE_FILE; - else if (xmlStrEqual(type, BAD_CAST "pipe")) - chr->srcType = QEMUD_CHR_SRC_TYPE_PIPE; - else if (xmlStrEqual(type, BAD_CAST "stdio")) - chr->srcType = QEMUD_CHR_SRC_TYPE_STDIO; - else if (xmlStrEqual(type, BAD_CAST "udp")) - chr->srcType = QEMUD_CHR_SRC_TYPE_UDP; - else if (xmlStrEqual(type, BAD_CAST "tcp")) - chr->srcType = QEMUD_CHR_SRC_TYPE_TCP; - else if (xmlStrEqual(type, BAD_CAST "unix")) - chr->srcType = QEMUD_CHR_SRC_TYPE_UNIX; - else - chr->srcType = QEMUD_CHR_SRC_TYPE_NULL; - } - - cur = node->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE) { - if (xmlStrEqual(cur->name, BAD_CAST "source")) { - if (mode == NULL) - mode = xmlGetProp(cur, BAD_CAST "mode"); - - switch (chr->srcType) { - case QEMUD_CHR_SRC_TYPE_PTY: - case QEMUD_CHR_SRC_TYPE_DEV: - case QEMUD_CHR_SRC_TYPE_FILE: - case QEMUD_CHR_SRC_TYPE_PIPE: - case QEMUD_CHR_SRC_TYPE_UNIX: - if (path == NULL) - path = xmlGetProp(cur, BAD_CAST "path"); - - break; - - case QEMUD_CHR_SRC_TYPE_UDP: - case QEMUD_CHR_SRC_TYPE_TCP: - if (mode == NULL || - STREQ((const char *)mode, "connect")) { - - if (connectHost == NULL) - connectHost = xmlGetProp(cur, BAD_CAST "host"); - if (connectService == NULL) - connectService = xmlGetProp(cur, BAD_CAST "service"); - } else { - if (bindHost == NULL) - bindHost = xmlGetProp(cur, BAD_CAST "host"); - if (bindService == NULL) - bindService = xmlGetProp(cur, BAD_CAST "service"); - } - - if (chr->srcType == QEMUD_CHR_SRC_TYPE_UDP) { - xmlFree(mode); - mode = NULL; - } - } - } else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) { - if (protocol == NULL) - protocol = xmlGetProp(cur, BAD_CAST "type"); - } - } - cur = cur->next; - } - - - chr->dstPort = portNum; - - switch (chr->srcType) { - case QEMUD_CHR_SRC_TYPE_NULL: - /* Nada */ - break; - - case QEMUD_CHR_SRC_TYPE_VC: - break; - - case QEMUD_CHR_SRC_TYPE_PTY: - /* @path attribute is an output only property - pty is auto-allocted */ - break; - - case QEMUD_CHR_SRC_TYPE_DEV: - case QEMUD_CHR_SRC_TYPE_FILE: - case QEMUD_CHR_SRC_TYPE_PIPE: - if (path == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("Missing source path attribute for char device")); - goto cleanup; - } - - strncpy(chr->srcData.file.path, (const char *)path, - sizeof(chr->srcData.file.path)); - NUL_TERMINATE(chr->srcData.file.path); - break; - - case QEMUD_CHR_SRC_TYPE_STDIO: - /* Nada */ - break; - - case QEMUD_CHR_SRC_TYPE_TCP: - if (mode == NULL || - STREQ((const char *)mode, "connect")) { - if (connectHost == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("Missing source host attribute for char device")); - goto cleanup; - } - if (connectService == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("Missing source service attribute for char device")); - goto cleanup; - } - - strncpy(chr->srcData.tcp.host, (const char *)connectHost, - sizeof(chr->srcData.tcp.host)); - NUL_TERMINATE(chr->srcData.tcp.host); - strncpy(chr->srcData.tcp.service, (const char *)connectService, - sizeof(chr->srcData.tcp.service)); - NUL_TERMINATE(chr->srcData.tcp.service); - - chr->srcData.tcp.listen = 0; - } else { - if (bindHost == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("Missing source host attribute for char device")); - goto cleanup; - } - if (bindService == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("Missing source service attribute for char device")); - goto cleanup; - } - - strncpy(chr->srcData.tcp.host, (const char *)bindHost, - sizeof(chr->srcData.tcp.host)); - NUL_TERMINATE(chr->srcData.tcp.host); - strncpy(chr->srcData.tcp.service, (const char *)bindService, - sizeof(chr->srcData.tcp.service)); - NUL_TERMINATE(chr->srcData.tcp.service); - - chr->srcData.tcp.listen = 1; - } - if (protocol != NULL && - STREQ((const char *)protocol, "telnet")) - chr->srcData.tcp.protocol = QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET; - else - chr->srcData.tcp.protocol = QEMUD_CHR_SRC_TCP_PROTOCOL_RAW; - break; - - case QEMUD_CHR_SRC_TYPE_UDP: - if (connectService == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("Missing source service attribute for char device")); - goto cleanup; - } - - if (connectHost != NULL) { - strncpy(chr->srcData.udp.connectHost, (const char *)connectHost, - sizeof(chr->srcData.udp.connectHost)); - NUL_TERMINATE(chr->srcData.udp.connectHost); - } - strncpy(chr->srcData.udp.connectService, (const char *)connectService, - sizeof(chr->srcData.udp.connectService)); - NUL_TERMINATE(chr->srcData.udp.connectService); - - if (bindHost != NULL) { - strncpy(chr->srcData.udp.bindHost, (const char *)bindHost, - sizeof(chr->srcData.udp.bindHost)); - NUL_TERMINATE(chr->srcData.udp.bindHost); - } - if (bindService != NULL) { - strncpy(chr->srcData.udp.bindService, (const char *)bindService, - sizeof(chr->srcData.udp.bindService)); - NUL_TERMINATE(chr->srcData.udp.bindService); - } - break; - - case QEMUD_CHR_SRC_TYPE_UNIX: - if (path == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("Missing source path attribute for char device")); - goto cleanup; - } - - if (mode != NULL && - STRNEQ((const char *)mode, "connect")) - chr->srcData.nix.listen = 1; - else - chr->srcData.nix.listen = 0; - - strncpy(chr->srcData.nix.path, (const char *)path, - sizeof(chr->srcData.nix.path)); - NUL_TERMINATE(chr->srcData.nix.path); - break; - } - - ret = 0; - -cleanup: - xmlFree(mode); - xmlFree(protocol); - xmlFree(type); - xmlFree(bindHost); - xmlFree(bindService); - xmlFree(connectHost); - xmlFree(connectService); - xmlFree(path); - - return ret; -} - - -static int qemudParseCharXMLDevices(virConnectPtr conn, - xmlXPathContextPtr ctxt, - const char *xpath, - unsigned int *ndevs, - struct qemud_vm_chr_def **devs) -{ - xmlXPathObjectPtr obj; - int i, ret = -1; - - obj = xmlXPathEval(BAD_CAST xpath, ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { - struct qemud_vm_chr_def *prev = *devs; - if (ndevs == NULL && - obj->nodesetval->nodeNr > 1) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("too many character devices")); - goto cleanup; - } - - for (i = 0; i < obj->nodesetval->nodeNr; i++) { - struct qemud_vm_chr_def *chr; - if (VIR_ALLOC(chr) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", - _("failed to allocate space for char device")); - goto cleanup; - } - - if (qemudParseCharXML(conn, chr, i, obj->nodesetval->nodeTab[i]) < 0) { - VIR_FREE(chr); - goto cleanup; - } - if (ndevs) - (*ndevs)++; - chr->next = NULL; - if (i == 0) { - *devs = chr; - } else { - prev->next = chr; - } - prev = chr; - } - } - - ret = 0; - -cleanup: - xmlXPathFreeObject(obj); - return ret; -} - - -/* Parse the XML definition for a network interface */ -static int qemudParseInputXML(virConnectPtr conn, - const struct qemud_vm_def *vm, - struct qemud_vm_input_def *input, - xmlNodePtr node) { - xmlChar *type = NULL; - xmlChar *bus = NULL; - - type = xmlGetProp(node, BAD_CAST "type"); - bus = xmlGetProp(node, BAD_CAST "bus"); - - if (!type) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("missing input device type")); - goto error; - } - - if (STREQ((const char *)type, "mouse")) { - input->type = QEMU_INPUT_TYPE_MOUSE; - } else if (STREQ((const char *)type, "tablet")) { - input->type = QEMU_INPUT_TYPE_TABLET; - } else { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("unsupported input device type %s"), - (const char*)type); - goto error; - } - - if (bus) { - if (STREQ(vm->os.type, "hvm")) { - if (STREQ((const char*)bus, "ps2")) { /* Only allow mouse */ - if (input->type != QEMU_INPUT_TYPE_MOUSE) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("ps2 bus does not support %s input device"), - (const char*)type); - goto error; - } - input->bus = QEMU_INPUT_BUS_PS2; - } else if (STREQ((const char *)bus, "usb")) { /* Allow mouse & tablet */ - input->bus = QEMU_INPUT_BUS_USB; - } else { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("unsupported input bus %s"), (const char*)bus); - goto error; - } - } else { - if (STREQ((const char *)bus, "xen")) { /* Allow mouse only */ - input->bus = QEMU_INPUT_BUS_XEN; - if (input->type != QEMU_INPUT_TYPE_MOUSE) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("xen bus does not support %s input device"), - (const char*)type); - goto error; - } - } else { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("unsupported input bus %s"), (const char*)bus); - goto error; - } - } - } else { - if (STREQ(vm->os.type, "hvm")) { - if (input->type == QEMU_INPUT_TYPE_MOUSE) - input->bus = QEMU_INPUT_BUS_PS2; - else - input->bus = QEMU_INPUT_BUS_USB; - } else { - input->bus = QEMU_INPUT_BUS_XEN; - } - } - - xmlFree(type); - xmlFree(bus); - - return 0; - - error: - xmlFree(type); - xmlFree(bus); - - return -1; -} - -static int qemudDiskCompare(const void *aptr, const void *bptr) { - struct qemud_vm_disk_def *a = (struct qemud_vm_disk_def *) aptr; - struct qemud_vm_disk_def *b = (struct qemud_vm_disk_def *) bptr; - if (a->bus == b->bus) - return virDiskNameToIndex(a->dst) - virDiskNameToIndex(b->dst); - else - return a->bus - b->bus; -} - -static const char *qemudBusIdToName(int busId, int qemuIF) { - const char *busnames[] = { "ide", - (qemuIF ? "floppy" : "fdc"), - "scsi", - "virtio", - "xen"}; - verify_true(ARRAY_CARDINALITY(busnames) == QEMUD_DISK_BUS_LAST); - - return busnames[busId]; -} - -/* Sound device helper functions */ -static int qemudSoundModelFromString(const char *model) { - if (STREQ(model, "sb16")) { - return QEMU_SOUND_SB16; - } else if (STREQ(model, "es1370")) { - return QEMU_SOUND_ES1370; - } else if (STREQ(model, "pcspk")) { - return QEMU_SOUND_PCSPK; - } - - return -1; -} - -static const char *qemudSoundModelToString(const int model) { - - if (model == QEMU_SOUND_SB16) { - return "sb16"; - } else if (model == QEMU_SOUND_ES1370) { - return "es1370"; - } else if (model == QEMU_SOUND_PCSPK) { - return "pcspk"; - } - - return NULL; -} - - -static int qemudParseSoundXML(virConnectPtr conn, - struct qemud_vm_sound_def *sound, - const xmlNodePtr node) { - - int err = -1; - xmlChar *model = NULL; - model = xmlGetProp(node, BAD_CAST "model"); - - if (!model) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("missing sound model")); - goto error; - } - if ((sound->model = qemudSoundModelFromString((char *) model)) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("invalid sound model '%s'"), (char *) model); - goto error; - } - - err = 0; - error: - xmlFree(model); - return err; -} - -/* - * Parses a libvirt XML definition of a guest, and populates the - * the qemud_vm struct with matching data about the guests config - */ -static struct qemud_vm_def *qemudParseXML(virConnectPtr conn, - struct qemud_driver *driver, - xmlDocPtr xml) { - xmlNodePtr root = NULL; - xmlChar *prop = NULL; - xmlXPathContextPtr ctxt = NULL; - xmlXPathObjectPtr obj = NULL; - char *conv = NULL; - int i; - struct qemud_vm_def *def; - - if (VIR_ALLOC(def) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for xmlXPathContext")); - return NULL; - } - - /* Prepare parser / xpath context */ - root = xmlDocGetRootElement(xml); - if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "domain"))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("incorrect root element")); - goto error; - } - - ctxt = xmlXPathNewContext(xml); - if (ctxt == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for xmlXPathContext")); - goto error; - } - - - /* Find out what type of QEMU virtualization to use */ - if (!(prop = xmlGetProp(root, BAD_CAST "type"))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("missing domain type attribute")); - goto error; - } - - if (STREQ((char *)prop, "qemu")) - def->virtType = QEMUD_VIRT_QEMU; - else if (STREQ((char *)prop, "kqemu")) - def->virtType = QEMUD_VIRT_KQEMU; - else if (STREQ((char *)prop, "kvm")) - def->virtType = QEMUD_VIRT_KVM; - else { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("invalid domain type attribute")); - goto error; - } - VIR_FREE(prop); - - - /* Extract domain name */ - obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_NAME, NULL); - goto error; - } - if (strlen((const char *)obj->stringval) >= (QEMUD_MAX_NAME_LEN-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("domain name length too long")); - goto error; - } - strcpy(def->name, (const char *)obj->stringval); - xmlXPathFreeObject(obj); - - - /* Extract domain uuid */ - obj = xmlXPathEval(BAD_CAST "string(/domain/uuid[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - int err; - if ((err = virUUIDGenerate(def->uuid))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("Failed to generate UUID: %s"), strerror(err)); - goto error; - } - } else if (virUUIDParse((const char *)obj->stringval, def->uuid) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("malformed uuid element")); - goto error; - } - xmlXPathFreeObject(obj); - - - /* Extract domain memory */ - obj = xmlXPathEval(BAD_CAST "string(/domain/memory[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("missing memory element")); - goto error; - } else { - conv = NULL; - def->maxmem = strtoll((const char*)obj->stringval, &conv, 10); - if (conv == (const char*)obj->stringval) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("malformed memory information")); - goto error; - } - } - xmlXPathFreeObject(obj); - - - /* Extract domain memory */ - obj = xmlXPathEval(BAD_CAST "string(/domain/currentMemory[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - def->memory = def->maxmem; - } else { - conv = NULL; - def->memory = strtoll((const char*)obj->stringval, &conv, 10); - if (def->memory > def->maxmem) - def->memory = def->maxmem; - if (conv == (const char*)obj->stringval) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("malformed memory information")); - goto error; - } - } - xmlXPathFreeObject(obj); - - /* Extract domain vcpu info */ - obj = xmlXPathEval(BAD_CAST "string(/domain/vcpu[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - def->vcpus = 1; - } else { - conv = NULL; - def->vcpus = strtoll((const char*)obj->stringval, &conv, 10); - if (conv == (const char*)obj->stringval) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("malformed vcpu information")); - goto error; - } - } - xmlXPathFreeObject(obj); - - /* Extract domain vcpu info */ - obj = xmlXPathEval(BAD_CAST "string(/domain/vcpu[1]/@cpuset)", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - /* Allow use on all CPUS */ - memset(def->cpumask, 1, QEMUD_CPUMASK_LEN); - } else { - char *set = (char *)obj->stringval; - memset(def->cpumask, 0, QEMUD_CPUMASK_LEN); - if (virParseCpuSet(conn, (const char **)&set, - 0, def->cpumask, - QEMUD_CPUMASK_LEN) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("malformed vcpu mask information")); - goto error; - } - } - xmlXPathFreeObject(obj); - - /* See if ACPI feature is requested */ - obj = xmlXPathEval(BAD_CAST "/domain/features/acpi", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) { - def->features |= QEMUD_FEATURE_ACPI; - } - xmlXPathFreeObject(obj); - - - /* See if we disable reboots */ - obj = xmlXPathEval(BAD_CAST "string(/domain/on_reboot)", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - def->noReboot = 0; - } else { - if (STREQ((char*)obj->stringval, "destroy")) - def->noReboot = 1; - else - def->noReboot = 0; - } - xmlXPathFreeObject(obj); - - /* See if we set clock to localtime */ - obj = xmlXPathEval(BAD_CAST "string(/domain/clock/@offset)", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - def->localtime = 0; - } else { - if (STREQ((char*)obj->stringval, "localtime")) - def->localtime = 1; - else - def->localtime = 0; - } - 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); - - /* Set a default OS type, since <type> is optional with bootloader */ - strcpy(def->os.type, "xen"); - } - xmlXPathFreeObject(obj); - - /* 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)) { - 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); - obj = NULL; - - 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) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - const char *defaultArch = virCapabilitiesDefaultGuestArch(driver->caps, def->os.type); - if (defaultArch == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("unsupported architecture")); - goto error; - } - if (strlen(defaultArch) >= (QEMUD_OS_TYPE_MAX_LEN-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("architecture type too long")); - goto error; - } - strcpy(def->os.arch, defaultArch); - } else { - if (strlen((const char *)obj->stringval) >= (QEMUD_OS_TYPE_MAX_LEN-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("architecture type too long")); - goto error; - } - strcpy(def->os.arch, (const char *)obj->stringval); - } - xmlXPathFreeObject(obj); - - obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1]/@machine)", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - const char *defaultMachine = virCapabilitiesDefaultGuestMachine(driver->caps, - def->os.type, - def->os.arch); - if (defaultMachine == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("unsupported architecture")); - goto error; - } - if (strlen(defaultMachine) >= (QEMUD_OS_MACHINE_MAX_LEN-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("machine type too long")); - goto error; - } - strcpy(def->os.machine, defaultMachine); - } else { - if (strlen((const char *)obj->stringval) >= (QEMUD_OS_MACHINE_MAX_LEN-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("architecture type too long")); - goto error; - } - strcpy(def->os.machine, (const char *)obj->stringval); - } - xmlXPathFreeObject(obj); - - - 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); - } - 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; - } - } - - obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - const char *type = qemudVirtTypeToString(def->virtType); - if (!type) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("unknown virt type")); - goto error; - } - const char *emulator = virCapabilitiesDefaultGuestEmulator(driver->caps, - def->os.type, - def->os.arch, - type); - if (!emulator) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("unsupported guest type")); - goto error; - } - strcpy(def->os.binary, emulator); - } else { - if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("emulator path too long")); - goto error; - } - strcpy(def->os.binary, (const char *)obj->stringval); - } - xmlXPathFreeObject(obj); - - obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics", ctxt); - if ((obj == NULL) || (obj->type != XPATH_NODESET) || - (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) { - def->graphicsType = QEMUD_GRAPHICS_NONE; - } else if ((prop = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "type"))) { - if (STREQ((char *)prop, "vnc")) { - xmlChar *vncport, *vnclisten; - def->graphicsType = QEMUD_GRAPHICS_VNC; - vncport = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "port"); - if (vncport) { - conv = NULL; - def->vncPort = strtoll((const char*)vncport, &conv, 10); - } else { - def->vncPort = -1; - } - vnclisten = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "listen"); - if (vnclisten && *vnclisten) - strncpy(def->vncListen, (char *)vnclisten, BR_INET_ADDR_MAXLEN-1); - else - strcpy(def->vncListen, driver->vncListen); - def->vncListen[BR_INET_ADDR_MAXLEN-1] = '\0'; - def->keymap = (char *) xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "keymap"); - xmlFree(vncport); - xmlFree(vnclisten); - } else if (STREQ((char *)prop, "sdl")) { - def->graphicsType = QEMUD_GRAPHICS_SDL; - } else { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("Unsupported graphics type %s"), prop); - goto error; - } - xmlFree(prop); - prop = NULL; - } - xmlXPathFreeObject(obj); - - /* analysis of the disk devices */ - obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { - for (i = 0; i < obj->nodesetval->nodeNr; i++) { - struct qemud_vm_disk_def *disk; - if (VIR_ALLOC(disk) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for disk string")); - goto error; - } - if (qemudParseDiskXML(conn, disk, obj->nodesetval->nodeTab[i]) < 0) { - VIR_FREE(disk); - goto error; - } - def->ndisks++; - if (i == 0) { - disk->next = NULL; - def->disks = disk; - } else { - struct qemud_vm_disk_def *ptr = def->disks; - while (ptr) { - if (!ptr->next || qemudDiskCompare(disk, ptr->next) < 0) { - disk->next = ptr->next; - ptr->next = disk; - break; - } - ptr = ptr->next; - } - } - } - } - xmlXPathFreeObject(obj); - obj = NULL; - - /* analysis of the character devices */ - if (qemudParseCharXMLDevices(conn, ctxt, - "/domain/devices/parallel", - &def->nparallels, - &def->parallels) < 0) - goto error; - if (qemudParseCharXMLDevices(conn, ctxt, - "/domain/devices/serial", - &def->nserials, - &def->serials) < 0) - goto error; - - /* - * If no serial devices were listed, then look for console - * devices which is the legacy syntax for the same thing - */ - if (def->nserials == 0) { - obj = xmlXPathEval(BAD_CAST "/domain/devices/console", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) { - struct qemud_vm_chr_def *chr; - if (VIR_ALLOC(chr) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", - _("failed to allocate space for char device")); - goto error; - } - - if (qemudParseCharXML(conn, chr, 0, obj->nodesetval->nodeTab[0]) < 0) { - VIR_FREE(chr); - goto error; - } - def->nserials = 1; - def->serials = chr; - } - xmlXPathFreeObject(obj); - } - - - /* analysis of the network devices */ - obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { - struct qemud_vm_net_def *prev = NULL; - for (i = 0; i < obj->nodesetval->nodeNr; i++) { - struct qemud_vm_net_def *net; - if (VIR_ALLOC(net) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for net string")); - goto error; - } - if (qemudParseInterfaceXML(conn, net, obj->nodesetval->nodeTab[i]) < 0) { - VIR_FREE(net); - goto error; - } - def->nnets++; - net->next = NULL; - if (i == 0) { - def->nets = net; - } else { - prev->next = net; - } - prev = net; - } - } - xmlXPathFreeObject(obj); - - /* analysis of the input devices */ - obj = xmlXPathEval(BAD_CAST "/domain/devices/input", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { - struct qemud_vm_input_def *prev = NULL; - for (i = 0; i < obj->nodesetval->nodeNr; i++) { - struct qemud_vm_input_def *input; - if (VIR_ALLOC(input) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for input string")); - goto error; - } - if (qemudParseInputXML(conn, def, input, obj->nodesetval->nodeTab[i]) < 0) { - VIR_FREE(input); - goto error; - } - /* Mouse + PS/2 is implicit with graphics, so don't store it */ - if (input->bus == QEMU_INPUT_BUS_PS2 && - input->type == QEMU_INPUT_TYPE_MOUSE) { - VIR_FREE(input); - continue; - } - def->ninputs++; - input->next = NULL; - if (def->inputs == NULL) { - def->inputs = input; - } else { - prev->next = input; - } - prev = input; - } - } - xmlXPathFreeObject(obj); - - /* Parse sound driver xml */ - obj = xmlXPathEval(BAD_CAST "/domain/devices/sound", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { - struct qemud_vm_sound_def *prev = NULL; - for (i = 0; i < obj->nodesetval->nodeNr; i++) { - - struct qemud_vm_sound_def *sound; - struct qemud_vm_sound_def *check = def->sounds; - int collision = 0; - if (VIR_ALLOC(sound) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for sound dev")); - goto error; - } - if (qemudParseSoundXML(conn, sound, - obj->nodesetval->nodeTab[i]) < 0) { - VIR_FREE(sound); - goto error; - } - - // Check that model type isn't already present in sound dev list - while(check) { - if (check->model == sound->model) { - collision = 1; - break; - } - check = check->next; - } - if (collision) { - VIR_FREE(sound); - continue; - } - - def->nsounds++; - sound->next = NULL; - if (def->sounds == NULL) { - def->sounds = sound; - } else { - prev->next = sound; - } - prev = sound; - } - } - xmlXPathFreeObject(obj); - obj = NULL; - - /* If graphics are enabled, there's an implicit PS2 mouse */ - if (def->graphicsType != QEMUD_GRAPHICS_NONE) { - int hasPS2mouse = 0; - struct qemud_vm_input_def *input = def->inputs; - while (input) { - if (input->type == QEMU_INPUT_TYPE_MOUSE && - input->bus == QEMU_INPUT_BUS_PS2) - hasPS2mouse = 1; - input = input->next; - } - - if (!hasPS2mouse) { - if (VIR_ALLOC(input) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for input string")); - goto error; - } - input->type = QEMU_INPUT_TYPE_MOUSE; - input->bus = QEMU_INPUT_BUS_PS2; - input->next = def->inputs; - def->inputs = input; - def->ninputs++; - } - } - - xmlXPathFreeContext(ctxt); - - return def; - - error: - VIR_FREE(prop); - xmlXPathFreeObject(obj); - xmlXPathFreeContext(ctxt); - qemudFreeVMDef(def); - return NULL; -} - static char * qemudNetworkIfaceConnect(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm, - struct qemud_vm_net_def *net, + int **tapfds, + int *ntapfds, + virDomainNetDefPtr net, int vlan) { virNetworkObjPtr network = NULL; @@ -2236,38 +553,37 @@ int err; int tapfd = -1; - if (net->type == QEMUD_NET_NETWORK) { - if (!(network = virNetworkFindByName(driver->networks, net->dst.network.name))) { + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (!(network = virNetworkFindByName(driver->networks, net->data.network.name))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("Network '%s' not found"), - net->dst.network.name); + net->data.network.name); goto error; } else if (network->def->bridge == NULL) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("Network '%s' not active"), - net->dst.network.name); + net->data.network.name); goto error; } brname = network->def->bridge; - if (net->dst.network.ifname[0] == '\0' || - STRPREFIX(net->dst.network.ifname, "vnet") || - strchr(net->dst.network.ifname, '%')) { - strcpy(net->dst.network.ifname, "vnet%d"); - } - ifname = net->dst.network.ifname; - } else if (net->type == QEMUD_NET_BRIDGE) { - brname = net->dst.bridge.brname; - if (net->dst.bridge.ifname[0] == '\0' || - STRPREFIX(net->dst.bridge.ifname, "vnet") || - strchr(net->dst.bridge.ifname, '%')) { - strcpy(net->dst.bridge.ifname, "vnet%d"); - } - ifname = net->dst.bridge.ifname; + } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { + brname = net->data.bridge.brname; } else { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("Network type %d is not supported"), net->type); goto error; } + + if (!net->ifname || + STRPREFIX(net->ifname, "vnet") || + strchr(net->ifname, '%')) { + VIR_FREE(net->ifname); + if (!(net->ifname = strdup("vnet%d"))) { + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + } + ifname = net->ifname; if (!driver->brctl && (err = brInit(&driver->brctl))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, @@ -2291,11 +607,10 @@ if (!(retval = strdup(tapfdstr))) goto no_memory; - if (VIR_REALLOC_N(vm->tapfds, vm->ntapfds+2) < 0) + if (VIR_REALLOC_N(*tapfds, (*ntapfds)+1) < 0) goto no_memory; - vm->tapfds[vm->ntapfds++] = tapfd; - vm->tapfds[vm->ntapfds] = -1; + (*tapfds)[(*ntapfds)++] = tapfd; return retval; @@ -2309,71 +624,71 @@ return NULL; } -static int qemudBuildCommandLineChrDevStr(struct qemud_vm_chr_def *dev, +static int qemudBuildCommandLineChrDevStr(virDomainChrDefPtr dev, char *buf, int buflen) { - switch (dev->srcType) { - case QEMUD_CHR_SRC_TYPE_NULL: + switch (dev->type) { + case VIR_DOMAIN_CHR_TYPE_NULL: strncpy(buf, "null", buflen); buf[buflen-1] = '\0'; break; - case QEMUD_CHR_SRC_TYPE_VC: + case VIR_DOMAIN_CHR_TYPE_VC: strncpy(buf, "vc", buflen); buf[buflen-1] = '\0'; break; - case QEMUD_CHR_SRC_TYPE_PTY: + case VIR_DOMAIN_CHR_TYPE_PTY: strncpy(buf, "pty", buflen); buf[buflen-1] = '\0'; break; - case QEMUD_CHR_SRC_TYPE_DEV: + case VIR_DOMAIN_CHR_TYPE_DEV: if (snprintf(buf, buflen, "%s", - dev->srcData.file.path) >= buflen) + dev->data.file.path) >= buflen) return -1; break; - case QEMUD_CHR_SRC_TYPE_FILE: + case VIR_DOMAIN_CHR_TYPE_FILE: if (snprintf(buf, buflen, "file:%s", - dev->srcData.file.path) >= buflen) + dev->data.file.path) >= buflen) return -1; break; - case QEMUD_CHR_SRC_TYPE_PIPE: + case VIR_DOMAIN_CHR_TYPE_PIPE: if (snprintf(buf, buflen, "pipe:%s", - dev->srcData.file.path) >= buflen) + dev->data.file.path) >= buflen) return -1; break; - case QEMUD_CHR_SRC_TYPE_STDIO: + case VIR_DOMAIN_CHR_TYPE_STDIO: strncpy(buf, "stdio", buflen); buf[buflen-1] = '\0'; break; - case QEMUD_CHR_SRC_TYPE_UDP: + case VIR_DOMAIN_CHR_TYPE_UDP: if (snprintf(buf, buflen, "udp:%s:%s@%s:%s", - dev->srcData.udp.connectHost, - dev->srcData.udp.connectService, - dev->srcData.udp.bindHost, - dev->srcData.udp.bindService) >= buflen) + dev->data.udp.connectHost, + dev->data.udp.connectService, + dev->data.udp.bindHost, + dev->data.udp.bindService) >= buflen) return -1; break; - case QEMUD_CHR_SRC_TYPE_TCP: + case VIR_DOMAIN_CHR_TYPE_TCP: if (snprintf(buf, buflen, "%s:%s:%s%s", - dev->srcData.tcp.protocol == QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET ? "telnet" : "tcp", - dev->srcData.tcp.host, - dev->srcData.tcp.service, - dev->srcData.tcp.listen ? ",listen" : "") >= buflen) + dev->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET ? "telnet" : "tcp", + dev->data.tcp.host, + dev->data.tcp.service, + dev->data.tcp.listen ? ",listen" : "") >= buflen) return -1; break; - case QEMUD_CHR_SRC_TYPE_UNIX: + case VIR_DOMAIN_CHR_TYPE_UNIX: if (snprintf(buf, buflen, "unix:%s%s", - dev->srcData.nix.path, - dev->srcData.nix.listen ? ",listen" : "") >= buflen) + dev->data.nix.path, + dev->data.nix.listen ? ",listen" : "") >= buflen) return -1; break; } @@ -2387,29 +702,26 @@ */ int qemudBuildCommandLine(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm, - char ***retargv) { + virDomainObjPtr vm, + int qemuCmdFlags, + char ***retargv, + int **tapfds, + int *ntapfds, + const char *migrateFrom) { int i; char memory[50]; char vcpus[50]; - char boot[QEMUD_MAX_BOOT_DEVS+1]; - struct qemud_vm_disk_def *disk = vm->def->disks; - struct qemud_vm_net_def *net = vm->def->nets; - struct qemud_vm_input_def *input = vm->def->inputs; - struct qemud_vm_sound_def *sound = vm->def->sounds; - struct qemud_vm_chr_def *serial = vm->def->serials; - struct qemud_vm_chr_def *parallel = vm->def->parallels; + char boot[VIR_DOMAIN_BOOT_LAST]; + virDomainDiskDefPtr disk = vm->def->disks; + virDomainNetDefPtr net = vm->def->nets; + virDomainInputDefPtr input = vm->def->inputs; + virDomainSoundDefPtr sound = vm->def->sounds; + virDomainChrDefPtr serial = vm->def->serials; + virDomainChrDefPtr parallel = vm->def->parallels; struct utsname ut; int disableKQEMU = 0; int qargc = 0, qarga = 0; char **qargv = NULL; - - if (vm->qemuVersion == 0) { - if (qemudExtractVersionInfo(vm->def->os.binary, - &(vm->qemuVersion), - &(vm->qemuCmdFlags)) < 0) - return -1; - } uname(&ut); @@ -2425,9 +737,9 @@ * 2. Guest is 'qemu' * 3. The qemu binary has the -no-kqemu flag */ - if ((vm->qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) && + if ((qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) && STREQ(ut.machine, vm->def->os.arch) && - vm->def->virtType == QEMUD_VIRT_QEMU) + vm->def->virtType == VIR_DOMAIN_VIRT_QEMU) disableKQEMU = 1; #define ADD_ARG_SPACE \ @@ -2453,10 +765,10 @@ } while (0) snprintf(memory, sizeof(memory), "%lu", vm->def->memory/1024); - snprintf(vcpus, sizeof(vcpus), "%d", vm->def->vcpus); + snprintf(vcpus, sizeof(vcpus), "%lu", vm->def->vcpus); - ADD_ARG_LIT(vm->def->os.binary); + ADD_ARG_LIT(vm->def->emulator); ADD_ARG_LIT("-S"); ADD_ARG_LIT("-M"); ADD_ARG_LIT(vm->def->os.machine); @@ -2467,7 +779,7 @@ ADD_ARG_LIT("-smp"); ADD_ARG_LIT(vcpus); - if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_NAME) { + if (qemuCmdFlags & QEMUD_CMD_FLAG_NAME) { ADD_ARG_LIT("-name"); ADD_ARG_LIT(vm->def->name); } @@ -2478,7 +790,7 @@ * if you ask for nographic. So we have to make sure we override * these defaults ourselves... */ - if (vm->def->graphicsType == QEMUD_GRAPHICS_NONE) + if (!vm->def->graphics) ADD_ARG_LIT("-nographic"); ADD_ARG_LIT("-monitor"); @@ -2487,26 +799,26 @@ if (vm->def->localtime) ADD_ARG_LIT("-localtime"); - if ((vm->qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) && - vm->def->noReboot) + if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) && + vm->def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART) ADD_ARG_LIT("-no-reboot"); - if (!(vm->def->features & QEMUD_FEATURE_ACPI)) + if (!(vm->def->features & (1 << VIR_DOMAIN_FEATURE_ACPI))) ADD_ARG_LIT("-no-acpi"); - if (!vm->def->os.bootloader[0]) { + if (!vm->def->os.bootloader) { for (i = 0 ; i < vm->def->os.nBootDevs ; i++) { switch (vm->def->os.bootDevs[i]) { - case QEMUD_BOOT_CDROM: + case VIR_DOMAIN_BOOT_CDROM: boot[i] = 'd'; break; - case QEMUD_BOOT_FLOPPY: + case VIR_DOMAIN_BOOT_FLOPPY: boot[i] = 'a'; break; - case QEMUD_BOOT_DISK: + case VIR_DOMAIN_BOOT_DISK: boot[i] = 'c'; break; - case QEMUD_BOOT_NET: + case VIR_DOMAIN_BOOT_NET: boot[i] = 'n'; break; default: @@ -2518,15 +830,15 @@ ADD_ARG_LIT("-boot"); ADD_ARG_LIT(boot); - if (vm->def->os.kernel[0]) { + if (vm->def->os.kernel) { ADD_ARG_LIT("-kernel"); ADD_ARG_LIT(vm->def->os.kernel); } - if (vm->def->os.initrd[0]) { + if (vm->def->os.initrd) { ADD_ARG_LIT("-initrd"); ADD_ARG_LIT(vm->def->os.initrd); } - if (vm->def->os.cmdline[0]) { + if (vm->def->os.cmdline) { ADD_ARG_LIT("-append"); ADD_ARG_LIT(vm->def->os.cmdline); } @@ -2536,20 +848,20 @@ } /* If QEMU supports -drive param instead of old -hda, -hdb, -cdrom .. */ - if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) { + if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) { int bootCD = 0, bootFloppy = 0, bootDisk = 0; /* If QEMU supports boot=on for -drive param... */ - if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_BOOT) { + if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_BOOT) { for (i = 0 ; i < vm->def->os.nBootDevs ; i++) { switch (vm->def->os.bootDevs[i]) { - case QEMUD_BOOT_CDROM: + case VIR_DOMAIN_BOOT_CDROM: bootCD = 1; break; - case QEMUD_BOOT_FLOPPY: + case VIR_DOMAIN_BOOT_FLOPPY: bootFloppy = 1; break; - case QEMUD_BOOT_DISK: + case VIR_DOMAIN_BOOT_DISK: bootDisk = 1; break; } @@ -2561,6 +873,7 @@ const char *media = NULL; int bootable = 0; int idx = virDiskNameToIndex(disk->dst); + const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus); if (idx < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, @@ -2568,26 +881,26 @@ goto error; } - if (disk->device == QEMUD_DISK_CDROM) + if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) media = "media=cdrom,"; switch (disk->device) { - case QEMUD_DISK_CDROM: + case VIR_DOMAIN_DISK_DEVICE_CDROM: bootable = bootCD; bootCD = 0; break; - case QEMUD_DISK_FLOPPY: + case VIR_DOMAIN_DISK_DEVICE_FLOPPY: bootable = bootFloppy; bootFloppy = 0; break; - case QEMUD_DISK_DISK: + case VIR_DOMAIN_DISK_DEVICE_DISK: bootable = bootDisk; bootDisk = 0; break; } snprintf(opt, PATH_MAX, "file=%s,if=%s,%sindex=%d%s", - disk->src, qemudBusIdToName(disk->bus, 1), + disk->src, bus, media ? media : "", idx, bootable ? ",boot=on" : ""); @@ -2602,8 +915,8 @@ char file[PATH_MAX]; if (STREQ(disk->dst, "hdc") && - disk->device == QEMUD_DISK_CDROM) { - if (disk->src[0]) { + disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + if (disk->src) { snprintf(dev, NAME_MAX, "-%s", "cdrom"); } else { disk = disk->next; @@ -2643,7 +956,8 @@ net->mac[2], net->mac[3], net->mac[4], net->mac[5], vlan, - (net->model[0] ? ",model=" : ""), net->model) >= sizeof(nic)) + (net->model ? ",model=" : ""), + (net->model ? net->model : "")) >= sizeof(nic)) goto error; ADD_ARG_LIT("-net"); @@ -2651,22 +965,24 @@ ADD_ARG_LIT("-net"); switch (net->type) { - case QEMUD_NET_NETWORK: - case QEMUD_NET_BRIDGE: + case VIR_DOMAIN_NET_TYPE_NETWORK: + case VIR_DOMAIN_NET_TYPE_BRIDGE: { - char *tap = qemudNetworkIfaceConnect(conn, driver, vm, net, vlan); + char *tap = qemudNetworkIfaceConnect(conn, driver, + tapfds, ntapfds, + net, vlan); if (tap == NULL) goto error; ADD_ARG(tap); break; } - case QEMUD_NET_ETHERNET: + case VIR_DOMAIN_NET_TYPE_ETHERNET: { char arg[PATH_MAX]; if (snprintf(arg, PATH_MAX-1, "tap,ifname=%s,script=%s,vlan=%d", - net->dst.ethernet.ifname, - net->dst.ethernet.script, + net->ifname, + net->data.ethernet.script, vlan) >= (PATH_MAX-1)) goto error; @@ -2674,27 +990,27 @@ } break; - case QEMUD_NET_CLIENT: - case QEMUD_NET_SERVER: - case QEMUD_NET_MCAST: + case VIR_DOMAIN_NET_TYPE_CLIENT: + case VIR_DOMAIN_NET_TYPE_SERVER: + case VIR_DOMAIN_NET_TYPE_MCAST: { char arg[PATH_MAX]; const char *mode = NULL; switch (net->type) { - case QEMUD_NET_CLIENT: + case VIR_DOMAIN_NET_TYPE_CLIENT: mode = "connect"; break; - case QEMUD_NET_SERVER: + case VIR_DOMAIN_NET_TYPE_SERVER: mode = "listen"; break; - case QEMUD_NET_MCAST: + case VIR_DOMAIN_NET_TYPE_MCAST: mode = "mcast"; break; } if (snprintf(arg, PATH_MAX-1, "socket,%s=%s:%d,vlan=%d", mode, - net->dst.socket.address, - net->dst.socket.port, + net->data.socket.address, + net->data.socket.port, vlan) >= (PATH_MAX-1)) goto error; @@ -2702,7 +1018,7 @@ } break; - case QEMUD_NET_USER: + case VIR_DOMAIN_NET_TYPE_USER: default: { char arg[PATH_MAX]; @@ -2754,19 +1070,20 @@ ADD_ARG_LIT("-usb"); while (input) { - if (input->bus == QEMU_INPUT_BUS_USB) { + if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) { ADD_ARG_LIT("-usbdevice"); - ADD_ARG_LIT(input->type == QEMU_INPUT_TYPE_MOUSE ? "mouse" : "tablet"); + ADD_ARG_LIT(input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ? "mouse" : "tablet"); } input = input->next; } - if (vm->def->graphicsType == QEMUD_GRAPHICS_VNC) { + if (vm->def->graphics && + vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { char vncdisplay[PATH_MAX]; int ret; - if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) { + if (qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) { char options[PATH_MAX] = ""; if (driver->vncTLS) { strcat(options, ",tls"); @@ -2780,25 +1097,24 @@ options[sizeof(options)-1] = '\0'; } ret = snprintf(vncdisplay, sizeof(vncdisplay), "%s:%d%s", - vm->def->vncListen, - vm->def->vncActivePort - 5900, + vm->def->graphics->data.vnc.listenAddr, + vm->def->graphics->data.vnc.port - 5900, options); } else { ret = snprintf(vncdisplay, sizeof(vncdisplay), "%d", - vm->def->vncActivePort - 5900); + vm->def->graphics->data.vnc.port - 5900); } if (ret < 0 || ret >= (int)sizeof(vncdisplay)) goto error; ADD_ARG_LIT("-vnc"); ADD_ARG_LIT(vncdisplay); - if (vm->def->keymap) { + if (vm->def->graphics->data.vnc.keymap) { ADD_ARG_LIT("-k"); - ADD_ARG_LIT(vm->def->keymap); + ADD_ARG_LIT(vm->def->graphics->data.vnc.keymap); } - } else if (vm->def->graphicsType == QEMUD_GRAPHICS_NONE) { - /* Nada - we added -nographic earlier in this function */ - } else { + } else if (vm->def->graphics && + vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) { /* SDL is the default. no args needed */ } @@ -2810,7 +1126,7 @@ goto no_memory; while(sound && size > 0) { - const char *model = qemudSoundModelToString(sound->model); + const char *model = virDomainSoundModelTypeToString(sound->model); if (!model) { VIR_FREE(modstr); qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, @@ -2827,9 +1143,9 @@ ADD_ARG(modstr); } - if (vm->migrateFrom[0]) { + if (migrateFrom) { ADD_ARG_LIT("-incoming"); - ADD_ARG_LIT(vm->migrateFrom); + ADD_ARG_LIT(migrateFrom); } ADD_ARG(NULL); @@ -2841,12 +1157,12 @@ qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for argv string")); error: - if (vm->tapfds) { - for (i = 0; vm->tapfds[i] != -1; i++) - close(vm->tapfds[i]); - VIR_FREE(vm->tapfds); - vm->tapfds = NULL; - vm->ntapfds = 0; + if (tapfds && + *tapfds) { + for (i = 0; ntapfds; i++) + close((*tapfds)[i]); + VIR_FREE(*tapfds); + *ntapfds = 0; } if (qargv) { for (i = 0 ; i < qargc ; i++) @@ -2861,755 +1177,4 @@ } -/* Save a guest's config data into a persistent file */ -static int qemudSaveConfig(virConnectPtr conn, - struct qemud_driver *driver, - struct qemud_vm *vm, - struct qemud_vm_def *def) { - char *xml; - int fd = -1, ret = -1; - int towrite; - - if (!(xml = qemudGenerateXML(conn, driver, vm, def, 0))) - return -1; - - if ((fd = open(vm->configFile, - O_WRONLY | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR )) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot create config file %s: %s"), - vm->configFile, strerror(errno)); - goto cleanup; - } - - towrite = strlen(xml); - if (safewrite(fd, xml, towrite) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot write config file %s: %s"), - vm->configFile, strerror(errno)); - goto cleanup; - } - - if (close(fd) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot save config file %s: %s"), - vm->configFile, strerror(errno)); - goto cleanup; - } - - ret = 0; - - cleanup: - if (fd != -1) - close(fd); - - VIR_FREE(xml); - - return ret; -} - -struct qemud_vm_device_def * -qemudParseVMDeviceDef(virConnectPtr conn, - const struct qemud_vm_def *def, - const char *xmlStr) -{ - xmlDocPtr xml; - xmlNodePtr node; - struct qemud_vm_device_def *dev; - - if (VIR_ALLOC(dev) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); - return NULL; - } - - if (!(xml = xmlReadDoc(BAD_CAST xmlStr, "device.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, NULL); - goto error; - } - - node = xmlDocGetRootElement(xml); - if (node == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, - "%s", _("missing root element")); - goto error; - } - if (xmlStrEqual(node->name, BAD_CAST "disk")) { - dev->type = QEMUD_DEVICE_DISK; - qemudParseDiskXML(conn, &(dev->data.disk), node); - } else if (xmlStrEqual(node->name, BAD_CAST "interface")) { - dev->type = QEMUD_DEVICE_NET; - qemudParseInterfaceXML(conn, &(dev->data.net), node); - } else if (xmlStrEqual(node->name, BAD_CAST "input")) { - dev->type = QEMUD_DEVICE_DISK; - qemudParseInputXML(conn, def, &(dev->data.input), node); - } else if (xmlStrEqual(node->name, BAD_CAST "sound")) { - dev->type = QEMUD_DEVICE_SOUND; - qemudParseSoundXML(conn, &(dev->data.sound), node); - } else { - qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, - "%s", _("unknown device type")); - goto error; - } - - xmlFreeDoc(xml); - - return dev; - - error: - if (xml) xmlFreeDoc(xml); - VIR_FREE(dev); - return NULL; -} - -struct qemud_vm_def * -qemudParseVMDef(virConnectPtr conn, - struct qemud_driver *driver, - const char *xmlStr, - const char *displayName) { - xmlDocPtr xml; - struct qemud_vm_def *def = NULL; - - if (!(xml = xmlReadDoc(BAD_CAST xmlStr, displayName ? displayName : "domain.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, NULL); - return NULL; - } - - def = qemudParseXML(conn, driver, xml); - - xmlFreeDoc(xml); - - return def; -} - -struct qemud_vm * -qemudAssignVMDef(virConnectPtr conn, - struct qemud_driver *driver, - struct qemud_vm_def *def) -{ - struct qemud_vm *vm = NULL; - - if ((vm = qemudFindVMByName(driver, def->name))) { - if (!qemudIsActiveVM(vm)) { - qemudFreeVMDef(vm->def); - vm->def = def; - } else { - if (vm->newDef) - qemudFreeVMDef(vm->newDef); - vm->newDef = def; - } - /* Reset version, because the emulator path might have changed */ - vm->qemuVersion = 0; - vm->qemuCmdFlags = 0; - return vm; - } - - if (VIR_ALLOC(vm) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for vm string")); - return NULL; - } - - vm->stdin = -1; - vm->stdout = -1; - vm->stderr = -1; - vm->monitor = -1; - vm->pid = -1; - vm->id = -1; - vm->state = VIR_DOMAIN_SHUTOFF; - vm->def = def; - vm->next = driver->vms; - - driver->vms = vm; - driver->ninactivevms++; - - return vm; -} - -void -qemudRemoveInactiveVM(struct qemud_driver *driver, - struct qemud_vm *vm) -{ - struct qemud_vm *prev = NULL, *curr; - - curr = driver->vms; - while (curr != vm) { - prev = curr; - curr = curr->next; - } - - if (curr) { - if (prev) - prev->next = curr->next; - else - driver->vms = curr->next; - - driver->ninactivevms--; - } - - qemudFreeVM(vm); -} - -int -qemudSaveVMDef(virConnectPtr conn, - struct qemud_driver *driver, - struct qemud_vm *vm, - struct qemud_vm_def *def) { - if (vm->configFile[0] == '\0') { - int err; - - if ((err = virFileMakePath(driver->configDir))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot create config directory %s: %s"), - driver->configDir, strerror(err)); - return -1; - } - - if (virFileBuildPath(driver->configDir, def->name, ".xml", - vm->configFile, PATH_MAX) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot construct config file path")); - return -1; - } - - if (virFileBuildPath(driver->autostartDir, def->name, ".xml", - vm->autostartLink, PATH_MAX) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot construct autostart link path")); - vm->configFile[0] = '\0'; - return -1; - } - } - - return qemudSaveConfig(conn, driver, vm, def); -} - - -static struct qemud_vm * -qemudLoadConfig(struct qemud_driver *driver, - const char *file, - const char *path, - const char *xml, - const char *autostartLink) { - struct qemud_vm_def *def; - struct qemud_vm *vm; - - if (!(def = qemudParseVMDef(NULL, driver, xml, file))) { - virErrorPtr err = virGetLastError(); - qemudLog(QEMUD_WARN, _("Error parsing QEMU guest config '%s' : %s"), - path, (err ? err->message : - _("BUG: unknown error - please report it\n"))); - return NULL; - } - - if (!virFileMatchesNameSuffix(file, def->name, ".xml")) { - qemudLog(QEMUD_WARN, - _("QEMU guest config filename '%s'" - " does not match guest name '%s'"), - path, def->name); - qemudFreeVMDef(def); - return NULL; - } - - if (!(vm = qemudAssignVMDef(NULL, driver, def))) { - qemudLog(QEMUD_WARN, - _("Failed to load QEMU guest config '%s': out of memory"), - path); - qemudFreeVMDef(def); - return NULL; - } - - strncpy(vm->configFile, path, PATH_MAX); - vm->configFile[PATH_MAX-1] = '\0'; - - strncpy(vm->autostartLink, autostartLink, PATH_MAX); - vm->autostartLink[PATH_MAX-1] = '\0'; - - vm->autostart = virFileLinkPointsTo(vm->autostartLink, vm->configFile); - - return vm; -} - -static -int qemudScanConfigDir(struct qemud_driver *driver, - const char *configDir, - const char *autostartDir) { - DIR *dir; - struct dirent *entry; - - if (!(dir = opendir(configDir))) { - if (errno == ENOENT) - return 0; - qemudLog(QEMUD_ERR, _("Failed to open dir '%s': %s"), - configDir, strerror(errno)); - return -1; - } - - while ((entry = readdir(dir))) { - char *xml; - char path[PATH_MAX]; - char autostartLink[PATH_MAX]; - - if (entry->d_name[0] == '.') - continue; - - if (!virFileHasSuffix(entry->d_name, ".xml")) - continue; - - if (virFileBuildPath(configDir, entry->d_name, NULL, path, PATH_MAX) < 0) { - qemudLog(QEMUD_WARN, _("Config filename '%s/%s' is too long"), - configDir, entry->d_name); - continue; - } - - if (virFileBuildPath(autostartDir, entry->d_name, NULL, - autostartLink, PATH_MAX) < 0) { - qemudLog(QEMUD_WARN, _("Autostart link path '%s/%s' is too long"), - autostartDir, entry->d_name); - continue; - } - - if (virFileReadAll(path, QEMUD_MAX_XML_LEN, &xml) < 0) - continue; - - qemudLoadConfig(driver, entry->d_name, path, xml, autostartLink); - - VIR_FREE(xml); - } - - closedir(dir); - - return 0; -} - -/* Scan for all guest and network config files */ -int qemudScanConfigs(struct qemud_driver *driver) { - if (qemudScanConfigDir(driver, driver->configDir, driver->autostartDir) < 0) - return -1; - - return 0; -} - -static int qemudGenerateXMLChar(virBufferPtr buf, - const struct qemud_vm_chr_def *dev, - const char *type) -{ - const char *const types[] = { - "null", - "vc", - "pty", - "dev", - "file", - "pipe", - "stdio", - "udp", - "tcp", - "unix" - }; - verify_true(ARRAY_CARDINALITY(types) == QEMUD_CHR_SRC_TYPE_LAST); - - /* Compat with legacy <console tty='/dev/pts/5'/> syntax */ - if (STREQ(type, "console") && - dev->srcType == QEMUD_CHR_SRC_TYPE_PTY && - dev->srcData.file.path[0] != '\0') { - virBufferVSprintf(buf, " <%s type='%s' tty='%s'>\n", - type, types[dev->srcType], - dev->srcData.file.path); - } else { - virBufferVSprintf(buf, " <%s type='%s'>\n", - type, types[dev->srcType]); - } - - switch (dev->srcType) { - case QEMUD_CHR_SRC_TYPE_NULL: - case QEMUD_CHR_SRC_TYPE_VC: - case QEMUD_CHR_SRC_TYPE_STDIO: - /* nada */ - break; - - case QEMUD_CHR_SRC_TYPE_PTY: - case QEMUD_CHR_SRC_TYPE_DEV: - case QEMUD_CHR_SRC_TYPE_FILE: - case QEMUD_CHR_SRC_TYPE_PIPE: - if (dev->srcType != QEMUD_CHR_SRC_TYPE_PTY || - dev->srcData.file.path[0]) { - virBufferVSprintf(buf, " <source path='%s'/>\n", - dev->srcData.file.path); - } - break; - - case QEMUD_CHR_SRC_TYPE_UDP: - if (dev->srcData.udp.bindService[0] != '\0' && - dev->srcData.udp.bindHost[0] != '\0') { - virBufferVSprintf(buf, " <source mode='bind' host='%s' service='%s'/>\n", - dev->srcData.udp.bindHost, - dev->srcData.udp.bindService); - } else if (dev->srcData.udp.bindHost[0] !='\0') { - virBufferVSprintf(buf, " <source mode='bind' host='%s'/>\n", - dev->srcData.udp.bindHost); - } else if (dev->srcData.udp.bindService[0] != '\0') { - virBufferVSprintf(buf, " <source mode='bind' service='%s'/>\n", - dev->srcData.udp.bindService); - } - - if (dev->srcData.udp.connectService[0] != '\0' && - dev->srcData.udp.connectHost[0] != '\0') { - virBufferVSprintf(buf, " <source mode='connect' host='%s' service='%s'/>\n", - dev->srcData.udp.connectHost, - dev->srcData.udp.connectService); - } else if (dev->srcData.udp.connectHost[0] != '\0') { - virBufferVSprintf(buf, " <source mode='connect' host='%s'/>\n", - dev->srcData.udp.connectHost); - } else if (dev->srcData.udp.connectService[0] != '\0') { - virBufferVSprintf(buf, " <source mode='connect' service='%s'/>\n", - dev->srcData.udp.connectService); - } - break; - - case QEMUD_CHR_SRC_TYPE_TCP: - virBufferVSprintf(buf, " <source mode='%s' host='%s' service='%s'/>\n", - dev->srcData.tcp.listen ? "bind" : "connect", - dev->srcData.tcp.host, - dev->srcData.tcp.service); - virBufferVSprintf(buf, " <protocol type='%s'/>\n", - dev->srcData.tcp.protocol == QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET - ? "telnet" : "raw"); - break; - - case QEMUD_CHR_SRC_TYPE_UNIX: - virBufferVSprintf(buf, " <source mode='%s' path='%s'/>\n", - dev->srcData.nix.listen ? "bind" : "connect", - dev->srcData.nix.path); - break; - } - - virBufferVSprintf(buf, " <target port='%d'/>\n", - dev->dstPort); - - virBufferVSprintf(buf, " </%s>\n", - type); - - return 0; -} - - -/* Generate an XML document describing the guest's configuration */ -char *qemudGenerateXML(virConnectPtr conn, - struct qemud_driver *driver ATTRIBUTE_UNUSED, - struct qemud_vm *vm, - struct qemud_vm_def *def, - int live) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - unsigned char *uuid; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - const struct qemud_vm_disk_def *disk; - const struct qemud_vm_net_def *net; - const struct qemud_vm_input_def *input; - const struct qemud_vm_sound_def *sound; - const struct qemud_vm_chr_def *chr; - const char *type = NULL, *tmp; - int n, allones = 1; - - if (!(type = qemudVirtTypeToString(def->virtType))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("unexpected domain type %d"), def->virtType); - goto cleanup; - } - - if (qemudIsActiveVM(vm) && live) - virBufferVSprintf(&buf, "<domain type='%s' id='%d'>\n", type, vm->id); - else - virBufferVSprintf(&buf, "<domain type='%s'>\n", type); - - virBufferVSprintf(&buf, " <name>%s</name>\n", def->name); - - uuid = def->uuid; - virUUIDFormat(uuid, uuidstr); - virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr); - - virBufferVSprintf(&buf, " <memory>%lu</memory>\n", def->maxmem); - virBufferVSprintf(&buf, " <currentMemory>%lu</currentMemory>\n", def->memory); - - for (n = 0 ; n < QEMUD_CPUMASK_LEN ; n++) - if (def->cpumask[n] != 1) - allones = 0; - - if (allones) { - virBufferVSprintf(&buf, " <vcpu>%d</vcpu>\n", def->vcpus); - } else { - char *cpumask = NULL; - if ((cpumask = virSaveCpuSet(conn, def->cpumask, QEMUD_CPUMASK_LEN)) == NULL) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("allocating cpu mask")); - goto cleanup; - } - virBufferVSprintf(&buf, " <vcpu cpuset='%s'>%d</vcpu>\n", cpumask, def->vcpus); - VIR_FREE(cpumask); - } - - if (def->os.bootloader[0]) - virBufferVSprintf(&buf, " <bootloader>%s</bootloader>\n", def->os.bootloader); - virBufferAddLit(&buf, " <os>\n"); - - if (def->virtType == QEMUD_VIRT_QEMU) - virBufferVSprintf(&buf, " <type arch='%s' machine='%s'>%s</type>\n", - def->os.arch, def->os.machine, def->os.type); - else - virBufferVSprintf(&buf, " <type>%s</type>\n", def->os.type); - - 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); - } - } - - virBufferAddLit(&buf, " </os>\n"); - - if (def->features & QEMUD_FEATURE_ACPI) { - virBufferAddLit(&buf, " <features>\n"); - virBufferAddLit(&buf, " <acpi/>\n"); - virBufferAddLit(&buf, " </features>\n"); - } - - virBufferVSprintf(&buf, " <clock offset='%s'/>\n", def->localtime ? "localtime" : "utc"); - - virBufferAddLit(&buf, " <on_poweroff>destroy</on_poweroff>\n"); - if (def->noReboot) - virBufferAddLit(&buf, " <on_reboot>destroy</on_reboot>\n"); - else - virBufferAddLit(&buf, " <on_reboot>restart</on_reboot>\n"); - - virBufferAddLit(&buf, " <on_crash>destroy</on_crash>\n"); - virBufferAddLit(&buf, " <devices>\n"); - - virBufferVSprintf(&buf, " <emulator>%s</emulator>\n", def->os.binary); - - disk = def->disks; - while (disk) { - const char *types[] = { - "block", - "file", - }; - const char *typeAttrs[] = { - "dev", - "file", - }; - const char *devices[] = { - "disk", - "cdrom", - "floppy", - }; - virBufferVSprintf(&buf, " <disk type='%s' device='%s'>\n", - types[disk->type], devices[disk->device]); - - if (disk->src[0]) - virBufferVSprintf(&buf, " <source %s='%s'/>\n", - typeAttrs[disk->type], disk->src); - - virBufferVSprintf(&buf, " <target dev='%s' bus='%s'/>\n", - disk->dst, qemudBusIdToName(disk->bus, 0)); - - if (disk->readonly) - virBufferAddLit(&buf, " <readonly/>\n"); - - virBufferAddLit(&buf, " </disk>\n"); - - disk = disk->next; - } - - net = def->nets; - while (net) { - const char *types[] = { - "user", - "ethernet", - "server", - "client", - "mcast", - "network", - "bridge", - }; - virBufferVSprintf(&buf, " <interface type='%s'>\n", - types[net->type]); - - virBufferVSprintf(&buf, " <mac address='%02x:%02x:%02x:%02x:%02x:%02x'/>\n", - net->mac[0], net->mac[1], net->mac[2], - net->mac[3], net->mac[4], net->mac[5]); - - switch (net->type) { - case QEMUD_NET_NETWORK: - virBufferVSprintf(&buf, " <source network='%s'/>\n", net->dst.network.name); - - if (net->dst.network.ifname[0] != '\0') - virBufferVSprintf(&buf, " <target dev='%s'/>\n", net->dst.network.ifname); - break; - - case QEMUD_NET_ETHERNET: - if (net->dst.ethernet.ifname[0] != '\0') - virBufferVSprintf(&buf, " <target dev='%s'/>\n", net->dst.ethernet.ifname); - if (net->dst.ethernet.script[0] != '\0') - virBufferVSprintf(&buf, " <script path='%s'/>\n", net->dst.ethernet.script); - break; - - case QEMUD_NET_BRIDGE: - virBufferVSprintf(&buf, " <source bridge='%s'/>\n", net->dst.bridge.brname); - if (net->dst.bridge.ifname[0] != '\0') - virBufferVSprintf(&buf, " <target dev='%s'/>\n", net->dst.bridge.ifname); - break; - - case QEMUD_NET_SERVER: - case QEMUD_NET_CLIENT: - case QEMUD_NET_MCAST: - if (net->dst.socket.address[0] != '\0') - virBufferVSprintf(&buf, " <source address='%s' port='%d'/>\n", - net->dst.socket.address, net->dst.socket.port); - else - virBufferVSprintf(&buf, " <source port='%d'/>\n", - net->dst.socket.port); - } - - if (net->model && net->model[0] != '\0') { - virBufferVSprintf(&buf, " <model type='%s'/>\n", - net->model); - } - - virBufferAddLit(&buf, " </interface>\n"); - - net = net->next; - } - - chr = def->serials; - while (chr) { - if (qemudGenerateXMLChar(&buf, chr, "serial") < 0) - goto no_memory; - - chr = chr->next; - } - - chr = def->parallels; - while (chr) { - if (qemudGenerateXMLChar(&buf, chr, "parallel") < 0) - goto no_memory; - - chr = chr->next; - } - - /* First serial device is the primary console */ - if (def->nserials > 0 && - qemudGenerateXMLChar(&buf, def->serials, "console") < 0) - goto no_memory; - - input = def->inputs; - while (input) { - if (input->bus == QEMU_INPUT_BUS_USB) - virBufferVSprintf(&buf, " <input type='%s' bus='usb'/>\n", - input->type == QEMU_INPUT_TYPE_MOUSE ? "mouse" : "tablet"); - input = input->next; - } - /* If graphics is enable, add implicit mouse */ - if (def->graphicsType != QEMUD_GRAPHICS_NONE) - virBufferVSprintf(&buf, " <input type='mouse' bus='%s'/>\n", - STREQ(def->os.type, "hvm") ? "ps2" : "xen"); - - switch (def->graphicsType) { - case QEMUD_GRAPHICS_VNC: - virBufferAddLit(&buf, " <graphics type='vnc'"); - - if (def->vncPort) - virBufferVSprintf(&buf, " port='%d'", - qemudIsActiveVM(vm) && live ? def->vncActivePort : def->vncPort); - - if (def->vncListen[0]) - virBufferVSprintf(&buf, " listen='%s'", - def->vncListen); - - if (def->keymap) - virBufferVSprintf(&buf, " keymap='%s'", - def->keymap); - - virBufferAddLit(&buf, "/>\n"); - break; - - case QEMUD_GRAPHICS_SDL: - virBufferAddLit(&buf, " <graphics type='sdl'/>\n"); - break; - - case QEMUD_GRAPHICS_NONE: - default: - break; - } - - sound = def->sounds; - while(sound) { - const char *model = qemudSoundModelToString(sound->model); - if (!model) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("invalid sound model")); - goto cleanup; - } - virBufferVSprintf(&buf, " <sound model='%s'/>\n", model); - sound = sound->next; - } - - virBufferAddLit(&buf, " </devices>\n"); - virBufferAddLit(&buf, "</domain>\n"); - - if (virBufferError(&buf)) - goto no_memory; - - return virBufferContentAndReset(&buf); - - no_memory: - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, - "%s", _("failed to generate XML: out of memory")); - cleanup: - tmp = virBufferContentAndReset(&buf); - VIR_FREE(tmp); - return NULL; -} - - -int qemudDeleteConfig(virConnectPtr conn, - struct qemud_driver *driver ATTRIBUTE_UNUSED, - const char *configFile, - const char *name) { - if (!configFile[0]) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("no config file for %s"), name); - return -1; - } - - if (unlink(configFile) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot remove config for %s"), name); - return -1; - } - - return 0; -} - #endif /* WITH_QEMU */ diff -r 8b6e9b6cbaa5 src/qemu_conf.h --- a/src/qemu_conf.h Tue Jul 08 15:26:54 2008 +0100 +++ b/src/qemu_conf.h Tue Jul 08 15:29:16 2008 +0100 @@ -29,217 +29,15 @@ #ifdef WITH_QEMU #include "internal.h" +#include "iptables.h" #include "bridge.h" -#include "iptables.h" #include "capabilities.h" #include "network_conf.h" -#include <netinet/in.h> -#include <sched.h> +#include "domain_conf.h" #define qemudDebug(fmt, ...) do {} while(0) -/* Different types of QEMU acceleration possible */ -enum qemud_vm_virt_type { - QEMUD_VIRT_QEMU, - QEMUD_VIRT_KQEMU, - QEMUD_VIRT_KVM, -}; - -/* Two types of disk backends */ -enum qemud_vm_disk_type { - QEMUD_DISK_BLOCK, - QEMUD_DISK_FILE -}; - -/* Three types of disk frontend */ -enum qemud_vm_disk_device { - QEMUD_DISK_DISK, - QEMUD_DISK_CDROM, - QEMUD_DISK_FLOPPY, -}; - -enum qemud_vm_disk_bus { - QEMUD_DISK_BUS_IDE, - QEMUD_DISK_BUS_FDC, - QEMUD_DISK_BUS_SCSI, - QEMUD_DISK_BUS_VIRTIO, - QEMUD_DISK_BUS_XEN, - - QEMUD_DISK_BUS_LAST -}; - -/* Stores the virtual disk configuration */ -struct qemud_vm_disk_def { - int type; - int device; - int bus; - char src[PATH_MAX]; - char dst[NAME_MAX]; - int readonly; - - struct qemud_vm_disk_def *next; -}; - -#define QEMUD_MAC_ADDRESS_LEN 6 -#define QEMUD_MODEL_MAX_LEN 10 -#define QEMUD_OS_TYPE_MAX_LEN 10 -#define QEMUD_OS_ARCH_MAX_LEN 10 -#define QEMUD_OS_MACHINE_MAX_LEN 10 - -/* 5 different types of networking config */ -enum qemud_vm_net_type { - QEMUD_NET_USER, - QEMUD_NET_ETHERNET, - QEMUD_NET_SERVER, - QEMUD_NET_CLIENT, - QEMUD_NET_MCAST, - QEMUD_NET_NETWORK, - QEMUD_NET_BRIDGE, -}; - -#define QEMUD_MAX_NAME_LEN 50 -#define QEMUD_MAX_XML_LEN 4096 -#define QEMUD_MAX_ERROR_LEN 1024 #define QEMUD_CPUMASK_LEN CPU_SETSIZE - -/* Stores the virtual network interface configuration */ -struct qemud_vm_net_def { - int type; - unsigned char mac[QEMUD_MAC_ADDRESS_LEN]; - char model[QEMUD_MODEL_MAX_LEN]; - union { - struct { - char ifname[BR_IFNAME_MAXLEN]; - char script[PATH_MAX]; - } ethernet; - struct { - char address[BR_INET_ADDR_MAXLEN]; - int port; - } socket; /* any of NET_CLIENT or NET_SERVER or NET_MCAST */ - struct { - char name[QEMUD_MAX_NAME_LEN]; - char ifname[BR_IFNAME_MAXLEN]; - } network; - struct { - char brname[BR_IFNAME_MAXLEN]; - char ifname[BR_IFNAME_MAXLEN]; - } bridge; - } dst; - - struct qemud_vm_net_def *next; -}; - -enum qemu_vm_chr_dst_type { - QEMUD_CHR_SRC_TYPE_NULL, - QEMUD_CHR_SRC_TYPE_VC, - QEMUD_CHR_SRC_TYPE_PTY, - QEMUD_CHR_SRC_TYPE_DEV, - QEMUD_CHR_SRC_TYPE_FILE, - QEMUD_CHR_SRC_TYPE_PIPE, - QEMUD_CHR_SRC_TYPE_STDIO, - QEMUD_CHR_SRC_TYPE_UDP, - QEMUD_CHR_SRC_TYPE_TCP, - QEMUD_CHR_SRC_TYPE_UNIX, - - QEMUD_CHR_SRC_TYPE_LAST, -}; - -enum { - QEMUD_CHR_SRC_TCP_PROTOCOL_RAW, - QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET, -}; - -struct qemud_vm_chr_def { - int dstPort; - - int srcType; - union { - struct { - char path[PATH_MAX]; - } file; /* pty, file, pipe, or device */ - struct { - char host[BR_INET_ADDR_MAXLEN]; - char service[BR_INET_ADDR_MAXLEN]; - int listen; - int protocol; - } tcp; - struct { - char bindHost[BR_INET_ADDR_MAXLEN]; - char bindService[BR_INET_ADDR_MAXLEN]; - char connectHost[BR_INET_ADDR_MAXLEN]; - char connectService[BR_INET_ADDR_MAXLEN]; - } udp; - struct { - char path[PATH_MAX]; - int listen; - } nix; - } srcData; - - struct qemud_vm_chr_def *next; -}; - -enum qemu_vm_input_type { - QEMU_INPUT_TYPE_MOUSE, - QEMU_INPUT_TYPE_TABLET, -}; - -enum qemu_vm_input_bus { - QEMU_INPUT_BUS_PS2, - QEMU_INPUT_BUS_USB, - QEMU_INPUT_BUS_XEN, -}; - -struct qemud_vm_input_def { - int type; - int bus; - struct qemud_vm_input_def *next; -}; - -enum qemu_vm_sound_model { - QEMU_SOUND_NONE = 0, - QEMU_SOUND_SB16, - QEMU_SOUND_ES1370, - QEMU_SOUND_PCSPK, -}; - -struct qemud_vm_sound_def { - int model; - struct qemud_vm_sound_def *next; -}; - -/* Flags for the 'type' field in next struct */ -enum qemud_vm_device_type { - QEMUD_DEVICE_DISK, - QEMUD_DEVICE_NET, - QEMUD_DEVICE_INPUT, - QEMUD_DEVICE_SOUND, -}; - -struct qemud_vm_device_def { - int type; - union { - struct qemud_vm_disk_def disk; - struct qemud_vm_net_def net; - struct qemud_vm_input_def input; - struct qemud_vm_sound_def sound; - } data; -}; - -#define QEMUD_MAX_BOOT_DEVS 4 - -/* 3 possible boot devices */ -enum qemud_vm_boot_order { - QEMUD_BOOT_FLOPPY, - QEMUD_BOOT_CDROM, - QEMUD_BOOT_DISK, - QEMUD_BOOT_NET, -}; -/* 3 possible graphics console modes */ -enum qemud_vm_graphics_type { - QEMUD_GRAPHICS_NONE, - QEMUD_GRAPHICS_SDL, - QEMUD_GRAPHICS_VNC, -}; /* Internal flags to keep track of qemu command line capabilities */ enum qemud_cmd_flags { @@ -251,107 +49,12 @@ QEMUD_CMD_FLAG_NAME = (1 << 5), }; - -enum qemud_vm_features { - QEMUD_FEATURE_ACPI = 1, -}; - -/* Operating system configuration data & machine / arch */ -struct qemud_vm_os_def { - char type[QEMUD_OS_TYPE_MAX_LEN]; - char arch[QEMUD_OS_ARCH_MAX_LEN]; - char machine[QEMUD_OS_MACHINE_MAX_LEN]; - int nBootDevs; - int bootDevs[QEMUD_MAX_BOOT_DEVS]; - char kernel[PATH_MAX]; - char initrd[PATH_MAX]; - char cmdline[PATH_MAX]; - char binary[PATH_MAX]; - char bootloader[PATH_MAX]; -}; - -/* Guest VM main configuration */ -struct qemud_vm_def { - int virtType; - unsigned char uuid[VIR_UUID_BUFLEN]; - char name[QEMUD_MAX_NAME_LEN]; - - unsigned long memory; - unsigned long maxmem; - int vcpus; - char cpumask[QEMUD_CPUMASK_LEN]; - - int noReboot; - - struct qemud_vm_os_def os; - - int localtime; - int features; - int graphicsType; - int vncPort; - int vncActivePort; - char vncListen[BR_INET_ADDR_MAXLEN]; - char *keymap; - - unsigned int ndisks; - struct qemud_vm_disk_def *disks; - - unsigned int nnets; - struct qemud_vm_net_def *nets; - - unsigned int ninputs; - struct qemud_vm_input_def *inputs; - - unsigned int nsounds; - struct qemud_vm_sound_def *sounds; - - unsigned int nserials; - struct qemud_vm_chr_def *serials; - - unsigned int nparallels; - struct qemud_vm_chr_def *parallels; -}; - -/* Guest VM runtime state */ -struct qemud_vm { - int stdin; - int stdout; - int stderr; - int monitor; - int logfile; - int pid; - int id; - int state; - - int *tapfds; - int ntapfds; - - int nvcpupids; - int *vcpupids; - - int qemuVersion; - int qemuCmdFlags; /* values from enum qemud_cmd_flags */ - - char configFile[PATH_MAX]; - char autostartLink[PATH_MAX]; - char migrateFrom[PATH_MAX]; - - struct qemud_vm_def *def; /* The current definition */ - struct qemud_vm_def *newDef; /* New definition to activate at shutdown */ - - unsigned int autostart : 1; - - struct qemud_vm *next; -}; - /* Main driver state */ struct qemud_driver { int qemuVersion; - int nactivevms; - int ninactivevms; - struct qemud_vm *vms; int nextvmid; + virDomainObjPtr domains; virNetworkObjPtr networks; brControl *brctl; @@ -360,21 +63,15 @@ char *autostartDir; char *networkConfigDir; char *networkAutostartDir; - char logDir[PATH_MAX]; + char *logDir; unsigned int vncTLS : 1; unsigned int vncTLSx509verify : 1; char *vncTLSx509certdir; - char vncListen[BR_INET_ADDR_MAXLEN]; + char *vncListen; virCapsPtr caps; }; - -static inline int -qemudIsActiveVM(const struct qemud_vm *vm) -{ - return vm->id != -1; -} void qemudReportError(virConnectPtr conn, virDomainPtr dom, @@ -386,57 +83,22 @@ int qemudLoadDriverConfig(struct qemud_driver *driver, const char *filename); -struct qemud_vm *qemudFindVMByID(const struct qemud_driver *driver, - int id); -struct qemud_vm *qemudFindVMByUUID(const struct qemud_driver *driver, - const unsigned char *uuid); -struct qemud_vm *qemudFindVMByName(const struct qemud_driver *driver, - const char *name); - virCapsPtr qemudCapsInit (void); int qemudExtractVersion (virConnectPtr conn, struct qemud_driver *driver); +int qemudExtractVersionInfo (const char *qemu, + int *version, + int *flags); + int qemudBuildCommandLine (virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm, - char ***argv); - -int qemudScanConfigs (struct qemud_driver *driver); -int qemudDeleteConfig (virConnectPtr conn, - struct qemud_driver *driver, - const char *configFile, - const char *name); - -void qemudFreeVMDef (struct qemud_vm_def *vm); -void qemudFreeVM (struct qemud_vm *vm); - -struct qemud_vm * - qemudAssignVMDef (virConnectPtr conn, - struct qemud_driver *driver, - struct qemud_vm_def *def); -void qemudRemoveInactiveVM (struct qemud_driver *driver, - struct qemud_vm *vm); - -struct qemud_vm_device_def * - qemudParseVMDeviceDef (virConnectPtr conn, - const struct qemud_vm_def *def, - const char *xmlStr); - -struct qemud_vm_def * - qemudParseVMDef (virConnectPtr conn, - struct qemud_driver *driver, - const char *xmlStr, - const char *displayName); -int qemudSaveVMDef (virConnectPtr conn, - struct qemud_driver *driver, - struct qemud_vm *vm, - struct qemud_vm_def *def); -char * qemudGenerateXML (virConnectPtr conn, - struct qemud_driver *driver, - struct qemud_vm *vm, - struct qemud_vm_def *def, - int live); + virDomainObjPtr dom, + int qemuCmdFlags, + char ***argv, + int **tapfds, + int *ntapfds, + const char *migrateFrom); const char *qemudVirtTypeToString (int type); diff -r 8b6e9b6cbaa5 src/qemu_driver.c --- a/src/qemu_driver.c Tue Jul 08 15:26:54 2008 +0100 +++ b/src/qemu_driver.c Tue Jul 08 15:29:16 2008 +0100 @@ -44,7 +44,6 @@ #include <pwd.h> #include <stdio.h> #include <sys/wait.h> -#include <libxml/uri.h> #if HAVE_NUMACTL #include <numa.h> @@ -54,13 +53,12 @@ #include <sched.h> #endif -#include "internal.h" +#include "qemu_driver.h" +#include "qemu_conf.h" #include "c-ctype.h" #include "event.h" #include "buf.h" #include "util.h" -#include "qemu_driver.h" -#include "qemu_conf.h" #include "nodeinfo.h" #include "stats_linux.h" #include "capabilities.h" @@ -112,11 +110,12 @@ static void qemudDispatchVMEvent(int fd, int events, void *opaque); static int qemudStartVMDaemon(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm); + virDomainObjPtr vm, + const char *migrateFrom); static void qemudShutdownVMDaemon(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm); + virDomainObjPtr vm); static int qemudStartNetworkDaemon(virConnectPtr conn, struct qemud_driver *driver, @@ -128,7 +127,7 @@ static int qemudDomainGetMaxVcpus(virDomainPtr dom); static int qemudMonitorCommand (const struct qemud_driver *driver, - const struct qemud_vm *vm, + const virDomainObjPtr vm, const char *cmd, char **reply); @@ -138,7 +137,7 @@ static void qemudAutostartConfigs(struct qemud_driver *driver) { virNetworkObjPtr network; - struct qemud_vm *vm; + virDomainObjPtr vm; network = driver->networks; while (network != NULL) { @@ -155,13 +154,13 @@ network = next; } - vm = driver->vms; + vm = driver->domains; while (vm != NULL) { - struct qemud_vm *next = vm->next; + virDomainObjPtr next = vm->next; if (vm->autostart && - !qemudIsActiveVM(vm) && - qemudStartVMDaemon(NULL, driver, vm) < 0) { + !virDomainIsActive(vm) && + qemudStartVMDaemon(NULL, driver, vm, NULL) < 0) { virErrorPtr err = virGetLastError(); qemudLog(QEMUD_ERR, _("Failed to autostart VM '%s': %s"), vm->def->name, err->message); @@ -191,8 +190,9 @@ qemu_driver->nextvmid = 1; if (!uid) { - if (snprintf(qemu_driver->logDir, PATH_MAX, "%s/log/libvirt/qemu", LOCAL_STATE_DIR) >= PATH_MAX) - goto snprintf_error; + if (asprintf(&qemu_driver->logDir, + "%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1) + goto out_of_memory; if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL) goto out_of_memory; @@ -203,8 +203,9 @@ goto out_of_memory; } - if (snprintf(qemu_driver->logDir, PATH_MAX, "%s/.libvirt/qemu/log", pw->pw_dir) >= PATH_MAX) - goto snprintf_error; + if (asprintf(&qemu_driver->logDir, + "%s/.libvirt/qemu/log", pw->pw_dir) == -1) + goto out_of_memory; if (asprintf (&base, "%s/.libvirt", pw->pw_dir) == -1) { qemudLog (QEMUD_ERR, @@ -243,7 +244,11 @@ return -1; } - if (qemudScanConfigs(qemu_driver) < 0) { + if (virDomainLoadAllConfigs(NULL, + qemu_driver->caps, + &qemu_driver->domains, + qemu_driver->configDir, + qemu_driver->autostartDir) < 0) { qemudShutdown(); return -1; } @@ -257,11 +262,6 @@ qemudAutostartConfigs(qemu_driver); return 0; - - snprintf_error: - qemudLog(QEMUD_ERR, - "%s", _("Resulting path to long for buffer in qemudInitPaths()")); - return -1; out_of_memory: qemudLog (QEMUD_ERR, @@ -279,7 +279,12 @@ */ static int qemudReload(void) { - qemudScanConfigs(qemu_driver); + virDomainLoadAllConfigs(NULL, + qemu_driver->caps, + &qemu_driver->domains, + qemu_driver->configDir, + qemu_driver->autostartDir); + virNetworkLoadAllConfigs(NULL, &qemu_driver->networks, qemu_driver->networkConfigDir, @@ -306,15 +311,19 @@ */ static int qemudActive(void) { + virDomainObjPtr dom = qemu_driver->domains; virNetworkObjPtr net = qemu_driver->networks; + while (dom) { + if (virDomainIsActive(dom)) + return 1; + dom = dom->next; + } + while (net) { - if (net->active) + if (virNetworkIsActive(net)) return 1; net = net->next; } - - if (qemu_driver->nactivevms) - return 1; /* Otherwise we're happy to deal with a shutdown */ return 0; @@ -327,7 +336,7 @@ */ static int qemudShutdown(void) { - struct qemud_vm *vm; + virDomainObjPtr vm; virNetworkObjPtr network; if (!qemu_driver) @@ -336,26 +345,25 @@ virCapabilitiesFree(qemu_driver->caps); /* shutdown active VMs */ - vm = qemu_driver->vms; + vm = qemu_driver->domains; while (vm) { - struct qemud_vm *next = vm->next; - if (qemudIsActiveVM(vm)) + virDomainObjPtr next = vm->next; + if (virDomainIsActive(vm)) qemudShutdownVMDaemon(NULL, qemu_driver, vm); - if (!vm->configFile[0]) - qemudRemoveInactiveVM(qemu_driver, vm); + if (!vm->configFile) + virDomainRemoveInactive(&qemu_driver->domains, + vm); vm = next; } /* free inactive VMs */ - vm = qemu_driver->vms; + vm = qemu_driver->domains; while (vm) { - struct qemud_vm *next = vm->next; - qemudFreeVM(vm); + virDomainObjPtr next = vm->next; + virDomainObjFree(vm); vm = next; } - qemu_driver->vms = NULL; - qemu_driver->nactivevms = 0; - qemu_driver->ninactivevms = 0; + qemu_driver->domains = NULL; /* shutdown active networks */ network = qemu_driver->networks; @@ -375,6 +383,7 @@ } qemu_driver->networks = NULL; + VIR_FREE(qemu_driver->logDir); VIR_FREE(qemu_driver->configDir); VIR_FREE(qemu_driver->autostartDir); VIR_FREE(qemu_driver->networkConfigDir); @@ -395,14 +404,14 @@ /* Return -1 for error, 1 to continue reading and 0 for success */ typedef int qemudHandlerMonitorOutput(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm, + virDomainObjPtr vm, const char *output, int fd); static int qemudReadMonitorOutput(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm, + virDomainObjPtr vm, int fd, char *buf, int buflen, @@ -475,7 +484,7 @@ static int qemudCheckMonitorPrompt(virConnectPtr conn ATTRIBUTE_UNUSED, struct qemud_driver *driver ATTRIBUTE_UNUSED, - struct qemud_vm *vm, + virDomainObjPtr vm, const char *output, int fd) { @@ -489,7 +498,7 @@ static int qemudOpenMonitor(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm, + virDomainObjPtr vm, const char *monitor) { int monfd; char buf[1024]; @@ -566,13 +575,13 @@ static int qemudFindCharDevicePTYs(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm, + virDomainObjPtr vm, const char *output, int fd ATTRIBUTE_UNUSED) { char monitor[PATH_MAX]; size_t offset = 0; - struct qemud_vm_chr_def *chr; + virDomainChrDefPtr chr; /* The order in which QEMU prints out the PTY paths is the order in which it procsses its monitor, serial @@ -586,10 +595,10 @@ /* then the serial devices */ chr = vm->def->serials; while (chr) { - if (chr->srcType == QEMUD_CHR_SRC_TYPE_PTY) { + if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) { if (qemudExtractMonitorPath(output, &offset, - chr->srcData.file.path, - sizeof(chr->srcData.file.path)) < 0) + chr->data.file.path, + sizeof(chr->data.file.path)) < 0) return 1; /* keep reading */ } chr = chr->next; @@ -598,10 +607,10 @@ /* and finally the parallel devices */ chr = vm->def->parallels; while (chr) { - if (chr->srcType == QEMUD_CHR_SRC_TYPE_PTY) { + if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) { if (qemudExtractMonitorPath(output, &offset, - chr->srcData.file.path, - sizeof(chr->srcData.file.path)) < 0) + chr->data.file.path, + sizeof(chr->data.file.path)) < 0) return 1; /* keep reading */ } chr = chr->next; @@ -613,7 +622,7 @@ static int qemudWaitForMonitor(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm) { + virDomainObjPtr vm) { char buf[1024]; /* Plenty of space to get startup greeting */ int ret = qemudReadMonitorOutput(conn, driver, vm, vm->stderr, @@ -634,14 +643,14 @@ static int qemudDetectVcpuPIDs(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm) { + virDomainObjPtr vm) { char *qemucpus = NULL; char *line; int lastVcpu = -1; /* Only KVM has seperate threads for CPUs, others just use main QEMU process for CPU */ - if (vm->def->virtType != QEMUD_VIRT_KVM) + if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM) vm->nvcpupids = 1; else vm->nvcpupids = vm->def->vcpus; @@ -652,7 +661,7 @@ return -1; } - if (vm->def->virtType != QEMUD_VIRT_KVM) { + if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM) { vm->vcpupids[0] = vm->pid; return 0; } @@ -734,7 +743,7 @@ static int qemudInitCpus(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm) { + virDomainObjPtr vm) { char *info = NULL; #if HAVE_SCHED_GETAFFINITY cpu_set_t mask; @@ -815,28 +824,33 @@ static int qemudStartVMDaemon(virConnectPtr conn, struct qemud_driver *driver, - struct qemud_vm *vm) { + virDomainObjPtr vm, + const char *migrateFrom) { char **argv = NULL, **tmp; int i, ret; char logfile[PATH_MAX]; struct stat sb; + int *tapfds = NULL; + int ntapfds = 0; + int qemuCmdFlags; - if (qemudIsActiveVM(vm)) { + if (virDomainIsActive(vm)) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("VM is already active")); return -1; } - if (vm->def->vncPort < 0) { + if (vm->def->graphics && + vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && + vm->def->graphics->data.vnc.autoport) { int port = qemudNextFreeVNCPort(driver); if (port < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to find an unused VNC port")); return -1; } - vm->def->vncActivePort = port; - } else - vm->def->vncActivePort = vm->def->vncPort; + vm->def->graphics->data.vnc.port = port; + } if ((strlen(driver->logDir) + /* path */ 1 + /* Separator */ @@ -880,16 +894,26 @@ * Technically we could catch the exec() failure, but that's * in a sub-process so its hard to feed back a useful error */ - if (stat(vm->def->os.binary, &sb) < 0) { + if (stat(vm->def->emulator, &sb) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("Cannot find QEMU binary %s: %s"), - vm->def->os.binary, + vm->def->emulator, strerror(errno)); return -1; } + if (qemudExtractVersionInfo(vm->def->emulator, + NULL, + &qemuCmdFlags) < 0) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("Cannot determine QEMU argv syntax %s"), + vm->def->emulator); + return -1; + } - if (qemudBuildCommandLine(conn, driver, vm, &argv) < 0) { + if (qemudBuildCommandLine(conn, driver, vm, + qemuCmdFlags, &argv, + &tapfds, &ntapfds, migrateFrom) < 0) { close(vm->logfile); vm->logfile = -1; return -1; @@ -912,24 +936,19 @@ ret = virExecNonBlock(conn, argv, &vm->pid, vm->stdin, &vm->stdout, &vm->stderr); if (ret == 0) { - vm->id = driver->nextvmid++; - vm->state = vm->migrateFrom[0] ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING; - - driver->ninactivevms--; - driver->nactivevms++; + vm->def->id = driver->nextvmid++; + vm->state = migrateFrom ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING; } for (i = 0 ; argv[i] ; i++) VIR_FREE(argv[i]); VIR_FREE(argv); - if (vm->tapfds) { - for (i = 0; vm->tapfds[i] != -1; i++) { - close(vm->tapfds[i]); - vm->tapfds[i] = -1; + if (tapfds) { + for (i = 0 ; i < ntapfds ; i++) { + close(tapfds[i]); } - VIR_FREE(vm->tapfds); - vm->ntapfds = 0; + VIR_FREE(tapfds); } if (ret == 0) { @@ -953,7 +972,7 @@ } static int qemudVMData(struct qemud_driver *driver ATTRIBUTE_UNUSED, - struct qemud_vm *vm, int fd) { + virDomainObjPtr vm, int fd) { char buf[4096]; if (vm->pid < 0) return 0; @@ -982,8 +1001,8 @@ static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED, - struct qemud_driver *driver, struct qemud_vm *vm) { - if (!qemudIsActiveVM(vm)) + struct qemud_driver *driver, virDomainObjPtr vm) { + if (!virDomainIsActive(vm)) return; qemudLog(QEMUD_INFO, _("Shutting down VM '%s'"), vm->def->name); @@ -1017,35 +1036,35 @@ } vm->pid = -1; - vm->id = -1; + vm->def->id = -1; vm->state = VIR_DOMAIN_SHUTOFF; VIR_FREE(vm->vcpupids); vm->nvcpupids = 0; if (vm->newDef) { - qemudFreeVMDef(vm->def); + virDomainDefFree(vm->def); vm->def = vm->newDef; + vm->def->id = -1; vm->newDef = NULL; } - - driver->nactivevms--; - driver->ninactivevms++; } -static int qemudDispatchVMLog(struct qemud_driver *driver, struct qemud_vm *vm, int fd) { +static int qemudDispatchVMLog(struct qemud_driver *driver, virDomainObjPtr vm, int fd) { if (qemudVMData(driver, vm, fd) < 0) { qemudShutdownVMDaemon(NULL, driver, vm); - if (!vm->configFile[0]) - qemudRemoveInactiveVM(driver, vm); + if (!vm->configFile) + virDomainRemoveInactive(&driver->domains, + vm); } return 0; } -static int qemudDispatchVMFailure(struct qemud_driver *driver, struct qemud_vm *vm, +static int qemudDispatchVMFailure(struct qemud_driver *driver, virDomainObjPtr vm, int fd ATTRIBUTE_UNUSED) { qemudShutdownVMDaemon(NULL, driver, vm); - if (!vm->configFile[0]) - qemudRemoveInactiveVM(driver, vm); + if (!vm->configFile) + virDomainRemoveInactive(&driver->domains, + vm); return 0; } @@ -1575,10 +1594,10 @@ static void qemudDispatchVMEvent(int fd, int events, void *opaque) { struct qemud_driver *driver = (struct qemud_driver *)opaque; - struct qemud_vm *vm = driver->vms; + virDomainObjPtr vm = driver->domains; while (vm) { - if (qemudIsActiveVM(vm) && + if (virDomainIsActive(vm) && (vm->stdout == fd || vm->stderr == fd)) break; @@ -1597,7 +1616,7 @@ static int qemudMonitorCommand (const struct qemud_driver *driver ATTRIBUTE_UNUSED, - const struct qemud_vm *vm, + const virDomainObjPtr vm, const char *cmd, char **reply) { int size = 0; @@ -1867,9 +1886,9 @@ static virDomainPtr qemudDomainLookupByID(virConnectPtr conn, - int id) { + int id) { struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - struct qemud_vm *vm = qemudFindVMByID(driver, id); + virDomainObjPtr vm = virDomainFindByID(driver->domains, id); virDomainPtr dom; if (!vm) { @@ -1878,13 +1897,13 @@ } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (dom) dom->id = vm->id; + if (dom) dom->id = vm->def->id; return dom; } static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn, - const unsigned char *uuid) { + const unsigned char *uuid) { struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, uuid); virDomainPtr dom; if (!vm) { @@ -1893,13 +1912,13 @@ } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (dom) dom->id = vm->id; + if (dom) dom->id = vm->def->id; return dom; } static virDomainPtr qemudDomainLookupByName(virConnectPtr conn, - const char *name) { + const char *name) { struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - struct qemud_vm *vm = qemudFindVMByName(driver, name); + virDomainObjPtr vm = virDomainFindByName(driver->domains, name); virDomainPtr dom; if (!vm) { @@ -1908,7 +1927,7 @@ } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (dom) dom->id = vm->id; + if (dom) dom->id = vm->def->id; return dom; } @@ -1945,11 +1964,11 @@ static int qemudListDomains(virConnectPtr conn, int *ids, int nids) { struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - struct qemud_vm *vm = driver->vms; + virDomainObjPtr vm = driver->domains; int got = 0; while (vm && got < nids) { - if (qemudIsActiveVM(vm)) { - ids[got] = vm->id; + if (virDomainIsActive(vm)) { + ids[got] = vm->def->id; got++; } vm = vm->next; @@ -1958,30 +1977,40 @@ } static int qemudNumDomains(virConnectPtr conn) { struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - return driver->nactivevms; + int n = 0; + virDomainObjPtr dom = driver->domains; + while (dom) { + if (virDomainIsActive(dom)) + n++; + dom = dom->next; + } + return n; } static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { - struct qemud_vm_def *def; - struct qemud_vm *vm; + virDomainDefPtr def; + virDomainObjPtr vm; virDomainPtr dom; struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - if (!(def = qemudParseVMDef(conn, driver, xml, NULL))) + if (!(def = virDomainDefParseString(conn, driver->caps, xml))) return NULL; - if (!(vm = qemudAssignVMDef(conn, driver, def))) { - qemudFreeVMDef(def); + if (!(vm = virDomainAssignDef(conn, + &driver->domains, + def))) { + virDomainDefFree(def); return NULL; } - if (qemudStartVMDaemon(conn, driver, vm) < 0) { - qemudRemoveInactiveVM(driver, vm); + if (qemudStartVMDaemon(conn, driver, vm, NULL) < 0) { + virDomainRemoveInactive(&driver->domains, + vm); return NULL; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (dom) dom->id = vm->id; + if (dom) dom->id = vm->def->id; return dom; } @@ -1989,12 +2018,12 @@ static int qemudDomainSuspend(virDomainPtr dom) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; char *info; - struct qemud_vm *vm = qemudFindVMByID(driver, dom->id); + virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); return -1; } - if (!qemudIsActiveVM(vm)) { + if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); return -1; @@ -2017,13 +2046,13 @@ static int qemudDomainResume(virDomainPtr dom) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; char *info; - struct qemud_vm *vm = qemudFindVMByID(driver, dom->id); + virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); return -1; } - if (!qemudIsActiveVM(vm)) { + if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); return -1; @@ -2044,7 +2073,7 @@ static int qemudDomainShutdown(virDomainPtr dom) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByID(driver, dom->id); + virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id); char* info; if (!vm) { @@ -2065,7 +2094,7 @@ static int qemudDomainDestroy(virDomainPtr dom) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByID(driver, dom->id); + virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -2074,8 +2103,9 @@ } qemudShutdownVMDaemon(dom->conn, driver, vm); - if (!vm->configFile[0]) - qemudRemoveInactiveVM(driver, vm); + if (!vm->configFile) + virDomainRemoveInactive(&driver->domains, + vm); return 0; } @@ -2083,7 +2113,7 @@ static char *qemudDomainGetOSType(virDomainPtr dom) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); char *type; if (!vm) { @@ -2103,7 +2133,7 @@ /* Returns max memory in kb, 0 if error */ static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -2116,7 +2146,7 @@ static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -2136,7 +2166,7 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -2144,7 +2174,7 @@ return -1; } - if (qemudIsActiveVM(vm)) { + if (virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", _("cannot set memory of an active domain")); return -1; @@ -2161,9 +2191,9 @@ } static int qemudDomainGetInfo(virDomainPtr dom, - virDomainInfoPtr info) { + virDomainInfoPtr info) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -2172,7 +2202,7 @@ info->state = vm->state; - if (!qemudIsActiveVM(vm)) { + if (!virDomainIsActive(vm)) { info->cpuTime = 0; } else { if (qemudGetProcessInfo(&(info->cpuTime), vm->pid) < 0) { @@ -2284,7 +2314,7 @@ static int qemudDomainSave(virDomainPtr dom, const char *path) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByID(driver, dom->id); + virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id); char *command, *info; int fd; char *safe_path; @@ -2301,7 +2331,7 @@ return -1; } - if (!qemudIsActiveVM(vm)) { + if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); return -1; @@ -2318,7 +2348,7 @@ } /* Get XML for the domain */ - xml = qemudGenerateXML(dom->conn, driver, vm, vm->def, 0); + xml = virDomainDefFormat(dom->conn, vm->def, VIR_DOMAIN_XML_SECURE); if (!xml) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to get domain xml")); @@ -2382,8 +2412,9 @@ /* Shut it down */ qemudShutdownVMDaemon(dom->conn, driver, vm); - if (!vm->configFile[0]) - qemudRemoveInactiveVM(driver, vm); + if (!vm->configFile) + virDomainRemoveInactive(&driver->domains, + vm); return 0; } @@ -2391,7 +2422,7 @@ static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) { const struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); int max; if (!vm) { @@ -2400,7 +2431,7 @@ return -1; } - if (qemudIsActiveVM(vm)) { + if (virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", _("cannot change vcpu count of an active domain")); return -1; @@ -2431,12 +2462,12 @@ unsigned char *cpumap, int maplen) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); cpu_set_t mask; int i, maxcpu; virNodeInfo nodeinfo; - if (!qemudIsActiveVM(vm)) { + if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, "%s",_("cannot pin vcpus on an inactive domain")); return -1; @@ -2484,11 +2515,11 @@ unsigned char *cpumaps, int maplen) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); virNodeInfo nodeinfo; int i, v, maxcpu; - if (!qemudIsActiveVM(vm)) { + if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, "%s",_("cannot pin vcpus on an inactive domain")); return -1; @@ -2549,7 +2580,7 @@ static int qemudDomainGetMaxVcpus(virDomainPtr dom) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); const char *type; int ret; @@ -2559,7 +2590,7 @@ return -1; } - if (!(type = qemudVirtTypeToString(vm->def->virtType))) { + if (!(type = virDomainVirtTypeToString(vm->def->virtType))) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, _("unknown virt type in domain definition '%d'"), vm->def->virtType); @@ -2577,8 +2608,8 @@ static int qemudDomainRestore(virConnectPtr conn, const char *path) { struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - struct qemud_vm_def *def; - struct qemud_vm *vm; + virDomainDefPtr def; + virDomainObjPtr vm; int fd; int ret; char *xml; @@ -2629,7 +2660,7 @@ } /* Create a domain from this XML */ - if (!(def = qemudParseVMDef(conn, driver, xml, NULL))) { + if (!(def = virDomainDefParseString(conn, driver->caps, xml))) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to parse XML")); close(fd); @@ -2639,35 +2670,37 @@ VIR_FREE(xml); /* Ensure the name and UUID don't already exist in an active VM */ - vm = qemudFindVMByUUID(driver, def->uuid); - if (!vm) vm = qemudFindVMByName(driver, def->name); - if (vm && qemudIsActiveVM(vm)) { + vm = virDomainFindByUUID(driver->domains, def->uuid); + if (!vm) + vm = virDomainFindByName(driver->domains, def->name); + if (vm && virDomainIsActive(vm)) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("domain is already active as '%s'"), vm->def->name); close(fd); return -1; } - if (!(vm = qemudAssignVMDef(conn, driver, def))) { + if (!(vm = virDomainAssignDef(conn, + &driver->domains, + def))) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to assign new VM")); - qemudFreeVMDef(def); + virDomainDefFree(def); close(fd); return -1; } /* Set the migration source and start it up. */ - snprintf(vm->migrateFrom, sizeof(vm->migrateFrom), "stdio"); vm->stdin = fd; - ret = qemudStartVMDaemon(conn, driver, vm); + ret = qemudStartVMDaemon(conn, driver, vm, "stdio"); close(fd); - vm->migrateFrom[0] = '\0'; vm->stdin = -1; if (ret < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to start VM")); - if (!vm->configFile[0]) - qemudRemoveInactiveVM(driver, vm); + if (!vm->configFile) + virDomainRemoveInactive(&driver->domains, + vm); return -1; } @@ -2688,26 +2721,29 @@ static char *qemudDomainDumpXML(virDomainPtr dom, - int flags ATTRIBUTE_UNUSED) { + int flags ATTRIBUTE_UNUSED) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); return NULL; } - return qemudGenerateXML(dom->conn, driver, vm, vm->def, 1); + return virDomainDefFormat(dom->conn, + (flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ? + vm->newDef : vm->def, + flags); } static int qemudListDefinedDomains(virConnectPtr conn, char **const names, int nnames) { struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - struct qemud_vm *vm = driver->vms; + virDomainObjPtr vm = driver->domains; int got = 0, i; while (vm && got < nnames) { - if (!qemudIsActiveVM(vm)) { + if (!virDomainIsActive(vm)) { if (!(names[got] = strdup(vm->def->name))) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for VM name string")); @@ -2728,13 +2764,20 @@ static int qemudNumDefinedDomains(virConnectPtr conn) { struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - return driver->ninactivevms; + int n = 0; + virDomainObjPtr dom = driver->domains; + while (dom) { + if (!virDomainIsActive(dom)) + n++; + dom = dom->next; + } + return 0; } static int qemudDomainStart(virDomainPtr dom) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -2742,37 +2785,43 @@ return -1; } - return qemudStartVMDaemon(dom->conn, driver, vm); + return qemudStartVMDaemon(dom->conn, driver, vm, NULL); } static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) { struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - struct qemud_vm_def *def; - struct qemud_vm *vm; + virDomainDefPtr def; + virDomainObjPtr vm; virDomainPtr dom; - if (!(def = qemudParseVMDef(conn, driver, xml, NULL))) + if (!(def = virDomainDefParseString(conn, driver->caps, xml))) return NULL; - if (!(vm = qemudAssignVMDef(conn, driver, def))) { - qemudFreeVMDef(def); + if (!(vm = virDomainAssignDef(conn, + &driver->domains, + def))) { + virDomainDefFree(def); return NULL; } - if (qemudSaveVMDef(conn, driver, vm, def) < 0) { - qemudRemoveInactiveVM(driver, vm); + if (virDomainSaveConfig(conn, + driver->configDir, + driver->autostartDir, + vm) < 0) { + virDomainRemoveInactive(&driver->domains, + vm); return NULL; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (dom) dom->id = vm->id; + if (dom) dom->id = vm->def->id; return dom; } static int qemudDomainUndefine(virDomainPtr dom) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -2780,35 +2829,29 @@ return -1; } - if (qemudIsActiveVM(vm)) { + if (virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot delete active domain")); return -1; } - if (qemudDeleteConfig(dom->conn, driver, vm->configFile, vm->def->name) < 0) + if (virDomainDeleteConfig(dom->conn, vm) < 0) return -1; - if (unlink(vm->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) - qemudLog(QEMUD_WARN, _("Failed to delete autostart link '%s': %s"), - vm->autostartLink, strerror(errno)); - - vm->configFile[0] = '\0'; - vm->autostartLink[0] = '\0'; - - qemudRemoveInactiveVM(driver, vm); + virDomainRemoveInactive(&driver->domains, + vm); return 0; } static int qemudDomainChangeCDROM(virDomainPtr dom, - struct qemud_vm *vm, - struct qemud_vm_disk_def *olddisk, - struct qemud_vm_disk_def *newdisk) { + virDomainObjPtr vm, + virDomainDiskDefPtr olddisk, + virDomainDiskDefPtr newdisk) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; char *cmd, *reply, *safe_path; - if (newdisk->src[0]) { + if (newdisk->src) { safe_path = qemudEscapeMonitorArg(newdisk->src); if (!safe_path) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, @@ -2848,9 +2891,9 @@ static int qemudDomainAttachDevice(virDomainPtr dom, const char *xml) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); - struct qemud_vm_device_def *dev; - struct qemud_vm_disk_def *disk; + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); + virDomainDeviceDefPtr dev; + virDomainDiskDefPtr disk; if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -2858,18 +2901,19 @@ return -1; } - if (!qemudIsActiveVM(vm)) { + if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot attach device on inactive domain")); return -1; } - dev = qemudParseVMDeviceDef(dom->conn, vm->def, xml); + dev = virDomainDeviceDefParse(dom->conn, vm->def, xml); if (dev == NULL) { return -1; } - if (dev->type != QEMUD_DEVICE_DISK || dev->data.disk.device != QEMUD_DISK_CDROM) { + if (dev->type != VIR_DOMAIN_DEVICE_DISK || + dev->data.disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", _("only CDROM disk devices can be attached")); VIR_FREE(dev); @@ -2878,8 +2922,8 @@ disk = vm->def->disks; while (disk) { - if (disk->device == QEMUD_DISK_CDROM && - STREQ(disk->dst, dev->data.disk.dst)) + if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM && + STREQ(disk->dst, dev->data.disk->dst)) break; disk = disk->next; } @@ -2891,7 +2935,7 @@ return -1; } - if (qemudDomainChangeCDROM(dom, vm, disk, &dev->data.disk) < 0) { + if (qemudDomainChangeCDROM(dom, vm, disk, dev->data.disk) < 0) { VIR_FREE(dev); return -1; } @@ -2903,7 +2947,7 @@ static int qemudDomainGetAutostart(virDomainPtr dom, int *autostart) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -2919,7 +2963,7 @@ static int qemudDomainSetAutostart(virDomainPtr dom, int autostart) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -2977,14 +3021,14 @@ const char *p, *eol; char qemu_dev_name[32]; size_t len; - const struct qemud_vm *vm = qemudFindVMByID(driver, dom->id); + const virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id); if (!vm) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); return -1; } - if (!qemudIsActiveVM (vm)) { + if (!virDomainIsActive (vm)) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); return -1; @@ -3111,8 +3155,8 @@ { #ifdef __linux__ struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByID (driver, dom->id); - struct qemud_vm_net_def *net; + virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id); + virDomainNetDefPtr net; if (!vm) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -3120,7 +3164,7 @@ return -1; } - if (!qemudIsActiveVM(vm)) { + if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); return -1; @@ -3134,20 +3178,8 @@ /* Check the path is one of the domain's network interfaces. */ for (net = vm->def->nets; net; net = net->next) { - switch (net->type) { - case QEMUD_NET_NETWORK: - if (STREQ (net->dst.network.ifname, path)) - goto ok; - break; - case QEMUD_NET_ETHERNET: - if (STREQ (net->dst.ethernet.ifname, path)) - goto ok; - break; - case QEMUD_NET_BRIDGE: - if (STREQ (net->dst.bridge.ifname, path)) - goto ok; - break; - } + if (STREQ (net->ifname, path)) + goto ok; } qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, @@ -3171,8 +3203,8 @@ unsigned int flags ATTRIBUTE_UNUSED) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByUUID (driver, dom->uuid); - int i; + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); + virDomainDiskDefPtr disk; int fd, ret = -1; if (!vm) { @@ -3188,8 +3220,9 @@ } /* Check the path belongs to this domain. */ - for (i = 0; i < vm->def->ndisks; ++i) { - if (STREQ (vm->def->disks[i].src, path)) goto found; + for (disk = vm->def->disks ; disk != NULL ; disk = disk->next) { + if (disk->src != NULL && + STREQ (disk->src, path)) goto found; } qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, _("invalid path")); @@ -3228,7 +3261,7 @@ unsigned int flags) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - struct qemud_vm *vm = qemudFindVMByID (driver, dom->id); + virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id); char cmd[256], *info; char tmp[] = TEMPDIR "/qemu.mem.XXXXXX"; int fd = -1, ret = -1; @@ -3245,7 +3278,7 @@ return -1; } - if (!qemudIsActiveVM(vm)) { + if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); return -1; @@ -3401,7 +3434,7 @@ } static virNetworkPtr qemudNetworkCreate(virConnectPtr conn, const char *xml) { - struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData; + struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData; virNetworkDefPtr def; virNetworkObjPtr network; virNetworkPtr net; diff -r 8b6e9b6cbaa5 tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml --- a/tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml Tue Jul 08 15:26:54 2008 +0100 +++ b/tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml Tue Jul 08 15:29:16 2008 +0100 @@ -6,7 +6,7 @@ <vcpu>1</vcpu> <bootloader>/usr/bin/pygrub</bootloader> <os> - <type>xen</type> + <type arch='x86_64' machine='xenner'>xen</type> </os> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> diff -r 8b6e9b6cbaa5 tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc.xml --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc.xml Tue Jul 08 15:26:54 2008 +0100 +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc.xml Tue Jul 08 15:29:16 2008 +0100 @@ -19,6 +19,6 @@ <target dev='hda' bus='ide'/> </disk> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5903' listen='127.0.0.1'/> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'/> </devices> </domain> diff -r 8b6e9b6cbaa5 tests/qemuxml2argvdata/qemuxml2argv-input-xen.args --- a/tests/qemuxml2argvdata/qemuxml2argv-input-xen.args Tue Jul 08 15:26:54 2008 +0100 +++ b/tests/qemuxml2argvdata/qemuxml2argv-input-xen.args Tue Jul 08 15:29:16 2008 +0100 @@ -1,1 +1,1 @@ -/usr/bin/xenner -S -M xenner -m 214 -smp 1 -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb -vnc :-5901 \ No newline at end of file +/usr/bin/xenner -S -M xenner -m 214 -smp 1 -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb -vnc 127.0.0.1:3 \ No newline at end of file diff -r 8b6e9b6cbaa5 tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml --- a/tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml Tue Jul 08 15:26:54 2008 +0100 +++ b/tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml Tue Jul 08 15:29:16 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>219200</currentMemory> <vcpu>1</vcpu> <os> - <type>xen</type> + <type arch='x86_64' machine='xenner'>xen</type> <boot dev='hd'/> </os> <clock offset='utc'/> @@ -19,6 +19,6 @@ <target dev='hda' bus='ide'/> </disk> <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1'/> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'/> </devices> </domain> diff -r 8b6e9b6cbaa5 tests/qemuxml2argvdata/qemuxml2argv-sound.xml --- a/tests/qemuxml2argvdata/qemuxml2argv-sound.xml Tue Jul 08 15:26:54 2008 +0100 +++ b/tests/qemuxml2argvdata/qemuxml2argv-sound.xml Tue Jul 08 15:29:16 2008 +0100 @@ -16,15 +16,10 @@ <emulator>/usr/bin/qemu</emulator> <disk type='block' device='disk'> <source dev='/dev/HostVG/QEMUGuest1'/> - <target dev='hda'/> + <target dev='hda' bus='ide'/> </disk> <sound model='pcspk'/> - <sound model='pcspk'/> <sound model='es1370'/> - <sound model='pcspk'/> - <sound model='sb16'/> - <sound model='es1370'/> - <sound model='pcspk'/> <sound model='sb16'/> </devices> </domain> diff -r 8b6e9b6cbaa5 tests/qemuxml2argvtest.c --- a/tests/qemuxml2argvtest.c Tue Jul 08 15:26:54 2008 +0100 +++ b/tests/qemuxml2argvtest.c Tue Jul 08 15:29:16 2008 +0100 @@ -23,39 +23,33 @@ #define MAX_FILE 4096 static int testCompareXMLToArgvFiles(const char *xml, const char *cmd, int extraFlags) { - char xmlData[MAX_FILE]; char argvData[MAX_FILE]; - char *xmlPtr = &(xmlData[0]); char *expectargv = &(argvData[0]); char *actualargv = NULL; char **argv = NULL; char **tmp = NULL; - int ret = -1, len; - struct qemud_vm_def *vmdef = NULL; - struct qemud_vm vm; - - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) - goto fail; + int ret = -1, len, flags; + virDomainDefPtr vmdef = NULL; + virDomainObj vm; if (virtTestLoadFile(cmd, &expectargv, MAX_FILE) < 0) goto fail; - if (!(vmdef = qemudParseVMDef(NULL, &driver, xmlData, "test"))) + if (!(vmdef = virDomainDefParseFile(NULL, driver.caps, xml))) goto fail; memset(&vm, 0, sizeof vm); vm.def = vmdef; + vm.def->id = -1; vm.pid = -1; - vm.id = -1; - vm.qemuVersion = 0 * 1000 * 100 + (8 * 1000) + 1; - vm.qemuCmdFlags = QEMUD_CMD_FLAG_VNC_COLON | - QEMUD_CMD_FLAG_NO_REBOOT; - vm.qemuCmdFlags |= extraFlags; - vm.migrateFrom[0] = '\0'; - vmdef->vncActivePort = vmdef->vncPort; + flags = QEMUD_CMD_FLAG_VNC_COLON | + QEMUD_CMD_FLAG_NO_REBOOT | + extraFlags; - if (qemudBuildCommandLine(NULL, &driver, &vm, &argv) < 0) + if (qemudBuildCommandLine(NULL, &driver, + &vm, flags, &argv, + NULL, NULL, NULL) < 0) goto fail; tmp = argv; @@ -92,8 +86,7 @@ } free(argv); } - if (vmdef) - qemudFreeVMDef(vmdef); + virDomainDefFree(vmdef); return ret; } diff -r 8b6e9b6cbaa5 tests/qemuxml2xmltest.c --- a/tests/qemuxml2xmltest.c Tue Jul 08 15:26:54 2008 +0100 +++ b/tests/qemuxml2xmltest.c Tue Jul 08 15:29:16 2008 +0100 @@ -27,25 +27,15 @@ char *xmlPtr = &(xmlData[0]); char *actual = NULL; int ret = -1; - struct qemud_vm_def *vmdef = NULL; - struct qemud_vm vm; + virDomainDefPtr vmdef = NULL; if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) goto fail; - if (!(vmdef = qemudParseVMDef(NULL, &driver, xmlData, "test"))) + if (!(vmdef = virDomainDefParseString(NULL, driver.caps, xmlData))) goto fail; - vm.def = vmdef; - vm.pid = -1; - vm.id = -1; - vm.qemuVersion = 0 * 1000 * 100 + (8 * 1000) + 1; - vm.qemuCmdFlags = QEMUD_CMD_FLAG_VNC_COLON | - QEMUD_CMD_FLAG_NO_REBOOT; - - vmdef->vncActivePort = vmdef->vncPort; - - if (!(actual = qemudGenerateXML(NULL, &driver, &vm, vmdef, 0))) + if (!(actual = virDomainDefFormat(NULL, vmdef, 0))) goto fail; if (STRNEQ(xmlData, actual)) { @@ -57,8 +47,7 @@ fail: free(actual); - if (vmdef) - qemudFreeVMDef(vmdef); + virDomainDefFree(vmdef); return ret; } @@ -115,6 +104,7 @@ DO_TEST("misc-no-reboot"); DO_TEST("net-user"); DO_TEST("net-virtio"); + DO_TEST("sound"); DO_TEST("serial-vc"); DO_TEST("serial-pty"); -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch is a cleanup to prepare the way for the next set of Xen related patches. It basically removes a bunch of no-op or unused code. proxy_internal.c | 10 -- xen_unified.c | 3 xend_internal.c | 242 +++++++++++-------------------------------------------- xend_internal.h | 91 -------------------- xs_internal.c | 10 -- 5 files changed, 52 insertions(+), 304 deletions(-) Daniel diff -r afea2b6ba5c5 src/proxy_internal.c --- a/src/proxy_internal.c Mon Jun 30 10:20:16 2008 +0100 +++ b/src/proxy_internal.c Mon Jun 30 10:34:45 2008 +0100 @@ -87,16 +87,6 @@ NULL, /* domainSetSchedulerParameters */ }; -/** - * xenProxyInit: - * - * Initialise the xen proxy driver. - */ -int -xenProxyInit (void) -{ - return 0; -} /************************************************************************ * * diff -r afea2b6ba5c5 src/xen_unified.c --- a/src/xen_unified.c Mon Jun 30 10:20:16 2008 +0100 +++ b/src/xen_unified.c Mon Jun 30 10:34:45 2008 +0100 @@ -1367,9 +1367,6 @@ { /* Ignore failures here. */ (void) xenHypervisorInit (); - (void) xenProxyInit (); - (void) xenDaemonInit (); - (void) xenStoreInit (); (void) xenXMInit (); return virRegisterDriver (&xenUnifiedDriver); diff -r afea2b6ba5c5 src/xend_internal.c --- a/src/xend_internal.c Mon Jun 30 10:20:16 2008 +0100 +++ b/src/xend_internal.c Mon Jun 30 10:34:45 2008 +0100 @@ -54,23 +54,6 @@ #define DEBUG0(msg) VIR_DEBUG(__FILE__, "%s", msg) #ifndef PROXY -static int xenDaemonListDomains(virConnectPtr conn, int *ids, int maxids); -static int xenDaemonNumOfDomains(virConnectPtr conn); -static int xenDaemonListDefinedDomains(virConnectPtr conn, char **const names, int maxnames); -static int xenDaemonNumOfDefinedDomains(virConnectPtr conn); -static virDomainPtr xenDaemonCreateLinux(virConnectPtr conn, - const char *xmlDesc, - unsigned int flags); -static char *xenDaemonDomainGetOSType(virDomainPtr domain); -static int xenDaemonAttachDevice(virDomainPtr domain, const char *xml); -static int xenDaemonDetachDevice(virDomainPtr domain, const char *xml); -static int xenDaemonDomainCoreDump(virDomainPtr domain, const char *filename, - int flags); -static char *xenDaemonGetSchedulerType(virDomainPtr domain, int *nparams); -static int xenDaemonGetSchedulerParameters(virDomainPtr domain, - virSchedParameterPtr params, int *nparams); -static int xenDaemonSetSchedulerParameters(virDomainPtr domain, - virSchedParameterPtr params, int nparams); /* * The number of Xen scheduler parameters @@ -79,61 +62,6 @@ #define XEN_SCHED_CRED_NPARAM 2 #endif /* PROXY */ - -#ifndef PROXY -struct xenUnifiedDriver xenDaemonDriver = { - xenDaemonOpen, /* open */ - xenDaemonClose, /* close */ - xenDaemonGetVersion, /* version */ - NULL, /* hostname */ - NULL, /* URI */ - xenDaemonNodeGetInfo, /* nodeGetInfo */ - NULL, /* getCapabilities */ - xenDaemonListDomains, /* listDomains */ - xenDaemonNumOfDomains, /* numOfDomains */ - xenDaemonCreateLinux, /* domainCreateLinux */ - xenDaemonDomainSuspend, /* domainSuspend */ - xenDaemonDomainResume, /* domainResume */ - xenDaemonDomainShutdown, /* domainShutdown */ - xenDaemonDomainReboot, /* domainReboot */ - xenDaemonDomainDestroy, /* domainDestroy */ - xenDaemonDomainGetOSType, /* domainGetOSType */ - xenDaemonDomainGetMaxMemory, /* domainGetMaxMemory */ - xenDaemonDomainSetMaxMemory, /* domainSetMaxMemory */ - xenDaemonDomainSetMemory, /* domainMaxMemory */ - xenDaemonDomainGetInfo, /* domainGetInfo */ - xenDaemonDomainSave, /* domainSave */ - xenDaemonDomainRestore, /* domainRestore */ - xenDaemonDomainCoreDump, /* domainCoreDump */ - xenDaemonDomainSetVcpus, /* domainSetVcpus */ - xenDaemonDomainPinVcpu, /* domainPinVcpu */ - xenDaemonDomainGetVcpus, /* domainGetVcpus */ - NULL, /* domainGetMaxVcpus */ - xenDaemonListDefinedDomains, /* listDefinedDomains */ - xenDaemonNumOfDefinedDomains, /* numOfDefinedDomains */ - xenDaemonDomainCreate, /* domainCreate */ - xenDaemonDomainDefineXML, /* domainDefineXML */ - xenDaemonDomainUndefine, /* domainUndefine */ - xenDaemonAttachDevice, /* domainAttachDevice */ - xenDaemonDetachDevice, /* domainDetachDevice */ - xenDaemonDomainGetAutostart, /* domainGetAutostart */ - xenDaemonDomainSetAutostart, /* domainSetAutostart */ - xenDaemonGetSchedulerType, /* domainGetSchedulerType */ - xenDaemonGetSchedulerParameters, /* domainGetSchedulerParameters */ - xenDaemonSetSchedulerParameters, /* domainSetSchedulerParameters */ -}; - -/** - * xenDaemonInit: - * - * Initialise the xenDaemon driver. - */ -int -xenDaemonInit (void) -{ - return 0; -} -#endif /* !PROXY */ /** * xend_connection_type: @@ -213,16 +141,6 @@ __virRaiseError(conn, NULL, NULL, VIR_FROM_XEND, error, VIR_ERR_ERROR, errmsg, NULL, NULL, val, 0, errmsg, val); } - - -#define foreach(iterator, start) \ - for (_for_i = (start), *iterator = (start)->u.s.car; \ - _for_i->kind == SEXPR_CONS; \ - _for_i = _for_i->u.s.cdr, iterator = _for_i->u.s.car) - -#define foreach_node(iterator, start, path) \ - foreach(iterator, start) \ - if (sexpr_lookup(iterator, path)) /** * do_connect: @@ -608,7 +526,7 @@ #ifndef PROXY /** - * xend_op_ext2: + * xend_op_ext: * @xend: pointer to the Xen Daemon structure * @path: path for the object * @error: buffer for the error output @@ -621,8 +539,8 @@ * Returns 0 in case of success, -1 in case of failure. */ static int -xend_op_ext2(virConnectPtr xend, const char *path, char *error, - size_t n_error, const char *key, va_list ap) +xend_op_ext(virConnectPtr xend, const char *path, char *error, + size_t n_error, const char *key, va_list ap) { const char *k = key, *v; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -655,33 +573,7 @@ /** - * xend_node_op: - * @xend: pointer to the Xen Daemon structure - * @path: path for the object - * @key: the key for the operation - * @...: input values to pass to the operation - * - * internal routine to run a POST RPC operation to the Xen Daemon - * - * Returns 0 in case of success, -1 in case of failure. - */ -static int -xend_node_op(virConnectPtr xend, const char *path, const char *key, ...) -{ - va_list ap; - int ret; - char error[1024]; - - va_start(ap, key); - ret = xend_op_ext2(xend, path, error, sizeof(error), key, ap); - va_end(ap); - - return ret; -} - - -/** - * xend_op_ext: + * xend_op: * @xend: pointer to the Xen Daemon structure * @name: the domain name target of this operation * @error: buffer for the error output @@ -706,7 +598,7 @@ snprintf(buffer, sizeof(buffer), "/xend/domain/%s", name); va_start(ap, key); - ret = xend_op_ext2(xend, buffer, error, sizeof(error), key, ap); + ret = xend_op_ext(xend, buffer, error, sizeof(error), key, ap); va_end(ap); return ret; @@ -1027,7 +919,7 @@ * * Returns 0 in case of success, -1 in case of error. */ -int +static int xenDaemonOpen_tcp(virConnectPtr conn, const char *host, int port) { struct in_addr ip; @@ -1309,83 +1201,6 @@ return (0); } -/** - * xend_node_shutdown: - * @xend: A xend instance - * - * This method shuts down the physical machine running Xen. - * - * Returns 0 on success; -1 (with errno) on error - */ -int -xend_node_shutdown(virConnectPtr xend) -{ - return xend_node_op(xend, "/xend/node/", "op", "halt", NULL); -} - -/** - * xend_node_restart: - * @xend: A xend instance - * - * This method restarts the physical machine running Xen. - * - * Returns 0 on success; -1 (with errno) on error - */ -int -xend_node_restart(virConnectPtr xend) -{ - return xend_node_op(xend, "/xend/node/", "op", "restart", NULL); -} - - -/** - * xend_dmesg: - * @xend: A xend instance - * @buffer: A buffer to hold the messages - * @n_buffer: Size of buffer (including null terminator) - * - * This function will place the debugging messages from the - * hypervisor into a buffer with a null terminator. - * - * Returns 0 on success; -1 (with errno) on error - */ -int -xend_dmesg(virConnectPtr xend, char *buffer, size_t n_buffer) -{ - return http2unix(xend, xend_get(xend, "/xend/node/dmesg", buffer, n_buffer)); -} - -/** - * xend_dmesg_clear: - * @xend: A xend instance - * - * This function will clear the debugging message ring queue - * in the hypervisor. - * - * Returns 0 on success; -1 (with errno) on error - */ -int -xend_dmesg_clear(virConnectPtr xend) -{ - return xend_node_op(xend, "/xend/node/dmesg", "op", "clear", NULL); -} - -/** - * xend_log: - * @xend: A xend instance - * @buffer: The buffer to hold the messages - * @n_buffer: Size of buffer (including null terminator) - * - * This function will place the Xend debugging messages into - * a buffer with a null terminator. - * - * Returns 0 on success; -1 (with errno) on error - */ -int -xend_log(virConnectPtr xend, char *buffer, size_t n_buffer) -{ - return http2unix(xend, xend_get(xend, "/xend/node/log", buffer, n_buffer)); -} #endif /* PROXY */ /***************************************************************** @@ -4213,7 +4028,8 @@ return(ret); } -int xenDaemonListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) { +static int +xenDaemonListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) { struct sexpr *root = NULL; int ret = -1; struct sexpr *_for_i, *node; @@ -4631,5 +4447,47 @@ return ret; } +struct xenUnifiedDriver xenDaemonDriver = { + xenDaemonOpen, /* open */ + xenDaemonClose, /* close */ + xenDaemonGetVersion, /* version */ + NULL, /* hostname */ + NULL, /* URI */ + xenDaemonNodeGetInfo, /* nodeGetInfo */ + NULL, /* getCapabilities */ + xenDaemonListDomains, /* listDomains */ + xenDaemonNumOfDomains, /* numOfDomains */ + xenDaemonCreateLinux, /* domainCreateLinux */ + xenDaemonDomainSuspend, /* domainSuspend */ + xenDaemonDomainResume, /* domainResume */ + xenDaemonDomainShutdown, /* domainShutdown */ + xenDaemonDomainReboot, /* domainReboot */ + xenDaemonDomainDestroy, /* domainDestroy */ + xenDaemonDomainGetOSType, /* domainGetOSType */ + xenDaemonDomainGetMaxMemory, /* domainGetMaxMemory */ + xenDaemonDomainSetMaxMemory, /* domainSetMaxMemory */ + xenDaemonDomainSetMemory, /* domainMaxMemory */ + xenDaemonDomainGetInfo, /* domainGetInfo */ + xenDaemonDomainSave, /* domainSave */ + xenDaemonDomainRestore, /* domainRestore */ + xenDaemonDomainCoreDump, /* domainCoreDump */ + xenDaemonDomainSetVcpus, /* domainSetVcpus */ + xenDaemonDomainPinVcpu, /* domainPinVcpu */ + xenDaemonDomainGetVcpus, /* domainGetVcpus */ + NULL, /* domainGetMaxVcpus */ + xenDaemonListDefinedDomains, /* listDefinedDomains */ + xenDaemonNumOfDefinedDomains,/* numOfDefinedDomains */ + xenDaemonDomainCreate, /* domainCreate */ + xenDaemonDomainDefineXML, /* domainDefineXML */ + xenDaemonDomainUndefine, /* domainUndefine */ + xenDaemonAttachDevice, /* domainAttachDevice */ + xenDaemonDetachDevice, /* domainDetachDevice */ + xenDaemonDomainGetAutostart, /* domainGetAutostart */ + xenDaemonDomainSetAutostart, /* domainSetAutostart */ + xenDaemonGetSchedulerType, /* domainGetSchedulerType */ + xenDaemonGetSchedulerParameters, /* domainGetSchedulerParameters */ + xenDaemonSetSchedulerParameters, /* domainSetSchedulerParameters */ +}; + #endif /* ! PROXY */ #endif /* WITH_XEN */ diff -r afea2b6ba5c5 src/xend_internal.h --- a/src/xend_internal.h Mon Jun 30 10:20:16 2008 +0100 +++ b/src/xend_internal.h Mon Jun 30 10:34:45 2008 +0100 @@ -26,33 +26,8 @@ extern "C" { #endif -/** - * \brief Setup the connection to a xend instance via TCP - * \param host The host name to connect to - * \param port The port number to connect to - * \return 0 in case of success, -1 in case of error - * - * This method creates a new Xend instance via TCP. - * - * This function may not fail if Xend is not running. - * - * Make sure to call xenDaemonClose(). - */ -int xenDaemonOpen_tcp(virConnectPtr xend, const char *host, int port); - -/** - * \brief Setup the connection to xend instance via a Unix domain socket - * \param path The path to the domain socket - * \return 0 in case of success, -1 in case of error - * - * This method creates a new xend instance via a Unix domain socket. - * - * This function may not fail if Xend is not running. - * - * Make sure to call xenDaemonClose(). - */ -int xenDaemonOpen_unix(virConnectPtr xend, const char *path); - +int +xenDaemonOpen_unix(virConnectPtr conn, const char *path); /** * \brief Blocks until a domain's devices are initialized @@ -117,68 +92,6 @@ const char *name, int flags, const char *cpus); - -/** - * \brief Lookup information about the host machine - * \param xend A xend instance - * \return node info on success; NULL (with errno) on error - * - * This method returns information about the physical host - * machine running Xen. - */ - struct xend_node *xend_get_node(virConnectPtr xend); - -/** - * \brief Shutdown physical host machine - * \param xend A xend instance - * \return 0 on success; -1 (with errno) on error - * - * This method shuts down the physical machine running Xen. - */ - int xend_node_shutdown(virConnectPtr xend); - -/** - * \brief Restarts physical host machine - * \param xend A xend instance - * \return 0 on success; -1 (with errno) on error - * - * This method restarts the physical machine running Xen. - */ - int xend_node_restart(virConnectPtr xend); - -/** - * \brief Return hypervisor debugging messages - * \param xend A xend instance - * \param buffer A buffer to hold the messages - * \param n_buffer Size of buffer (including null terminator) - * \return 0 on success; -1 (with errno) on error - * - * This function will place the debugging messages from the - * hypervisor into a buffer with a null terminator. - */ - int xend_dmesg(virConnectPtr xend, char *buffer, size_t n_buffer); - -/** - * \brief Clear the hypervisor debugging messages - * \param xend A xend instance - * \return 0 on success; -1 (with errno) on error - * - * This function will clear the debugging message ring queue - * in the hypervisor. - */ - int xend_dmesg_clear(virConnectPtr xend); - -/** - * \brief Obtain the Xend log messages - * \param xend A xend instance - * \param buffer The buffer to hold the messages - * \param n_buffer Size of buffer (including null terminator) - * \return 0 on success; -1 (with errno) on error - * - * This function will place the Xend debugging messages into - * a buffer with a null terminator. - */ - int xend_log(virConnectPtr xend, char *buffer, size_t n_buffer); int xend_parse_sexp_desc_char(virConnectPtr conn, virBufferPtr buf, diff -r afea2b6ba5c5 src/xs_internal.c --- a/src/xs_internal.c Mon Jun 30 10:20:16 2008 +0100 +++ b/src/xs_internal.c Mon Jun 30 10:34:45 2008 +0100 @@ -86,16 +86,6 @@ NULL, /* domainSetSchedulerParameters */ }; -/** - * xenStoreInit: - * - * Initialisation. - */ -int -xenStoreInit () -{ - return 0; -} #endif /* ! PROXY */ /** -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Tue, Jul 08, 2008 at 05:37:37PM +0100, Daniel P. Berrange wrote:
This patch is a cleanup to prepare the way for the next set of Xen related patches. It basically removes a bunch of no-op or unused code.
okay, +1, Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

This replaces the code which converts from the SEXPR into XML with code which converts from the SEXPR to virDomainDefPtr object. We then simply call virDomainDefFormat() to generate the XML. The generated XML is thus guarenteed consistent with the QEMU driver & others using domain_conf.c routines. Nearly all of the XML files had to be updated because the generic XML formatter outputs various elements in an alternate order than the Xen driver did. proxy/Makefile.am | 1 src/domain_conf.c | 3 src/domain_conf.h | 2 src/sexpr.c | 15 src/sexpr.h | 1 src/xend_internal.c | 1583 ++++++++++------- src/xend_internal.h | 6 tests/sexpr2xmldata/sexpr2xml-curmem.xml | 14 tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml | 9 tests/sexpr2xmldata/sexpr2xml-disk-block.xml | 6 tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-qcow.xml | 6 tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-raw.xml | 6 tests/sexpr2xmldata/sexpr2xml-disk-file.xml | 6 tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml | 9 tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml | 11 tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml | 24 tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml | 26 tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml | 26 tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml | 26 tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml | 26 tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml | 26 tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml | 26 tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.xml | 26 tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml | 26 tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml | 30 tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml | 26 tests/sexpr2xmldata/sexpr2xml-fv-sound-all.sexpr | 2 tests/sexpr2xmldata/sexpr2xml-fv-sound-all.xml | 25 tests/sexpr2xmldata/sexpr2xml-fv-sound.sexpr | 2 tests/sexpr2xmldata/sexpr2xml-fv-sound.xml | 24 tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml | 24 tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml | 24 tests/sexpr2xmldata/sexpr2xml-fv-utc.xml | 24 tests/sexpr2xmldata/sexpr2xml-fv-v2.xml | 16 tests/sexpr2xmldata/sexpr2xml-fv.xml | 24 tests/sexpr2xmldata/sexpr2xml-net-bridged.xml | 9 tests/sexpr2xmldata/sexpr2xml-net-e1000.xml | 9 tests/sexpr2xmldata/sexpr2xml-net-routed.xml | 8 tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml | 20 tests/sexpr2xmldata/sexpr2xml-pv-bootloader.xml | 9 tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml | 10 tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml | 10 tests/sexpr2xmldata/sexpr2xml-pv.xml | 6 tests/sexpr2xmltest.c | 19 44 files changed, 1319 insertions(+), 912 deletions(-) Daniel diff -r 3dea6bbe639b proxy/Makefile.am --- a/proxy/Makefile.am Thu Jul 03 11:42:42 2008 +0100 +++ b/proxy/Makefile.am Thu Jul 03 12:50:05 2008 +0100 @@ -15,6 +15,7 @@ @top_srcdir@/src/xs_internal.c @top_srcdir@/src/buf.c \ @top_srcdir@/src/capabilities.c \ @top_srcdir@/src/memory.c \ + @top_srcdir@/src/domain_conf.c \ @top_srcdir@/src/util.c \ @top_srcdir@/src/uuid.c libvirt_proxy_LDFLAGS = $(WARN_CFLAGS) diff -r 3dea6bbe639b src/domain_conf.c --- a/src/domain_conf.c Thu Jul 03 11:42:42 2008 +0100 +++ b/src/domain_conf.c Thu Jul 03 12:50:05 2008 +0100 @@ -430,6 +430,7 @@ virDomainObjFree(dom); } +#ifndef PROXY static int virDomainDiskCompare(virDomainDiskDefPtr a, virDomainDiskDefPtr b) { if (a->bus == b->bus) @@ -1910,7 +1911,7 @@ xmlXPathFreeContext(ctxt); return def; } - +#endif /* ! PROXY */ /************************************************************************ * * diff -r 3dea6bbe639b src/domain_conf.h --- a/src/domain_conf.h Thu Jul 03 11:42:42 2008 +0100 +++ b/src/domain_conf.h Thu Jul 03 12:50:05 2008 +0100 @@ -424,6 +424,7 @@ void virDomainRemoveInactive(virDomainObjPtr *doms, virDomainObjPtr dom); +#ifndef PROXY virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn, const virDomainDefPtr def, const char *xmlStr); @@ -437,6 +438,7 @@ virCapsPtr caps, xmlDocPtr doc, xmlNodePtr root); +#endif char *virDomainDefFormat(virConnectPtr conn, virDomainDefPtr def, int flags); diff -r 3dea6bbe639b src/sexpr.c --- a/src/sexpr.c Thu Jul 03 11:42:42 2008 +0100 +++ b/src/sexpr.c Thu Jul 03 12:50:05 2008 +0100 @@ -550,6 +550,21 @@ return (n && n->u.s.car->kind == SEXPR_VALUE) ? n->u.s.car->u.value : NULL; } +int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst) +{ + const char *val = sexpr_node(sexpr, node); + + if (val) { + *dst = strdup(val); + if (!(*dst)) + return -1; + } else { + *dst = NULL; + } + return 0; +} + + /** * sexpr_fmt_node: * @sexpr: a pointer to a parsed S-Expression diff -r 3dea6bbe639b src/sexpr.h --- a/src/sexpr.h Thu Jul 03 11:42:42 2008 +0100 +++ b/src/sexpr.h Thu Jul 03 12:50:05 2008 +0100 @@ -47,6 +47,7 @@ /* lookup in S-Expressions */ const char *sexpr_node(const struct sexpr *sexpr, const char *node); +int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst); const char *sexpr_fmt_node(const struct sexpr *sexpr, const char *fmt, ...) ATTRIBUTE_FORMAT(printf,2,3); struct sexpr *sexpr_lookup(const struct sexpr *sexpr, const char *node); diff -r 3dea6bbe639b src/xend_internal.c --- a/src/xend_internal.c Thu Jul 03 11:42:42 2008 +0100 +++ b/src/xend_internal.c Thu Jul 03 12:50:05 2008 +0100 @@ -40,6 +40,7 @@ #include "xml.h" #include "buf.h" #include "capabilities.h" +#include "domain_conf.h" #include "uuid.h" #include "xen_unified.h" #include "xend_internal.h" @@ -114,6 +115,8 @@ va_start (args, fmt); vsnprintf (msg, sizeof (msg), fmt, args); va_end (args); + } else { + msg[0] = '\0'; } msg2 = __virErrorMsg (error, fmt ? msg : NULL); @@ -1205,21 +1208,15 @@ /***************************************************************** ****** - ****** - ****** - ****** - Needed helper code - ****** - ****** - ****** + ****** Parsing of SEXPR into virDomainDef objects ****** *****************************************************************/ /** - * xend_parse_sexp_desc_os: + * xenDaemonParseSxprOS * @xend: the xend connection object * @node: the root of the parsed S-Expression - * @buf: output buffer object + * @def: the domain config * @hvm: true or 1 if no contains HVM S-Expression * @bootloader: true or 1 if a bootloader is defined * @@ -1228,90 +1225,82 @@ * Returns 0 in case of success and -1 in case of error */ static int -xend_parse_sexp_desc_os(virConnectPtr xend, struct sexpr *node, virBufferPtr buf, int hvm, int bootloader) -{ - const char *loader = NULL; - const char *kernel = NULL; - const char *initrd = NULL; - const char *cmdline = NULL; - const char *root = NULL; - - if (node == NULL || buf == NULL) { - return(-1); - } - - virBufferAddLit(buf, " <os>\n"); - if (hvm) - virBufferAddLit(buf, " <type>hvm</type>\n"); - else - virBufferAddLit(buf, " <type>linux</type>\n"); - +xenDaemonParseSxprOS(virConnectPtr xend, struct sexpr *node, + virDomainDefPtr def, + int hvm) +{ if (hvm) { - loader = sexpr_node(node, "domain/image/hvm/loader"); - if (loader == NULL) { - loader = sexpr_node(node, "domain/image/hvm/kernel"); - - if (loader == NULL) { + if (sexpr_node_copy(node, "domain/image/hvm/loader", &def->os.loader) < 0) + goto no_memory; + if (def->os.loader == NULL) { + if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.loader) < 0) + goto no_memory; + + if (def->os.loader == NULL) { virXendError(xend, VIR_ERR_INTERNAL_ERROR, _("domain information incomplete, missing HVM loader")); return(-1); } } else { - kernel = sexpr_node(node, "domain/image/hvm/kernel"); - initrd = sexpr_node(node, "domain/image/hvm/ramdisk"); - cmdline = sexpr_node(node, "domain/image/hvm/args"); - root = sexpr_node(node, "domain/image/hvm/root"); - } - } else { - kernel = sexpr_node(node, "domain/image/linux/kernel"); - initrd = sexpr_node(node, "domain/image/linux/ramdisk"); - cmdline = sexpr_node(node, "domain/image/linux/args"); - root = sexpr_node(node, "domain/image/linux/root"); - } - - if (hvm) - virBufferVSprintf(buf, " <loader>%s</loader>\n", loader); - - if ((kernel) && ((!loader) || (STRNEQ(kernel, loader)))) { - virBufferVSprintf(buf, " <kernel>%s</kernel>\n", kernel); - if (initrd && initrd[0]) - virBufferVSprintf(buf, " <initrd>%s</initrd>\n", initrd); - if (root && root[0]) - virBufferVSprintf(buf, " <root>%s</root>\n", root); - if (cmdline && cmdline[0]) - virBufferEscapeString(buf, " <cmdline>%s</cmdline>\n", cmdline); - } else { - if (hvm) { - const char *boot = sexpr_node(node, "domain/image/hvm/boot"); - if ((boot != NULL) && (boot[0] != 0)) { - while (*boot) { - if (*boot == 'a') - /* XXX no way to deal with boot from 2nd floppy */ - virBufferAddLit(buf, " <boot dev='fd'/>\n"); - else if (*boot == '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 - */ - virBufferAddLit(buf, " <boot dev='hd'/>\n"); - else if (*boot == 'd') - virBufferAddLit(buf, " <boot dev='cdrom'/>\n"); - else if (*boot == 'n') - virBufferAddLit(buf, " <boot dev='network'/>\n"); - boot++; - } - } - } else if (!bootloader) { - virXendError(xend, VIR_ERR_INTERNAL_ERROR, - _("domain information incomplete, missing kernel & bootloader")); - return(-1); - } - } - - virBufferAddLit(buf, " </os>\n"); - return(0); + if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.kernel) < 0) + goto no_memory; + if (sexpr_node_copy(node, "domain/image/hvm/ramdisk", &def->os.initrd) < 0) + goto no_memory; + if (sexpr_node_copy(node, "domain/image/hvm/args", &def->os.cmdline) < 0) + goto no_memory; + if (sexpr_node_copy(node, "domain/image/hvm/root", &def->os.root) < 0) + goto no_memory; + } + } else { + if (sexpr_node_copy(node, "domain/image/linux/kernel", &def->os.kernel) < 0) + goto no_memory; + if (sexpr_node_copy(node, "domain/image/linux/ramdisk", &def->os.initrd) < 0) + goto no_memory; + if (sexpr_node_copy(node, "domain/image/linux/args", &def->os.cmdline) < 0) + goto no_memory; + if (sexpr_node_copy(node, "domain/image/linux/root", &def->os.root) < 0) + goto no_memory; + } + + /* If HVM kenrel == loader, then old xend, so kill off kernel */ + if (hvm && + def->os.kernel && + STREQ(def->os.kernel, def->os.loader)) { + VIR_FREE(def->os.kernel); + } + + if (!def->os.kernel && + hvm) { + const char *boot = sexpr_node(node, "domain/image/hvm/boot"); + if ((boot != NULL) && (boot[0] != 0)) { + while (*boot && + def->os.nBootDevs < VIR_DOMAIN_BOOT_LAST) { + if (*boot == 'a') + def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_FLOPPY; + else if (*boot == 'c') + def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_DISK; + else if (*boot == 'd') + def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_CDROM; + else if (*boot == 'n') + def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_NET; + boot++; + } + } + } + + if (!hvm && + !def->os.kernel && + !def->os.bootloader) { + virXendError(xend, VIR_ERR_INTERNAL_ERROR, + _("domain information incomplete, missing kernel & bootloader")); + return -1; + } + + return 0; + +no_memory: + virXendError(xend, VIR_ERR_NO_MEMORY, NULL); + return -1; } @@ -1538,36 +1527,170 @@ return ret; } -typedef int - (*sexp_blockdevs_cb) - (virConnectPtr conn, void *data, - int isBlock, int cdrom, int isNoSrcCdrom, int hvm, - const char *drvName, const char *drvType, - const char *src, const char *dst, - const char *mode); - -/** - * xend_parse_sexp_blockdevs: +static virDomainChrDefPtr +xenDaemonParseSxprChar(virConnectPtr conn, + const char *value, + const char *tty) +{ + char prefix[10]; + char *tmp; + virDomainChrDefPtr def; + + if (VIR_ALLOC(def) < 0) { + virXendError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + strncpy(prefix, value, sizeof(prefix)-1); + NUL_TERMINATE(prefix); + + if (value[0] == '/') { + def->type = VIR_DOMAIN_CHR_TYPE_DEV; + } else { + if ((tmp = strchr(prefix, ':')) != NULL) { + *tmp = '\0'; + value += (tmp - prefix) + 1; + } + + if (STREQ(prefix, "telnet")) { + def->type = VIR_DOMAIN_CHR_TYPE_TCP; + def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET; + } else { + if ((def->type = virDomainChrTypeFromString(prefix)) < 0) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown chr device type '%s'"), prefix); + goto error; + } + } + } + + /* Compat with legacy <console tty='/dev/pts/5'/> syntax */ + switch (def->type) { + case VIR_DOMAIN_CHR_TYPE_PTY: + if (tty != NULL && + !(def->data.file.path = strdup(tty))) + goto no_memory; + break; + + case VIR_DOMAIN_CHR_TYPE_FILE: + case VIR_DOMAIN_CHR_TYPE_PIPE: + if (!(def->data.file.path = strdup(value))) + goto no_memory; + break; + + case VIR_DOMAIN_CHR_TYPE_TCP: + { + const char *offset = strchr(value, ':'); + const char *offset2; + + if (offset == NULL) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("malformed char device string")); + goto error; + } + + if (offset != value && + (def->data.tcp.host = strndup(value, offset - value)) == NULL) + goto no_memory; + + offset2 = strchr(offset, ','); + if (offset2 == NULL) + def->data.tcp.service = strdup(offset+1); + else + def->data.tcp.service = strndup(offset+1, offset2-(offset+1)); + if (def->data.tcp.service == NULL) + goto no_memory; + + if (offset2 && strstr(offset2, ",listen")) + def->data.tcp.listen = 1; + } + break; + + case VIR_DOMAIN_CHR_TYPE_UDP: + { + const char *offset = strchr(value, ':'); + const char *offset2, *offset3; + + if (offset == NULL) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("malformed char device string")); + goto error; + } + + if (offset != value && + (def->data.udp.connectHost = strndup(value, offset - value)) == NULL) + goto no_memory; + + offset2 = strchr(offset, '@'); + if (offset2 != NULL) { + if ((def->data.udp.connectService = strndup(offset + 1, offset2-(offset+1))) == NULL) + goto no_memory; + + offset3 = strchr(offset2, ':'); + if (offset3 == NULL) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("malformed char device string")); + goto error; + } + + if (offset3 > (offset2 + 1) && + (def->data.udp.bindHost = strndup(offset2 + 1, offset3 - (offset2+1))) == NULL) + goto no_memory; + + if ((def->data.udp.bindService = strdup(offset3 + 1)) == NULL) + goto no_memory; + } else { + if ((def->data.udp.connectService = strdup(offset + 1)) == NULL) + goto no_memory; + } + } + break; + + case VIR_DOMAIN_CHR_TYPE_UNIX: + { + const char *offset = strchr(value, ','); + if (offset) + def->data.nix.path = strndup(value, (offset - value)); + else + def->data.nix.path = strdup(value); + if (def->data.nix.path == NULL) + goto no_memory; + + if (offset != NULL && + strstr(offset, ",listen") != NULL) + def->data.nix.listen = 1; + } + break; + } + + return def; + +no_memory: + virXendError(conn, VIR_ERR_NO_MEMORY, NULL); +error: + virDomainChrDefFree(def); + return NULL; +} + +/** + * xend_parse_sexp_desc_disks * @conn: connection * @root: root sexpr * @xendConfigVersion: version of xend - * @fn: callback function - * @data: optional data for callback function - * - * This parses out block devices from the domain sexpr and calls - * fn (conn, data, ...) for each block device found. + * + * This parses out block devices from the domain sexpr * * Returns 0 if successful or -1 if failed. */ static int -xend_parse_sexp_blockdevs (virConnectPtr conn, struct sexpr *root, - int xendConfigVersion, - sexp_blockdevs_cb fn, void *data) +xenDaemonParseSxprDisks(virConnectPtr conn, + virDomainDefPtr def, + struct sexpr *root, + int hvm, + int xendConfigVersion) { struct sexpr *cur, *node; - int hvm; - - hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0; + virDomainDiskDefPtr disk = NULL, prev = def->disks; for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) { node = cur->u.s.car; @@ -1577,12 +1700,6 @@ if (sexpr_lookup(node, "device/vbd") || sexpr_lookup(node, "device/tap")) { char *offset; - int ret = -1; - int isBlock = 0; - int cdrom = 0; - int isNoSrcCdrom = 0; - char *drvName = NULL; - char *drvType = NULL; const char *src = NULL; const char *dst = NULL; const char *mode = NULL; @@ -1598,84 +1715,84 @@ mode = sexpr_node(node, "device/tap/mode"); } + if (VIR_ALLOC(disk) < 0) + goto no_memory; + if (dst == NULL) { virXendError(conn, VIR_ERR_INTERNAL_ERROR, _("domain information incomplete, vbd has no dev")); - goto bad_parse; + goto error; } if (src == NULL) { /* There is a case without the uname to the CD-ROM device */ offset = strchr(dst, ':'); - if (offset) { - if (hvm && STREQ(offset, ":cdrom")) { - isNoSrcCdrom = 1; - } - offset[0] = '\0'; - } - if (!isNoSrcCdrom) { + if (!offset || + !hvm || + STRNEQ(offset, ":cdrom")) { virXendError(conn, VIR_ERR_INTERNAL_ERROR, _("domain information incomplete, vbd has no src")); - goto bad_parse; - } - } - - if (!isNoSrcCdrom) { + goto error; + } + } + + if (src != NULL) { offset = strchr(src, ':'); if (!offset) { virXendError(conn, VIR_ERR_INTERNAL_ERROR, _("cannot parse vbd filename, missing driver name")); - goto bad_parse; - } - - if (VIR_ALLOC_N(drvName, (offset-src)+1) < 0) { - virXendError(conn, VIR_ERR_NO_MEMORY, - _("allocate new buffer")); - goto bad_parse; - } - strncpy(drvName, src, (offset-src)); - drvName[offset-src] = '\0'; + goto error; + } + + if (VIR_ALLOC_N(disk->driverName, (offset-src)+1) < 0) + goto no_memory; + strncpy(disk->driverName, src, (offset-src)); + disk->driverName[offset-src] = '\0'; src = offset + 1; - if (STREQ (drvName, "tap")) { + if (STREQ (disk->driverName, "tap")) { offset = strchr(src, ':'); if (!offset) { virXendError(conn, VIR_ERR_INTERNAL_ERROR, _("cannot parse vbd filename, missing driver type")); - goto bad_parse; + goto error; } - if (VIR_ALLOC_N(drvType, (offset-src)+1)< 0) { - virXendError(conn, VIR_ERR_NO_MEMORY, - _("allocate new buffer")); - goto bad_parse; - } - strncpy(drvType, src, (offset-src)); - drvType[offset-src] = '\0'; + if (VIR_ALLOC_N(disk->driverType, (offset-src)+1)< 0) + goto no_memory; + strncpy(disk->driverType, src, (offset-src)); + disk->driverType[offset-src] = '\0'; + src = offset + 1; /* Its possible to use blktap driver for block devs too, but kinda pointless because blkback is better, so we assume common case here. If blktap becomes omnipotent, we can revisit this, perhaps stat()'ing the src file in question */ - isBlock = 0; - } else if (STREQ(drvName, "phy")) { - isBlock = 1; - } else if (STREQ(drvName, "file")) { - isBlock = 0; - } + disk->type = VIR_DOMAIN_DISK_TYPE_FILE; + } else if (STREQ(disk->driverName, "phy")) { + disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK; + } else if (STREQ(disk->driverName, "file")) { + disk->type = VIR_DOMAIN_DISK_TYPE_FILE; + } + } else { + /* No CDROM media so can't really tell. We'll just + call if a FILE for now and update when media + is inserted later */ + disk->type = VIR_DOMAIN_DISK_TYPE_FILE; } if (STREQLEN (dst, "ioemu:", 6)) dst += 6; + disk->device = VIR_DOMAIN_DISK_DEVICE_DISK; /* New style disk config from Xen >= 3.0.3 */ if (xendConfigVersion > 1) { offset = strrchr(dst, ':'); if (offset) { if (STREQ (offset, ":cdrom")) { - cdrom = 1; + disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; } else if (STREQ (offset, ":disk")) { /* The default anyway */ } else { @@ -1685,458 +1802,697 @@ } } - /* Call the callback function. */ - ret = fn (conn, data, isBlock, cdrom, isNoSrcCdrom, hvm, - drvName, drvType, src, dst, mode); - - bad_parse: - VIR_FREE(drvName); - VIR_FREE(drvType); - - if (ret == -1) return -1; - } - } - - return 0; -} - -static int -xend_parse_sexp_desc_blockdev (virConnectPtr conn ATTRIBUTE_UNUSED, - void *data, - int isBlock, int cdrom, int isNoSrcCdrom, - int hvm, - const char *drvName, const char *drvType, - const char *src, const char *dst, - const char *mode) -{ - virBuffer *buf = (virBuffer *) data; - const char *bus = NULL; - - if (!isNoSrcCdrom) { - virBufferVSprintf(buf, " <disk type='%s' device='%s'>\n", - isBlock ? "block" : "file", - cdrom ? "cdrom" : "disk"); - if (drvType) { - virBufferVSprintf(buf, " <driver name='%s' type='%s'/>\n", drvName, drvType); - } else { - virBufferVSprintf(buf, " <driver name='%s'/>\n", drvName); - } - if (isBlock) { - virBufferVSprintf(buf, " <source dev='%s'/>\n", src); - } else { - virBufferVSprintf(buf, " <source file='%s'/>\n", src); - } - } else { - /* This case is the cdrom device only */ - virBufferAddLit(buf, " <disk device='cdrom'>\n"); - } - if (STRPREFIX(dst, "xvd") || !hvm) { - bus = "xen"; - } else if (STRPREFIX(dst, "sd")) { - bus = "scsi"; - } else { - bus = "ide"; - } - virBufferVSprintf(buf, " <target dev='%s' bus='%s'/>\n", - dst, bus); - - /* XXX should we force mode == r, if cdrom==1, or assume - xend has already done this ? */ - if ((mode != NULL) && (STREQ (mode, "r"))) - virBufferAddLit(buf, " <readonly/>\n"); - else if ((mode != NULL) && (STREQ (mode, "w!"))) - virBufferAddLit(buf, " <shareable/>\n"); - virBufferAddLit(buf, " </disk>\n"); - - return 0; -} - -/** - * xend_parse_sexp_desc: - * @conn: the connection associated with the XML - * @root: the root of the parsed S-Expression - * @xendConfigVersion: version of xend - * @flags: a combination of virDomainXMLFlags - * @cpus: set of cpus the domain may be pinned to - * - * Parse the xend sexp description and turn it into the XML format similar - * to the one unsed for creation. - * - * Returns the 0 terminated XML string or NULL in case of error. - * the caller must free() the returned value. - */ -static char * -xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root, - int xendConfigVersion, int flags, const char *cpus) -{ + if (!(disk->dst = strdup(dst))) + goto no_memory; + if (src && + !(disk->src = strdup(src))) + goto no_memory; + + if (STRPREFIX(disk->dst, "xvd")) + disk->bus = VIR_DOMAIN_DISK_BUS_XEN; + else if (STRPREFIX(disk->dst, "hd")) + disk->bus = VIR_DOMAIN_DISK_BUS_IDE; + else if (STRPREFIX(disk->dst, "sd")) + disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; + else + disk->bus = VIR_DOMAIN_DISK_BUS_IDE; + + if (mode && + strchr(mode, 'r')) + disk->readonly = 1; + if (mode && + strchr(mode, '!')) + disk->shared = 1; + + if (prev) + prev->next = disk; + else + def->disks = disk; + + prev = disk; + disk = NULL; + } + } + + return 0; + +no_memory: + virXendError(conn, VIR_ERR_NO_MEMORY, NULL); + +error: + virDomainDiskDefFree(disk); + return -1; +} + + +static int +xenDaemonParseSxprNets(virConnectPtr conn, + virDomainDefPtr def, + struct sexpr *root) +{ + virDomainNetDefPtr net = NULL, prev = def->nets; struct sexpr *cur, *node; const char *tmp; - char *tty, *val; - virBuffer buf = VIR_BUFFER_INITIALIZER; - int hvm = 0, bootloader = 0, vfb = 0; - int domid = -1; - int max_mem, cur_mem; - unsigned char uuid[VIR_UUID_BUFLEN]; - char uuidstr[VIR_UUID_STRING_BUFLEN]; int vif_index = 0; - if (root == NULL) { - /* ERROR */ - return (NULL); - } - - tmp = sexpr_node(root, "domain/domid"); - if (tmp == NULL && xendConfigVersion < 3) { /* Old XenD, domid was mandatory */ - virXendError(conn, VIR_ERR_INTERNAL_ERROR, - _("domain information incomplete, missing id")); - goto error; - } - if (tmp) - domid = sexpr_int(root, "domain/domid"); - else - domid = -1; - virBufferVSprintf(&buf, "<domain type='xen' id='%d'>\n", domid); - - tmp = sexpr_node(root, "domain/name"); - if (tmp == NULL) { - virXendError(conn, VIR_ERR_INTERNAL_ERROR, - _("domain information incomplete, missing name")); - goto error; - } - virBufferVSprintf(&buf, " <name>%s</name>\n", tmp); - tmp = sexpr_node(root, "domain/uuid"); - if (tmp == NULL) { - virXendError(conn, VIR_ERR_INTERNAL_ERROR, - _("domain information incomplete, missing name")); - goto error; - } - virUUIDParse(tmp, uuid); - virUUIDFormat(uuid, uuidstr); - virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr); - - hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0; - if (!hvm) { - tmp = sexpr_node(root, "domain/bootloader"); - if (tmp != NULL) { - bootloader = 1; - virBufferVSprintf(&buf, " <bootloader>%s</bootloader>\n", tmp); - } else if (sexpr_has(root, "domain/bootloader")) { - bootloader = 1; - virBufferAddLit(&buf, " <bootloader/>\n"); - } - tmp = sexpr_node(root, "domain/bootloader_args"); - if (tmp != NULL && bootloader) { - /* - * Only insert bootloader_args if there is also a bootloader param - */ - virBufferEscapeString(&buf, " <bootloader_args>%s</bootloader_args>\n", tmp); - } - } - - if (domid != 0) { - if (sexpr_lookup(root, "domain/image")) { - if (xend_parse_sexp_desc_os(conn, root, &buf, hvm, bootloader) < 0) - goto error; - } - } - - max_mem = (int) (sexpr_u64(root, "domain/maxmem") << 10); - cur_mem = (int) (sexpr_u64(root, "domain/memory") << 10); - if (cur_mem > max_mem) - max_mem = cur_mem; - virBufferVSprintf(&buf, " <memory>%d</memory>\n", max_mem); - if ((cur_mem >= MIN_XEN_GUEST_SIZE) && (cur_mem != max_mem)) - virBufferVSprintf(&buf, " <currentMemory>%d</currentMemory>\n", - cur_mem); - - virBufferAddLit(&buf, " <vcpu"); - if (cpus != NULL) { - virBufferVSprintf(&buf, " cpuset='%s'", cpus); - } - virBufferVSprintf(&buf, ">%d</vcpu>\n", - sexpr_int(root, "domain/vcpus")); - /* TODO if need to output the cpus values, - * - parse the cpus values if xend exports - * or - * - analyze the cpus values extracted by xenDaemonDomainGetVcpus - */ - tmp = sexpr_node(root, "domain/on_poweroff"); - if (tmp != NULL) - virBufferVSprintf(&buf, " <on_poweroff>%s</on_poweroff>\n", tmp); - tmp = sexpr_node(root, "domain/on_reboot"); - if (tmp != NULL) - virBufferVSprintf(&buf, " <on_reboot>%s</on_reboot>\n", tmp); - tmp = sexpr_node(root, "domain/on_crash"); - if (tmp != NULL) - virBufferVSprintf(&buf, " <on_crash>%s</on_crash>\n", tmp); - - if (hvm) { - int clockLocal; - - virBufferAddLit(&buf, " <features>\n"); - if (sexpr_int(root, "domain/image/hvm/acpi")) - virBufferAddLit(&buf, " <acpi/>\n"); - if (sexpr_int(root, "domain/image/hvm/apic")) - virBufferAddLit(&buf, " <apic/>\n"); - if (sexpr_int(root, "domain/image/hvm/pae")) - virBufferAddLit(&buf, " <pae/>\n"); - virBufferAddLit(&buf, " </features>\n"); - - clockLocal = sexpr_int(root, "domain/image/hvm/localtime"); - virBufferVSprintf(&buf, " <clock offset='%s'/>\n", clockLocal ? "localtime" : "utc"); - } - - virBufferAddLit(&buf, " <devices>\n"); - - if (hvm) - tmp = sexpr_node(root, "domain/image/hvm/device_model"); - else - tmp = sexpr_node(root, "domain/image/linux/device_model"); - if ((tmp != NULL) && (tmp[0] != 0)) - virBufferVSprintf(&buf, " <emulator>%s</emulator>\n", tmp); - - /* append block devices */ - if (xend_parse_sexp_blockdevs (conn, root, xendConfigVersion, - xend_parse_sexp_desc_blockdev, &buf) == -1) - goto error; - - /* append network devices and framebuffer */ for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) { node = cur->u.s.car; if (sexpr_lookup(node, "device/vif")) { const char *tmp2, *model; + char buf[50]; tmp2 = sexpr_node(node, "device/vif/script"); tmp = sexpr_node(node, "device/vif/bridge"); model = sexpr_node(node, "device/vif/model"); + + if (VIR_ALLOC(net) < 0) + goto no_memory; + if ((tmp2 && strstr(tmp2, "bridge")) || tmp) { - virBufferAddLit(&buf, " <interface type='bridge'>\n"); - if (tmp != NULL) - virBufferVSprintf(&buf, " <source bridge='%s'/>\n", - tmp); - } else { - virBufferAddLit(&buf, " <interface type='ethernet'>\n"); + net->type = VIR_DOMAIN_NET_TYPE_BRIDGE; + /* XXX virtual network reverse resolve */ + + if (tmp && + !(net->data.bridge.brname = strdup(tmp))) + goto no_memory; + } else { + net->type = VIR_DOMAIN_NET_TYPE_ETHERNET; } tmp = sexpr_node(node, "device/vif/vifname"); - if (tmp) - virBufferVSprintf(&buf, " <target dev='%s'/>\n", - tmp); - else - virBufferVSprintf(&buf, " <target dev='vif%d.%d'/>\n", - domid, vif_index); + if (!tmp) { + snprintf(buf, sizeof(buf), "vif%d.%d", def->id, vif_index); + tmp = buf; + } + if (!(net->ifname = strdup(tmp))) + goto no_memory; + tmp = sexpr_node(node, "device/vif/mac"); - if (tmp) - virBufferVSprintf(&buf, " <mac address='%s'/>\n", - tmp); + if (tmp) { + unsigned int mac[6]; + sscanf(tmp, "%02x:%02x:%02x:%02x:%02x:%02x", + (unsigned int*)&mac[0], + (unsigned int*)&mac[1], + (unsigned int*)&mac[2], + (unsigned int*)&mac[3], + (unsigned int*)&mac[4], + (unsigned int*)&mac[5]); + net->mac[0] = mac[0]; + net->mac[1] = mac[1]; + net->mac[2] = mac[2]; + net->mac[3] = mac[3]; + net->mac[4] = mac[4]; + net->mac[5] = mac[5]; + } + tmp = sexpr_node(node, "device/vif/ip"); - if (tmp) - virBufferVSprintf(&buf, " <ip address='%s'/>\n", - tmp); - if (tmp2) - virBufferVSprintf(&buf, " <script path='%s'/>\n", - tmp2); - - if (model) - virBufferVSprintf(&buf, " <model type='%s'/>\n", - model); - - virBufferAddLit(&buf, " </interface>\n"); + if (tmp && + !(net->data.ethernet.ipaddr = strdup(tmp))) + goto no_memory; + + if (tmp2 && + net->type == VIR_DOMAIN_NET_TYPE_ETHERNET && + !(net->data.ethernet.script = strdup(tmp2))) + goto no_memory; + + if (model && + !(net->model = strdup(model))) + goto no_memory; + + if (prev) + prev->next = net; + else + def->nets = net; vif_index++; - } else if (sexpr_lookup(node, "device/vfb")) { + } + } + + return 0; + +no_memory: + virXendError(conn, VIR_ERR_NO_MEMORY, NULL); + virDomainNetDefFree(net); + return -1; +} + +static int +xenDaemonParseSxprSound(virConnectPtr conn, + virDomainDefPtr def, + const char *str) +{ + if (STREQ(str, "all")) { + int i; + virDomainSoundDefPtr prev = NULL; + for (i = 0 ; i < VIR_DOMAIN_SOUND_MODEL_LAST ; i++) { + virDomainSoundDefPtr sound; + if (VIR_ALLOC(sound) < 0) + goto no_memory; + sound->model = i; + if (prev) + prev->next = sound; + else + def->sounds = sound; + prev = sound; + } + } else { + char model[10]; + const char *offset = str, *offset2; + virDomainSoundDefPtr prev = NULL; + do { + int len; + virDomainSoundDefPtr sound; + offset2 = strchr(offset, ','); + if (offset2) + len = (offset2 - offset); + else + len = strlen(offset); + if (len > (sizeof(model)-1)) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected sound model %s"), offset); + goto error; + } + strncpy(model, offset, len); + model[len] = '\0'; + + if (VIR_ALLOC(sound) < 0) + goto no_memory; + + if ((sound->model = virDomainSoundModelTypeFromString(model)) < 0) { + VIR_FREE(sound); + goto error; + } + + if (prev) + prev->next = sound; + else + def->sounds = sound; + prev = sound; + offset = offset2 ? offset2 + 1 : NULL; + } while (offset); + } + + return 0; + +no_memory: + virXendError(conn, VIR_ERR_NO_MEMORY, NULL); +error: + return -1; +} + + +static int +xenDaemonParseSxprUSB(virConnectPtr conn, + virDomainDefPtr def, + struct sexpr *root) +{ + virDomainInputDefPtr prev = def->inputs; + struct sexpr *cur, *node; + const char *tmp; + + for (cur = sexpr_lookup(root, "domain/image/hvm"); cur && cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) { + node = cur->u.s.car; + if (sexpr_lookup(node, "usbdevice")) { + tmp = sexpr_node(node, "usbdevice"); + if (tmp && *tmp) { + if (STREQ(tmp, "tablet") || + STREQ(tmp, "mouse")) { + virDomainInputDefPtr input; + if (VIR_ALLOC(input) < 0) + goto no_memory; + input->bus = VIR_DOMAIN_INPUT_BUS_USB; + if (STREQ(tmp, "tablet")) + input->type = VIR_DOMAIN_INPUT_TYPE_TABLET; + else + input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE; + + if (prev) + prev->next = input; + else + def->inputs = input; + prev = input; + } else { + /* XXX Handle other non-input USB devices later */ + } + } + } + } + return 0; + +no_memory: + virXendError(conn, VIR_ERR_NO_MEMORY, NULL); + return -1; +} + +static int +xenDaemonParseSxprGraphicsOld(virConnectPtr conn, + virDomainDefPtr def, + struct sexpr *root, + int hvm, + int xendConfigVersion) +{ + const char *tmp; + virDomainGraphicsDefPtr graphics = NULL; + + if ((tmp = sexpr_fmt_node(root, "domain/image/%s/vnc", hvm ? "hvm" : "linux")) && + tmp[0] == '1') { + /* Graphics device (HVM, or old (pre-3.0.4) style PV VNC config) */ + int port = xenStoreDomainGetVNCPort(conn, def->id); + const char *listenAddr = sexpr_fmt_node(root, "domain/image/%s/vnclisten", hvm ? "hvm" : "linux"); + const char *vncPasswd = sexpr_fmt_node(root, "domain/image/%s/vncpasswd", hvm ? "hvm" : "linux"); + const char *keymap = sexpr_fmt_node(root, "domain/image/%s/keymap", hvm ? "hvm" : "linux"); + const char *unused = sexpr_fmt_node(root, "domain/image/%s/vncunused", hvm ? "hvm" : "linux"); + + if (VIR_ALLOC(graphics) < 0) + goto no_memory; + + graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC; + /* For Xen >= 3.0.3, don't generate a fixed port mapping + * because it will almost certainly be wrong ! Just leave + * it as -1 which lets caller see that the VNC server isn't + * present yet. Subsquent dumps of the XML will eventually + * find the port in XenStore once VNC server has started + */ + if (port == -1 && xendConfigVersion < 2) + port = 5900 + def->id; + + if ((unused && STREQ(unused, "1")) || port == -1) + graphics->data.vnc.autoport = 1; + graphics->data.vnc.port = port; + + if (listenAddr && + !(graphics->data.vnc.listenAddr = strdup(listenAddr))) + goto no_memory; + + if (vncPasswd && + !(graphics->data.vnc.passwd = strdup(vncPasswd))) + goto no_memory; + + if (keymap && + !(graphics->data.vnc.keymap = strdup(keymap))) + goto no_memory; + + def->graphics = graphics; + } else if ((tmp = sexpr_fmt_node(root, "domain/image/%s/sdl", hvm ? "hvm" : "linux")) && + tmp[0] == '1') { + /* Graphics device (HVM, or old (pre-3.0.4) style PV sdl config) */ + const char *display = sexpr_fmt_node(root, "domain/image/%s/display", hvm ? "hvm" : "linux"); + const char *xauth = sexpr_fmt_node(root, "domain/image/%s/xauthority", hvm ? "hvm" : "linux"); + + if (VIR_ALLOC(graphics) < 0) + goto no_memory; + + graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL; + if (display && + !(graphics->data.sdl.display = strdup(display))) + goto no_memory; + if (xauth && + !(graphics->data.sdl.xauth = strdup(xauth))) + goto no_memory; + + def->graphics = graphics; + } + + return 0; + +no_memory: + virXendError(conn, VIR_ERR_NO_MEMORY, NULL); + virDomainGraphicsDefFree(graphics); + return -1; +} + + +static int +xenDaemonParseSxprGraphicsNew(virConnectPtr conn, + virDomainDefPtr def, + struct sexpr *root) +{ + virDomainGraphicsDefPtr graphics = NULL; + struct sexpr *cur, *node; + const char *tmp; + + /* append network devices and framebuffer */ + for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) { + node = cur->u.s.car; + if (sexpr_lookup(node, "device/vfb")) { /* New style graphics config for PV guests in >= 3.0.4, * or for HVM guests in >= 3.0.5 */ tmp = sexpr_node(node, "device/vfb/type"); - if (tmp && STREQ(tmp, "sdl")) { - vfb = 1; - virBufferVSprintf(&buf, " <input type='mouse' bus='%s'/>\n", hvm ? "ps2": "xen"); - virBufferAddLit(&buf, " <graphics type='sdl'/>\n"); - } else if (tmp && STREQ(tmp, "vnc")) { - int port = xenStoreDomainGetVNCPort(conn, domid); + if (VIR_ALLOC(graphics) < 0) + goto no_memory; + + if ((graphics->type = virDomainGraphicsTypeFromString(tmp)) < 0) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown graphics type '%s'"), tmp); + goto error; + } + + if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) { + const char *display = sexpr_node(node, "device/vfb/display"); + const char *xauth = sexpr_node(node, "device/vfb/xauthority"); + if (display && + !(graphics->data.sdl.display = strdup(display))) + goto no_memory; + if (xauth && + !(graphics->data.sdl.xauth = strdup(xauth))) + goto no_memory; + } else { + int port = xenStoreDomainGetVNCPort(conn, def->id); const char *listenAddr = sexpr_node(node, "device/vfb/vnclisten"); - const char *vncPasswd = NULL; + const char *vncPasswd = sexpr_node(node, "device/vfb/vncpasswd");; const char *keymap = sexpr_node(node, "device/vfb/keymap"); - vfb = 1; - virBufferVSprintf(&buf, " <input type='mouse' bus='%s'/>\n", hvm ? "ps2": "xen"); - virBufferVSprintf(&buf, " <graphics type='vnc' port='%d'", port); - if (listenAddr) - virBufferVSprintf(&buf, " listen='%s'", listenAddr); - if (flags & VIR_DOMAIN_XML_SECURE) { - vncPasswd = sexpr_node(node, "device/vfb/vncpasswd"); - if (vncPasswd) - virBufferVSprintf(&buf, " passwd='%s'", vncPasswd); - } - if (keymap) - virBufferVSprintf(&buf, " keymap='%s'", keymap); - virBufferAddLit(&buf, "/>\n"); - } - } - } + const char *unused = sexpr_node(node, "device/vfb/vncunused"); + + if ((unused && STREQ(unused, "1")) || port == -1) + graphics->data.vnc.autoport = 1; + graphics->data.vnc.port = port; + + if (listenAddr && + !(graphics->data.vnc.listenAddr = strdup(listenAddr))) + goto no_memory; + + if (vncPasswd && + !(graphics->data.vnc.passwd = strdup(vncPasswd))) + goto no_memory; + + if (keymap && + !(graphics->data.vnc.keymap = strdup(keymap))) + goto no_memory; + } + + def->graphics = graphics; + break; + } + } + + return 0; + +no_memory: + virXendError(conn, VIR_ERR_NO_MEMORY, NULL); +error: + virDomainGraphicsDefFree(graphics); + return -1; +} + + +/** + * xenDaemonParseSxpr: + * @conn: the connection associated with the XML + * @root: the root of the parsed S-Expression + * @xendConfigVersion: version of xend + * @cpus: set of cpus the domain may be pinned to + * + * Parse the xend sexp description and turn it into the XML format similar + * to the one unsed for creation. + * + * Returns the 0 terminated XML string or NULL in case of error. + * the caller must free() the returned value. + */ +static virDomainDefPtr +xenDaemonParseSxpr(virConnectPtr conn, + struct sexpr *root, + int xendConfigVersion, + const char *cpus) +{ + const char *tmp; + virDomainDefPtr def; + int hvm = 0; + char *tty = NULL; + + if (VIR_ALLOC(def) < 0) + goto no_memory; + + tmp = sexpr_node(root, "domain/domid"); + if (tmp == NULL && xendConfigVersion < 3) { /* Old XenD, domid was mandatory */ + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("domain information incomplete, missing id")); + goto error; + } + def->virtType = VIR_DOMAIN_VIRT_XEN; + if (tmp) + def->id = sexpr_int(root, "domain/domid"); + else + def->id = -1; + + if (sexpr_node_copy(root, "domain/name", &def->name) < 0) + goto no_memory; + if (def->name == NULL) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("domain information incomplete, missing name")); + goto error; + } + + tmp = sexpr_node(root, "domain/uuid"); + if (tmp == NULL) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("domain information incomplete, missing name")); + goto error; + } + virUUIDParse(tmp, def->uuid); + + hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0; + if (!hvm) { + if (sexpr_node_copy(root, "domain/bootloader", + &def->os.bootloader) < 0) + goto no_memory; + + if (!def->os.bootloader && + sexpr_has(root, "domain/bootloader") && + (def->os.bootloader = strdup("")) == NULL) + goto no_memory; + + if (def->os.bootloader && + sexpr_node_copy(root, "domain/bootloader_args", + &def->os.bootloaderArgs) < 0) + goto no_memory; + } + + if (!(def->os.type = strdup(hvm ? "hvm" : "linux"))) + goto no_memory; + + if (def->id != 0) { + if (sexpr_lookup(root, "domain/image")) { + if (xenDaemonParseSxprOS(conn, root, def, hvm) < 0) + goto error; + } + } + + def->maxmem = (unsigned long) (sexpr_u64(root, "domain/maxmem") << 10); + def->memory = (unsigned long) (sexpr_u64(root, "domain/memory") << 10); + if (def->memory > def->maxmem) + def->maxmem = def->memory; + + if (cpus != NULL) { + if (virDomainCpuSetParse(conn, &cpus, + 0, def->cpumask, + def->cpumasklen) < 0) + goto error; + } + def->vcpus = sexpr_int(root, "domain/vcpus"); + + tmp = sexpr_node(root, "domain/on_poweroff"); + if (tmp != NULL) { + if ((def->onPoweroff = virDomainLifecycleTypeFromString(tmp)) < 0) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown lifecycle type %s"), tmp); + goto error; + } + } else + def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY; + + tmp = sexpr_node(root, "domain/on_reboot"); + if (tmp != NULL) { + if ((def->onReboot = virDomainLifecycleTypeFromString(tmp)) < 0) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown lifecycle type %s"), tmp); + goto error; + } + } else + def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART; + + tmp = sexpr_node(root, "domain/on_crash"); + if (tmp != NULL) { + if ((def->onCrash = virDomainLifecycleTypeFromString(tmp)) < 0) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown lifecycle type %s"), tmp); + goto error; + } + } else + def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY; + if (hvm) { - tmp = sexpr_node(root, "domain/image/hvm/fda"); + if (sexpr_int(root, "domain/image/hvm/acpi")) + def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI); + if (sexpr_int(root, "domain/image/hvm/apic")) + def->features |= (1 << VIR_DOMAIN_FEATURE_APIC); + if (sexpr_int(root, "domain/image/hvm/pae")) + def->features |= (1 << VIR_DOMAIN_FEATURE_PAE); + + if (sexpr_int(root, "domain/image/hvm/localtime")) + def->localtime = 1; + } + + if (sexpr_node_copy(root, hvm ? + "domain/image/hvm/device_model" : + "domain/image/linux/device_model", + &def->emulator) < 0) + goto no_memory; + + /* append block devices */ + if (xenDaemonParseSxprDisks(conn, def, root, hvm, xendConfigVersion) < 0) + goto error; + + if (xenDaemonParseSxprNets(conn, def, root) < 0) + goto error; + + /* New style graphics device config */ + if (xenDaemonParseSxprGraphicsNew(conn, def, root) < 0) + goto error; + + /* Graphics device (HVM <= 3.0.4, or PV <= 3.0.3) vnc config */ + if (!def->graphics && + xenDaemonParseSxprGraphicsOld(conn, def, root, hvm, xendConfigVersion) < 0) + goto error; + + + /* Old style cdrom config from Xen <= 3.0.2 */ + if (hvm && + xendConfigVersion == 1) { + tmp = sexpr_node(root, "domain/image/hvm/cdrom"); if ((tmp != NULL) && (tmp[0] != 0)) { - virBufferAddLit(&buf, " <disk type='file' device='floppy'>\n"); - virBufferVSprintf(&buf, " <source file='%s'/>\n", tmp); - virBufferAddLit(&buf, " <target dev='fda' bus='fdc'/>\n"); - virBufferAddLit(&buf, " </disk>\n"); - } - tmp = sexpr_node(root, "domain/image/hvm/fdb"); - if ((tmp != NULL) && (tmp[0] != 0)) { - virBufferAddLit(&buf, " <disk type='file' device='floppy'>\n"); - virBufferVSprintf(&buf, " <source file='%s'/>\n", tmp); - virBufferAddLit(&buf, " <target dev='fdb' bus='fdc'/>\n"); - virBufferAddLit(&buf, " </disk>\n"); - } - - /* Old style cdrom config from Xen <= 3.0.2 */ - if (xendConfigVersion == 1) { - tmp = sexpr_node(root, "domain/image/hvm/cdrom"); + virDomainDiskDefPtr disk, prev; + if (VIR_ALLOC(disk) < 0) + goto no_memory; + if (!(disk->src = strdup(tmp))) { + VIR_FREE(disk); + goto no_memory; + } + disk->type = VIR_DOMAIN_DISK_TYPE_FILE; + disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; + if (!(disk->dst = strdup("hdc"))) { + VIR_FREE(disk); + goto no_memory; + } + if (!(disk->driverName = strdup("file"))) { + VIR_FREE(disk); + goto no_memory; + } + disk->bus = VIR_DOMAIN_DISK_BUS_IDE; + disk->readonly = 1; + + prev = def->disks; + while (prev && prev->next) { + prev = prev->next; + } + if (prev) + prev->next = disk; + else + def->disks = disk; + } + } + + + /* Floppy disk config */ + if (hvm) { + const char *const fds[] = { "fda", "fdb" }; + int i; + for (i = 0 ; i < sizeof(fds)/sizeof(fds[0]) ; i++) { + tmp = sexpr_fmt_node(root, "domain/image/hvm/%s", fds[i]); if ((tmp != NULL) && (tmp[0] != 0)) { - virBufferAddLit(&buf, " <disk type='file' device='cdrom'>\n"); - virBufferAddLit(&buf, " <driver name='file'/>\n"); - virBufferVSprintf(&buf, " <source file='%s'/>\n", tmp); - virBufferAddLit(&buf, " <target dev='hdc' bus='ide'/>\n"); - virBufferAddLit(&buf, " <readonly/>\n"); - virBufferAddLit(&buf, " </disk>\n"); - } - } - } - - /* in case of HVM we have devices emulation */ - if (hvm) { - for (cur = sexpr_lookup(root, "domain/image/hvm"); cur && cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) { - node = cur->u.s.car; - if (sexpr_lookup(node, "usbdevice")) { - tmp = sexpr_node(node, "usbdevice"); - if (tmp && *tmp) { - if (STREQ(tmp, "tablet")) - virBufferAddLit(&buf, " <input type='tablet' bus='usb'/>\n"); - else if (STREQ(tmp, "mouse")) - virBufferAddLit(&buf, " <input type='mouse' bus='usb'/>\n"); - } - } - } - } - - /* Graphics device (HVM <= 3.0.4, or PV <= 3.0.3) vnc config */ - if (!vfb) { - tmp = sexpr_fmt_node(root, "domain/image/%s/vnc", hvm ? "hvm" : "linux"); - if (tmp != NULL) { - if (tmp[0] == '1') { - int port = xenStoreDomainGetVNCPort(conn, domid); - const char *listenAddr = sexpr_fmt_node(root, "domain/image/%s/vnclisten", hvm ? "hvm" : "linux"); - const char *vncPasswd = NULL; - const char *keymap = sexpr_fmt_node(root, "domain/image/%s/keymap", hvm ? "hvm" : "linux"); - /* For Xen >= 3.0.3, don't generate a fixed port mapping - * because it will almost certainly be wrong ! Just leave - * it as -1 which lets caller see that the VNC server isn't - * present yet. Subsquent dumps of the XML will eventually - * find the port in XenStore once VNC server has started - */ - if (port == -1 && xendConfigVersion < 2) - port = 5900 + domid; - virBufferVSprintf(&buf, " <input type='mouse' bus='%s'/>\n", hvm ? "ps2" : "xen"); - virBufferVSprintf(&buf, " <graphics type='vnc' port='%d'", port); - if (listenAddr) - virBufferVSprintf(&buf, " listen='%s'", listenAddr); - if (flags & VIR_DOMAIN_XML_SECURE) { - vncPasswd = sexpr_fmt_node(root, "domain/image/%s/vncpasswd", hvm ? "hvm" : "linux"); - if (vncPasswd) - virBufferVSprintf(&buf, " passwd='%s'", vncPasswd); - } - if (keymap) - virBufferVSprintf(&buf, " keymap='%s'", keymap); - virBufferAddLit(&buf, "/>\n"); - } - } - - /* Graphics device (HVM, or old (pre-3.0.4) style PV sdl config) */ - tmp = sexpr_fmt_node(root, "domain/image/%s/sdl", hvm ? "hvm" : "linux"); - if (tmp != NULL) { - if (tmp[0] == '1') { - virBufferVSprintf(&buf, " <input type='mouse' bus='%s'/>\n", hvm ? "ps2" : "xen"); - virBufferAddLit(&buf, " <graphics type='sdl'/>\n"); - } - } - } - - tty = xenStoreDomainGetConsolePath(conn, domid); + virDomainDiskDefPtr disk, prev; + if (VIR_ALLOC(disk) < 0) + goto no_memory; + if (!(disk->src = strdup(tmp))) { + VIR_FREE(disk); + goto no_memory; + } + disk->type = VIR_DOMAIN_DISK_TYPE_FILE; + disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY; + if (!(disk->dst = strdup(fds[i]))) { + VIR_FREE(disk); + goto no_memory; + } + if (!(disk->driverName = strdup("file"))) { + VIR_FREE(disk); + goto no_memory; + } + disk->bus = VIR_DOMAIN_DISK_BUS_FDC; + + prev = def->disks; + while (prev && prev->next) { + prev = prev->next; + } + if (prev) + prev->next = disk; + else + def->disks = disk; + } + } + } + + /* in case of HVM we have USB device emulation */ + if (hvm && + xenDaemonParseSxprUSB(conn, def, root) < 0) + goto error; + + /* Character device config */ + tty = xenStoreDomainGetConsolePath(conn, def->id); if (hvm) { tmp = sexpr_node(root, "domain/image/hvm/serial"); if (tmp && STRNEQ(tmp, "none")) { - if (xend_parse_sexp_desc_char(conn, &buf, "serial", 0, tmp, tty) < 0) - goto error; - /* Add back-compat <console/> tag for primary console */ - if (xend_parse_sexp_desc_char(conn, &buf, "console", 0, tmp, tty) < 0) + if ((def->serials = xenDaemonParseSxprChar(conn, tmp, tty)) == NULL) goto error; } tmp = sexpr_node(root, "domain/image/hvm/parallel"); if (tmp && STRNEQ(tmp, "none")) { /* XXX does XenD stuff parallel port tty info into xenstore somewhere ? */ - if (xend_parse_sexp_desc_char(conn, &buf, "parallel", 0, tmp, NULL) < 0) - goto error; - } - } else { - /* Paravirt always has a console */ - if (tty) { - virBufferVSprintf(&buf, " <console type='pty' tty='%s'>\n", tty); - virBufferVSprintf(&buf, " <source path='%s'/>\n", tty); - } else { - virBufferAddLit(&buf, " <console type='pty'>\n"); - } - virBufferAddLit(&buf, " <target port='0'/>\n"); - virBufferAddLit(&buf, " </console>\n"); + if ((def->parallels = xenDaemonParseSxprChar(conn, tmp, NULL)) == NULL) + goto error; + } + } else { + /* Fake a paravirt console, since that's not in the sexpr */ + if (!(def->console = xenDaemonParseSxprChar(conn, "pty", tty))) + goto error; } VIR_FREE(tty); - if (hvm) { - if (sexpr_node(root, "domain/image/hvm/soundhw")) { - char *soundxml; - tmp = sexpr_node(root, "domain/image/hvm/soundhw"); - if (tmp && *tmp) { - if ((soundxml = sound_string_to_xml(tmp))) { - virBufferVSprintf(&buf, "%s", soundxml); - VIR_FREE(soundxml); - } else { - virXendError(conn, VIR_ERR_INTERNAL_ERROR, - _("parsing soundhw string failed.")); - goto error; - } - } - } - } - - virBufferAddLit(&buf, " </devices>\n"); - virBufferAddLit(&buf, "</domain>\n"); - - if (virBufferError(&buf)) { - virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer")); - return NULL; - } - - return virBufferContentAndReset(&buf); - - error: - val = virBufferContentAndReset(&buf); - VIR_FREE(val); - return (NULL); -} - -char * -xend_parse_domain_sexp(virConnectPtr conn, char *sexpr, int xendConfigVersion) { - struct sexpr *root = string2sexpr(sexpr); - char *data; - - if (!root) - return NULL; - - data = xend_parse_sexp_desc(conn, root, xendConfigVersion, 0, NULL); - - sexpr_free(root); - - return data; -} + + /* Sound device config */ + if (hvm && + (tmp = sexpr_node(root, "domain/image/hvm/soundhw")) != NULL && + *tmp) { + if (xenDaemonParseSxprSound(conn, def, tmp) < 0) + goto error; + } + + return def; + +no_memory: + virXendError(conn, VIR_ERR_NO_MEMORY, NULL); +error: + VIR_FREE(tty); + virDomainDefFree(def); + return NULL; +} + +virDomainDefPtr +xenDaemonParseSxprString(virConnectPtr conn, + const char *sexpr, + int xendConfigVersion) +{ + struct sexpr *root = string2sexpr(sexpr); + virDomainDefPtr def; + + if (!root) + return NULL; + + def = xenDaemonParseSxpr(conn, root, xendConfigVersion, NULL); + + sexpr_free(root); + + return def; +} + /** * sexpr_to_xend_domain_info: @@ -2864,6 +3220,7 @@ char *ret = NULL; struct sexpr *root; xenUnifiedPrivatePtr priv; + virDomainDefPtr def; root = sexpr_get(conn, "/xend/domain/%d?detail=1", domid); if (root == NULL) { @@ -2875,9 +3232,15 @@ priv = (xenUnifiedPrivatePtr) conn->privateData; - ret = xend_parse_sexp_desc(conn, root, priv->xendConfigVersion, - flags, cpus); - sexpr_free(root); + if (!(def = xenDaemonParseSxpr(conn, root, priv->xendConfigVersion, + cpus))) + goto cleanup; + + ret = virDomainDefFormat(conn, def, flags); + +cleanup: + sexpr_free(root); + virDomainDefFree(def); return (ret); } @@ -2889,6 +3252,7 @@ char *ret = NULL; struct sexpr *root; xenUnifiedPrivatePtr priv; + virDomainDefPtr def; root = sexpr_get(conn, "/xend/domain/%s?detail=1", name); if (root == NULL) { @@ -2900,9 +3264,15 @@ priv = (xenUnifiedPrivatePtr) conn->privateData; - ret = xend_parse_sexp_desc(conn, root, priv->xendConfigVersion, - flags, cpus); - sexpr_free(root); + if (!(def = xenDaemonParseSxpr(conn, root, priv->xendConfigVersion, + cpus))) + goto cleanup; + + ret = virDomainDefFormat(conn, def, flags); + +cleanup: + sexpr_free(root); + virDomainDefFree(def); return (ret); } @@ -4339,29 +4709,6 @@ return (ret); } -struct check_path_data { - const char *path; - int ok; -}; - -static int -check_path (virConnectPtr conn ATTRIBUTE_UNUSED, void *vp, - int isBlock ATTRIBUTE_UNUSED, - int cdrom, int isNoSrcCdrom, - int hvm ATTRIBUTE_UNUSED, - const char *drvName ATTRIBUTE_UNUSED, - const char *drvType ATTRIBUTE_UNUSED, - const char *src, const char *dst ATTRIBUTE_UNUSED, - const char *mode ATTRIBUTE_UNUSED) -{ - struct check_path_data *data = (struct check_path_data *) vp; - - if (!isNoSrcCdrom && !cdrom && src && STREQ (src, data->path)) - data->ok = 1; - - return 0; -} - /** * xenDaemonDomainBlockPeek: * @dom: domain object @@ -4378,9 +4725,11 @@ void *buffer) { xenUnifiedPrivatePtr priv; - struct sexpr *root; - struct check_path_data data; - int fd, ret = -1; + struct sexpr *root = NULL; + int fd = -1, ret = -1; + int found = 0; + virDomainDefPtr def; + virDomainDiskDefPtr disk; priv = (xenUnifiedPrivatePtr) domain->conn->privateData; @@ -4406,18 +4755,22 @@ return -1; } - data.path = path; - data.ok = 0; - - if (xend_parse_sexp_blockdevs (domain->conn, root, - priv->xendConfigVersion, - check_path, &data) == -1) - return -1; - - if (!data.ok) { + if (!(def = xenDaemonParseSxpr(domain->conn, root, priv->xendConfigVersion, NULL))) + goto cleanup; + + disk = def->disks; + while (disk) { + if (disk->src && + STREQ(disk->src, path)) { + found = 1; + break; + } + disk = disk->next; + } + if (!found) { virXendError (domain->conn, VIR_ERR_INVALID_ARG, _("%s: invalid path"), path); - return -1; + goto cleanup; } /* The path is correct, now try to open it and get its size. */ @@ -4426,7 +4779,7 @@ virXendError (domain->conn, VIR_ERR_SYSTEM_ERROR, _("failed to open for reading: %s: %s"), path, strerror (errno)); - goto done; + goto cleanup; } /* Seek and read. */ @@ -4438,12 +4791,14 @@ virXendError (domain->conn, VIR_ERR_SYSTEM_ERROR, _("failed to lseek or read from file: %s: %s"), path, strerror (errno)); - goto done; - } - - ret = 0; - done: + goto cleanup; + } + + ret = 0; + cleanup: if (fd >= 0) close (fd); + sexpr_free(root); + virDomainDefFree(def); return ret; } diff -r 3dea6bbe639b src/xend_internal.h --- a/src/xend_internal.h Thu Jul 03 11:42:42 2008 +0100 +++ b/src/xend_internal.h Thu Jul 03 12:50:05 2008 +0100 @@ -20,6 +20,7 @@ #include "libvirt/libvirt.h" #include "capabilities.h" +#include "domain_conf.h" #include "buf.h" #ifdef __cplusplus @@ -100,7 +101,10 @@ const char *value, const char *tty); - char *xend_parse_domain_sexp(virConnectPtr conn, char *root, int xendConfigVersion); +virDomainDefPtr +xenDaemonParseSxprString(virConnectPtr conn, + const char *sexpr, + int xendConfigVersion); int is_sound_model_valid(const char *model); int is_sound_model_conflict(const char *model, const char *soundstr); diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-curmem.xml --- a/tests/sexpr2xmldata/sexpr2xml-curmem.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-curmem.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,6 +1,9 @@ <domain type='xen' id='5'> <name>rhel5</name> <uuid>4f77abd2-3019-58e8-3bab-6fbf2118f880</uuid> + <memory>394240</memory> + <currentMemory>179200</currentMemory> + <vcpu>1</vcpu> <bootloader>/usr/bin/pygrub</bootloader> <os> <type>linux</type> @@ -8,9 +11,7 @@ <initrd>/var/lib/xen/initrd.gULTf1</initrd> <cmdline>ro root=/dev/VolGroup00/LogVol00 rhgb quiet</cmdline> </os> - <memory>394240</memory> - <currentMemory>179200</currentMemory> - <vcpu>1</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> @@ -21,15 +22,14 @@ <target dev='xvda' bus='xen'/> </disk> <interface type='bridge'> + <mac address='00:16:3e:1d:06:15'/> <source bridge='xenbr0'/> <target dev='vif5.0'/> - <mac address='00:16:3e:1d:06:15'/> - <script path='vif-bridge'/> </interface> - <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1'/> <console type='pty'> <target port='0'/> </console> + <input type='mouse' bus='xen'/> + <graphics type='vnc' port='-1' autoport='yes'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml --- a/tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,10 +1,14 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>49a0c6ff-c066-5392-6498-3632d093c2e7</uuid> - <bootloader>/usr/bin/pygrub</bootloader> <memory>524288</memory> <currentMemory>393216</currentMemory> <vcpu>1</vcpu> + <bootloader>/usr/bin/pygrub</bootloader> + <os> + <type>linux</type> + </os> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> @@ -16,10 +20,9 @@ <shareable/> </disk> <interface type='bridge'> + <mac address='00:16:3e:23:9e:eb'/> <source bridge='xenbr0'/> <target dev='vif6.0'/> - <mac address='00:16:3e:23:9e:eb'/> - <script path='vif-bridge'/> </interface> <console type='pty'> <target port='0'/> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-disk-block.xml --- a/tests/sexpr2xmldata/sexpr2xml-disk-block.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-disk-block.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,14 +1,16 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu>2</vcpu> <os> <type>linux</type> <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... </cmdline> </os> - <memory>430080</memory> - <vcpu>2</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-qcow.xml --- a/tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-qcow.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-qcow.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,14 +1,16 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu>2</vcpu> <os> <type>linux</type> <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... </cmdline> </os> - <memory>430080</memory> - <vcpu>2</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-raw.xml --- a/tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-raw.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-disk-drv-blktap-raw.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,14 +1,16 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu>2</vcpu> <os> <type>linux</type> <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... </cmdline> </os> - <memory>430080</memory> - <vcpu>2</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-disk-file.xml --- a/tests/sexpr2xmldata/sexpr2xml-disk-file.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-disk-file.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,14 +1,16 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu>2</vcpu> <os> <type>linux</type> <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... </cmdline> </os> - <memory>430080</memory> - <vcpu>2</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,6 +1,9 @@ <domain type='xen' id='15'> <name>fvtest</name> <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu>2</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> @@ -8,14 +11,10 @@ <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... </cmdline> </os> - <memory>430080</memory> - <vcpu>2</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> - <features> - </features> - <clock offset='utc'/> <devices> <disk type='file' device='disk'> <driver name='file'/> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='1'> <name>s10u4</name> <uuid>fde0533d-d043-88c6-dfba-4822fa32f309</uuid> + <memory>1048576</memory> + <currentMemory>1048576</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>1048576</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <pae/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <interface type='ethernet'> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='3'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='localtime'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,19 +23,18 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif3.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif3.0'/> + </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5903' keymap='ja'/> + <graphics type='vnc' port='5903' autoport='no' keymap='ja'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='1'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,24 +23,23 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif1.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5901'/> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif1.0'/> + </interface> <parallel type='tcp'> <source mode='connect' host='localhost' service='9999'/> <protocol type='raw'/> <target port='0'/> </parallel> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='5901' autoport='no'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='1'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,20 +23,17 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif1.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5901'/> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif1.0'/> + </interface> <serial type='file'> <source path='/tmp/serial.log'/> <target port='0'/> @@ -44,5 +42,7 @@ <source path='/tmp/serial.log'/> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='5901' autoport='no'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='1'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,25 +23,24 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif1.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5901'/> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif1.0'/> + </interface> <serial type='null'> <target port='0'/> </serial> <console type='null'> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='5901' autoport='no'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='1'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,20 +23,17 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif1.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5901'/> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif1.0'/> + </interface> <serial type='pipe'> <source path='/tmp/serial.pipe'/> <target port='0'/> @@ -44,5 +42,7 @@ <source path='/tmp/serial.pipe'/> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='5901' autoport='no'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='1'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,25 +23,24 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif1.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5901'/> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif1.0'/> + </interface> <serial type='pty'> <target port='0'/> </serial> <console type='pty'> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='5901' autoport='no'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='1'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,25 +23,24 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif1.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5901'/> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif1.0'/> + </interface> <serial type='stdio'> <target port='0'/> </serial> <console type='stdio'> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='5901' autoport='no'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='1'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,20 +23,17 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif1.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5901'/> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif1.0'/> + </interface> <serial type='tcp'> <source mode='bind' host='localhost' service='9999'/> <protocol type='telnet'/> @@ -46,5 +44,7 @@ <protocol type='telnet'/> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='5901' autoport='no'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='1'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,20 +23,17 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif1.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5901'/> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif1.0'/> + </interface> <serial type='tcp'> <source mode='bind' host='localhost' service='9999'/> <protocol type='raw'/> @@ -46,5 +44,7 @@ <protocol type='raw'/> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='5901' autoport='no'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='1'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,29 +23,28 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif1.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5901'/> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif1.0'/> + </interface> <serial type='udp'> + <source mode='bind' host='localhost' service='9999'/> <source mode='connect' host='localhost' service='9998'/> - <source mode='bind' host='localhost' service='9999'/> <target port='0'/> </serial> <console type='udp'> + <source mode='bind' host='localhost' service='9999'/> <source mode='connect' host='localhost' service='9998'/> - <source mode='bind' host='localhost' service='9999'/> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='5901' autoport='no'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='1'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,20 +23,17 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif1.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5901'/> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif1.0'/> + </interface> <serial type='unix'> <source mode='bind' path='/tmp/serial.sock'/> <target port='0'/> @@ -44,5 +42,7 @@ <source mode='bind' path='/tmp/serial.sock'/> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='5901' autoport='no'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-sound-all.sexpr --- a/tests/sexpr2xmldata/sexpr2xml-fv-sound-all.sexpr Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-sound-all.sexpr Thu Jul 03 12:50:05 2008 +0100 @@ -1,1 +1,1 @@ -(domain (domid 3)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(device_model '/usr/lib64/xen/bin/qemu-dm')(boot c)(cdrom '/root/boot.iso')(acpi 1)(vnc 1)(keymap ja)(soundhw 'idontexit,es1370,all')))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) +(domain (domid 3)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(device_model '/usr/lib64/xen/bin/qemu-dm')(boot c)(cdrom '/root/boot.iso')(acpi 1)(vnc 1)(keymap ja)(soundhw 'all')))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-sound-all.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-sound-all.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-sound-all.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='3'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,21 +23,21 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif3.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif3.0'/> + </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5903' keymap='ja'/> + <graphics type='vnc' port='5903' autoport='no' keymap='ja'/> <sound model='sb16'/> <sound model='es1370'/> + <sound model='pcspk'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-sound.sexpr --- a/tests/sexpr2xmldata/sexpr2xml-fv-sound.sexpr Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-sound.sexpr Thu Jul 03 12:50:05 2008 +0100 @@ -1,1 +1,1 @@ -(domain (domid 3)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(device_model '/usr/lib64/xen/bin/qemu-dm')(boot c)(cdrom '/root/boot.iso')(acpi 1)(vnc 1)(keymap ja)(soundhw 'sb16,es1370,idontexist,es1370more')))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) +(domain (domid 3)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(device_model '/usr/lib64/xen/bin/qemu-dm')(boot c)(cdrom '/root/boot.iso')(acpi 1)(vnc 1)(keymap ja)(soundhw 'sb16,es1370')))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-sound.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-sound.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-sound.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='3'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,20 +23,19 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif3.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif3.0'/> + </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5903' keymap='ja'/> + <graphics type='vnc' port='5903' autoport='no' keymap='ja'/> <sound model='sb16'/> <sound model='es1370'/> </devices> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='3'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,20 +23,19 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif3.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif3.0'/> + </interface> <input type='mouse' bus='usb'/> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5903' keymap='ja'/> + <graphics type='vnc' port='5903' autoport='no' keymap='ja'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='3'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,20 +23,19 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif3.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif3.0'/> + </interface> <input type='tablet' bus='usb'/> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5903' keymap='ja'/> + <graphics type='vnc' port='5903' autoport='no' keymap='ja'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-utc.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-utc.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-utc.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='3'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,19 +23,18 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif3.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif3.0'/> + </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5903' keymap='ja'/> + <graphics type='vnc' port='5903' autoport='no' keymap='ja'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-v2.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv-v2.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-v2.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='3'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='cdrom'> @@ -29,12 +30,11 @@ <target dev='hda' bus='ide'/> </disk> <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> <source bridge='xenbr0'/> <target dev='vif3.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' keymap='ja'/> + <graphics type='vnc' port='-1' autoport='yes' keymap='ja'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv.xml --- a/tests/sexpr2xmldata/sexpr2xml-fv.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='3'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'> @@ -22,19 +23,18 @@ <source file='/root/foo.img'/> <target dev='hda' bus='ide'/> </disk> - <interface type='bridge'> - <source bridge='xenbr0'/> - <target dev='vif3.0'/> - <mac address='00:16:3e:1b:b1:47'/> - <script path='vif-bridge'/> - </interface> <disk type='file' device='cdrom'> <driver name='file'/> <source file='/root/boot.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> + <interface type='bridge'> + <mac address='00:16:3e:1b:b1:47'/> + <source bridge='xenbr0'/> + <target dev='vif3.0'/> + </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='5903' keymap='ja'/> + <graphics type='vnc' port='5903' autoport='no' keymap='ja'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-net-bridged.xml --- a/tests/sexpr2xmldata/sexpr2xml-net-bridged.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-net-bridged.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,14 +1,16 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu>2</vcpu> <os> <type>linux</type> <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... </cmdline> </os> - <memory>430080</memory> - <vcpu>2</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> @@ -19,10 +21,9 @@ <target dev='xvda' bus='xen'/> </disk> <interface type='bridge'> + <mac address='00:11:22:33:44:55'/> <source bridge='xenbr2'/> <target dev='vif6.0'/> - <mac address='00:11:22:33:44:55'/> - <script path='vif-bridge'/> </interface> <console type='pty'> <target port='0'/> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-net-e1000.xml --- a/tests/sexpr2xmldata/sexpr2xml-net-e1000.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-net-e1000.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,14 +1,16 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu>2</vcpu> <os> <type>linux</type> <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... </cmdline> </os> - <memory>430080</memory> - <vcpu>2</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> @@ -19,10 +21,9 @@ <target dev='xvda' bus='xen'/> </disk> <interface type='bridge'> + <mac address='00:11:22:33:44:55'/> <source bridge='xenbr2'/> <target dev='vif6.0'/> - <mac address='00:11:22:33:44:55'/> - <script path='vif-bridge'/> <model type='e1000'/> </interface> <console type='pty'> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-net-routed.xml --- a/tests/sexpr2xmldata/sexpr2xml-net-routed.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-net-routed.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,14 +1,16 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu>2</vcpu> <os> <type>linux</type> <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... </cmdline> </os> - <memory>430080</memory> - <vcpu>2</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> @@ -19,10 +21,10 @@ <target dev='xvda' bus='xen'/> </disk> <interface type='ethernet'> - <target dev='vif6.0'/> <mac address='00:11:22:33:44:55'/> <ip address='172.14.5.6'/> <script path='vif-routed'/> + <target dev='vif6.0'/> </interface> <console type='pty'> <target port='0'/> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml --- a/tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,23 +1,23 @@ <domain type='xen' id='6'> <name>test</name> <uuid>cc2315e7-d26a-307a-438c-6d188ec4c09c</uuid> + <memory>391168</memory> + <currentMemory>358400</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>391168</memory> - <currentMemory>358400</currentMemory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>destroy</on_reboot> - <on_crash>destroy</on_crash> <features> <acpi/> <apic/> <pae/> </features> <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -25,22 +25,22 @@ <source dev='/dev/sda8'/> <target dev='hda' bus='ide'/> </disk> - <disk device='cdrom'> + <disk type='file' device='cdrom'> <target dev='hdc' bus='ide'/> <readonly/> </disk> <interface type='bridge'> + <mac address='00:16:3e:0a:7b:39'/> <source bridge='xenbr0'/> <target dev='vif6.0'/> - <mac address='00:16:3e:0a:7b:39'/> </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1'/> <serial type='pty'> <target port='0'/> </serial> <console type='pty'> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-pv-bootloader.xml --- a/tests/sexpr2xmldata/sexpr2xml-pv-bootloader.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-pv-bootloader.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,10 +1,15 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu>2</vcpu> <bootloader>/usr/bin/pypxeboot</bootloader> <bootloader_args>mac=AA:00:86:e2:35:72</bootloader_args> - <memory>430080</memory> - <vcpu>2</vcpu> + <os> + <type>linux</type> + </os> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml --- a/tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-pv-vfb-new.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,14 +1,16 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu>2</vcpu> <os> <type>linux</type> <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... </cmdline> </os> - <memory>430080</memory> - <vcpu>2</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> @@ -18,10 +20,10 @@ <source file='/root/some.img'/> <target dev='xvda' bus='xen'/> </disk> - <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1' listen='0.0.0.0' keymap='ja'/> <console type='pty'> <target port='0'/> </console> + <input type='mouse' bus='xen'/> + <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' keymap='ja'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml --- a/tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-pv-vfb-orig.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,14 +1,16 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu>2</vcpu> <os> <type>linux</type> <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... </cmdline> </os> - <memory>430080</memory> - <vcpu>2</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> @@ -18,10 +20,10 @@ <source file='/root/some.img'/> <target dev='xvda' bus='xen'/> </disk> - <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1' listen='0.0.0.0' keymap='ja'/> <console type='pty'> <target port='0'/> </console> + <input type='mouse' bus='xen'/> + <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' keymap='ja'/> </devices> </domain> diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-pv.xml --- a/tests/sexpr2xmldata/sexpr2xml-pv.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-pv.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,14 +1,16 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu>2</vcpu> <os> <type>linux</type> <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... </cmdline> </os> - <memory>430080</memory> - <vcpu>2</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> diff -r 3dea6bbe639b tests/sexpr2xmltest.c --- a/tests/sexpr2xmltest.c Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmltest.c Thu Jul 03 12:50:05 2008 +0100 @@ -24,19 +24,19 @@ char *xmlPtr = &(xmlData[0]); char *sexprPtr = &(sexprData[0]); int ret = -1; + virDomainDefPtr def = NULL; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) { - printf("Missing %s\n", xml); + if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) goto fail; - } - if (virtTestLoadFile(sexpr, &sexprPtr, MAX_FILE) < 0) { - printf("Missing %s\n", sexpr); + if (virtTestLoadFile(sexpr, &sexprPtr, MAX_FILE) < 0) goto fail; - } - if (!(gotxml = xend_parse_domain_sexp(NULL, sexprData, xendConfigVersion))) - goto fail; + if (!(def = xenDaemonParseSxprString(NULL, sexprData, xendConfigVersion))) + goto fail; + + if (!(gotxml = virDomainDefFormat(NULL, def, 0))) + goto fail; if (STRNEQ(xmlData, gotxml)) { virtTestDifference(stderr, xmlData, gotxml); @@ -47,6 +47,7 @@ fail: free(gotxml); + virDomainDefFree(def); return ret; } @@ -122,7 +123,7 @@ DO_TEST("fv-utc", "fv-utc", 1); DO_TEST("fv-localtime", "fv-localtime", 1); DO_TEST("fv-usbmouse", "fv-usbmouse", 1); - DO_TEST("fv-usbmouse", "fv-usbmouse", 1); + DO_TEST("fv-usbtablet", "fv-usbtablet", 1); DO_TEST("fv-kernel", "fv-kernel", 1); DO_TEST("fv-serial-null", "fv-serial-null", 1); -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Tue, Jul 08, 2008 at 05:38:41PM +0100, Daniel P. Berrange wrote:
This replaces the code which converts from the SEXPR into XML with code which converts from the SEXPR to virDomainDefPtr object. We then simply call virDomainDefFormat() to generate the XML. The generated XML is thus guarenteed consistent with the QEMU driver & others using domain_conf.c routines.
Nearly all of the XML files had to be updated because the generic XML formatter outputs various elements in an alternate order than the Xen driver did.
okay
+int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst) +{ + const char *val = sexpr_node(sexpr, node); + + if (val) { + *dst = strdup(val);
Hum we really ought to use the new macros here and raise the error, no ?
+ if (!(*dst)) + return -1; + } else { + *dst = NULL; + } + return 0; +} + + [...] - const char *boot = sexpr_node(node, "domain/image/hvm/boot"); - if ((boot != NULL) && (boot[0] != 0)) { - while (*boot) { - if (*boot == 'a') - /* XXX no way to deal with boot from 2nd floppy */ - virBufferAddLit(buf, " <boot dev='fd'/>\n"); - else if (*boot == '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 - */ - virBufferAddLit(buf, " <boot dev='hd'/>\n"); - else if (*boot == 'd') - virBufferAddLit(buf, " <boot dev='cdrom'/>\n"); - else if (*boot == 'n') - virBufferAddLit(buf, " <boot dev='network'/>\n"); - boot++; - } - }
Hum, the logic in virDomainDefFormat() seems rather different, I hope this won't lead to too many regressions. [...]
+ if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.kernel) < 0) + goto no_memory;
so you raise the memory issue here, i guess that's fine too.
+ if (!def->os.kernel && + hvm) { + const char *boot = sexpr_node(node, "domain/image/hvm/boot"); + if ((boot != NULL) && (boot[0] != 0)) { + while (*boot && + def->os.nBootDevs < VIR_DOMAIN_BOOT_LAST) { + if (*boot == 'a') + def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_FLOPPY; + else if (*boot == 'c') + def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_DISK; + else if (*boot == 'd') + def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_CDROM; + else if (*boot == 'n') + def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_NET; + boot++; + } + } + }
okay, the same logic is actually carried that way, fine. [...]
+ if (tmp) { + unsigned int mac[6]; + sscanf(tmp, "%02x:%02x:%02x:%02x:%02x:%02x", + (unsigned int*)&mac[0], + (unsigned int*)&mac[1], + (unsigned int*)&mac[2], + (unsigned int*)&mac[3], + (unsigned int*)&mac[4], + (unsigned int*)&mac[5]);
checking that the call returned 6 could be a good idea.
+ net->mac[0] = mac[0]; + net->mac[1] = mac[1]; + net->mac[2] = mac[2]; + net->mac[3] = mac[3]; + net->mac[4] = mac[4]; + net->mac[5] = mac[5]; + } + [...] + if (tmp && + !(net->data.ethernet.ipaddr = strdup(tmp))) + goto no_memory;
hum, VIR_STRDUP macro and a hook into VIR_ALLOC would be good, at least it would allow to regression tests on out of memory situations in that part which is checked as part of make check. But that can be done separately of course.
diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-curmem.xml --- a/tests/sexpr2xmldata/sexpr2xml-curmem.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-curmem.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,6 +1,9 @@ <domain type='xen' id='5'> <name>rhel5</name> <uuid>4f77abd2-3019-58e8-3bab-6fbf2118f880</uuid> + <memory>394240</memory> + <currentMemory>179200</currentMemory> + <vcpu>1</vcpu> <bootloader>/usr/bin/pygrub</bootloader> <os> <type>linux</type> @@ -8,9 +11,7 @@ <initrd>/var/lib/xen/initrd.gULTf1</initrd> <cmdline>ro root=/dev/VolGroup00/LogVol00 rhgb quiet</cmdline> </os> - <memory>394240</memory> - <currentMemory>179200</currentMemory> - <vcpu>1</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> @@ -21,15 +22,14 @@ <target dev='xvda' bus='xen'/> </disk> <interface type='bridge'> + <mac address='00:16:3e:1d:06:15'/> <source bridge='xenbr0'/> <target dev='vif5.0'/> - <mac address='00:16:3e:1d:06:15'/> - <script path='vif-bridge'/> </interface> - <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1'/> <console type='pty'> <target port='0'/> </console> + <input type='mouse' bus='xen'/> + <graphics type='vnc' port='-1' autoport='yes'/> </devices> </domain>
Hum, I guess the automatic addition of <clock offset='utc'/> , <input type='mouse' bus='xen'/> and <graphics type='vnc' port='-1' autoport='yes'/> aren't a problem, i.e. not changing the default behaviour, but it seems we are loosing the <script path='vif-bridge'/> information on the way out, and that looks significant, right ?
diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml --- a/tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,10 +1,14 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>49a0c6ff-c066-5392-6498-3632d093c2e7</uuid> - <bootloader>/usr/bin/pygrub</bootloader> <memory>524288</memory> <currentMemory>393216</currentMemory> <vcpu>1</vcpu> + <bootloader>/usr/bin/pygrub</bootloader> + <os> + <type>linux</type> + </os>
pygrub probanly means a linux boot right, but
- <script path='vif-bridge'/>
lost script again. [...]
+++ b/tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='3'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='localtime'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'>
We create currentMemory from memory value or I'm mistaken ? [...]
diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-sound-all.sexpr --- a/tests/sexpr2xmldata/sexpr2xml-fv-sound-all.sexpr Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-sound-all.sexpr Thu Jul 03 12:50:05 2008 +0100 @@ -1,1 +1,1 @@ -(domain (domid 3)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(device_model '/usr/lib64/xen/bin/qemu-dm')(boot c)(cdrom '/root/boot.iso')(acpi 1)(vnc 1)(keymap ja)(soundhw 'idontexit,es1370,all')))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) +(domain (domid 3)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(device_model '/usr/lib64/xen/bin/qemu-dm')(boot c)(cdrom '/root/boot.iso')(acpi 1)(vnc 1)(keymap ja)(soundhw 'all')))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
hum hard to decript, but here it seems we lost the value of the sound emulation, going from 'idontexit,es1370,all' to 'all' this looks fishy
diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-sound.sexpr --- a/tests/sexpr2xmldata/sexpr2xml-fv-sound.sexpr Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-sound.sexpr Thu Jul 03 12:50:05 2008 +0100 @@ -1,1 +1,1 @@ -(domain (domid 3)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(device_model '/usr/lib64/xen/bin/qemu-dm')(boot c)(cdrom '/root/boot.iso')(acpi 1)(vnc 1)(keymap ja)(soundhw 'sb16,es1370,idontexist,es1370more')))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) +(domain (domid 3)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(device_model '/usr/lib64/xen/bin/qemu-dm')(boot c)(cdrom '/root/boot.iso')(acpi 1)(vnc 1)(keymap ja)(soundhw 'sb16,es1370')))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
Same thing soundhw went from 'sb16,es1370,idontexist,es1370more' to 'sb16,es1370', it's a bit weird Okidoc, so it looks basically okay to me except the loss of the network bridging script and the strange thing happening to sound hardware descriptions. Maybe the simplest is to commit and fix the 2 issues after with a second patch because rereviewing the whole is while just a few lines need fixing sounds inefficient :-) Excellent thing that we have all those regression tests on the SXP<->XML data !!! thanks ! Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

On Thu, Jul 24, 2008 at 08:24:32AM -0400, Daniel Veillard wrote:
On Tue, Jul 08, 2008 at 05:38:41PM +0100, Daniel P. Berrange wrote:
- const char *boot = sexpr_node(node, "domain/image/hvm/boot"); - if ((boot != NULL) && (boot[0] != 0)) { - while (*boot) { - if (*boot == 'a') - /* XXX no way to deal with boot from 2nd floppy */ - virBufferAddLit(buf, " <boot dev='fd'/>\n"); - else if (*boot == '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 - */ - virBufferAddLit(buf, " <boot dev='hd'/>\n"); - else if (*boot == 'd') - virBufferAddLit(buf, " <boot dev='cdrom'/>\n"); - else if (*boot == 'n') - virBufferAddLit(buf, " <boot dev='network'/>\n"); - boot++; - } - }
Hum, the logic in virDomainDefFormat() seems rather different, I hope this won't lead to too many regressions.
Yep, fortunately we have pretty good test coverage of the XML parsing & formatting for Xen drivers, so it should catch most of the problems :-)
[...]
+ if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.kernel) < 0) + goto no_memory;
so you raise the memory issue here, i guess that's fine too.
Yep, I added a 'sexpr_node_copy' convenience method to catch OOM conditions more easily.
[...]
+ if (tmp) { + unsigned int mac[6]; + sscanf(tmp, "%02x:%02x:%02x:%02x:%02x:%02x", + (unsigned int*)&mac[0], + (unsigned int*)&mac[1], + (unsigned int*)&mac[2], + (unsigned int*)&mac[3], + (unsigned int*)&mac[4], + (unsigned int*)&mac[5]);
checking that the call returned 6 could be a good idea.
Good point.
+ net->mac[0] = mac[0]; + net->mac[1] = mac[1]; + net->mac[2] = mac[2]; + net->mac[3] = mac[3]; + net->mac[4] = mac[4]; + net->mac[5] = mac[5]; + } + [...] + if (tmp && + !(net->data.ethernet.ipaddr = strdup(tmp))) + goto no_memory;
hum, VIR_STRDUP macro and a hook into VIR_ALLOC would be good, at least it would allow to regression tests on out of memory situations in that part which is checked as part of make check. But that can be done separately of course.
That's a nice idea - I'll cook up a patch to do add a VIR_STRDUP later.
diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-curmem.xml --- a/tests/sexpr2xmldata/sexpr2xml-curmem.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-curmem.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,6 +1,9 @@ <domain type='xen' id='5'> <name>rhel5</name> <uuid>4f77abd2-3019-58e8-3bab-6fbf2118f880</uuid> + <memory>394240</memory> + <currentMemory>179200</currentMemory> + <vcpu>1</vcpu> <bootloader>/usr/bin/pygrub</bootloader> <os> <type>linux</type> @@ -8,9 +11,7 @@ <initrd>/var/lib/xen/initrd.gULTf1</initrd> <cmdline>ro root=/dev/VolGroup00/LogVol00 rhgb quiet</cmdline> </os> - <memory>394240</memory> - <currentMemory>179200</currentMemory> - <vcpu>1</vcpu> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> @@ -21,15 +22,14 @@ <target dev='xvda' bus='xen'/> </disk> <interface type='bridge'> + <mac address='00:16:3e:1d:06:15'/> <source bridge='xenbr0'/> <target dev='vif5.0'/> - <mac address='00:16:3e:1d:06:15'/> - <script path='vif-bridge'/> </interface> - <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1'/> <console type='pty'> <target port='0'/> </console> + <input type='mouse' bus='xen'/> + <graphics type='vnc' port='-1' autoport='yes'/> </devices> </domain>
Hum, I guess the automatic addition of <clock offset='utc'/> , <input type='mouse' bus='xen'/> and <graphics type='vnc' port='-1' autoport='yes'/> aren't a problem, i.e. not changing the default behaviour, but it seems we are loosing the <script path='vif-bridge'/> information on the way out, and that looks significant, right ?
The reason the <graphics> and <input> elements are added here is because of a bug in the test suite - the sexpr2xmldatatest.c was setting the wrong xendConfigVersion for this particular test case, so previously it missed the VNC config. Fixing the test suite meant I had to add in the <graphics> elements. The <clock> stuf is a new feature - we previously only tracked the clock setting for HVM guests. Paravirt guests are automatically synced to UTC, so adding this new element is OK here. You are correct that we are removing <script> element here, but I have only done this for the <interface type='bridge'>. It does not really make sense to customize the script for bringing up an interface, because then its not really bridging in the sense thta the libvirt XML describes. THe script parameter is still used for the generic network config with <interface type='ethernet'>, but I don't think I have a test case for that.
diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml --- a/tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-disk-block-shareable.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,10 +1,14 @@ <domain type='xen' id='6'> <name>pvtest</name> <uuid>49a0c6ff-c066-5392-6498-3632d093c2e7</uuid> - <bootloader>/usr/bin/pygrub</bootloader> <memory>524288</memory> <currentMemory>393216</currentMemory> <vcpu>1</vcpu> + <bootloader>/usr/bin/pygrub</bootloader> + <os> + <type>linux</type> + </os>
pygrub probanly means a linux boot right, but
Yep, I decided we should be explicit and always add the <os> block even if we have a bootloader, so people don't need to special case the paravirt guest config in this area.
- <script path='vif-bridge'/>
lost script again.
[...]
+++ b/tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml Thu Jul 03 12:50:05 2008 +0100 @@ -1,20 +1,21 @@ <domain type='xen' id='3'> <name>fvtest</name> <uuid>b5d70dd2-75cd-aca5-1776-9660b059d8bc</uuid> + <memory>409600</memory> + <currentMemory>409600</currentMemory> + <vcpu>1</vcpu> <os> <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> - <memory>409600</memory> - <vcpu>1</vcpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>restart</on_crash> <features> <acpi/> </features> <clock offset='localtime'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> <devices> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <disk type='file' device='disk'>
We create currentMemory from memory value or I'm mistaken ?
Yes, if there is no explicit 'maxmem' setting, we set it based on the 'memory' value, and vica-verca. So when outputting the XML we will always have both elements.
[...]
diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-sound-all.sexpr --- a/tests/sexpr2xmldata/sexpr2xml-fv-sound-all.sexpr Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-sound-all.sexpr Thu Jul 03 12:50:05 2008 +0100 @@ -1,1 +1,1 @@ -(domain (domid 3)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(device_model '/usr/lib64/xen/bin/qemu-dm')(boot c)(cdrom '/root/boot.iso')(acpi 1)(vnc 1)(keymap ja)(soundhw 'idontexit,es1370,all')))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) +(domain (domid 3)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(device_model '/usr/lib64/xen/bin/qemu-dm')(boot c)(cdrom '/root/boot.iso')(acpi 1)(vnc 1)(keymap ja)(soundhw 'all')))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
hum hard to decript, but here it seems we lost the value of the sound emulation, going from 'idontexit,es1370,all' to 'all' this looks fishy
The parser is a little more fussy here - it expects either the single string 'all', or a list of models. It's not letting you mix a list of strings and 'all' at the same time. I will look at fixing this again.
diff -r 3dea6bbe639b tests/sexpr2xmldata/sexpr2xml-fv-sound.sexpr --- a/tests/sexpr2xmldata/sexpr2xml-fv-sound.sexpr Thu Jul 03 11:42:42 2008 +0100 +++ b/tests/sexpr2xmldata/sexpr2xml-fv-sound.sexpr Thu Jul 03 12:50:05 2008 +0100 @@ -1,1 +1,1 @@ -(domain (domid 3)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(device_model '/usr/lib64/xen/bin/qemu-dm')(boot c)(cdrom '/root/boot.iso')(acpi 1)(vnc 1)(keymap ja)(soundhw 'sb16,es1370,idontexist,es1370more')))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) +(domain (domid 3)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(device_model '/usr/lib64/xen/bin/qemu-dm')(boot c)(cdrom '/root/boot.iso')(acpi 1)(vnc 1)(keymap ja)(soundhw 'sb16,es1370')))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
Same thing soundhw went from 'sb16,es1370,idontexist,es1370more' to 'sb16,es1370', it's a bit weird
In this case, it would previously just ignore those bogus values, but the parser now rejects them explicitly. The real world, if you had a Xen config with a bogus 'idontexist' you'd get a nice error message when dumping the XML "unexpected sound model idontexist" at lesat you would if I had remembered to call __virRaiseError(), which I notice I missed in this particular example. So I'll fix that bit. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Jul 24, 2008 at 02:24:43PM +0100, Daniel P. Berrange wrote:
On Thu, Jul 24, 2008 at 08:24:32AM -0400, Daniel Veillard wrote: You are correct that we are removing <script> element here, but I have only done this for the <interface type='bridge'>. It does not really make sense to customize the script for bringing up an interface, because then its not really bridging in the sense thta the libvirt XML describes. THe script parameter is still used for the generic network config with <interface type='ethernet'>, but I don't think I have a test case for that.
okay, that's my only remaining concern then, we may break people doing weird stuff with 2 different kind of bridging.
pygrub probanly means a linux boot right, but
Yep, I decided we should be explicit and always add the <os> block even if we have a bootloader, so people don't need to special case the paravirt guest config in this area.
okay
We create currentMemory from memory value or I'm mistaken ?
Yes, if there is no explicit 'maxmem' setting, we set it based on the 'memory' value, and vica-verca. So when outputting the XML we will always have both elements.
hum hard to decript, but here it seems we lost the value of the sound emulation, going from 'idontexit,es1370,all' to 'all' this looks fishy
The parser is a little more fussy here - it expects either the single string 'all', or a list of models. It's not letting you mix a list of strings and 'all' at the same time. I will look at fixing this again.
okay this makes sense then
Same thing soundhw went from 'sb16,es1370,idontexist,es1370more' to 'sb16,es1370', it's a bit weird
In this case, it would previously just ignore those bogus values, but the parser now rejects them explicitly. The real world, if you had a Xen config with a bogus 'idontexist' you'd get a nice error message when dumping the XML
"unexpected sound model idontexist"
at lesat you would if I had remembered to call __virRaiseError(), which I notice I missed in this particular example. So I'll fix that bit.
the only problem is that you do error checking in libvirt instead of letting Xen act on it, as a result you need to maintain the list. But since we need the checking for QEmu and Xen should be a subset i assume that's the right approach, +1 Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

This replaces the code which converts from the XML into SEXPR with code which converts from the virDomainDefPtr object to a SEXPR. We then simply use virDomainDefParseString() to generate the initial virDomainDefPtr. This makes the SEXPR generating code much easier to follow. As part of this cleaned the code all moved out of xml.c and into xend_internal.c so its in the same place as its inverse SEXPR -> XML code. I'm half-inclined to actually move all the SEXPR related code into a xen_conf.{c,h} file independant of the main driver routine. This would reflect the split we for QEMU, LXC & OpenVZ drivers. I had to do some minor fixes to several of the XML files for the test suite, and also all the sexpr changed due to better generation of the options for the graphical framebuffer options b/tests/testutilsxen.c | 53 b/tests/testutilsxen.h | 5 proxy/Makefile.am | 2 proxy/libvirt_proxy.c | 26 src/xen_internal.c | 102 src/xen_internal.h | 14 src/xen_unified.c | 8 src/xen_unified.h | 2 src/xend_internal.c | 1013 ++++++++- src/xend_internal.h | 33 src/xm_internal.c | 22 src/xml.c | 1642 --------------- src/xml.h | 48 tests/Makefile.am | 2 tests/xencapstest.c | 15 tests/xml2sexprdata/xml2sexpr-curmem.sexpr | 2 tests/xml2sexprdata/xml2sexpr-disk-block-shareable.sexpr | 2 tests/xml2sexprdata/xml2sexpr-disk-block.sexpr | 2 tests/xml2sexprdata/xml2sexpr-disk-drv-blkback.sexpr | 2 tests/xml2sexprdata/xml2sexpr-disk-drv-blktap-qcow.sexpr | 2 tests/xml2sexprdata/xml2sexpr-disk-drv-blktap-raw.sexpr | 2 tests/xml2sexprdata/xml2sexpr-disk-drv-blktap.sexpr | 2 tests/xml2sexprdata/xml2sexpr-disk-drv-loop.sexpr | 2 tests/xml2sexprdata/xml2sexpr-disk-file.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-kernel.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-localtime.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-localtime.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-parallel-tcp.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-parallel-tcp.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-file.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-file.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-null.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-null.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-pipe.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-pipe.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-pty.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-pty.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-stdio.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-stdio.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-tcp-telnet.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-tcp-telnet.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-udp.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-udp.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-unix.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-serial-unix.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-sound.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-sound.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-usbmouse.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-usbmouse.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-usbtablet.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-usbtablet.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-utc.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-utc.xml | 2 tests/xml2sexprdata/xml2sexpr-fv-v2.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-vncunused.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv-vncunused.xml | 2 tests/xml2sexprdata/xml2sexpr-fv.sexpr | 2 tests/xml2sexprdata/xml2sexpr-fv.xml | 2 tests/xml2sexprdata/xml2sexpr-net-bridged.sexpr | 2 tests/xml2sexprdata/xml2sexpr-net-e1000.sexpr | 2 tests/xml2sexprdata/xml2sexpr-net-routed.sexpr | 2 tests/xml2sexprdata/xml2sexpr-no-source-cdrom.sexpr | 2 tests/xml2sexprdata/xml2sexpr-no-source-cdrom.xml | 2 tests/xml2sexprdata/xml2sexpr-pv-bootloader.sexpr | 2 tests/xml2sexprdata/xml2sexpr-pv-vfb-new.sexpr | 2 tests/xml2sexprdata/xml2sexpr-pv-vfb-orig.sexpr | 2 tests/xml2sexprdata/xml2sexpr-pv.sexpr | 2 tests/xml2sexprtest.c | 34 70 files changed, 1236 insertions(+), 1893 deletions(-) Daniel diff -r ae83be3e7918 proxy/Makefile.am --- a/proxy/Makefile.am Thu Jul 03 12:50:05 2008 +0100 +++ b/proxy/Makefile.am Thu Jul 03 13:02:42 2008 +0100 @@ -11,7 +11,7 @@ libvirt_proxy_SOURCES = libvirt_proxy.c @top_srcdir@/src/xend_internal.c \ @top_srcdir@/src/xen_internal.c @top_srcdir@/src/virterror.c \ - @top_srcdir@/src/sexpr.c @top_srcdir@/src/xml.c \ + @top_srcdir@/src/sexpr.c \ @top_srcdir@/src/xs_internal.c @top_srcdir@/src/buf.c \ @top_srcdir@/src/capabilities.c \ @top_srcdir@/src/memory.c \ diff -r ae83be3e7918 proxy/libvirt_proxy.c --- a/proxy/libvirt_proxy.c Thu Jul 03 12:50:05 2008 +0100 +++ b/proxy/libvirt_proxy.c Thu Jul 03 13:02:42 2008 +0100 @@ -358,6 +358,7 @@ */ static int proxyReadClientSocket(int nr) { + virDomainDefPtr def; virProxyFullPacket request; virProxyPacketPtr req = (virProxyPacketPtr) &request; int ret; @@ -622,22 +623,29 @@ * rather hard to get from that code path. So proxy * users won't see CPU pinning (last NULL arg) */ - xml = xenDaemonDomainDumpXMLByID(conn, request.data.arg, 0, NULL); - if (!xml) { + def = xenDaemonDomainFetch(conn, request.data.arg, NULL, NULL); + if (!def) { req->data.arg = -1; req->len = sizeof(virProxyPacket); } else { - int xmllen = strlen(xml); - if (xmllen > (int) sizeof(request.extra.str)) { - req->data.arg = -2; + xml = virDomainDefFormat(conn, def, 0); + if (!xml) { + req->data.arg = -1; req->len = sizeof(virProxyPacket); } else { - req->data.arg = 0; - memmove(&request.extra.str[0], xml, xmllen); - req->len = sizeof(virProxyPacket) + xmllen; + int xmllen = strlen(xml); + if (xmllen > (int) sizeof(request.extra.str)) { + req->data.arg = -2; + req->len = sizeof(virProxyPacket); + } else { + req->data.arg = 0; + memmove(&request.extra.str[0], xml, xmllen); + req->len = sizeof(virProxyPacket) + xmllen; + } + free(xml); } - free(xml); } + virDomainDefFree(def); break; case VIR_PROXY_DOMAIN_OSTYPE: if (req->len != sizeof(virProxyPacket)) diff -r ae83be3e7918 src/xen_internal.c --- a/src/xen_internal.c Thu Jul 03 12:50:05 2008 +0100 +++ b/src/xen_internal.c Thu Jul 03 13:02:42 2008 +0100 @@ -2161,8 +2161,7 @@ static virCapsPtr -xenHypervisorBuildCapabilities(virConnectPtr conn, - const char *hostmachine, +xenHypervisorBuildCapabilities(const char *hostmachine, int host_pae, char *hvm_type, struct guest_arch *guest_archs, @@ -2188,7 +2187,7 @@ if (sys_interface_version >= 4) { - if (xenDaemonNodeGetTopology(conn, caps) != 0) { + if (xenDaemonNodeGetTopology(NULL, caps) != 0) { virCapabilitiesFree(caps); return NULL; } @@ -2273,10 +2272,9 @@ * * Return the capabilities of this hypervisor. */ -char * -xenHypervisorMakeCapabilitiesXML(virConnectPtr conn, - const char *hostmachine, - FILE *cpuinfo, FILE *capabilities) +virCapsPtr +xenHypervisorMakeCapabilitiesInternal(const char *hostmachine, + FILE *cpuinfo, FILE *capabilities) { char line[1024], *str, *token; regmatch_t subs[4]; @@ -2287,10 +2285,6 @@ int host_pae = 0; struct guest_arch guest_archs[32]; int nr_guest_archs = 0; - - char *xml; - - virCapsPtr caps = NULL; memset(guest_archs, 0, sizeof(guest_archs)); @@ -2412,24 +2406,64 @@ } } - if ((caps = xenHypervisorBuildCapabilities(conn, - hostmachine, + if ((caps = xenHypervisorBuildCapabilities(hostmachine, host_pae, hvm_type, guest_archs, nr_guest_archs)) == NULL) goto no_memory; - if ((xml = virCapabilitiesFormatXML(caps)) == NULL) - goto no_memory; - virCapabilitiesFree(caps); - return xml; + return caps; no_memory: - virXenError(conn, VIR_ERR_NO_MEMORY, __FUNCTION__, 0); + virXenError(NULL, VIR_ERR_NO_MEMORY, __FUNCTION__, 0); virCapabilitiesFree(caps); return NULL; } + +/** + * xenHypervisorMakeCapabilities: + * + * Return the capabilities of this hypervisor. + */ +virCapsPtr +xenHypervisorMakeCapabilities(void) +{ + virCapsPtr caps; + FILE *cpuinfo, *capabilities; + struct utsname utsname; + + /* Really, this never fails - look at the man-page. */ + uname (&utsname); + + cpuinfo = fopen ("/proc/cpuinfo", "r"); + if (cpuinfo == NULL) { + if (errno != ENOENT) { + virXenPerror (NULL, "/proc/cpuinfo"); + return NULL; + } + } + + capabilities = fopen ("/sys/hypervisor/properties/capabilities", "r"); + if (capabilities == NULL) { + if (errno != ENOENT) { + fclose(cpuinfo); + virXenPerror (NULL, "/sys/hypervisor/properties/capabilities"); + return NULL; + } + } + + caps = xenHypervisorMakeCapabilitiesInternal(utsname.machine, cpuinfo, capabilities); + + if (cpuinfo) + fclose(cpuinfo); + if (capabilities) + fclose(capabilities); + + return caps; +} + + /** * xenHypervisorGetCapabilities: @@ -2440,39 +2474,17 @@ char * xenHypervisorGetCapabilities (virConnectPtr conn) { + xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData; char *xml; - FILE *cpuinfo, *capabilities; - struct utsname utsname; - /* Really, this never fails - look at the man-page. */ - uname (&utsname); - - cpuinfo = fopen ("/proc/cpuinfo", "r"); - if (cpuinfo == NULL) { - if (errno != ENOENT) { - virXenPerror (conn, "/proc/cpuinfo"); - return NULL; - } + if (!(xml = virCapabilitiesFormatXML(priv->caps))) { + virXenError(conn, VIR_ERR_NO_MEMORY, NULL, 0); + return NULL; } - - capabilities = fopen ("/sys/hypervisor/properties/capabilities", "r"); - if (capabilities == NULL) { - if (errno != ENOENT) { - fclose(cpuinfo); - virXenPerror (conn, "/sys/hypervisor/properties/capabilities"); - return NULL; - } - } - - xml = xenHypervisorMakeCapabilitiesXML(conn, utsname.machine, cpuinfo, capabilities); - - if (cpuinfo) - fclose(cpuinfo); - if (capabilities) - fclose(capabilities); return xml; } + /** * xenHypervisorNumOfDomains: diff -r ae83be3e7918 src/xen_internal.h --- a/src/xen_internal.h Thu Jul 03 12:50:05 2008 +0100 +++ b/src/xen_internal.h Thu Jul 03 13:02:42 2008 +0100 @@ -15,8 +15,13 @@ extern "C" { #endif +#include "internal.h" +#include "capabilities.h" + extern struct xenUnifiedDriver xenHypervisorDriver; int xenHypervisorInit (void); + +virCapsPtr xenHypervisorMakeCapabilities (void); /* The following calls are made directly by the Xen proxy: */ @@ -36,11 +41,10 @@ int xenHypervisorClose (virConnectPtr conn); int xenHypervisorGetVersion (virConnectPtr conn, unsigned long *hvVer); -char * - xenHypervisorMakeCapabilitiesXML (virConnectPtr conn, - const char *hostmachine, - FILE *cpuinfo, - FILE *capabilities); +virCapsPtr + xenHypervisorMakeCapabilitiesInternal(const char *hostmachine, + FILE *cpuinfo, + FILE *capabilities); char * xenHypervisorGetCapabilities (virConnectPtr conn); unsigned long diff -r ae83be3e7918 src/xen_unified.c --- a/src/xen_unified.c Thu Jul 03 12:50:05 2008 +0100 +++ b/src/xen_unified.c Thu Jul 03 13:02:42 2008 +0100 @@ -197,7 +197,7 @@ } } } - res = virSaveCpuSet(dom->conn, cpulist, nb_cpu); + res = virDomainCpuSetFormat(dom->conn, cpulist, nb_cpu); } done: @@ -334,6 +334,11 @@ } } + if (!(priv->caps = xenHypervisorMakeCapabilities())) { + DEBUG0("Failed to make capabilities"); + goto fail; + } + return VIR_DRV_OPEN_SUCCESS; fail: @@ -353,6 +358,7 @@ GET_PRIVATE(conn); int i; + virCapabilitiesFree(priv->caps); for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) if (priv->opened[i] && drivers[i]->close) (void) drivers[i]->close (conn); diff -r ae83be3e7918 src/xen_unified.h --- a/src/xen_unified.h Thu Jul 03 12:50:05 2008 +0100 +++ b/src/xen_unified.h Thu Jul 03 13:02:42 2008 +0100 @@ -12,6 +12,7 @@ #define __VIR_XEN_UNIFIED_H__ #include "internal.h" +#include "capabilities.h" #ifndef HAVE_WINSOCK2_H #include <sys/un.h> @@ -91,6 +92,7 @@ * low-level drivers access parts of this structure. */ struct _xenUnifiedPrivate { + virCapsPtr caps; #ifdef WITH_XEN int handle; /* Xen hypervisor handle */ diff -r ae83be3e7918 src/xend_internal.c --- a/src/xend_internal.c Thu Jul 03 12:50:05 2008 +0100 +++ b/src/xend_internal.c Thu Jul 03 13:02:42 2008 +0100 @@ -33,17 +33,13 @@ #include <libxml/uri.h> #include <errno.h> -#include "internal.h" +#include "xend_internal.h" #include "driver.h" #include "util.h" #include "sexpr.h" -#include "xml.h" #include "buf.h" -#include "capabilities.h" -#include "domain_conf.h" #include "uuid.h" #include "xen_unified.h" -#include "xend_internal.h" #include "xen_internal.h" /* for DOM0_INTERFACE_VERSION */ #include "xs_internal.h" /* To extract VNC port & Serial console TTY */ #include "memory.h" @@ -88,6 +84,21 @@ struct sockaddr_in addr_in; }; + +#ifndef PROXY +static int +xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainDiskDefPtr def, + virBufferPtr buf, + int hvm, + int xendConfigVersion); +static int +xenDaemonFormatSxprNet(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainNetDefPtr def, + virBufferPtr buf, + int hvm, + int xendConfigVersion); +#endif static void virXendError(virConnectPtr conn, virErrorNumber error, const char *fmt, ...) @@ -2660,7 +2671,7 @@ for (cpu = 0; cpu < numCpus; cpu++) cpuset[cpu] = 0; } else { - nb_cpus = virParseCpuSet(conn, &cur, 'n', cpuset, numCpus); + nb_cpus = virDomainCpuSetParse(conn, &cur, 'n', cpuset, numCpus); if (nb_cpus < 0) goto error; } @@ -3210,71 +3221,39 @@ #endif /* ! PROXY */ -/* XXX change proxy to use Name instead of ID, then - dumpxml will work over proxy for inactive domains - and this can be removed */ -char * -xenDaemonDomainDumpXMLByID(virConnectPtr conn, int domid, int flags, - const char *cpus) -{ - char *ret = NULL; - struct sexpr *root; - xenUnifiedPrivatePtr priv; - virDomainDefPtr def; - - root = sexpr_get(conn, "/xend/domain/%d?detail=1", domid); +virDomainDefPtr +xenDaemonDomainFetch(virConnectPtr conn, + int domid, + const char *name, + const char *cpus) +{ + struct sexpr *root; + xenUnifiedPrivatePtr priv; + virDomainDefPtr def; + + if (name) + root = sexpr_get(conn, "/xend/domain/%s?detail=1", name); + else + root = sexpr_get(conn, "/xend/domain/%d?detail=1", domid); if (root == NULL) { virXendError (conn, VIR_ERR_XEN_CALL, - _("xenDaemonDomainDumpXMLByID failed to" + _("xenDaemonDomainFetch failed to" " find this domain")); return (NULL); } priv = (xenUnifiedPrivatePtr) conn->privateData; - if (!(def = xenDaemonParseSxpr(conn, root, priv->xendConfigVersion, + if (!(def = xenDaemonParseSxpr(conn, + root, + priv->xendConfigVersion, cpus))) goto cleanup; - ret = virDomainDefFormat(conn, def, flags); - cleanup: sexpr_free(root); - virDomainDefFree(def); - - return (ret); -} - -char * -xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name, int flags, - const char *cpus) -{ - char *ret = NULL; - struct sexpr *root; - xenUnifiedPrivatePtr priv; - virDomainDefPtr def; - - root = sexpr_get(conn, "/xend/domain/%s?detail=1", name); - if (root == NULL) { - virXendError (conn, VIR_ERR_XEN_CALL, - _("xenDaemonDomainDumpXMLByName failed to" - " find this domain")); - return (NULL); - } - - priv = (xenUnifiedPrivatePtr) conn->privateData; - - if (!(def = xenDaemonParseSxpr(conn, root, priv->xendConfigVersion, - cpus))) - goto cleanup; - - ret = virDomainDefFormat(conn, def, flags); - -cleanup: - sexpr_free(root); - virDomainDefFree(def); - - return (ret); + + return (def); } @@ -3294,6 +3273,8 @@ xenDaemonDomainDumpXML(virDomainPtr domain, int flags, const char *cpus) { xenUnifiedPrivatePtr priv; + virDomainDefPtr def; + char *xml; if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG, @@ -3307,12 +3288,17 @@ return(NULL); } - if (domain->id < 0) - return xenDaemonDomainDumpXMLByName(domain->conn, domain->name, flags, - cpus); - else - return xenDaemonDomainDumpXMLByID(domain->conn, domain->id, flags, - cpus); + if (!(def = xenDaemonDomainFetch(domain->conn, + domain->id, + domain->name, + cpus))) + return(NULL); + + xml = virDomainDefFormat(domain->conn, def, flags); + + virDomainDefFree(def); + + return xml; } #endif /* !PROXY */ @@ -3860,28 +3846,21 @@ { int ret; char *sexpr; - char *name = NULL; virDomainPtr dom = NULL; xenUnifiedPrivatePtr priv; - - if (!VIR_IS_CONNECT(conn)) { - virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (NULL); - } - if (xmlDesc == NULL) { - virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - priv = (xenUnifiedPrivatePtr) conn->privateData; - - sexpr = virDomainParseXMLDesc(conn, xmlDesc, &name, priv->xendConfigVersion); - if ((sexpr == NULL) || (name == NULL)) { + virDomainDefPtr def; + + priv = (xenUnifiedPrivatePtr) conn->privateData; + + if (!(def = virDomainDefParseString(conn, + priv->caps, + xmlDesc))) + return (NULL); + + if (!(sexpr = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion))) { virXendError(conn, VIR_ERR_XML_ERROR, - _("failed to parse domain description")); - VIR_FREE(sexpr); - VIR_FREE(name); - + "%s", _("failed to build sexpr")); + virDomainDefFree(def); return (NULL); } @@ -3893,17 +3872,16 @@ /* This comes before wait_for_devices, to ensure that latter cleanup will destroy the domain upon failure */ - if (!(dom = virDomainLookupByName(conn, name))) - goto error; - - if ((ret = xend_wait_for_devices(conn, name)) < 0) + if (!(dom = virDomainLookupByName(conn, def->name))) + goto error; + + if ((ret = xend_wait_for_devices(conn, def->name)) < 0) goto error; if ((ret = xenDaemonDomainResume(dom)) < 0) goto error; - VIR_FREE(name); - + virDomainDefFree(def); return (dom); error: @@ -3912,7 +3890,7 @@ xenDaemonDomainDestroy(dom); virUnrefDomain(dom); } - VIR_FREE(name); + virDomainDefFree(def); return (NULL); } @@ -3929,15 +3907,17 @@ static int xenDaemonAttachDevice(virDomainPtr domain, const char *xml) { - char *sexpr, *conf, *str; - int hvm = 0, ret; - xenUnifiedPrivatePtr priv; - char class[8], ref[80]; - - if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { - virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG, - __FUNCTION__); - return (-1); + xenUnifiedPrivatePtr priv; + char *sexpr = NULL; + int ret = -1; + virDomainDeviceDefPtr dev = NULL; + virDomainDefPtr def = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { + virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG, + __FUNCTION__); + return -1; } priv = (xenUnifiedPrivatePtr) domain->conn->privateData; @@ -3947,20 +3927,44 @@ * avoid doing this on inactive guests */ if ((domain->id < 0) && (priv->xendConfigVersion < 3)) - return (-1); - - str = virDomainGetOSType(domain); - if (STREQ(str, "hvm")) - hvm = 1; - VIR_FREE(str); - sexpr = virParseXMLDevice(domain->conn, xml, hvm, priv->xendConfigVersion); - if (sexpr == NULL) - return (-1); - if (!memcmp(sexpr, "(device ", 8)) { - conf = sexpr + 8; - *(conf + strlen(conf) -1) = 0; /* suppress final ) */ - } - else conf = sexpr; + return -1; + + if (!(def = xenDaemonDomainFetch(domain->conn, + domain->id, + domain->name, + NULL))) + goto cleanup; + + if (!(dev = virDomainDeviceDefParse(domain->conn, def, xml))) + goto cleanup; + + + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + if (xenDaemonFormatSxprDisk(domain->conn, + dev->data.disk, + &buf, + STREQ(def->os.type, "hvm") ? 1 : 0, + priv->xendConfigVersion) < 0) + goto cleanup; + + case VIR_DOMAIN_DEVICE_NET: + if (xenDaemonFormatSxprNet(domain->conn, + dev->data.net, + &buf, + STREQ(def->os.type, "hvm") ? 1 : 0, + priv->xendConfigVersion) < 0) + goto cleanup; + + default: + virXendError(domain->conn, VIR_ERR_NO_SUPPORT, "%s", + _("unsupported device type")); + goto cleanup; + } + + sexpr = virBufferContentAndReset(&buf); + +#if 0 if (virDomainXMLDevID(domain, xml, class, ref, sizeof(ref))) { /* device doesn't exist, define it */ ret = xend_op(domain->conn, domain->name, "op", "device_create", @@ -3971,7 +3975,11 @@ ret = xend_op(domain->conn, domain->name, "op", "device_configure", "config", conf, "dev", ref, NULL); } +#endif +cleanup: VIR_FREE(sexpr); + virDomainDefFree(def); + virDomainDeviceDefFree(dev); return ret; } @@ -3987,6 +3995,7 @@ static int xenDaemonDetachDevice(virDomainPtr domain, const char *xml) { +#if 0 char class[8], ref[80]; if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { @@ -3998,6 +4007,8 @@ return (-1); return(xend_op(domain->conn, domain->name, "op", "device_destroy", "type", class, "dev", ref, "force", "0", "rm_cfg", "1", NULL)); +#endif + return (domain == (void*)xml) ? -1 : -1; } int @@ -4280,29 +4291,23 @@ char *name = NULL; virDomainPtr dom; xenUnifiedPrivatePtr priv; - - if (!VIR_IS_CONNECT(conn)) { - virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (NULL); - } - if (xmlDesc == NULL) { - virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - priv = (xenUnifiedPrivatePtr) conn->privateData; - - if (priv->xendConfigVersion < 3) - return(NULL); - - sexpr = virDomainParseXMLDesc(conn, xmlDesc, &name, priv->xendConfigVersion); - if ((sexpr == NULL) || (name == NULL)) { + virDomainDefPtr def; + + priv = (xenUnifiedPrivatePtr) conn->privateData; + + if (priv->xendConfigVersion < 3) + return(NULL); + + if (!(def = virDomainDefParseString(conn, priv->caps, xmlDesc))) { virXendError(conn, VIR_ERR_XML_ERROR, _("failed to parse domain description")); - VIR_FREE(sexpr); - VIR_FREE(name); - - return (NULL); + return (NULL); + } + + if (!(sexpr = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion))) { + virXendError(conn, VIR_ERR_XML_ERROR, + _("failed to build sexpr")); + goto error; } ret = xend_op(conn, "", "op", "new", "config", sexpr, NULL); @@ -4316,10 +4321,11 @@ if (dom == NULL) { goto error; } - + virDomainDefFree(def); return (dom); - error: - VIR_FREE(name); + + error: + virDomainDefFree(def); return (NULL); } int xenDaemonDomainCreate(virDomainPtr domain) @@ -4844,5 +4850,738 @@ xenDaemonSetSchedulerParameters, /* domainSetSchedulerParameters */ }; +/************************************************************************ + * * + * Converter functions to go from the XML tree to an S-Expr for Xen * + * * + ************************************************************************/ + + +/** + * virtDomainParseXMLGraphicsDescVFB: + * @conn: pointer to the hypervisor connection + * @node: node containing graphics description + * @buf: a buffer for the result S-Expr + * + * Parse the graphics part of the XML description and add it to the S-Expr + * in buf. This is a temporary interface as the S-Expr interface will be + * replaced by XML-RPC in the future. However the XML format should stay + * valid over time. + * + * Returns 0 in case of success, -1 in case of error + */ +static int +xenDaemonFormatSxprGraphicsNew(virConnectPtr conn, + virDomainGraphicsDefPtr def, + virBufferPtr buf) +{ + if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL && + def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected graphics type %d"), + def->type); + return -1; + } + + virBufferAddLit(buf, "(device (vkbd))"); + virBufferAddLit(buf, "(device (vfb "); + + if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) { + virBufferAddLit(buf, "(type sdl)"); + if (def->data.sdl.display) + virBufferVSprintf(buf, "(display '%s')", def->data.sdl.display); + if (def->data.sdl.xauth) + virBufferVSprintf(buf, "(xauthority '%s')", def->data.sdl.xauth); + } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { + virBufferAddLit(buf, "(type vnc)"); + if (def->data.vnc.autoport) { + virBufferAddLit(buf, "(vncunused 1)"); + } else { + virBufferAddLit(buf, "(vncunused 0)"); + virBufferVSprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900); + } + + if (def->data.vnc.listenAddr) + virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr); + if (def->data.vnc.passwd) + virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.passwd); + if (def->data.vnc.keymap) + virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap); + } + + virBufferAddLit(buf, "))"); + + return 0; +} + + +static int +xenDaemonFormatSxprGraphicsOld(virConnectPtr conn, + virDomainGraphicsDefPtr def, + virBufferPtr buf, + int xendConfigVersion) +{ + if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL && + def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected graphics type %d"), + def->type); + return -1; + } + + if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) { + virBufferAddLit(buf, "(sdl 1)"); + if (def->data.sdl.display) + virBufferVSprintf(buf, "(display '%s')", def->data.sdl.display); + if (def->data.sdl.xauth) + virBufferVSprintf(buf, "(xauthority '%s')", def->data.sdl.xauth); + } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { + virBufferAddLit(buf, "(vnc 1)"); + if (xendConfigVersion >= 2) { + if (def->data.vnc.autoport) { + virBufferAddLit(buf, "(vncunused 1)"); + } else { + virBufferAddLit(buf, "(vncunused 0)"); + virBufferVSprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900); + } + + if (def->data.vnc.listenAddr) + virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr); + if (def->data.vnc.passwd) + virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.passwd); + if (def->data.vnc.keymap) + virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap); + + } + } + + return 0; +} + +static int +xenDaemonFormatSxprChr(virConnectPtr conn, + virDomainChrDefPtr def, + virBufferPtr buf, + const char *name) +{ + const char *type = virDomainChrTypeToString(def->type); + + if (!type) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected chr device type")); + return -1; + } + + switch (def->type) { + case VIR_DOMAIN_CHR_TYPE_NULL: + case VIR_DOMAIN_CHR_TYPE_STDIO: + case VIR_DOMAIN_CHR_TYPE_VC: + case VIR_DOMAIN_CHR_TYPE_PTY: + virBufferVSprintf(buf, "(%s %s)", name, type); + break; + + case VIR_DOMAIN_CHR_TYPE_FILE: + case VIR_DOMAIN_CHR_TYPE_PIPE: + virBufferVSprintf(buf, "(%s %s:%s)", name, type, def->data.file.path); + break; + + case VIR_DOMAIN_CHR_TYPE_DEV: + virBufferVSprintf(buf, "(%s %s)", name, def->data.file.path); + break; + + case VIR_DOMAIN_CHR_TYPE_TCP: + virBufferVSprintf(buf, "(%s %s:%s:%s%s)", name, + (def->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW ? + "tcp" : "telnet"), + (def->data.tcp.host ? def->data.tcp.host : ""), + (def->data.tcp.service ? def->data.tcp.service : ""), + (def->data.tcp.listen ? ",listen" : "")); + break; + + case VIR_DOMAIN_CHR_TYPE_UDP: + virBufferVSprintf(buf, "(%s %s:%s:%s@%s:%s)", name, type, + (def->data.udp.connectHost ? def->data.udp.connectHost : ""), + (def->data.udp.connectService ? def->data.udp.connectService : ""), + (def->data.udp.bindHost ? def->data.udp.bindHost : ""), + (def->data.udp.bindService ? def->data.udp.bindService : "")); + break; + + case VIR_DOMAIN_CHR_TYPE_UNIX: + virBufferVSprintf(buf, "(%s %s:%s%s)", name, type, + def->data.nix.path, + def->data.nix.listen ? ",listen" : ""); + break; + } + + return 0; +} + + +/** + * virDomainParseXMLDiskDesc: + * @node: node containing disk description + * @conn: pointer to the hypervisor connection + * @buf: a buffer for the result S-Expr + * @xendConfigVersion: xend configuration file format + * + * Parse the one disk in the XML description and add it to the S-Expr in buf + * This is a temporary interface as the S-Expr interface + * will be replaced by XML-RPC in the future. However the XML format should + * stay valid over time. + * + * Returns 0 in case of success, -1 in case of error. + */ +static int +xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainDiskDefPtr def, + virBufferPtr buf, + int hvm, + int xendConfigVersion) +{ + /* Xend (all versions) put the floppy device config + * under the hvm (image (os)) block + */ + if (hvm && + def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) + return 0; + + /* Xend <= 3.0.2 doesn't include cdrom config here */ + if (hvm && + def->device == VIR_DOMAIN_DISK_DEVICE_CDROM && + xendConfigVersion == 1) + return 0; + + virBufferAddLit(buf, "(device "); + /* Normally disks are in a (device (vbd ...)) block + * but blktap disks ended up in a differently named + * (device (tap ....)) block.... */ + if (def->driverName && + STREQ(def->driverName, "tap")) { + virBufferAddLit(buf, "(tap "); + } else { + virBufferAddLit(buf, "(vbd "); + } + + if (hvm) { + /* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */ + if (xendConfigVersion == 1) + virBufferVSprintf(buf, "(dev 'ioemu:%s')", def->dst); + else /* But newer does not */ + virBufferVSprintf(buf, "(dev '%s:%s')", def->dst, + def->device == VIR_DOMAIN_DISK_DEVICE_CDROM ? + "cdrom" : "disk"); + } else { + virBufferVSprintf(buf, "(dev '%s')", def->dst); + } + + if (def->src) { + if (def->driverName) { + if (STREQ(def->driverName, "tap")) { + virBufferVSprintf(buf, "(uname '%s:%s:%s')", + def->driverName, + def->driverType ? def->driverType : "aio", + def->src); + } else { + virBufferVSprintf(buf, "(uname '%s:%s')", + def->driverName, + def->src); + } + } else { + if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) { + virBufferVSprintf(buf, "(uname 'file:%s')", def->src); + } else { + if (def->src[0] == '/') + virBufferVSprintf(buf, "(uname 'phy:%s')", def->src); + else + virBufferVSprintf(buf, "(uname 'phy:/dev/%s')", def->src); + } + } + } + + if (def->readonly) + virBufferAddLit(buf, "(mode 'r')"); + else if (def->shared) + virBufferAddLit(buf, "(mode 'w!')"); + else + virBufferAddLit(buf, "(mode 'w')"); + + virBufferAddLit(buf, "))"); + + return 0; +} + +/** + * xenDaemonFormatSxprNet + * @conn: pointer to the hypervisor connection + * @node: node containing the interface description + * @buf: a buffer for the result S-Expr + * @xendConfigVersion: xend configuration file format + * + * Parse the one interface the XML description and add it to the S-Expr in buf + * This is a temporary interface as the S-Expr interface + * will be replaced by XML-RPC in the future. However the XML format should + * stay valid over time. + * + * Returns 0 in case of success, -1 in case of error. + */ +static int +xenDaemonFormatSxprNet(virConnectPtr conn, + virDomainNetDefPtr def, + virBufferPtr buf, + int hvm, + int xendConfigVersion) +{ + if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE && + def->type != VIR_DOMAIN_NET_TYPE_NETWORK && + def->type != VIR_DOMAIN_NET_TYPE_ETHERNET) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unsupported network type %d"), def->type); + return -1; + } + + virBufferAddLit(buf, "(device (vif "); + + virBufferVSprintf(buf, + "(mac '%02x:%02x:%02x:%02x:%02x:%02x')", + def->mac[0], def->mac[1], def->mac[2], + def->mac[3], def->mac[4], def->mac[5]); + + switch (def->type) { + case VIR_DOMAIN_NET_TYPE_BRIDGE: + virBufferVSprintf(buf, "(bridge '%s')", def->data.bridge.brname); + virBufferAddLit(buf, "(script 'vif-bridge')"); + break; + + case VIR_DOMAIN_NET_TYPE_NETWORK: + { + virNetworkPtr network = + virNetworkLookupByName(conn, def->data.network.name); + char *bridge; + + if (!network) { + virXendError(conn, VIR_ERR_NO_SOURCE, "%s", + def->data.network.name); + return -1; + } + + bridge = virNetworkGetBridgeName(network); + virNetworkFree(network); + if (!bridge) { + virXendError(conn, VIR_ERR_NO_SOURCE, "%s", + def->data.network.name); + return -1; + } + virBufferVSprintf(buf, "(bridge '%s')", bridge); + virBufferAddLit(buf, "(script 'vif-bridge')"); + VIR_FREE(bridge); + } + break; + + case VIR_DOMAIN_NET_TYPE_ETHERNET: + if (def->data.ethernet.script) + virBufferVSprintf(buf, "(script '%s')", def->data.ethernet.script); + if (def->data.ethernet.ipaddr != NULL) + virBufferVSprintf(buf, "(ip '%s')", def->data.ethernet.ipaddr); + break; + } + + if (def->ifname != NULL && + !STRPREFIX(def->ifname, "vif")) + virBufferVSprintf(buf, "(vifname '%s')", def->ifname); + + if (def->model != NULL) + virBufferVSprintf(buf, "(model '%s')", def->model); + + /* + * apparently (type ioemu) breaks paravirt drivers on HVM so skip this + * from Xen 3.1.0 + */ + if ((hvm) && (xendConfigVersion < 4)) + virBufferAddLit(buf, "(type ioemu)"); + + virBufferAddLit(buf, "))"); + + return 0; +} + +static int +xenDaemonFormatSxprSound(virConnectPtr conn, + virDomainSoundDefPtr sound, + virBufferPtr buf) +{ + const char *str; + virDomainSoundDefPtr prev = NULL; + if (!sound) + return 0; + + virBufferAddLit(buf, "(soundhw '"); + while (sound) { + if (!(str = virDomainSoundModelTypeToString(sound->model))) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected sound model %d"), sound->model); + return -1; + } + virBufferVSprintf(buf, "%s%s", prev ? "," : "", str); + prev = sound; + sound = sound->next; + } + + virBufferAddLit(buf, "')"); + return 0; +} + + +static int +xenDaemonFormatSxprInput(virConnectPtr conn, + virDomainInputDefPtr input, + virBufferPtr buf) +{ + if (input->bus != VIR_DOMAIN_INPUT_BUS_USB) + return 0; + + if (input->type != VIR_DOMAIN_INPUT_TYPE_MOUSE && + input->type != VIR_DOMAIN_INPUT_TYPE_TABLET) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected input type %d"), input->type); + return -1; + } + + virBufferVSprintf(buf, "(usbdevice %s)", + input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ? + "mouse" : "tablet"); + + return 0; +} + + +/** + * xenDaemonFormatSxpr: + * @conn: pointer to the hypervisor connection + * @def: domain config definition + * @xendConfigVersion: xend configuration file format + * + * Generate an SEXPR representing the domain configuration. + * + * Returns the 0 terminatedi S-Expr string or NULL in case of error. + * the caller must free() the returned value. + */ +char * +xenDaemonFormatSxpr(virConnectPtr conn, + virDomainDefPtr def, + int xendConfigVersion) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + const char *tmp; + int hvm = 0, i; + virDomainNetDefPtr net; + virDomainDiskDefPtr disk; + virDomainInputDefPtr input; + + virBufferAddLit(&buf, "(vm "); + virBufferVSprintf(&buf, "(name '%s')", def->name); + virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", + def->memory/1024, def->maxmem/1024); + virBufferVSprintf(&buf, "(vcpus %lu)", def->vcpus); + + if (def->cpumask) { + char *ranges = virDomainCpuSetFormat(conn, def->cpumask, def->cpumasklen); + if (ranges == NULL) + goto error; + virBufferVSprintf(&buf, "(cpus '%s')", ranges); + VIR_FREE(ranges); + } + + virUUIDFormat(def->uuid, uuidstr); + virBufferVSprintf(&buf, "(uuid '%s')", uuidstr); + + if (def->os.bootloader) { + if (def->os.bootloader[0]) + virBufferVSprintf(&buf, "(bootloader '%s')", def->os.bootloader); + else + virBufferAddLit(&buf, "(bootloader)"); + + if (def->os.bootloaderArgs) + virBufferVSprintf(&buf, "(bootloader_args '%s')", def->os.bootloaderArgs); + } + + if (!(tmp = virDomainLifecycleTypeToString(def->onPoweroff))) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected lifecycle value %d"), def->onPoweroff); + goto error; + } + virBufferVSprintf(&buf, "(on_poweroff '%s')", tmp); + + if (!(tmp = virDomainLifecycleTypeToString(def->onReboot))) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected lifecycle value %d"), def->onReboot); + goto error; + } + virBufferVSprintf(&buf, "(on_reboot '%s')", tmp); + + if (!(tmp = virDomainLifecycleTypeToString(def->onCrash))) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected lifecycle value %d"), def->onCrash); + goto error; + } + virBufferVSprintf(&buf, "(on_crash '%s')", tmp); + + if (!def->os.bootloader) { + if (STREQ(def->os.type, "hvm")) + hvm = 1; + + if (hvm) + virBufferAddLit(&buf, "(image (hvm "); + else + virBufferAddLit(&buf, "(image (linux "); + + if (hvm && + def->os.loader == NULL) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + "%s",_("no HVM domain loader")); + goto error; + } + + if (def->os.kernel) + virBufferVSprintf(&buf, "(kernel '%s')", def->os.kernel); + if (def->os.initrd) + virBufferVSprintf(&buf, "(ramdisk '%s')", def->os.initrd); + if (def->os.root) + virBufferVSprintf(&buf, "(root '%s')", def->os.root); + if (def->os.cmdline) + virBufferVSprintf(&buf, "(args '%s')", def->os.cmdline); + + if (hvm) { + char bootorder[VIR_DOMAIN_BOOT_LAST+1]; + if (def->os.kernel) + virBufferVSprintf(&buf, "(loader '%s')", def->os.loader); + else + virBufferVSprintf(&buf, "(kernel '%s')", def->os.loader); + + virBufferVSprintf(&buf, "(vcpus %lu)", def->vcpus); + + for (i = 0 ; i < def->os.nBootDevs ; i++) { + switch (def->os.bootDevs[i]) { + case VIR_DOMAIN_BOOT_FLOPPY: + bootorder[i] = 'a'; + break; + default: + case VIR_DOMAIN_BOOT_DISK: + bootorder[i] = 'c'; + break; + case VIR_DOMAIN_BOOT_CDROM: + bootorder[i] = 'd'; + break; + case VIR_DOMAIN_BOOT_NET: + bootorder[i] = 'n'; + break; + } + } + if (def->os.nBootDevs == 0) { + bootorder[0] = 'c'; + bootorder[1] = '\0'; + } else { + bootorder[def->os.nBootDevs] = '\0'; + } + virBufferVSprintf(&buf, "(boot %s)", bootorder); + + /* get the cdrom device file */ + /* Only XenD <= 3.0.2 wants cdrom config here */ + if (xendConfigVersion == 1) { + disk = def->disks; + while (disk) { + if (disk->type == VIR_DOMAIN_DISK_DEVICE_CDROM && + STREQ(disk->dst, "hdc") && + disk->src) { + virBufferVSprintf(&buf, "(cdrom '%s')", + disk->src); + break; + } + disk = disk->next; + } + } + + if (def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)) + virBufferAddLit(&buf, "(acpi 1)"); + if (def->features & (1 << VIR_DOMAIN_FEATURE_APIC)) + virBufferAddLit(&buf, "(apic 1)"); + if (def->features & (1 << VIR_DOMAIN_FEATURE_PAE)) + virBufferAddLit(&buf, "(pae 1)"); + + virBufferAddLit(&buf, "(usb 1)"); + + input = def->inputs; + while (input) { + if (xenDaemonFormatSxprInput(conn, input, &buf) < 0) + goto error; + input = input->next; + } + + if (def->parallels) { + if (xenDaemonFormatSxprChr(conn, def->parallels, &buf, "parallel") < 0) + goto error; + } else { + virBufferAddLit(&buf, "(parallel none)"); + } + if (def->serials) { + if (xenDaemonFormatSxprChr(conn, def->serials, &buf, "serial") < 0) + goto error; + } else { + virBufferAddLit(&buf, "(serial none)"); + } + + if (def->localtime) + virBufferAddLit(&buf, "(localtime 1)"); + + if (xenDaemonFormatSxprSound(conn, def->sounds, &buf) < 0) + goto error; + } + + /* get the device emulation model */ + if (def->emulator && (hvm || xendConfigVersion >= 3)) + virBufferVSprintf(&buf, "(device_model '%s')", def->emulator); + + + /* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */ + if ((!hvm && xendConfigVersion < 3) || + (hvm && xendConfigVersion < 4)) { + if (def->graphics && + xenDaemonFormatSxprGraphicsOld(conn, def->graphics, &buf, xendConfigVersion) < 0) + goto error; + } + + virBufferAddLit(&buf, "))"); + } + + disk = def->disks; + while (disk) { + if (xenDaemonFormatSxprDisk(conn, disk, &buf, hvm, xendConfigVersion) < 0) + goto error; + disk = disk->next; + } + + net = def->nets; + while (net) { + if (xenDaemonFormatSxprNet(conn, net, &buf, hvm, xendConfigVersion) < 0) + goto error; + net = net->next; + } + + /* New style PV graphics config xen >= 3.0.4, + * or HVM graphics config xen >= 3.0.5 */ + if ((xendConfigVersion >= 3 && !hvm) || + (xendConfigVersion >= 4 && hvm)) { + if (def->graphics && + xenDaemonFormatSxprGraphicsNew(conn, def->graphics, &buf) < 0) + goto error; + } + + virBufferAddLit(&buf, ")"); /* closes (vm */ + + return virBufferContentAndReset(&buf); + +error: + tmp = virBufferContentAndReset(&buf); + VIR_FREE(tmp); + return NULL; +} + + +#if 0 +/** + * virDomainXMLDevID: + * @domain: pointer to domain object + * @xmldesc: string with the XML description + * @class: Xen device class "vbd" or "vif" (OUT) + * @ref: Xen device reference (OUT) + * + * Set class according to XML root, and: + * - if disk, copy in ref the target name from description + * - if network, get MAC address from description, scan XenStore and + * copy in ref the corresponding vif number. + * + * Returns 0 in case of success, -1 in case of failure. + */ +int +virDomainXMLDevID(virDomainPtr domain, const char *xmldesc, char *class, + char *ref, int ref_len) +{ + xmlDocPtr xml = NULL; + xmlNodePtr node, cur; + xmlChar *attr = NULL; + + char *xref; + int ret = 0; + + xml = xmlReadDoc((const xmlChar *) xmldesc, "device.xml", NULL, + XML_PARSE_NOENT | XML_PARSE_NONET | + XML_PARSE_NOERROR | XML_PARSE_NOWARNING); + if (xml == NULL) { + virXendError(NULL, VIR_ERR_XML_ERROR, NULL, 0); + goto error; + } + node = xmlDocGetRootElement(xml); + if (node == NULL) + goto error; + if (xmlStrEqual(node->name, BAD_CAST "disk")) { + strcpy(class, "vbd"); + for (cur = node->children; cur != NULL; cur = cur->next) { + if ((cur->type != XML_ELEMENT_NODE) || + (!xmlStrEqual(cur->name, BAD_CAST "target"))) + continue; + attr = xmlGetProp(cur, BAD_CAST "dev"); + if (attr == NULL) + goto error; + xref = xenStoreDomainGetDiskID(domain->conn, domain->id, + (char *) attr); + if (xref != NULL) { + strncpy(ref, xref, ref_len); + free(xref); + ref[ref_len - 1] = '\0'; + goto cleanup; + } + /* hack to avoid the warning that domain is unused */ + if (domain->id < 0) + ret = -1; + + goto error; + } + } else if (xmlStrEqual(node->name, BAD_CAST "interface")) { + strcpy(class, "vif"); + for (cur = node->children; cur != NULL; cur = cur->next) { + if ((cur->type != XML_ELEMENT_NODE) || + (!xmlStrEqual(cur->name, BAD_CAST "mac"))) + continue; + attr = xmlGetProp(cur, BAD_CAST "address"); + if (attr == NULL) + goto error; + + xref = xenStoreDomainGetNetworkID(domain->conn, domain->id, + (char *) attr); + if (xref != NULL) { + strncpy(ref, xref, ref_len); + free(xref); + ref[ref_len - 1] = '\0'; + goto cleanup; + } + /* hack to avoid the warning that domain is unused */ + if (domain->id < 0) + ret = -1; + + goto error; + } + } else { + virXendError(NULL, VIR_ERR_XML_ERROR, (const char *) node->name, 0); + } + error: + ret = -1; + cleanup: + if (xml != NULL) + xmlFreeDoc(xml); + xmlFree(attr); + return ret; +} +#endif + #endif /* ! PROXY */ #endif /* WITH_XEN */ diff -r ae83be3e7918 src/xend_internal.h --- a/src/xend_internal.h Thu Jul 03 12:50:05 2008 +0100 +++ b/src/xend_internal.h Thu Jul 03 13:02:42 2008 +0100 @@ -1,24 +1,26 @@ /* - * libxend/xend.h -- Xend library + * xend_internal.h * * Copyright (C) 2005,2006 * * Anthony Liguori <aliguori@us.ibm.com> * Daniel Veillard <veillard@redhat.com> * + * Copyright 2006-2008 Red Hat + * * This file is subject to the terms and conditions of the GNU Lesser General * Public License. See the file COPYING in the main directory of this archive * for more details. */ -#ifndef _LIBXEND_XEND_H_ -#define _LIBXEND_XEND_H_ +#ifndef __XEND_INTERNAL_H_ +#define __XEND_INTERNAL_H_ #include <sys/types.h> #include <stdint.h> #include <stdbool.h> -#include "libvirt/libvirt.h" +#include "internal.h" #include "capabilities.h" #include "domain_conf.h" #include "buf.h" @@ -84,15 +86,11 @@ char **name, unsigned char *uuid); -char *xenDaemonDomainDumpXMLByID(virConnectPtr xend, - int domid, - int flags, - const char *cpus); - -char *xenDaemonDomainDumpXMLByName(virConnectPtr xend, - const char *name, - int flags, - const char *cpus); +virDomainDefPtr +xenDaemonDomainFetch(virConnectPtr xend, + int domid, + const char *name, + const char *cpus); int xend_parse_sexp_desc_char(virConnectPtr conn, virBufferPtr buf, @@ -105,6 +103,10 @@ xenDaemonParseSxprString(virConnectPtr conn, const char *sexpr, int xendConfigVersion); +char * +xenDaemonFormatSxpr(virConnectPtr conn, + virDomainDefPtr def, + int xendConfigVersion); int is_sound_model_valid(const char *model); int is_sound_model_conflict(const char *model, const char *soundstr); @@ -163,7 +165,4 @@ int xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path, unsigned long long offset, size_t size, void *buffer); -#ifdef __cplusplus -} -#endif -#endif +#endif /* __XEND_INTERNAL_H_ */ diff -r ae83be3e7918 src/xm_internal.c --- a/src/xm_internal.c Thu Jul 03 12:50:05 2008 +0100 +++ b/src/xm_internal.c Thu Jul 03 13:02:42 2008 +0100 @@ -1475,16 +1475,9 @@ int ret; unsigned char uuid[VIR_UUID_BUFLEN]; xenUnifiedPrivatePtr priv; - - if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { - xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG, - __FUNCTION__); - return (-1); - } + virDomainDefPtr def; if (domain->id != -1) - return (-1); - if (domain->conn->flags & VIR_CONNECT_RO) return (-1); if (!(xml = xenXMDomainDumpXML(domain, 0))) @@ -1492,11 +1485,20 @@ priv = (xenUnifiedPrivatePtr) domain->conn->privateData; - if (!(sexpr = virDomainParseXMLDesc(domain->conn, xml, NULL, priv->xendConfigVersion))) { - VIR_FREE(xml); + if (!(def = virDomainDefParseString(domain->conn, priv->caps, xml))) { + xenXMError(domain->conn, VIR_ERR_XML_ERROR, + _("failed to parse domain description")); return (-1); } VIR_FREE(xml); + + if (!(sexpr = xenDaemonFormatSxpr(domain->conn, def, priv->xendConfigVersion))) { + virDomainDefFree(def); + xenXMError(domain->conn, VIR_ERR_XML_ERROR, + _("failed to build sexpr")); + return (-1); + } + virDomainDefFree(def); ret = xenDaemonDomainCreateLinux(domain->conn, sexpr); VIR_FREE(sexpr); diff -r ae83be3e7918 src/xml.c --- a/src/xml.c Thu Jul 03 12:50:05 2008 +0100 +++ b/src/xml.c Thu Jul 03 13:02:42 2008 +0100 @@ -15,21 +15,15 @@ #include <string.h> #include <stdarg.h> #include <limits.h> -#ifdef WITH_XEN -#include <xs.h> -#endif #include <math.h> /* for isnan() */ #include "c-ctype.h" #include "internal.h" -#include "hash.h" -#include "sexpr.h" #include "xml.h" #include "buf.h" #include "util.h" #include "memory.h" -#include "xs_internal.h" /* for xenStoreDomainGetNetworkID */ -#include "xen_unified.h" #include "xend_internal.h" /* for is_sound_* functions */ + /** * virXMLError: @@ -54,317 +48,6 @@ errmsg, info, NULL, value, 0, errmsg, info, value); } -/************************************************************************ - * * - * Parser and converter for the CPUset strings used in libvirt * - * * - ************************************************************************/ -#if WITH_XEN || WITH_QEMU -/** - * parseCpuNumber: - * @str: pointer to the char pointer used - * @maxcpu: maximum CPU number allowed - * - * Parse a CPU number - * - * Returns the CPU number or -1 in case of error. @str will be - * updated to skip the number. - */ -static int -parseCpuNumber(const char **str, int maxcpu) -{ - int ret = 0; - const char *cur = *str; - - if (!c_isdigit(*cur)) - return (-1); - - while (c_isdigit(*cur)) { - ret = ret * 10 + (*cur - '0'); - if (ret >= maxcpu) - return (-1); - cur++; - } - *str = cur; - return (ret); -} - -/** - * virSaveCpuSet: - * @conn: connection - * @cpuset: pointer to a char array for the CPU set - * @maxcpu: number of elements available in @cpuset - * - * Serialize the cpuset to a string - * - * Returns the new string NULL in case of error. The string need to be - * freed by the caller. - */ -char * -virSaveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu) -{ - virBuffer buf = VIR_BUFFER_INITIALIZER; - int start, cur; - int first = 1; - - if ((cpuset == NULL) || (maxcpu <= 0) || (maxcpu > 100000)) - return (NULL); - - cur = 0; - start = -1; - while (cur < maxcpu) { - if (cpuset[cur]) { - if (start == -1) - start = cur; - } else if (start != -1) { - if (!first) - virBufferAddLit(&buf, ","); - else - first = 0; - if (cur == start + 1) - virBufferVSprintf(&buf, "%d", start); - else - virBufferVSprintf(&buf, "%d-%d", start, cur - 1); - start = -1; - } - cur++; - } - if (start != -1) { - if (!first) - virBufferAddLit(&buf, ","); - if (maxcpu == start + 1) - virBufferVSprintf(&buf, "%d", start); - else - virBufferVSprintf(&buf, "%d-%d", start, maxcpu - 1); - } - - if (virBufferError(&buf)) { - virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 1000); - return NULL; - } - - return virBufferContentAndReset(&buf); -} - -/** - * virParseCpuSet: - * @conn: connection - * @str: pointer to a CPU set string pointer - * @sep: potential character used to mark the end of string if not 0 - * @cpuset: pointer to a char array for the CPU set - * @maxcpu: number of elements available in @cpuset - * - * Parse the cpu set, it will set the value for enabled CPUs in the @cpuset - * to 1, and 0 otherwise. The syntax allows coma separated entries each - * can be either a CPU number, ^N to unset that CPU or N-M for ranges. - * - * Returns the number of CPU found in that set, or -1 in case of error. - * @cpuset is modified accordingly to the value parsed. - * @str is updated to the end of the part parsed - */ -int -virParseCpuSet(virConnectPtr conn, const char **str, char sep, - char *cpuset, int maxcpu) -{ - const char *cur; - int ret = 0; - int i, start, last; - int neg = 0; - - if ((str == NULL) || (cpuset == NULL) || (maxcpu <= 0) || - (maxcpu > 100000)) - return (-1); - - cur = *str; - virSkipSpaces(&cur); - if (*cur == 0) - goto parse_error; - - /* initialize cpumap to all 0s */ - for (i = 0; i < maxcpu; i++) - cpuset[i] = 0; - ret = 0; - - while ((*cur != 0) && (*cur != sep)) { - /* - * 3 constructs are allowed: - * - N : a single CPU number - * - N-M : a range of CPU numbers with N < M - * - ^N : remove a single CPU number from the current set - */ - if (*cur == '^') { - cur++; - neg = 1; - } - - if (!c_isdigit(*cur)) - goto parse_error; - start = parseCpuNumber(&cur, maxcpu); - if (start < 0) - goto parse_error; - virSkipSpaces(&cur); - if ((*cur == ',') || (*cur == 0) || (*cur == sep)) { - if (neg) { - if (cpuset[start] == 1) { - cpuset[start] = 0; - ret--; - } - } else { - if (cpuset[start] == 0) { - cpuset[start] = 1; - ret++; - } - } - } else if (*cur == '-') { - if (neg) - goto parse_error; - cur++; - virSkipSpaces(&cur); - last = parseCpuNumber(&cur, maxcpu); - if (last < start) - goto parse_error; - for (i = start; i <= last; i++) { - if (cpuset[i] == 0) { - cpuset[i] = 1; - ret++; - } - } - virSkipSpaces(&cur); - } - if (*cur == ',') { - cur++; - virSkipSpaces(&cur); - neg = 0; - } else if ((*cur == 0) || (*cur == sep)) { - break; - } else - goto parse_error; - } - *str = cur; - return (ret); - - parse_error: - virXMLError(conn, VIR_ERR_XEN_CALL, - _("topology cpuset syntax error"), 0); - return (-1); -} -#endif - -#if WITH_XEN -/** - * virConvertCpuSet: - * @conn: connection - * @str: pointer to a Xen or user provided CPU set string pointer - * @maxcpu: number of CPUs on the node, if 0 4096 will be used - * - * Parse the given CPU set string and convert it to a range based - * string. - * - * Returns a new string which must be freed by the caller or NULL in - * case of error. - */ -char * -virConvertCpuSet(virConnectPtr conn, const char *str, int maxcpu) { - int ret; - char *res, *cpuset; - const char *cur = str; - - if (str == NULL) - return(NULL); - - if (maxcpu <= 0) - maxcpu = 4096; - - if (VIR_ALLOC_N(cpuset, maxcpu) < 0) { - virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0); - return(NULL); - } - - ret = virParseCpuSet(conn, &cur, 0, cpuset, maxcpu); - if (ret < 0) { - VIR_FREE(cpuset); - return(NULL); - } - res = virSaveCpuSet(conn, cpuset, maxcpu); - VIR_FREE(cpuset); - return (res); -} - -#ifndef PROXY -/** - * virBuildSoundStringFromXML - * @sound buffer to populate - * @len size of preallocated buffer 'sound' - * @ctxt xml context to pull sound info from - * - * Builds a string of the form m1,m2,m3 from the different sound models - * in the xml. String must be free'd by caller. - * - * Returns string on success, NULL on error - */ -char * virBuildSoundStringFromXML(virConnectPtr conn, - xmlXPathContextPtr ctxt) { - - int nb_nodes, size = 256; - char *sound; - xmlNodePtr *nodes = NULL; - - if (VIR_ALLOC_N(sound, size + 1) < 0) { - virXMLError(conn, VIR_ERR_NO_MEMORY, - _("failed to allocate sound string"), 0); - return NULL; - } - - nb_nodes = virXPathNodeSet("/domain/devices/sound", ctxt, &nodes); - if (nb_nodes > 0) { - int i; - for (i = 0; i < nb_nodes && size > 0; i++) { - char *model = NULL; - int collision = 0; - - model = (char *) xmlGetProp(nodes[i], (xmlChar *) "model"); - if (!model) { - virXMLError(conn, VIR_ERR_XML_ERROR, - _("no model for sound device"), 0); - goto error; - } - - if (!is_sound_model_valid(model)) { - virXMLError(conn, VIR_ERR_XML_ERROR, - _("unknown sound model type"), 0); - VIR_FREE(model); - goto error; - } - - // Check for duplicates in currently built string - if (*sound) - collision = is_sound_model_conflict(model, sound); - - // If no collision, add to string - if (!collision) { - if (*sound && (size >= (strlen(model) + 1))) { - strncat(sound, ",", size--); - } else if (*sound || size < strlen(model)) { - VIR_FREE(model); - continue; - } - strncat(sound, model, size); - size -= strlen(model); - } - - VIR_FREE(model); - } - } - VIR_FREE(nodes); - return sound; - - error: - VIR_FREE(nodes); - return NULL; -} -#endif /* !PROXY */ -#endif /* WITH_XEN */ -#ifndef PROXY /************************************************************************ * * @@ -685,148 +368,118 @@ return (ret); } -/************************************************************************ - * * - * Converter functions to go from the XML tree to an S-Expr for Xen * - * * - ************************************************************************/ #if WITH_XEN +#ifndef PROXY /** - * virtDomainParseXMLGraphicsDescImage: - * @conn: pointer to the hypervisor connection - * @node: node containing graphics description - * @buf: a buffer for the result S-Expr - * @xendConfigVersion: xend configuration file format + * virConvertCpuSet: + * @conn: connection + * @str: pointer to a Xen or user provided CPU set string pointer + * @maxcpu: number of CPUs on the node, if 0 4096 will be used * - * Parse the graphics part of the XML description and add it to the S-Expr - * in buf. This is a temporary interface as the S-Expr interface will be - * replaced by XML-RPC in the future. However the XML format should stay - * valid over time. + * Parse the given CPU set string and convert it to a range based + * string. * - * Returns 0 in case of success, -1 in case of error + * Returns a new string which must be freed by the caller or NULL in + * case of error. */ -static int -virDomainParseXMLGraphicsDescImage(virConnectPtr conn ATTRIBUTE_UNUSED, - xmlNodePtr node, virBufferPtr buf, - int xendConfigVersion) -{ - xmlChar *graphics_type = NULL; +char * +virConvertCpuSet(virConnectPtr conn, const char *str, int maxcpu) { + int ret; + char *res, *cpuset; + const char *cur = str; - graphics_type = xmlGetProp(node, BAD_CAST "type"); - if (graphics_type != NULL) { - if (xmlStrEqual(graphics_type, BAD_CAST "sdl")) { - virBufferAddLit(buf, "(sdl 1)"); - /* TODO: - * Need to understand sdl options - * - *virBufferAddLit(buf, "(display localhost:10.0)"); - *virBufferAddLit(buf, "(xauthority /root/.Xauthority)"); - */ - } else if (xmlStrEqual(graphics_type, BAD_CAST "vnc")) { - virBufferAddLit(buf, "(vnc 1)"); - if (xendConfigVersion >= 2) { - xmlChar *vncport = xmlGetProp(node, BAD_CAST "port"); - xmlChar *vnclisten = xmlGetProp(node, BAD_CAST "listen"); - xmlChar *vncpasswd = xmlGetProp(node, BAD_CAST "passwd"); - xmlChar *keymap = xmlGetProp(node, BAD_CAST "keymap"); + if (str == NULL) + return(NULL); - if (vncport != NULL) { - long port = strtol((const char *) vncport, NULL, 10); + if (maxcpu <= 0) + maxcpu = 4096; - if (port == -1) - virBufferAddLit(buf, "(vncunused 1)"); - else if (port >= 5900) - virBufferVSprintf(buf, "(vncdisplay %ld)", - port - 5900); - xmlFree(vncport); - } - if (vnclisten != NULL) { - virBufferVSprintf(buf, "(vnclisten %s)", vnclisten); - xmlFree(vnclisten); - } - if (vncpasswd != NULL) { - virBufferVSprintf(buf, "(vncpasswd %s)", vncpasswd); - xmlFree(vncpasswd); - } - if (keymap != NULL) { - virBufferVSprintf(buf, "(keymap %s)", keymap); - xmlFree(keymap); - } - } - } - xmlFree(graphics_type); + if (VIR_ALLOC_N(cpuset, maxcpu) < 0) { + virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0); + return(NULL); } - return 0; + + ret = virDomainCpuSetParse(conn, &cur, 0, cpuset, maxcpu); + if (ret < 0) { + VIR_FREE(cpuset); + return(NULL); + } + res = virDomainCpuSetFormat(conn, cpuset, maxcpu); + VIR_FREE(cpuset); + return (res); } /** - * virtDomainParseXMLGraphicsDescVFB: - * @conn: pointer to the hypervisor connection - * @node: node containing graphics description - * @buf: a buffer for the result S-Expr + * virBuildSoundStringFromXML + * @sound buffer to populate + * @len size of preallocated buffer 'sound' + * @ctxt xml context to pull sound info from * - * Parse the graphics part of the XML description and add it to the S-Expr - * in buf. This is a temporary interface as the S-Expr interface will be - * replaced by XML-RPC in the future. However the XML format should stay - * valid over time. + * Builds a string of the form m1,m2,m3 from the different sound models + * in the xml. String must be free'd by caller. * - * Returns 0 in case of success, -1 in case of error + * Returns string on success, NULL on error */ -static int -virDomainParseXMLGraphicsDescVFB(virConnectPtr conn ATTRIBUTE_UNUSED, - xmlNodePtr node, virBufferPtr buf) -{ - xmlChar *graphics_type = NULL; +char * virBuildSoundStringFromXML(virConnectPtr conn, + xmlXPathContextPtr ctxt) { - graphics_type = xmlGetProp(node, BAD_CAST "type"); - if (graphics_type != NULL) { - virBufferAddLit(buf, "(device (vkbd))"); - virBufferAddLit(buf, "(device (vfb "); - if (xmlStrEqual(graphics_type, BAD_CAST "sdl")) { - virBufferAddLit(buf, "(type sdl)"); - /* TODO: - * Need to understand sdl options - * - *virBufferAddLit(buf, "(display localhost:10.0)"); - *virBufferAddLit(buf, "(xauthority /root/.Xauthority)"); - */ - } else if (xmlStrEqual(graphics_type, BAD_CAST "vnc")) { - virBufferAddLit(buf, "(type vnc)"); - xmlChar *vncport = xmlGetProp(node, BAD_CAST "port"); - xmlChar *vnclisten = xmlGetProp(node, BAD_CAST "listen"); - xmlChar *vncpasswd = xmlGetProp(node, BAD_CAST "passwd"); - xmlChar *keymap = xmlGetProp(node, BAD_CAST "keymap"); + int nb_nodes, size = 256; + char *sound; + xmlNodePtr *nodes = NULL; - if (vncport != NULL) { - long port = strtol((const char *) vncport, NULL, 10); + if (VIR_ALLOC_N(sound, size + 1) < 0) { + virXMLError(conn, VIR_ERR_NO_MEMORY, + _("failed to allocate sound string"), 0); + return NULL; + } - if (port == -1) - virBufferAddLit(buf, "(vncunused 1)"); - else if (port >= 5900) - virBufferVSprintf(buf, "(vncdisplay %ld)", - port - 5900); - xmlFree(vncport); + nb_nodes = virXPathNodeSet("/domain/devices/sound", ctxt, &nodes); + if (nb_nodes > 0) { + int i; + for (i = 0; i < nb_nodes && size > 0; i++) { + char *model = NULL; + int collision = 0; + + model = (char *) xmlGetProp(nodes[i], (xmlChar *) "model"); + if (!model) { + virXMLError(conn, VIR_ERR_XML_ERROR, + _("no model for sound device"), 0); + goto error; } - if (vnclisten != NULL) { - virBufferVSprintf(buf, "(vnclisten %s)", vnclisten); - xmlFree(vnclisten); + + if (!is_sound_model_valid(model)) { + virXMLError(conn, VIR_ERR_XML_ERROR, + _("unknown sound model type"), 0); + VIR_FREE(model); + goto error; } - if (vncpasswd != NULL) { - virBufferVSprintf(buf, "(vncpasswd %s)", vncpasswd); - xmlFree(vncpasswd); + + // Check for duplicates in currently built string + if (*sound) + collision = is_sound_model_conflict(model, sound); + + // If no collision, add to string + if (!collision) { + if (*sound && (size >= (strlen(model) + 1))) { + strncat(sound, ",", size--); + } else if (*sound || size < strlen(model)) { + VIR_FREE(model); + continue; + } + strncat(sound, model, size); + size -= strlen(model); } - if (keymap != NULL) { - virBufferVSprintf(buf, "(keymap %s)", keymap); - xmlFree(keymap); - } + + VIR_FREE(model); } - virBufferAddLit(buf, "))"); - xmlFree(graphics_type); } - return 0; + VIR_FREE(nodes); + return sound; + error: + VIR_FREE(nodes); + return NULL; } - int virDomainParseXMLOSDescHVMChar(virConnectPtr conn, @@ -1000,1123 +653,6 @@ return -1; } -/** - * virDomainParseXMLOSDescHVM: - * @conn: pointer to the hypervisor connection - * @node: node containing HVM OS description - * @buf: a buffer for the result S-Expr - * @ctxt: a path context representing the XML description - * @vcpus: number of virtual CPUs to configure - * @xendConfigVersion: xend configuration file format - * @hasKernel: whether the domain is booting from a kernel - * - * Parse the OS part of the XML description for a HVM domain - * and add it to the S-Expr in buf. - * - * Returns 0 in case of success, -1 in case of error. - */ -static int -virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, - virBufferPtr buf, xmlXPathContextPtr ctxt, - int vcpus, int xendConfigVersion, - int hasKernel) -{ - xmlNodePtr cur, txt; - xmlNodePtr *nodes = NULL; - xmlChar *loader = NULL; - char bootorder[5]; - int nbootorder = 0; - int res, nb_nodes; - char *str; +#endif /* !PROXY */ - cur = node->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE) { - if ((loader == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "loader"))) { - txt = cur->children; - if ((txt != NULL) && (txt->type == XML_TEXT_NODE) && - (txt->next == NULL)) - loader = txt->content; - } else if ((xmlStrEqual(cur->name, BAD_CAST "boot"))) { - xmlChar *boot_dev = xmlGetProp(cur, BAD_CAST "dev"); - - if (nbootorder == - ((sizeof(bootorder) / sizeof(bootorder[0])) - 1)) { - virXMLError(conn, VIR_ERR_XML_ERROR, - _("too many boot devices"), 0); - return (-1); - } - if (xmlStrEqual(boot_dev, BAD_CAST "fd")) { - bootorder[nbootorder++] = 'a'; - } else if (xmlStrEqual(boot_dev, BAD_CAST "cdrom")) { - bootorder[nbootorder++] = 'd'; - } else if (xmlStrEqual(boot_dev, BAD_CAST "network")) { - bootorder[nbootorder++] = 'n'; - } else if (xmlStrEqual(boot_dev, BAD_CAST "hd")) { - bootorder[nbootorder++] = 'c'; - } else { - xmlFree(boot_dev); - /* Any other type of boot dev is unsupported right now */ - virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0); - return (-1); - } - xmlFree(boot_dev); - } - } - cur = cur->next; - } - /* - * XenD always needs boot order defined for HVM, even if - * booting off a kernel + initrd, so force to 'c' if nothing - * else is specified - */ - if (nbootorder == 0) - bootorder[nbootorder++] = 'c'; - bootorder[nbootorder] = '\0'; - - if (loader == NULL) { - virXMLError(conn, VIR_ERR_INTERNAL_ERROR, _("no HVM domain loader"), 0); - return -1; - } - - /* - * Originally XenD abused the 'kernel' parameter for the HVM - * firmware. New XenD allows HVM guests to boot from a kernel - * and if this is enabled, the HVM firmware must use the new - * 'loader' parameter - */ - if (hasKernel) { - virBufferVSprintf(buf, "(loader '%s')", (const char *) loader); - } else { - virBufferVSprintf(buf, "(kernel '%s')", (const char *) loader); - } - - virBufferVSprintf(buf, "(vcpus %d)", vcpus); - - if (nbootorder) - virBufferVSprintf(buf, "(boot %s)", bootorder); - - /* get the 1st floppy device file */ - cur = virXPathNode( - "/domain/devices/disk[@device='floppy' and target/@dev='fda']/source", - ctxt); - if (cur != NULL) { - xmlChar *fdfile; - - fdfile = xmlGetProp(cur, BAD_CAST "file"); - if (fdfile != NULL) { - virBufferVSprintf(buf, "(fda '%s')", fdfile); - VIR_FREE(fdfile); - } - } - - /* get the 2nd floppy device file */ - cur = virXPathNode( - "/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source", - ctxt); - if (cur != NULL) { - xmlChar *fdfile; - - fdfile = xmlGetProp(cur, BAD_CAST "file"); - if (fdfile != NULL) { - virBufferVSprintf(buf, "(fdb '%s')", fdfile); - VIR_FREE(fdfile); - } - } - - /* get the cdrom device file */ - /* Only XenD <= 3.0.2 wants cdrom config here */ - if (xendConfigVersion == 1) { - cur = virXPathNode( - "/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source", - ctxt); - if (cur != NULL) { - xmlChar *cdfile; - - cdfile = xmlGetProp(cur, BAD_CAST "file"); - if (cdfile != NULL) { - virBufferVSprintf(buf, "(cdrom '%s')", - (const char *) cdfile); - xmlFree(cdfile); - } - } - } - - if (virXPathNode("/domain/features/acpi", ctxt) != NULL) - virBufferAddLit(buf, "(acpi 1)"); - if (virXPathNode("/domain/features/apic", ctxt) != NULL) - virBufferAddLit(buf, "(apic 1)"); - if (virXPathNode("/domain/features/pae", ctxt) != NULL) - virBufferAddLit(buf, "(pae 1)"); - - virBufferAddLit(buf, "(usb 1)"); - nb_nodes = virXPathNodeSet("/domain/devices/input", ctxt, &nodes); - if (nb_nodes > 0) { - int i; - - for (i = 0; i < nb_nodes; i++) { - xmlChar *itype = NULL, *bus = NULL; - int isMouse = 1; - - itype = xmlGetProp(nodes[i], (xmlChar *) "type"); - - if (!itype) { - goto error; - } - if (STREQ((const char *) itype, "tablet")) - isMouse = 0; - else if (STRNEQ((const char *) itype, "mouse")) { - xmlFree(itype); - virXMLError(conn, VIR_ERR_XML_ERROR, - _("invalid input device"), 0); - goto error; - } - xmlFree(itype); - - bus = xmlGetProp(nodes[i], (xmlChar *) "bus"); - if (!bus) { - if (!isMouse) { - /* Nothing - implicit ps2 */ - } else { - virBufferAddLit(buf, "(usbdevice tablet)"); - } - } else { - if (STREQ((const char *) bus, "ps2")) { - if (!isMouse) { - xmlFree(bus); - virXMLError(conn, VIR_ERR_XML_ERROR, - _("invalid input device"), 0); - goto error; - } - /* Nothing - implicit ps2 */ - } else if (STREQ((const char *) bus, "usb")) { - if (isMouse) - virBufferAddLit(buf, "(usbdevice mouse)"); - else - virBufferAddLit(buf, "(usbdevice tablet)"); - } - } - xmlFree(bus); - } - VIR_FREE(nodes); - nodes = NULL; - } - - cur = virXPathNode("/domain/devices/parallel[1]", ctxt); - if (cur != NULL) { - char scratch[PATH_MAX]; - if (virDomainParseXMLOSDescHVMChar(conn, scratch, sizeof(scratch), cur) < 0) - goto error; - virBufferVSprintf(buf, "(parallel %s)", scratch); - } else { - virBufferAddLit(buf, "(parallel none)"); - } - - cur = virXPathNode("/domain/devices/serial[1]", ctxt); - if (cur != NULL) { - char scratch[PATH_MAX]; - if (virDomainParseXMLOSDescHVMChar(conn, scratch, sizeof(scratch), cur) < 0) - goto error; - virBufferVSprintf(buf, "(serial %s)", scratch); - } else { - res = virXPathBoolean("count(/domain/devices/console) > 0", ctxt); - if (res < 0) { - virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0); - goto error; - } - if (res) { - virBufferAddLit(buf, "(serial pty)"); - } else { - virBufferAddLit(buf, "(serial none)"); - } - } - - cur = virXPathNode("/domain/devices/sound", ctxt); - if (cur) { - char *soundstr; - if (!(soundstr = virBuildSoundStringFromXML(conn, ctxt))) - goto error; - virBufferVSprintf(buf, "(soundhw '%s')", soundstr); - VIR_FREE(soundstr); - } - - str = virXPathString("string(/domain/clock/@offset)", ctxt); - if (str != NULL && STREQ(str, "localtime")) { - virBufferAddLit(buf, "(localtime 1)"); - } - VIR_FREE(str); - - return (0); - - error: - VIR_FREE(nodes); - return (-1); -} - - -/** - * virDomainParseXMLOSDescKernel: - * @conn: pointer to the hypervisor connection - * @node: node containing PV OS description - * @buf: a buffer for the result S-Expr - * - * Parse the OS part of the XML description for a domain using a direct - * kernel and initrd to boot. - * - * Returns 0 in case of success, -1 in case of error. - */ -static int -virDomainParseXMLOSDescKernel(virConnectPtr conn ATTRIBUTE_UNUSED, - xmlNodePtr node, - virBufferPtr buf) -{ - xmlNodePtr cur, txt; - const xmlChar *root = NULL; - const xmlChar *kernel = NULL; - const xmlChar *initrd = NULL; - const xmlChar *cmdline = NULL; - - cur = node->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE) { - if ((kernel == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "kernel"))) { - txt = cur->children; - if ((txt != NULL) && (txt->type == XML_TEXT_NODE) && - (txt->next == NULL)) - kernel = txt->content; - } else if ((root == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "root"))) { - txt = cur->children; - if ((txt != NULL) && (txt->type == XML_TEXT_NODE) && - (txt->next == NULL)) - root = txt->content; - } else if ((initrd == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "initrd"))) { - txt = cur->children; - if ((txt != NULL) && (txt->type == XML_TEXT_NODE) && - (txt->next == NULL)) - initrd = txt->content; - } else if ((cmdline == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "cmdline"))) { - txt = cur->children; - if ((txt != NULL) && (txt->type == XML_TEXT_NODE) && - (txt->next == NULL)) - cmdline = txt->content; - } - } - cur = cur->next; - } - - virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel); - - if (initrd != NULL) - virBufferVSprintf(buf, "(ramdisk '%s')", (const char *) initrd); - if (root != NULL) - virBufferVSprintf(buf, "(root '%s')", (const char *) root); - if (cmdline != NULL) - virBufferVSprintf(buf, "(args '%s')", (const char *) cmdline); - - return (0); -} - -/** - * virCatchXMLParseError: - * @ctx: the context - * @msg: the error message - * @...: extra arguments - * - * SAX callback on parsing errors, act as a gate for libvirt own - * error reporting. - */ -static void -virCatchXMLParseError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) -{ - xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; - - if ((ctxt != NULL) && - (ctxt->lastError.level == XML_ERR_FATAL) && - (ctxt->lastError.message != NULL)) { - virXMLError(NULL, VIR_ERR_XML_DETAIL, ctxt->lastError.message, - ctxt->lastError.line); - } -} - -/** - * virDomainParseXMLDiskDesc: - * @node: node containing disk description - * @conn: pointer to the hypervisor connection - * @buf: a buffer for the result S-Expr - * @xendConfigVersion: xend configuration file format - * - * Parse the one disk in the XML description and add it to the S-Expr in buf - * This is a temporary interface as the S-Expr interface - * will be replaced by XML-RPC in the future. However the XML format should - * stay valid over time. - * - * Returns 0 in case of success, -1 in case of error. - */ -static int -virDomainParseXMLDiskDesc(virConnectPtr conn, xmlNodePtr node, - virBufferPtr buf, int hvm, int xendConfigVersion) -{ - xmlNodePtr cur; - xmlChar *type = NULL; - xmlChar *device = NULL; - xmlChar *source = NULL; - xmlChar *target = NULL; - xmlChar *drvName = NULL; - xmlChar *drvType = NULL; - int ro = 0; - int shareable = 0; - int typ = 0; - int cdrom = 0; - int isNoSrcCdrom = 0; - int ret = 0; - - type = xmlGetProp(node, BAD_CAST "type"); - if (type != NULL) { - if (xmlStrEqual(type, BAD_CAST "file")) - typ = 0; - else if (xmlStrEqual(type, BAD_CAST "block")) - typ = 1; - xmlFree(type); - } - device = xmlGetProp(node, BAD_CAST "device"); - - cur = node->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE) { - if ((source == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "source"))) { - - if (typ == 0) - source = xmlGetProp(cur, BAD_CAST "file"); - else - source = xmlGetProp(cur, BAD_CAST "dev"); - } else if ((target == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "target"))) { - target = xmlGetProp(cur, BAD_CAST "dev"); - } else if ((drvName == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "driver"))) { - drvName = xmlGetProp(cur, BAD_CAST "name"); - if (drvName && STREQ((const char *) drvName, "tap")) - drvType = xmlGetProp(cur, BAD_CAST "type"); - } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) { - ro = 1; - } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) { - shareable = 1; - } - } - cur = cur->next; - } - - if (source == NULL) { - /* There is a case without the source - * to the CD-ROM device - */ - if (hvm && device && STREQ((const char *) device, "cdrom")) { - isNoSrcCdrom = 1; - } - if (!isNoSrcCdrom) { - virXMLError(conn, VIR_ERR_NO_SOURCE, (const char *) target, 0); - ret = -1; - goto cleanup; - } - } - if (target == NULL) { - virXMLError(conn, VIR_ERR_NO_TARGET, (const char *) source, 0); - ret = -1; - goto cleanup; - } - - /* Xend (all versions) put the floppy device config - * under the hvm (image (os)) block - */ - if (hvm && device && STREQ((const char *) device, "floppy")) { - goto cleanup; - } - - /* Xend <= 3.0.2 doesn't include cdrom config here */ - if (hvm && device && STREQ((const char *) device, "cdrom")) { - if (xendConfigVersion == 1) - goto cleanup; - else - cdrom = 1; - } - - - virBufferAddLit(buf, "(device "); - /* Normally disks are in a (device (vbd ...)) block - * but blktap disks ended up in a differently named - * (device (tap ....)) block.... */ - if (drvName && STREQ((const char *) drvName, "tap")) { - virBufferAddLit(buf, "(tap "); - } else { - virBufferAddLit(buf, "(vbd "); - } - - if (hvm) { - char *tmp = (char *) target; - - /* Just in case user mistakenly still puts ioemu: in their XML */ - if (STRPREFIX((const char *) tmp, "ioemu:")) - tmp += 6; - - /* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */ - if (xendConfigVersion == 1) - virBufferVSprintf(buf, "(dev 'ioemu:%s')", (const char *) tmp); - else /* But newer does not */ - virBufferVSprintf(buf, "(dev '%s%s')", (const char *) tmp, - cdrom ? ":cdrom" : ":disk"); - } else - virBufferVSprintf(buf, "(dev '%s')", (const char *) target); - - if (drvName && !isNoSrcCdrom) { - if (STREQ((const char *) drvName, "tap")) { - virBufferVSprintf(buf, "(uname '%s:%s:%s')", - (const char *) drvName, - (drvType ? (const char *) drvType : "aio"), - (const char *) source); - } else { - virBufferVSprintf(buf, "(uname '%s:%s')", - (const char *) drvName, - (const char *) source); - } - } else if (!isNoSrcCdrom) { - if (typ == 0) - virBufferVSprintf(buf, "(uname 'file:%s')", source); - else if (typ == 1) { - if (source[0] == '/') - virBufferVSprintf(buf, "(uname 'phy:%s')", source); - else - virBufferVSprintf(buf, "(uname 'phy:/dev/%s')", source); - } - } - if (ro == 1) - virBufferAddLit(buf, "(mode 'r')"); - else if (shareable == 1) - virBufferAddLit(buf, "(mode 'w!')"); - else - virBufferAddLit(buf, "(mode 'w')"); - - virBufferAddLit(buf, ")"); - virBufferAddLit(buf, ")"); - - cleanup: - xmlFree(drvType); - xmlFree(drvName); - xmlFree(device); - xmlFree(target); - xmlFree(source); - return (ret); -} - -/** - * virDomainParseXMLIfDesc: - * @conn: pointer to the hypervisor connection - * @node: node containing the interface description - * @buf: a buffer for the result S-Expr - * @xendConfigVersion: xend configuration file format - * - * Parse the one interface the XML description and add it to the S-Expr in buf - * This is a temporary interface as the S-Expr interface - * will be replaced by XML-RPC in the future. However the XML format should - * stay valid over time. - * - * Returns 0 in case of success, -1 in case of error. - */ -static int -virDomainParseXMLIfDesc(virConnectPtr conn ATTRIBUTE_UNUSED, - xmlNodePtr node, virBufferPtr buf, int hvm, - int xendConfigVersion) -{ - xmlNodePtr cur; - xmlChar *type = NULL; - xmlChar *source = NULL; - xmlChar *mac = NULL; - xmlChar *script = NULL; - xmlChar *model = NULL; - xmlChar *ip = NULL; - int typ = 0; - int ret = -1; - - type = xmlGetProp(node, BAD_CAST "type"); - if (type != NULL) { - if (xmlStrEqual(type, BAD_CAST "bridge")) - typ = 0; - else if (xmlStrEqual(type, BAD_CAST "ethernet")) - typ = 1; - else if (xmlStrEqual(type, BAD_CAST "network")) - typ = 2; - xmlFree(type); - } - cur = node->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE) { - if ((source == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "source"))) { - if (typ == 0) - source = xmlGetProp(cur, BAD_CAST "bridge"); - else if (typ == 1) - source = xmlGetProp(cur, BAD_CAST "dev"); - else - source = xmlGetProp(cur, BAD_CAST "network"); - } else if ((mac == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "mac"))) { - mac = xmlGetProp(cur, BAD_CAST "address"); - } else if ((script == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "script"))) { - script = xmlGetProp(cur, BAD_CAST "path"); - } else if ((model == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "model"))) { - model = xmlGetProp(cur, BAD_CAST "type"); - } else if ((ip == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "ip"))) { - /* XXX in future expect to need to have > 1 ip - * address element - eg ipv4 & ipv6. For now - * xen only supports a single address though - * so lets ignore that complication */ - ip = xmlGetProp(cur, BAD_CAST "address"); - } - } - cur = cur->next; - } - - virBufferAddLit(buf, "(vif "); - if (mac != NULL) { - unsigned char addr[6]; - if (virParseMacAddr((const char*) mac, addr) == -1) { - virXMLError(conn, VIR_ERR_INVALID_MAC, (const char *) mac, 0); - goto error; - } - virBufferVSprintf(buf, "(mac '%s')", (const char *) mac); - } - if (source != NULL) { - if (typ == 0) - virBufferVSprintf(buf, "(bridge '%s')", (const char *) source); - else if (typ == 1) /* TODO does that work like that ? */ - virBufferVSprintf(buf, "(dev '%s')", (const char *) source); - else { - virNetworkPtr network = - virNetworkLookupByName(conn, (const char *) source); - char *bridge; - - if (!network || !(bridge = virNetworkGetBridgeName(network))) { - if (network) - virNetworkFree(network); - virXMLError(conn, VIR_ERR_NO_SOURCE, (const char *) source, - 0); - goto error; - } - virNetworkFree(network); - virBufferVSprintf(buf, "(bridge '%s')", bridge); - VIR_FREE(bridge); - } - } - if (script != NULL) - virBufferVSprintf(buf, "(script '%s')", script); - if (model != NULL) - virBufferVSprintf(buf, "(model '%s')", model); - if (ip != NULL) - virBufferVSprintf(buf, "(ip '%s')", ip); - /* - * apparently (type ioemu) breaks paravirt drivers on HVM so skip this - * from Xen 3.1.0 - */ - if ((hvm) && (xendConfigVersion < 4)) - virBufferAddLit(buf, "(type ioemu)"); - - virBufferAddLit(buf, ")"); - ret = 0; - error: - xmlFree(mac); - xmlFree(source); - xmlFree(script); - xmlFree(ip); - xmlFree(model); - return (ret); -} - -/** - * virDomainParseXMLDesc: - * @conn: pointer to the hypervisor connection - * @xmldesc: string with the XML description - * @xendConfigVersion: xend configuration file format - * - * Parse the XML description and turn it into the xend sexp needed to - * create the domain. This is a temporary interface as the S-Expr interface - * will be replaced by XML-RPC in the future. However the XML format should - * stay valid over time. - * - * Returns the 0 terminatedi S-Expr string or NULL in case of error. - * the caller must free() the returned value. - */ -char * -virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, - int xendConfigVersion) -{ - xmlDocPtr xml = NULL; - xmlNodePtr node; - char *nam = NULL, *tmp; - virBuffer buf = VIR_BUFFER_INITIALIZER; - xmlChar *prop; - xmlParserCtxtPtr pctxt; - xmlXPathContextPtr ctxt = NULL; - int i, res; - int bootloader = 0; - int hvm = 0; - unsigned int vcpus = 1; - unsigned long mem = 0, max_mem = 0; - char *str; - double f; - xmlNodePtr *nodes; - int nb_nodes; - - if (name != NULL) - *name = NULL; - - pctxt = xmlNewParserCtxt(); - if ((pctxt == NULL) || (pctxt->sax == NULL)) { - goto error; - } - - /* TODO pass the connection point to the error handler: - * pctxt->userData = virConnectPtr; - */ - pctxt->sax->error = virCatchXMLParseError; - - xml = xmlCtxtReadDoc(pctxt, (const xmlChar *) xmldesc, "domain.xml", - NULL, XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOWARNING); - if (xml == NULL) { - goto error; - } - node = xmlDocGetRootElement(xml); - if ((node == NULL) || (!xmlStrEqual(node->name, BAD_CAST "domain"))) - goto error; - - prop = xmlGetProp(node, BAD_CAST "type"); - if (prop != NULL) { - if (!xmlStrEqual(prop, BAD_CAST "xen")) { - xmlFree(prop); - goto error; - } - xmlFree(prop); - } - virBufferAddLit(&buf, "(vm "); - ctxt = xmlXPathNewContext(xml); - if (ctxt == NULL) { - goto error; - } - /* - * extract some of the basics, name, memory, cpus ... - */ - nam = virXPathString("string(/domain/name[1])", ctxt); - if (nam == NULL) { - virXMLError(conn, VIR_ERR_NO_NAME, xmldesc, 0); - goto error; - } - virBufferVSprintf(&buf, "(name '%s')", nam); - - if ((virXPathNumber("number(/domain/memory[1])", ctxt, &f) < 0) || - (f < MIN_XEN_GUEST_SIZE * 1024)) { - max_mem = 128; - } else { - max_mem = (f / 1024); - } - - if ((virXPathNumber("number(/domain/currentMemory[1])", ctxt, &f) < 0) - || (f < MIN_XEN_GUEST_SIZE * 1024)) { - mem = max_mem; - } else { - mem = (f / 1024); - if (mem > max_mem) { - max_mem = mem; - } - } - virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", mem, max_mem); - - if ((virXPathNumber("number(/domain/vcpu[1])", ctxt, &f) == 0) && - (f > 0)) { - vcpus = (unsigned int) f; - } - virBufferVSprintf(&buf, "(vcpus %u)", vcpus); - - str = virXPathString("string(/domain/vcpu/@cpuset)", ctxt); - if (str != NULL) { - int maxcpu = xenNbCpus(conn); - char *cpuset = NULL; - char *ranges = NULL; - const char *cur = str; - - /* - * Parse the CPUset attribute given in libvirt format and reserialize - * it in a range format guaranteed to be understood by Xen. - */ - if (maxcpu > 0) { - if (VIR_ALLOC_N(cpuset, maxcpu) < 0) { - virXMLError(conn, VIR_ERR_NO_MEMORY, xmldesc, 0); - goto error; - } - res = virParseCpuSet(conn, &cur, 0, cpuset, maxcpu); - if (res > 0) { - ranges = virSaveCpuSet(conn, cpuset, maxcpu); - if (ranges != NULL) { - virBufferVSprintf(&buf, "(cpus '%s')", ranges); - VIR_FREE(ranges); - } - } - VIR_FREE(cpuset); - if (res < 0) - goto error; - } - VIR_FREE(str); - } - - str = virXPathString("string(/domain/uuid[1])", ctxt); - if (str != NULL) { - virBufferVSprintf(&buf, "(uuid '%s')", str); - VIR_FREE(str); - } - - str = virXPathString("string(/domain/bootloader[1])", ctxt); - if (str != NULL) { - virBufferVSprintf(&buf, "(bootloader '%s')", str); - /* - * if using a bootloader, the kernel and initrd strings are not - * significant and should be discarded - */ - bootloader = 1; - VIR_FREE(str); - } else if (virXPathNumber("count(/domain/bootloader)", ctxt, &f) == 0 - && (f > 0)) { - virBufferAddLit(&buf, "(bootloader)"); - /* - * if using a bootloader, the kernel and initrd strings are not - * significant and should be discarded - */ - bootloader = 1; - } - - str = virXPathString("string(/domain/bootloader_args[1])", ctxt); - if (str != NULL && bootloader) { - /* - * ignore the bootloader_args value unless a bootloader was specified - */ - virBufferVSprintf(&buf, "(bootloader_args '%s')", str); - VIR_FREE(str); - } - - str = virXPathString("string(/domain/on_poweroff[1])", ctxt); - if (str != NULL) { - virBufferVSprintf(&buf, "(on_poweroff '%s')", str); - VIR_FREE(str); - } - - str = virXPathString("string(/domain/on_reboot[1])", ctxt); - if (str != NULL) { - virBufferVSprintf(&buf, "(on_reboot '%s')", str); - VIR_FREE(str); - } - - str = virXPathString("string(/domain/on_crash[1])", ctxt); - if (str != NULL) { - virBufferVSprintf(&buf, "(on_crash '%s')", str); - VIR_FREE(str); - } - - if (!bootloader) { - if ((node = virXPathNode("/domain/os[1]", ctxt)) != NULL) { - int has_kernel = 0; - - /* Analyze of the os description, based on HVM or PV. */ - str = virXPathString("string(/domain/os/type[1])", ctxt); - if ((str != NULL) && STREQ(str, "hvm")) - hvm = 1; - xmlFree(str); - str = NULL; - - if (hvm) - virBufferAddLit(&buf, "(image (hvm "); - else - virBufferAddLit(&buf, "(image (linux "); - - if (virXPathBoolean("count(/domain/os/kernel) > 0", ctxt)) { - if (virDomainParseXMLOSDescKernel(conn, node, - &buf) != 0) - goto error; - has_kernel = 1; - } - - if (hvm && - virDomainParseXMLOSDescHVM(conn, node, - &buf, ctxt, vcpus, - xendConfigVersion, - has_kernel) != 0) - goto error; - - /* get the device emulation model */ - str = virXPathString("string(/domain/devices/emulator[1])", ctxt); - if (str != NULL) { - virBufferVSprintf(&buf, "(device_model '%s')", str); - xmlFree(str); - str = NULL; - } - - /* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */ - if ((!hvm && xendConfigVersion < 3) || - (hvm && xendConfigVersion < 4)) { - xmlNodePtr cur; - cur = virXPathNode("/domain/devices/graphics[1]", ctxt); - if (cur != NULL && - virDomainParseXMLGraphicsDescImage(conn, cur, &buf, - xendConfigVersion) != 0) - goto error; - } - - virBufferAddLit(&buf, "))"); - } else { - virXMLError(conn, VIR_ERR_NO_OS, nam, 0); - goto error; - } - } - - /* analyze of the devices */ - nb_nodes = virXPathNodeSet("/domain/devices/disk", ctxt, &nodes); - if (nb_nodes > 0) { - for (i = 0; i < nb_nodes; i++) { - res = virDomainParseXMLDiskDesc(conn, nodes[i], &buf, - hvm, xendConfigVersion); - if (res != 0) { - VIR_FREE(nodes); - goto error; - } - } - VIR_FREE(nodes); - } - - nb_nodes = virXPathNodeSet("/domain/devices/interface", ctxt, &nodes); - if (nb_nodes > 0) { - for (i = 0; i < nb_nodes; i++) { - virBufferAddLit(&buf, "(device "); - res = - virDomainParseXMLIfDesc(conn, nodes[i], &buf, hvm, - xendConfigVersion); - if (res != 0) { - VIR_FREE(nodes); - goto error; - } - virBufferAddLit(&buf, ")"); - } - VIR_FREE(nodes); - } - - /* New style PV graphics config xen >= 3.0.4, - * or HVM graphics config xen >= 3.0.5 */ - if ((xendConfigVersion >= 3 && !hvm) || - (xendConfigVersion >= 4 && hvm)) { - nb_nodes = virXPathNodeSet("/domain/devices/graphics", ctxt, &nodes); - if (nb_nodes > 0) { - for (i = 0; i < nb_nodes; i++) { - res = virDomainParseXMLGraphicsDescVFB(conn, nodes[i], &buf); - if (res != 0) { - VIR_FREE(nodes); - goto error; - } - } - VIR_FREE(nodes); - } - } - - - virBufferAddLit(&buf, ")"); /* closes (vm */ - - xmlXPathFreeContext(ctxt); - xmlFreeDoc(xml); - xmlFreeParserCtxt(pctxt); - - if (name != NULL) - *name = nam; - else - VIR_FREE(nam); - - if (virBufferError(&buf)) { - virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0); - return NULL; - } - - return virBufferContentAndReset(&buf); - - error: - VIR_FREE(nam); - if (name != NULL) - *name = NULL; - xmlXPathFreeContext(ctxt); - if (xml != NULL) - xmlFreeDoc(xml); - if (pctxt != NULL) - xmlFreeParserCtxt(pctxt); - tmp = virBufferContentAndReset(&buf); - VIR_FREE(tmp); - return (NULL); -} - -/** - * virParseXMLDevice: - * @conn: pointer to the hypervisor connection - * @xmldesc: string with the XML description - * @hvm: 1 for fully virtualized guest, 0 for paravirtualized - * @xendConfigVersion: xend configuration file format - * - * Parse the XML description and turn it into the xend sexp needed to - * create the device. This is a temporary interface as the S-Expr interface - * will be replaced by XML-RPC in the future. However the XML format should - * stay valid over time. - * - * Returns the 0-terminated S-Expr string, or NULL in case of error. - * the caller must free() the returned value. - */ -char * -virParseXMLDevice(virConnectPtr conn, const char *xmldesc, int hvm, - int xendConfigVersion) -{ - xmlDocPtr xml = NULL; - xmlNodePtr node; - virBuffer buf = VIR_BUFFER_INITIALIZER; - - xml = xmlReadDoc((const xmlChar *) xmldesc, "device.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING); - if (xml == NULL) { - virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0); - goto error; - } - node = xmlDocGetRootElement(xml); - if (node == NULL) - goto error; - if (xmlStrEqual(node->name, BAD_CAST "disk")) { - if (virDomainParseXMLDiskDesc(conn, node, &buf, hvm, - xendConfigVersion) != 0) - goto error; - } else if (xmlStrEqual(node->name, BAD_CAST "interface")) { - if (virDomainParseXMLIfDesc(conn, node, &buf, hvm, - xendConfigVersion) != 0) - goto error; - } else { - virXMLError(conn, VIR_ERR_XML_ERROR, (const char *) node->name, 0); - goto error; - } - - xmlFreeDoc(xml); - - if (virBufferError(&buf)) { - virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0); - return NULL; - } - - return virBufferContentAndReset(&buf); - - error: - free(virBufferContentAndReset(&buf)); - xmlFreeDoc(xml); - return NULL; -} - - -/** - * virDomainXMLDevID: - * @domain: pointer to domain object - * @xmldesc: string with the XML description - * @class: Xen device class "vbd" or "vif" (OUT) - * @ref: Xen device reference (OUT) - * - * Set class according to XML root, and: - * - if disk, copy in ref the target name from description - * - if network, get MAC address from description, scan XenStore and - * copy in ref the corresponding vif number. - * - * Returns 0 in case of success, -1 in case of failure. - */ -int -virDomainXMLDevID(virDomainPtr domain, const char *xmldesc, char *class, - char *ref, int ref_len) -{ - xmlDocPtr xml = NULL; - xmlNodePtr node, cur; - xmlChar *attr = NULL; - - char *xref; - int ret = 0; - - xml = xmlReadDoc((const xmlChar *) xmldesc, "device.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING); - if (xml == NULL) { - virXMLError(NULL, VIR_ERR_XML_ERROR, NULL, 0); - goto error; - } - node = xmlDocGetRootElement(xml); - if (node == NULL) - goto error; - if (xmlStrEqual(node->name, BAD_CAST "disk")) { - strcpy(class, "vbd"); - for (cur = node->children; cur != NULL; cur = cur->next) { - if ((cur->type != XML_ELEMENT_NODE) || - (!xmlStrEqual(cur->name, BAD_CAST "target"))) - continue; - attr = xmlGetProp(cur, BAD_CAST "dev"); - if (attr == NULL) - goto error; - xref = xenStoreDomainGetDiskID(domain->conn, domain->id, - (char *) attr); - if (xref != NULL) { - strncpy(ref, xref, ref_len); - free(xref); - ref[ref_len - 1] = '\0'; - goto cleanup; - } - /* hack to avoid the warning that domain is unused */ - if (domain->id < 0) - ret = -1; - - goto error; - } - } else if (xmlStrEqual(node->name, BAD_CAST "interface")) { - strcpy(class, "vif"); - for (cur = node->children; cur != NULL; cur = cur->next) { - if ((cur->type != XML_ELEMENT_NODE) || - (!xmlStrEqual(cur->name, BAD_CAST "mac"))) - continue; - attr = xmlGetProp(cur, BAD_CAST "address"); - if (attr == NULL) - goto error; - - xref = xenStoreDomainGetNetworkID(domain->conn, domain->id, - (char *) attr); - if (xref != NULL) { - strncpy(ref, xref, ref_len); - free(xref); - ref[ref_len - 1] = '\0'; - goto cleanup; - } - /* hack to avoid the warning that domain is unused */ - if (domain->id < 0) - ret = -1; - - goto error; - } - } else { - virXMLError(NULL, VIR_ERR_XML_ERROR, (const char *) node->name, 0); - } - error: - ret = -1; - cleanup: - if (xml != NULL) - xmlFreeDoc(xml); - xmlFree(attr); - return ret; -} #endif /* WITH_XEN */ -#endif /* !PROXY */ diff -r ae83be3e7918 src/xml.h --- a/src/xml.h Thu Jul 03 12:50:05 2008 +0100 +++ b/src/xml.h Thu Jul 03 13:02:42 2008 +0100 @@ -5,16 +5,11 @@ #ifndef __VIR_XML_H__ #define __VIR_XML_H__ -#include "libvirt/libvirt.h" #include "internal.h" -#include "buf.h" #include <libxml/parser.h> #include <libxml/tree.h> #include <libxml/xpath.h> -#ifdef __cplusplus -extern "C" { -#endif int virXPathBoolean (const char *xpath, xmlXPathContextPtr ctxt); @@ -44,43 +39,16 @@ char * virXMLPropString(xmlNodePtr node, const char *name); +char * +virConvertCpuSet(virConnectPtr conn, const char *str, int maxcpu); -#if WITH_XEN || WITH_QEMU -int virParseCpuSet (virConnectPtr conn, - const char **str, - char sep, - char *cpuset, - int maxcpu); -char * virSaveCpuSet (virConnectPtr conn, - char *cpuset, - int maxcpu); -#endif -#if WITH_XEN -char * virConvertCpuSet(virConnectPtr conn, - const char *str, - int maxcpu); -int virDomainParseXMLOSDescHVMChar(virConnectPtr conn, - char *buf, - size_t buflen, - xmlNodePtr node); -char * virDomainParseXMLDesc(virConnectPtr conn, - const char *xmldesc, - char **name, - int xendConfigVersion); -char * virParseXMLDevice(virConnectPtr conn, - const char *xmldesc, - int hvm, - int xendConfigVersion); -int virDomainXMLDevID(virDomainPtr domain, - const char *xmldesc, - char *class, - char *ref, - int ref_len); char * virBuildSoundStringFromXML(virConnectPtr conn, xmlXPathContextPtr ctxt); -#endif -#ifdef __cplusplus -} -#endif /* __cplusplus */ +int +virDomainParseXMLOSDescHVMChar(virConnectPtr conn, + char *buf, + size_t buflen, + xmlNodePtr node); + #endif /* __VIR_XML_H__ */ diff -r ae83be3e7918 tests/Makefile.am --- a/tests/Makefile.am Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/Makefile.am Thu Jul 03 13:02:42 2008 +0100 @@ -90,7 +90,7 @@ xmlrpctest_LDADD = $(LDADDS) xml2sexprtest_SOURCES = \ - xml2sexprtest.c \ + xml2sexprtest.c testutilsxen.c testutilsxen.h \ testutils.c testutils.h xml2sexprtest_LDADD = $(LDADDS) diff -r ae83be3e7918 tests/testutilsxen.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/testutilsxen.c Thu Jul 03 13:02:42 2008 +0100 @@ -0,0 +1,53 @@ +#include <config.h> + +#include <sys/utsname.h> +#include <stdlib.h> + +#include "testutilsxen.h" + +virCapsPtr testXenCapsInit(void) { + struct utsname utsname; + virCapsPtr caps; + virCapsGuestPtr guest; + static const char *const x86_machines[] = { + "xenfv" + }; + static const char *const xen_machines[] = { + "xenpv" + }; + + uname (&utsname); + if ((caps = virCapabilitiesNew(utsname.machine, + 0, 0)) == NULL) + return NULL; + + if ((guest = virCapabilitiesAddGuest(caps, "hvm", "i686", 32, + "/usr/lib/xen/bin/qemu-dm", NULL, + 1, x86_machines)) == NULL) + goto cleanup; + if (virCapabilitiesAddGuestDomain(guest, + "xen", + NULL, + NULL, + 0, + NULL) == NULL) + goto cleanup; + + if ((guest = virCapabilitiesAddGuest(caps, "xen", "i686", 32, + "/usr/lib/xen/bin/qemu-dm", NULL, + 1, xen_machines)) == NULL) + goto cleanup; + if (virCapabilitiesAddGuestDomain(guest, + "xen", + NULL, + NULL, + 0, + NULL) == NULL) + goto cleanup; + + return caps; + +cleanup: + virCapabilitiesFree(caps); + return NULL; +} diff -r ae83be3e7918 tests/testutilsxen.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/testutilsxen.h Thu Jul 03 13:02:42 2008 +0100 @@ -0,0 +1,5 @@ + +#include "capabilities.h" + +virCapsPtr testXenCapsInit(void); + diff -r ae83be3e7918 tests/xencapstest.c --- a/tests/xencapstest.c Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xencapstest.c Thu Jul 03 13:02:42 2008 +0100 @@ -25,6 +25,7 @@ char *expectxml = &(xmlData[0]); char *actualxml = NULL; FILE *fp1 = NULL, *fp2 = NULL; + virCapsPtr caps = NULL; int ret = -1; @@ -40,16 +41,19 @@ abs_srcdir, capabilities_rel); if (virtTestLoadFile(xml, &expectxml, MAX_FILE) < 0) - goto fail; + goto fail; if (!(fp1 = fopen(cpuinfo, "r"))) - goto fail; + goto fail; if (!(fp2 = fopen(capabilities, "r"))) - goto fail; + goto fail; - if (!(actualxml = xenHypervisorMakeCapabilitiesXML(NULL, hostmachine, fp1, fp2))) - goto fail; + if (!(caps = xenHypervisorMakeCapabilitiesInternal(hostmachine, fp1, fp2))) + goto fail; + + if (!(actualxml = virCapabilitiesFormatXML(caps))) + goto fail; if (STRNEQ(expectxml, actualxml)) { virtTestDifference(stderr, expectxml, actualxml); @@ -66,6 +70,7 @@ if (fp2) fclose(fp2); + virCapabilitiesFree(caps); return ret; } diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-curmem.sexpr --- a/tests/xml2sexprdata/xml2sexpr-curmem.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-curmem.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'rhel5')(memory 175)(maxmem 385)(vcpus 1)(uuid '4f77abd2301958e83bab6fbf2118f880')(bootloader '/usr/bin/pygrub')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(device (tap (dev 'xvda:disk')(uname 'tap:aio:/xen/rhel5.img')(mode 'w')))(device (vif (mac '00:16:3e:1d:06:15')(bridge 'xenbr0')(script 'vif-bridge')))) \ No newline at end of file +(vm (name 'rhel5')(memory 175)(maxmem 385)(vcpus 1)(uuid '4f77abd2-3019-58e8-3bab-6fbf2118f880')(bootloader '/usr/bin/pygrub')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(device (tap (dev 'xvda:disk')(uname 'tap:aio:/xen/rhel5.img')(mode 'w')))(device (vif (mac '00:16:3e:1d:06:15')(bridge 'xenbr0')(script 'vif-bridge')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-disk-block-shareable.sexpr --- a/tests/xml2sexprdata/xml2sexpr-disk-block-shareable.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-disk-block-shareable.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 384)(maxmem 512)(vcpus 1)(uuid '49a0c6ffc066539264983632d093c2e7')(bootloader '/usr/bin/pygrub')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(device (tap (dev 'xvda')(uname 'tap:aio:/var/lib/xen/images/rhel5pv.img')(mode 'w!')))(device (vif (mac '00:16:3e:23:9e:eb')(bridge 'xenbr0')(script 'vif-bridge')))) \ No newline at end of file +(vm (name 'pvtest')(memory 384)(maxmem 512)(vcpus 1)(uuid '49a0c6ff-c066-5392-6498-3632d093c2e7')(bootloader '/usr/bin/pygrub')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(device (tap (dev 'xvda')(uname 'tap:aio:/var/lib/xen/images/rhel5pv.img')(mode 'w!')))(device (vif (mac '00:16:3e:23:9e:eb')(bridge 'xenbr0')(script 'vif-bridge')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-disk-block.sexpr --- a/tests/xml2sexprdata/xml2sexpr-disk-block.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-disk-block.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'phy:/dev/MainVG/GuestLV')(mode 'w')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'phy:/dev/MainVG/GuestLV')(mode 'w')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-disk-drv-blkback.sexpr --- a/tests/xml2sexprdata/xml2sexpr-disk-drv-blkback.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-disk-drv-blkback.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'phy:/dev/MainVG/GuestLV')(mode 'w')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'phy:/dev/MainVG/GuestLV')(mode 'w')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-disk-drv-blktap-qcow.sexpr --- a/tests/xml2sexprdata/xml2sexpr-disk-drv-blktap-qcow.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-disk-drv-blktap-qcow.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (tap (dev 'xvda')(uname 'tap:qcow:/root/some.img')(mode 'w')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (tap (dev 'xvda')(uname 'tap:qcow:/root/some.img')(mode 'w')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-disk-drv-blktap-raw.sexpr --- a/tests/xml2sexprdata/xml2sexpr-disk-drv-blktap-raw.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-disk-drv-blktap-raw.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (tap (dev 'xvda')(uname 'tap:aio:/root/some.img')(mode 'w')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (tap (dev 'xvda')(uname 'tap:aio:/root/some.img')(mode 'w')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-disk-drv-blktap.sexpr --- a/tests/xml2sexprdata/xml2sexpr-disk-drv-blktap.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-disk-drv-blktap.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (tap (dev 'xvda')(uname 'tap:aio:/root/some.img')(mode 'w')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (tap (dev 'xvda')(uname 'tap:aio:/root/some.img')(mode 'w')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-disk-drv-loop.sexpr --- a/tests/xml2sexprdata/xml2sexpr-disk-drv-loop.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-disk-drv-loop.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-disk-file.sexpr --- a/tests/xml2sexprdata/xml2sexpr-disk-file.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-disk-file.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-kernel.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-kernel.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-kernel.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (hvm (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')(loader '/usr/lib/xen/boot/hvmloader')(vcpus 2)(boot c)(usb 1)(parallel none)(serial pty)))(device (vbd (dev 'ioemu:xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file +(vm (name 'fvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (hvm (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')(loader '/usr/lib/xen/boot/hvmloader')(vcpus 2)(boot c)(usb 1)(parallel none)(serial pty)(device_model '/usr/lib/xen/bin/qemu-dm')))(device (vbd (dev 'ioemu:xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-localtime.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-localtime.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-localtime.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(localtime 1)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(localtime 1)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-localtime.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-localtime.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-localtime.xml Thu Jul 03 13:02:42 2008 +0100 @@ -29,7 +29,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <graphics type='vnc' port='5917' keymap='ja'/> </devices> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-parallel-tcp.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-parallel-tcp.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-parallel-tcp.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel tcp:localhost:9999)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel tcp:localhost:9999)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-parallel-tcp.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-parallel-tcp.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-parallel-tcp.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <parallel type='tcp'> <source mode='connect' host='localhost' service='9999' wiremode='raw'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-file.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-file.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-file.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial file:/tmp/serial.log)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial file:/tmp/serial.log)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-file.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-file.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-file.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <serial type='file'> <source path='/tmp/serial.log'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-null.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-null.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-null.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial null)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial null)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-null.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-null.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-null.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <serial type='null'> <target port='0'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-pipe.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-pipe.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-pipe.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial pipe:/tmp/serial.pipe)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial pipe:/tmp/serial.pipe)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-pipe.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-pipe.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-pipe.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <serial type='pipe'> <source path='/tmp/serial.pipe'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-pty.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-pty.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-pty.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial pty)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial pty)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-pty.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-pty.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-pty.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <serial type='pty'> <target port='0'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-stdio.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-stdio.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-stdio.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial stdio)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial stdio)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-stdio.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-stdio.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-stdio.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <serial type='stdio'> <target port='0'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-tcp-telnet.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp-telnet.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp-telnet.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial telnet:localhost:9999,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial telnet:localhost:9999,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-tcp-telnet.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp-telnet.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp-telnet.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <serial type='tcp'> <source mode='bind' host='localhost' service='9999'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial tcp:localhost:9999,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial tcp:localhost:9999,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <serial type='tcp'> <source mode='bind' host='localhost' service='9999' wiremode='raw'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-udp.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-udp.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-udp.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial udp:localhost:9998@localhost:9999)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial udp:localhost:9998@localhost:9999)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-udp.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-udp.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-udp.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <serial type='udp'> <source mode='connect' host='localhost' service='9998'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-unix.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-unix.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-unix.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial unix:/tmp/serial.sock,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial unix:/tmp/serial.sock,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-serial-unix.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-serial-unix.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-unix.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <serial type='unix'> <source mode='bind' path='/tmp/serial.sock'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-sound.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-sound.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-sound.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(soundhw 'sb16,es1370')(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(soundhw 'sb16,es1370')(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-sound.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-sound.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-sound.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <graphics type='vnc' port='5917' keymap='ja'/> <sound model='sb16'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-usbmouse.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-usbmouse.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-usbmouse.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(usbdevice mouse)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(usbdevice mouse)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-usbmouse.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-usbmouse.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-usbmouse.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <input type='mouse' bus='usb'/> <graphics type='vnc' port='5917' keymap='ja'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-usbtablet.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-usbtablet.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-usbtablet.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(usbdevice tablet)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(usbdevice tablet)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-usbtablet.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-usbtablet.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-usbtablet.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <input type='tablet' bus='usb'/> <graphics type='vnc' port='5917' keymap='ja'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-utc.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-utc.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-utc.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-utc.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-utc.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-utc.xml Thu Jul 03 13:02:42 2008 +0100 @@ -29,7 +29,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <graphics type='vnc' port='5917' keymap='ja'/> </devices> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-v2.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-v2.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-v2.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)(vncdisplay 17)(keymap ja)))(device (vbd (dev 'hdc:cdrom')(uname 'file:/root/boot.iso')(mode 'r')))(device (vbd (dev 'hda:disk')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)(vncunused 0)(vncdisplay 17)(keymap 'ja')))(device (vbd (dev 'hdc:cdrom')(uname 'file:/root/boot.iso')(mode 'r')))(device (vbd (dev 'hda:disk')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-vncunused.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv-vncunused.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-vncunused.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)(vncunused 1)(keymap ja)))(device (vbd (dev 'hdc:cdrom')(uname 'file:/root/boot.iso')(mode 'r')))(device (vbd (dev 'hda:disk')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)(vncunused 1)(keymap 'ja')))(device (vbd (dev 'hdc:cdrom')(uname 'file:/root/boot.iso')(mode 'r')))(device (vbd (dev 'hda:disk')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-vncunused.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-vncunused.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-vncunused.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <graphics type='vnc' port='-1' keymap='ja'/> </devices> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv.sexpr --- a/tests/xml2sexprdata/xml2sexpr-fv.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file +(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv.xml --- a/tests/xml2sexprdata/xml2sexpr-fv.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv.xml Thu Jul 03 13:02:42 2008 +0100 @@ -28,7 +28,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <graphics type='vnc' port='5917' keymap='ja'/> </devices> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-net-bridged.sexpr --- a/tests/xml2sexprdata/xml2sexpr-net-bridged.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-net-bridged.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(bridge 'xenbr2')(script 'vif-bridge')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(bridge 'xenbr2')(script 'vif-bridge')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-net-e1000.sexpr --- a/tests/xml2sexprdata/xml2sexpr-net-e1000.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-net-e1000.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(bridge 'xenbr2')(script 'vif-bridge')(model 'e1000')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(bridge 'xenbr2')(script 'vif-bridge')(model 'e1000')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-net-routed.sexpr --- a/tests/xml2sexprdata/xml2sexpr-net-routed.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-net-routed.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(dev 'eth3')(script 'vif-routed')(ip '172.14.5.6')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(script 'vif-routed')(ip '172.14.5.6')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-no-source-cdrom.sexpr --- a/tests/xml2sexprdata/xml2sexpr-no-source-cdrom.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-no-source-cdrom.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'test')(memory 350)(maxmem 382)(vcpus 1)(uuid 'cc2315e7d26a307a438c6d188ec4c09c')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(acpi 1)(apic 1)(pae 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib/xen/bin/qemu-dm')(vnc 1)(vncdisplay 6)))(device (vbd (dev 'hda:disk:disk')(uname 'phy:/dev/sda8')(mode 'w')))(device (vbd (dev 'hdc:cdrom')(mode 'r')))(device (vif (mac '00:16:3e:0a:7b:39')(type ioemu)))) \ No newline at end of file +(vm (name 'test')(memory 350)(maxmem 382)(vcpus 1)(uuid 'cc2315e7-d26a-307a-438c-6d188ec4c09c')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(acpi 1)(apic 1)(pae 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib/xen/bin/qemu-dm')(vnc 1)(vncunused 0)(vncdisplay 6)))(device (vbd (dev 'hda:disk')(uname 'phy:/dev/sda8')(mode 'w')))(device (vbd (dev 'hdc:cdrom')(mode 'r')))(device (vif (mac '00:16:3e:0a:7b:39')(type ioemu)))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-no-source-cdrom.xml --- a/tests/xml2sexprdata/xml2sexpr-no-source-cdrom.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-no-source-cdrom.xml Thu Jul 03 13:02:42 2008 +0100 @@ -25,7 +25,7 @@ <disk type='block' device='disk'> <driver name='phy'/> <source dev='/dev/sda8'/> - <target dev='hda:disk'/> + <target dev='hda'/> </disk> <disk device='cdrom'> <target dev='hdc'/> diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-pv-bootloader.sexpr --- a/tests/xml2sexprdata/xml2sexpr-pv-bootloader.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-pv-bootloader.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(bootloader '/usr/bin/pypxeboot')(bootloader_args 'mac=AA:00:86:e2:35:72')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(bootloader '/usr/bin/pypxeboot')(bootloader_args 'mac=AA:00:86:e2:35:72')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-pv-vfb-new.sexpr --- a/tests/xml2sexprdata/xml2sexpr-pv-vfb-new.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-pv-vfb-new.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vkbd))(device (vfb (type vnc)(vncdisplay 6)(vnclisten 127.0.0.1)(vncpasswd 123456)(keymap ja)))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')(device_model '/usr/lib/xen/bin/qemu-dm')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vkbd))(device (vfb (type vnc)(vncunused 0)(vncdisplay 6)(vnclisten '127.0.0.1')(vncpasswd '123456')(keymap 'ja')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-pv-vfb-orig.sexpr --- a/tests/xml2sexprdata/xml2sexpr-pv-vfb-orig.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-pv-vfb-orig.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')(vnc 1)(vncdisplay 6)(vnclisten 127.0.0.1)(vncpasswd 123456)(keymap ja)))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')(vnc 1)(vncunused 0)(vncdisplay 6)(vnclisten '127.0.0.1')(vncpasswd '123456')(keymap 'ja')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-pv.sexpr --- a/tests/xml2sexprdata/xml2sexpr-pv.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-pv.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file diff -r ae83be3e7918 tests/xml2sexprtest.c --- a/tests/xml2sexprtest.c Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprtest.c Thu Jul 03 13:02:42 2008 +0100 @@ -11,48 +11,47 @@ #if WITH_XEN #include "internal.h" -#include "xml.h" +#include "xend_internal.h" #include "testutils.h" +#include "testutilsxen.h" static char *progname; static char *abs_srcdir; +static virCapsPtr caps; #define MAX_FILE 4096 static int testCompareFiles(const char *xml, const char *sexpr, - const char *name, int xendConfigVersion) { + int xendConfigVersion) { char xmlData[MAX_FILE]; char sexprData[MAX_FILE]; - char *gotname = NULL; char *gotsexpr = NULL; char *xmlPtr = &(xmlData[0]); char *sexprPtr = &(sexprData[0]); int ret = -1; + virDomainDefPtr def = NULL; if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) - goto fail; + goto fail; if (virtTestLoadFile(sexpr, &sexprPtr, MAX_FILE) < 0) - goto fail; + goto fail; - if (!(gotsexpr = virDomainParseXMLDesc(NULL, xmlData, &gotname, xendConfigVersion))) - goto fail; + if (!(def = virDomainDefParseString(NULL, caps, xmlData))) + goto fail; + + if (!(gotsexpr = xenDaemonFormatSxpr(NULL, def, xendConfigVersion))) + goto fail; if (STRNEQ(sexprData, gotsexpr)) { virtTestDifference(stderr, sexprData, gotsexpr); goto fail; } - if (STRNEQ(name, gotname)) { - printf("Got wrong name: expected %s, got %s\n", name, gotname); - goto fail; - } - ret = 0; fail: - - free(gotname); + virDomainDefFree(def); free(gotsexpr); return ret; @@ -73,7 +72,7 @@ abs_srcdir, info->input); snprintf(args, PATH_MAX, "%s/xml2sexprdata/xml2sexpr-%s.sexpr", abs_srcdir, info->output); - return testCompareFiles(xml, args, info->name, info->version); + return testCompareFiles(xml, args, info->version); } @@ -101,6 +100,9 @@ 1, testCompareHelper, &info) < 0) \ ret = -1; \ } while (0) + + if (!(caps = testXenCapsInit())) + return(EXIT_FAILURE); DO_TEST("pv", "pv", "pvtest", 1); DO_TEST("fv", "fv", "fvtest", 1); @@ -145,6 +147,8 @@ DO_TEST("fv-sound", "fv-sound", "fvtest", 1); + virCapabilitiesFree(caps); + return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Daniel P. Berrange schreef:
This replaces the code which converts from the XML into SEXPR with code which converts from the virDomainDefPtr object to a SEXPR. We then simply use virDomainDefParseString() to generate the initial virDomainDefPtr. This makes the SEXPR generating code much easier to follow.
Could you elaborate on why you are using the SEXPR instead of the XenAPI XML code? Stefan

On Tue, Jul 08, 2008 at 06:48:45PM +0200, Stefan de Konink wrote:
Daniel P. Berrange schreef:
This replaces the code which converts from the XML into SEXPR with code which converts from the virDomainDefPtr object to a SEXPR. We then simply use virDomainDefParseString() to generate the initial virDomainDefPtr. This makes the SEXPR generating code much easier to follow.
Could you elaborate on why you are using the SEXPR instead of the XenAPI XML code?
SEXPR works for all XenD. XenAPI only works for XenD >= 3.1.0 We're open to having an XenAPI impl too, but so far no one's provided an impl and its not really a high priority since existing impl works fine Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Daniel P. Berrange schreef:
On Tue, Jul 08, 2008 at 06:48:45PM +0200, Stefan de Konink wrote:
Daniel P. Berrange schreef:
This replaces the code which converts from the XML into SEXPR with code which converts from the virDomainDefPtr object to a SEXPR. We then simply use virDomainDefParseString() to generate the initial virDomainDefPtr. This makes the SEXPR generating code much easier to follow. Could you elaborate on why you are using the SEXPR instead of the XenAPI XML code?
SEXPR works for all XenD. XenAPI only works for XenD >= 3.1.0
Ok that makes sence :) At least from a less work, more fun perspective.
We're open to having an XenAPI impl too, but so far no one's provided an impl and its not really a high priority since existing impl works fine
Ok Ok :) Stefan

On Tue, Jul 08, 2008 at 05:39:27PM +0100, Daniel P. Berrange wrote:
This replaces the code which converts from the XML into SEXPR with code which converts from the virDomainDefPtr object to a SEXPR. We then simply use virDomainDefParseString() to generate the initial virDomainDefPtr. This makes the SEXPR generating code much easier to follow.
okay
As part of this cleaned the code all moved out of xml.c and into xend_internal.c so its in the same place as its inverse SEXPR -> XML code. I'm half-inclined to actually move all the SEXPR related code into a xen_conf.{c,h} file independant of the main driver routine. This would reflect the split we for QEMU, LXC & OpenVZ drivers.
might make sense, but not urgent
static virCapsPtr -xenHypervisorBuildCapabilities(virConnectPtr conn, - const char *hostmachine, +xenHypervisorBuildCapabilities(const char *hostmachine, int host_pae, char *hvm_type, struct guest_arch *guest_archs,
Sounds fishy obviously some error can occur and not propagating the connection how to you carry the error properly to the remote connection using the Xen node ? For example virCaps allocation may fail no ?
@@ -2188,7 +2187,7 @@
if (sys_interface_version >= 4) { - if (xenDaemonNodeGetTopology(conn, caps) != 0) { + if (xenDaemonNodeGetTopology(NULL, caps) != 0) {
Hum, why ?
-char * -xenHypervisorMakeCapabilitiesXML(virConnectPtr conn, - const char *hostmachine, - FILE *cpuinfo, FILE *capabilities) +virCapsPtr +xenHypervisorMakeCapabilitiesInternal(const char *hostmachine, + FILE *cpuinfo, FILE *capabilities)
I don't understand really
+/** + * xenHypervisorMakeCapabilities: + * + * Return the capabilities of this hypervisor. + */ +virCapsPtr +xenHypervisorMakeCapabilities(void) +{ + virCapsPtr caps; + FILE *cpuinfo, *capabilities; + struct utsname utsname; + + /* Really, this never fails - look at the man-page. */ + uname (&utsname); + + cpuinfo = fopen ("/proc/cpuinfo", "r"); + if (cpuinfo == NULL) { + if (errno != ENOENT) { + virXenPerror (NULL, "/proc/cpuinfo"); + return NULL; + } + } + + capabilities = fopen ("/sys/hypervisor/properties/capabilities", "r"); + if (capabilities == NULL) { + if (errno != ENOENT) { + fclose(cpuinfo); + virXenPerror (NULL, "/sys/hypervisor/properties/capabilities"); + return NULL; + } + } + + caps = xenHypervisorMakeCapabilitiesInternal(utsname.machine, cpuinfo, capabilities); + + if (cpuinfo) + fclose(cpuinfo); + if (capabilities) + fclose(capabilities); + + return caps; +}
I really think the connection should be passed down here. [...]
@@ -3987,6 +3995,7 @@ static int xenDaemonDetachDevice(virDomainPtr domain, const char *xml) { +#if 0 char class[8], ref[80];
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { @@ -3998,6 +4007,8 @@ return (-1); return(xend_op(domain->conn, domain->name, "op", "device_destroy", "type", class, "dev", ref, "force", "0", "rm_cfg", "1", NULL)); +#endif + return (domain == (void*)xml) ? -1 : -1; }
err, I really don't understand that is that a temporary state which will be fixed by a later patch ? [...]
+ switch (def->type) { + case VIR_DOMAIN_NET_TYPE_BRIDGE: + virBufferVSprintf(buf, "(bridge '%s')", def->data.bridge.brname); + virBufferAddLit(buf, "(script 'vif-bridge')");
hum, see the problem reported in the previous patch. i think we should carry the bridge script in the definition structure or loose some functionality in the transition.
+static int +xenDaemonFormatSxprSound(virConnectPtr conn, + virDomainSoundDefPtr sound, + virBufferPtr buf) +{ + const char *str; + virDomainSoundDefPtr prev = NULL; + if (!sound) + return 0; + + virBufferAddLit(buf, "(soundhw '"); + while (sound) { + if (!(str = virDomainSoundModelTypeToString(sound->model))) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected sound model %d"), sound->model); + return -1; + } + virBufferVSprintf(buf, "%s%s", prev ? "," : "", str); + prev = sound; + sound = sound->next; + }
based on this I suppose the problem exposed in the previous patch about soundhw values, the 2 first values are lost when building the list.
+#if 0 +/** + * virDomainXMLDevID: + * @domain: pointer to domain object + * @xmldesc: string with the XML description + * @class: Xen device class "vbd" or "vif" (OUT) + * @ref: Xen device reference (OUT) + * + * Set class according to XML root, and: + * - if disk, copy in ref the target name from description + * - if network, get MAC address from description, scan XenStore and + * copy in ref the corresponding vif number. + * + * Returns 0 in case of success, -1 in case of failure. + */
hum, missing functionality ? [...]
diff -r ae83be3e7918 tests/testutilsxen.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/testutilsxen.c Thu Jul 03 13:02:42 2008 +0100 @@ -0,0 +1,53 @@ +#include <config.h> + +#include <sys/utsname.h> +#include <stdlib.h> + +#include "testutilsxen.h" + +virCapsPtr testXenCapsInit(void) { + struct utsname utsname; + virCapsPtr caps; + virCapsGuestPtr guest; + static const char *const x86_machines[] = { + "xenfv" + }; + static const char *const xen_machines[] = { + "xenpv" + }; + + uname (&utsname); + if ((caps = virCapabilitiesNew(utsname.machine, + 0, 0)) == NULL) + return NULL;
I think it's better to pass a NULL here for the connection but still keep the normal connection error reporting capabilities in the library code.
+ if ((guest = virCapabilitiesAddGuest(caps, "hvm", "i686", 32, + "/usr/lib/xen/bin/qemu-dm", NULL, + 1, x86_machines)) == NULL) --- a/tests/xml2sexprdata/xml2sexpr-curmem.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-curmem.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'rhel5')(memory 175)(maxmem 385)(vcpus 1)(uuid '4f77abd2301958e83bab6fbf2118f880')(bootloader '/usr/bin/pygrub')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(device (tap (dev 'xvda:disk')(uname 'tap:aio:/xen/rhel5.img')(mode 'w')))(device (vif (mac '00:16:3e:1d:06:15')(bridge 'xenbr0')(script 'vif-bridge')))) \ No newline at end of file +(vm (name 'rhel5')(memory 175)(maxmem 385)(vcpus 1)(uuid '4f77abd2-3019-58e8-3bab-6fbf2118f880')(bootloader '/usr/bin/pygrub')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(device (tap (dev 'xvda:disk')(uname 'tap:aio:/xen/rhel5.img')(mode 'w')))(device (vif (mac '00:16:3e:1d:06:15')(bridge 'xenbr0')(script 'vif-bridge'))))
Hum, we changed the UUID output format ! Isn't there a danger here ? I'm not sure all versions of Xend will be smart ... [...]
diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-localtime.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-localtime.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-localtime.xml Thu Jul 03 13:02:42 2008 +0100 @@ -29,7 +29,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <graphics type='vnc' port='5917' keymap='ja'/> </devices>
hum, why changing the inputs ? we can't parse it ?
diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-no-source-cdrom.xml --- a/tests/xml2sexprdata/xml2sexpr-no-source-cdrom.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-no-source-cdrom.xml Thu Jul 03 13:02:42 2008 +0100 @@ -25,7 +25,7 @@ <disk type='block' device='disk'> <driver name='phy'/> <source dev='/dev/sda8'/> - <target dev='hda:disk'/> + <target dev='hda'/> </disk> <disk device='cdrom'> <target dev='hdc'/>
agreed the input looks a bit stange there :-)
+++ b/tests/xml2sexprdata/xml2sexpr-pv-vfb-new.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vkbd))(device (vfb (type vnc)(vncdisplay 6)(vnclisten 127.0.0.1)(vncpasswd 123456)(keymap ja)))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')(device_model '/usr/lib/xen/bin/qemu-dm')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vkbd))(device (vfb (type vnc)(vncunused 0)(vncdisplay 6)(vnclisten '127.0.0.1')(vncpasswd '123456')(keymap 'ja'))))
Hum we lost more informations here: (device_model '/usr/lib/xen/bin/qemu-dm')
diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-pv-vfb-orig.sexpr --- a/tests/xml2sexprdata/xml2sexpr-pv-vfb-orig.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-pv-vfb-orig.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')(vnc 1)(vncdisplay 6)(vnclisten 127.0.0.1)(vncpasswd 123456)(keymap ja)))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')(vnc 1)(vncunused 0)(vncdisplay 6)(vnclisten '127.0.0.1')(vncpasswd '123456')(keymap 'ja')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
We add (vncunused 0) I must admit i don't see what it could mean in that context the input is <graphics type='vnc' port='5906' listen="127.0.0.1" passwd="123456" keymap="ja"/> Basically same as the previous one, i guess it's globally okay, there is a few issues, one stylistic and the others on the outputs but which can be adressed as separate patches on top. Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

On Thu, Jul 24, 2008 at 09:32:41AM -0400, Daniel Veillard wrote:
On Tue, Jul 08, 2008 at 05:39:27PM +0100, Daniel P. Berrange wrote:
static virCapsPtr -xenHypervisorBuildCapabilities(virConnectPtr conn, - const char *hostmachine, +xenHypervisorBuildCapabilities(const char *hostmachine, int host_pae, char *hvm_type, struct guest_arch *guest_archs,
Sounds fishy obviously some error can occur and not propagating the connection how to you carry the error properly to the remote connection using the Xen node ? For example virCaps allocation may fail no ?
Previously the code for building the virCaps object would be called every time the virConnectGetCapabilities() API was invokved, so it'd have a virConnectPtr object. After this re-factoring the virCaps object is created at the time the connection is opened, so no virConnectPtr object yet exists. The reason for this is that the virCaps object is used in the XML parsers/formatters now so we need it around all the time. The errors are still reported - they'll be reported as a failure to cthe virConnectOpen() call, accessible via the global virGetLastError() API.
@@ -3987,6 +3995,7 @@ static int xenDaemonDetachDevice(virDomainPtr domain, const char *xml) { +#if 0 char class[8], ref[80];
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { @@ -3998,6 +4007,8 @@ return (-1); return(xend_op(domain->conn, domain->name, "op", "device_destroy", "type", class, "dev", ref, "force", "0", "rm_cfg", "1", NULL)); +#endif + return (domain == (void*)xml) ? -1 : -1; }
err, I really don't understand that is that a temporary state which will be fixed by a later patch ?
Urgh, I've posted the wrong version of this patch. The one on my machine implements this correctly.
[...]
+ switch (def->type) { + case VIR_DOMAIN_NET_TYPE_BRIDGE: + virBufferVSprintf(buf, "(bridge '%s')", def->data.bridge.brname); + virBufferAddLit(buf, "(script 'vif-bridge')");
hum, see the problem reported in the previous patch. i think we should carry the bridge script in the definition structure or loose some functionality in the transition.
The issue is that when converting from a SEXPR -> XML format, the Xend driver does if (STREQ(script, "vif-bridge")) type = BRIDGE else type = ETHERNET So, if you pass a custom script for vif-bridge, that check won't match and thus the XML you get back out is <interface type='ethernet'> So, it seems pointless adding <script> element for <interface type='bridge'> since it'll never change.
+static int +xenDaemonFormatSxprSound(virConnectPtr conn, + virDomainSoundDefPtr sound, + virBufferPtr buf) +{ + const char *str; + virDomainSoundDefPtr prev = NULL; + if (!sound) + return 0; + + virBufferAddLit(buf, "(soundhw '"); + while (sound) { + if (!(str = virDomainSoundModelTypeToString(sound->model))) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected sound model %d"), sound->model); + return -1; + } + virBufferVSprintf(buf, "%s%s", prev ? "," : "", str); + prev = sound; + sound = sound->next; + }
based on this I suppose the problem exposed in the previous patch about soundhw values, the 2 first values are lost when building the list.
+#if 0 +/** + * virDomainXMLDevID: + * @domain: pointer to domain object + * @xmldesc: string with the XML description + * @class: Xen device class "vbd" or "vif" (OUT) + * @ref: Xen device reference (OUT) + * + * Set class according to XML root, and: + * - if disk, copy in ref the target name from description + * - if network, get MAC address from description, scan XenStore and + * copy in ref the corresponding vif number. + * + * Returns 0 in case of success, -1 in case of failure. + */
hum, missing functionality ?
Yep, also fixed on my laptop.
+virCapsPtr testXenCapsInit(void) { + struct utsname utsname; + virCapsPtr caps; + virCapsGuestPtr guest; + static const char *const x86_machines[] = { + "xenfv" + }; + static const char *const xen_machines[] = { + "xenpv" + }; + + uname (&utsname); + if ((caps = virCapabilitiesNew(utsname.machine, + 0, 0)) == NULL) + return NULL;
I think it's better to pass a NULL here for the connection but still keep the normal connection error reporting capabilities in the library code.
This is called from virConnectOpen, which is why i removed the conn parameter, but could add it back.
+ if ((guest = virCapabilitiesAddGuest(caps, "hvm", "i686", 32, + "/usr/lib/xen/bin/qemu-dm", NULL, + 1, x86_machines)) == NULL) --- a/tests/xml2sexprdata/xml2sexpr-curmem.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-curmem.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'rhel5')(memory 175)(maxmem 385)(vcpus 1)(uuid '4f77abd2301958e83bab6fbf2118f880')(bootloader '/usr/bin/pygrub')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(device (tap (dev 'xvda:disk')(uname 'tap:aio:/xen/rhel5.img')(mode 'w')))(device (vif (mac '00:16:3e:1d:06:15')(bridge 'xenbr0')(script 'vif-bridge')))) \ No newline at end of file +(vm (name 'rhel5')(memory 175)(maxmem 385)(vcpus 1)(uuid '4f77abd2-3019-58e8-3bab-6fbf2118f880')(bootloader '/usr/bin/pygrub')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(device (tap (dev 'xvda:disk')(uname 'tap:aio:/xen/rhel5.img')(mode 'w')))(device (vif (mac '00:16:3e:1d:06:15')(bridge 'xenbr0')(script 'vif-bridge'))))
Hum, we changed the UUID output format ! Isn't there a danger here ? I'm not sure all versions of Xend will be smart ...
The xm_internal.c driver already used the format including '-', but I could change this back if desired.
[...]
diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-fv-localtime.xml --- a/tests/xml2sexprdata/xml2sexpr-fv-localtime.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-fv-localtime.xml Thu Jul 03 13:02:42 2008 +0100 @@ -29,7 +29,7 @@ </disk> <disk type='file'> <source file='/root/foo.img'/> - <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <graphics type='vnc' port='5917' keymap='ja'/> </devices>
hum, why changing the inputs ? we can't parse it ?
Actaully we can parse & ignore this prefix. I can get rid of this tweak to the XML - its left-over from an intermediate version of my patch.
diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-no-source-cdrom.xml --- a/tests/xml2sexprdata/xml2sexpr-no-source-cdrom.xml Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-no-source-cdrom.xml Thu Jul 03 13:02:42 2008 +0100 @@ -25,7 +25,7 @@ <disk type='block' device='disk'> <driver name='phy'/> <source dev='/dev/sda8'/> - <target dev='hda:disk'/> + <target dev='hda'/> </disk> <disk device='cdrom'> <target dev='hdc'/>
agreed the input looks a bit stange there :-)
Yeah, the corresponding SXPR was wrong too - simple test case bug.
+++ b/tests/xml2sexprdata/xml2sexpr-pv-vfb-new.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vkbd))(device (vfb (type vnc)(vncdisplay 6)(vnclisten 127.0.0.1)(vncpasswd 123456)(keymap ja)))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')(device_model '/usr/lib/xen/bin/qemu-dm')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vkbd))(device (vfb (type vnc)(vncunused 0)(vncdisplay 6)(vnclisten '127.0.0.1')(vncpasswd '123456')(keymap 'ja'))))
Hum we lost more informations here: (device_model '/usr/lib/xen/bin/qemu-dm')
We *added* the 'device_model' actually :-)
diff -r ae83be3e7918 tests/xml2sexprdata/xml2sexpr-pv-vfb-orig.sexpr --- a/tests/xml2sexprdata/xml2sexpr-pv-vfb-orig.sexpr Thu Jul 03 12:50:05 2008 +0100 +++ b/tests/xml2sexprdata/xml2sexpr-pv-vfb-orig.sexpr Thu Jul 03 13:02:42 2008 +0100 @@ -1,1 +1,1 @@ -(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')(vnc 1)(vncdisplay 6)(vnclisten 127.0.0.1)(vncpasswd 123456)(keymap ja)))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... ')(vnc 1)(vncunused 0)(vncdisplay 6)(vnclisten '127.0.0.1')(vncpasswd '123456')(keymap 'ja')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
We add (vncunused 0) I must admit i don't see what it could mean in that context the input is <graphics type='vnc' port='5906' listen="127.0.0.1" passwd="123456" keymap="ja"/>
It is a safety net - we have an explicit port, given via (vncdisplay 6), but adding the (vncunused 0) is just a safety net incase XenD changes its default handling - one version of xen-unstable did this before, but we caught it before release. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Jul 24, 2008 at 04:49:50PM +0100, Daniel P. Berrange wrote:
On Thu, Jul 24, 2008 at 09:32:41AM -0400, Daniel Veillard wrote:
On Tue, Jul 08, 2008 at 05:39:27PM +0100, Daniel P. Berrange wrote:
static virCapsPtr -xenHypervisorBuildCapabilities(virConnectPtr conn, - const char *hostmachine, +xenHypervisorBuildCapabilities(const char *hostmachine, int host_pae, char *hvm_type, struct guest_arch *guest_archs,
Sounds fishy obviously some error can occur and not propagating the connection how to you carry the error properly to the remote connection using the Xen node ? For example virCaps allocation may fail no ?
Previously the code for building the virCaps object would be called every time the virConnectGetCapabilities() API was invokved, so it'd have a virConnectPtr object.
After this re-factoring the virCaps object is created at the time the connection is opened, so no virConnectPtr object yet exists. The reason for this is that the virCaps object is used in the XML parsers/formatters now so we need it around all the time.
The errors are still reported - they'll be reported as a failure to cthe virConnectOpen() call, accessible via the global virGetLastError() API.
Ah, okay, I remember now this been discussed, but i had forgotten !
Urgh, I've posted the wrong version of this patch. The one on my machine implements this correctly.
haha, :-)
[...]
+ switch (def->type) { + case VIR_DOMAIN_NET_TYPE_BRIDGE: + virBufferVSprintf(buf, "(bridge '%s')", def->data.bridge.brname); + virBufferAddLit(buf, "(script 'vif-bridge')");
hum, see the problem reported in the previous patch. i think we should carry the bridge script in the definition structure or loose some functionality in the transition.
The issue is that when converting from a SEXPR -> XML format, the Xend driver does
if (STREQ(script, "vif-bridge")) type = BRIDGE else type = ETHERNET
So, if you pass a custom script for vif-bridge, that check won't match and thus the XML you get back out is
<interface type='ethernet'>
So, it seems pointless adding <script> element for <interface type='bridge'> since it'll never change.
okay, that removes my concern, there is no loss of functionlity possible.
Yep, also fixed on my laptop.
Let's push the final version to CVS, really !
Hum, we changed the UUID output format ! Isn't there a danger here ? I'm not sure all versions of Xend will be smart ...
The xm_internal.c driver already used the format including '-', but I could change this back if desired.
nahh as long as it doesn't break, I don't care
- <target dev='ioemu:hda'/> + <target dev='hda'/> </disk> <graphics type='vnc' port='5917' keymap='ja'/> </devices>
hum, why changing the inputs ? we can't parse it ?
Actaully we can parse & ignore this prefix. I can get rid of this tweak to the XML - its left-over from an intermediate version of my patch.
okay
We add (vncunused 0) I must admit i don't see what it could mean in that context the input is <graphics type='vnc' port='5906' listen="127.0.0.1" passwd="123456" keymap="ja"/>
It is a safety net - we have an explicit port, given via (vncdisplay 6), but adding the (vncunused 0) is just a safety net incase XenD changes its default handling - one version of xen-unstable did this before, but we caught it before release.
Okay +1 Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

This is a refactoring of the XM driver. Previously we would store the virConfPtr objects as our master 'in memory' representation of inactive domains. This switch it over to using virDomainDefPtr objects instead. The code for reading/writing the config files is unchanged at this time. Again the XML config file has changed because of re-ordering of elements by the generic XML formatter src/xm_internal.c | 1038 ++++------------- src/xm_internal.h | 13 tests/Makefile.am | 2 tests/xmconfigdata/test-escape-paths.cfg | 2 tests/xmconfigdata/test-escape-paths.xml | 24 tests/xmconfigdata/test-fullvirt-localtime.cfg | 2 tests/xmconfigdata/test-fullvirt-localtime.xml | 24 tests/xmconfigdata/test-fullvirt-new-cdrom.cfg | 2 tests/xmconfigdata/test-fullvirt-new-cdrom.xml | 24 tests/xmconfigdata/test-fullvirt-old-cdrom.cfg | 2 tests/xmconfigdata/test-fullvirt-old-cdrom.xml | 24 tests/xmconfigdata/test-fullvirt-parallel-tcp.cfg | 2 tests/xmconfigdata/test-fullvirt-parallel-tcp.xml | 26 tests/xmconfigdata/test-fullvirt-serial-file.cfg | 2 tests/xmconfigdata/test-fullvirt-serial-file.xml | 26 tests/xmconfigdata/test-fullvirt-serial-null.cfg | 2 tests/xmconfigdata/test-fullvirt-serial-null.xml | 26 tests/xmconfigdata/test-fullvirt-serial-pipe.cfg | 2 tests/xmconfigdata/test-fullvirt-serial-pipe.xml | 26 tests/xmconfigdata/test-fullvirt-serial-pty.cfg | 2 tests/xmconfigdata/test-fullvirt-serial-pty.xml | 26 tests/xmconfigdata/test-fullvirt-serial-stdio.cfg | 2 tests/xmconfigdata/test-fullvirt-serial-stdio.xml | 26 tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.cfg | 2 tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml | 26 tests/xmconfigdata/test-fullvirt-serial-tcp.cfg | 2 tests/xmconfigdata/test-fullvirt-serial-tcp.xml | 26 tests/xmconfigdata/test-fullvirt-serial-udp.cfg | 2 tests/xmconfigdata/test-fullvirt-serial-udp.xml | 30 tests/xmconfigdata/test-fullvirt-serial-unix.cfg | 2 tests/xmconfigdata/test-fullvirt-serial-unix.xml | 26 tests/xmconfigdata/test-fullvirt-sound.cfg | 2 tests/xmconfigdata/test-fullvirt-sound.xml | 24 tests/xmconfigdata/test-fullvirt-usbmouse.cfg | 2 tests/xmconfigdata/test-fullvirt-usbmouse.xml | 24 tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml | 2 tests/xmconfigdata/test-fullvirt-usbtablet.cfg | 2 tests/xmconfigdata/test-fullvirt-usbtablet.xml | 24 tests/xmconfigdata/test-fullvirt-utc.cfg | 2 tests/xmconfigdata/test-fullvirt-utc.xml | 24 tests/xmconfigdata/test-paravirt-net-e1000.cfg | 2 tests/xmconfigdata/test-paravirt-net-e1000.xml | 19 tests/xmconfigdata/test-paravirt-new-pvfb.cfg | 2 tests/xmconfigdata/test-paravirt-new-pvfb.xml | 19 tests/xmconfigdata/test-paravirt-old-pvfb.cfg | 2 tests/xmconfigdata/test-paravirt-old-pvfb.xml | 19 tests/xmconfigtest.c | 29 47 files changed, 581 insertions(+), 1058 deletions(-) Daniel diff -r a6688e03b4fc src/xm_internal.c --- a/src/xm_internal.c Mon Jul 07 07:11:30 2008 -0400 +++ b/src/xm_internal.c Mon Jul 07 10:12:49 2008 -0400 @@ -47,7 +47,6 @@ #include "xen_unified.h" #include "xm_internal.h" #include "xend_internal.h" -#include "conf.h" #include "hash.h" #include "internal.h" #include "xml.h" @@ -63,7 +62,7 @@ typedef struct xenXMConfCache { typedef struct xenXMConfCache { time_t refreshedAt; char filename[PATH_MAX]; - virConfPtr conf; + virDomainDefPtr def; } xenXMConfCache; static char configDir[PATH_MAX]; @@ -75,10 +74,6 @@ static time_t lastRefresh = 0; static time_t lastRefresh = 0; char * xenXMAutoAssignMac(void); -static int xenXMAttachDisk(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm, - xmlNodePtr node, xenXMConfCachePtr entry); -static int xenXMAttachInterface(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm, - xmlNodePtr node, xenXMConfCachePtr entry); static int xenXMDomainAttachDevice(virDomainPtr domain, const char *xml); static int xenXMDomainDetachDevice(virDomainPtr domain, const char *xml); @@ -233,59 +228,10 @@ static int xenXMConfigGetUUID(virConfPtr } -/* Ensure that a config object has a valid UUID in it, - if it doesn't then (re-)generate one */ -static int xenXMConfigEnsureIdentity(virConfPtr conf, const char *filename) { - unsigned char uuid[VIR_UUID_BUFLEN]; - const char *name; - - /* Had better have a name...*/ - if (xenXMConfigGetString(conf, "name", &name) < 0) { - virConfValuePtr value; - if (VIR_ALLOC(value) < 0) - return (-1); - - /* Set name based on filename */ - value->type = VIR_CONF_STRING; - value->str = strdup(filename); - if (!value->str) { - VIR_FREE(value); - return (-1); - } - if (virConfSetValue(conf, "name", value) < 0) - return (-1); - } - - /* If there is no uuid...*/ - if (xenXMConfigGetUUID(conf, "uuid", uuid) < 0) { - virConfValuePtr value; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - - if (VIR_ALLOC(value) < 0) - return (-1); - - /* ... then generate one */ - virUUIDGenerate(uuid); - virUUIDFormat(uuid, uuidstr); - - value->type = VIR_CONF_STRING; - value->str = strdup(uuidstr); - if (!value->str) { - VIR_FREE(value); - return (-1); - } - - /* And stuff the UUID back into the config file */ - if (virConfSetValue(conf, "uuid", value) < 0) - return (-1); - } - return (0); -} - /* Release memory associated with a cached config object */ static void xenXMConfigFree(void *payload, const char *key ATTRIBUTE_UNUSED) { xenXMConfCachePtr entry = (xenXMConfCachePtr)payload; - virConfFree(entry->conf); + virDomainDefFree(entry->def); VIR_FREE(entry); } @@ -295,20 +241,47 @@ static int xenXMConfigReaper(const void time_t now = *(const time_t *)data; xenXMConfCachePtr entry = (xenXMConfCachePtr)payload; + /* We're going to purge this config file, so check if it + is currently mapped as owner of a named domain. */ if (entry->refreshedAt != now) { - const char *olddomname; - /* We're going to pure this config file, so check if it - is currently mapped as owner of a named domain. */ - if (xenXMConfigGetString(entry->conf, "name", &olddomname) != -1) { - char *nameowner = (char *)virHashLookup(nameConfigMap, olddomname); - if (nameowner && STREQ(nameowner, key)) { - virHashRemoveEntry(nameConfigMap, olddomname, NULL); - } + const char *olddomname = entry->def->name; + char *nameowner = (char *)virHashLookup(nameConfigMap, olddomname); + if (nameowner && STREQ(nameowner, key)) { + virHashRemoveEntry(nameConfigMap, olddomname, NULL); } return (1); } return (0); } + + +static virDomainDefPtr +xenXMConfigReadFile(virConnectPtr conn, const char *filename) { + virConfPtr conf; + virDomainDefPtr def; + + if (!(conf = virConfReadFile(filename))) + return NULL; + + def = xenXMDomainConfigParse(conn, conf); + virConfFree(conf); + + return def; +} + +static int +xenXMConfigSaveFile(virConnectPtr conn, const char *filename, virDomainDefPtr def) { + virConfPtr conf; + int ret; + + if (!(conf = xenXMDomainConfigFormat(conn, def))) + return -1; + + ret = virConfWriteFile(filename, conf); + virConfFree(conf); + return ret; +} + /* This method is called by various methods to scan /etc/xen (or whatever directory was set by LIBVIRT_XM_CONFIG_DIR @@ -343,7 +316,6 @@ static int xenXMConfigCacheRefresh (virC struct stat st; int newborn = 0; char path[PATH_MAX]; - const char *domname = NULL; /* * Skip a bunch of crufty files that clearly aren't config files @@ -387,7 +359,7 @@ static int xenXMConfigCacheRefresh (virC /* If we already have a matching entry and it is not modified, then carry on to next one*/ if ((entry = virHashLookup(configCache, path))) { - const char *olddomname = NULL; + char *nameowner; if (entry->refreshedAt >= st.st_mtime) { entry->refreshedAt = now; @@ -396,16 +368,14 @@ static int xenXMConfigCacheRefresh (virC /* If we currently own the name, then release it and re-acquire it later - just in case it was renamed */ - if (xenXMConfigGetString(entry->conf, "name", &olddomname) != -1) { - char *nameowner = (char *)virHashLookup(nameConfigMap, olddomname); - if (nameowner && STREQ(nameowner, path)) { - virHashRemoveEntry(nameConfigMap, olddomname, NULL); - } + nameowner = (char *)virHashLookup(nameConfigMap, entry->def->name); + if (nameowner && STREQ(nameowner, path)) { + virHashRemoveEntry(nameConfigMap, entry->def->name, NULL); } /* Clear existing config entry which needs refresh */ - virConfFree(entry->conf); - entry->conf = NULL; + virDomainDefFree(entry->def); + entry->def = NULL; } else { /* Completely new entry */ newborn = 1; if (VIR_ALLOC(entry) < 0) { @@ -416,31 +386,18 @@ static int xenXMConfigCacheRefresh (virC } entry->refreshedAt = now; - if (!(entry->conf = virConfReadFile(entry->filename)) || - xenXMConfigEnsureIdentity(entry->conf, ent->d_name) < 0) { - if (!newborn) { + if (!(entry->def = xenXMConfigReadFile(conn, entry->filename))) { + if (!newborn) virHashRemoveEntry(configCache, path, NULL); - } VIR_FREE(entry); continue; - } - - /* Lookup what domain name the conf contains */ - if (xenXMConfigGetString(entry->conf, "name", &domname) < 0) { - if (!newborn) { - virHashRemoveEntry(configCache, path, NULL); - } - VIR_FREE(entry); - xenXMError (conn, VIR_ERR_INTERNAL_ERROR, - _("xenXMConfigCacheRefresh: name")); - goto cleanup; } /* If its a completely new entry, it must be stuck into the cache (refresh'd entries are already registered) */ if (newborn) { if (virHashAddEntry(configCache, entry->filename, entry) < 0) { - virConfFree(entry->conf); + virDomainDefFree(entry->def); VIR_FREE(entry); xenXMError (conn, VIR_ERR_INTERNAL_ERROR, _("xenXMConfigCacheRefresh: virHashAddEntry")); @@ -451,10 +408,10 @@ static int xenXMConfigCacheRefresh (virC /* See if we need to map this config file in as the primary owner * of the domain in question */ - if (!virHashLookup(nameConfigMap, domname)) { - if (virHashAddEntry(nameConfigMap, domname, entry->filename) < 0) { + if (!virHashLookup(nameConfigMap, entry->def->name)) { + if (virHashAddEntry(nameConfigMap, entry->def->name, entry->filename) < 0) { virHashRemoveEntry(configCache, ent->d_name, NULL); - virConfFree(entry->conf); + virDomainDefFree(entry->def); VIR_FREE(entry); } } @@ -529,8 +486,6 @@ int xenXMDomainGetInfo(virDomainPtr doma int xenXMDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) { const char *filename; xenXMConfCachePtr entry; - long vcpus; - long mem; if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -547,22 +502,9 @@ int xenXMDomainGetInfo(virDomainPtr doma return (-1); memset(info, 0, sizeof(virDomainInfo)); - if (xenXMConfigGetInt(entry->conf, "memory", &mem) < 0 || - mem < 0) - info->memory = MIN_XEN_GUEST_SIZE * 1024 * 2; - else - info->memory = (unsigned long)mem * 1024; - if (xenXMConfigGetInt(entry->conf, "maxmem", &mem) < 0 || - mem < 0) - info->maxMem = info->memory; - else - info->maxMem = (unsigned long)mem * 1024; - - if (xenXMConfigGetInt(entry->conf, "vcpus", &vcpus) < 0 || - vcpus < 0) - info->nrVirtCpu = 1; - else - info->nrVirtCpu = (unsigned short)vcpus; + info->maxMem = entry->def->maxmem; + info->memory = entry->def->memory; + info->nrVirtCpu = entry->def->vcpus; info->state = VIR_DOMAIN_SHUTOFF; info->cpuTime = 0; @@ -575,7 +517,8 @@ int xenXMDomainGetInfo(virDomainPtr doma * Turn a config record into a lump of XML describing the * domain, suitable for later feeding for virDomainCreateLinux */ -char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf) { +virDomainDefPtr +xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { virBuffer buf = VIR_BUFFER_INITIALIZER; const char *name; unsigned char uuid[VIR_UUID_BUFLEN]; @@ -592,6 +535,8 @@ char *xenXMDomainFormatXML(virConnectPtr const char *vncpasswd = NULL; const char *keymap = NULL; xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData; + virDomainDefPtr def = NULL; + char *xml; if (xenXMConfigGetString(conf, "name", &name) < 0) return (NULL); @@ -1080,7 +1025,15 @@ char *xenXMDomainFormatXML(virConnectPtr goto error; } - return virBufferContentAndReset(&buf); + xml = virBufferContentAndReset(&buf); + + if (!(def = virDomainDefParseString(conn, priv->caps, xml))) { + VIR_FREE(xml); + return NULL; + } + + VIR_FREE(xml); + return def; error: str = virBufferContentAndReset(&buf); @@ -1093,7 +1046,7 @@ char *xenXMDomainFormatXML(virConnectPtr * Turn a config record into a lump of XML describing the * domain, suitable for later feeding for virDomainCreateLinux */ -char *xenXMDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED) { +char *xenXMDomainDumpXML(virDomainPtr domain, int flags) { const char *filename; xenXMConfCachePtr entry; @@ -1111,7 +1064,7 @@ char *xenXMDomainDumpXML(virDomainPtr do if (!(entry = virHashLookup(configCache, filename))) return (NULL); - return xenXMDomainFormatXML(domain->conn, entry->conf); + return virDomainDefFormat(domain->conn, entry->def, flags); } @@ -1121,7 +1074,6 @@ int xenXMDomainSetMemory(virDomainPtr do int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory) { const char *filename; xenXMConfCachePtr entry; - virConfValuePtr value; if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG, @@ -1139,19 +1091,14 @@ int xenXMDomainSetMemory(virDomainPtr do if (!(entry = virHashLookup(configCache, filename))) return (-1); - if (VIR_ALLOC(value) < 0) - return (-1); - - value->type = VIR_CONF_LONG; - value->l = (memory/1024); - - if (virConfSetValue(entry->conf, "memory", value) < 0) - return (-1); + entry->def->memory = memory; + if (entry->def->memory > entry->def->maxmem) + entry->def->memory = entry->def->maxmem; /* If this fails, should we try to undo our changes to the * in-memory representation of the config file. I say not! */ - if (virConfWriteFile(entry->filename, entry->conf) < 0) + if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0) return (-1); return (0); @@ -1163,7 +1110,6 @@ int xenXMDomainSetMaxMemory(virDomainPtr int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) { const char *filename; xenXMConfCachePtr entry; - virConfValuePtr value; if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG, @@ -1181,19 +1127,14 @@ int xenXMDomainSetMaxMemory(virDomainPtr if (!(entry = virHashLookup(configCache, filename))) return (-1); - if (VIR_ALLOC(value) < 0) - return (-1); - - value->type = VIR_CONF_LONG; - value->l = (memory/1024); - - if (virConfSetValue(entry->conf, "maxmem", value) < 0) - return (-1); + entry->def->maxmem = memory; + if (entry->def->memory > entry->def->maxmem) + entry->def->memory = entry->def->maxmem; /* If this fails, should we try to undo our changes to the * in-memory representation of the config file. I say not! */ - if (virConfWriteFile(entry->filename, entry->conf) < 0) + if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0) return (-1); return (0); @@ -1205,7 +1146,6 @@ unsigned long xenXMDomainGetMaxMemory(vi unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain) { const char *filename; xenXMConfCachePtr entry; - long val; if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG, @@ -1221,13 +1161,7 @@ unsigned long xenXMDomainGetMaxMemory(vi if (!(entry = virHashLookup(configCache, filename))) return (-1); - if (xenXMConfigGetInt(entry->conf, "maxmem", &val) < 0 || - val < 0) - if (xenXMConfigGetInt(entry->conf, "memory", &val) < 0 || - val < 0) - val = MIN_XEN_GUEST_SIZE * 2; - - return (val * 1024); + return entry->def->maxmem; } /* @@ -1236,7 +1170,6 @@ int xenXMDomainSetVcpus(virDomainPtr dom int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) { const char *filename; xenXMConfCachePtr entry; - virConfValuePtr value; if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG, @@ -1254,19 +1187,12 @@ int xenXMDomainSetVcpus(virDomainPtr dom if (!(entry = virHashLookup(configCache, filename))) return (-1); - if (VIR_ALLOC(value) < 0) - return (-1); - - value->type = VIR_CONF_LONG; - value->l = vcpus; - - if (virConfSetValue(entry->conf, "vcpus", value) < 0) - return (-1); + entry->def->vcpus = vcpus; /* If this fails, should we try to undo our changes to the * in-memory representation of the config file. I say not! */ - if (virConfWriteFile(entry->filename, entry->conf) < 0) + if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0) return (-1); return (0); @@ -1291,9 +1217,10 @@ int xenXMDomainPinVcpu(virDomainPtr doma xenXMConfCachePtr entry; virBuffer mapbuf = VIR_BUFFER_INITIALIZER; char *mapstr = NULL; - char *ranges = NULL; int i, j, n, comma = 0; int ret = -1; + char *cpuset = NULL; + int maxcpu = 4096; if (domain == NULL || domain->conn == NULL || domain->name == NULL || cpumap == NULL || maplen < 1 || maplen > (int)sizeof(cpumap_t)) { @@ -1342,24 +1269,28 @@ int xenXMDomainPinVcpu(virDomainPtr doma mapstr = virBufferContentAndReset(&mapbuf); - /* convert the mapstr to a range based string */ - ranges = virConvertCpuSet(domain->conn, mapstr, 0); - - if (ranges != NULL) { - if (xenXMConfigSetString(entry->conf, "cpus", ranges) < 0) - goto cleanup; - } else - if (xenXMConfigSetString(entry->conf, "cpus", mapstr) < 0) - goto cleanup; - - if (virConfWriteFile(entry->filename, entry->conf) < 0) + if (VIR_ALLOC_N(cpuset, maxcpu) < 0) { + xenXMError(domain->conn, VIR_ERR_NO_MEMORY, _("allocate buffer")); + goto cleanup; + } + if (virDomainCpuSetParse(domain->conn, + (const char **)&mapstr, 0, + cpuset, maxcpu) < 0) + goto cleanup; + + VIR_FREE(entry->def->cpumask); + entry->def->cpumask = cpuset; + entry->def->cpumasklen = maxcpu; + cpuset = NULL; + + if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(mapstr); - VIR_FREE(ranges); + VIR_FREE(cpuset); return (ret); } @@ -1370,7 +1301,7 @@ virDomainPtr xenXMDomainLookupByName(vir const char *filename; xenXMConfCachePtr entry; virDomainPtr ret; - unsigned char uuid[VIR_UUID_BUFLEN]; + if (!VIR_IS_CONNECT(conn)) { xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); @@ -1390,12 +1321,7 @@ virDomainPtr xenXMDomainLookupByName(vir return (NULL); } - - if (xenXMConfigGetUUID(entry->conf, "uuid", uuid) < 0) { - return (NULL); - } - - if (!(ret = virGetDomain(conn, domname, uuid))) { + if (!(ret = virGetDomain(conn, domname, entry->def->uuid))) { return (NULL); } @@ -1411,15 +1337,10 @@ virDomainPtr xenXMDomainLookupByName(vir * Hash table iterator to search for a domain based on UUID */ static int xenXMDomainSearchForUUID(const void *payload, const char *name ATTRIBUTE_UNUSED, const void *data) { - unsigned char uuid[VIR_UUID_BUFLEN]; const unsigned char *wantuuid = (const unsigned char *)data; const xenXMConfCachePtr entry = (const xenXMConfCachePtr)payload; - if (xenXMConfigGetUUID(entry->conf, "uuid", uuid) < 0) { - return (0); - } - - if (!memcmp(uuid, wantuuid, VIR_UUID_BUFLEN)) + if (!memcmp(entry->def->uuid, wantuuid, VIR_UUID_BUFLEN)) return (1); return (0); @@ -1432,7 +1353,6 @@ virDomainPtr xenXMDomainLookupByUUID(vir const unsigned char *uuid) { xenXMConfCachePtr entry; virDomainPtr ret; - const char *domname; if (!VIR_IS_CONNECT(conn)) { xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__); @@ -1450,11 +1370,7 @@ virDomainPtr xenXMDomainLookupByUUID(vir return (NULL); } - if (xenXMConfigGetString(entry->conf, "name", &domname) < 0) { - return (NULL); - } - - if (!(ret = virGetDomain(conn, domname, uuid))) { + if (!(ret = virGetDomain(conn, entry->def->name, uuid))) { return (NULL); } @@ -1470,35 +1386,28 @@ virDomainPtr xenXMDomainLookupByUUID(vir * Start a domain from an existing defined config file */ int xenXMDomainCreate(virDomainPtr domain) { - char *xml; char *sexpr; int ret; - unsigned char uuid[VIR_UUID_BUFLEN]; xenUnifiedPrivatePtr priv; - virDomainDefPtr def; + const char *filename; + xenXMConfCachePtr entry; + + priv = (xenUnifiedPrivatePtr) domain->conn->privateData; if (domain->id != -1) return (-1); - if (!(xml = xenXMDomainDumpXML(domain, 0))) - return (-1); - - priv = (xenUnifiedPrivatePtr) domain->conn->privateData; - - if (!(def = virDomainDefParseString(domain->conn, priv->caps, xml))) { - xenXMError(domain->conn, VIR_ERR_XML_ERROR, - _("failed to parse domain description")); - return (-1); - } - VIR_FREE(xml); - - if (!(sexpr = xenDaemonFormatSxpr(domain->conn, def, priv->xendConfigVersion))) { - virDomainDefFree(def); + if (!(filename = virHashLookup(nameConfigMap, domain->name))) + return (-1); + + if (!(entry = virHashLookup(configCache, filename))) + return (-1); + + if (!(sexpr = xenDaemonFormatSxpr(domain->conn, entry->def, priv->xendConfigVersion))) { xenXMError(domain->conn, VIR_ERR_XML_ERROR, _("failed to build sexpr")); return (-1); } - virDomainDefFree(def); ret = xenDaemonDomainCreateLinux(domain->conn, sexpr); VIR_FREE(sexpr); @@ -1506,7 +1415,8 @@ int xenXMDomainCreate(virDomainPtr domai return (-1); } - if ((ret = xenDaemonDomainLookupByName_ids(domain->conn, domain->name, uuid)) < 0) { + if ((ret = xenDaemonDomainLookupByName_ids(domain->conn, domain->name, + entry->def->uuid)) < 0) { return (-1); } domain->id = ret; @@ -1930,7 +1840,8 @@ static char *xenXMParseXMLVif(virConnect } -virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml) { +virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, + virDomainDefPtr def) { xmlDocPtr doc = NULL; xmlNodePtr node; xmlXPathObjectPtr obj = NULL; @@ -1940,10 +1851,17 @@ virConfPtr xenXMParseXMLToConfig(virConn int hvm = 0, i; xenUnifiedPrivatePtr priv; char *cpus; + char *xml; + + priv = (xenUnifiedPrivatePtr) conn->privateData; + + if (!(xml = virDomainDefFormat(conn, def, VIR_DOMAIN_XML_SECURE))) + return NULL; doc = xmlReadDoc((const xmlChar *) xml, "domain.xml", NULL, XML_PARSE_NOENT | XML_PARSE_NONET | XML_PARSE_NOERROR | XML_PARSE_NOWARNING); + VIR_FREE(xml); if (doc == NULL) { xenXMError(conn, VIR_ERR_XML_ERROR, _("cannot read XML domain definition")); @@ -2024,8 +1942,6 @@ virConfPtr xenXMParseXMLToConfig(virConn hvm = 1; xmlXPathFreeObject(obj); obj = NULL; - - priv = (xenUnifiedPrivatePtr) conn->privateData; if (hvm) { const char *boot = "c"; @@ -2390,10 +2306,9 @@ virDomainPtr xenXMDomainDefineXML(virCon virDomainPtr olddomain; char filename[PATH_MAX]; const char * oldfilename; - unsigned char uuid[VIR_UUID_BUFLEN]; - virConfPtr conf = NULL; + virDomainDefPtr def = NULL; xenXMConfCachePtr entry = NULL; - virConfValuePtr value; + xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData; if (!VIR_IS_CONNECT(conn)) { xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__); @@ -2409,21 +2324,13 @@ virDomainPtr xenXMDomainDefineXML(virCon if (xenXMConfigCacheRefresh (conn) < 0) return (NULL); - if (!(conf = xenXMParseXMLToConfig(conn, xml))) - goto error; - - if (!(value = virConfGetValue(conf, "name")) || - value->type != VIR_CONF_STRING || - value->str == NULL) { - xenXMError(conn, VIR_ERR_INTERNAL_ERROR, - _("name config parameter is missing")); - goto error; - } - - if (virHashLookup(nameConfigMap, value->str)) { + if (!(def = virDomainDefParseString(conn, priv->caps, xml))) + return (NULL); + + if (virHashLookup(nameConfigMap, def->name)) { /* domain exists, we will overwrite it */ - if (!(oldfilename = (char *)virHashLookup(nameConfigMap, value->str))) { + if (!(oldfilename = (char *)virHashLookup(nameConfigMap, def->name))) { xenXMError(conn, VIR_ERR_INTERNAL_ERROR, _("can't retrieve config filename for domain to overwrite")); goto error; @@ -2435,17 +2342,12 @@ virDomainPtr xenXMDomainDefineXML(virCon goto error; } - if (xenXMConfigGetUUID(entry->conf, "uuid", uuid) < 0) { - xenXMError(conn, VIR_ERR_INTERNAL_ERROR, - _("uuid config parameter is missing")); - goto error; - } - - if (!(olddomain = virGetDomain(conn, value->str, uuid))) + /* XXX wtf.com is this line for - it appears to be amemory leak */ + if (!(olddomain = virGetDomain(conn, def->name, entry->def->uuid))) goto error; /* Remove the name -> filename mapping */ - if (virHashRemoveEntry(nameConfigMap, value->str, NULL) < 0) { + if (virHashRemoveEntry(nameConfigMap, def->name, NULL) < 0) { xenXMError(conn, VIR_ERR_INTERNAL_ERROR, _("failed to remove old domain from config map")); goto error; @@ -2461,7 +2363,7 @@ virDomainPtr xenXMDomainDefineXML(virCon entry = NULL; } - if ((strlen(configDir) + 1 + strlen(value->str) + 1) > PATH_MAX) { + if ((strlen(configDir) + 1 + strlen(def->name) + 1) > PATH_MAX) { xenXMError(conn, VIR_ERR_INTERNAL_ERROR, _("config file name is too long")); goto error; @@ -2469,13 +2371,10 @@ virDomainPtr xenXMDomainDefineXML(virCon strcpy(filename, configDir); strcat(filename, "/"); - strcat(filename, value->str); - - if (virConfWriteFile(filename, conf) < 0) { - xenXMError(conn, VIR_ERR_INTERNAL_ERROR, - _("unable to write config file")); + strcat(filename, def->name); + + if (xenXMConfigSaveFile(conn, filename, def) < 0) goto error; - } if (VIR_ALLOC(entry) < 0) { xenXMError(conn, VIR_ERR_NO_MEMORY, _("config")); @@ -2489,13 +2388,7 @@ virDomainPtr xenXMDomainDefineXML(virCon } memmove(entry->filename, filename, PATH_MAX); - entry->conf = conf; - - if (xenXMConfigGetUUID(conf, "uuid", uuid) < 0) { - xenXMError(conn, VIR_ERR_INTERNAL_ERROR, - _("uuid config parameter is missing")); - goto error; - } + entry->def = def; if (virHashAddEntry(configCache, filename, entry) < 0) { xenXMError(conn, VIR_ERR_INTERNAL_ERROR, @@ -2503,25 +2396,23 @@ virDomainPtr xenXMDomainDefineXML(virCon goto error; } - if (virHashAddEntry(nameConfigMap, value->str, entry->filename) < 0) { + if (virHashAddEntry(nameConfigMap, def->name, entry->filename) < 0) { virHashRemoveEntry(configCache, filename, NULL); xenXMError(conn, VIR_ERR_INTERNAL_ERROR, _("unable to store config file handle")); goto error; } - entry = NULL; - - if (!(ret = virGetDomain(conn, value->str, uuid))) - goto error; + if (!(ret = virGetDomain(conn, def->name, def->uuid))) + return NULL; + ret->id = -1; return (ret); error: VIR_FREE(entry); - if (conf) - virConfFree(conf); + virDomainDefFree(def); return (NULL); } @@ -2628,6 +2519,15 @@ int xenXMNumOfDefinedDomains(virConnectP return virHashSize(nameConfigMap); } + +static int xenXMDiskCompare(virDomainDiskDefPtr a, + virDomainDiskDefPtr b) { + if (a->bus == b->bus) + return virDiskNameToIndex(a->dst) - virDiskNameToIndex(b->dst); + else + return a->bus - b->bus; +} + /** * xenXMDomainAttachDevice: @@ -2643,75 +2543,65 @@ xenXMDomainAttachDevice(virDomainPtr dom xenXMDomainAttachDevice(virDomainPtr domain, const char *xml) { const char *filename = NULL; xenXMConfCachePtr entry = NULL; - xmlDocPtr doc = NULL; - xmlNodePtr node = NULL; - xmlXPathContextPtr ctxt = NULL; - xmlXPathObjectPtr obj = NULL; - char *domxml = NULL; - int ret = -1, hvm = 0; + int ret = -1; + virDomainDeviceDefPtr dev = NULL; if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) { xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG, __FUNCTION__); - goto cleanup; + return -1; } if (domain->conn->flags & VIR_CONNECT_RO) - goto cleanup; + return -1; if (domain->id != -1) - goto cleanup; + return -1; + if (!(filename = virHashLookup(nameConfigMap, domain->name))) - goto cleanup; + return -1; if (!(entry = virHashLookup(configCache, filename))) - goto cleanup; - if (!(entry->conf)) - goto cleanup; - - if (!(domxml = xenXMDomainDumpXML(domain, 0))) - goto cleanup; - - doc = xmlReadDoc((const xmlChar *) domxml, "domain.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING); - if (!doc) { - xenXMError(domain->conn, VIR_ERR_XML_ERROR, - _("cannot read XML domain definition")); - goto cleanup; - } - if (!(ctxt = xmlXPathNewContext(doc))) { - xenXMError(domain->conn, VIR_ERR_INTERNAL_ERROR, - _("cannot create XPath context")); - goto cleanup; - } - obj = xmlXPathEval(BAD_CAST "string(/domain/os/type)", ctxt); - if ((obj != NULL) && (obj->type == XPATH_STRING) && - (obj->stringval) && (STREQ((char *)obj->stringval, "hvm"))) - hvm = 1; - - xmlXPathFreeContext(ctxt); - ctxt = NULL; - if (doc) - xmlFreeDoc(doc); - doc = xmlReadDoc((const xmlChar *) xml, "device.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING); - if (!doc) { - xenXMError(domain->conn, VIR_ERR_XML_ERROR, - _("cannot read XML domain definition")); - goto cleanup; - } - if (!(ctxt = xmlXPathNewContext(doc))) { - xenXMError(domain->conn, VIR_ERR_INTERNAL_ERROR, - _("cannot create XPath context")); - goto cleanup; - } - - if ((node = virXPathNode("/disk", ctxt))) { - if (xenXMAttachDisk(domain, ctxt, hvm, node, entry)) - goto cleanup; - } else if ((node = virXPathNode("/interface", ctxt))) { - if (xenXMAttachInterface(domain, ctxt, hvm, node, entry)) - goto cleanup; - } else { + return -1; + + if (!(dev = virDomainDeviceDefParse(domain->conn, + entry->def, + xml))) + return -1; + + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + { + /* Maintain list in sorted order according to target device name */ + if (entry->def->disks == NULL) { + dev->data.disk->next = entry->def->disks; + entry->def->disks = dev->data.disk; + } else { + virDomainDiskDefPtr ptr = entry->def->disks; + while (ptr) { + if (!ptr->next || xenXMDiskCompare(dev->data.disk, ptr->next) < 0) { + dev->data.disk->next = ptr->next; + ptr->next = dev->data.disk; + break; + } + ptr = ptr->next; + } + } + dev->data.disk = NULL; + } + break; + + case VIR_DOMAIN_DEVICE_NET: + { + virDomainNetDefPtr net = entry->def->nets; + while (net && net->next) + net = net->next; + if (net) + net->next = dev->data.net; + else + entry->def->nets = dev->data.net; + dev->data.net = NULL; + break; + } + + default: xenXMError(domain->conn, VIR_ERR_XML_ERROR, _("unknown device")); goto cleanup; @@ -2720,318 +2610,17 @@ xenXMDomainAttachDevice(virDomainPtr dom /* If this fails, should we try to undo our changes to the * in-memory representation of the config file. I say not! */ - if (virConfWriteFile(entry->filename, entry->conf) < 0) + if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0) goto cleanup; ret = 0; cleanup: - VIR_FREE(domxml); - xmlXPathFreeObject(obj); - xmlXPathFreeContext(ctxt); - if (doc) - xmlFreeDoc(doc); + virDomainDeviceDefFree(dev); return ret; } -static int -xenXMAttachDisk(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm, - xmlNodePtr node, xenXMConfCachePtr entry) { - virConfValuePtr list_item = NULL, list_val = NULL, prev = NULL; - xenUnifiedPrivatePtr priv = NULL; - xmlChar *type = NULL, *source = NULL, *target = NULL; - int ret = -1; - char *dev; - - priv = (xenUnifiedPrivatePtr) domain->conn->privateData; - xenXMParseXMLDisk(node, hvm, ((xenUnifiedPrivatePtr) domain->conn->privateData)->xendConfigVersion, &dev); - if (!dev) - goto cleanup; - - if (!(type = xmlGetProp(node, BAD_CAST "type"))) { - xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR); - goto cleanup; - } - if (!(node = virXPathNode("/disk/source", ctxt))) { - xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR); - goto cleanup; - } - if (STREQ((const char *) type, "block")) - source = xmlGetProp(node, BAD_CAST "dev"); - else if (STREQ((const char *) type, "file")) - source = xmlGetProp(node, BAD_CAST "file"); - else { - xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR); - goto cleanup; - } - if (!(node = virXPathNode("/disk/target", ctxt))) { - xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR); - goto cleanup; - } - target = xmlGetProp(node, BAD_CAST "dev"); - - list_item = virConfGetValue(entry->conf, "disk"); - if (list_item && list_item->type == VIR_CONF_LIST) { - prev = list_item; - list_val = list_item->list; - while (list_val) { - if ((list_val->type != VIR_CONF_STRING) || (!list_val->str)) - goto skip; - char domdev[NAME_MAX]; - char *head; - char *offset; - char *tmp; - - head = list_val->str; - - /* Extract the source */ - if (!(offset = strchr(head, ',')) || offset[0] == '\0') - goto skip; - if ((offset - head) >= (PATH_MAX-1)) - goto skip; - head = offset + 1; - - /* Extract the dest */ - if (!(offset = strchr(head, ',')) || offset[0] == '\0') - goto skip; - if ((offset - head) >= (PATH_MAX-1)) - goto skip; - strncpy(domdev, head, (offset - head)); - domdev[(offset-head)] = '\0'; - head = offset + 1; - - /* Remove legacy ioemu: junk */ - if (STRPREFIX(domdev, "ioemu:")) { - memmove(domdev, domdev+6, strlen(domdev)-5); - } - - /* Check for a :cdrom/:disk postfix */ - if ((tmp = strchr(domdev, ':'))) - tmp[0] = '\0'; - - if (STREQ(domdev, (const char *) target)) - break; - skip: - prev = list_val; - list_val = list_val->next; - } - } else if (!list_item) { - if (VIR_ALLOC(list_item) < 0) - goto cleanup; - list_item->type = VIR_CONF_LIST; - if(virConfSetValue(entry->conf, "disk", list_item)) { - VIR_FREE(list_item); - goto cleanup; - } - list_val = NULL; - prev = list_item; - } else - goto cleanup; - - if (!list_val) { - /* insert */ - if (VIR_ALLOC(list_val) < 0) - goto cleanup; - list_val->type = VIR_CONF_STRING; - list_val->next = NULL; - list_val->str = dev; - if (prev->type == VIR_CONF_LIST) - prev->list = list_val; - else - prev->next = list_val; - } else { - /* configure */ - VIR_FREE(list_val->str); - list_val->str = dev; - } - - ret = 0; - goto cleanup; - - cleanup: - VIR_FREE(type); - VIR_FREE(source); - VIR_FREE(target); - - return (ret); -} - -static int -xenXMAttachInterface(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm, - xmlNodePtr node, xenXMConfCachePtr entry) { - virConfValuePtr list_item = NULL, list_val = NULL, prev = NULL; - xmlChar *type = NULL, *source = NULL, *mac = NULL; - int ret = -1, autoassign = 0; - char *dev; - - xmlNodePtr node_cur = NULL, node_tmp = NULL; - xmlAttrPtr attr_node = NULL; - xmlNodePtr text_node = NULL; - - if(!(type = xmlGetProp(node, BAD_CAST "type"))) { - xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR); - goto cleanup; - } - - if (!(node = virXPathNode("/interface/source", ctxt))) { - xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR); - goto cleanup; - } - source = xmlGetProp(node, BAD_CAST type); - - if ((node = virXPathNode("/interface/mac", ctxt))) - mac = xmlGetProp(node, BAD_CAST "address"); - if (!node || !mac) { - if (!(mac = (xmlChar *)xenXMAutoAssignMac())) - goto cleanup; - autoassign = 1; - } - - list_item = virConfGetValue(entry->conf, "vif"); - if (list_item && list_item->type == VIR_CONF_LIST) { - prev = list_item; - list_val = list_item->list; - while (list_val) { - if ((list_val->type != VIR_CONF_STRING) || (!list_val->str)) - goto skip; - char dommac[18]; - char *key; - - dommac[0] = '\0'; - - key = list_val->str; - while (key) { - char *data; - char *nextkey = strchr(key, ','); - - if (!(data = strchr(key, '=')) || (data[0] == '\0')) - goto skip; - data++; - - if (STRPREFIX(key, "mac=")) { - int len = nextkey ? (nextkey - data) : 17; - if (len > 17) - len = 17; - strncpy(dommac, data, len); - dommac[len] = '\0'; - } - - while (nextkey && (nextkey[0] == ',' || - nextkey[0] == ' ' || - nextkey[0] == '\t')) - nextkey++; - key = nextkey; - } - - if (virMacAddrCompare (dommac, (const char *) mac) == 0) { - if (autoassign) { - VIR_FREE(mac); - mac = NULL; - if (!(mac = (xmlChar *)xenXMAutoAssignMac())) - goto cleanup; - /* initialize the list */ - list_item = virConfGetValue(entry->conf, "vif"); - prev = list_item; - list_val = list_item->list; - continue; - } else - break; - } - skip: - prev = list_val; - list_val = list_val->next; - } - } else if (!list_item) { - if (VIR_ALLOC(list_item) < 0) - goto cleanup; - list_item->type = VIR_CONF_LIST; - if(virConfSetValue(entry->conf, "vif", list_item)) { - VIR_FREE(list_item); - goto cleanup; - } - list_val = NULL; - prev = list_item; - } else - goto cleanup; - - if ((node = virXPathNode("/interface", ctxt))) { - if (autoassign) { - node_cur = node->children; - - while (node_cur->next) - node_cur = node_cur->next; - - if (VIR_ALLOC(node_tmp) < 0) - goto node_cleanup; - node_tmp->type = XML_ELEMENT_NODE; - if (VIR_ALLOC_N(node_tmp->name, 4) < 0) - goto node_cleanup; - strcpy((char *)node_tmp->name, "mac"); - node_tmp->children = NULL; - - if (VIR_ALLOC(attr_node) < 0) - goto node_cleanup; - attr_node->type = XML_ATTRIBUTE_NODE; - attr_node->ns = NULL; - if (VIR_ALLOC_N(attr_node->name, 8) < 0) - goto node_cleanup; - strcpy((char *) attr_node->name, "address"); - node_tmp->properties = attr_node; - - if (VIR_ALLOC(text_node) < 0) - goto node_cleanup; - text_node->type = XML_TEXT_NODE; - text_node->_private = NULL; - if (VIR_ALLOC_N(text_node->name, 5) < 0) - goto node_cleanup; - strcpy((char *) text_node->name, "text"); - text_node->children = NULL; - text_node->parent = (xmlNodePtr)attr_node; - text_node->content = mac; - mac = NULL; - attr_node->children = text_node; - attr_node->last = text_node; - attr_node->parent = node_tmp; - - node_cur->next = node_tmp; - } - if (!(dev = xenXMParseXMLVif(domain->conn, node, hvm))) - goto cleanup; - } else - goto cleanup; - - if (!list_val) { - /* insert */ - if (VIR_ALLOC(list_val) < 0) - goto cleanup; - list_val->type = VIR_CONF_STRING; - list_val->next = NULL; - list_val->str = dev; - if (prev->type == VIR_CONF_LIST) - prev->list = list_val; - else - prev->next = list_val; - } else { - /* configure */ - VIR_FREE(list_val->str); - list_val->str = dev; - } - - ret = 0; - goto cleanup; - - node_cleanup: - xmlFree(node_tmp); - xmlFree(attr_node); - xmlFree(text_node); - cleanup: - VIR_FREE(type); - VIR_FREE(source); - VIR_FREE(mac); - - return (ret); -} /** * xenXMAutoAssignMac: @@ -3067,180 +2656,87 @@ static int static int xenXMDomainDetachDevice(virDomainPtr domain, const char *xml) { const char *filename = NULL; - char device[8], *domdevice = NULL; xenXMConfCachePtr entry = NULL; - virConfValuePtr prev = NULL, list_ptr = NULL, list_val = NULL; - xmlDocPtr doc = NULL; - xmlNodePtr node = NULL; - xmlXPathContextPtr ctxt = NULL; - xmlChar *key = NULL; + virDomainDeviceDefPtr dev = NULL; int ret = -1; if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) { xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + if (domain->conn->flags & VIR_CONNECT_RO) + return -1; + if (domain->id != -1) + return -1; + if (!(filename = virHashLookup(nameConfigMap, domain->name))) + return -1; + if (!(entry = virHashLookup(configCache, filename))) + return -1; + + if (!(dev = virDomainDeviceDefParse(domain->conn, + entry->def, + xml))) + return -1; + + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + { + virDomainDiskDefPtr disk = entry->def->disks; + virDomainDiskDefPtr prev = NULL; + while (disk) { + if (disk->dst && + dev->data.disk->dst && + STREQ(disk->dst, dev->data.disk->dst)) { + if (prev) { + prev->next = disk->next; + } else { + entry->def->disks = disk->next; + } + virDomainDiskDefFree(disk); + break; + } + prev = disk; + disk = disk->next; + } + break; + } + + case VIR_DOMAIN_DEVICE_NET: + { + virDomainNetDefPtr net = entry->def->nets; + virDomainNetDefPtr prev = NULL; + while (net) { + if (!memcmp(net->mac, dev->data.net->mac, VIR_DOMAIN_NET_MAC_SIZE)) { + if (prev) { + prev->next = net->next; + } else { + entry->def->nets = net->next; + } + virDomainNetDefFree(net); + break; + } + prev = net; + net = net->next; + } + break; + } + default: + xenXMError(domain->conn, VIR_ERR_XML_ERROR, + _("unknown device")); goto cleanup; - } - if (domain->conn->flags & VIR_CONNECT_RO) - goto cleanup; - if (domain->id != -1) - goto cleanup; - if (!(filename = virHashLookup(nameConfigMap, domain->name))) - goto cleanup; - - doc = xmlReadDoc((const xmlChar *) xml, "device.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING); - if (!doc) { - xenXMError(domain->conn, VIR_ERR_XML_ERROR, - _("cannot read XML domain definition")); - goto cleanup; - } - if (!(ctxt = xmlXPathNewContext(doc))) { - xenXMError(domain->conn, VIR_ERR_INTERNAL_ERROR, - _("cannot create XPath context")); - goto cleanup; - } - - if ((node = virXPathNode("/disk", ctxt))) { - strcpy(device, "disk"); - if (!(node = virXPathNode("/disk/target", ctxt))) - goto cleanup; - key = xmlGetProp(node, BAD_CAST "dev"); - } else if ((node = virXPathNode("/interface", ctxt))) { - strcpy(device, "vif"); - if (!(node = virXPathNode("/interface/mac", ctxt))) - goto cleanup; - key = xmlGetProp(node, BAD_CAST "address"); - } else - goto cleanup; - if (!key || (strlen((char *)key) == 0)) - goto cleanup; - - if (!(entry = virHashLookup(configCache, filename))) - goto cleanup; - if (!entry->conf) - goto cleanup; - - list_ptr = virConfGetValue(entry->conf, device); - if (!list_ptr) - goto cleanup; - else if (list_ptr && list_ptr->type == VIR_CONF_LIST) { - list_val = list_ptr->list; - while (list_val) { - if (STREQ(device, "disk")) { - char domdev[NAME_MAX]; - char *head; - char *offset; - char *tmp; - - if ((list_val->type != VIR_CONF_STRING) || (!list_val->str)) - goto skip; - head = list_val->str; - - /* Extract the source */ - if (!(offset = strchr(head, ',')) || offset[0] == '\0') - goto skip; - if ((offset - head) >= (PATH_MAX-1)) - goto skip; - head = offset + 1; - - /* Extract the dest */ - if (!(offset = strchr(head, ',')) || offset[0] == '\0') - goto skip; - if ((offset - head) >= (PATH_MAX-1)) - goto skip; - strncpy(domdev, head, (offset - head)); - domdev[(offset-head)] = '\0'; - head = offset + 1; - - /* Remove legacy ioemu: junk */ - if (STRPREFIX(domdev, "ioemu:")) { - memmove(domdev, domdev+6, strlen(domdev)-5); - } - - /* Check for a :cdrom/:disk postfix */ - if ((tmp = strchr(domdev, ':'))) - tmp[0] = '\0'; - - if (STREQ(domdev, (const char *) key)) - break; - } else { - char dommac[18]; - char *mac; - - dommac[0] = '\0'; - - if ((list_val->type != VIR_CONF_STRING) || (!list_val->str)) - goto skip; - - mac = list_val->str; - while (mac) { - char *data; - char *nextmac = strchr(mac, ','); - - if (!(data = strchr(mac, '=')) || (data[0] == '\0')) - goto skip; - data++; - - if (STRPREFIX(mac, "mac=")) { - int len = nextmac ? (nextmac - data) : 17; - if (len > 17) - len = 17; - strncpy(dommac, data, len); - dommac[len] = '\0'; - } - - while (nextmac && (nextmac[0] == ',' || - nextmac[0] == ' ' || - nextmac[0] == '\t')) - nextmac++; - mac = nextmac; - } - - if (virMacAddrCompare (dommac, (const char *) key) == 0) - break; - } - skip: - prev = list_val; - list_val = list_val->next; - } - } - - if (!list_val) - goto cleanup; - else { - if (!prev) { - virConfValuePtr value; - if (VIR_ALLOC(value) < 0) - goto cleanup; - value->type = VIR_CONF_LIST; - value->list = list_val->next; - list_val->next = NULL; - if (virConfSetValue(entry->conf, device, value)) { - VIR_FREE(value); - goto cleanup; - } - } else - prev->next = list_val->next; } /* If this fails, should we try to undo our changes to the * in-memory representation of the config file. I say not! */ - if (virConfWriteFile(entry->filename, entry->conf) < 0) + if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0) goto cleanup; ret = 0; cleanup: - xmlXPathFreeContext(ctxt); - if (doc) - xmlFreeDoc(doc); - VIR_FREE(domdevice); - VIR_FREE(key); - VIR_FREE(list_val); - + virDomainDeviceDefFree(dev); return (ret); } diff -r a6688e03b4fc src/xm_internal.h --- a/src/xm_internal.h Mon Jul 07 07:11:30 2008 -0400 +++ b/src/xm_internal.h Mon Jul 07 10:11:29 2008 -0400 @@ -28,10 +28,7 @@ #include "libvirt/libvirt.h" #include "conf.h" #include "internal.h" - -#ifdef __cplusplus -extern "C" { -#endif +#include "domain_conf.h" extern struct xenUnifiedDriver xenXMDriver; int xenXMInit (void); @@ -58,11 +55,9 @@ virDomainPtr xenXMDomainDefineXML(virCon virDomainPtr xenXMDomainDefineXML(virConnectPtr con, const char *xml); int xenXMDomainUndefine(virDomainPtr domain); -virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml); -char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf); +virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, virDomainDefPtr def); +virDomainDefPtr xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf); + int xenXMDomainBlockPeek (virDomainPtr dom, const char *path, unsigned long long offset, size_t size, void *buffer); -#ifdef __cplusplus -} #endif -#endif diff -r a6688e03b4fc tests/Makefile.am --- a/tests/Makefile.am Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/Makefile.am Mon Jul 07 07:11:30 2008 -0400 @@ -100,7 +100,7 @@ sexpr2xmltest_LDADD = $(LDADDS) sexpr2xmltest_LDADD = $(LDADDS) xmconfigtest_SOURCES = \ - xmconfigtest.c \ + xmconfigtest.c testutilsxen.c testutilsxen.h \ testutils.c testutils.h xmconfigtest_LDADD = $(LDADDS) diff -r a6688e03b4fc tests/xmconfigdata/test-escape-paths.cfg --- a/tests/xmconfigdata/test-escape-paths.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-escape-paths.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,7 +20,7 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso&test,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "none" soundhw = "sb16,es1370" diff -r a6688e03b4fc tests/xmconfigdata/test-escape-paths.xml --- a/tests/xmconfigdata/test-escape-paths.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-escape-paths.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2&test</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader&test</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm&test</emulator> <disk type='block' device='disk'> @@ -32,11 +32,11 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> <sound model='sb16'/> <sound model='es1370'/> </devices> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-localtime.cfg --- a/tests/xmconfigdata/test-fullvirt-localtime.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-localtime.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "none" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-localtime.xml --- a/tests/xmconfigdata/test-fullvirt-localtime.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-localtime.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='localtime'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='localtime'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,10 +32,10 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-new-cdrom.cfg --- a/tests/xmconfigdata/test-fullvirt-new-cdrom.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-new-cdrom.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "none" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-new-cdrom.xml --- a/tests/xmconfigdata/test-fullvirt-new-cdrom.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-new-cdrom.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,10 +32,10 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-old-cdrom.cfg --- a/tests/xmconfigdata/test-fullvirt-old-cdrom.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-old-cdrom.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -21,6 +21,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,ioemu:hda,w" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr0,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr0,type=ioemu" ] parallel = "none" serial = "none" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-old-cdrom.xml --- a/tests/xmconfigdata/test-fullvirt-old-cdrom.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-old-cdrom.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,10 +32,10 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr0'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-parallel-tcp.cfg --- a/tests/xmconfigdata/test-fullvirt-parallel-tcp.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-parallel-tcp.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "tcp:127.0.0.1:7777" serial = "none" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-parallel-tcp.xml --- a/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,15 +32,15 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <parallel type='tcp'> <source mode='connect' host='127.0.0.1' service='7777'/> <protocol type='raw'/> <target port='0'/> </parallel> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-file.cfg --- a/tests/xmconfigdata/test-fullvirt-serial-file.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-file.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "file:/tmp/serial.log" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-file.xml --- a/tests/xmconfigdata/test-fullvirt-serial-file.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-file.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,11 +32,9 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <serial type='file'> <source path='/tmp/serial.log'/> <target port='0'/> @@ -45,5 +43,7 @@ <source path='/tmp/serial.log'/> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-null.cfg --- a/tests/xmconfigdata/test-fullvirt-serial-null.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-null.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "null" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-null.xml --- a/tests/xmconfigdata/test-fullvirt-serial-null.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-null.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,16 +32,16 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <serial type='null'> <target port='0'/> </serial> <console type='null'> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-pipe.cfg --- a/tests/xmconfigdata/test-fullvirt-serial-pipe.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-pipe.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "pipe:/tmp/serial.pipe" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-pipe.xml --- a/tests/xmconfigdata/test-fullvirt-serial-pipe.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-pipe.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,11 +32,9 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <serial type='pipe'> <source path='/tmp/serial.pipe'/> <target port='0'/> @@ -45,5 +43,7 @@ <source path='/tmp/serial.pipe'/> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-pty.cfg --- a/tests/xmconfigdata/test-fullvirt-serial-pty.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-pty.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "pty" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-pty.xml --- a/tests/xmconfigdata/test-fullvirt-serial-pty.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-pty.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,16 +32,16 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <serial type='pty'> <target port='0'/> </serial> <console type='pty'> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-stdio.cfg --- a/tests/xmconfigdata/test-fullvirt-serial-stdio.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-stdio.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "stdio" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-stdio.xml --- a/tests/xmconfigdata/test-fullvirt-serial-stdio.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-stdio.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,16 +32,16 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <serial type='stdio'> <target port='0'/> </serial> <console type='stdio'> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.cfg --- a/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "telnet:127.0.0.1:9999,listen" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml --- a/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,11 +32,9 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <serial type='tcp'> <source mode='bind' host='127.0.0.1' service='9999'/> <protocol type='telnet'/> @@ -47,5 +45,7 @@ <protocol type='telnet'/> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-tcp.cfg --- a/tests/xmconfigdata/test-fullvirt-serial-tcp.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-tcp.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "tcp:127.0.0.1:7777" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-tcp.xml --- a/tests/xmconfigdata/test-fullvirt-serial-tcp.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-tcp.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,11 +32,9 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <serial type='tcp'> <source mode='connect' host='127.0.0.1' service='7777'/> <protocol type='raw'/> @@ -47,5 +45,7 @@ <protocol type='raw'/> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-udp.cfg --- a/tests/xmconfigdata/test-fullvirt-serial-udp.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-udp.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "udp:127.0.0.1:9999@0.0.0.0:99998" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-udp.xml --- a/tests/xmconfigdata/test-fullvirt-serial-udp.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-udp.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,20 +32,20 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <serial type='udp'> + <source mode='bind' host='0.0.0.0' service='99998'/> <source mode='connect' host='127.0.0.1' service='9999'/> - <source mode='bind' host='0.0.0.0' service='99998'/> <target port='0'/> </serial> <console type='udp'> + <source mode='bind' host='0.0.0.0' service='99998'/> <source mode='connect' host='127.0.0.1' service='9999'/> - <source mode='bind' host='0.0.0.0' service='99998'/> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-unix.cfg --- a/tests/xmconfigdata/test-fullvirt-serial-unix.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-unix.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "unix:/tmp/serial.sock,listen" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-serial-unix.xml --- a/tests/xmconfigdata/test-fullvirt-serial-unix.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-serial-unix.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,11 +32,9 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <serial type='unix'> <source mode='bind' path='/tmp/serial.sock'/> <target port='0'/> @@ -45,5 +43,7 @@ <source mode='bind' path='/tmp/serial.sock'/> <target port='0'/> </console> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-sound.cfg --- a/tests/xmconfigdata/test-fullvirt-sound.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-sound.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,7 +20,7 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "none" soundhw = "sb16,es1370" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-sound.xml --- a/tests/xmconfigdata/test-fullvirt-sound.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-sound.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,11 +32,11 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> <sound model='sb16'/> <sound model='es1370'/> </devices> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-usbmouse.cfg --- a/tests/xmconfigdata/test-fullvirt-usbmouse.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-usbmouse.cfg Mon Jul 07 10:11:29 2008 -0400 @@ -21,6 +21,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "none" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-usbmouse.xml --- a/tests/xmconfigdata/test-fullvirt-usbmouse.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-usbmouse.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,11 +32,11 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> <input type='mouse' bus='usb'/> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml --- a/tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml Mon Jul 07 07:11:30 2008 -0400 @@ -32,7 +32,7 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> <input type='tablet'/> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-usbtablet.cfg --- a/tests/xmconfigdata/test-fullvirt-usbtablet.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-usbtablet.cfg Mon Jul 07 10:11:29 2008 -0400 @@ -21,6 +21,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "none" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-usbtablet.xml --- a/tests/xmconfigdata/test-fullvirt-usbtablet.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-usbtablet.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,11 +32,11 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> <input type='tablet' bus='usb'/> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-utc.cfg --- a/tests/xmconfigdata/test-fullvirt-utc.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-utc.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -20,6 +20,6 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ] -vif = [ "mac=00:16:3E:66:92:9C,bridge=xenbr1,type=ioemu" ] +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,type=ioemu" ] parallel = "none" serial = "none" diff -r a6688e03b4fc tests/xmconfigdata/test-fullvirt-utc.xml --- a/tests/xmconfigdata/test-fullvirt-utc.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-fullvirt-utc.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> - <features> - <pae/> - <acpi/> - <apic/> - </features> - <clock offset='utc'/> <devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> @@ -32,10 +32,10 @@ <readonly/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:92:9C'/> + <mac address='00:16:3e:66:92:9c'/> <source bridge='xenbr1'/> </interface> <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-paravirt-net-e1000.cfg --- a/tests/xmconfigdata/test-paravirt-net-e1000.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-paravirt-net-e1000.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -9,4 +9,4 @@ on_crash = "restart" on_crash = "restart" vfb = [ "type=vnc,vncunused=1,vnclisten=127.0.0.1,vncpasswd=123poi" ] disk = [ "phy:/dev/HostVG/XenGuest1,xvda,w" ] -vif = [ "mac=00:16:3E:66:94:9C,model=e1000,ip=192.168.0.9" ] +vif = [ "mac=00:16:3e:66:94:9c,bridge=br0,model=e1000" ] diff -r a6688e03b4fc tests/xmconfigdata/test-paravirt-net-e1000.xml --- a/tests/xmconfigdata/test-paravirt-net-e1000.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-paravirt-net-e1000.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,28 +1,33 @@ <domain type='xen'> <name>XenGuest1</name> <uuid>c7a5fdb0-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <bootloader>/usr/bin/pygrub</bootloader> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <os> + <type arch='i686' machine='xenpv'>linux</type> + </os> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <devices> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> <driver name='phy'/> <source dev='/dev/HostVG/XenGuest1'/> <target dev='xvda' bus='xen'/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:94:9C'/> - <ip address='192.168.0.9'/> + <mac address='00:16:3e:66:94:9c'/> + <source bridge='br0'/> <model type='e1000'/> </interface> - <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <console type='pty'> <target port='0'/> </console> + <input type='mouse' bus='xen'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-paravirt-new-pvfb.cfg --- a/tests/xmconfigdata/test-paravirt-new-pvfb.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-paravirt-new-pvfb.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -9,4 +9,4 @@ on_crash = "restart" on_crash = "restart" vfb = [ "type=vnc,vncunused=1,vnclisten=127.0.0.1,vncpasswd=123poi" ] disk = [ "phy:/dev/HostVG/XenGuest1,xvda,w" ] -vif = [ "mac=00:16:3E:66:94:9C,ip=192.168.0.9" ] +vif = [ "mac=00:16:3e:66:94:9c,bridge=br0" ] diff -r a6688e03b4fc tests/xmconfigdata/test-paravirt-new-pvfb.xml --- a/tests/xmconfigdata/test-paravirt-new-pvfb.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-paravirt-new-pvfb.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,27 +1,32 @@ <domain type='xen'> <name>XenGuest1</name> <uuid>c7a5fdb0-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <bootloader>/usr/bin/pygrub</bootloader> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <os> + <type arch='i686' machine='xenpv'>linux</type> + </os> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <devices> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> <driver name='phy'/> <source dev='/dev/HostVG/XenGuest1'/> <target dev='xvda' bus='xen'/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:94:9C'/> - <ip address='192.168.0.9'/> + <mac address='00:16:3e:66:94:9c'/> + <source bridge='br0'/> </interface> - <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <console type='pty'> <target port='0'/> </console> + <input type='mouse' bus='xen'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigdata/test-paravirt-old-pvfb.cfg --- a/tests/xmconfigdata/test-paravirt-old-pvfb.cfg Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-paravirt-old-pvfb.cfg Mon Jul 07 07:11:30 2008 -0400 @@ -13,4 +13,4 @@ vnclisten = "127.0.0.1" vnclisten = "127.0.0.1" vncpasswd = "123poi" disk = [ "phy:/dev/HostVG/XenGuest1,xvda,w" ] -vif = [ "mac=00:16:3E:66:94:9C,ip=192.168.0.9" ] +vif = [ "mac=00:16:3e:66:94:9c,bridge=br0" ] diff -r a6688e03b4fc tests/xmconfigdata/test-paravirt-old-pvfb.xml --- a/tests/xmconfigdata/test-paravirt-old-pvfb.xml Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigdata/test-paravirt-old-pvfb.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,27 +1,32 @@ <domain type='xen'> <name>XenGuest1</name> <uuid>c7a5fdb0-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <bootloader>/usr/bin/pygrub</bootloader> - <currentMemory>403456</currentMemory> - <memory>592896</memory> - <vcpu>1</vcpu> + <os> + <type arch='i686' machine='xenpv'>linux</type> + </os> + <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <devices> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> <driver name='phy'/> <source dev='/dev/HostVG/XenGuest1'/> <target dev='xvda' bus='xen'/> </disk> <interface type='bridge'> - <mac address='00:16:3E:66:94:9C'/> - <ip address='192.168.0.9'/> + <mac address='00:16:3e:66:94:9c'/> + <source bridge='br0'/> </interface> - <input type='mouse' bus='xen'/> - <graphics type='vnc' port='-1' listen='127.0.0.1' passwd='123poi'/> <console type='pty'> <target port='0'/> </console> + <input type='mouse' bus='xen'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> </devices> </domain> diff -r a6688e03b4fc tests/xmconfigtest.c --- a/tests/xmconfigtest.c Mon Jul 07 07:11:30 2008 -0400 +++ b/tests/xmconfigtest.c Mon Jul 07 07:35:08 2008 -0400 @@ -33,10 +33,12 @@ #include "xen_unified.h" #include "xm_internal.h" #include "testutils.h" -#include "conf.h" +#include "testutilsxen.h" +#include "memory.h" static char *progname; static char *abs_srcdir; +static virCapsPtr caps; #define MAX_FILE 4096 @@ -54,6 +56,7 @@ static int testCompareParseXML(const cha int wrote = MAX_FILE; void *old_priv = NULL; struct _xenUnifiedPrivate priv; + virDomainDefPtr def = NULL; conn = virConnectOpenReadOnly("test:///default"); if (!conn) goto fail; @@ -67,9 +70,13 @@ static int testCompareParseXML(const cha /* Many puppies died to bring you this code. */ priv.xendConfigVersion = xendConfigVersion; + priv.caps = caps; conn->privateData = &priv; - if (!(conf = xenXMParseXMLToConfig(conn, xmlPtr))) + if (!(def = virDomainDefParseString(NULL, caps, xmlPtr))) + goto fail; + + if (!(conf = xenXMDomainConfigFormat(conn, def))) goto fail; if (virConfWriteMem(gotxmcfgPtr, &wrote, conf) < 0) @@ -86,7 +93,7 @@ static int testCompareParseXML(const cha fail: if (conf) virConfFree(conf); - + virDomainDefFree(def); if (conn) { conn->privateData = old_priv; virConnectClose(conn); @@ -107,6 +114,7 @@ static int testCompareFormatXML(const ch virConnectPtr conn; void *old_priv; struct _xenUnifiedPrivate priv; + virDomainDefPtr def = NULL; conn = virConnectOpenReadOnly("test:///default"); if (!conn) goto fail; @@ -120,12 +128,16 @@ static int testCompareFormatXML(const ch /* Many puppies died to bring you this code. */ priv.xendConfigVersion = xendConfigVersion; + priv.caps = caps; conn->privateData = &priv; if (!(conf = virConfReadMem(xmcfgPtr, strlen(xmcfgPtr)))) goto fail; - if (!(gotxml = xenXMDomainFormatXML(conn, conf))) + if (!(def = xenXMDomainConfigParse(conn, conf))) + goto fail; + + if (!(gotxml = virDomainDefFormat(conn, def, VIR_DOMAIN_XML_SECURE))) goto fail; if (STRNEQ(xmlData, gotxml)) { @@ -138,8 +150,8 @@ static int testCompareFormatXML(const ch fail: if (conf) virConfFree(conf); - free(gotxml); - + VIR_FREE(gotxml); + virDomainDefFree(def); if (conn) { conn->privateData = old_priv; virConnectClose(conn); @@ -187,6 +199,8 @@ mymain(int argc, char **argv) if (!abs_srcdir) abs_srcdir = getcwd(cwd, sizeof(cwd)); + if (!(caps = testXenCapsInit())) + return(EXIT_FAILURE); #define DO_TEST(name, version) \ do { \ @@ -224,6 +238,9 @@ mymain(int argc, char **argv) DO_TEST("fullvirt-sound", 2); DO_TEST("escape-paths", 2); + + virCapabilitiesFree(caps); + return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Tue, Jul 08, 2008 at 05:40:17PM +0100, Daniel P. Berrange wrote:
This is a refactoring of the XM driver. Previously we would store the virConfPtr objects as our master 'in memory' representation of inactive domains. This switch it over to using virDomainDefPtr objects instead. The code for reading/writing the config files is unchanged at this time.
[...]
@@ -1291,9 +1217,10 @@ int xenXMDomainPinVcpu(virDomainPtr doma xenXMConfCachePtr entry; virBuffer mapbuf = VIR_BUFFER_INITIALIZER; char *mapstr = NULL; - char *ranges = NULL; int i, j, n, comma = 0; int ret = -1; + char *cpuset = NULL; + int maxcpu = 4096;
hum, we use MAX_VIRT_CPUS at places
+++ b/tests/xmconfigdata/test-fullvirt-new-cdrom.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type>
I'm just a bit surprized by that addition, is that derived from the features set ? I don't see why the arch can't be x86-64 for example just based on the tests/xmconfigdata/test-fullvirt-new-cdrom.cfg config data.
+++ b/tests/xmconfigdata/test-paravirt-old-pvfb.xml Mon Jul 07 10:11:30 2008 -0400 [..] <devices> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
So we are adding the emulator here, I guess nobody is gonna change that A couple of surprises in the tests, but the replacement looks safe +1 Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

On Thu, Jul 24, 2008 at 10:44:18AM -0400, Daniel Veillard wrote:
On Tue, Jul 08, 2008 at 05:40:17PM +0100, Daniel P. Berrange wrote:
This is a refactoring of the XM driver. Previously we would store the virConfPtr objects as our master 'in memory' representation of inactive domains. This switch it over to using virDomainDefPtr objects instead. The code for reading/writing the config files is unchanged at this time.
[...]
@@ -1291,9 +1217,10 @@ int xenXMDomainPinVcpu(virDomainPtr doma xenXMConfCachePtr entry; virBuffer mapbuf = VIR_BUFFER_INITIALIZER; char *mapstr = NULL; - char *ranges = NULL; int i, j, n, comma = 0; int ret = -1; + char *cpuset = NULL; + int maxcpu = 4096;
hum, we use MAX_VIRT_CPUS at places
Yeah, we need todo better here. The problem is Xen's idea of max CPU's is different from Linux's :-)
+++ b/tests/xmconfigdata/test-fullvirt-new-cdrom.xml Mon Jul 07 10:11:30 2008 -0400 @@ -1,23 +1,23 @@ <domain type='xen'> <name>XenGuest2</name> <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu>1</vcpu> <os> - <type>hvm</type> + <type arch='i686' machine='xenfv'>hvm</type>
I'm just a bit surprized by that addition, is that derived from the features set ? I don't see why the arch can't be x86-64 for example just based on the tests/xmconfigdata/test-fullvirt-new-cdrom.cfg config data.
What's happening is that in the Xen test suite we now define a static set of XML capabilities, which are independant of the host machine running the test. In the Xen case I defined the test suite to be a 32-bit machine, so the test XML files have to use 'i686'. Outside of the tst suite, the real capabilities data is fetched from the hypervisor so supports whatever is appropriate - i686, x86_64, ia64, ppc, etc.
+++ b/tests/xmconfigdata/test-paravirt-old-pvfb.xml Mon Jul 07 10:11:30 2008 -0400 [..] <devices> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
So we are adding the emulator here, I guess nobody is gonna change that
This is also driven off the capabilities data - so its just matching the the path defined in the test suite capabilities XML. In real Xen driver usage, it varies according to usr/lib vs /usr/lib64 on 32 vs 64 bit hosts Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Jul 24, 2008 at 05:10:55PM +0100, Daniel P. Berrange wrote:
On Thu, Jul 24, 2008 at 10:44:18AM -0400, Daniel Veillard wrote:
On Tue, Jul 08, 2008 at 05:40:17PM +0100, Daniel P. Berrange wrote:
This is a refactoring of the XM driver. Previously we would store the virConfPtr objects as our master 'in memory' representation of inactive domains. This switch it over to using virDomainDefPtr objects instead. The code for reading/writing the config files is unchanged at this time.
[...]
@@ -1291,9 +1217,10 @@ int xenXMDomainPinVcpu(virDomainPtr doma xenXMConfCachePtr entry; virBuffer mapbuf = VIR_BUFFER_INITIALIZER; char *mapstr = NULL; - char *ranges = NULL; int i, j, n, comma = 0; int ret = -1; + char *cpuset = NULL; + int maxcpu = 4096;
hum, we use MAX_VIRT_CPUS at places
Yeah, we need todo better here. The problem is Xen's idea of max CPU's is different from Linux's :-)
maybe a LIBVIRT_MAX_CPU exported from the libvirt.h API so that users know what is the limitation we use internally (or make everything dynamic but it's maybe too much).
+++ b/tests/xmconfigdata/test-fullvirt-new-cdrom.xml Mon Jul 07 10:11:30 2008 -0400 I'm just a bit surprized by that addition, is that derived from the features set ? I don't see why the arch can't be x86-64 for example just based on the tests/xmconfigdata/test-fullvirt-new-cdrom.cfg config data.
What's happening is that in the Xen test suite we now define a static set of XML capabilities, which are independant of the host machine running the test. In the Xen case I defined the test suite to be a 32-bit machine, so the test XML files have to use 'i686'. Outside of the tst suite, the real capabilities data is fetched from the hypervisor so supports whatever is appropriate - i686, x86_64, ia64, ppc, etc.
okay, makes sense actually we don't want the regression test to break on every different arch. +1 let's push it ! Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

On Thu, Jul 24, 2008 at 10:44:18AM -0400, Daniel Veillard wrote:
On Tue, Jul 08, 2008 at 05:40:17PM +0100, Daniel P. Berrange wrote:
This is a refactoring of the XM driver. Previously we would store the virConfPtr objects as our master 'in memory' representation of inactive domains. This switch it over to using virDomainDefPtr objects instead. The code for reading/writing the config files is unchanged at this time.
[...]
@@ -1291,9 +1217,10 @@ int xenXMDomainPinVcpu(virDomainPtr doma xenXMConfCachePtr entry; virBuffer mapbuf = VIR_BUFFER_INITIALIZER; char *mapstr = NULL; - char *ranges = NULL; int i, j, n, comma = 0; int ret = -1; + char *cpuset = NULL; + int maxcpu = 4096;
hum, we use MAX_VIRT_CPUS at places
I've checked up on this now - MAX_VIRT_CPUS refers to the Xen hypervisor and kernel limits on virtual CPUs - this is currently 32 or 64 depending on the architecture. The libvirt code here is refering to physical CPUs, whose limit is independant of virtual CPU limit, so we shouldnt' use the MAX_VIRT_CPUS constant here. I'll just #define a constant at the top of this file for now. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This replaces the code which converts from virConfPtr objects into XML, with code which converts from virConfPtr objects straight into virDomainDefPtr objects. A few more XML changes are needed in the test suite to take account of better XML generation this produces src/xend_internal.c | 67 - src/xend_internal.h | 11 src/xm_internal.c | 821 ++++++++++------- tests/xmconfigdata/test-escape-paths.xml | 2 tests/xmconfigdata/test-fullvirt-localtime.xml | 2 tests/xmconfigdata/test-fullvirt-new-cdrom.xml | 2 tests/xmconfigdata/test-fullvirt-old-cdrom.xml | 2 tests/xmconfigdata/test-fullvirt-parallel-tcp.xml | 2 tests/xmconfigdata/test-fullvirt-serial-file.xml | 2 tests/xmconfigdata/test-fullvirt-serial-null.xml | 2 tests/xmconfigdata/test-fullvirt-serial-pipe.xml | 2 tests/xmconfigdata/test-fullvirt-serial-pty.xml | 2 tests/xmconfigdata/test-fullvirt-serial-stdio.xml | 2 tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml | 2 tests/xmconfigdata/test-fullvirt-serial-tcp.xml | 2 tests/xmconfigdata/test-fullvirt-serial-udp.xml | 2 tests/xmconfigdata/test-fullvirt-serial-unix.xml | 2 tests/xmconfigdata/test-fullvirt-sound.xml | 2 tests/xmconfigdata/test-fullvirt-usbmouse.xml | 2 tests/xmconfigdata/test-fullvirt-usbtablet.xml | 2 tests/xmconfigdata/test-fullvirt-utc.xml | 2 tests/xmconfigdata/test-paravirt-net-e1000.xml | 3 tests/xmconfigdata/test-paravirt-new-pvfb.xml | 3 tests/xmconfigdata/test-paravirt-old-pvfb.xml | 3 24 files changed, 543 insertions(+), 401 deletions(-) Daniel diff -r ee609596fc5a src/xend_internal.c --- a/src/xend_internal.c Mon Jul 07 11:40:09 2008 +0100 +++ b/src/xend_internal.c Mon Jul 07 11:40:15 2008 +0100 @@ -820,68 +820,6 @@ cur = dupe + strlen(model); } return 0; -} - -/** - * sound_string_to_xml: - * @soundstr : soundhw string for the form m1,m2,m3 ... - * - * Parses the passed string and returns a heap allocated string containing - * the valid libvirt soundxml. Must be free'd by caller. - * - * Returns NULL on fail, xml string on success (can be the empty string). - */ -char *sound_string_to_xml(const char *sound) { - - virBuffer buf = VIR_BUFFER_INITIALIZER; - char *tmp; - - while (sound) { - int modelsize, valid, collision = 0; - char *model = NULL; - char *model_end = strchr(sound, ','); - modelsize = (model_end ? (model_end - sound) : strlen(sound)); - - if(!(model = strndup(sound, modelsize))) - goto error; - - if (!(valid = is_sound_model_valid(model))) { - // Check for magic 'all' model. If found, throw out current xml - // and build with all available models - if (STREQ(model, "all")) { - int i; - if (virBufferError(&buf)) { - VIR_FREE(model); - goto error; - } - tmp = virBufferContentAndReset(&buf); - VIR_FREE(tmp); - - for (i=0; i < sizeof(sound_models)/sizeof(*sound_models); ++i) - virBufferVSprintf(&buf, " <sound model='%s'/>\n", - sound_models[i]); - VIR_FREE(model); - break; - } - } - - if (valid && model_end) - collision = is_sound_model_conflict(model, model_end); - if (valid && !collision) - virBufferVSprintf(&buf, " <sound model='%s'/>\n", model); - - sound = (model_end ? ++model_end : NULL); - VIR_FREE(model); - } - - if (virBufferError(&buf)) - goto error; - return virBufferContentAndReset(&buf); - - error: - tmp = virBufferContentAndReset(&buf); - VIR_FREE(tmp); - return NULL; } @@ -1538,7 +1476,7 @@ return ret; } -static virDomainChrDefPtr +virDomainChrDefPtr xenDaemonParseSxprChar(virConnectPtr conn, const char *value, const char *tty) @@ -1945,7 +1883,8 @@ return -1; } -static int + +int xenDaemonParseSxprSound(virConnectPtr conn, virDomainDefPtr def, const char *str) diff -r ee609596fc5a src/xend_internal.h --- a/src/xend_internal.h Mon Jul 07 11:40:09 2008 +0100 +++ b/src/xend_internal.h Mon Jul 07 11:40:15 2008 +0100 @@ -103,6 +103,16 @@ xenDaemonParseSxprString(virConnectPtr conn, const char *sexpr, int xendConfigVersion); + +int +xenDaemonParseSxprSound(virConnectPtr conn, + virDomainDefPtr def, + const char *str); +virDomainChrDefPtr +xenDaemonParseSxprChar(virConnectPtr conn, + const char *value, + const char *tty); + char * xenDaemonFormatSxpr(virConnectPtr conn, virDomainDefPtr def, @@ -110,7 +120,6 @@ int is_sound_model_valid(const char *model); int is_sound_model_conflict(const char *model, const char *soundstr); - char *sound_string_to_xml(const char *sound); /* refactored ones */ diff -r ee609596fc5a src/xm_internal.c --- a/src/xm_internal.c Mon Jul 07 11:40:09 2008 +0100 +++ b/src/xm_internal.c Mon Jul 07 11:40:15 2008 +0100 @@ -57,6 +57,8 @@ static int xenXMConfigSetString(virConfPtr conf, const char *setting, const char *str); +static int xenXMDiskCompare(virDomainDiskDefPtr a, + virDomainDiskDefPtr b); typedef struct xenXMConfCache *xenXMConfCachePtr; typedef struct xenXMConfCache { @@ -129,16 +131,23 @@ }; static void -xenXMError(virConnectPtr conn, virErrorNumber error, const char *info) +xenXMError(virConnectPtr conn, int code, const char *fmt, ...) { - const char *errmsg; + va_list args; + char errorMessage[1024]; + const char *virerr; - if (error == VIR_ERR_OK) - return; + if (fmt) { + va_start(args, fmt); + vsnprintf(errorMessage, sizeof(errorMessage)-1, fmt, args); + va_end(args); + } else { + errorMessage[0] = '\0'; + } - errmsg = __virErrorMsg(error, info); - __virRaiseError(conn, NULL, NULL, VIR_FROM_XENXM, error, VIR_ERR_ERROR, - errmsg, info, NULL, 0, 0, errmsg, info); + virerr = __virErrorMsg(code, (errorMessage[0] ? errorMessage : NULL)); + __virRaiseError(conn, NULL, NULL, VIR_FROM_XENXM, code, VIR_ERR_ERROR, + virerr, errorMessage, NULL, -1, -1, virerr, errorMessage); } int @@ -165,47 +174,149 @@ /* Convenience method to grab a int from the config file object */ -static int xenXMConfigGetInt(virConfPtr conf, const char *name, long *value) { +static int xenXMConfigGetBool(virConnectPtr conn, + virConfPtr conf, + const char *name, + int *value, + int def) { virConfValuePtr val; - if (!value || !name || !conf) - return (-1); + *value = 0; if (!(val = virConfGetValue(conf, name))) { - return (-1); + *value = def; + return 0; + } + + if (val->type == VIR_CONF_LONG) { + *value = val->l ? 1 : 0; + } else if (val->type == VIR_CONF_STRING) { + if (!val->str) { + *value = def; + } + *value = STREQ(val->str, "1") ? 1 : 0; + } else { + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("config value %s was malformed"), name); + return -1; + } + return 0; +} + + +/* Convenience method to grab a int from the config file object */ +static int xenXMConfigGetULong(virConnectPtr conn, + virConfPtr conf, + const char *name, + unsigned long *value, + int def) { + virConfValuePtr val; + + *value = 0; + if (!(val = virConfGetValue(conf, name))) { + *value = def; + return 0; } if (val->type == VIR_CONF_LONG) { *value = val->l; } else if (val->type == VIR_CONF_STRING) { char *ret; - if (!val->str) - return (-1); + if (!val->str) { + *value = def; + } *value = strtol(val->str, &ret, 10); - if (ret == val->str) - return (-1); + if (ret == val->str) { + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("config value %s was malformed"), name); + return -1; + } } else { - return (-1); + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("config value %s was malformed"), name); + return -1; } - return (0); + return 0; } /* Convenience method to grab a string from the config file object */ -static int xenXMConfigGetString(virConfPtr conf, const char *name, const char **value) { +static int xenXMConfigGetString(virConnectPtr conn, + virConfPtr conf, + const char *name, + const char **value, + const char *def) { virConfValuePtr val; - if (!value || !name || !conf) - return (-1); + *value = NULL; if (!(val = virConfGetValue(conf, name))) { - return (-1); + *value = def; + return 0; } - if (val->type != VIR_CONF_STRING) - return (-1); + + if (val->type != VIR_CONF_STRING) { + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("config value %s was malformed"), name); + return -1; + } if (!val->str) - return (-1); - *value = val->str; - return (0); + *value = def; + else + *value = val->str; + return 0; } + +static int xenXMConfigCopyStringInternal(virConnectPtr conn, + virConfPtr conf, + const char *name, + char **value, + int allowMissing) { + virConfValuePtr val; + + *value = NULL; + if (!(val = virConfGetValue(conf, name))) { + if (allowMissing) + return 0; + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("config value %s was missing"), name); + return -1; + } + + if (val->type != VIR_CONF_STRING) { + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("config value %s was not a string"), name); + return -1; + } + if (!val->str) { + if (allowMissing) + return 0; + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("config value %s was missing"), name); + return -1; + } + + if (!(*value = strdup(val->str))) { + xenXMError(conn, VIR_ERR_NO_MEMORY, NULL); + return -1; + } + + return 0; +} + + +static int xenXMConfigCopyString(virConnectPtr conn, + virConfPtr conf, + const char *name, + char **value) { + return xenXMConfigCopyStringInternal(conn, conf, name, value, 0); +} + +static int xenXMConfigCopyStringOpt(virConnectPtr conn, + virConfPtr conf, + const char *name, + char **value) { + return xenXMConfigCopyStringInternal(conn, conf, name, value, 1); +} + /* Convenience method to grab a string UUID from the config file object */ static int xenXMConfigGetUUID(virConfPtr conf, const char *name, unsigned char *uuid) { @@ -495,167 +606,163 @@ */ virDomainDefPtr xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - const char *name; - unsigned char uuid[VIR_UUID_BUFLEN]; - char uuidstr[VIR_UUID_STRING_BUFLEN]; const char *str; int hvm = 0; - long val; + int val; virConfValuePtr list; - int vnc = 0, sdl = 0; - char vfb[MAX_VFB]; - long vncdisplay; - long vncunused = 1; - const char *vnclisten = NULL; - const char *vncpasswd = NULL; - const char *keymap = NULL; xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData; virDomainDefPtr def = NULL; - char *xml; + virDomainDiskDefPtr disk = NULL; + virDomainNetDefPtr net = NULL; + virDomainGraphicsDefPtr graphics = NULL; + int i; - if (xenXMConfigGetString(conf, "name", &name) < 0) - return (NULL); - if (xenXMConfigGetUUID(conf, "uuid", uuid) < 0) - return (NULL); + if (VIR_ALLOC(def) < 0) + return NULL; - virBufferAddLit(&buf, "<domain type='xen'>\n"); - virBufferEscapeString(&buf, " <name>%s</name>\n", name); - virUUIDFormat(uuid, uuidstr); - virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr); + def->virtType = VIR_DOMAIN_VIRT_XEN; + def->id = -1; - if ((xenXMConfigGetString(conf, "builder", &str) == 0) && + if (xenXMConfigCopyString(conn, conf, "name", &def->name) < 0) + goto cleanup; + if (xenXMConfigGetUUID(conf, "uuid", def->uuid) < 0) + goto cleanup; + + + if ((xenXMConfigGetString(conn, conf, "builder", &str, "linux") == 0) && STREQ(str, "hvm")) hvm = 1; + if (!(def->os.type = strdup(hvm ? "hvm" : "xen"))) + goto no_memory; + if (hvm) { const char *boot; - virBufferAddLit(&buf, " <os>\n"); - virBufferAddLit(&buf, " <type>hvm</type>\n"); - if (xenXMConfigGetString(conf, "kernel", &str) == 0) - virBufferEscapeString(&buf, " <loader>%s</loader>\n", str); + if (xenXMConfigCopyString(conn, conf, "kernel", &def->os.loader) < 0) + goto cleanup; - if (xenXMConfigGetString(conf, "boot", &boot) < 0) - boot = "c"; + if (xenXMConfigGetString(conn, conf, "boot", &boot, "c") < 0) + goto cleanup; - while (*boot) { - const char *dev; + for (i = 0 ; i < VIR_DOMAIN_BOOT_LAST && boot[i] ; i++) { switch (*boot) { case 'a': - dev = "fd"; + def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY; break; case 'd': - dev = "cdrom"; + def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM; + break; + case 'n': + def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET; break; case 'c': default: - dev = "hd"; + def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK; break; } - virBufferVSprintf(&buf, " <boot dev='%s'/>\n", dev); - boot++; + def->os.nBootDevs++; } + } else { + if (xenXMConfigCopyStringOpt(conn, conf, "bootloader", &def->os.bootloader) < 0) + goto cleanup; + if (xenXMConfigCopyStringOpt(conn, conf, "bootargs", &def->os.bootloaderArgs) < 0) + goto cleanup; - virBufferAddLit(&buf, " </os>\n"); - } else { - - if (xenXMConfigGetString(conf, "bootloader", &str) == 0) - virBufferEscapeString(&buf, " <bootloader>%s</bootloader>\n", str); - if (xenXMConfigGetString(conf, "bootargs", &str) == 0) - virBufferEscapeString(&buf, " <bootloader_args>%s</bootloader_args>\n", str); - if (xenXMConfigGetString(conf, "kernel", &str) == 0) { - virBufferAddLit(&buf, " <os>\n"); - virBufferAddLit(&buf, " <type>linux</type>\n"); - virBufferEscapeString(&buf, " <kernel>%s</kernel>\n", str); - if (xenXMConfigGetString(conf, "ramdisk", &str) == 0) - virBufferEscapeString(&buf, " <initrd>%s</initrd>\n", str); - if (xenXMConfigGetString(conf, "extra", &str) == 0) - virBufferEscapeString(&buf, " <cmdline>%s</cmdline>\n", str); - virBufferAddLit(&buf, " </os>\n"); - } + if (xenXMConfigCopyStringOpt(conn, conf, "kernel", &def->os.kernel) < 0) + goto cleanup; + if (xenXMConfigCopyStringOpt(conn, conf, "ramdisk", &def->os.initrd) < 0) + goto cleanup; + if (xenXMConfigCopyStringOpt(conn, conf, "extra", &def->os.cmdline) < 0) + goto cleanup; } - if (xenXMConfigGetInt(conf, "memory", &val) < 0) - val = MIN_XEN_GUEST_SIZE * 2; - virBufferVSprintf(&buf, " <currentMemory>%ld</currentMemory>\n", - val * 1024); + if (xenXMConfigGetULong(conn, conf, "memory", &def->memory, MIN_XEN_GUEST_SIZE * 2) < 0) + goto cleanup; - if (xenXMConfigGetInt(conf, "maxmem", &val) < 0) - if (xenXMConfigGetInt(conf, "memory", &val) < 0) - val = MIN_XEN_GUEST_SIZE * 2; - virBufferVSprintf(&buf, " <memory>%ld</memory>\n", val * 1024); + if (xenXMConfigGetULong(conn, conf, "maxmem", &def->maxmem, def->memory) < 0) + goto cleanup; - virBufferAddLit(&buf, " <vcpu"); - if (xenXMConfigGetString(conf, "cpus", &str) == 0) { - char *ranges; + def->memory *= 1024; + def->maxmem *= 1024; - ranges = virConvertCpuSet(conn, str, 0); - if (ranges != NULL) { - virBufferVSprintf(&buf, " cpuset='%s'", ranges); - VIR_FREE(ranges); - } else - virBufferVSprintf(&buf, " cpuset='%s'", str); + + if (xenXMConfigGetULong(conn, conf, "vcpus", &def->vcpus, 1) < 0) + goto cleanup; + + if (xenXMConfigGetString(conn, conf, "cpus", &str, NULL) < 0) + goto cleanup; + if (str) { + def->cpumasklen = 4096; + if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0) + goto no_memory; + + if (virDomainCpuSetParse(conn, &str, 0, + def->cpumask, def->cpumasklen) < 0) + goto cleanup; } - if (xenXMConfigGetInt(conf, "vcpus", &val) < 0) - val = 1; - virBufferVSprintf(&buf, ">%ld</vcpu>\n", val); - if (xenXMConfigGetString(conf, "on_poweroff", &str) < 0) - str = "destroy"; - virBufferVSprintf(&buf, " <on_poweroff>%s</on_poweroff>\n", str); - if (xenXMConfigGetString(conf, "on_reboot", &str) < 0) - str = "restart"; - virBufferVSprintf(&buf, " <on_reboot>%s</on_reboot>\n", str); + if (xenXMConfigGetString(conn, conf, "on_poweroff", &str, "destroy") < 0) + goto cleanup; + if ((def->onPoweroff = virDomainLifecycleTypeFromString(str)) < 0) { + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected value %s for on_poweroff"), str); + goto cleanup; + } - if (xenXMConfigGetString(conf, "on_crash", &str) < 0) - str = "restart"; - virBufferVSprintf(&buf, " <on_crash>%s</on_crash>\n", str); + if (xenXMConfigGetString(conn, conf, "on_reboot", &str, "restart") < 0) + goto cleanup; + if ((def->onReboot = virDomainLifecycleTypeFromString(str)) < 0) { + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected value %s for on_reboot"), str); + goto cleanup; + } + + if (xenXMConfigGetString(conn, conf, "on_crash", &str, "restart") < 0) + goto cleanup; + if ((def->onCrash = virDomainLifecycleTypeFromString(str)) < 0) { + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected value %s for on_crash"), str); + goto cleanup; + } + if (hvm) { - virBufferAddLit(&buf, " <features>\n"); - if (xenXMConfigGetInt(conf, "pae", &val) == 0 && - val) - virBufferAddLit(&buf, " <pae/>\n"); - if (xenXMConfigGetInt(conf, "acpi", &val) == 0 && - val) - virBufferAddLit(&buf, " <acpi/>\n"); - if (xenXMConfigGetInt(conf, "apic", &val) == 0 && - val) - virBufferAddLit(&buf, " <apic/>\n"); - virBufferAddLit(&buf, " </features>\n"); + if (xenXMConfigGetBool(conn, conf, "pae", &val, 0) < 0) + goto cleanup; + else if (val) + def->features |= (1 << VIR_DOMAIN_FEATURE_PAE); + if (xenXMConfigGetBool(conn, conf, "acpi", &val, 0) < 0) + goto cleanup; + else if (val) + def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI); + if (xenXMConfigGetBool(conn, conf, "apic", &val, 0) < 0) + goto cleanup; + else if (val) + def->features |= (1 << VIR_DOMAIN_FEATURE_APIC); - if (xenXMConfigGetInt(conf, "localtime", &val) < 0) - val = 0; - virBufferVSprintf(&buf, " <clock offset='%s'/>\n", val ? "localtime" : "utc"); - } + if (xenXMConfigGetBool(conn, conf, "localtime", &def->localtime, 0) < 0) + goto cleanup; - virBufferAddLit(&buf, " <devices>\n"); - - if (hvm) { - if (xenXMConfigGetString(conf, "device_model", &str) == 0) - virBufferEscapeString(&buf, " <emulator>%s</emulator>\n", str); + if (xenXMConfigCopyString(conn, conf, "device_model", &def->emulator) < 0) + goto cleanup; } list = virConfGetValue(conf, "disk"); if (list && list->type == VIR_CONF_LIST) { list = list->list; while (list) { - int block = 0; - int cdrom = 0; - char src[PATH_MAX]; - char dev[NAME_MAX]; - char drvName[NAME_MAX] = ""; - char drvType[NAME_MAX] = ""; char *head; char *offset; char *tmp, *tmp1; - const char *bus; if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) goto skipdisk; head = list->str; + + if (VIR_ALLOC(disk) < 0) + goto no_memory; /* * Disks have 3 components, SOURCE,DEST-DEVICE,MODE @@ -665,105 +772,143 @@ * The DEST-DEVICE is optionally post-fixed with disk type */ - /* Extract the source */ + /* Extract the source file path*/ if (!(offset = strchr(head, ',')) || offset[0] == '\0') goto skipdisk; if ((offset - head) >= (PATH_MAX-1)) goto skipdisk; - strncpy(src, head, (offset - head)); - src[(offset-head)] = '\0'; + if (VIR_ALLOC_N(disk->src, (offset - head) + 1) < 0) + goto no_memory; + strncpy(disk->src, head, (offset - head)); + disk->src[(offset-head)] = '\0'; head = offset + 1; - /* Extract the dest */ + /* Remove legacy ioemu: junk */ + if (STRPREFIX(head, "ioemu:")) + head = head + 6; + + /* Extract the dest device name */ if (!(offset = strchr(head, ',')) || offset[0] == '\0') goto skipdisk; - if ((offset - head) >= (PATH_MAX-1)) - goto skipdisk; - strncpy(dev, head, (offset - head)); - dev[(offset-head)] = '\0'; + if (VIR_ALLOC_N(disk->dst, (offset - head) + 1) < 0) + goto no_memory; + strncpy(disk->dst, head, (offset - head)); + disk->dst[(offset-head)] = '\0'; head = offset + 1; /* Extract source driver type */ - if (!src[0]) { - strcpy(drvName, "phy"); - tmp = &src[0]; - } else if ((tmp = strchr(src, ':')) != NULL) { - strncpy(drvName, src, (tmp-src)); - drvName[tmp-src] = '\0'; + if (disk->src && + (tmp = strchr(disk->src, ':')) != NULL) { + if (VIR_ALLOC_N(disk->driverName, (tmp - disk->src) + 1) < 0) + goto no_memory; + strncpy(disk->driverName, disk->src, (tmp - disk->src)); + disk->driverName[tmp - disk->src] = '\0'; + } else { + if (!(disk->driverName = strdup("phy"))) + goto no_memory; + tmp = disk->src; } /* And the source driver sub-type */ - if (STRPREFIX(drvName, "tap")) { + if (STRPREFIX(disk->driverName, "tap")) { if (!(tmp1 = strchr(tmp+1, ':')) || !tmp1[0]) goto skipdisk; - strncpy(drvType, tmp+1, (tmp1-(tmp+1))); - memmove(src, src+(tmp1-src)+1, strlen(src)-(tmp1-src)); + if (VIR_ALLOC_N(disk->driverType, (tmp1-(tmp+1))) < 0) + goto no_memory; + strncpy(disk->driverType, tmp+1, (tmp1-(tmp+1))); + memmove(disk->src, disk->src+(tmp1-disk->src)+1, strlen(disk->src)-(tmp1-disk->src)); } else { - drvType[0] = '\0'; - if (src[0] && tmp) - memmove(src, src+(tmp-src)+1, strlen(src)-(tmp-src)); + disk->driverType = NULL; + if (disk->src[0] && tmp) + memmove(disk->src, disk->src+(tmp-disk->src)+1, strlen(disk->src)-(tmp-disk->src)); } /* phy: type indicates a block device */ - if (STREQ(drvName, "phy")) { - block = 1; - } - - /* Remove legacy ioemu: junk */ - if (STRPREFIX(dev, "ioemu:")) { - memmove(dev, dev+6, strlen(dev)-5); - } + disk->type = STREQ(disk->driverName, "phy") ? + VIR_DOMAIN_DISK_TYPE_BLOCK : VIR_DOMAIN_DISK_TYPE_FILE; /* Check for a :cdrom/:disk postfix */ - if ((tmp = strchr(dev, ':')) != NULL) { + disk->device = VIR_DOMAIN_DISK_DEVICE_DISK; + if ((tmp = strchr(disk->dst, ':')) != NULL) { if (STREQ(tmp, ":cdrom")) - cdrom = 1; + disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; tmp[0] = '\0'; } - if (STRPREFIX(dev, "xvd") || !hvm) { - bus = "xen"; - } else if (STRPREFIX(dev, "sd")) { - bus = "scsi"; + if (STRPREFIX(disk->dst, "xvd") || !hvm) { + disk->bus = VIR_DOMAIN_DISK_BUS_XEN; + } else if (STRPREFIX(disk->dst, "sd")) { + disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; } else { - bus = "ide"; + disk->bus = VIR_DOMAIN_DISK_BUS_IDE; } - virBufferVSprintf(&buf, " <disk type='%s' device='%s'>\n", - block ? "block" : "file", - cdrom ? "cdrom" : "disk"); - if (drvType[0]) - virBufferVSprintf(&buf, " <driver name='%s' type='%s'/>\n", drvName, drvType); - else - virBufferVSprintf(&buf, " <driver name='%s'/>\n", drvName); - if (src[0]) { - virBufferVSprintf(&buf, " <source %s=", block ? "dev" : "file"); - virBufferEscapeString(&buf, "'%s'/>\n", src); - } - virBufferEscapeString(&buf, " <target dev='%s'", dev); - virBufferVSprintf(&buf, " bus='%s'/>\n", bus); if (STREQ(head, "r") || STREQ(head, "ro")) - virBufferAddLit(&buf, " <readonly/>\n"); + disk->readonly = 1; else if ((STREQ(head, "w!")) || (STREQ(head, "!"))) - virBufferAddLit(&buf, " <shareable/>\n"); - virBufferAddLit(&buf, " </disk>\n"); + disk->shared = 1; - skipdisk: + /* Maintain list in sorted order according to target device name */ + if (def->disks == NULL) { + disk->next = def->disks; + def->disks = disk; + } else { + virDomainDiskDefPtr ptr = def->disks; + while (ptr) { + if (!ptr->next || xenXMDiskCompare(disk, ptr->next) < 0) { + disk->next = ptr->next; + ptr->next = disk; + break; + } + ptr = ptr->next; + } + } + disk = NULL; + + skipdisk: list = list->next; + virDomainDiskDefFree(disk); } } if (hvm && priv->xendConfigVersion == 1) { - if (xenXMConfigGetString(conf, "cdrom", &str) == 0) { - virBufferAddLit(&buf, " <disk type='file' device='cdrom'>\n"); - virBufferAddLit(&buf, " <driver name='file'/>\n"); - virBufferEscapeString(&buf, " <source file='%s'/>\n", str); - virBufferAddLit(&buf, " <target dev='hdc' bus='ide'/>\n"); - virBufferAddLit(&buf, " <readonly/>\n"); - virBufferAddLit(&buf, " </disk>\n"); + if (xenXMConfigGetString(conn, conf, "cdrom", &str, NULL) < 0) + goto cleanup; + if (str) { + if (VIR_ALLOC(disk) < 0) + goto no_memory; + + disk->type = VIR_DOMAIN_DISK_TYPE_FILE; + disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; + if (!(disk->driverName = strdup("file"))) + goto no_memory; + if (!(disk->src = strdup(str))) + goto no_memory; + if (!(disk->dst = strdup("hdc"))) + goto no_memory; + disk->bus = VIR_DOMAIN_DISK_BUS_IDE; + disk->readonly = 1; + + + /* Maintain list in sorted order according to target device name */ + if (def->disks == NULL) { + disk->next = def->disks; + def->disks = disk; + } else { + virDomainDiskDefPtr ptr = def->disks; + while (ptr) { + if (!ptr->next || xenXMDiskCompare(disk, ptr->next) < 0) { + disk->next = ptr->next; + ptr->next = disk; + break; + } + ptr = ptr->next; + } + } + disk = NULL; } } @@ -842,62 +987,143 @@ type = 1; } - virBufferAddLit(&buf, " <interface type='bridge'>\n"); - if (mac[0]) - virBufferVSprintf(&buf, " <mac address='%s'/>\n", mac); - if (type == 1 && bridge[0]) - virBufferVSprintf(&buf, " <source bridge='%s'/>\n", bridge); - if (script[0]) - virBufferEscapeString(&buf, " <script path='%s'/>\n", script); - if (ip[0]) - virBufferVSprintf(&buf, " <ip address='%s'/>\n", ip); - if (model[0]) - virBufferVSprintf(&buf, " <model type='%s'/>\n", model); - virBufferAddLit(&buf, " </interface>\n"); + if (VIR_ALLOC(net) < 0) + goto cleanup; + + if (mac[0]) { + unsigned int rawmac[6]; + sscanf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", + (unsigned int*)&rawmac[0], + (unsigned int*)&rawmac[1], + (unsigned int*)&rawmac[2], + (unsigned int*)&rawmac[3], + (unsigned int*)&rawmac[4], + (unsigned int*)&rawmac[5]); + net->mac[0] = rawmac[0]; + net->mac[1] = rawmac[1]; + net->mac[2] = rawmac[2]; + net->mac[3] = rawmac[3]; + net->mac[4] = rawmac[4]; + net->mac[5] = rawmac[5]; + } + + if (bridge[0] || STREQ(script, "vif-bridge")) + net->type = VIR_DOMAIN_NET_TYPE_BRIDGE; + else + net->type = VIR_DOMAIN_NET_TYPE_ETHERNET; + + if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { + if (bridge[0] && + !(net->data.bridge.brname = strdup(bridge))) + goto no_memory; + } else { + if (script[0] && + !(net->data.ethernet.script = strdup(script))) + goto no_memory; + if (ip[0] && + !(net->data.ethernet.ipaddr = strdup(ip))) + goto no_memory; + } + if (model[0] && + !(net->model = strdup(model))) + goto no_memory; + + if (!def->nets) { + net->next = NULL; + def->nets = net; + } else { + virDomainNetDefPtr ptr = def->nets; + while (ptr->next) + ptr = ptr->next; + ptr->next = net; + } + net = NULL; skipnic: list = list->next; + virDomainNetDefFree(net); } } if (hvm) { - if (xenXMConfigGetString(conf, "usbdevice", &str) == 0 && str) { - if (STREQ(str, "tablet")) - virBufferAddLit(&buf, " <input type='tablet' bus='usb'/>\n"); - else if (STREQ(str, "mouse")) - virBufferAddLit(&buf, " <input type='mouse' bus='usb'/>\n"); - /* Ignore else branch - probably some other non-input device we don't - support in libvirt yet */ + if (xenXMConfigGetString(conn, conf, "usbdevice", &str, NULL) < 0) + goto cleanup; + if (str && + (STREQ(str, "tablet") || + STREQ(str, "mouse"))) { + virDomainInputDefPtr input; + if (VIR_ALLOC(input) < 0) + goto no_memory; + input->bus = VIR_DOMAIN_INPUT_BUS_USB; + input->type = STREQ(str, "tablet") ? + VIR_DOMAIN_INPUT_TYPE_TABLET : + VIR_DOMAIN_INPUT_TYPE_MOUSE; + def->inputs = input; } } /* HVM guests, or old PV guests use this config format */ if (hvm || priv->xendConfigVersion < 3) { - if (xenXMConfigGetInt(conf, "vnc", &val) == 0 && val) { - vnc = 1; - if (xenXMConfigGetInt(conf, "vncunused", &vncunused) < 0) - vncunused = 1; - if (xenXMConfigGetInt(conf, "vncdisplay", &vncdisplay) < 0) - vncdisplay = 0; - if (xenXMConfigGetString(conf, "vnclisten", &vnclisten) < 0) - vnclisten = NULL; - if (xenXMConfigGetString(conf, "vncpasswd", &vncpasswd) < 0) - vncpasswd = NULL; - if (xenXMConfigGetString(conf, "keymap", &keymap) < 0) - keymap = NULL; + if (xenXMConfigGetBool(conn, conf, "vnc", &val, 0) < 0) + goto cleanup; + + if (val) { + if (VIR_ALLOC(graphics) < 0) + goto no_memory; + graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC; + if (xenXMConfigGetBool(conn, conf, "vncunused", &val, 1) < 0) + goto cleanup; + graphics->data.vnc.autoport = val ? 1 : 0; + + if (!graphics->data.vnc.autoport) { + unsigned long vncdisplay; + if (xenXMConfigGetULong(conn, conf, "vncdisplay", &vncdisplay, 0) < 0) + goto cleanup; + graphics->data.vnc.port = (int)vncdisplay + 5900; + } + if (xenXMConfigCopyStringOpt(conn, conf, "vnclisten", &graphics->data.vnc.listenAddr) < 0) + goto cleanup; + if (xenXMConfigCopyStringOpt(conn, conf, "vncpasswd", &graphics->data.vnc.passwd) < 0) + goto cleanup; + if (xenXMConfigCopyStringOpt(conn, conf, "keymap", &graphics->data.vnc.keymap) < 0) + goto cleanup; + + def->graphics = graphics; + graphics = NULL; + } else { + if (xenXMConfigGetBool(conn, conf, "sdl", &val, 0) < 0) + goto cleanup; + if (val) { + if (VIR_ALLOC(graphics) < 0) + goto no_memory; + graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL; + if (xenXMConfigCopyStringOpt(conn, conf, "display", &graphics->data.sdl.display) < 0) + goto cleanup; + if (xenXMConfigCopyStringOpt(conn, conf, "xauthority", &graphics->data.sdl.xauth) < 0) + goto cleanup; + def->graphics = graphics; + graphics = NULL; + } } - if (xenXMConfigGetInt(conf, "sdl", &val) == 0 && val) - sdl = 1; } - if (!hvm && !sdl && !vnc) { /* New PV guests use this format */ + + if (!hvm && def->graphics == NULL) { /* New PV guests use this format */ list = virConfGetValue(conf, "vfb"); if (list && list->type == VIR_CONF_LIST && list->list && list->list->type == VIR_CONF_STRING && list->list->str) { - + char vfb[MAX_VFB]; char *key = vfb; strncpy(vfb, list->list->str, MAX_VFB-1); vfb[MAX_VFB-1] = '\0'; + + if (VIR_ALLOC(graphics) < 0) + goto no_memory; + + if (strstr(key, "type=sdl")) + graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL; + else + graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC; while (key) { char *data; @@ -912,20 +1138,30 @@ break; data++; - if (STRPREFIX(key, "type=sdl")) { - sdl = 1; - } else if (STRPREFIX(key, "type=vnc")) { - vnc = 1; - } else if (STRPREFIX(key, "vncunused=")) { - vncunused = strtol(key+10, NULL, 10); - } else if (STRPREFIX(key, "vnclisten=")) { - vnclisten = key + 10; - } else if (STRPREFIX(key, "vncpasswd=")) { - vncpasswd = key + 10; - } else if (STRPREFIX(key, "keymap=")) { - keymap = key + 7; - } else if (STRPREFIX(key, "vncdisplay=")) { - vncdisplay = strtol(key+11, NULL, 10); + if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { + if (STRPREFIX(key, "vncunused=")) { + if (STREQ(key + 10, "1")) + graphics->data.vnc.autoport = 1; + } else if (STRPREFIX(key, "vnclisten=")) { + if (!(graphics->data.vnc.listenAddr = strdup(key + 10))) + goto no_memory; + } else if (STRPREFIX(key, "vncpasswd=")) { + if (!(graphics->data.vnc.passwd = strdup(key + 10))) + goto no_memory; + } else if (STRPREFIX(key, "keymap=")) { + if (!(graphics->data.vnc.keymap = strdup(key + 7))) + goto no_memory; + } else if (STRPREFIX(key, "vncdisplay=")) { + graphics->data.vnc.port = strtol(key+11, NULL, 10) + 5900; + } + } else { + if (STRPREFIX(key, "display=")) { + if (!(graphics->data.sdl.display = strdup(key + 8))) + goto no_memory; + } else if (STRPREFIX(key, "xauthority=")) { + if (!(graphics->data.sdl.xauth = strdup(key + 11))) + goto no_memory; + } } while (nextkey && (nextkey[0] == ',' || @@ -934,86 +1170,47 @@ nextkey++; key = nextkey; } + def->graphics = graphics; + graphics = NULL; } } - if (vnc || sdl) { - virBufferVSprintf(&buf, " <input type='mouse' bus='%s'/>\n", hvm ? "ps2":"xen"); - } - if (vnc) { - virBufferVSprintf(&buf, - " <graphics type='vnc' port='%ld'", - (vncunused ? -1 : 5900+vncdisplay)); - if (vnclisten) { - virBufferVSprintf(&buf, " listen='%s'", vnclisten); - } - if (vncpasswd) { - virBufferEscapeString(&buf, " passwd='%s'", vncpasswd); - } - if (keymap) { - virBufferEscapeString(&buf, " keymap='%s'", keymap); - } - virBufferAddLit(&buf, "/>\n"); - } - if (sdl) { - virBufferAddLit(&buf, " <graphics type='sdl'/>\n"); + if (hvm) { + if (xenXMConfigGetString(conn, conf, "parallel", &str, NULL) < 0) + goto cleanup; + if (str && STRNEQ(str, "none") && + !(def->parallels = xenDaemonParseSxprChar(conn, str, NULL))) + goto cleanup; + + if (xenXMConfigGetString(conn, conf, "serial", &str, NULL) < 0) + goto cleanup; + if (str && STRNEQ(str, "none") && + !(def->serials = xenDaemonParseSxprChar(conn, str, NULL))) + goto cleanup; + } else { + if (!(def->console = xenDaemonParseSxprChar(conn, "pty", NULL))) + goto cleanup; } if (hvm) { - if (xenXMConfigGetString(conf, "parallel", &str) == 0) { - if (STRNEQ(str, "none")) - xend_parse_sexp_desc_char(conn, &buf, "parallel", 0, str, NULL); - } - if (xenXMConfigGetString(conf, "serial", &str) == 0) { - if (STRNEQ(str, "none")) { - xend_parse_sexp_desc_char(conn, &buf, "serial", 0, str, NULL); - /* Add back-compat console tag for primary console */ - xend_parse_sexp_desc_char(conn, &buf, "console", 0, str, NULL); - } - } - } else { - /* Paravirt implicitly always has a single console */ - virBufferAddLit(&buf, " <console type='pty'>\n"); - virBufferAddLit(&buf, " <target port='0'/>\n"); - virBufferAddLit(&buf, " </console>\n"); + if (xenXMConfigGetString(conn, conf, "soundhw", &str, NULL) < 0) + goto cleanup; + + if (str && + xenDaemonParseSxprSound(conn, def, str) < 0) + goto cleanup; } - if (hvm) { - if ((xenXMConfigGetString(conf, "soundhw", &str) == 0) && str) { - char *soundxml; - if ((soundxml = sound_string_to_xml(str))) { - virBufferVSprintf(&buf, "%s", soundxml); - VIR_FREE(soundxml); - } else { - xenXMError(conn, VIR_ERR_INTERNAL_ERROR, - _("parsing soundhw string failed.")); - goto error; - } - } - } - - virBufferAddLit(&buf, " </devices>\n"); - - virBufferAddLit(&buf, "</domain>\n"); - - if (virBufferError(&buf)) { - xenXMError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer")); - goto error; - } - - xml = virBufferContentAndReset(&buf); - - if (!(def = virDomainDefParseString(conn, priv->caps, xml))) { - VIR_FREE(xml); - return NULL; - } - - VIR_FREE(xml); return def; - error: - str = virBufferContentAndReset(&buf); - VIR_FREE(str); +no_memory: + xenXMError(conn, VIR_ERR_NO_MEMORY, NULL); + /* fallthrough */ + cleanup: + virDomainGraphicsDefFree(graphics); + virDomainNetDefFree(net); + virDomainDiskDefFree(disk); + virDomainDefFree(def); return NULL; } diff -r ee609596fc5a tests/xmconfigdata/test-escape-paths.xml --- a/tests/xmconfigdata/test-escape-paths.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-escape-paths.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader&test</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-localtime.xml --- a/tests/xmconfigdata/test-fullvirt-localtime.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-localtime.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-new-cdrom.xml --- a/tests/xmconfigdata/test-fullvirt-new-cdrom.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-new-cdrom.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-old-cdrom.xml --- a/tests/xmconfigdata/test-fullvirt-old-cdrom.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-old-cdrom.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-parallel-tcp.xml --- a/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-serial-file.xml --- a/tests/xmconfigdata/test-fullvirt-serial-file.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-serial-file.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-serial-null.xml --- a/tests/xmconfigdata/test-fullvirt-serial-null.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-serial-null.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-serial-pipe.xml --- a/tests/xmconfigdata/test-fullvirt-serial-pipe.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-serial-pipe.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-serial-pty.xml --- a/tests/xmconfigdata/test-fullvirt-serial-pty.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-serial-pty.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-serial-stdio.xml --- a/tests/xmconfigdata/test-fullvirt-serial-stdio.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-serial-stdio.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml --- a/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-serial-tcp.xml --- a/tests/xmconfigdata/test-fullvirt-serial-tcp.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-serial-tcp.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-serial-udp.xml --- a/tests/xmconfigdata/test-fullvirt-serial-udp.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-serial-udp.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-serial-unix.xml --- a/tests/xmconfigdata/test-fullvirt-serial-unix.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-serial-unix.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-sound.xml --- a/tests/xmconfigdata/test-fullvirt-sound.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-sound.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-usbmouse.xml --- a/tests/xmconfigdata/test-fullvirt-usbmouse.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-usbmouse.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-usbtablet.xml --- a/tests/xmconfigdata/test-fullvirt-usbtablet.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-usbtablet.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-fullvirt-utc.xml --- a/tests/xmconfigdata/test-fullvirt-utc.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-utc.xml Mon Jul 07 11:40:15 2008 +0100 @@ -5,7 +5,7 @@ <currentMemory>403456</currentMemory> <vcpu>1</vcpu> <os> - <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type> <loader>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> diff -r ee609596fc5a tests/xmconfigdata/test-paravirt-net-e1000.xml --- a/tests/xmconfigdata/test-paravirt-net-e1000.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-paravirt-net-e1000.xml Mon Jul 07 11:40:15 2008 +0100 @@ -6,14 +6,13 @@ <vcpu>1</vcpu> <bootloader>/usr/bin/pygrub</bootloader> <os> - <type arch='i686' machine='xenpv'>linux</type> + <type>linux</type> </os> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <devices> - <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> <driver name='phy'/> <source dev='/dev/HostVG/XenGuest1'/> diff -r ee609596fc5a tests/xmconfigdata/test-paravirt-new-pvfb.xml --- a/tests/xmconfigdata/test-paravirt-new-pvfb.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-paravirt-new-pvfb.xml Mon Jul 07 11:40:15 2008 +0100 @@ -6,14 +6,13 @@ <vcpu>1</vcpu> <bootloader>/usr/bin/pygrub</bootloader> <os> - <type arch='i686' machine='xenpv'>linux</type> + <type>linux</type> </os> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <devices> - <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> <driver name='phy'/> <source dev='/dev/HostVG/XenGuest1'/> diff -r ee609596fc5a tests/xmconfigdata/test-paravirt-old-pvfb.xml --- a/tests/xmconfigdata/test-paravirt-old-pvfb.xml Mon Jul 07 11:40:09 2008 +0100 +++ b/tests/xmconfigdata/test-paravirt-old-pvfb.xml Mon Jul 07 11:40:15 2008 +0100 @@ -6,14 +6,13 @@ <vcpu>1</vcpu> <bootloader>/usr/bin/pygrub</bootloader> <os> - <type arch='i686' machine='xenpv'>linux</type> + <type>linux</type> </os> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <devices> - <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'> <driver name='phy'/> <source dev='/dev/HostVG/XenGuest1'/> -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Tue, Jul 08, 2008 at 05:41:01PM +0100, Daniel P. Berrange wrote:
This replaces the code which converts from virConfPtr objects into XML, with code which converts from virConfPtr objects straight into virDomainDefPtr objects. A few more XML changes are needed in the test suite to take account of better XML generation this produces [...] -/** - * sound_string_to_xml: - * @soundstr : soundhw string for the form m1,m2,m3 ...
okay the function which wasn't doing the check and got out of the way
-xenXMError(virConnectPtr conn, virErrorNumber error, const char *info) +xenXMError(virConnectPtr conn, int code, const char *fmt, ...)
cool improvement I didn't spot anything suspicious in the code. I was just expecting it to be a bit smaller, but the allocation of the virConfPtr and sub objects takes as much code as outputting the equivalent XML buf, to my surprise.
- <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type>
Hum the previous patch was changing things the way around ...
<devices> - <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'>
and removing the extra emulator All looks fine to me, +1 Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

On Thu, Jul 24, 2008 at 11:53:48AM -0400, Daniel Veillard wrote:
On Tue, Jul 08, 2008 at 05:41:01PM +0100, Daniel P. Berrange wrote:
This replaces the code which converts from virConfPtr objects into XML, with code which converts from virConfPtr objects straight into virDomainDefPtr objects. A few more XML changes are needed in the test suite to take account of better XML generation this produces [...] -/** - * sound_string_to_xml: - * @soundstr : soundhw string for the form m1,m2,m3 ...
okay the function which wasn't doing the check and got out of the way
-xenXMError(virConnectPtr conn, virErrorNumber error, const char *info) +xenXMError(virConnectPtr conn, int code, const char *fmt, ...)
cool improvement
I didn't spot anything suspicious in the code. I was just expecting it to be a bit smaller, but the allocation of the virConfPtr and sub objects takes as much code as outputting the equivalent XML buf, to my surprise.
Yes, it surprised me too. On the plus side though I think the new code is easier to read/follow, even if it is the same length
- <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type>
Hum the previous patch was changing things the way around ...
Yes that's odd - I'll investigate this.
<devices> - <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'>
and removing the extra emulator
Also unexpected. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Jul 24, 2008 at 06:03:24PM +0100, Daniel P. Berrange wrote:
On Thu, Jul 24, 2008 at 11:53:48AM -0400, Daniel Veillard wrote:
On Tue, Jul 08, 2008 at 05:41:01PM +0100, Daniel P. Berrange wrote:
This replaces the code which converts from virConfPtr objects into XML, with code which converts from virConfPtr objects straight into virDomainDefPtr objects. A few more XML changes are needed in the test suite to take account of better XML generation this produces [...] -/** - * sound_string_to_xml: - * @soundstr : soundhw string for the form m1,m2,m3 ...
okay the function which wasn't doing the check and got out of the way
-xenXMError(virConnectPtr conn, virErrorNumber error, const char *info) +xenXMError(virConnectPtr conn, int code, const char *fmt, ...)
cool improvement
I didn't spot anything suspicious in the code. I was just expecting it to be a bit smaller, but the allocation of the virConfPtr and sub objects takes as much code as outputting the equivalent XML buf, to my surprise.
Yes, it surprised me too. On the plus side though I think the new code is easier to read/follow, even if it is the same length
it's also deeper in the analysis of the strings passed back and forth, which explains the inflation, it's more thorough.
- <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type>
Hum the previous patch was changing things the way around ...
Yes that's odd - I'll investigate this.
<devices> - <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'>
and removing the extra emulator
Also unexpected.
Ah, i found something in the end :-) Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

On Thu, Jul 24, 2008 at 11:53:48AM -0400, Daniel Veillard wrote:
- <type arch='i686' machine='xenfv'>hvm</type> + <type>hvm</type>
Hum the previous patch was changing things the way around ...
<devices> - <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <disk type='block' device='disk'>
and removing the extra emulator
Yes were indeed both bugs - I'm fixing them as I commit, so there'll be no changes to test suite needed for this patch Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This completes the Xen driver work, replacing the code which converts from XML into virConfPtr objects, with code which converts from virDomainDefPtr into virConfPtr objects. The XML parsing is now fully handled by the generic routines. At this point, the xml.c file no longer contains any Xen specific code and is solely generic XML routines. src/xend_internal.c | 45 src/xend_internal.h | 9 src/xm_internal.c | 1288 +++++++++---------------- src/xm_internal.h | 3 src/xml.c | 288 ----- src/xml.h | 12 tests/xmconfigdata/test-fullvirt-usbmouse.cfg | 1 tests/xmconfigdata/test-fullvirt-usbtablet.cfg | 1 8 files changed, 527 insertions(+), 1120 deletions(-) Daniel diff -r 6f2488f348b8 src/xend_internal.c --- a/src/xend_internal.c Thu Jul 03 16:50:10 2008 +0100 +++ b/src/xend_internal.c Thu Jul 03 16:50:15 2008 +0100 @@ -4897,11 +4897,10 @@ return 0; } -static int +int xenDaemonFormatSxprChr(virConnectPtr conn, virDomainChrDefPtr def, - virBufferPtr buf, - const char *name) + virBufferPtr buf) { const char *type = virDomainChrTypeToString(def->type); @@ -4916,20 +4915,20 @@ case VIR_DOMAIN_CHR_TYPE_STDIO: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_PTY: - virBufferVSprintf(buf, "(%s %s)", name, type); + virBufferVSprintf(buf, "%s", type); break; case VIR_DOMAIN_CHR_TYPE_FILE: case VIR_DOMAIN_CHR_TYPE_PIPE: - virBufferVSprintf(buf, "(%s %s:%s)", name, type, def->data.file.path); + virBufferVSprintf(buf, "%s:%s", type, def->data.file.path); break; case VIR_DOMAIN_CHR_TYPE_DEV: - virBufferVSprintf(buf, "(%s %s)", name, def->data.file.path); + virBufferVSprintf(buf, "%s", def->data.file.path); break; case VIR_DOMAIN_CHR_TYPE_TCP: - virBufferVSprintf(buf, "(%s %s:%s:%s%s)", name, + virBufferVSprintf(buf, "%s:%s:%s%s", (def->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW ? "tcp" : "telnet"), (def->data.tcp.host ? def->data.tcp.host : ""), @@ -4938,7 +4937,7 @@ break; case VIR_DOMAIN_CHR_TYPE_UDP: - virBufferVSprintf(buf, "(%s %s:%s:%s@%s:%s)", name, type, + virBufferVSprintf(buf, "%s:%s:%s@%s:%s", type, (def->data.udp.connectHost ? def->data.udp.connectHost : ""), (def->data.udp.connectService ? def->data.udp.connectService : ""), (def->data.udp.bindHost ? def->data.udp.bindHost : ""), @@ -4946,7 +4945,7 @@ break; case VIR_DOMAIN_CHR_TYPE_UNIX: - virBufferVSprintf(buf, "(%s %s:%s%s)", name, type, + virBufferVSprintf(buf, "%s:%s%s", type, def->data.nix.path, def->data.nix.listen ? ",listen" : ""); break; @@ -5143,17 +5142,14 @@ return 0; } -static int +int xenDaemonFormatSxprSound(virConnectPtr conn, virDomainSoundDefPtr sound, virBufferPtr buf) { const char *str; virDomainSoundDefPtr prev = NULL; - if (!sound) - return 0; - - virBufferAddLit(buf, "(soundhw '"); + while (sound) { if (!(str = virDomainSoundModelTypeToString(sound->model))) { virXendError(conn, VIR_ERR_INTERNAL_ERROR, @@ -5165,7 +5161,6 @@ sound = sound->next; } - virBufferAddLit(buf, "')"); return 0; } @@ -5357,14 +5352,18 @@ } if (def->parallels) { - if (xenDaemonFormatSxprChr(conn, def->parallels, &buf, "parallel") < 0) - goto error; + virBufferAddLit(&buf, "(parallel "); + if (xenDaemonFormatSxprChr(conn, def->parallels, &buf) < 0) + goto error; + virBufferAddLit(&buf, ")"); } else { virBufferAddLit(&buf, "(parallel none)"); } if (def->serials) { - if (xenDaemonFormatSxprChr(conn, def->serials, &buf, "serial") < 0) - goto error; + virBufferAddLit(&buf, "(serial "); + if (xenDaemonFormatSxprChr(conn, def->serials, &buf) < 0) + goto error; + virBufferAddLit(&buf, ")"); } else { virBufferAddLit(&buf, "(serial none)"); } @@ -5372,8 +5371,12 @@ if (def->localtime) virBufferAddLit(&buf, "(localtime 1)"); - if (xenDaemonFormatSxprSound(conn, def->sounds, &buf) < 0) - goto error; + if (def->sounds) { + virBufferAddLit(&buf, "(soundhw '"); + if (xenDaemonFormatSxprSound(conn, def->sounds, &buf) < 0) + goto error; + virBufferAddLit(&buf, "')"); + } } /* get the device emulation model */ diff -r 6f2488f348b8 src/xend_internal.h --- a/src/xend_internal.h Thu Jul 03 16:50:10 2008 +0100 +++ b/src/xend_internal.h Thu Jul 03 16:50:15 2008 +0100 @@ -112,6 +112,15 @@ xenDaemonParseSxprChar(virConnectPtr conn, const char *value, const char *tty); + +int +xenDaemonFormatSxprChr(virConnectPtr conn, + virDomainChrDefPtr def, + virBufferPtr buf); +int +xenDaemonFormatSxprSound(virConnectPtr conn, + virDomainSoundDefPtr sound, + virBufferPtr buf); char * xenDaemonFormatSxpr(virConnectPtr conn, diff -r 6f2488f348b8 src/xm_internal.c --- a/src/xm_internal.c Thu Jul 03 16:50:10 2008 +0100 +++ b/src/xm_internal.c Thu Jul 03 16:50:15 2008 +0100 @@ -36,20 +36,10 @@ #include <stdint.h> #include <xen/dom0_ops.h> -#include <libxml/parser.h> -#include <libxml/tree.h> -#include <libxml/xpath.h> - -#ifndef NAME_MAX -#define NAME_MAX 255 -#endif - +#include "xm_internal.h" #include "xen_unified.h" -#include "xm_internal.h" #include "xend_internal.h" #include "hash.h" -#include "internal.h" -#include "xml.h" #include "buf.h" #include "uuid.h" #include "util.h" @@ -1653,829 +1643,533 @@ } -/* - * Convenience method to set an int config param - * based on an XPath expression - */ -static -int xenXMConfigSetIntFromXPath(virConnectPtr conn, - virConfPtr conf, xmlXPathContextPtr ctxt, - const char *setting, const char *xpath, - long scale, int allowMissing, const char *error) { - xmlXPathObjectPtr obj; - long intval; - char *strend; - int ret = -1; +static int xenXMDomainConfigFormatDisk(virConnectPtr conn, + virConfValuePtr list, + virDomainDiskDefPtr disk, + int hvm, + int xendConfigVersion) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + virConfValuePtr val, tmp; + char *str; - obj = xmlXPathEval(BAD_CAST xpath, ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - if (allowMissing) - ret = 0; - else - xenXMError(conn, VIR_ERR_XML_ERROR, error); - goto error; + if(disk->src) { + if (disk->driverName) { + virBufferVSprintf(&buf, "%s:", disk->driverName); + if (STREQ(disk->driverName, "tap")) + virBufferVSprintf(&buf, "%s:", disk->driverType ? disk->driverType : "aio"); + } else { + virBufferVSprintf(&buf, "%s:", + disk->type == VIR_DOMAIN_DISK_TYPE_FILE ? + "file" : "phy"); + } + virBufferVSprintf(&buf, "%s", disk->src); + } + virBufferAddLit(&buf, ","); + if (hvm && xendConfigVersion == 1) + virBufferAddLit(&buf, "ioemu:"); + + virBufferVSprintf(&buf, "%s", disk->dst); + if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) + virBufferAddLit(&buf, ":cdrom"); + + if (disk->readonly) + virBufferAddLit(&buf, ",r"); + else if (disk->shared) + virBufferAddLit(&buf, ",!"); + else + virBufferAddLit(&buf, ",w"); + + if (virBufferError(&buf)) { + xenXMError(conn, VIR_ERR_NO_MEMORY, NULL); + return -1; } - intval = strtol((char *)obj->stringval, &strend, 10); - if (strend == (char *)obj->stringval) { - xenXMError(conn, VIR_ERR_XML_ERROR, error); - goto error; - } - - if (scale > 0) - intval = intval * scale; - else if (scale < 0) - intval = intval / (-1*scale); - - if (xenXMConfigSetInt(conf, setting, intval) < 0) - goto error; - - ret = 0; - - error: - xmlXPathFreeObject(obj); - - return ret; -} - -/* - * Convenience method to set a string param - * based on an XPath expression - */ -static -int xenXMConfigSetStringFromXPath(virConnectPtr conn, - virConfPtr conf, xmlXPathContextPtr ctxt, - const char *setting, const char *xpath, - int allowMissing, const char *error) { - xmlXPathObjectPtr obj; - int ret = -1; - - obj = xmlXPathEval(BAD_CAST xpath, ctxt); - - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - if (allowMissing) - ret = 0; - else - xenXMError(conn, VIR_ERR_XML_ERROR, error); - goto error; - } - - if (xenXMConfigSetString(conf, setting, (const char *)obj->stringval) < 0) - goto error; - - ret = 0; - - error: - xmlXPathFreeObject(obj); - - return ret; -} - -static int xenXMParseXMLDisk(xmlNodePtr node, int hvm, int xendConfigVersion, char **disk) { - xmlNodePtr cur; - xmlChar *type = NULL; - xmlChar *device = NULL; - xmlChar *source = NULL; - xmlChar *target = NULL; - xmlChar *drvName = NULL; - xmlChar *drvType = NULL; - int readonly = 0; - int shareable = 0; - int typ = 0; - int cdrom = 0; - int ret = -1; - int buflen = 0; - char *buf = NULL; - - type = xmlGetProp(node, BAD_CAST "type"); - if (type != NULL) { - if (xmlStrEqual(type, BAD_CAST "file")) - typ = 0; - else if (xmlStrEqual(type, BAD_CAST "block")) - typ = 1; - xmlFree(type); - } - device = xmlGetProp(node, BAD_CAST "device"); - - cur = node->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE) { - if ((source == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "source"))) { - - if (typ == 0) - source = xmlGetProp(cur, BAD_CAST "file"); - else - source = xmlGetProp(cur, BAD_CAST "dev"); - } else if ((target == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "target"))) { - target = xmlGetProp(cur, BAD_CAST "dev"); - } else if ((drvName == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "driver"))) { - drvName = xmlGetProp(cur, BAD_CAST "name"); - if (drvName && STREQ((const char *)drvName, "tap")) - drvType = xmlGetProp(cur, BAD_CAST "type"); - } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) { - readonly = 1; - } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) { - shareable = 1; - } - } - cur = cur->next; - } - - if (target == NULL) { - xmlFree(source); - xmlFree(device); - return (-1); - } - - /* Xend (all versions) put the floppy device config - * under the hvm (image (os)) block - */ - if (hvm && - device && - STREQ((const char *)device, "floppy")) { - ret = 0; + if (VIR_ALLOC(val) < 0) { + xenXMError(conn, VIR_ERR_NO_MEMORY, NULL); goto cleanup; } - /* Xend <= 3.0.2 doesn't include cdrom config here */ - if (hvm && - device && - STREQ((const char *)device, "cdrom")) { - if (xendConfigVersion == 1) { - ret = 0; - goto cleanup; + val->type = VIR_CONF_STRING; + val->str = virBufferContentAndReset(&buf); + tmp = list->list; + while (tmp && tmp->next) + tmp = tmp->next; + if (tmp) + tmp->next = val; + else + list->list = val; + + return 0; + +cleanup: + str = virBufferContentAndReset(&buf); + VIR_FREE(str); + return -1; +} + +static int xenXMDomainConfigFormatNet(virConnectPtr conn, + virConfValuePtr list, + virDomainNetDefPtr net, + int hvm) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + virConfValuePtr val, tmp; + char *str; + + virBufferVSprintf(&buf, "mac=%02x:%02x:%02x:%02x:%02x:%02x", + net->mac[0], net->mac[1], + net->mac[2], net->mac[3], + net->mac[4], net->mac[5]); + + switch (net->type) { + case VIR_DOMAIN_NET_TYPE_BRIDGE: + virBufferVSprintf(&buf, ",bridge=%s", net->data.bridge.brname); + break; + + case VIR_DOMAIN_NET_TYPE_ETHERNET: + if (net->data.ethernet.script) + virBufferVSprintf(&buf, ",script=%s", net->data.ethernet.script); + if (net->data.ethernet.ipaddr) + virBufferVSprintf(&buf, ",ip=%s", net->data.ethernet.ipaddr); + break; + + case VIR_DOMAIN_NET_TYPE_NETWORK: + break; + + default: + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("unsupported network type %d"), + net->type); + goto cleanup; + } + + if (hvm) + virBufferAddLit(&buf, ",type=ioemu"); + + if (net->model) + virBufferVSprintf(&buf, ",model=%s", + net->model); + + if (VIR_ALLOC(val) < 0) { + xenXMError(conn, VIR_ERR_NO_MEMORY, NULL); + goto cleanup; + } + + val->type = VIR_CONF_STRING; + val->str = virBufferContentAndReset(&buf); + tmp = list->list; + while (tmp && tmp->next) + tmp = tmp->next; + if (tmp) + tmp->next = val; + else + list->list = val; + + return 0; + +cleanup: + str = virBufferContentAndReset(&buf); + VIR_FREE(str); + return -1; +} + + + +virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, + virDomainDefPtr def) { + virConfPtr conf = NULL; + int hvm = 0, i; + xenUnifiedPrivatePtr priv; + char *cpus = NULL; + const char *lifecycle; + char uuid[VIR_UUID_STRING_BUFLEN]; + virDomainDiskDefPtr disk; + virDomainNetDefPtr net; + virConfValuePtr diskVal = NULL; + virConfValuePtr netVal = NULL; + + priv = (xenUnifiedPrivatePtr) conn->privateData; + + if (!(conf = virConfNew())) + goto cleanup; + + + if (xenXMConfigSetString(conf, "name", def->name) < 0) + goto no_memory; + + virUUIDFormat(def->uuid, uuid); + if (xenXMConfigSetString(conf, "uuid", uuid) < 0) + goto no_memory; + + if (xenXMConfigSetInt(conf, "maxmem", def->maxmem / 1024) < 0) + goto no_memory; + + if (xenXMConfigSetInt(conf, "memory", def->memory / 1024) < 0) + goto no_memory; + + if (xenXMConfigSetInt(conf, "vcpus", def->vcpus) < 0) + goto no_memory; + + if (def->cpumask && + !(cpus = virDomainCpuSetFormat(conn, def->cpumask, def->cpumasklen)) < 0) + goto cleanup; + + if (cpus && + xenXMConfigSetString(conf, "cpus", cpus) < 0) + goto no_memory; + VIR_FREE(cpus); + + hvm = STREQ(def->os.type, "hvm") ? 1 : 0; + + if (hvm) { + char boot[VIR_DOMAIN_BOOT_LAST+1]; + if (xenXMConfigSetString(conf, "builder", "hvm") < 0) + goto no_memory; + + if (def->os.loader && + xenXMConfigSetString(conf, "kernel", def->os.loader) < 0) + goto no_memory; + + for (i = 0 ; i < def->os.nBootDevs ; i++) { + switch (def->os.bootDevs[i]) { + case VIR_DOMAIN_BOOT_FLOPPY: + boot[i] = 'a'; + break; + case VIR_DOMAIN_BOOT_CDROM: + boot[i] = 'd'; + break; + case VIR_DOMAIN_BOOT_NET: + boot[i] = 'n'; + break; + case VIR_DOMAIN_BOOT_DISK: + default: + boot[i] = 'c'; + break; + } + } + if (!def->os.nBootDevs) { + boot[0] = 'c'; + boot[1] = '\0'; } else { - cdrom = 1; + boot[def->os.nBootDevs] = '\0'; + } + + if (xenXMConfigSetString(conf, "boot", boot) < 0) + goto no_memory; + + if (xenXMConfigSetInt(conf, "pae", + (def->features & + (1 << VIR_DOMAIN_FEATURE_PAE)) ? 1 : 0) < 0) + goto no_memory; + + if (xenXMConfigSetInt(conf, "acpi", + (def->features & + (1 << VIR_DOMAIN_FEATURE_ACPI)) ? 1 : 0) < 0) + goto no_memory; + + if (xenXMConfigSetInt(conf, "apic", + (def->features & + (1 << VIR_DOMAIN_FEATURE_APIC)) ? 1 : 0) < 0) + goto no_memory; + + + if (xenXMConfigSetInt(conf, "localtime", def->localtime ? 1 : 0) < 0) + goto no_memory; + + if (priv->xendConfigVersion == 1) { + disk = def->disks; + while (disk) { + if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM && + disk->dst && STREQ(disk->dst, "hdc") && disk->src) { + if (xenXMConfigSetString(conf, "cdrom", disk->src) < 0) + goto no_memory; + break; + } + disk = disk->next; + } + } + + /* XXX floppy disks */ + } else { + if (def->os.bootloader && + xenXMConfigSetString(conf, "bootloader", def->os.bootloader) < 0) + goto no_memory; + if (def->os.bootloaderArgs && + xenXMConfigSetString(conf, "bootloader_args", def->os.bootloaderArgs) < 0) + goto no_memory; + if (def->os.kernel && + xenXMConfigSetString(conf, "kernel", def->os.kernel) < 0) + goto no_memory; + if (def->os.initrd && + xenXMConfigSetString(conf, "ramdisk", def->os.initrd) < 0) + goto no_memory; + if (def->os.cmdline && + xenXMConfigSetString(conf, "extra", def->os.cmdline) < 0) + goto no_memory; + + } + + if (!(lifecycle = virDomainLifecycleTypeToString(def->onPoweroff))) { + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected lifecycle action %d"), def->onPoweroff); + goto cleanup; + } + if (xenXMConfigSetString(conf, "on_poweroff", lifecycle) < 0) + goto no_memory; + + + if (!(lifecycle = virDomainLifecycleTypeToString(def->onReboot))) { + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected lifecycle action %d"), def->onReboot); + goto cleanup; + } + if (xenXMConfigSetString(conf, "on_reboot", lifecycle) < 0) + goto no_memory; + + + if (!(lifecycle = virDomainLifecycleTypeToString(def->onCrash))) { + xenXMError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected lifecycle action %d"), def->onCrash); + goto cleanup; + } + if (xenXMConfigSetString(conf, "on_crash", lifecycle) < 0) + goto no_memory; + + + + if (hvm) { + virDomainInputDefPtr input; + if (def->emulator && + xenXMConfigSetString(conf, "device_model", def->emulator) < 0) + goto no_memory; + + input = def->inputs; + while (input) { + if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) { + if (xenXMConfigSetInt(conf, "usb", 1) < 0) + goto no_memory; + if (xenXMConfigSetString(conf, "usbdevice", + input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ? + "mouse" : "tablet") < 0) + goto no_memory; + break; + } + input = input->next; } } - if (source == NULL && !cdrom) { - xmlFree(target); - xmlFree(device); - return (-1); - } - - if (drvName) { - buflen += strlen((const char*)drvName) + 1; - if (STREQ((const char*)drvName, "tap")) { - if (drvType) - buflen += strlen((const char*)drvType) + 1; - else - buflen += 4; - } - } else { - if (typ == 0) - buflen += 5; - else - buflen += 4; - } - - if(source) - buflen += strlen((const char*)source) + 1; - else - buflen += 1; - buflen += strlen((const char*)target) + 1; - if (hvm && xendConfigVersion == 1) /* ioemu: */ - buflen += 6; - - if (cdrom) /* :cdrom */ - buflen += 6; - - buflen += 2; /* mode */ - - if (VIR_ALLOC_N(buf, buflen) < 0) - goto cleanup; - - if(source) { - if (drvName) { - strcpy(buf, (const char*)drvName); - if (STREQ((const char*)drvName, "tap")) { - strcat(buf, ":"); - if (drvType) - strcat(buf, (const char*)drvType); - else - strcat(buf, "aio"); + if (def->graphics) { + if (hvm || priv->xendConfigVersion < 3) { + if (def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) { + if (xenXMConfigSetInt(conf, "sdl", 1) < 0) + goto no_memory; + if (xenXMConfigSetInt(conf, "vnc", 0) < 0) + goto no_memory; + if (def->graphics->data.sdl.display && + xenXMConfigSetString(conf, "display", + def->graphics->data.sdl.display) < 0) + goto no_memory; + if (def->graphics->data.sdl.xauth && + xenXMConfigSetString(conf, "xauthority", + def->graphics->data.sdl.xauth) < 0) + goto no_memory; + } else { + if (xenXMConfigSetInt(conf, "sdl", 0) < 0) + goto no_memory; + if (xenXMConfigSetInt(conf, "vnc", 1) < 0) + goto no_memory; + if (xenXMConfigSetInt(conf, "vncunused", + def->graphics->data.vnc.autoport ? 1 : 0) < 0) + goto no_memory; + if (!def->graphics->data.vnc.autoport && + xenXMConfigSetInt(conf, "vncdisplay", + def->graphics->data.vnc.port - 5900) < 0) + goto no_memory; + if (def->graphics->data.vnc.listenAddr && + xenXMConfigSetString(conf, "vnclisten", + def->graphics->data.vnc.listenAddr) < 0) + goto no_memory; + if (def->graphics->data.vnc.passwd && + xenXMConfigSetString(conf, "vncpasswd", + def->graphics->data.vnc.passwd) < 0) + goto no_memory; + if (def->graphics->data.vnc.keymap && + xenXMConfigSetString(conf, "keymap", + def->graphics->data.vnc.keymap) < 0) + goto no_memory; } } else { - if (typ == 0) - strcpy(buf, "file"); - else - strcpy(buf, "phy"); + virConfValuePtr vfb, disp; + char *vfbstr = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + if (def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) { + virBufferAddLit(&buf, "type=sdl"); + if (def->graphics->data.sdl.display) + virBufferVSprintf(&buf, ",display=%s", + def->graphics->data.sdl.display); + if (def->graphics->data.sdl.xauth) + virBufferVSprintf(&buf, ",xauthority=%s", + def->graphics->data.sdl.xauth); + } else { + virBufferAddLit(&buf, "type=vnc"); + virBufferVSprintf(&buf, ",vncunused=%d", + def->graphics->data.vnc.autoport ? 1 : 0); + if (!def->graphics->data.vnc.autoport) + virBufferVSprintf(&buf, ",vncdisplay=%d", + def->graphics->data.vnc.port - 5900); + if (def->graphics->data.vnc.listenAddr) + virBufferVSprintf(&buf, ",vnclisten=%s", + def->graphics->data.vnc.listenAddr); + if (def->graphics->data.vnc.passwd) + virBufferVSprintf(&buf, ",vncpasswd=%s", + def->graphics->data.vnc.passwd); + if (def->graphics->data.vnc.keymap) + virBufferVSprintf(&buf, ",keymap=%s", + def->graphics->data.vnc.keymap); + } + if (virBufferError(&buf)) + goto no_memory; + + vfbstr = virBufferContentAndReset(&buf); + + if (VIR_ALLOC(vfb) < 0) { + VIR_FREE(vfbstr); + goto no_memory; + } + + if (VIR_ALLOC(disp) < 0) { + VIR_FREE(vfb); + VIR_FREE(vfbstr); + goto no_memory; + } + + vfb->type = VIR_CONF_LIST; + vfb->list = disp; + disp->type = VIR_CONF_STRING; + disp->str = vfbstr; + + if (virConfSetValue(conf, "vfb", vfb) < 0) + goto no_memory; } - strcat(buf, ":"); - strcat(buf, (const char*)source); - } else { - strcpy(buf, ""); - } - strcat(buf, ","); - if (hvm && xendConfigVersion == 1) - strcat(buf, "ioemu:"); - strcat(buf, (const char*)target); - if (cdrom) - strcat(buf, ":cdrom"); - - if (readonly) - strcat(buf, ",r"); - else if (shareable) - strcat(buf, ",!"); - else - strcat(buf, ",w"); - ret = 0; - cleanup: - xmlFree(drvType); - xmlFree(drvName); - xmlFree(device); - xmlFree(target); - xmlFree(source); - *disk = buf; - - return (ret); -} -static char *xenXMParseXMLVif(virConnectPtr conn, xmlNodePtr node, int hvm) { - xmlNodePtr cur; - xmlChar *type = NULL; - xmlChar *source = NULL; - xmlChar *mac = NULL; - xmlChar *script = NULL; - xmlChar *model = NULL; - xmlChar *ip = NULL; - int typ = 0; - char *buf = NULL; - int buflen = 0; - char *bridge = NULL; - - type = xmlGetProp(node, BAD_CAST "type"); - if (type != NULL) { - if (xmlStrEqual(type, BAD_CAST "bridge")) - typ = 0; - else if (xmlStrEqual(type, BAD_CAST "ethernet")) - typ = 1; - else if (xmlStrEqual(type, BAD_CAST "network")) - typ = 2; - xmlFree(type); - } - cur = node->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE) { - if ((source == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "source"))) { - - if (typ == 0) - source = xmlGetProp(cur, BAD_CAST "bridge"); - else if (typ == 1) - source = xmlGetProp(cur, BAD_CAST "dev"); - else - source = xmlGetProp(cur, BAD_CAST "network"); - } else if ((mac == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "mac"))) { - mac = xmlGetProp(cur, BAD_CAST "address"); - } else if ((model == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "model"))) { - model = xmlGetProp(cur, BAD_CAST "type"); - } else if ((ip == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "ip"))) { - ip = xmlGetProp(cur, BAD_CAST "address"); - } else if ((script == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "script"))) { - script = xmlGetProp(cur, BAD_CAST "path"); - } - } - cur = cur->next; - } - - if (!mac) { - goto cleanup; - } - buflen += 5 + strlen((const char *)mac); - if (source) { - if (typ == 0) { - buflen += 8 + strlen((const char *)source); - } else if (typ == 1) { - buflen += 5 + strlen((const char *)source); - } else { - virNetworkPtr network = virNetworkLookupByName(conn, (const char *) source); - if (!network || !(bridge = virNetworkGetBridgeName(network))) { - if (network) - virNetworkFree(network); - goto cleanup; - } - virNetworkFree(network); - buflen += 8 + strlen(bridge); - } - } - if (hvm) - buflen += 11; - if (script) - buflen += 8 + strlen((const char*)script); - if (model) - buflen += 7 + strlen((const char*)model); - if (ip) - buflen += 4 + strlen((const char*)ip); - - if (VIR_ALLOC_N(buf, buflen) < 0) - goto cleanup; - - strcpy(buf, "mac="); - strcat(buf, (const char*)mac); - if (source) { - if (typ == 0) { - strcat(buf, ",bridge="); - strcat(buf, (const char*)source); - } else if (typ == 1) { - strcat(buf, ",dev="); - strcat(buf, (const char*)source); - } else { - strcat(buf, ",bridge="); - strcat(buf, bridge); - } - } - if (hvm) { - strcat(buf, ",type=ioemu"); - } - if (script) { - strcat(buf, ",script="); - strcat(buf, (const char*)script); - } - if (model) { - strcat(buf, ",model="); - strcat(buf, (const char*)model); - } - if (ip) { - strcat(buf, ",ip="); - strcat(buf, (const char*)ip); - } - - cleanup: - VIR_FREE(bridge); - xmlFree(mac); - xmlFree(source); - xmlFree(script); - xmlFree(ip); - xmlFree(model); - - return buf; -} - - -virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, - virDomainDefPtr def) { - xmlDocPtr doc = NULL; - xmlNodePtr node; - xmlXPathObjectPtr obj = NULL; - xmlXPathContextPtr ctxt = NULL; - xmlChar *prop = NULL; - virConfPtr conf = NULL; - int hvm = 0, i; - xenUnifiedPrivatePtr priv; - char *cpus; - char *xml; - - priv = (xenUnifiedPrivatePtr) conn->privateData; - - if (!(xml = virDomainDefFormat(conn, def, VIR_DOMAIN_XML_SECURE))) - return NULL; - - doc = xmlReadDoc((const xmlChar *) xml, "domain.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING); - VIR_FREE(xml); - if (doc == NULL) { - xenXMError(conn, VIR_ERR_XML_ERROR, - _("cannot read XML domain definition")); - return (NULL); - } - node = xmlDocGetRootElement(doc); - if ((node == NULL) || (!xmlStrEqual(node->name, BAD_CAST "domain"))) { - xenXMError(conn, VIR_ERR_XML_ERROR, - _("missing top level domain element")); - goto error; - } - - prop = xmlGetProp(node, BAD_CAST "type"); - if (prop != NULL) { - if (!xmlStrEqual(prop, BAD_CAST "xen")) { - xenXMError(conn, VIR_ERR_XML_ERROR, - _("domain type is invalid")); - goto error; - } - xmlFree(prop); - prop = NULL; - } - if (!(ctxt = xmlXPathNewContext(doc))) { - xenXMError(conn, VIR_ERR_INTERNAL_ERROR, - _("cannot create XPath context")); - goto error; - } - if (!(conf = virConfNew())) - goto error; - - - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "name", "string(/domain/name)", 0, - "domain name element missing") < 0) - goto error; - - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "uuid", "string(/domain/uuid)", 0, - "domain uuid element missing") < 0) - goto error; - - if (xenXMConfigSetIntFromXPath(conn, conf, ctxt, "maxmem", "string(/domain/memory)", -1024, 0, - "domain memory element missing") < 0) - goto error; - - if (xenXMConfigSetIntFromXPath(conn, conf, ctxt, "memory", "string(/domain/memory)", -1024, 0, - "domain memory element missing") < 0) - goto error; - - if (xenXMConfigSetIntFromXPath(conn, conf, ctxt, "memory", "string(/domain/currentMemory)", -1024, 1, - "domain currentMemory element missing") < 0) - goto error; - - if (xenXMConfigSetInt(conf, "vcpus", 1) < 0) - goto error; - - if (xenXMConfigSetIntFromXPath(conn, conf, ctxt, "vcpus", "string(/domain/vcpu)", 0, 1, - "cannot set vcpus config parameter") < 0) - goto error; - - cpus = virXPathString("string(/domain/vcpu/@cpuset)", ctxt); - if (cpus != NULL) { - char *ranges; - - ranges = virConvertCpuSet(conn, cpus, 0); - VIR_FREE(cpus); - if (ranges == NULL) { - goto error; - } - if (xenXMConfigSetString(conf, "cpus", ranges) < 0) { - VIR_FREE(ranges); - goto error; - } - VIR_FREE(ranges); - } - - obj = xmlXPathEval(BAD_CAST "string(/domain/os/type)", ctxt); - if ((obj != NULL) && (obj->type == XPATH_STRING) && - (obj->stringval != NULL) && STREQ((char*)obj->stringval, "hvm")) - hvm = 1; - xmlXPathFreeObject(obj); - obj = NULL; - - if (hvm) { - const char *boot = "c"; - int clockLocal = 0; - if (xenXMConfigSetString(conf, "builder", "hvm") < 0) - goto error; - - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "kernel", "string(/domain/os/loader)", 1, - "cannot set the os loader parameter") < 0) - goto error; - - obj = xmlXPathEval(BAD_CAST "string(/domain/os/boot/@dev)", ctxt); - if ((obj != NULL) && (obj->type == XPATH_STRING) && - (obj->stringval != NULL)) { - if (STREQ((const char*)obj->stringval, "fd")) - boot = "a"; - else if (STREQ((const char*)obj->stringval, "hd")) - boot = "c"; - else if (STREQ((const char*)obj->stringval, "cdrom")) - boot = "d"; - } - xmlXPathFreeObject(obj); - obj = NULL; - if (xenXMConfigSetString(conf, "boot", boot) < 0) - goto error; - - if (xenXMConfigSetIntFromXPath(conn, conf, ctxt, "pae", "string(count(/domain/features/pae))", 0, 0, - "cannot set the pae parameter") < 0) - goto error; - - if (xenXMConfigSetIntFromXPath(conn, conf, ctxt, "acpi", "string(count(/domain/features/acpi))", 0, 0, - "cannot set the acpi parameter") < 0) - goto error; - - if (xenXMConfigSetIntFromXPath(conn, conf, ctxt, "apic", "string(count(/domain/features/apic))", 0, 0, - "cannot set the apic parameter") < 0) - goto error; - - obj = xmlXPathEval(BAD_CAST "string(/domain/clock/@offset)", ctxt); - if ((obj != NULL) && (obj->type == XPATH_STRING) && - (obj->stringval != NULL)) { - if (STREQ((const char*)obj->stringval, "localtime")) - clockLocal = 1; - } - xmlXPathFreeObject(obj); - obj = NULL; - if (xenXMConfigSetInt(conf, "localtime", clockLocal) < 0) - goto error; - - if (priv->xendConfigVersion == 1) { - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "cdrom", "string(/domain/devices/disk[@device='cdrom']/source/@file)", 1, - "cannot set the cdrom parameter") < 0) - goto error; - } - } else { - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "bootloader", "string(/domain/bootloader)", 1, - "cannot set the bootloader parameter") < 0) - goto error; - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "bootargs", "string(/domain/bootloader_args)", 1, - "cannot set the bootloader_args parameter") < 0) - goto error; - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "kernel", "string(/domain/os/kernel)", 1, - "cannot set the kernel parameter") < 0) - goto error; - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "ramdisk", "string(/domain/os/initrd)", 1, - "cannot set the ramdisk parameter") < 0) - goto error; - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "extra", "string(/domain/os/cmdline)", 1, - "cannot set the cmdline parameter") < 0) - goto error; - - } - - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "on_poweroff", "string(/domain/on_poweroff)", 1, - "cannot set the on_poweroff parameter") < 0) - goto error; - - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "on_reboot", "string(/domain/on_reboot)", 1, - "cannot set the on_reboot parameter") < 0) - goto error; - - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "on_crash", "string(/domain/on_crash)", 1, - "cannot set the on_crash parameter") < 0) - goto error; - - - if (hvm) { - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "device_model", "string(/domain/devices/emulator)", 1, - "cannot set the device_model parameter") < 0) - goto error; - - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "usbdevice", "string(/domain/devices/input[@bus='usb' or (not(@bus) and @type='tablet')]/@type)", 1, - "cannot set the usbdevice parameter") < 0) - goto error; - } - - if (hvm || priv->xendConfigVersion < 3) { - if (xenXMConfigSetIntFromXPath(conn, conf, ctxt, "sdl", "string(count(/domain/devices/graphics[@type='sdl']))", 0, 0, - "cannot set the sdl parameter") < 0) - goto error; - if (xenXMConfigSetIntFromXPath(conn, conf, ctxt, "vnc", "string(count(/domain/devices/graphics[@type='vnc']))", 0, 0, - "cannot set the vnc parameter") < 0) - goto error; - if (xenXMConfigSetIntFromXPath(conn, conf, ctxt, "vncunused", "string(count(/domain/devices/graphics[@type='vnc' and @port='-1']))", 0, 0, - "cannot set the vncunused parameter") < 0) - goto error; - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "vnclisten", "string(/domain/devices/graphics[@type='vnc']/@listen)", 1, - "cannot set the vnclisten parameter") < 0) - goto error; - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "vncpasswd", "string(/domain/devices/graphics[@type='vnc']/@passwd)", 1, - "cannot set the vncpasswd parameter") < 0) - goto error; - if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "keymap", "string(/domain/devices/graphics[@type='vnc']/@keymap)", 1, - "cannot set the keymap parameter") < 0) - goto error; - - obj = xmlXPathEval(BAD_CAST "string(/domain/devices/graphics[@type='vnc']/@port)", ctxt); - if ((obj != NULL) && (obj->type == XPATH_STRING) && - (obj->stringval != NULL)) { - int port = strtol((const char *)obj->stringval, NULL, 10); - if (port != -1) { - char portstr[50]; - snprintf(portstr, sizeof(portstr), "%d", port-5900); - if (xenXMConfigSetString(conf, "vncdisplay", portstr) < 0) - goto error; - } - } - xmlXPathFreeObject(obj); - } else { - virConfValuePtr vfb; - obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { - if (VIR_ALLOC(vfb) < 0) { - xenXMError(conn, VIR_ERR_NO_MEMORY, _("config")); - goto error; - } - vfb->type = VIR_CONF_LIST; - vfb->list = NULL; - for (i = obj->nodesetval->nodeNr -1 ; i >= 0 ; i--) { - xmlChar *type; - char *val = NULL; - - if (!(type = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "type"))) { - continue; - } - if (STREQ((const char*)type, "sdl")) { - val = strdup("type=sdl"); - } else if (STREQ((const char*)type, "vnc")) { - int len = 8 + 1; /* type=vnc & NULL */ - xmlChar *vncport = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "port"); - xmlChar *vnclisten = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "listen"); - xmlChar *vncpasswd = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "passwd"); - xmlChar *keymap = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "keymap"); - int vncunused = vncport ? (STREQ((const char*)vncport, "-1") ? 1 : 0) : 1; - if (vncunused) - len += 12; - else - len += 12 + strlen((const char*)vncport);/* vncdisplay= */ - if (vnclisten) - len += 11 + strlen((const char*)vnclisten); - if (vncpasswd) - len += 11 + strlen((const char*)vncpasswd); - if (keymap) - len += 8 + strlen((const char*)keymap); - if (VIR_ALLOC_N(val, len) < 0) { - xmlFree(type); - xmlFree(vncport); - xmlFree(vnclisten); - xmlFree(vncpasswd); - xmlFree(keymap); - VIR_FREE(vfb); - xenXMError (conn, VIR_ERR_NO_MEMORY, strerror (errno)); - goto error; - } - strcpy(val, "type=vnc"); - if (vncunused) { - strcat(val, ",vncunused=1"); - } else { - char portstr[50]; - int port = atoi((const char*)vncport); - snprintf(portstr, sizeof(portstr), "%d", port-5900); - strcat(val, ",vncdisplay="); - strcat(val, portstr); - } - xmlFree(vncport); - if (vnclisten) { - strcat(val, ",vnclisten="); - strcat(val, (const char*)vnclisten); - xmlFree(vnclisten); - } - if (vncpasswd) { - strcat(val, ",vncpasswd="); - strcat(val, (const char*)vncpasswd); - xmlFree(vncpasswd); - } - if (keymap) { - strcat(val, ",keymap="); - strcat(val, (const char*)keymap); - xmlFree(keymap); - } - } - xmlFree(type); - if (val) { - virConfValuePtr disp; - if (VIR_ALLOC(disp) < 0) { - VIR_FREE(val); - VIR_FREE(vfb); - xenXMError(conn, VIR_ERR_NO_MEMORY, _("config")); - goto error; - } - disp->type = VIR_CONF_STRING; - disp->str = val; - disp->next = vfb->list; - vfb->list = disp; - } - } - if (virConfSetValue(conf, "vfb", vfb) < 0) - goto error; - } - xmlXPathFreeObject(obj); } /* analyze of the devices */ - obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { - virConfValuePtr disks; - if (VIR_ALLOC(disks) < 0) { - xenXMError(conn, VIR_ERR_NO_MEMORY, _("config")); - goto error; + disk = def->disks; + if (VIR_ALLOC(diskVal) < 0) + goto no_memory; + diskVal->type = VIR_CONF_LIST; + diskVal->list = NULL; + + while (disk) { + if (priv->xendConfigVersion == 1 && + disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM && + disk->dst && STREQ(disk->dst, "hdc")) { + disk = disk->next; + continue; } - disks->type = VIR_CONF_LIST; - disks->list = NULL; - for (i = obj->nodesetval->nodeNr -1 ; i >= 0 ; i--) { - virConfValuePtr thisDisk; - char *disk = NULL; - if (xenXMParseXMLDisk(obj->nodesetval->nodeTab[i], hvm, priv->xendConfigVersion, &disk) < 0) { - virConfFreeValue(disks); - goto error; - } - if (disk) { - if (VIR_ALLOC(thisDisk) < 0) { - VIR_FREE(disk); - virConfFreeValue(disks); - xenXMError(conn, VIR_ERR_NO_MEMORY, _("config")); - goto error; - } - thisDisk->type = VIR_CONF_STRING; - thisDisk->str = disk; - thisDisk->next = disks->list; - disks->list = thisDisk; - } - } - if (virConfSetValue(conf, "disk", disks) < 0) - goto error; + if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) + continue; + + if (xenXMDomainConfigFormatDisk(conn, diskVal, disk, + hvm, priv->xendConfigVersion) < 0) + goto cleanup; + + disk = disk->next; } - xmlXPathFreeObject(obj); + if (diskVal->list == NULL) + VIR_FREE(diskVal); + else if (virConfSetValue(conf, "disk", diskVal) < 0) { + diskVal = NULL; + goto no_memory; + } + diskVal = NULL; - obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { - virConfValuePtr vifs; - if (VIR_ALLOC(vifs) < 0) { - xenXMError(conn, VIR_ERR_NO_MEMORY, _("config")); - goto error; - } - vifs->type = VIR_CONF_LIST; - vifs->list = NULL; - for (i = obj->nodesetval->nodeNr - 1; i >= 0; i--) { - virConfValuePtr thisVif; - char *vif = xenXMParseXMLVif(conn, obj->nodesetval->nodeTab[i], hvm); - if (!vif) { - virConfFreeValue(vifs); - goto error; - } - if (VIR_ALLOC(thisVif) < 0) { - VIR_FREE(vif); - virConfFreeValue(vifs); - xenXMError(conn, VIR_ERR_NO_MEMORY, _("config")); - goto error; - } - thisVif->type = VIR_CONF_STRING; - thisVif->str = vif; - thisVif->next = vifs->list; - vifs->list = thisVif; - } - if (virConfSetValue(conf, "vif", vifs) < 0) - goto error; + + net = def->nets; + if (VIR_ALLOC(netVal) < 0) + goto no_memory; + netVal->type = VIR_CONF_LIST; + netVal->list = NULL; + + while (net) { + if (xenXMDomainConfigFormatNet(conn, netVal, net, + hvm) < 0) + goto cleanup; + + net = net->next; } - xmlXPathFreeObject(obj); - obj = NULL; + if (netVal->list == NULL) + VIR_FREE(netVal); + else if (virConfSetValue(conf, "vif", netVal) < 0) { + netVal = NULL; + goto no_memory; + } + netVal = NULL; if (hvm) { - xmlNodePtr cur; - cur = virXPathNode("/domain/devices/parallel[1]", ctxt); - if (cur != NULL) { - char scratch[PATH_MAX]; + if (def->parallels) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *str; + int ret; - if (virDomainParseXMLOSDescHVMChar(conn, scratch, sizeof(scratch), cur) < 0) { - goto error; - } - - if (xenXMConfigSetString(conf, "parallel", scratch) < 0) - goto error; + ret = xenDaemonFormatSxprChr(conn, def->parallels, &buf); + str = virBufferContentAndReset(&buf); + if (ret == 0) + ret = xenXMConfigSetString(conf, "parallel", str); + VIR_FREE(str); + if (ret < 0) + goto no_memory; } else { if (xenXMConfigSetString(conf, "parallel", "none") < 0) - goto error; + goto no_memory; } - cur = virXPathNode("/domain/devices/serial[1]", ctxt); - if (cur != NULL) { - char scratch[PATH_MAX]; - if (virDomainParseXMLOSDescHVMChar(conn, scratch, sizeof(scratch), cur) < 0) - goto error; - if (xenXMConfigSetString(conf, "serial", scratch) < 0) - goto error; + if (def->serials) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *str; + int ret; + + ret = xenDaemonFormatSxprChr(conn, def->serials, &buf); + str = virBufferContentAndReset(&buf); + if (ret == 0) + ret = xenXMConfigSetString(conf, "serial", str); + VIR_FREE(str); + if (ret < 0) + goto no_memory; } else { - if (virXPathBoolean("count(/domain/devices/console) > 0", ctxt)) { - if (xenXMConfigSetString(conf, "serial", "pty") < 0) - goto error; - } else { - if (xenXMConfigSetString(conf, "serial", "none") < 0) - goto error; - } + if (xenXMConfigSetString(conf, "serial", "none") < 0) + goto no_memory; } - if (virXPathNode("/domain/devices/sound", ctxt)) { - char *soundstr; - if (!(soundstr = virBuildSoundStringFromXML(conn, ctxt))) - goto error; - if (xenXMConfigSetString(conf, "soundhw", soundstr) < 0) { - VIR_FREE(soundstr); - goto error; - } - VIR_FREE(soundstr); + + if (def->sounds) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *str = NULL; + int ret = xenDaemonFormatSxprSound(conn, + def->sounds, + &buf); + str = virBufferContentAndReset(&buf); + if (ret == 0) + ret = xenXMConfigSetString(conf, "soundhw", str); + + VIR_FREE(str); + if (ret < 0) + goto no_memory; } } - xmlFreeDoc(doc); - xmlXPathFreeContext(ctxt); - return conf; - error: +no_memory: + xenXMError(conn, VIR_ERR_NO_MEMORY, NULL); + +cleanup: + virConfFreeValue(diskVal); + virConfFreeValue(netVal); + VIR_FREE(cpus); if (conf) virConfFree(conf); - xmlFree(prop); - xmlXPathFreeObject(obj); - xmlXPathFreeContext(ctxt); - if (doc != NULL) - xmlFreeDoc(doc); return (NULL); } diff -r 6f2488f348b8 src/xm_internal.h --- a/src/xm_internal.h Thu Jul 03 16:50:10 2008 +0100 +++ b/src/xm_internal.h Thu Jul 03 16:50:15 2008 +0100 @@ -25,9 +25,8 @@ #ifndef _LIBVIRT_XM_INTERNAL_H_ #define _LIBVIRT_XM_INTERNAL_H_ -#include "libvirt/libvirt.h" +#include "internal.h" #include "conf.h" -#include "internal.h" #include "domain_conf.h" extern struct xenUnifiedDriver xenXMDriver; diff -r 6f2488f348b8 src/xml.c --- a/src/xml.c Thu Jul 03 16:50:10 2008 +0100 +++ b/src/xml.c Thu Jul 03 16:50:15 2008 +0100 @@ -368,291 +368,3 @@ return (ret); } -#if WITH_XEN -#ifndef PROXY -/** - * virConvertCpuSet: - * @conn: connection - * @str: pointer to a Xen or user provided CPU set string pointer - * @maxcpu: number of CPUs on the node, if 0 4096 will be used - * - * Parse the given CPU set string and convert it to a range based - * string. - * - * Returns a new string which must be freed by the caller or NULL in - * case of error. - */ -char * -virConvertCpuSet(virConnectPtr conn, const char *str, int maxcpu) { - int ret; - char *res, *cpuset; - const char *cur = str; - - if (str == NULL) - return(NULL); - - if (maxcpu <= 0) - maxcpu = 4096; - - if (VIR_ALLOC_N(cpuset, maxcpu) < 0) { - virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0); - return(NULL); - } - - ret = virDomainCpuSetParse(conn, &cur, 0, cpuset, maxcpu); - if (ret < 0) { - VIR_FREE(cpuset); - return(NULL); - } - res = virDomainCpuSetFormat(conn, cpuset, maxcpu); - VIR_FREE(cpuset); - return (res); -} - - -/** - * virBuildSoundStringFromXML - * @sound buffer to populate - * @len size of preallocated buffer 'sound' - * @ctxt xml context to pull sound info from - * - * Builds a string of the form m1,m2,m3 from the different sound models - * in the xml. String must be free'd by caller. - * - * Returns string on success, NULL on error - */ -char * virBuildSoundStringFromXML(virConnectPtr conn, - xmlXPathContextPtr ctxt) { - - int nb_nodes, size = 256; - char *sound; - xmlNodePtr *nodes = NULL; - - if (VIR_ALLOC_N(sound, size + 1) < 0) { - virXMLError(conn, VIR_ERR_NO_MEMORY, - _("failed to allocate sound string"), 0); - return NULL; - } - - nb_nodes = virXPathNodeSet("/domain/devices/sound", ctxt, &nodes); - if (nb_nodes > 0) { - int i; - for (i = 0; i < nb_nodes && size > 0; i++) { - char *model = NULL; - int collision = 0; - - model = (char *) xmlGetProp(nodes[i], (xmlChar *) "model"); - if (!model) { - virXMLError(conn, VIR_ERR_XML_ERROR, - _("no model for sound device"), 0); - goto error; - } - - if (!is_sound_model_valid(model)) { - virXMLError(conn, VIR_ERR_XML_ERROR, - _("unknown sound model type"), 0); - VIR_FREE(model); - goto error; - } - - // Check for duplicates in currently built string - if (*sound) - collision = is_sound_model_conflict(model, sound); - - // If no collision, add to string - if (!collision) { - if (*sound && (size >= (strlen(model) + 1))) { - strncat(sound, ",", size--); - } else if (*sound || size < strlen(model)) { - VIR_FREE(model); - continue; - } - strncat(sound, model, size); - size -= strlen(model); - } - - VIR_FREE(model); - } - } - VIR_FREE(nodes); - return sound; - error: - VIR_FREE(nodes); - return NULL; -} - -int -virDomainParseXMLOSDescHVMChar(virConnectPtr conn, - char *buf, - size_t buflen, - xmlNodePtr node) -{ - xmlChar *type = NULL; - xmlChar *path = NULL; - xmlChar *bindHost = NULL; - xmlChar *bindService = NULL; - xmlChar *connectHost = NULL; - xmlChar *connectService = NULL; - xmlChar *mode = NULL; - xmlChar *protocol = NULL; - xmlNodePtr cur; - - type = xmlGetProp(node, BAD_CAST "type"); - - if (type != NULL) { - cur = node->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE) { - if (xmlStrEqual(cur->name, BAD_CAST "source")) { - if (mode == NULL) - mode = xmlGetProp(cur, BAD_CAST "mode"); - - if (STREQ((const char *)type, "dev") || - STREQ((const char *)type, "file") || - STREQ((const char *)type, "pipe") || - STREQ((const char *)type, "unix")) { - if (path == NULL) - path = xmlGetProp(cur, BAD_CAST "path"); - - } else if (STREQ((const char *)type, "udp") || - STREQ((const char *)type, "tcp")) { - if (mode == NULL || - STREQ((const char *)mode, "connect")) { - - if (connectHost == NULL) - connectHost = xmlGetProp(cur, BAD_CAST "host"); - if (connectService == NULL) - connectService = xmlGetProp(cur, BAD_CAST "service"); - } else { - if (bindHost == NULL) - bindHost = xmlGetProp(cur, BAD_CAST "host"); - if (bindService == NULL) - bindService = xmlGetProp(cur, BAD_CAST "service"); - } - - if (STREQ((const char*)type, "udp")) { - xmlFree(mode); - mode = NULL; - } - } - } else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) { - if (protocol == NULL) - protocol = xmlGetProp(cur, BAD_CAST "type"); - } - } - cur = cur->next; - } - } - - if (type == NULL || - STREQ((const char *)type, "pty")) { - strncpy(buf, "pty", buflen); - } else if (STREQ((const char *)type, "null") || - STREQ((const char *)type, "stdio") || - STREQ((const char *)type, "vc")) { - snprintf(buf, buflen, "%s", type); - } else if (STREQ((const char *)type, "file") || - STREQ((const char *)type, "dev") || - STREQ((const char *)type, "pipe")) { - if (path == NULL) { - virXMLError(conn, VIR_ERR_XML_ERROR, - _("Missing source path attribute for char device"), 0); - goto cleanup; - } - - if (STREQ((const char *)type, "dev")) - strncpy(buf, (const char *)path, buflen); - else - snprintf(buf, buflen, "%s:%s", type, path); - } else if (STREQ((const char *)type, "tcp")) { - int telnet = 0; - if (protocol != NULL && - STREQ((const char *)protocol, "telnet")) - telnet = 1; - - if (mode == NULL || - STREQ((const char *)mode, "connect")) { - if (connectHost == NULL) { - virXMLError(conn, VIR_ERR_INTERNAL_ERROR, - _("Missing source host attribute for char device"), 0); - goto cleanup; - } - if (connectService == NULL) { - virXMLError(conn, VIR_ERR_INTERNAL_ERROR, - _("Missing source service attribute for char device"), 0); - goto cleanup; - } - - snprintf(buf, buflen, "%s:%s:%s", - (telnet ? "telnet" : "tcp"), - connectHost, connectService); - } else { - if (bindHost == NULL) { - virXMLError(conn, VIR_ERR_INTERNAL_ERROR, - _("Missing source host attribute for char device"), 0); - goto cleanup; - } - if (bindService == NULL) { - virXMLError(conn, VIR_ERR_INTERNAL_ERROR, - _("Missing source service attribute for char device"), 0); - goto cleanup; - } - - snprintf(buf, buflen, "%s:%s:%s,listen", - (telnet ? "telnet" : "tcp"), - bindHost, bindService); - } - } else if (STREQ((const char *)type, "udp")) { - if (connectService == NULL) { - virXMLError(conn, VIR_ERR_XML_ERROR, - _("Missing source service attribute for char device"), 0); - goto cleanup; - } - - snprintf(buf, buflen, "udp:%s:%s@%s:%s", - connectHost ? (const char *)connectHost : "", - connectService, - bindHost ? (const char *)bindHost : "", - bindService ? (const char *)bindService : ""); - } else if (STREQ((const char *)type, "unix")) { - if (path == NULL) { - virXMLError(conn, VIR_ERR_XML_ERROR, - _("Missing source path attribute for char device"), 0); - goto cleanup; - } - - if (mode == NULL || - STREQ((const char *)mode, "connect")) { - snprintf(buf, buflen, "%s:%s", type, path); - } else { - snprintf(buf, buflen, "%s:%s,listen", type, path); - } - } - buf[buflen-1] = '\0'; - - xmlFree(mode); - xmlFree(protocol); - xmlFree(type); - xmlFree(bindHost); - xmlFree(bindService); - xmlFree(connectHost); - xmlFree(connectService); - xmlFree(path); - - return 0; - -cleanup: - xmlFree(mode); - xmlFree(protocol); - xmlFree(type); - xmlFree(bindHost); - xmlFree(bindService); - xmlFree(connectHost); - xmlFree(connectService); - xmlFree(path); - return -1; -} - -#endif /* !PROXY */ - -#endif /* WITH_XEN */ diff -r 6f2488f348b8 src/xml.h --- a/src/xml.h Thu Jul 03 16:50:10 2008 +0100 +++ b/src/xml.h Thu Jul 03 16:50:15 2008 +0100 @@ -39,16 +39,4 @@ char * virXMLPropString(xmlNodePtr node, const char *name); -char * -virConvertCpuSet(virConnectPtr conn, const char *str, int maxcpu); - -char * virBuildSoundStringFromXML(virConnectPtr conn, - xmlXPathContextPtr ctxt); - -int -virDomainParseXMLOSDescHVMChar(virConnectPtr conn, - char *buf, - size_t buflen, - xmlNodePtr node); - #endif /* __VIR_XML_H__ */ diff -r 6f2488f348b8 tests/xmconfigdata/test-fullvirt-usbmouse.cfg --- a/tests/xmconfigdata/test-fullvirt-usbmouse.cfg Thu Jul 03 16:50:10 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-usbmouse.cfg Thu Jul 03 16:50:15 2008 +0100 @@ -14,6 +14,7 @@ on_reboot = "restart" on_crash = "restart" device_model = "/usr/lib/xen/bin/qemu-dm" +usb = 1 usbdevice = "mouse" sdl = 0 vnc = 1 diff -r 6f2488f348b8 tests/xmconfigdata/test-fullvirt-usbtablet.cfg --- a/tests/xmconfigdata/test-fullvirt-usbtablet.cfg Thu Jul 03 16:50:10 2008 +0100 +++ b/tests/xmconfigdata/test-fullvirt-usbtablet.cfg Thu Jul 03 16:50:15 2008 +0100 @@ -14,6 +14,7 @@ on_reboot = "restart" on_crash = "restart" device_model = "/usr/lib/xen/bin/qemu-dm" +usb = 1 usbdevice = "tablet" sdl = 0 vnc = 1 -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Tue, Jul 08, 2008 at 05:41:46PM +0100, Daniel P. Berrange wrote:
This completes the Xen driver work, replacing the code which converts from XML into virConfPtr objects, with code which converts from virDomainDefPtr into virConfPtr objects. The XML parsing is now fully handled by the generic routines.
At this point, the xml.c file no longer contains any Xen specific code and is solely generic XML routines.
[...]
--- a/src/xend_internal.c Thu Jul 03 16:50:10 2008 +0100 +++ b/src/xend_internal.c Thu Jul 03 16:50:15 2008 +0100
okay the SExpr output routines gets refactored a bit. In general the diffs are really hard to follow on that patch
+usb = 1 usbdevice = "mouse"
Looks fine, +1 Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

The generic XML parsing routines can generate various errors. We were not passing a virConnectPtr object into any of them, so the errors were not propagated back to the calling app correctly. This fixes that problem domain_conf.c | 60 ++++++++++++++++++++++++++++----------------------------- lxc_conf.c | 14 ++++++------- network_conf.c | 22 ++++++++++---------- storage_conf.c | 60 ++++++++++++++++++++++++++++----------------------------- test.c | 20 +++++++++---------- xml.c | 53 ++++++++++++++++++++++++++++++++------------------ xml.h | 27 +++++++++++++++++-------- 7 files changed, 140 insertions(+), 116 deletions(-) Daniel diff -r 4dbf0dba3661 src/domain_conf.c --- a/src/domain_conf.c Thu Jul 03 16:50:15 2008 +0100 +++ b/src/domain_conf.c Thu Jul 03 16:50:19 2008 +0100 @@ -1291,7 +1291,7 @@ int *val, int defaultVal) { - char *tmp = virXPathString(xpath, ctxt); + char *tmp = virXPathString(conn, xpath, ctxt); if (tmp == NULL) { *val = defaultVal; } else { @@ -1385,7 +1385,7 @@ def->id = -1; /* Find out what type of QEMU virtualization to use */ - if (!(tmp = virXPathString("string(./@type)", ctxt))) { + if (!(tmp = virXPathString(conn, "string(./@type)", ctxt))) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("missing domain type attribute")); goto error; @@ -1399,13 +1399,13 @@ VIR_FREE(tmp); /* Extract domain name */ - if (!(def->name = virXPathString("string(./name[1])", ctxt))) { + if (!(def->name = virXPathString(conn, "string(./name[1])", ctxt))) { virDomainReportError(conn, VIR_ERR_NO_NAME, NULL); goto error; } /* Extract domain uuid */ - tmp = virXPathString("string(./uuid[1])", ctxt); + tmp = virXPathString(conn, "string(./uuid[1])", ctxt); if (!tmp) { int err; if ((err = virUUIDGenerate(def->uuid))) { @@ -1424,19 +1424,19 @@ } /* Extract domain memory */ - if (virXPathULong("string(./memory[1])", ctxt, &def->maxmem) < 0) { + if (virXPathULong(conn, "string(./memory[1])", ctxt, &def->maxmem) < 0) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("missing memory element")); goto error; } - if (virXPathULong("string(./currentMemory[1])", ctxt, &def->memory) < 0) + if (virXPathULong(conn, "string(./currentMemory[1])", ctxt, &def->memory) < 0) def->memory = def->maxmem; - if (virXPathULong("string(./vcpu[1])", ctxt, &def->vcpus) < 0) + if (virXPathULong(conn, "string(./vcpu[1])", ctxt, &def->vcpus) < 0) def->vcpus = 1; - tmp = virXPathString("string(./vcpu[1]/@cpuset)", ctxt); + tmp = virXPathString(conn, "string(./vcpu[1]/@cpuset)", ctxt); if (tmp) { char *set = tmp; def->cpumasklen = VIR_DOMAIN_CPUMASK_LEN; @@ -1451,7 +1451,7 @@ VIR_FREE(tmp); } - if ((n = virXPathNodeSet("./features/*", ctxt, &nodes)) > 0) { + if ((n = virXPathNodeSet(conn, "./features/*", ctxt, &nodes)) > 0) { for (i = 0 ; i < n ; i++) { int val = virDomainFeatureTypeFromString((const char *)nodes[i]->name); if (val < 0) { @@ -1478,15 +1478,15 @@ goto error; - tmp = virXPathString("string(./clock/@offset)", ctxt); + tmp = virXPathString(conn, "string(./clock/@offset)", ctxt); if (tmp && STREQ(tmp, "localtime")) def->localtime = 1; VIR_FREE(tmp); - def->os.bootloader = virXPathString("string(./bootloader)", ctxt); - def->os.bootloaderArgs = virXPathString("string(./bootloader_args)", ctxt); + def->os.bootloader = virXPathString(conn, "string(./bootloader)", ctxt); + def->os.bootloaderArgs = virXPathString(conn, "string(./bootloader_args)", ctxt); - def->os.type = virXPathString("string(./os/type[1])", ctxt); + def->os.type = virXPathString(conn, "string(./os/type[1])", ctxt); if (!def->os.type) { if (def->os.bootloader) { def->os.type = strdup("xen"); @@ -1520,7 +1520,7 @@ goto error; } - def->os.arch = virXPathString("string(./os/type[1]/@arch)", ctxt); + def->os.arch = virXPathString(conn, "string(./os/type[1]/@arch)", ctxt); if (!def->os.arch) { const char *defaultArch = virCapabilitiesDefaultGuestArch(caps, def->os.type); if (defaultArch == NULL) { @@ -1535,7 +1535,7 @@ } } - def->os.machine = virXPathString("string(./os/type[1]/@machine)", ctxt); + def->os.machine = virXPathString(conn, "string(./os/type[1]/@machine)", ctxt); if (!def->os.machine) { const char *defaultMachine = virCapabilitiesDefaultGuestMachine(caps, def->os.type, @@ -1549,14 +1549,14 @@ } if (!def->os.bootloader) { - def->os.kernel = virXPathString("string(./os/kernel[1])", ctxt); - def->os.initrd = virXPathString("string(./os/initrd[1])", ctxt); - def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt); - def->os.root = virXPathString("string(./os/root[1])", ctxt); - def->os.loader = virXPathString("string(./os/loader[1])", ctxt); + def->os.kernel = virXPathString(conn, "string(./os/kernel[1])", ctxt); + def->os.initrd = virXPathString(conn, "string(./os/initrd[1])", ctxt); + def->os.cmdline = virXPathString(conn, "string(./os/cmdline[1])", ctxt); + def->os.root = virXPathString(conn, "string(./os/root[1])", ctxt); + def->os.loader = virXPathString(conn, "string(./os/loader[1])", ctxt); /* analysis of the boot devices */ - if ((n = virXPathNodeSet("./os/boot", ctxt, &nodes)) < 0) { + if ((n = virXPathNodeSet(conn, "./os/boot", ctxt, &nodes)) < 0) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot extract boot device")); goto error; @@ -1586,7 +1586,7 @@ VIR_FREE(nodes); } - def->emulator = virXPathString("string(./devices/emulator[1])", ctxt); + def->emulator = virXPathString(conn, "string(./devices/emulator[1])", ctxt); if (!def->emulator) { const char *type = virDomainVirtTypeToString(def->virtType); if (!type) { @@ -1610,7 +1610,7 @@ } /* analysis of the disk devices */ - if ((n = virXPathNodeSet("./devices/disk", ctxt, &nodes)) < 0) { + if ((n = virXPathNodeSet(conn, "./devices/disk", ctxt, &nodes)) < 0) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot extract disk devices")); goto error; @@ -1640,7 +1640,7 @@ VIR_FREE(nodes); /* analysis of the network devices */ - if ((n = virXPathNodeSet("./devices/interface", ctxt, &nodes)) < 0) { + if ((n = virXPathNodeSet(conn, "./devices/interface", ctxt, &nodes)) < 0) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot extract network devices")); goto error; @@ -1658,7 +1658,7 @@ /* analysis of the character devices */ - if ((n = virXPathNodeSet("./devices/parallel", ctxt, &nodes)) < 0) { + if ((n = virXPathNodeSet(conn, "./devices/parallel", ctxt, &nodes)) < 0) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot extract parallel devices")); goto error; @@ -1675,7 +1675,7 @@ } VIR_FREE(nodes); - if ((n = virXPathNodeSet("./devices/serial", ctxt, &nodes)) < 0) { + if ((n = virXPathNodeSet(conn, "./devices/serial", ctxt, &nodes)) < 0) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot extract serial devices")); goto error; @@ -1697,7 +1697,7 @@ * devices which is the legacy syntax for the same thing */ if (def->serials == NULL) { - if ((node = virXPathNode("./devices/console[1]", ctxt)) != NULL) { + if ((node = virXPathNode(conn, "./devices/console[1]", ctxt)) != NULL) { virDomainChrDefPtr chr = virDomainChrDefParseXML(conn, node); if (!chr) @@ -1719,7 +1719,7 @@ /* analysis of the input devices */ - if ((n = virXPathNodeSet("./devices/input", ctxt, &nodes)) < 0) { + if ((n = virXPathNodeSet(conn, "./devices/input", ctxt, &nodes)) < 0) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot extract input devices")); goto error; @@ -1751,7 +1751,7 @@ VIR_FREE(nodes); /* analysis of the input devices */ - if ((n = virXPathNodeSet("./devices/graphics", ctxt, &nodes)) < 0) { + if ((n = virXPathNodeSet(conn, "./devices/graphics", ctxt, &nodes)) < 0) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot extract graphics devices")); goto error; @@ -1787,7 +1787,7 @@ /* analysis of the sound devices */ - if ((n = virXPathNodeSet("./devices/sound", ctxt, &nodes)) < 0) { + if ((n = virXPathNodeSet(conn, "./devices/sound", ctxt, &nodes)) < 0) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot extract sound devices")); goto error; diff -r 4dbf0dba3661 src/lxc_conf.c --- a/src/lxc_conf.c Thu Jul 03 16:50:15 2008 +0100 +++ b/src/lxc_conf.c Thu Jul 03 16:50:19 2008 +0100 @@ -210,7 +210,7 @@ DEBUG0("parsing nets"); - res = virXPathNodeSet("/domain/devices/interface", contextPtr, &list); + res = virXPathNodeSet(conn, "/domain/devices/interface", contextPtr, &list); if (res > 0) { for (i = 0; i < res; ++i) { netDef = calloc(1, sizeof(lxc_net_def_t)); @@ -338,7 +338,7 @@ { char *res; - res = virXPathString("string(/domain/name[1])", contextPtr); + res = virXPathString(conn, "string(/domain/name[1])", contextPtr); if (res == NULL) { lxcError(conn, NULL, VIR_ERR_NO_NAME, NULL); return(-1); @@ -353,7 +353,7 @@ { char *res; - res = virXPathString("string(/domain/uuid[1])", contextPtr); + res = virXPathString(conn, "string(/domain/uuid[1])", contextPtr); if (res == NULL) { if (virUUIDGenerate(uuid)) { lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, @@ -384,7 +384,7 @@ xmlNodePtr *list; int res; - res = virXPathNodeSet("/domain/devices/filesystem", contextPtr, &list); + res = virXPathNodeSet(conn, "/domain/devices/filesystem", contextPtr, &list); if (res > 0) { for (i = 0; i < res; ++i) { if (VIR_ALLOC(mountObj) < 0) { @@ -422,7 +422,7 @@ { char *res; - res = virXPathString("string(/domain/os/init[1])", contextPtr); + res = virXPathString(conn, "string(/domain/os/init[1])", contextPtr); if (res == NULL) { lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, _("invalid or missing init element")); @@ -446,7 +446,7 @@ { char *res; - res = virXPathString("string(/domain/devices/console[1]/@tty)", contextPtr); + res = virXPathString(conn, "string(/domain/devices/console[1]/@tty)", contextPtr); if (res == NULL) { /* make sure the tty string is empty */ *tty = strdup(""); @@ -466,7 +466,7 @@ long res; int rc; - rc = virXPathLong("string(/domain/memory[1])", contextPtr, &res); + rc = virXPathLong(conn, "string(/domain/memory[1])", contextPtr, &res); if ((rc == -2) || ((rc == 0) && (res <= 0))) { *memory = -1; lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, diff -r 4dbf0dba3661 src/network_conf.c --- a/src/network_conf.c Thu Jul 03 16:50:15 2008 +0100 +++ b/src/network_conf.c Thu Jul 03 16:50:19 2008 +0100 @@ -239,14 +239,14 @@ } /* Extract network name */ - def->name = virXPathString("string(./name[1])", ctxt); + def->name = virXPathString(conn, "string(./name[1])", ctxt); if (!def->name) { virNetworkReportError(conn, VIR_ERR_NO_NAME, NULL); goto error; } /* Extract network uuid */ - tmp = virXPathString("string(./uuid[1])", ctxt); + tmp = virXPathString(conn, "string(./uuid[1])", ctxt); if (!tmp) { int err; if ((err = virUUIDGenerate(def->uuid))) { @@ -265,16 +265,16 @@ } /* Parse bridge information */ - def->bridge = virXPathString("string(./bridge[1]/@name)", ctxt); - tmp = virXPathString("string(./bridge[1]/@stp)", ctxt); + def->bridge = virXPathString(conn, "string(./bridge[1]/@name)", ctxt); + tmp = virXPathString(conn, "string(./bridge[1]/@stp)", ctxt); def->stp = (tmp && STREQ(tmp, "off")) ? 0 : 1; VIR_FREE(tmp); - if (virXPathULong("string(./bridge[1]/@delay)", ctxt, &def->delay) < 0) + if (virXPathULong(conn, "string(./bridge[1]/@delay)", ctxt, &def->delay) < 0) def->delay = 0; - def->ipAddress = virXPathString("string(./ip[1]/@address)", ctxt); - def->netmask = virXPathString("string(./ip[1]/@netmask)", ctxt); + def->ipAddress = virXPathString(conn, "string(./ip[1]/@address)", ctxt); + def->netmask = virXPathString(conn, "string(./ip[1]/@netmask)", ctxt); if (def->ipAddress && def->netmask) { /* XXX someday we want IPv6 too, so inet_aton won't work there */ @@ -303,14 +303,14 @@ goto error; } - if ((dhcp = virXPathNode("./ip[1]/dhcp[1]", ctxt)) && + if ((dhcp = virXPathNode(conn, "./ip[1]/dhcp[1]", ctxt)) && virNetworkDHCPRangeDefParseXML(conn, def, dhcp) < 0) goto error; } /* IPv4 forwarding setup */ - if (virXPathBoolean("count(./forward) > 0", ctxt)) { + if (virXPathBoolean(conn, "count(./forward) > 0", ctxt)) { if (!def->ipAddress || !def->netmask) { virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, @@ -318,7 +318,7 @@ goto error; } - tmp = virXPathString("string(./forward[1]/@mode)", ctxt); + tmp = virXPathString(conn, "string(./forward[1]/@mode)", ctxt); if (tmp) { if ((def->forwardType = virNetworkForwardTypeFromString(tmp)) < 0) { virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, @@ -332,7 +332,7 @@ } - def->forwardDev = virXPathString("string(./forward[1]/@dev)", ctxt); + def->forwardDev = virXPathString(conn, "string(./forward[1]/@dev)", ctxt); } else { def->forwardType = VIR_NETWORK_FORWARD_NONE; } diff -r 4dbf0dba3661 src/storage_conf.c --- a/src/storage_conf.c Thu Jul 03 16:50:15 2008 +0100 +++ b/src/storage_conf.c Thu Jul 03 16:50:19 2008 +0100 @@ -149,14 +149,14 @@ virStoragePoolDefParseAuthChap(virConnectPtr conn, xmlXPathContextPtr ctxt, virStoragePoolAuthChapPtr auth) { - auth->login = virXPathString("string(/pool/source/auth/@login)", ctxt); + auth->login = virXPathString(conn, "string(/pool/source/auth/@login)", ctxt); if (auth->login == NULL) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("missing auth host attribute")); return -1; } - auth->passwd = virXPathString("string(/pool/source/auth/@passwd)", ctxt); + auth->passwd = virXPathString(conn, "string(/pool/source/auth/@passwd)", ctxt); if (auth->passwd == NULL) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("missing auth passwd attribute")); @@ -174,7 +174,7 @@ char *mode; long v; - mode = virXPathString("string(/pool/permissions/mode)", ctxt); + mode = virXPathString(conn, "string(/pool/permissions/mode)", ctxt); if (!mode) { perms->mode = 0700; } else { @@ -187,10 +187,10 @@ } } - if (virXPathNode("/pool/permissions/owner", ctxt) == NULL) { + if (virXPathNode(conn, "/pool/permissions/owner", ctxt) == NULL) { perms->uid = getuid(); } else { - if (virXPathLong("number(/pool/permissions/owner)", ctxt, &v) < 0) { + if (virXPathLong(conn, "number(/pool/permissions/owner)", ctxt, &v) < 0) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("malformed owner element")); return -1; @@ -198,10 +198,10 @@ perms->uid = (int)v; } - if (virXPathNode("/pool/permissions/group", ctxt) == NULL) { + if (virXPathNode(conn, "/pool/permissions/group", ctxt) == NULL) { perms->uid = getgid(); } else { - if (virXPathLong("number(/pool/permissions/group)", ctxt, &v) < 0) { + if (virXPathLong(conn, "number(/pool/permissions/group)", ctxt, &v) < 0) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("malformed group element")); return -1; @@ -210,7 +210,7 @@ } /* NB, we're ignoring missing labels here - they'll simply inherit */ - perms->label = virXPathString("string(/pool/permissions/label)", ctxt); + perms->label = virXPathString(conn, "string(/pool/permissions/label)", ctxt); return 0; } @@ -248,13 +248,13 @@ goto cleanup; } - if ((ret->name = virXPathString("string(/pool/name)", ctxt)) == NULL) { + if ((ret->name = virXPathString(conn, "string(/pool/name)", ctxt)) == NULL) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("missing name element")); goto cleanup; } - uuid = virXPathString("string(/pool/uuid)", ctxt); + uuid = virXPathString(conn, "string(/pool/uuid)", ctxt); if (uuid == NULL) { if (virUUIDGenerate(ret->uuid) < 0) { virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, @@ -271,7 +271,7 @@ } if (options->formatFromString) { - char *format = virXPathString("string(/pool/source/format/@type)", ctxt); + char *format = virXPathString(conn, "string(/pool/source/format/@type)", ctxt); if ((ret->source.format = (options->formatFromString)(conn, format)) < 0) { VIR_FREE(format); goto cleanup; @@ -280,7 +280,7 @@ } if (options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_HOST) { - if ((ret->source.host.name = virXPathString("string(/pool/source/host/@name)", ctxt)) == NULL) { + if ((ret->source.host.name = virXPathString(conn, "string(/pool/source/host/@name)", ctxt)) == NULL) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("missing source host name")); goto cleanup; @@ -290,7 +290,7 @@ xmlNodePtr *nodeset = NULL; int nsource, i; - if ((nsource = virXPathNodeSet("/pool/source/device", ctxt, &nodeset)) <= 0) { + if ((nsource = virXPathNodeSet(conn, "/pool/source/device", ctxt, &nodeset)) <= 0) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("cannot extract source devices")); goto cleanup; @@ -314,7 +314,7 @@ ret->source.ndevice = nsource; } if (options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_DIR) { - if ((ret->source.dir = virXPathString("string(/pool/source/dir/@path)", ctxt)) == NULL) { + if ((ret->source.dir = virXPathString(conn, "string(/pool/source/dir/@path)", ctxt)) == NULL) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("missing source path")); goto cleanup; @@ -322,7 +322,7 @@ } - authType = virXPathString("string(/pool/source/auth/@type)", ctxt); + authType = virXPathString(conn, "string(/pool/source/auth/@type)", ctxt); if (authType == NULL) { ret->source.authType = VIR_STORAGE_POOL_AUTH_NONE; } else { @@ -343,7 +343,7 @@ goto cleanup; } - if ((ret->target.path = virXPathString("string(/pool/target/path)", ctxt)) == NULL) { + if ((ret->target.path = virXPathString(conn, "string(/pool/target/path)", ctxt)) == NULL) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("missing target path")); goto cleanup; @@ -522,7 +522,7 @@ char *mode; long v; - mode = virXPathString("string(/volume/permissions/mode)", ctxt); + mode = virXPathString(conn, "string(/volume/permissions/mode)", ctxt); if (!mode) { perms->mode = 0600; } else { @@ -535,20 +535,20 @@ } } - if (virXPathNode("/volume/permissions/owner", ctxt) == NULL) { + if (virXPathNode(conn, "/volume/permissions/owner", ctxt) == NULL) { perms->uid = getuid(); } else { - if (virXPathLong("number(/volume/permissions/owner)", ctxt, &v) < 0) { + if (virXPathLong(conn, "number(/volume/permissions/owner)", ctxt, &v) < 0) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("missing owner element")); return -1; } perms->uid = (int)v; } - if (virXPathNode("/volume/permissions/group", ctxt) == NULL) { + if (virXPathNode(conn, "/volume/permissions/group", ctxt) == NULL) { perms->gid = getgid(); } else { - if (virXPathLong("number(/volume/permissions/group)", ctxt, &v) < 0) { + if (virXPathLong(conn, "number(/volume/permissions/group)", ctxt, &v) < 0) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("missing owner element")); return -1; @@ -557,7 +557,7 @@ } /* NB, we're ignoring missing labels here - they'll simply inherit */ - perms->label = virXPathString("string(/volume/permissions/label)", ctxt); + perms->label = virXPathString(conn, "string(/volume/permissions/label)", ctxt); return 0; } @@ -662,7 +662,7 @@ goto cleanup; } - ret->name = virXPathString("string(/volume/name)", ctxt); + ret->name = virXPathString(conn, "string(/volume/name)", ctxt); if (ret->name == NULL) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("missing name element")); @@ -670,10 +670,10 @@ } /* Auto-generated so deliberately ignore */ - /*ret->key = virXPathString("string(/volume/key)", ctxt);*/ + /*ret->key = virXPathString(conn, "string(/volume/key)", ctxt);*/ - capacity = virXPathString("string(/volume/capacity)", ctxt); - unit = virXPathString("string(/volume/capacity/@unit)", ctxt); + capacity = virXPathString(conn, "string(/volume/capacity)", ctxt); + unit = virXPathString(conn, "string(/volume/capacity/@unit)", ctxt); if (capacity == NULL) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("missing capacity element")); @@ -684,9 +684,9 @@ VIR_FREE(capacity); VIR_FREE(unit); - allocation = virXPathString("string(/volume/allocation)", ctxt); + allocation = virXPathString(conn, "string(/volume/allocation)", ctxt); if (allocation) { - unit = virXPathString("string(/volume/allocation/@unit)", ctxt); + unit = virXPathString(conn, "string(/volume/allocation/@unit)", ctxt); if (virStorageSize(conn, unit, allocation, &ret->allocation) < 0) goto cleanup; VIR_FREE(allocation); @@ -695,9 +695,9 @@ ret->allocation = ret->capacity; } - ret->target.path = virXPathString("string(/volume/target/path)", ctxt); + ret->target.path = virXPathString(conn, "string(/volume/target/path)", ctxt); if (options->formatFromString) { - char *format = virXPathString("string(/volume/target/format/@type)", ctxt); + char *format = virXPathString(conn, "string(/volume/target/format/@type)", ctxt); if ((ret->target.format = (options->formatFromString)(conn, format)) < 0) { VIR_FREE(format); goto cleanup; diff -r 4dbf0dba3661 src/test.c --- a/src/test.c Thu Jul 03 16:50:15 2008 +0100 +++ b/src/test.c Thu Jul 03 16:50:19 2008 +0100 @@ -362,7 +362,7 @@ memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo)); nodeInfo = &privconn->nodeInfo; - ret = virXPathLong("string(/node/cpu/nodes[1])", ctxt, &l); + ret = virXPathLong(conn, "string(/node/cpu/nodes[1])", ctxt, &l); if (ret == 0) { nodeInfo->nodes = l; } else if (ret == -2) { @@ -370,7 +370,7 @@ goto error; } - ret = virXPathLong("string(/node/cpu/sockets[1])", ctxt, &l); + ret = virXPathLong(conn, "string(/node/cpu/sockets[1])", ctxt, &l); if (ret == 0) { nodeInfo->sockets = l; } else if (ret == -2) { @@ -378,7 +378,7 @@ goto error; } - ret = virXPathLong("string(/node/cpu/cores[1])", ctxt, &l); + ret = virXPathLong(conn, "string(/node/cpu/cores[1])", ctxt, &l); if (ret == 0) { nodeInfo->cores = l; } else if (ret == -2) { @@ -386,7 +386,7 @@ goto error; } - ret = virXPathLong("string(/node/cpu/threads[1])", ctxt, &l); + ret = virXPathLong(conn, "string(/node/cpu/threads[1])", ctxt, &l); if (ret == 0) { nodeInfo->threads = l; } else if (ret == -2) { @@ -395,7 +395,7 @@ } nodeInfo->cpus = nodeInfo->cores * nodeInfo->threads * nodeInfo->sockets * nodeInfo->nodes; - ret = virXPathLong("string(/node/cpu/active[1])", ctxt, &l); + ret = virXPathLong(conn, "string(/node/cpu/active[1])", ctxt, &l); if (ret == 0) { if (l < nodeInfo->cpus) { nodeInfo->cpus = l; @@ -404,7 +404,7 @@ testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node active cpu")); goto error; } - ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l); + ret = virXPathLong(conn, "string(/node/cpu/mhz[1])", ctxt, &l); if (ret == 0) { nodeInfo->mhz = l; } else if (ret == -2) { @@ -412,14 +412,14 @@ goto error; } - str = virXPathString("string(/node/cpu/model[1])", ctxt); + str = virXPathString(conn, "string(/node/cpu/model[1])", ctxt); if (str != NULL) { strncpy(nodeInfo->model, str, sizeof(nodeInfo->model)-1); nodeInfo->model[sizeof(nodeInfo->model)-1] = '\0'; VIR_FREE(str); } - ret = virXPathLong("string(/node/memory[1])", ctxt, &l); + ret = virXPathLong(conn, "string(/node/memory[1])", ctxt, &l); if (ret == 0) { nodeInfo->memory = l; } else if (ret == -2) { @@ -427,7 +427,7 @@ goto error; } - ret = virXPathNodeSet("/node/domain", ctxt, &domains); + ret = virXPathNodeSet(conn, "/node/domain", ctxt, &domains); if (ret < 0) { testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node domain list")); goto error; @@ -466,7 +466,7 @@ domains = NULL; } - ret = virXPathNodeSet("/node/network", ctxt, &networks); + ret = virXPathNodeSet(conn, "/node/network", ctxt, &networks); if (ret < 0) { testError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, _("node network list")); goto error; diff -r 4dbf0dba3661 src/xml.c --- a/src/xml.c Thu Jul 03 16:50:15 2008 +0100 +++ b/src/xml.c Thu Jul 03 16:50:19 2008 +0100 @@ -22,8 +22,6 @@ #include "buf.h" #include "util.h" #include "memory.h" -#include "xend_internal.h" /* for is_sound_* functions */ - /** * virXMLError: @@ -66,14 +64,16 @@ * if the evaluation failed. */ char * -virXPathString(const char *xpath, xmlXPathContextPtr ctxt) +virXPathString(virConnectPtr conn, + const char *xpath, + xmlXPathContextPtr ctxt) { xmlXPathObjectPtr obj; xmlNodePtr relnode; char *ret; if ((ctxt == NULL) || (xpath == NULL)) { - virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, + virXMLError(conn, VIR_ERR_INTERNAL_ERROR, _("Invalid parameter to virXPathString()"), 0); return (NULL); } @@ -87,7 +87,7 @@ ret = strdup((char *) obj->stringval); xmlXPathFreeObject(obj); if (ret == NULL) { - virXMLError(NULL, VIR_ERR_NO_MEMORY, _("strdup failed"), 0); + virXMLError(conn, VIR_ERR_NO_MEMORY, _("strdup failed"), 0); } ctxt->node = relnode; return (ret); @@ -105,13 +105,16 @@ * or -1 if the evaluation failed. */ int -virXPathNumber(const char *xpath, xmlXPathContextPtr ctxt, double *value) +virXPathNumber(virConnectPtr conn, + const char *xpath, + xmlXPathContextPtr ctxt, + double *value) { xmlXPathObjectPtr obj; xmlNodePtr relnode; if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) { - virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, + virXMLError(conn, VIR_ERR_INTERNAL_ERROR, _("Invalid parameter to virXPathNumber()"), 0); return (-1); } @@ -143,14 +146,17 @@ * value doesn't have a long format. */ int -virXPathLong(const char *xpath, xmlXPathContextPtr ctxt, long *value) +virXPathLong(virConnectPtr conn, + const char *xpath, + xmlXPathContextPtr ctxt, + long *value) { xmlXPathObjectPtr obj; xmlNodePtr relnode; int ret = 0; if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) { - virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, + virXMLError(conn, VIR_ERR_INTERNAL_ERROR, _("Invalid parameter to virXPathNumber()"), 0); return (-1); } @@ -195,14 +201,17 @@ * value doesn't have a long format. */ int -virXPathULong(const char *xpath, xmlXPathContextPtr ctxt, unsigned long *value) +virXPathULong(virConnectPtr conn, + const char *xpath, + xmlXPathContextPtr ctxt, + unsigned long *value) { xmlXPathObjectPtr obj; xmlNodePtr relnode; int ret = 0; if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) { - virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, + virXMLError(conn, VIR_ERR_INTERNAL_ERROR, _("Invalid parameter to virXPathNumber()"), 0); return (-1); } @@ -251,14 +260,16 @@ * Returns 0 if false, 1 if true, or -1 if the evaluation failed. */ int -virXPathBoolean(const char *xpath, xmlXPathContextPtr ctxt) +virXPathBoolean(virConnectPtr conn, + const char *xpath, + xmlXPathContextPtr ctxt) { xmlXPathObjectPtr obj; xmlNodePtr relnode; int ret; if ((ctxt == NULL) || (xpath == NULL)) { - virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, + virXMLError(conn, VIR_ERR_INTERNAL_ERROR, _("Invalid parameter to virXPathBoolean()"), 0); return (-1); } @@ -287,14 +298,16 @@ * Returns a pointer to the node or NULL if the evaluation failed. */ xmlNodePtr -virXPathNode(const char *xpath, xmlXPathContextPtr ctxt) +virXPathNode(virConnectPtr conn, + const char *xpath, + xmlXPathContextPtr ctxt) { xmlXPathObjectPtr obj; xmlNodePtr relnode; xmlNodePtr ret; if ((ctxt == NULL) || (xpath == NULL)) { - virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, + virXMLError(conn, VIR_ERR_INTERNAL_ERROR, _("Invalid parameter to virXPathNode()"), 0); return (NULL); } @@ -326,15 +339,17 @@ * must be freed) or -1 if the evaluation failed. */ int -virXPathNodeSet(const char *xpath, xmlXPathContextPtr ctxt, - xmlNodePtr ** list) +virXPathNodeSet(virConnectPtr conn, + const char *xpath, + xmlXPathContextPtr ctxt, + xmlNodePtr **list) { xmlXPathObjectPtr obj; xmlNodePtr relnode; int ret; if ((ctxt == NULL) || (xpath == NULL)) { - virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, + virXMLError(conn, VIR_ERR_INTERNAL_ERROR, _("Invalid parameter to virXPathNodeSet()"), 0); return (-1); } @@ -354,7 +369,7 @@ ret = obj->nodesetval->nodeNr; if (list != NULL && ret) { if (VIR_ALLOC_N(*list, ret) < 0) { - virXMLError(NULL, VIR_ERR_NO_MEMORY, + virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate string array"), ret * sizeof(**list)); ret = -1; diff -r 4dbf0dba3661 src/xml.h --- a/src/xml.h Thu Jul 03 16:50:15 2008 +0100 +++ b/src/xml.h Thu Jul 03 16:50:19 2008 +0100 @@ -11,28 +11,37 @@ #include <libxml/tree.h> #include <libxml/xpath.h> -int virXPathBoolean (const char *xpath, +int virXPathBoolean (virConnectPtr conn, + const char *xpath, xmlXPathContextPtr ctxt); -char * virXPathString (const char *xpath, +char * virXPathString (virConnectPtr conn, + const char *xpath, xmlXPathContextPtr ctxt); -int virXPathNumber (const char *xpath, +int virXPathNumber (virConnectPtr conn, + const char *xpath, xmlXPathContextPtr ctxt, double *value); -int virXPathInt (const char *xpath, +int virXPathInt (virConnectPtr conn, + const char *xpath, xmlXPathContextPtr ctxt, int *value); -int virXPathUInt (const char *xpath, +int virXPathUInt (virConnectPtr conn, + const char *xpath, xmlXPathContextPtr ctxt, unsigned int *value); -int virXPathLong (const char *xpath, +int virXPathLong (virConnectPtr conn, + const char *xpath, xmlXPathContextPtr ctxt, long *value); -int virXPathULong (const char *xpath, +int virXPathULong (virConnectPtr conn, + const char *xpath, xmlXPathContextPtr ctxt, unsigned long *value); -xmlNodePtr virXPathNode (const char *xpath, +xmlNodePtr virXPathNode (virConnectPtr conn, + const char *xpath, xmlXPathContextPtr ctxt); -int virXPathNodeSet (const char *xpath, +int virXPathNodeSet (virConnectPtr conn, + const char *xpath, xmlXPathContextPtr ctxt, xmlNodePtr **list); -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Tue, Jul 08, 2008 at 05:42:36PM +0100, Daniel P. Berrange wrote:
The generic XML parsing routines can generate various errors. We were not passing a virConnectPtr object into any of them, so the errors were not propagated back to the calling app correctly. This fixes that problem
Excellent, yes, hopefully we will always have a connection pointer available in a libvirt context. okay rather trivial, i just hope there isn't too much conde not yet submitted using the xml.h API in the old way, +1 Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

On Tue, Jul 08, 2008 at 05:31:13PM +0100, Daniel P. Berrange wrote:
The following series of patchs provide a generic XML parser and formatter for the network and domain XML config formats. They then switch over the test, qemu, Xend and XM drivers to these APIs.
Patches 1-> 7 are now applied to CVS. This covers everything except for the XenD / XM driver re-factoring which hasn't really been reviewed yet Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
participants (4)
-
Daniel P. Berrange
-
Daniel Veillard
-
Jim Meyering
-
Stefan de Konink