[libvirt] [PATCH 0/5] parallels: continue rewriting code to use sdk

This patch series replaces a series of functions, which retieve different domains info and modifies domains state with new ones, which use parallels sdk instead of executing prlctl command. These functions don't use cached domains list _parallelsConn.domains, so when we rewrite all code, we will be able to remove it. Alexander Burluka (1): parallels: obtain domain info with SDK Dmitry Guryanov (4): parallels: list domains with parallels SDK parallels: implement lookup functions with SDK parallels: move IS_CT macro to parallels_utils.h parallels: change domains state with SDK src/parallels/parallels_driver.c | 178 +----- src/parallels/parallels_sdk.c | 1189 ++++++++++++++++++++++++++++++++++++++ src/parallels/parallels_sdk.h | 14 + src/parallels/parallels_utils.h | 3 + 4 files changed, 1230 insertions(+), 154 deletions(-) -- 1.9.3

Use SDK to return a list of domains in parallelsConnectListAllDomains function instead of prlctl. Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/parallels/parallels_driver.c | 9 +- src/parallels/parallels_sdk.c | 243 +++++++++++++++++++++++++++++++++++++++ src/parallels/parallels_sdk.h | 3 + 3 files changed, 247 insertions(+), 8 deletions(-) diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c index 516a296..e4649dc 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -1137,16 +1137,9 @@ parallelsConnectListAllDomains(virConnectPtr conn, virDomainPtr **domains, unsigned int flags) { - parallelsConnPtr privconn = conn->privateData; - int ret = -1; - virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); - parallelsDriverLock(privconn); - ret = virDomainObjListExport(privconn->domains, conn, domains, - NULL, flags); - parallelsDriverUnlock(privconn); - return ret; + return prlsdkListAllDomains(conn, domains, flags); } static virDomainPtr diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index 1c77d27..80e3f7b 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -24,6 +24,7 @@ #include "virerror.h" #include "viralloc.h" +#include "datatypes.h" #include "parallels_sdk.h" @@ -72,6 +73,14 @@ logPrlErrorHelper(PRL_RESULT err, const char *filename, logPrlErrorHelper(code, __FILE__, \ __FUNCTION__, __LINE__) +# define prlsdkCheckRetGoto(ret, label) \ + do { \ + if (PRL_FAILED(ret)) { \ + logPrlError(ret); \ + goto label; \ + } \ + } while (0) + static PRL_RESULT logPrlEventErrorHelper(PRL_HANDLE event, const char *filename, const char *funcname, size_t linenr) @@ -239,3 +248,237 @@ prlsdkDisconnect(parallelsConnPtr privconn) PrlHandle_Free(privconn->server); } + +static int +prlsdkGetDomainIds(PRL_HANDLE sdkdom, + char **name, + unsigned char *uuid) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN + 2]; + PRL_UINT32 len; + PRL_RESULT pret; + + len = 0; + /* get name length */ + pret = PrlVmCfg_GetName(sdkdom, NULL, &len); + prlsdkCheckRetGoto(pret, error); + + if (VIR_ALLOC_N(*name, len) < 0) + goto error; + + PrlVmCfg_GetName(sdkdom, *name, &len); + prlsdkCheckRetGoto(pret, error); + + len = sizeof(uuidstr); + PrlVmCfg_GetUuid(sdkdom, uuidstr, &len); + prlsdkCheckRetGoto(pret, error); + + /* trim curly braces */ + uuidstr[strlen(uuidstr) - 1] = '\0'; + if (virUUIDParse(uuidstr + 1, uuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("UUID in config file malformed")); + goto error; + } + + return 0; + + error: + VIR_FREE(*name); + return -1; +} + +static int +prlsdkHandleToDomain(virConnectPtr conn, + PRL_HANDLE sdkdom, + virDomainPtr *dom) +{ + char *name = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; + int ret = -1; + + if (prlsdkGetDomainIds(sdkdom, &name, uuid) < 0) + goto cleanup; + + *dom = virGetDomain(conn, name, uuid); + if (!(*dom)) + goto cleanup; + + ret = 0; + cleanup: + VIR_FREE(name); + return ret; +} + +static int +prlsdkGetDomainState(parallelsConnPtr privconn, + PRL_HANDLE sdkdom, + VIRTUAL_MACHINE_STATE_PTR vmState) +{ + PRL_HANDLE job = PRL_INVALID_HANDLE; + PRL_HANDLE result = PRL_INVALID_HANDLE; + PRL_HANDLE vmInfo = PRL_INVALID_HANDLE; + PRL_RESULT pret; + int ret = -1; + + job = PrlVm_GetState(sdkdom); + + if (!(result = getJobResult(job, privconn->jobTimeout))) + goto cleanup; + + pret = PrlResult_GetParamByIndex(result, 0, &vmInfo); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmInfo_GetState(vmInfo, vmState); + prlsdkCheckRetGoto(pret, cleanup); + + ret = 0; + + cleanup: + PrlHandle_Free(vmInfo); + PrlHandle_Free(result); + return ret; +} + +#define MATCH(FLAG) (flags & (FLAG)) +/* Returns 1, if domain satisfies flags, 0 if doesn't, -1 in case + * of error. */ +static int +prlsdkCheckDomainSatisfiesFlags(parallelsConnPtr privconn, + PRL_HANDLE sdkdom, + unsigned int flags) +{ + VIRTUAL_MACHINE_STATE vmState; + PRL_VM_AUTOSTART_OPTION vmAutoStart; + PRL_RESULT ret; + bool isActive; + + if (prlsdkGetDomainState(privconn, sdkdom, &vmState) < 0) + return -1; + + isActive = vmState == VMS_RUNNING || vmState == VMS_PAUSED; + + /* filter by active state */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) && + !((MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE) && + isActive) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE) && + !isActive))) + return 0; + + /* All domains in PCS are persistent */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT) && + !(MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT))) + return 0; + + /* filter by domain state */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE)) { + if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) && + vmState == VMS_RUNNING) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) && + vmState == VMS_PAUSED) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) && + vmState == VMS_STOPPED) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) && + (vmState != VMS_RUNNING && + vmState != VMS_PAUSED && + vmState != VMS_STOPPED)))) + return 0; + } + + /* filter by existence of managed save state */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_MANAGEDSAVE) && + !((MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && + vmState == VMS_SUSPENDED) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE) && + vmState != VMS_SUSPENDED))) + return 0; + + ret = PrlVmCfg_GetAutoStart(sdkdom, &vmAutoStart); + if (PRL_FAILED(ret)) { + logPrlError(ret); + return -1; + } + + /* filter by autostart option */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_AUTOSTART) && + !((MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) && + vmAutoStart != PAO_VM_START_MANUAL) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART) && + vmAutoStart == PAO_VM_START_MANUAL))) + return 0; + + /* filter by snapshot existence */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT)) { + if (!MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT)) + return 0; + } + + return 1; +} +#undef MATCH + +int +prlsdkListAllDomains(virConnectPtr conn, + virDomainPtr **domains, + unsigned int flags) +{ + parallelsConnPtr privconn = conn->privateData; + PRL_HANDLE job = PRL_INVALID_HANDLE; + PRL_HANDLE result; + PRL_HANDLE sdkdom; + PRL_UINT32 paramsCount; + PRL_RESULT pret; + int ret; + virDomainPtr *domPtrArray = NULL; + size_t i = 0, j; + + virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); + + job = PrlSrv_GetVmListEx(privconn->server, PVTF_VM | PVTF_CT); + + if (!(result = getJobResult(job, privconn->jobTimeout))) + return -1; + + pret = PrlResult_GetParamsCount(result, ¶msCount); + prlsdkCheckRetGoto(pret, error); + + if (VIR_ALLOC_N(domPtrArray, paramsCount) < 0) + goto error; + + j = 0; + for (i = 0; i < paramsCount; i++) { + pret = PrlResult_GetParamByIndex(result, i, &sdkdom); + if (PRL_FAILED(pret)) { + logPrlError(pret); + PrlHandle_Free(sdkdom); + goto error; + } + + if (!prlsdkCheckDomainSatisfiesFlags(privconn, sdkdom, flags)) { + PrlHandle_Free(sdkdom); + continue; + } + + ret = prlsdkHandleToDomain(conn, sdkdom, &domPtrArray[j]); + PrlHandle_Free(sdkdom); + j++; + + if (ret < 0) + goto error; + } + + /* trim array to final size */ + ignore_value(VIR_REALLOC_N(domPtrArray, j)); + *domains = domPtrArray; + PrlHandle_Free(result); + return j; + + error: + for (j = i - 1; j <= 0; j--) + virDomainFree(domPtrArray[j]); + VIR_FREE(domPtrArray); + PrlHandle_Free(result); + PrlHandle_Free(job); + return -1; +} diff --git a/src/parallels/parallels_sdk.h b/src/parallels/parallels_sdk.h index cefe67d..400c95d 100644 --- a/src/parallels/parallels_sdk.h +++ b/src/parallels/parallels_sdk.h @@ -28,3 +28,6 @@ int prlsdkInit(parallelsConnPtr privconn); void prlsdkDeinit(void); int prlsdkConnect(parallelsConnPtr privconn); void prlsdkDisconnect(parallelsConnPtr privconn); +int prlsdkListAllDomains(virConnectPtr conn, + virDomainPtr **domains, + unsigned int flags); -- 1.9.3

