Commit f7b4a940a430da0e2d48b74e85a8a941c1c2fabc
1 parent
fa879c64
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
Showing
2 changed files
with
125 additions
and
0 deletions
osdep.h
| @@ -7,6 +7,10 @@ | @@ -7,6 +7,10 @@ | ||
| 7 | #include <sys/signal.h> | 7 | #include <sys/signal.h> |
| 8 | #endif | 8 | #endif |
| 9 | 9 | ||
| 10 | +#ifndef _WIN32 | ||
| 11 | +#include <sys/time.h> | ||
| 12 | +#endif | ||
| 13 | + | ||
| 10 | #ifndef glue | 14 | #ifndef glue |
| 11 | #define xglue(x, y) x ## y | 15 | #define xglue(x, y) x ## y |
| 12 | #define glue(x, y) xglue(x, y) | 16 | #define glue(x, y) xglue(x, y) |
qemu-img.c
| @@ -22,6 +22,7 @@ | @@ -22,6 +22,7 @@ | ||
| 22 | * THE SOFTWARE. | 22 | * THE SOFTWARE. |
| 23 | */ | 23 | */ |
| 24 | #include "qemu-common.h" | 24 | #include "qemu-common.h" |
| 25 | +#include "osdep.h" | ||
| 25 | #include "block_int.h" | 26 | #include "block_int.h" |
| 26 | #include <assert.h> | 27 | #include <assert.h> |
| 27 | 28 | ||
| @@ -60,6 +61,7 @@ static void help(void) | @@ -60,6 +61,7 @@ static void help(void) | ||
| 60 | " commit [-f fmt] filename\n" | 61 | " commit [-f fmt] filename\n" |
| 61 | " convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n" | 62 | " convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n" |
| 62 | " info [-f fmt] filename\n" | 63 | " info [-f fmt] filename\n" |
| 64 | + " snapshot [-l|-a snapshot|-c snapshot|-d snapshot] filename\n" | ||
| 63 | "\n" | 65 | "\n" |
| 64 | "Command parameters:\n" | 66 | "Command parameters:\n" |
| 65 | " 'filename' is a disk image filename\n" | 67 | " 'filename' is a disk image filename\n" |
| @@ -77,6 +79,13 @@ static void help(void) | @@ -77,6 +79,13 @@ static void help(void) | ||
| 77 | " '-c' indicates that target image must be compressed (qcow format only)\n" | 79 | " '-c' indicates that target image must be compressed (qcow format only)\n" |
| 78 | " '-e' indicates that the target image must be encrypted (qcow format only)\n" | 80 | " '-e' indicates that the target image must be encrypted (qcow format only)\n" |
| 79 | " '-6' indicates that the target image must use compatibility level 6 (vmdk format only)\n" | 81 | " '-6' indicates that the target image must use compatibility level 6 (vmdk format only)\n" |
| 82 | + "\n" | ||
| 83 | + " Parameters to snapshot subcommand:\n" | ||
| 84 | + " 'snapshot' is the name of the snapshot to create, apply or delete\n" | ||
| 85 | + " '-a' applies a snapshot (revert disk to saved state)\n" | ||
| 86 | + " '-c' creates a snapshot\n" | ||
| 87 | + " '-d' deletes a snapshot\n" | ||
| 88 | + " '-l' lists all snapshots in the given image\n" | ||
| 80 | ); | 89 | ); |
| 81 | printf("\nSupported format:"); | 90 | printf("\nSupported format:"); |
| 82 | bdrv_iterate_format(format_print, NULL); | 91 | bdrv_iterate_format(format_print, NULL); |
| @@ -732,6 +741,116 @@ static int img_info(int argc, char **argv) | @@ -732,6 +741,116 @@ static int img_info(int argc, char **argv) | ||
| 732 | return 0; | 741 | return 0; |
| 733 | } | 742 | } |
| 734 | 743 | ||
| 744 | +#define SNAPSHOT_LIST 1 | ||
| 745 | +#define SNAPSHOT_CREATE 2 | ||
| 746 | +#define SNAPSHOT_APPLY 3 | ||
| 747 | +#define SNAPSHOT_DELETE 4 | ||
| 748 | + | ||
| 749 | +static void img_snapshot(int argc, char **argv) | ||
| 750 | +{ | ||
| 751 | + BlockDriverState *bs; | ||
| 752 | + QEMUSnapshotInfo sn; | ||
| 753 | + char *filename, *snapshot_name = NULL; | ||
| 754 | + char c; | ||
| 755 | + int ret; | ||
| 756 | + int action = 0; | ||
| 757 | + qemu_timeval tv; | ||
| 758 | + | ||
| 759 | + /* Parse commandline parameters */ | ||
| 760 | + for(;;) { | ||
| 761 | + c = getopt(argc, argv, "la:c:d:h"); | ||
| 762 | + if (c == -1) | ||
| 763 | + break; | ||
| 764 | + switch(c) { | ||
| 765 | + case 'h': | ||
| 766 | + help(); | ||
| 767 | + return; | ||
| 768 | + case 'l': | ||
| 769 | + if (action) { | ||
| 770 | + help(); | ||
| 771 | + return; | ||
| 772 | + } | ||
| 773 | + action = SNAPSHOT_LIST; | ||
| 774 | + break; | ||
| 775 | + case 'a': | ||
| 776 | + if (action) { | ||
| 777 | + help(); | ||
| 778 | + return; | ||
| 779 | + } | ||
| 780 | + action = SNAPSHOT_APPLY; | ||
| 781 | + snapshot_name = optarg; | ||
| 782 | + break; | ||
| 783 | + case 'c': | ||
| 784 | + if (action) { | ||
| 785 | + help(); | ||
| 786 | + return; | ||
| 787 | + } | ||
| 788 | + action = SNAPSHOT_CREATE; | ||
| 789 | + snapshot_name = optarg; | ||
| 790 | + break; | ||
| 791 | + case 'd': | ||
| 792 | + if (action) { | ||
| 793 | + help(); | ||
| 794 | + return; | ||
| 795 | + } | ||
| 796 | + action = SNAPSHOT_DELETE; | ||
| 797 | + snapshot_name = optarg; | ||
| 798 | + break; | ||
| 799 | + } | ||
| 800 | + } | ||
| 801 | + | ||
| 802 | + if (optind >= argc) | ||
| 803 | + help(); | ||
| 804 | + filename = argv[optind++]; | ||
| 805 | + | ||
| 806 | + /* Open the image */ | ||
| 807 | + bs = bdrv_new(""); | ||
| 808 | + if (!bs) | ||
| 809 | + error("Not enough memory"); | ||
| 810 | + | ||
| 811 | + if (bdrv_open2(bs, filename, 0, NULL) < 0) { | ||
| 812 | + error("Could not open '%s'", filename); | ||
| 813 | + } | ||
| 814 | + | ||
| 815 | + /* Perform the requested action */ | ||
| 816 | + switch(action) { | ||
| 817 | + case SNAPSHOT_LIST: | ||
| 818 | + dump_snapshots(bs); | ||
| 819 | + break; | ||
| 820 | + | ||
| 821 | + case SNAPSHOT_CREATE: | ||
| 822 | + memset(&sn, 0, sizeof(sn)); | ||
| 823 | + pstrcpy(sn.name, sizeof(sn.name), snapshot_name); | ||
| 824 | + | ||
| 825 | + qemu_gettimeofday(&tv); | ||
| 826 | + sn.date_sec = tv.tv_sec; | ||
| 827 | + sn.date_nsec = tv.tv_usec * 1000; | ||
| 828 | + | ||
| 829 | + ret = bdrv_snapshot_create(bs, &sn); | ||
| 830 | + if (ret) | ||
| 831 | + error("Could not create snapshot '%s': %d (%s)", | ||
| 832 | + snapshot_name, ret, strerror(-ret)); | ||
| 833 | + break; | ||
| 834 | + | ||
| 835 | + case SNAPSHOT_APPLY: | ||
| 836 | + ret = bdrv_snapshot_goto(bs, snapshot_name); | ||
| 837 | + if (ret) | ||
| 838 | + error("Could not apply snapshot '%s': %d (%s)", | ||
| 839 | + snapshot_name, ret, strerror(-ret)); | ||
| 840 | + break; | ||
| 841 | + | ||
| 842 | + case SNAPSHOT_DELETE: | ||
| 843 | + ret = bdrv_snapshot_delete(bs, snapshot_name); | ||
| 844 | + if (ret) | ||
| 845 | + error("Could not delete snapshot '%s': %d (%s)", | ||
| 846 | + snapshot_name, ret, strerror(-ret)); | ||
| 847 | + break; | ||
| 848 | + } | ||
| 849 | + | ||
| 850 | + /* Cleanup */ | ||
| 851 | + bdrv_delete(bs); | ||
| 852 | +} | ||
| 853 | + | ||
| 735 | int main(int argc, char **argv) | 854 | int main(int argc, char **argv) |
| 736 | { | 855 | { |
| 737 | const char *cmd; | 856 | const char *cmd; |
| @@ -749,6 +868,8 @@ int main(int argc, char **argv) | @@ -749,6 +868,8 @@ int main(int argc, char **argv) | ||
| 749 | img_convert(argc, argv); | 868 | img_convert(argc, argv); |
| 750 | } else if (!strcmp(cmd, "info")) { | 869 | } else if (!strcmp(cmd, "info")) { |
| 751 | img_info(argc, argv); | 870 | img_info(argc, argv); |
| 871 | + } else if (!strcmp(cmd, "snapshot")) { | ||
| 872 | + img_snapshot(argc, argv); | ||
| 752 | } else { | 873 | } else { |
| 753 | help(); | 874 | help(); |
| 754 | } | 875 | } |