]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
ch_driver: Support Save, Restore VM actions from monitor
authorPurna Pavan Chandra Aekkaladevi <paekkaladevi@linux.microsoft.com>
Mon, 11 Mar 2024 09:43:57 +0000 (09:43 +0000)
committerMichal Privoznik <mprivozn@redhat.com>
Wed, 20 Mar 2024 13:05:10 +0000 (14:05 +0100)
Implement folowing API calls from CH monitor
* vmm.snapshot -> to save a domain
* vmm.restore -> to restore saved domain

Signed-off-by: Purna Pavan Chandra Aekkaladevi <paekkaladevi@linux.microsoft.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/ch/ch_monitor.c
src/ch/ch_monitor.h

index fefbf7e67a789de5dbd07a63be96501e5cea7edc..facbff002e91562ef0cfdc3c75dd371d9a33706a 100644 (file)
@@ -457,6 +457,22 @@ virCHMonitorBuildVMJson(virCHDriver *driver, virDomainDef *vmdef,
     return 0;
 }
 
+static int
+virCHMonitorBuildKeyValueStringJson(char **jsonstr,
+                                    const char *key,
+                                    const char *value)
+{
+    g_autoptr(virJSONValue) content = virJSONValueNewObject();
+
+    if (virJSONValueObjectAppendString(content, key, value) < 0)
+        return -1;
+
+    if (!(*jsonstr = virJSONValueToString(content, false)))
+        return -1;
+
+    return 0;
+}
+
 static int
 chMonitorCreateSocket(const char *socket_path)
 {
@@ -896,6 +912,77 @@ virCHMonitorResumeVM(virCHMonitor *mon)
     return virCHMonitorPutNoContent(mon, URL_VM_RESUME);
 }
 
+static int
+virCHMonitorSaveRestoreVM(virCHMonitor *mon, const char *path, bool save)
+{
+    g_autofree char *url = NULL;
+    int responseCode = 0;
+    int ret = -1;
+    g_autofree char *payload = NULL;
+    g_autofree char *path_url = NULL;
+    struct curl_slist *headers = NULL;
+    struct curl_data data = {0};
+
+    if (save)
+        url = g_strdup_printf("%s/%s", URL_ROOT, URL_VM_SAVE);
+    else
+        url = g_strdup_printf("%s/%s", URL_ROOT, URL_VM_RESTORE);
+
+    headers = curl_slist_append(headers, "Accept: application/json");
+    headers = curl_slist_append(headers, "Content-Type: application/json");
+
+    path_url = g_strdup_printf("file://%s", path);
+    if (save) {
+        if (virCHMonitorBuildKeyValueStringJson(&payload, "destination_url", path_url) != 0)
+            return -1;
+    } else {
+        if (virCHMonitorBuildKeyValueStringJson(&payload, "source_url", path_url) != 0)
+            return -1;
+    }
+
+    VIR_WITH_OBJECT_LOCK_GUARD(mon) {
+        /* reset all options of a libcurl session handle at first */
+        curl_easy_reset(mon->handle);
+
+        curl_easy_setopt(mon->handle, CURLOPT_UNIX_SOCKET_PATH, mon->socketpath);
+        curl_easy_setopt(mon->handle, CURLOPT_URL, url);
+        curl_easy_setopt(mon->handle, CURLOPT_CUSTOMREQUEST, "PUT");
+        curl_easy_setopt(mon->handle, CURLOPT_HTTPHEADER, headers);
+        curl_easy_setopt(mon->handle, CURLOPT_POSTFIELDS, payload);
+        curl_easy_setopt(mon->handle, CURLOPT_WRITEFUNCTION, curl_callback);
+        curl_easy_setopt(mon->handle, CURLOPT_WRITEDATA, (void *)&data);
+
+        responseCode = virCHMonitorCurlPerform(mon->handle);
+    }
+
+    if (responseCode == 200 || responseCode == 204) {
+        ret = 0;
+    } else {
+        data.content = g_realloc(data.content, data.size + 1);
+        data.content[data.size] = 0;
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       data.content);
+        g_free(data.content);
+    }
+
+    /* reset the libcurl handle to avoid leaking a stack pointer to data */
+    curl_easy_reset(mon->handle);
+    curl_slist_free_all(headers);
+    return ret;
+}
+
+int
+virCHMonitorSaveVM(virCHMonitor *mon, const char *to)
+{
+    return virCHMonitorSaveRestoreVM(mon, to, true);
+}
+
+int
+virCHMonitorRestoreVM(virCHMonitor *mon, const char *from)
+{
+    return virCHMonitorSaveRestoreVM(mon, from, false);
+}
+
 /**
  * virCHMonitorGetInfo:
  * @mon: Pointer to the monitor
index 47b4e7abbdad9f5736722b0b15ac662b92d1f9c9..3e0befe5d056907597fbe21a037f39460f6de1cc 100644 (file)
@@ -37,6 +37,8 @@
 #define URL_VM_Suspend "vm.pause"
 #define URL_VM_RESUME "vm.resume"
 #define URL_VM_INFO "vm.info"
+#define URL_VM_SAVE "vm.snapshot"
+#define URL_VM_RESTORE "vm.restore"
 
 #define VIRCH_THREAD_NAME_LEN   16
 
@@ -110,6 +112,8 @@ int virCHMonitorShutdownVM(virCHMonitor *mon);
 int virCHMonitorRebootVM(virCHMonitor *mon);
 int virCHMonitorSuspendVM(virCHMonitor *mon);
 int virCHMonitorResumeVM(virCHMonitor *mon);
+int virCHMonitorSaveVM(virCHMonitor *mon, const char *to);
+int virCHMonitorRestoreVM(virCHMonitor *mon, const char *from);
 int virCHMonitorGetInfo(virCHMonitor *mon, virJSONValue **info);
 
 void virCHMonitorCPUInfoFree(virCHMonitorCPUInfo *cpus);