Introduce a bunch of new public APIs related to backup checkpoints.
Checkpoints are modeled heavily after virDomainSnapshotPtr (both
represent a point in time of the guest), although a snapshot exists
with the intent of rolling back to that state, while a checkpoint
exists to make it possible to create an incremental backup at a later
time.
The following map shows the API relations to snapshots, with new APIs
on the right:
Operate on a domain object to create/redefine a child:
virDomainSnapshotCreateXML virDomainCheckpointCreateXML
Operate on a child object for lifetime management:
virDomainSnapshotDelete virDomainCheckpointDelete
virDomainSnapshotFree virDomainCheckpointFree
virDomainSnapshotRef virDomainCheckpointRef
Operate on a child object to learn more about it:
virDomainSnapshotGetXMLDesc virDomainCheckpointGetXMLDesc
virDomainSnapshotGetConnect virDomainCheckpointGetConnect
virDomainSnapshotGetDomain virDomainCheckpointGetDomain
virDomainSnapshotGetName virDomainCheckpiontGetName
virDomainSnapshotGetParent virDomainCheckpiontGetParent
virDomainSnapshotHasMetadata virDomainCheckpointHasMetadata
virDomainSnapshotIsCurrent virDomainCheckpointIsCurrent
Operate on a domain object to list all children:
virDomainSnapshotNum (no counterpart, this is the old
virDomainSnapshotListNames racy interface)
virDomainSnapshotListAllSnapshots virDomainListAllCheckpoints
Operate on a child object to list descendents:
virDomainSnapshotNumChildren (no counterpart, this is the old
virDomainSnapshotListChildrenNames racy interface)
virDomainSnapshotListAllChildren virDomainCheckpointListAllChildren
Operate on a domain to locate a particular child:
virDomainSnapshotLookupByName virDomainCheckpointLookupByName
virDomainHasCurrentSnapshot virDomainHasCurrentCheckpoint
virDomainSnapshotCurrent virDomainCheckpointCurrent
Operate on a snapshot to roll back to earlier state:
virDomainSnapshotRevert (no counterpart, instead checkpoints
are used in incremental backups via
XML to virDomainBackupBegin)
Signed-off-by: Eric Blake <eblake(a)redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
include/libvirt/libvirt-domain-checkpoint.h | 161 +++++
include/libvirt/libvirt-domain.h | 6 +
include/libvirt/libvirt.h | 5 +-
src/conf/virdomainmomentobjlist.h | 5 +-
src/driver-hypervisor.h | 58 ++
docs/Makefile.am | 3 +
docs/apibuild.py | 2 +
docs/docs.html.in | 1 +
libvirt.spec.in | 1 +
mingw-libvirt.spec.in | 2 +
po/POTFILES | 1 +
src/Makefile.am | 2 +
src/libvirt-domain-checkpoint.c | 750 ++++++++++++++++++++
src/libvirt-domain.c | 18 +-
src/libvirt_public.syms | 20 +
15 files changed, 1026 insertions(+), 9 deletions(-)
create mode 100644 include/libvirt/libvirt-domain-checkpoint.h
create mode 100644 src/libvirt-domain-checkpoint.c
diff --git a/include/libvirt/libvirt-domain-checkpoint.h
b/include/libvirt/libvirt-domain-checkpoint.h
new file mode 100644
index 0000000000..9d37a4e29c
--- /dev/null
+++ b/include/libvirt/libvirt-domain-checkpoint.h
@@ -0,0 +1,161 @@
+/*
+ * libvirt-domain-checkpoint.h
+ * Summary: APIs for management of domain checkpoints
+ * Description: Provides APIs for the management of domain checkpoints
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LIBVIRT_DOMAIN_CHECKPOINT_H
+# define LIBVIRT_DOMAIN_CHECKPOINT_H
+
+# ifndef __VIR_LIBVIRT_H_INCLUDES__
+# error "Don't include this file directly, only use libvirt/libvirt.h"
+# endif
+
+/**
+ * virDomainCheckpoint:
+ *
+ * A virDomainCheckpoint is a private structure representing a checkpoint of
+ * a domain. A checkpoint is useful for tracking which portions of the
+ * domain disks have been altered since a point in time, but by itself does
+ * not allow reverting back to that point in time.
+ */
+typedef struct _virDomainCheckpoint virDomainCheckpoint;
+
+/**
+ * virDomainCheckpointPtr:
+ *
+ * A virDomainCheckpointPtr is pointer to a virDomainCheckpoint
+ * private structure, and is the type used to reference a domain
+ * checkpoint in the API.
+ */
+typedef virDomainCheckpoint *virDomainCheckpointPtr;
+
+const char *virDomainCheckpointGetName(virDomainCheckpointPtr checkpoint);
+virDomainPtr virDomainCheckpointGetDomain(virDomainCheckpointPtr checkpoint);
+virConnectPtr virDomainCheckpointGetConnect(virDomainCheckpointPtr checkpoint);
+
+typedef enum {
+ VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE = (1 << 0), /* Restore or alter
+ metadata */
+ VIR_DOMAIN_CHECKPOINT_CREATE_CURRENT = (1 << 1), /* With redefine, make
+ checkpoint current */
+ VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA = (1 << 2), /* Make checkpoint
without
+ remembering it */
+ VIR_DOMAIN_CHECKPOINT_CREATE_QUIESCE = (1 << 3), /* use guest agent to
+ quiesce all mounted
+ file systems within
+ the domain */
+} virDomainCheckpointCreateFlags;
+
+/* Create a checkpoint using the current VM state. */
+virDomainCheckpointPtr virDomainCheckpointCreateXML(virDomainPtr domain,
+ const char *xmlDesc,
+ unsigned int flags);
+
+typedef enum {
+ VIR_DOMAIN_CHECKPOINT_XML_SECURE = (1 << 0), /* Include sensitive data */
+ VIR_DOMAIN_CHECKPOINT_XML_NO_DOMAIN = (1 << 1), /* Suppress <domain>
+ subelement */
+ VIR_DOMAIN_CHECKPOINT_XML_SIZE = (1 << 2), /* Include dynamic
+ per-<disk> size */
+} virDomainCheckpointXMLFlags;
+
+/* Dump the XML of a checkpoint */
+char *virDomainCheckpointGetXMLDesc(virDomainCheckpointPtr checkpoint,
+ unsigned int flags);
+
+/**
+ * virDomainCheckpointListFlags:
+ *
+ * Flags valid for virDomainListAllCheckpoints() and
+ * virDomainCheckpointListAllChildren(). Note that the interpretation of
+ * flag (1<<0) depends on which function it is passed to; but serves
+ * to toggle the per-call default of whether the listing is shallow or
+ * recursive. Remaining bits come in groups; if all bits from a group
+ * are 0, then that group is not used to filter results. */
+typedef enum {
+ VIR_DOMAIN_CHECKPOINT_LIST_ROOTS = (1 << 0), /* Filter by checkpoints
+ with no parents, when
+ listing a domain */
+ VIR_DOMAIN_CHECKPOINT_LIST_DESCENDANTS = (1 << 0), /* List all descendants,
+ not just children, when
+ listing a checkpoint */
+ VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL = (1 << 1), /* Ensure parents occur
+ before children in
+ the resulting list */
+
+ VIR_DOMAIN_CHECKPOINT_LIST_LEAVES = (1 << 2), /* Filter by checkpoints
+ with no children */
+ VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES = (1 << 3), /* Filter by checkpoints
+ that have children */
+
+ VIR_DOMAIN_CHECKPOINT_LIST_METADATA = (1 << 4), /* Filter by checkpoints
+ which have metadata */
+ VIR_DOMAIN_CHECKPOINT_LIST_NO_METADATA = (1 << 5), /* Filter by checkpoints
+ with no metadata */
+} virDomainCheckpointListFlags;
+
+/* Get all checkpoint objects for this domain */
+int virDomainListAllCheckpoints(virDomainPtr domain,
+ virDomainCheckpointPtr **checkpoints,
+ unsigned int flags);
+
+/* Get all checkpoint object children for this checkpoint */
+int virDomainCheckpointListAllChildren(virDomainCheckpointPtr checkpoint,
+ virDomainCheckpointPtr **children,
+ unsigned int flags);
+
+/* Get a handle to a named checkpoint */
+virDomainCheckpointPtr virDomainCheckpointLookupByName(virDomainPtr domain,
+ const char *name,
+ unsigned int flags);
+
+/* Check whether a domain has a checkpoint which is currently used */
+int virDomainHasCurrentCheckpoint(virDomainPtr domain, unsigned int flags);
+
+/* Get a handle to the current checkpoint */
+virDomainCheckpointPtr virDomainCheckpointCurrent(virDomainPtr domain,
+ unsigned int flags);
+
+/* Get a handle to the parent checkpoint, if one exists */
+virDomainCheckpointPtr virDomainCheckpointGetParent(virDomainCheckpointPtr checkpoint,
+ unsigned int flags);
+
+/* Determine if a checkpoint is the current checkpoint of its domain. */
+int virDomainCheckpointIsCurrent(virDomainCheckpointPtr checkpoint,
+ unsigned int flags);
+
+/* Determine if checkpoint has metadata that would prevent domain deletion. */
+int virDomainCheckpointHasMetadata(virDomainCheckpointPtr checkpoint,
+ unsigned int flags);
+
+/* Delete a checkpoint */
+typedef enum {
+ VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN = (1 << 0), /* Also delete children
*/
+ VIR_DOMAIN_CHECKPOINT_DELETE_METADATA_ONLY = (1 << 1), /* Delete just metadata
*/
+ VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY = (1 << 2), /* Delete just children
*/
+} virDomainCheckpointDeleteFlags;
+
+int virDomainCheckpointDelete(virDomainCheckpointPtr checkpoint,
+ unsigned int flags);
+
+int virDomainCheckpointRef(virDomainCheckpointPtr checkpoint);
+int virDomainCheckpointFree(virDomainCheckpointPtr checkpoint);
+
+#endif /* LIBVIRT_DOMAIN_CHECKPOINT_H */
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 7d36820b5a..fe9ff011fe 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -1788,6 +1788,9 @@ typedef enum {
VIR_DOMAIN_UNDEFINE_NVRAM = (1 << 2), /* Also remove any
nvram file */
VIR_DOMAIN_UNDEFINE_KEEP_NVRAM = (1 << 3), /* Keep nvram file */
+ VIR_DOMAIN_UNDEFINE_CHECKPOINTS_METADATA = (1 << 4), /* If last use of domain,
+ then also remove any
+ checkpoint metadata */
/* Future undefine control flags should come here. */
} virDomainUndefineFlagsValues;
@@ -1826,6 +1829,9 @@ typedef enum {
VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT = 1 << 12,
VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT = 1 << 13,
+
+ VIR_CONNECT_LIST_DOMAINS_HAS_CHECKPOINT = 1 << 14,
+ VIR_CONNECT_LIST_DOMAINS_NO_CHECKPOINT = 1 << 15,
} virConnectListAllDomainsFlags;
int virConnectListAllDomains (virConnectPtr conn,
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
index 13de151cb6..f93e3bfa85 100644
--- a/include/libvirt/libvirt.h
+++ b/include/libvirt/libvirt.h
@@ -34,10 +34,7 @@ extern "C" {
# include <libvirt/libvirt-common.h>
# include <libvirt/libvirt-host.h>
# include <libvirt/libvirt-domain.h>
-/* FIXME: Temporary hack until later patch creates new
- * libvirt-domain-checkpoint.h file */
-typedef struct _virDomainCheckpoint virDomainCheckpoint;
-typedef virDomainCheckpoint *virDomainCheckpointPtr;
+# include <libvirt/libvirt-domain-checkpoint.h>
# include <libvirt/libvirt-domain-snapshot.h>
# include <libvirt/libvirt-event.h>
# include <libvirt/libvirt-interface.h>
diff --git a/src/conf/virdomainmomentobjlist.h b/src/conf/virdomainmomentobjlist.h
index 6481c771de..04808e1ac7 100644
--- a/src/conf/virdomainmomentobjlist.h
+++ b/src/conf/virdomainmomentobjlist.h
@@ -71,8 +71,9 @@ virDomainMomentObjPtr virDomainMomentAssignDef(virDomainMomentObjListPtr
moments
virDomainMomentDefPtr def);
/* Various enum bits that map to public API filters. Note that the
- * values of the internal bits are not necessarily the same as the
- * public ones. */
+ * values of the internal bits are not the same as the public ones for
+ * snapshot, however, this list should be kept in sync with the public
+ * ones for checkpoint. */
typedef enum {
VIR_DOMAIN_MOMENT_LIST_ROOTS = (1 << 0),
VIR_DOMAIN_MOMENT_LIST_DESCENDANTS = (1 << 0),
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index 5315e33dde..49b676dbbb 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1328,6 +1328,53 @@ typedef int
int *nparams,
unsigned int flags);
+typedef virDomainCheckpointPtr
+(*virDrvDomainCheckpointCreateXML)(virDomainPtr domain,
+ const char *xmlDesc,
+ unsigned int flags);
+
+typedef char *
+(*virDrvDomainCheckpointGetXMLDesc)(virDomainCheckpointPtr checkpoint,
+ unsigned int flags);
+
+typedef int
+(*virDrvDomainListAllCheckpoints)(virDomainPtr domain,
+ virDomainCheckpointPtr **checkpoints,
+ unsigned int flags);
+
+typedef int
+(*virDrvDomainCheckpointListAllChildren)(virDomainCheckpointPtr checkpoint,
+ virDomainCheckpointPtr **children,
+ unsigned int flags);
+
+typedef virDomainCheckpointPtr
+(*virDrvDomainCheckpointLookupByName)(virDomainPtr domain,
+ const char *name,
+ unsigned int flags);
+
+typedef int
+(*virDrvDomainHasCurrentCheckpoint)(virDomainPtr domain,
+ unsigned int flags);
+
+typedef virDomainCheckpointPtr
+(*virDrvDomainCheckpointGetParent)(virDomainCheckpointPtr checkpoint,
+ unsigned int flags);
+
+typedef virDomainCheckpointPtr
+(*virDrvDomainCheckpointCurrent)(virDomainPtr domain,
+ unsigned int flags);
+
+typedef int
+(*virDrvDomainCheckpointIsCurrent)(virDomainCheckpointPtr checkpoint,
+ unsigned int flags);
+
+typedef int
+(*virDrvDomainCheckpointHasMetadata)(virDomainCheckpointPtr checkpoint,
+ unsigned int flags);
+
+typedef int
+(*virDrvDomainCheckpointDelete)(virDomainCheckpointPtr checkpoint,
+ unsigned int flags);
typedef struct _virHypervisorDriver virHypervisorDriver;
typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1580,6 +1627,17 @@ struct _virHypervisorDriver {
virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU;
virDrvNodeGetSEVInfo nodeGetSEVInfo;
virDrvDomainGetLaunchSecurityInfo domainGetLaunchSecurityInfo;
+ virDrvDomainCheckpointCreateXML domainCheckpointCreateXML;
+ virDrvDomainCheckpointGetXMLDesc domainCheckpointGetXMLDesc;
+ virDrvDomainListAllCheckpoints domainListAllCheckpoints;
+ virDrvDomainCheckpointListAllChildren domainCheckpointListAllChildren;
+ virDrvDomainCheckpointLookupByName domainCheckpointLookupByName;
+ virDrvDomainHasCurrentCheckpoint domainHasCurrentCheckpoint;
+ virDrvDomainCheckpointGetParent domainCheckpointGetParent;
+ virDrvDomainCheckpointCurrent domainCheckpointCurrent;
+ virDrvDomainCheckpointIsCurrent domainCheckpointIsCurrent;
+ virDrvDomainCheckpointHasMetadata domainCheckpointHasMetadata;
+ virDrvDomainCheckpointDelete domainCheckpointDelete;
};
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 29b0761a2b..f608b7994a 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -25,6 +25,7 @@ apihtml = \
apihtml_generated = \
html/libvirt-libvirt-common.html \
html/libvirt-libvirt-domain.html \
+ html/libvirt-libvirt-domain-checkpoint.html \
html/libvirt-libvirt-domain-snapshot.html \
html/libvirt-libvirt-event.html \
html/libvirt-libvirt-host.html \
@@ -305,6 +306,7 @@ $(python_generated_files): $(APIBUILD_STAMP)
$(APIBUILD_STAMP): $(srcdir)/apibuild.py \
$(top_srcdir)/include/libvirt/libvirt.h \
$(top_srcdir)/include/libvirt/libvirt-common.h.in \
+ $(top_srcdir)/include/libvirt/libvirt-domain-checkpoint.h \
$(top_srcdir)/include/libvirt/libvirt-domain-snapshot.h \
$(top_srcdir)/include/libvirt/libvirt-domain.h \
$(top_srcdir)/include/libvirt/libvirt-event.h \
@@ -321,6 +323,7 @@ $(APIBUILD_STAMP): $(srcdir)/apibuild.py \
$(top_srcdir)/include/libvirt/libvirt-admin.h \
$(top_srcdir)/include/libvirt/virterror.h \
$(top_srcdir)/src/libvirt.c \
+ $(top_srcdir)/src/libvirt-domain-checkpoint.c \
$(top_srcdir)/src/libvirt-domain-snapshot.c \
$(top_srcdir)/src/libvirt-domain.c \
$(top_srcdir)/src/libvirt-host.c \
diff --git a/docs/apibuild.py b/docs/apibuild.py
index 9e04871220..dbdc1c95af 100755
--- a/docs/apibuild.py
+++ b/docs/apibuild.py
@@ -26,6 +26,7 @@ debugsym = None
included_files = {
"libvirt-common.h": "header with general libvirt API definitions",
"libvirt-domain.h": "header with general libvirt API definitions",
+ "libvirt-domain-checkpoint.h": "header with general libvirt API
definitions",
"libvirt-domain-snapshot.h": "header with general libvirt API
definitions",
"libvirt-event.h": "header with general libvirt API definitions",
"libvirt-host.h": "header with general libvirt API definitions",
@@ -39,6 +40,7 @@ included_files = {
"virterror.h": "header with error specific API definitions",
"libvirt.c": "Main interfaces for the libvirt library",
"libvirt-domain.c": "Domain interfaces for the libvirt library",
+ "libvirt-domain-checkpoint.c": "Domain checkpoint interfaces for the
libvirt library",
"libvirt-domain-snapshot.c": "Domain snapshot interfaces for the libvirt
library",
"libvirt-host.c": "Host interfaces for the libvirt library",
"libvirt-interface.c": "Interface interfaces for the libvirt
library",
diff --git a/docs/docs.html.in b/docs/docs.html.in
index b6b03313fa..400b149791 100644
--- a/docs/docs.html.in
+++ b/docs/docs.html.in
@@ -99,6 +99,7 @@
<dd>Reference manual for the C public API, split in
<a href="html/libvirt-libvirt-common.html">common</a>,
<a href="html/libvirt-libvirt-domain.html">domain</a>,
+ <a href="html/libvirt-libvirt-domain-checkpoint.html">domain
checkpoint</a>,
<a href="html/libvirt-libvirt-domain-snapshot.html">domain
snapshot</a>,
<a href="html/libvirt-virterror.html">error</a>,
<a href="html/libvirt-libvirt-event.html">event</a>,
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 76f6d13673..3513e080f3 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1862,6 +1862,7 @@ exit 0
%{_includedir}/libvirt/libvirt-admin.h
%{_includedir}/libvirt/libvirt-common.h
%{_includedir}/libvirt/libvirt-domain.h
+%{_includedir}/libvirt/libvirt-domain-checkpoint.h
%{_includedir}/libvirt/libvirt-domain-snapshot.h
%{_includedir}/libvirt/libvirt-event.h
%{_includedir}/libvirt/libvirt-host.h
diff --git a/mingw-libvirt.spec.in b/mingw-libvirt.spec.in
index 562fd1a1e9..d1889adade 100644
--- a/mingw-libvirt.spec.in
+++ b/mingw-libvirt.spec.in
@@ -265,6 +265,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt-guests.sh
%{mingw32_includedir}/libvirt/libvirt.h
%{mingw32_includedir}/libvirt/libvirt-common.h
%{mingw32_includedir}/libvirt/libvirt-domain.h
+%{mingw32_includedir}/libvirt/libvirt-domain-checkpoint.h
%{mingw32_includedir}/libvirt/libvirt-domain-snapshot.h
%{mingw32_includedir}/libvirt/libvirt-event.h
%{mingw32_includedir}/libvirt/libvirt-host.h
@@ -355,6 +356,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt-guests.sh
%{mingw64_includedir}/libvirt/libvirt.h
%{mingw64_includedir}/libvirt/libvirt-common.h
%{mingw64_includedir}/libvirt/libvirt-domain.h
+%{mingw64_includedir}/libvirt/libvirt-domain-checkpoint.h
%{mingw64_includedir}/libvirt/libvirt-domain-snapshot.h
%{mingw64_includedir}/libvirt/libvirt-event.h
%{mingw64_includedir}/libvirt/libvirt-host.h
diff --git a/po/POTFILES b/po/POTFILES
index 9dd4ee7d99..88af551664 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -69,6 +69,7 @@ src/interface/interface_backend_netcf.c
src/interface/interface_backend_udev.c
src/internal.h
src/libvirt-admin.c
+src/libvirt-domain-checkpoint.c
src/libvirt-domain-snapshot.c
src/libvirt-domain.c
src/libvirt-host.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 7d452a9490..38df84d0c1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -167,6 +167,7 @@ DRIVER_SOURCES += \
$(DATATYPES_SOURCES) \
libvirt.c libvirt_internal.h \
libvirt-domain.c \
+ libvirt-domain-checkpoint.c \
libvirt-domain-snapshot.c \
libvirt-host.c \
libvirt-interface.c \
@@ -719,6 +720,7 @@ libvirt_setuid_rpc_client_la_SOURCES = \
datatypes.c \
libvirt.c \
libvirt-domain.c \
+ libvirt-domain-checkpoint.c \
libvirt-domain-snapshot.c \
libvirt-host.c \
libvirt-interface.c \
diff --git a/src/libvirt-domain-checkpoint.c b/src/libvirt-domain-checkpoint.c
new file mode 100644
index 0000000000..8bab4011a3
--- /dev/null
+++ b/src/libvirt-domain-checkpoint.c
@@ -0,0 +1,750 @@
+/*
+ * libvirt-domain-checkpoint.c: entry points for virDomainCheckpointPtr APIs
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "datatypes.h"
+#include "virlog.h"
+
+VIR_LOG_INIT("libvirt.domain-checkpoint");
+
+#define VIR_FROM_THIS VIR_FROM_DOMAIN_CHECKPOINT
+
+/**
+ * virDomainCheckpointGetName:
+ * @checkpoint: a checkpoint object
+ *
+ * Get the public name for that checkpoint
+ *
+ * Returns a pointer to the name or NULL, the string need not be deallocated
+ * as its lifetime will be the same as the checkpoint object.
+ */
+const char *
+virDomainCheckpointGetName(virDomainCheckpointPtr checkpoint)
+{
+ VIR_DEBUG("checkpoint=%p", checkpoint);
+
+ virResetLastError();
+
+ virCheckDomainCheckpointReturn(checkpoint, NULL);
+
+ return checkpoint->name;
+}
+
+
+/**
+ * virDomainCheckpointGetDomain:
+ * @checkpoint: a checkpoint object
+ *
+ * Provides the domain pointer associated with a checkpoint. The
+ * reference counter on the domain is not increased by this
+ * call.
+ *
+ * Returns the domain or NULL.
+ */
+virDomainPtr
+virDomainCheckpointGetDomain(virDomainCheckpointPtr checkpoint)
+{
+ VIR_DEBUG("checkpoint=%p", checkpoint);
+
+ virResetLastError();
+
+ virCheckDomainCheckpointReturn(checkpoint, NULL);
+
+ return checkpoint->domain;
+}
+
+
+/**
+ * virDomainCheckpointGetConnect:
+ * @checkpoint: a checkpoint object
+ *
+ * Provides the connection pointer associated with a checkpoint. The
+ * reference counter on the connection is not increased by this
+ * call.
+ *
+ * Returns the connection or NULL.
+ */
+virConnectPtr
+virDomainCheckpointGetConnect(virDomainCheckpointPtr checkpoint)
+{
+ VIR_DEBUG("checkpoint=%p", checkpoint);
+
+ virResetLastError();
+
+ virCheckDomainCheckpointReturn(checkpoint, NULL);
+
+ return checkpoint->domain->conn;
+}
+
+
+/**
+ * virDomainCheckpointCreateXML:
+ * @domain: a domain object
+ * @xmlDesc: description of the checkpoint to create
+ * @flags: bitwise-OR of supported virDomainCheckpointCreateFlags
+ *
+ * Create a new checkpoint using @xmlDesc, with a top-level
+ * <domaincheckpoint> element, on a running @domain. Typically, it is
+ * more common to create a new checkpoint as part of kicking off a
+ * backup job with virDomainBackupBegin() or when creating a snapshot
+ * with virDomainSnapshotCreateXML2(); however, it is also possible to
+ * start a checkpoint without a backup.
+ *
+ * See <a href=formatcheckpoint.html#CheckpointAttributes">Checkpoint
XML</a>
+ * for more details on @xmlDesc. In particular, some hypervisors may require
+ * particular disk formats, such as qcow2, in order to support this
+ * command; where @xmlDesc can be used to limit the checkpoint to a working
+ * subset of the domain's disks.
+ *
+ * If @flags includes VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE, then this
+ * is a request to reinstate checkpoint metadata that was previously
+ * captured from virDomainCheckpointGetXMLDesc() before removing that
+ * metadata, rather than creating a new checkpoint. Note that while
+ * original creation can omit a number of elements from @xmlDesc (and
+ * libvirt will supply sane defaults based on the domain state at that
+ * point in time), a redefinition must supply more elements (as the
+ * domain may have changed in the meantime, so that libvirt no longer
+ * has a way to resupply correct defaults). When redefining
+ * checkpoint metadata, the domain's current checkpoint will not be
+ * altered unless the VIR_DOMAIN_CHECKPOINT_CREATE_CURRENT flag is
+ * also present. It is an error to request the
+ * VIR_DOMAIN_CHECKPOINT_CREATE_CURRENT flag without
+ * VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE. Not all hypervisors support
+ * these flags.
+ *
+ * If @flags includes VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA, then
+ * the domain's disk images are modified according to @xmlDesc, but
+ * libvirt does not track any metadata (similar to immediately calling
+ * virDomainCheckpointDelete() with
+ * VIR_DOMAIN_CHECKPOINT_DELETE_METADATA_ONLY). This flag is
+ * incompatible with VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE.
+ *
+ * If @flags includes VIR_DOMAIN_CHECKPOINT_CREATE_QUIESCE, then the
+ * libvirt will attempt to use guest agent to freeze and thaw all file
+ * systems in use within domain OS. However, if the guest agent is not
+ * present, an error is thrown. This flag is incompatible with
+ * VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE.
+ *
+ * Returns an (opaque) new virDomainCheckpointPtr on success or NULL
+ * on failure.
+ */
+virDomainCheckpointPtr
+virDomainCheckpointCreateXML(virDomainPtr domain,
+ const char *xmlDesc,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(domain, "xmlDesc=%s, flags=0x%x", xmlDesc, flags);
+
+ virResetLastError();
+
+ virCheckDomainReturn(domain, NULL);
+ conn = domain->conn;
+
+ virCheckNonNullArgGoto(xmlDesc, error);
+ virCheckReadOnlyGoto(conn->flags, error);
+
+ VIR_REQUIRE_FLAG_GOTO(VIR_DOMAIN_CHECKPOINT_CREATE_CURRENT,
+ VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE,
+ error);
+
+ VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE,
+ VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA,
+ error);
+ VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE,
+ VIR_DOMAIN_CHECKPOINT_CREATE_QUIESCE,
+ error);
+
+ if (conn->driver->domainCheckpointCreateXML) {
+ virDomainCheckpointPtr ret;
+ ret = conn->driver->domainCheckpointCreateXML(domain, xmlDesc, flags);
+ if (!ret)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return NULL;
+}
+
+
+/**
+ * virDomainCheckpointGetXMLDesc:
+ * @checkpoint: a domain checkpoint object
+ * @flags: bitwise-OR of supported virDomainCheckpointXMLFlags
+ *
+ * Provide an XML description of the domain checkpoint.
+ *
+ * No security-sensitive data will be included unless @flags contains
+ * VIR_DOMAIN_CHECKPOINT_XML_SECURE; this flag is rejected on read-only
+ * connections.
+ *
+ * Normally, the XML description includes an element giving a full
+ * description of the domain at the time the snapshot was created; to
+ * reduce parsing time, it will be suppressed when @flags contains
+ * VIR_DOMAIN_CHECKPOINT_XML_NO_DOMAIN.
+ *
+ * By default, the XML description contains only static information that
+ * does not change over time. However, when @flags contains
+ * VIR_DOMAIN_CHECKPOINT_XML_SIZE, each <disk> listing adds an additional
+ * attribute that shows an estimate of the current size in bytes that
+ * have been dirtied between the time the checkpoint was created and the
+ * current point in time.
+ *
+ * Returns a 0 terminated UTF-8 encoded XML instance or NULL in case
+ * of error. The caller must free() the returned value.
+ */
+char *
+virDomainCheckpointGetXMLDesc(virDomainCheckpointPtr checkpoint,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+ VIR_DEBUG("checkpoint=%p, flags=0x%x", checkpoint, flags);
+
+ virResetLastError();
+
+ virCheckDomainCheckpointReturn(checkpoint, NULL);
+ conn = checkpoint->domain->conn;
+
+ if ((conn->flags & VIR_CONNECT_RO) &&
+ (flags & VIR_DOMAIN_CHECKPOINT_XML_SECURE)) {
+ virReportError(VIR_ERR_OPERATION_DENIED, "%s",
+ _("virDomainCheckpointGetXMLDesc with secure flag"));
+ goto error;
+ }
+
+ if (conn->driver->domainCheckpointGetXMLDesc) {
+ char *ret;
+ ret = conn->driver->domainCheckpointGetXMLDesc(checkpoint, flags);
+ if (!ret)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return NULL;
+}
+
+
+/**
+ * virDomainListAllCheckpoints:
+ * @domain: a domain object
+ * @checkpoints: pointer to variable to store the array containing checkpoint
+ * object, or NULL if the list is not required (just returns
+ * number of checkpoints)
+ * @flags: bitwise-OR of supported virDomainCheckpoinListFlags
+ *
+ * Collect the list of domain checkpoints for the given domain and allocate
+ * an array to store those objects.
+ *
+ * If @flags contains VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL,
+ * @checkpoints is non-NULL, and no other connection is modifying
+ * checkpoints, then it is guaranteed that for any checkpoint in the
+ * resulting list, no checkpoints later in the list can be reached by
+ * a sequence of virDomainCheckpointGetParent() starting from that
+ * earlier checkpoint; otherwise, the order of checkpoints in the
+ * resulting list is unspecified.
+ *
+ * By default, this command covers all checkpoints. It is also
+ * possible to limit things to just checkpoints with no parents, when
+ * @flags includes VIR_DOMAIN_CHECKPOINT_LIST_ROOTS. Additional
+ * filters are provided in groups listed below. Within a group, bits
+ * are mutually exclusive, where all possible checkpoints are
+ * described by exactly one bit from the group. Some hypervisors might
+ * reject particular flags where it cannot make a distinction for
+ * filtering. If the set of filter flags selected forms an impossible
+ * combination, the hypervisor may return either 0 or an error.
+ *
+ * The first group of @flags is VIR_DOMAIN_CHECKPOINT_LIST_LEAVES and
+ * VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES, to filter based on checkpoints that
+ * have no further children (a leaf checkpoint).
+ *
+ * The next group of @flags is VIR_DOMAIN_CHECKPOINT_LIST_METADATA and
+ * VIR_DOMAIN_CHECKPOINT_LIST_NO_METADATA, for filtering checkpoints based on
+ * whether they have metadata that would prevent the removal of the last
+ * reference to a domain.
+ *
+ * Returns the number of domain checkpoints found or -1 and sets @checkpoints
+ * to NULL in case of error. On success, the array stored into @checkpoints
+ * is guaranteed to have an extra allocated element set to NULL but not
+ * included in the return count, to make iteration easier. The caller is
+ * responsible for calling virDomainCheckpointFree() on each array element,
+ * then calling free() on @checkpoints.
+ */
+int
+virDomainListAllCheckpoints(virDomainPtr domain,
+ virDomainCheckpointPtr **checkpoints,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(domain, "checkpoints=%p, flags=0x%x", checkpoints,
flags);
+
+ virResetLastError();
+
+ if (checkpoints)
+ *checkpoints = NULL;
+
+ virCheckDomainReturn(domain, -1);
+ conn = domain->conn;
+
+ if (conn->driver->domainListAllCheckpoints) {
+ int ret = conn->driver->domainListAllCheckpoints(domain, checkpoints,
+ flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return -1;
+}
+
+
+/**
+ * virDomainCheckpointListAllChildren:
+ * @checkpoint: a domain checkpoint object
+ * @children: pointer to variable to store the array containing checkpoint
+ * objects or NULL if the list is not required (just returns
+ * number of checkpoints)
+ * @flags: bitwise-OR of supported virDomainCheckpointListFlags
+ *
+ * Collect the list of domain checkpoints that are children of the given
+ * checkpoint, and allocate an array to store those objects.
+ *
+ * If @flags contains VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL,
+ * @checkpoints is non-NULL, and no other connection is modifying
+ * checkpoints, then it is guaranteed that for any checkpoint in the
+ * resulting list, no checkpoints later in the list can be reached by
+ * a sequence of virDomainCheckpointGetParent() starting from that
+ * earlier checkpoint; otherwise, the order of checkpoints in the
+ * resulting list is unspecified.
+ *
+ * By default, this command covers only direct children. It is also
+ * possible to expand things to cover all descendants, when @flags
+ * includes VIR_DOMAIN_CHECKPOINT_LIST_DESCENDANTS. Additional
+ * are provided via the remaining @flags values as documented in
+ * virDomainListAllCheckpoints(), with the exception that
+ * VIR_DOMAIN_CHECKPOINT_LIST_ROOTS is not supported (in fact,
+ * VIR_DOMAIN_CHECKPOINT_LIST_DESCENDANTS has the same bit value but
+ * opposite semantics of widening rather than narrowing the listing).
+ *
+ * Returns the number of domain checkpoints found or -1 and sets @children to
+ * NULL in case of error. On success, the array stored into @children is
+ * guaranteed to have an extra allocated element set to NULL but not included
+ * in the return count, to make iteration easier. The caller is responsible
+ * for calling virDomainCheckpointFree() on each array element, then calling
+ * free() on @children.
+ */
+int
+virDomainCheckpointListAllChildren(virDomainCheckpointPtr checkpoint,
+ virDomainCheckpointPtr **children,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DEBUG("checkpoint=%p, children=%p, flags=0x%x",
+ checkpoint, children, flags);
+
+ virResetLastError();
+
+ if (children)
+ *children = NULL;
+
+ virCheckDomainCheckpointReturn(checkpoint, -1);
+ conn = checkpoint->domain->conn;
+
+ if (conn->driver->domainCheckpointListAllChildren) {
+ int ret = conn->driver->domainCheckpointListAllChildren(checkpoint,
+ children,
+ flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return -1;
+}
+
+
+/**
+ * virDomainCheckpointLookupByName:
+ * @domain: a domain object
+ * @name: name for the domain checkpoint
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Try to lookup a domain checkpoint based on its name.
+ *
+ * Returns a domain checkpoint object or NULL in case of failure. If the
+ * domain checkpoint cannot be found, then the VIR_ERR_NO_DOMAIN_CHECKPOINT
+ * error is raised.
+ */
+virDomainCheckpointPtr
+virDomainCheckpointLookupByName(virDomainPtr domain,
+ const char *name,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(domain, "name=%s, flags=0x%x", name, flags);
+
+ virResetLastError();
+
+ virCheckDomainReturn(domain, NULL);
+ conn = domain->conn;
+
+ virCheckNonNullArgGoto(name, error);
+
+ if (conn->driver->domainCheckpointLookupByName) {
+ virDomainCheckpointPtr dom;
+ dom = conn->driver->domainCheckpointLookupByName(domain, name, flags);
+ if (!dom)
+ goto error;
+ return dom;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return NULL;
+}
+
+
+/**
+ * virDomainHasCurrentCheckpoint:
+ * @domain: pointer to the domain object
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Determine if the domain has a current checkpoint.
+ *
+ * Returns 1 if such checkpoint exists, 0 if it doesn't, -1 on error.
+ */
+int
+virDomainHasCurrentCheckpoint(virDomainPtr domain,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(domain, "flags=0x%x", flags);
+
+ virResetLastError();
+
+ virCheckDomainReturn(domain, -1);
+ conn = domain->conn;
+
+ if (conn->driver->domainHasCurrentCheckpoint) {
+ int ret = conn->driver->domainHasCurrentCheckpoint(domain, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return -1;
+}
+
+
+/**
+ * virDomainCheckpointCurrent:
+ * @domain: a domain object
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Get the current checkpoint for a domain, if any.
+ *
+ * virDomainCheckpointFree should be used to free the resources after the
+ * checkpoint object is no longer needed.
+ *
+ * Returns a domain checkpoint object or NULL in case of failure. If the
+ * current domain checkpoint cannot be found, then the
+ * VIR_ERR_NO_DOMAIN_CHECKPOINT error is raised.
+ */
+virDomainCheckpointPtr
+virDomainCheckpointCurrent(virDomainPtr domain,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(domain, "flags=0x%x", flags);
+
+ virResetLastError();
+
+ virCheckDomainReturn(domain, NULL);
+ conn = domain->conn;
+
+ if (conn->driver->domainCheckpointCurrent) {
+ virDomainCheckpointPtr snap;
+ snap = conn->driver->domainCheckpointCurrent(domain, flags);
+ if (!snap)
+ goto error;
+ return snap;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return NULL;
+}
+
+
+/**
+ * virDomainCheckpointGetParent:
+ * @checkpoint: a checkpoint object
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Get the parent checkpoint for @checkpoint, if any.
+ *
+ * virDomainCheckpointFree should be used to free the resources after the
+ * checkpoint object is no longer needed.
+ *
+ * Returns a domain checkpoint object or NULL in case of failure. If the
+ * given checkpoint is a root (no parent), then the VIR_ERR_NO_DOMAIN_CHECKPOINT
+ * error is raised.
+ */
+virDomainCheckpointPtr
+virDomainCheckpointGetParent(virDomainCheckpointPtr checkpoint,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DEBUG("checkpoint=%p, flags=0x%x", checkpoint, flags);
+
+ virResetLastError();
+
+ virCheckDomainCheckpointReturn(checkpoint, NULL);
+ conn = checkpoint->domain->conn;
+
+ if (conn->driver->domainCheckpointGetParent) {
+ virDomainCheckpointPtr snap;
+ snap = conn->driver->domainCheckpointGetParent(checkpoint, flags);
+ if (!snap)
+ goto error;
+ return snap;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return NULL;
+}
+
+
+/**
+ * virDomainCheckpointIsCurrent:
+ * @checkpoint: a checkpoint object
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Determine if the given checkpoint is the domain's current checkpoint. See
+ * also virDomainHasCurrentCheckpoint().
+ *
+ * Returns 1 if current, 0 if not current, or -1 on error.
+ */
+int
+virDomainCheckpointIsCurrent(virDomainCheckpointPtr checkpoint,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DEBUG("checkpoint=%p, flags=0x%x", checkpoint, flags);
+
+ virResetLastError();
+
+ virCheckDomainCheckpointReturn(checkpoint, -1);
+ conn = checkpoint->domain->conn;
+
+ if (conn->driver->domainCheckpointIsCurrent) {
+ int ret;
+ ret = conn->driver->domainCheckpointIsCurrent(checkpoint, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return -1;
+}
+
+
+/**
+ * virDomainCheckpointHasMetadata:
+ * @checkpoint: a checkpoint object
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Determine if the given checkpoint is associated with libvirt metadata
+ * that would prevent the deletion of the domain.
+ *
+ * Returns 1 if the checkpoint has metadata, 0 if the checkpoint exists without
+ * help from libvirt, or -1 on error.
+ */
+int
+virDomainCheckpointHasMetadata(virDomainCheckpointPtr checkpoint,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DEBUG("checkpoint=%p, flags=0x%x", checkpoint, flags);
+
+ virResetLastError();
+
+ virCheckDomainCheckpointReturn(checkpoint, -1);
+ conn = checkpoint->domain->conn;
+
+ if (conn->driver->domainCheckpointHasMetadata) {
+ int ret;
+ ret = conn->driver->domainCheckpointHasMetadata(checkpoint, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return -1;
+}
+
+
+/**
+ * virDomainCheckpointDelete:
+ * @checkpoint: the checkpoint to remove
+ * @flags: bitwise-OR of supported virDomainCheckpointDeleteFlags
+ *
+ * Removes a checkpoint from the domain.
+ *
+ * When removing a checkpoint, the record of which portions of the
+ * disk were dirtied after the checkpoint will be merged into the
+ * record tracked by the parent checkpoint, if any. Likewise, if the
+ * checkpoint being deleted was the current checkpoint, the parent
+ * checkpoint becomes the new current checkpoint.
+ *
+ * If @flags includes VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN, then any
+ * descendant checkpoints are also deleted. If @flags includes
+ * VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY, then any descendant
+ * checkepoints are deleted, but this checkpoint remains. These two
+ * flags are mutually exclusive.
+ *
+ * If @flags includes VIR_DOMAIN_CHECKPOINT_DELETE_METADATA_ONLY, then
+ * any checkpoint metadata tracked by libvirt is removed while keeping
+ * the checkpoint contents intact; if a hypervisor does not require
+ * any libvirt metadata to track checkpoints, then this flag is
+ * silently ignored.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+int
+virDomainCheckpointDelete(virDomainCheckpointPtr checkpoint,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DEBUG("checkpoint=%p, flags=0x%x", checkpoint, flags);
+
+ virResetLastError();
+
+ virCheckDomainCheckpointReturn(checkpoint, -1);
+ conn = checkpoint->domain->conn;
+
+ virCheckReadOnlyGoto(conn->flags, error);
+
+ VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN,
+ VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY,
+ error);
+
+ if (conn->driver->domainCheckpointDelete) {
+ int ret = conn->driver->domainCheckpointDelete(checkpoint, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return -1;
+}
+
+
+/**
+ * virDomainCheckpointRef:
+ * @checkpoint: the checkpoint to hold a reference on
+ *
+ * Increment the reference count on the checkpoint. For each
+ * additional call to this method, there shall be a corresponding
+ * call to virDomainCheckpointFree to release the reference count, once
+ * the caller no longer needs the reference to this object.
+ *
+ * This method is typically useful for applications where multiple
+ * threads are using a connection, and it is required that the
+ * connection and domain remain open until all threads have finished
+ * using the checkpoint. ie, each new thread using a checkpoint would
+ * increment the reference count.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virDomainCheckpointRef(virDomainCheckpointPtr checkpoint)
+{
+ VIR_DEBUG("checkpoint=%p, refs=%d", checkpoint,
+ checkpoint ? checkpoint->parent.u.s.refs : 0);
+
+ virResetLastError();
+
+ virCheckDomainCheckpointReturn(checkpoint, -1);
+
+ virObjectRef(checkpoint);
+ return 0;
+}
+
+
+/**
+ * virDomainCheckpointFree:
+ * @checkpoint: a domain checkpoint object
+ *
+ * Free the domain checkpoint object. The checkpoint itself is not modified.
+ * The data structure is freed and should not be used thereafter.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virDomainCheckpointFree(virDomainCheckpointPtr checkpoint)
+{
+ VIR_DEBUG("checkpoint=%p", checkpoint);
+
+ virResetLastError();
+
+ virCheckDomainCheckpointReturn(checkpoint, -1);
+
+ virObjectUnref(checkpoint);
+ return 0;
+}
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index baf21824fe..44438c3be8 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -6227,8 +6227,9 @@ virDomainDefineXMLFlags(virConnectPtr conn, const char *xml,
unsigned int flags)
*
* If the domain has a managed save image (see
* virDomainHasManagedSaveImage()), or if it is inactive and has any
- * snapshot metadata (see virDomainSnapshotNum()), then the undefine will
- * fail. See virDomainUndefineFlags() for more control.
+ * snapshot metadata (see virDomainSnapshotNum()) or checkpoint
+ * metadata (see virDomainListAllCheckpoints()), then the undefine
+ * will fail. See virDomainUndefineFlags() for more control.
*
* Returns 0 in case of success, -1 in case of error
*/
@@ -6284,6 +6285,15 @@ virDomainUndefine(virDomainPtr domain)
* whether this flag is present. On hypervisors where snapshots do
* not use libvirt metadata, this flag has no effect.
*
+ * If the domain is inactive and has any checkpoint metadata (see
+ * virDomainListAllCheckpoints()), then including
+ * VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA in @flags will also remove
+ * that metadata. Omitting the flag will cause the undefine of an
+ * inactive domain to fail. Active checkpoints will retain checkpoint
+ * metadata until the (now-transient) domain halts, regardless of
+ * whether this flag is present. On hypervisors where checkpoints do
+ * not use libvirt metadata, this flag has no effect.
+ *
* If the domain has any nvram specified, the undefine process will fail
* unless VIR_DOMAIN_UNDEFINE_KEEP_NVRAM is specified, or if
* VIR_DOMAIN_UNDEFINE_NVRAM is specified to remove the nvram file.
@@ -6444,7 +6454,9 @@ virConnectListDefinedDomains(virConnectPtr conn, char **const
names,
* VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART, for filtering based on autostart;
* VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT and
* VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT, for filtering based on whether
- * a domain has snapshots.
+ * a domain has snapshots; VIR_CONNECT_LIST_DOMAINS_HAS_CHECKPOINT and
+ * VIR_CONNECT_LIST_DOMAINS_NO_CHECKPOINT, for filtering based on whether
+ * a domain has checkpoints.
*
* Example of usage:
*
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index dbce3336d5..a54804682e 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -819,4 +819,24 @@ LIBVIRT_5.2.0 {
virConnectGetStoragePoolCapabilities;
} LIBVIRT_4.10.0;
+LIBVIRT_5.3.0 {
+ global:
+ virDomainCheckpointCreateXML;
+ virDomainCheckpointCurrent;
+ virDomainCheckpointDelete;
+ virDomainCheckpointFree;
+ virDomainCheckpointGetConnect;
+ virDomainCheckpointGetDomain;
+ virDomainCheckpointGetName;
+ virDomainCheckpointGetParent;
+ virDomainCheckpointGetXMLDesc;
+ virDomainCheckpointHasMetadata;
+ virDomainCheckpointIsCurrent;
+ virDomainCheckpointListAllChildren;
+ virDomainCheckpointLookupByName;
+ virDomainCheckpointRef;
+ virDomainHasCurrentCheckpoint;
+ virDomainListAllCheckpoints;
+} LIBVIRT_5.2.0;
+
# .... define new API here using predicted next version number ....
--
2.20.1