Move the code for handling the QEMU virDomainObjPtr private data, and custom XML namespace into a separate file * src/qemu/qemu_domain.c, src/qemu/qemu_domain.h: New file for private data & namespace code * src/qemu/qemu_driver.c, src/qemu/qemu_driver.h: Remove private data & namespace code * src/qemu/qemu_driver.h, src/qemu/qemu_command.h: Update includes * src/Makefile.am: Add src/qemu/qemu_domain.c --- src/Makefile.am | 1 + src/qemu/qemu_command.h | 1 + src/qemu/qemu_conf.h | 3 - src/qemu/qemu_domain.c | 374 +++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_domain.h | 83 +++++++++++ src/qemu/qemu_driver.c | 329 +----------------------------------------- src/qemu/qemu_driver.h | 9 - 7 files changed, 461 insertions(+), 339 deletions(-) create mode 100644 src/qemu/qemu_domain.c create mode 100644 src/qemu/qemu_domain.h diff --git a/src/Makefile.am b/src/Makefile.am index d4626d9..d2fcd5f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -269,6 +269,7 @@ VBOX_DRIVER_EXTRA_DIST = vbox/vbox_tmpl.c vbox/README QEMU_DRIVER_SOURCES = \ qemu/qemu_capabilities.c qemu/qemu_capabilities.h\ qemu/qemu_command.c qemu/qemu_command.h \ + qemu/qemu_domain.c qemu/qemu_domain.h \ qemu/qemu_conf.c qemu/qemu_conf.h \ qemu/qemu_monitor.c qemu/qemu_monitor.h \ qemu/qemu_monitor_text.c \ diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index da35d3b..5545e54 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -28,6 +28,7 @@ #include "command.h" #include "capabilities.h" #include "qemu_conf.h" +#include "qemu_domain.h" /* Config type for XML import/export conversions */ # define QEMU_CONFIG_FORMAT_ARGV "qemu-argv" diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index eac8603..4c61891 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -130,9 +130,6 @@ struct qemud_driver { virSysinfoDefPtr hostsysinfo; }; -typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet; -typedef qemuDomainPCIAddressSet *qemuDomainPCIAddressSetPtr; - typedef struct _qemuDomainCmdlineDef qemuDomainCmdlineDef; typedef qemuDomainCmdlineDef *qemuDomainCmdlineDefPtr; struct _qemuDomainCmdlineDef { diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c new file mode 100644 index 0000000..14364ff --- /dev/null +++ b/src/qemu/qemu_domain.c @@ -0,0 +1,374 @@ +/* + * qemu_domain.h: QEMU domain private state + * + * Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc. + * Copyright (C) 2006 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@xxxxxxxxxx> + */ + +#include <config.h> + +#include "qemu_domain.h" +#include "qemu_command.h" +#include "memory.h" +#include "logging.h" +#include "virterror_internal.h" +#include "c-ctype.h" + +#include <libxml/xpathInternals.h> + +#define VIR_FROM_THIS VIR_FROM_QEMU + +#define QEMU_NAMESPACE_HREF "http://libvirt.org/schemas/domain/qemu/1.0" + +static void *qemuDomainObjPrivateAlloc(void) +{ + qemuDomainObjPrivatePtr priv; + + if (VIR_ALLOC(priv) < 0) + return NULL; + + return priv; +} + +static void qemuDomainObjPrivateFree(void *data) +{ + qemuDomainObjPrivatePtr priv = data; + + qemuDomainPCIAddressSetFree(priv->pciaddrs); + virDomainChrDefFree(priv->monConfig); + VIR_FREE(priv->vcpupids); + + /* This should never be non-NULL if we get here, but just in case... */ + if (priv->mon) { + VIR_ERROR0(_("Unexpected QEMU monitor still active during domain deletion")); + qemuMonitorClose(priv->mon); + } + VIR_FREE(priv); +} + + +static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data) +{ + qemuDomainObjPrivatePtr priv = data; + const char *monitorpath; + + /* priv->monitor_chr is set only for qemu */ + if (priv->monConfig) { + switch (priv->monConfig->type) { + case VIR_DOMAIN_CHR_TYPE_UNIX: + monitorpath = priv->monConfig->data.nix.path; + break; + default: + case VIR_DOMAIN_CHR_TYPE_PTY: + monitorpath = priv->monConfig->data.file.path; + break; + } + + virBufferEscapeString(buf, " <monitor path='%s'", monitorpath); + if (priv->monJSON) + virBufferAddLit(buf, " json='1'"); + virBufferVSprintf(buf, " type='%s'/>\n", + virDomainChrTypeToString(priv->monConfig->type)); + } + + + if (priv->nvcpupids) { + int i; + virBufferAddLit(buf, " <vcpus>\n"); + for (i = 0 ; i < priv->nvcpupids ; i++) { + virBufferVSprintf(buf, " <vcpu pid='%d'/>\n", priv->vcpupids[i]); + } + virBufferAddLit(buf, " </vcpus>\n"); + } + + return 0; +} + +static int qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data) +{ + qemuDomainObjPrivatePtr priv = data; + char *monitorpath; + char *tmp; + int n, i; + xmlNodePtr *nodes = NULL; + + if (VIR_ALLOC(priv->monConfig) < 0) { + virReportOOMError(); + goto error; + } + + if (!(priv->monConfig->info.alias = strdup("monitor"))) { + virReportOOMError(); + goto error; + } + + if (!(monitorpath = + virXPathString("string(./monitor[1]/@path)", ctxt))) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("no monitor path")); + goto error; + } + + tmp = virXPathString("string(./monitor[1]/@type)", ctxt); + if (tmp) + priv->monConfig->type = virDomainChrTypeFromString(tmp); + else + priv->monConfig->type = VIR_DOMAIN_CHR_TYPE_PTY; + VIR_FREE(tmp); + + if (virXPathBoolean("count(./monitor[@json = '1']) > 0", ctxt)) { + priv->monJSON = 1; + } else { + priv->monJSON = 0; + } + + switch (priv->monConfig->type) { + case VIR_DOMAIN_CHR_TYPE_PTY: + priv->monConfig->data.file.path = monitorpath; + break; + case VIR_DOMAIN_CHR_TYPE_UNIX: + priv->monConfig->data.nix.path = monitorpath; + break; + default: + VIR_FREE(monitorpath); + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("unsupported monitor type '%s'"), + virDomainChrTypeToString(priv->monConfig->type)); + goto error; + } + + n = virXPathNodeSet("./vcpus/vcpu", ctxt, &nodes); + if (n < 0) + goto error; + if (n) { + priv->nvcpupids = n; + if (VIR_REALLOC_N(priv->vcpupids, priv->nvcpupids) < 0) { + virReportOOMError(); + goto error; + } + + for (i = 0 ; i < n ; i++) { + char *pidstr = virXMLPropString(nodes[i], "pid"); + if (!pidstr) + goto error; + + if (virStrToLong_i(pidstr, NULL, 10, &(priv->vcpupids[i])) < 0) { + VIR_FREE(pidstr); + goto error; + } + VIR_FREE(pidstr); + } + VIR_FREE(nodes); + } + + return 0; + +error: + virDomainChrDefFree(priv->monConfig); + priv->monConfig = NULL; + VIR_FREE(nodes); + return -1; +} + + +static void +qemuDomainDefNamespaceFree(void *nsdata) +{ + qemuDomainCmdlineDefPtr cmd = nsdata; + unsigned int i; + + if (!cmd) + return; + + for (i = 0; i < cmd->num_args; i++) + VIR_FREE(cmd->args[i]); + for (i = 0; i < cmd->num_env; i++) { + VIR_FREE(cmd->env_name[i]); + VIR_FREE(cmd->env_value[i]); + } + VIR_FREE(cmd->args); + VIR_FREE(cmd->env_name); + VIR_FREE(cmd->env_value); + VIR_FREE(cmd); +} + +static int +qemuDomainDefNamespaceParse(xmlDocPtr xml, + xmlNodePtr root, + xmlXPathContextPtr ctxt, + void **data) +{ + qemuDomainCmdlineDefPtr cmd = NULL; + xmlNsPtr ns; + xmlNodePtr *nodes = NULL; + int n, i; + + ns = xmlSearchNs(xml, root, BAD_CAST "qemu"); + if (!ns) + /* this is fine; it just means there was no qemu namespace listed */ + return 0; + + if (STRNEQ((const char *)ns->href, QEMU_NAMESPACE_HREF)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Found namespace '%s' doesn't match expected '%s'"), + ns->href, QEMU_NAMESPACE_HREF); + return -1; + } + + if (xmlXPathRegisterNs(ctxt, ns->prefix, ns->href) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to register xml namespace '%s'"), ns->href); + return -1; + } + + if (VIR_ALLOC(cmd) < 0) { + virReportOOMError(); + return -1; + } + + /* first handle the extra command-line arguments */ + n = virXPathNodeSet("./qemu:commandline/qemu:arg", ctxt, &nodes); + if (n < 0) + /* virXPathNodeSet already set the error */ + goto error; + + if (n && VIR_ALLOC_N(cmd->args, n) < 0) + goto no_memory; + + for (i = 0; i < n; i++) { + cmd->args[cmd->num_args] = virXMLPropString(nodes[i], "value"); + if (cmd->args[cmd->num_args] == NULL) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("No qemu command-line argument specified")); + goto error; + } + cmd->num_args++; + } + + VIR_FREE(nodes); + + /* now handle the extra environment variables */ + n = virXPathNodeSet("./qemu:commandline/qemu:env", ctxt, &nodes); + if (n < 0) + /* virXPathNodeSet already set the error */ + goto error; + + if (n && VIR_ALLOC_N(cmd->env_name, n) < 0) + goto no_memory; + + if (n && VIR_ALLOC_N(cmd->env_value, n) < 0) + goto no_memory; + + for (i = 0; i < n; i++) { + char *tmp; + + tmp = virXMLPropString(nodes[i], "name"); + if (tmp == NULL) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("No qemu environment name specified")); + goto error; + } + if (tmp[0] == '\0') { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Empty qemu environment name specified")); + goto error; + } + if (!c_isalpha(tmp[0]) && tmp[0] != '_') { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Invalid environment name, it must begin with a letter or underscore")); + goto error; + } + if (strspn(tmp, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_") != strlen(tmp)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Invalid environment name, it must contain only alphanumerics and underscore")); + goto error; + } + + cmd->env_name[cmd->num_env] = tmp; + + cmd->env_value[cmd->num_env] = virXMLPropString(nodes[i], "value"); + /* a NULL value for command is allowed, since it might be empty */ + cmd->num_env++; + } + + VIR_FREE(nodes); + + *data = cmd; + + return 0; + +no_memory: + virReportOOMError(); + +error: + VIR_FREE(nodes); + qemuDomainDefNamespaceFree(cmd); + return -1; +} + +static int +qemuDomainDefNamespaceFormatXML(virBufferPtr buf, + void *nsdata) +{ + qemuDomainCmdlineDefPtr cmd = nsdata; + unsigned int i; + + if (!cmd->num_args && !cmd->num_env) + return 0; + + virBufferAddLit(buf, " <qemu:commandline>\n"); + for (i = 0; i < cmd->num_args; i++) + virBufferEscapeString(buf, " <qemu:arg value='%s'/>\n", + cmd->args[i]); + for (i = 0; i < cmd->num_env; i++) { + virBufferVSprintf(buf, " <qemu:env name='%s'", cmd->env_name[i]); + if (cmd->env_value[i]) + virBufferEscapeString(buf, " value='%s'", cmd->env_value[i]); + virBufferAddLit(buf, "/>\n"); + } + virBufferAddLit(buf, " </qemu:commandline>\n"); + + return 0; +} + +static const char * +qemuDomainDefNamespaceHref(void) +{ + return "xmlns:qemu='" QEMU_NAMESPACE_HREF "'"; +} + + +void qemuDomainSetPrivateDataHooks(virCapsPtr caps) +{ + /* Domain XML parser hooks */ + caps->privateDataAllocFunc = qemuDomainObjPrivateAlloc; + caps->privateDataFreeFunc = qemuDomainObjPrivateFree; + caps->privateDataXMLFormat = qemuDomainObjPrivateXMLFormat; + caps->privateDataXMLParse = qemuDomainObjPrivateXMLParse; + +} + +void qemuDomainSetNamespaceHooks(virCapsPtr caps) +{ + /* Domain Namespace XML parser hooks */ + caps->ns.parse = qemuDomainDefNamespaceParse; + caps->ns.free = qemuDomainDefNamespaceFree; + caps->ns.format = qemuDomainDefNamespaceFormatXML; + caps->ns.href = qemuDomainDefNamespaceHref; +} diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h new file mode 100644 index 0000000..0d1e222 --- /dev/null +++ b/src/qemu/qemu_domain.h @@ -0,0 +1,83 @@ +/* + * qemu_domain.h: QEMU domain private state + * + * Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc. + * Copyright (C) 2006 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@xxxxxxxxxx> + */ + +#ifndef __QEMU_DOMAIN_H__ +# define __QEMU_DOMAIN_H__ + +# include "threads.h" +# include "domain_conf.h" +# include "qemu_monitor.h" + +/* Only 1 job is allowed at any time + * A job includes *all* monitor commands, even those just querying + * information, not merely actions */ +enum qemuDomainJob { + QEMU_JOB_NONE = 0, /* Always set to 0 for easy if (jobActive) conditions */ + QEMU_JOB_UNSPECIFIED, + QEMU_JOB_MIGRATION_OUT, + QEMU_JOB_MIGRATION_IN, + QEMU_JOB_SAVE, + QEMU_JOB_DUMP, +}; + +enum qemuDomainJobSignals { + QEMU_JOB_SIGNAL_CANCEL = 1 << 0, /* Request job cancellation */ + QEMU_JOB_SIGNAL_SUSPEND = 1 << 1, /* Request VM suspend to finish live migration offline */ + QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME = 1 << 2, /* Request migration downtime change */ +}; + +struct qemuDomainJobSignalsData { + unsigned long long migrateDowntime; /* Data for QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME */ +}; + +typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet; +typedef qemuDomainPCIAddressSet *qemuDomainPCIAddressSetPtr; + +typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate; +typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr; +struct _qemuDomainObjPrivate { + virCond jobCond; /* Use in conjunction with main virDomainObjPtr lock */ + enum qemuDomainJob jobActive; /* Currently running job */ + unsigned int jobSignals; /* Signals for running job */ + struct qemuDomainJobSignalsData jobSignalsData; /* Signal specific data */ + virDomainJobInfo jobInfo; + unsigned long long jobStart; + + qemuMonitorPtr mon; + virDomainChrDefPtr monConfig; + int monJSON; + int monitor_warned; + bool gotShutdown; + + int nvcpupids; + int *vcpupids; + + qemuDomainPCIAddressSetPtr pciaddrs; + int persistentAddrs; +}; + + +void qemuDomainSetPrivateDataHooks(virCapsPtr caps); +void qemuDomainSetNamespaceHooks(virCapsPtr caps); + +#endif /* __QEMU_DOMAIN_H__ */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0489a7a..9ce8fbe 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -47,7 +47,6 @@ #include <sys/ioctl.h> #include <sys/un.h> -#include <libxml/xpathInternals.h> #include "virterror_internal.h" #include "logging.h" @@ -96,7 +95,6 @@ #define QEMU_NB_MEM_PARAM 3 -#define QEMU_NAMESPACE_HREF "http://libvirt.org/schemas/domain/qemu/1.0" #define timeval_to_ms(tv) (((tv).tv_sec * 1000ull) + ((tv).tv_usec / 1000)) @@ -158,158 +156,6 @@ static int qemudVMFiltersInstantiate(virConnectPtr conn, static struct qemud_driver *qemu_driver = NULL; -static void *qemuDomainObjPrivateAlloc(void) -{ - qemuDomainObjPrivatePtr priv; - - if (VIR_ALLOC(priv) < 0) - return NULL; - - return priv; -} - -static void qemuDomainObjPrivateFree(void *data) -{ - qemuDomainObjPrivatePtr priv = data; - - qemuDomainPCIAddressSetFree(priv->pciaddrs); - virDomainChrDefFree(priv->monConfig); - VIR_FREE(priv->vcpupids); - - /* This should never be non-NULL if we get here, but just in case... */ - if (priv->mon) { - VIR_ERROR0(_("Unexpected QEMU monitor still active during domain deletion")); - qemuMonitorClose(priv->mon); - } - VIR_FREE(priv); -} - - -static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data) -{ - qemuDomainObjPrivatePtr priv = data; - const char *monitorpath; - - /* priv->monitor_chr is set only for qemu */ - if (priv->monConfig) { - switch (priv->monConfig->type) { - case VIR_DOMAIN_CHR_TYPE_UNIX: - monitorpath = priv->monConfig->data.nix.path; - break; - default: - case VIR_DOMAIN_CHR_TYPE_PTY: - monitorpath = priv->monConfig->data.file.path; - break; - } - - virBufferEscapeString(buf, " <monitor path='%s'", monitorpath); - if (priv->monJSON) - virBufferAddLit(buf, " json='1'"); - virBufferVSprintf(buf, " type='%s'/>\n", - virDomainChrTypeToString(priv->monConfig->type)); - } - - - if (priv->nvcpupids) { - int i; - virBufferAddLit(buf, " <vcpus>\n"); - for (i = 0 ; i < priv->nvcpupids ; i++) { - virBufferVSprintf(buf, " <vcpu pid='%d'/>\n", priv->vcpupids[i]); - } - virBufferAddLit(buf, " </vcpus>\n"); - } - - return 0; -} - -static int qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data) -{ - qemuDomainObjPrivatePtr priv = data; - char *monitorpath; - char *tmp; - int n, i; - xmlNodePtr *nodes = NULL; - - if (VIR_ALLOC(priv->monConfig) < 0) { - virReportOOMError(); - goto error; - } - - if (!(priv->monConfig->info.alias = strdup("monitor"))) { - virReportOOMError(); - goto error; - } - - if (!(monitorpath = - virXPathString("string(./monitor[1]/@path)", ctxt))) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("no monitor path")); - goto error; - } - - tmp = virXPathString("string(./monitor[1]/@type)", ctxt); - if (tmp) - priv->monConfig->type = virDomainChrTypeFromString(tmp); - else - priv->monConfig->type = VIR_DOMAIN_CHR_TYPE_PTY; - VIR_FREE(tmp); - - if (virXPathBoolean("count(./monitor[@json = '1']) > 0", ctxt)) { - priv->monJSON = 1; - } else { - priv->monJSON = 0; - } - - switch (priv->monConfig->type) { - case VIR_DOMAIN_CHR_TYPE_PTY: - priv->monConfig->data.file.path = monitorpath; - break; - case VIR_DOMAIN_CHR_TYPE_UNIX: - priv->monConfig->data.nix.path = monitorpath; - break; - default: - VIR_FREE(monitorpath); - qemuReportError(VIR_ERR_INTERNAL_ERROR, - _("unsupported monitor type '%s'"), - virDomainChrTypeToString(priv->monConfig->type)); - goto error; - } - - n = virXPathNodeSet("./vcpus/vcpu", ctxt, &nodes); - if (n < 0) - goto error; - if (n) { - priv->nvcpupids = n; - if (VIR_REALLOC_N(priv->vcpupids, priv->nvcpupids) < 0) { - virReportOOMError(); - goto error; - } - - for (i = 0 ; i < n ; i++) { - char *pidstr = virXMLPropString(nodes[i], "pid"); - if (!pidstr) - goto error; - - if (virStrToLong_i(pidstr, NULL, 10, &(priv->vcpupids[i])) < 0) { - VIR_FREE(pidstr); - goto error; - } - VIR_FREE(pidstr); - } - VIR_FREE(nodes); - } - - return 0; - -error: - virDomainChrDefFree(priv->monConfig); - priv->monConfig = NULL; - VIR_FREE(nodes); - return -1; -} - - - /* * obj must be locked before calling, qemud_driver must NOT be locked * @@ -567,168 +413,6 @@ static int doStopCPUs(struct qemud_driver *driver, virDomainObjPtr vm) return ret; } -void qemuDomainDefNamespaceFree(void *nsdata) -{ - qemuDomainCmdlineDefPtr cmd = nsdata; - unsigned int i; - - if (!cmd) - return; - - for (i = 0; i < cmd->num_args; i++) - VIR_FREE(cmd->args[i]); - for (i = 0; i < cmd->num_env; i++) { - VIR_FREE(cmd->env_name[i]); - VIR_FREE(cmd->env_value[i]); - } - VIR_FREE(cmd->args); - VIR_FREE(cmd->env_name); - VIR_FREE(cmd->env_value); - VIR_FREE(cmd); -} - -int qemuDomainDefNamespaceParse(xmlDocPtr xml, - xmlNodePtr root, - xmlXPathContextPtr ctxt, - void **data) -{ - qemuDomainCmdlineDefPtr cmd = NULL; - xmlNsPtr ns; - xmlNodePtr *nodes = NULL; - int n, i; - - ns = xmlSearchNs(xml, root, BAD_CAST "qemu"); - if (!ns) - /* this is fine; it just means there was no qemu namespace listed */ - return 0; - - if (STRNEQ((const char *)ns->href, QEMU_NAMESPACE_HREF)) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - _("Found namespace '%s' doesn't match expected '%s'"), - ns->href, QEMU_NAMESPACE_HREF); - return -1; - } - - if (xmlXPathRegisterNs(ctxt, ns->prefix, ns->href) < 0) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to register xml namespace '%s'"), ns->href); - return -1; - } - - if (VIR_ALLOC(cmd) < 0) { - virReportOOMError(); - return -1; - } - - /* first handle the extra command-line arguments */ - n = virXPathNodeSet("./qemu:commandline/qemu:arg", ctxt, &nodes); - if (n < 0) - /* virXPathNodeSet already set the error */ - goto error; - - if (n && VIR_ALLOC_N(cmd->args, n) < 0) - goto no_memory; - - for (i = 0; i < n; i++) { - cmd->args[cmd->num_args] = virXMLPropString(nodes[i], "value"); - if (cmd->args[cmd->num_args] == NULL) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("No qemu command-line argument specified")); - goto error; - } - cmd->num_args++; - } - - VIR_FREE(nodes); - - /* now handle the extra environment variables */ - n = virXPathNodeSet("./qemu:commandline/qemu:env", ctxt, &nodes); - if (n < 0) - /* virXPathNodeSet already set the error */ - goto error; - - if (n && VIR_ALLOC_N(cmd->env_name, n) < 0) - goto no_memory; - - if (n && VIR_ALLOC_N(cmd->env_value, n) < 0) - goto no_memory; - - for (i = 0; i < n; i++) { - char *tmp; - - tmp = virXMLPropString(nodes[i], "name"); - if (tmp == NULL) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("No qemu environment name specified")); - goto error; - } - if (tmp[0] == '\0') { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("Empty qemu environment name specified")); - goto error; - } - if (!c_isalpha(tmp[0]) && tmp[0] != '_') { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("Invalid environment name, it must begin with a letter or underscore")); - goto error; - } - if (strspn(tmp, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_") != strlen(tmp)) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("Invalid environment name, it must contain only alphanumerics and underscore")); - goto error; - } - - cmd->env_name[cmd->num_env] = tmp; - - cmd->env_value[cmd->num_env] = virXMLPropString(nodes[i], "value"); - /* a NULL value for command is allowed, since it might be empty */ - cmd->num_env++; - } - - VIR_FREE(nodes); - - *data = cmd; - - return 0; - -no_memory: - virReportOOMError(); - -error: - VIR_FREE(nodes); - qemuDomainDefNamespaceFree(cmd); - return -1; -} - -int qemuDomainDefNamespaceFormatXML(virBufferPtr buf, - void *nsdata) -{ - qemuDomainCmdlineDefPtr cmd = nsdata; - unsigned int i; - - if (!cmd->num_args && !cmd->num_env) - return 0; - - virBufferAddLit(buf, " <qemu:commandline>\n"); - for (i = 0; i < cmd->num_args; i++) - virBufferEscapeString(buf, " <qemu:arg value='%s'/>\n", - cmd->args[i]); - for (i = 0; i < cmd->num_env; i++) { - virBufferVSprintf(buf, " <qemu:env name='%s'", cmd->env_name[i]); - if (cmd->env_value[i]) - virBufferEscapeString(buf, " value='%s'", cmd->env_value[i]); - virBufferAddLit(buf, "/>\n"); - } - virBufferAddLit(buf, " </qemu:commandline>\n"); - - return 0; -} - -const char *qemuDomainDefNamespaceHref(void) -{ - return "xmlns:qemu='" QEMU_NAMESPACE_HREF "'"; -} - static int qemuCgroupControllerActive(struct qemud_driver *driver, int controller) { @@ -1614,11 +1298,8 @@ qemuCreateCapabilities(virCapsPtr oldcaps, caps->defaultDiskDriverType = "raw"; } - /* Domain XML parser hooks */ - caps->privateDataAllocFunc = qemuDomainObjPrivateAlloc; - caps->privateDataFreeFunc = qemuDomainObjPrivateFree; - caps->privateDataXMLFormat = qemuDomainObjPrivateXMLFormat; - caps->privateDataXMLParse = qemuDomainObjPrivateXMLParse; + qemuDomainSetPrivateDataHooks(caps); + qemuDomainSetNamespaceHooks(caps); if (virGetHostUUID(caps->host.host_uuid)) { qemuReportError(VIR_ERR_INTERNAL_ERROR, @@ -1626,12 +1307,6 @@ qemuCreateCapabilities(virCapsPtr oldcaps, goto err_exit; } - /* Domain Namespace XML parser hooks */ - caps->ns.parse = qemuDomainDefNamespaceParse; - caps->ns.free = qemuDomainDefNamespaceFree; - caps->ns.format = qemuDomainDefNamespaceFormatXML; - caps->ns.href = qemuDomainDefNamespaceHref; - /* Security driver data */ if (driver->securityPrimaryDriver) { const char *doi, *model; diff --git a/src/qemu/qemu_driver.h b/src/qemu/qemu_driver.h index 60131a7..dac0935 100644 --- a/src/qemu/qemu_driver.h +++ b/src/qemu/qemu_driver.h @@ -51,13 +51,4 @@ int qemuRegister(void); -void qemuDomainDefNamespaceFree(void *nsdata); -int qemuDomainDefNamespaceParse(xmlDocPtr xml, - xmlNodePtr root, - xmlXPathContextPtr ctxt, - void **data); -int qemuDomainDefNamespaceFormatXML(virBufferPtr buf, - void *nsdata); -const char *qemuDomainDefNamespaceHref(void); - #endif /* QEMUD_DRIVER_H */ -- 1.7.2.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list