snapshot subcommand for qemu-img (Kevin Wolf)
Add snapshot subcommand to qemu-img which allows to list, create, apply and delete snapshots on qcow2 images. Signed-off-by: Kevin Wolf <kwolf@suse.de> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6215 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
fa879c6414
commit
f7b4a940a4
4
osdep.h
4
osdep.h
@ -7,6 +7,10 @@
|
|||||||
#include <sys/signal.h>
|
#include <sys/signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef glue
|
#ifndef glue
|
||||||
#define xglue(x, y) x ## y
|
#define xglue(x, y) x ## y
|
||||||
#define glue(x, y) xglue(x, y)
|
#define glue(x, y) xglue(x, y)
|
||||||
|
121
qemu-img.c
121
qemu-img.c
@ -22,6 +22,7 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
|
#include "osdep.h"
|
||||||
#include "block_int.h"
|
#include "block_int.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@ -60,6 +61,7 @@ static void help(void)
|
|||||||
" commit [-f fmt] filename\n"
|
" commit [-f fmt] filename\n"
|
||||||
" convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n"
|
" convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n"
|
||||||
" info [-f fmt] filename\n"
|
" info [-f fmt] filename\n"
|
||||||
|
" snapshot [-l|-a snapshot|-c snapshot|-d snapshot] filename\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Command parameters:\n"
|
"Command parameters:\n"
|
||||||
" 'filename' is a disk image filename\n"
|
" 'filename' is a disk image filename\n"
|
||||||
@ -77,6 +79,13 @@ static void help(void)
|
|||||||
" '-c' indicates that target image must be compressed (qcow format only)\n"
|
" '-c' indicates that target image must be compressed (qcow format only)\n"
|
||||||
" '-e' indicates that the target image must be encrypted (qcow format only)\n"
|
" '-e' indicates that the target image must be encrypted (qcow format only)\n"
|
||||||
" '-6' indicates that the target image must use compatibility level 6 (vmdk format only)\n"
|
" '-6' indicates that the target image must use compatibility level 6 (vmdk format only)\n"
|
||||||
|
"\n"
|
||||||
|
" Parameters to snapshot subcommand:\n"
|
||||||
|
" 'snapshot' is the name of the snapshot to create, apply or delete\n"
|
||||||
|
" '-a' applies a snapshot (revert disk to saved state)\n"
|
||||||
|
" '-c' creates a snapshot\n"
|
||||||
|
" '-d' deletes a snapshot\n"
|
||||||
|
" '-l' lists all snapshots in the given image\n"
|
||||||
);
|
);
|
||||||
printf("\nSupported format:");
|
printf("\nSupported format:");
|
||||||
bdrv_iterate_format(format_print, NULL);
|
bdrv_iterate_format(format_print, NULL);
|
||||||
@ -732,6 +741,116 @@ static int img_info(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SNAPSHOT_LIST 1
|
||||||
|
#define SNAPSHOT_CREATE 2
|
||||||
|
#define SNAPSHOT_APPLY 3
|
||||||
|
#define SNAPSHOT_DELETE 4
|
||||||
|
|
||||||
|
static void img_snapshot(int argc, char **argv)
|
||||||
|
{
|
||||||
|
BlockDriverState *bs;
|
||||||
|
QEMUSnapshotInfo sn;
|
||||||
|
char *filename, *snapshot_name = NULL;
|
||||||
|
char c;
|
||||||
|
int ret;
|
||||||
|
int action = 0;
|
||||||
|
qemu_timeval tv;
|
||||||
|
|
||||||
|
/* Parse commandline parameters */
|
||||||
|
for(;;) {
|
||||||
|
c = getopt(argc, argv, "la:c:d:h");
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
switch(c) {
|
||||||
|
case 'h':
|
||||||
|
help();
|
||||||
|
return;
|
||||||
|
case 'l':
|
||||||
|
if (action) {
|
||||||
|
help();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
action = SNAPSHOT_LIST;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
if (action) {
|
||||||
|
help();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
action = SNAPSHOT_APPLY;
|
||||||
|
snapshot_name = optarg;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
if (action) {
|
||||||
|
help();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
action = SNAPSHOT_CREATE;
|
||||||
|
snapshot_name = optarg;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
if (action) {
|
||||||
|
help();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
action = SNAPSHOT_DELETE;
|
||||||
|
snapshot_name = optarg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc)
|
||||||
|
help();
|
||||||
|
filename = argv[optind++];
|
||||||
|
|
||||||
|
/* Open the image */
|
||||||
|
bs = bdrv_new("");
|
||||||
|
if (!bs)
|
||||||
|
error("Not enough memory");
|
||||||
|
|
||||||
|
if (bdrv_open2(bs, filename, 0, NULL) < 0) {
|
||||||
|
error("Could not open '%s'", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform the requested action */
|
||||||
|
switch(action) {
|
||||||
|
case SNAPSHOT_LIST:
|
||||||
|
dump_snapshots(bs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SNAPSHOT_CREATE:
|
||||||
|
memset(&sn, 0, sizeof(sn));
|
||||||
|
pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
|
||||||
|
|
||||||
|
qemu_gettimeofday(&tv);
|
||||||
|
sn.date_sec = tv.tv_sec;
|
||||||
|
sn.date_nsec = tv.tv_usec * 1000;
|
||||||
|
|
||||||
|
ret = bdrv_snapshot_create(bs, &sn);
|
||||||
|
if (ret)
|
||||||
|
error("Could not create snapshot '%s': %d (%s)",
|
||||||
|
snapshot_name, ret, strerror(-ret));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SNAPSHOT_APPLY:
|
||||||
|
ret = bdrv_snapshot_goto(bs, snapshot_name);
|
||||||
|
if (ret)
|
||||||
|
error("Could not apply snapshot '%s': %d (%s)",
|
||||||
|
snapshot_name, ret, strerror(-ret));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SNAPSHOT_DELETE:
|
||||||
|
ret = bdrv_snapshot_delete(bs, snapshot_name);
|
||||||
|
if (ret)
|
||||||
|
error("Could not delete snapshot '%s': %d (%s)",
|
||||||
|
snapshot_name, ret, strerror(-ret));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
bdrv_delete(bs);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *cmd;
|
const char *cmd;
|
||||||
@ -749,6 +868,8 @@ int main(int argc, char **argv)
|
|||||||
img_convert(argc, argv);
|
img_convert(argc, argv);
|
||||||
} else if (!strcmp(cmd, "info")) {
|
} else if (!strcmp(cmd, "info")) {
|
||||||
img_info(argc, argv);
|
img_info(argc, argv);
|
||||||
|
} else if (!strcmp(cmd, "snapshot")) {
|
||||||
|
img_snapshot(argc, argv);
|
||||||
} else {
|
} else {
|
||||||
help();
|
help();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user