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 <paekkaladevi@linux.microsoft.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Purna Pavan Chandra Aekkaladevi 2024-03-11 09:43:57 +00:00 committed by Michal Privoznik
parent aead1e49da
commit 6ea6208f35
2 changed files with 91 additions and 0 deletions

View 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

View 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);