]> xenbits.xensource.com Git - libvirt.git/commitdiff
ch_driver: Implement domain restore callbacks
authorPurna Pavan Chandra Aekkaladevi <paekkaladevi@linux.microsoft.com>
Mon, 11 Mar 2024 09:44:03 +0000 (09:44 +0000)
committerMichal Privoznik <mprivozn@redhat.com>
Wed, 20 Mar 2024 13:05:26 +0000 (14:05 +0100)
Following callbacks have been implemented
* domainRestore
* domainRestoreFlags
The path parameter to these callbacks has to be of the directory where
libvirt has performed save. Additionally, call restore in `domainCreate`
if the domain has managedsave.

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

index dace267d996c9f7a88b0d8bda0dbb89700adfa38..7b704702cf0a4a8532917b54185a5347f422cd2f 100644 (file)
@@ -252,6 +252,8 @@ chDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
 {
     virCHDriver *driver = dom->conn->privateData;
     virDomainObj *vm;
+    virCHDomainObjPrivate *priv;
+    g_autofree char *managed_save_path = NULL;
     int ret = -1;
 
     virCheckFlags(0, -1);
@@ -265,8 +267,34 @@ chDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
     if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0)
         goto cleanup;
 
-    ret = virCHProcessStart(driver, vm, VIR_DOMAIN_RUNNING_BOOTED);
+    if (vm->hasManagedSave) {
+        priv = vm->privateData;
+        managed_save_path = chDomainManagedSavePath(driver, vm);
+        if (virCHProcessStartRestore(driver, vm, managed_save_path) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("failed to restore domain from managed save"));
+            goto endjob;
+        }
+        if (virCHMonitorResumeVM(priv->monitor) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("failed to resume domain after restore from managed save"));
+            goto endjob;
+        }
+        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_RESTORED);
+        /* cleanup the save dir after restore */
+        if (virFileDeleteTree(managed_save_path) < 0) {
+            virReportSystemError(errno,
+                                 _("Failed to remove managed save path '%1$s'"),
+                                 managed_save_path);
+            goto endjob;
+        }
+        vm->hasManagedSave = false;
+        ret = 0;
+    } else {
+        ret = virCHProcessStart(driver, vm, VIR_DOMAIN_RUNNING_BOOTED);
+    }
 
+ endjob:
     virDomainObjEndJob(vm);
 
  cleanup:
@@ -989,6 +1017,70 @@ chDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
     return ret;
 }
 
+static int
+chDomainRestoreFlags(virConnectPtr conn,
+                     const char *from,
+                     const char *dxml,
+                     unsigned int flags)
+{
+    virCHDriver *driver = conn->privateData;
+    virDomainObj *vm = NULL;
+    virCHDomainObjPrivate *priv;
+    g_autoptr(virDomainDef) def = NULL;
+    int ret = -1;
+
+    virCheckFlags(0, -1);
+
+    if (dxml) {
+        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                       _("xml modification unsupported"));
+        return -1;
+    }
+
+    if (chDomainSaveImageRead(driver, from, &def) < 0)
+        goto cleanup;
+
+    if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
+        goto cleanup;
+
+    if (!(vm = virDomainObjListAdd(driver->domains, &def,
+                                   driver->xmlopt,
+                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
+                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
+                                   NULL)))
+        goto cleanup;
+
+    if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0)
+        goto cleanup;
+
+    if (virCHProcessStartRestore(driver, vm, from) < 0)
+        goto endjob;
+
+    priv = vm->privateData;
+    if (virCHMonitorResumeVM(priv->monitor) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("failed to resume domain after restore"));
+        goto endjob;
+    }
+    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_RESTORED);
+    ret = 0;
+
+ endjob:
+    virDomainObjEndJob(vm);
+
+ cleanup:
+    if (vm && ret < 0)
+        virCHDomainRemoveInactive(driver, vm);
+    virDomainObjEndAPI(&vm);
+    return ret;
+}
+
+static int
+chDomainRestore(virConnectPtr conn, const char *from)
+{
+    return chDomainRestoreFlags(conn, from, NULL, 0);
+}
+
 static virDomainPtr chDomainLookupByID(virConnectPtr conn,
                                        int id)
 {
@@ -2117,6 +2209,8 @@ static virHypervisorDriver chHypervisorDriver = {
     .domainManagedSaveRemove = chDomainManagedSaveRemove,   /* 10.2.0 */
     .domainManagedSaveGetXMLDesc = chDomainManagedSaveGetXMLDesc,   /* 10.2.0 */
     .domainHasManagedSaveImage = chDomainHasManagedSaveImage,   /* 10.2.0 */
+    .domainRestore = chDomainRestore,                       /* 10.2.0 */
+    .domainRestoreFlags = chDomainRestoreFlags,             /* 10.2.0 */
 };
 
 static virConnectDriver chConnectDriver = {
index 250d66bc185118b57e15d16e46510f913a2e5520..48190a12736f4509db009f7d27e51761e5902b00 100644 (file)
@@ -853,3 +853,56 @@ virCHProcessStop(virCHDriver *driver G_GNUC_UNUSED,
 
     return 0;
 }
+
+/**
+ * virCHProcessStartRestore:
+ * @driver: pointer to driver structure
+ * @vm: pointer to virtual machine structure
+ * @from: directory path to restore the VM from
+ *
+ * Starts Cloud-Hypervisor process with the restored VM
+ *
+ * Returns 0 on success or -1 in case of error
+ */
+int
+virCHProcessStartRestore(virCHDriver *driver, virDomainObj *vm, const char *from)
+{
+    virCHDomainObjPrivate *priv = vm->privateData;
+    g_autoptr(virCHDriverConfig) cfg = virCHDriverGetConfig(priv->driver);
+
+    if (!priv->monitor) {
+        /* Get the first monitor connection if not already */
+        if (!(priv->monitor = virCHProcessConnectMonitor(driver, vm))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("failed to create connection to CH socket"));
+            return -1;
+        }
+    }
+
+    vm->pid = priv->monitor->pid;
+    vm->def->id = vm->pid;
+    priv->machineName = virCHDomainGetMachineName(vm);
+
+    if (virCHMonitorRestoreVM(priv->monitor, from) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("failed to restore domain"));
+        return -1;
+    }
+
+    /* Pass 0, NULL as restore only works without networking support */
+    if (virDomainCgroupSetupCgroup("ch", vm,
+                                   0, NULL, /* nnicindexes, nicindexes */
+                                   &priv->cgroup,
+                                   cfg->cgroupControllers,
+                                   0, /*maxThreadsPerProc*/
+                                   priv->driver->privileged,
+                                   priv->machineName) < 0)
+        return -1;
+
+    if (virCHProcessSetup(vm) < 0)
+        return -1;
+
+    virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_FROM_SNAPSHOT);
+
+    return 0;
+}
index 800e3f4e23462116b0410d92b5f36e985231da08..38bfce3b7f35933d259b6e5467b6662aada3225c 100644 (file)
@@ -32,3 +32,7 @@ int virCHProcessStop(virCHDriver *driver,
 
 int virCHProcessSetupVcpu(virDomainObj *vm,
                           unsigned int vcpuid);
+
+int virCHProcessStartRestore(virCHDriver *driver,
+                         virDomainObj *vm,
+                         const char *from);