Patchwork [v2,17/17] vm-snapshot-save: add force parameter

login
register
mail settings
Submitter Pavel Hrdina
Date Dec. 13, 2012, 3:40 p.m.
Message ID <8d2408738c0924a14049e816d00a13711cc87325.1355404685.git.phrdina@redhat.com>
Download mbox | patch
Permalink /patch/206186/
State New
Headers show

Comments

Pavel Hrdina - Dec. 13, 2012, 3:40 p.m.
HMP command "savevm" now takes extra optional force parameter to specifi whether
replace existing snapshot or not.

QMP command "vm-snapshot-save" has also extra optional force parameter and
name parameter isn't optional anymore.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
 hmp-commands.hx  | 16 ++++++++--------
 hmp.c            | 25 ++++++++++++++++++++++++-
 qapi-schema.json |  9 ++++++---
 qmp-commands.hx  | 15 +++++++++------
 savevm.c         | 34 +++++++++++++---------------------
 5 files changed, 60 insertions(+), 39 deletions(-)

Patch

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 0b3d783..04cee55 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -307,19 +307,19 @@  ETEXI
 
     {
         .name       = "savevm",
-        .args_type  = "name:s?",
-        .params     = "[tag|id]",
-        .help       = "save a VM snapshot. If no tag or id are provided, a new snapshot is created",
+        .args_type  = "force:-b,name:s?,",
+        .params     = "[-f] [tag|id]",
+        .help       = "save a VM snapshot. To replace existing snapshot use force flag.",
         .mhandler.cmd = hmp_vm_snapshot_save,
     },
 
 STEXI
-@item savevm [@var{tag}|@var{id}]
+@item savevm [@var{-f}] [@var{tag}|@var{id}]
 @findex savevm
-Create a snapshot of the whole virtual machine. If @var{tag} is
-provided, it is used as human readable identifier. If there is already
-a snapshot with the same @var{tag} or @var{id}, it is replaced. More info at
-@ref{vm_snapshots}.
+Create a snapshot of the whole virtual machine. Paramtere "name" is optional.
+If @var{tag} is provided, it is used as human readable identifier. If there is
+already a snapshot with the same @var{tag} or @var{id}, @var{-f} flag needs to
+be specified. More info at @ref{vm_snapshots}.
 ETEXI
 
     {
diff --git a/hmp.c b/hmp.c
index 1983210..f5e7334 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1372,9 +1372,32 @@  void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict)
 void hmp_vm_snapshot_save(Monitor *mon, const QDict *qdict)
 {
     const char *name = qdict_get_try_str(qdict, "name");
+    char new_name[256];
+    bool force = qdict_get_try_bool(qdict, "force", 0);
     Error *err = NULL;
+#ifdef _WIN32
+    struct _timeb tb;
+    struct tm *ptm;
+#else
+    struct timeval tv;
+    struct tm tm;
+#endif
+
+    if (!name) {
+#ifdef _WIN32
+        time_t t = tb.time;
+        ptm = localtime(&t);
+        strftime(new_name, sizeof(new_name), "vm-%Y%m%d%H%M%S", ptm);
+#else
+        /* cast below needed for OpenBSD where tv_sec is still 'long' */
+        localtime_r((const time_t *)&tv.tv_sec, &tm);
+        strftime(new_name, sizeof(new_name), "vm-%Y%m%d%H%M%S", &tm);
+#endif
+    } else {
+        pstrcpy(new_name, sizeof(new_name), name);
+    }
 
-    qmp_vm_snapshot_save(!!name, name, &err);
+    qmp_vm_snapshot_save(new_name, !!force, force, &err);
     hmp_handle_error(mon, &err);
 }
 
diff --git a/qapi-schema.json b/qapi-schema.json
index a8742a1..452b52b 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3036,19 +3036,22 @@ 
 #
 # Create a snapshot of the whole virtual machine. If tag is provided as @name,
 # it is used as human readable identifier. If there is already a snapshot
-# with the same tag or ID, it is replaced.
+# with the same tag or id, the force argument needs to be true to replace it.
 #
 # The VM is automatically stopped and resumed and saving a snapshot can take
 # a long time.
 #
