From nobody Sat May 4 08:26:31 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=linux.ibm.com ARC-Seal: i=1; a=rsa-sha256; t=1563911338; cv=none; d=zoho.com; s=zohoarc; b=bMwfzSeqqMA1zXfrK9u6jxD+EPXWN85h4VKXRr1J72m9qpN7y2z3OZM6n8Un7OIVj1bBonPM+VEkWsuYk0N+nYbbVw5zbVIh8+ah1XyEoe34IOxyjTGrsXTd8NpSt/wd+mZ2T0z7tGbmEMY5HNc32+n6KtJCXJDyrl2VHZQSucs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563911338; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To:ARC-Authentication-Results; bh=j8aCc7urCsdFCOF+X82fEDGas13ha5M0AAVyEdvICns=; b=CGHAK+mHxfrFiIqXamIhaeYEGJ6R8fdJx2fEquptiGdtxZKkaHKxCHHXw8iIgsP2GRUtyRlzHhUQiyxMldQ6xzipkDn8Q9bKR3eSjlJWDx3san8NOiDmER9rPJ18TTWp7G8KtDgXV6G+vwg9scibV701YIBZDTBlxunuepGtJDc= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1563911338371139.54547346170637; Tue, 23 Jul 2019 12:48:58 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 738CEC0AD28F; Tue, 23 Jul 2019 19:48:55 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4D0CD19C67; Tue, 23 Jul 2019 19:48:53 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 19C7118045CE; Tue, 23 Jul 2019 19:48:48 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x6NJmk2L030947 for ; Tue, 23 Jul 2019 15:48:46 -0400 Received: by smtp.corp.redhat.com (Postfix) id B569160BCE; Tue, 23 Jul 2019 19:48:46 +0000 (UTC) Received: from mx1.redhat.com (ext-mx19.extmail.prod.ext.phx2.redhat.com [10.5.110.48]) by smtp.corp.redhat.com (Postfix) with ESMTPS id ADC7B60497 for ; Tue, 23 Jul 2019 19:48:44 +0000 (UTC) Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5E77130923DE for ; Tue, 23 Jul 2019 19:48:43 +0000 (UTC) Received: from pps.filterd (m0098420.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x6NJmavF074980 for ; Tue, 23 Jul 2019 15:48:42 -0400 Received: from e14.ny.us.ibm.com (e14.ny.us.ibm.com [129.33.205.204]) by mx0b-001b2d01.pphosted.com with ESMTP id 2tx85ys77k-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Tue, 23 Jul 2019 15:48:38 -0400 Received: from localhost by e14.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 23 Jul 2019 20:47:12 +0100 Received: from b01cxnp23033.gho.pok.ibm.com (9.57.198.28) by e14.ny.us.ibm.com (146.89.104.201) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Tue, 23 Jul 2019 20:47:09 +0100 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp23033.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id x6NJl86l39059806 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 23 Jul 2019 19:47:08 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 64267AE060; Tue, 23 Jul 2019 19:47:08 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 9B7C5AE05C; Tue, 23 Jul 2019 19:47:07 +0000 (GMT) Received: from maxibm.br.ibm.com (unknown [9.18.235.170]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 23 Jul 2019 19:47:07 +0000 (GMT) From: "Maxiwell S. Garcia" To: libvir-list@redhat.com Date: Tue, 23 Jul 2019 16:47:05 -0300 MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 19072319-0052-0000-0000-000003E49638 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00011483; HX=3.00000242; KW=3.00000007; PH=3.00000004; SC=3.00000287; SDB=6.01236430; UDB=6.00651671; IPR=6.01017786; MB=3.00027858; MTD=3.00000008; XFM=3.00000015; UTC=2019-07-23 19:47:11 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 19072319-0053-0000-0000-000061CFA206 Message-Id: <20190723194705.27615-1-maxiwell@linux.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-07-23_08:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1906280000 definitions=main-1907230202 X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 238 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Tue, 23 Jul 2019 19:48:43 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Tue, 23 Jul 2019 19:48:43 +0000 (UTC) for IP:'148.163.158.5' DOMAIN:'mx0b-001b2d01.pphosted.com' HELO:'mx0a-001b2d01.pphosted.com' FROM:'maxiwell@linux.ibm.com' RCPT:'' X-RedHat-Spam-Score: -0.7 (RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS) 148.163.158.5 mx0b-001b2d01.pphosted.com 148.163.158.5 mx0b-001b2d01.pphosted.com X-Scanned-By: MIMEDefang 2.84 on 10.5.110.48 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com Cc: danielhb413@gmail.com, pkrempa@redhat.com, "Maxiwell S. Garcia" Subject: [libvirt] [PATCH v2] snapshot: Store both config and live XML in the snapshot domain X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Tue, 23 Jul 2019 19:48:57 +0000 (UTC) Content-Type: text/plain; charset="utf-8" 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 entry. In case of offline guest, the behavior remains the same and the config XML is saved in the snapshot XML as entry. The behavior of older snapshots of running guests, that don't have the new , remains the same too. The revert, in this case, overrides both active and inactive domain with the entry. So, the 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 Reviewed-by: Daniel Henrique Barboza --- src/conf/moment_conf.c | 1 + src/conf/moment_conf.h | 11 +++++++++ src/conf/snapshot_conf.c | 48 +++++++++++++++++++++++++++++++++++----- src/qemu/qemu_driver.c | 27 +++++++++++++++++----- src/util/virxml.c | 45 +++++++++++++++++++++++++++++++++++++ src/util/virxml.h | 8 +++++++ 6 files changed, 130 insertions(+), 10 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); } =20 /* 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 */ =20 + /* + * 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; }; =20 virClassPtr virClassForDomainMomentDef(void); diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c index 324901a560..8aeac9ab20 100644 --- a/src/conf/snapshot_conf.c +++ b/src/conf/snapshot_conf.c @@ -243,6 +243,8 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt, char *memoryFile =3D NULL; bool offline =3D !!(flags & VIR_DOMAIN_SNAPSHOT_PARSE_OFFLINE); virSaveCookieCallbacksPtr saveCookie =3D virDomainXMLOptionGetSaveCook= ie(xmlopt); + int domainflags =3D VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE; =20 if (!(def =3D virDomainSnapshotDefNew())) return NULL; @@ -292,8 +294,6 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt, * clients will have to decide between best effort * initialization or outright failure. */ if ((tmp =3D virXPathString("string(./domain/@type)", ctxt))) { - int domainflags =3D VIR_DOMAIN_DEF_PARSE_INACTIVE | - VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE; xmlNodePtr domainNode =3D virXPathNode("./domain", ctxt); =20 VIR_FREE(tmp); @@ -309,6 +309,20 @@ 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 (virXPathString("string(./inactiveDomain/@type)", ctxt)) { + xmlNodePtr domainNode =3D virXPathNode("./inactiveDomain", ctx= t); + + if (domainNode) { + def->parent.inactiveDom =3D virDomainDefParseNode(ctxt->no= de->doc, domainNode, + caps, xmlo= pt, NULL, domainflags); + if (!def->parent.inactiveDom) + goto cleanup; + } + } } else if (virDomainXMLOptionRunMomentPostParse(xmlopt, &def->parent) = < 0) { goto cleanup; } @@ -845,6 +859,10 @@ virDomainSnapshotDefFormatInternal(virBufferPtr buf, { size_t i; int domainflags =3D VIR_DOMAIN_DEF_FORMAT_INACTIVE; + virBuffer inactivedom_buf =3D VIR_BUFFER_INITIALIZER; + xmlXPathContextPtr inactivedom_ctxt =3D NULL; + char *inactivedom_str =3D NULL; + int ret =3D -1; =20 if (flags & VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE) domainflags |=3D VIR_DOMAIN_DEF_FORMAT_SECURE; @@ -903,6 +921,20 @@ virDomainSnapshotDefFormatInternal(virBufferPtr buf, virBufferAddLit(buf, "\n"); } =20 + if (def->parent.inactiveDom) { + if (virDomainDefFormatInternal(def->parent.inactiveDom, caps, + domainflags, &inactivedom_buf, xmlo= pt) < 0) + goto error; + + inactivedom_ctxt =3D virXPathBuildContext(&inactivedom_buf); + if (!(inactivedom_str =3D virXPathRenameNode("/domain", "inactiveD= omain", + inactivedom_ctxt))) + goto error; + + virBufferAddStr(buf, inactivedom_str); + virBufferAddLit(buf, "\n"); + } + if (virSaveCookieFormatBuf(buf, def->cookie, virDomainXMLOptionGetSaveCookie(xmlopt)) < = 0) goto error; @@ -917,11 +949,17 @@ virDomainSnapshotDefFormatInternal(virBufferPtr buf, if (virBufferCheckError(buf) < 0) goto error; =20 - return 0; + ret =3D 0; =20 error: - virBufferFreeAndReset(buf); - return -1; + VIR_FREE(inactivedom_str); + xmlXPathFreeContext(inactivedom_ctxt); + virBufferFreeAndReset(&inactivedom_buf); + + if (ret < 0) + virBufferFreeAndReset(buf); + + return ret; } =20 =20 diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 482f915b67..9b95e9b766 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -15697,6 +15697,13 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, VIR_DOMAIN_DEF_PAR= SE_SKIP_VALIDATE))) goto endjob; =20 + if (vm->newDef) { + def->parent.inactiveDom =3D virDomainDefCopy(vm->newDef, caps, + driver->xmlopt, NUL= L, true); + if (!def->parent.inactiveDom) + goto endjob; + } + if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) { align_location =3D VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL; align_match =3D false; @@ -16231,6 +16238,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr sna= pshot, qemuDomainObjPrivatePtr priv; int rc; virDomainDefPtr config =3D NULL; + virDomainDefPtr inactiveConfig =3D NULL; virQEMUDriverConfigPtr cfg =3D NULL; virCapsPtr caps =3D NULL; bool was_stopped =3D false; @@ -16331,17 +16339,22 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr s= napshot, * in the failure cases where we know there was no change? */ } =20 - /* 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 =3D virDomainDefCopy(snap->def->dom, caps, driver->xmlopt, NULL, true); if (!config) goto endjob; } + if (snap->def->inactiveDom) { + inactiveConfig =3D virDomainDefCopy(snap->def->inactiveDom, caps, + driver->xmlopt, NULL, true); + if (!inactiveConfig) + goto endjob; + } =20 cookie =3D (qemuDomainSaveCookiePtr) snapdef->cookie; =20 @@ -16592,6 +16605,10 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr sn= apshot, goto endjob; } =20 + if (inactiveConfig) { + virDomainDefFree(vm->newDef); + VIR_STEAL_PTR(vm->newDef, inactiveConfig); + } ret =3D 0; =20 endjob: diff --git a/src/util/virxml.c b/src/util/virxml.c index f55b9a362c..756c0eedbc 100644 --- a/src/util/virxml.c +++ b/src/util/virxml.c @@ -1408,3 +1408,48 @@ virXPathContextNodeRestore(virXPathContextNodeSavePt= r save) =20 save->ctxt->node =3D save->node; } + + +/** + * virXPathBuildContext: convert an parent buffer to an + * XPath context ptr. The caller has to free the ptr. + */ +xmlXPathContextPtr +virXPathBuildContext(virBufferPtr root) +{ + xmlDocPtr doc; + + if (!root) + return NULL; + + doc =3D virXMLParseString(virBufferCurrentContent(root), NULL); + if (!doc) + return NULL; + + return xmlXPathNewContext(doc); +} + + +/** + * virXPathRenameNode: get the XML node using the 'xpath' and + * rename it with the 'newname' string. + * + * Returns the XML string of the node found by 'xpath' or NULL + * on error. The caller has to free the string. + */ +char * +virXPathRenameNode(const char *xpath, + const char *newname, + xmlXPathContextPtr ctxt) +{ + xmlNodePtr node; + + if (!xpath || !newname || !ctxt) + return NULL; + + if (!(node =3D virXPathNode(xpath, ctxt))) + return NULL; + + xmlNodeSetName(node, (xmlChar *) newname); + return virXMLNodeToString(node->doc, node); +} diff --git a/src/util/virxml.h b/src/util/virxml.h index 6208977dd1..48a507c3c1 100644 --- a/src/util/virxml.h +++ b/src/util/virxml.h @@ -220,6 +220,14 @@ virXMLFormatElement(virBufferPtr buf, virBufferPtr childBuf) ATTRIBUTE_RETURN_CHECK; =20 +xmlXPathContextPtr +virXPathBuildContext(virBufferPtr root); + +char * +virXPathRenameNode(const char *xpath, + const char *newname, + xmlXPathContextPtr ctxt); + struct _virXPathContextNodeSave { xmlXPathContextPtr ctxt; xmlNodePtr node; --=20 2.20.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list