On Tue, Jun 02, 2009 at 03:55:27PM +0200, Daniel Veillard wrote: > On Wed, May 27, 2009 at 04:58:44PM +0100, Daniel P. Berrange wrote: > [...] > > + xmlXPathContextPtr ctxt) > > +{ > > + char *tmp = NULL; > > + long val; > > + xmlNodePtr config; > > + xmlNodePtr oldctxt; > > I would s/oldctxt/oldnode/ as what is saved is really only the old > XPath current node not the context itself. Good idea, changed this. > > [...] > > +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))) > > Hum we are leaking the buffer content here. > > > + goto cleanup; > > + > > + virBufferAdd(&buf, config_xml, strlen(config_xml)); > > + virBufferAddLit(&buf, "</domstatus>\n"); > > + > > + xml = virBufferContentAndReset(&buf); > > +cleanup: > > + VIR_FREE(config_xml); > > + return xml; > > + > > +} Yes, and also forgetting to check virBufferError() to report OOM. Fixed the cleanup in this function now. > > + virDomainObjUnlock(obj); > > + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, > > + _("unexpected domain %s already exists"), obj->def->name); > > > let's wrap to 80 columns > > [...] > > +/* > > + * Open an existing VM's monitor, and re-detect VCPUs > > + * threads > > maybe update the comment about the security labels too, especially as > this is a bit arcane. Updated these two. > > @@ -1519,10 +1519,8 @@ cleanup: > > vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && > > vm->def->graphics[0]->data.vnc.autoport) > > vm->def->graphics[0]->data.vnc.port = -1; > > - if (vm->logfile != -1) { > > - close(vm->logfile); > > - vm->logfile = -1; > > - } > > + if (logfile != -1) > > + close(logfile); > > vm->def->id = -1; > > return -1; > > } > > Hum, do we still use vm->logfile field then ? Maybe I didn't see the > place where it was removed from the structure. Yep, this field in the struct has been killed off - see domain_conf.h Here's the updated patch in full Daniel diff --git a/src/domain_conf.c b/src/domain_conf.c --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -39,6 +39,7 @@ #include "util.h" #include "buf.h" #include "c-ctype.h" +#include "logging.h" #define VIR_FROM_THIS VIR_FROM_DOMAIN @@ -511,6 +512,31 @@ void virDomainObjListFree(virDomainObjLi 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, virDomainObjListPtr doms, const virDomainDefPtr def) @@ -530,29 +556,15 @@ virDomainObjPtr virDomainAssignDef(virCo 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; + if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) { + virReportOOMError(conn); + return NULL; + } + + if (!(domain = virDomainObjNew(conn))) + return NULL; + domain->def = def; - domain->monitorWatch = -1; - domain->monitor = -1; - - if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) { - virReportOOMError(conn); - VIR_FREE(domain); - return NULL; - } doms->objs[doms->count] = domain; doms->count++; @@ -2623,6 +2635,68 @@ no_memory: 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. */ static void catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) @@ -2755,6 +2829,78 @@ cleanup: xmlXPathFreeContext(ctxt); 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 */ /************************************************************************ @@ -3707,6 +3853,40 @@ char *virDomainDefFormat(virConnectPtr c 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 @@ -3782,6 +3962,27 @@ cleanup: 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, virCapsPtr caps, @@ -3835,17 +4036,68 @@ error: 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, virCapsPtr caps, virDomainObjListPtr doms, const char *configDir, const char *autostartDir, + int liveStatus, virDomainLoadConfigNotify notify, void *opaque) { DIR *dir; struct dirent *entry; + VIR_INFO("Scanning for %s configs in %s", + liveStatus ? "live" : "persistent", configDir); + if (!(dir = opendir(configDir))) { if (errno == ENOENT) return 0; @@ -3866,14 +4118,24 @@ int virDomainLoadAllConfigs(virConnectPt /* NB: ignoring errors, so one malformed config doesn't kill the whole process */ - dom = virDomainLoadConfig(conn, - caps, - doms, - configDir, - autostartDir, - entry->d_name, - notify, - opaque); + 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, + caps, + doms, + configDir, + autostartDir, + entry->d_name, + notify, + opaque); if (dom) { virDomainObjUnlock(dom); dom->persistent = 1; diff --git a/src/domain_conf.h b/src/domain_conf.h --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -515,7 +515,6 @@ struct _virDomainObj { int monitor; char *monitorpath; int monitorWatch; - int logfile; int pid; int state; @@ -589,10 +588,22 @@ virDomainDefPtr virDomainDefParseNode(vi xmlDocPtr doc, xmlNodePtr root, int flags); + +virDomainObjPtr virDomainObjParseFile(virConnectPtr conn, + virCapsPtr caps, + const char *filename); +virDomainObjPtr virDomainObjParseNode(virConnectPtr conn, + virCapsPtr caps, + xmlDocPtr xml, + xmlNodePtr root); + #endif char *virDomainDefFormat(virConnectPtr conn, virDomainDefPtr def, int flags); +char *virDomainObjFormat(virConnectPtr conn, + virDomainObjPtr obj, + int flags); int virDomainCpuSetParse(virConnectPtr conn, const char **str, @@ -615,6 +626,9 @@ int virDomainSaveXML(virConnectPtr conn, int virDomainSaveConfig(virConnectPtr conn, const char *configDir, virDomainDefPtr def); +int virDomainSaveStatus(virConnectPtr conn, + const char *statusDir, + virDomainObjPtr obj); typedef void (*virDomainLoadConfigNotify)(virDomainObjPtr dom, int newDomain, @@ -634,6 +648,7 @@ int virDomainLoadAllConfigs(virConnectPt virDomainObjListPtr doms, const char *configDir, const char *autostartDir, + int liveStatus, virDomainLoadConfigNotify notify, void *opaque); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -94,6 +94,7 @@ virDomainObjListFree; virDomainRemoveInactive; virDomainSaveXML; virDomainSaveConfig; +virDomainSaveStatus; virDomainSoundDefFree; virDomainSoundModelTypeFromString; virDomainSoundModelTypeToString; diff --git a/src/lxc_driver.c b/src/lxc_driver.c --- a/src/lxc_driver.c +++ b/src/lxc_driver.c @@ -1190,7 +1190,7 @@ static int lxcStartup(void) &lxc_driver->domains, lxc_driver->configDir, lxc_driver->autostartDir, - NULL, NULL) < 0) + 0, NULL, NULL) < 0) goto cleanup; for (i = 0 ; i < lxc_driver->domains.count ; i++) { diff --git a/src/qemu_conf.c b/src/qemu_conf.c --- a/src/qemu_conf.c +++ b/src/qemu_conf.c @@ -2798,193 +2798,3 @@ cleanup: 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; -} diff --git a/src/qemu_conf.h b/src/qemu_conf.h --- a/src/qemu_conf.h +++ b/src/qemu_conf.h @@ -92,15 +92,6 @@ struct qemud_driver { 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. */ #define QEMUD_MIGRATION_FIRST_PORT 49152 @@ -143,13 +134,4 @@ virDomainDefPtr qemuParseCommandLineStri virCapsPtr caps, 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 */ diff --git a/src/qemu_driver.c b/src/qemu_driver.c --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -120,6 +120,8 @@ static int qemudMonitorCommandExtra(cons static int qemudDomainSetMemoryBalloon(virConnectPtr conn, virDomainObjPtr vm, unsigned long newmem); +static int qemudDetectVcpuPIDs(virConnectPtr conn, + virDomainObjPtr vm); static struct qemud_driver *qemu_driver = NULL; @@ -282,79 +284,65 @@ static int qemudOpenMonitor(virConnectPt const char *monitor, 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 * - * Reconnect running vms to the daemon process - */ -static int -qemudReconnectVMs(struct qemud_driver *driver) + * Try to re-open the resources for live VMs that we care + * about. + */ +static void +qemuReconnectDomains(struct qemud_driver *driver) { int i; for (i = 0 ; i < driver->domains.count ; i++) { - virDomainObjPtr vm = driver->domains.objs[i]; - qemudDomainStatusPtr status = NULL; - char *config = NULL; - int rc; - - virDomainObjLock(vm); - if ((rc = virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) == 0) - DEBUG("Found pid %d for '%s'", vm->pid, vm->def->name); - else - goto next; - - 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; - } - - 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; + virDomainObjPtr obj = driver->domains.objs[i]; + + virDomainObjLock(obj); + if (qemuReconnectDomain(driver, obj) < 0) { + /* If we can't get the monitor back, then kill the VM + * so user has ability to start it again later without + * danger of ending up running twice */ + qemudShutdownVMDaemon(NULL, driver, obj); + } + virDomainObjUnlock(obj); + } } static int @@ -508,14 +496,25 @@ qemudStartup(void) { 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, qemu_driver->caps, &qemu_driver->domains, qemu_driver->configDir, qemu_driver->autostartDir, - NULL, NULL) < 0) - goto error; - qemudReconnectVMs(qemu_driver); + 0, NULL, NULL) < 0) + goto error; qemuDriverUnlock(qemu_driver); qemudAutostartConfigs(qemu_driver); @@ -564,7 +563,7 @@ qemudReload(void) { &qemu_driver->domains, qemu_driver->configDir, qemu_driver->autostartDir, - qemudNotifyLoadDomain, qemu_driver); + 0, qemudNotifyLoadDomain, qemu_driver); qemuDriverUnlock(qemu_driver); qemudAutostartConfigs(qemu_driver); @@ -1329,6 +1328,7 @@ static int qemudStartVMDaemon(virConnect int pos = -1; char ebuf[1024]; char *pidfile = NULL; + int logfile; struct gemudHookData hookData; hookData.conn = conn; @@ -1370,7 +1370,7 @@ static int qemudStartVMDaemon(virConnect 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; emulator = vm->def->emulator; @@ -1419,29 +1419,29 @@ static int qemudStartVMDaemon(virConnect tmp = progenv; 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"), 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"), virStrerror(errno, ebuf, sizeof ebuf)); tmp++; } tmp = argv; 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"), 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"), virStrerror(errno, ebuf, sizeof ebuf)); tmp++; } - if (safewrite(vm->logfile, "\n", 1) < 0) + if (safewrite(logfile, "\n", 1) < 0) VIR_WARN(_("Unable to write argv to logfile: %s\n"), 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"), virStrerror(errno, ebuf, sizeof ebuf)); @@ -1449,7 +1449,7 @@ static int qemudStartVMDaemon(virConnect FD_SET(tapfds[i], &keepfd); ret = virExecDaemonize(conn, argv, progenv, &keepfd, &child, - stdin_fd, &vm->logfile, &vm->logfile, + stdin_fd, &logfile, &logfile, VIR_EXEC_NONBLOCK, qemudSecurityHook, &hookData, pidfile); @@ -1499,7 +1499,7 @@ static int qemudStartVMDaemon(virConnect (qemudInitCpus(conn, vm, migrateFrom) < 0) || (qemudInitPasswords(conn, driver, vm) < 0) || (qemudDomainSetMemoryBalloon(conn, vm, vm->def->memory) < 0) || - (qemudSaveDomainStatus(conn, qemu_driver, vm) < 0)) { + (virDomainSaveStatus(conn, driver->stateDir, vm) < 0)) { qemudShutdownVMDaemon(conn, driver, vm); ret = -1; /* 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]->data.vnc.autoport) vm->def->graphics[0]->data.vnc.port = -1; - if (vm->logfile != -1) { - close(vm->logfile); - vm->logfile = -1; - } + if (logfile != -1) + close(logfile); vm->def->id = -1; return -1; } @@ -1547,14 +1545,8 @@ static void qemudShutdownVMDaemon(virCon 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) close(vm->monitor); - vm->logfile = -1; vm->monitor = -1; /* shut it off for sure */ @@ -2183,7 +2175,7 @@ static int qemudDomainSuspend(virDomainP VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); VIR_FREE(info); } - if (qemudSaveDomainStatus(dom->conn, driver, vm) < 0) + if (virDomainSaveStatus(dom->conn, driver->stateDir, vm) < 0) goto cleanup; ret = 0; @@ -2233,7 +2225,7 @@ static int qemudDomainResume(virDomainPt VIR_DOMAIN_EVENT_RESUMED_UNPAUSED); VIR_FREE(info); } - if (qemudSaveDomainStatus(dom->conn, driver, vm) < 0) + if (virDomainSaveStatus(dom->conn, driver->stateDir, vm) < 0) goto cleanup; ret = 0; @@ -4116,7 +4108,7 @@ static int qemudDomainAttachDevice(virDo goto cleanup; } - if (!ret && qemudSaveDomainStatus(dom->conn, driver, vm) < 0) + if (!ret && virDomainSaveStatus(dom->conn, driver->stateDir, vm) < 0) ret = -1; cleanup: @@ -4238,7 +4230,7 @@ static int qemudDomainDetachDevice(virDo qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%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; cleanup: diff --git a/src/security.h b/src/security.h --- a/src/security.h +++ b/src/security.h @@ -38,6 +38,8 @@ typedef int (*virSecurityDomainSetImageL virDomainDiskDefPtr disk); typedef int (*virSecurityDomainGenLabel) (virConnectPtr conn, virDomainObjPtr sec); +typedef int (*virSecurityDomainReserveLabel) (virConnectPtr conn, + virDomainObjPtr sec); typedef int (*virSecurityDomainGetLabel) (virConnectPtr conn, virDomainObjPtr vm, virSecurityLabelPtr sec); @@ -57,6 +59,7 @@ struct _virSecurityDriver { virSecurityDomainRestoreImageLabel domainRestoreSecurityImageLabel; virSecurityDomainSetImageLabel domainSetSecurityImageLabel; virSecurityDomainGenLabel domainGenSecurityLabel; + virSecurityDomainReserveLabel domainReserveSecurityLabel; virSecurityDomainGetLabel domainGetSecurityLabel; virSecurityDomainSetLabel domainSetSecurityLabel; virSecurityDomainRestoreLabel domainRestoreSecurityLabel; diff --git a/src/security_selinux.c b/src/security_selinux.c --- a/src/security_selinux.c +++ b/src/security_selinux.c @@ -216,6 +216,44 @@ done: } 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 SELinuxSecurityDriverProbe(void) { return is_selinux_enabled() ? SECURITY_DRIVER_ENABLE : SECURITY_DRIVER_DISABLE; @@ -422,6 +460,7 @@ virSecurityDriver virSELinuxSecurityDriv .domainSetSecurityImageLabel = SELinuxSetSecurityImageLabel, .domainRestoreSecurityImageLabel = SELinuxRestoreSecurityImageLabel, .domainGenSecurityLabel = SELinuxGenSecurityLabel, + .domainReserveSecurityLabel = SELinuxReserveSecurityLabel, .domainGetSecurityLabel = SELinuxGetSecurityLabel, .domainRestoreSecurityLabel = SELinuxRestoreSecurityLabel, .domainSetSecurityLabel = SELinuxSetSecurityLabel, diff --git a/src/uml_driver.c b/src/uml_driver.c --- a/src/uml_driver.c +++ b/src/uml_driver.c @@ -394,7 +394,7 @@ umlStartup(void) { ¨_driver->domains, uml_driver->configDir, uml_driver->autostartDir, - NULL, NULL) < 0) + 0, NULL, NULL) < 0) goto error; umlAutostartConfigs(uml_driver); @@ -433,7 +433,7 @@ umlReload(void) { ¨_driver->domains, uml_driver->configDir, uml_driver->autostartDir, - NULL, NULL); + 0, NULL, NULL); umlAutostartConfigs(uml_driver); umlDriverUnlock(uml_driver); -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list