-# @name: #optional tag of new snapshot or tag|id of existing snapshot
+# @name: tag of new snapshot or tag|id of existing snapshot
+#
+# @force: #optional specify whether existing snapshot is replaced or not,
+#         default is false
 #
 # Returns: Nothing on success
 #          If an error occurs, GenericError with error message
 #
 # Since: 1.4.0
 ##
-{ 'command': 'vm-snapshot-save', 'data': {'*name': 'str'} }
+{ 'command': 'vm-snapshot-save', 'data': {'name': 'str', '*force': 'bool'} }
 
 ##
 # @vm-snapshot-load:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index f839c40..077276e 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1349,9 +1349,9 @@  Example:
 EQMP
     {
         .name       = "vm-snapshot-save",
-        .args_type  = "name:s?",
-        .params     = "name",
-        .help       = "save a VM snapshot. If no tag or id are provided, a new snapshot is created",
+        .args_type  = "name:s,force:b?",
+        .params     = "name [force]",
+        .help       = "save a VM snapshot. To replace existing snapshot use force parameter.",
         .mhandler.cmd_new = qmp_marshal_input_vm_snapshot_save
     },
 
@@ -1360,15 +1360,18 @@  vm-snapshot-save
 ------
 
 Create a snapshot of the whole virtual machine. If tag is provided as name,
-it is used as human readable identifier. If there is already a snapshot
-with the same tag or id, it is replaced.
+it is used as human readable identifier. If there is already a snapshot with
+the same tag, the force argument needs to be true to replace it.
 
 The VM is automatically stopped and resumed and saving a snapshot can take
 a long time.
 
 Arguments:
 
-- "name": tag of new snapshot or tag|id of existing snapshot (json-string, optional)
+- "name": tag of new snapshot or tag|id of existing snapshot (json-string)
+
+- "force": specify whether existing snapshot is replaced or not,
+           default is false (json-bool, optional)
 
 Example:
 
diff --git a/savevm.c b/savevm.c
index 36ccc46..effb4df 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2141,7 +2141,7 @@  static int del_existing_snapshots(const char *name,
     return 0;
 }
 
-void qmp_vm_snapshot_save(bool has_name, const char *name, Error **errp)
+void qmp_vm_snapshot_save(const char *name, bool has_force, bool force, Error **errp)
 {
     BlockDriverState *bs, *bs1;
     QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
@@ -2151,10 +2151,8 @@  void qmp_vm_snapshot_save(bool has_name, const char *name, Error **errp)
     uint64_t vm_state_size;
 #ifdef _WIN32
     struct _timeb tb;
-    struct tm *ptm;
 #else
     struct timeval tv;
-    struct tm tm;
 #endif
 
     /* Verify if there is a device that doesn't support snapshots and is writable */
@@ -2195,29 +2193,23 @@  void qmp_vm_snapshot_save(bool has_name, const char *name, Error **errp)
 #endif
     sn->vm_clock_nsec = qemu_get_clock_ns(vm_clock);
 
-    if (has_name) {
-        ret = bdrv_snapshot_find(bs, old_sn, name, NULL);
-        if (ret >= 0) {
+    ret = bdrv_snapshot_find(bs, old_sn, name, NULL);
+    if (ret >= 0) {
+        if (has_force && force) {
             pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
             pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
+
+            del_existing_snapshots(name, errp);
+            if (error_is_set(errp)) {
+                goto the_end;
+            }
         } else {
-            pstrcpy(sn->name, sizeof(sn->name), name);
+            error_setg(errp, "Snapshot '%s' exist. For override specify "
+                       "'force=yes'.", name);
+            goto the_end;
         }
     } else {
-#ifdef _WIN32
-        time_t t = tb.time;
-        ptm = localtime(&t);
-        strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", ptm);
-#else
-        /* cast below needed for OpenBSD where tv_sec is still 'long' */
-        localtime_r((const time_t *)&tv.tv_sec, &tm);
-        strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", &tm);
-#endif
-    }
-
-    /* Delete old snapshots of the same name */
-    if (has_name && del_existing_snapshots(name, errp) < 0) {
-        goto the_end;
+        pstrcpy(sn->name, sizeof(sn->name), name);
     }
 
     /* save the VM state */