[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, ¶msCount);
> + 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