From: Alexander Burluka <aburl...@parallels.com>

Obtain information about domains using parallels sdk
instead of prlctl. prlsdkLoadDomains functions behaves
as former parallelsLoadDomains with NULL as second
parameter (name) - it fills parallelsConn.domains list.

prlsdkLoadDomain is now able to update specified domain
by given virDomainObjPtr.

Signed-off-by: Dmitry Guryanov <dgurya...@parallels.com>
---
 src/parallels/parallels_driver.c |  747 +---------------------------
 src/parallels/parallels_sdk.c    | 1008 ++++++++++++++++++++++++++++++++++++++
 src/parallels/parallels_sdk.h    |    4 +
 src/parallels/parallels_utils.h  |    1 +
 4 files changed, 1019 insertions(+), 741 deletions(-)

diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index 0085c8f..8db4997 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -49,7 +49,6 @@
 #include "virfile.h"
 #include "virstoragefile.h"
 #include "nodeinfo.h"
-#include "c-ctype.h"
 #include "virstring.h"
 #include "cpu/cpu.h"
 
@@ -99,21 +98,6 @@ parallelsDriverUnlock(parallelsConnPtr driver)
     virMutexUnlock(&driver->lock);
 }
 
-
-static void
-parallelsDomObjFreePrivate(void *p)
-{
-    parallelsDomObjPtr pdom = p;
-
-    if (!pdom)
-        return;
-
-    virBitmapFree(pdom->cpumask);
-    VIR_FREE(pdom->uuid);
-    VIR_FREE(pdom->home);
-    VIR_FREE(p);
-};
-
 static virCapsPtr
 parallelsBuildCapabilities(void)
 {
@@ -191,729 +175,6 @@ parallelsConnectGetCapabilities(virConnectPtr conn)
 }
 
 static int
