On Fri, Oct 12, 2018 at 00:10:08 -0500, Eric Blake wrote: > 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 full list of new API: > virDomainCheckpointCreateXML; > virDomainCheckpointCurrent; > virDomainCheckpointDelete; > virDomainCheckpointFree; > virDomainCheckpointGetConnect; > virDomainCheckpointGetDomain; > virDomainCheckpointGetParent; > virDomainCheckpointGetXMLDesc; > virDomainCheckpointHasMetadata; > virDomainCheckpointIsCurrent; > virDomainCheckpointListChildren; > virDomainCheckpointLookupByName; > virDomainCheckpointRef; > virDomainHasCurrentCheckpoint; > virDomainListCheckpoints; > virDomainCheckpointGetName; > > Signed-off-by: Eric Blake <[email protected]> > --- > include/libvirt/libvirt-domain-checkpoint.h | 156 +++++ > include/libvirt/libvirt.h | 5 +- > src/driver-hypervisor.h | 60 +- > 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 | 723 ++++++++++++++++++++ > src/libvirt_public.syms | 20 + > 12 files changed, 972 insertions(+), 4 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..cfca8f4b7f > --- /dev/null > +++ b/include/libvirt/libvirt-domain-checkpoint.h > @@ -0,0 +1,156 @@ > +/* > + * libvirt-domain-checkpoint.h > + * Summary: APIs for management of domain checkpoints > + * Description: Provides APIs for the management of domain checkpoints > + * Author: Eric Blake <[email protected]> > + * > + * Copyright (C) 2006-2018 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 __VIR_LIBVIRT_DOMAIN_CHECKPOINT_H__ > +# define __VIR_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 */
Is this worth adding? Will there be a way to start an incremental backup
without a previously existing libvirt checkpoint (thus having metadata)?
> + /* TODO: VIR_DOMAIN_CHECKPOINT_CREATE_QUIESCE */
> +} 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 virDomainListCheckpoints() and
> + * virDomainCheckpointListChildren(). 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_LEAVES = (1 << 1), /* Filter by
> checkpoints
> + with no children */
> + VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES = (1 << 2), /* Filter by
> checkpoints
> + that have children
> */
> +
> + VIR_DOMAIN_CHECKPOINT_LIST_METADATA = (1 << 3), /* Filter by
> checkpoints
> + which have
> metadata */
> + VIR_DOMAIN_CHECKPOINT_LIST_NO_METADATA = (1 << 4), /* Filter by
> checkpoints
> + with no metadata */
> +} virDomainCheckpointListFlags;
> +
> +/* Get all checkpoint objects for this domain */
> +int virDomainListCheckpoints(virDomainPtr domain,
> + virDomainCheckpointPtr **checkpoints,
> + unsigned int flags);
> +
> +/* Get all checkpoint object children for this checkpoint */
> +int virDomainCheckpointListChildren(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 /* __VIR_LIBVIRT_DOMAIN_CHECKPOINT_H__ */
> diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
> index 26887a40e7..4e7da0afc4 100644
> --- a/include/libvirt/libvirt.h
> +++ b/include/libvirt/libvirt.h
> @@ -4,7 +4,7 @@
> * Description: Provides the interfaces of the libvirt library to handle
> * virtualized domains
> *
> - * Copyright (C) 2005-2006, 2010-2014 Red Hat, Inc.
> + * Copyright (C) 2005-2006, 2010-2018 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
> @@ -36,8 +36,7 @@ extern "C" {
> # include <libvirt/libvirt-common.h>
> # include <libvirt/libvirt-host.h>
> # include <libvirt/libvirt-domain.h>
> -typedef struct _virDomainCheckpoint virDomainCheckpoint;
> -typedef virDomainCheckpoint *virDomainCheckpointPtr;
This should be part of the patch adding the data structure.
> +# 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/libvirt-domain-checkpoint.c b/src/libvirt-domain-checkpoint.c
> new file mode 100644
> index 0000000000..8a7b5b3c56
> --- /dev/null
> +++ b/src/libvirt-domain-checkpoint.c
> @@ -0,0 +1,723 @@
> +/*
> + * libvirt-domain-checkpoint.c: entry points for virDomainCheckpointPtr APIs
> + *
> + * Copyright (C) 2006-2014, 2018 Red Hat, Inc.
For a new file?
> + *
> + * 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)
This does not seem to be very useful. Users always can do a two step
lookup.
> +{
> + 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 on a running @domain.
> + * Typically, it is more common to create a new checkpoint as part of
> + * kicking off a backup job with virDomainBackupBegin(); 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
> + * discarded, rather than creating a new checkpoint. When redefining
> + * checkpoint metadata, the 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.
> + *
> + * If @flags includes VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA, then
> + * the domain's disk images are modified according to @xmlDesc, but
> + * then the just-created checkpoint has its metadata deleted. 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);
> +
> + 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.
As discussed in other places, I'm not convinced that storing a domain is
needed with backups.
> + *
> + * Normally, the XML description includes an element giving a full
> + * description of the domain at the time the snapshot was created; to
Missed reference to snapshots.
> + * 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;
> +}
> +
> +
> +/**
> + * virDomainListCheckpoints:
> + * @domain: a domain object
> + * @checkpoints: 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 virDomainCheckpoinListFlags
s/virDomainCheckpoinListFlags/virDomainCheckpointListFlags/
> + *
> + * Collect the list of domain checkpoints for the given domain, and allocate
> + * an array to store those objects.
> + *
> + * 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, where each group contains bits that describe mutually exclusive
> + * attributes of a checkpoint, and where all bits within a group describe
> + * all possible checkpoints. Some hypervisors might reject explicit bits
> + * from a group where the hypervisor cannot make a distinction. For a
> + * group supported by a given hypervisor, the behavior when no bits of a
> + * group are set is identical to the behavior when all bits in that group
> + * are set. When setting bits from more than one group, it is possible to
> + * select an impossible combination, in that case a 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
> +virDomainListCheckpoints(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->domainListCheckpoints) {
> + int ret = conn->driver->domainListCheckpoints(domain, checkpoints,
> + flags);
> + if (ret < 0)
> + goto error;
> + return ret;
> + }
> +
> + virReportUnsupportedError();
> + error:
> + virDispatchError(conn);
> + return -1;
> +}
[...]
> +/**
> + * 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().
Depending on whether 'current checkpoint' makes sense this might not be
needed.
> + *
> + * 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.
Given that we've never implemented metadata-less snapshots do we expect
this to happen with checkpoints?
> + * 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: not used yet, pass 0
> + * @flags: bitwise-OR of supported virDomainCheckpointDeleteFlags
@flags present twice
> + *
> + * 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.
So as a high-level question, since from the APIs added here is clear
that we expect tree-like topologies of checkpoints. Does merging of the
data _into_ the parent invalidate any other children?
This is a big problem we'll be facing when doing external snapshot
reversion.
> 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_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;
> +}
signature.asc
Description: PGP signature
-- libvir-list mailing list [email protected] https://www.redhat.com/mailman/listinfo/libvir-list
