[PATCH V2 1/4] qemu monitor: add snaphot-save/delete QMP commands

Nikolai Barybin via Devel posted 4 patches 2 months ago
[PATCH V2 1/4] qemu monitor: add snaphot-save/delete QMP commands
Posted by Nikolai Barybin via Devel 2 months ago
Signed-off-by: Nikolai Barybin <nikolai.barybin@virtuozzo.com>
---
 src/qemu/qemu_monitor.c      | 30 ++++++++++++++++
 src/qemu/qemu_monitor.h      | 13 +++++++
 src/qemu/qemu_monitor_json.c | 66 ++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor_json.h | 13 +++++++
 4 files changed, 122 insertions(+)

diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index b1c0c6a064..53f5ecf223 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2763,6 +2763,36 @@ qemuMonitorDeleteSnapshot(qemuMonitor *mon, const char *name)
 }
 
 
+int
+qemuMonitorSnapshotSave(qemuMonitor *mon,
+                        const char *jobname,
+                        const char *snapshotName,
+                        const char *vmstateDev,
+                        char **wrdevs)
+{
+    VIR_DEBUG("jobname=%s, snapshotName=%s, vmstateDev=%s, wrdevs=%p",
+              jobname, snapshotName, vmstateDev, wrdevs);
+
+    QEMU_CHECK_MONITOR(mon);
+
+    return qemuMonitorJSONSnapshotSave(mon, jobname, snapshotName, vmstateDev, wrdevs);
+}
+
+
+int
+qemuMonitorSnapshotDelete(qemuMonitor *mon,
+                          const char *jobname,
+                          const char *snapshotName,
+                          char **wrdevs)
+{
+    VIR_DEBUG("jobname=%s, snapshotName=%s, wrdevs=%p", jobname, snapshotName, wrdevs);
+
+    QEMU_CHECK_MONITOR(mon);
+
+    return qemuMonitorJSONSnapshotDelete(mon, jobname, snapshotName, wrdevs);
+}
+
+
 int
 qemuMonitorBlockdevMirror(qemuMonitor *mon,
                           const char *jobname,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 76c859a888..27dbb78e06 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1617,3 +1617,16 @@ int
 qemuMonitorDisplayReload(qemuMonitor *mon,
                          const char *type,
                          bool tlsCerts);
+
+int
+qemuMonitorSnapshotSave(qemuMonitor *mon,
+                        const char *jobname,
+                        const char *snapshotName,
+                        const char *vmstateDev,
+                        char **wrdevs);
+
+int
+qemuMonitorSnapshotDelete(qemuMonitor *mon,
+                          const char *jobname,
+                          const char *snapshotName,
+                          char **wrdevs);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 8a20ce57e6..312a4aee04 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -8955,3 +8955,69 @@ int qemuMonitorJSONDisplayReload(qemuMonitor *mon,
 
     return 0;
 }
+
+int
+qemuMonitorJSONSnapshotSave(qemuMonitor *mon,
+                            const char *jobname,
+                            const char *snapshotName,
+                            const char *vmstateDev,
+                            char **wrdevs)
+{
+    g_autoptr(virJSONValue) cmd = NULL;
+    g_autoptr(virJSONValue) reply = NULL;
+    g_autoptr(virJSONValue) wrdev_list = NULL;
+    size_t i = 0;
+
+    if (wrdevs) {
+        wrdev_list = virJSONValueNewArray();
+
+        for (i = 0; wrdevs[i]; i++)
+            if (virJSONValueArrayAppendString(wrdev_list, wrdevs[i]) < 0)
+                return -1;
+    }
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("snapshot-save",
+                                           "s:job-id", jobname,
+                                           "s:tag", snapshotName,
+                                           "s:vmstate", vmstateDev,
+                                           "A:devices", &wrdev_list,
+                                           NULL)))
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return -1;
+
+    return qemuMonitorJSONCheckError(cmd, reply);
+}
+
+int
+qemuMonitorJSONSnapshotDelete(qemuMonitor *mon,
+                              const char *jobname,
+                              const char *snapshotName,
+                              char **wrdevs)
+{
+    g_autoptr(virJSONValue) cmd = NULL;
+    g_autoptr(virJSONValue) reply = NULL;
+    g_autoptr(virJSONValue) wrdev_list = NULL;
+    size_t i = 0;
+
+    if (wrdevs) {
+        wrdev_list = virJSONValueNewArray();
+
+        for (i = 0; wrdevs[i]; i++)
+            if (virJSONValueArrayAppendString(wrdev_list, wrdevs[i]) < 0)
+                return -1;
+    }
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("snapshot-delete",
+                                           "s:job-id", jobname,
+                                           "s:tag", snapshotName,
+                                           "A:devices", &wrdev_list,
+                                           NULL)))
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return -1;
+
+    return qemuMonitorJSONCheckError(cmd, reply);
+}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 921dd34ed2..0245cd54fc 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -825,3 +825,16 @@ qemuMonitorJSONQueryStats(qemuMonitor *mon,
 int qemuMonitorJSONDisplayReload(qemuMonitor *mon,
                                  const char *type,
                                  bool tlsCerts);
+
+int
+qemuMonitorJSONSnapshotSave(qemuMonitor *mon,
+                            const char *jobname,
+                            const char *snapshotName,
+                            const char *vmstateDev,
+                            char **wrdevs);
+
+int
+qemuMonitorJSONSnapshotDelete(qemuMonitor *mon,
+                              const char *jobname,
+                              const char *snapshotName,
+                              char **wrdevs);
-- 
2.43.5
Re: [PATCH V2 1/4] qemu monitor: add snaphot-save/delete QMP commands
Posted by Peter Krempa 1 month ago
On Wed, Jul 17, 2024 at 21:21:35 +0300, Nikolai Barybin via Devel wrote:
> Signed-off-by: Nikolai Barybin <nikolai.barybin@virtuozzo.com>
> ---
>  src/qemu/qemu_monitor.c      | 30 ++++++++++++++++
>  src/qemu/qemu_monitor.h      | 13 +++++++
>  src/qemu/qemu_monitor_json.c | 66 ++++++++++++++++++++++++++++++++++++
>  src/qemu/qemu_monitor_json.h | 13 +++++++
>  4 files changed, 122 insertions(+)
> 
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index b1c0c6a064..53f5ecf223 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -2763,6 +2763,36 @@ qemuMonitorDeleteSnapshot(qemuMonitor *mon, const char *name)
>  }
>  
>  
> +int
> +qemuMonitorSnapshotSave(qemuMonitor *mon,
> +                        const char *jobname,
> +                        const char *snapshotName,
> +                        const char *vmstateDev,
> +                        char **wrdevs)
> +{
> +    VIR_DEBUG("jobname=%s, snapshotName=%s, vmstateDev=%s, wrdevs=%p",
> +              jobname, snapshotName, vmstateDev, wrdevs);

Logging pointer to wrdevs is not useful as you can't get to the data
from logs. In this case we can simply drop it.

Also the variable values should be surrounded by quotes ('%s') to
visualy separate the value.

> +
> +    QEMU_CHECK_MONITOR(mon);
> +
> +    return qemuMonitorJSONSnapshotSave(mon, jobname, snapshotName, vmstateDev, wrdevs);
> +}

