From nobody Wed Apr 24 09:27:17 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=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 1552358499113439.9562032839043; Mon, 11 Mar 2019 19:41:39 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D82BDC049D67; Tue, 12 Mar 2019 02:41:35 +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 384C860BF1; Tue, 12 Mar 2019 02:41:35 +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 F0B76181A136; Tue, 12 Mar 2019 02:41:33 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x2C2cgmH014234 for ; Mon, 11 Mar 2019 22:38:42 -0400 Received: by smtp.corp.redhat.com (Postfix) id A0235614E6; Tue, 12 Mar 2019 02:38:42 +0000 (UTC) Received: from blue.redhat.com (ovpn-118-35.phx2.redhat.com [10.3.118.35]) by smtp.corp.redhat.com (Postfix) with ESMTP id 19E07648AB; Tue, 12 Mar 2019 02:38:42 +0000 (UTC) From: Eric Blake To: libvir-list@redhat.com Date: Mon, 11 Mar 2019 21:38:32 -0500 Message-Id: <20190312023839.11069-2-eblake@redhat.com> In-Reply-To: <20190312023839.11069-1-eblake@redhat.com> References: <20190312023839.11069-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: nsoffer@redhat.com, jtomko@redhat.com Subject: [libvirt] [PATCH v4 1/8] snapshot: Add new API for bulk dumpxml/redefine 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.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Tue, 12 Mar 2019 02:41:37 +0000 (UTC) Content-Type: text/plain; charset="utf-8" Right now, copying the state of a transient domain with snapshots from one host to another requires multiple API calls on both machines - on the host: get the domain XML, get a list of the snapshots, and then for each snapshot get the snapshot's XML; then on the destination: create the domain, then multiple domain snapshot create calls (must be in topological order) with the REDEFINE flag. This patch aims to make the process use fewer APIs by making it possible to grab the XML for all snapshots at once on the source, then redefine from that same list at the destination. In fact, although it is easy to match recent changes to allow output in topological order, it is also easy to do bulk redefine in arbitrary order. Consideration was given to adding a flag to existing APIs; but to do that, there would be an asymmetry of dumping as a sub-element of during virDomainGetXMLDesc(), vs. redefining as a top-level element (and different than the normal top-level element) of virDomainSnapshotCreateXML(). Thus, it is cleaner to have two new APIs: virDomainGetSnapshotsXMLDesc virDomainImportSnapshotsXML Signed-off-by: Eric Blake Reviewed-by: J=C3=A1n Tomko --- include/libvirt/libvirt-domain-snapshot.h | 16 ++- src/driver-hypervisor.h | 13 ++- src/libvirt-domain-snapshot.c | 122 +++++++++++++++++++++- src/libvirt_public.syms | 2 + 4 files changed, 148 insertions(+), 5 deletions(-) diff --git a/include/libvirt/libvirt-domain-snapshot.h b/include/libvirt/li= bvirt-domain-snapshot.h index 602e5def59..7c2e001b87 100644 --- a/include/libvirt/libvirt-domain-snapshot.h +++ b/include/libvirt/libvirt-domain-snapshot.h @@ -3,7 +3,7 @@ * Summary: APIs for management of domain snapshots * Description: Provides APIs for the management of domain snapshots * - * Copyright (C) 2006-2014 Red Hat, Inc. + * Copyright (C) 2006-2019 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -78,6 +78,11 @@ virDomainSnapshotPtr virDomainSnapshotCreateXML(virDomai= nPtr domain, const char *xmlDesc, unsigned int flags); +/* Bulk import a list of snapshots */ +int virDomainImportSnapshotsXML(virDomainPtr domain, + const char *xmlDesc, + unsigned int flags); + typedef enum { VIR_DOMAIN_SNAPSHOT_XML_SECURE =3D VIR_DOMAIN_XML_SECURE, /* d= ump security sensitive information too */ } virDomainSnapshotXMLFlags; @@ -86,6 +91,15 @@ typedef enum { char *virDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, unsigned int flags); +typedef enum { + VIR_DOMAIN_GET_SNAPSHOTS_XML_SECURE =3D (1 << 0), /* dump secu= rity sensitive information too */ + VIR_DOMAIN_GET_SNAPSHOTS_XML_TOPOLOGICAL =3D (1 << 1), /* ensure pa= rents occur before children */ +} virDomainGetSnapshotsXMLFlags; + +/* Dump the XML of all snapshots */ +char *virDomainGetSnapshotsXMLDesc(virDomainPtr domain, + unsigned int flags); + /** * virDomainSnapshotListFlags: * diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index 5315e33dde..c30e16b690 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1,7 +1,7 @@ /* * driver-hypervisor.h: entry points for hypervisor drivers * - * Copyright (C) 2006-2015 Red Hat, Inc. + * Copyright (C) 2006-2019 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -797,10 +797,19 @@ typedef virDomainSnapshotPtr const char *xmlDesc, unsigned int flags); +typedef int +(*virDrvDomainImportSnapshotsXML)(virDomainPtr domain, + const char *xmlDesc, + unsigned int flags); + typedef char * (*virDrvDomainSnapshotGetXMLDesc)(virDomainSnapshotPtr snapshot, unsigned int flags); +typedef char * +(*virDrvDomainGetSnapshotsXMLDesc)(virDomainPtr domain, + unsigned int flags); + typedef int (*virDrvDomainSnapshotNum)(virDomainPtr domain, unsigned int flags); @@ -1494,7 +1503,9 @@ struct _virHypervisorDriver { virDrvDomainManagedSaveGetXMLDesc domainManagedSaveGetXMLDesc; virDrvDomainManagedSaveDefineXML domainManagedSaveDefineXML; virDrvDomainSnapshotCreateXML domainSnapshotCreateXML; + virDrvDomainImportSnapshotsXML domainImportSnapshotsXML; virDrvDomainSnapshotGetXMLDesc domainSnapshotGetXMLDesc; + virDrvDomainGetSnapshotsXMLDesc domainGetSnapshotsXMLDesc; virDrvDomainSnapshotNum domainSnapshotNum; virDrvDomainSnapshotListNames domainSnapshotListNames; virDrvDomainListAllSnapshots domainListAllSnapshots; diff --git a/src/libvirt-domain-snapshot.c b/src/libvirt-domain-snapshot.c index d133c84933..1ad8dfbfb8 100644 --- a/src/libvirt-domain-snapshot.c +++ b/src/libvirt-domain-snapshot.c @@ -133,7 +133,8 @@ virDomainSnapshotGetConnect(virDomainSnapshotPtr snapsh= ot) * not exist, the hypervisor may validate that reverting to the * snapshot appears to be possible (for example, disk images have * snapshot contents by the requested name). Not all hypervisors - * support these flags. + * support these flags; and some hypervisors support + * virDomainImportSnapshotsXML() for redefining all metadata in one call. * * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, then the * domain's disk images are modified according to @xmlDesc, but then @@ -242,6 +243,65 @@ virDomainSnapshotCreateXML(virDomainPtr domain, } +/** + * virDomainImportSnapshotsXML: + * @domain: a domain object + * @xmlDesc: string containing an XML description of a list of domain snap= shots + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * Imports the metadata for a list of domain snapshots using + * @xmlDesc with a top-level element of . + * + * This call requires that the domain currently has no snapshot + * metadata, and the snapshots can be listed in any order, whereas + * using virDomainSnapshotCreateXML() with its + * VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE flag requires multiple calls + * and topological sorting. Bulk redefinition is mainly useful for + * reinstating metadata in situations such as transient domains or + * migration. + * + * Generally, the list of snapshots is obtained from + * virDomainGetSnapshotsXMLDesc() prior to a scenario that requires + * removing snapshot metadata (such as virDomainUndefine() on a + * transient domain); although it could also be constructed by + * concatenating virDomainSnapshotGetXMLDesc() for each snapshot and + * wrapping with a element and optional attribute + * current=3D'name' pointing to the current snapshot. + * + * Returns a count of snapshots imported on success, or -1 on failure. + */ +int +virDomainImportSnapshotsXML(virDomainPtr domain, + const char *xmlDesc, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "xmlDesc=3D%s, flags=3D0x%x", xmlDesc, flags); + + virResetLastError(); + + virCheckDomainReturn(domain, -1); + conn =3D domain->conn; + + virCheckNonNullArgGoto(xmlDesc, error); + virCheckReadOnlyGoto(conn->flags, error); + + if (conn->driver->domainImportSnapshotsXML) { + int ret =3D conn->driver->domainImportSnapshotsXML(domain, xmlDesc, + flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + error: + virDispatchError(conn); + return -1; +} + + /** * virDomainSnapshotGetXMLDesc: * @snapshot: a domain snapshot object @@ -254,8 +314,8 @@ virDomainSnapshotCreateXML(virDomainPtr domain, * VIR_DOMAIN_SNAPSHOT_XML_SECURE; this flag is rejected on read-only * connections. * - * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of e= rror. - * the caller must free() the returned value. + * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case + * of error. The caller must free() the returned value. */ char * virDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, @@ -291,6 +351,62 @@ virDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snaps= hot, } +/** + * virDomainGetSnapshotsXMLDesc: + * @domain: a domain object + * @flags: bitwise-OR of virDomainGetSnapshotsXMLFlags + * + * Provide an XML description of all domain snapshots, with a top-level + * element of . + * + * No security-sensitive data will be included unless @flags contains + * VIR_DOMAIN_GET_SNAPSHOTS_XML_SECURE; this flag is rejected on read-only + * connections. + * + * If @flags contains VIR_DOMAIN_GET_SNAPSHOTS_XML_TOPOLOGICAL, then + * it is guaranteed that no snapshot appears in the resulting XML + * prior to its parent; otherwise, the order of snapshots in the + * resulting list is unspecified. Use of this flag is not required for + * virDomainImportSnapshotsXML() to transfer snapshot metadata to + * another instance of libvirt. + * + * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case + * of error. The caller must free() the returned value. + */ +char * +virDomainGetSnapshotsXMLDesc(virDomainPtr domain, + unsigned int flags) +{ + virConnectPtr conn; + VIR_DOMAIN_DEBUG(domain, "flags=3D0x%x", flags); + + virResetLastError(); + + virCheckDomainReturn(domain, NULL); + conn =3D domain->conn; + + if ((conn->flags & VIR_CONNECT_RO) && + (flags & VIR_DOMAIN_GET_SNAPSHOTS_XML_SECURE)) { + virReportError(VIR_ERR_OPERATION_DENIED, "%s", + _("virDomainGetSnapshotsXMLDesc with secure flag")); + goto error; + } + + if (conn->driver->domainGetSnapshotsXMLDesc) { + char *ret; + ret =3D conn->driver->domainGetSnapshotsXMLDesc(domain, flags); + if (!ret) + goto error; + return ret; + } + + virReportUnsupportedError(); + error: + virDispatchError(conn); + return NULL; +} + + /** * virDomainSnapshotNum: * @domain: a domain object diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index dbce3336d5..d40da8b893 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -817,6 +817,8 @@ LIBVIRT_4.10.0 { LIBVIRT_5.2.0 { global: virConnectGetStoragePoolCapabilities; + virDomainGetSnapshotsXMLDesc; + virDomainImportSnapshotsXML; } LIBVIRT_4.10.0; # .... define new API here using predicted next version number .... --=20 2.20.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Wed Apr 24 09:27:17 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=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 1552358629605415.0851184055807; Mon, 11 Mar 2019 19:43:49 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B50DE3082E4B; Tue, 12 Mar 2019 02:43:47 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8871F5C553; Tue, 12 Mar 2019 02:43:47 +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 3F9803FB11; Tue, 12 Mar 2019 02:43:47 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x2C2chsa014239 for ; Mon, 11 Mar 2019 22:38:43 -0400 Received: by smtp.corp.redhat.com (Postfix) id 571F1648AD; Tue, 12 Mar 2019 02:38:43 +0000 (UTC) Received: from blue.redhat.com (ovpn-118-35.phx2.redhat.com [10.3.118.35]) by smtp.corp.redhat.com (Postfix) with ESMTP id C215B648AB; Tue, 12 Mar 2019 02:38:42 +0000 (UTC) From: Eric Blake To: libvir-list@redhat.com Date: Mon, 11 Mar 2019 21:38:33 -0500 Message-Id: <20190312023839.11069-3-eblake@redhat.com> In-Reply-To: <20190312023839.11069-1-eblake@redhat.com> References: <20190312023839.11069-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: nsoffer@redhat.com, jtomko@redhat.com Subject: [libvirt] [PATCH v4 2/8] snapshot: Support topological virDomainSnapshotForEach() 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.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Tue, 12 Mar 2019 02:43:48 +0000 (UTC) Content-Type: text/plain; charset="utf-8" Previous patches added topological sorting only for existing public API functions, but it turns out that it will also useful for an upcoming API addition that wants to visit all snapshots. Add a parameter, and update all existing callers (none of which care about ordering). Signed-off-by: Eric Blake --- src/conf/snapshot_conf.h | 1 + src/conf/snapshot_conf.c | 6 +++++- src/qemu/qemu_domain.c | 2 +- src/vz/vz_driver.c | 3 ++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/conf/snapshot_conf.h b/src/conf/snapshot_conf.h index 6d79dbb0da..ba9362c744 100644 --- a/src/conf/snapshot_conf.h +++ b/src/conf/snapshot_conf.h @@ -170,6 +170,7 @@ virDomainSnapshotObjPtr virDomainSnapshotFindByName(vir= DomainSnapshotObjListPtr void virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots, virDomainSnapshotObjPtr snapshot); int virDomainSnapshotForEach(virDomainSnapshotObjListPtr snapshots, + bool topological, virHashIterator iter, void *data); int virDomainSnapshotForEachChild(virDomainSnapshotObjPtr snapshot, diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c index e2c91a5072..8235d7c526 100644 --- a/src/conf/snapshot_conf.c +++ b/src/conf/snapshot_conf.c @@ -1050,7 +1050,7 @@ virDomainSnapshotObjListFormat(virBufferPtr buf, current_snapshot->def->name); virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); - if (virDomainSnapshotForEach(snapshots, virDomainSnapshotFormatOne, + if (virDomainSnapshotForEach(snapshots, false, virDomainSnapshotFormat= One, &data) < 0) { virBufferFreeAndReset(buf); return -1; @@ -1293,9 +1293,13 @@ void virDomainSnapshotObjListRemove(virDomainSnapsho= tObjListPtr snapshots, int virDomainSnapshotForEach(virDomainSnapshotObjListPtr snapshots, + bool topological, virHashIterator iter, void *data) { + if (topological) + return virDomainSnapshotForEachDescendant(&snapshots->metaroot, + iter, data); return virHashForEach(snapshots->objs, iter, data); } diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 1659e88478..34f3669967 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8675,7 +8675,7 @@ qemuDomainSnapshotDiscardAllMetadata(virQEMUDriverPtr= driver, rem.vm =3D vm; rem.metadata_only =3D true; rem.err =3D 0; - virDomainSnapshotForEach(vm->snapshots, qemuDomainSnapshotDiscardAll, + virDomainSnapshotForEach(vm->snapshots, false, qemuDomainSnapshotDisca= rdAll, &rem); if (rem.current) vm->current_snapshot =3D NULL; diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c index 066d617524..2a0fc98f72 100644 --- a/src/vz/vz_driver.c +++ b/src/vz/vz_driver.c @@ -2170,7 +2170,8 @@ vzFindCurrentSnapshot(virDomainSnapshotObjListPtr sna= pshots) { virDomainSnapshotObjPtr current =3D NULL; - virDomainSnapshotForEach(snapshots, vzCurrentSnapshotIterator, ¤= t); + virDomainSnapshotForEach(snapshots, false, vzCurrentSnapshotIterator, + ¤t); return current; } --=20 2.20.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Wed Apr 24 09:27:17 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=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 1552358507080974.3304820188367; Mon, 11 Mar 2019 19:41:47 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4905B307D857; Tue, 12 Mar 2019 02:41:45 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 1D2C96012C; Tue, 12 Mar 2019 02:41:45 +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 D5EFA41F3E; Tue, 12 Mar 2019 02:41:44 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x2C2ciD0014247 for ; Mon, 11 Mar 2019 22:38:44 -0400 Received: by smtp.corp.redhat.com (Postfix) id 08110614CE; Tue, 12 Mar 2019 02:38:44 +0000 (UTC) Received: from blue.redhat.com (ovpn-118-35.phx2.redhat.com [10.3.118.35]) by smtp.corp.redhat.com (Postfix) with ESMTP id 78F77648AB; Tue, 12 Mar 2019 02:38:43 +0000 (UTC) From: Eric Blake To: libvir-list@redhat.com Date: Mon, 11 Mar 2019 21:38:34 -0500 Message-Id: <20190312023839.11069-4-eblake@redhat.com> In-Reply-To: <20190312023839.11069-1-eblake@redhat.com> References: <20190312023839.11069-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: nsoffer@redhat.com, jtomko@redhat.com Subject: [libvirt] [PATCH v4 3/8] snapshot: Tweaks to support new bulk dumpxml/import API 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.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Tue, 12 Mar 2019 02:41:45 +0000 (UTC) Content-Type: text/plain; charset="utf-8" Change the return value of virDomainSnapshotObjLisParse() to return the number of snapshots imported, and allow a return of 0 (the original proposal of adding a flag to virDomainSnapshotCreateXML required returning an arbitrary non-NULL snapshot, but with a new API that returns a count, we are no longer constrained to a non-empty list). Change virDomainSnapshotObjListFormat()'s flags argument to be the new public virDomainGetSnapshotsXMLFlags, since it is easy to support both flag values. Signed-off-by: Eric Blake Reviewed-by: J=C3=A1n Tomko --- src/conf/snapshot_conf.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c index 8235d7c526..3f24a80f76 100644 --- a/src/conf/snapshot_conf.c +++ b/src/conf/snapshot_conf.c @@ -507,8 +507,10 @@ virDomainSnapshotRedefineValidate(virDomainSnapshotDef= Ptr def, } -/* Parse a XML entry into snapshots, which must start empty. - * Any sub-elements of a must match domain_uuid. +/* Parse a XML entry into snapshots, which must start + * empty. Any sub-elements of a must match + * domain_uuid. @flags is virDomainSnapshotParseFlags. Return the + * number of snapshots parsed, or -1 on error. */ int virDomainSnapshotObjListParse(const char *xmlStr, @@ -562,11 +564,6 @@ virDomainSnapshotObjListParse(const char *xmlStr, 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; @@ -601,7 +598,7 @@ virDomainSnapshotObjListParse(const char *xmlStr, (*current_snap)->def->current =3D true; } - ret =3D 0; + ret =3D n; cleanup: if (ret < 0) { /* There were no snapshots before this call; so on error, just @@ -1025,8 +1022,9 @@ virDomainSnapshotFormatOne(void *payload, } -/* Format the XML for all snapshots in the list into buf. On error, - * clear the buffer and return -1. */ +/* Format the XML for all snapshots in the list into buf. @flags is + * virDomainGetSnapshotsXMLFlags. On error, clear the buffer and + * return -1. */ int virDomainSnapshotObjListFormat(virBufferPtr buf, const char *uuidstr, @@ -1041,17 +1039,23 @@ virDomainSnapshotObjListFormat(virBufferPtr buf, .uuidstr =3D uuidstr, .caps =3D caps, .xmlopt =3D xmlopt, - .flags =3D flags, + .flags =3D 0, }; + bool topological =3D flags & VIR_DOMAIN_GET_SNAPSHOTS_XML_TOPOLOGICAL; + virCheckFlags(VIR_DOMAIN_GET_SNAPSHOTS_XML_SECURE | + VIR_DOMAIN_GET_SNAPSHOTS_XML_TOPOLOGICAL, -1); + + if (flags & VIR_DOMAIN_GET_SNAPSHOTS_XML_SECURE) + data.flags |=3D VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE; virBufferAddLit(buf, "def->name); virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); - if (virDomainSnapshotForEach(snapshots, false, virDomainSnapshotFormat= One, - &data) < 0) { + if (virDomainSnapshotForEach(snapshots, topological, + virDomainSnapshotFormatOne, &data) < 0) { virBufferFreeAndReset(buf); return -1; } --=20 2.20.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Wed Apr 24 09:27:17 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=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 1552358511243808.9176340097977; Mon, 11 Mar 2019 19:41:51 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 57A1137E85; Tue, 12 Mar 2019 02:41:49 +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 29CF2579A3; Tue, 12 Mar 2019 02:41:49 +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 E3710181A138; Tue, 12 Mar 2019 02:41:48 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x2C2ci7B014257 for ; Mon, 11 Mar 2019 22:38:44 -0400 Received: by smtp.corp.redhat.com (Postfix) id AB013648AD; Tue, 12 Mar 2019 02:38:44 +0000 (UTC) Received: from blue.redhat.com (ovpn-118-35.phx2.redhat.com [10.3.118.35]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2A6DA648AB; Tue, 12 Mar 2019 02:38:44 +0000 (UTC) From: Eric Blake To: libvir-list@redhat.com Date: Mon, 11 Mar 2019 21:38:35 -0500 Message-Id: <20190312023839.11069-5-eblake@redhat.com> In-Reply-To: <20190312023839.11069-1-eblake@redhat.com> References: <20190312023839.11069-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: nsoffer@redhat.com, jtomko@redhat.com Subject: [libvirt] [PATCH v4 4/8] remote: Wire up snapshot bulk dumpxml/import 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.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Tue, 12 Mar 2019 02:41:49 +0000 (UTC) Content-Type: text/plain; charset="utf-8" Typical copy-and-paste addition. Fortunately, the generator handles this one without needing manual overrides. Signed-off-by: Eric Blake Reviewed-by: J=C3=A1n Tomko --- src/remote/remote_driver.c | 6 ++++-- src/remote/remote_protocol.x | 38 ++++++++++++++++++++++++++++++++++-- src/remote_protocol-structs | 17 ++++++++++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index eabe7a3823..51b2a6a448 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2,7 +2,7 @@ * remote_driver.c: driver to provide access to libvirtd running * on a remote machine * - * Copyright (C) 2007-2015 Red Hat, Inc. + * Copyright (C) 2007-2019 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -8516,7 +8516,9 @@ static virHypervisorDriver hypervisor_driver =3D { .connectCompareHypervisorCPU =3D remoteConnectCompareHypervisorCPU, /*= 4.4.0 */ .connectBaselineHypervisorCPU =3D remoteConnectBaselineHypervisorCPU, = /* 4.4.0 */ .nodeGetSEVInfo =3D remoteNodeGetSEVInfo, /* 4.5.0 */ - .domainGetLaunchSecurityInfo =3D remoteDomainGetLaunchSecurityInfo /* = 4.5.0 */ + .domainGetLaunchSecurityInfo =3D remoteDomainGetLaunchSecurityInfo, /*= 4.5.0 */ + .domainGetSnapshotsXMLDesc =3D remoteDomainGetSnapshotsXMLDesc, /* 5.2= .0 */ + .domainImportSnapshotsXML =3D remoteDomainImportSnapshotsXML, /* 5.2.0= */ }; static virNetworkDriver network_driver =3D { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 74be4b37d0..c585ec10ef 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3,7 +3,7 @@ * remote_internal driver and libvirtd. This protocol is * internal and may change at any time. * - * Copyright (C) 2006-2015 Red Hat, Inc. + * Copyright (C) 2006-2019 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -3573,6 +3573,26 @@ struct remote_connect_get_storage_pool_capabilities_= ret { remote_nonnull_string capabilities; }; +struct remote_domain_get_snapshots_xml_desc_args { + remote_nonnull_domain domain; + unsigned int flags; +}; + +struct remote_domain_get_snapshots_xml_desc_ret { + remote_nonnull_string xml; +}; + +struct remote_domain_import_snapshots_xml_args { + remote_nonnull_domain dom; + remote_nonnull_string xml; + unsigned int flags; +}; + +struct remote_domain_import_snapshots_xml_ret { + int result; +}; + + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here.= */ @@ -6342,5 +6362,19 @@ enum remote_procedure { * @generate: both * @acl: connect:read */ - REMOTE_PROC_CONNECT_GET_STORAGE_POOL_CAPABILITIES =3D 403 + REMOTE_PROC_CONNECT_GET_STORAGE_POOL_CAPABILITIES =3D 403, + + /** + * @generate: both + * @priority: high + * @acl: domain:read + * @acl: domain:read_secure:VIR_DOMAIN_GET_SNAPSHOTS_XML_SECURE + */ + REMOTE_PROC_DOMAIN_GET_SNAPSHOTS_XML_DESC =3D 404, + + /** + * @generate: both + * @acl: domain:snapshot + */ + REMOTE_PROC_DOMAIN_IMPORT_SNAPSHOTS_XML =3D 405 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 768189c573..b783d43a42 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2981,6 +2981,21 @@ struct remote_connect_get_storage_pool_capabilities_= args { struct remote_connect_get_storage_pool_capabilities_ret { remote_nonnull_string capabilities; }; +struct remote_domain_get_snapshots_xml_desc_args { + remote_nonnull_domain domain; + u_int flags; +}; +struct remote_domain_get_snapshots_xml_desc_ret { + remote_nonnull_string xml; +}; +struct remote_domain_import_snapshots_xml_args { + remote_nonnull_domain dom; + remote_nonnull_string xml; + u_int flags; +}; +struct remote_domain_import_snapshots_xml_ret { + int result; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN =3D 1, REMOTE_PROC_CONNECT_CLOSE =3D 2, @@ -3385,4 +3400,6 @@ enum remote_procedure { REMOTE_PROC_CONNECT_LIST_ALL_NWFILTER_BINDINGS =3D 401, REMOTE_PROC_DOMAIN_SET_IOTHREAD_PARAMS =3D 402, REMOTE_PROC_CONNECT_GET_STORAGE_POOL_CAPABILITIES =3D 403, + REMOTE_PROC_DOMAIN_GET_SNAPSHOTS_XML_DESC =3D 404, + REMOTE_PROC_DOMAIN_IMPORT_SNAPSHOTS_XML =3D 405, }; --=20 2.20.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Wed Apr 24 09:27:17 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=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 1552358633190343.25746688426216; Mon, 11 Mar 2019 19:43:53 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 22D8730821DF; Tue, 12 Mar 2019 02:43:51 +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 E7B8F6012C; Tue, 12 Mar 2019 02:43:50 +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 AF74A181A138; Tue, 12 Mar 2019 02:43:50 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x2C2cju3014265 for ; Mon, 11 Mar 2019 22:38:45 -0400 Received: by smtp.corp.redhat.com (Postfix) id 5A928648AD; Tue, 12 Mar 2019 02:38:45 +0000 (UTC) Received: from blue.redhat.com (ovpn-118-35.phx2.redhat.com [10.3.118.35]) by smtp.corp.redhat.com (Postfix) with ESMTP id CDFEA648AB; Tue, 12 Mar 2019 02:38:44 +0000 (UTC) From: Eric Blake To: libvir-list@redhat.com Date: Mon, 11 Mar 2019 21:38:36 -0500 Message-Id: <20190312023839.11069-6-eblake@redhat.com> In-Reply-To: <20190312023839.11069-1-eblake@redhat.com> References: <20190312023839.11069-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: nsoffer@redhat.com, jtomko@redhat.com Subject: [libvirt] [PATCH v4 5/8] virsh: Expose bulk snapshot dumpxml/import 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.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.47]); Tue, 12 Mar 2019 02:43:51 +0000 (UTC) Content-Type: text/plain; charset="utf-8" Add a new 'snapshot-import' command for bulk import. For bulk XML, it was easier to just add new flags to the existing 'snapshot-dumpxml' than to figure out a new command name. I debated about whether omitting the snapshotname should be enough to trigger the new API call, or whether to require a new bool --all; in the end, I went with the latter. Signed-off-by: Eric Blake Reviewed-by: J=C3=A1n Tomko --- tools/virsh-snapshot.c | 111 ++++++++++++++++++++++++++++++++++++----- tools/virsh.pod | 15 +++++- 2 files changed, 112 insertions(+), 14 deletions(-) diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c index 31153f5b10..2a2fc0108b 100644 --- a/tools/virsh-snapshot.c +++ b/tools/virsh-snapshot.c @@ -1,7 +1,7 @@ /* * virsh-snapshot.c: Commands to manage domain snapshot * - * Copyright (C) 2005, 2007-2016 Red Hat, Inc. + * Copyright (C) 2005-2019 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -444,6 +444,61 @@ cmdSnapshotCreateAs(vshControl *ctl, const vshCmd *cmd) return ret; } +/* + * "snapshot-import" command + */ +static const vshCmdInfo info_snapshot_import[] =3D { + {.name =3D "help", + .data =3D N_("Bulk import snapshots from XML") + }, + {.name =3D "desc", + .data =3D N_("Import the metadata for multiple snapshots from XML") + }, + {.name =3D NULL} +}; + +static const vshCmdOptDef opts_snapshot_import[] =3D { + VIRSH_COMMON_OPT_DOMAIN_FULL(0), + {.name =3D "xmlfile", + .type =3D VSH_OT_DATA, + .flags =3D VSH_OFLAG_REQ, + .help =3D N_("domain snapshots XML"), + }, + {.name =3D NULL} +}; + +static bool +cmdSnapshotImport(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom =3D NULL; + bool ret =3D false; + const char *from =3D NULL; + char *buffer =3D NULL; + int count; + + if (!(dom =3D virshCommandOptDomain(ctl, cmd, NULL))) + goto cleanup; + + if (vshCommandOptStringReq(ctl, cmd, "xmlfile", &from) < 0) + goto cleanup; + if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) { + vshSaveLibvirtError(); + goto cleanup; + } + + if ((count =3D virDomainImportSnapshotsXML(dom, buffer, 0)) < 0) + goto cleanup; + vshPrint(ctl, _("Imported %d snapshots"), count); + + ret =3D true; + + cleanup: + VIR_FREE(buffer); + virshDomainFree(dom); + + return ret; +} + /* Helper for resolving {--current | --ARG name} into a snapshot * belonging to DOM. If EXCLUSIVE, fail if both --current and arg are * present. On success, populate *SNAP and *NAME, before returning 0. @@ -1664,11 +1719,18 @@ static const vshCmdInfo info_snapshot_dumpxml[] =3D= { static const vshCmdOptDef opts_snapshot_dumpxml[] =3D { VIRSH_COMMON_OPT_DOMAIN_FULL(0), {.name =3D "snapshotname", - .type =3D VSH_OT_DATA, - .flags =3D VSH_OFLAG_REQ, + .type =3D VSH_OT_STRING, .help =3D N_("snapshot name"), .completer =3D virshSnapshotNameCompleter, }, + {.name =3D "all", + .type =3D VSH_OT_BOOL, + .help =3D N_("list all snapshots at once"), + }, + {.name =3D "topological", + .type =3D VSH_OT_BOOL, + .help =3D N_("with --all, ensure listing is topologically sorted"), + }, {.name =3D "security-info", .type =3D VSH_OT_BOOL, .help =3D N_("include security sensitive information in XML dump") @@ -1681,32 +1743,49 @@ cmdSnapshotDumpXML(vshControl *ctl, const vshCmd *c= md) { virDomainPtr dom =3D NULL; bool ret =3D false; - const char *name =3D NULL; + const char *snapshotname =3D NULL; virDomainSnapshotPtr snapshot =3D NULL; char *xml =3D NULL; unsigned int flags =3D 0; + bool all =3D vshCommandOptBool(cmd, "all"); + + if (vshCommandOptStringReq(ctl, cmd, "snapshotname", &snapshotname) < = 0) + return false; + + VSH_EXCLUSIVE_OPTIONS_VAR(snapshotname, all); + VSH_EXCLUSIVE_OPTIONS("snapshotname", "topological"); if (vshCommandOptBool(cmd, "security-info")) - flags |=3D VIR_DOMAIN_XML_SECURE; - - if (vshCommandOptStringReq(ctl, cmd, "snapshotname", &name) < 0) - return false; + flags |=3D all ? VIR_DOMAIN_GET_SNAPSHOTS_XML_SECURE : + VIR_DOMAIN_XML_SECURE; + if (vshCommandOptBool(cmd, "topological")) + flags |=3D VIR_DOMAIN_GET_SNAPSHOTS_XML_TOPOLOGICAL; if (!(dom =3D virshCommandOptDomain(ctl, cmd, NULL))) return false; - if (!(snapshot =3D virDomainSnapshotLookupByName(dom, name, 0))) - goto cleanup; + if (all) { + if (!(xml =3D virDomainGetSnapshotsXMLDesc(dom, flags))) + goto cleanup; + } else { + if (!snapshotname) { + vshError(ctl, "%s", _("either snapshotname or --all required")= ); + goto cleanup; + } + if (!(snapshot =3D virDomainSnapshotLookupByName(dom, snapshotname= , 0))) + goto cleanup; - if (!(xml =3D virDomainSnapshotGetXMLDesc(snapshot, flags))) - goto cleanup; + if (!(xml =3D virDomainSnapshotGetXMLDesc(snapshot, flags))) + goto cleanup; + } vshPrint(ctl, "%s", xml); ret =3D true; cleanup: VIR_FREE(xml); - virshDomainSnapshotFree(snapshot); + if (!all) + virshDomainSnapshotFree(snapshot); virshDomainFree(dom); return ret; @@ -1952,6 +2031,12 @@ const vshCmdDef snapshotCmds[] =3D { .info =3D info_snapshot_create_as, .flags =3D 0 }, + {.name =3D "snapshot-import", + .handler =3D cmdSnapshotImport, + .opts =3D opts_snapshot_import, + .info =3D info_snapshot_import, + .flags =3D 0, + }, {.name =3D "snapshot-current", .handler =3D cmdSnapshotCurrent, .opts =3D opts_snapshot_current, diff --git a/tools/virsh.pod b/tools/virsh.pod index 66e2bf24ec..28adcb85c3 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -4680,6 +4680,15 @@ If I<--live> is specified, libvirt takes the snapsho= t while the guest is running. This increases the size of the memory image of the external snapshot. This is currently supported only for external full system snapsh= ots. +=3Ditem B I I + +Import the metadata for all snapshots, for a domain with no existing +snapshot metadata. This is useful for migrating snapshots from one +host (with B) to another. + +This command is a shortcut to using B one +snapshot at a time. + =3Ditem B I {[I<--name>] | [I<--security-info>] | [I]} @@ -4786,9 +4795,13 @@ that use internal storage of existing disk images. = If I<--external> is specified, the list will be filtered to snapshots that use external files for disk images or memory state. -=3Ditem B I I [I<--security-info>] +=3Ditem B I {I | I<--all> [I<--topolog= ical>]} +[I<--security-info>] Output the snapshot XML for the domain's snapshot named I. +Alternatively, if I<--all> is passed instead of I output XML +describing all snapshots at once, where I<--topological> can also be +used to ensure no child is listed before a parent. Using I<--security-info> will also include security sensitive information. Use B to easily access the XML of the current snapshot. --=20 2.20.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Wed Apr 24 09:27:17 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=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 15523586367441022.7530748627825; Mon, 11 Mar 2019 19:43:56 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 37AC73092644; Tue, 12 Mar 2019 02:43:55 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 143F660C55; Tue, 12 Mar 2019 02:43:55 +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 C85DF3FB12; Tue, 12 Mar 2019 02:43:54 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x2C2cken014271 for ; Mon, 11 Mar 2019 22:38:46 -0400 Received: by smtp.corp.redhat.com (Postfix) id 0900960C4C; Tue, 12 Mar 2019 02:38:46 +0000 (UTC) Received: from blue.redhat.com (ovpn-118-35.phx2.redhat.com [10.3.118.35]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7C43F648AB; Tue, 12 Mar 2019 02:38:45 +0000 (UTC) From: Eric Blake To: libvir-list@redhat.com Date: Mon, 11 Mar 2019 21:38:37 -0500 Message-Id: <20190312023839.11069-7-eblake@redhat.com> In-Reply-To: <20190312023839.11069-1-eblake@redhat.com> References: <20190312023839.11069-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: nsoffer@redhat.com, jtomko@redhat.com Subject: [libvirt] [PATCH v4 6/8] test: Implement bulk snapshot operations 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.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Tue, 12 Mar 2019 02:43:55 +0000 (UTC) Content-Type: text/plain; charset="utf-8" Implement the new API calls for bulk snapshot dump and import. The bulk of the work is already done by the common code. Since each connection to test:///default restarts at the same canned state, this can easily be tested with: $ virsh -c test:///default " snapshot-create-as test s1 snapshot-create-as test s2 echo witness snapshot-dumpxml test --all" | sed '1,/witness/d' > list.xml $ virsh -c test:///default " snapshot-list test snapshot-import test list.xml snapshot-current --name test snapshot-list --parent test " Name Creation Time State Reviewed-by: J=C3=A1n Tomko ------------------------------- Imported 2 snapshots s2 Name Creation Time State Parent ------------------------------------------------------ s1 2019-02-20 22:26:52 -0600 running s2 2019-02-20 22:26:52 -0600 running s1 The test driver also makes it easy to test input validation, by modifying list.xml incorrectly (such as trying to attempt circular dependencies). Proving that that --topological makes a difference is a bit harder (since we randomize the hash seed, it is not 100% reproducible which order you get without it), but I found that creating snapshots s1, s3, s2 in that order tended to be more likely to hash in non-topological order without the flag. Signed-off-by: Eric Blake --- src/test/test_driver.c | 62 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 02cd4f4d07..085e228873 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -1,7 +1,7 @@ /* * test_driver.c: A "mock" hypervisor for use by application unit tests * - * Copyright (C) 2006-2015 Red Hat, Inc. + * Copyright (C) 2006-2019 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -6222,6 +6222,36 @@ testDomainSnapshotGetXMLDesc(virDomainSnapshotPtr sn= apshot, return xml; } +static char * +testDomainGetSnapshotsXMLDesc(virDomainPtr domain, + unsigned int flags) +{ + virDomainObjPtr vm =3D NULL; + char *xml =3D NULL; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + testDriverPtr privconn =3D domain->conn->privateData; + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + + virCheckFlags(VIR_DOMAIN_GET_SNAPSHOTS_XML_SECURE | + VIR_DOMAIN_GET_SNAPSHOTS_XML_TOPOLOGICAL, NULL); + + if (!(vm =3D testDomObjFromDomain(domain))) + return NULL; + + virUUIDFormat(domain->uuid, uuidstr); + + if (virDomainSnapshotObjListFormat(&buf, uuidstr, vm->snapshots, + vm->current_snapshot, privconn->cap= s, + privconn->xmlopt, flags) < 0) + goto cleanup; + + xml =3D virBufferContentAndReset(&buf); + + cleanup: + virDomainObjEndAPI(&vm); + return xml; +} + static int testDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, unsigned int flags) @@ -6409,6 +6439,34 @@ testDomainSnapshotCreateXML(virDomainPtr domain, } +static int +testDomainImportSnapshotsXML(virDomainPtr domain, + const char *xmlDesc, + unsigned int flags) +{ + testDriverPtr privconn =3D domain->conn->privateData; + virDomainObjPtr vm =3D NULL; + int ret =3D -1; + unsigned int parse_flags =3D VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE | + VIR_DOMAIN_SNAPSHOT_PARSE_DISKS; + + virCheckFlags(0, -1); + + if (!(vm =3D testDomObjFromDomain(domain))) + return -1; + + ret =3D virDomainSnapshotObjListParse(xmlDesc, + vm->def->uuid, + vm->snapshots, + &vm->current_snapshot, + privconn->caps, + privconn->xmlopt, + parse_flags); + virDomainObjEndAPI(&vm); + return ret; +} + + typedef struct _testSnapRemoveData testSnapRemoveData; typedef testSnapRemoveData *testSnapRemoveDataPtr; struct _testSnapRemoveData { @@ -6840,6 +6898,7 @@ static virHypervisorDriver testHypervisorDriver =3D { .domainSnapshotListNames =3D testDomainSnapshotListNames, /* 1.1.4 */ .domainListAllSnapshots =3D testDomainListAllSnapshots, /* 1.1.4 */ .domainSnapshotGetXMLDesc =3D testDomainSnapshotGetXMLDesc, /* 1.1.4 */ + .domainGetSnapshotsXMLDesc =3D testDomainGetSnapshotsXMLDesc, /* 5.2.0= */ .domainSnapshotNumChildren =3D testDomainSnapshotNumChildren, /* 1.1.4= */ .domainSnapshotListChildrenNames =3D testDomainSnapshotListChildrenNam= es, /* 1.1.4 */ .domainSnapshotListAllChildren =3D testDomainSnapshotListAllChildren, = /* 1.1.4 */ @@ -6850,6 +6909,7 @@ static virHypervisorDriver testHypervisorDriver =3D { .domainSnapshotIsCurrent =3D testDomainSnapshotIsCurrent, /* 1.1.4 */ .domainSnapshotHasMetadata =3D testDomainSnapshotHasMetadata, /* 1.1.4= */ .domainSnapshotCreateXML =3D testDomainSnapshotCreateXML, /* 1.1.4 */ + .domainImportSnapshotsXML =3D testDomainImportSnapshotsXML, /* 5.2.0 */ .domainRevertToSnapshot =3D testDomainRevertToSnapshot, /* 1.1.4 */ .domainSnapshotDelete =3D testDomainSnapshotDelete, /* 1.1.4 */ --=20 2.20.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Wed Apr 24 09:27:17 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=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 15523585150411018.3013841985414; Mon, 11 Mar 2019 19:41:55 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 372933092643; Tue, 12 Mar 2019 02:41:53 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0C5B65C6C1; Tue, 12 Mar 2019 02:41: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 BC8D041F3F; Tue, 12 Mar 2019 02:41:52 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x2C2eAmB014317 for ; Mon, 11 Mar 2019 22:40:10 -0400 Received: by smtp.corp.redhat.com (Postfix) id 0179F648AB; Tue, 12 Mar 2019 02:40:10 +0000 (UTC) Received: from blue.redhat.com (ovpn-118-35.phx2.redhat.com [10.3.118.35]) by smtp.corp.redhat.com (Postfix) with ESMTP id 46EE360A9A; Tue, 12 Mar 2019 02:40:07 +0000 (UTC) From: Eric Blake To: libvir-list@redhat.com Date: Mon, 11 Mar 2019 21:38:38 -0500 Message-Id: <20190312023839.11069-8-eblake@redhat.com> In-Reply-To: <20190312023839.11069-1-eblake@redhat.com> References: <20190312023839.11069-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: nsoffer@redhat.com, jtomko@redhat.com Subject: [libvirt] [PATCH v4 7/8] qemu: Factor out qemuDomainSnapshotValidate() helper 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.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Tue, 12 Mar 2019 02:41:53 +0000 (UTC) Content-Type: text/plain; charset="utf-8" Straight code motion, coupled with changing goto into return -1 as needed. This change will be important to later patches adding bulk redefinition (where each snapshot in a list has to meet the same constraints). Signed-off-by: Eric Blake Reviewed-by: John Ferlan Reviewed-by: J=C3=A1n Tomko --- src/qemu/qemu_driver.c | 120 ++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 54 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e461fb51b0..d679587819 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -15661,6 +15661,69 @@ qemuDomainSnapshotCreateActiveExternal(virQEMUDriv= erPtr driver, } +/* Validate that a snapshot object does not violate any qemu-specific + * constraints. */ +static int +qemuDomainSnapshotValidate(virDomainSnapshotDefPtr def, + virDomainSnapshotState state, + unsigned int flags) +{ + /* reject snapshot names containing slashes or starting with dot as + * snapshot definitions are saved in files named by the snapshot name = */ + if (!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) { + if (strchr(def->name, '/')) { + virReportError(VIR_ERR_XML_DETAIL, + _("invalid snapshot name '%s': " + "name can't contain '/'"), + def->name); + return -1; + } + + if (def->name[0] =3D=3D '.') { + virReportError(VIR_ERR_XML_DETAIL, + _("invalid snapshot name '%s': " + "name can't start with '.'"), + def->name); + return -1; + } + } + + /* allow snapshots only in certain states */ + switch (state) { + /* valid states */ + case VIR_DOMAIN_SNAPSHOT_RUNNING: + case VIR_DOMAIN_SNAPSHOT_PAUSED: + case VIR_DOMAIN_SNAPSHOT_SHUTDOWN: + case VIR_DOMAIN_SNAPSHOT_SHUTOFF: + case VIR_DOMAIN_SNAPSHOT_CRASHED: + break; + + case VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT: + if (!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid domain state= %s"), + virDomainSnapshotStateTypeToString(state)); + return -1; + } + break; + + case VIR_DOMAIN_SNAPSHOT_PMSUSPENDED: + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("qemu doesn't support taking snapshots of " + "PMSUSPENDED guests")); + return -1; + + /* invalid states */ + case VIR_DOMAIN_SNAPSHOT_NOSTATE: + case VIR_DOMAIN_SNAPSHOT_BLOCKED: /* invalid state, unused in qemu */ + case VIR_DOMAIN_SNAPSHOT_LAST: + virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid domain state %s"= ), + virDomainSnapshotStateTypeToString(state)); + return -1; + } + return 0; +} + + static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc, @@ -15681,7 +15744,6 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, virQEMUDriverConfigPtr cfg =3D NULL; virCapsPtr caps =3D NULL; qemuDomainObjPrivatePtr priv; - virDomainSnapshotState state; virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE | VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT | @@ -15736,25 +15798,9 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, parse_flags))) goto cleanup; - /* reject snapshot names containing slashes or starting with dot as - * snapshot definitions are saved in files named by the snapshot name = */ - if (!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) { - if (strchr(def->name, '/')) { - virReportError(VIR_ERR_XML_DETAIL, - _("invalid snapshot name '%s': " - "name can't contain '/'"), - def->name); - goto cleanup; - } - - if (def->name[0] =3D=3D '.') { - virReportError(VIR_ERR_XML_DETAIL, - _("invalid snapshot name '%s': " - "name can't start with '.'"), - def->name); - goto cleanup; - } - } + if (qemuDomainSnapshotValidate(def, redefine ? def->state : vm->state.= state, + flags) < 0) + goto cleanup; /* reject the VIR_DOMAIN_SNAPSHOT_CREATE_LIVE flag where not supported= */ if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE && @@ -15766,40 +15812,6 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, goto cleanup; } - /* allow snapshots only in certain states */ - state =3D redefine ? def->state : vm->state.state; - switch (state) { - /* valid states */ - case VIR_DOMAIN_SNAPSHOT_RUNNING: - case VIR_DOMAIN_SNAPSHOT_PAUSED: - case VIR_DOMAIN_SNAPSHOT_SHUTDOWN: - case VIR_DOMAIN_SNAPSHOT_SHUTOFF: - case VIR_DOMAIN_SNAPSHOT_CRASHED: - break; - - case VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT: - if (!redefine) { - virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid domain state= %s"), - virDomainSnapshotStateTypeToString(state)); - goto cleanup; - } - break; - - case VIR_DOMAIN_SNAPSHOT_PMSUSPENDED: - virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", - _("qemu doesn't support taking snapshots of " - "PMSUSPENDED guests")); - goto cleanup; - - /* invalid states */ - case VIR_DOMAIN_SNAPSHOT_NOSTATE: - case VIR_DOMAIN_SNAPSHOT_BLOCKED: /* invalid state, unused in qemu */ - case VIR_DOMAIN_SNAPSHOT_LAST: - virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid domain state %s"= ), - virDomainSnapshotStateTypeToString(state)); - goto cleanup; - } - /* We are going to modify the domain below. Internal snapshots would u= se * a regular job, so we need to set the job mask to disallow query as * 'savevm' blocks the monitor. External snapshot will then modify the --=20 2.20.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Wed Apr 24 09:27:17 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=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 1552358518152529.7274481904718; Mon, 11 Mar 2019 19:41: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 4DFB5308425A; Tue, 12 Mar 2019 02:41:56 +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 25E7D19739; Tue, 12 Mar 2019 02:41:56 +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 DFE41181A13C; Tue, 12 Mar 2019 02:41:55 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x2C2eAhj014322 for ; Mon, 11 Mar 2019 22:40:10 -0400 Received: by smtp.corp.redhat.com (Postfix) id A4A03614E6; Tue, 12 Mar 2019 02:40:10 +0000 (UTC) Received: from blue.redhat.com (ovpn-118-35.phx2.redhat.com [10.3.118.35]) by smtp.corp.redhat.com (Postfix) with ESMTP id 217F4648AB; Tue, 12 Mar 2019 02:40:10 +0000 (UTC) From: Eric Blake To: libvir-list@redhat.com Date: Mon, 11 Mar 2019 21:38:39 -0500 Message-Id: <20190312023839.11069-9-eblake@redhat.com> In-Reply-To: <20190312023839.11069-1-eblake@redhat.com> References: <20190312023839.11069-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: nsoffer@redhat.com, jtomko@redhat.com Subject: [libvirt] [PATCH v4 8/8] qemu: Implement bulk snapshot operations 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.40]); Tue, 12 Mar 2019 02:41:56 +0000 (UTC) Content-Type: text/plain; charset="utf-8" Implement the new API calls for bulk snapshot dump and import. This borrows from ideas in the test driver, but import is further complicated by the fact that qemu writes snapshot XML to disk, and thus must do additional validation after the initial parse to ensure the user didn't attempt to create a snapshot with "../" or similar. Signed-off-by: Eric Blake Reviewed-by: J=C3=A1n Tomko --- src/qemu/qemu_driver.c | 116 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d679587819..e1be3d0c5e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1,7 +1,7 @@ /* * qemu_driver.c: core driver methods for managing qemu guests * - * Copyright (C) 2006-2016 Red Hat, Inc. + * Copyright (C) 2006-2019 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -15974,6 +15974,84 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, } +/* Struct and hash-iterator callback used when bulk redefining snapshots */ +struct qemuDomainSnapshotBulk { + virDomainObjPtr vm; + virQEMUDriverPtr driver; + const char *snapshotDir; +}; + +static int +qemuDomainSnapshotBulkRedefine(void *payload, + const void *name ATTRIBUTE_UNUSED, + void *opaque) +{ + virDomainSnapshotObjPtr snap =3D payload; + struct qemuDomainSnapshotBulk *data =3D opaque; + + if (qemuDomainSnapshotValidate(snap->def, snap->def->state, + VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE) < 0) + return -1; + if (qemuDomainSnapshotWriteMetadata(data->vm, snap, data->driver->caps, + data->driver->xmlopt, + data->snapshotDir) < 0) + return -1; + return 0; +} + + +static int +qemuDomainImportSnapshotsXML(virDomainPtr domain, + const char *xmlDesc, + unsigned int flags) +{ + virQEMUDriverPtr driver =3D domain->conn->privateData; + virDomainObjPtr vm =3D NULL; + int ret =3D -1; + unsigned int parse_flags =3D VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE | + VIR_DOMAIN_SNAPSHOT_PARSE_DISKS; + struct qemuDomainSnapshotBulk bulk =3D { .driver =3D driver, }; + virQEMUDriverConfigPtr cfg =3D NULL; + + virCheckFlags(0, -1); + + if (!(vm =3D qemuDomObjFromDomain(domain))) + return -1; + + if (virDomainImportSnapshotsXMLEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + + cfg =3D virQEMUDriverGetConfig(driver); + + ret =3D virDomainSnapshotObjListParse(xmlDesc, vm->def->uuid, vm->snap= shots, + &vm->current_snapshot, driver->cap= s, + driver->xmlopt, parse_flags); + if (ret < 0) + goto cleanup; + + /* Validate and save the snapshots to disk. Since we don't get + * here unless there were no snapshots beforehand, just delete + * everything on the first failure, ignoring further errors. */ + bulk.vm =3D vm; + bulk.snapshotDir =3D cfg->snapshotDir; + if (virDomainSnapshotForEach(vm->snapshots, false, + qemuDomainSnapshotBulkRedefine, &bulk) < = 0) { + virErrorPtr orig_err =3D NULL; + + virErrorPreserveLast(&orig_err); + qemuDomainSnapshotDiscardAllMetadata(driver, vm); + virErrorRestore(&orig_err); + ret =3D 0; + goto cleanup; + } + + cleanup: + virDomainObjEndAPI(&vm); + virObjectUnref(cfg); + return ret; +} + + static int qemuDomainSnapshotListNames(virDomainPtr domain, char **names, @@ -16292,6 +16370,40 @@ qemuDomainSnapshotGetXMLDesc(virDomainSnapshotPtr = snapshot, } +static char * +qemuDomainGetSnapshotsXMLDesc(virDomainPtr domain, + unsigned int flags) +{ + virQEMUDriverPtr driver =3D domain->conn->privateData; + virDomainObjPtr vm =3D NULL; + char *xml =3D NULL; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + + virCheckFlags(VIR_DOMAIN_GET_SNAPSHOTS_XML_SECURE | + VIR_DOMAIN_GET_SNAPSHOTS_XML_TOPOLOGICAL, NULL); + + if (!(vm =3D qemuDomObjFromDomain(domain))) + return NULL; + + if (virDomainGetSnapshotsXMLDescEnsureACL(domain->conn, vm->def, flags= ) < 0) + goto cleanup; + + virUUIDFormat(domain->uuid, uuidstr); + + if (virDomainSnapshotObjListFormat(&buf, uuidstr, vm->snapshots, + vm->current_snapshot, driver->caps, + driver->xmlopt, flags) < 0) + goto cleanup; + + xml =3D virBufferContentAndReset(&buf); + + cleanup: + virDomainObjEndAPI(&vm); + return xml; +} + + static int qemuDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, unsigned int flags) @@ -22585,7 +22697,9 @@ static virHypervisorDriver qemuHypervisorDriver =3D= { .domainManagedSaveGetXMLDesc =3D qemuDomainManagedSaveGetXMLDesc, /* 3= .7.0 */ .domainManagedSaveDefineXML =3D qemuDomainManagedSaveDefineXML, /* 3.7= .0 */ .domainSnapshotCreateXML =3D qemuDomainSnapshotCreateXML, /* 0.8.0 */ + .domainImportSnapshotsXML =3D qemuDomainImportSnapshotsXML, /* 5.2.0 */ .domainSnapshotGetXMLDesc =3D qemuDomainSnapshotGetXMLDesc, /* 0.8.0 */ + .domainGetSnapshotsXMLDesc =3D qemuDomainGetSnapshotsXMLDesc, /* 5.2.0= */ .domainSnapshotNum =3D qemuDomainSnapshotNum, /* 0.8.0 */ .domainSnapshotListNames =3D qemuDomainSnapshotListNames, /* 0.8.0 */ .domainListAllSnapshots =3D qemuDomainListAllSnapshots, /* 0.9.13 */ --=20 2.20.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list