-parallelsGetSerialInfo(virDomainChrDefPtr chr,
-                       const char *name, virJSONValuePtr value)
-{
-    const char *tmp;
-
-    chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
-    chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
-    if (virStrToLong_i(name + strlen("serial"),
-                       NULL, 10, &chr->target.port) < 0) {
-        parallelsParseError();
-        return -1;
-    }
-
-    if (virJSONValueObjectHasKey(value, "output")) {
-        chr->source.type = VIR_DOMAIN_CHR_TYPE_FILE;
-
-        tmp = virJSONValueObjectGetString(value, "output");
-        if (!tmp) {
-            parallelsParseError();
-            return -1;
-        }
-
-        if (VIR_STRDUP(chr->source.data.file.path, tmp) < 0)
-            return -1;
-    } else if (virJSONValueObjectHasKey(value, "socket")) {
-        chr->source.type = VIR_DOMAIN_CHR_TYPE_UNIX;
-
-        tmp = virJSONValueObjectGetString(value, "socket");
-        if (!tmp) {
-            parallelsParseError();
-            return -1;
-        }
-
-        if (VIR_STRDUP(chr->source.data.nix.path, tmp) < 0)
-            return -1;
-        chr->source.data.nix.listen = false;
-    } else if (virJSONValueObjectHasKey(value, "real")) {
-        chr->source.type = VIR_DOMAIN_CHR_TYPE_DEV;
-
-        tmp = virJSONValueObjectGetString(value, "real");
-        if (!tmp) {
-            parallelsParseError();
-            return -1;
-        }
-
-        if (VIR_STRDUP(chr->source.data.file.path, tmp) < 0)
-            return -1;
-    } else {
-        parallelsParseError();
-        return -1;
-    }
-
-    return 0;
-}
-
-static int
-parallelsAddSerialInfo(virDomainChrDefPtr **serials, size_t *nserials,
-                       const char *key, virJSONValuePtr value)
-{
-    virDomainChrDefPtr chr = NULL;
-
-    if (!(chr = virDomainChrDefNew()))
-        goto cleanup;
-
-    if (parallelsGetSerialInfo(chr, key, value))
-        goto cleanup;
-
-    if (VIR_APPEND_ELEMENT(*serials, *nserials, chr) < 0)
-        goto cleanup;
-
-    return 0;
-
- cleanup:
-    virDomainChrDefFree(chr);
-    return -1;
-}
-
-static int
-parallelsAddVideoInfo(virDomainDefPtr def, virJSONValuePtr value)
-{
-    virDomainVideoDefPtr video = NULL;
-    virDomainVideoAccelDefPtr accel = NULL;
-    const char *tmp;
-    char *endptr;
-    unsigned long mem;
-
-    if (!(tmp = virJSONValueObjectGetString(value, "size"))) {
-        parallelsParseError();
-        goto error;
-    }
-
-    if (virStrToLong_ul(tmp, &endptr, 10, &mem) < 0) {
-        parallelsParseError();
-        goto error;
-    }
-
-    if (!STREQ(endptr, "Mb")) {
-        parallelsParseError();
-        goto 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 = mem << 20;
-    video->heads = 1;
-    video->accel = accel;
-
-    return 0;
-
- error:
-    VIR_FREE(accel);
-    virDomainVideoDefFree(video);
-    return -1;
-}
-
-static int
-parallelsGetHddInfo(virDomainDefPtr def,
-                    virDomainDiskDefPtr disk,
-                    const char *key,
-                    virJSONValuePtr value)
-{
-    const char *tmp;
-    unsigned int idx;
-
-    disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
-
-    if (virJSONValueObjectHasKey(value, "real") == 1) {
-        virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
-
-        if (!(tmp = virJSONValueObjectGetString(value, "real"))) {
-            parallelsParseError();
-            return -1;
-        }
-
-        if (virDomainDiskSetSource(disk, tmp) < 0)
-            return -1;
-    } else {
-        virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
-
-        if (!(tmp = virJSONValueObjectGetString(value, "image"))) {
-            parallelsParseError();
-            return -1;
-        }
-
-        if (virDomainDiskSetSource(disk, tmp) < 0)
-            return -1;
-
-        virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_PLOOP);
-    }
-
-    tmp = virJSONValueObjectGetString(value, "port");
-    if (!tmp && !IS_CT(def)) {
-        parallelsParseError();
-        return -1;
-    }
-
-    if (tmp) {
-        if (STRPREFIX(tmp, "ide")) {
-            disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-        } else if (STRPREFIX(tmp, "sata")) {
-            disk->bus = VIR_DOMAIN_DISK_BUS_SATA;
-        } else if (STRPREFIX(tmp, "scsi")) {
-            disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
-        } else {
-            parallelsParseError();
-            return -1;
-        }
-
-        char *colonp;
-        unsigned int pos;
-
-        if (!(colonp = strchr(tmp, ':'))) {
-            parallelsParseError();
-            return -1;
-        }
-
-        if (virStrToLong_ui(colonp + 1, NULL, 10, &pos) < 0) {
-            parallelsParseError();
-            return -1;
-        }
-
-        disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
-        disk->info.addr.drive.target = pos;
-    } else {
-        /* Actually there are no disk devices in containers, but in
-         * in Parallels Cloud Server we mount disk images as container's
-         * root fs during start, so it looks like a disk device. */
-        disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-    }
-
-    if (virStrToLong_ui(key + strlen("hdd"), NULL, 10, &idx) < 0) {
-        parallelsParseError();
-        return -1;
-    }
-
-    if (!(disk->dst = virIndexToDiskName(idx, "sd")))
-        return -1;
-
-    return 0;
-}
-
-static int
-parallelsAddHddInfo(virDomainDefPtr def, const char *key, virJSONValuePtr 
value)
-{
-    virDomainDiskDefPtr disk = NULL;
-
-    if (!(disk = virDomainDiskDefNew()))
-        goto error;
-
-    if (parallelsGetHddInfo(def, disk, key, value))
-        goto error;
-
-    if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
-        goto error;
-
-    return 0;
-
- error:
-    virDomainDiskDefFree(disk);
-    return -1;
-}
-
-static inline unsigned char hex2int(char c)
-{
-    if (c <= '9')
-        return c - '0';
-    else
-        return 10 + c - 'A';
-}
-
-/*
- * Parse MAC address in format XXXXXXXXXXXX.
- */
-static int
-parallelsMacAddrParse(const char *str, virMacAddrPtr addr)
-{
-    size_t i;
-
-    if (strlen(str) != 12)
-        goto error;
-
-    for (i = 0; i < 6; i++) {
-        if (!c_isxdigit(str[2 * i]) || !c_isxdigit(str[2 * i + 1]))
-            goto error;
-
-        addr->addr[i] = (hex2int(str[2 * i]) << 4) + hex2int(str[2 * i + 1]);
-    }
-
-    return 0;
- error:
-    virReportError(VIR_ERR_INVALID_ARG,
-                   _("Invalid MAC address format '%s'"), str);
-    return -1;
-}
-
-static int
-parallelsGetNetInfo(virDomainNetDefPtr net,
-                    const char *key,
-                    virJSONValuePtr value)
-{
-    const char *tmp;
-
-    /* use device name, shown by prlctl as target device
-     * for identifying network adapter in virDomainDefineXML */
-    if (VIR_STRDUP(net->ifname, key) < 0)
-        goto error;
-
-    net->type = VIR_DOMAIN_NET_TYPE_NETWORK;
-
-    if (!(tmp = virJSONValueObjectGetString(value, "mac"))) {
-        parallelsParseError();
-        return -1;
-    }
-
-    if (parallelsMacAddrParse(tmp, &net->mac) < 0) {
-        parallelsParseError();
-        goto error;
-    }
-
-
-    if (virJSONValueObjectHasKey(value, "network")) {
-        if (!(tmp = virJSONValueObjectGetString(value, "network"))) {
-            parallelsParseError();
-            goto error;
-        }
-
-        if (VIR_STRDUP(net->data.network.name, tmp) < 0)
-            goto error;
-    } else if (virJSONValueObjectHasKey(value, "type")) {
-        if (!(tmp = virJSONValueObjectGetString(value, "type"))) {
-            parallelsParseError();
-            goto error;
-        }
-
-        if (!STREQ(tmp, "routed")) {
-            parallelsParseError();
-            goto error;
-        }
-
-        if (VIR_STRDUP(net->data.network.name,
-                       PARALLELS_ROUTED_NETWORK_NAME) < 0)
-            goto error;
-    } else {
-        parallelsParseError();
-        goto error;
-    }
-
-    net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP;
-    if ((tmp = virJSONValueObjectGetString(value, "state")) &&
-        STREQ(tmp, "disconnected")) {
-        net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN;
-    }
-
-    return 0;
-
- error:
-    return -1;
-}
-
-static int
-parallelsAddNetInfo(virDomainDefPtr def, const char *key, virJSONValuePtr 
value)
-{
-    virDomainNetDefPtr net = NULL;
-
-    if (VIR_ALLOC(net) < 0)
-        goto error;
-
-    if (parallelsGetNetInfo(net, key, value))
-        goto error;
-
-    if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0)
-        goto error;
-
-    def->nets[def->nnets - 1] = net;
-
-    return 0;
-
- error:
-    virDomainNetDefFree(net);
-    return -1;
-}
-
-static int
-parallelsAddDomainHardware(virDomainDefPtr def, virJSONValuePtr jobj)
-{
-    int n;
-    size_t i;
-    virJSONValuePtr value;
-    const char *key;
-
-    n = virJSONValueObjectKeysNumber(jobj);
-    if (n < 1)
-        goto cleanup;
-
-    for (i = 0; i < n; i++) {
-        key = virJSONValueObjectGetKey(jobj, i);
-        value = virJSONValueObjectGetValue(jobj, i);
-
-        if (STRPREFIX(key, "serial")) {
-            if (parallelsAddSerialInfo(&def->serials,
-                                       &def->nserials, key, value))
-                goto cleanup;
-            if (def->nconsoles == 0) {
-                if (parallelsAddSerialInfo(&def->consoles,
-                                           &def->nconsoles, key, value))
-                    goto cleanup;
-            }
-        } else if (STREQ(key, "video")) {
-            if (parallelsAddVideoInfo(def, value))
-                goto cleanup;
-        } else if (STRPREFIX(key, "hdd")) {
-            if (parallelsAddHddInfo(def, key, value))
-                goto cleanup;
-        } else if (STRPREFIX(key, "net")) {
-            if (parallelsAddNetInfo(def, key, value))
-                goto cleanup;
-        }
-    }
-
-    return 0;
-
- cleanup:
-    return -1;
-}
-
-static int
-parallelsAddVNCInfo(virDomainDefPtr def, virJSONValuePtr jobj_root)
-{
-    const char *tmp;
-    unsigned int port;
-    virJSONValuePtr jobj;
-    int ret = -1;
-    virDomainGraphicsDefPtr gr = NULL;
-
-    jobj = virJSONValueObjectGet(jobj_root, "Remote display");
-    if (!jobj) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    tmp = virJSONValueObjectGetString(jobj, "mode");
-    if (!tmp) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if (STREQ(tmp, "off")) {
-        ret = 0;
-        goto cleanup;
-    }
-
-    if (VIR_ALLOC(gr) < 0)
-        goto cleanup;
-
-    if (STREQ(tmp, "auto")) {
-        if (virJSONValueObjectGetNumberUint(jobj, "port", &port) < 0)
-            port = 0;
-        gr->data.vnc.autoport = true;
-    } else {
-        if (virJSONValueObjectGetNumberUint(jobj, "port", &port) < 0) {
-            parallelsParseError();
-            goto cleanup;
-        }
-        gr->data.vnc.autoport = false;
-    }
-
-    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 (!(tmp = virJSONValueObjectGetString(jobj, "address"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if (VIR_ALLOC(gr->listens) < 0)
-        goto cleanup;
-
-    gr->nListens = 1;
-
-    if (VIR_STRDUP(gr->listens[0].address, tmp) < 0)
-        goto cleanup;
-
-    gr->listens[0].type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS;
-
-    if (VIR_APPEND_ELEMENT(def->graphics, def->ngraphics, gr) < 0)
-        goto cleanup;
-
-    return 0;
-
- cleanup:
-    virDomainGraphicsDefFree(gr);
-    return ret;
-}
-
-/*
- * Must be called with privconn->lock held
- */
-static virDomainObjPtr
-parallelsLoadDomain(parallelsConnPtr privconn, virJSONValuePtr jobj)
-{
-    virDomainObjPtr dom = NULL;
-    virDomainDefPtr def = NULL;
-    parallelsDomObjPtr pdom = NULL;
-    virJSONValuePtr jobj2, jobj3;
-    const char *tmp;
-    char *endptr;
-    unsigned long mem;
-    unsigned int x;
-    const char *autostart;
-    const char *state;
-    int hostcpus;
-
-    if (VIR_ALLOC(def) < 0)
-        goto cleanup;
-
-    if (VIR_ALLOC(pdom) < 0)
-        goto cleanup;
-
-    def->virtType = VIR_DOMAIN_VIRT_PARALLELS;
-    def->id = -1;
-
-    if (!(tmp = virJSONValueObjectGetString(jobj, "Name"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-    if (VIR_STRDUP(def->name, tmp) < 0)
-        goto cleanup;
-
-    if (!(tmp = virJSONValueObjectGetString(jobj, "ID"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if (virUUIDParse(tmp, def->uuid) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("UUID in config file malformed"));
-        goto cleanup;
-    }
-
-    if (!(tmp = virJSONValueObjectGetString(jobj, "Description"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-    if (VIR_STRDUP(def->description, tmp) < 0)
-        goto cleanup;
-
-    if (!(jobj2 = virJSONValueObjectGet(jobj, "Hardware"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if (!(jobj3 = virJSONValueObjectGet(jobj2, "cpu"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if (virJSONValueObjectGetNumberUint(jobj3, "cpus", &x) == 0) {
-        def->vcpus = x;
-        def->maxvcpus = x;
-    } else if ((tmp = virJSONValueObjectGetString(jobj3, "cpus"))) {
-        if (STREQ(tmp, "unlimited")) {
-            virNodeInfo nodeinfo;
-
-            if (nodeGetInfo(&nodeinfo) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                               _("Can't get node info"));
-                goto cleanup;
-            }
-
-            def->vcpus = nodeinfo.cpus;
-            def->maxvcpus = def->vcpus;
-        } else {
-            parallelsParseError();
-            goto cleanup;
-        }
-    } else {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if ((hostcpus = nodeGetCPUCount()) < 0)
-        goto cleanup;
-
-    if (!(tmp = virJSONValueObjectGetString(jobj3, "mask"))) {
-        /* Absence of this field means that all domains cpus are available */
-        if (!(pdom->cpumask = virBitmapNew(hostcpus)))
-            goto cleanup;
-        virBitmapSetAll(pdom->cpumask);
-    } else {
-        if (virBitmapParse(tmp, 0, &pdom->cpumask, hostcpus) < 0)
-            goto cleanup;
-    }
-
-    if (!(jobj3 = virJSONValueObjectGet(jobj2, "memory"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if (!(tmp = virJSONValueObjectGetString(jobj3, "size"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if (virStrToLong_ul(tmp, &endptr, 10, &mem) < 0) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if (!STREQ(endptr, "Mb")) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    def->mem.max_balloon = mem;
-    def->mem.max_balloon <<= 10;
-    def->mem.cur_balloon = def->mem.max_balloon;
-
-    if (!(tmp = virJSONValueObjectGetString(jobj, "Type"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if (STREQ(tmp, "CT")) {
-        if (VIR_STRDUP(def->os.type, "exe") < 0)
-            goto cleanup;
-        if (VIR_STRDUP(def->os.init, "/sbin/init") < 0)
-            goto cleanup;
-    } else if (STREQ(tmp, "VM")) {
-        if (VIR_STRDUP(def->os.type, "hvm") < 0)
-            goto cleanup;
-    }
-
-    def->os.arch = VIR_ARCH_X86_64;
-
-    if (virJSONValueObjectGetNumberUint(jobj, "EnvID", &x) < 0)
-        goto cleanup;
-    pdom->id = x;
-    if (!(tmp = virJSONValueObjectGetString(jobj, "ID"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-    if (VIR_STRDUP(pdom->uuid, tmp) < 0)
-        goto cleanup;
-
-    if (!(tmp = virJSONValueObjectGetString(jobj, "Home"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if (VIR_STRDUP(pdom->home, tmp) < 0)
-        goto cleanup;
-
-    if (!(state = virJSONValueObjectGetString(jobj, "State"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if (!(autostart = virJSONValueObjectGetString(jobj, "Autostart"))) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    if (parallelsAddDomainHardware(def, jobj2) < 0)
-        goto cleanup;
-
-    if (parallelsAddVNCInfo(def, jobj) < 0)
-        goto cleanup;
-
-    if (!(dom = virDomainObjListAdd(privconn->domains, def,
-                                    privconn->xmlopt,
-                                    0, NULL)))
-        goto cleanup;
-    /* dom is locked here */
-
-    dom->privateDataFreeFunc = parallelsDomObjFreePrivate;
-    dom->privateData = pdom;
-    dom->persistent = 1;
-
-    /* TODO: handle all possible states */
-    if (STREQ(state, "running")) {
-        virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
-                             VIR_DOMAIN_RUNNING_BOOTED);
-        def->id = pdom->id;
-    }
-
-    if (STREQ(autostart, "on"))
-        dom->autostart = 1;
-    else
-        dom->autostart = 0;
-
-    virObjectUnlock(dom);
-
-    return dom;
-
- cleanup:
-    virDomainDefFree(def);
-    parallelsDomObjFreePrivate(pdom);
-    return NULL;
-}
-
-/*
- * Must be called with privconn->lock held
- *
- * if domain_name is NULL - load information about all
- * registered domains.
- */
-static int
-parallelsLoadDomains(parallelsConnPtr privconn, const char *domain_name)
-{
-    int count;
-    size_t i;
-    virJSONValuePtr jobj;
-    virJSONValuePtr jobj2;
-    virDomainObjPtr dom = NULL;
-    int ret = -1;
-
-    jobj = parallelsParseOutput(PRLCTL, "list", "-j", "-a", "-i", "-H",
-                                "--vmtype", "all", domain_name, NULL);
-    if (!jobj) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    count = virJSONValueArraySize(jobj);
-    if (count < 0) {
-        parallelsParseError();
-        goto cleanup;
-    }
-
-    for (i = 0; i < count; i++) {
-        jobj2 = virJSONValueArrayGet(jobj, i);
-        if (!jobj2) {
-            parallelsParseError();
-            goto cleanup;
-        }
-
-        dom = parallelsLoadDomain(privconn, jobj2);
-        if (!dom)
-            goto cleanup;
-    }
-
-    ret = 0;
-
- cleanup:
-    virJSONValueFree(jobj);
-    return ret;
-}
-
-
-static int
 parallelsDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED,
                             virCapsPtr caps ATTRIBUTE_UNUSED,
                             void *opaque ATTRIBUTE_UNUSED)
@@ -972,7 +233,7 @@ parallelsOpenDefault(virConnectPtr conn)
 
     conn->privateData = privconn;
 
-    if (parallelsLoadDomains(privconn, NULL))
+    if (prlsdkLoadDomains(privconn))
         goto error;
 
     return VIR_DRV_OPEN_SUCCESS;
@@ -2292,6 +1553,7 @@ parallelsDomainDefineXML(virConnectPtr conn, const char 
*xml)
     virDomainPtr ret = NULL;
     virDomainDefPtr def;
     virDomainObjPtr olddom = NULL;
+    virDomainObjPtr dom = NULL;
 
     parallelsDriverLock(privconn);
     if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
@@ -2316,7 +1578,10 @@ parallelsDomainDefineXML(virConnectPtr conn, const char 
*xml)
                            _("Unsupported OS type: %s"), def->os.type);
             goto cleanup;
         }
-        if (parallelsLoadDomains(privconn, def->name))
+        dom = prlsdkAddDomain(privconn, def->uuid);
+        if (dom)
+            virObjectUnlock(dom);
+        else
             goto cleanup;
         olddom = virDomainObjListFindByName(privconn->domains, def->name);
         if (!olddom) {
diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c
index 1c77d27..c6cf78a 100644
--- a/src/parallels/parallels_sdk.c
+++ b/src/parallels/parallels_sdk.c
@@ -24,6 +24,9 @@
 
 #include "virerror.h"
 #include "viralloc.h"
+#include "virstring.h"
+#include "nodeinfo.h"
+#include "virlog.h"
 
 #include "parallels_sdk.h"
 
@@ -32,6 +35,8 @@
 
 PRL_UINT32 defaultJobTimeout = JOB_INFINIT_WAIT_TIMEOUT;
 
+VIR_LOG_INIT("parallels.sdk");
+
 /*
  * Log error description
  */
@@ -72,6 +77,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 +252,998 @@ prlsdkDisconnect(parallelsConnPtr privconn)
 
     PrlHandle_Free(privconn->server);
 }
+
+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(parallelsConnPtr privconn, 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(privconn, 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;
+}
+
+static int
+prlsdkUUIDParse(const char *uuidstr, unsigned char *uuid)
+{
+    char *tmp = NULL;
+    int ret = -1;
+
+    virCheckNonNullArgGoto(uuidstr, error);
+    virCheckNonNullArgGoto(uuid, error);
+
+    if (VIR_STRDUP(tmp, uuidstr) < 0)
+        goto error;
+
+    tmp[strlen(tmp) - 1] = '\0';
+
+    /* trim curly braces */
+    if (virUUIDParse(tmp + 1, uuid) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("UUID in config file malformed"));
+        ret = -1;
+        goto error;
+    }
+
+    ret = 0;
+ error:
+    VIR_FREE(tmp);
+    return ret;
+}
+
+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);
+
+    if (prlsdkUUIDParse(uuidstr, uuid) < 0)
+        goto error;
+
+    return 0;
+
+ error:
+    VIR_FREE(*name);
+    return -1;
+}
+
+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;
+}
+
+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
+prlsdkGetDiskInfo(PRL_HANDLE prldisk,
+                  virDomainDiskDefPtr disk)
+{
+    char *buf = NULL;
+    PRL_UINT32 buflen = 0;
+    PRL_RESULT pret;
+    PRL_UINT32 emulatedType;
+    PRL_UINT32 ifType;
+    PRL_UINT32 pos;
+    PRL_UINT32 prldiskIndex;
+    int ret = -1;
+
+    pret = PrlVmDev_GetEmulatedType(prldisk, &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(prldisk, NULL, &buflen);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (VIR_ALLOC_N(buf, buflen) < 0)
+        goto cleanup;
+
+    pret = PrlVmDev_GetFriendlyName(prldisk, buf, &buflen);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (virDomainDiskSetSource(disk, buf) < 0)
+        goto cleanup;
+
+    pret = PrlVmDev_GetIfaceType(prldisk, &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(prldisk, &pos);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
+    disk->info.addr.drive.target = pos;
+
+    pret = PrlVmDev_GetIndex(prldisk, &prldiskIndex);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (!(disk->dst = virIndexToDiskName(prldiskIndex, "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 (prlsdkGetDiskInfo(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(VIRTUAL_MACHINE_STATE domainState,
+                         PRL_UINT32 envId,
+                         virDomainObjPtr dom)
+{
+    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
+prlsdkConvertCpuInfo(PRL_HANDLE sdkdom,
+                     virDomainDefPtr def,
+                     parallelsDomObjPtr pdom)
+{
+    char *buf;
+    PRL_UINT32 buflen = 0;
+    int hostcpus;
+    PRL_UINT32 cpuCount;
+    PRL_RESULT pret;
+    int ret = -1;
+
+    if ((hostcpus = nodeGetCPUCount()) < 0)
+        goto cleanup;
+
+    /* get number of CPUs */
+    pret = PrlVmCfg_GetCpuCount(sdkdom, &cpuCount);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (cpuCount > hostcpus)
+        cpuCount = hostcpus;
+
+    def->vcpus = cpuCount;
+    def->maxvcpus = cpuCount;
+
+    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 (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 PCM_CPU_MODE_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;
+}
+
+/*
+ * This function retrieves information about domain.
+ * If the domains is already in the domains list
+ * privconn->domains, then locked 'olddom' must be
+ * provided. If the domains must be added to the list,
+ * olddom must be NULL.
+ *
+ * The function return a pointer to a locked virDomainObj.
+ */
+static virDomainObjPtr
+prlsdkLoadDomain(parallelsConnPtr privconn,
+                 PRL_HANDLE sdkdom,
+                 virDomainObjPtr olddom)
+{
+    virDomainObjPtr dom = NULL;
+    virDomainDefPtr def = NULL;
+    parallelsDomObjPtr pdom = NULL;
+    VIRTUAL_MACHINE_STATE domainState;
+
+    PRL_UINT32 buflen = 0;
+    PRL_RESULT pret;
+    PRL_UINT32 ram;
+    PRL_UINT32 envId;
+    PRL_VM_AUTOSTART_OPTION autostart;
+
+    virCheckNonNullArgGoto(privconn, error);
+    virCheckNonNullArgGoto(sdkdom, error);
+
+    if (VIR_ALLOC(def) < 0)
+        goto error;
+
+    if (!olddom) {
+        if (VIR_ALLOC(pdom) < 0)
+            goto error;
+    } else {
+        pdom = olddom->privateData;
+    }
+
+    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 error;
+
+    /* get RAM parameters */
+    pret = PrlVmCfg_GetRamSize(sdkdom, &ram);
+    prlsdkCheckRetGoto(pret, error);
+    def->mem.max_balloon = ram << 10; /* RAM size obtained in Mbytes,
+                                         convert to Kbytes */
+    def->mem.cur_balloon = def->mem.max_balloon;
+
+    if (prlsdkConvertCpuInfo(sdkdom, def, pdom) < 0)
+        goto error;
+
+    if (prlsdkConvertCpuMode(sdkdom, def) < 0)
+        goto error;
+
+    if (prlsdkConvertDomainType(sdkdom, def) < 0)
+        goto error;
+
+    if (prlsdkAddDomainHardware(sdkdom, def) < 0)
+        goto error;
+
+    if (prlsdkAddVNCInfo(sdkdom, def) < 0)
+        goto error;
+
+    pret = PrlVmCfg_GetEnvId(sdkdom, &envId);
+    prlsdkCheckRetGoto(pret, error);
+    pdom->id = envId;
+
+    buflen = 0;
+    pret = PrlVmCfg_GetHomePath(sdkdom, NULL, &buflen);
+    prlsdkCheckRetGoto(pret, error);
+
+    VIR_FREE(pdom->home);
+    if (VIR_ALLOC_N(pdom->home, buflen) < 0)
+        goto error;
+
+    pret = PrlVmCfg_GetHomePath(sdkdom, pdom->home, &buflen);
+    prlsdkCheckRetGoto(pret, error);
+
+    if (olddom) {
+        /* assign new virDomainDef without any checks */
+        /* we can't use virDomainObjAssignDef, because it checks
+         * for state and domain name */
+        dom = olddom;
+        virDomainDefFree(dom->def);
+        virDomainDefFree(dom->newDef);
+        dom->def = def;
+        dom->newDef = def;
+    } else {
+        if (!(dom = virDomainObjListAdd(privconn->domains, def,
+                                        privconn->xmlopt,
+                                        0, NULL)))
+        goto error;
+    }
+    /* dom is locked here */
+
+    dom->privateData = pdom;
+    dom->privateDataFreeFunc = prlsdkDomObjFreePrivate;
+    dom->persistent = 1;
+
+    if (prlsdkGetDomainState(privconn, sdkdom, &domainState) < 0)
+        goto error;
+
+    if (prlsdkConvertDomainState(domainState, envId, dom) < 0)
+        goto error;
+
+    pret = PrlVmCfg_GetAutoStart(sdkdom, &autostart);
+    prlsdkCheckRetGoto(pret, error);
+
+    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 error;
+    }
+
+    if (!pdom->sdkdom) {
+        pret = PrlHandle_AddRef(sdkdom);
+        prlsdkCheckRetGoto(pret, error);
+        pdom->sdkdom = sdkdom;
+    }
+
+    return dom;
+ error:
+    if (dom && !olddom)
+        virDomainObjListRemove(privconn->domains, dom);
+    virDomainDefFree(def);
+    prlsdkDomObjFreePrivate(pdom);
+    return NULL;
+}
+
+int
+prlsdkLoadDomains(parallelsConnPtr privconn)
+{
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+    PRL_HANDLE result;
+    PRL_HANDLE sdkdom;
+    PRL_UINT32 paramsCount;
+    PRL_RESULT pret;
+    size_t i = 0;
+    virDomainObjPtr dom;
+
+    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);
+
+    for (i = 0; i < paramsCount; i++) {
+        pret = PrlResult_GetParamByIndex(result, i, &sdkdom);
+        if (PRL_FAILED(pret)) {
+            logPrlError(pret);
+            PrlHandle_Free(sdkdom);
+            goto error;
+        }
+
+        dom = prlsdkLoadDomain(privconn, sdkdom, NULL);
+        PrlHandle_Free(sdkdom);
+
+        if (!dom)
+            goto error;
+        else
+            virObjectUnlock(dom);
+    }
+
+    PrlHandle_Free(result);
+    return 0;
+
+ error:
+    PrlHandle_Free(result);
+    PrlHandle_Free(job);
+    return -1;
+}
+
+virDomainObjPtr
+prlsdkAddDomain(parallelsConnPtr privconn, const unsigned char *uuid)
+{
+    PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
+    virDomainObjPtr dom;
+
+    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
+    if (dom) {
+        /* domain is already in the list */
+        return dom;
+    }
+
+    sdkdom = prlsdkSdkDomainLookupByUUID(privconn, uuid);
+    if (sdkdom == PRL_INVALID_HANDLE)
+        return NULL;
+
+    dom = prlsdkLoadDomain(privconn, sdkdom, NULL);
+    PrlHandle_Free(sdkdom);
+    return dom;
+}
diff --git a/src/parallels/parallels_sdk.h b/src/parallels/parallels_sdk.h
index cefe67d..d9461ca 100644
--- a/src/parallels/parallels_sdk.h
+++ b/src/parallels/parallels_sdk.h
@@ -28,3 +28,7 @@ int prlsdkInit(parallelsConnPtr privconn);
 void prlsdkDeinit(void);
 int prlsdkConnect(parallelsConnPtr privconn);
 void prlsdkDisconnect(parallelsConnPtr privconn);
+int
+prlsdkLoadDomains(parallelsConnPtr privconn);
+virDomainObjPtr
+prlsdkAddDomain(parallelsConnPtr privconn, const unsigned char *uuid);
diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h
index 163d99b..e054b08 100644
--- a/src/parallels/parallels_utils.h
+++ b/src/parallels/parallels_utils.h
@@ -62,6 +62,7 @@ struct parallelsDomObj {
     char *uuid;
     char *home;
     virBitmapPtr cpumask;
+    PRL_HANDLE sdkdom;
 };
 
 typedef struct parallelsDomObj *parallelsDomObjPtr;
-- 
1.9.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to