Patchwork [14/18] qapi: Convert loadvm

login
register
mail settings
Submitter Pavel Hrdina
Date Aug. 15, 2012, 7:41 a.m.
Message ID <bdbae297768d2a0cef3a75652305fc29707cc370.1345016001.git.phrdina@redhat.com>
Download mbox | patch
Permalink /patch/177570/
State New
Headers show

Comments

Pavel Hrdina - Aug. 15, 2012, 7:41 a.m.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
 hmp-commands.hx  |  2 +-
 hmp.c            | 10 +++++++++
 hmp.h            |  1 +
 monitor.c        | 12 -----------
 qapi-schema.json | 15 ++++++++++++++
 qmp-commands.hx  | 25 ++++++++++++++++++++++
 savevm.c         | 63 ++++++++++++++++++++++++++++----------------------------
 sysemu.h         |  1 -
 vl.c             |  7 ++++++-
 9 files changed, 90 insertions(+), 46 deletions(-)
Eric Blake - Aug. 16, 2012, 3:31 a.m.
On 08/15/2012 01:41 AM, Pavel Hrdina wrote:
> Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
> ---
>  hmp-commands.hx  |  2 +-
>  hmp.c            | 10 +++++++++
>  hmp.h            |  1 +
>  monitor.c        | 12 -----------
>  qapi-schema.json | 15 ++++++++++++++
>  qmp-commands.hx  | 25 ++++++++++++++++++++++
>  savevm.c         | 63 ++++++++++++++++++++++++++++----------------------------
>  sysemu.h         |  1 -
>  vl.c             |  7 ++++++-
>  9 files changed, 90 insertions(+), 46 deletions(-)
> 

> +
> +##
> +# @vm-snapshot-load:
> +#
> +# Set the whole virtual machine to the snapshot identified by the tag
> +# 'tag' or the unique snapshot ID 'id'.
> +#
> +# @name: tag or id of existing snapshot
> +#
> +# Returns: Nothing on success
> +#          If an error occurs, GenericError with error message
> +#
> +# Since: 1.2

1.3
Eric Blake - Aug. 16, 2012, 4:34 a.m.
On 08/15/2012 09:31 PM, Eric Blake wrote:

> 
>> +
>> +##
>> +# @vm-snapshot-load:
>> +#
>> +# Set the whole virtual machine to the snapshot identified by the tag
>> +# 'tag' or the unique snapshot ID 'id'.
>> +#
>> +# @name: tag or id of existing snapshot
>> +#
>> +# Returns: Nothing on success
>> +#          If an error occurs, GenericError with error message

It might also be worth documenting that vm-snapshot-load can only load
online snapshots with associated VM state (those created by savevm), and
not offline snapshots (those created by 'qemu-img snapshot').

Patch

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 32476d1..f9709d9 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -284,7 +284,7 @@  ETEXI
         .args_type  = "name:s",
         .params     = "tag|id",
         .help       = "restore a VM snapshot from its tag or id",
-        .mhandler.cmd = do_loadvm,
+        .mhandler.cmd = hmp_vm_snapshot_load,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 9f791e8..c2db7b2 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1112,3 +1112,13 @@  void hmp_vm_snapshot_save(Monitor *mon, const QDict *qdict)
 
     hmp_handle_error(mon, &err);
 }
+
+void hmp_vm_snapshot_load(Monitor *mon, const QDict *qdict)
+{
+    const char *name = qdict_get_str(qdict, "name");
+    Error *err = NULL;
+
+    qmp_vm_snapshot_load(name, &err);
+
+    hmp_handle_error(mon, &err);
+}
diff --git a/hmp.h b/hmp.h
index 0ce1021..b669b66 100644
--- a/hmp.h
+++ b/hmp.h
@@ -72,5 +72,6 @@  void hmp_netdev_del(Monitor *mon, const QDict *qdict);
 void hmp_getfd(Monitor *mon, const QDict *qdict);
 void hmp_closefd(Monitor *mon, const QDict *qdict);
 void hmp_vm_snapshot_save(Monitor *mon, const QDict *qdict);
+void hmp_vm_snapshot_load(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/monitor.c b/monitor.c
index dd63f1d..b75b9e0 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2330,18 +2330,6 @@  void qmp_closefd(const char *fdname, Error **errp)
     error_set(errp, QERR_FD_NOT_FOUND, fdname);
 }
 
