Use SDK to return a list of domains in
parallelsConnectListAllDomains function instead of prlctl.
Signed-off-by: Dmitry Guryanov <dguryanov(a)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