From 6ea6208f357a6c3007f5498d8ab27b6d15679825 Mon Sep 17 00:00:00 2001 From: Purna Pavan Chandra Aekkaladevi Date: Mon, 11 Mar 2024 09:43:57 +0000 Subject: [PATCH] ch_driver: Support Save, Restore VM actions from monitor 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 Reviewed-by: Michal Privoznik --- src/ch/ch_monitor.c | 87 +++++++++++++++++++++++++++++++++++++++++++++ src/ch/ch_monitor.h | 4 +++ 2 files changed, 91 insertions(+) diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c index fefbf7e67a..facbff002e 100644 --- a/src/ch/ch_monitor.c +++ b/src/ch/ch_monitor.c @@ -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 diff --git a/src/ch/ch_monitor.h b/src/ch/ch_monitor.h index 47b4e7abbd..3e0befe5d0 100644 --- a/src/ch/ch_monitor.h +++ b/src/ch/ch_monitor.h @@ -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);