[libvirt] [PATCH v3 2/2] snapshot: Store both config and live XML in the snapshot domain

Daniel Henrique Barboza danielhb413 at gmail.com
Mon Aug 19 18:50:13 UTC 2019



On 8/14/19 11:47 AM, Maxiwell S. Garcia wrote:
> The snapshot-create operation of running guests saves the live
> XML and uses it to replace the active and inactive domain in
> case of revert. So, the config XML is ignored by the snapshot
> process. This commit changes it and adds the config XML in the
> snapshot XML as the <inactiveDomain> entry.
>
> In case of offline guest, the behavior remains the same and the
> config XML is saved in the snapshot XML as <domain> entry. The
> behavior of older snapshots of running guests, that don't have
> the new <inactiveDomain>, remains the same too. The revert, in
> this case, overrides both active and inactive domain with the
> <domain> entry. So, the <inactiveDomain> in the snapshot XML is
> not required to snapshot work, but it's useful to preserve the
> config XML of running guests.
>
> Signed-off-by: Maxiwell S. Garcia <maxiwell at linux.ibm.com>
> ---

Reviewed-by: Daniel Henrique Barboza <danielhb413 at gmail.com>
Tested-by: Daniel Henrique Barboza <danielhb413 at gmail.com>

>   src/conf/moment_conf.c   |  1 +
>   src/conf/moment_conf.h   | 11 +++++++++++
>   src/conf/snapshot_conf.c | 23 +++++++++++++++++++++--
>   src/qemu/qemu_driver.c   | 37 ++++++++++++++++++++++++++++---------
>   4 files changed, 61 insertions(+), 11 deletions(-)
>
> diff --git a/src/conf/moment_conf.c b/src/conf/moment_conf.c
> index fea13f0f97..f54a44b33e 100644
> --- a/src/conf/moment_conf.c
> +++ b/src/conf/moment_conf.c
> @@ -66,6 +66,7 @@ virDomainMomentDefDispose(void *obj)
>       VIR_FREE(def->description);
>       VIR_FREE(def->parent_name);
>       virDomainDefFree(def->dom);
> +    virDomainDefFree(def->inactiveDom);
>   }
>   
>   /* Provide defaults for creation time and moment name after parsing XML */
> diff --git a/src/conf/moment_conf.h b/src/conf/moment_conf.h
> index 9fdbef2172..70cc47bd70 100644
> --- a/src/conf/moment_conf.h
> +++ b/src/conf/moment_conf.h
> @@ -36,7 +36,18 @@ struct _virDomainMomentDef {
>       char *parent_name;
>       long long creationTime; /* in seconds */
>   
> +    /*
> +     * Store the active domain definition in case of online
> +     * guest and the inactive domain definition in case of
> +     * offline guest
> +     */
>       virDomainDefPtr dom;
> +
> +    /*
> +     * Store the inactive domain definition in case of online
> +     * guest and leave NULL in case of offline guest
> +     */
> +    virDomainDefPtr inactiveDom;
>   };
>   
>   virClassPtr virClassForDomainMomentDef(void);
> diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
> index 7996589ad2..36435043ca 100644
> --- a/src/conf/snapshot_conf.c
> +++ b/src/conf/snapshot_conf.c
> @@ -235,6 +235,7 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt,
>       virDomainSnapshotDefPtr def = NULL;
>       virDomainSnapshotDefPtr ret = NULL;
>       xmlNodePtr *nodes = NULL;
> +    xmlNodePtr inactiveDomNode = NULL;
>       size_t i;
>       int n;
>       char *creation = NULL, *state = NULL;
> @@ -244,6 +245,8 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt,
>       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;
> @@ -293,8 +296,6 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt,
>            * 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);
> @@ -311,6 +312,16 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt,
>           } 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;
>       }
> @@ -405,6 +416,7 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt,
>       VIR_FREE(nodes);
>       VIR_FREE(memorySnapshot);
>       VIR_FREE(memoryFile);
> +    VIR_FREE(inactiveDomNode);
>       virObjectUnref(def);
>   
>       return ret;
> @@ -908,6 +920,13 @@ virDomainSnapshotDefFormatInternal(virBufferPtr buf,
>           virBufferAddLit(buf, "</domain>\n");
>       }
>   
> +    if (def->parent.inactiveDom) {
> +        int inactivedomainflags = domainflags | VIR_DOMAIN_DEF_FORMAT_INACTIVE_NODE;
> +        if (virDomainDefFormatInternal(def->parent.inactiveDom, caps,
> +                                       inactivedomainflags, buf, xmlopt) < 0)
> +            goto error;
> +    }
> +
>       if (virSaveCookieFormatBuf(buf, def->cookie,
>                                  virDomainXMLOptionGetSaveCookie(xmlopt)) < 0)
>           goto error;
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 48c7b5628b..b3edb40a80 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -15911,6 +15911,13 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
>                                                           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;
> @@ -16443,6 +16450,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
>       qemuDomainObjPrivatePtr priv;
>       int rc;
>       virDomainDefPtr config = NULL;
> +    virDomainDefPtr inactiveConfig = NULL;
>       virQEMUDriverConfigPtr cfg = NULL;
>       virCapsPtr caps = NULL;
>       bool was_stopped = false;
> @@ -16544,11 +16552,10 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
>            * 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?  */
> +    /* Prepare to copy the snapshot inactive domain as the config XML
> +     * and the snapshot domain as the live XML. In case of inactive domain
> +     * NULL, both config and live XML will be copied from snapshot domain.
> +     */
>       if (snap->def->dom) {
>           config = virDomainDefCopy(snap->def->dom, caps,
>                                     driver->xmlopt, priv->qemuCaps, true);
> @@ -16556,6 +16563,15 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
>               goto endjob;
>       }
>   
> +    if (snap->def->inactiveDom) {
> +        inactiveConfig = virDomainDefCopy(snap->def->inactiveDom, caps,
> +                                          driver->xmlopt, priv->qemuCaps, true);
> +        if (!inactiveConfig)
> +            goto endjob;
> +    } else {
> +        inactiveConfig = config;
> +    }
> +
>       cookie = (qemuDomainSaveCookiePtr) snapdef->cookie;
>   
>       switch ((virDomainSnapshotState) snapdef->state) {
> @@ -16658,16 +16674,19 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
>                   goto endjob;
>               }
>               if (config) {
> -                virDomainObjAssignDef(vm, config, false, NULL);
>                   virCPUDefFree(priv->origCPU);
>                   VIR_STEAL_PTR(priv->origCPU, origCPU);
>               }
> +            if (inactiveConfig)
> +                virDomainObjAssignDef(vm, inactiveConfig, false, NULL);
>           } else {
>               /* Transitions 2, 3 */
>           load:
>               was_stopped = true;
> +            if (inactiveConfig)
> +                virDomainObjAssignDef(vm, inactiveConfig, false, NULL);
>               if (config)
> -                virDomainObjAssignDef(vm, config, false, NULL);
> +                virDomainObjAssignDef(vm, config, true, NULL);
>   
>               /* No cookie means libvirt which saved the domain was too old to
>                * mess up the CPU definitions.
> @@ -16753,8 +16772,8 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
>               qemuProcessEndJob(driver, vm);
>               goto cleanup;
>           }
> -        if (config)
> -            virDomainObjAssignDef(vm, config, false, NULL);
> +        if (inactiveConfig)
> +            virDomainObjAssignDef(vm, inactiveConfig, false, NULL);
>   
>           if (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
>                        VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) {

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20190819/d809eabe/attachment-0001.htm>


More information about the libvir-list mailing list