diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c index f5e58a8fef..3102007e5e 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -990,6 +990,8 @@ parallelsDomainHasManagedSaveImage(virDomainPtr domain, unsigned int flags) { parallelsConnPtr privconn = domain->conn->privateData; virDomainObjPtr dom = NULL; + int state, reason; + int ret = 0; virCheckFlags(0, -1); @@ -999,9 +1001,72 @@ parallelsDomainHasManagedSaveImage(virDomainPtr domain, unsigned int flags) return -1; } + state = virDomainObjGetState(dom, &reason); + if (state == VIR_DOMAIN_SHUTOFF && reason == VIR_DOMAIN_SHUTOFF_SAVED) + ret = 1; virObjectUnlock(dom); - return 0; + return ret; +} + +static int +parallelsDomainManagedSave(virDomainPtr domain, unsigned int flags) +{ + parallelsConnPtr privconn = domain->conn->privateData; + virDomainObjPtr dom = NULL; + int state, reason; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_SAVE_RUNNING | + VIR_DOMAIN_SAVE_PAUSED, -1); + + dom = virDomainObjListFindByUUID(privconn->domains, domain->uuid); + if (dom == NULL) { + parallelsDomNotFoundError(domain); + return -1; + } + + state = virDomainObjGetState(dom, &reason); + + if (state == VIR_DOMAIN_RUNNING && (flags & VIR_DOMAIN_SAVE_PAUSED)) { + ret = prlsdkDomainChangeStateLocked(privconn, dom, prlsdkPause); + if (ret) + goto cleanup; + } + + ret = prlsdkDomainChangeStateLocked(privconn, dom, prlsdkSuspend); + + cleanup: + virObjectUnlock(dom); + return ret; +} + +static int +parallelsDomainManagedSaveRemove(virDomainPtr domain, unsigned int flags) +{ + parallelsConnPtr privconn = domain->conn->privateData; + virDomainObjPtr dom = NULL; + int state, reason; + int ret = -1; + + virCheckFlags(0, -1); + + dom = virDomainObjListFindByUUID(privconn->domains, domain->uuid); + if (dom == NULL) { + parallelsDomNotFoundError(domain); + return -1; + } + + state = virDomainObjGetState(dom, &reason); + + if (!(state == VIR_DOMAIN_SHUTOFF && reason == VIR_DOMAIN_SHUTOFF_SAVED)) + goto cleanup; + + ret = prlsdkDomainManagedSaveRemove(privconn, dom); + + cleanup: + virObjectUnlock(dom); + return ret; } static virHypervisorDriver parallelsDriver = { @@ -1046,6 +1111,8 @@ static virHypervisorDriver parallelsDriver = { .connectIsSecure = parallelsConnectIsSecure, /* 1.2.5 */ .connectIsAlive = parallelsConnectIsAlive, /* 1.2.5 */ .domainHasManagedSaveImage = parallelsDomainHasManagedSaveImage, /* 1.2.13 */ + .domainManagedSave = parallelsDomainManagedSave, /* 1.2.14 */ + .domainManagedSaveRemove = parallelsDomainManagedSaveRemove, /* 1.2.14 */ }; static virConnectDriver parallelsConnectDriver = { diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index d61e14ed6d..1b6751b146 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -1720,6 +1720,14 @@ PRL_RESULT prlsdkResume(parallelsConnPtr privconn, PRL_HANDLE sdkdom) return waitJob(job, privconn->jobTimeout); } +PRL_RESULT prlsdkSuspend(parallelsConnPtr privconn, PRL_HANDLE sdkdom) +{ + PRL_HANDLE job = PRL_INVALID_HANDLE; + + job = PrlVm_Suspend(sdkdom); + return waitJob(job, privconn->jobTimeout); +} + int prlsdkDomainChangeStateLocked(parallelsConnPtr privconn, virDomainObjPtr dom, @@ -3210,3 +3218,16 @@ prlsdkUnregisterDomain(parallelsConnPtr privconn, virDomainObjPtr dom) virDomainObjListRemove(privconn->domains, dom); return 0; } + +int +prlsdkDomainManagedSaveRemove(parallelsConnPtr privconn, virDomainObjPtr dom) +{ + parallelsDomObjPtr privdom = dom->privateData; + PRL_HANDLE job; + + job = PrlVm_DropSuspendedState(privdom->sdkdom); + if (PRL_FAILED(waitJob(job, privconn->jobTimeout))) + return -1; + + return 0; +} diff --git a/src/parallels/parallels_sdk.h b/src/parallels/parallels_sdk.h index 780a226bf5..b084678e47 100644 --- a/src/parallels/parallels_sdk.h +++ b/src/parallels/parallels_sdk.h @@ -40,6 +40,7 @@ PRL_RESULT prlsdkKill(parallelsConnPtr privconn, PRL_HANDLE sdkdom); PRL_RESULT prlsdkStop(parallelsConnPtr privconn, PRL_HANDLE sdkdom); PRL_RESULT prlsdkPause(parallelsConnPtr privconn, PRL_HANDLE sdkdom); PRL_RESULT prlsdkResume(parallelsConnPtr privconn, PRL_HANDLE sdkdom); +PRL_RESULT prlsdkSuspend(parallelsConnPtr privconn, PRL_HANDLE sdkdom); typedef PRL_RESULT (*prlsdkChangeStateFunc)(parallelsConnPtr privconn, PRL_HANDLE sdkdom); int @@ -57,3 +58,5 @@ int prlsdkCreateVm(virConnectPtr conn, virDomainDefPtr def); int prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def); int prlsdkUnregisterDomain(parallelsConnPtr privconn, virDomainObjPtr dom); +int +prlsdkDomainManagedSaveRemove(parallelsConnPtr privconn, virDomainObjPtr dom);