[libvirt] [PATCH 1/5] parallels: list domains with parallels SDK

Dmitry Guryanov dguryanov at parallels.com
Tue Oct 14 14:23:32 UTC 2014


Use SDK to return a list of domains in
parallelsConnectListAllDomains function instead of prlctl.

Signed-off-by: Dmitry Guryanov <dguryanov at 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, &paramsCount);
+    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




More information about the libvir-list mailing list