From nobody Sat Feb 7 10:44:38 2026 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=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1550957108505649.8810646135089; Sat, 23 Feb 2019 13:25:08 -0800 (PST) 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 ABC56C057F40; Sat, 23 Feb 2019 21:25:06 +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 757F157BF; Sat, 23 Feb 2019 21:25:06 +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 1C4D2181A135; Sat, 23 Feb 2019 21:25:06 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x1NLOpPt005054 for ; Sat, 23 Feb 2019 16:24:51 -0500 Received: by smtp.corp.redhat.com (Postfix) id 5EFC05C5E0; Sat, 23 Feb 2019 21:24:51 +0000 (UTC) Received: from blue.redhat.com (ovpn-116-222.phx2.redhat.com [10.3.116.222]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1E9595C21E; Sat, 23 Feb 2019 21:24:51 +0000 (UTC) From: Eric Blake To: libvir-list@redhat.com Date: Sat, 23 Feb 2019 15:24:40 -0600 Message-Id: <20190223212445.21786-7-eblake@redhat.com> In-Reply-To: <20190223212445.21786-1-eblake@redhat.com> References: <20190223212445.21786-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-loop: libvir-list@redhat.com Cc: nsoffer@redhat.com Subject: [libvirt] [PATCH v2 06/11] snapshot: Add virDomainSnapshotDefParseList 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]); Sat, 23 Feb 2019 21:25:07 +0000 (UTC) Content-Type: text/plain; charset="utf-8" Add a new function to make it possible to parse a list of snapshots at once. This is a counterpart to the previous patch making it possible to produce all snapshots in a single XML string, and intentionally parses the same top-level element with an optional attribute current=3D'name'. Note that existing REDEFINE code uses virDomainSnapshotRedefinePrep() for some sanity checking - much of that checking involves parent/child relationships (which make sense when doing one element at a time and worrying about replacement), but where this patch gets away with the much simpler final call to virDomainSnapshotUpdateRelations() (for all relationship checking after the end, since we know we started with no relations at all, and since checking parent relationships per-snapshot is not viable as we don't control which order the snapshots appear in). All other domain-agnostic sanity checks used during a redefinition are copied here. Signed-off-by: Eric Blake Reviewed-by: John Ferlan --- src/conf/snapshot_conf.h | 7 ++ src/conf/snapshot_conf.c | 135 +++++++++++++++++++++++++++++++++++++++ src/libvirt_private.syms | 1 + 3 files changed, 143 insertions(+) diff --git a/src/conf/snapshot_conf.h b/src/conf/snapshot_conf.h index 19ab75f895..6a92241fe6 100644 --- a/src/conf/snapshot_conf.h +++ b/src/conf/snapshot_conf.h @@ -117,6 +117,13 @@ virDomainSnapshotDefPtr virDomainSnapshotDefParseNode(= xmlDocPtr xml, virCapsPtr caps, virDomainXMLOptionPt= r xmlopt, unsigned int flags); +int virDomainSnapshotDefParseList(const char *xmlSstr, + const unsigned char *domain_uuid, + virDomainSnapshotObjListPtr snapshots, + virDomainSnapshotObjPtr *current_snap, + virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, + unsigned int flags); void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def); char *virDomainSnapshotDefFormat(const char *uuidstr, virDomainSnapshotDefPtr def, diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c index 963dc10247..61e26726e9 100644 --- a/src/conf/snapshot_conf.c +++ b/src/conf/snapshot_conf.c @@ -426,6 +426,141 @@ virDomainSnapshotDefParseString(const char *xmlStr, } +int virDomainSnapshotDefParseList(const char *xmlStr, + const unsigned char *domain_uuid, + virDomainSnapshotObjListPtr snapshots, + virDomainSnapshotObjPtr *current_snap, + virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, + unsigned int flags) +{ + int ret =3D -1; + xmlDocPtr xml; + xmlNodePtr root; + xmlXPathContextPtr ctxt =3D NULL; + char *current =3D NULL; + int n; + size_t i; + VIR_AUTOFREE(xmlNodePtr *) nodes =3D NULL; + int keepBlanksDefault =3D xmlKeepBlanksDefault(0); + + if (!(flags & VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE) || + (flags & VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("incorrect flags for bulk parse")); + return -1; + } + if (snapshots->metaroot.nchildren || *current_snap) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("bulk define of snapshots only possible with " + "no existing snapshot")); + return -1; + } + + if (!(xml =3D virXMLParse(NULL, xmlStr, _("(domain_snapshot)")))) + goto cleanup; + + root =3D xmlDocGetRootElement(xml); + if (!virXMLNodeNameEqual(root, "snapshots")) { + virReportError(VIR_ERR_XML_ERROR, + _("unexpected root element <%s>, " + "expecting "), root->name); + goto cleanup; + } + ctxt =3D xmlXPathNewContext(xml); + if (ctxt =3D=3D NULL) { + virReportOOMError(); + goto cleanup; + } + ctxt->node =3D root; + current =3D virXMLPropString(root, "current"); + + if ((n =3D virXPathNodeSet("./domainsnapshot", ctxt, &nodes)) < 0) + goto cleanup; + if (!n) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("expected at least one child")); + goto cleanup; + } + + for (i =3D 0; i < n; i++) { + virDomainSnapshotDefPtr def; + virDomainSnapshotObjPtr snap; + int align_location =3D VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL; + bool align_match =3D true; + bool offline; + + def =3D virDomainSnapshotDefParseNode(xml, nodes[i], caps, xmlopt,= flags); + if (!def) + goto cleanup; + if (!(snap =3D virDomainSnapshotAssignDef(snapshots, def))) { + virDomainSnapshotDefFree(def); + goto cleanup; + } + /* Sanity checking, similar to virDomainSnapshotRedefinePrep */ + offline =3D def->state =3D=3D VIR_DOMAIN_DISK_SNAPSHOT || + virDomainSnapshotDefIsExternal(def); + if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) && !offline) { + virReportError(VIR_ERR_INVALID_ARG, + _("disk-only flag for snapshot %s requires " + "disk-snapshot state"), + def->name); + goto cleanup; + } + if (def->dom) { + if (memcmp(def->dom->uuid, domain_uuid, VIR_UUID_BUFLEN)) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + virUUIDFormat(domain_uuid, uuidstr); + virReportError(VIR_ERR_INVALID_ARG, + _("definition for snapshot %s must use uuid= %s"), + def->name, uuidstr); + goto cleanup; + } + if (offline || + def->memory =3D=3D VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) { + align_location =3D VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL; + align_match =3D false; + } + if (virDomainSnapshotAlignDisks(def, align_location, + align_match) < 0) + goto cleanup; + } + } + + if (virDomainSnapshotUpdateRelations(snapshots) < 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _(" contains inconsistent parent-child " + "relationships")); + goto cleanup; + } + + if (current) { + if (!(*current_snap =3D virDomainSnapshotFindByName(snapshots, + current))) { + virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, + _("no snapshot matching current=3D'%s'"), curre= nt); + goto cleanup; + } + (*current_snap)->def->current =3D true; + } + + ret =3D 0; + cleanup: + if (ret < 0) { + /* There were no snapshots before this call; so on error, just + * blindly delete anything created before the failure. */ + virHashRemoveAll(snapshots->objs); + snapshots->metaroot.nchildren =3D 0; + snapshots->metaroot.first_child =3D NULL; + } + VIR_FREE(current); + xmlXPathFreeContext(ctxt); + xmlFreeDoc(xml); + xmlKeepBlanksDefault(keepBlanksDefault); + return ret; +} + /** * virDomainSnapshotDefAssignExternalNames: * @def: snapshot def object diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c623737c30..96f54a97fe 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -881,6 +881,7 @@ virDomainSnapshotAssignDef; virDomainSnapshotDefFormat; virDomainSnapshotDefFree; virDomainSnapshotDefIsExternal; +virDomainSnapshotDefParseList; virDomainSnapshotDefParseString; virDomainSnapshotDropParent; virDomainSnapshotFindByName; --=20 2.20.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list