+Thu May 21 14:59:22 BST 2009 Daniel P. Berrange <berrange@redhat.com>
+
+ Basic domain XML conversions
+ * src/qemu_conf.c, src/qemu_conf.h, src/qemu_driver.c: Wire up
+ API for conversion from XML to native argv
+ * src/xen_unified.c, src/xen_unified.h: Wire up API for domain
+ XML conversions to & from native
+
Thu May 21 14:48:22 BST 2009 Daniel P. Berrange <berrange@redhat.com>
Remote protocol support for domain XML conversion APIs
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;
+
+ 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_LIT(arg);
+ ADD_ARG(virBufferContentAndReset(&buf));
}
break;
#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)
}
+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);
+
+ memset(net, 0, sizeof *net);
+
+ 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) {
+ char *brname = net->data.bridge.brname;
+ char *script = net->data.bridge.script;
+ char *ipaddr = net->data.bridge.ipaddr;
+
+ memset(net, 0, sizeof *net);
+
+ net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
+ net->data.ethernet.dev = brname;
+ net->data.ethernet.script = script;
+ net->data.ethernet.ipaddr = ipaddr;
+ }
+ }
+ 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;
qemudNodeGetSecurityModel, /* nodeGetSecurityModel */
qemudDomainDumpXML, /* domainDumpXML */
NULL, /* domainXmlFromNative */
- NULL, /* domainXmlToNative */
+ qemuDomainXMLToNative, /* domainXMLToNative */
qemudListDefinedDomains, /* listDefinedDomains */
qemudNumDefinedDomains, /* numOfDefinedDomains */
qemudDomainStart, /* domainCreate */
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,
NULL, /* domainGetSecurityLabel */
NULL, /* nodeGetSecurityModel */
xenUnifiedDomainDumpXML, /* domainDumpXML */
- NULL, /* domainXmlFromNative */
- NULL, /* domainXmlToNative */
+ xenUnifiedDomainXMLFromNative, /* domainXmlFromNative */
+ xenUnifiedDomainXMLToNative, /* domainXmlToNative */
xenUnifiedListDefinedDomains, /* listDefinedDomains */
xenUnifiedNumOfDefinedDomains, /* numOfDefinedDomains */
xenUnifiedDomainCreate, /* domainCreate */
#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