Implement functions parallelsDomainLookupByUUID and parallelsDomainLookupByName with SDK instead of running prlctl command. Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/parallels/parallels_driver.c | 48 +---------------------- src/parallels/parallels_sdk.c | 83 ++++++++++++++++++++++++++++++++++++++++ src/parallels/parallels_sdk.h | 4 ++ 3 files changed, 89 insertions(+), 46 deletions(-) diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c index e4649dc..2617ab9 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -1171,57 +1171,13 @@ parallelsDomainLookupByID(virConnectPtr conn, int id) static virDomainPtr parallelsDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { - parallelsConnPtr privconn = conn->privateData; - virDomainPtr ret = NULL; - virDomainObjPtr dom; - - parallelsDriverLock(privconn); - dom = virDomainObjListFindByUUID(privconn->domains, uuid); - parallelsDriverUnlock(privconn); - - if (dom == NULL) { - char uuidstr[VIR_UUID_STRING_BUFLEN]; - virUUIDFormat(uuid, uuidstr); - virReportError(VIR_ERR_NO_DOMAIN, - _("no domain with matching uuid '%s'"), uuidstr); - goto cleanup; - } - - ret = virGetDomain(conn, dom->def->name, dom->def->uuid); - if (ret) - ret->id = dom->def->id; - - cleanup: - if (dom) - virObjectUnlock(dom); - return ret; + return prlsdkDomainLookupByUUID(conn, uuid); } static virDomainPtr parallelsDomainLookupByName(virConnectPtr conn, const char *name) { - parallelsConnPtr privconn = conn->privateData; - virDomainPtr ret = NULL; - virDomainObjPtr dom; - - parallelsDriverLock(privconn); - dom = virDomainObjListFindByName(privconn->domains, name); - parallelsDriverUnlock(privconn); - - if (dom == NULL) { - virReportError(VIR_ERR_NO_DOMAIN, - _("no domain with matching name '%s'"), name); - goto cleanup; - } - - ret = virGetDomain(conn, dom->def->name, dom->def->uuid); - if (ret) - ret->id = dom->def->id; - - cleanup: - if (dom) - virObjectUnlock(dom); - return ret; + return prlsdkDomainLookupByName(conn, name); } static int diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index 80e3f7b..111c52a 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -482,3 +482,86 @@ prlsdkListAllDomains(virConnectPtr conn, PrlHandle_Free(job); return -1; } + +int +prlsdkSdkDomainLookup(parallelsConnPtr privconn, + const char *id, + unsigned int flags, + PRL_HANDLE *sdkdom) +{ + PRL_HANDLE job = PRL_INVALID_HANDLE; + PRL_HANDLE result = PRL_INVALID_HANDLE; + PRL_RESULT pret = PRL_ERR_UNINITIALIZED; + int ret = -1; + + job = PrlSrv_GetVmConfig(privconn->server, id, flags); + if (!(result = getJobResult(job, privconn->jobTimeout))) + goto cleanup; + + pret = PrlResult_GetParamByIndex(result, 0, sdkdom); + prlsdkCheckRetGoto(pret, cleanup); + + ret = 0; + + cleanup: + PrlHandle_Free(result); + return ret; +} + +PRL_HANDLE +prlsdkSdkDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN + 2]; + PRL_HANDLE sdkdom = PRL_INVALID_HANDLE; + + virUUIDFormat(uuid, uuidstr + 1); + + uuidstr[0] = '{'; + uuidstr[VIR_UUID_STRING_BUFLEN] = '}'; + uuidstr[VIR_UUID_STRING_BUFLEN + 1] = '\0'; + + if (prlsdkSdkDomainLookup(conn->privateData, uuidstr, + PGVC_SEARCH_BY_UUID, &sdkdom) < 0) { + virUUIDFormat(uuid, uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + return PRL_INVALID_HANDLE; + } + + return sdkdom; +} +virDomainPtr +prlsdkDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) +{ + PRL_HANDLE sdkdom; + virDomainPtr dom = NULL; + + sdkdom = prlsdkSdkDomainLookupByUUID(conn, uuid); + if (sdkdom == PRL_INVALID_HANDLE) + return NULL; + + prlsdkHandleToDomain(conn, sdkdom, &dom); + PrlHandle_Free(sdkdom); + + return dom; +} + +virDomainPtr +prlsdkDomainLookupByName(virConnectPtr conn, const char *name) +{ + PRL_HANDLE sdkdom = PRL_INVALID_HANDLE; + virDomainPtr dom = NULL; + + if (prlsdkSdkDomainLookup(conn->privateData, name, + PGVC_SEARCH_BY_NAME, &sdkdom) < 0) { + virReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching name '%s'"), name); + goto cleanup; + } + + prlsdkHandleToDomain(conn, sdkdom, &dom); + + cleanup: + PrlHandle_Free(sdkdom); + return dom; +} diff --git a/src/parallels/parallels_sdk.h b/src/parallels/parallels_sdk.h index 400c95d..16df5f2 100644 --- a/src/parallels/parallels_sdk.h +++ b/src/parallels/parallels_sdk.h @@ -31,3 +31,7 @@ void prlsdkDisconnect(parallelsConnPtr privconn); int prlsdkListAllDomains(virConnectPtr conn, virDomainPtr **domains, unsigned int flags); +virDomainPtr +prlsdkDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid); +virDomainPtr +prlsdkDomainLookupByName(virConnectPtr conn, const char *name); -- 1.9.3

This macro will be used in paralles_sdk.c so move it to common header. Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/parallels/parallels_driver.c | 2 -- src/parallels/parallels_utils.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c index 2617ab9..fac1f8e 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -72,8 +72,6 @@ VIR_LOG_INIT("parallels.parallels_driver"); _("no domain with matching uuid '%s'"), uuidstr); \ } while (0) -#define IS_CT(def) (STREQ_NULLABLE(def->os.type, "exe")) - static int parallelsConnectClose(virConnectPtr conn); static const char * parallelsGetDiskBusName(int bus) { diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h index aef590f..269020a 100644 --- a/src/parallels/parallels_utils.h +++ b/src/parallels/parallels_utils.h @@ -37,6 +37,8 @@ virReportErrorHelper(VIR_FROM_TEST, VIR_ERR_OPERATION_FAILED, __FILE__, \ __FUNCTION__, __LINE__, _("Can't parse prlctl output")) +#define IS_CT(def) (STREQ_NULLABLE(def->os.type, "exe")) + # define PARALLELS_ROUTED_NETWORK_NAME "Routed" struct _parallelsConn { -- 1.9.3