-static void do_loadvm(Monitor *mon, const QDict *qdict)
-{
-    int saved_vm_running  = runstate_is_running();
-    const char *name = qdict_get_str(qdict, "name");
-
-    vm_stop(RUN_STATE_RESTORE_VM);
-
-    if (load_vmstate(name) == 0 && saved_vm_running) {
-        vm_start();
-    }
-}
-
 int monitor_get_fd(Monitor *mon, const char *fdname)
 {
     mon_fd_t *monfd;
diff --git a/qapi-schema.json b/qapi-schema.json
index 5c086f9..c477b26 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2375,3 +2375,18 @@ 
 # Since: 1.2
 ##
 { 'command': 'vm-snapshot-save', 'data': {'*name': 'str'} }
+
+##
+# @vm-snapshot-load:
+#
+# Set the whole virtual machine to the snapshot identified by the tag
+# 'tag' or the unique snapshot ID 'id'.
+#
+# @name: tag or id of existing snapshot
+#
+# Returns: Nothing on success
+#          If an error occurs, GenericError with error message
+#
+# Since: 1.2
+##
+{ 'command': 'vm-snapshot-load', 'data': {'name': 'str'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index ac7c4c9..a044345 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1140,6 +1140,31 @@  Example:
 
 EQMP
     {
+        .name       = "vm-snapshot-load",
+        .args_type  = "name:s",
+        .params     = "name",
+        .help       = "restore a VM snapshot from its tag or id",
+        .mhandler.cmd_new = qmp_marshal_input_vm_snapshot_load
+    },
+
+SQMP
+vm-snapshot-load
+------
+
+Set the whole virtual machine to the snapshot identified by the tag
+'tag' or the unique snapshot ID 'id'.
+
+Arguments:
+
+- "name": tag or id of existing snapshot
+
+Example:
+
+-> { "execute": "vm-snapshot-load", "arguments": { "name": "my_snapshot" } }
+<- { "return": {} }
+
+EQMP
+    {
         .name       = "qmp_capabilities",
         .args_type  = "",
         .params     = "",
diff --git a/savevm.c b/savevm.c
index 42e496f..0b95646 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2233,27 +2233,28 @@  void qmp_xen_save_devices_state(const char *filename, Error **errp)
     return;
 }
 
-int load_vmstate(const char *name)
+void qmp_vm_snapshot_load(const char *name, Error **errp)
 {
     BlockDriverState *bs, *bs_vm_state;
     QEMUSnapshotInfo sn;
     QEMUFile *f;
-    int ret;
+    int ret, saved_vm_running;
 
     bs_vm_state = bdrv_snapshots();
     if (!bs_vm_state) {
-        error_report("No block device supports snapshots");
-        return -ENOTSUP;
+        error_set(errp, QERR_NOT_SUPPORTED);
+        return;
     }
 
     /* Don't even try to load empty VM states */
-    ret = bdrv_snapshot_find(bs_vm_state, &sn, name, NULL);
-    if (ret < 0) {
-        return ret;
-    } else if (sn.vm_state_size == 0) {
-        error_report("This is a disk-only snapshot. Revert to it offline "
-            "using qemu-img.");
-        return -EINVAL;
+    bdrv_snapshot_find(bs_vm_state, &sn, name, errp);
+    if (error_is_set(errp)) {
+        return;
+    }
+    if (sn.vm_state_size == 0) {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
+                  "name", "whole VM snapshot");
+        return;
     }
 
     /* Verify if there is any device that doesn't support snapshots and is
@@ -2266,30 +2267,28 @@  int load_vmstate(const char *name)
         }
 
         if (!bdrv_can_snapshot(bs)) {
-            error_report("Device '%s' is writable but does not support snapshots.",
-                               bdrv_get_device_name(bs));
-            return -ENOTSUP;
+            error_set(errp, QERR_NOT_SUPPORTED);
+            return;
         }
 
-        ret = bdrv_snapshot_find(bs, &sn, name, NULL);
-        if (ret < 0) {
-            error_report("Device '%s' does not have the requested snapshot '%s'",
-                           bdrv_get_device_name(bs), name);
-            return ret;
+        bdrv_snapshot_find(bs, &sn, name, errp);
+        if (error_is_set(errp)) {
+            return;
         }
     }
 
+    saved_vm_running = runstate_is_running();
+    vm_stop(RUN_STATE_RESTORE_VM);
+
     /* Flush all IO requests so they don't interfere with the new state.  */
     bdrv_drain_all();
 
     bs = NULL;
     while ((bs = bdrv_next(bs))) {
         if (bdrv_can_snapshot(bs)) {
-            ret = bdrv_snapshot_goto(bs, name, NULL);
-            if (ret < 0) {
-                error_report("Error %d while activating snapshot '%s' on '%s'",
-                             ret, name, bdrv_get_device_name(bs));
-                return ret;
+            ret = bdrv_snapshot_goto(bs, name, errp);
+            if (error_is_set(errp)) {
+                return;
             }
         }
     }
@@ -2297,20 +2296,22 @@  int load_vmstate(const char *name)
     /* restore the VM state */
     f = qemu_fopen_bdrv(bs_vm_state, 0);
     if (!f) {
-        error_report("Could not open VM state file");
-        return -EINVAL;
+        error_set(errp, QERR_OPEN_FILE_FAILED,
+                  bdrv_get_device_name(bs_vm_state));
+        return;
     }
 
     qemu_system_reset(VMRESET_SILENT);
-    ret = qemu_loadvm_state(f, NULL);
+    qemu_loadvm_state(f, errp);
 
     qemu_fclose(f);
-    if (ret < 0) {
-        error_report("Error %d while loading VM state", ret);
-        return ret;
+    if (error_is_set(errp)) {
+        return;
     }
 
-    return 0;
+    if (saved_vm_running) {
+        vm_start();
+    }
 }
 
 void do_delvm(Monitor *mon, const QDict *qdict)
diff --git a/sysemu.h b/sysemu.h
index d1ceade..3327c49 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -69,7 +69,6 @@  void qemu_remove_exit_notifier(Notifier *notify);
 
 void qemu_add_machine_init_done_notifier(Notifier *notify);
 
-int load_vmstate(const char *name);
 void do_delvm(Monitor *mon, const QDict *qdict);
 void do_info_snapshots(Monitor *mon);
 
diff --git a/vl.c b/vl.c
index d01256a..190fe66 100644
--- a/vl.c
+++ b/vl.c
@@ -3683,8 +3683,13 @@  int main(int argc, char **argv, char **envp)
 
     qemu_system_reset(VMRESET_SILENT);
     if (loadvm) {
-        if (load_vmstate(loadvm) < 0) {
+        Error *errp = NULL;
+        qmp_vm_snapshot_load(loadvm, &errp);
+
+        if (error_is_set(&errp)) {
             autostart = 0;
+            error_report("%s", error_get_pretty(errp));
+            error_free(errp);
         }
     }