[...]

> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 8a20ce57e6..312a4aee04 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -8955,3 +8955,69 @@ int qemuMonitorJSONDisplayReload(qemuMonitor *mon,
>  
>      return 0;
>  }
> +
> +int
> +qemuMonitorJSONSnapshotSave(qemuMonitor *mon,
> +                            const char *jobname,
> +                            const char *snapshotName,
> +                            const char *vmstateDev,
> +                            char **wrdevs)

const char **

> +{
> +    g_autoptr(virJSONValue) cmd = NULL;
> +    g_autoptr(virJSONValue) reply = NULL;
> +    g_autoptr(virJSONValue) wrdev_list = NULL;
> +    size_t i = 0;

A counter variable is not needed to iterate a NULL-terminated string
list once.

> +
> +    if (wrdevs) {
> +        wrdev_list = virJSONValueNewArray();
> +
> +        for (i = 0; wrdevs[i]; i++)
> +            if (virJSONValueArrayAppendString(wrdev_list, wrdevs[i]) < 0)
> +                return -1;
> +    }
> +
> +    if (!(cmd = qemuMonitorJSONMakeCommand("snapshot-save",
> +                                           "s:job-id", jobname,
> +                                           "s:tag", snapshotName,
> +                                           "s:vmstate", vmstateDev,
> +                                           "A:devices", &wrdev_list,
> +                                           NULL)))
> +        return -1;
> +
> +    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
> +        return -1;
> +
> +    return qemuMonitorJSONCheckError(cmd, reply);
> +}

Looks good, but it's missing tests in test/qemumonitorjsontest.c. This
test case is important because it validates the commands libvirt uses
against the QMP schema obtained from qemu. Validation allows us to catch
deprecations and changes early.