Use SDK to return a list of domains in parallelsConnectListAllDomains function instead of prlctl. Signed-off-by: Dmitry Guryanov <dguryanov@xxxxxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list