On 11/07/12 07:48, Doug Goldstein wrote:
On Tue, Nov 6, 2012 at 10:00 PM, Eric Blake <eblake@xxxxxxxxxx> wrote:External checkpoints could be created with snapshot-create, but without libvirt supplying a default name for the memory file, it is essential to add a new argument to snapshot-create-as to allow the user to choose the memory file name. This adds the option --memspec [file=]name[,snapshot=type], where type can be none, internal, or external. For an example, virsh snapshot-create-as $dom --memspec /path/to/file is the shortest possible command line for creating an external checkpoint, named after the current timestamp. * tools/virsh-snapshot.c (vshParseSnapshotMemspec): New function. (cmdSnapshotCreateAs): Use it. * tests/virsh-optparse (test_url): Test it. * tools/virsh.pod (snapshot-create-as): Document it. --- tests/virsh-optparse | 5 +++-- tools/virsh-snapshot.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 17 ++++++++++++----- 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/tests/virsh-optparse b/tests/virsh-optparse index 4ddc31a..214ae41 100755 --- a/tests/virsh-optparse +++ b/tests/virsh-optparse @@ -1,7 +1,7 @@ #!/bin/sh # Ensure that virsh option parsing doesn't regress -# Copyright (C) 2011 Red Hat, Inc. +# Copyright (C) 2011-2012 Red Hat, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -73,6 +73,7 @@ done cat <<\EOF > exp-out || framework_failure <domainsnapshot> <description>1<2</description> + <memory file='d,e'/> <disks> <disk name='vda' snapshot='external'> <source file='a&b,c'/> @@ -84,7 +85,7 @@ cat <<\EOF > exp-out || framework_failure EOF virsh -q -c $test_url snapshot-create-as --print-xml test \ --diskspec 'vda,file=a&b,,c,snapshot=external' --description '1<2' \ - --diskspec vdb >out 2>>err || fail=1 + --diskspec vdb --memspec file=d,,e >out 2>>err || fail=1 compare exp-out out || fail=1 cat <<\EOF > exp-out || framework_failure diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c index 159f577..952dec5 100644 --- a/tools/virsh-snapshot.c +++ b/tools/virsh-snapshot.c @@ -194,6 +194,49 @@ cleanup: * "snapshot-create-as" command */ static int +vshParseSnapshotMemspec(vshControl *ctl, virBufferPtr buf, const char *str) +{ + int ret = -1; + const char *snapshot = NULL; + const char *file = NULL; + char **array = NULL; + int narray; + int i; + + if (!str) + return 0; + + narray = vshStringToArray(str, &array); + if (narray < 0) + goto cleanup; + + for (i = 0; i < narray; i++) { + if (!snapshot && STRPREFIX(array[i], "snapshot=")) + snapshot = array[i] + strlen("snapshot="); + else if (!file && STRPREFIX(array[i], "file=")) + file = array[i] + strlen("file="); + else if (!file && *array[i] == '/') + file = array[i]; + else + goto cleanup; + } + + virBufferAddLit(buf, " <memory"); + virBufferEscapeString(buf, " snapshot='%s'", snapshot);What's this do when a snapshot value wasn't supplied?
virBufferEscapeString has an automagic behavior where it skips adding anything to the buffer if either of the arguments is NULL. This is used to avoid conditions when creating XML docs.
+ virBufferEscapeString(buf, " file='%s'", file); + virBufferAddLit(buf, "/>\n"); + ret = 0; +cleanup: + if (ret < 0) + vshError(ctl, _("unable to parse memspec: %s"), str); + if (array) { + VIR_FREE(*array); + VIR_FREE(array); + } + return ret; +} + +static int vshParseSnapshotDiskspec(vshControl *ctl, virBufferPtr buf, const char *str) { int ret = -1; @@ -263,6 +306,8 @@ static const vshCmdOptDef opts_snapshot_create_as[] = { {"quiesce", VSH_OT_BOOL, 0, N_("quiesce guest's file systems")}, {"atomic", VSH_OT_BOOL, 0, N_("require atomic operation")}, {"live", VSH_OT_BOOL, 0, N_("take a live snapshot")}, + {"memspec", VSH_OT_DATA, VSH_OFLAG_REQ_OPT, + N_("memory attributes: [file=]name[,snapshot=type]")}, {"diskspec", VSH_OT_ARGV, 0, N_("disk attributes: disk[,snapshot=type][,driver=type][,file=name]")}, {NULL, 0, 0, NULL} @@ -276,6 +321,7 @@ cmdSnapshotCreateAs(vshControl *ctl, const vshCmd *cmd) char *buffer = NULL; const char *name = NULL; const char *desc = NULL; + const char *memspec = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; unsigned int flags = 0; const vshCmdOpt *opt = NULL; @@ -310,6 +356,12 @@ cmdSnapshotCreateAs(vshControl *ctl, const vshCmd *cmd) virBufferEscapeString(&buf, " <name>%s</name>\n", name); if (desc) virBufferEscapeString(&buf, " <description>%s</description>\n", desc); + + if (vshCommandOptString(cmd, "memspec", &memspec) < 0 || + vshParseSnapshotMemspec(ctl, &buf, memspec) < 0) { + virBufferFreeAndReset(&buf); + goto cleanup; + } if (vshCommandOptBool(cmd, "diskspec")) { virBufferAddLit(&buf, " <disks>\n"); while ((opt = vshCommandOptArgv(cmd, opt))) { diff --git a/tools/virsh.pod b/tools/virsh.pod index 4ec9f2e..3f9b3ea 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -2670,8 +2670,8 @@ by command such as B<destroy> or by internal guest action). =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>] -[I<--live>] [[I<--diskspec>] B<diskspec>]...] +[I<description>] [I<--disk-only> [I<--quiesce>]] [I<--atomic>] +[[I<--live>] [I<--memspec> B<memspec>]] [I<--diskspec>] B<diskspec>]... Create a snapshot for domain I<domain> with the given <name> and <description>; if either value is omitted, libvirt will choose a @@ -2681,9 +2681,16 @@ Otherwise, if I<--halt> is specified, the domain will be left in an inactive state after the snapshot is created, and if I<--disk-only> is specified, the snapshot will not include vm state. -The I<--disk-only> flag is used to request a disk-only snapshot. When -this flag is in use, the command can also take additional I<diskspec> -arguments to add <disk> elements to the xml. Each <diskspec> is in the +The I<--memspec> option can be used to control whether a checkpoint +is internal or external. The I<--memspec> flag is mandatory, followed +by a B<memspec> of the form B<[file=]name[,snapshot=type]>, where +type can be B<none>, B<internal>, or B<external>. To include a literal +comma in B<file=name>, escape it with a second comma. + +The I<--diskspec> option can be used to control how I<--disk-only> and +external checkpoints create external files. 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[,snapshot=type][,driver=type][,file=name]>. To include a literal comma in B<disk> or in B<file=name>, escape it with a second comma. A literal I<--diskspec> must precede each B<diskspec> unless -- 1.7.11.7Just one small question. I haven't compiled it or syntax checked it but visually it looks good.
ACK to the patch. Hm, it would be great to have the ability to have auto-generated file names for memory images for external checkpoints unfortunately there's the issue with the location as we don't have any template. I think we are good for now, but we might consider adding a default location of those.
Peter
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list