Move QEMU private data & namespace code into separate file
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
This commit is contained in:
parent
0f2e4b9c68
commit
df4aabafbe
@ -54,6 +54,7 @@ src/qemu/qemu_bridge_filter.c
|
|||||||
src/qemu/qemu_capabilities.c
|
src/qemu/qemu_capabilities.c
|
||||||
src/qemu/qemu_command.c
|
src/qemu/qemu_command.c
|
||||||
src/qemu/qemu_conf.c
|
src/qemu/qemu_conf.c
|
||||||
|
src/qemu/qemu_domain.c
|
||||||
src/qemu/qemu_driver.c
|
src/qemu/qemu_driver.c
|
||||||
src/qemu/qemu_monitor.c
|
src/qemu/qemu_monitor.c
|
||||||
src/qemu/qemu_monitor_json.c
|
src/qemu/qemu_monitor_json.c
|
||||||
|
@ -269,6 +269,7 @@ VBOX_DRIVER_EXTRA_DIST = vbox/vbox_tmpl.c vbox/README
|
|||||||
QEMU_DRIVER_SOURCES = \
|
QEMU_DRIVER_SOURCES = \
|
||||||
qemu/qemu_capabilities.c qemu/qemu_capabilities.h\
|
qemu/qemu_capabilities.c qemu/qemu_capabilities.h\
|
||||||
qemu/qemu_command.c qemu/qemu_command.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_conf.c qemu/qemu_conf.h \
|
||||||
qemu/qemu_monitor.c qemu/qemu_monitor.h \
|
qemu/qemu_monitor.c qemu/qemu_monitor.h \
|
||||||
qemu/qemu_monitor_text.c \
|
qemu/qemu_monitor_text.c \
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
# include "command.h"
|
# include "command.h"
|
||||||
# include "capabilities.h"
|
# include "capabilities.h"
|
||||||
# include "qemu_conf.h"
|
# include "qemu_conf.h"
|
||||||
|
# include "qemu_domain.h"
|
||||||
|
|
||||||
/* Config type for XML import/export conversions */
|
/* Config type for XML import/export conversions */
|
||||||
# define QEMU_CONFIG_FORMAT_ARGV "qemu-argv"
|
# define QEMU_CONFIG_FORMAT_ARGV "qemu-argv"
|
||||||
|
@ -130,9 +130,6 @@ struct qemud_driver {
|
|||||||
virSysinfoDefPtr hostsysinfo;
|
virSysinfoDefPtr hostsysinfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet;
|
|
||||||
typedef qemuDomainPCIAddressSet *qemuDomainPCIAddressSetPtr;
|
|
||||||
|
|
||||||
typedef struct _qemuDomainCmdlineDef qemuDomainCmdlineDef;
|
typedef struct _qemuDomainCmdlineDef qemuDomainCmdlineDef;
|
||||||
typedef qemuDomainCmdlineDef *qemuDomainCmdlineDefPtr;
|
typedef qemuDomainCmdlineDef *qemuDomainCmdlineDefPtr;
|
||||||
struct _qemuDomainCmdlineDef {
|
struct _qemuDomainCmdlineDef {
|
||||||
|
374
src/qemu/qemu_domain.c
Normal file
374
src/qemu/qemu_domain.c
Normal file
@ -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@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
83
src/qemu/qemu_domain.h
Normal file
83
src/qemu/qemu_domain.h
Normal file
@ -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@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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__ */
|
@ -47,7 +47,6 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
|
||||||
#include <libxml/xpathInternals.h>
|
|
||||||
|
|
||||||
#include "virterror_internal.h"
|
#include "virterror_internal.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
@ -96,55 +95,9 @@
|
|||||||
|
|
||||||
#define QEMU_NB_MEM_PARAM 3
|
#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))
|
#define timeval_to_ms(tv) (((tv).tv_sec * 1000ull) + ((tv).tv_usec / 1000))
|
||||||
|
|
||||||
/* 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 _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;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct watchdogEvent
|
struct watchdogEvent
|
||||||
{
|
{
|
||||||
virDomainObjPtr vm;
|
virDomainObjPtr vm;
|
||||||
@ -203,158 +156,6 @@ static int qemudVMFiltersInstantiate(virConnectPtr conn,
|
|||||||
static struct qemud_driver *qemu_driver = NULL;
|
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
|
* obj must be locked before calling, qemud_driver must NOT be locked
|
||||||
*
|
*
|
||||||
@ -612,168 +413,6 @@ static int doStopCPUs(struct qemud_driver *driver, virDomainObjPtr vm)
|
|||||||
return ret;
|
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,
|
static int qemuCgroupControllerActive(struct qemud_driver *driver,
|
||||||
int controller)
|
int controller)
|
||||||
{
|
{
|
||||||
@ -1659,11 +1298,8 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
|
|||||||
caps->defaultDiskDriverType = "raw";
|
caps->defaultDiskDriverType = "raw";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Domain XML parser hooks */
|
qemuDomainSetPrivateDataHooks(caps);
|
||||||
caps->privateDataAllocFunc = qemuDomainObjPrivateAlloc;
|
qemuDomainSetNamespaceHooks(caps);
|
||||||
caps->privateDataFreeFunc = qemuDomainObjPrivateFree;
|
|
||||||
caps->privateDataXMLFormat = qemuDomainObjPrivateXMLFormat;
|
|
||||||
caps->privateDataXMLParse = qemuDomainObjPrivateXMLParse;
|
|
||||||
|
|
||||||
if (virGetHostUUID(caps->host.host_uuid)) {
|
if (virGetHostUUID(caps->host.host_uuid)) {
|
||||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -1671,12 +1307,6 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
|
|||||||
goto err_exit;
|
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 */
|
/* Security driver data */
|
||||||
if (driver->securityPrimaryDriver) {
|
if (driver->securityPrimaryDriver) {
|
||||||
const char *doi, *model;
|
const char *doi, *model;
|
||||||
|
@ -51,13 +51,4 @@
|
|||||||
|
|
||||||
int qemuRegister(void);
|
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 */
|
#endif /* QEMUD_DRIVER_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user