On Mon, Mar 11, 2019 at 09:38:32PM -0500, Eric Blake wrote:
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 <snapshots> as a
sub-element of <domain> during virDomainGetXMLDesc(), vs. redefining
<snapshots> 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
These do not share a common prefix, but that makes them look nicer IMO.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
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/libvirt-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.
Do we actually care about updating these?
But an include file will possibly be read by people without git access.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
[...]
@@ -242,6 +243,65 @@ virDomainSnapshotCreateXML(virDomainPtr domain,
}
+/**
+ * virDomainImportSnapshotsXML:
+ * @domain: a domain object
+ * @xmlDesc: string containing an XML description of a list of domain snapshots
+ * @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 <snapshots>.
+ *
+ * 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 <snapshots> element and optional attribute
+ * current='name' pointing to the current snapshot.
+ *
+ * Returns a count of snapshots imported on success, or -1 on failure.
This says nothing about partial success, i.e. whether the count returned
can be different from the number of snapshots present in the file.
+ */
+int
+virDomainImportSnapshotsXML(virDomainPtr domain,
+ const char *xmlDesc,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(domain, "xmlDesc=%s, flags=0x%x", xmlDesc, flags);
+
+ virResetLastError();
+
+ virCheckDomainReturn(domain, -1);
+ conn = domain->conn;
+
+ virCheckNonNullArgGoto(xmlDesc, error);
+ virCheckReadOnlyGoto(conn->flags, error);
+
+ if (conn->driver->domainImportSnapshotsXML) {
+ int ret = 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 error.
- * 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.
Unrelated change.
*/
char *
virDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
Reviewed-by: Ján Tomko <jtomko(a)redhat.com>
Jano