[libvirt] [PATCH v3 02/12] parallels: get domain info with SDK

Maxim Nestratov mnestratov at parallels.com
Tue Nov 25 12:04:47 UTC 2014


18.11.2014 16:16, Dmitry Guryanov пишет:
> From: Alexander Burluka <aburluka at 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 <dguryanov at 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;
ack




More information about the libvir-list mailing list