This patches provides an implenmentation of the new APIs for Xen which can convert to/from both XM config format (/etc/xen files), and the SEXPR format used by XenD. The former is most useful to end users, but it was easy to add the latter too, so I did. It can be a useful debugging aid sometimes. For QEMU, it implemnets export of domain XML into the QEMU argv format. qemu_conf.c | 25 +++++------- qemu_conf.h | 3 + qemu_driver.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- xen_unified.c | 95 +++++++++++++++++++++++++++++++++++++++++++++- xen_unified.h | 3 + 5 files changed, 228 insertions(+), 17 deletions(-) Daniel diff -r f55fa9b69d85 src/qemu_conf.c --- a/src/qemu_conf.c Wed May 13 13:13:18 2009 +0100 +++ b/src/qemu_conf.c Wed May 13 13:16:50 2009 +0100 @@ -1248,21 +1248,18 @@ int qemudBuildCommandLine(virConnectPtr case VIR_DOMAIN_NET_TYPE_ETHERNET: { - char arg[PATH_MAX]; - if (net->ifname) { - if (snprintf(arg, PATH_MAX-1, "tap,ifname=%s,script=%s,vlan=%d", - net->ifname, - net->data.ethernet.script, - vlan) >= (PATH_MAX-1)) - goto error; - } else { - if (snprintf(arg, PATH_MAX-1, "tap,script=%s,vlan=%d", - net->data.ethernet.script, - vlan) >= (PATH_MAX-1)) - goto error; - } + virBuffer buf = VIR_BUFFER_INITIALIZER; - ADD_ARG_LIT(arg); + virBufferAddLit(&buf, "tap"); + if (net->ifname) + virBufferVSprintf(&buf, ",ifname=%s", net->ifname); + if (net->data.ethernet.script) + virBufferVSprintf(&buf, ",script=%s", net->data.ethernet.script); + virBufferVSprintf(&buf, ",vlan=%d", vlan); + if (virBufferError(&buf)) + goto error; + + ADD_ARG(virBufferContentAndReset(&buf)); } break; diff -r f55fa9b69d85 src/qemu_conf.h --- a/src/qemu_conf.h Wed May 13 13:13:18 2009 +0100 +++ b/src/qemu_conf.h Wed May 13 13:16:50 2009 +0100 @@ -106,6 +106,9 @@ struct _qemudDomainStatus { #define QEMUD_MIGRATION_FIRST_PORT 49152 #define QEMUD_MIGRATION_NUM_PORTS 64 +/* Config type for XML import/export conversions */ +#define QEMU_CONFIG_FORMAT_ARGV "qemu-argv" + #define qemudReportError(conn, dom, net, code, fmt...) \ virReportErrorHelper(conn, VIR_FROM_QEMU, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) diff -r f55fa9b69d85 src/qemu_driver.c --- a/src/qemu_driver.c Wed May 13 13:13:18 2009 +0100 +++ b/src/qemu_driver.c Wed May 13 13:16:50 2009 +0100 @@ -3423,6 +3423,123 @@ cleanup: } +static char *qemuDomainXMLToNative(virConnectPtr conn, + const char *format, + const char *xmlData, + unsigned int flags ATTRIBUTE_UNUSED) { + struct qemud_driver *driver = conn->privateData; + virDomainDefPtr def = NULL; + const char *emulator; + unsigned int qemuCmdFlags; + struct stat sb; + const char **retargv = NULL; + const char **retenv = NULL; + const char **tmp; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *ret = NULL; + int i; + + if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_ARG, + _("unsupported config type %s"), format); + goto cleanup; + } + + def = virDomainDefParseString(conn, driver->caps, xmlData, 0); + if (!def) + goto cleanup; + + /* Since we're just exporting args, we can't do bridge/network + * setups, since libvirt will normally create TAP devices + * directly. We convert those configs into generic 'ethernet' + * config and assume the user has suitable 'ifup-qemu' scripts + */ + for (i = 0 ; i < def->nnets ; i++) { + virDomainNetDefPtr net = def->nets[i]; + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + VIR_FREE(net->data.network.name); + net->type = VIR_DOMAIN_NET_TYPE_ETHERNET; + net->data.ethernet.dev = NULL; + net->data.ethernet.script = NULL; + net->data.ethernet.ipaddr = NULL; + } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { + net->type = VIR_DOMAIN_NET_TYPE_ETHERNET; + /* Rely on fact that the 'ethernet' and 'bridge' + * union structs have members in same place */ + } + } + for (i = 0 ; i < def->ngraphics ; i++) { + if (def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && + def->graphics[i]->data.vnc.autoport) + def->graphics[i]->data.vnc.port = 5900; + } + emulator = def->emulator; + if (!emulator) + emulator = virDomainDefDefaultEmulator(conn, def, driver->caps); + if (!emulator) + goto cleanup; + + /* Make sure the binary we are about to try exec'ing exists. + * 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(emulator, &sb) < 0) { + virReportSystemError(conn, errno, + _("Cannot find QEMU binary %s"), + emulator); + goto cleanup; + } + + if (qemudExtractVersionInfo(emulator, + NULL, + &qemuCmdFlags) < 0) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("Cannot determine QEMU argv syntax %s"), + emulator); + goto cleanup; + } + + + if (qemudBuildCommandLine(conn, driver, def, + qemuCmdFlags, + &retargv, &retenv, + NULL, NULL, /* Don't want it to create TAP devices */ + NULL) < 0) { + goto cleanup; + } + + tmp = retenv; + while (*tmp) { + virBufferAdd(&buf, *tmp, strlen(*tmp)); + virBufferAddLit(&buf, " "); + tmp++; + } + tmp = retargv; + while (*tmp) { + virBufferAdd(&buf, *tmp, strlen(*tmp)); + virBufferAddLit(&buf, " "); + tmp++; + } + + if (virBufferError(&buf)) + goto cleanup; + + ret = virBufferContentAndReset(&buf); + +cleanup: + for (tmp = retargv ; tmp && *tmp ; tmp++) + VIR_FREE(*tmp); + VIR_FREE(retargv); + + for (tmp = retenv ; tmp && *tmp ; tmp++) + VIR_FREE(*tmp); + VIR_FREE(retenv); + + virDomainDefFree(def); + return ret; +} + + static int qemudListDefinedDomains(virConnectPtr conn, char **const names, int nnames) { struct qemud_driver *driver = conn->privateData; @@ -5232,7 +5349,7 @@ static virDriver qemuDriver = { qemudNodeGetSecurityModel, /* nodeGetSecurityModel */ qemudDomainDumpXML, /* domainDumpXML */ NULL, /* domainXmlFromNative */ - NULL, /* domainXmlToNative */ + qemuDomainXMLToNative, /* domainXMLToNative */ qemudListDefinedDomains, /* listDefinedDomains */ qemudNumDefinedDomains, /* numOfDefinedDomains */ qemudDomainStart, /* domainCreate */ diff -r f55fa9b69d85 src/xen_unified.c --- a/src/xen_unified.c Wed May 13 13:13:18 2009 +0100 +++ b/src/xen_unified.c Wed May 13 13:16:50 2009 +0100 @@ -1043,6 +1043,97 @@ xenUnifiedDomainDumpXML (virDomainPtr do return NULL; } + +static char * +xenUnifiedDomainXMLFromNative(virConnectPtr conn, + const char *format, + const char *config, + unsigned int flags ATTRIBUTE_UNUSED) +{ + virDomainDefPtr def = NULL; + char *ret = NULL; + virConfPtr conf = NULL; + GET_PRIVATE(conn); + + if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) && + STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) { + xenUnifiedError(conn, VIR_ERR_INVALID_ARG, + _("unsupported config type %s"), format); + return NULL; + } + + if (STREQ(format, XEN_CONFIG_FORMAT_XM)) { + conf = virConfReadMem(config, strlen(config)); + if (!conf) + goto cleanup; + + def = xenXMDomainConfigParse(conn, conf); + } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) { + def = xenDaemonParseSxprString(conn, config, priv->xendConfigVersion); + } + if (!def) + goto cleanup; + + ret = virDomainDefFormat(conn, def, 0); + +cleanup: + virDomainDefFree(def); + return ret; +} + + +#define MAX_CONFIG_SIZE (1024 * 65) +static char * +xenUnifiedDomainXMLToNative(virConnectPtr conn, + const char *format, + const char *xmlData, + unsigned int flags ATTRIBUTE_UNUSED) +{ + virDomainDefPtr def = NULL; + char *ret = NULL; + virConfPtr conf = NULL; + GET_PRIVATE(conn); + + if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) && + STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) { + xenUnifiedError(conn, VIR_ERR_INVALID_ARG, + _("unsupported config type %s"), format); + goto cleanup; + } + + if (!(def = virDomainDefParseString(conn, + priv->caps, + xmlData, + 0))) + goto cleanup; + + if (STREQ(format, XEN_CONFIG_FORMAT_XM)) { + int len = MAX_CONFIG_SIZE; + conf = xenXMDomainConfigFormat(conn, def); + if (!conf) + goto cleanup; + + if (VIR_ALLOC_N(ret, len) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + if (virConfWriteMem(ret, &len, conf) < 0) { + VIR_FREE(ret); + goto cleanup; + } + } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) { + ret = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion); + } + +cleanup: + virDomainDefFree(def); + if (conf) + virConfFree(conf); + return ret; +} + + static int xenUnifiedDomainMigratePrepare (virConnectPtr dconn, char **cookie, @@ -1580,8 +1671,8 @@ static virDriver xenUnifiedDriver = { NULL, /* domainGetSecurityLabel */ NULL, /* nodeGetSecurityModel */ xenUnifiedDomainDumpXML, /* domainDumpXML */ - NULL, /* domainXmlFromNative */ - NULL, /* domainXmlToNative */ + xenUnifiedDomainXMLFromNative, /* domainXmlFromNative */ + xenUnifiedDomainXMLToNative, /* domainXmlToNative */ xenUnifiedListDefinedDomains, /* listDefinedDomains */ xenUnifiedNumOfDefinedDomains, /* numOfDefinedDomains */ xenUnifiedDomainCreate, /* domainCreate */ diff -r f55fa9b69d85 src/xen_unified.h --- a/src/xen_unified.h Wed May 13 13:13:18 2009 +0100 +++ b/src/xen_unified.h Wed May 13 13:16:50 2009 +0100 @@ -46,6 +46,9 @@ extern int xenRegister (void); #define MIN_XEN_GUEST_SIZE 64 /* 64 megabytes */ +#define XEN_CONFIG_FORMAT_XM "xen-xm" +#define XEN_CONFIG_FORMAT_SEXPR "xen-sxpr" + /* _xenUnifiedDriver: * * Entry points into the underlying Xen drivers. This structure -- |: 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 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list