ch_driver: Implement domain restore callbacks

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>
This commit is contained in:
Purna Pavan Chandra Aekkaladevi 2024-03-11 09:44:03 +00:00 committed by Michal Privoznik
parent ed12c63f89
commit 53ec0fd09d
3 changed files with 152 additions and 1 deletions

View 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 = {

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

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