[libvirt] [PATCH v9 08/13] backup: Implement virsh support for checkpoints

Peter Krempa pkrempa at redhat.com
Mon Jul 8 13:26:28 UTC 2019


On Sat, Jul 06, 2019 at 22:56:08 -0500, Eric Blake wrote:
> Introduce a bunch of new virsh commands for managing checkpoints in
> isolation. More commands are needed for performing incremental
> backups, but these commands were easy to implement by modeling heavily
> after virsh-snapshot.c. There is no need for checkpoint-revert or
> checkpoint-current since those snapshot APIs have no checkpoint
> counterpart.  Similarly, it is not necessary to change which
> checkpoint is current when redefining from XML, since checkpoints
> expose whether they are current in the public XML (rather than the way
> snapshots did it behind the scenese).  checkpoint-list is a bit
> simpler, in part because we don't have to cater to back-compat to
> older API.  checkpoint-info is a bit trickier, because it requires
> parsing XML (maybe we'll want virDomainCheckpointIsCurrent() as an API
> after all).
> 
> Signed-off-by: Eric Blake <eblake at redhat.com>
> ---

[...]

> diff --git a/tools/virsh-checkpoint.c b/tools/virsh-checkpoint.c
> new file mode 100644
> index 0000000000..8200687f8a
> --- /dev/null
> +++ b/tools/virsh-checkpoint.c
> @@ -0,0 +1,1226 @@

[...]

