mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-29 17:33:09 +00:00
Fix re-detection of transient VMs after libvirtd restart
This commit is contained in:
parent
3bdda17adc
commit
56a46886ad
20
ChangeLog
20
ChangeLog
@ -1,3 +1,19 @@
|
|||||||
|
Thu Jun 12 12:26:42 BST 2009 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
|
Fix re-detection of transient VMs after libvirtd restart
|
||||||
|
* src/domain_conf.c, src/domain_conf.h, src/libvirt_private.syms:
|
||||||
|
Extend virDomainLoadAllConfigs to allow for loading of live
|
||||||
|
state info from XML files. Add APIs to format/parse state info
|
||||||
|
from virDomainObjPtr to XML.
|
||||||
|
* src/lxc_driver.c, src/uml_driver.c: Adapt for API change in
|
||||||
|
virDomainLoadAllConfigs.
|
||||||
|
* src/qemu_driver.c, src/qemu_conf.c, src/qemu_conf.h: Remove
|
||||||
|
all code for loading live state files, and use standard APIs
|
||||||
|
from domain_conf.h.
|
||||||
|
* src/security.h, src/security_selinux.c: Add API for reserving
|
||||||
|
an existing in-use MCS context from a running VM detected at
|
||||||
|
daemon startup.
|
||||||
|
|
||||||
Thu Jun 11 17:33:43 CEST 2009 Daniel Veillard <veillard@redhat.com>
|
Thu Jun 11 17:33:43 CEST 2009 Daniel Veillard <veillard@redhat.com>
|
||||||
|
|
||||||
* qemud/remote.c: fixing a typo pointed out by Runa Bhattacharjee
|
* qemud/remote.c: fixing a typo pointed out by Runa Bhattacharjee
|
||||||
@ -6,8 +22,8 @@ Thu Jun 11 16:22:22 CEST 2009 Daniel Veillard <veillard@redhat.com>
|
|||||||
|
|
||||||
* src/node_device_hal.c src/node_device_conf.[ch]: add support
|
* src/node_device_hal.c src/node_device_conf.[ch]: add support
|
||||||
for serial number in HAL storage backend, patch by Dave Allan
|
for serial number in HAL storage backend, patch by Dave Allan
|
||||||
* docs/schemas/nodedev.rng
|
* docs/schemas/nodedev.rng,
|
||||||
tests/nodedevschemadata/storage_serial_3600c0ff000d7a2a5d463ff4902000000.xml:
|
tests/nodedevschemadata/storage_serial_3600c0ff000d7a2a5d463ff4902000000.xml:
|
||||||
update the schemas and add a test case, also by Dave Allan
|
update the schemas and add a test case, also by Dave Allan
|
||||||
|
|
||||||
Thu Jun 11 15:18:44 GMT 2009 Mark McLoughlin <markmc@redhat.com>
|
Thu Jun 11 15:18:44 GMT 2009 Mark McLoughlin <markmc@redhat.com>
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "buf.h"
|
#include "buf.h"
|
||||||
#include "c-ctype.h"
|
#include "c-ctype.h"
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_DOMAIN
|
#define VIR_FROM_THIS VIR_FROM_DOMAIN
|
||||||
|
|
||||||
@ -511,6 +512,31 @@ void virDomainObjListFree(virDomainObjListPtr vms)
|
|||||||
vms->count = 0;
|
vms->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static virDomainObjPtr virDomainObjNew(virConnectPtr conn)
|
||||||
|
{
|
||||||
|
virDomainObjPtr domain;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(domain) < 0) {
|
||||||
|
virReportOOMError(conn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virMutexInit(&domain->lock) < 0) {
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("cannot initialize mutex"));
|
||||||
|
VIR_FREE(domain);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virDomainObjLock(domain);
|
||||||
|
domain->state = VIR_DOMAIN_SHUTOFF;
|
||||||
|
domain->monitorWatch = -1;
|
||||||
|
domain->monitor = -1;
|
||||||
|
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
virDomainObjPtr virDomainAssignDef(virConnectPtr conn,
|
virDomainObjPtr virDomainAssignDef(virConnectPtr conn,
|
||||||
virDomainObjListPtr doms,
|
virDomainObjListPtr doms,
|
||||||
const virDomainDefPtr def)
|
const virDomainDefPtr def)
|
||||||
@ -530,30 +556,16 @@ virDomainObjPtr virDomainAssignDef(virConnectPtr conn,
|
|||||||
return domain;
|
return domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VIR_ALLOC(domain) < 0) {
|
|
||||||
virReportOOMError(conn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virMutexInit(&domain->lock) < 0) {
|
|
||||||
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s", _("cannot initialize mutex"));
|
|
||||||
VIR_FREE(domain);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
virDomainObjLock(domain);
|
|
||||||
domain->state = VIR_DOMAIN_SHUTOFF;
|
|
||||||
domain->def = def;
|
|
||||||
domain->monitorWatch = -1;
|
|
||||||
domain->monitor = -1;
|
|
||||||
|
|
||||||
if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) {
|
if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) {
|
||||||
virReportOOMError(conn);
|
virReportOOMError(conn);
|
||||||
VIR_FREE(domain);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(domain = virDomainObjNew(conn)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
domain->def = def;
|
||||||
|
|
||||||
doms->objs[doms->count] = domain;
|
doms->objs[doms->count] = domain;
|
||||||
doms->count++;
|
doms->count++;
|
||||||
|
|
||||||
@ -2623,6 +2635,68 @@ no_memory:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static virDomainObjPtr virDomainObjParseXML(virConnectPtr conn,
|
||||||
|
virCapsPtr caps,
|
||||||
|
xmlXPathContextPtr ctxt)
|
||||||
|
{
|
||||||
|
char *tmp = NULL;
|
||||||
|
long val;
|
||||||
|
xmlNodePtr config;
|
||||||
|
xmlNodePtr oldnode;
|
||||||
|
virDomainObjPtr obj;
|
||||||
|
|
||||||
|
if (!(obj = virDomainObjNew(conn)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!(config = virXPathNode(conn, "./domain", ctxt))) {
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("no domain config"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
oldnode = ctxt->node;
|
||||||
|
ctxt->node = config;
|
||||||
|
obj->def = virDomainDefParseXML(conn, caps, ctxt, 0);
|
||||||
|
ctxt->node = oldnode;
|
||||||
|
if (!obj->def)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(tmp = virXPathString(conn, "string(./@state)", ctxt))) {
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("missing domain state"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if ((obj->state = virDomainStateTypeFromString(tmp)) < 0) {
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("invalid domain state '%s'"), tmp);
|
||||||
|
VIR_FREE(tmp);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
VIR_FREE(tmp);
|
||||||
|
|
||||||
|
if ((virXPathLong(conn, "string(./@pid)", ctxt, &val)) < 0) {
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("invalid pid"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
obj->pid = (pid_t)val;
|
||||||
|
|
||||||
|
if(!(obj->monitorpath =
|
||||||
|
virXPathString(conn, "string(./monitor[1]/@path)", ctxt))) {
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("no monitor path"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virDomainObjFree(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Called from SAX on parsing errors in the XML. */
|
/* Called from SAX on parsing errors in the XML. */
|
||||||
static void
|
static void
|
||||||
catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
|
catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
|
||||||
@ -2755,6 +2829,78 @@ cleanup:
|
|||||||
xmlXPathFreeContext(ctxt);
|
xmlXPathFreeContext(ctxt);
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virDomainObjPtr virDomainObjParseFile(virConnectPtr conn,
|
||||||
|
virCapsPtr caps,
|
||||||
|
const char *filename)
|
||||||
|
{
|
||||||
|
xmlParserCtxtPtr pctxt;
|
||||||
|
xmlDocPtr xml = NULL;
|
||||||
|
xmlNodePtr root;
|
||||||
|
virDomainObjPtr obj = NULL;
|
||||||
|
|
||||||
|
/* Set up a parser context so we can catch the details of XML errors. */
|
||||||
|
pctxt = xmlNewParserCtxt ();
|
||||||
|
if (!pctxt || !pctxt->sax)
|
||||||
|
goto cleanup;
|
||||||
|
pctxt->sax->error = catchXMLError;
|
||||||
|
pctxt->_private = conn;
|
||||||
|
|
||||||
|
if (conn) virResetError (&conn->err);
|
||||||
|
xml = xmlCtxtReadFile (pctxt, filename, NULL,
|
||||||
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||||
|
XML_PARSE_NOWARNING);
|
||||||
|
if (!xml) {
|
||||||
|
if (virGetLastError() == NULL)
|
||||||
|
virDomainReportError(conn, VIR_ERR_XML_ERROR,
|
||||||
|
"%s", _("failed to parse xml document"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((root = xmlDocGetRootElement(xml)) == NULL) {
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("missing root element"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = virDomainObjParseNode(conn, caps, xml, root);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
xmlFreeParserCtxt (pctxt);
|
||||||
|
xmlFreeDoc (xml);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virDomainObjPtr virDomainObjParseNode(virConnectPtr conn,
|
||||||
|
virCapsPtr caps,
|
||||||
|
xmlDocPtr xml,
|
||||||
|
xmlNodePtr root)
|
||||||
|
{
|
||||||
|
xmlXPathContextPtr ctxt = NULL;
|
||||||
|
virDomainObjPtr obj = NULL;
|
||||||
|
|
||||||
|
if (!xmlStrEqual(root->name, BAD_CAST "domstatus")) {
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("incorrect root element"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxt = xmlXPathNewContext(xml);
|
||||||
|
if (ctxt == NULL) {
|
||||||
|
virReportOOMError(conn);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxt->node = root;
|
||||||
|
obj = virDomainObjParseXML(conn, caps, ctxt);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
xmlXPathFreeContext(ctxt);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* ! PROXY */
|
#endif /* ! PROXY */
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@ -3707,6 +3853,40 @@ char *virDomainDefFormat(virConnectPtr conn,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *virDomainObjFormat(virConnectPtr conn,
|
||||||
|
virDomainObjPtr obj,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
char *config_xml = NULL, *xml = NULL;
|
||||||
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
|
||||||
|
virBufferVSprintf(&buf, "<domstatus state='%s' pid='%d'>\n",
|
||||||
|
virDomainStateTypeToString(obj->state),
|
||||||
|
obj->pid);
|
||||||
|
virBufferEscapeString(&buf, " <monitor path='%s'/>\n", obj->monitorpath);
|
||||||
|
|
||||||
|
if (!(config_xml = virDomainDefFormat(conn,
|
||||||
|
obj->def,
|
||||||
|
flags)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
virBufferAdd(&buf, config_xml, strlen(config_xml));
|
||||||
|
VIR_FREE(config_xml);
|
||||||
|
virBufferAddLit(&buf, "</domstatus>\n");
|
||||||
|
|
||||||
|
if (virBufferError(&buf))
|
||||||
|
goto no_memory;
|
||||||
|
|
||||||
|
return virBufferContentAndReset(&buf);
|
||||||
|
|
||||||
|
no_memory:
|
||||||
|
virReportOOMError(conn);
|
||||||
|
error:
|
||||||
|
xml = virBufferContentAndReset(&buf);
|
||||||
|
VIR_FREE(xml);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef PROXY
|
#ifndef PROXY
|
||||||
|
|
||||||
@ -3782,6 +3962,27 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int virDomainSaveStatus(virConnectPtr conn,
|
||||||
|
const char *statusDir,
|
||||||
|
virDomainObjPtr obj)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
char *xml;
|
||||||
|
|
||||||
|
if (!(xml = virDomainObjFormat(conn,
|
||||||
|
obj,
|
||||||
|
VIR_DOMAIN_XML_SECURE)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainSaveXML(conn, statusDir, obj->def, xml))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(xml);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virDomainObjPtr virDomainLoadConfig(virConnectPtr conn,
|
virDomainObjPtr virDomainLoadConfig(virConnectPtr conn,
|
||||||
virCapsPtr caps,
|
virCapsPtr caps,
|
||||||
@ -3835,17 +4036,67 @@ error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static virDomainObjPtr virDomainLoadStatus(virConnectPtr conn,
|
||||||
|
virCapsPtr caps,
|
||||||
|
virDomainObjListPtr doms,
|
||||||
|
const char *statusDir,
|
||||||
|
const char *name,
|
||||||
|
virDomainLoadConfigNotify notify,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
char *statusFile = NULL;
|
||||||
|
virDomainObjPtr obj = NULL;
|
||||||
|
virDomainObjPtr tmp = NULL;
|
||||||
|
|
||||||
|
if ((statusFile = virDomainConfigFile(conn, statusDir, name)) == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(obj = virDomainObjParseFile(conn, caps, statusFile)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
tmp = virDomainFindByName(doms, obj->def->name);
|
||||||
|
if (tmp) {
|
||||||
|
virDomainObjUnlock(obj);
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("unexpected domain %s already exists"),
|
||||||
|
obj->def->name);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) {
|
||||||
|
virReportOOMError(conn);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
doms->objs[doms->count] = obj;
|
||||||
|
doms->count++;
|
||||||
|
|
||||||
|
if (notify)
|
||||||
|
(*notify)(obj, 1, opaque);
|
||||||
|
|
||||||
|
VIR_FREE(statusFile);
|
||||||
|
return obj;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virDomainObjFree(obj);
|
||||||
|
VIR_FREE(statusFile);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int virDomainLoadAllConfigs(virConnectPtr conn,
|
int virDomainLoadAllConfigs(virConnectPtr conn,
|
||||||
virCapsPtr caps,
|
virCapsPtr caps,
|
||||||
virDomainObjListPtr doms,
|
virDomainObjListPtr doms,
|
||||||
const char *configDir,
|
const char *configDir,
|
||||||
const char *autostartDir,
|
const char *autostartDir,
|
||||||
|
int liveStatus,
|
||||||
virDomainLoadConfigNotify notify,
|
virDomainLoadConfigNotify notify,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
|
|
||||||
|
VIR_INFO("Scanning for configs in %s", configDir);
|
||||||
|
|
||||||
if (!(dir = opendir(configDir))) {
|
if (!(dir = opendir(configDir))) {
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
return 0;
|
return 0;
|
||||||
@ -3866,6 +4117,16 @@ int virDomainLoadAllConfigs(virConnectPtr conn,
|
|||||||
|
|
||||||
/* NB: ignoring errors, so one malformed config doesn't
|
/* NB: ignoring errors, so one malformed config doesn't
|
||||||
kill the whole process */
|
kill the whole process */
|
||||||
|
VIR_INFO("Loading config file '%s.xml'", entry->d_name);
|
||||||
|
if (liveStatus)
|
||||||
|
dom = virDomainLoadStatus(conn,
|
||||||
|
caps,
|
||||||
|
doms,
|
||||||
|
configDir,
|
||||||
|
entry->d_name,
|
||||||
|
notify,
|
||||||
|
opaque);
|
||||||
|
else
|
||||||
dom = virDomainLoadConfig(conn,
|
dom = virDomainLoadConfig(conn,
|
||||||
caps,
|
caps,
|
||||||
doms,
|
doms,
|
||||||
|
@ -515,7 +515,6 @@ struct _virDomainObj {
|
|||||||
int monitor;
|
int monitor;
|
||||||
char *monitorpath;
|
char *monitorpath;
|
||||||
int monitorWatch;
|
int monitorWatch;
|
||||||
int logfile;
|
|
||||||
int pid;
|
int pid;
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
@ -589,10 +588,22 @@ virDomainDefPtr virDomainDefParseNode(virConnectPtr conn,
|
|||||||
xmlDocPtr doc,
|
xmlDocPtr doc,
|
||||||
xmlNodePtr root,
|
xmlNodePtr root,
|
||||||
int flags);
|
int flags);
|
||||||
|
|
||||||
|
virDomainObjPtr virDomainObjParseFile(virConnectPtr conn,
|
||||||
|
virCapsPtr caps,
|
||||||
|
const char *filename);
|
||||||
|
virDomainObjPtr virDomainObjParseNode(virConnectPtr conn,
|
||||||
|
virCapsPtr caps,
|
||||||
|
xmlDocPtr xml,
|
||||||
|
xmlNodePtr root);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
char *virDomainDefFormat(virConnectPtr conn,
|
char *virDomainDefFormat(virConnectPtr conn,
|
||||||
virDomainDefPtr def,
|
virDomainDefPtr def,
|
||||||
int flags);
|
int flags);
|
||||||
|
char *virDomainObjFormat(virConnectPtr conn,
|
||||||
|
virDomainObjPtr obj,
|
||||||
|
int flags);
|
||||||
|
|
||||||
int virDomainCpuSetParse(virConnectPtr conn,
|
int virDomainCpuSetParse(virConnectPtr conn,
|
||||||
const char **str,
|
const char **str,
|
||||||
@ -615,6 +626,9 @@ int virDomainSaveXML(virConnectPtr conn,
|
|||||||
int virDomainSaveConfig(virConnectPtr conn,
|
int virDomainSaveConfig(virConnectPtr conn,
|
||||||
const char *configDir,
|
const char *configDir,
|
||||||
virDomainDefPtr def);
|
virDomainDefPtr def);
|
||||||
|
int virDomainSaveStatus(virConnectPtr conn,
|
||||||
|
const char *statusDir,
|
||||||
|
virDomainObjPtr obj);
|
||||||
|
|
||||||
typedef void (*virDomainLoadConfigNotify)(virDomainObjPtr dom,
|
typedef void (*virDomainLoadConfigNotify)(virDomainObjPtr dom,
|
||||||
int newDomain,
|
int newDomain,
|
||||||
@ -634,6 +648,7 @@ int virDomainLoadAllConfigs(virConnectPtr conn,
|
|||||||
virDomainObjListPtr doms,
|
virDomainObjListPtr doms,
|
||||||
const char *configDir,
|
const char *configDir,
|
||||||
const char *autostartDir,
|
const char *autostartDir,
|
||||||
|
int liveStatus,
|
||||||
virDomainLoadConfigNotify notify,
|
virDomainLoadConfigNotify notify,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ virDomainObjListFree;
|
|||||||
virDomainRemoveInactive;
|
virDomainRemoveInactive;
|
||||||
virDomainSaveXML;
|
virDomainSaveXML;
|
||||||
virDomainSaveConfig;
|
virDomainSaveConfig;
|
||||||
|
virDomainSaveStatus;
|
||||||
virDomainSoundDefFree;
|
virDomainSoundDefFree;
|
||||||
virDomainSoundModelTypeFromString;
|
virDomainSoundModelTypeFromString;
|
||||||
virDomainSoundModelTypeToString;
|
virDomainSoundModelTypeToString;
|
||||||
|
@ -1190,7 +1190,7 @@ static int lxcStartup(void)
|
|||||||
&lxc_driver->domains,
|
&lxc_driver->domains,
|
||||||
lxc_driver->configDir,
|
lxc_driver->configDir,
|
||||||
lxc_driver->autostartDir,
|
lxc_driver->autostartDir,
|
||||||
NULL, NULL) < 0)
|
0, NULL, NULL) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
for (i = 0 ; i < lxc_driver->domains.count ; i++) {
|
for (i = 0 ; i < lxc_driver->domains.count ; i++) {
|
||||||
|
190
src/qemu_conf.c
190
src/qemu_conf.c
@ -2888,193 +2888,3 @@ cleanup:
|
|||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Called from SAX on parsing errors in the XML. */
|
|
||||||
static void
|
|
||||||
catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
|
|
||||||
{
|
|
||||||
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
|
|
||||||
|
|
||||||
if (ctxt) {
|
|
||||||
virConnectPtr conn = ctxt->_private;
|
|
||||||
|
|
||||||
if (ctxt->lastError.level == XML_ERR_FATAL &&
|
|
||||||
ctxt->lastError.message != NULL) {
|
|
||||||
qemudReportError (conn, NULL, NULL, VIR_ERR_XML_DETAIL,
|
|
||||||
_("at line %d: %s"),
|
|
||||||
ctxt->lastError.line,
|
|
||||||
ctxt->lastError.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* qemudDomainStatusParseFile
|
|
||||||
*
|
|
||||||
* read the last known status of a domain
|
|
||||||
*
|
|
||||||
* Returns 0 on success
|
|
||||||
*/
|
|
||||||
qemudDomainStatusPtr
|
|
||||||
qemudDomainStatusParseFile(virConnectPtr conn,
|
|
||||||
virCapsPtr caps,
|
|
||||||
const char *filename, int flags)
|
|
||||||
{
|
|
||||||
xmlParserCtxtPtr pctxt = NULL;
|
|
||||||
xmlXPathContextPtr ctxt = NULL;
|
|
||||||
xmlDocPtr xml = NULL;
|
|
||||||
xmlNodePtr root, config_root;
|
|
||||||
virDomainDefPtr def = NULL;
|
|
||||||
char *tmp = NULL;
|
|
||||||
long val;
|
|
||||||
qemudDomainStatusPtr status = NULL;
|
|
||||||
|
|
||||||
if (VIR_ALLOC(status) < 0) {
|
|
||||||
virReportOOMError(conn);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up a parser context so we can catch the details of XML errors. */
|
|
||||||
pctxt = xmlNewParserCtxt ();
|
|
||||||
if (!pctxt || !pctxt->sax)
|
|
||||||
goto error;
|
|
||||||
pctxt->sax->error = catchXMLError;
|
|
||||||
pctxt->_private = conn;
|
|
||||||
|
|
||||||
if (conn) virResetError (&conn->err);
|
|
||||||
xml = xmlCtxtReadFile (pctxt, filename, NULL,
|
|
||||||
XML_PARSE_NOENT | XML_PARSE_NONET |
|
|
||||||
XML_PARSE_NOWARNING);
|
|
||||||
if (!xml) {
|
|
||||||
if (conn && conn->err.code == VIR_ERR_NONE)
|
|
||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR,
|
|
||||||
"%s", _("failed to parse xml document"));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((root = xmlDocGetRootElement(xml)) == NULL) {
|
|
||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s", _("missing root element"));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctxt = xmlXPathNewContext(xml);
|
|
||||||
if (ctxt == NULL) {
|
|
||||||
virReportOOMError(conn);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!xmlStrEqual(root->name, BAD_CAST "domstatus")) {
|
|
||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s", _("incorrect root element"));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctxt->node = root;
|
|
||||||
if(!(tmp = virXPathString(conn, "string(./@state)", ctxt))) {
|
|
||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s", _("invalid domain state"));
|
|
||||||
goto error;
|
|
||||||
} else {
|
|
||||||
status->state = virDomainStateTypeFromString(tmp);
|
|
||||||
VIR_FREE(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if((virXPathLong(conn, "string(./@pid)", ctxt, &val)) < 0) {
|
|
||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s", _("invalid pid"));
|
|
||||||
goto error;
|
|
||||||
} else
|
|
||||||
status->pid = (pid_t)val;
|
|
||||||
|
|
||||||
if(!(tmp = virXPathString(conn, "string(./monitor[1]/@path)", ctxt))) {
|
|
||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s", _("no monitor path"));
|
|
||||||
goto error;
|
|
||||||
} else
|
|
||||||
status->monitorpath = tmp;
|
|
||||||
|
|
||||||
if(!(config_root = virXPathNode(conn, "./domain", ctxt))) {
|
|
||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s", _("no domain config"));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if(!(def = virDomainDefParseNode(conn, caps, xml, config_root, flags)))
|
|
||||||
goto error;
|
|
||||||
else
|
|
||||||
status->def = def;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
xmlFreeParserCtxt (pctxt);
|
|
||||||
xmlXPathFreeContext(ctxt);
|
|
||||||
xmlFreeDoc (xml);
|
|
||||||
return status;
|
|
||||||
|
|
||||||
error:
|
|
||||||
VIR_FREE(tmp);
|
|
||||||
VIR_FREE(status);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* qemudDomainStatusFormat
|
|
||||||
*
|
|
||||||
* Get the state of a running domain as XML
|
|
||||||
*
|
|
||||||
* Returns xml on success
|
|
||||||
*/
|
|
||||||
static char*
|
|
||||||
qemudDomainStatusFormat(virConnectPtr conn,
|
|
||||||
virDomainObjPtr vm)
|
|
||||||
{
|
|
||||||
char *config_xml = NULL, *xml = NULL;
|
|
||||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
||||||
|
|
||||||
virBufferVSprintf(&buf, "<domstatus state='%s' pid='%d'>\n",
|
|
||||||
virDomainStateTypeToString(vm->state),
|
|
||||||
vm->pid);
|
|
||||||
virBufferEscapeString(&buf, " <monitor path='%s'/>\n", vm->monitorpath);
|
|
||||||
|
|
||||||
if (!(config_xml = virDomainDefFormat(conn,
|
|
||||||
vm->def,
|
|
||||||
VIR_DOMAIN_XML_SECURE)))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
virBufferAdd(&buf, config_xml, strlen(config_xml));
|
|
||||||
virBufferAddLit(&buf, "</domstatus>\n");
|
|
||||||
|
|
||||||
xml = virBufferContentAndReset(&buf);
|
|
||||||
cleanup:
|
|
||||||
VIR_FREE(config_xml);
|
|
||||||
return xml;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* qemudSaveDomainStatus
|
|
||||||
*
|
|
||||||
* Save the current status of a running domain
|
|
||||||
*
|
|
||||||
* Returns 0 on success
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
qemudSaveDomainStatus(virConnectPtr conn,
|
|
||||||
struct qemud_driver *driver,
|
|
||||||
virDomainObjPtr vm)
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
char *xml = NULL;
|
|
||||||
|
|
||||||
if (!(xml = qemudDomainStatusFormat(conn, vm)))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if ((ret = virDomainSaveXML(conn, driver->stateDir, vm->def, xml)))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
cleanup:
|
|
||||||
VIR_FREE(xml);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
@ -92,15 +92,6 @@ struct qemud_driver {
|
|||||||
virSecurityDriverPtr securityDriver;
|
virSecurityDriverPtr securityDriver;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Status needed to reconenct to running VMs */
|
|
||||||
typedef struct _qemudDomainStatus qemudDomainStatus;
|
|
||||||
typedef qemudDomainStatus *qemudDomainStatusPtr;
|
|
||||||
struct _qemudDomainStatus {
|
|
||||||
char *monitorpath;
|
|
||||||
pid_t pid;
|
|
||||||
int state;
|
|
||||||
virDomainDefPtr def;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Port numbers used for KVM migration. */
|
/* Port numbers used for KVM migration. */
|
||||||
#define QEMUD_MIGRATION_FIRST_PORT 49152
|
#define QEMUD_MIGRATION_FIRST_PORT 49152
|
||||||
@ -149,13 +140,4 @@ virDomainDefPtr qemuParseCommandLineString(virConnectPtr conn,
|
|||||||
virCapsPtr caps,
|
virCapsPtr caps,
|
||||||
const char *args);
|
const char *args);
|
||||||
|
|
||||||
const char *qemudVirtTypeToString (int type);
|
|
||||||
qemudDomainStatusPtr qemudDomainStatusParseFile(virConnectPtr conn,
|
|
||||||
virCapsPtr caps,
|
|
||||||
const char *filename,
|
|
||||||
int flags);
|
|
||||||
int qemudSaveDomainStatus(virConnectPtr conn,
|
|
||||||
struct qemud_driver *driver,
|
|
||||||
virDomainObjPtr vm);
|
|
||||||
|
|
||||||
#endif /* __QEMUD_CONF_H */
|
#endif /* __QEMUD_CONF_H */
|
||||||
|
@ -120,6 +120,8 @@ static int qemudMonitorCommandExtra(const virDomainObjPtr vm,
|
|||||||
static int qemudDomainSetMemoryBalloon(virConnectPtr conn,
|
static int qemudDomainSetMemoryBalloon(virConnectPtr conn,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
unsigned long newmem);
|
unsigned long newmem);
|
||||||
|
static int qemudDetectVcpuPIDs(virConnectPtr conn,
|
||||||
|
virDomainObjPtr vm);
|
||||||
|
|
||||||
static struct qemud_driver *qemu_driver = NULL;
|
static struct qemud_driver *qemu_driver = NULL;
|
||||||
|
|
||||||
@ -282,79 +284,65 @@ static int qemudOpenMonitor(virConnectPtr conn,
|
|||||||
const char *monitor,
|
const char *monitor,
|
||||||
int reconnect);
|
int reconnect);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open an existing VM's monitor, re-detect VCPU threads
|
||||||
|
* and re-reserve the security labels in use
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
qemuReconnectDomain(struct qemud_driver *driver,
|
||||||
|
virDomainObjPtr obj)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if ((rc = qemudOpenMonitor(NULL, driver, obj, obj->monitorpath, 1)) != 0) {
|
||||||
|
VIR_ERROR(_("Failed to reconnect monitor for %s: %d\n"),
|
||||||
|
obj->def->name, rc);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qemudDetectVcpuPIDs(NULL, obj) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
|
||||||
|
driver->securityDriver &&
|
||||||
|
driver->securityDriver->domainReserveSecurityLabel &&
|
||||||
|
driver->securityDriver->domainReserveSecurityLabel(NULL, obj) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (obj->def->id >= driver->nextvmid)
|
||||||
|
driver->nextvmid = obj->def->id + 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qemudReconnectVMs
|
* qemudReconnectVMs
|
||||||
*
|
*
|
||||||
* Reconnect running vms to the daemon process
|
* Try to re-open the resources for live VMs that we care
|
||||||
|
* about.
|
||||||
*/
|
*/
|
||||||
static int
|
static void
|
||||||
qemudReconnectVMs(struct qemud_driver *driver)
|
qemuReconnectDomains(struct qemud_driver *driver)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0 ; i < driver->domains.count ; i++) {
|
for (i = 0 ; i < driver->domains.count ; i++) {
|
||||||
virDomainObjPtr vm = driver->domains.objs[i];
|
virDomainObjPtr obj = driver->domains.objs[i];
|
||||||
qemudDomainStatusPtr status = NULL;
|
|
||||||
char *config = NULL;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
virDomainObjLock(vm);
|
virDomainObjLock(obj);
|
||||||
if ((rc = virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) == 0)
|
if (qemuReconnectDomain(driver, obj) < 0) {
|
||||||
DEBUG("Found pid %d for '%s'", vm->pid, vm->def->name);
|
/* If we can't get the monitor back, then kill the VM
|
||||||
else
|
* so user has ability to start it again later without
|
||||||
goto next;
|
* danger of ending up running twice */
|
||||||
|
qemudShutdownVMDaemon(NULL, driver, obj);
|
||||||
if ((config = virDomainConfigFile(NULL,
|
|
||||||
driver->stateDir,
|
|
||||||
vm->def->name)) == NULL) {
|
|
||||||
VIR_ERROR(_("Failed to read domain status for %s\n"),
|
|
||||||
vm->def->name);
|
|
||||||
goto next_error;
|
|
||||||
}
|
}
|
||||||
|
virDomainObjUnlock(obj);
|
||||||
status = qemudDomainStatusParseFile(NULL, driver->caps, config, 0);
|
|
||||||
if (status) {
|
|
||||||
vm->newDef = vm->def;
|
|
||||||
vm->def = status->def;
|
|
||||||
} else {
|
|
||||||
VIR_ERROR(_("Failed to parse domain status for %s\n"),
|
|
||||||
vm->def->name);
|
|
||||||
goto next_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rc = qemudOpenMonitor(NULL, driver, vm, status->monitorpath, 1)) != 0) {
|
|
||||||
VIR_ERROR(_("Failed to reconnect monitor for %s: %d\n"),
|
|
||||||
vm->def->name, rc);
|
|
||||||
goto next_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((vm->logfile = qemudLogFD(NULL, driver->logDir, vm->def->name)) < 0)
|
|
||||||
goto next_error;
|
|
||||||
|
|
||||||
if (vm->def->id >= driver->nextvmid)
|
|
||||||
driver->nextvmid = vm->def->id + 1;
|
|
||||||
|
|
||||||
vm->state = status->state;
|
|
||||||
goto next;
|
|
||||||
|
|
||||||
next_error:
|
|
||||||
/* we failed to reconnect the vm so remove it's traces */
|
|
||||||
vm->def->id = -1;
|
|
||||||
qemudRemoveDomainStatus(NULL, driver, vm);
|
|
||||||
/* Restore orignal def, if we'd loaded a live one */
|
|
||||||
if (vm->newDef) {
|
|
||||||
virDomainDefFree(vm->def);
|
|
||||||
vm->def = vm->newDef;
|
|
||||||
vm->newDef = NULL;
|
|
||||||
}
|
|
||||||
next:
|
|
||||||
virDomainObjUnlock(vm);
|
|
||||||
if (status)
|
|
||||||
VIR_FREE(status->monitorpath);
|
|
||||||
VIR_FREE(status);
|
|
||||||
VIR_FREE(config);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -508,14 +496,25 @@ qemudStartup(void) {
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get all the running persistent or transient configs first */
|
||||||
|
if (virDomainLoadAllConfigs(NULL,
|
||||||
|
qemu_driver->caps,
|
||||||
|
&qemu_driver->domains,
|
||||||
|
qemu_driver->stateDir,
|
||||||
|
NULL,
|
||||||
|
1, NULL, NULL) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
qemuReconnectDomains(qemu_driver);
|
||||||
|
|
||||||
|
/* Then inactive persistent configs */
|
||||||
if (virDomainLoadAllConfigs(NULL,
|
if (virDomainLoadAllConfigs(NULL,
|
||||||
qemu_driver->caps,
|
qemu_driver->caps,
|
||||||
&qemu_driver->domains,
|
&qemu_driver->domains,
|
||||||
qemu_driver->configDir,
|
qemu_driver->configDir,
|
||||||
qemu_driver->autostartDir,
|
qemu_driver->autostartDir,
|
||||||
NULL, NULL) < 0)
|
0, NULL, NULL) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
qemudReconnectVMs(qemu_driver);
|
|
||||||
qemuDriverUnlock(qemu_driver);
|
qemuDriverUnlock(qemu_driver);
|
||||||
|
|
||||||
qemudAutostartConfigs(qemu_driver);
|
qemudAutostartConfigs(qemu_driver);
|
||||||
@ -564,7 +563,7 @@ qemudReload(void) {
|
|||||||
&qemu_driver->domains,
|
&qemu_driver->domains,
|
||||||
qemu_driver->configDir,
|
qemu_driver->configDir,
|
||||||
qemu_driver->autostartDir,
|
qemu_driver->autostartDir,
|
||||||
qemudNotifyLoadDomain, qemu_driver);
|
0, qemudNotifyLoadDomain, qemu_driver);
|
||||||
qemuDriverUnlock(qemu_driver);
|
qemuDriverUnlock(qemu_driver);
|
||||||
|
|
||||||
qemudAutostartConfigs(qemu_driver);
|
qemudAutostartConfigs(qemu_driver);
|
||||||
@ -1329,6 +1328,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
|||||||
int pos = -1;
|
int pos = -1;
|
||||||
char ebuf[1024];
|
char ebuf[1024];
|
||||||
char *pidfile = NULL;
|
char *pidfile = NULL;
|
||||||
|
int logfile;
|
||||||
|
|
||||||
struct gemudHookData hookData;
|
struct gemudHookData hookData;
|
||||||
hookData.conn = conn;
|
hookData.conn = conn;
|
||||||
@ -1370,7 +1370,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((vm->logfile = qemudLogFD(conn, driver->logDir, vm->def->name)) < 0)
|
if ((logfile = qemudLogFD(conn, driver->logDir, vm->def->name)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
emulator = vm->def->emulator;
|
emulator = vm->def->emulator;
|
||||||
@ -1419,29 +1419,29 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
|||||||
|
|
||||||
tmp = progenv;
|
tmp = progenv;
|
||||||
while (*tmp) {
|
while (*tmp) {
|
||||||
if (safewrite(vm->logfile, *tmp, strlen(*tmp)) < 0)
|
if (safewrite(logfile, *tmp, strlen(*tmp)) < 0)
|
||||||
VIR_WARN(_("Unable to write envv to logfile: %s\n"),
|
VIR_WARN(_("Unable to write envv to logfile: %s\n"),
|
||||||
virStrerror(errno, ebuf, sizeof ebuf));
|
virStrerror(errno, ebuf, sizeof ebuf));
|
||||||
if (safewrite(vm->logfile, " ", 1) < 0)
|
if (safewrite(logfile, " ", 1) < 0)
|
||||||
VIR_WARN(_("Unable to write envv to logfile: %s\n"),
|
VIR_WARN(_("Unable to write envv to logfile: %s\n"),
|
||||||
virStrerror(errno, ebuf, sizeof ebuf));
|
virStrerror(errno, ebuf, sizeof ebuf));
|
||||||
tmp++;
|
tmp++;
|
||||||
}
|
}
|
||||||
tmp = argv;
|
tmp = argv;
|
||||||
while (*tmp) {
|
while (*tmp) {
|
||||||
if (safewrite(vm->logfile, *tmp, strlen(*tmp)) < 0)
|
if (safewrite(logfile, *tmp, strlen(*tmp)) < 0)
|
||||||
VIR_WARN(_("Unable to write argv to logfile: %s\n"),
|
VIR_WARN(_("Unable to write argv to logfile: %s\n"),
|
||||||
virStrerror(errno, ebuf, sizeof ebuf));
|
virStrerror(errno, ebuf, sizeof ebuf));
|
||||||
if (safewrite(vm->logfile, " ", 1) < 0)
|
if (safewrite(logfile, " ", 1) < 0)
|
||||||
VIR_WARN(_("Unable to write argv to logfile: %s\n"),
|
VIR_WARN(_("Unable to write argv to logfile: %s\n"),
|
||||||
virStrerror(errno, ebuf, sizeof ebuf));
|
virStrerror(errno, ebuf, sizeof ebuf));
|
||||||
tmp++;
|
tmp++;
|
||||||
}
|
}
|
||||||
if (safewrite(vm->logfile, "\n", 1) < 0)
|
if (safewrite(logfile, "\n", 1) < 0)
|
||||||
VIR_WARN(_("Unable to write argv to logfile: %s\n"),
|
VIR_WARN(_("Unable to write argv to logfile: %s\n"),
|
||||||
virStrerror(errno, ebuf, sizeof ebuf));
|
virStrerror(errno, ebuf, sizeof ebuf));
|
||||||
|
|
||||||
if ((pos = lseek(vm->logfile, 0, SEEK_END)) < 0)
|
if ((pos = lseek(logfile, 0, SEEK_END)) < 0)
|
||||||
VIR_WARN(_("Unable to seek to end of logfile: %s\n"),
|
VIR_WARN(_("Unable to seek to end of logfile: %s\n"),
|
||||||
virStrerror(errno, ebuf, sizeof ebuf));
|
virStrerror(errno, ebuf, sizeof ebuf));
|
||||||
|
|
||||||
@ -1449,7 +1449,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
|||||||
FD_SET(tapfds[i], &keepfd);
|
FD_SET(tapfds[i], &keepfd);
|
||||||
|
|
||||||
ret = virExecDaemonize(conn, argv, progenv, &keepfd, &child,
|
ret = virExecDaemonize(conn, argv, progenv, &keepfd, &child,
|
||||||
stdin_fd, &vm->logfile, &vm->logfile,
|
stdin_fd, &logfile, &logfile,
|
||||||
VIR_EXEC_NONBLOCK,
|
VIR_EXEC_NONBLOCK,
|
||||||
qemudSecurityHook, &hookData,
|
qemudSecurityHook, &hookData,
|
||||||
pidfile);
|
pidfile);
|
||||||
@ -1499,7 +1499,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
|||||||
(qemudInitCpus(conn, vm, migrateFrom) < 0) ||
|
(qemudInitCpus(conn, vm, migrateFrom) < 0) ||
|
||||||
(qemudInitPasswords(conn, driver, vm) < 0) ||
|
(qemudInitPasswords(conn, driver, vm) < 0) ||
|
||||||
(qemudDomainSetMemoryBalloon(conn, vm, vm->def->memory) < 0) ||
|
(qemudDomainSetMemoryBalloon(conn, vm, vm->def->memory) < 0) ||
|
||||||
(qemudSaveDomainStatus(conn, qemu_driver, vm) < 0)) {
|
(virDomainSaveStatus(conn, driver->stateDir, vm) < 0)) {
|
||||||
qemudShutdownVMDaemon(conn, driver, vm);
|
qemudShutdownVMDaemon(conn, driver, vm);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
/* No need for 'goto cleanup' now since qemudShutdownVMDaemon does enough */
|
/* No need for 'goto cleanup' now since qemudShutdownVMDaemon does enough */
|
||||||
@ -1517,10 +1517,8 @@ cleanup:
|
|||||||
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
|
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
|
||||||
vm->def->graphics[0]->data.vnc.autoport)
|
vm->def->graphics[0]->data.vnc.autoport)
|
||||||
vm->def->graphics[0]->data.vnc.port = -1;
|
vm->def->graphics[0]->data.vnc.port = -1;
|
||||||
if (vm->logfile != -1) {
|
if (logfile != -1)
|
||||||
close(vm->logfile);
|
close(logfile);
|
||||||
vm->logfile = -1;
|
|
||||||
}
|
|
||||||
vm->def->id = -1;
|
vm->def->id = -1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1547,14 +1545,8 @@ static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
vm->monitorWatch = -1;
|
vm->monitorWatch = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(vm->logfile) < 0) {
|
|
||||||
char ebuf[1024];
|
|
||||||
VIR_WARN(_("Unable to close logfile: %s\n"),
|
|
||||||
virStrerror(errno, ebuf, sizeof ebuf));
|
|
||||||
}
|
|
||||||
if (vm->monitor != -1)
|
if (vm->monitor != -1)
|
||||||
close(vm->monitor);
|
close(vm->monitor);
|
||||||
vm->logfile = -1;
|
|
||||||
vm->monitor = -1;
|
vm->monitor = -1;
|
||||||
|
|
||||||
/* shut it off for sure */
|
/* shut it off for sure */
|
||||||
@ -2183,7 +2175,7 @@ static int qemudDomainSuspend(virDomainPtr dom) {
|
|||||||
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
|
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
|
||||||
VIR_FREE(info);
|
VIR_FREE(info);
|
||||||
}
|
}
|
||||||
if (qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
|
if (virDomainSaveStatus(dom->conn, driver->stateDir, vm) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
@ -2233,7 +2225,7 @@ static int qemudDomainResume(virDomainPtr dom) {
|
|||||||
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
||||||
VIR_FREE(info);
|
VIR_FREE(info);
|
||||||
}
|
}
|
||||||
if (qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
|
if (virDomainSaveStatus(dom->conn, driver->stateDir, vm) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
@ -4116,7 +4108,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret && qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
|
if (!ret && virDomainSaveStatus(dom->conn, driver->stateDir, vm) < 0)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@ -4238,7 +4230,7 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
|
|||||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
|
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
|
||||||
"%s", _("only SCSI or virtio disk device can be detached dynamically"));
|
"%s", _("only SCSI or virtio disk device can be detached dynamically"));
|
||||||
|
|
||||||
if (!ret && qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
|
if (!ret && virDomainSaveStatus(dom->conn, driver->stateDir, vm) < 0)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
@ -38,6 +38,8 @@ typedef int (*virSecurityDomainSetImageLabel) (virConnectPtr conn,
|
|||||||
virDomainDiskDefPtr disk);
|
virDomainDiskDefPtr disk);
|
||||||
typedef int (*virSecurityDomainGenLabel) (virConnectPtr conn,
|
typedef int (*virSecurityDomainGenLabel) (virConnectPtr conn,
|
||||||
virDomainObjPtr sec);
|
virDomainObjPtr sec);
|
||||||
|
typedef int (*virSecurityDomainReserveLabel) (virConnectPtr conn,
|
||||||
|
virDomainObjPtr sec);
|
||||||
typedef int (*virSecurityDomainGetLabel) (virConnectPtr conn,
|
typedef int (*virSecurityDomainGetLabel) (virConnectPtr conn,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virSecurityLabelPtr sec);
|
virSecurityLabelPtr sec);
|
||||||
@ -57,6 +59,7 @@ struct _virSecurityDriver {
|
|||||||
virSecurityDomainRestoreImageLabel domainRestoreSecurityImageLabel;
|
virSecurityDomainRestoreImageLabel domainRestoreSecurityImageLabel;
|
||||||
virSecurityDomainSetImageLabel domainSetSecurityImageLabel;
|
virSecurityDomainSetImageLabel domainSetSecurityImageLabel;
|
||||||
virSecurityDomainGenLabel domainGenSecurityLabel;
|
virSecurityDomainGenLabel domainGenSecurityLabel;
|
||||||
|
virSecurityDomainReserveLabel domainReserveSecurityLabel;
|
||||||
virSecurityDomainGetLabel domainGetSecurityLabel;
|
virSecurityDomainGetLabel domainGetSecurityLabel;
|
||||||
virSecurityDomainSetLabel domainSetSecurityLabel;
|
virSecurityDomainSetLabel domainSetSecurityLabel;
|
||||||
virSecurityDomainRestoreLabel domainRestoreSecurityLabel;
|
virSecurityDomainRestoreLabel domainRestoreSecurityLabel;
|
||||||
|
@ -215,6 +215,44 @@ done:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
SELinuxReserveSecurityLabel(virConnectPtr conn,
|
||||||
|
virDomainObjPtr vm)
|
||||||
|
{
|
||||||
|
security_context_t pctx;
|
||||||
|
context_t ctx = NULL;
|
||||||
|
const char *mcs;
|
||||||
|
|
||||||
|
if (getpidcon(vm->pid, &pctx) == -1) {
|
||||||
|
char ebuf[1024];
|
||||||
|
virSecurityReportError(conn, VIR_ERR_ERROR, _("%s: error calling "
|
||||||
|
"getpidcon(): %s"), __func__,
|
||||||
|
virStrerror(errno, ebuf, sizeof ebuf));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = context_new(pctx);
|
||||||
|
VIR_FREE(pctx);
|
||||||
|
if (!ctx)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
mcs = context_range_get(ctx);
|
||||||
|
if (!mcs)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
mcsAdd(mcs);
|
||||||
|
|
||||||
|
context_free(ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
context_free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
SELinuxSecurityDriverProbe(void)
|
SELinuxSecurityDriverProbe(void)
|
||||||
{
|
{
|
||||||
@ -422,6 +460,7 @@ virSecurityDriver virSELinuxSecurityDriver = {
|
|||||||
.domainSetSecurityImageLabel = SELinuxSetSecurityImageLabel,
|
.domainSetSecurityImageLabel = SELinuxSetSecurityImageLabel,
|
||||||
.domainRestoreSecurityImageLabel = SELinuxRestoreSecurityImageLabel,
|
.domainRestoreSecurityImageLabel = SELinuxRestoreSecurityImageLabel,
|
||||||
.domainGenSecurityLabel = SELinuxGenSecurityLabel,
|
.domainGenSecurityLabel = SELinuxGenSecurityLabel,
|
||||||
|
.domainReserveSecurityLabel = SELinuxReserveSecurityLabel,
|
||||||
.domainGetSecurityLabel = SELinuxGetSecurityLabel,
|
.domainGetSecurityLabel = SELinuxGetSecurityLabel,
|
||||||
.domainRestoreSecurityLabel = SELinuxRestoreSecurityLabel,
|
.domainRestoreSecurityLabel = SELinuxRestoreSecurityLabel,
|
||||||
.domainSetSecurityLabel = SELinuxSetSecurityLabel,
|
.domainSetSecurityLabel = SELinuxSetSecurityLabel,
|
||||||
|
@ -394,7 +394,7 @@ umlStartup(void) {
|
|||||||
¨_driver->domains,
|
¨_driver->domains,
|
||||||
uml_driver->configDir,
|
uml_driver->configDir,
|
||||||
uml_driver->autostartDir,
|
uml_driver->autostartDir,
|
||||||
NULL, NULL) < 0)
|
0, NULL, NULL) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
umlAutostartConfigs(uml_driver);
|
umlAutostartConfigs(uml_driver);
|
||||||
@ -433,7 +433,7 @@ umlReload(void) {
|
|||||||
¨_driver->domains,
|
¨_driver->domains,
|
||||||
uml_driver->configDir,
|
uml_driver->configDir,
|
||||||
uml_driver->autostartDir,
|
uml_driver->autostartDir,
|
||||||
NULL, NULL);
|
0, NULL, NULL);
|
||||||
|
|
||||||
umlAutostartConfigs(uml_driver);
|
umlAutostartConfigs(uml_driver);
|
||||||
umlDriverUnlock(uml_driver);
|
umlDriverUnlock(uml_driver);
|
||||||
|
Loading…
Reference in New Issue
Block a user