[libvirt] [PATCH 4/5] parallels: obtain domain info with SDK

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


From: Alexander Burluka <aburluka at 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 at 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




More information about the libvir-list mailing list