virDomainSnapshotDefPtr def = NULL;
virDomainSnapshotDefPtr ret = NULL;
xmlNodePtr *nodes = NULL;
+ xmlNodePtr inactiveDomNode = NULL;
size_t i;
int n;
char *creation = NULL, *state = NULL;
char *memoryFile = NULL;
bool offline = !!(flags & VIR_DOMAIN_SNAPSHOT_PARSE_OFFLINE);
virSaveCookieCallbacksPtr saveCookie = virDomainXMLOptionGetSaveCookie(xmlopt);
+ int domainflags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
+ VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
if (!(def = virDomainSnapshotDefNew()))
return NULL;
* clients will have to decide between best effort
* initialization or outright failure. */
if ((tmp = virXPathString("string(./domain/@type)", ctxt))) {
- int domainflags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
- VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
xmlNodePtr domainNode = virXPathNode("./domain", ctxt);
VIR_FREE(tmp);
} else {
VIR_WARN("parsing older snapshot that lacks domain");
}
+
+ /* /inactiveDomain entry saves the config XML present in a running
+ * VM. In case of absent, leave parent.inactiveDom NULL and use
+ * parent.dom for config and live XML. */
+ if ((inactiveDomNode = virXPathNode("./inactiveDomain", ctxt))) {
+ def->parent.inactiveDom = virDomainDefParseNode(ctxt->node->doc, inactiveDomNode,
+ caps, xmlopt, NULL, domainflags);
+ if (!def->parent.inactiveDom)
+ goto cleanup;
+ }
} else if (virDomainXMLOptionRunMomentPostParse(xmlopt, &def->parent) < 0) {
goto cleanup;
}
virBufferAddLit(buf, "</domain>\n");
}
+ if (def->parent.inactiveDom) {
+ if (virDomainDefFormatInternalSetRootName(def->parent.inactiveDom, caps,
+ domainflags, buf, xmlopt,
+ "inactiveDomain") < 0)
+ goto error;
+ }
+
if (virSaveCookieFormatBuf(buf, def->cookie,
virDomainXMLOptionGetSaveCookie(xmlopt)) < 0)
goto error;
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
goto endjob;
+ if (vm->newDef) {
+ def->parent.inactiveDom = virDomainDefCopy(vm->newDef, caps,
+ driver->xmlopt, priv->qemuCaps, true);
+ if (!def->parent.inactiveDom)
+ goto endjob;
+ }
+
if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
align_match = false;
qemuDomainObjPrivatePtr priv;
int rc;
virDomainDefPtr config = NULL;
+ virDomainDefPtr inactiveConfig = NULL;
virQEMUDriverConfigPtr cfg = NULL;
virCapsPtr caps = NULL;
bool was_stopped = false;
* in the failure cases where we know there was no change? */
}
- /* Prepare to copy the snapshot inactive xml as the config of this
- * domain.
- *
- * XXX Should domain snapshots track live xml rather
- * than inactive xml? */
if (snap->def->dom) {
config = virDomainDefCopy(snap->def->dom, caps,
driver->xmlopt, priv->qemuCaps, true);
goto endjob;
}
+ if (snap->def->inactiveDom) {
+ inactiveConfig = virDomainDefCopy(snap->def->inactiveDom, caps,
+ driver->xmlopt, priv->qemuCaps, true);
+ if (!inactiveConfig)
+ goto endjob;
+ } else {
+ /* Inactive domain definition is missing:
+ * - either this is an old active snapshot and we need to copy the
+ * active definition as an inactive one
+ * - or this is an inactive snapshot which means config contains the
+ * inactive definition.
+ */
+ if (snapdef->state == VIR_DOMAIN_SNAPSHOT_RUNNING ||
+ snapdef->state == VIR_DOMAIN_SNAPSHOT_PAUSED) {
+ inactiveConfig = virDomainDefCopy(snap->def->dom, caps,
+ driver->xmlopt, priv->qemuCaps, true);
+ if (!inactiveConfig)
+ goto endjob;
+ } else {
+ VIR_STEAL_PTR(inactiveConfig, config);
+ }
+ }
+
cookie = (qemuDomainSaveCookiePtr) snapdef->cookie;
switch ((virDomainSnapshotState) snapdef->state) {
goto endjob;
}
if (config) {
- virDomainObjAssignDef(vm, config, false, NULL);
virCPUDefFree(priv->origCPU);
VIR_STEAL_PTR(priv->origCPU, origCPU);
- config = NULL;
- defined = true;
}
if (cookie && !cookie->slirpHelper)
priv->disableSlirp = true;
+ if (inactiveConfig) {
+ virDomainObjAssignDef(vm, inactiveConfig, false, NULL);
+ inactiveConfig = NULL;
+ defined = true;
+ }
} else {
/* Transitions 2, 3 */
load:
was_stopped = true;
+
+ if (inactiveConfig) {
+ virDomainObjAssignDef(vm, inactiveConfig, false, NULL);
+ inactiveConfig = NULL;
+ defined = true;
+ }
+
if (config) {
- virDomainObjAssignDef(vm, config, false, NULL);
+ virDomainObjAssignDef(vm, config, true, NULL);
config = NULL;
- defined = true;
}
/* No cookie means libvirt which saved the domain was too old to
qemuProcessEndJob(driver, vm);
goto cleanup;
}
- if (config) {
- virDomainObjAssignDef(vm, config, false, NULL);
- config = NULL;
+
+ if (inactiveConfig) {
+ virDomainObjAssignDef(vm, inactiveConfig, false, NULL);
+ inactiveConfig = NULL;
defined = true;
}
virNWFilterUnlockFilterUpdates();
virCPUDefFree(origCPU);
virDomainDefFree(config);
+ virDomainDefFree(inactiveConfig);
return ret;
}