From: Alexander Burluka <aburluka@parallels.com> Add code, which can fill virDomainDef structure by parallels sdk handle. prlsdkCreateDomainObj function is an analogue of parallelsLoadDomain from parallels_driver.c. Also use this new code in parallelsDomainGetXMLDesc to check it and remove build error about unused function. Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/parallels/parallels_driver.c | 5 +- src/parallels/parallels_sdk.c | 779 ++++++++++++++++++++++++++++++++++++++- src/parallels/parallels_sdk.h | 2 + src/parallels/parallels_utils.h | 1 + 4 files changed, 781 insertions(+), 6 deletions(-) diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c index fac1f8e..ac192a0 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -1284,16 +1284,13 @@ parallelsDomainGetState(virDomainPtr domain, static char * parallelsDomainGetXMLDesc(virDomainPtr domain, unsigned int flags) { - parallelsConnPtr privconn = domain->conn->privateData; virDomainDefPtr def; virDomainObjPtr privdom; char *ret = NULL; /* Flags checked by virDomainDefFormat */ - parallelsDriverLock(privconn); - privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid); - parallelsDriverUnlock(privconn); + privdom = prlsdkDomainObjLookupByUUID(domain->conn, domain->uuid); if (privdom == NULL) { parallelsDomNotFoundError(domain); diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index 111c52a..ba9d226 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -25,12 +25,17 @@ #include "virerror.h" #include "viralloc.h" #include "datatypes.h" +#include "virstring.h" +#include "nodeinfo.h" +#include "virlog.h" #include "parallels_sdk.h" #define VIR_FROM_THIS VIR_FROM_PARALLELS #define JOB_INFINIT_WAIT_TIMEOUT UINT_MAX +VIR_LOG_INIT("parallels.sdk"); + PRL_UINT32 defaultJobTimeout = JOB_INFINIT_WAIT_TIMEOUT; /* @@ -475,8 +480,8 @@ prlsdkListAllDomains(virConnectPtr conn, return j; error: - for (j = i - 1; j <= 0; j--) - virDomainFree(domPtrArray[j]); + for (i = j - 1; i <= 0; i--) + virDomainFree(domPtrArray[i]); VIR_FREE(domPtrArray); PrlHandle_Free(result); PrlHandle_Free(job); @@ -565,3 +570,773 @@ prlsdkDomainLookupByName(virConnectPtr conn, const char *name) PrlHandle_Free(sdkdom); return dom; } + +static void +prlsdkDomObjFreePrivate(void *p) +{ + parallelsDomObjPtr pdom = p; + + if (!pdom) + return; + + PrlHandle_Free(pdom->sdkdom); + virBitmapFree(pdom->cpumask); + VIR_FREE(pdom->uuid); + VIR_FREE(pdom->home); + VIR_FREE(p); +}; + + +static int +prlsdkAddDomainVideoInfo(PRL_HANDLE sdkdom, virDomainDefPtr def) +{ + virDomainVideoDefPtr video = NULL; + virDomainVideoAccelDefPtr accel = NULL; + PRL_RESULT ret; + PRL_UINT32 videoRam; + + /* video info */ + ret = PrlVmCfg_GetVideoRamSize(sdkdom, &videoRam); + prlsdkCheckRetGoto(ret, error); + + if (VIR_ALLOC(video) < 0) + goto error; + + if (VIR_ALLOC(accel) < 0) + goto error; + + if (VIR_APPEND_ELEMENT_COPY(def->videos, def->nvideos, video) < 0) + goto error; + + video->type = VIR_DOMAIN_VIDEO_TYPE_VGA; + video->vram = videoRam << 10; /* from mbibytes to kbibytes */ + video->heads = 1; + video->accel = accel; + + return 0; + + error: + VIR_FREE(accel); + virDomainVideoDefFree(video); + return -1; +} + +static int +prlsdkGetHddInfo(PRL_HANDLE hdd, + virDomainDiskDefPtr disk) +{ + char *buf = NULL; + PRL_UINT32 buflen = 0; + PRL_RESULT pret; + PRL_UINT32 emulatedType; + PRL_UINT32 ifType; + PRL_UINT32 pos; + PRL_UINT32 hddIndex; + int ret = -1; + + pret = PrlVmDev_GetEmulatedType(hdd, &emulatedType); + prlsdkCheckRetGoto(pret, cleanup); + if (emulatedType == PDT_USE_IMAGE_FILE) { + virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); + virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_PLOOP); + } else { + virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK); + } + + pret = PrlVmDev_GetFriendlyName(hdd, NULL, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (VIR_ALLOC_N(buf, buflen) < 0) + goto cleanup; + + pret = PrlVmDev_GetFriendlyName(hdd, buf, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (virDomainDiskSetSource(disk, buf) < 0) + goto cleanup; + + pret = PrlVmDev_GetIfaceType(hdd, &ifType); + prlsdkCheckRetGoto(pret, cleanup); + switch (ifType) { + case PMS_IDE_DEVICE: + disk->bus = VIR_DOMAIN_DISK_BUS_IDE; + break; + case PMS_SCSI_DEVICE: + disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; + break; + case PMS_SATA_DEVICE: + disk->bus = VIR_DOMAIN_DISK_BUS_SATA; + break; + default: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown disk bus: %X"), ifType); + goto cleanup; + break; + } + + pret = PrlVmDev_GetStackIndex(hdd, &pos); + prlsdkCheckRetGoto(pret, cleanup); + + disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE; + disk->info.addr.drive.target = pos; + + pret = PrlVmDev_GetIndex(hdd, &hddIndex); + prlsdkCheckRetGoto(pret, cleanup); + + if (!(disk->dst = virIndexToDiskName(hddIndex, "sd"))) + goto cleanup; + + ret = 0; + + cleanup: + VIR_FREE(buf); + return ret; +} + +static int +prlsdkAddDomainHardDisksInfo(PRL_HANDLE sdkdom, virDomainDefPtr def) +{ + PRL_RESULT pret; + PRL_UINT32 hddCount; + PRL_UINT32 i; + PRL_HANDLE hdd = PRL_INVALID_HANDLE; + virDomainDiskDefPtr disk = NULL; + + pret = PrlVmCfg_GetHardDisksCount(sdkdom, &hddCount); + prlsdkCheckRetGoto(pret, error); + + for (i = 0; i < hddCount; ++i) { + pret = PrlVmCfg_GetHardDisk(sdkdom, i, &hdd); + prlsdkCheckRetGoto(pret, error); + + if (IS_CT(def)) { + /* TODO: convert info about disks in container + * to virDomainFSDef structs */ + VIR_WARN("Skipping disk information for container"); + + PrlHandle_Free(hdd); + hdd = PRL_INVALID_HANDLE; + } else { + if (!(disk = virDomainDiskDefNew())) + goto error; + + if (prlsdkGetHddInfo(hdd, disk) < 0) + goto error; + + PrlHandle_Free(hdd); + hdd = PRL_INVALID_HANDLE; + + if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0) + goto error; + } + } + + return 0; + + error: + PrlHandle_Free(hdd); + virDomainDiskDefFree(disk); + return -1; +} + +static int +prlsdkGetNetInfo(PRL_HANDLE netAdapter, virDomainNetDefPtr net, bool isCt) +{ + char macstr[VIR_MAC_STRING_BUFLEN]; + PRL_UINT32 buflen; + PRL_UINT32 netAdapterIndex; + PRL_UINT32 emulatedType; + PRL_RESULT pret; + PRL_BOOL isConnected; + int ret = -1; + + net->type = VIR_DOMAIN_NET_TYPE_NETWORK; + + + /* use device name, shown by prlctl as target device + * for identifying network adapter in virDomainDefineXML */ + pret = PrlVmDev_GetIndex(netAdapter, &netAdapterIndex); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDevNet_GetHostInterfaceName(netAdapter, NULL, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (VIR_ALLOC_N(net->ifname, buflen) < 0) + goto cleanup; + + pret = PrlVmDevNet_GetHostInterfaceName(netAdapter, net->ifname, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (isCt && netAdapterIndex == (PRL_UINT32) -1) { + /* venet devices don't have mac address and + * always up */ + net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP; + if (VIR_STRDUP(net->data.network.name, + PARALLELS_ROUTED_NETWORK_NAME) < 0) + goto cleanup; + return 0; + } + + buflen = ARRAY_CARDINALITY(macstr); + if (VIR_ALLOC_N(macstr, buflen)) + goto cleanup; + pret = PrlVmDevNet_GetMacAddressCanonical(netAdapter, macstr, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (virMacAddrParse(macstr, &net->mac) < 0) + goto cleanup; + + pret = PrlVmDev_GetEmulatedType(netAdapter, &emulatedType); + prlsdkCheckRetGoto(pret, cleanup); + + if (emulatedType == PNA_ROUTED) { + if (VIR_STRDUP(net->data.network.name, + PARALLELS_ROUTED_NETWORK_NAME) < 0) + goto cleanup; + } else { + pret = PrlVmDevNet_GetVirtualNetworkId(netAdapter, NULL, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (VIR_ALLOC_N(net->data.network.name, buflen) < 0) + goto cleanup; + + pret = PrlVmDevNet_GetVirtualNetworkId(netAdapter, + net->data.network.name, + &buflen); + prlsdkCheckRetGoto(pret, cleanup); + } + + pret = PrlVmDev_IsConnected(netAdapter, &isConnected); + prlsdkCheckRetGoto(pret, cleanup); + + if (isConnected) + net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP; + else + net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN; + + ret = 0; + cleanup: + return ret; +} + +static int +prlsdkAddDomainNetInfo(PRL_HANDLE sdkdom, virDomainDefPtr def) +{ + virDomainNetDefPtr net = NULL; + PRL_RESULT ret; + PRL_HANDLE netAdapter; + PRL_UINT32 netAdaptersCount; + PRL_UINT32 i; + + ret = PrlVmCfg_GetNetAdaptersCount(sdkdom, &netAdaptersCount); + prlsdkCheckRetGoto(ret, error); + for (i = 0; i < netAdaptersCount; ++i) { + ret = PrlVmCfg_GetNetAdapter(sdkdom, i, &netAdapter); + prlsdkCheckRetGoto(ret, error); + + if (VIR_ALLOC(net) < 0) + goto error; + + if (prlsdkGetNetInfo(netAdapter, net, IS_CT(def)) < 0) + goto error; + + PrlHandle_Free(netAdapter); + netAdapter = PRL_INVALID_HANDLE; + + if (VIR_APPEND_ELEMENT(def->nets, def->nnets, net) < 0) + goto error; + } + + return 0; + + error: + PrlHandle_Free(netAdapter); + virDomainNetDefFree(net); + return -1; +} + +static int +prlsdkGetSerialInfo(PRL_HANDLE serialPort, virDomainChrDefPtr chr) +{ + PRL_RESULT pret; + PRL_UINT32 serialPortIndex; + PRL_UINT32 emulatedType; + char *friendlyName = NULL; + PRL_UINT32 buflen; + + chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL; + chr->targetTypeAttr = false; + pret = PrlVmDev_GetIndex(serialPort, &serialPortIndex); + prlsdkCheckRetGoto(pret, error); + chr->target.port = serialPortIndex; + + pret = PrlVmDev_GetEmulatedType(serialPort, &emulatedType); + prlsdkCheckRetGoto(pret, error); + + pret = PrlVmDev_GetFriendlyName(serialPort, NULL, &buflen); + prlsdkCheckRetGoto(pret, error); + + if (VIR_ALLOC_N(friendlyName, buflen) < 0) + goto error; + + pret = PrlVmDev_GetFriendlyName(serialPort, friendlyName, &buflen); + prlsdkCheckRetGoto(pret, error); + + switch (emulatedType) { + case PDT_USE_OUTPUT_FILE: + chr->source.type = VIR_DOMAIN_CHR_TYPE_FILE; + chr->source.data.file.path = friendlyName; + break; + case PDT_USE_SERIAL_PORT_SOCKET_MODE: + chr->source.type = VIR_DOMAIN_CHR_TYPE_UNIX; + chr->source.data.nix.path = friendlyName; + break; + case PDT_USE_REAL_DEVICE: + chr->source.type = VIR_DOMAIN_CHR_TYPE_DEV; + chr->source.data.file.path = friendlyName; + break; + default: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown serial type: %X"), emulatedType); + goto error; + break; + } + + return 0; + error: + VIR_FREE(friendlyName); + return -1; +} + + +static int +prlsdkAddSerialInfo(PRL_HANDLE sdkdom, + virDomainChrDefPtr **serials, + size_t *nserials) +{ + PRL_RESULT ret; + PRL_HANDLE serialPort; + PRL_UINT32 serialPortsCount; + PRL_UINT32 i; + virDomainChrDefPtr chr = NULL; + + ret = PrlVmCfg_GetSerialPortsCount(sdkdom, &serialPortsCount); + prlsdkCheckRetGoto(ret, cleanup); + for (i = 0; i < serialPortsCount; ++i) { + ret = PrlVmCfg_GetSerialPort(sdkdom, i, &serialPort); + prlsdkCheckRetGoto(ret, cleanup); + + if (!(chr = virDomainChrDefNew())) + goto cleanup; + + if (prlsdkGetSerialInfo(serialPort, chr)) + goto cleanup; + + PrlHandle_Free(serialPort); + serialPort = PRL_INVALID_HANDLE; + + if (VIR_APPEND_ELEMENT(*serials, *nserials, chr) < 0) + goto cleanup; + } + + return 0; + + cleanup: + PrlHandle_Free(serialPort); + virDomainChrDefFree(chr); + return -1; +} + + +static int +prlsdkAddDomainHardware(PRL_HANDLE sdkdom, virDomainDefPtr def) +{ + if (!IS_CT(def)) + if (prlsdkAddDomainVideoInfo(sdkdom, def) < 0) + goto error; + + if (prlsdkAddDomainHardDisksInfo(sdkdom, def) < 0) + goto error; + + if (prlsdkAddDomainNetInfo(sdkdom, def) < 0) + goto error; + + if (prlsdkAddSerialInfo(sdkdom, + &def->serials, + &def->nserials) < 0) + goto error; + + return 0; + error: + return -1; +} + + +static int +prlsdkAddVNCInfo(PRL_HANDLE sdkdom, virDomainDefPtr def) +{ + virDomainGraphicsDefPtr gr = NULL; + PRL_VM_REMOTE_DISPLAY_MODE vncMode; + PRL_UINT32 port; + PRL_UINT32 buflen = 0; + PRL_RESULT pret; + + pret = PrlVmCfg_GetVNCMode(sdkdom, &vncMode); + prlsdkCheckRetGoto(pret, error); + + if (vncMode == PRD_DISABLED) + return 0; + + if (VIR_ALLOC(gr) < 0) + goto error; + + pret = PrlVmCfg_GetVNCPort(sdkdom, &port); + prlsdkCheckRetGoto(pret, error); + + gr->data.vnc.autoport = (vncMode == PRD_AUTO); + gr->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC; + gr->data.vnc.port = port; + gr->data.vnc.keymap = NULL; + gr->data.vnc.socket = NULL; + gr->data.vnc.auth.passwd = NULL; + gr->data.vnc.auth.expires = false; + gr->data.vnc.auth.connected = 0; + + if (VIR_ALLOC(gr->listens) < 0) + goto error; + + gr->nListens = 1; + + pret = PrlVmCfg_GetVNCHostName(sdkdom, NULL, &buflen); + prlsdkCheckRetGoto(pret, error); + + if (VIR_ALLOC_N(gr->listens[0].address, buflen) < 0) + goto error; + + pret = PrlVmCfg_GetVNCHostName(sdkdom, gr->listens[0].address, &buflen); + prlsdkCheckRetGoto(pret, error); + + gr->listens[0].type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS; + + if (VIR_APPEND_ELEMENT(def->graphics, def->ngraphics, gr) < 0) + goto error; + + return 0; + + error: + virDomainGraphicsDefFree(gr); + return -1; +} + +static int +prlsdkConvertDomainState(parallelsConnPtr privconn, + PRL_HANDLE sdkdom, + PRL_UINT32 envId, + virDomainObjPtr dom) +{ + VIRTUAL_MACHINE_STATE domainState; + + if (prlsdkGetDomainState(privconn, sdkdom, &domainState) < 0) + return -1; + + switch (domainState) { + case VMS_STOPPED: + case VMS_MOUNTED: + virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF, + VIR_DOMAIN_SHUTOFF_SHUTDOWN); + dom->def->id = -1; + break; + case VMS_STARTING: + case VMS_COMPACTING: + case VMS_RESETTING: + case VMS_PAUSING: + case VMS_RECONNECTING: + case VMS_RUNNING: + virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, + VIR_DOMAIN_RUNNING_BOOTED); + dom->def->id = envId; + break; + case VMS_PAUSED: + virDomainObjSetState(dom, VIR_DOMAIN_PAUSED, + VIR_DOMAIN_PAUSED_USER); + dom->def->id = envId; + break; + case VMS_SUSPENDED: + case VMS_DELETING_STATE: + case VMS_SUSPENDING_SYNC: + virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF, + VIR_DOMAIN_SHUTOFF_SAVED); + dom->def->id = -1; + break; + case VMS_STOPPING: + virDomainObjSetState(dom, VIR_DOMAIN_SHUTDOWN, + VIR_DOMAIN_SHUTDOWN_USER); + dom->def->id = envId; + break; + case VMS_SNAPSHOTING: + virDomainObjSetState(dom, VIR_DOMAIN_PAUSED, + VIR_DOMAIN_PAUSED_SNAPSHOT); + dom->def->id = envId; + break; + case VMS_MIGRATING: + virDomainObjSetState(dom, VIR_DOMAIN_PAUSED, + VIR_DOMAIN_PAUSED_MIGRATION); + dom->def->id = envId; + break; + case VMS_SUSPENDING: + virDomainObjSetState(dom, VIR_DOMAIN_PAUSED, + VIR_DOMAIN_PAUSED_SAVE); + dom->def->id = envId; + break; + case VMS_RESTORING: + virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, + VIR_DOMAIN_RUNNING_RESTORED); + dom->def->id = envId; + break; + case VMS_CONTINUING: + virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, + VIR_DOMAIN_RUNNING_UNPAUSED); + dom->def->id = envId; + break; + case VMS_RESUMING: + virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, + VIR_DOMAIN_RUNNING_RESTORED); + dom->def->id = envId; + break; + case VMS_UNKNOWN: + virDomainObjSetState(dom, VIR_DOMAIN_NOSTATE, + VIR_DOMAIN_NOSTATE_UNKNOWN); + break; + default: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown domain state: %X"), domainState); + return -1; + break; + } + + return 0; +} + +static int +prlsdkConvertCpuMask(PRL_HANDLE sdkdom, parallelsDomObjPtr pdom) +{ + char *buf; + PRL_UINT32 buflen = 0; + int hostcpus; + PRL_RESULT pret; + int ret = -1; + + pret = PrlVmCfg_GetCpuMask(sdkdom, NULL, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (VIR_ALLOC_N(buf, buflen) < 0) + goto cleanup; + + pret = PrlVmCfg_GetCpuMask(sdkdom, buf, &buflen); + + if ((hostcpus = nodeGetCPUCount()) < 0) + goto cleanup; + + if (strlen(buf) == 0) { + if (!(pdom->cpumask = virBitmapNew(hostcpus))) + goto cleanup; + virBitmapSetAll(pdom->cpumask); + } else { + if (virBitmapParse(buf, 0, &pdom->cpumask, hostcpus) < 0) + goto cleanup; + } + + ret = 0; + cleanup: + VIR_FREE(buf); + return ret; +} + +static int +prlsdkConvertDomainType(PRL_HANDLE sdkdom, virDomainDefPtr def) +{ + PRL_VM_TYPE domainType; + PRL_RESULT pret; + + pret = PrlVmCfg_GetVmType(sdkdom, &domainType); + prlsdkCheckRetGoto(pret, error); + + switch (domainType) { + case PVT_VM: + if (VIR_STRDUP(def->os.type, "hvm") < 0) + return -1; + break; + case PVT_CT: + if (VIR_STRDUP(def->os.type, "exe") < 0) + return -1; + if (VIR_STRDUP(def->os.init, "/sbin/init") < 0) + return -1; + break; + default: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown domain type: %X"), domainType); + return -1; + } + + return 0; + + error: + return -1; +} + +static int +prlsdkConvertCpuMode(PRL_HANDLE sdkdom, virDomainDefPtr def) +{ + PRL_RESULT pret; + PRL_CPU_MODE cpuMode; + + pret = PrlVmCfg_GetCpuMode(sdkdom, &cpuMode); + prlsdkCheckRetGoto(pret, error); + + switch (cpuMode) { + case PCM_CPU_MODE_32: + def->os.arch = VIR_ARCH_I686; + break; + case VIR_ARCH_X86_64: + def->os.arch = VIR_ARCH_X86_64; + break; + default: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown CPU mode: %X"), cpuMode); + return -1; + } + + return 0; + error: + return -1; +} + +static virDomainObjPtr +prlsdkCreateDomainObj(parallelsConnPtr privconn, PRL_HANDLE sdkdom) +{ + virDomainObjPtr dom = NULL; + virDomainDefPtr def = NULL; + parallelsDomObjPtr pdom = NULL; + + PRL_UINT32 buflen = 0; + PRL_RESULT pret; + PRL_UINT32 cpuCount; + PRL_UINT32 ram; + PRL_UINT32 envId; + PRL_VM_AUTOSTART_OPTION autostart; + + virCheckNonNullArgGoto(privconn, cleanup); + virCheckNonNullArgGoto(sdkdom, cleanup); + + if (VIR_ALLOC(def) < 0) + goto cleanup; + + if (VIR_ALLOC(pdom) < 0) + goto cleanup; + + def->virtType = VIR_DOMAIN_VIRT_PARALLELS; + def->id = -1; + + /* we will remove this field in the near future, so let's set it + * to NULL temporarily */ + pdom->uuid = NULL; + + if (prlsdkGetDomainIds(sdkdom, &def->name, def->uuid) < 0) + goto cleanup; + + /* get number of CPUs */ + pret = PrlVmCfg_GetCpuCount(sdkdom, &cpuCount); + prlsdkCheckRetGoto(pret, cleanup); + def->vcpus = cpuCount; + def->maxvcpus = cpuCount; + + /* get RAM parameters */ + pret = PrlVmCfg_GetRamSize(sdkdom, &ram); + prlsdkCheckRetGoto(pret, cleanup); + def->mem.max_balloon = ram << 10; /* RAM size obtained in Mbytes, + convert to Kbytes */ + def->mem.cur_balloon = def->mem.max_balloon; + + if (prlsdkConvertCpuMask(sdkdom, pdom) < 0) + goto cleanup; + + if (prlsdkConvertCpuMode(sdkdom, def) < 0) + goto cleanup; + + if (prlsdkConvertDomainType(sdkdom, def) < 0) + goto cleanup; + + if (prlsdkAddDomainHardware(sdkdom, def) < 0) + goto cleanup; + + if (prlsdkAddVNCInfo(sdkdom, def) < 0) + goto cleanup; + + pret = PrlVmCfg_GetEnvId(sdkdom, &envId); + prlsdkCheckRetGoto(pret, cleanup); + pdom->id = envId; + + buflen = 0; + pret = PrlVmCfg_GetHomePath(sdkdom, NULL, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (VIR_ALLOC_N(pdom->home, buflen) < 0) + goto cleanup; + + pret = PrlVmCfg_GetHomePath(sdkdom, pdom->home, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (!(dom = virDomainObjNew(privconn->xmlopt))) + goto cleanup; + + dom->def = def; + dom->privateData = pdom; + dom->privateDataFreeFunc = prlsdkDomObjFreePrivate; + dom->persistent = 1; + + if (prlsdkConvertDomainState(privconn, sdkdom, envId, dom) < 0) + goto cleanup; + + pret = PrlVmCfg_GetAutoStart(sdkdom, &autostart); + prlsdkCheckRetGoto(pret, cleanup); + + switch (autostart) { + case PAO_VM_START_ON_LOAD: + dom->autostart = 1; + break; + case PAO_VM_START_MANUAL: + dom->autostart = 0; + break; + default: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown autostart mode: %X"), autostart); + goto cleanup; + } + + pret = PrlHandle_AddRef(sdkdom); + prlsdkCheckRetGoto(pret, cleanup); + pdom->sdkdom = sdkdom; + /* dom is locked here */ + + return dom; + cleanup: + virDomainDefFree(def); + prlsdkDomObjFreePrivate(pdom); + return NULL; +} + +virDomainObjPtr +prlsdkDomainObjLookupByUUID(virConnectPtr conn, const unsigned char *uuid) +{ + PRL_HANDLE sdkdom; + virDomainObjPtr dom = NULL; + + sdkdom = prlsdkSdkDomainLookupByUUID(conn, uuid); + if (sdkdom == PRL_INVALID_HANDLE) + return NULL; + + dom = prlsdkCreateDomainObj(conn->privateData, sdkdom); + PrlHandle_Free(sdkdom); + + return dom; +} diff --git a/src/parallels/parallels_sdk.h b/src/parallels/parallels_sdk.h index 16df5f2..30c6c21 100644 --- a/src/parallels/parallels_sdk.h +++ b/src/parallels/parallels_sdk.h @@ -35,3 +35,5 @@ virDomainPtr prlsdkDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid); virDomainPtr prlsdkDomainLookupByName(virConnectPtr conn, const char *name); +virDomainObjPtr +prlsdkDomainObjLookupByUUID(virConnectPtr conn, const unsigned char *uuid); diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h index 269020a..95206d6 100644 --- a/src/parallels/parallels_utils.h +++ b/src/parallels/parallels_utils.h @@ -61,6 +61,7 @@ struct parallelsDomObj { char *uuid; char *home; virBitmapPtr cpumask; + PRL_HANDLE sdkdom; }; typedef struct parallelsDomObj *parallelsDomObjPtr; -- 1.9.3

Implement functions, which change domain state with SDK. We have to keep stored domains list up-to-date, so update domain info after calling prlsdkDomain*. When we remove cached domain list, we can remove functions parallelsDomain*, because they will be just calling corresponding functions from parallels_sdk.c Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/parallels/parallels_driver.c | 114 +++++++-------------------------------- src/parallels/parallels_sdk.c | 88 ++++++++++++++++++++++++++++++ src/parallels/parallels_sdk.h | 5 ++ 3 files changed, 113 insertions(+), 94 deletions(-) diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c index ac192a0..bbed9dc 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -1333,118 +1333,44 @@ parallelsDomainGetAutostart(virDomainPtr domain, int *autostart) return ret; } -typedef int (*parallelsChangeStateFunc)(virDomainObjPtr privdom); -#define PARALLELS_UUID(x) (((parallelsDomObjPtr)(x->privateData))->uuid) - -static int -parallelsDomainChangeState(virDomainPtr domain, - virDomainState req_state, const char *req_state_name, - parallelsChangeStateFunc chstate, - virDomainState new_state, int reason) +int parallelsDomainSuspend(virDomainPtr domain) { - parallelsConnPtr privconn = domain->conn->privateData; - virDomainObjPtr privdom; - int state; - int ret = -1; - - parallelsDriverLock(privconn); - privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid); - parallelsDriverUnlock(privconn); - - if (privdom == NULL) { - parallelsDomNotFoundError(domain); - goto cleanup; - } - - state = virDomainObjGetState(privdom, NULL); - if (state != req_state) { - virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not %s"), - privdom->def->name, req_state_name); - goto cleanup; - } - - if (chstate(privdom)) - goto cleanup; - - virDomainObjSetState(privdom, new_state, reason); - - ret = 0; - - cleanup: - if (privdom) - virObjectUnlock(privdom); + if (prlsdkDomainSuspend(domain) < 0) + return -1; - return ret; + return parallelsLoadDomains(domain->conn->privateData, domain->name); } -static int parallelsPause(virDomainObjPtr privdom) +int parallelsDomainResume(virDomainPtr domain) { - return parallelsCmdRun(PRLCTL, "pause", PARALLELS_UUID(privdom), NULL); -} - -static int -parallelsDomainSuspend(virDomainPtr domain) -{ - return parallelsDomainChangeState(domain, - VIR_DOMAIN_RUNNING, "running", - parallelsPause, - VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER); -} - -static int parallelsResume(virDomainObjPtr privdom) -{ - return parallelsCmdRun(PRLCTL, "resume", PARALLELS_UUID(privdom), NULL); -} + if (prlsdkDomainResume(domain) < 0) + return -1; -static int -parallelsDomainResume(virDomainPtr domain) -{ - return parallelsDomainChangeState(domain, - VIR_DOMAIN_PAUSED, "paused", - parallelsResume, - VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNPAUSED); + return parallelsLoadDomains(domain->conn->privateData, domain->name); } -static int parallelsStart(virDomainObjPtr privdom) +int parallelsDomainCreate(virDomainPtr domain) { - return parallelsCmdRun(PRLCTL, "start", PARALLELS_UUID(privdom), NULL); -} + if (prlsdkDomainCreate(domain) < 0) + return -1; -static int -parallelsDomainCreate(virDomainPtr domain) -{ - return parallelsDomainChangeState(domain, - VIR_DOMAIN_SHUTOFF, "stopped", - parallelsStart, - VIR_DOMAIN_RUNNING, VIR_DOMAIN_EVENT_STARTED_BOOTED); + return parallelsLoadDomains(domain->conn->privateData, domain->name); } -static int parallelsKill(virDomainObjPtr privdom) +int parallelsDomainDestroy(virDomainPtr domain) { - return parallelsCmdRun(PRLCTL, "stop", PARALLELS_UUID(privdom), "--kill", NULL); -} + if (prlsdkDomainDestroy(domain) < 0) + return -1; -static int -parallelsDomainDestroy(virDomainPtr domain) -{ - return parallelsDomainChangeState(domain, - VIR_DOMAIN_RUNNING, "running", - parallelsKill, - VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_DESTROYED); + return parallelsLoadDomains(domain->conn->privateData, domain->name); } -static int parallelsStop(virDomainObjPtr privdom) +int parallelsDomainShutdown(virDomainPtr domain) { - return parallelsCmdRun(PRLCTL, "stop", PARALLELS_UUID(privdom), NULL); -} + if (prlsdkDomainShutdown(domain) < 0) + return -1; -static int -parallelsDomainShutdown(virDomainPtr domain) -{ - return parallelsDomainChangeState(domain, - VIR_DOMAIN_RUNNING, "running", - parallelsStop, - VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + return parallelsLoadDomains(domain->conn->privateData, domain->name); } static int diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index ba9d226..8d22da3 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -1340,3 +1340,91 @@ prlsdkDomainObjLookupByUUID(virConnectPtr conn, const unsigned char *uuid) return dom; } + +static int prlsdkStart(parallelsConnPtr privconn, PRL_HANDLE sdkdom) +{ + PRL_HANDLE job = PRL_INVALID_HANDLE; + + job = PrlVm_StartEx(sdkdom, PSM_VM_START, 0); + return waitJob(job, privconn->jobTimeout); +} + +static int prlsdkStopEx(parallelsConnPtr privconn, + PRL_HANDLE sdkdom, + PRL_UINT32 mode) +{ + PRL_HANDLE job = PRL_INVALID_HANDLE; + + job = PrlVm_StopEx(sdkdom, mode, 0); + return waitJob(job, privconn->jobTimeout); +} + +static int prlsdkKill(parallelsConnPtr privconn, PRL_HANDLE sdkdom) +{ + return prlsdkStopEx(privconn, sdkdom, PSM_KILL); +} + +static int prlsdkStop(parallelsConnPtr privconn, PRL_HANDLE sdkdom) +{ + return prlsdkStopEx(privconn, sdkdom, PSM_SHUTDOWN); +} + +static int prlsdkPause(parallelsConnPtr privconn, PRL_HANDLE sdkdom) +{ + PRL_HANDLE job = PRL_INVALID_HANDLE; + + job = PrlVm_Pause(sdkdom, false); + return waitJob(job, privconn->jobTimeout); +} + +static int prlsdkResume(parallelsConnPtr privconn, PRL_HANDLE sdkdom) +{ + PRL_HANDLE job = PRL_INVALID_HANDLE; + + job = PrlVm_Resume(sdkdom); + return waitJob(job, privconn->jobTimeout); +} + +typedef int (*prlsdkChangeStateFunc)(parallelsConnPtr privconn, PRL_HANDLE sdkdom); + +static int +prlsdkDomainChangeState(virDomainPtr domain, + prlsdkChangeStateFunc chstate) +{ + parallelsConnPtr privconn = domain->conn->privateData; + PRL_HANDLE sdkdom = PRL_INVALID_HANDLE; + int ret = -1; + + sdkdom = prlsdkSdkDomainLookupByUUID(domain->conn, domain->uuid); + if (sdkdom == PRL_INVALID_HANDLE) + return -1; + + ret = chstate(privconn, sdkdom); + PrlHandle_Free(sdkdom); + return ret; +} + +int prlsdkDomainSuspend(virDomainPtr domain) +{ + return prlsdkDomainChangeState(domain, prlsdkPause); +} + +int prlsdkDomainResume(virDomainPtr domain) +{ + return prlsdkDomainChangeState(domain, prlsdkResume); +} + +int prlsdkDomainCreate(virDomainPtr domain) +{ + return prlsdkDomainChangeState(domain, prlsdkStart); +} + +int prlsdkDomainDestroy(virDomainPtr domain) +{ + return prlsdkDomainChangeState(domain, prlsdkKill); +} + +int prlsdkDomainShutdown(virDomainPtr domain) +{ + return prlsdkDomainChangeState(domain, prlsdkStop); +} diff --git a/src/parallels/parallels_sdk.h b/src/parallels/parallels_sdk.h index 30c6c21..b02565b 100644 --- a/src/parallels/parallels_sdk.h +++ b/src/parallels/parallels_sdk.h @@ -37,3 +37,8 @@ virDomainPtr prlsdkDomainLookupByName(virConnectPtr conn, const char *name); virDomainObjPtr prlsdkDomainObjLookupByUUID(virConnectPtr conn, const unsigned char *uuid); +int prlsdkDomainSuspend(virDomainPtr domain); +int prlsdkDomainResume(virDomainPtr domain); +int prlsdkDomainCreate(virDomainPtr domain); +int prlsdkDomainDestroy(virDomainPtr domain); +int prlsdkDomainShutdown(virDomainPtr domain); -- 1.9.3

On Tuesday 14 October 2014 18:23:31 you wrote:
This patch series replaces a series of functions, which retieve different domains info and modifies domains state with new ones, which use parallels sdk instead of executing prlctl command.
These functions don't use cached domains list _parallelsConn.domains, so when we rewrite all code, we will be able to remove it.
Hello, We have decided to keep the list of domains parallelsConn.domains. To keep it up-to-date we subscribe to events from PCS and modify it when events about new, removed or changed domains occur. It's better because first, the file parallels_driver.c will be similar to corresponding files in other drivers, so it'll be easier to maintain it, second, it will be faster, because requesting domain info from PCS takes some time, and also it needs less modifications of current code. So, please, don't review these patches, I've already implemented this new approach and will send it today or tomorrow.
Alexander Burluka (1): parallels: obtain domain info with SDK
Dmitry Guryanov (4): parallels: list domains with parallels SDK parallels: implement lookup functions with SDK parallels: move IS_CT macro to parallels_utils.h parallels: change domains state with SDK
src/parallels/parallels_driver.c | 178 +----- src/parallels/parallels_sdk.c | 1189 ++++++++++++++++++++++++++++++++++++++
src/parallels/parallels_sdk.h |
14 + src/parallels/parallels_utils.h | 3 + 4 files changed, 1230 insertions(+), 154 deletions(-)
-- Dmitry Guryanov

On Wed, Oct 22, 2014 at 01:31:41PM +0400, Dmitry Guryanov wrote:
On Tuesday 14 October 2014 18:23:31 you wrote:
This patch series replaces a series of functions, which retieve different domains info and modifies domains state with new ones, which use parallels sdk instead of executing prlctl command.
These functions don't use cached domains list _parallelsConn.domains, so when we rewrite all code, we will be able to remove it.
Hello,
We have decided to keep the list of domains parallelsConn.domains. To keep it up-to-date we subscribe to events from PCS and modify it when events about new, removed or changed domains occur.
It's better because first, the file parallels_driver.c will be similar to corresponding files in other drivers, so it'll be easier to maintain it, second, it will be faster, because requesting domain info from PCS takes some time, and also it needs less modifications of current code.
So, please, don't review these patches, I've already implemented this new approach and will send it today or tomorrow.
That sounds good - listening to events from PCS is also beneficial because it will let you support the libvirt domain lifecycle event API, so that mgmt apps using libvirt can get notifications of VMs changing state. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (2)
-
Daniel P. Berrange
-
Dmitry Guryanov