> +static const vshCmdOptDef opts_checkpoint_create[] = {
> +    VIRSH_COMMON_OPT_DOMAIN_FULL(0),
> +    {.name = "xmlfile",
> +     .type = VSH_OT_STRING,
> +     .help = N_("domain checkpoint XML")
> +    },
> +    {.name = "redefine",
> +     .type = VSH_OT_BOOL,
> +     .help = N_("redefine metadata for existing checkpoint")
> +    },
> +    {.name = "no-metadata",
> +     .type = VSH_OT_BOOL,
> +     .help = N_("create checkpoint but create no metadata")
> +    },

This needs to be deleted. [1]

> +    {.name = "quiesce",
> +     .type = VSH_OT_BOOL,
> +     .help = N_("quiesce guest's file systems")
> +    },
> +    {.name = NULL}
> +};
> +
> +static bool
> +cmdCheckpointCreate(vshControl *ctl,
> +                    const vshCmd *cmd)
> +{
> +    virDomainPtr dom = NULL;
> +    bool ret = false;
> +    const char *from = NULL;
> +    char *buffer = NULL;
> +    unsigned int flags = 0;
> +
> +    if (vshCommandOptBool(cmd, "redefine"))
> +        flags |= VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE;
> +    if (vshCommandOptBool(cmd, "no-metadata"))
> +        flags |= VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA;

[1]

[...]

> +static const vshCmdOptDef opts_checkpoint_create_as[] = {
> +    VIRSH_COMMON_OPT_DOMAIN_FULL(0),
> +    {.name = "name",
> +     .type = VSH_OT_STRING,
> +     .help = N_("name of checkpoint")
> +    },
> +    {.name = "description",
> +     .type = VSH_OT_STRING,
> +     .help = N_("description of checkpoint")
> +    },
> +    {.name = "print-xml",
> +     .type = VSH_OT_BOOL,
> +     .help = N_("print XML document rather than create")
> +    },
> +    {.name = "no-metadata",
> +     .type = VSH_OT_BOOL,
> +     .help = N_("take checkpoint but create no metadata")

[1]

> +static bool
> +cmdCheckpointCreateAs(vshControl *ctl,
> +                      const vshCmd *cmd)
> +{
> +    virDomainPtr dom = NULL;
> +    bool ret = false;
> +    char *buffer = NULL;
> +    const char *name = NULL;
> +    const char *desc = NULL;
> +    virBuffer buf = VIR_BUFFER_INITIALIZER;
> +    unsigned int flags = 0;
> +    const vshCmdOpt *opt = NULL;
> +
> +    if (vshCommandOptBool(cmd, "no-metadata"))
> +        flags |= VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA;

[1]

[...]

> +/* Helper for resolving {--current | --ARG name} into a checkpoint
> + * belonging to DOM.  On success, populate *CHK and *NAME, before
> + * returning 0.  On failure, return -1 after issuing an error
> + * message.  */
> +static int
> +virshLookupCheckpoint(vshControl *ctl,
> +                      const vshCmd *cmd,
> +                      const char *arg,
> +                      virDomainPtr dom,
> +                      virDomainCheckpointPtr *chk,
> +                      const char **name)
> +{
> +    bool current = vshCommandOptBool(cmd, "current");
> +    const char *chkname = NULL;
> +
> +    if (vshCommandOptStringReq(ctl, cmd, arg, &chkname) < 0)
> +        return -1;
> +
> +    if (current && chkname) {
> +        vshError(ctl, _("--%s and --current are mutually exclusive"), arg);
> +        return -1;
> +    }
> +
> +    if (chkname) {
> +        *chk = virDomainCheckpointLookupByName(dom, chkname, 0);
> +    } else if (current) {
> +        int count;
> +        virDomainCheckpointPtr *checkpoints = NULL;
> +
> +        count = virDomainListAllCheckpoints(dom, &checkpoints,
> +                                            VIR_DOMAIN_CHECKPOINT_LIST_CURRENT);
> +        if (count < 0)
> +            return -1;
> +        if (count == 0) {
> +            vshError(ctl, _("domain has no current checkpoint"));
> +            return -1;
> +        }
> +        if (count > 1) {
> +            while (count-- > 0)
> +                virDomainCheckpointFree(checkpoints[count]);
> +            VIR_FREE(checkpoints);
> +            vshError(ctl, _("domain has more than one current checkpoint"));

Ummm, so what's the point of all this? I'd rather not include any of
this if it's not done properly. [2]


> +            return -1;
> +        }
> +        *chk = checkpoints[0];
> +        VIR_FREE(checkpoints);
> +    } else {
> +        vshError(ctl, _("--%s or --current is required"), arg);
> +        return -1;
> +    }
> +    if (!*chk) {
> +        vshReportError(ctl);
> +        return -1;
> +    }
> +
> +    *name = virDomainCheckpointGetName(*chk);
> +    return 0;
> +}

[...]

> diff --git a/tools/virsh.pod b/tools/virsh.pod
> index 4dffcafea0..8d69d349e9 100644
> --- a/tools/virsh.pod
> +++ b/tools/virsh.pod

[...]

> @@ -4655,6 +4669,10 @@ a persistent domain.  However, for transient domains, snapshot
>  metadata is silently lost when the domain quits running (whether
>  by command such as B<destroy> or by internal guest action).
> 
> +For now, it is not possible to create snapshots in a domain that has
> +checkpoints, although this restriction will be lifted in a future
> +release.

Next time please consider splitting out the tangentially related stuff
such as this or the changes to snapshot lists into separate commits to
improve review comfort.

> +
>  =item B<snapshot-create-as> I<domain> {[I<--print-xml>]
>  [I<--no-metadata>] [I<--halt>] [I<--reuse-external>]} [I<name>]
>  [I<description>] [I<--disk-only> [I<--quiesce>]] [I<--atomic>]

[...]

> @@ -4892,6 +4914,191 @@ the data contents from that point in time.
> 
>  =back
> 
> +=head1 CHECKPOINT COMMANDS
> +
> +The following commands manipulate domain checkpoints.  Checkpoints serve as
> +a point in time to identify which portions of a guest's disks have changed
> +after that time, making it possible to perform incremental and differential
> +backups.  Checkpoints are identified with a unique name.  See
> +L<https://libvirt.org/formatcheckpoint.html> for documentation of the XML
> +format used to represent properties of checkpoints.
> +
> +=over 4
> +
> +=item B<checkpoint-create> I<domain> [I<xmlfile>] { I<--redefine>
> +| [I<--no-metadata>] [I<--quiesce>]}
> +
> +Create a checkpoint for domain I<domain> with the properties specified
> +in I<xmlfile> describing a <domaincheckpoint> top-level element. The
> +format of the input XML file will be validated against an internal RNG
> +schema (idential to using the L<virt-xml-validate(1)> tool). If
> +I<xmlfile> is completely omitted, then libvirt will create a
> +checkpoint with a name based on the current time.
> +
> +If I<--redefine> is specified, then all XML elements produced by
> +B<checkpoint-dumpxml> are valid; this can be used to migrate
> +checkpoint hierarchy from one machine to another, to recreate
> +hierarchy for the case of a transient domain that goes away and is
> +later recreated with the same name and UUID, or to make slight
> +alterations in the checkpoint metadata (such as host-specific aspects
> +of the domain XML embedded in the checkpoint).  When this flag is
> +supplied, the I<xmlfile> argument is mandatory.
> +
> +If I<--no-metadata> is specified, then the checkpoint is only created
> +if the server does not require libvirt to track metadata for the
> +checkpoint (some hypervisors may always fail if this flag is
> +requested).

[1]

> +
> +If I<--quiesce> is specified, libvirt will try to use guest agent
> +to freeze and unfreeze domain's mounted file systems. However,
> +if domain has no guest agent, checkpoint creation will fail.
> +
> +Existence of checkpoint metadata will prevent attempts to B<undefine>
> +a persistent domain.  However, for transient domains, checkpoint
> +metadata is silently lost when the domain quits running (whether
> +by command such as B<destroy> or by internal guest action).
> +
> +For now, it is not possible to create checkpoints in a domain that has
> +snapshots, although this restriction will be lifted in a future
> +release.
> +
> +=item B<checkpoint-create-as> I<domain> {[I<--print-xml>]
> +| [I<--no-metadata>]} [I<name>] [I<description>] [I<--quiesce>]
> +[I<--diskspec>] B<diskspec>]...
> +
> +Create a checkpoint for domain I<domain> with the given <name> and
> +<description>; if either value is omitted, libvirt will choose a
> +value.  If I<--print-xml> is specified, then XML appropriate for
> +I<checkpoint-create> is output, rather than actually creating a
> +checkpoint.
> +
> +The I<--diskspec> option can be used to control which guest disks
> +participate in the checkpoint. This option can occur multiple times,
> +according to the number of <disk> elements in the domain xml.  Each
> +<diskspec> is in the form B<disk[,checkpoint=type][,bitmap=name]>. A
> +literal I<--diskspec> must precede each B<diskspec> unless
> +all three of I<domain>, I<name>, and I<description> are also present.
> +For example, a diskspec of "vda,checkpoint=bitmap,bitmap=map1"
> +results in the following XML:
> +  <disk name='vda' checkpoint='bitmap' bitmap='map1'/>
> +
> +If I<--quiesce> is specified, libvirt will try to use guest agent
> +to freeze and unfreeze domain's mounted file systems. However,
> +if domain has no guest agent, checkpoint creation will fail.
> +
> +If I<--no-metadata> is specified, then the checkpoint is only created
> +if the server does not require libvirt to track metadata for the
> +checkpoint (some hypervisors may always fail if this flag is
> +requested).

[1]

> +
> +For now, it is not possible to create checkpoints in a domain that has
> +snapshots, although this restriction will be lifted in a future
> +release.
> +
ACK if you get rid of [1], [2] and all uses of VIRSH_COMMON_OPT_CURRENT
in this patch.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20190708/e9c68787/attachment-0001.sig>


More information about the libvir-list mailing list