]> xenbits.xensource.com Git - libvirt.git/commitdiff
parallels: rename all parallels files and driver directory to vz
authorMaxim Nestratov <mnestratov@parallels.com>
Wed, 10 Jun 2015 07:50:00 +0000 (10:50 +0300)
committerDmitry Guryanov <dguryanov@parallels.com>
Wed, 17 Jun 2015 12:07:55 +0000 (15:07 +0300)
This patch moves all src/parallels/parallels* files to vz/vz*
and fixes build accordingly.
No functional changes.

Signed-off-by: Maxim Nestratov <mnestratov@parallels.com>
19 files changed:
po/POTFILES.in
src/Makefile.am
src/libvirt.c
src/parallels/parallels_driver.c [deleted file]
src/parallels/parallels_driver.h [deleted file]
src/parallels/parallels_network.c [deleted file]
src/parallels/parallels_sdk.c [deleted file]
src/parallels/parallels_sdk.h [deleted file]
src/parallels/parallels_storage.c [deleted file]
src/parallels/parallels_utils.c [deleted file]
src/parallels/parallels_utils.h [deleted file]
src/vz/vz_driver.c [new file with mode: 0644]
src/vz/vz_driver.h [new file with mode: 0644]
src/vz/vz_network.c [new file with mode: 0644]
src/vz/vz_sdk.c [new file with mode: 0644]
src/vz/vz_sdk.h [new file with mode: 0644]
src/vz/vz_storage.c [new file with mode: 0644]
src/vz/vz_utils.c [new file with mode: 0644]
src/vz/vz_utils.h [new file with mode: 0644]

index 189e2cc2f4d9d4667adc83d2ccd61cce84fff04e..1d5917d10cf31c809b63cdebfc803acbd17a573f 100644 (file)
@@ -106,12 +106,12 @@ src/nwfilter/nwfilter_learnipaddr.c
 src/openvz/openvz_conf.c
 src/openvz/openvz_driver.c
 src/openvz/openvz_util.c
-src/parallels/parallels_driver.c
-src/parallels/parallels_network.c
-src/parallels/parallels_sdk.c
-src/parallels/parallels_utils.c
-src/parallels/parallels_utils.h
-src/parallels/parallels_storage.c
+src/vz/vz_driver.c
+src/vz/vz_network.c
+src/vz/vz_sdk.c
+src/vz/vz_utils.c
+src/vz/vz_utils.h
+src/vz/vz_storage.c
 src/phyp/phyp_driver.c
 src/qemu/qemu_agent.c
 src/qemu/qemu_blockjob.c
index 1e1b841ca9990c6dd7cb5c28934add1eead143af..47b6d61b2f1985921419bd6ffcbd05d94cfac85b 100644 (file)
@@ -558,7 +558,7 @@ DRIVER_SOURCE_FILES = \
        $(NODE_DEVICE_DRIVER_UDEV_SOURCES) \
        $(NWFILTER_DRIVER_SOURCES) \
        $(OPENVZ_DRIVER_SOURCES) \
-       $(PARALLELS_DRIVER_SOURCES) \
+       $(VZ_DRIVER_SOURCES) \
        $(PHYP_DRIVER_SOURCES) \
        $(QEMU_DRIVER_SOURCES) \
        $(REMOTE_DRIVER_SOURCES) \
@@ -826,15 +826,15 @@ HYPERV_DRIVER_EXTRA_DIST =                                                        \
                hyperv/hyperv_wmi_generator.py                                  \
                $(HYPERV_DRIVER_GENERATED)
 
-PARALLELS_DRIVER_SOURCES =                                     \
-               parallels/parallels_driver.h                    \
-               parallels/parallels_driver.c                    \
-               parallels/parallels_utils.c                     \
-               parallels/parallels_utils.h                     \
-               parallels/parallels_storage.c           \
-               parallels/parallels_network.c           \
-               parallels/parallels_sdk.h                       \
-               parallels/parallels_sdk.c
+VZ_DRIVER_SOURCES =                                    \
+               vz/vz_driver.h                  \
+               vz/vz_driver.c                  \
+               vz/vz_utils.c                   \
+               vz/vz_utils.h                   \
+               vz/vz_storage.c         \
+               vz/vz_network.c         \
+               vz/vz_sdk.h                     \
+               vz/vz_sdk.c
 
 BHYVE_DRIVER_SOURCES =                                         \
                bhyve/bhyve_capabilities.c                      \
@@ -1415,13 +1415,13 @@ libvirt_driver_hyperv_la_SOURCES = $(HYPERV_DRIVER_SOURCES)
 endif WITH_HYPERV
 
 if WITH_PARALLELS
-noinst_LTLIBRARIES += libvirt_driver_parallels.la
-libvirt_la_BUILT_LIBADD += libvirt_driver_parallels.la
-libvirt_driver_parallels_la_CFLAGS = \
+noinst_LTLIBRARIES += libvirt_driver_vz.la
+libvirt_la_BUILT_LIBADD += libvirt_driver_vz.la
+libvirt_driver_vz_la_CFLAGS = \
                -I$(srcdir)/conf $(AM_CFLAGS) \
                $(PARALLELS_SDK_CFLAGS) $(LIBNL_CFLAGS)
-libvirt_driver_parallels_la_LIBADD = $(PARALLELS_SDK_LIBS) $(LIBNL_LIBS)
-libvirt_driver_parallels_la_SOURCES = $(PARALLELS_DRIVER_SOURCES)
+libvirt_driver_vz_la_LIBADD = $(PARALLELS_SDK_LIBS) $(LIBNL_LIBS)
+libvirt_driver_vz_la_SOURCES = $(VZ_DRIVER_SOURCES)
 endif WITH_PARALLELS
 
 if WITH_BHYVE
@@ -1787,7 +1787,7 @@ EXTRA_DIST +=                                                     \
                $(ESX_DRIVER_EXTRA_DIST)                        \
                $(HYPERV_DRIVER_SOURCES)                        \
                $(HYPERV_DRIVER_EXTRA_DIST)                     \
-               $(PARALLELS_DRIVER_SOURCES)                     \
+               $(VZ_DRIVER_SOURCES)                            \
                $(BHYVE_DRIVER_SOURCES)                         \
                $(NETWORK_DRIVER_SOURCES)                       \
                $(INTERFACE_DRIVER_SOURCES)                     \
index f1e8d3f8859bfbc68ff0874c0958477e09dcfdba..4204446ebb9a41ce95687727727e8172c14c8587 100644 (file)
@@ -93,7 +93,7 @@
 # include "xenapi/xenapi_driver.h"
 #endif
 #ifdef WITH_PARALLELS
-# include "parallels/parallels_driver.h"
+# include "vz/vz_driver.h"
 #endif
 #ifdef WITH_BHYVE
 # include "bhyve/bhyve_driver.h"
diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
deleted file mode 100644 (file)
index 8edddc4..0000000
+++ /dev/null
@@ -1,1418 +0,0 @@
-/*
- * parallels_driver.c: core driver functions for managing
- * Parallels Cloud Server hosts
- *
- * Copyright (C) 2014-2015 Red Hat, Inc.
- * Copyright (C) 2012 Parallels, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <config.h>
-
-#include <sys/types.h>
-#include <sys/poll.h>
-#include <limits.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <paths.h>
-#include <pwd.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <sys/statvfs.h>
-
-#include "datatypes.h"
-#include "virerror.h"
-#include "viralloc.h"
-#include "virlog.h"
-#include "vircommand.h"
-#include "configmake.h"
-#include "virfile.h"
-#include "virstoragefile.h"
-#include "nodeinfo.h"
-#include "virstring.h"
-#include "cpu/cpu.h"
-#include "virtypedparam.h"
-
-#include "parallels_driver.h"
-#include "parallels_utils.h"
-#include "parallels_sdk.h"
-
-#define VIR_FROM_THIS VIR_FROM_PARALLELS
-
-VIR_LOG_INIT("parallels.parallels_driver");
-
-#define PRLCTL                      "prlctl"
-#define PRLSRVCTL                   "prlsrvctl"
-
-static int vzConnectClose(virConnectPtr conn);
-
-void
-vzDriverLock(vzConnPtr driver)
-{
-    virMutexLock(&driver->lock);
-}
-
-void
-vzDriverUnlock(vzConnPtr driver)
-{
-    virMutexUnlock(&driver->lock);
-}
-
-static virCapsPtr
-vzBuildCapabilities(void)
-{
-    virCapsPtr caps = NULL;
-    virCPUDefPtr cpu = NULL;
-    virCPUDataPtr data = NULL;
-    virCapsGuestPtr guest;
-    virNodeInfo nodeinfo;
-
-    if ((caps = virCapabilitiesNew(virArchFromHost(),
-                                   false, false)) == NULL)
-        return NULL;
-
-    if (nodeCapsInitNUMA(caps) < 0)
-        goto error;
-
-    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM,
-                                         VIR_ARCH_X86_64,
-                                         "parallels",
-                                         NULL, 0, NULL)) == NULL)
-        goto error;
-
-    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM,
-                                         VIR_ARCH_I686,
-                                         "parallels",
-                                         NULL, 0, NULL)) == NULL)
-        goto error;
-
-
-    if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_PARALLELS,
-                                      NULL, NULL, 0, NULL) == NULL)
-        goto error;
-
-    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_EXE,
-                                         VIR_ARCH_X86_64,
-                                         "parallels",
-                                         NULL, 0, NULL)) == NULL)
-        goto error;
-
-    if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_PARALLELS,
-                                      NULL, NULL, 0, NULL) == NULL)
-        goto error;
-
-    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM,
-                                         VIR_ARCH_X86_64,
-                                         "vz",
-                                         NULL, 0, NULL)) == NULL)
-        goto error;
-
-    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM,
-                                         VIR_ARCH_I686,
-                                         "vz",
-                                         NULL, 0, NULL)) == NULL)
-        goto error;
-
-
-    if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_VZ,
-                                      NULL, NULL, 0, NULL) == NULL)
-        goto error;
-
-    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_EXE,
-                                         VIR_ARCH_X86_64,
-                                         "vz",
-                                         NULL, 0, NULL)) == NULL)
-        goto error;
-
-    if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_VZ,
-                                      NULL, NULL, 0, NULL) == NULL)
-        goto error;
-
-    if (nodeGetInfo(&nodeinfo))
-        goto error;
-
-    if (VIR_ALLOC(cpu) < 0)
-        goto error;
-
-    cpu->arch = caps->host.arch;
-    cpu->type = VIR_CPU_TYPE_HOST;
-    cpu->sockets = nodeinfo.sockets;
-    cpu->cores = nodeinfo.cores;
-    cpu->threads = nodeinfo.threads;
-
-    caps->host.cpu = cpu;
-
-    if (!(data = cpuNodeData(cpu->arch))
-        || cpuDecode(cpu, data, NULL, 0, NULL) < 0) {
-        goto cleanup;
-    }
-
- cleanup:
-    cpuDataFree(data);
-    return caps;
-
- error:
-    virObjectUnref(caps);
-    goto cleanup;
-}
-
-static char *
-vzConnectGetCapabilities(virConnectPtr conn)
-{
-    vzConnPtr privconn = conn->privateData;
-    char *xml;
-
-    vzDriverLock(privconn);
-    xml = virCapabilitiesFormatXML(privconn->caps);
-    vzDriverUnlock(privconn);
-    return xml;
-}
-
-static int
-vzDomainDefPostParse(virDomainDefPtr def,
-                            virCapsPtr caps ATTRIBUTE_UNUSED,
-                            void *opaque ATTRIBUTE_UNUSED)
-{
-    /* memory hotplug tunables are not supported by this driver */
-    if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
-        return -1;
-
-    return 0;
-}
-
-static int
-vzDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
-                                  const virDomainDef *def,
-                                  virCapsPtr caps ATTRIBUTE_UNUSED,
-                                  void *opaque ATTRIBUTE_UNUSED)
-{
-    int ret = -1;
-
-    if (dev->type == VIR_DOMAIN_DEVICE_NET &&
-        (dev->data.net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
-         dev->data.net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
-        !dev->data.net->model &&
-        def->os.type == VIR_DOMAIN_OSTYPE_HVM &&
-        VIR_STRDUP(dev->data.net->model, "e1000") < 0)
-        goto cleanup;
-
-    ret = 0;
- cleanup:
-    return ret;
-}
-
-
-virDomainDefParserConfig vzDomainDefParserConfig = {
-    .macPrefix = {0x42, 0x1C, 0x00},
-    .devicesPostParseCallback = vzDomainDeviceDefPostParse,
-    .domainPostParseCallback = vzDomainDefPostParse,
-};
-
-
-static int
-vzOpenDefault(virConnectPtr conn)
-{
-    vzConnPtr privconn;
-
-    if (VIR_ALLOC(privconn) < 0)
-        return VIR_DRV_OPEN_ERROR;
-    if (virMutexInit(&privconn->lock) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("cannot initialize mutex"));
-        goto err_free;
-    }
-
-    privconn->drivername = conn->driver->name;
-
-    if (prlsdkInit()) {
-        VIR_DEBUG("%s", _("Can't initialize Parallels SDK"));
-        goto err_free;
-    }
-
-    if (prlsdkConnect(privconn) < 0)
-        goto err_free;
-
-    if (!(privconn->caps = vzBuildCapabilities()))
-        goto error;
-
-    if (!(privconn->xmlopt = virDomainXMLOptionNew(&vzDomainDefParserConfig,
-                                                 NULL, NULL)))
-        goto error;
-
-    if (!(privconn->domains = virDomainObjListNew()))
-        goto error;
-
-    if (!(privconn->domainEventState = virObjectEventStateNew()))
-        goto error;
-
-    if (prlsdkSubscribeToPCSEvents(privconn))
-        goto error;
-
-    conn->privateData = privconn;
-
-    if (prlsdkLoadDomains(privconn))
-        goto error;
-
-    return VIR_DRV_OPEN_SUCCESS;
-
- error:
-    virObjectUnref(privconn->domains);
-    virObjectUnref(privconn->caps);
-    virStoragePoolObjListFree(&privconn->pools);
-    virObjectEventStateFree(privconn->domainEventState);
-    prlsdkDisconnect(privconn);
-    prlsdkDeinit();
- err_free:
-    VIR_FREE(privconn);
-    return VIR_DRV_OPEN_ERROR;
-}
-
-static virDrvOpenStatus
-vzConnectOpen(virConnectPtr conn,
-                     virConnectAuthPtr auth ATTRIBUTE_UNUSED,
-                     unsigned int flags)
-{
-    int ret;
-
-    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
-
-    if (!conn->uri)
-        return VIR_DRV_OPEN_DECLINED;
-
-    if (!conn->uri->scheme)
-        return VIR_DRV_OPEN_DECLINED;
-
-    if (STRNEQ(conn->uri->scheme, "vz") &&
-        STRNEQ(conn->uri->scheme, "parallels"))
-        return VIR_DRV_OPEN_DECLINED;
-
-    if (STREQ(conn->uri->scheme, "vz") && STRNEQ(conn->driver->name, "vz"))
-        return VIR_DRV_OPEN_DECLINED;
-
-    if (STREQ(conn->uri->scheme, "parallels") && STRNEQ(conn->driver->name, "Parallels"))
-        return VIR_DRV_OPEN_DECLINED;
-
-    /* Remote driver should handle these. */
-    if (conn->uri->server)
-        return VIR_DRV_OPEN_DECLINED;
-
-    /* From this point on, the connection is for us. */
-    if (!STREQ_NULLABLE(conn->uri->path, "/system")) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Unexpected Virtuozzo URI path '%s', try vz:///system"),
-                       conn->uri->path);
-        return VIR_DRV_OPEN_ERROR;
-    }
-
-    if ((ret = vzOpenDefault(conn)) != VIR_DRV_OPEN_SUCCESS ||
-        (ret = vzStorageOpen(conn, flags)) != VIR_DRV_OPEN_SUCCESS ||
-        (ret = vzNetworkOpen(conn, flags)) != VIR_DRV_OPEN_SUCCESS) {
-        vzConnectClose(conn);
-        return ret;
-    }
-
-    return VIR_DRV_OPEN_SUCCESS;
-}
-
-static int
-vzConnectClose(virConnectPtr conn)
-{
-    vzConnPtr privconn = conn->privateData;
-
-    if (!privconn)
-        return 0;
-
-    vzNetworkClose(conn);
-    vzStorageClose(conn);
-
-    vzDriverLock(privconn);
-    prlsdkUnsubscribeFromPCSEvents(privconn);
-    virObjectUnref(privconn->caps);
-    virObjectUnref(privconn->xmlopt);
-    virObjectUnref(privconn->domains);
-    virObjectEventStateFree(privconn->domainEventState);
-    prlsdkDisconnect(privconn);
-    conn->privateData = NULL;
-    prlsdkDeinit();
-
-    vzDriverUnlock(privconn);
-    virMutexDestroy(&privconn->lock);
-
-    VIR_FREE(privconn);
-    return 0;
-}
-
-static int
-vzConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *hvVer)
-{
-    char *output, *sVer, *tmp;
-    const char *searchStr = "prlsrvctl version ";
-    int ret = -1;
-
-    output = vzGetOutput(PRLSRVCTL, "--help", NULL);
-
-    if (!output) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (!(sVer = strstr(output, searchStr))) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    sVer = sVer + strlen(searchStr);
-
-    /* parallels server has versions number like 6.0.17977.782218,
-     * so libvirt can handle only first two numbers. */
-    if (!(tmp = strchr(sVer, '.'))) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (!(tmp = strchr(tmp + 1, '.'))) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    tmp[0] = '\0';
-    if (virParseVersionString(sVer, hvVer, true) < 0) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    ret = 0;
-
- cleanup:
-    VIR_FREE(output);
-    return ret;
-}
-
-
-static char *vzConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
-{
-    return virGetHostname();
-}
-
-
-static int
-vzConnectListDomains(virConnectPtr conn, int *ids, int maxids)
-{
-    vzConnPtr privconn = conn->privateData;
-    int n;
-
-    vzDriverLock(privconn);
-    n = virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
-                                     NULL, NULL);
-    vzDriverUnlock(privconn);
-
-    return n;
-}
-
-static int
-vzConnectNumOfDomains(virConnectPtr conn)
-{
-    vzConnPtr privconn = conn->privateData;
-    int count;
-
-    vzDriverLock(privconn);
-    count = virDomainObjListNumOfDomains(privconn->domains, true,
-                                         NULL, NULL);
-    vzDriverUnlock(privconn);
-
-    return count;
-}
-
-static int
-vzConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
-{
-    vzConnPtr privconn = conn->privateData;
-    int n;
-
-    vzDriverLock(privconn);
-    memset(names, 0, sizeof(*names) * maxnames);
-    n = virDomainObjListGetInactiveNames(privconn->domains, names,
-                                         maxnames, NULL, NULL);
-    vzDriverUnlock(privconn);
-
-    return n;
-}
-
-static int
-vzConnectNumOfDefinedDomains(virConnectPtr conn)
-{
-    vzConnPtr privconn = conn->privateData;
-    int count;
-
-    vzDriverLock(privconn);
-    count = virDomainObjListNumOfDomains(privconn->domains, false,
-                                         NULL, NULL);
-    vzDriverUnlock(privconn);
-
-    return count;
-}
-
-static int
-vzConnectListAllDomains(virConnectPtr conn,
-                               virDomainPtr **domains,
-                               unsigned int flags)
-{
-    vzConnPtr privconn = conn->privateData;
-    int ret = -1;
-
-    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
-    vzDriverLock(privconn);
-    ret = virDomainObjListExport(privconn->domains, conn, domains,
-                                 NULL, flags);
-    vzDriverUnlock(privconn);
-
-    return ret;
-}
-
-static virDomainPtr
-vzDomainLookupByID(virConnectPtr conn, int id)
-{
-    vzConnPtr privconn = conn->privateData;
-    virDomainPtr ret = NULL;
-    virDomainObjPtr dom;
-
-    vzDriverLock(privconn);
-    dom = virDomainObjListFindByID(privconn->domains, id);
-    vzDriverUnlock(privconn);
-
-    if (dom == NULL) {
-        virReportError(VIR_ERR_NO_DOMAIN, NULL);
-        goto cleanup;
-    }
-
-    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
-    if (ret)
-        ret->id = dom->def->id;
-
- cleanup:
-    if (dom)
-        virObjectUnlock(dom);
-    return ret;
-}
-
-static virDomainPtr
-vzDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
-{
-    vzConnPtr privconn = conn->privateData;
-    virDomainPtr ret = NULL;
-    virDomainObjPtr dom;
-
-    vzDriverLock(privconn);
-    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
-    vzDriverUnlock(privconn);
-
-    if (dom == NULL) {
-        char uuidstr[VIR_UUID_STRING_BUFLEN];
-        virUUIDFormat(uuid, uuidstr);
-        virReportError(VIR_ERR_NO_DOMAIN,
-                       _("no domain with matching uuid '%s'"), uuidstr);
-        goto cleanup;
-    }
-
-    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
-    if (ret)
-        ret->id = dom->def->id;
-
- cleanup:
-    if (dom)
-        virObjectUnlock(dom);
-    return ret;
-}
-
-static virDomainPtr
-vzDomainLookupByName(virConnectPtr conn, const char *name)
-{
-    vzConnPtr privconn = conn->privateData;
-    virDomainPtr ret = NULL;
-    virDomainObjPtr dom;
-
-    vzDriverLock(privconn);
-    dom = virDomainObjListFindByName(privconn->domains, name);
-    vzDriverUnlock(privconn);
-
-    if (dom == NULL) {
-        virReportError(VIR_ERR_NO_DOMAIN,
-                       _("no domain with matching name '%s'"), name);
-        goto cleanup;
-    }
-
-    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
-    if (ret)
-        ret->id = dom->def->id;
-
- cleanup:
-    virDomainObjEndAPI(&dom);
-    return ret;
-}
-
-static int
-vzDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
-{
-    virDomainObjPtr privdom;
-    int ret = -1;
-
-    if (!(privdom = vzDomObjFromDomain(domain)))
-        goto cleanup;
-
-    info->state = virDomainObjGetState(privdom, NULL);
-    info->memory = privdom->def->mem.cur_balloon;
-    info->maxMem = virDomainDefGetMemoryActual(privdom->def);
-    info->nrVirtCpu = privdom->def->vcpus;
-    info->cpuTime = 0;
-    ret = 0;
-
- cleanup:
-    if (privdom)
-        virObjectUnlock(privdom);
-    return ret;
-}
-
-static char *
-vzDomainGetOSType(virDomainPtr domain)
-{
-    virDomainObjPtr privdom;
-
-    char *ret = NULL;
-
-    if (!(privdom = vzDomObjFromDomain(domain)))
-        goto cleanup;
-
-    ignore_value(VIR_STRDUP(ret, virDomainOSTypeToString(privdom->def->os.type)));
-
- cleanup:
-    if (privdom)
-        virObjectUnlock(privdom);
-    return ret;
-}
-
-static int
-vzDomainIsPersistent(virDomainPtr domain)
-{
-    virDomainObjPtr privdom;
-    int ret = -1;
-
-    if (!(privdom = vzDomObjFromDomain(domain)))
-        goto cleanup;
-
-    ret = 1;
-
- cleanup:
-    if (privdom)
-        virObjectUnlock(privdom);
-    return ret;
-}
-
-static int
-vzDomainGetState(virDomainPtr domain,
-                  int *state, int *reason, unsigned int flags)
-{
-    virDomainObjPtr privdom;
-    int ret = -1;
-    virCheckFlags(0, -1);
-
-    if (!(privdom = vzDomObjFromDomain(domain)))
-        goto cleanup;
-
-    *state = virDomainObjGetState(privdom, reason);
-    ret = 0;
-
- cleanup:
-    if (privdom)
-        virObjectUnlock(privdom);
-    return ret;
-}
-
-static char *
-vzDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
-{
-    virDomainDefPtr def;
-    virDomainObjPtr privdom;
-    char *ret = NULL;
-
-    /* Flags checked by virDomainDefFormat */
-
-    if (!(privdom = vzDomObjFromDomain(domain)))
-        goto cleanup;
-
-    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
-        privdom->newDef ? privdom->newDef : privdom->def;
-
-    ret = virDomainDefFormat(def, flags);
-
- cleanup:
-    if (privdom)
-        virObjectUnlock(privdom);
-    return ret;
-}
-
-static int
-vzDomainGetAutostart(virDomainPtr domain, int *autostart)
-{
-    virDomainObjPtr privdom;
-    int ret = -1;
-
-    if (!(privdom = vzDomObjFromDomain(domain)))
-        goto cleanup;
-
-    *autostart = privdom->autostart;
-    ret = 0;
-
- cleanup:
-    if (privdom)
-        virObjectUnlock(privdom);
-    return ret;
-}
-
-static virDomainPtr
-vzDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
-{
-    vzConnPtr privconn = conn->privateData;
-    virDomainPtr retdom = NULL;
-    virDomainDefPtr def;
-    virDomainObjPtr olddom = NULL;
-    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
-
-    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
-
-    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
-        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE;
-
-    vzDriverLock(privconn);
-    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
-                                       parse_flags)) == NULL)
-        goto cleanup;
-
-    olddom = virDomainObjListFindByUUID(privconn->domains, def->uuid);
-    if (olddom == NULL) {
-        virResetLastError();
-        if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-            if (prlsdkCreateVm(conn, def))
-                goto cleanup;
-        } else if (def->os.type == VIR_DOMAIN_OSTYPE_EXE) {
-            if (prlsdkCreateCt(conn, def))
-                goto cleanup;
-        } else {
-            virReportError(VIR_ERR_INVALID_ARG,
-                           _("Unsupported OS type: %s"),
-                           virDomainOSTypeToString(def->os.type));
-            goto cleanup;
-        }
-
-        olddom = prlsdkAddDomain(privconn, def->uuid);
-        if (!olddom)
-            goto cleanup;
-    } else {
-        int state, reason;
-
-        state = virDomainObjGetState(olddom, &reason);
-
-        if (state == VIR_DOMAIN_SHUTOFF &&
-            reason == VIR_DOMAIN_SHUTOFF_SAVED) {
-
-            /* PCS doesn't store domain config in managed save state file.
-             * It's forbidden to change config for VMs in this state.
-             * It's possible to change config for containers, but after
-             * restoring domain will have that new config, not a config,
-             * which domain had at the moment of virDomainManagedSave.
-             *
-             * So forbid this operation, if config is changed. If it's
-             * not changed - just do nothing. */
-
-            if (!virDomainDefCheckABIStability(olddom->def, def)) {
-                virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
-                               _("Can't change domain configuration "
-                                 "in managed save state"));
-                goto cleanup;
-            }
-        } else {
-            if (prlsdkApplyConfig(conn, olddom, def))
-                goto cleanup;
-
-            if (prlsdkUpdateDomain(privconn, olddom))
-                goto cleanup;
-        }
-    }
-
-    retdom = virGetDomain(conn, def->name, def->uuid);
-    if (retdom)
-        retdom->id = def->id;
-
- cleanup:
-    if (olddom)
-        virObjectUnlock(olddom);
-    virDomainDefFree(def);
-    vzDriverUnlock(privconn);
-    return retdom;
-}
-
-static virDomainPtr
-vzDomainDefineXML(virConnectPtr conn, const char *xml)
-{
-    return vzDomainDefineXMLFlags(conn, xml, 0);
-}
-
-
-static int
-vzNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED,
-                     virNodeInfoPtr nodeinfo)
-{
-    return nodeGetInfo(nodeinfo);
-}
-
-static int vzConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
-{
-    /* Encryption is not relevant / applicable to way we talk to PCS */
-    return 0;
-}
-
-static int vzConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
-{
-    /* We run CLI tools directly so this is secure */
-    return 1;
-}
-
-static int vzConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
-{
-    return 1;
-}
-
-
-static char *
-vzConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
-                            const char **xmlCPUs,
-                            unsigned int ncpus,
-                            unsigned int flags)
-{
-    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);
-
-    return cpuBaselineXML(xmlCPUs, ncpus, NULL, 0, flags);
-}
-
-
-static int
-vzDomainGetVcpus(virDomainPtr domain,
-                        virVcpuInfoPtr info,
-                        int maxinfo,
-                        unsigned char *cpumaps,
-                        int maplen)
-{
-    virDomainObjPtr privdom = NULL;
-    size_t i;
-    int v, maxcpu, hostcpus;
-    int ret = -1;
-
-    if (!(privdom = vzDomObjFromDomain(domain)))
-        goto cleanup;
-
-    if (!virDomainObjIsActive(privdom)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       "%s",
-                       _("cannot list vcpu pinning for an inactive domain"));
-        goto cleanup;
-    }
-
-    if ((hostcpus = nodeGetCPUCount()) < 0)
-        goto cleanup;
-
-    maxcpu = maplen * 8;
-    if (maxcpu > hostcpus)
-        maxcpu = hostcpus;
-
-    if (maxinfo >= 1) {
-        if (info != NULL) {
-            memset(info, 0, sizeof(*info) * maxinfo);
-            for (i = 0; i < maxinfo; i++) {
-                info[i].number = i;
-                info[i].state = VIR_VCPU_RUNNING;
-            }
-        }
-        if (cpumaps != NULL) {
-            unsigned char *tmpmap = NULL;
-            int tmpmapLen = 0;
-
-            memset(cpumaps, 0, maplen * maxinfo);
-            virBitmapToData(privdom->def->cpumask, &tmpmap, &tmpmapLen);
-            if (tmpmapLen > maplen)
-                tmpmapLen = maplen;
-
-            for (v = 0; v < maxinfo; v++) {
-                unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
-                memcpy(cpumap, tmpmap, tmpmapLen);
-            }
-            VIR_FREE(tmpmap);
-        }
-    }
-    ret = maxinfo;
-
- cleanup:
-    if (privdom)
-        virObjectUnlock(privdom);
-    return ret;
-}
-
-
-static int
-vzNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
-                       unsigned char **cpumap,
-                       unsigned int *online,
-                       unsigned int flags)
-{
-    return nodeGetCPUMap(cpumap, online, flags);
-}
-
-static int
-vzConnectDomainEventRegisterAny(virConnectPtr conn,
-                                       virDomainPtr domain,
-                                       int eventID,
-                                       virConnectDomainEventGenericCallback callback,
-                                       void *opaque,
-                                       virFreeCallback freecb)
-{
-    int ret = -1;
-    vzConnPtr privconn = conn->privateData;
-    if (virDomainEventStateRegisterID(conn,
-                                      privconn->domainEventState,
-                                      domain, eventID,
-                                      callback, opaque, freecb, &ret) < 0)
-        ret = -1;
-    return ret;
-}
-
-static int
-vzConnectDomainEventDeregisterAny(virConnectPtr conn,
-                                         int callbackID)
-{
-    vzConnPtr privconn = conn->privateData;
-    int ret = -1;
-
-    if (virObjectEventStateDeregisterID(conn,
-                                        privconn->domainEventState,
-                                        callbackID) < 0)
-        goto cleanup;
-
-    ret = 0;
-
- cleanup:
-    return ret;
-}
-
-static int vzDomainSuspend(virDomainPtr domain)
-{
-    return prlsdkDomainChangeState(domain, prlsdkPause);
-}
-
-static int vzDomainResume(virDomainPtr domain)
-{
-    return prlsdkDomainChangeState(domain, prlsdkResume);
-}
-
-static int vzDomainCreate(virDomainPtr domain)
-{
-    return prlsdkDomainChangeState(domain, prlsdkStart);
-}
-
-static int vzDomainDestroy(virDomainPtr domain)
-{
-    return prlsdkDomainChangeState(domain, prlsdkKill);
-}
-
-static int vzDomainShutdown(virDomainPtr domain)
-{
-    return prlsdkDomainChangeState(domain, prlsdkStop);
-}
-
-static int vzDomainIsActive(virDomainPtr domain)
-{
-    virDomainObjPtr dom = NULL;
-    int ret = -1;
-
-    if (!(dom = vzDomObjFromDomain(domain)))
-        return -1;
-
-    ret = virDomainObjIsActive(dom);
-    virObjectUnlock(dom);
-
-    return ret;
-}
-
-static int
-vzDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
-{
-    /* we don't support any create flags */
-    virCheckFlags(0, -1);
-
-    return vzDomainCreate(domain);
-}
-
-static int
-vzDomainUndefineFlags(virDomainPtr domain,
-                             unsigned int flags)
-{
-    vzConnPtr privconn = domain->conn->privateData;
-    virDomainObjPtr dom = NULL;
-    int ret;
-
-    virCheckFlags(0, -1);
-
-    if (!(dom = vzDomObjFromDomain(domain)))
-        return -1;
-
-    ret = prlsdkUnregisterDomain(privconn, dom);
-    if (ret)
-         virObjectUnlock(dom);
-
-    return ret;
-}
-
-static int
-vzDomainUndefine(virDomainPtr domain)
-{
-    return vzDomainUndefineFlags(domain, 0);
-}
-
-static int
-vzDomainHasManagedSaveImage(virDomainPtr domain, unsigned int flags)
-{
-    virDomainObjPtr dom = NULL;
-    int state, reason;
-    int ret = 0;
-
-    virCheckFlags(0, -1);
-
-    if (!(dom = vzDomObjFromDomain(domain)))
-        return -1;
-
-    state = virDomainObjGetState(dom, &reason);
-    if (state == VIR_DOMAIN_SHUTOFF && reason == VIR_DOMAIN_SHUTOFF_SAVED)
-        ret = 1;
-    virObjectUnlock(dom);
-
-    return ret;
-}
-
-static int
-vzDomainManagedSave(virDomainPtr domain, unsigned int flags)
-{
-    vzConnPtr privconn = domain->conn->privateData;
-    virDomainObjPtr dom = NULL;
-    int state, reason;
-    int ret = -1;
-
-    virCheckFlags(VIR_DOMAIN_SAVE_RUNNING |
-                  VIR_DOMAIN_SAVE_PAUSED, -1);
-
-    if (!(dom = vzDomObjFromDomain(domain)))
-        return -1;
-
-    state = virDomainObjGetState(dom, &reason);
-
-    if (state == VIR_DOMAIN_RUNNING && (flags & VIR_DOMAIN_SAVE_PAUSED)) {
-        ret = prlsdkDomainChangeStateLocked(privconn, dom, prlsdkPause);
-        if (ret)
-            goto cleanup;
-    }
-
-    ret = prlsdkDomainChangeStateLocked(privconn, dom, prlsdkSuspend);
-
- cleanup:
-    virObjectUnlock(dom);
-    return ret;
-}
-
-static int
-vzDomainManagedSaveRemove(virDomainPtr domain, unsigned int flags)
-{
-    virDomainObjPtr dom = NULL;
-    int state, reason;
-    int ret = -1;
-
-    virCheckFlags(0, -1);
-
-    if (!(dom = vzDomObjFromDomain(domain)))
-        return -1;
-
-    state = virDomainObjGetState(dom, &reason);
-
-    if (!(state == VIR_DOMAIN_SHUTOFF && reason == VIR_DOMAIN_SHUTOFF_SAVED))
-        goto cleanup;
-
-    ret = prlsdkDomainManagedSaveRemove(dom);
-
- cleanup:
-    virObjectUnlock(dom);
-    return ret;
-}
-
-static int vzDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
-                                            unsigned int flags)
-{
-    int ret = -1;
-    vzConnPtr privconn = dom->conn->privateData;
-    virDomainDeviceDefPtr dev = NULL;
-    virDomainObjPtr privdom = NULL;
-    bool domactive = false;
-
-    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
-                  VIR_DOMAIN_AFFECT_CONFIG, -1);
-
-    if (!(privdom = vzDomObjFromDomain(dom)))
-        return -1;
-
-    if (!(flags & VIR_DOMAIN_AFFECT_CONFIG)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("device attach needs VIR_DOMAIN_AFFECT_CONFIG "
-                         "flag to be set"));
-        goto cleanup;
-    }
-
-    domactive = virDomainObjIsActive(privdom);
-    if (!domactive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("cannot do live update a device on "
-                         "inactive domain"));
-        goto cleanup;
-    }
-    if (domactive && !(flags & VIR_DOMAIN_AFFECT_LIVE)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("Updates on a running domain need "
-                         "VIR_DOMAIN_AFFECT_LIVE flag"));
-    }
-
-    dev = virDomainDeviceDefParse(xml, privdom->def, privconn->caps,
-                                  privconn->xmlopt, VIR_DOMAIN_XML_INACTIVE);
-    if (dev == NULL)
-        goto cleanup;
-
-    switch (dev->type) {
-    case VIR_DOMAIN_DEVICE_DISK:
-        ret = prlsdkAttachVolume(privdom, dev->data.disk);
-        if (ret) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("disk attach failed"));
-            goto cleanup;
-        }
-        break;
-    default:
-        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
-                       _("device type '%s' cannot be attached"),
-                       virDomainDeviceTypeToString(dev->type));
-        break;
-    }
-
-    ret = 0;
- cleanup:
-    virObjectUnlock(privdom);
-    return ret;
-}
-
-static int vzDomainAttachDevice(virDomainPtr dom, const char *xml)
-{
-    return vzDomainAttachDeviceFlags(dom, xml,
-                                            VIR_DOMAIN_AFFECT_CONFIG | VIR_DOMAIN_AFFECT_LIVE);
-}
-
-static int vzDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
-                                            unsigned int flags)
-{
-    int ret = -1;
-    vzConnPtr privconn = dom->conn->privateData;
-    virDomainDeviceDefPtr dev = NULL;
-    virDomainObjPtr privdom = NULL;
-    bool domactive = false;
-
-    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
-                  VIR_DOMAIN_AFFECT_CONFIG, -1);
-
-    privdom = vzDomObjFromDomain(dom);
-    if (privdom == NULL)
-        return -1;
-
-    if (!(flags & VIR_DOMAIN_AFFECT_CONFIG)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("device detach needs VIR_DOMAIN_AFFECT_CONFIG "
-                         "flag to be set"));
-        goto cleanup;
-    }
-
-    domactive = virDomainObjIsActive(privdom);
-    if (!domactive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("cannot do live update a device on "
-                         "inactive domain"));
-        goto cleanup;
-    }
-    if (domactive && !(flags & VIR_DOMAIN_AFFECT_LIVE)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("Updates on a running domain need "
-                         "VIR_DOMAIN_AFFECT_LIVE flag"));
-    }
-
-    dev = virDomainDeviceDefParse(xml, privdom->def, privconn->caps,
-                                  privconn->xmlopt, VIR_DOMAIN_XML_INACTIVE);
-    if (dev == NULL)
-        goto cleanup;
-
-    switch (dev->type) {
-    case VIR_DOMAIN_DEVICE_DISK:
-        ret = prlsdkDetachVolume(privdom, dev->data.disk);
-        if (ret) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("disk detach failed"));
-            goto cleanup;
-        }
-        break;
-    default:
-        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
-                       _("device type '%s' cannot be detached"),
-                       virDomainDeviceTypeToString(dev->type));
-        break;
-    }
-
-    ret = 0;
- cleanup:
-    virObjectUnlock(privdom);
-    return ret;
-}
-
-static int vzDomainDetachDevice(virDomainPtr dom, const char *xml)
-{
-    return vzDomainDetachDeviceFlags(dom, xml,
-                                            VIR_DOMAIN_AFFECT_CONFIG | VIR_DOMAIN_AFFECT_LIVE);
-}
-
-static unsigned long long
-vzDomainGetMaxMemory(virDomainPtr domain)
-{
-    virDomainObjPtr dom = NULL;
-    int ret = -1;
-
-    if (!(dom = vzDomObjFromDomain(domain)))
-        return -1;
-
-    ret = dom->def->mem.max_balloon;
-    virObjectUnlock(dom);
-    return ret;
-}
-
-static int
-vzDomainBlockStats(virDomainPtr domain, const char *path,
-                     virDomainBlockStatsPtr stats)
-{
-    virDomainObjPtr dom = NULL;
-    int ret = -1;
-    size_t i;
-    int idx;
-
-    if (!(dom = vzDomObjFromDomainRef(domain)))
-        return -1;
-
-    if (*path) {
-        if ((idx = virDomainDiskIndexByName(dom->def, path, false)) < 0) {
-            virReportError(VIR_ERR_INVALID_ARG, _("invalid path: %s"), path);
-            goto cleanup;
-        }
-        if (prlsdkGetBlockStats(dom, dom->def->disks[idx], stats) < 0)
-            goto cleanup;
-    } else {
-        virDomainBlockStatsStruct s;
-
-#define PARALLELS_ZERO_STATS(VAR, TYPE, NAME)           \
-        stats->VAR = 0;
-
-        PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_ZERO_STATS)
-
-#undef PARALLELS_ZERO_STATS
-
-        for (i = 0; i < dom->def->ndisks; i++) {
-            if (prlsdkGetBlockStats(dom, dom->def->disks[i], &s) < 0)
-                goto cleanup;
-
-#define PARALLELS_SUM_STATS(VAR, TYPE, NAME)        \
-        if (s.VAR != -1)                            \
-           stats->VAR += s.VAR;
-
-            PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_SUM_STATS)
-
-#undef PARALLELS_SUM_STATS
-        }
-    }
-    stats->errs = -1;
-    ret = 0;
-
- cleanup:
-    if (dom)
-        virDomainObjEndAPI(&dom);
-
-    return ret;
-}
-
-static int
-vzDomainBlockStatsFlags(virDomainPtr domain,
-                          const char *path,
-                          virTypedParameterPtr params,
-                          int *nparams,
-                          unsigned int flags)
-{
-    virDomainBlockStatsStruct stats;
-    int ret = -1;
-    size_t i;
-
-    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
-    /* We don't return strings, and thus trivially support this flag.  */
-    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
-
-    if (vzDomainBlockStats(domain, path, &stats) < 0)
-        goto cleanup;
-
-    if (*nparams == 0) {
-#define PARALLELS_COUNT_STATS(VAR, TYPE, NAME)       \
-        if ((stats.VAR) != -1)                       \
-            ++*nparams;
-
-        PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_COUNT_STATS)
-
-#undef PARALLELS_COUNT_STATS
-        ret = 0;
-        goto cleanup;
-    }
-
-    i = 0;
-#define PARALLELS_BLOCK_STATS_ASSIGN_PARAM(VAR, TYPE, NAME)                    \
-    if (i < *nparams && (stats.VAR) != -1) {                                   \
-        if (virTypedParameterAssign(params + i, TYPE,                          \
-                                    VIR_TYPED_PARAM_LLONG, (stats.VAR)) < 0)   \
-            goto cleanup;                                                      \
-        i++;                                                                   \
-    }
-
-    PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_BLOCK_STATS_ASSIGN_PARAM)
-
-#undef PARALLELS_BLOCK_STATS_ASSIGN_PARAM
-
-    *nparams = i;
-    ret = 0;
-
- cleanup:
-    return ret;
-}
-
-
-static virHypervisorDriver vzDriver = {
-    .name = "vz",
-    .connectOpen = vzConnectOpen,            /* 0.10.0 */
-    .connectClose = vzConnectClose,          /* 0.10.0 */
-    .connectGetVersion = vzConnectGetVersion,   /* 0.10.0 */
-    .connectGetHostname = vzConnectGetHostname,      /* 0.10.0 */
-    .nodeGetInfo = vzNodeGetInfo,      /* 0.10.0 */
-    .connectGetCapabilities = vzConnectGetCapabilities,      /* 0.10.0 */
-    .connectBaselineCPU = vzConnectBaselineCPU, /* 1.2.6 */
-    .connectListDomains = vzConnectListDomains,      /* 0.10.0 */
-    .connectNumOfDomains = vzConnectNumOfDomains,    /* 0.10.0 */
-    .connectListDefinedDomains = vzConnectListDefinedDomains,        /* 0.10.0 */
-    .connectNumOfDefinedDomains = vzConnectNumOfDefinedDomains,      /* 0.10.0 */
-    .connectListAllDomains = vzConnectListAllDomains, /* 0.10.0 */
-    .domainLookupByID = vzDomainLookupByID,    /* 0.10.0 */
-    .domainLookupByUUID = vzDomainLookupByUUID,        /* 0.10.0 */
-    .domainLookupByName = vzDomainLookupByName,        /* 0.10.0 */
-    .domainGetOSType = vzDomainGetOSType,    /* 0.10.0 */
-    .domainGetInfo = vzDomainGetInfo,  /* 0.10.0 */
-    .domainGetState = vzDomainGetState,        /* 0.10.0 */
-    .domainGetXMLDesc = vzDomainGetXMLDesc,    /* 0.10.0 */
-    .domainIsPersistent = vzDomainIsPersistent,        /* 0.10.0 */
-    .domainGetAutostart = vzDomainGetAutostart,        /* 0.10.0 */
-    .domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
-    .domainSuspend = vzDomainSuspend,    /* 0.10.0 */
-    .domainResume = vzDomainResume,    /* 0.10.0 */
-    .domainDestroy = vzDomainDestroy,  /* 0.10.0 */
-    .domainShutdown = vzDomainShutdown, /* 0.10.0 */
-    .domainCreate = vzDomainCreate,    /* 0.10.0 */
-    .domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
-    .domainDefineXML = vzDomainDefineXML,      /* 0.10.0 */
-    .domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */
-    .domainUndefine = vzDomainUndefine, /* 1.2.10 */
-    .domainUndefineFlags = vzDomainUndefineFlags, /* 1.2.10 */
-    .domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
-    .domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
-    .domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
-    .domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
-    .domainIsActive = vzDomainIsActive, /* 1.2.10 */
-    .connectDomainEventRegisterAny = vzConnectDomainEventRegisterAny, /* 1.2.10 */
-    .connectDomainEventDeregisterAny = vzConnectDomainEventDeregisterAny, /* 1.2.10 */
-    .nodeGetCPUMap = vzNodeGetCPUMap, /* 1.2.8 */
-    .connectIsEncrypted = vzConnectIsEncrypted, /* 1.2.5 */
-    .connectIsSecure = vzConnectIsSecure, /* 1.2.5 */
-    .connectIsAlive = vzConnectIsAlive, /* 1.2.5 */
-    .domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
-    .domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
-    .domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
-    .domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
-    .domainBlockStats = vzDomainBlockStats, /* 1.3.0 */
-    .domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.3.0 */
-};
-
-static virConnectDriver vzConnectDriver = {
-    .hypervisorDriver = &vzDriver,
-    .storageDriver = &vzStorageDriver,
-    .networkDriver = &vzNetworkDriver,
-};
-
-/* Parallels domain type backward compatibility*/
-static virHypervisorDriver parallelsDriver;
-static virConnectDriver parallelsConnectDriver;
-
-/**
- * vzRegister:
- *
- * Registers the vz driver
- */
-int
-vzRegister(void)
-{
-    char *prlctl_path;
-
-    prlctl_path = virFindFileInPath(PRLCTL);
-    if (!prlctl_path) {
-        VIR_DEBUG("%s", _("Can't find prlctl command in the PATH env"));
-        return 0;
-    }
-
-    VIR_FREE(prlctl_path);
-
-    /* Backward compatibility with Parallels domain type */
-    parallelsDriver = vzDriver;
-    parallelsDriver.name = "Parallels";
-    parallelsConnectDriver = vzConnectDriver;
-    parallelsConnectDriver.hypervisorDriver = &parallelsDriver;
-    if (virRegisterConnectDriver(&parallelsConnectDriver, false) < 0)
-        return -1;
-
-    if (virRegisterConnectDriver(&vzConnectDriver, false) < 0)
-        return -1;
-
-    return 0;
-}
diff --git a/src/parallels/parallels_driver.h b/src/parallels/parallels_driver.h
deleted file mode 100644 (file)
index 173764b..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * parallels_driver.h: core driver functions for managing
- * Parallels Cloud Server hosts
- *
- * Copyright (C) 2012 Parallels, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef PARALLELS_DRIVER_H
-# define PARALLELS_DRIVER_H
-
-int vzRegister(void);
-
-#endif
diff --git a/src/parallels/parallels_network.c b/src/parallels/parallels_network.c
deleted file mode 100644 (file)
index 6e18707..0000000
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * parallels_network.c: core privconn functions for managing
- * Parallels Cloud Server hosts
- *
- * Copyright (C) 2013-2014 Red Hat, Inc.
- * Copyright (C) 2012 Parallels, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <config.h>
-
-#include "datatypes.h"
-#include "dirname.h"
-#include "viralloc.h"
-#include "virerror.h"
-#include "virfile.h"
-#include "virnetdev.h"
-#include "md5.h"
-#include "parallels_utils.h"
-#include "virstring.h"
-
-#define VIR_FROM_THIS VIR_FROM_PARALLELS
-#define PARALLELS_ROUTED_NETWORK_UUID   "eb593dd1-6846-45b0-84a0-de0729286982"
-
-#define vzParseError()                                                  \
-    virReportErrorHelper(VIR_FROM_TEST, VIR_ERR_OPERATION_FAILED, __FILE__,    \
-                     __FUNCTION__, __LINE__, _("Can't parse prlctl output"))
-
-static int vzGetBridgedNetInfo(virNetworkDefPtr def, virJSONValuePtr jobj)
-{
-    const char *ifname;
-    char *bridgeLink = NULL;
-    char *bridgePath = NULL;
-    char *bridgeAddressPath = NULL;
-    char *bridgeAddress = NULL;
-    int len = 0;
-    int ret = -1;
-
-    if (!(ifname = virJSONValueObjectGetString(jobj, "Bound To"))) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (virAsprintf(&bridgeLink, SYSFS_NET_DIR "%s/brport/bridge", ifname) < 0)
-        goto cleanup;
-
-    if (virFileResolveLink(bridgeLink, &bridgePath) < 0) {
-        virReportSystemError(errno, _("cannot read link '%s'"), bridgeLink);
-        goto cleanup;
-    }
-
-    if (VIR_STRDUP(def->bridge, last_component(bridgePath)) < 0)
-        goto cleanup;
-
-    if (virAsprintf(&bridgeAddressPath, SYSFS_NET_DIR "%s/brport/bridge/address",
-                    ifname) < 0)
-        goto cleanup;
-
-    if ((len = virFileReadAll(bridgeAddressPath, 18, &bridgeAddress)) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Error reading file '%s'"), bridgeAddressPath);
-
-        goto cleanup;
-    }
-
-    if (len < VIR_MAC_STRING_BUFLEN) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Error reading MAC from '%s'"), bridgeAddressPath);
-    }
-
-    bridgeAddress[VIR_MAC_STRING_BUFLEN - 1] = '\0';
-    if (virMacAddrParse(bridgeAddress, &def->mac) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Can't parse MAC '%s'"), bridgeAddress);
-        goto cleanup;
-    }
-    def->mac_specified = 1;
-
-    ret = 0;
-
- cleanup:
-    VIR_FREE(bridgeLink);
-    VIR_FREE(bridgePath);
-    VIR_FREE(bridgeAddress);
-    VIR_FREE(bridgeAddressPath);
-    return ret;
-}
-
-static int vzGetHostOnlyNetInfo(virNetworkDefPtr def, const char *name)
-{
-    const char *tmp;
-    virJSONValuePtr jobj = NULL, jobj2;
-    int ret = -1;
-
-    if (VIR_EXPAND_N(def->ips, def->nips, 1) < 0)
-        goto cleanup;
-
-    jobj = vzParseOutput("prlsrvctl", "net", "info", "-j", name, NULL);
-
-    if (!jobj) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (!(jobj2 = virJSONValueObjectGet(jobj, "Parallels adapter"))) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (VIR_STRDUP(def->ips[0].family, "ipv4") < 0)
-        goto cleanup;
-
-    if (!(tmp = virJSONValueObjectGetString(jobj2, "IP address"))) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (virSocketAddrParseIPv4(&def->ips[0].address, tmp) < 0) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (!(tmp = virJSONValueObjectGetString(jobj2, "Subnet mask"))) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (virSocketAddrParseIPv4(&def->ips[0].netmask, tmp) < 0) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (!(jobj2 = virJSONValueObjectGet(jobj, "DHCPv4 server"))) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (VIR_EXPAND_N(def->ips[0].ranges, def->ips[0].nranges, 1) < 0)
-        goto cleanup;
-
-    if (!(tmp = virJSONValueObjectGetString(jobj2, "IP scope start address"))) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (virSocketAddrParseIPv4(&def->ips[0].ranges[0].start, tmp) < 0) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (!(tmp = virJSONValueObjectGetString(jobj2, "IP scope end address"))) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (virSocketAddrParseIPv4(&def->ips[0].ranges[0].end, tmp) < 0) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    ret = 0;
- cleanup:
-    virJSONValueFree(jobj);
-    return ret;
-}
-
-static int
-vzLoadNetwork(vzConnPtr privconn, virJSONValuePtr jobj)
-{
-    int ret = -1;
-    virNetworkObjPtr net = NULL;
-    virNetworkDefPtr def;
-    const char *tmp;
-    /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
-    unsigned char md5[MD5_DIGEST_SIZE];
-
-    if (VIR_ALLOC(def) < 0)
-        goto cleanup;
-
-    if (!(tmp = virJSONValueObjectGetString(jobj, "Network ID"))) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (VIR_STRDUP(def->name, tmp) < 0)
-        goto cleanup;
-
-    /* Network names are unique in Parallels Cloud Server, so we can make
-     * a UUID from it */
-    md5_buffer(tmp, strlen(tmp), md5);
-    memcpy(def->uuid, md5, VIR_UUID_BUFLEN);
-    def->uuid_specified = 1;
-
-    if (!(tmp = virJSONValueObjectGetString(jobj, "Type"))) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (STREQ(tmp, PARALLELS_BRIDGED_NETWORK_TYPE)) {
-        def->forward.type = VIR_NETWORK_FORWARD_BRIDGE;
-
-        if (vzGetBridgedNetInfo(def, jobj) < 0) {
-
-            /* Only mandatory networks are required to be configured completely */
-            if (STRNEQ(def->name, PARALLELS_REQUIRED_BRIDGED_NETWORK))
-                ret = 0;
-
-            goto cleanup;
-        }
-    } else if (STREQ(tmp, PARALLELS_HOSTONLY_NETWORK_TYPE)) {
-        def->forward.type = VIR_NETWORK_FORWARD_NONE;
-
-        if (vzGetHostOnlyNetInfo(def, def->name) < 0) {
-
-            /* Only mandatory networks are required to be configured completely */
-            if (STRNEQ(def->name, PARALLELS_REQUIRED_HOSTONLY_NETWORK))
-                ret = 0;
-
-            goto cleanup;
-        }
-    } else {
-        vzParseError();
-        goto cleanup;
-    }
-
-    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
-        goto cleanup;
-    def = NULL;
-    net->active = 1;
-    net->autostart = 1;
-    ret = 0;
-
- cleanup:
-    virNetworkObjEndAPI(&net);
-    virNetworkDefFree(def);
-    return ret;
-}
-
-static int
-vzAddRoutedNetwork(vzConnPtr privconn)
-{
-    virNetworkObjPtr net = NULL;
-    virNetworkDefPtr def;
-
-    if (VIR_ALLOC(def) < 0)
-        goto cleanup;
-
-    def->forward.type = VIR_NETWORK_FORWARD_ROUTE;
-
-    if (VIR_STRDUP(def->name, PARALLELS_DOMAIN_ROUTED_NETWORK_NAME) < 0)
-        goto cleanup;
-
-    if (virUUIDParse(PARALLELS_ROUTED_NETWORK_UUID, def->uuid) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("Can't parse UUID"));
-        goto cleanup;
-    }
-    def->uuid_specified = 1;
-
-    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
-        goto cleanup;
-
-    net->active = 1;
-    net->autostart = 1;
-    virNetworkObjEndAPI(&net);
-
-    return 0;
-
- cleanup:
-    virNetworkDefFree(def);
-    return -1;
-}
-
-static int vzLoadNetworks(vzConnPtr privconn)
-{
-    virJSONValuePtr jobj, jobj2;
-    int ret = -1;
-    int count;
-    size_t i;
-
-    jobj = vzParseOutput("prlsrvctl", "net", "list", "-j", NULL);
-
-    if (!jobj) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    count = virJSONValueArraySize(jobj);
-    if (count < 0) {
-        vzParseError();
-        goto cleanup;
-    }
-
-    for (i = 0; i < count; i++) {
-        jobj2 = virJSONValueArrayGet(jobj, i);
-        if (!jobj2) {
-            vzParseError();
-            goto cleanup;
-        }
-
-        if (vzLoadNetwork(privconn, jobj2) < 0)
-            goto cleanup;
-    }
-
-    if (vzAddRoutedNetwork(privconn) < 0)
-        goto cleanup;
-
-    ret = 0;
-
- cleanup:
-    virJSONValueFree(jobj);
-    return ret;
-}
-
-virDrvOpenStatus
-vzNetworkOpen(virConnectPtr conn,
-                     unsigned int flags)
-{
-    vzConnPtr privconn = conn->privateData;
-
-    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
-
-    if (STRNEQ(conn->driver->name, "vz") &&
-        STRNEQ(conn->driver->name, "Parallels"))
-        return VIR_DRV_OPEN_DECLINED;
-
-    if (!(privconn->networks = virNetworkObjListNew()))
-        goto error;
-
-    if (vzLoadNetworks(conn->privateData) < 0)
-        goto error;
-
-    return VIR_DRV_OPEN_SUCCESS;
- error:
-    virObjectUnref(privconn->networks);
-    privconn->networks = NULL;
-    return VIR_DRV_OPEN_ERROR;
-}
-
-int vzNetworkClose(virConnectPtr conn)
-{
-    vzConnPtr privconn = conn->privateData;
-
-    if (!privconn)
-        return 0;
-
-    virObjectUnref(privconn->networks);
-    return 0;
-}
-
-static int vzConnectNumOfNetworks(virConnectPtr conn)
-{
-    int nactive;
-    vzConnPtr privconn = conn->privateData;
-
-    nactive = virNetworkObjListNumOfNetworks(privconn->networks,
-                                             true, NULL, conn);
-    return nactive;
-}
-
-static int vzConnectListNetworks(virConnectPtr conn,
-                                        char **const names,
-                                        int nnames)
-{
-    vzConnPtr privconn = conn->privateData;
-    int got;
-
-    got = virNetworkObjListGetNames(privconn->networks,
-                                    true, names, nnames, NULL, conn);
-    return got;
-}
-
-static int vzConnectNumOfDefinedNetworks(virConnectPtr conn)
-{
-    int ninactive;
-    vzConnPtr privconn = conn->privateData;
-
-    ninactive = virNetworkObjListNumOfNetworks(privconn->networks,
-                                               false, NULL, conn);
-    return ninactive;
-}
-
-static int vzConnectListDefinedNetworks(virConnectPtr conn,
-                                               char **const names,
-                                               int nnames)
-{
-    vzConnPtr privconn = conn->privateData;
-    int got;
-
-    got = virNetworkObjListGetNames(privconn->networks,
-                                    false, names, nnames, NULL, conn);
-    return got;
-}
-
-static int vzConnectListAllNetworks(virConnectPtr conn,
-                                           virNetworkPtr **nets,
-                                           unsigned int flags)
-{
-    vzConnPtr privconn = conn->privateData;
-
-    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);
-
-    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
-}
-
-static virNetworkPtr vzNetworkLookupByUUID(virConnectPtr conn,
-                                                  const unsigned char *uuid)
-{
-    vzConnPtr privconn = conn->privateData;
-    virNetworkObjPtr network;
-    virNetworkPtr ret = NULL;
-
-    network = virNetworkObjFindByUUID(privconn->networks, uuid);
-    if (!network) {
-        virReportError(VIR_ERR_NO_NETWORK,
-                       "%s", _("no network with matching uuid"));
-        goto cleanup;
-    }
-
-    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
-
- cleanup:
-    virNetworkObjEndAPI(&network);
-    return ret;
-}
-
-static virNetworkPtr vzNetworkLookupByName(virConnectPtr conn,
-                                                  const char *name)
-{
-    vzConnPtr privconn = conn->privateData;
-    virNetworkObjPtr network;
-    virNetworkPtr ret = NULL;
-
-    network = virNetworkObjFindByName(privconn->networks, name);
-    if (!network) {
-        virReportError(VIR_ERR_NO_NETWORK,
-                       _("no network with matching name '%s'"), name);
-        goto cleanup;
-    }
-
-    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
-
- cleanup:
-    virNetworkObjEndAPI(&network);
-    return ret;
-}
-
-static char *vzNetworkGetXMLDesc(virNetworkPtr net,
-                                        unsigned int flags)
-{
-    vzConnPtr privconn = net->conn->privateData;
-    virNetworkObjPtr network;
-    char *ret = NULL;
-
-    virCheckFlags(VIR_NETWORK_XML_INACTIVE, NULL);
-
-    network = virNetworkObjFindByUUID(privconn->networks, net->uuid);
-    if (!network) {
-        virReportError(VIR_ERR_NO_NETWORK,
-                       "%s", _("no network with matching uuid"));
-        goto cleanup;
-    }
-
-    ret = virNetworkDefFormat(network->def, flags);
-
- cleanup:
-    virNetworkObjEndAPI(&network);
-    return ret;
-}
-
-static int vzNetworkIsActive(virNetworkPtr net)
-{
-    vzConnPtr privconn = net->conn->privateData;
-    virNetworkObjPtr obj;
-    int ret = -1;
-
-    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NETWORK, NULL);
-        goto cleanup;
-    }
-    ret = virNetworkObjIsActive(obj);
-
- cleanup:
-    virNetworkObjEndAPI(&obj);
-    return ret;
-}
-
-static int vzNetworkIsPersistent(virNetworkPtr net)
-{
-    vzConnPtr privconn = net->conn->privateData;
-    virNetworkObjPtr obj;
-    int ret = -1;
-
-    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NETWORK, NULL);
-        goto cleanup;
-    }
-    ret = obj->persistent;
-
- cleanup:
-    virNetworkObjEndAPI(&obj);
-    return ret;
-}
-
-static int vzNetworkGetAutostart(virNetworkPtr net,
-                                 int *autostart)
-{
-    vzConnPtr privconn = net->conn->privateData;
-    virNetworkObjPtr network;
-    int ret = -1;
-
-    network = virNetworkObjFindByUUID(privconn->networks, net->uuid);
-    if (!network) {
-        virReportError(VIR_ERR_NO_NETWORK,
-                       "%s", _("no network with matching uuid"));
-        goto cleanup;
-    }
-
-    *autostart = network->autostart;
-    ret = 0;
-
- cleanup:
-    virNetworkObjEndAPI(&network);
-    return ret;
-}
-
-virNetworkDriver vzNetworkDriver = {
-    .name = "Parallels",
-    .connectNumOfNetworks = vzConnectNumOfNetworks, /* 1.0.1 */
-    .connectListNetworks = vzConnectListNetworks, /* 1.0.1 */
-    .connectNumOfDefinedNetworks = vzConnectNumOfDefinedNetworks, /* 1.0.1 */
-    .connectListDefinedNetworks = vzConnectListDefinedNetworks, /* 1.0.1 */
-    .connectListAllNetworks = vzConnectListAllNetworks, /* 1.0.1 */
-    .networkLookupByUUID = vzNetworkLookupByUUID, /* 1.0.1 */
-    .networkLookupByName = vzNetworkLookupByName, /* 1.0.1 */
-    .networkGetXMLDesc = vzNetworkGetXMLDesc, /* 1.0.1 */
-    .networkGetAutostart = vzNetworkGetAutostart, /* 1.0.1 */
-    .networkIsActive = vzNetworkIsActive, /* 1.0.1 */
-    .networkIsPersistent = vzNetworkIsPersistent, /* 1.0.1 */
-};
diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c
deleted file mode 100644 (file)
index 4dafe7c..0000000
+++ /dev/null
@@ -1,3660 +0,0 @@
-/*
- * parallels_sdk.c: core driver functions for managing
- * Parallels Cloud Server hosts
- *
- * Copyright (C) 2014 Parallels, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <config.h>
-#include <stdarg.h>
-
-#include "virerror.h"
-#include "viralloc.h"
-#include "virstring.h"
-#include "nodeinfo.h"
-#include "virlog.h"
-#include "datatypes.h"
-#include "domain_conf.h"
-#include "virtime.h"
-
-#include "parallels_sdk.h"
-
-#define VIR_FROM_THIS VIR_FROM_PARALLELS
-#define JOB_INFINIT_WAIT_TIMEOUT UINT_MAX
-
-VIR_LOG_INIT("parallels.sdk");
-
-/*
- * Log error description
- */
-static void
-logPrlErrorHelper(PRL_RESULT err, const char *filename,
-                  const char *funcname, size_t linenr)
-{
-    char *msg1 = NULL, *msg2 = NULL;
-    PRL_UINT32 len = 0;
-
-    /* Get required buffer length */
-    PrlApi_GetResultDescription(err, PRL_TRUE, PRL_FALSE, NULL, &len);
-
-    if (VIR_ALLOC_N(msg1, len) < 0)
-        goto cleanup;
-
-    /* get short error description */
-    PrlApi_GetResultDescription(err, PRL_TRUE, PRL_FALSE, msg1, &len);
-
-    PrlApi_GetResultDescription(err, PRL_FALSE, PRL_FALSE, NULL, &len);
-
-    if (VIR_ALLOC_N(msg2, len) < 0)
-        goto cleanup;
-
-    /* get long error description */
-    PrlApi_GetResultDescription(err, PRL_FALSE, PRL_FALSE, msg2, &len);
-
-    virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INTERNAL_ERROR,
-                         filename, funcname, linenr,
-                         _("%s %s"), msg1, msg2);
-
- cleanup:
-    VIR_FREE(msg1);
-    VIR_FREE(msg2);
-}
-
-#define logPrlError(code)                          \
-    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)
-{
-    PRL_RESULT ret, retCode;
-    char *msg1 = NULL, *msg2 = NULL;
-    PRL_UINT32 len = 0;
-    int err = -1;
-
-    if ((ret = PrlEvent_GetErrCode(event, &retCode))) {
-        logPrlError(ret);
-        return ret;
-    }
-
-    PrlEvent_GetErrString(event, PRL_TRUE, PRL_FALSE, NULL, &len);
-
-    if (VIR_ALLOC_N(msg1, len) < 0)
-        goto cleanup;
-
-    PrlEvent_GetErrString(event, PRL_TRUE, PRL_FALSE, msg1, &len);
-
-    PrlEvent_GetErrString(event, PRL_FALSE, PRL_FALSE, NULL, &len);
-
-    if (VIR_ALLOC_N(msg2, len) < 0)
-        goto cleanup;
-
-    PrlEvent_GetErrString(event, PRL_FALSE, PRL_FALSE, msg2, &len);
-
-    virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INTERNAL_ERROR,
-                         filename, funcname, linenr,
-                         _("%s %s"), msg1, msg2);
-    err = 0;
-
- cleanup:
-    VIR_FREE(msg1);
-    VIR_FREE(msg2);
-
-    return err;
-}
-
-#define logPrlEventError(event)                    \
-    logPrlEventErrorHelper(event, __FILE__,        \
-                         __FUNCTION__, __LINE__)
-
-static PRL_RESULT
-getJobResultHelper(PRL_HANDLE job, unsigned int timeout, PRL_HANDLE *result,
-                   const char *filename, const char *funcname,
-                   size_t linenr)
-{
-    PRL_RESULT ret, retCode;
-
-    if ((ret = PrlJob_Wait(job, timeout))) {
-        logPrlErrorHelper(ret, filename, funcname, linenr);
-        goto cleanup;
-    }
-
-    if ((ret = PrlJob_GetRetCode(job, &retCode))) {
-        logPrlErrorHelper(ret, filename, funcname, linenr);
-        goto cleanup;
-    }
-
-    if (retCode) {
-        PRL_HANDLE err_handle;
-
-        /* Sometimes it's possible to get additional error info. */
-        if ((ret = PrlJob_GetError(job, &err_handle))) {
-            logPrlErrorHelper(ret, filename, funcname, linenr);
-            goto cleanup;
-        }
-
-        if (logPrlEventErrorHelper(err_handle, filename, funcname, linenr))
-            logPrlErrorHelper(retCode, filename, funcname, linenr);
-
-        PrlHandle_Free(err_handle);
-        ret = retCode;
-    } else {
-        ret = PrlJob_GetResult(job, result);
-        if (PRL_FAILED(ret)) {
-            logPrlErrorHelper(ret, filename, funcname, linenr);
-            PrlHandle_Free(*result);
-            *result = NULL;
-            goto cleanup;
-        }
-
-        ret = PRL_ERR_SUCCESS;
-    }
-
- cleanup:
-    PrlHandle_Free(job);
-    return ret;
-}
-
-#define getJobResult(job, result)                       \
-    getJobResultHelper(job, JOB_INFINIT_WAIT_TIMEOUT,   \
-            result, __FILE__, __FUNCTION__, __LINE__)
-
-static PRL_RESULT
-waitJobHelper(PRL_HANDLE job, unsigned int timeout,
-              const char *filename, const char *funcname,
-              size_t linenr)
-{
-    PRL_HANDLE result = PRL_INVALID_HANDLE;
-    PRL_RESULT ret;
-
-    ret = getJobResultHelper(job, timeout, &result,
-                             filename, funcname, linenr);
-    PrlHandle_Free(result);
-    return ret;
-}
-
-#define waitJob(job)                                        \
-    waitJobHelper(job, JOB_INFINIT_WAIT_TIMEOUT, __FILE__,  \
-                         __FUNCTION__, __LINE__)
-
-
-int
-prlsdkInit(void)
-{
-    PRL_RESULT ret;
-
-    /* Disable console output */
-    PrlApi_SwitchConsoleLogging(0);
-
-    ret = PrlApi_InitEx(PARALLELS_API_VER, PAM_SERVER, 0, 0);
-    if (PRL_FAILED(ret)) {
-        logPrlError(ret);
-        return -1;
-    }
-
-    return 0;
-};
-
-void
-prlsdkDeinit(void)
-{
-    PrlApi_Deinit();
-};
-
-int
-prlsdkConnect(vzConnPtr privconn)
-{
-    PRL_RESULT ret;
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-
-    ret = PrlSrv_Create(&privconn->server);
-    if (PRL_FAILED(ret)) {
-        logPrlError(ret);
-        return -1;
-    }
-
-    job = PrlSrv_LoginLocalEx(privconn->server, NULL, 0,
-                              PSL_HIGH_SECURITY, PACF_NON_INTERACTIVE_MODE);
-
-    if (waitJob(job)) {
-        PrlHandle_Free(privconn->server);
-        return -1;
-    }
-
-    return 0;
-}
-
-void
-prlsdkDisconnect(vzConnPtr privconn)
-{
-    PRL_HANDLE job;
-
-    job = PrlSrv_Logoff(privconn->server);
-    waitJob(job);
-
-    PrlHandle_Free(privconn->server);
-}
-
-static int
-prlsdkSdkDomainLookup(vzConnPtr 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 (PRL_FAILED(getJobResult(job, &result)))
-        goto cleanup;
-
-    pret = PrlResult_GetParamByIndex(result, 0, sdkdom);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    ret = 0;
-
- cleanup:
-    PrlHandle_Free(result);
-    return ret;
-}
-
-static void
-prlsdkUUIDFormat(const unsigned char *uuid, char *uuidstr)
-{
-    virUUIDFormat(uuid, uuidstr + 1);
-
-    uuidstr[0] = '{';
-    uuidstr[VIR_UUID_STRING_BUFLEN] = '}';
-    uuidstr[VIR_UUID_STRING_BUFLEN + 1] = '\0';
-}
-
-static PRL_HANDLE
-prlsdkSdkDomainLookupByUUID(vzConnPtr privconn, const unsigned char *uuid)
-{
-    char uuidstr[VIR_UUID_STRING_BUFLEN + 2];
-    PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
-
-    prlsdkUUIDFormat(uuid, uuidstr);
-
-    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(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 (PRL_FAILED(getJobResult(job, &result)))
-        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)
-{
-    vzDomObjPtr pdom = p;
-
-    if (!pdom)
-        return;
-
-    PrlHandle_Free(pdom->sdkdom);
-    PrlHandle_Free(pdom->cache.stats);
-    virCondDestroy(&pdom->cache.cond);
-    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,
-                  bool isCdrom,
-                  bool isCt)
-{
-    char *buf = NULL;
-    PRL_UINT32 buflen = 0;
-    PRL_RESULT pret;
-    PRL_UINT32 emulatedType;
-    PRL_UINT32 ifType;
-    PRL_UINT32 pos;
-    virDomainDeviceDriveAddressPtr address;
-    int ret = -1;
-
-    pret = PrlVmDev_GetEmulatedType(prldisk, &emulatedType);
-    prlsdkCheckRetGoto(pret, cleanup);
-    if (emulatedType == PDT_USE_IMAGE_FILE) {
-        virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
-        if (isCdrom)
-            virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
-        else
-            virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_PLOOP);
-    } else {
-        virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
-        virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
-    }
-
-    if (isCdrom) {
-        disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
-        disk->src->readonly = true;
-    } else {
-        disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
-    }
-
-    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;
-
-    /* Let physical devices added to CT look like SATA disks */
-    if (isCt) {
-        ifType = PMS_SATA_DEVICE;
-    } else {
-        pret = PrlVmDev_GetIfaceType(prldisk, &ifType);
-        prlsdkCheckRetGoto(pret, cleanup);
-    }
-
-    pret = PrlVmDev_GetStackIndex(prldisk, &pos);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    address = &disk->info.addr.drive;
-    switch (ifType) {
-    case PMS_IDE_DEVICE:
-        disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-        disk->dst = virIndexToDiskName(pos, "hd");
-        address->bus = pos / 2;
-        address->target = 0;
-        address->unit = pos % 2;
-        break;
-    case PMS_SCSI_DEVICE:
-        disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
-        disk->dst = virIndexToDiskName(pos, "sd");
-        address->bus = 0;
-        address->target = 0;
-        address->unit = pos;
-        break;
-    case PMS_SATA_DEVICE:
-        disk->bus = VIR_DOMAIN_DISK_BUS_SATA;
-        disk->dst = virIndexToDiskName(pos, "sd");
-        address->bus = 0;
-        address->target = 0;
-        address->unit = pos;
-        break;
-    default:
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Unknown disk bus: %X"), ifType);
-        goto cleanup;
-        break;
-    }
-
-    if (!disk->dst)
-        goto cleanup;
-
-    disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
-
-    ret = 0;
-
- cleanup:
-    VIR_FREE(buf);
-    return ret;
-}
-
-static int
-prlsdkGetFSInfo(PRL_HANDLE prldisk,
-                virDomainFSDefPtr fs)
-{
-    char *buf = NULL;
-    PRL_UINT32 buflen = 0;
-    PRL_RESULT pret;
-    int ret = -1;
-
-    fs->type = VIR_DOMAIN_FS_TYPE_FILE;
-    fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP;
-    fs->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH;
-    fs->wrpolicy = VIR_DOMAIN_FS_WRPOLICY_DEFAULT;
-    fs->format = VIR_STORAGE_FILE_PLOOP;
-
-    fs->readonly = false;
-    fs->symlinksResolved = false;
-
-    pret = PrlVmDev_GetImagePath(prldisk, NULL, &buflen);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    if (VIR_ALLOC_N(buf, buflen) < 0)
-        goto cleanup;
-
-    pret = PrlVmDev_GetImagePath(prldisk, buf, &buflen);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    fs->src = buf;
-    buf = NULL;
-
-    pret = PrlVmDevHd_GetMountPoint(prldisk, NULL, &buflen);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    if (VIR_ALLOC_N(buf, buflen) < 0)
-        goto cleanup;
-
-    pret = PrlVmDevHd_GetMountPoint(prldisk, buf, &buflen);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    fs->dst = buf;
-    buf = NULL;
-
-    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;
-    virDomainFSDefPtr fs = NULL;
-
-    pret = PrlVmCfg_GetHardDisksCount(sdkdom, &hddCount);
-    prlsdkCheckRetGoto(pret, error);
-
-    for (i = 0; i < hddCount; ++i) {
-
-        PRL_UINT32 emulatedType;
-
-        pret = PrlVmCfg_GetHardDisk(sdkdom, i, &hdd);
-        prlsdkCheckRetGoto(pret, error);
-
-        pret = PrlVmDev_GetEmulatedType(hdd, &emulatedType);
-        prlsdkCheckRetGoto(pret, error);
-
-        if (PDT_USE_REAL_DEVICE != emulatedType && IS_CT(def)) {
-
-            if (VIR_ALLOC(fs) < 0)
-                goto error;
-
-            if (prlsdkGetFSInfo(hdd, fs) < 0)
-                goto error;
-
-            if (virDomainFSInsert(def, fs) < 0)
-                goto error;
-
-            fs = NULL;
-            PrlHandle_Free(hdd);
-            hdd = PRL_INVALID_HANDLE;
-        } else {
-            if (!(disk = virDomainDiskDefNew(NULL)))
-                goto error;
-
-            if (prlsdkGetDiskInfo(hdd, disk, false, IS_CT(def)) < 0)
-                goto error;
-
-            if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
-                goto error;
-
-            disk = NULL;
-            PrlHandle_Free(hdd);
-            hdd = PRL_INVALID_HANDLE;
-        }
-    }
-
-    return 0;
-
- error:
-    PrlHandle_Free(hdd);
-    virDomainDiskDefFree(disk);
-    virDomainFSDefFree(fs);
-    return -1;
-}
-
-static int
-prlsdkAddDomainOpticalDisksInfo(PRL_HANDLE sdkdom, virDomainDefPtr def)
-{
-    PRL_RESULT pret;
-    PRL_UINT32 cdromsCount;
-    PRL_UINT32 i;
-    PRL_HANDLE cdrom = PRL_INVALID_HANDLE;
-    virDomainDiskDefPtr disk = NULL;
-
-    pret = PrlVmCfg_GetOpticalDisksCount(sdkdom, &cdromsCount);
-    prlsdkCheckRetGoto(pret, error);
-
-    for (i = 0; i < cdromsCount; ++i) {
-        pret = PrlVmCfg_GetOpticalDisk(sdkdom, i, &cdrom);
-        prlsdkCheckRetGoto(pret, error);
-
-        if (!(disk = virDomainDiskDefNew(NULL)))
-            goto error;
-
-        if (prlsdkGetDiskInfo(cdrom, disk, true, IS_CT(def)) < 0)
-            goto error;
-
-        PrlHandle_Free(cdrom);
-        cdrom = PRL_INVALID_HANDLE;
-
-        if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
-            goto error;
-    }
-
-    return 0;
-
- error:
-    PrlHandle_Free(cdrom);
-    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 = 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);
-
-    pret = PrlVmDev_GetIndex(netAdapter, &netAdapterIndex);
-    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_DOMAIN_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_DOMAIN_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);
-
-        /*
-         * We use VIR_DOMAIN_NET_TYPE_NETWORK for all network adapters
-         * except those whose Virtual Network Id differ from Parallels
-         * predefined ones such as PARALLELS_DOMAIN_BRIDGED_NETWORK_NAME
-         * and PARALLELS_DONAIN_ROUTED_NETWORK_NAME
-         */
-        if (STRNEQ(net->data.network.name, PARALLELS_DOMAIN_BRIDGED_NETWORK_NAME))
-            net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
-
-    }
-
-    if (!isCt) {
-        PRL_VM_NET_ADAPTER_TYPE type;
-        pret = PrlVmDevNet_GetAdapterType(netAdapter, &type);
-        prlsdkCheckRetGoto(pret, cleanup);
-
-        switch (type) {
-        case PNT_RTL:
-            if (VIR_STRDUP(net->model, "rtl8139") < 0)
-                goto cleanup;
-            break;
-        case PNT_E1000:
-            if (VIR_STRDUP(net->model, "e1000") < 0)
-                goto cleanup;
-            break;
-        case PNT_VIRTIO:
-            if (VIR_STRDUP(net->model, "virtio") < 0)
-                goto cleanup;
-            break;
-        default:
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Unknown adapter type: %X"), type);
-            goto 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 (prlsdkAddDomainOpticalDisksInfo(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;
-
-    if (IS_CT(def)) {
-        virDomainVideoDefPtr video;
-        if (VIR_ALLOC(video) < 0)
-            goto error;
-        video->type = virDomainVideoDefaultType(def);
-        if (video->type < 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("cannot determine default video type"));
-            VIR_FREE(video);
-            goto error;
-        }
-        video->vram = virDomainVideoDefaultRAM(def, video->type);
-        video->heads = 1;
-        if (VIR_ALLOC_N(def->videos, 1) < 0) {
-            virDomainVideoDefFree(video);
-            goto error;
-        }
-        def->videos[def->nvideos++] = video;
-    }
-    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)
-{
-    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 (!(def->cpumask = virBitmapNew(hostcpus)))
-            goto cleanup;
-        virBitmapSetAll(def->cpumask);
-    } else {
-        if (virBitmapParse(buf, 0, &def->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:
-        def->os.type = VIR_DOMAIN_OSTYPE_HVM;
-        break;
-    case PVT_CT:
-        def->os.type = VIR_DOMAIN_OSTYPE_EXE;
-        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(vzConnPtr privconn,
-                 PRL_HANDLE sdkdom,
-                 virDomainObjPtr olddom)
-{
-    virDomainObjPtr dom = NULL;
-    virDomainDefPtr def = NULL;
-    vzDomObjPtr 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 (!(def = virDomainDefNew()))
-        goto error;
-
-    if (!olddom) {
-        if (VIR_ALLOC(pdom) < 0)
-            goto error;
-    } else {
-        pdom = olddom->privateData;
-    }
-
-    if (STREQ(privconn->drivername, "vz"))
-        def->virtType = VIR_DOMAIN_VIRT_VZ;
-    else
-        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;
-
-    pdom->cache.stats = PRL_INVALID_HANDLE;
-    pdom->cache.count = -1;
-    if (virCondInit(&pdom->cache.cond) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot initialize condition"));
-        goto error;
-    }
-
-    if (prlsdkGetDomainIds(sdkdom, &def->name, def->uuid) < 0)
-        goto error;
-
-    def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
-    def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
-    def->onCrash = VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY;
-
-    /* get RAM parameters */
-    pret = PrlVmCfg_GetRamSize(sdkdom, &ram);
-    prlsdkCheckRetGoto(pret, error);
-    virDomainDefSetMemoryInitial(def, ram << 10); /* RAM size obtained in Mbytes,
-                                                     convert to Kbytes */
-    def->mem.cur_balloon = ram << 10;
-
-    if (prlsdkConvertCpuInfo(sdkdom, def) < 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);
-
-    /* For VMs pdom->home is actually /directory/config.pvs */
-    if (!IS_CT(def)) {
-        /* Get rid of /config.pvs in path string */
-        char *s = strrchr(pdom->home, '/');
-        if (s)
-            *s = '\0';
-    }
-
-    pret = PrlVmCfg_GetAutoStart(sdkdom, &autostart);
-    prlsdkCheckRetGoto(pret, error);
-
-    if (prlsdkGetDomainState(sdkdom, &domainState) < 0)
-        goto error;
-
-    if (virDomainDefAddImplicitControllers(def) < 0)
-        goto error;
-
-    if (def->ngraphics > 0) {
-        int bus = IS_CT(def) ? VIR_DOMAIN_INPUT_BUS_PARALLELS:
-                                VIR_DOMAIN_INPUT_BUS_PS2;
-
-        if (virDomainDefMaybeAddInput(def,
-                                      VIR_DOMAIN_INPUT_TYPE_MOUSE,
-                                      bus) < 0)
-            goto error;
-
-        if (virDomainDefMaybeAddInput(def,
-                                      VIR_DOMAIN_INPUT_TYPE_KBD,
-                                      bus) < 0)
-            goto 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);
-        dom->def = 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;
-
-    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 (prlsdkConvertDomainState(domainState, envId, dom) < 0)
-        goto error;
-
-    if (!pdom->sdkdom) {
-        pret = PrlHandle_AddRef(sdkdom);
-        prlsdkCheckRetGoto(pret, error);
-        pdom->sdkdom = sdkdom;
-    }
-
-    return dom;
- error:
-    if (dom && !olddom) {
-        /* Domain isn't persistent means that we haven't yet set
-         * prlsdkDomObjFreePrivate and should call it manually
-         */
-        if (!dom->persistent)
-            prlsdkDomObjFreePrivate(pdom);
-
-        virDomainObjListRemove(privconn->domains, dom);
-    }
-    /* Delete newly allocated def only if we haven't assigned it to domain
-     * Otherwise we will end up with domain having invalid def within it
-     */
-    if (!dom)
-        virDomainDefFree(def);
-
-    return NULL;
-}
-
-int
-prlsdkLoadDomains(vzConnPtr 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 (PRL_FAILED(getJobResult(job, &result)))
-        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);
-    return -1;
-}
-
-virDomainObjPtr
-prlsdkAddDomain(vzConnPtr 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;
-}
-
-int
-prlsdkUpdateDomain(vzConnPtr privconn, virDomainObjPtr dom)
-{
-    PRL_HANDLE job;
-    virDomainObjPtr retdom = NULL;
-    vzDomObjPtr pdom = dom->privateData;
-
-    job = PrlVm_RefreshConfig(pdom->sdkdom);
-    if (waitJob(job))
-        return -1;
-
-    retdom = prlsdkLoadDomain(privconn, pdom->sdkdom, dom);
-    return retdom ? 0 : -1;
-}
-
-static int prlsdkSendEvent(vzConnPtr privconn,
-                           virDomainObjPtr dom,
-                           virDomainEventType lvEventType,
-                           int lvEventTypeDetails)
-{
-    virObjectEventPtr event = NULL;
-
-    event = virDomainEventLifecycleNewFromObj(dom,
-                                              lvEventType,
-                                              lvEventTypeDetails);
-    if (!event)
-        return -1;
-
-    virObjectEventStateQueue(privconn->domainEventState, event);
-    return 0;
-}
-
-static void
-prlsdkNewStateToEvent(VIRTUAL_MACHINE_STATE domainState,
-                      virDomainEventType *lvEventType,
-                      int *lvEventTypeDetails)
-{
-    /* We skip all intermediate states here, because
-     * libvirt doesn't have correspoding event types for
-     * them */
-    switch (domainState) {
-    case VMS_STOPPED:
-    case VMS_MOUNTED:
-        *lvEventType = VIR_DOMAIN_EVENT_STOPPED;
-        *lvEventTypeDetails = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
-        break;
-    case VMS_RUNNING:
-        *lvEventType = VIR_DOMAIN_EVENT_STARTED;
-        *lvEventTypeDetails = VIR_DOMAIN_EVENT_STARTED_BOOTED;
-        break;
-    case VMS_PAUSED:
-        *lvEventType = VIR_DOMAIN_EVENT_SUSPENDED;
-        *lvEventTypeDetails = VIR_DOMAIN_EVENT_SUSPENDED_PAUSED;
-        break;
-    case VMS_SUSPENDED:
-        *lvEventType = VIR_DOMAIN_EVENT_STOPPED;
-        *lvEventTypeDetails = VIR_DOMAIN_EVENT_STOPPED_SAVED;
-        break;
-    default:
-        VIR_DEBUG("Skip sending event about changing state to %X",
-                  domainState);
-        break;
-    }
-}
-
-static void
-prlsdkHandleVmStateEvent(vzConnPtr privconn,
-                         PRL_HANDLE prlEvent,
-                         unsigned char *uuid)
-{
-    PRL_RESULT pret = PRL_ERR_FAILURE;
-    PRL_HANDLE eventParam = PRL_INVALID_HANDLE;
-    PRL_INT32 domainState;
-    virDomainObjPtr dom = NULL;
-    vzDomObjPtr pdom;
-    virDomainEventType lvEventType = 0;
-    int lvEventTypeDetails = 0;
-
-    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
-    if (dom == NULL)
-        return;
-
-    pret = PrlEvent_GetParamByName(prlEvent, "vminfo_vm_state", &eventParam);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlEvtPrm_ToInt32(eventParam, &domainState);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pdom = dom->privateData;
-    if (prlsdkConvertDomainState(domainState, pdom->id, dom) < 0)
-        goto cleanup;
-
-    prlsdkNewStateToEvent(domainState,
-                          &lvEventType,
-                          &lvEventTypeDetails);
-
-    prlsdkSendEvent(privconn, dom, lvEventType, lvEventTypeDetails);
-
- cleanup:
-    virObjectUnlock(dom);
-    return;
-}
-
-static void
-prlsdkHandleVmConfigEvent(vzConnPtr privconn,
-                          unsigned char *uuid)
-{
-    virDomainObjPtr dom = NULL;
-
-    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
-    if (dom == NULL)
-        return;
-
-    if (prlsdkUpdateDomain(privconn, dom) < 0)
-        goto cleanup;
-
-    prlsdkSendEvent(privconn, dom, VIR_DOMAIN_EVENT_DEFINED,
-                        VIR_DOMAIN_EVENT_DEFINED_UPDATED);
-
- cleanup:
-    virObjectUnlock(dom);
-    return;
-}
-
-static void
-prlsdkHandleVmAddedEvent(vzConnPtr privconn,
-                       unsigned char *uuid)
-{
-    virDomainObjPtr dom = NULL;
-
-    dom = prlsdkAddDomain(privconn, uuid);
-    if (dom == NULL)
-        return;
-
-    prlsdkSendEvent(privconn, dom, VIR_DOMAIN_EVENT_DEFINED,
-                        VIR_DOMAIN_EVENT_DEFINED_ADDED);
-
-    virObjectUnlock(dom);
-    return;
-}
-
-static void
-prlsdkHandleVmRemovedEvent(vzConnPtr privconn,
-                           unsigned char *uuid)
-{
-    virDomainObjPtr dom = NULL;
-
-    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
-    /* domain was removed from the list from the libvirt
-     * API function in current connection */
-    if (dom == NULL)
-        return;
-
-    prlsdkSendEvent(privconn, dom, VIR_DOMAIN_EVENT_UNDEFINED,
-                        VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
-
-    virDomainObjListRemove(privconn->domains, dom);
-    return;
-}
-
-#define PARALLELS_STATISTICS_DROP_COUNT 3
-
-static PRL_RESULT
-prlsdkHandlePerfEvent(vzConnPtr privconn,
-                           PRL_HANDLE event,
-                           unsigned char *uuid)
-{
-    virDomainObjPtr dom = NULL;
-    vzDomObjPtr privdom = NULL;
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-
-    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
-    if (dom == NULL)
-        goto cleanup;
-    privdom = dom->privateData;
-
-    // delayed event after unsubscribe
-    if (privdom->cache.count == -1)
-        goto cleanup;
-
-    PrlHandle_Free(privdom->cache.stats);
-    privdom->cache.stats = PRL_INVALID_HANDLE;
-
-    if (privdom->cache.count > PARALLELS_STATISTICS_DROP_COUNT) {
-        job = PrlVm_UnsubscribeFromPerfStats(privdom->sdkdom);
-        if (PRL_FAILED(waitJob(job)))
-            goto cleanup;
-        // change state to unsubscribed
-        privdom->cache.count = -1;
-    } else {
-        ++privdom->cache.count;
-        privdom->cache.stats = event;
-        // thus we get own of event handle
-        event = PRL_INVALID_HANDLE;
-        virCondSignal(&privdom->cache.cond);
-    }
-
- cleanup:
-    PrlHandle_Free(event);
-    if (dom)
-        virObjectUnlock(dom);
-
-    return PRL_ERR_SUCCESS;
-}
-
-static void
-prlsdkHandleVmEvent(vzConnPtr privconn, PRL_HANDLE prlEvent)
-{
-    PRL_RESULT pret = PRL_ERR_FAILURE;
-    char uuidstr[VIR_UUID_STRING_BUFLEN + 2];
-    unsigned char uuid[VIR_UUID_BUFLEN];
-    PRL_UINT32 bufsize = ARRAY_CARDINALITY(uuidstr);
-    PRL_EVENT_TYPE prlEventType;
-
-    pret = PrlEvent_GetType(prlEvent, &prlEventType);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlEvent_GetIssuerId(prlEvent, uuidstr, &bufsize);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    if (prlsdkUUIDParse(uuidstr, uuid) < 0)
-        goto cleanup;
-
-    switch (prlEventType) {
-        case PET_DSP_EVT_VM_STATE_CHANGED:
-            prlsdkHandleVmStateEvent(privconn, prlEvent, uuid);
-            break;
-        case PET_DSP_EVT_VM_CONFIG_CHANGED:
-            prlsdkHandleVmConfigEvent(privconn, uuid);
-            break;
-        case PET_DSP_EVT_VM_CREATED:
-        case PET_DSP_EVT_VM_ADDED:
-            prlsdkHandleVmAddedEvent(privconn, uuid);
-            break;
-        case PET_DSP_EVT_VM_DELETED:
-        case PET_DSP_EVT_VM_UNREGISTERED:
-            prlsdkHandleVmRemovedEvent(privconn, uuid);
-            break;
-        case PET_DSP_EVT_VM_PERFSTATS:
-            prlsdkHandlePerfEvent(privconn, prlEvent, uuid);
-            // above function takes own of event
-            prlEvent = PRL_INVALID_HANDLE;
-            break;
-        default:
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Can't handle event of type %d"), prlEventType);
-    }
-
- cleanup:
-    PrlHandle_Free(prlEvent);
-    return;
-}
-
-static PRL_RESULT
-prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque)
-{
-    vzConnPtr privconn = opaque;
-    PRL_RESULT pret = PRL_ERR_FAILURE;
-    PRL_HANDLE_TYPE handleType;
-    PRL_EVENT_ISSUER_TYPE prlIssuerType = PIE_UNKNOWN;
-
-    pret = PrlHandle_GetType(prlEvent, &handleType);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    /* Currently, there is no need to handle anything but events */
-    if (handleType != PHT_EVENT)
-        goto cleanup;
-
-    if (privconn == NULL)
-        goto cleanup;
-
-    PrlEvent_GetIssuerType(prlEvent, &prlIssuerType);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    switch (prlIssuerType) {
-        case PIE_VIRTUAL_MACHINE:
-            prlsdkHandleVmEvent(privconn, prlEvent);
-            // above function takes own of event
-            prlEvent = PRL_INVALID_HANDLE;
-            break;
-        default:
-            VIR_DEBUG("Skipping event of issuer type %d", prlIssuerType);
-    }
-
- cleanup:
-    PrlHandle_Free(prlEvent);
-    return PRL_ERR_SUCCESS;
-}
-
-
-int prlsdkSubscribeToPCSEvents(vzConnPtr privconn)
-{
-    PRL_RESULT pret = PRL_ERR_UNINITIALIZED;
-
-    pret = PrlSrv_RegEventHandler(privconn->server,
-                                 prlsdkEventsHandler,
-                                 privconn);
-    prlsdkCheckRetGoto(pret, error);
-    return 0;
-
- error:
-    return -1;
-}
-
-void prlsdkUnsubscribeFromPCSEvents(vzConnPtr privconn)
-{
-    PRL_RESULT ret = PRL_ERR_UNINITIALIZED;
-    ret = PrlSrv_UnregEventHandler(privconn->server,
-                                 prlsdkEventsHandler,
-                                 privconn);
-    if (PRL_FAILED(ret))
-        logPrlError(ret);
-}
-
-PRL_RESULT prlsdkStart(PRL_HANDLE sdkdom)
-{
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-
-    job = PrlVm_StartEx(sdkdom, PSM_VM_START, 0);
-    return waitJob(job);
-}
-
-static PRL_RESULT prlsdkStopEx(PRL_HANDLE sdkdom, PRL_UINT32 mode)
-{
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-
-    job = PrlVm_StopEx(sdkdom, mode, 0);
-    return waitJob(job);
-}
-
-PRL_RESULT prlsdkKill(PRL_HANDLE sdkdom)
-{
-    return prlsdkStopEx(sdkdom, PSM_KILL);
-}
-
-PRL_RESULT prlsdkStop(PRL_HANDLE sdkdom)
-{
-    return prlsdkStopEx(sdkdom, PSM_SHUTDOWN);
-}
-
-PRL_RESULT prlsdkPause(PRL_HANDLE sdkdom)
-{
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-
-    job = PrlVm_Pause(sdkdom, false);
-    return waitJob(job);
-}
-
-PRL_RESULT prlsdkResume(PRL_HANDLE sdkdom)
-{
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-
-    job = PrlVm_Resume(sdkdom);
-    return waitJob(job);
-}
-
-PRL_RESULT prlsdkSuspend(PRL_HANDLE sdkdom)
-{
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-
-    job = PrlVm_Suspend(sdkdom);
-    return waitJob(job);
-}
-
-int
-prlsdkDomainChangeStateLocked(vzConnPtr privconn,
-                              virDomainObjPtr dom,
-                              prlsdkChangeStateFunc chstate)
-{
-    vzDomObjPtr pdom;
-    PRL_RESULT pret;
-    virErrorNumber virerr;
-
-    pdom = dom->privateData;
-    pret = chstate(pdom->sdkdom);
-    if (PRL_FAILED(pret)) {
-        virResetLastError();
-
-        switch (pret) {
-        case PRL_ERR_DISP_VM_IS_NOT_STARTED:
-        case PRL_ERR_DISP_VM_IS_NOT_STOPPED:
-            virerr = VIR_ERR_OPERATION_INVALID;
-            break;
-        default:
-            virerr = VIR_ERR_OPERATION_FAILED;
-        }
-
-        virReportError(virerr, "%s", _("Can't change domain state."));
-        return -1;
-    }
-
-    return prlsdkUpdateDomain(privconn, dom);
-}
-
-int
-prlsdkDomainChangeState(virDomainPtr domain,
-                        prlsdkChangeStateFunc chstate)
-{
-    vzConnPtr privconn = domain->conn->privateData;
-    virDomainObjPtr dom;
-    int ret = -1;
-
-    if (!(dom = vzDomObjFromDomain(domain)))
-        return -1;
-
-    ret = prlsdkDomainChangeStateLocked(privconn, dom, chstate);
-    virObjectUnlock(dom);
-    return ret;
-}
-
-static int
-prlsdkCheckUnsupportedParams(PRL_HANDLE sdkdom, virDomainDefPtr def)
-{
-    size_t i;
-    PRL_VM_TYPE vmType;
-    PRL_RESULT pret;
-    virDomainNumatuneMemMode memMode;
-
-    if (def->title) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("titles are not supported by vz driver"));
-        return -1;
-    }
-
-    if (def->blkio.ndevices > 0) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("blkio parameters are not supported "
-                         "by vz driver"));
-        return -1;
-    }
-
-    if (virDomainDefGetMemoryActual(def) != def->mem.cur_balloon) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                   _("changing balloon parameters is not supported "
-                     "by vz driver"));
-       return -1;
-    }
-
-    if (virDomainDefGetMemoryActual(def) % (1 << 10) != 0) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                   _("Memory size should be multiple of 1Mb."));
-        return -1;
-    }
-
-    if (def->mem.nhugepages ||
-        virMemoryLimitIsSet(def->mem.hard_limit) ||
-        virMemoryLimitIsSet(def->mem.soft_limit) ||
-        def->mem.min_guarantee ||
-        virMemoryLimitIsSet(def->mem.swap_hard_limit)) {
-
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Memory parameter is not supported "
-                         "by vz driver"));
-        return -1;
-    }
-
-    if (def->vcpus != def->maxvcpus) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                   _("current vcpus must be equal to maxvcpus"));
-        return -1;
-    }
-
-    if (def->placement_mode) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("changing cpu placement mode is not supported "
-                         "by vz driver"));
-        return -1;
-    }
-
-    if (def->cputune.shares ||
-        def->cputune.sharesSpecified ||
-        def->cputune.period ||
-        def->cputune.quota) {
-
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("cputune is not supported by vz driver"));
-        return -1;
-    }
-
-    if (def->cputune.vcpupin) {
-       for (i = 0; i < def->vcpus; i++) {
-            if (!virBitmapEqual(def->cpumask,
-                                def->cputune.vcpupin[i]->cpumask)) {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                               "%s", _("vcpupin cpumask differs from default cpumask"));
-                return -1;
-            }
-        }
-    }
-
-
-    /*
-     * Though we don't support NUMA configuration at the moment
-     * virDomainDefPtr always contain non zero NUMA configuration
-     * So, just make sure this configuration does't differ from auto generated.
-     */
-    if ((virDomainNumatuneGetMode(def->numa, -1, &memMode) == 0 &&
-         memMode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) ||
-         virDomainNumatuneHasPerNodeBinding(def->numa)) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                        _("numa parameters are not supported "
-                          "by vz driver"));
-        return -1;
-    }
-
-    if (def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART ||
-        def->onPoweroff != VIR_DOMAIN_LIFECYCLE_DESTROY ||
-        def->onCrash != VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY) {
-
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("on_reboot, on_poweroff and on_crash parameters "
-                         "are not supported by vz driver"));
-        return -1;
-    }
-
-    /* we fill only type and arch fields in vzLoadDomain for
-     * hvm type and also init for containers, so we can check that all
-     * other paramenters are null and boot devices config is default */
-
-    if (def->os.machine != NULL || def->os.bootmenu != 0 ||
-        def->os.kernel != NULL || def->os.initrd != NULL ||
-        def->os.cmdline != NULL || def->os.root != NULL ||
-        def->os.loader != NULL || def->os.bootloader != NULL ||
-        def->os.bootloaderArgs != NULL || def->os.smbios_mode != 0 ||
-        def->os.bios.useserial != 0) {
-
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("changing OS parameters is not supported "
-                         "by vz driver"));
-        return -1;
-    }
-
-    pret = PrlVmCfg_GetVmType(sdkdom, &vmType);
-    if (PRL_FAILED(pret)) {
-        logPrlError(pret);
-        return -1;
-    }
-
-    if (!(vmType == PVT_VM && !IS_CT(def)) &&
-        !(vmType == PVT_CT && IS_CT(def))) {
-
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("changing OS type is not supported "
-                         "by vz driver"));
-        return -1;
-    }
-
-    if (!IS_CT(def)) {
-        if (def->os.nBootDevs != 1 ||
-            def->os.bootDevs[0] != VIR_DOMAIN_BOOT_DISK ||
-            def->os.init != NULL || def->os.initargv != NULL) {
-
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("changing OS parameters is not supported "
-                             "by vz driver"));
-            return -1;
-        }
-    } else {
-        if (def->os.nBootDevs != 0 ||
-            !STREQ_NULLABLE(def->os.init, "/sbin/init") ||
-            (def->os.initargv != NULL && def->os.initargv[0] != NULL)) {
-
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("changing OS parameters is not supported "
-                             "by vz driver"));
-            return -1;
-        }
-    }
-
-    if (def->emulator) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("changing emulator is not supported "
-                         "by vz driver"));
-        return -1;
-    }
-
-    for (i = 0; i < VIR_DOMAIN_FEATURE_LAST; i++) {
-        if (def->features[i]) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("changing features is not supported "
-                             "by vz driver"));
-            return -1;
-        }
-    }
-
-    if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC ||
-        def->clock.ntimers != 0) {
-
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("changing clock parameters is not supported "
-                         "by vz driver"));
-        return -1;
-    }
-
-    if (!IS_CT(def) && def->nfss != 0) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Filesystems in VMs are not supported "
-                         "by vz driver"));
-        return -1;
-    }
-
-    if (def->nsounds != 0 || def->nhostdevs != 0 ||
-        def->nredirdevs != 0 || def->nsmartcards != 0 ||
-        def->nparallels || def->nchannels != 0 ||
-        def->nleases != 0 || def->nhubs != 0) {
-
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("changing devices parameters is not supported "
-                         "by vz driver"));
-        return -1;
-    }
-
-    /* there may be one auto-input */
-    if (def->ninputs != 0 &&
-        (def->ninputs != 2 &&
-            def->inputs[0]->type != VIR_DOMAIN_INPUT_TYPE_MOUSE &&
-            def->inputs[0]->bus != VIR_DOMAIN_INPUT_BUS_PS2 &&
-            def->inputs[1]->type != VIR_DOMAIN_INPUT_TYPE_KBD &&
-            def->inputs[1]->bus != VIR_DOMAIN_INPUT_BUS_PS2)) {
-
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("changing input devices parameters is not supported "
-                         "by vz driver"));
-        return -1;
-    }
-
-    return 0;
-}
-
-static int prlsdkClearDevices(PRL_HANDLE sdkdom)
-{
-    PRL_RESULT pret;
-    PRL_UINT32 n, i;
-    PRL_HANDLE devList;
-    PRL_HANDLE dev;
-    int ret = -1;
-
-    pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_DISABLED);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmCfg_GetAllDevices(sdkdom, &devList);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlHndlList_GetItemsCount(devList, &n);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    for (i = 0; i < n; i++) {
-        pret = PrlHndlList_GetItem(devList, i, &dev);
-        prlsdkCheckRetGoto(pret, cleanup);
-
-        pret = PrlVmDev_Remove(dev);
-        PrlHandle_Free(dev);
-    }
-
-    ret = 0;
- cleanup:
-    PrlHandle_Free(devList);
-    return ret;
-}
-
-static int
-prlsdkRemoveBootDevices(PRL_HANDLE sdkdom)
-{
-    PRL_RESULT pret;
-    PRL_UINT32 i, devCount;
-    PRL_HANDLE dev = PRL_INVALID_HANDLE;
-    PRL_DEVICE_TYPE devType;
-
-    pret = PrlVmCfg_GetBootDevCount(sdkdom, &devCount);
-    prlsdkCheckRetGoto(pret, error);
-
-    for (i = 0; i < devCount; i++) {
-
-        /* always get device by index 0, because device list resort after delete */
-        pret = PrlVmCfg_GetBootDev(sdkdom, 0, &dev);
-        prlsdkCheckRetGoto(pret, error);
-
-        pret = PrlBootDev_GetType(dev, &devType);
-        prlsdkCheckRetGoto(pret, error);
-
-        pret = PrlBootDev_Remove(dev);
-        prlsdkCheckRetGoto(pret, error);
-    }
-
-    return 0;
-
- error:
-    return -1;
-}
-
-static int
-prlsdkAddDeviceToBootList(PRL_HANDLE sdkdom,
-                          PRL_UINT32 devIndex,
-                          PRL_DEVICE_TYPE devType,
-                          PRL_UINT32 bootSequence)
-{
-    PRL_RESULT pret;
-    PRL_HANDLE bootDev = PRL_INVALID_HANDLE;
-
-    pret = PrlVmCfg_CreateBootDev(sdkdom, &bootDev);
-    prlsdkCheckRetGoto(pret, error);
-
-    pret = PrlBootDev_SetIndex(bootDev, devIndex);
-    prlsdkCheckRetGoto(pret, error);
-
-    pret = PrlBootDev_SetType(bootDev, devType);
-    prlsdkCheckRetGoto(pret, error);
-
-    pret = PrlBootDev_SetSequenceIndex(bootDev, bootSequence);
-    prlsdkCheckRetGoto(pret, error);
-
-    pret = PrlBootDev_SetInUse(bootDev, PRL_TRUE);
-    prlsdkCheckRetGoto(pret, error);
-
-    return 0;
-
- error:
-    if (bootDev != PRL_INVALID_HANDLE)
-        PrlBootDev_Remove(bootDev);
-
-    return -1;
-}
-
-static int prlsdkCheckGraphicsUnsupportedParams(virDomainDefPtr def)
-{
-    virDomainGraphicsDefPtr gr;
-
-    if (def->ngraphics == 0)
-        return 0;
-
-    if (def->ngraphics > 1) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("vz driver supports only "
-                         "one VNC per domain."));
-        return -1;
-    }
-
-    gr = def->graphics[0];
-
-    if (gr->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("vz driver supports only "
-                         "VNC graphics."));
-        return -1;
-    }
-
-    if (gr->data.vnc.websocket != 0) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("vz driver doesn't support "
-                         "websockets for VNC graphics."));
-        return -1;
-    }
-
-    if (gr->data.vnc.keymap != 0) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("vz driver doesn't support "
-                         "keymap setting for VNC graphics."));
-        return -1;
-    }
-
-    if (gr->data.vnc.sharePolicy == VIR_DOMAIN_GRAPHICS_VNC_SHARE_ALLOW_EXCLUSIVE) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("vz driver doesn't support "
-                         "exclusive share policy for VNC graphics."));
-        return -1;
-    }
-
-    if (gr->data.vnc.socket) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("vz driver doesn't support "
-                         "VNC graphics over unix sockets."));
-        return -1;
-    }
-
-    if (gr->data.vnc.auth.connected == VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_FAIL ||
-            gr->data.vnc.auth.connected == VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_KEEP) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("vz driver doesn't support "
-                         "given action in case of password change."));
-        return -1;
-    }
-
-    if (gr->data.vnc.auth.expires) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("vz driver doesn't support "
-                         "setting password expire time."));
-        return -1;
-    }
-
-    if (gr->nListens > 1) {
-        virReportError(VIR_ERR_INVALID_ARG, "%s",
-                       _("vz driver doesn't support more than "
-                         "one listening VNC server per domain"));
-        return -1;
-    }
-
-    if (gr->nListens == 1 &&
-        virDomainGraphicsListenGetType(gr, 0) != VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) {
-        virReportError(VIR_ERR_INVALID_ARG, "%s",
-                       _("vz driver supports only address-based VNC listening"));
-        return -1;
-    }
-
-    return 0;
-}
-
-static int prlsdkCheckVideoUnsupportedParams(virDomainDefPtr def)
-{
-    virDomainVideoDefPtr v;
-
-    if (IS_CT(def)) {
-        if (def->nvideos == 0) {
-            return 0;
-        } else {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("Video adapters are not supported "
-                             "int containers."));
-            return -1;
-        }
-    } else {
-        if (def->nvideos != 1) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("vz driver supports "
-                             "only one video adapter."));
-            return -1;
-        }
-    }
-
-    v = def->videos[0];
-
-    if (v->type != VIR_DOMAIN_VIDEO_TYPE_VGA) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("vz driver supports "
-                         "only VGA video adapters."));
-        return -1;
-    }
-
-    if (v->heads != 1) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("vz driver doesn't support "
-                         "multihead video adapters."));
-        return -1;
-    }
-
-    if (v->accel != NULL && (v->accel->support2d || v->accel->support3d)) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("vz driver doesn't support "
-                         "setting video acceleration parameters."));
-        return -1;
-    }
-
-    return 0;
-}
-
-static int prlsdkCheckSerialUnsupportedParams(virDomainChrDefPtr chr)
-{
-    if (chr->deviceType != VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Specified character device type is not supported "
-                         "by vz driver."));
-        return -1;
-    }
-
-    if (chr->targetTypeAttr) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Specified character device target type is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_DEV &&
-        chr->source.type != VIR_DOMAIN_CHR_TYPE_FILE &&
-        chr->source.type != VIR_DOMAIN_CHR_TYPE_UNIX) {
-
-
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Specified character device source type is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (chr->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting device info for character devices is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (chr->nseclabels > 0) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting security labels is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    return 0;
-}
-
-static int prlsdkCheckNetUnsupportedParams(virDomainNetDefPtr net)
-{
-    if (net->type != VIR_DOMAIN_NET_TYPE_NETWORK &&
-        net->type != VIR_DOMAIN_NET_TYPE_BRIDGE) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Specified network adapter type is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (net->backend.tap || net->backend.vhost) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Interface backend parameters are not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (net->data.network.portgroup) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Virtual network portgroups are not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (net->tune.sndbuf_specified) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting interface sndbuf is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (net->script) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting interface script is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (net->ifname_guest) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting guest interface name is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (net->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting device info for network devices is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (net->filter) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting network filter is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (net->bandwidth) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting network bandwidth is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (net->vlan.trunk) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting up vlans is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    return 0;
-}
-
-static int prlsdkCheckDiskUnsupportedParams(virDomainDiskDefPtr disk)
-{
-    if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK &&
-        disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
-
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Only hard disks and cdroms are supported "
-                         "by vz driver."));
-        return -1;
-    }
-
-   if (disk->blockio.logical_block_size ||
-       disk->blockio.physical_block_size) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting disk block sizes is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (disk->blkdeviotune.total_bytes_sec ||
-        disk->blkdeviotune.read_bytes_sec ||
-        disk->blkdeviotune.write_bytes_sec ||
-        disk->blkdeviotune.total_iops_sec ||
-        disk->blkdeviotune.read_iops_sec ||
-        disk->blkdeviotune.write_iops_sec) {
-
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting disk io limits is not "
-                         "supported by vz driver yet."));
-        return -1;
-    }
-
-    if (disk->serial) {
-        VIR_INFO("%s", _("Setting disk serial number is not "
-                         "supported by vz driver."));
-    }
-
-    if (disk->wwn) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting disk wwn id is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (disk->vendor) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting disk vendor is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (disk->product) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting disk product id is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (disk->error_policy != VIR_DOMAIN_DISK_ERROR_POLICY_DEFAULT) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting disk error policy is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (disk->iomode) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting disk io mode is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (disk->copy_on_read) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Disk copy_on_read is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (disk->startupPolicy != VIR_DOMAIN_STARTUP_POLICY_DEFAULT) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting up disk startup policy is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (disk->transient) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Transient disks are not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (disk->discard) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting up disk discard parameter is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (disk->iothread) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting up disk io thread # is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (disk->src->type != VIR_STORAGE_TYPE_FILE &&
-        disk->src->type != VIR_STORAGE_TYPE_BLOCK) {
-
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Only disk and block storage types are "
-                         "supported by vz driver."));
-        return -1;
-
-    }
-
-    return 0;
-}
-
-static int prlsdkCheckFSUnsupportedParams(virDomainFSDefPtr fs)
-{
-    if (fs->type != VIR_DOMAIN_FS_TYPE_FILE) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Only file based filesystems are "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (fs->fsdriver != VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Only ploop fs driver is "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (fs->accessmode != VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Changing fs access mode is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (fs->wrpolicy != VIR_DOMAIN_FS_WRPOLICY_DEFAULT) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Changing fs write policy is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (fs->format != VIR_STORAGE_FILE_PLOOP) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Only ploop disk images are "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (fs->readonly) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting readonly for filesystems is "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    if (fs->space_hard_limit || fs->space_soft_limit) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Setting fs quotas is not "
-                         "supported by vz driver."));
-        return -1;
-    }
-
-    return 0;
-}
-
-static int prlsdkApplyGraphicsParams(PRL_HANDLE sdkdom, virDomainDefPtr def)
-{
-    virDomainGraphicsDefPtr gr;
-    PRL_RESULT pret;
-    int ret  = -1;
-    const char *listenAddr = NULL;
-
-    if (prlsdkCheckGraphicsUnsupportedParams(def))
-        return -1;
-
-    if (def->ngraphics == 0)
-        return 0;
-
-    gr = def->graphics[0];
-
-    if (gr->data.vnc.autoport) {
-        pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_AUTO);
-        prlsdkCheckRetGoto(pret, cleanup);
-    } else {
-        pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_MANUAL);
-        prlsdkCheckRetGoto(pret, cleanup);
-
-        pret = PrlVmCfg_SetVNCPort(sdkdom, gr->data.vnc.port);
-        prlsdkCheckRetGoto(pret, cleanup);
-    }
-
-    if (gr->nListens == 1) {
-        listenAddr = virDomainGraphicsListenGetAddress(gr, 0);
-        if (!listenAddr)
-            goto cleanup;
-        pret = PrlVmCfg_SetVNCHostName(sdkdom, listenAddr);
-        prlsdkCheckRetGoto(pret, cleanup);
-    }
-
-    ret = 0;
- cleanup:
-    return ret;
-}
-
-static int prlsdkApplyVideoParams(PRL_HANDLE sdkdom ATTRIBUTE_UNUSED, virDomainDefPtr def)
-{
-    PRL_RESULT pret;
-
-    if (def->nvideos == 0)
-        return 0;
-
-    if (IS_CT(def)) {
-        /* ignore video parameters */
-        return 0;
-    }
-
-    if (prlsdkCheckVideoUnsupportedParams(def))
-        return -1;
-
-    pret = PrlVmCfg_SetVideoRamSize(sdkdom, def->videos[0]->vram >> 10);
-    prlsdkCheckRetGoto(pret, error);
-
-    return 0;
- error:
-    return -1;
-}
-
-static int prlsdkAddSerial(PRL_HANDLE sdkdom, virDomainChrDefPtr chr)
-{
-    PRL_RESULT pret;
-    PRL_HANDLE sdkchr = PRL_INVALID_HANDLE;
-    PRL_VM_DEV_EMULATION_TYPE emutype;
-    PRL_SERIAL_PORT_SOCKET_OPERATION_MODE socket_mode =
-                                    PSP_SERIAL_SOCKET_SERVER;
-    char *path;
-    int ret = -1;
-
-    if (prlsdkCheckSerialUnsupportedParams(chr) < 0)
-        return -1;
-
-    pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_SERIAL_PORT, &sdkchr);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    switch (chr->source.type) {
-    case VIR_DOMAIN_CHR_TYPE_DEV:
-        emutype = PDT_USE_REAL_DEVICE;
-        path = chr->source.data.file.path;
-        break;
-    case VIR_DOMAIN_CHR_TYPE_FILE:
-        emutype = PDT_USE_OUTPUT_FILE;
-        path = chr->source.data.file.path;
-        break;
-    case VIR_DOMAIN_CHR_TYPE_UNIX:
-        emutype = PDT_USE_SERIAL_PORT_SOCKET_MODE;
-        path = chr->source.data.nix.path;
-        if (chr->source.data.nix.listen)
-            socket_mode = PSP_SERIAL_SOCKET_SERVER;
-        else
-            socket_mode = PSP_SERIAL_SOCKET_CLIENT;
-        break;
-    default:
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("vz driver doesn't support "
-                         "specified serial source type."));
-        goto cleanup;
-    }
-
-    pret = PrlVmDev_SetEmulatedType(sdkchr, emutype);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetSysName(sdkchr, path);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetFriendlyName(sdkchr, path);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    if (chr->source.type == VIR_DOMAIN_CHR_TYPE_UNIX) {
-        pret = PrlVmDevSerial_SetSocketMode(sdkchr, socket_mode);
-        prlsdkCheckRetGoto(pret, cleanup);
-    }
-
-    pret = PrlVmDev_SetEnabled(sdkchr, 1);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetIndex(sdkchr, chr->target.port);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    ret = 0;
- cleanup:
-    PrlHandle_Free(sdkchr);
-    return ret;
-}
-
-#define PRL_MAC_STRING_BUFNAME  13
-
-static const char * prlsdkFormatMac(virMacAddrPtr mac, char *macstr)
-{
-    snprintf(macstr, PRL_MAC_STRING_BUFNAME,
-             "%02X%02X%02X%02X%02X%02X",
-             mac->addr[0], mac->addr[1], mac->addr[2],
-             mac->addr[3], mac->addr[4], mac->addr[5]);
-    macstr[PRL_MAC_STRING_BUFNAME - 1] = '\0';
-    return macstr;
-}
-
-static int prlsdkAddNet(PRL_HANDLE sdkdom,
-                        vzConnPtr privconn,
-                        virDomainNetDefPtr net,
-                        bool isCt)
-{
-    PRL_RESULT pret;
-    PRL_HANDLE sdknet = PRL_INVALID_HANDLE;
-    PRL_HANDLE vnet = PRL_INVALID_HANDLE;
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-    int ret = -1;
-    char macstr[PRL_MAC_STRING_BUFNAME];
-
-    if (prlsdkCheckNetUnsupportedParams(net) < 0)
-        return -1;
-
-    pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_GENERIC_NETWORK_ADAPTER, &sdknet);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetEnabled(sdknet, 1);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetConnected(sdknet, net->linkstate !=
-                                 VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN);
-
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    if (net->ifname) {
-        pret = PrlVmDevNet_SetHostInterfaceName(sdknet, net->ifname);
-        prlsdkCheckRetGoto(pret, cleanup);
-    }
-
-    prlsdkFormatMac(&net->mac, macstr);
-    pret = PrlVmDevNet_SetMacAddress(sdknet, macstr);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    if (isCt) {
-        if (net->model)
-             VIR_WARN("Setting network adapter for containers is not "
-                      "supported by vz driver.");
-    } else {
-        if (STREQ(net->model, "rtl8139")) {
-            pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_RTL);
-        } else if (STREQ(net->model, "e1000")) {
-            pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_E1000);
-        } else if (STREQ(net->model, "virtio")) {
-            pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_VIRTIO);
-        } else {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Specified network adapter model is not "
-                         "supported by vz driver."));
-            goto cleanup;
-        }
-        prlsdkCheckRetGoto(pret, cleanup);
-    }
-
-    if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
-        if (STREQ(net->data.network.name, PARALLELS_DOMAIN_ROUTED_NETWORK_NAME)) {
-            pret = PrlVmDev_SetEmulatedType(sdknet, PNA_ROUTED);
-            prlsdkCheckRetGoto(pret, cleanup);
-        } else if (STREQ(net->data.network.name, PARALLELS_DOMAIN_BRIDGED_NETWORK_NAME)) {
-            pret = PrlVmDev_SetEmulatedType(sdknet, PNA_BRIDGED_ETHERNET);
-            prlsdkCheckRetGoto(pret, cleanup);
-
-            pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.network.name);
-            prlsdkCheckRetGoto(pret, cleanup);
-        }
-    } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
-        /*
-         * For this type of adapter we create a new
-         * Virtual Network assuming that bridge with given name exists
-         * Failing creating this means domain creation failure
-         */
-        pret = PrlVirtNet_Create(&vnet);
-        prlsdkCheckRetGoto(pret, cleanup);
-
-        pret = PrlVirtNet_SetNetworkId(vnet, net->data.network.name);
-        prlsdkCheckRetGoto(pret, cleanup);
-
-        pret = PrlVirtNet_SetNetworkType(vnet, PVN_BRIDGED_ETHERNET);
-        prlsdkCheckRetGoto(pret, cleanup);
-
-        job = PrlSrv_AddVirtualNetwork(privconn->server, vnet, 0);
-        if (PRL_FAILED(pret = waitJob(job)))
-            goto cleanup;
-
-        pret = PrlVmDev_SetEmulatedType(sdknet, PNA_BRIDGED_ETHERNET);
-        prlsdkCheckRetGoto(pret, cleanup);
-
-        pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.network.name);
-        prlsdkCheckRetGoto(pret, cleanup);
-    }
-
-    if (net->trustGuestRxFilters == VIR_TRISTATE_BOOL_YES)
-        pret = PrlVmDevNet_SetPktFilterPreventMacSpoof(sdknet, 0);
-    else if (net->trustGuestRxFilters == VIR_TRISTATE_BOOL_NO)
-        pret = PrlVmDevNet_SetPktFilterPreventMacSpoof(sdknet, 1);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    ret = 0;
- cleanup:
-    PrlHandle_Free(vnet);
-    PrlHandle_Free(sdknet);
-    return ret;
-}
-
-static void prlsdkDelNet(vzConnPtr privconn, virDomainNetDefPtr net)
-{
-    PRL_RESULT pret;
-    PRL_HANDLE vnet = PRL_INVALID_HANDLE;
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-
-    if (net->type != VIR_DOMAIN_NET_TYPE_BRIDGE)
-        return;
-
-    pret = PrlVirtNet_Create(&vnet);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVirtNet_SetNetworkId(vnet, net->data.network.name);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    PrlSrv_DeleteVirtualNetwork(privconn->server, vnet, 0);
-    if (PRL_FAILED(pret = waitJob(job)))
-        goto cleanup;
-
- cleanup:
-    PrlHandle_Free(vnet);
-}
-
-static int prlsdkDelDisk(PRL_HANDLE sdkdom, int idx)
-{
-    int ret = -1;
-    PRL_RESULT pret;
-    PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
-
-    pret = PrlVmCfg_GetHardDisk(sdkdom, idx, &sdkdisk);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_Remove(sdkdisk);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    ret = 0;
-
- cleanup:
-    PrlHandle_Free(sdkdisk);
-    return ret;
-}
-
-static int prlsdkAddDisk(PRL_HANDLE sdkdom,
-                         virDomainDiskDefPtr disk,
-                         bool bootDisk,
-                         bool isCt)
-{
-    PRL_RESULT pret;
-    PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
-    int ret = -1;
-    PRL_VM_DEV_EMULATION_TYPE emutype;
-    PRL_MASS_STORAGE_INTERFACE_TYPE sdkbus;
-    int idx;
-    virDomainDeviceDriveAddressPtr drive;
-    PRL_UINT32 devIndex;
-    PRL_DEVICE_TYPE devType;
-    char *dst = NULL;
-
-    if (prlsdkCheckDiskUnsupportedParams(disk) < 0)
-        return -1;
-
-    if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
-        devType = PDE_HARD_DISK;
-    else
-        devType = PDE_OPTICAL_DISK;
-
-    pret = PrlVmCfg_CreateVmDev(sdkdom, devType, &sdkdisk);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetEnabled(sdkdisk, 1);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetConnected(sdkdisk, 1);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    if (disk->src->type == VIR_STORAGE_TYPE_FILE) {
-        if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
-            virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_PLOOP) {
-
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid format of "
-                           "disk %s, vz driver supports only "
-                           "images in ploop format."), disk->src->path);
-            goto cleanup;
-        }
-
-        emutype = PDT_USE_IMAGE_FILE;
-    } else {
-        if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
-            (virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_RAW &&
-             virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_NONE &&
-             virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_AUTO)) {
-
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid format "
-                           "of disk %s, it should be either not set, or set "
-                           "to raw or auto."), disk->src->path);
-            goto cleanup;
-        }
-        emutype = PDT_USE_REAL_DEVICE;
-    }
-
-    pret = PrlVmDev_SetEmulatedType(sdkdisk, emutype);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetSysName(sdkdisk, disk->src->path);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetFriendlyName(sdkdisk, disk->src->path);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    drive = &disk->info.addr.drive;
-    if (drive->controller > 0) {
-        /* We have only one controller of each type */
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid drive "
-                       "address of disk %s, vz driver supports "
-                       "only one controller."), disk->dst);
-        goto cleanup;
-    }
-
-    if (drive->target > 0) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid drive "
-                       "address of disk %s, vz driver supports "
-                       "only target 0."), disk->dst);
-        goto cleanup;
-    }
-
-    switch (disk->bus) {
-    case VIR_DOMAIN_DISK_BUS_IDE:
-        if (drive->unit > 1) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid drive "
-                           "address of disk %s, vz driver supports "
-                           "only units 0-1 for IDE bus."), disk->dst);
-            goto cleanup;
-        }
-        sdkbus = PMS_IDE_DEVICE;
-        idx = 2 * drive->bus + drive->unit;
-        dst = virIndexToDiskName(idx, "hd");
-        break;
-    case VIR_DOMAIN_DISK_BUS_SCSI:
-        if (drive->bus > 0) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid drive "
-                           "address of disk %s, vz driver supports "
-                           "only bus 0 for SCSI bus."), disk->dst);
-            goto cleanup;
-        }
-        sdkbus = PMS_SCSI_DEVICE;
-        idx = drive->unit;
-        dst = virIndexToDiskName(idx, "sd");
-        break;
-    case VIR_DOMAIN_DISK_BUS_SATA:
-        if (drive->bus > 0) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid drive "
-                           "address of disk %s, vz driver supports "
-                           "only bus 0 for SATA bus."), disk->dst);
-            goto cleanup;
-        }
-        sdkbus = PMS_SATA_DEVICE;
-        idx = drive->unit;
-        dst = virIndexToDiskName(idx, "sd");
-        break;
-    default:
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Specified disk bus is not "
-                         "supported by vz driver."));
-        goto cleanup;
-    }
-
-    if (!dst)
-        goto cleanup;
-
-    if (STRNEQ(dst, disk->dst)) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid drive "
-                       "address of disk %s, vz driver supports "
-                       "only defaults address to logical device name."), disk->dst);
-        goto cleanup;
-    }
-
-    pret = PrlVmDev_SetIfaceType(sdkdisk, sdkbus);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetStackIndex(sdkdisk, idx);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    switch (disk->cachemode) {
-    case VIR_DOMAIN_DISK_CACHE_DISABLE:
-        pret = PrlVmCfg_SetDiskCacheWriteBack(sdkdom, PRL_FALSE);
-        prlsdkCheckRetGoto(pret, cleanup);
-        break;
-    case VIR_DOMAIN_DISK_CACHE_WRITEBACK:
-        pret = PrlVmCfg_SetDiskCacheWriteBack(sdkdom, PRL_TRUE);
-        prlsdkCheckRetGoto(pret, cleanup);
-        break;
-    case VIR_DOMAIN_DISK_CACHE_DEFAULT:
-        break;
-    default:
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Specified disk cache mode is not "
-                         "supported by vz driver."));
-        goto cleanup;
-    }
-
-    if (bootDisk == true) {
-        pret = PrlVmDev_GetIndex(sdkdisk, &devIndex);
-        prlsdkCheckRetGoto(pret, cleanup);
-
-        if (prlsdkAddDeviceToBootList(sdkdom, devIndex, devType, 0) < 0)
-            goto cleanup;
-
-        /* If we add physical device as a boot disk to container
-         * we have to specify mount point for it */
-        if (isCt) {
-            pret = PrlVmDevHd_SetMountPoint(sdkdisk, "/");
-            prlsdkCheckRetGoto(pret, cleanup);
-        }
-    }
-
-    return 0;
- cleanup:
-    PrlHandle_Free(sdkdisk);
-    VIR_FREE(dst);
-    return ret;
-}
-
-int
-prlsdkAttachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk)
-{
-    int ret = -1;
-    vzDomObjPtr privdom = dom->privateData;
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-
-    job = PrlVm_BeginEdit(privdom->sdkdom);
-    if (PRL_FAILED(waitJob(job)))
-        goto cleanup;
-
-    ret = prlsdkAddDisk(privdom->sdkdom, disk, false, IS_CT(dom->def));
-    if (ret == 0) {
-        job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
-        if (PRL_FAILED(waitJob(job))) {
-            ret = -1;
-            goto cleanup;
-        }
-    }
-
- cleanup:
-    return ret;
-}
-
-static int
-prlsdkGetDiskIndex(PRL_HANDLE sdkdom, virDomainDiskDefPtr disk)
-{
-    int idx = -1;
-    char *buf = NULL;
-    PRL_UINT32 buflen = 0;
-    PRL_RESULT pret;
-    PRL_UINT32 hddCount;
-    PRL_UINT32 i;
-    PRL_HANDLE hdd = PRL_INVALID_HANDLE;
-
-    pret = PrlVmCfg_GetHardDisksCount(sdkdom, &hddCount);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    for (i = 0; i < hddCount; ++i) {
-
-        pret = PrlVmCfg_GetHardDisk(sdkdom, i, &hdd);
-        prlsdkCheckRetGoto(pret, cleanup);
-
-        pret = PrlVmDev_GetFriendlyName(hdd, 0, &buflen);
-        prlsdkCheckRetGoto(pret, cleanup);
-
-        if (VIR_ALLOC_N(buf, buflen) < 0)
-            goto cleanup;
-
-        pret = PrlVmDev_GetFriendlyName(hdd, buf, &buflen);
-        prlsdkCheckRetGoto(pret, cleanup);
-
-        if (STRNEQ(disk->src->path, buf)) {
-
-            PrlHandle_Free(hdd);
-            hdd = PRL_INVALID_HANDLE;
-            VIR_FREE(buf);
-            continue;
-        }
-
-        VIR_FREE(buf);
-        idx = i;
-        break;
-    }
-
- cleanup:
-    PrlHandle_Free(hdd);
-    return idx;
-}
-
-int
-prlsdkDetachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk)
-{
-    int ret = -1, idx;
-    vzDomObjPtr privdom = dom->privateData;
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-
-    idx = prlsdkGetDiskIndex(privdom->sdkdom, disk);
-    if (idx < 0)
-        goto cleanup;
-
-    job = PrlVm_BeginEdit(privdom->sdkdom);
-    if (PRL_FAILED(waitJob(job)))
-        goto cleanup;
-
-    ret = prlsdkDelDisk(privdom->sdkdom, idx);
-    if (ret == 0) {
-        job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
-        if (PRL_FAILED(waitJob(job))) {
-            ret = -1;
-            goto cleanup;
-        }
-    }
-
- cleanup:
-    return ret;
-}
-
-static int
-prlsdkAddFS(PRL_HANDLE sdkdom, virDomainFSDefPtr fs)
-{
-    PRL_RESULT pret;
-    PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
-    int ret = -1;
-
-    if (prlsdkCheckFSUnsupportedParams(fs) < 0)
-        return -1;
-
-    pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_HARD_DISK, &sdkdisk);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetEnabled(sdkdisk, 1);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetConnected(sdkdisk, 1);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetEmulatedType(sdkdisk, PDT_USE_IMAGE_FILE);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetSysName(sdkdisk, fs->src);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetImagePath(sdkdisk, fs->src);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDev_SetFriendlyName(sdkdisk, fs->src);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmDevHd_SetMountPoint(sdkdisk, fs->dst);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    ret = 0;
-
- cleanup:
-    PrlHandle_Free(sdkdisk);
-    return ret;
-}
-static int
-prlsdkDoApplyConfig(virConnectPtr conn,
-                    PRL_HANDLE sdkdom,
-                    virDomainDefPtr def,
-                    virDomainDefPtr olddef)
-{
-    PRL_RESULT pret;
-    size_t i;
-    char uuidstr[VIR_UUID_STRING_BUFLEN + 2];
-    bool needBoot = true;
-    char *mask = NULL;
-
-    if (prlsdkCheckUnsupportedParams(sdkdom, def) < 0)
-        return -1;
-
-    if (def->description) {
-        pret = PrlVmCfg_SetDescription(sdkdom, def->description);
-        prlsdkCheckRetGoto(pret, error);
-    }
-
-    if (def->name) {
-        pret = PrlVmCfg_SetName(sdkdom, def->name);
-        prlsdkCheckRetGoto(pret, error);
-    }
-
-    if (def->uuid) {
-        prlsdkUUIDFormat(def->uuid, uuidstr);
-
-        pret = PrlVmCfg_SetUuid(sdkdom, uuidstr);
-        prlsdkCheckRetGoto(pret, error);
-    }
-
-    pret = PrlVmCfg_SetRamSize(sdkdom, virDomainDefGetMemoryActual(def) >> 10);
-    prlsdkCheckRetGoto(pret, error);
-
-    pret = PrlVmCfg_SetCpuCount(sdkdom, def->vcpus);
-    prlsdkCheckRetGoto(pret, error);
-
-    if (!(mask = virBitmapFormat(def->cpumask)))
-        goto error;
-
-    pret = PrlVmCfg_SetCpuMask(sdkdom, mask);
-    prlsdkCheckRetGoto(pret, error);
-    VIR_FREE(mask);
-
-    switch (def->os.arch) {
-        case VIR_ARCH_X86_64:
-            pret = PrlVmCfg_SetCpuMode(sdkdom, PCM_CPU_MODE_64);
-            break;
-        case VIR_ARCH_I686:
-            pret = PrlVmCfg_SetCpuMode(sdkdom, PCM_CPU_MODE_32);
-            break;
-        default:
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Unknown CPU mode: %s"),
-                           virArchToString(def->os.arch));
-            goto error;
-    }
-    prlsdkCheckRetGoto(pret, error);
-
-    if (prlsdkClearDevices(sdkdom) < 0)
-        goto error;
-
-    if (prlsdkRemoveBootDevices(sdkdom) < 0)
-        goto error;
-
-    if (olddef) {
-        for (i = 0; i < olddef->nnets; i++)
-            prlsdkDelNet(conn->privateData, olddef->nets[i]);
-    }
-
-    for (i = 0; i < def->nnets; i++) {
-        if (prlsdkAddNet(sdkdom, conn->privateData, def->nets[i], IS_CT(def)) < 0)
-           goto error;
-    }
-
-    if (prlsdkApplyGraphicsParams(sdkdom, def) < 0)
-        goto error;
-
-    if (prlsdkApplyVideoParams(sdkdom, def) < 0)
-        goto error;
-
-    for (i = 0; i < def->nserials; i++) {
-        if (prlsdkAddSerial(sdkdom, def->serials[i]) < 0)
-            goto error;
-    }
-
-    for (i = 0; i < def->nfss; i++) {
-        if (STREQ(def->fss[i]->dst, "/"))
-            needBoot = false;
-        if (prlsdkAddFS(sdkdom, def->fss[i]) < 0)
-            goto error;
-    }
-
-    for (i = 0; i < def->ndisks; i++) {
-        bool bootDisk = false;
-
-        if (needBoot == true &&
-            def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
-
-            needBoot = false;
-            bootDisk = true;
-        }
-        if (prlsdkAddDisk(sdkdom, def->disks[i], bootDisk, IS_CT(def)) < 0)
-            goto error;
-    }
-
-    return 0;
-
- error:
-    VIR_FREE(mask);
-
-    for (i = 0; i < def->nnets; i++)
-        prlsdkDelNet(conn->privateData, def->nets[i]);
-
-   return -1;
-}
-
-int
-prlsdkApplyConfig(virConnectPtr conn,
-                  virDomainObjPtr dom,
-                  virDomainDefPtr new)
-{
-    vzConnPtr privconn = conn->privateData;
-    PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-    int ret;
-
-    sdkdom = prlsdkSdkDomainLookupByUUID(privconn, dom->def->uuid);
-    if (sdkdom == PRL_INVALID_HANDLE)
-        return -1;
-
-    job = PrlVm_BeginEdit(sdkdom);
-    if (PRL_FAILED(waitJob(job)))
-        return -1;
-
-    ret = prlsdkDoApplyConfig(conn, sdkdom, new, dom->def);
-
-    if (ret == 0) {
-        job = PrlVm_CommitEx(sdkdom, PVCF_DETACH_HDD_BUNDLE);
-        if (PRL_FAILED(waitJob(job)))
-            ret = -1;
-    }
-
-    PrlHandle_Free(sdkdom);
-
-    return ret;
-}
-
-int
-prlsdkCreateVm(virConnectPtr conn, virDomainDefPtr def)
-{
-    vzConnPtr privconn = conn->privateData;
-    PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-    PRL_HANDLE result = PRL_INVALID_HANDLE;
-    PRL_HANDLE srvconf = PRL_INVALID_HANDLE;
-    PRL_RESULT pret;
-    int ret = -1;
-
-    pret = PrlSrv_CreateVm(privconn->server, &sdkdom);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    job = PrlSrv_GetSrvConfig(privconn->server);
-    if (PRL_FAILED(getJobResult(job, &result)))
-        goto cleanup;
-
-    pret = PrlResult_GetParamByIndex(result, 0, &srvconf);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmCfg_SetDefaultConfig(sdkdom, srvconf, PVS_GUEST_VER_LIN_REDHAT, 0);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    pret = PrlVmCfg_SetOfflineManagementEnabled(sdkdom, 0);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    ret = prlsdkDoApplyConfig(conn, sdkdom, def, NULL);
-    if (ret)
-        goto cleanup;
-
-    job = PrlVm_Reg(sdkdom, "", 1);
-    if (PRL_FAILED(waitJob(job)))
-        ret = -1;
-
- cleanup:
-    PrlHandle_Free(sdkdom);
-    return ret;
-}
-
-int
-prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def)
-{
-    vzConnPtr privconn = conn->privateData;
-    PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
-    PRL_GET_VM_CONFIG_PARAM_DATA confParam;
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-    PRL_HANDLE result = PRL_INVALID_HANDLE;
-    PRL_RESULT pret;
-    int ret = -1;
-    int useTemplate = 0;
-    size_t i;
-
-    if (def->nfss > 1) {
-        /* Check all filesystems */
-        for (i = 0; i < def->nfss; i++) {
-            if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_FILE) {
-                virReportError(VIR_ERR_INVALID_ARG, "%s",
-                               _("Unsupported filesystem type."));
-                return -1;
-            }
-        }
-    } else if (def->nfss == 1) {
-        if (def->fss[0]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE) {
-            useTemplate = 1;
-        } else if (def->fss[0]->type != VIR_DOMAIN_FS_TYPE_FILE) {
-            virReportError(VIR_ERR_INVALID_ARG, "%s",
-                           _("Unsupported filesystem type."));
-            return -1;
-        }
-    }
-
-    confParam.nVmType = PVT_CT;
-    confParam.sConfigSample = "vswap.1024MB";
-    confParam.nOsVersion = 0;
-
-    job = PrlSrv_GetDefaultVmConfig(privconn->server, &confParam, 0);
-    if (PRL_FAILED(getJobResult(job, &result)))
-        goto cleanup;
-
-    pret = PrlResult_GetParamByIndex(result, 0, &sdkdom);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    if (useTemplate) {
-        pret = PrlVmCfg_SetOsTemplate(sdkdom, def->fss[0]->src);
-        prlsdkCheckRetGoto(pret, cleanup);
-
-    }
-
-    ret = prlsdkDoApplyConfig(conn, sdkdom, def, NULL);
-    if (ret)
-        goto cleanup;
-
-    job = PrlVm_RegEx(sdkdom, "",
-                      PACF_NON_INTERACTIVE_MODE | PRNVM_PRESERVE_DISK);
-    if (PRL_FAILED(waitJob(job)))
-        ret = -1;
-
- cleanup:
-    PrlHandle_Free(sdkdom);
-    return ret;
-}
-
-int
-prlsdkUnregisterDomain(vzConnPtr privconn, virDomainObjPtr dom)
-{
-    vzDomObjPtr privdom = dom->privateData;
-    PRL_HANDLE job;
-    size_t i;
-
-    for (i = 0; i < dom->def->nnets; i++)
-       prlsdkDelNet(privconn, dom->def->nets[i]);
-
-    job = PrlVm_Unreg(privdom->sdkdom);
-    if (PRL_FAILED(waitJob(job)))
-        return -1;
-
-    if (prlsdkSendEvent(privconn, dom, VIR_DOMAIN_EVENT_UNDEFINED,
-                        VIR_DOMAIN_EVENT_UNDEFINED_REMOVED) < 0)
-        return -1;
-
-    virDomainObjListRemove(privconn->domains, dom);
-    return 0;
-}
-
-int
-prlsdkDomainManagedSaveRemove(virDomainObjPtr dom)
-{
-    vzDomObjPtr privdom = dom->privateData;
-    PRL_HANDLE job;
-
-    job = PrlVm_DropSuspendedState(privdom->sdkdom);
-    if (PRL_FAILED(waitJob(job)))
-        return -1;
-
-    return 0;
-}
-
-static int
-prlsdkExtractStatsParam(PRL_HANDLE sdkstats, const char *name, long long *val)
-{
-    PRL_HANDLE param = PRL_INVALID_HANDLE;
-    PRL_RESULT pret;
-    PRL_INT64 pval = 0;
-    int ret = -1;
-
-    pret = PrlEvent_GetParamByName(sdkstats, name, &param);
-    if (pret == PRL_ERR_NO_DATA) {
-        *val = -1;
-        ret = 0;
-        goto cleanup;
-    } else if (PRL_FAILED(pret)) {
-        logPrlError(pret);
-        goto cleanup;
-    }
-    pret = PrlEvtPrm_ToInt64(param, &pval);
-    prlsdkCheckRetGoto(pret, cleanup);
-
-    *val = pval;
-    ret = 0;
-
- cleanup:
-    PrlHandle_Free(param);
-    return ret;
-}
-
-#define PARALLELS_STATISTICS_TIMEOUT (60 * 1000)
-
-static int
-prlsdkGetStatsParam(virDomainObjPtr dom, const char *name, long long *val)
-{
-    vzDomObjPtr privdom = dom->privateData;
-    PRL_HANDLE job = PRL_INVALID_HANDLE;
-    unsigned long long now;
-
-    if (privdom->cache.stats != PRL_INVALID_HANDLE) {
-        // reset count to keep subscribtion
-        privdom->cache.count = 0;
-        return prlsdkExtractStatsParam(privdom->cache.stats, name, val);
-    }
-
-    if (privdom->cache.count == -1) {
-        job = PrlVm_SubscribeToPerfStats(privdom->sdkdom, NULL);
-        if (PRL_FAILED(waitJob(job)))
-            goto error;
-    }
-
-    // change state to subscribed in case of unsubscribed
-    // or reset count so we stop unsubscribe attempts
-    privdom->cache.count = 0;
-
-    if (virTimeMillisNow(&now) < 0) {
-        virReportSystemError(errno, "%s", _("Unable to get current time"));
-        goto error;
-    }
-
-    while (privdom->cache.stats == PRL_INVALID_HANDLE) {
-        if (virCondWaitUntil(&privdom->cache.cond, &dom->parent.lock,
-                        now + PARALLELS_STATISTICS_TIMEOUT) < 0) {
-            if (errno == ETIMEDOUT) {
-                virReportError(VIR_ERR_OPERATION_TIMEOUT, "%s",
-                               _("Timeout on waiting statistics event."));
-                goto error;
-            } else {
-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                               _("Unable to wait on monitor condition"));
-                goto error;
-            }
-        }
-    }
-
-    return prlsdkExtractStatsParam(privdom->cache.stats, name, val);
- error:
-    return -1;
-}
-
-int
-prlsdkGetBlockStats(virDomainObjPtr dom, virDomainDiskDefPtr disk, virDomainBlockStatsPtr stats)
-{
-    virDomainDeviceDriveAddressPtr address;
-    int idx;
-    const char *prefix;
-    int ret = -1;
-    char *name = NULL;
-
-    address = &disk->info.addr.drive;
-    switch (disk->bus) {
-    case VIR_DOMAIN_DISK_BUS_IDE:
-        prefix = "ide";
-        idx = address->bus * 2 + address->unit;
-        break;
-    case VIR_DOMAIN_DISK_BUS_SATA:
-        prefix = "sata";
-        idx = address->unit;
-        break;
-    case VIR_DOMAIN_DISK_BUS_SCSI:
-        prefix = "scsi";
-        idx = address->unit;
-        break;
-    default:
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                   _("Unknown disk bus: %X"), disk->bus);
-        goto cleanup;
-    }
-
-
-#define PRLSDK_GET_STAT_PARAM(VAL, TYPE, NAME)                          \
-    if (virAsprintf(&name, "devices.%s%d.%s", prefix, idx, NAME) < 0)   \
-        goto cleanup;                                                   \
-    if (prlsdkGetStatsParam(dom, name, &stats->VAL) < 0)                \
-        goto cleanup;                                                   \
-    VIR_FREE(name);
-
-    PARALLELS_BLOCK_STATS_FOREACH(PRLSDK_GET_STAT_PARAM)
-
-#undef PRLSDK_GET_STAT_PARAM
-
-    ret = 0;
-
- cleanup:
-
-    VIR_FREE(name);
-    return ret;
-}
diff --git a/src/parallels/parallels_sdk.h b/src/parallels/parallels_sdk.h
deleted file mode 100644 (file)
index 5de6473..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * parallels_sdk.h: core driver functions for managing
- * Parallels Cloud Server hosts
- *
- * Copyright (C) 2014 Parallels, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <Parallels.h>
-
-#include "parallels_utils.h"
-
-int prlsdkInit(void);
-void prlsdkDeinit(void);
-int prlsdkConnect(vzConnPtr privconn);
-void prlsdkDisconnect(vzConnPtr privconn);
-int
-prlsdkLoadDomains(vzConnPtr privconn);
-virDomainObjPtr
-prlsdkAddDomain(vzConnPtr privconn, const unsigned char *uuid);
-int prlsdkUpdateDomain(vzConnPtr privconn, virDomainObjPtr dom);
-int prlsdkSubscribeToPCSEvents(vzConnPtr privconn);
-void prlsdkUnsubscribeFromPCSEvents(vzConnPtr privconn);
-PRL_RESULT prlsdkStart(PRL_HANDLE sdkdom);
-PRL_RESULT prlsdkKill(PRL_HANDLE sdkdom);
-PRL_RESULT prlsdkStop(PRL_HANDLE sdkdom);
-PRL_RESULT prlsdkPause(PRL_HANDLE sdkdom);
-PRL_RESULT prlsdkResume(PRL_HANDLE sdkdom);
-PRL_RESULT prlsdkSuspend(PRL_HANDLE sdkdom);
-
-typedef PRL_RESULT (*prlsdkChangeStateFunc)(PRL_HANDLE sdkdom);
-int
-prlsdkDomainChangeState(virDomainPtr domain,
-                        prlsdkChangeStateFunc chstate);
-int
-prlsdkDomainChangeStateLocked(vzConnPtr privconn,
-                              virDomainObjPtr dom,
-                              prlsdkChangeStateFunc chstate);
-int
-prlsdkApplyConfig(virConnectPtr conn,
-                  virDomainObjPtr dom,
-                  virDomainDefPtr new);
-int prlsdkCreateVm(virConnectPtr conn, virDomainDefPtr def);
-int prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def);
-int
-prlsdkUnregisterDomain(vzConnPtr privconn, virDomainObjPtr dom);
-int
-prlsdkDomainManagedSaveRemove(virDomainObjPtr dom);
-int
-prlsdkAttachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk);
-int
-prlsdkDetachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk);
-int
-prlsdkGetBlockStats(virDomainObjPtr dom, virDomainDiskDefPtr disk, virDomainBlockStatsPtr stats);
diff --git a/src/parallels/parallels_storage.c b/src/parallels/parallels_storage.c
deleted file mode 100644 (file)
index b0dac50..0000000
+++ /dev/null
@@ -1,1654 +0,0 @@
-/*
- * parallels_storage.c: core driver functions for managing
- * Parallels Cloud Server hosts
- *
- * Copyright (C) 2013-2014 Red Hat, Inc.
- * Copyright (C) 2012 Parallels, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <config.h>
-
-#include <stdlib.h>
-#include <dirent.h>
-#include <sys/statvfs.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "datatypes.h"
-#include "dirname.h"
-#include "viralloc.h"
-#include "configmake.h"
-#include "virstoragefile.h"
-#include "virerror.h"
-#include "virfile.h"
-#include "parallels_utils.h"
-#include "virstring.h"
-
-#define VIR_FROM_THIS VIR_FROM_PARALLELS
-
-#define vzPoolNotFoundError(pool_name)                    \
-    virReportError(VIR_ERR_INVALID_ARG,                          \
-                   _("pool '%s' not found"), pool_name);
-
-static virStorageVolDefPtr
-vzStorageVolDefineXML(virStoragePoolObjPtr pool, const char *xmldesc,
-                             const char *xmlfile, bool is_new);
-static virStorageVolPtr
-vzStorageVolLookupByPath(virConnectPtr conn, const char *path);
-
-static int
-vzStoragePoolGetAlloc(virStoragePoolDefPtr def);
-
-static void
-vzStorageLock(virStorageDriverStatePtr driver)
-{
-    virMutexLock(&driver->lock);
-}
-
-static void
-vzStorageUnlock(virStorageDriverStatePtr driver)
-{
-    virMutexUnlock(&driver->lock);
-}
-
-int
-vzStorageClose(virConnectPtr conn)
-{
-    vzConnPtr privconn = conn->privateData;
-
-    if (!privconn)
-        return 0;
-
-    virStorageDriverStatePtr storageState = privconn->storageState;
-    privconn->storageState = NULL;
-
-    if (!storageState)
-        return 0;
-
-    vzStorageLock(storageState);
-    virStoragePoolObjListFree(&privconn->pools);
-    VIR_FREE(storageState->configDir);
-    VIR_FREE(storageState->autostartDir);
-    vzStorageUnlock(storageState);
-    virMutexDestroy(&storageState->lock);
-    VIR_FREE(storageState);
-
-    return 0;
-}
-
-static int
-vzFindVolumes(virStoragePoolObjPtr pool)
-{
-    DIR *dir;
-    struct dirent *ent;
-    char *path = NULL;
-    int ret = -1;
-    int direrr;
-
-    if (!(dir = opendir(pool->def->target.path))) {
-        virReportSystemError(errno,
-                             _("cannot open path '%s'"),
-                             pool->def->target.path);
-        return -1;
-    }
-
-    while ((direrr = virDirRead(dir, &ent, pool->def->target.path)) > 0) {
-        if (!virFileHasSuffix(ent->d_name, ".xml"))
-            continue;
-
-        if (!(path = virFileBuildPath(pool->def->target.path,
-                                      ent->d_name, NULL)))
-            goto cleanup;
-        if (!vzStorageVolDefineXML(pool, NULL, path, false))
-            goto cleanup;
-
-        VIR_FREE(path);
-    }
-    if (direrr < 0)
-        goto cleanup;
-
-    ret = 0;
- cleanup:
-    VIR_FREE(path);
-    closedir(dir);
-    return ret;
-
-}
-
-/*
- * Generate unique pool name by path
- */
-static char *vzMakePoolName(virConnectPtr conn, const char *path)
-{
-    vzConnPtr privconn = conn->privateData;
-    char *name;
-    size_t i;
-
-    for (i = 0; i < UINT_MAX; i++) {
-        bool found = false;
-        size_t j;
-
-        if ((!i && VIR_STRDUP(name, path) < 0) ||
-            (i && virAsprintf(&name, "%s-%zu", path, i) < 0))
-            return NULL;
-
-        for (j = 0; j < strlen(name); j++)
-            if (name[j] == '/')
-                name[j] = '-';
-
-        for (j = 0; j < privconn->pools.count; j++) {
-            if (STREQ(name, privconn->pools.objs[j]->def->name)) {
-                found = true;
-                break;
-            }
-        }
-
-        if (!found)
-            return name;
-
-        VIR_FREE(name);
-    }
-
-    return NULL;
-}
-
-static virStoragePoolObjPtr
-vzPoolCreateByPath(virConnectPtr conn, const char *path)
-{
-    vzConnPtr privconn = conn->privateData;
-    virStoragePoolObjListPtr pools = &privconn->pools;
-    virStoragePoolDefPtr def;
-    virStoragePoolObjPtr pool = NULL;
-
-    if (VIR_ALLOC(def) < 0)
-        goto error;
-
-    if (!(def->name = vzMakePoolName(conn, path)))
-        goto error;
-
-    if (virUUIDGenerate(def->uuid)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("Can't generate UUID"));
-        goto error;
-    }
-
-    def->type = VIR_STORAGE_POOL_DIR;
-    if (VIR_STRDUP(def->target.path, path) < 0)
-        goto error;
-
-    if (!(pool = virStoragePoolObjAssignDef(pools, def)))
-        goto error;
-
-    if (virStoragePoolObjSaveDef(privconn->storageState, pool, def) < 0) {
-        virStoragePoolObjRemove(pools, pool);
-        goto error;
-    }
-
-    virStoragePoolObjUnlock(pool);
-
-    return pool;
- error:
-    virStoragePoolDefFree(def);
-    if (pool)
-        virStoragePoolObjUnlock(pool);
-    return NULL;
-}
-
-/*
- * Create pool of type VIR_STORAGE_POOL_DIR with
- * path to the VM, if it does not exist.
- */
-static virStoragePoolObjPtr
-vzPoolAddByDomain(virConnectPtr conn, virDomainObjPtr dom)
-{
-    vzConnPtr privconn = conn->privateData;
-    vzDomObjPtr pdom = dom->privateData;
-    virStoragePoolObjListPtr pools = &privconn->pools;
-    char *poolPath;
-    virStoragePoolObjPtr pool = NULL;
-    size_t j;
-
-    poolPath = mdir_name(pdom->home);
-    if (!poolPath) {
-        virReportOOMError();
-        return NULL;
-    }
-
-    for (j = 0; j < pools->count; j++) {
-        if (STREQ(poolPath, pools->objs[j]->def->target.path)) {
-            pool = pools->objs[j];
-            break;
-        }
-    }
-
-    if (!pool)
-        pool = vzPoolCreateByPath(conn, poolPath);
-
-    VIR_FREE(poolPath);
-    return pool;
-}
-
-static int vzDiskDescParseNode(xmlDocPtr xml,
-                                      xmlNodePtr root,
-                                      virStorageVolDefPtr def)
-{
-    xmlXPathContextPtr ctxt = NULL;
-    int ret = -1;
-
-    if (STRNEQ((const char *)root->name, "Parallels_disk_image")) {
-        virReportError(VIR_ERR_XML_ERROR,
-                       "%s", _("unknown root element for storage pool"));
-        goto cleanup;
-    }
-
-    ctxt = xmlXPathNewContext(xml);
-    if (ctxt == NULL) {
-        virReportOOMError();
-        goto cleanup;
-    }
-
-    ctxt->node = root;
-
-    if (virXPathULongLong("string(./Disk_Parameters/Disk_size)",
-                          ctxt, &def->target.capacity) < 0) {
-        virReportError(VIR_ERR_XML_ERROR,
-                       "%s", _("failed to get disk size from "
-                               "the disk descriptor xml"));
-        goto cleanup;
-    }
-
-    def->target.capacity <<= 9;
-    def->target.allocation = def->target.capacity;
-    ret = 0;
- cleanup:
-    xmlXPathFreeContext(ctxt);
-    return ret;
-
-}
-
-static int vzDiskDescParse(const char *path, virStorageVolDefPtr def)
-{
-    xmlDocPtr xml;
-    int ret = -1;
-
-    if (!(xml = virXMLParse(path, NULL, NULL)))
-        return -1;
-
-    ret = vzDiskDescParseNode(xml, xmlDocGetRootElement(xml), def);
-    xmlFreeDoc(xml);
-    return ret;
-}
-
-static int vzAddDiskVolume(virStoragePoolObjPtr pool,
-                                  virDomainObjPtr dom,
-                                  const char *diskName,
-                                  const char *diskPath,
-                                  const char *diskDescPath)
-{
-    virStorageVolDefPtr def = NULL;
-
-    if (VIR_ALLOC(def))
-        goto error;
-
-    if (virAsprintf(&def->name, "%s-%s", dom->def->name, diskName) < 0)
-        goto error;
-
-    def->type = VIR_STORAGE_VOL_FILE;
-
-    if (vzDiskDescParse(diskDescPath, def) < 0)
-        goto error;
-
-    if (!(def->target.path = realpath(diskPath, NULL)))
-        goto no_memory;
-
-    if (VIR_STRDUP(def->key, def->target.path) < 0)
-        goto error;
-
-    if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, def) < 0)
-        goto error;
-
-    return 0;
- no_memory:
-    virReportOOMError();
- error:
-    virStorageVolDefFree(def);
-    return -1;
-}
-
-static int vzFindVmVolumes(virStoragePoolObjPtr pool,
-                                  virDomainObjPtr dom)
-{
-    vzDomObjPtr pdom = dom->privateData;
-    DIR *dir;
-    struct dirent *ent;
-    char *diskPath = NULL, *diskDescPath = NULL;
-    struct stat sb;
-    int ret = -1;
-    int direrr;
-
-    if (!(dir = opendir(pdom->home))) {
-        virReportSystemError(errno,
-                             _("cannot open path '%s'"),
-                             pdom->home);
-        return ret;
-    }
-
-    while ((direrr = virDirRead(dir, &ent, pdom->home)) > 0) {
-        VIR_FREE(diskPath);
-        VIR_FREE(diskDescPath);
-
-        if (!(diskPath = virFileBuildPath(pdom->home, ent->d_name, NULL)))
-            goto cleanup;
-
-        if (lstat(diskPath, &sb) < 0) {
-            virReportSystemError(errno,
-                                 _("cannot stat path '%s'"),
-                                 ent->d_name);
-            goto cleanup;
-        }
-
-        if (!S_ISDIR(sb.st_mode))
-            continue;
-
-        if (!(diskDescPath = virFileBuildPath(diskPath,
-                                              "DiskDescriptor", ".xml")))
-            goto cleanup;
-
-        if (!virFileExists(diskDescPath))
-            continue;
-
-        /* here we know, that ent->d_name is a disk image directory */
-
-        if (vzAddDiskVolume(pool, dom, ent->d_name,
-                                   diskPath, diskDescPath))
-            goto cleanup;
-    }
-    if (direrr < 0)
-        goto cleanup;
-
-    ret = 0;
- cleanup:
-    VIR_FREE(diskPath);
-    VIR_FREE(diskDescPath);
-    closedir(dir);
-    return ret;
-
-}
-
-static int
-vzPoolsAdd(virDomainObjPtr dom,
-                  void *opaque)
-{
-    virConnectPtr conn = opaque;
-    virStoragePoolObjPtr pool;
-
-    if (!(pool = vzPoolAddByDomain(conn, dom)))
-        return -1;
-
-    if (vzFindVmVolumes(pool, dom))
-        return -1;
-
-    return 0;
-}
-
-static int vzLoadPools(virConnectPtr conn)
-{
-    vzConnPtr privconn = conn->privateData;
-    virStorageDriverStatePtr storageState = privconn->storageState;
-    char *base = NULL;
-    size_t i;
-
-    if (VIR_STRDUP(base, SYSCONFDIR "/libvirt") < 0)
-        goto error;
-
-    /* Configuration path is /etc/libvirt/parallels-storage/... . */
-    if (virAsprintf(&storageState->configDir,
-                    "%s/parallels-storage", base) == -1)
-        goto error;
-
-    if (virAsprintf(&storageState->autostartDir,
-                    "%s/parallels-storage/autostart", base) == -1)
-        goto error;
-
-    VIR_FREE(base);
-
-    if (virStoragePoolLoadAllConfigs(&privconn->pools,
-                                     storageState->configDir,
-                                     storageState->autostartDir) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("Failed to load pool configs"));
-        goto error;
-    }
-
-    if (virDomainObjListForEach(privconn->domains, vzPoolsAdd, conn) < 0)
-        goto error;
-
-    for (i = 0; i < privconn->pools.count; i++) {
-        virStoragePoolObjLock(privconn->pools.objs[i]);
-        virStoragePoolObjPtr pool;
-
-        pool = privconn->pools.objs[i];
-        pool->active = 1;
-
-        if (vzStoragePoolGetAlloc(pool->def) < 0)
-            goto error;
-
-        if (vzFindVolumes(pool) < 0)
-            goto error;
-
-        virStoragePoolObjUnlock(privconn->pools.objs[i]);
-    }
-
-    return 0;
-
- error:
-    VIR_FREE(base);
-    return -1;
-}
-
-virDrvOpenStatus
-vzStorageOpen(virConnectPtr conn,
-                     unsigned int flags)
-{
-    vzConnPtr privconn = conn->privateData;
-    virStorageDriverStatePtr storageState;
-    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
-
-    if (STRNEQ(conn->driver->name, "vz") &&
-        STRNEQ(conn->driver->name, "Parallels"))
-        return VIR_DRV_OPEN_DECLINED;
-
-    if (VIR_ALLOC(storageState) < 0)
-        return VIR_DRV_OPEN_ERROR;
-
-    if (virMutexInit(&storageState->lock) < 0) {
-        VIR_FREE(storageState);
-        return VIR_DRV_OPEN_ERROR;
-    }
-
-    privconn->storageState = storageState;
-    vzStorageLock(storageState);
-
-    if (vzLoadPools(conn))
-        goto error;
-
-    vzStorageUnlock(storageState);
-
-    return VIR_DRV_OPEN_SUCCESS;
-
- error:
-    vzStorageUnlock(storageState);
-    vzStorageClose(conn);
-    return VIR_DRV_OPEN_ERROR;
-}
-
-static int
-vzConnectNumOfStoragePools(virConnectPtr conn)
-{
-    vzConnPtr privconn = conn->privateData;
-    int numActive = 0;
-    size_t i;
-
-    vzDriverLock(privconn);
-    for (i = 0; i < privconn->pools.count; i++)
-        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
-            numActive++;
-    vzDriverUnlock(privconn);
-
-    return numActive;
-}
-
-static int
-vzConnectListStoragePools(virConnectPtr conn, char **const names, int nnames)
-{
-    vzConnPtr privconn = conn->privateData;
-    int n = 0;
-    size_t i;
-
-    vzDriverLock(privconn);
-    memset(names, 0, sizeof(*names) * nnames);
-    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
-        virStoragePoolObjLock(privconn->pools.objs[i]);
-        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
-            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
-            virStoragePoolObjUnlock(privconn->pools.objs[i]);
-            goto error;
-        }
-        virStoragePoolObjUnlock(privconn->pools.objs[i]);
-    }
-    vzDriverUnlock(privconn);
-
-    return n;
-
- error:
-    for (n = 0; n < nnames; n++)
-        VIR_FREE(names[n]);
-    vzDriverUnlock(privconn);
-    return -1;
-}
-
-static int
-vzConnectNumOfDefinedStoragePools(virConnectPtr conn)
-{
-    vzConnPtr privconn = conn->privateData;
-    int numInactive = 0;
-    size_t i;
-
-    vzDriverLock(privconn);
-    for (i = 0; i < privconn->pools.count; i++) {
-        virStoragePoolObjLock(privconn->pools.objs[i]);
-        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
-            numInactive++;
-        virStoragePoolObjUnlock(privconn->pools.objs[i]);
-    }
-    vzDriverUnlock(privconn);
-
-    return numInactive;
-}
-
-static int
-vzConnectListDefinedStoragePools(virConnectPtr conn,
-                                        char **const names, int nnames)
-{
-    vzConnPtr privconn = conn->privateData;
-    int n = 0;
-    size_t i;
-
-    vzDriverLock(privconn);
-    memset(names, 0, sizeof(*names) * nnames);
-    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
-        virStoragePoolObjLock(privconn->pools.objs[i]);
-        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
-            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
-            virStoragePoolObjUnlock(privconn->pools.objs[i]);
-            goto error;
-        }
-        virStoragePoolObjUnlock(privconn->pools.objs[i]);
-    }
-    vzDriverUnlock(privconn);
-
-    return n;
-
- error:
-    for (n = 0; n < nnames; n++)
-        VIR_FREE(names[n]);
-    vzDriverUnlock(privconn);
-    return -1;
-}
-
-
-static int
-vzStoragePoolIsActive(virStoragePoolPtr pool)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr obj;
-    int ret = -1;
-
-    vzDriverLock(privconn);
-    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
-    vzDriverUnlock(privconn);
-    if (!obj) {
-        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
-        goto cleanup;
-    }
-    ret = virStoragePoolObjIsActive(obj);
-
- cleanup:
-    if (obj)
-        virStoragePoolObjUnlock(obj);
-    return ret;
-}
-
-static int
-vzStoragePoolIsPersistent(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
-{
-    return 1;
-}
-
-static virStoragePoolPtr
-vzStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
-{
-    vzConnPtr privconn = conn->privateData;
-    virStoragePoolObjPtr pool;
-    virStoragePoolPtr ret = NULL;
-
-    vzDriverLock(privconn);
-    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
-    vzDriverUnlock(privconn);
-
-    if (pool == NULL) {
-        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
-        goto cleanup;
-    }
-
-    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
-                            NULL, NULL);
-
- cleanup:
-    if (pool)
-        virStoragePoolObjUnlock(pool);
-    return ret;
-}
-
-static virStoragePoolPtr
-vzStoragePoolLookupByName(virConnectPtr conn, const char *name)
-{
-    vzConnPtr privconn = conn->privateData;
-    virStoragePoolObjPtr pool;
-    virStoragePoolPtr ret = NULL;
-
-    vzDriverLock(privconn);
-    pool = virStoragePoolObjFindByName(&privconn->pools, name);
-    vzDriverUnlock(privconn);
-
-    if (pool == NULL) {
-        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
-        goto cleanup;
-    }
-
-    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
-                            NULL, NULL);
-
- cleanup:
-    if (pool)
-        virStoragePoolObjUnlock(pool);
-    return ret;
-}
-
-static virStoragePoolPtr
-vzStoragePoolLookupByVolume(virStorageVolPtr vol)
-{
-    return vzStoragePoolLookupByName(vol->conn, vol->pool);
-}
-
-/*
- * Fill capacity, available and allocation
- * fields in pool definition.
- */
-static int
-vzStoragePoolGetAlloc(virStoragePoolDefPtr def)
-{
-    struct statvfs sb;
-
-    if (statvfs(def->target.path, &sb) < 0) {
-        virReportSystemError(errno,
-                             _("cannot statvfs path '%s'"),
-                             def->target.path);
-        return -1;
-    }
-
-    def->capacity = ((unsigned long long)sb.f_frsize *
-                     (unsigned long long)sb.f_blocks);
-    def->available = ((unsigned long long)sb.f_bfree *
-                      (unsigned long long)sb.f_frsize);
-    def->allocation = def->capacity - def->available;
-
-    return 0;
-}
-
-static virStoragePoolPtr
-vzStoragePoolDefineXML(virConnectPtr conn,
-                              const char *xml, unsigned int flags)
-{
-    vzConnPtr privconn = conn->privateData;
-    virStoragePoolDefPtr def;
-    virStoragePoolObjPtr pool = NULL;
-    virStoragePoolPtr ret = NULL;
-
-    virCheckFlags(0, NULL);
-
-    vzDriverLock(privconn);
-    if (!(def = virStoragePoolDefParseString(xml)))
-        goto cleanup;
-
-    if (def->type != VIR_STORAGE_POOL_DIR) {
-        virReportError(VIR_ERR_NO_SUPPORT, "%s",
-                       _("Only local directories are supported"));
-        goto cleanup;
-    }
-
-    if (virStoragePoolObjIsDuplicate(&privconn->pools, def, 0) < 0)
-        goto cleanup;
-
-    if (virStoragePoolSourceFindDuplicate(conn, &privconn->pools, def) < 0)
-        goto cleanup;
-
-    if (vzStoragePoolGetAlloc(def))
-        goto cleanup;
-
-    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
-        goto cleanup;
-
-    if (virStoragePoolObjSaveDef(privconn->storageState, pool, def) < 0) {
-        virStoragePoolObjRemove(&privconn->pools, pool);
-        def = NULL;
-        goto cleanup;
-    }
-    def = NULL;
-
-    if (VIR_STRDUP(pool->configFile, "\0") < 0)
-        goto cleanup;
-
-    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
-                            NULL, NULL);
-
- cleanup:
-    virStoragePoolDefFree(def);
-    if (pool)
-        virStoragePoolObjUnlock(pool);
-    vzDriverUnlock(privconn);
-    return ret;
-}
-
-static int
-vzStoragePoolUndefine(virStoragePoolPtr pool)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    int ret = -1;
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto cleanup;
-    }
-
-    if (virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is still active"), pool->name);
-        goto cleanup;
-    }
-
-    if (virStoragePoolObjDeleteDef(privpool) < 0)
-        goto cleanup;
-
-    VIR_FREE(privpool->configFile);
-
-    virStoragePoolObjRemove(&privconn->pools, privpool);
-    ret = 0;
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    vzDriverUnlock(privconn);
-    return ret;
-}
-
-static int
-vzStoragePoolCreate(virStoragePoolPtr pool, unsigned int flags)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    int ret = -1;
-
-    virCheckFlags(0, -1);
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto cleanup;
-    }
-
-    if (virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is already active"), pool->name);
-        goto cleanup;
-    }
-
-    privpool->active = 1;
-    ret = 0;
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-static int
-vzStoragePoolDestroy(virStoragePoolPtr pool)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    int ret = -1;
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto cleanup;
-    }
-
-    if (!virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), pool->name);
-        goto cleanup;
-    }
-
-    if (privpool->configFile == NULL) {
-        virStoragePoolObjRemove(&privconn->pools, privpool);
-        privpool = NULL;
-    }
-    ret = 0;
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    vzDriverUnlock(privconn);
-    return ret;
-}
-
-static int
-vzStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    int ret = -1;
-
-    virCheckFlags(0, -1);
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto cleanup;
-    }
-
-    if (!virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), pool->name);
-        goto cleanup;
-    }
-    ret = 0;
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-
-static int
-vzStoragePoolGetInfo(virStoragePoolPtr pool, virStoragePoolInfoPtr info)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    int ret = -1;
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto cleanup;
-    }
-
-    memset(info, 0, sizeof(virStoragePoolInfo));
-    if (privpool->active)
-        info->state = VIR_STORAGE_POOL_RUNNING;
-    else
-        info->state = VIR_STORAGE_POOL_INACTIVE;
-    info->capacity = privpool->def->capacity;
-    info->allocation = privpool->def->allocation;
-    info->available = privpool->def->available;
-    ret = 0;
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-static char *
-vzStoragePoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    char *ret = NULL;
-
-    virCheckFlags(0, NULL);
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto cleanup;
-    }
-
-    ret = virStoragePoolDefFormat(privpool->def);
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-static int
-vzStoragePoolGetAutostart(virStoragePoolPtr pool, int *autostart)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    int ret = -1;
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto cleanup;
-    }
-
-    if (!privpool->configFile) {
-        *autostart = 0;
-    } else {
-        *autostart = privpool->autostart;
-    }
-    ret = 0;
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-static int
-vzStoragePoolSetAutostart(virStoragePoolPtr pool, int autostart)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    int ret = -1;
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto cleanup;
-    }
-
-    if (!privpool->configFile) {
-        virReportError(VIR_ERR_INVALID_ARG, "%s", _("pool has no config file"));
-        goto cleanup;
-    }
-
-    privpool->autostart = (autostart != 0);
-    ret = 0;
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-static int
-vzStoragePoolNumOfVolumes(virStoragePoolPtr pool)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    int ret = -1;
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto cleanup;
-    }
-
-    if (!virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), pool->name);
-        goto cleanup;
-    }
-
-    ret = privpool->volumes.count;
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-static int
-vzStoragePoolListVolumes(virStoragePoolPtr pool,
-                                char **const names, int maxnames)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    int n = 0;
-    size_t i = 0;
-
-    memset(names, 0, maxnames * sizeof(*names));
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto error;
-    }
-
-
-    if (!virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                 _("storage pool '%s' is not active"), pool->name);
-        goto error;
-    }
-
-    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
-        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
-            goto error;
-    }
-
-    virStoragePoolObjUnlock(privpool);
-    return n;
-
- error:
-    for (n = 0; n < maxnames; n++)
-        VIR_FREE(names[i]);
-
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return -1;
-}
-
-static virStorageVolPtr
-vzStorageVolLookupByName(virStoragePoolPtr pool,
-                                   const char *name)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol;
-    virStorageVolPtr ret = NULL;
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto cleanup;
-    }
-
-
-    if (!virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), pool->name);
-        goto cleanup;
-    }
-
-    privvol = virStorageVolDefFindByName(privpool, name);
-
-    if (!privvol) {
-        virReportError(VIR_ERR_NO_STORAGE_VOL,
-                       _("no storage vol with matching name '%s'"), name);
-        goto cleanup;
-    }
-
-    ret = virGetStorageVol(pool->conn, privpool->def->name,
-                           privvol->name, privvol->key,
-                           NULL, NULL);
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-
-static virStorageVolPtr
-vzStorageVolLookupByKey(virConnectPtr conn, const char *key)
-{
-    vzConnPtr privconn = conn->privateData;
-    size_t i;
-    virStorageVolPtr ret = NULL;
-
-    vzDriverLock(privconn);
-    for (i = 0; i < privconn->pools.count; i++) {
-        virStoragePoolObjLock(privconn->pools.objs[i]);
-        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
-            virStorageVolDefPtr privvol =
-                virStorageVolDefFindByKey(privconn->pools.objs[i], key);
-
-            if (privvol) {
-                ret = virGetStorageVol(conn,
-                                       privconn->pools.objs[i]->def->name,
-                                       privvol->name, privvol->key,
-                                       NULL, NULL);
-                virStoragePoolObjUnlock(privconn->pools.objs[i]);
-                break;
-            }
-        }
-        virStoragePoolObjUnlock(privconn->pools.objs[i]);
-    }
-    vzDriverUnlock(privconn);
-
-    if (!ret)
-        virReportError(VIR_ERR_NO_STORAGE_VOL,
-                       _("no storage vol with matching key '%s'"), key);
-
-    return ret;
-}
-
-virStorageVolPtr
-vzStorageVolLookupByPathLocked(virConnectPtr conn, const char *path)
-{
-    vzConnPtr privconn = conn->privateData;
-    size_t i;
-    virStorageVolPtr ret = NULL;
-
-    for (i = 0; i < privconn->pools.count; i++) {
-        virStoragePoolObjLock(privconn->pools.objs[i]);
-        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
-            virStorageVolDefPtr privvol =
-                virStorageVolDefFindByPath(privconn->pools.objs[i], path);
-
-            if (privvol) {
-                ret = virGetStorageVol(conn,
-                                       privconn->pools.objs[i]->def->name,
-                                       privvol->name, privvol->key,
-                                       NULL, NULL);
-                virStoragePoolObjUnlock(privconn->pools.objs[i]);
-                break;
-            }
-        }
-        virStoragePoolObjUnlock(privconn->pools.objs[i]);
-    }
-
-    if (!ret)
-        virReportError(VIR_ERR_NO_STORAGE_VOL,
-                       _("no storage vol with matching path '%s'"), path);
-
-    return ret;
-}
-
-static virStorageVolPtr
-vzStorageVolLookupByPath(virConnectPtr conn, const char *path)
-{
-    vzConnPtr privconn = conn->privateData;
-    virStorageVolPtr ret = NULL;
-
-    vzDriverLock(privconn);
-    ret = vzStorageVolLookupByPathLocked(conn, path);
-    vzDriverUnlock(privconn);
-
-    return ret;
-}
-
-static virStorageVolDefPtr
-vzStorageVolDefineXML(virStoragePoolObjPtr pool,
-                             const char *xmldesc,
-                             const char *xmlfile, bool is_new)
-{
-    virStorageVolDefPtr privvol = NULL;
-    virStorageVolDefPtr ret = NULL;
-    char *xml_path = NULL;
-
-    if (xmlfile)
-        privvol = virStorageVolDefParseFile(pool->def, xmlfile, 0);
-    else
-        privvol = virStorageVolDefParseString(pool->def, xmldesc, 0);
-
-    if (privvol == NULL)
-        goto cleanup;
-
-    if (virStorageVolDefFindByName(pool, privvol->name)) {
-        virReportError(VIR_ERR_OPERATION_FAILED,
-                       "%s", _("storage vol already exists"));
-        goto cleanup;
-    }
-
-    if (is_new) {
-        /* Make sure enough space */
-        if ((pool->def->allocation + privvol->target.allocation) >
-            pool->def->capacity) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Not enough free space in pool for volume '%s'"),
-                           privvol->name);
-            goto cleanup;
-        }
-    }
-
-    if (virAsprintf(&privvol->target.path, "%s/%s",
-                    pool->def->target.path, privvol->name) < 0)
-        goto cleanup;
-
-    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0)
-        goto cleanup;
-
-    if (is_new) {
-        xml_path = vzAddFileExt(privvol->target.path, ".xml");
-        if (!xml_path)
-            goto cleanup;
-
-        if (virXMLSaveFile(xml_path, NULL, "volume-create", xmldesc)) {
-            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
-                           _("Can't create file with volume description"));
-            goto cleanup;
-        }
-
-        pool->def->allocation += privvol->target.allocation;
-        pool->def->available = (pool->def->capacity -
-                                pool->def->allocation);
-    }
-
-    if (VIR_APPEND_ELEMENT_COPY(pool->volumes.objs,
-                                pool->volumes.count, privvol) < 0)
-        goto cleanup;
-
-    ret = privvol;
-    privvol = NULL;
-
- cleanup:
-    virStorageVolDefFree(privvol);
-    VIR_FREE(xml_path);
-    return ret;
-}
-
-static virStorageVolPtr
-vzStorageVolCreateXML(virStoragePoolPtr pool,
-                                const char *xmldesc, unsigned int flags)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    virStorageVolPtr ret = NULL;
-    virStorageVolDefPtr privvol = NULL;
-
-    virCheckFlags(0, NULL);
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto cleanup;
-    }
-
-    if (!virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), pool->name);
-        goto cleanup;
-    }
-
-    privvol = vzStorageVolDefineXML(privpool, xmldesc, NULL, true);
-    if (!privvol)
-        goto cleanup;
-
-    ret = virGetStorageVol(pool->conn, privpool->def->name,
-                           privvol->name, privvol->key,
-                           NULL, NULL);
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-static virStorageVolPtr
-vzStorageVolCreateXMLFrom(virStoragePoolPtr pool,
-                                    const char *xmldesc,
-                                    virStorageVolPtr clonevol,
-                                    unsigned int flags)
-{
-    vzConnPtr privconn = pool->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol = NULL, origvol = NULL;
-    virStorageVolPtr ret = NULL;
-
-    virCheckFlags(0, NULL);
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(pool->name);
-        goto cleanup;
-    }
-
-    if (!virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), pool->name);
-        goto cleanup;
-    }
-
-    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
-    if (privvol == NULL)
-        goto cleanup;
-
-    if (virStorageVolDefFindByName(privpool, privvol->name)) {
-        virReportError(VIR_ERR_OPERATION_FAILED,
-                       "%s", _("storage vol already exists"));
-        goto cleanup;
-    }
-
-    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
-    if (!origvol) {
-        virReportError(VIR_ERR_NO_STORAGE_VOL,
-                       _("no storage vol with matching name '%s'"),
-                       clonevol->name);
-        goto cleanup;
-    }
-
-    /* Make sure enough space */
-    if ((privpool->def->allocation + privvol->target.allocation) >
-        privpool->def->capacity) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Not enough free space in pool for volume '%s'"),
-                       privvol->name);
-        goto cleanup;
-    }
-    privpool->def->available = (privpool->def->capacity -
-                                privpool->def->allocation);
-
-    if (virAsprintf(&privvol->target.path, "%s/%s",
-                    privpool->def->target.path, privvol->name) == -1)
-        goto cleanup;
-
-    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0)
-        goto cleanup;
-
-    privpool->def->allocation += privvol->target.allocation;
-    privpool->def->available = (privpool->def->capacity -
-                                privpool->def->allocation);
-
-    if (VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
-                                privpool->volumes.count, privvol) < 0)
-        goto cleanup;
-
-    ret = virGetStorageVol(pool->conn, privpool->def->name,
-                           privvol->name, privvol->key,
-                           NULL, NULL);
-    privvol = NULL;
-
- cleanup:
-    virStorageVolDefFree(privvol);
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-int vzStorageVolDefRemove(virStoragePoolObjPtr privpool,
-                                    virStorageVolDefPtr privvol)
-{
-    int ret = -1;
-    char *xml_path = NULL;
-    size_t i;
-
-    privpool->def->allocation -= privvol->target.allocation;
-    privpool->def->available = (privpool->def->capacity -
-                                privpool->def->allocation);
-
-    for (i = 0; i < privpool->volumes.count; i++) {
-        if (privpool->volumes.objs[i] == privvol) {
-            xml_path = vzAddFileExt(privvol->target.path, ".xml");
-            if (!xml_path)
-                goto cleanup;
-
-            if (unlink(xml_path)) {
-                virReportError(VIR_ERR_OPERATION_FAILED,
-                               _("Can't remove file '%s'"), xml_path);
-                goto cleanup;
-            }
-
-            virStorageVolDefFree(privvol);
-
-            VIR_DELETE_ELEMENT(privpool->volumes.objs, i, privpool->volumes.count);
-            break;
-        }
-    }
-
-    ret = 0;
- cleanup:
-    VIR_FREE(xml_path);
-    return ret;
-}
-
-static int
-vzStorageVolDelete(virStorageVolPtr vol, unsigned int flags)
-{
-    vzConnPtr privconn = vol->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol;
-    int ret = -1;
-
-    virCheckFlags(0, -1);
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(vol->pool);
-        goto cleanup;
-    }
-
-
-    privvol = virStorageVolDefFindByName(privpool, vol->name);
-
-    if (privvol == NULL) {
-        virReportError(VIR_ERR_NO_STORAGE_VOL,
-                       _("no storage vol with matching name '%s'"), vol->name);
-        goto cleanup;
-    }
-
-    if (!virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), vol->pool);
-        goto cleanup;
-    }
-
-
-    if (vzStorageVolDefRemove(privpool, privvol))
-        goto cleanup;
-
-    ret = 0;
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-
-static int
-vzStorageVolTypeForPool(int pooltype)
-{
-
-    switch (pooltype) {
-        case VIR_STORAGE_POOL_DIR:
-        case VIR_STORAGE_POOL_FS:
-        case VIR_STORAGE_POOL_NETFS:
-            return VIR_STORAGE_VOL_FILE;
- default:
-            return VIR_STORAGE_VOL_BLOCK;
-    }
-}
-
-static int
-vzStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr info)
-{
-    vzConnPtr privconn = vol->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol;
-    int ret = -1;
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(vol->pool);
-        goto cleanup;
-    }
-
-    privvol = virStorageVolDefFindByName(privpool, vol->name);
-
-    if (privvol == NULL) {
-        virReportError(VIR_ERR_NO_STORAGE_VOL,
-                       _("no storage vol with matching name '%s'"), vol->name);
-        goto cleanup;
-    }
-
-    if (!virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), vol->pool);
-        goto cleanup;
-    }
-
-    memset(info, 0, sizeof(*info));
-    info->type = vzStorageVolTypeForPool(privpool->def->type);
-    info->capacity = privvol->target.capacity;
-    info->allocation = privvol->target.allocation;
-    ret = 0;
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-static char *
-vzStorageVolGetXMLDesc(virStorageVolPtr vol, unsigned int flags)
-{
-    vzConnPtr privconn = vol->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol;
-    char *ret = NULL;
-
-    virCheckFlags(0, NULL);
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(vol->pool);
-        goto cleanup;
-    }
-
-    privvol = virStorageVolDefFindByName(privpool, vol->name);
-
-    if (privvol == NULL) {
-        virReportError(VIR_ERR_NO_STORAGE_VOL,
-                       _("no storage vol with matching name '%s'"), vol->name);
-        goto cleanup;
-    }
-
-    if (!virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), vol->pool);
-        goto cleanup;
-    }
-
-    ret = virStorageVolDefFormat(privpool->def, privvol);
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-static char *
-vzStorageVolGetPath(virStorageVolPtr vol)
-{
-    vzConnPtr privconn = vol->conn->privateData;
-    virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol;
-    char *ret = NULL;
-
-    vzDriverLock(privconn);
-    privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool);
-    vzDriverUnlock(privconn);
-
-    if (privpool == NULL) {
-        vzPoolNotFoundError(vol->pool);
-        goto cleanup;
-    }
-
-    privvol = virStorageVolDefFindByName(privpool, vol->name);
-
-    if (privvol == NULL) {
-        virReportError(VIR_ERR_NO_STORAGE_VOL,
-                       _("no storage vol with matching name '%s'"), vol->name);
-        goto cleanup;
-    }
-
-    if (!virStoragePoolObjIsActive(privpool)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), vol->pool);
-        goto cleanup;
-    }
-
-    ignore_value(VIR_STRDUP(ret, privvol->target.path));
-
- cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return ret;
-}
-
-virStorageDriver vzStorageDriver = {
-    .name = "Parallels",
-
-    .connectNumOfStoragePools = vzConnectNumOfStoragePools,   /* 0.10.0 */
-    .connectListStoragePools = vzConnectListStoragePools,   /* 0.10.0 */
-    .connectNumOfDefinedStoragePools = vzConnectNumOfDefinedStoragePools,     /* 0.10.0 */
-    .connectListDefinedStoragePools = vzConnectListDefinedStoragePools,     /* 0.10.0 */
-    .storagePoolLookupByName = vzStoragePoolLookupByName,     /* 0.10.0 */
-    .storagePoolLookupByUUID = vzStoragePoolLookupByUUID,     /* 0.10.0 */
-    .storagePoolLookupByVolume = vzStoragePoolLookupByVolume, /* 0.10.0 */
-    .storagePoolDefineXML = vzStoragePoolDefineXML,      /* 0.10.0 */
-    .storagePoolUndefine = vzStoragePoolUndefine,     /* 0.10.0 */
-    .storagePoolCreate = vzStoragePoolCreate,  /* 0.10.0 */
-    .storagePoolDestroy = vzStoragePoolDestroy,       /* 0.10.0 */
-    .storagePoolRefresh = vzStoragePoolRefresh,       /* 0.10.0 */
-    .storagePoolGetInfo = vzStoragePoolGetInfo,       /* 0.10.0 */
-    .storagePoolGetXMLDesc = vzStoragePoolGetXMLDesc, /* 0.10.0 */
-    .storagePoolGetAutostart = vzStoragePoolGetAutostart,     /* 0.10.0 */
-    .storagePoolSetAutostart = vzStoragePoolSetAutostart,     /* 0.10.0 */
-    .storagePoolNumOfVolumes = vzStoragePoolNumOfVolumes,       /* 0.10.0 */
-    .storagePoolListVolumes = vzStoragePoolListVolumes,       /* 0.10.0 */
-
-    .storageVolLookupByName = vzStorageVolLookupByName,    /* 0.10.0 */
-    .storageVolLookupByKey = vzStorageVolLookupByKey,      /* 0.10.0 */
-    .storageVolLookupByPath = vzStorageVolLookupByPath,    /* 0.10.0 */
-    .storageVolCreateXML = vzStorageVolCreateXML,  /* 0.10.0 */
-    .storageVolCreateXMLFrom = vzStorageVolCreateXMLFrom,  /* 0.10.0 */
-    .storageVolDelete = vzStorageVolDelete,        /* 0.10.0 */
-    .storageVolGetInfo = vzStorageVolGetInfo,      /* 0.10.0 */
-    .storageVolGetXMLDesc = vzStorageVolGetXMLDesc,        /* 0.10.0 */
-    .storageVolGetPath = vzStorageVolGetPath,      /* 0.10.0 */
-    .storagePoolIsActive = vzStoragePoolIsActive,     /* 0.10.0 */
-    .storagePoolIsPersistent = vzStoragePoolIsPersistent,     /* 0.10.0 */
-};
diff --git a/src/parallels/parallels_utils.c b/src/parallels/parallels_utils.c
deleted file mode 100644 (file)
index 995ef79..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * parallels_utils.c: core driver functions for managing
- * Parallels Cloud Server hosts
- *
- * Copyright (C) 2012 Parallels, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <config.h>
-
-#include <stdarg.h>
-
-#include "vircommand.h"
-#include "virerror.h"
-#include "viralloc.h"
-#include "virjson.h"
-#include "parallels_utils.h"
-#include "virstring.h"
-#include "datatypes.h"
-
-#define VIR_FROM_THIS VIR_FROM_PARALLELS
-
-/**
- * vzDomObjFromDomain:
- * @domain: Domain pointer that has to be looked up
- *
- * This function looks up @domain and returns the appropriate virDomainObjPtr
- * that has to be unlocked by virObjectUnlock().
- *
- * Returns the domain object without incremented reference counter which is locked
- * on success, NULL otherwise.
- */
-virDomainObjPtr
-vzDomObjFromDomain(virDomainPtr domain)
-{
-    virDomainObjPtr vm;
-    vzConnPtr privconn = domain->conn->privateData;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
-
-    vm = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
-    if (!vm) {
-        virUUIDFormat(domain->uuid, uuidstr);
-        virReportError(VIR_ERR_NO_DOMAIN,
-                       _("no domain with matching uuid '%s' (%s)"),
-                       uuidstr, domain->name);
-        return NULL;
-    }
-
-    return vm;
-
-}
-
-/**
- * vzDomObjFromDomainRef:
- * @domain: Domain pointer that has to be looked up
- *
- * This function looks up @domain and returns the appropriate virDomainObjPtr
- * that has to be released by calling virDomainObjEndAPI().
- *
- * Returns the domain object with incremented reference counter which is locked
- * on success, NULL otherwise.
- */
-virDomainObjPtr
-vzDomObjFromDomainRef(virDomainPtr domain)
-{
-    virDomainObjPtr vm;
-    vzConnPtr privconn = domain->conn->privateData;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
-
-    vm = virDomainObjListFindByUUIDRef(privconn->domains, domain->uuid);
-    if (!vm) {
-        virUUIDFormat(domain->uuid, uuidstr);
-        virReportError(VIR_ERR_NO_DOMAIN,
-                       _("no domain with matching uuid '%s' (%s)"),
-                       uuidstr, domain->name);
-        return NULL;
-    }
-
-    return vm;
-}
-
-static int
-vzDoCmdRun(char **outbuf, const char *binary, va_list list)
-{
-    virCommandPtr cmd = virCommandNewVAList(binary, list);
-    int ret = -1;
-
-    if (outbuf)
-        virCommandSetOutputBuffer(cmd, outbuf);
-
-    if (virCommandRun(cmd, NULL) < 0)
-        goto cleanup;
-
-    ret = 0;
-
- cleanup:
-    virCommandFree(cmd);
-    if (ret && outbuf)
-        VIR_FREE(*outbuf);
-    return ret;
-}
-
-/*
- * Run command and parse its JSON output, return
- * pointer to virJSONValue or NULL in case of error.
- */
-virJSONValuePtr
-vzParseOutput(const char *binary, ...)
-{
-    char *outbuf;
-    virJSONValuePtr jobj = NULL;
-    va_list list;
-    int ret;
-
-    va_start(list, binary);
-    ret = vzDoCmdRun(&outbuf, binary, list);
-    va_end(list);
-    if (ret)
-        return NULL;
-
-    jobj = virJSONValueFromString(outbuf);
-    if (!jobj)
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("invalid output from prlctl: %s"), outbuf);
-
-    VIR_FREE(outbuf);
-    return jobj;
-}
-
-/*
- * Run command and return its output, pointer to
- * buffer or NULL in case of error. Caller os responsible
- * for freeing the buffer.
- */
-char *
-vzGetOutput(const char *binary, ...)
-{
-    char *outbuf;
-    va_list list;
-    int ret;
-
-    va_start(list, binary);
-    ret = vzDoCmdRun(&outbuf, binary, list);
-    va_end(list);
-    if (ret)
-        return NULL;
-
-    return outbuf;
-}
-
-/*
- * Run prlctl command and check for errors
- *
- * Return value is 0 in case of success, else - -1
- */
-int
-vzCmdRun(const char *binary, ...)
-{
-    int ret;
-    va_list list;
-
-    va_start(list, binary);
-    ret = vzDoCmdRun(NULL, binary, list);
-    va_end(list);
-
-    return ret;
-}
-
-/*
- * Return new file path in malloced string created by
- * concatenating first and second function arguments.
- */
-char *
-vzAddFileExt(const char *path, const char *ext)
-{
-    char *new_path = NULL;
-    size_t len = strlen(path) + strlen(ext) + 1;
-
-    if (VIR_ALLOC_N(new_path, len) < 0)
-        return NULL;
-
-    if (!virStrcpy(new_path, path, len)) {
-        VIR_FREE(new_path);
-        return NULL;
-    }
-    strcat(new_path, ext);
-
-    return new_path;
-}
diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h
deleted file mode 100644 (file)
index ce540b6..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * parallels_utils.h: core driver functions for managing
- * Parallels Cloud Server hosts
- *
- * Copyright (C) 2012 Parallels, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef PARALLELS_UTILS_H
-# define PARALLELS_UTILS_H
-
-# include <Parallels.h>
-
-# include "driver.h"
-# include "conf/domain_conf.h"
-# include "conf/storage_conf.h"
-# include "conf/domain_event.h"
-# include "conf/network_conf.h"
-# include "virthread.h"
-# include "virjson.h"
-
-# define vzParseError()                                                 \
-    virReportErrorHelper(VIR_FROM_TEST, VIR_ERR_OPERATION_FAILED, __FILE__,    \
-                     __FUNCTION__, __LINE__, _("Can't parse prlctl output"))
-
-# define IS_CT(def)  (def->os.type == VIR_DOMAIN_OSTYPE_EXE)
-
-# define vzDomNotFoundError(domain)                               \
-    do {                                                                 \
-        char uuidstr[VIR_UUID_STRING_BUFLEN];                            \
-        virUUIDFormat(domain->uuid, uuidstr);                            \
-        virReportError(VIR_ERR_NO_DOMAIN,                                \
-                       _("no domain with matching uuid '%s'"), uuidstr); \
-    } while (0)
-
-# define PARALLELS_DOMAIN_ROUTED_NETWORK_NAME   "Routed"
-# define PARALLELS_DOMAIN_BRIDGED_NETWORK_NAME  "Bridged"
-
-# define PARALLELS_REQUIRED_HOSTONLY_NETWORK "Host-Only"
-# define PARALLELS_HOSTONLY_NETWORK_TYPE "host-only"
-# define PARALLELS_REQUIRED_BRIDGED_NETWORK  "Bridged"
-# define PARALLELS_BRIDGED_NETWORK_TYPE  "bridged"
-
-struct _vzConn {
-    virMutex lock;
-
-    /* Immutable pointer, self-locking APIs */
-    virDomainObjListPtr domains;
-
-    PRL_HANDLE server;
-    virStoragePoolObjList pools;
-    virNetworkObjListPtr networks;
-    virCapsPtr caps;
-    virDomainXMLOptionPtr xmlopt;
-    virObjectEventStatePtr domainEventState;
-    virStorageDriverStatePtr storageState;
-    const char *drivername;
-};
-
-typedef struct _vzConn vzConn;
-typedef struct _vzConn *vzConnPtr;
-
-struct _vzCountersCache {
-    PRL_HANDLE stats;
-    virCond cond;
-    // -1 - unsubscribed
-    // > -1 - subscribed
-    int count;
-};
-
-typedef struct _vzCountersCache vzCountersCache;
-
-struct vzDomObj {
-    int id;
-    char *uuid;
-    char *home;
-    PRL_HANDLE sdkdom;
-    vzCountersCache cache;
-};
-
-typedef struct vzDomObj *vzDomObjPtr;
-
-virDrvOpenStatus vzStorageOpen(virConnectPtr conn, unsigned int flags);
-int vzStorageClose(virConnectPtr conn);
-extern virStorageDriver vzStorageDriver;
-
-virDrvOpenStatus vzNetworkOpen(virConnectPtr conn, unsigned int flags);
-int vzNetworkClose(virConnectPtr conn);
-extern virNetworkDriver vzNetworkDriver;
-
-virDomainObjPtr vzDomObjFromDomain(virDomainPtr domain);
-virDomainObjPtr vzDomObjFromDomainRef(virDomainPtr domain);
-
-virJSONValuePtr vzParseOutput(const char *binary, ...)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_SENTINEL;
-char * vzGetOutput(const char *binary, ...)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_SENTINEL;
-int vzCmdRun(const char *binary, ...)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_SENTINEL;
-char * vzAddFileExt(const char *path, const char *ext);
-void vzDriverLock(vzConnPtr driver);
-void vzDriverUnlock(vzConnPtr driver);
-virStorageVolPtr vzStorageVolLookupByPathLocked(virConnectPtr conn,
-                                                       const char *path);
-int vzStorageVolDefRemove(virStoragePoolObjPtr privpool,
-                                 virStorageVolDefPtr privvol);
-
-# define PARALLELS_BLOCK_STATS_FOREACH(OP)                                   \
-             OP(rd_req, VIR_DOMAIN_BLOCK_STATS_READ_REQ, "read_requests")    \
-             OP(rd_bytes, VIR_DOMAIN_BLOCK_STATS_READ_BYTES, "read_total")   \
-             OP(wr_req, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ, "write_requests")  \
-             OP(wr_bytes, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES, "write_total")
-
-#endif
diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c
new file mode 100644 (file)
index 0000000..cef3c77
--- /dev/null
@@ -0,0 +1,1418 @@
+/*
+ * vz_driver.c: core driver functions for managing
+ * Parallels Cloud Server hosts
+ *
+ * Copyright (C) 2014-2015 Red Hat, Inc.
+ * Copyright (C) 2012 Parallels, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <pwd.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/statvfs.h>
+
+#include "datatypes.h"
+#include "virerror.h"
+#include "viralloc.h"
+#include "virlog.h"
+#include "vircommand.h"
+#include "configmake.h"
+#include "virfile.h"
+#include "virstoragefile.h"
+#include "nodeinfo.h"
+#include "virstring.h"
+#include "cpu/cpu.h"
+#include "virtypedparam.h"
+
+#include "vz_driver.h"
+#include "vz_utils.h"
+#include "vz_sdk.h"
+
+#define VIR_FROM_THIS VIR_FROM_PARALLELS
+
+VIR_LOG_INIT("parallels.parallels_driver");
+
+#define PRLCTL                      "prlctl"
+#define PRLSRVCTL                   "prlsrvctl"
+
+static int vzConnectClose(virConnectPtr conn);
+
+void
+vzDriverLock(vzConnPtr driver)
+{
+    virMutexLock(&driver->lock);
+}
+
+void
+vzDriverUnlock(vzConnPtr driver)
+{
+    virMutexUnlock(&driver->lock);
+}
+
+static virCapsPtr
+vzBuildCapabilities(void)
+{
+    virCapsPtr caps = NULL;
+    virCPUDefPtr cpu = NULL;
+    virCPUDataPtr data = NULL;
+    virCapsGuestPtr guest;
+    virNodeInfo nodeinfo;
+
+    if ((caps = virCapabilitiesNew(virArchFromHost(),
+                                   false, false)) == NULL)
+        return NULL;
+
+    if (nodeCapsInitNUMA(caps) < 0)
+        goto error;
+
+    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM,
+                                         VIR_ARCH_X86_64,
+                                         "parallels",
+                                         NULL, 0, NULL)) == NULL)
+        goto error;
+
+    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM,
+                                         VIR_ARCH_I686,
+                                         "parallels",
+                                         NULL, 0, NULL)) == NULL)
+        goto error;
+
+
+    if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_PARALLELS,
+                                      NULL, NULL, 0, NULL) == NULL)
+        goto error;
+
+    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_EXE,
+                                         VIR_ARCH_X86_64,
+                                         "parallels",
+                                         NULL, 0, NULL)) == NULL)
+        goto error;
+
+    if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_PARALLELS,
+                                      NULL, NULL, 0, NULL) == NULL)
+        goto error;
+
+    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM,
+                                         VIR_ARCH_X86_64,
+                                         "vz",
+                                         NULL, 0, NULL)) == NULL)
+        goto error;
+
+    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM,
+                                         VIR_ARCH_I686,
+                                         "vz",
+                                         NULL, 0, NULL)) == NULL)
+        goto error;
+
+
+    if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_VZ,
+                                      NULL, NULL, 0, NULL) == NULL)
+        goto error;
+
+    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_EXE,
+                                         VIR_ARCH_X86_64,
+                                         "vz",
+                                         NULL, 0, NULL)) == NULL)
+        goto error;
+
+    if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_VZ,
+                                      NULL, NULL, 0, NULL) == NULL)
+        goto error;
+
+    if (nodeGetInfo(&nodeinfo))
+        goto error;
+
+    if (VIR_ALLOC(cpu) < 0)
+        goto error;
+
+    cpu->arch = caps->host.arch;
+    cpu->type = VIR_CPU_TYPE_HOST;
+    cpu->sockets = nodeinfo.sockets;
+    cpu->cores = nodeinfo.cores;
+    cpu->threads = nodeinfo.threads;
+
+    caps->host.cpu = cpu;
+
+    if (!(data = cpuNodeData(cpu->arch))
+        || cpuDecode(cpu, data, NULL, 0, NULL) < 0) {
+        goto cleanup;
+    }
+
+ cleanup:
+    cpuDataFree(data);
+    return caps;
+
+ error:
+    virObjectUnref(caps);
+    goto cleanup;
+}
+
+static char *
+vzConnectGetCapabilities(virConnectPtr conn)
+{
+    vzConnPtr privconn = conn->privateData;
+    char *xml;
+
+    vzDriverLock(privconn);
+    xml = virCapabilitiesFormatXML(privconn->caps);
+    vzDriverUnlock(privconn);
+    return xml;
+}
+
+static int
+vzDomainDefPostParse(virDomainDefPtr def,
+                            virCapsPtr caps ATTRIBUTE_UNUSED,
+                            void *opaque ATTRIBUTE_UNUSED)
+{
+    /* memory hotplug tunables are not supported by this driver */
+    if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
+        return -1;
+
+    return 0;
+}
+
+static int
+vzDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
+                                  const virDomainDef *def,
+                                  virCapsPtr caps ATTRIBUTE_UNUSED,
+                                  void *opaque ATTRIBUTE_UNUSED)
+{
+    int ret = -1;
+
+    if (dev->type == VIR_DOMAIN_DEVICE_NET &&
+        (dev->data.net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
+         dev->data.net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
+        !dev->data.net->model &&
+        def->os.type == VIR_DOMAIN_OSTYPE_HVM &&
+        VIR_STRDUP(dev->data.net->model, "e1000") < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    return ret;
+}
+
+
+virDomainDefParserConfig vzDomainDefParserConfig = {
+    .macPrefix = {0x42, 0x1C, 0x00},
+    .devicesPostParseCallback = vzDomainDeviceDefPostParse,
+    .domainPostParseCallback = vzDomainDefPostParse,
+};
+
+
+static int
+vzOpenDefault(virConnectPtr conn)
+{
+    vzConnPtr privconn;
+
+    if (VIR_ALLOC(privconn) < 0)
+        return VIR_DRV_OPEN_ERROR;
+    if (virMutexInit(&privconn->lock) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("cannot initialize mutex"));
+        goto err_free;
+    }
+
+    privconn->drivername = conn->driver->name;
+
+    if (prlsdkInit()) {
+        VIR_DEBUG("%s", _("Can't initialize Parallels SDK"));
+        goto err_free;
+    }
+
+    if (prlsdkConnect(privconn) < 0)
+        goto err_free;
+
+    if (!(privconn->caps = vzBuildCapabilities()))
+        goto error;
+
+    if (!(privconn->xmlopt = virDomainXMLOptionNew(&vzDomainDefParserConfig,
+                                                 NULL, NULL)))
+        goto error;
+
+    if (!(privconn->domains = virDomainObjListNew()))
+        goto error;
+
+    if (!(privconn->domainEventState = virObjectEventStateNew()))
+        goto error;
+
+    if (prlsdkSubscribeToPCSEvents(privconn))
+        goto error;
+
+    conn->privateData = privconn;
+
+    if (prlsdkLoadDomains(privconn))
+        goto error;
+
+    return VIR_DRV_OPEN_SUCCESS;
+
+ error:
+    virObjectUnref(privconn->domains);
+    virObjectUnref(privconn->caps);
+    virStoragePoolObjListFree(&privconn->pools);
+    virObjectEventStateFree(privconn->domainEventState);
+    prlsdkDisconnect(privconn);
+    prlsdkDeinit();
+ err_free:
+    VIR_FREE(privconn);
+    return VIR_DRV_OPEN_ERROR;
+}
+
+static virDrvOpenStatus
+vzConnectOpen(virConnectPtr conn,
+                     virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+                     unsigned int flags)
+{
+    int ret;
+
+    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
+
+    if (!conn->uri)
+        return VIR_DRV_OPEN_DECLINED;
+
+    if (!conn->uri->scheme)
+        return VIR_DRV_OPEN_DECLINED;
+
+    if (STRNEQ(conn->uri->scheme, "vz") &&
+        STRNEQ(conn->uri->scheme, "parallels"))
+        return VIR_DRV_OPEN_DECLINED;
+
+    if (STREQ(conn->uri->scheme, "vz") && STRNEQ(conn->driver->name, "vz"))
+        return VIR_DRV_OPEN_DECLINED;
+
+    if (STREQ(conn->uri->scheme, "parallels") && STRNEQ(conn->driver->name, "Parallels"))
+        return VIR_DRV_OPEN_DECLINED;
+
+    /* Remote driver should handle these. */
+    if (conn->uri->server)
+        return VIR_DRV_OPEN_DECLINED;
+
+    /* From this point on, the connection is for us. */
+    if (!STREQ_NULLABLE(conn->uri->path, "/system")) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Unexpected Virtuozzo URI path '%s', try vz:///system"),
+                       conn->uri->path);
+        return VIR_DRV_OPEN_ERROR;
+    }
+
+    if ((ret = vzOpenDefault(conn)) != VIR_DRV_OPEN_SUCCESS ||
+        (ret = vzStorageOpen(conn, flags)) != VIR_DRV_OPEN_SUCCESS ||
+        (ret = vzNetworkOpen(conn, flags)) != VIR_DRV_OPEN_SUCCESS) {
+        vzConnectClose(conn);
+        return ret;
+    }
+
+    return VIR_DRV_OPEN_SUCCESS;
+}
+
+static int
+vzConnectClose(virConnectPtr conn)
+{
+    vzConnPtr privconn = conn->privateData;
+
+    if (!privconn)
+        return 0;
+
+    vzNetworkClose(conn);
+    vzStorageClose(conn);
+
+    vzDriverLock(privconn);
+    prlsdkUnsubscribeFromPCSEvents(privconn);
+    virObjectUnref(privconn->caps);
+    virObjectUnref(privconn->xmlopt);
+    virObjectUnref(privconn->domains);
+    virObjectEventStateFree(privconn->domainEventState);
+    prlsdkDisconnect(privconn);
+    conn->privateData = NULL;
+    prlsdkDeinit();
+
+    vzDriverUnlock(privconn);
+    virMutexDestroy(&privconn->lock);
+
+    VIR_FREE(privconn);
+    return 0;
+}
+
+static int
+vzConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *hvVer)
+{
+    char *output, *sVer, *tmp;
+    const char *searchStr = "prlsrvctl version ";
+    int ret = -1;
+
+    output = vzGetOutput(PRLSRVCTL, "--help", NULL);
+
+    if (!output) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (!(sVer = strstr(output, searchStr))) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    sVer = sVer + strlen(searchStr);
+
+    /* parallels server has versions number like 6.0.17977.782218,
+     * so libvirt can handle only first two numbers. */
+    if (!(tmp = strchr(sVer, '.'))) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (!(tmp = strchr(tmp + 1, '.'))) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    tmp[0] = '\0';
+    if (virParseVersionString(sVer, hvVer, true) < 0) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(output);
+    return ret;
+}
+
+
+static char *vzConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    return virGetHostname();
+}
+
+
+static int
+vzConnectListDomains(virConnectPtr conn, int *ids, int maxids)
+{
+    vzConnPtr privconn = conn->privateData;
+    int n;
+
+    vzDriverLock(privconn);
+    n = virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
+                                     NULL, NULL);
+    vzDriverUnlock(privconn);
+
+    return n;
+}
+
+static int
+vzConnectNumOfDomains(virConnectPtr conn)
+{
+    vzConnPtr privconn = conn->privateData;
+    int count;
+
+    vzDriverLock(privconn);
+    count = virDomainObjListNumOfDomains(privconn->domains, true,
+                                         NULL, NULL);
+    vzDriverUnlock(privconn);
+
+    return count;
+}
+
+static int
+vzConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
+{
+    vzConnPtr privconn = conn->privateData;
+    int n;
+
+    vzDriverLock(privconn);
+    memset(names, 0, sizeof(*names) * maxnames);
+    n = virDomainObjListGetInactiveNames(privconn->domains, names,
+                                         maxnames, NULL, NULL);
+    vzDriverUnlock(privconn);
+
+    return n;
+}
+
+static int
+vzConnectNumOfDefinedDomains(virConnectPtr conn)
+{
+    vzConnPtr privconn = conn->privateData;
+    int count;
+
+    vzDriverLock(privconn);
+    count = virDomainObjListNumOfDomains(privconn->domains, false,
+                                         NULL, NULL);
+    vzDriverUnlock(privconn);
+
+    return count;
+}
+
+static int
+vzConnectListAllDomains(virConnectPtr conn,
+                               virDomainPtr **domains,
+                               unsigned int flags)
+{
+    vzConnPtr privconn = conn->privateData;
+    int ret = -1;
+
+    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
+    vzDriverLock(privconn);
+    ret = virDomainObjListExport(privconn->domains, conn, domains,
+                                 NULL, flags);
+    vzDriverUnlock(privconn);
+
+    return ret;
+}
+
+static virDomainPtr
+vzDomainLookupByID(virConnectPtr conn, int id)
+{
+    vzConnPtr privconn = conn->privateData;
+    virDomainPtr ret = NULL;
+    virDomainObjPtr dom;
+
+    vzDriverLock(privconn);
+    dom = virDomainObjListFindByID(privconn->domains, id);
+    vzDriverUnlock(privconn);
+
+    if (dom == NULL) {
+        virReportError(VIR_ERR_NO_DOMAIN, NULL);
+        goto cleanup;
+    }
+
+    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
+    if (ret)
+        ret->id = dom->def->id;
+
+ cleanup:
+    if (dom)
+        virObjectUnlock(dom);
+    return ret;
+}
+
+static virDomainPtr
+vzDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+{
+    vzConnPtr privconn = conn->privateData;
+    virDomainPtr ret = NULL;
+    virDomainObjPtr dom;
+
+    vzDriverLock(privconn);
+    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
+    vzDriverUnlock(privconn);
+
+    if (dom == NULL) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(uuid, uuidstr);
+        virReportError(VIR_ERR_NO_DOMAIN,
+                       _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
+    if (ret)
+        ret->id = dom->def->id;
+
+ cleanup:
+    if (dom)
+        virObjectUnlock(dom);
+    return ret;
+}
+
+static virDomainPtr
+vzDomainLookupByName(virConnectPtr conn, const char *name)
+{
+    vzConnPtr privconn = conn->privateData;
+    virDomainPtr ret = NULL;
+    virDomainObjPtr dom;
+
+    vzDriverLock(privconn);
+    dom = virDomainObjListFindByName(privconn->domains, name);
+    vzDriverUnlock(privconn);
+
+    if (dom == NULL) {
+        virReportError(VIR_ERR_NO_DOMAIN,
+                       _("no domain with matching name '%s'"), name);
+        goto cleanup;
+    }
+
+    ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
+    if (ret)
+        ret->id = dom->def->id;
+
+ cleanup:
+    virDomainObjEndAPI(&dom);
+    return ret;
+}
+
+static int
+vzDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
+{
+    virDomainObjPtr privdom;
+    int ret = -1;
+
+    if (!(privdom = vzDomObjFromDomain(domain)))
+        goto cleanup;
+
+    info->state = virDomainObjGetState(privdom, NULL);
+    info->memory = privdom->def->mem.cur_balloon;
+    info->maxMem = virDomainDefGetMemoryActual(privdom->def);
+    info->nrVirtCpu = privdom->def->vcpus;
+    info->cpuTime = 0;
+    ret = 0;
+
+ cleanup:
+    if (privdom)
+        virObjectUnlock(privdom);
+    return ret;
+}
+
+static char *
+vzDomainGetOSType(virDomainPtr domain)
+{
+    virDomainObjPtr privdom;
+
+    char *ret = NULL;
+
+    if (!(privdom = vzDomObjFromDomain(domain)))
+        goto cleanup;
+
+    ignore_value(VIR_STRDUP(ret, virDomainOSTypeToString(privdom->def->os.type)));
+
+ cleanup:
+    if (privdom)
+        virObjectUnlock(privdom);
+    return ret;
+}
+
+static int
+vzDomainIsPersistent(virDomainPtr domain)
+{
+    virDomainObjPtr privdom;
+    int ret = -1;
+
+    if (!(privdom = vzDomObjFromDomain(domain)))
+        goto cleanup;
+
+    ret = 1;
+
+ cleanup:
+    if (privdom)
+        virObjectUnlock(privdom);
+    return ret;
+}
+
+static int
+vzDomainGetState(virDomainPtr domain,
+                  int *state, int *reason, unsigned int flags)
+{
+    virDomainObjPtr privdom;
+    int ret = -1;
+    virCheckFlags(0, -1);
+
+    if (!(privdom = vzDomObjFromDomain(domain)))
+        goto cleanup;
+
+    *state = virDomainObjGetState(privdom, reason);
+    ret = 0;
+
+ cleanup:
+    if (privdom)
+        virObjectUnlock(privdom);
+    return ret;
+}
+
+static char *
+vzDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
+{
+    virDomainDefPtr def;
+    virDomainObjPtr privdom;
+    char *ret = NULL;
+
+    /* Flags checked by virDomainDefFormat */
+
+    if (!(privdom = vzDomObjFromDomain(domain)))
+        goto cleanup;
+
+    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
+        privdom->newDef ? privdom->newDef : privdom->def;
+
+    ret = virDomainDefFormat(def, flags);
+
+ cleanup:
+    if (privdom)
+        virObjectUnlock(privdom);
+    return ret;
+}
+
+static int
+vzDomainGetAutostart(virDomainPtr domain, int *autostart)
+{
+    virDomainObjPtr privdom;
+    int ret = -1;
+
+    if (!(privdom = vzDomObjFromDomain(domain)))
+        goto cleanup;
+
+    *autostart = privdom->autostart;
+    ret = 0;
+
+ cleanup:
+    if (privdom)
+        virObjectUnlock(privdom);
+    return ret;
+}
+
+static virDomainPtr
+vzDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
+{
+    vzConnPtr privconn = conn->privateData;
+    virDomainPtr retdom = NULL;
+    virDomainDefPtr def;
+    virDomainObjPtr olddom = NULL;
+    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
+
+    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
+
+    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
+        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE;
+
+    vzDriverLock(privconn);
+    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
+                                       parse_flags)) == NULL)
+        goto cleanup;
+
+    olddom = virDomainObjListFindByUUID(privconn->domains, def->uuid);
+    if (olddom == NULL) {
+        virResetLastError();
+        if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+            if (prlsdkCreateVm(conn, def))
+                goto cleanup;
+        } else if (def->os.type == VIR_DOMAIN_OSTYPE_EXE) {
+            if (prlsdkCreateCt(conn, def))
+                goto cleanup;
+        } else {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("Unsupported OS type: %s"),
+                           virDomainOSTypeToString(def->os.type));
+            goto cleanup;
+        }
+
+        olddom = prlsdkAddDomain(privconn, def->uuid);
+        if (!olddom)
+            goto cleanup;
+    } else {
+        int state, reason;
+
+        state = virDomainObjGetState(olddom, &reason);
+
+        if (state == VIR_DOMAIN_SHUTOFF &&
+            reason == VIR_DOMAIN_SHUTOFF_SAVED) {
+
+            /* PCS doesn't store domain config in managed save state file.
+             * It's forbidden to change config for VMs in this state.
+             * It's possible to change config for containers, but after
+             * restoring domain will have that new config, not a config,
+             * which domain had at the moment of virDomainManagedSave.
+             *
+             * So forbid this operation, if config is changed. If it's
+             * not changed - just do nothing. */
+
+            if (!virDomainDefCheckABIStability(olddom->def, def)) {
+                virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                               _("Can't change domain configuration "
+                                 "in managed save state"));
+                goto cleanup;
+            }
+        } else {
+            if (prlsdkApplyConfig(conn, olddom, def))
+                goto cleanup;
+
+            if (prlsdkUpdateDomain(privconn, olddom))
+                goto cleanup;
+        }
+    }
+
+    retdom = virGetDomain(conn, def->name, def->uuid);
+    if (retdom)
+        retdom->id = def->id;
+
+ cleanup:
+    if (olddom)
+        virObjectUnlock(olddom);
+    virDomainDefFree(def);
+    vzDriverUnlock(privconn);
+    return retdom;
+}
+
+static virDomainPtr
+vzDomainDefineXML(virConnectPtr conn, const char *xml)
+{
+    return vzDomainDefineXMLFlags(conn, xml, 0);
+}
+
+
+static int
+vzNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED,
+                     virNodeInfoPtr nodeinfo)
+{
+    return nodeGetInfo(nodeinfo);
+}
+
+static int vzConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    /* Encryption is not relevant / applicable to way we talk to PCS */
+    return 0;
+}
+
+static int vzConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    /* We run CLI tools directly so this is secure */
+    return 1;
+}
+
+static int vzConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    return 1;
+}
+
+
+static char *
+vzConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
+                            const char **xmlCPUs,
+                            unsigned int ncpus,
+                            unsigned int flags)
+{
+    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);
+
+    return cpuBaselineXML(xmlCPUs, ncpus, NULL, 0, flags);
+}
+
+
+static int
+vzDomainGetVcpus(virDomainPtr domain,
+                        virVcpuInfoPtr info,
+                        int maxinfo,
+                        unsigned char *cpumaps,
+                        int maplen)
+{
+    virDomainObjPtr privdom = NULL;
+    size_t i;
+    int v, maxcpu, hostcpus;
+    int ret = -1;
+
+    if (!(privdom = vzDomObjFromDomain(domain)))
+        goto cleanup;
+
+    if (!virDomainObjIsActive(privdom)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       "%s",
+                       _("cannot list vcpu pinning for an inactive domain"));
+        goto cleanup;
+    }
+
+    if ((hostcpus = nodeGetCPUCount()) < 0)
+        goto cleanup;
+
+    maxcpu = maplen * 8;
+    if (maxcpu > hostcpus)
+        maxcpu = hostcpus;
+
+    if (maxinfo >= 1) {
+        if (info != NULL) {
+            memset(info, 0, sizeof(*info) * maxinfo);
+            for (i = 0; i < maxinfo; i++) {
+                info[i].number = i;
+                info[i].state = VIR_VCPU_RUNNING;
+            }
+        }
+        if (cpumaps != NULL) {
+            unsigned char *tmpmap = NULL;
+            int tmpmapLen = 0;
+
+            memset(cpumaps, 0, maplen * maxinfo);
+            virBitmapToData(privdom->def->cpumask, &tmpmap, &tmpmapLen);
+            if (tmpmapLen > maplen)
+                tmpmapLen = maplen;
+
+            for (v = 0; v < maxinfo; v++) {
+                unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
+                memcpy(cpumap, tmpmap, tmpmapLen);
+            }
+            VIR_FREE(tmpmap);
+        }
+    }
+    ret = maxinfo;
+
+ cleanup:
+    if (privdom)
+        virObjectUnlock(privdom);
+    return ret;
+}
+
+
+static int
+vzNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
+                       unsigned char **cpumap,
+                       unsigned int *online,
+                       unsigned int flags)
+{
+    return nodeGetCPUMap(cpumap, online, flags);
+}
+
+static int
+vzConnectDomainEventRegisterAny(virConnectPtr conn,
+                                       virDomainPtr domain,
+                                       int eventID,
+                                       virConnectDomainEventGenericCallback callback,
+                                       void *opaque,
+                                       virFreeCallback freecb)
+{
+    int ret = -1;
+    vzConnPtr privconn = conn->privateData;
+    if (virDomainEventStateRegisterID(conn,
+                                      privconn->domainEventState,
+                                      domain, eventID,
+                                      callback, opaque, freecb, &ret) < 0)
+        ret = -1;
+    return ret;
+}
+
+static int
+vzConnectDomainEventDeregisterAny(virConnectPtr conn,
+                                         int callbackID)
+{
+    vzConnPtr privconn = conn->privateData;
+    int ret = -1;
+
+    if (virObjectEventStateDeregisterID(conn,
+                                        privconn->domainEventState,
+                                        callbackID) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    return ret;
+}
+
+static int vzDomainSuspend(virDomainPtr domain)
+{
+    return prlsdkDomainChangeState(domain, prlsdkPause);
+}
+
+static int vzDomainResume(virDomainPtr domain)
+{
+    return prlsdkDomainChangeState(domain, prlsdkResume);
+}
+
+static int vzDomainCreate(virDomainPtr domain)
+{
+    return prlsdkDomainChangeState(domain, prlsdkStart);
+}
+
+static int vzDomainDestroy(virDomainPtr domain)
+{
+    return prlsdkDomainChangeState(domain, prlsdkKill);
+}
+
+static int vzDomainShutdown(virDomainPtr domain)
+{
+    return prlsdkDomainChangeState(domain, prlsdkStop);
+}
+
+static int vzDomainIsActive(virDomainPtr domain)
+{
+    virDomainObjPtr dom = NULL;
+    int ret = -1;
+
+    if (!(dom = vzDomObjFromDomain(domain)))
+        return -1;
+
+    ret = virDomainObjIsActive(dom);
+    virObjectUnlock(dom);
+
+    return ret;
+}
+
+static int
+vzDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
+{
+    /* we don't support any create flags */
+    virCheckFlags(0, -1);
+
+    return vzDomainCreate(domain);
+}
+
+static int
+vzDomainUndefineFlags(virDomainPtr domain,
+                             unsigned int flags)
+{
+    vzConnPtr privconn = domain->conn->privateData;
+    virDomainObjPtr dom = NULL;
+    int ret;
+
+    virCheckFlags(0, -1);
+
+    if (!(dom = vzDomObjFromDomain(domain)))
+        return -1;
+
+    ret = prlsdkUnregisterDomain(privconn, dom);
+    if (ret)
+         virObjectUnlock(dom);
+
+    return ret;
+}
+
+static int
+vzDomainUndefine(virDomainPtr domain)
+{
+    return vzDomainUndefineFlags(domain, 0);
+}
+
+static int
+vzDomainHasManagedSaveImage(virDomainPtr domain, unsigned int flags)
+{
+    virDomainObjPtr dom = NULL;
+    int state, reason;
+    int ret = 0;
+
+    virCheckFlags(0, -1);
+
+    if (!(dom = vzDomObjFromDomain(domain)))
+        return -1;
+
+    state = virDomainObjGetState(dom, &reason);
+    if (state == VIR_DOMAIN_SHUTOFF && reason == VIR_DOMAIN_SHUTOFF_SAVED)
+        ret = 1;
+    virObjectUnlock(dom);
+
+    return ret;
+}
+
+static int
+vzDomainManagedSave(virDomainPtr domain, unsigned int flags)
+{
+    vzConnPtr privconn = domain->conn->privateData;
+    virDomainObjPtr dom = NULL;
+    int state, reason;
+    int ret = -1;
+
+    virCheckFlags(VIR_DOMAIN_SAVE_RUNNING |
+                  VIR_DOMAIN_SAVE_PAUSED, -1);
+
+    if (!(dom = vzDomObjFromDomain(domain)))
+        return -1;
+
+    state = virDomainObjGetState(dom, &reason);
+
+    if (state == VIR_DOMAIN_RUNNING && (flags & VIR_DOMAIN_SAVE_PAUSED)) {
+        ret = prlsdkDomainChangeStateLocked(privconn, dom, prlsdkPause);
+        if (ret)
+            goto cleanup;
+    }
+
+    ret = prlsdkDomainChangeStateLocked(privconn, dom, prlsdkSuspend);
+
+ cleanup:
+    virObjectUnlock(dom);
+    return ret;
+}
+
+static int
+vzDomainManagedSaveRemove(virDomainPtr domain, unsigned int flags)
+{
+    virDomainObjPtr dom = NULL;
+    int state, reason;
+    int ret = -1;
+
+    virCheckFlags(0, -1);
+
+    if (!(dom = vzDomObjFromDomain(domain)))
+        return -1;
+
+    state = virDomainObjGetState(dom, &reason);
+
+    if (!(state == VIR_DOMAIN_SHUTOFF && reason == VIR_DOMAIN_SHUTOFF_SAVED))
+        goto cleanup;
+
+    ret = prlsdkDomainManagedSaveRemove(dom);
+
+ cleanup:
+    virObjectUnlock(dom);
+    return ret;
+}
+
+static int vzDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
+                                            unsigned int flags)
+{
+    int ret = -1;
+    vzConnPtr privconn = dom->conn->privateData;
+    virDomainDeviceDefPtr dev = NULL;
+    virDomainObjPtr privdom = NULL;
+    bool domactive = false;
+
+    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+                  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+    if (!(privdom = vzDomObjFromDomain(dom)))
+        return -1;
+
+    if (!(flags & VIR_DOMAIN_AFFECT_CONFIG)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("device attach needs VIR_DOMAIN_AFFECT_CONFIG "
+                         "flag to be set"));
+        goto cleanup;
+    }
+
+    domactive = virDomainObjIsActive(privdom);
+    if (!domactive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("cannot do live update a device on "
+                         "inactive domain"));
+        goto cleanup;
+    }
+    if (domactive && !(flags & VIR_DOMAIN_AFFECT_LIVE)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("Updates on a running domain need "
+                         "VIR_DOMAIN_AFFECT_LIVE flag"));
+    }
+
+    dev = virDomainDeviceDefParse(xml, privdom->def, privconn->caps,
+                                  privconn->xmlopt, VIR_DOMAIN_XML_INACTIVE);
+    if (dev == NULL)
+        goto cleanup;
+
+    switch (dev->type) {
+    case VIR_DOMAIN_DEVICE_DISK:
+        ret = prlsdkAttachVolume(privdom, dev->data.disk);
+        if (ret) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("disk attach failed"));
+            goto cleanup;
+        }
+        break;
+    default:
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+                       _("device type '%s' cannot be attached"),
+                       virDomainDeviceTypeToString(dev->type));
+        break;
+    }
+
+    ret = 0;
+ cleanup:
+    virObjectUnlock(privdom);
+    return ret;
+}
+
+static int vzDomainAttachDevice(virDomainPtr dom, const char *xml)
+{
+    return vzDomainAttachDeviceFlags(dom, xml,
+                                            VIR_DOMAIN_AFFECT_CONFIG | VIR_DOMAIN_AFFECT_LIVE);
+}
+
+static int vzDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
+                                            unsigned int flags)
+{
+    int ret = -1;
+    vzConnPtr privconn = dom->conn->privateData;
+    virDomainDeviceDefPtr dev = NULL;
+    virDomainObjPtr privdom = NULL;
+    bool domactive = false;
+
+    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+                  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+    privdom = vzDomObjFromDomain(dom);
+    if (privdom == NULL)
+        return -1;
+
+    if (!(flags & VIR_DOMAIN_AFFECT_CONFIG)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("device detach needs VIR_DOMAIN_AFFECT_CONFIG "
+                         "flag to be set"));
+        goto cleanup;
+    }
+
+    domactive = virDomainObjIsActive(privdom);
+    if (!domactive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("cannot do live update a device on "
+                         "inactive domain"));
+        goto cleanup;
+    }
+    if (domactive && !(flags & VIR_DOMAIN_AFFECT_LIVE)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("Updates on a running domain need "
+                         "VIR_DOMAIN_AFFECT_LIVE flag"));
+    }
+
+    dev = virDomainDeviceDefParse(xml, privdom->def, privconn->caps,
+                                  privconn->xmlopt, VIR_DOMAIN_XML_INACTIVE);
+    if (dev == NULL)
+        goto cleanup;
+
+    switch (dev->type) {
+    case VIR_DOMAIN_DEVICE_DISK:
+        ret = prlsdkDetachVolume(privdom, dev->data.disk);
+        if (ret) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("disk detach failed"));
+            goto cleanup;
+        }
+        break;
+    default:
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+                       _("device type '%s' cannot be detached"),
+                       virDomainDeviceTypeToString(dev->type));
+        break;
+    }
+
+    ret = 0;
+ cleanup:
+    virObjectUnlock(privdom);
+    return ret;
+}
+
+static int vzDomainDetachDevice(virDomainPtr dom, const char *xml)
+{
+    return vzDomainDetachDeviceFlags(dom, xml,
+                                            VIR_DOMAIN_AFFECT_CONFIG | VIR_DOMAIN_AFFECT_LIVE);
+}
+
+static unsigned long long
+vzDomainGetMaxMemory(virDomainPtr domain)
+{
+    virDomainObjPtr dom = NULL;
+    int ret = -1;
+
+    if (!(dom = vzDomObjFromDomain(domain)))
+        return -1;
+
+    ret = dom->def->mem.max_balloon;
+    virObjectUnlock(dom);
+    return ret;
+}
+
+static int
+vzDomainBlockStats(virDomainPtr domain, const char *path,
+                     virDomainBlockStatsPtr stats)
+{
+    virDomainObjPtr dom = NULL;
+    int ret = -1;
+    size_t i;
+    int idx;
+
+    if (!(dom = vzDomObjFromDomainRef(domain)))
+        return -1;
+
+    if (*path) {
+        if ((idx = virDomainDiskIndexByName(dom->def, path, false)) < 0) {
+            virReportError(VIR_ERR_INVALID_ARG, _("invalid path: %s"), path);
+            goto cleanup;
+        }
+        if (prlsdkGetBlockStats(dom, dom->def->disks[idx], stats) < 0)
+            goto cleanup;
+    } else {
+        virDomainBlockStatsStruct s;
+
+#define PARALLELS_ZERO_STATS(VAR, TYPE, NAME)           \
+        stats->VAR = 0;
+
+        PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_ZERO_STATS)
+
+#undef PARALLELS_ZERO_STATS
+
+        for (i = 0; i < dom->def->ndisks; i++) {
+            if (prlsdkGetBlockStats(dom, dom->def->disks[i], &s) < 0)
+                goto cleanup;
+
+#define PARALLELS_SUM_STATS(VAR, TYPE, NAME)        \
+        if (s.VAR != -1)                            \
+           stats->VAR += s.VAR;
+
+            PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_SUM_STATS)
+
+#undef PARALLELS_SUM_STATS
+        }
+    }
+    stats->errs = -1;
+    ret = 0;
+
+ cleanup:
+    if (dom)
+        virDomainObjEndAPI(&dom);
+
+    return ret;
+}
+
+static int
+vzDomainBlockStatsFlags(virDomainPtr domain,
+                          const char *path,
+                          virTypedParameterPtr params,
+                          int *nparams,
+                          unsigned int flags)
+{
+    virDomainBlockStatsStruct stats;
+    int ret = -1;
+    size_t i;
+
+    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+    /* We don't return strings, and thus trivially support this flag.  */
+    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
+
+    if (vzDomainBlockStats(domain, path, &stats) < 0)
+        goto cleanup;
+
+    if (*nparams == 0) {
+#define PARALLELS_COUNT_STATS(VAR, TYPE, NAME)       \
+        if ((stats.VAR) != -1)                       \
+            ++*nparams;
+
+        PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_COUNT_STATS)
+
+#undef PARALLELS_COUNT_STATS
+        ret = 0;
+        goto cleanup;
+    }
+
+    i = 0;
+#define PARALLELS_BLOCK_STATS_ASSIGN_PARAM(VAR, TYPE, NAME)                    \
+    if (i < *nparams && (stats.VAR) != -1) {                                   \
+        if (virTypedParameterAssign(params + i, TYPE,                          \
+                                    VIR_TYPED_PARAM_LLONG, (stats.VAR)) < 0)   \
+            goto cleanup;                                                      \
+        i++;                                                                   \
+    }
+
+    PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_BLOCK_STATS_ASSIGN_PARAM)
+
+#undef PARALLELS_BLOCK_STATS_ASSIGN_PARAM
+
+    *nparams = i;
+    ret = 0;
+
+ cleanup:
+    return ret;
+}
+
+
+static virHypervisorDriver vzDriver = {
+    .name = "vz",
+    .connectOpen = vzConnectOpen,            /* 0.10.0 */
+    .connectClose = vzConnectClose,          /* 0.10.0 */
+    .connectGetVersion = vzConnectGetVersion,   /* 0.10.0 */
+    .connectGetHostname = vzConnectGetHostname,      /* 0.10.0 */
+    .nodeGetInfo = vzNodeGetInfo,      /* 0.10.0 */
+    .connectGetCapabilities = vzConnectGetCapabilities,      /* 0.10.0 */
+    .connectBaselineCPU = vzConnectBaselineCPU, /* 1.2.6 */
+    .connectListDomains = vzConnectListDomains,      /* 0.10.0 */
+    .connectNumOfDomains = vzConnectNumOfDomains,    /* 0.10.0 */
+    .connectListDefinedDomains = vzConnectListDefinedDomains,        /* 0.10.0 */
+    .connectNumOfDefinedDomains = vzConnectNumOfDefinedDomains,      /* 0.10.0 */
+    .connectListAllDomains = vzConnectListAllDomains, /* 0.10.0 */
+    .domainLookupByID = vzDomainLookupByID,    /* 0.10.0 */
+    .domainLookupByUUID = vzDomainLookupByUUID,        /* 0.10.0 */
+    .domainLookupByName = vzDomainLookupByName,        /* 0.10.0 */
+    .domainGetOSType = vzDomainGetOSType,    /* 0.10.0 */
+    .domainGetInfo = vzDomainGetInfo,  /* 0.10.0 */
+    .domainGetState = vzDomainGetState,        /* 0.10.0 */
+    .domainGetXMLDesc = vzDomainGetXMLDesc,    /* 0.10.0 */
+    .domainIsPersistent = vzDomainIsPersistent,        /* 0.10.0 */
+    .domainGetAutostart = vzDomainGetAutostart,        /* 0.10.0 */
+    .domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
+    .domainSuspend = vzDomainSuspend,    /* 0.10.0 */
+    .domainResume = vzDomainResume,    /* 0.10.0 */
+    .domainDestroy = vzDomainDestroy,  /* 0.10.0 */
+    .domainShutdown = vzDomainShutdown, /* 0.10.0 */
+    .domainCreate = vzDomainCreate,    /* 0.10.0 */
+    .domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
+    .domainDefineXML = vzDomainDefineXML,      /* 0.10.0 */
+    .domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */
+    .domainUndefine = vzDomainUndefine, /* 1.2.10 */
+    .domainUndefineFlags = vzDomainUndefineFlags, /* 1.2.10 */
+    .domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
+    .domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
+    .domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
+    .domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
+    .domainIsActive = vzDomainIsActive, /* 1.2.10 */
+    .connectDomainEventRegisterAny = vzConnectDomainEventRegisterAny, /* 1.2.10 */
+    .connectDomainEventDeregisterAny = vzConnectDomainEventDeregisterAny, /* 1.2.10 */
+    .nodeGetCPUMap = vzNodeGetCPUMap, /* 1.2.8 */
+    .connectIsEncrypted = vzConnectIsEncrypted, /* 1.2.5 */
+    .connectIsSecure = vzConnectIsSecure, /* 1.2.5 */
+    .connectIsAlive = vzConnectIsAlive, /* 1.2.5 */
+    .domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
+    .domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
+    .domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
+    .domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
+    .domainBlockStats = vzDomainBlockStats, /* 1.3.0 */
+    .domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.3.0 */
+};
+
+static virConnectDriver vzConnectDriver = {
+    .hypervisorDriver = &vzDriver,
+    .storageDriver = &vzStorageDriver,
+    .networkDriver = &vzNetworkDriver,
+};
+
+/* Parallels domain type backward compatibility*/
+static virHypervisorDriver parallelsDriver;
+static virConnectDriver parallelsConnectDriver;
+
+/**
+ * vzRegister:
+ *
+ * Registers the vz driver
+ */
+int
+vzRegister(void)
+{
+    char *prlctl_path;
+
+    prlctl_path = virFindFileInPath(PRLCTL);
+    if (!prlctl_path) {
+        VIR_DEBUG("%s", _("Can't find prlctl command in the PATH env"));
+        return 0;
+    }
+
+    VIR_FREE(prlctl_path);
+
+    /* Backward compatibility with Parallels domain type */
+    parallelsDriver = vzDriver;
+    parallelsDriver.name = "Parallels";
+    parallelsConnectDriver = vzConnectDriver;
+    parallelsConnectDriver.hypervisorDriver = &parallelsDriver;
+    if (virRegisterConnectDriver(&parallelsConnectDriver, false) < 0)
+        return -1;
+
+    if (virRegisterConnectDriver(&vzConnectDriver, false) < 0)
+        return -1;
+
+    return 0;
+}
diff --git a/src/vz/vz_driver.h b/src/vz/vz_driver.h
new file mode 100644 (file)
index 0000000..3c76106
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * vz_driver.h: core driver functions for managing
+ * Parallels Cloud Server hosts
+ *
+ * Copyright (C) 2012 Parallels, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef PARALLELS_DRIVER_H
+# define PARALLELS_DRIVER_H
+
+int vzRegister(void);
+
+#endif
diff --git a/src/vz/vz_network.c b/src/vz/vz_network.c
new file mode 100644 (file)
index 0000000..3a5a3ff
--- /dev/null
@@ -0,0 +1,556 @@
+/*
+ * vz_network.c: core privconn functions for managing
+ * Parallels Cloud Server hosts
+ *
+ * Copyright (C) 2013-2014 Red Hat, Inc.
+ * Copyright (C) 2012 Parallels, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include "datatypes.h"
+#include "dirname.h"
+#include "viralloc.h"
+#include "virerror.h"
+#include "virfile.h"
+#include "virnetdev.h"
+#include "md5.h"
+#include "vz_utils.h"
+#include "virstring.h"
+
+#define VIR_FROM_THIS VIR_FROM_PARALLELS
+#define PARALLELS_ROUTED_NETWORK_UUID   "eb593dd1-6846-45b0-84a0-de0729286982"
+
+#define vzParseError()                                                  \
+    virReportErrorHelper(VIR_FROM_TEST, VIR_ERR_OPERATION_FAILED, __FILE__,    \
+                     __FUNCTION__, __LINE__, _("Can't parse prlctl output"))
+
+static int vzGetBridgedNetInfo(virNetworkDefPtr def, virJSONValuePtr jobj)
+{
+    const char *ifname;
+    char *bridgeLink = NULL;
+    char *bridgePath = NULL;
+    char *bridgeAddressPath = NULL;
+    char *bridgeAddress = NULL;
+    int len = 0;
+    int ret = -1;
+
+    if (!(ifname = virJSONValueObjectGetString(jobj, "Bound To"))) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (virAsprintf(&bridgeLink, SYSFS_NET_DIR "%s/brport/bridge", ifname) < 0)
+        goto cleanup;
+
+    if (virFileResolveLink(bridgeLink, &bridgePath) < 0) {
+        virReportSystemError(errno, _("cannot read link '%s'"), bridgeLink);
+        goto cleanup;
+    }
+
+    if (VIR_STRDUP(def->bridge, last_component(bridgePath)) < 0)
+        goto cleanup;
+
+    if (virAsprintf(&bridgeAddressPath, SYSFS_NET_DIR "%s/brport/bridge/address",
+                    ifname) < 0)
+        goto cleanup;
+
+    if ((len = virFileReadAll(bridgeAddressPath, 18, &bridgeAddress)) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Error reading file '%s'"), bridgeAddressPath);
+
+        goto cleanup;
+    }
+
+    if (len < VIR_MAC_STRING_BUFLEN) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Error reading MAC from '%s'"), bridgeAddressPath);
+    }
+
+    bridgeAddress[VIR_MAC_STRING_BUFLEN - 1] = '\0';
+    if (virMacAddrParse(bridgeAddress, &def->mac) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Can't parse MAC '%s'"), bridgeAddress);
+        goto cleanup;
+    }
+    def->mac_specified = 1;
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(bridgeLink);
+    VIR_FREE(bridgePath);
+    VIR_FREE(bridgeAddress);
+    VIR_FREE(bridgeAddressPath);
+    return ret;
+}
+
+static int vzGetHostOnlyNetInfo(virNetworkDefPtr def, const char *name)
+{
+    const char *tmp;
+    virJSONValuePtr jobj = NULL, jobj2;
+    int ret = -1;
+
+    if (VIR_EXPAND_N(def->ips, def->nips, 1) < 0)
+        goto cleanup;
+
+    jobj = vzParseOutput("prlsrvctl", "net", "info", "-j", name, NULL);
+
+    if (!jobj) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (!(jobj2 = virJSONValueObjectGet(jobj, "Parallels adapter"))) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (VIR_STRDUP(def->ips[0].family, "ipv4") < 0)
+        goto cleanup;
+
+    if (!(tmp = virJSONValueObjectGetString(jobj2, "IP address"))) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (virSocketAddrParseIPv4(&def->ips[0].address, tmp) < 0) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (!(tmp = virJSONValueObjectGetString(jobj2, "Subnet mask"))) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (virSocketAddrParseIPv4(&def->ips[0].netmask, tmp) < 0) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (!(jobj2 = virJSONValueObjectGet(jobj, "DHCPv4 server"))) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (VIR_EXPAND_N(def->ips[0].ranges, def->ips[0].nranges, 1) < 0)
+        goto cleanup;
+
+    if (!(tmp = virJSONValueObjectGetString(jobj2, "IP scope start address"))) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (virSocketAddrParseIPv4(&def->ips[0].ranges[0].start, tmp) < 0) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (!(tmp = virJSONValueObjectGetString(jobj2, "IP scope end address"))) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (virSocketAddrParseIPv4(&def->ips[0].ranges[0].end, tmp) < 0) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    ret = 0;
+ cleanup:
+    virJSONValueFree(jobj);
+    return ret;
+}
+
+static int
+vzLoadNetwork(vzConnPtr privconn, virJSONValuePtr jobj)
+{
+    int ret = -1;
+    virNetworkObjPtr net = NULL;
+    virNetworkDefPtr def;
+    const char *tmp;
+    /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+    unsigned char md5[MD5_DIGEST_SIZE];
+
+    if (VIR_ALLOC(def) < 0)
+        goto cleanup;
+
+    if (!(tmp = virJSONValueObjectGetString(jobj, "Network ID"))) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (VIR_STRDUP(def->name, tmp) < 0)
+        goto cleanup;
+
+    /* Network names are unique in Parallels Cloud Server, so we can make
+     * a UUID from it */
+    md5_buffer(tmp, strlen(tmp), md5);
+    memcpy(def->uuid, md5, VIR_UUID_BUFLEN);
+    def->uuid_specified = 1;
+
+    if (!(tmp = virJSONValueObjectGetString(jobj, "Type"))) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (STREQ(tmp, PARALLELS_BRIDGED_NETWORK_TYPE)) {
+        def->forward.type = VIR_NETWORK_FORWARD_BRIDGE;
+
+        if (vzGetBridgedNetInfo(def, jobj) < 0) {
+
+            /* Only mandatory networks are required to be configured completely */
+            if (STRNEQ(def->name, PARALLELS_REQUIRED_BRIDGED_NETWORK))
+                ret = 0;
+
+            goto cleanup;
+        }
+    } else if (STREQ(tmp, PARALLELS_HOSTONLY_NETWORK_TYPE)) {
+        def->forward.type = VIR_NETWORK_FORWARD_NONE;
+
+        if (vzGetHostOnlyNetInfo(def, def->name) < 0) {
+
+            /* Only mandatory networks are required to be configured completely */
+            if (STRNEQ(def->name, PARALLELS_REQUIRED_HOSTONLY_NETWORK))
+                ret = 0;
+
+            goto cleanup;
+        }
+    } else {
+        vzParseError();
+        goto cleanup;
+    }
+
+    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
+        goto cleanup;
+    def = NULL;
+    net->active = 1;
+    net->autostart = 1;
+    ret = 0;
+
+ cleanup:
+    virNetworkObjEndAPI(&net);
+    virNetworkDefFree(def);
+    return ret;
+}
+
+static int
+vzAddRoutedNetwork(vzConnPtr privconn)
+{
+    virNetworkObjPtr net = NULL;
+    virNetworkDefPtr def;
+
+    if (VIR_ALLOC(def) < 0)
+        goto cleanup;
+
+    def->forward.type = VIR_NETWORK_FORWARD_ROUTE;
+
+    if (VIR_STRDUP(def->name, PARALLELS_DOMAIN_ROUTED_NETWORK_NAME) < 0)
+        goto cleanup;
+
+    if (virUUIDParse(PARALLELS_ROUTED_NETWORK_UUID, def->uuid) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Can't parse UUID"));
+        goto cleanup;
+    }
+    def->uuid_specified = 1;
+
+    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
+        goto cleanup;
+
+    net->active = 1;
+    net->autostart = 1;
+    virNetworkObjEndAPI(&net);
+
+    return 0;
+
+ cleanup:
+    virNetworkDefFree(def);
+    return -1;
+}
+
+static int vzLoadNetworks(vzConnPtr privconn)
+{
+    virJSONValuePtr jobj, jobj2;
+    int ret = -1;
+    int count;
+    size_t i;
+
+    jobj = vzParseOutput("prlsrvctl", "net", "list", "-j", NULL);
+
+    if (!jobj) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    count = virJSONValueArraySize(jobj);
+    if (count < 0) {
+        vzParseError();
+        goto cleanup;
+    }
+
+    for (i = 0; i < count; i++) {
+        jobj2 = virJSONValueArrayGet(jobj, i);
+        if (!jobj2) {
+            vzParseError();
+            goto cleanup;
+        }
+
+        if (vzLoadNetwork(privconn, jobj2) < 0)
+            goto cleanup;
+    }
+
+    if (vzAddRoutedNetwork(privconn) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    virJSONValueFree(jobj);
+    return ret;
+}
+
+virDrvOpenStatus
+vzNetworkOpen(virConnectPtr conn,
+                     unsigned int flags)
+{
+    vzConnPtr privconn = conn->privateData;
+
+    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
+
+    if (STRNEQ(conn->driver->name, "vz") &&
+        STRNEQ(conn->driver->name, "Parallels"))
+        return VIR_DRV_OPEN_DECLINED;
+
+    if (!(privconn->networks = virNetworkObjListNew()))
+        goto error;
+
+    if (vzLoadNetworks(conn->privateData) < 0)
+        goto error;
+
+    return VIR_DRV_OPEN_SUCCESS;
+ error:
+    virObjectUnref(privconn->networks);
+    privconn->networks = NULL;
+    return VIR_DRV_OPEN_ERROR;
+}
+
+int vzNetworkClose(virConnectPtr conn)
+{
+    vzConnPtr privconn = conn->privateData;
+
+    if (!privconn)
+        return 0;
+
+    virObjectUnref(privconn->networks);
+    return 0;
+}
+
+static int vzConnectNumOfNetworks(virConnectPtr conn)
+{
+    int nactive;
+    vzConnPtr privconn = conn->privateData;
+
+    nactive = virNetworkObjListNumOfNetworks(privconn->networks,
+                                             true, NULL, conn);
+    return nactive;
+}
+
+static int vzConnectListNetworks(virConnectPtr conn,
+                                        char **const names,
+                                        int nnames)
+{
+    vzConnPtr privconn = conn->privateData;
+    int got;
+
+    got = virNetworkObjListGetNames(privconn->networks,
+                                    true, names, nnames, NULL, conn);
+    return got;
+}
+
+static int vzConnectNumOfDefinedNetworks(virConnectPtr conn)
+{
+    int ninactive;
+    vzConnPtr privconn = conn->privateData;
+
+    ninactive = virNetworkObjListNumOfNetworks(privconn->networks,
+                                               false, NULL, conn);
+    return ninactive;
+}
+
+static int vzConnectListDefinedNetworks(virConnectPtr conn,
+                                               char **const names,
+                                               int nnames)
+{
+    vzConnPtr privconn = conn->privateData;
+    int got;
+
+    got = virNetworkObjListGetNames(privconn->networks,
+                                    false, names, nnames, NULL, conn);
+    return got;
+}
+
+static int vzConnectListAllNetworks(virConnectPtr conn,
+                                           virNetworkPtr **nets,
+                                           unsigned int flags)
+{
+    vzConnPtr privconn = conn->privateData;
+
+    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);
+
+    return virNetworkObjListExport(conn, privconn->networks, nets, NULL, flags);
+}
+
+static virNetworkPtr vzNetworkLookupByUUID(virConnectPtr conn,
+                                                  const unsigned char *uuid)
+{
+    vzConnPtr privconn = conn->privateData;
+    virNetworkObjPtr network;
+    virNetworkPtr ret = NULL;
+
+    network = virNetworkObjFindByUUID(privconn->networks, uuid);
+    if (!network) {
+        virReportError(VIR_ERR_NO_NETWORK,
+                       "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
+
+ cleanup:
+    virNetworkObjEndAPI(&network);
+    return ret;
+}
+
+static virNetworkPtr vzNetworkLookupByName(virConnectPtr conn,
+                                                  const char *name)
+{
+    vzConnPtr privconn = conn->privateData;
+    virNetworkObjPtr network;
+    virNetworkPtr ret = NULL;
+
+    network = virNetworkObjFindByName(privconn->networks, name);
+    if (!network) {
+        virReportError(VIR_ERR_NO_NETWORK,
+                       _("no network with matching name '%s'"), name);
+        goto cleanup;
+    }
+
+    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
+
+ cleanup:
+    virNetworkObjEndAPI(&network);
+    return ret;
+}
+
+static char *vzNetworkGetXMLDesc(virNetworkPtr net,
+                                        unsigned int flags)
+{
+    vzConnPtr privconn = net->conn->privateData;
+    virNetworkObjPtr network;
+    char *ret = NULL;
+
+    virCheckFlags(VIR_NETWORK_XML_INACTIVE, NULL);
+
+    network = virNetworkObjFindByUUID(privconn->networks, net->uuid);
+    if (!network) {
+        virReportError(VIR_ERR_NO_NETWORK,
+                       "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    ret = virNetworkDefFormat(network->def, flags);
+
+ cleanup:
+    virNetworkObjEndAPI(&network);
+    return ret;
+}
+
+static int vzNetworkIsActive(virNetworkPtr net)
+{
+    vzConnPtr privconn = net->conn->privateData;
+    virNetworkObjPtr obj;
+    int ret = -1;
+
+    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
+    if (!obj) {
+        virReportError(VIR_ERR_NO_NETWORK, NULL);
+        goto cleanup;
+    }
+    ret = virNetworkObjIsActive(obj);
+
+ cleanup:
+    virNetworkObjEndAPI(&obj);
+    return ret;
+}
+
+static int vzNetworkIsPersistent(virNetworkPtr net)
+{
+    vzConnPtr privconn = net->conn->privateData;
+    virNetworkObjPtr obj;
+    int ret = -1;
+
+    obj = virNetworkObjFindByUUID(privconn->networks, net->uuid);
+    if (!obj) {
+        virReportError(VIR_ERR_NO_NETWORK, NULL);
+        goto cleanup;
+    }
+    ret = obj->persistent;
+
+ cleanup:
+    virNetworkObjEndAPI(&obj);
+    return ret;
+}
+
+static int vzNetworkGetAutostart(virNetworkPtr net,
+                                 int *autostart)
+{
+    vzConnPtr privconn = net->conn->privateData;
+    virNetworkObjPtr network;
+    int ret = -1;
+
+    network = virNetworkObjFindByUUID(privconn->networks, net->uuid);
+    if (!network) {
+        virReportError(VIR_ERR_NO_NETWORK,
+                       "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    *autostart = network->autostart;
+    ret = 0;
+
+ cleanup:
+    virNetworkObjEndAPI(&network);
+    return ret;
+}
+
+virNetworkDriver vzNetworkDriver = {
+    .name = "Parallels",
+    .connectNumOfNetworks = vzConnectNumOfNetworks, /* 1.0.1 */
+    .connectListNetworks = vzConnectListNetworks, /* 1.0.1 */
+    .connectNumOfDefinedNetworks = vzConnectNumOfDefinedNetworks, /* 1.0.1 */
+    .connectListDefinedNetworks = vzConnectListDefinedNetworks, /* 1.0.1 */
+    .connectListAllNetworks = vzConnectListAllNetworks, /* 1.0.1 */
+    .networkLookupByUUID = vzNetworkLookupByUUID, /* 1.0.1 */
+    .networkLookupByName = vzNetworkLookupByName, /* 1.0.1 */
+    .networkGetXMLDesc = vzNetworkGetXMLDesc, /* 1.0.1 */
+    .networkGetAutostart = vzNetworkGetAutostart, /* 1.0.1 */
+    .networkIsActive = vzNetworkIsActive, /* 1.0.1 */
+    .networkIsPersistent = vzNetworkIsPersistent, /* 1.0.1 */
+};
diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c
new file mode 100644 (file)
index 0000000..f9cde44
--- /dev/null
@@ -0,0 +1,3660 @@
+/*
+ * vz_sdk.c: core driver functions for managing
+ * Parallels Cloud Server hosts
+ *
+ * Copyright (C) 2014 Parallels, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+#include <stdarg.h>
+
+#include "virerror.h"
+#include "viralloc.h"
+#include "virstring.h"
+#include "nodeinfo.h"
+#include "virlog.h"
+#include "datatypes.h"
+#include "domain_conf.h"
+#include "virtime.h"
+
+#include "vz_sdk.h"
+
+#define VIR_FROM_THIS VIR_FROM_PARALLELS
+#define JOB_INFINIT_WAIT_TIMEOUT UINT_MAX
+
+VIR_LOG_INIT("parallels.sdk");
+
+/*
+ * Log error description
+ */
+static void
+logPrlErrorHelper(PRL_RESULT err, const char *filename,
+                  const char *funcname, size_t linenr)
+{
+    char *msg1 = NULL, *msg2 = NULL;
+    PRL_UINT32 len = 0;
+
+    /* Get required buffer length */
+    PrlApi_GetResultDescription(err, PRL_TRUE, PRL_FALSE, NULL, &len);
+
+    if (VIR_ALLOC_N(msg1, len) < 0)
+        goto cleanup;
+
+    /* get short error description */
+    PrlApi_GetResultDescription(err, PRL_TRUE, PRL_FALSE, msg1, &len);
+
+    PrlApi_GetResultDescription(err, PRL_FALSE, PRL_FALSE, NULL, &len);
+
+    if (VIR_ALLOC_N(msg2, len) < 0)
+        goto cleanup;
+
+    /* get long error description */
+    PrlApi_GetResultDescription(err, PRL_FALSE, PRL_FALSE, msg2, &len);
+
+    virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INTERNAL_ERROR,
+                         filename, funcname, linenr,
+                         _("%s %s"), msg1, msg2);
+
+ cleanup:
+    VIR_FREE(msg1);
+    VIR_FREE(msg2);
+}
+
+#define logPrlError(code)                          \
+    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)
+{
+    PRL_RESULT ret, retCode;
+    char *msg1 = NULL, *msg2 = NULL;
+    PRL_UINT32 len = 0;
+    int err = -1;
+
+    if ((ret = PrlEvent_GetErrCode(event, &retCode))) {
+        logPrlError(ret);
+        return ret;
+    }
+
+    PrlEvent_GetErrString(event, PRL_TRUE, PRL_FALSE, NULL, &len);
+
+    if (VIR_ALLOC_N(msg1, len) < 0)
+        goto cleanup;
+
+    PrlEvent_GetErrString(event, PRL_TRUE, PRL_FALSE, msg1, &len);
+
+    PrlEvent_GetErrString(event, PRL_FALSE, PRL_FALSE, NULL, &len);
+
+    if (VIR_ALLOC_N(msg2, len) < 0)
+        goto cleanup;
+
+    PrlEvent_GetErrString(event, PRL_FALSE, PRL_FALSE, msg2, &len);
+
+    virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INTERNAL_ERROR,
+                         filename, funcname, linenr,
+                         _("%s %s"), msg1, msg2);
+    err = 0;
+
+ cleanup:
+    VIR_FREE(msg1);
+    VIR_FREE(msg2);
+
+    return err;
+}
+
+#define logPrlEventError(event)                    \
+    logPrlEventErrorHelper(event, __FILE__,        \
+                         __FUNCTION__, __LINE__)
+
+static PRL_RESULT
+getJobResultHelper(PRL_HANDLE job, unsigned int timeout, PRL_HANDLE *result,
+                   const char *filename, const char *funcname,
+                   size_t linenr)
+{
+    PRL_RESULT ret, retCode;
+
+    if ((ret = PrlJob_Wait(job, timeout))) {
+        logPrlErrorHelper(ret, filename, funcname, linenr);
+        goto cleanup;
+    }
+
+    if ((ret = PrlJob_GetRetCode(job, &retCode))) {
+        logPrlErrorHelper(ret, filename, funcname, linenr);
+        goto cleanup;
+    }
+
+    if (retCode) {
+        PRL_HANDLE err_handle;
+
+        /* Sometimes it's possible to get additional error info. */
+        if ((ret = PrlJob_GetError(job, &err_handle))) {
+            logPrlErrorHelper(ret, filename, funcname, linenr);
+            goto cleanup;
+        }
+
+        if (logPrlEventErrorHelper(err_handle, filename, funcname, linenr))
+            logPrlErrorHelper(retCode, filename, funcname, linenr);
+
+        PrlHandle_Free(err_handle);
+        ret = retCode;
+    } else {
+        ret = PrlJob_GetResult(job, result);
+        if (PRL_FAILED(ret)) {
+            logPrlErrorHelper(ret, filename, funcname, linenr);
+            PrlHandle_Free(*result);
+            *result = NULL;
+            goto cleanup;
+        }
+
+        ret = PRL_ERR_SUCCESS;
+    }
+
+ cleanup:
+    PrlHandle_Free(job);
+    return ret;
+}
+
+#define getJobResult(job, result)                       \
+    getJobResultHelper(job, JOB_INFINIT_WAIT_TIMEOUT,   \
+            result, __FILE__, __FUNCTION__, __LINE__)
+
+static PRL_RESULT
+waitJobHelper(PRL_HANDLE job, unsigned int timeout,
+              const char *filename, const char *funcname,
+              size_t linenr)
+{
+    PRL_HANDLE result = PRL_INVALID_HANDLE;
+    PRL_RESULT ret;
+
+    ret = getJobResultHelper(job, timeout, &result,
+                             filename, funcname, linenr);
+    PrlHandle_Free(result);
+    return ret;
+}
+
+#define waitJob(job)                                        \
+    waitJobHelper(job, JOB_INFINIT_WAIT_TIMEOUT, __FILE__,  \
+                         __FUNCTION__, __LINE__)
+
+
+int
+prlsdkInit(void)
+{
+    PRL_RESULT ret;
+
+    /* Disable console output */
+    PrlApi_SwitchConsoleLogging(0);
+
+    ret = PrlApi_InitEx(PARALLELS_API_VER, PAM_SERVER, 0, 0);
+    if (PRL_FAILED(ret)) {
+        logPrlError(ret);
+        return -1;
+    }
+
+    return 0;
+};
+
+void
+prlsdkDeinit(void)
+{
+    PrlApi_Deinit();
+};
+
+int
+prlsdkConnect(vzConnPtr privconn)
+{
+    PRL_RESULT ret;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    ret = PrlSrv_Create(&privconn->server);
+    if (PRL_FAILED(ret)) {
+        logPrlError(ret);
+        return -1;
+    }
+
+    job = PrlSrv_LoginLocalEx(privconn->server, NULL, 0,
+                              PSL_HIGH_SECURITY, PACF_NON_INTERACTIVE_MODE);
+
+    if (waitJob(job)) {
+        PrlHandle_Free(privconn->server);
+        return -1;
+    }
+
+    return 0;
+}
+
+void
+prlsdkDisconnect(vzConnPtr privconn)
+{
+    PRL_HANDLE job;
+
+    job = PrlSrv_Logoff(privconn->server);
+    waitJob(job);
+
+    PrlHandle_Free(privconn->server);
+}
+
+static int
+prlsdkSdkDomainLookup(vzConnPtr 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 (PRL_FAILED(getJobResult(job, &result)))
+        goto cleanup;
+
+    pret = PrlResult_GetParamByIndex(result, 0, sdkdom);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    ret = 0;
+
+ cleanup:
+    PrlHandle_Free(result);
+    return ret;
+}
+
+static void
+prlsdkUUIDFormat(const unsigned char *uuid, char *uuidstr)
+{
+    virUUIDFormat(uuid, uuidstr + 1);
+
+    uuidstr[0] = '{';
+    uuidstr[VIR_UUID_STRING_BUFLEN] = '}';
+    uuidstr[VIR_UUID_STRING_BUFLEN + 1] = '\0';
+}
+
+static PRL_HANDLE
+prlsdkSdkDomainLookupByUUID(vzConnPtr privconn, const unsigned char *uuid)
+{
+    char uuidstr[VIR_UUID_STRING_BUFLEN + 2];
+    PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
+
+    prlsdkUUIDFormat(uuid, uuidstr);
+
+    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(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 (PRL_FAILED(getJobResult(job, &result)))
+        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)
+{
+    vzDomObjPtr pdom = p;
+
+    if (!pdom)
+        return;
+
+    PrlHandle_Free(pdom->sdkdom);
+    PrlHandle_Free(pdom->cache.stats);
+    virCondDestroy(&pdom->cache.cond);
+    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,
+                  bool isCdrom,
+                  bool isCt)
+{
+    char *buf = NULL;
+    PRL_UINT32 buflen = 0;
+    PRL_RESULT pret;
+    PRL_UINT32 emulatedType;
+    PRL_UINT32 ifType;
+    PRL_UINT32 pos;
+    virDomainDeviceDriveAddressPtr address;
+    int ret = -1;
+
+    pret = PrlVmDev_GetEmulatedType(prldisk, &emulatedType);
+    prlsdkCheckRetGoto(pret, cleanup);
+    if (emulatedType == PDT_USE_IMAGE_FILE) {
+        virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
+        if (isCdrom)
+            virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
+        else
+            virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_PLOOP);
+    } else {
+        virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
+        virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
+    }
+
+    if (isCdrom) {
+        disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+        disk->src->readonly = true;
+    } else {
+        disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
+    }
+
+    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;
+
+    /* Let physical devices added to CT look like SATA disks */
+    if (isCt) {
+        ifType = PMS_SATA_DEVICE;
+    } else {
+        pret = PrlVmDev_GetIfaceType(prldisk, &ifType);
+        prlsdkCheckRetGoto(pret, cleanup);
+    }
+
+    pret = PrlVmDev_GetStackIndex(prldisk, &pos);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    address = &disk->info.addr.drive;
+    switch (ifType) {
+    case PMS_IDE_DEVICE:
+        disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+        disk->dst = virIndexToDiskName(pos, "hd");
+        address->bus = pos / 2;
+        address->target = 0;
+        address->unit = pos % 2;
+        break;
+    case PMS_SCSI_DEVICE:
+        disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+        disk->dst = virIndexToDiskName(pos, "sd");
+        address->bus = 0;
+        address->target = 0;
+        address->unit = pos;
+        break;
+    case PMS_SATA_DEVICE:
+        disk->bus = VIR_DOMAIN_DISK_BUS_SATA;
+        disk->dst = virIndexToDiskName(pos, "sd");
+        address->bus = 0;
+        address->target = 0;
+        address->unit = pos;
+        break;
+    default:
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Unknown disk bus: %X"), ifType);
+        goto cleanup;
+        break;
+    }
+
+    if (!disk->dst)
+        goto cleanup;
+
+    disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(buf);
+    return ret;
+}
+
+static int
+prlsdkGetFSInfo(PRL_HANDLE prldisk,
+                virDomainFSDefPtr fs)
+{
+    char *buf = NULL;
+    PRL_UINT32 buflen = 0;
+    PRL_RESULT pret;
+    int ret = -1;
+
+    fs->type = VIR_DOMAIN_FS_TYPE_FILE;
+    fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP;
+    fs->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH;
+    fs->wrpolicy = VIR_DOMAIN_FS_WRPOLICY_DEFAULT;
+    fs->format = VIR_STORAGE_FILE_PLOOP;
+
+    fs->readonly = false;
+    fs->symlinksResolved = false;
+
+    pret = PrlVmDev_GetImagePath(prldisk, NULL, &buflen);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (VIR_ALLOC_N(buf, buflen) < 0)
+        goto cleanup;
+
+    pret = PrlVmDev_GetImagePath(prldisk, buf, &buflen);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    fs->src = buf;
+    buf = NULL;
+
+    pret = PrlVmDevHd_GetMountPoint(prldisk, NULL, &buflen);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (VIR_ALLOC_N(buf, buflen) < 0)
+        goto cleanup;
+
+    pret = PrlVmDevHd_GetMountPoint(prldisk, buf, &buflen);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    fs->dst = buf;
+    buf = NULL;
+
+    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;
+    virDomainFSDefPtr fs = NULL;
+
+    pret = PrlVmCfg_GetHardDisksCount(sdkdom, &hddCount);
+    prlsdkCheckRetGoto(pret, error);
+
+    for (i = 0; i < hddCount; ++i) {
+
+        PRL_UINT32 emulatedType;
+
+        pret = PrlVmCfg_GetHardDisk(sdkdom, i, &hdd);
+        prlsdkCheckRetGoto(pret, error);
+
+        pret = PrlVmDev_GetEmulatedType(hdd, &emulatedType);
+        prlsdkCheckRetGoto(pret, error);
+
+        if (PDT_USE_REAL_DEVICE != emulatedType && IS_CT(def)) {
+
+            if (VIR_ALLOC(fs) < 0)
+                goto error;
+
+            if (prlsdkGetFSInfo(hdd, fs) < 0)
+                goto error;
+
+            if (virDomainFSInsert(def, fs) < 0)
+                goto error;
+
+            fs = NULL;
+            PrlHandle_Free(hdd);
+            hdd = PRL_INVALID_HANDLE;
+        } else {
+            if (!(disk = virDomainDiskDefNew(NULL)))
+                goto error;
+
+            if (prlsdkGetDiskInfo(hdd, disk, false, IS_CT(def)) < 0)
+                goto error;
+
+            if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
+                goto error;
+
+            disk = NULL;
+            PrlHandle_Free(hdd);
+            hdd = PRL_INVALID_HANDLE;
+        }
+    }
+
+    return 0;
+
+ error:
+    PrlHandle_Free(hdd);
+    virDomainDiskDefFree(disk);
+    virDomainFSDefFree(fs);
+    return -1;
+}
+
+static int
+prlsdkAddDomainOpticalDisksInfo(PRL_HANDLE sdkdom, virDomainDefPtr def)
+{
+    PRL_RESULT pret;
+    PRL_UINT32 cdromsCount;
+    PRL_UINT32 i;
+    PRL_HANDLE cdrom = PRL_INVALID_HANDLE;
+    virDomainDiskDefPtr disk = NULL;
+
+    pret = PrlVmCfg_GetOpticalDisksCount(sdkdom, &cdromsCount);
+    prlsdkCheckRetGoto(pret, error);
+
+    for (i = 0; i < cdromsCount; ++i) {
+        pret = PrlVmCfg_GetOpticalDisk(sdkdom, i, &cdrom);
+        prlsdkCheckRetGoto(pret, error);
+
+        if (!(disk = virDomainDiskDefNew(NULL)))
+            goto error;
+
+        if (prlsdkGetDiskInfo(cdrom, disk, true, IS_CT(def)) < 0)
+            goto error;
+
+        PrlHandle_Free(cdrom);
+        cdrom = PRL_INVALID_HANDLE;
+
+        if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
+            goto error;
+    }
+
+    return 0;
+
+ error:
+    PrlHandle_Free(cdrom);
+    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 = 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);
+
+    pret = PrlVmDev_GetIndex(netAdapter, &netAdapterIndex);
+    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_DOMAIN_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_DOMAIN_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);
+
+        /*
+         * We use VIR_DOMAIN_NET_TYPE_NETWORK for all network adapters
+         * except those whose Virtual Network Id differ from Parallels
+         * predefined ones such as PARALLELS_DOMAIN_BRIDGED_NETWORK_NAME
+         * and PARALLELS_DONAIN_ROUTED_NETWORK_NAME
+         */
+        if (STRNEQ(net->data.network.name, PARALLELS_DOMAIN_BRIDGED_NETWORK_NAME))
+            net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+
+    }
+
+    if (!isCt) {
+        PRL_VM_NET_ADAPTER_TYPE type;
+        pret = PrlVmDevNet_GetAdapterType(netAdapter, &type);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        switch (type) {
+        case PNT_RTL:
+            if (VIR_STRDUP(net->model, "rtl8139") < 0)
+                goto cleanup;
+            break;
+        case PNT_E1000:
+            if (VIR_STRDUP(net->model, "e1000") < 0)
+                goto cleanup;
+            break;
+        case PNT_VIRTIO:
+            if (VIR_STRDUP(net->model, "virtio") < 0)
+                goto cleanup;
+            break;
+        default:
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Unknown adapter type: %X"), type);
+            goto 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 (prlsdkAddDomainOpticalDisksInfo(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;
+
+    if (IS_CT(def)) {
+        virDomainVideoDefPtr video;
+        if (VIR_ALLOC(video) < 0)
+            goto error;
+        video->type = virDomainVideoDefaultType(def);
+        if (video->type < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("cannot determine default video type"));
+            VIR_FREE(video);
+            goto error;
+        }
+        video->vram = virDomainVideoDefaultRAM(def, video->type);
+        video->heads = 1;
+        if (VIR_ALLOC_N(def->videos, 1) < 0) {
+            virDomainVideoDefFree(video);
+            goto error;
+        }
+        def->videos[def->nvideos++] = video;
+    }
+    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)
+{
+    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 (!(def->cpumask = virBitmapNew(hostcpus)))
+            goto cleanup;
+        virBitmapSetAll(def->cpumask);
+    } else {
+        if (virBitmapParse(buf, 0, &def->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:
+        def->os.type = VIR_DOMAIN_OSTYPE_HVM;
+        break;
+    case PVT_CT:
+        def->os.type = VIR_DOMAIN_OSTYPE_EXE;
+        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(vzConnPtr privconn,
+                 PRL_HANDLE sdkdom,
+                 virDomainObjPtr olddom)
+{
+    virDomainObjPtr dom = NULL;
+    virDomainDefPtr def = NULL;
+    vzDomObjPtr 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 (!(def = virDomainDefNew()))
+        goto error;
+
+    if (!olddom) {
+        if (VIR_ALLOC(pdom) < 0)
+            goto error;
+    } else {
+        pdom = olddom->privateData;
+    }
+
+    if (STREQ(privconn->drivername, "vz"))
+        def->virtType = VIR_DOMAIN_VIRT_VZ;
+    else
+        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;
+
+    pdom->cache.stats = PRL_INVALID_HANDLE;
+    pdom->cache.count = -1;
+    if (virCondInit(&pdom->cache.cond) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot initialize condition"));
+        goto error;
+    }
+
+    if (prlsdkGetDomainIds(sdkdom, &def->name, def->uuid) < 0)
+        goto error;
+
+    def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
+    def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
+    def->onCrash = VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY;
+
+    /* get RAM parameters */
+    pret = PrlVmCfg_GetRamSize(sdkdom, &ram);
+    prlsdkCheckRetGoto(pret, error);
+    virDomainDefSetMemoryInitial(def, ram << 10); /* RAM size obtained in Mbytes,
+                                                     convert to Kbytes */
+    def->mem.cur_balloon = ram << 10;
+
+    if (prlsdkConvertCpuInfo(sdkdom, def) < 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);
+
+    /* For VMs pdom->home is actually /directory/config.pvs */
+    if (!IS_CT(def)) {
+        /* Get rid of /config.pvs in path string */
+        char *s = strrchr(pdom->home, '/');
+        if (s)
+            *s = '\0';
+    }
+
+    pret = PrlVmCfg_GetAutoStart(sdkdom, &autostart);
+    prlsdkCheckRetGoto(pret, error);
+
+    if (prlsdkGetDomainState(sdkdom, &domainState) < 0)
+        goto error;
+
+    if (virDomainDefAddImplicitControllers(def) < 0)
+        goto error;
+
+    if (def->ngraphics > 0) {
+        int bus = IS_CT(def) ? VIR_DOMAIN_INPUT_BUS_PARALLELS:
+                                VIR_DOMAIN_INPUT_BUS_PS2;
+
+        if (virDomainDefMaybeAddInput(def,
+                                      VIR_DOMAIN_INPUT_TYPE_MOUSE,
+                                      bus) < 0)
+            goto error;
+
+        if (virDomainDefMaybeAddInput(def,
+                                      VIR_DOMAIN_INPUT_TYPE_KBD,
+                                      bus) < 0)
+            goto 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);
+        dom->def = 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;
+
+    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 (prlsdkConvertDomainState(domainState, envId, dom) < 0)
+        goto error;
+
+    if (!pdom->sdkdom) {
+        pret = PrlHandle_AddRef(sdkdom);
+        prlsdkCheckRetGoto(pret, error);
+        pdom->sdkdom = sdkdom;
+    }
+
+    return dom;
+ error:
+    if (dom && !olddom) {
+        /* Domain isn't persistent means that we haven't yet set
+         * prlsdkDomObjFreePrivate and should call it manually
+         */
+        if (!dom->persistent)
+            prlsdkDomObjFreePrivate(pdom);
+
+        virDomainObjListRemove(privconn->domains, dom);
+    }
+    /* Delete newly allocated def only if we haven't assigned it to domain
+     * Otherwise we will end up with domain having invalid def within it
+     */
+    if (!dom)
+        virDomainDefFree(def);
+
+    return NULL;
+}
+
+int
+prlsdkLoadDomains(vzConnPtr 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 (PRL_FAILED(getJobResult(job, &result)))
+        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);
+    return -1;
+}
+
+virDomainObjPtr
+prlsdkAddDomain(vzConnPtr 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;
+}
+
+int
+prlsdkUpdateDomain(vzConnPtr privconn, virDomainObjPtr dom)
+{
+    PRL_HANDLE job;
+    virDomainObjPtr retdom = NULL;
+    vzDomObjPtr pdom = dom->privateData;
+
+    job = PrlVm_RefreshConfig(pdom->sdkdom);
+    if (waitJob(job))
+        return -1;
+
+    retdom = prlsdkLoadDomain(privconn, pdom->sdkdom, dom);
+    return retdom ? 0 : -1;
+}
+
+static int prlsdkSendEvent(vzConnPtr privconn,
+                           virDomainObjPtr dom,
+                           virDomainEventType lvEventType,
+                           int lvEventTypeDetails)
+{
+    virObjectEventPtr event = NULL;
+
+    event = virDomainEventLifecycleNewFromObj(dom,
+                                              lvEventType,
+                                              lvEventTypeDetails);
+    if (!event)
+        return -1;
+
+    virObjectEventStateQueue(privconn->domainEventState, event);
+    return 0;
+}
+
+static void
+prlsdkNewStateToEvent(VIRTUAL_MACHINE_STATE domainState,
+                      virDomainEventType *lvEventType,
+                      int *lvEventTypeDetails)
+{
+    /* We skip all intermediate states here, because
+     * libvirt doesn't have correspoding event types for
+     * them */
+    switch (domainState) {
+    case VMS_STOPPED:
+    case VMS_MOUNTED:
+        *lvEventType = VIR_DOMAIN_EVENT_STOPPED;
+        *lvEventTypeDetails = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
+        break;
+    case VMS_RUNNING:
+        *lvEventType = VIR_DOMAIN_EVENT_STARTED;
+        *lvEventTypeDetails = VIR_DOMAIN_EVENT_STARTED_BOOTED;
+        break;
+    case VMS_PAUSED:
+        *lvEventType = VIR_DOMAIN_EVENT_SUSPENDED;
+        *lvEventTypeDetails = VIR_DOMAIN_EVENT_SUSPENDED_PAUSED;
+        break;
+    case VMS_SUSPENDED:
+        *lvEventType = VIR_DOMAIN_EVENT_STOPPED;
+        *lvEventTypeDetails = VIR_DOMAIN_EVENT_STOPPED_SAVED;
+        break;
+    default:
+        VIR_DEBUG("Skip sending event about changing state to %X",
+                  domainState);
+        break;
+    }
+}
+
+static void
+prlsdkHandleVmStateEvent(vzConnPtr privconn,
+                         PRL_HANDLE prlEvent,
+                         unsigned char *uuid)
+{
+    PRL_RESULT pret = PRL_ERR_FAILURE;
+    PRL_HANDLE eventParam = PRL_INVALID_HANDLE;
+    PRL_INT32 domainState;
+    virDomainObjPtr dom = NULL;
+    vzDomObjPtr pdom;
+    virDomainEventType lvEventType = 0;
+    int lvEventTypeDetails = 0;
+
+    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
+    if (dom == NULL)
+        return;
+
+    pret = PrlEvent_GetParamByName(prlEvent, "vminfo_vm_state", &eventParam);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlEvtPrm_ToInt32(eventParam, &domainState);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pdom = dom->privateData;
+    if (prlsdkConvertDomainState(domainState, pdom->id, dom) < 0)
+        goto cleanup;
+
+    prlsdkNewStateToEvent(domainState,
+                          &lvEventType,
+                          &lvEventTypeDetails);
+
+    prlsdkSendEvent(privconn, dom, lvEventType, lvEventTypeDetails);
+
+ cleanup:
+    virObjectUnlock(dom);
+    return;
+}
+
+static void
+prlsdkHandleVmConfigEvent(vzConnPtr privconn,
+                          unsigned char *uuid)
+{
+    virDomainObjPtr dom = NULL;
+
+    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
+    if (dom == NULL)
+        return;
+
+    if (prlsdkUpdateDomain(privconn, dom) < 0)
+        goto cleanup;
+
+    prlsdkSendEvent(privconn, dom, VIR_DOMAIN_EVENT_DEFINED,
+                        VIR_DOMAIN_EVENT_DEFINED_UPDATED);
+
+ cleanup:
+    virObjectUnlock(dom);
+    return;
+}
+
+static void
+prlsdkHandleVmAddedEvent(vzConnPtr privconn,
+                       unsigned char *uuid)
+{
+    virDomainObjPtr dom = NULL;
+
+    dom = prlsdkAddDomain(privconn, uuid);
+    if (dom == NULL)
+        return;
+
+    prlsdkSendEvent(privconn, dom, VIR_DOMAIN_EVENT_DEFINED,
+                        VIR_DOMAIN_EVENT_DEFINED_ADDED);
+
+    virObjectUnlock(dom);
+    return;
+}
+
+static void
+prlsdkHandleVmRemovedEvent(vzConnPtr privconn,
+                           unsigned char *uuid)
+{
+    virDomainObjPtr dom = NULL;
+
+    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
+    /* domain was removed from the list from the libvirt
+     * API function in current connection */
+    if (dom == NULL)
+        return;
+
+    prlsdkSendEvent(privconn, dom, VIR_DOMAIN_EVENT_UNDEFINED,
+                        VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
+
+    virDomainObjListRemove(privconn->domains, dom);
+    return;
+}
+
+#define PARALLELS_STATISTICS_DROP_COUNT 3
+
+static PRL_RESULT
+prlsdkHandlePerfEvent(vzConnPtr privconn,
+                           PRL_HANDLE event,
+                           unsigned char *uuid)
+{
+    virDomainObjPtr dom = NULL;
+    vzDomObjPtr privdom = NULL;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
+    if (dom == NULL)
+        goto cleanup;
+    privdom = dom->privateData;
+
+    // delayed event after unsubscribe
+    if (privdom->cache.count == -1)
+        goto cleanup;
+
+    PrlHandle_Free(privdom->cache.stats);
+    privdom->cache.stats = PRL_INVALID_HANDLE;
+
+    if (privdom->cache.count > PARALLELS_STATISTICS_DROP_COUNT) {
+        job = PrlVm_UnsubscribeFromPerfStats(privdom->sdkdom);
+        if (PRL_FAILED(waitJob(job)))
+            goto cleanup;
+        // change state to unsubscribed
+        privdom->cache.count = -1;
+    } else {
+        ++privdom->cache.count;
+        privdom->cache.stats = event;
+        // thus we get own of event handle
+        event = PRL_INVALID_HANDLE;
+        virCondSignal(&privdom->cache.cond);
+    }
+
+ cleanup:
+    PrlHandle_Free(event);
+    if (dom)
+        virObjectUnlock(dom);
+
+    return PRL_ERR_SUCCESS;
+}
+
+static void
+prlsdkHandleVmEvent(vzConnPtr privconn, PRL_HANDLE prlEvent)
+{
+    PRL_RESULT pret = PRL_ERR_FAILURE;
+    char uuidstr[VIR_UUID_STRING_BUFLEN + 2];
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    PRL_UINT32 bufsize = ARRAY_CARDINALITY(uuidstr);
+    PRL_EVENT_TYPE prlEventType;
+
+    pret = PrlEvent_GetType(prlEvent, &prlEventType);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlEvent_GetIssuerId(prlEvent, uuidstr, &bufsize);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (prlsdkUUIDParse(uuidstr, uuid) < 0)
+        goto cleanup;
+
+    switch (prlEventType) {
+        case PET_DSP_EVT_VM_STATE_CHANGED:
+            prlsdkHandleVmStateEvent(privconn, prlEvent, uuid);
+            break;
+        case PET_DSP_EVT_VM_CONFIG_CHANGED:
+            prlsdkHandleVmConfigEvent(privconn, uuid);
+            break;
+        case PET_DSP_EVT_VM_CREATED:
+        case PET_DSP_EVT_VM_ADDED:
+            prlsdkHandleVmAddedEvent(privconn, uuid);
+            break;
+        case PET_DSP_EVT_VM_DELETED:
+        case PET_DSP_EVT_VM_UNREGISTERED:
+            prlsdkHandleVmRemovedEvent(privconn, uuid);
+            break;
+        case PET_DSP_EVT_VM_PERFSTATS:
+            prlsdkHandlePerfEvent(privconn, prlEvent, uuid);
+            // above function takes own of event
+            prlEvent = PRL_INVALID_HANDLE;
+            break;
+        default:
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Can't handle event of type %d"), prlEventType);
+    }
+
+ cleanup:
+    PrlHandle_Free(prlEvent);
+    return;
+}
+
+static PRL_RESULT
+prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque)
+{
+    vzConnPtr privconn = opaque;
+    PRL_RESULT pret = PRL_ERR_FAILURE;
+    PRL_HANDLE_TYPE handleType;
+    PRL_EVENT_ISSUER_TYPE prlIssuerType = PIE_UNKNOWN;
+
+    pret = PrlHandle_GetType(prlEvent, &handleType);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    /* Currently, there is no need to handle anything but events */
+    if (handleType != PHT_EVENT)
+        goto cleanup;
+
+    if (privconn == NULL)
+        goto cleanup;
+
+    PrlEvent_GetIssuerType(prlEvent, &prlIssuerType);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    switch (prlIssuerType) {
+        case PIE_VIRTUAL_MACHINE:
+            prlsdkHandleVmEvent(privconn, prlEvent);
+            // above function takes own of event
+            prlEvent = PRL_INVALID_HANDLE;
+            break;
+        default:
+            VIR_DEBUG("Skipping event of issuer type %d", prlIssuerType);
+    }
+
+ cleanup:
+    PrlHandle_Free(prlEvent);
+    return PRL_ERR_SUCCESS;
+}
+
+
+int prlsdkSubscribeToPCSEvents(vzConnPtr privconn)
+{
+    PRL_RESULT pret = PRL_ERR_UNINITIALIZED;
+
+    pret = PrlSrv_RegEventHandler(privconn->server,
+                                 prlsdkEventsHandler,
+                                 privconn);
+    prlsdkCheckRetGoto(pret, error);
+    return 0;
+
+ error:
+    return -1;
+}
+
+void prlsdkUnsubscribeFromPCSEvents(vzConnPtr privconn)
+{
+    PRL_RESULT ret = PRL_ERR_UNINITIALIZED;
+    ret = PrlSrv_UnregEventHandler(privconn->server,
+                                 prlsdkEventsHandler,
+                                 privconn);
+    if (PRL_FAILED(ret))
+        logPrlError(ret);
+}
+
+PRL_RESULT prlsdkStart(PRL_HANDLE sdkdom)
+{
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    job = PrlVm_StartEx(sdkdom, PSM_VM_START, 0);
+    return waitJob(job);
+}
+
+static PRL_RESULT prlsdkStopEx(PRL_HANDLE sdkdom, PRL_UINT32 mode)
+{
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    job = PrlVm_StopEx(sdkdom, mode, 0);
+    return waitJob(job);
+}
+
+PRL_RESULT prlsdkKill(PRL_HANDLE sdkdom)
+{
+    return prlsdkStopEx(sdkdom, PSM_KILL);
+}
+
+PRL_RESULT prlsdkStop(PRL_HANDLE sdkdom)
+{
+    return prlsdkStopEx(sdkdom, PSM_SHUTDOWN);
+}
+
+PRL_RESULT prlsdkPause(PRL_HANDLE sdkdom)
+{
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    job = PrlVm_Pause(sdkdom, false);
+    return waitJob(job);
+}
+
+PRL_RESULT prlsdkResume(PRL_HANDLE sdkdom)
+{
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    job = PrlVm_Resume(sdkdom);
+    return waitJob(job);
+}
+
+PRL_RESULT prlsdkSuspend(PRL_HANDLE sdkdom)
+{
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    job = PrlVm_Suspend(sdkdom);
+    return waitJob(job);
+}
+
+int
+prlsdkDomainChangeStateLocked(vzConnPtr privconn,
+                              virDomainObjPtr dom,
+                              prlsdkChangeStateFunc chstate)
+{
+    vzDomObjPtr pdom;
+    PRL_RESULT pret;
+    virErrorNumber virerr;
+
+    pdom = dom->privateData;
+    pret = chstate(pdom->sdkdom);
+    if (PRL_FAILED(pret)) {
+        virResetLastError();
+
+        switch (pret) {
+        case PRL_ERR_DISP_VM_IS_NOT_STARTED:
+        case PRL_ERR_DISP_VM_IS_NOT_STOPPED:
+            virerr = VIR_ERR_OPERATION_INVALID;
+            break;
+        default:
+            virerr = VIR_ERR_OPERATION_FAILED;
+        }
+
+        virReportError(virerr, "%s", _("Can't change domain state."));
+        return -1;
+    }
+
+    return prlsdkUpdateDomain(privconn, dom);
+}
+
+int
+prlsdkDomainChangeState(virDomainPtr domain,
+                        prlsdkChangeStateFunc chstate)
+{
+    vzConnPtr privconn = domain->conn->privateData;
+    virDomainObjPtr dom;
+    int ret = -1;
+
+    if (!(dom = vzDomObjFromDomain(domain)))
+        return -1;
+
+    ret = prlsdkDomainChangeStateLocked(privconn, dom, chstate);
+    virObjectUnlock(dom);
+    return ret;
+}
+
+static int
+prlsdkCheckUnsupportedParams(PRL_HANDLE sdkdom, virDomainDefPtr def)
+{
+    size_t i;
+    PRL_VM_TYPE vmType;
+    PRL_RESULT pret;
+    virDomainNumatuneMemMode memMode;
+
+    if (def->title) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("titles are not supported by vz driver"));
+        return -1;
+    }
+
+    if (def->blkio.ndevices > 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("blkio parameters are not supported "
+                         "by vz driver"));
+        return -1;
+    }
+
+    if (virDomainDefGetMemoryActual(def) != def->mem.cur_balloon) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                   _("changing balloon parameters is not supported "
+                     "by vz driver"));
+       return -1;
+    }
+
+    if (virDomainDefGetMemoryActual(def) % (1 << 10) != 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                   _("Memory size should be multiple of 1Mb."));
+        return -1;
+    }
+
+    if (def->mem.nhugepages ||
+        virMemoryLimitIsSet(def->mem.hard_limit) ||
+        virMemoryLimitIsSet(def->mem.soft_limit) ||
+        def->mem.min_guarantee ||
+        virMemoryLimitIsSet(def->mem.swap_hard_limit)) {
+
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Memory parameter is not supported "
+                         "by vz driver"));
+        return -1;
+    }
+
+    if (def->vcpus != def->maxvcpus) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                   _("current vcpus must be equal to maxvcpus"));
+        return -1;
+    }
+
+    if (def->placement_mode) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("changing cpu placement mode is not supported "
+                         "by vz driver"));
+        return -1;
+    }
+
+    if (def->cputune.shares ||
+        def->cputune.sharesSpecified ||
+        def->cputune.period ||
+        def->cputune.quota) {
+
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("cputune is not supported by vz driver"));
+        return -1;
+    }
+
+    if (def->cputune.vcpupin) {
+       for (i = 0; i < def->vcpus; i++) {
+            if (!virBitmapEqual(def->cpumask,
+                                def->cputune.vcpupin[i]->cpumask)) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               "%s", _("vcpupin cpumask differs from default cpumask"));
+                return -1;
+            }
+        }
+    }
+
+
+    /*
+     * Though we don't support NUMA configuration at the moment
+     * virDomainDefPtr always contain non zero NUMA configuration
+     * So, just make sure this configuration does't differ from auto generated.
+     */
+    if ((virDomainNumatuneGetMode(def->numa, -1, &memMode) == 0 &&
+         memMode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) ||
+         virDomainNumatuneHasPerNodeBinding(def->numa)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                        _("numa parameters are not supported "
+                          "by vz driver"));
+        return -1;
+    }
+
+    if (def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART ||
+        def->onPoweroff != VIR_DOMAIN_LIFECYCLE_DESTROY ||
+        def->onCrash != VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY) {
+
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("on_reboot, on_poweroff and on_crash parameters "
+                         "are not supported by vz driver"));
+        return -1;
+    }
+
+    /* we fill only type and arch fields in vzLoadDomain for
+     * hvm type and also init for containers, so we can check that all
+     * other paramenters are null and boot devices config is default */
+
+    if (def->os.machine != NULL || def->os.bootmenu != 0 ||
+        def->os.kernel != NULL || def->os.initrd != NULL ||
+        def->os.cmdline != NULL || def->os.root != NULL ||
+        def->os.loader != NULL || def->os.bootloader != NULL ||
+        def->os.bootloaderArgs != NULL || def->os.smbios_mode != 0 ||
+        def->os.bios.useserial != 0) {
+
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("changing OS parameters is not supported "
+                         "by vz driver"));
+        return -1;
+    }
+
+    pret = PrlVmCfg_GetVmType(sdkdom, &vmType);
+    if (PRL_FAILED(pret)) {
+        logPrlError(pret);
+        return -1;
+    }
+
+    if (!(vmType == PVT_VM && !IS_CT(def)) &&
+        !(vmType == PVT_CT && IS_CT(def))) {
+
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("changing OS type is not supported "
+                         "by vz driver"));
+        return -1;
+    }
+
+    if (!IS_CT(def)) {
+        if (def->os.nBootDevs != 1 ||
+            def->os.bootDevs[0] != VIR_DOMAIN_BOOT_DISK ||
+            def->os.init != NULL || def->os.initargv != NULL) {
+
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("changing OS parameters is not supported "
+                             "by vz driver"));
+            return -1;
+        }
+    } else {
+        if (def->os.nBootDevs != 0 ||
+            !STREQ_NULLABLE(def->os.init, "/sbin/init") ||
+            (def->os.initargv != NULL && def->os.initargv[0] != NULL)) {
+
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("changing OS parameters is not supported "
+                             "by vz driver"));
+            return -1;
+        }
+    }
+
+    if (def->emulator) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("changing emulator is not supported "
+                         "by vz driver"));
+        return -1;
+    }
+
+    for (i = 0; i < VIR_DOMAIN_FEATURE_LAST; i++) {
+        if (def->features[i]) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("changing features is not supported "
+                             "by vz driver"));
+            return -1;
+        }
+    }
+
+    if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC ||
+        def->clock.ntimers != 0) {
+
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("changing clock parameters is not supported "
+                         "by vz driver"));
+        return -1;
+    }
+
+    if (!IS_CT(def) && def->nfss != 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Filesystems in VMs are not supported "
+                         "by vz driver"));
+        return -1;
+    }
+
+    if (def->nsounds != 0 || def->nhostdevs != 0 ||
+        def->nredirdevs != 0 || def->nsmartcards != 0 ||
+        def->nparallels || def->nchannels != 0 ||
+        def->nleases != 0 || def->nhubs != 0) {
+
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("changing devices parameters is not supported "
+                         "by vz driver"));
+        return -1;
+    }
+
+    /* there may be one auto-input */
+    if (def->ninputs != 0 &&
+        (def->ninputs != 2 &&
+            def->inputs[0]->type != VIR_DOMAIN_INPUT_TYPE_MOUSE &&
+            def->inputs[0]->bus != VIR_DOMAIN_INPUT_BUS_PS2 &&
+            def->inputs[1]->type != VIR_DOMAIN_INPUT_TYPE_KBD &&
+            def->inputs[1]->bus != VIR_DOMAIN_INPUT_BUS_PS2)) {
+
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("changing input devices parameters is not supported "
+                         "by vz driver"));
+        return -1;
+    }
+
+    return 0;
+}
+
+static int prlsdkClearDevices(PRL_HANDLE sdkdom)
+{
+    PRL_RESULT pret;
+    PRL_UINT32 n, i;
+    PRL_HANDLE devList;
+    PRL_HANDLE dev;
+    int ret = -1;
+
+    pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_DISABLED);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmCfg_GetAllDevices(sdkdom, &devList);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlHndlList_GetItemsCount(devList, &n);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    for (i = 0; i < n; i++) {
+        pret = PrlHndlList_GetItem(devList, i, &dev);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        pret = PrlVmDev_Remove(dev);
+        PrlHandle_Free(dev);
+    }
+
+    ret = 0;
+ cleanup:
+    PrlHandle_Free(devList);
+    return ret;
+}
+
+static int
+prlsdkRemoveBootDevices(PRL_HANDLE sdkdom)
+{
+    PRL_RESULT pret;
+    PRL_UINT32 i, devCount;
+    PRL_HANDLE dev = PRL_INVALID_HANDLE;
+    PRL_DEVICE_TYPE devType;
+
+    pret = PrlVmCfg_GetBootDevCount(sdkdom, &devCount);
+    prlsdkCheckRetGoto(pret, error);
+
+    for (i = 0; i < devCount; i++) {
+
+        /* always get device by index 0, because device list resort after delete */
+        pret = PrlVmCfg_GetBootDev(sdkdom, 0, &dev);
+        prlsdkCheckRetGoto(pret, error);
+
+        pret = PrlBootDev_GetType(dev, &devType);
+        prlsdkCheckRetGoto(pret, error);
+
+        pret = PrlBootDev_Remove(dev);
+        prlsdkCheckRetGoto(pret, error);
+    }
+
+    return 0;
+
+ error:
+    return -1;
+}
+
+static int
+prlsdkAddDeviceToBootList(PRL_HANDLE sdkdom,
+                          PRL_UINT32 devIndex,
+                          PRL_DEVICE_TYPE devType,
+                          PRL_UINT32 bootSequence)
+{
+    PRL_RESULT pret;
+    PRL_HANDLE bootDev = PRL_INVALID_HANDLE;
+
+    pret = PrlVmCfg_CreateBootDev(sdkdom, &bootDev);
+    prlsdkCheckRetGoto(pret, error);
+
+    pret = PrlBootDev_SetIndex(bootDev, devIndex);
+    prlsdkCheckRetGoto(pret, error);
+
+    pret = PrlBootDev_SetType(bootDev, devType);
+    prlsdkCheckRetGoto(pret, error);
+
+    pret = PrlBootDev_SetSequenceIndex(bootDev, bootSequence);
+    prlsdkCheckRetGoto(pret, error);
+
+    pret = PrlBootDev_SetInUse(bootDev, PRL_TRUE);
+    prlsdkCheckRetGoto(pret, error);
+
+    return 0;
+
+ error:
+    if (bootDev != PRL_INVALID_HANDLE)
+        PrlBootDev_Remove(bootDev);
+
+    return -1;
+}
+
+static int prlsdkCheckGraphicsUnsupportedParams(virDomainDefPtr def)
+{
+    virDomainGraphicsDefPtr gr;
+
+    if (def->ngraphics == 0)
+        return 0;
+
+    if (def->ngraphics > 1) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vz driver supports only "
+                         "one VNC per domain."));
+        return -1;
+    }
+
+    gr = def->graphics[0];
+
+    if (gr->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vz driver supports only "
+                         "VNC graphics."));
+        return -1;
+    }
+
+    if (gr->data.vnc.websocket != 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vz driver doesn't support "
+                         "websockets for VNC graphics."));
+        return -1;
+    }
+
+    if (gr->data.vnc.keymap != 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vz driver doesn't support "
+                         "keymap setting for VNC graphics."));
+        return -1;
+    }
+
+    if (gr->data.vnc.sharePolicy == VIR_DOMAIN_GRAPHICS_VNC_SHARE_ALLOW_EXCLUSIVE) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vz driver doesn't support "
+                         "exclusive share policy for VNC graphics."));
+        return -1;
+    }
+
+    if (gr->data.vnc.socket) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vz driver doesn't support "
+                         "VNC graphics over unix sockets."));
+        return -1;
+    }
+
+    if (gr->data.vnc.auth.connected == VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_FAIL ||
+            gr->data.vnc.auth.connected == VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_KEEP) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vz driver doesn't support "
+                         "given action in case of password change."));
+        return -1;
+    }
+
+    if (gr->data.vnc.auth.expires) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vz driver doesn't support "
+                         "setting password expire time."));
+        return -1;
+    }
+
+    if (gr->nListens > 1) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("vz driver doesn't support more than "
+                         "one listening VNC server per domain"));
+        return -1;
+    }
+
+    if (gr->nListens == 1 &&
+        virDomainGraphicsListenGetType(gr, 0) != VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("vz driver supports only address-based VNC listening"));
+        return -1;
+    }
+
+    return 0;
+}
+
+static int prlsdkCheckVideoUnsupportedParams(virDomainDefPtr def)
+{
+    virDomainVideoDefPtr v;
+
+    if (IS_CT(def)) {
+        if (def->nvideos == 0) {
+            return 0;
+        } else {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("Video adapters are not supported "
+                             "int containers."));
+            return -1;
+        }
+    } else {
+        if (def->nvideos != 1) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("vz driver supports "
+                             "only one video adapter."));
+            return -1;
+        }
+    }
+
+    v = def->videos[0];
+
+    if (v->type != VIR_DOMAIN_VIDEO_TYPE_VGA) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vz driver supports "
+                         "only VGA video adapters."));
+        return -1;
+    }
+
+    if (v->heads != 1) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vz driver doesn't support "
+                         "multihead video adapters."));
+        return -1;
+    }
+
+    if (v->accel != NULL && (v->accel->support2d || v->accel->support3d)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vz driver doesn't support "
+                         "setting video acceleration parameters."));
+        return -1;
+    }
+
+    return 0;
+}
+
+static int prlsdkCheckSerialUnsupportedParams(virDomainChrDefPtr chr)
+{
+    if (chr->deviceType != VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Specified character device type is not supported "
+                         "by vz driver."));
+        return -1;
+    }
+
+    if (chr->targetTypeAttr) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Specified character device target type is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_DEV &&
+        chr->source.type != VIR_DOMAIN_CHR_TYPE_FILE &&
+        chr->source.type != VIR_DOMAIN_CHR_TYPE_UNIX) {
+
+
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Specified character device source type is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (chr->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting device info for character devices is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (chr->nseclabels > 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting security labels is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    return 0;
+}
+
+static int prlsdkCheckNetUnsupportedParams(virDomainNetDefPtr net)
+{
+    if (net->type != VIR_DOMAIN_NET_TYPE_NETWORK &&
+        net->type != VIR_DOMAIN_NET_TYPE_BRIDGE) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Specified network adapter type is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (net->backend.tap || net->backend.vhost) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Interface backend parameters are not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (net->data.network.portgroup) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Virtual network portgroups are not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (net->tune.sndbuf_specified) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting interface sndbuf is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (net->script) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting interface script is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (net->ifname_guest) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting guest interface name is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (net->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting device info for network devices is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (net->filter) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting network filter is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (net->bandwidth) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting network bandwidth is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (net->vlan.trunk) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting up vlans is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    return 0;
+}
+
+static int prlsdkCheckDiskUnsupportedParams(virDomainDiskDefPtr disk)
+{
+    if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK &&
+        disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
+
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Only hard disks and cdroms are supported "
+                         "by vz driver."));
+        return -1;
+    }
+
+   if (disk->blockio.logical_block_size ||
+       disk->blockio.physical_block_size) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting disk block sizes is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (disk->blkdeviotune.total_bytes_sec ||
+        disk->blkdeviotune.read_bytes_sec ||
+        disk->blkdeviotune.write_bytes_sec ||
+        disk->blkdeviotune.total_iops_sec ||
+        disk->blkdeviotune.read_iops_sec ||
+        disk->blkdeviotune.write_iops_sec) {
+
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting disk io limits is not "
+                         "supported by vz driver yet."));
+        return -1;
+    }
+
+    if (disk->serial) {
+        VIR_INFO("%s", _("Setting disk serial number is not "
+                         "supported by vz driver."));
+    }
+
+    if (disk->wwn) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting disk wwn id is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (disk->vendor) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting disk vendor is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (disk->product) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting disk product id is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (disk->error_policy != VIR_DOMAIN_DISK_ERROR_POLICY_DEFAULT) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting disk error policy is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (disk->iomode) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting disk io mode is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (disk->copy_on_read) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Disk copy_on_read is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (disk->startupPolicy != VIR_DOMAIN_STARTUP_POLICY_DEFAULT) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting up disk startup policy is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (disk->transient) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Transient disks are not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (disk->discard) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting up disk discard parameter is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (disk->iothread) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting up disk io thread # is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (disk->src->type != VIR_STORAGE_TYPE_FILE &&
+        disk->src->type != VIR_STORAGE_TYPE_BLOCK) {
+
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Only disk and block storage types are "
+                         "supported by vz driver."));
+        return -1;
+
+    }
+
+    return 0;
+}
+
+static int prlsdkCheckFSUnsupportedParams(virDomainFSDefPtr fs)
+{
+    if (fs->type != VIR_DOMAIN_FS_TYPE_FILE) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Only file based filesystems are "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (fs->fsdriver != VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Only ploop fs driver is "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (fs->accessmode != VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Changing fs access mode is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (fs->wrpolicy != VIR_DOMAIN_FS_WRPOLICY_DEFAULT) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Changing fs write policy is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (fs->format != VIR_STORAGE_FILE_PLOOP) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Only ploop disk images are "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (fs->readonly) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting readonly for filesystems is "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    if (fs->space_hard_limit || fs->space_soft_limit) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Setting fs quotas is not "
+                         "supported by vz driver."));
+        return -1;
+    }
+
+    return 0;
+}
+
+static int prlsdkApplyGraphicsParams(PRL_HANDLE sdkdom, virDomainDefPtr def)
+{
+    virDomainGraphicsDefPtr gr;
+    PRL_RESULT pret;
+    int ret  = -1;
+    const char *listenAddr = NULL;
+
+    if (prlsdkCheckGraphicsUnsupportedParams(def))
+        return -1;
+
+    if (def->ngraphics == 0)
+        return 0;
+
+    gr = def->graphics[0];
+
+    if (gr->data.vnc.autoport) {
+        pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_AUTO);
+        prlsdkCheckRetGoto(pret, cleanup);
+    } else {
+        pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_MANUAL);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        pret = PrlVmCfg_SetVNCPort(sdkdom, gr->data.vnc.port);
+        prlsdkCheckRetGoto(pret, cleanup);
+    }
+
+    if (gr->nListens == 1) {
+        listenAddr = virDomainGraphicsListenGetAddress(gr, 0);
+        if (!listenAddr)
+            goto cleanup;
+        pret = PrlVmCfg_SetVNCHostName(sdkdom, listenAddr);
+        prlsdkCheckRetGoto(pret, cleanup);
+    }
+
+    ret = 0;
+ cleanup:
+    return ret;
+}
+
+static int prlsdkApplyVideoParams(PRL_HANDLE sdkdom ATTRIBUTE_UNUSED, virDomainDefPtr def)
+{
+    PRL_RESULT pret;
+
+    if (def->nvideos == 0)
+        return 0;
+
+    if (IS_CT(def)) {
+        /* ignore video parameters */
+        return 0;
+    }
+
+    if (prlsdkCheckVideoUnsupportedParams(def))
+        return -1;
+
+    pret = PrlVmCfg_SetVideoRamSize(sdkdom, def->videos[0]->vram >> 10);
+    prlsdkCheckRetGoto(pret, error);
+
+    return 0;
+ error:
+    return -1;
+}
+
+static int prlsdkAddSerial(PRL_HANDLE sdkdom, virDomainChrDefPtr chr)
+{
+    PRL_RESULT pret;
+    PRL_HANDLE sdkchr = PRL_INVALID_HANDLE;
+    PRL_VM_DEV_EMULATION_TYPE emutype;
+    PRL_SERIAL_PORT_SOCKET_OPERATION_MODE socket_mode =
+                                    PSP_SERIAL_SOCKET_SERVER;
+    char *path;
+    int ret = -1;
+
+    if (prlsdkCheckSerialUnsupportedParams(chr) < 0)
+        return -1;
+
+    pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_SERIAL_PORT, &sdkchr);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    switch (chr->source.type) {
+    case VIR_DOMAIN_CHR_TYPE_DEV:
+        emutype = PDT_USE_REAL_DEVICE;
+        path = chr->source.data.file.path;
+        break;
+    case VIR_DOMAIN_CHR_TYPE_FILE:
+        emutype = PDT_USE_OUTPUT_FILE;
+        path = chr->source.data.file.path;
+        break;
+    case VIR_DOMAIN_CHR_TYPE_UNIX:
+        emutype = PDT_USE_SERIAL_PORT_SOCKET_MODE;
+        path = chr->source.data.nix.path;
+        if (chr->source.data.nix.listen)
+            socket_mode = PSP_SERIAL_SOCKET_SERVER;
+        else
+            socket_mode = PSP_SERIAL_SOCKET_CLIENT;
+        break;
+    default:
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vz driver doesn't support "
+                         "specified serial source type."));
+        goto cleanup;
+    }
+
+    pret = PrlVmDev_SetEmulatedType(sdkchr, emutype);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetSysName(sdkchr, path);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetFriendlyName(sdkchr, path);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (chr->source.type == VIR_DOMAIN_CHR_TYPE_UNIX) {
+        pret = PrlVmDevSerial_SetSocketMode(sdkchr, socket_mode);
+        prlsdkCheckRetGoto(pret, cleanup);
+    }
+
+    pret = PrlVmDev_SetEnabled(sdkchr, 1);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetIndex(sdkchr, chr->target.port);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    ret = 0;
+ cleanup:
+    PrlHandle_Free(sdkchr);
+    return ret;
+}
+
+#define PRL_MAC_STRING_BUFNAME  13
+
+static const char * prlsdkFormatMac(virMacAddrPtr mac, char *macstr)
+{
+    snprintf(macstr, PRL_MAC_STRING_BUFNAME,
+             "%02X%02X%02X%02X%02X%02X",
+             mac->addr[0], mac->addr[1], mac->addr[2],
+             mac->addr[3], mac->addr[4], mac->addr[5]);
+    macstr[PRL_MAC_STRING_BUFNAME - 1] = '\0';
+    return macstr;
+}
+
+static int prlsdkAddNet(PRL_HANDLE sdkdom,
+                        vzConnPtr privconn,
+                        virDomainNetDefPtr net,
+                        bool isCt)
+{
+    PRL_RESULT pret;
+    PRL_HANDLE sdknet = PRL_INVALID_HANDLE;
+    PRL_HANDLE vnet = PRL_INVALID_HANDLE;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+    int ret = -1;
+    char macstr[PRL_MAC_STRING_BUFNAME];
+
+    if (prlsdkCheckNetUnsupportedParams(net) < 0)
+        return -1;
+
+    pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_GENERIC_NETWORK_ADAPTER, &sdknet);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetEnabled(sdknet, 1);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetConnected(sdknet, net->linkstate !=
+                                 VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN);
+
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (net->ifname) {
+        pret = PrlVmDevNet_SetHostInterfaceName(sdknet, net->ifname);
+        prlsdkCheckRetGoto(pret, cleanup);
+    }
+
+    prlsdkFormatMac(&net->mac, macstr);
+    pret = PrlVmDevNet_SetMacAddress(sdknet, macstr);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (isCt) {
+        if (net->model)
+             VIR_WARN("Setting network adapter for containers is not "
+                      "supported by vz driver.");
+    } else {
+        if (STREQ(net->model, "rtl8139")) {
+            pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_RTL);
+        } else if (STREQ(net->model, "e1000")) {
+            pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_E1000);
+        } else if (STREQ(net->model, "virtio")) {
+            pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_VIRTIO);
+        } else {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Specified network adapter model is not "
+                         "supported by vz driver."));
+            goto cleanup;
+        }
+        prlsdkCheckRetGoto(pret, cleanup);
+    }
+
+    if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+        if (STREQ(net->data.network.name, PARALLELS_DOMAIN_ROUTED_NETWORK_NAME)) {
+            pret = PrlVmDev_SetEmulatedType(sdknet, PNA_ROUTED);
+            prlsdkCheckRetGoto(pret, cleanup);
+        } else if (STREQ(net->data.network.name, PARALLELS_DOMAIN_BRIDGED_NETWORK_NAME)) {
+            pret = PrlVmDev_SetEmulatedType(sdknet, PNA_BRIDGED_ETHERNET);
+            prlsdkCheckRetGoto(pret, cleanup);
+
+            pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.network.name);
+            prlsdkCheckRetGoto(pret, cleanup);
+        }
+    } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+        /*
+         * For this type of adapter we create a new
+         * Virtual Network assuming that bridge with given name exists
+         * Failing creating this means domain creation failure
+         */
+        pret = PrlVirtNet_Create(&vnet);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        pret = PrlVirtNet_SetNetworkId(vnet, net->data.network.name);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        pret = PrlVirtNet_SetNetworkType(vnet, PVN_BRIDGED_ETHERNET);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        job = PrlSrv_AddVirtualNetwork(privconn->server, vnet, 0);
+        if (PRL_FAILED(pret = waitJob(job)))
+            goto cleanup;
+
+        pret = PrlVmDev_SetEmulatedType(sdknet, PNA_BRIDGED_ETHERNET);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.network.name);
+        prlsdkCheckRetGoto(pret, cleanup);
+    }
+
+    if (net->trustGuestRxFilters == VIR_TRISTATE_BOOL_YES)
+        pret = PrlVmDevNet_SetPktFilterPreventMacSpoof(sdknet, 0);
+    else if (net->trustGuestRxFilters == VIR_TRISTATE_BOOL_NO)
+        pret = PrlVmDevNet_SetPktFilterPreventMacSpoof(sdknet, 1);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    ret = 0;
+ cleanup:
+    PrlHandle_Free(vnet);
+    PrlHandle_Free(sdknet);
+    return ret;
+}
+
+static void prlsdkDelNet(vzConnPtr privconn, virDomainNetDefPtr net)
+{
+    PRL_RESULT pret;
+    PRL_HANDLE vnet = PRL_INVALID_HANDLE;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    if (net->type != VIR_DOMAIN_NET_TYPE_BRIDGE)
+        return;
+
+    pret = PrlVirtNet_Create(&vnet);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVirtNet_SetNetworkId(vnet, net->data.network.name);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    PrlSrv_DeleteVirtualNetwork(privconn->server, vnet, 0);
+    if (PRL_FAILED(pret = waitJob(job)))
+        goto cleanup;
+
+ cleanup:
+    PrlHandle_Free(vnet);
+}
+
+static int prlsdkDelDisk(PRL_HANDLE sdkdom, int idx)
+{
+    int ret = -1;
+    PRL_RESULT pret;
+    PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
+
+    pret = PrlVmCfg_GetHardDisk(sdkdom, idx, &sdkdisk);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_Remove(sdkdisk);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    ret = 0;
+
+ cleanup:
+    PrlHandle_Free(sdkdisk);
+    return ret;
+}
+
+static int prlsdkAddDisk(PRL_HANDLE sdkdom,
+                         virDomainDiskDefPtr disk,
+                         bool bootDisk,
+                         bool isCt)
+{
+    PRL_RESULT pret;
+    PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
+    int ret = -1;
+    PRL_VM_DEV_EMULATION_TYPE emutype;
+    PRL_MASS_STORAGE_INTERFACE_TYPE sdkbus;
+    int idx;
+    virDomainDeviceDriveAddressPtr drive;
+    PRL_UINT32 devIndex;
+    PRL_DEVICE_TYPE devType;
+    char *dst = NULL;
+
+    if (prlsdkCheckDiskUnsupportedParams(disk) < 0)
+        return -1;
+
+    if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
+        devType = PDE_HARD_DISK;
+    else
+        devType = PDE_OPTICAL_DISK;
+
+    pret = PrlVmCfg_CreateVmDev(sdkdom, devType, &sdkdisk);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetEnabled(sdkdisk, 1);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetConnected(sdkdisk, 1);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (disk->src->type == VIR_STORAGE_TYPE_FILE) {
+        if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
+            virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_PLOOP) {
+
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid format of "
+                           "disk %s, vz driver supports only "
+                           "images in ploop format."), disk->src->path);
+            goto cleanup;
+        }
+
+        emutype = PDT_USE_IMAGE_FILE;
+    } else {
+        if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
+            (virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_RAW &&
+             virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_NONE &&
+             virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_AUTO)) {
+
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid format "
+                           "of disk %s, it should be either not set, or set "
+                           "to raw or auto."), disk->src->path);
+            goto cleanup;
+        }
+        emutype = PDT_USE_REAL_DEVICE;
+    }
+
+    pret = PrlVmDev_SetEmulatedType(sdkdisk, emutype);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetSysName(sdkdisk, disk->src->path);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetFriendlyName(sdkdisk, disk->src->path);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    drive = &disk->info.addr.drive;
+    if (drive->controller > 0) {
+        /* We have only one controller of each type */
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid drive "
+                       "address of disk %s, vz driver supports "
+                       "only one controller."), disk->dst);
+        goto cleanup;
+    }
+
+    if (drive->target > 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid drive "
+                       "address of disk %s, vz driver supports "
+                       "only target 0."), disk->dst);
+        goto cleanup;
+    }
+
+    switch (disk->bus) {
+    case VIR_DOMAIN_DISK_BUS_IDE:
+        if (drive->unit > 1) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid drive "
+                           "address of disk %s, vz driver supports "
+                           "only units 0-1 for IDE bus."), disk->dst);
+            goto cleanup;
+        }
+        sdkbus = PMS_IDE_DEVICE;
+        idx = 2 * drive->bus + drive->unit;
+        dst = virIndexToDiskName(idx, "hd");
+        break;
+    case VIR_DOMAIN_DISK_BUS_SCSI:
+        if (drive->bus > 0) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid drive "
+                           "address of disk %s, vz driver supports "
+                           "only bus 0 for SCSI bus."), disk->dst);
+            goto cleanup;
+        }
+        sdkbus = PMS_SCSI_DEVICE;
+        idx = drive->unit;
+        dst = virIndexToDiskName(idx, "sd");
+        break;
+    case VIR_DOMAIN_DISK_BUS_SATA:
+        if (drive->bus > 0) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid drive "
+                           "address of disk %s, vz driver supports "
+                           "only bus 0 for SATA bus."), disk->dst);
+            goto cleanup;
+        }
+        sdkbus = PMS_SATA_DEVICE;
+        idx = drive->unit;
+        dst = virIndexToDiskName(idx, "sd");
+        break;
+    default:
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Specified disk bus is not "
+                         "supported by vz driver."));
+        goto cleanup;
+    }
+
+    if (!dst)
+        goto cleanup;
+
+    if (STRNEQ(dst, disk->dst)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid drive "
+                       "address of disk %s, vz driver supports "
+                       "only defaults address to logical device name."), disk->dst);
+        goto cleanup;
+    }
+
+    pret = PrlVmDev_SetIfaceType(sdkdisk, sdkbus);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetStackIndex(sdkdisk, idx);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    switch (disk->cachemode) {
+    case VIR_DOMAIN_DISK_CACHE_DISABLE:
+        pret = PrlVmCfg_SetDiskCacheWriteBack(sdkdom, PRL_FALSE);
+        prlsdkCheckRetGoto(pret, cleanup);
+        break;
+    case VIR_DOMAIN_DISK_CACHE_WRITEBACK:
+        pret = PrlVmCfg_SetDiskCacheWriteBack(sdkdom, PRL_TRUE);
+        prlsdkCheckRetGoto(pret, cleanup);
+        break;
+    case VIR_DOMAIN_DISK_CACHE_DEFAULT:
+        break;
+    default:
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Specified disk cache mode is not "
+                         "supported by vz driver."));
+        goto cleanup;
+    }
+
+    if (bootDisk == true) {
+        pret = PrlVmDev_GetIndex(sdkdisk, &devIndex);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        if (prlsdkAddDeviceToBootList(sdkdom, devIndex, devType, 0) < 0)
+            goto cleanup;
+
+        /* If we add physical device as a boot disk to container
+         * we have to specify mount point for it */
+        if (isCt) {
+            pret = PrlVmDevHd_SetMountPoint(sdkdisk, "/");
+            prlsdkCheckRetGoto(pret, cleanup);
+        }
+    }
+
+    return 0;
+ cleanup:
+    PrlHandle_Free(sdkdisk);
+    VIR_FREE(dst);
+    return ret;
+}
+
+int
+prlsdkAttachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk)
+{
+    int ret = -1;
+    vzDomObjPtr privdom = dom->privateData;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    job = PrlVm_BeginEdit(privdom->sdkdom);
+    if (PRL_FAILED(waitJob(job)))
+        goto cleanup;
+
+    ret = prlsdkAddDisk(privdom->sdkdom, disk, false, IS_CT(dom->def));
+    if (ret == 0) {
+        job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
+        if (PRL_FAILED(waitJob(job))) {
+            ret = -1;
+            goto cleanup;
+        }
+    }
+
+ cleanup:
+    return ret;
+}
+
+static int
+prlsdkGetDiskIndex(PRL_HANDLE sdkdom, virDomainDiskDefPtr disk)
+{
+    int idx = -1;
+    char *buf = NULL;
+    PRL_UINT32 buflen = 0;
+    PRL_RESULT pret;
+    PRL_UINT32 hddCount;
+    PRL_UINT32 i;
+    PRL_HANDLE hdd = PRL_INVALID_HANDLE;
+
+    pret = PrlVmCfg_GetHardDisksCount(sdkdom, &hddCount);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    for (i = 0; i < hddCount; ++i) {
+
+        pret = PrlVmCfg_GetHardDisk(sdkdom, i, &hdd);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        pret = PrlVmDev_GetFriendlyName(hdd, 0, &buflen);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        if (VIR_ALLOC_N(buf, buflen) < 0)
+            goto cleanup;
+
+        pret = PrlVmDev_GetFriendlyName(hdd, buf, &buflen);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        if (STRNEQ(disk->src->path, buf)) {
+
+            PrlHandle_Free(hdd);
+            hdd = PRL_INVALID_HANDLE;
+            VIR_FREE(buf);
+            continue;
+        }
+
+        VIR_FREE(buf);
+        idx = i;
+        break;
+    }
+
+ cleanup:
+    PrlHandle_Free(hdd);
+    return idx;
+}
+
+int
+prlsdkDetachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk)
+{
+    int ret = -1, idx;
+    vzDomObjPtr privdom = dom->privateData;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    idx = prlsdkGetDiskIndex(privdom->sdkdom, disk);
+    if (idx < 0)
+        goto cleanup;
+
+    job = PrlVm_BeginEdit(privdom->sdkdom);
+    if (PRL_FAILED(waitJob(job)))
+        goto cleanup;
+
+    ret = prlsdkDelDisk(privdom->sdkdom, idx);
+    if (ret == 0) {
+        job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
+        if (PRL_FAILED(waitJob(job))) {
+            ret = -1;
+            goto cleanup;
+        }
+    }
+
+ cleanup:
+    return ret;
+}
+
+static int
+prlsdkAddFS(PRL_HANDLE sdkdom, virDomainFSDefPtr fs)
+{
+    PRL_RESULT pret;
+    PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
+    int ret = -1;
+
+    if (prlsdkCheckFSUnsupportedParams(fs) < 0)
+        return -1;
+
+    pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_HARD_DISK, &sdkdisk);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetEnabled(sdkdisk, 1);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetConnected(sdkdisk, 1);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetEmulatedType(sdkdisk, PDT_USE_IMAGE_FILE);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetSysName(sdkdisk, fs->src);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetImagePath(sdkdisk, fs->src);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_SetFriendlyName(sdkdisk, fs->src);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDevHd_SetMountPoint(sdkdisk, fs->dst);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    ret = 0;
+
+ cleanup:
+    PrlHandle_Free(sdkdisk);
+    return ret;
+}
+static int
+prlsdkDoApplyConfig(virConnectPtr conn,
+                    PRL_HANDLE sdkdom,
+                    virDomainDefPtr def,
+                    virDomainDefPtr olddef)
+{
+    PRL_RESULT pret;
+    size_t i;
+    char uuidstr[VIR_UUID_STRING_BUFLEN + 2];
+    bool needBoot = true;
+    char *mask = NULL;
+
+    if (prlsdkCheckUnsupportedParams(sdkdom, def) < 0)
+        return -1;
+
+    if (def->description) {
+        pret = PrlVmCfg_SetDescription(sdkdom, def->description);
+        prlsdkCheckRetGoto(pret, error);
+    }
+
+    if (def->name) {
+        pret = PrlVmCfg_SetName(sdkdom, def->name);
+        prlsdkCheckRetGoto(pret, error);
+    }
+
+    if (def->uuid) {
+        prlsdkUUIDFormat(def->uuid, uuidstr);
+
+        pret = PrlVmCfg_SetUuid(sdkdom, uuidstr);
+        prlsdkCheckRetGoto(pret, error);
+    }
+
+    pret = PrlVmCfg_SetRamSize(sdkdom, virDomainDefGetMemoryActual(def) >> 10);
+    prlsdkCheckRetGoto(pret, error);
+
+    pret = PrlVmCfg_SetCpuCount(sdkdom, def->vcpus);
+    prlsdkCheckRetGoto(pret, error);
+
+    if (!(mask = virBitmapFormat(def->cpumask)))
+        goto error;
+
+    pret = PrlVmCfg_SetCpuMask(sdkdom, mask);
+    prlsdkCheckRetGoto(pret, error);
+    VIR_FREE(mask);
+
+    switch (def->os.arch) {
+        case VIR_ARCH_X86_64:
+            pret = PrlVmCfg_SetCpuMode(sdkdom, PCM_CPU_MODE_64);
+            break;
+        case VIR_ARCH_I686:
+            pret = PrlVmCfg_SetCpuMode(sdkdom, PCM_CPU_MODE_32);
+            break;
+        default:
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Unknown CPU mode: %s"),
+                           virArchToString(def->os.arch));
+            goto error;
+    }
+    prlsdkCheckRetGoto(pret, error);
+
+    if (prlsdkClearDevices(sdkdom) < 0)
+        goto error;
+
+    if (prlsdkRemoveBootDevices(sdkdom) < 0)
+        goto error;
+
+    if (olddef) {
+        for (i = 0; i < olddef->nnets; i++)
+            prlsdkDelNet(conn->privateData, olddef->nets[i]);
+    }
+
+    for (i = 0; i < def->nnets; i++) {
+        if (prlsdkAddNet(sdkdom, conn->privateData, def->nets[i], IS_CT(def)) < 0)
+           goto error;
+    }
+
+    if (prlsdkApplyGraphicsParams(sdkdom, def) < 0)
+        goto error;
+
+    if (prlsdkApplyVideoParams(sdkdom, def) < 0)
+        goto error;
+
+    for (i = 0; i < def->nserials; i++) {
+        if (prlsdkAddSerial(sdkdom, def->serials[i]) < 0)
+            goto error;
+    }
+
+    for (i = 0; i < def->nfss; i++) {
+        if (STREQ(def->fss[i]->dst, "/"))
+            needBoot = false;
+        if (prlsdkAddFS(sdkdom, def->fss[i]) < 0)
+            goto error;
+    }
+
+    for (i = 0; i < def->ndisks; i++) {
+        bool bootDisk = false;
+
+        if (needBoot == true &&
+            def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
+
+            needBoot = false;
+            bootDisk = true;
+        }
+        if (prlsdkAddDisk(sdkdom, def->disks[i], bootDisk, IS_CT(def)) < 0)
+            goto error;
+    }
+
+    return 0;
+
+ error:
+    VIR_FREE(mask);
+
+    for (i = 0; i < def->nnets; i++)
+        prlsdkDelNet(conn->privateData, def->nets[i]);
+
+   return -1;
+}
+
+int
+prlsdkApplyConfig(virConnectPtr conn,
+                  virDomainObjPtr dom,
+                  virDomainDefPtr new)
+{
+    vzConnPtr privconn = conn->privateData;
+    PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+    int ret;
+
+    sdkdom = prlsdkSdkDomainLookupByUUID(privconn, dom->def->uuid);
+    if (sdkdom == PRL_INVALID_HANDLE)
+        return -1;
+
+    job = PrlVm_BeginEdit(sdkdom);
+    if (PRL_FAILED(waitJob(job)))
+        return -1;
+
+    ret = prlsdkDoApplyConfig(conn, sdkdom, new, dom->def);
+
+    if (ret == 0) {
+        job = PrlVm_CommitEx(sdkdom, PVCF_DETACH_HDD_BUNDLE);
+        if (PRL_FAILED(waitJob(job)))
+            ret = -1;
+    }
+
+    PrlHandle_Free(sdkdom);
+
+    return ret;
+}
+
+int
+prlsdkCreateVm(virConnectPtr conn, virDomainDefPtr def)
+{
+    vzConnPtr privconn = conn->privateData;
+    PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+    PRL_HANDLE result = PRL_INVALID_HANDLE;
+    PRL_HANDLE srvconf = PRL_INVALID_HANDLE;
+    PRL_RESULT pret;
+    int ret = -1;
+
+    pret = PrlSrv_CreateVm(privconn->server, &sdkdom);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    job = PrlSrv_GetSrvConfig(privconn->server);
+    if (PRL_FAILED(getJobResult(job, &result)))
+        goto cleanup;
+
+    pret = PrlResult_GetParamByIndex(result, 0, &srvconf);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmCfg_SetDefaultConfig(sdkdom, srvconf, PVS_GUEST_VER_LIN_REDHAT, 0);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmCfg_SetOfflineManagementEnabled(sdkdom, 0);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    ret = prlsdkDoApplyConfig(conn, sdkdom, def, NULL);
+    if (ret)
+        goto cleanup;
+
+    job = PrlVm_Reg(sdkdom, "", 1);
+    if (PRL_FAILED(waitJob(job)))
+        ret = -1;
+
+ cleanup:
+    PrlHandle_Free(sdkdom);
+    return ret;
+}
+
+int
+prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def)
+{
+    vzConnPtr privconn = conn->privateData;
+    PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
+    PRL_GET_VM_CONFIG_PARAM_DATA confParam;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+    PRL_HANDLE result = PRL_INVALID_HANDLE;
+    PRL_RESULT pret;
+    int ret = -1;
+    int useTemplate = 0;
+    size_t i;
+
+    if (def->nfss > 1) {
+        /* Check all filesystems */
+        for (i = 0; i < def->nfss; i++) {
+            if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_FILE) {
+                virReportError(VIR_ERR_INVALID_ARG, "%s",
+                               _("Unsupported filesystem type."));
+                return -1;
+            }
+        }
+    } else if (def->nfss == 1) {
+        if (def->fss[0]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE) {
+            useTemplate = 1;
+        } else if (def->fss[0]->type != VIR_DOMAIN_FS_TYPE_FILE) {
+            virReportError(VIR_ERR_INVALID_ARG, "%s",
+                           _("Unsupported filesystem type."));
+            return -1;
+        }
+    }
+
+    confParam.nVmType = PVT_CT;
+    confParam.sConfigSample = "vswap.1024MB";
+    confParam.nOsVersion = 0;
+
+    job = PrlSrv_GetDefaultVmConfig(privconn->server, &confParam, 0);
+    if (PRL_FAILED(getJobResult(job, &result)))
+        goto cleanup;
+
+    pret = PrlResult_GetParamByIndex(result, 0, &sdkdom);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (useTemplate) {
+        pret = PrlVmCfg_SetOsTemplate(sdkdom, def->fss[0]->src);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+    }
+
+    ret = prlsdkDoApplyConfig(conn, sdkdom, def, NULL);
+    if (ret)
+        goto cleanup;
+
+    job = PrlVm_RegEx(sdkdom, "",
+                      PACF_NON_INTERACTIVE_MODE | PRNVM_PRESERVE_DISK);
+    if (PRL_FAILED(waitJob(job)))
+        ret = -1;
+
+ cleanup:
+    PrlHandle_Free(sdkdom);
+    return ret;
+}
+
+int
+prlsdkUnregisterDomain(vzConnPtr privconn, virDomainObjPtr dom)
+{
+    vzDomObjPtr privdom = dom->privateData;
+    PRL_HANDLE job;
+    size_t i;
+
+    for (i = 0; i < dom->def->nnets; i++)
+       prlsdkDelNet(privconn, dom->def->nets[i]);
+
+    job = PrlVm_Unreg(privdom->sdkdom);
+    if (PRL_FAILED(waitJob(job)))
+        return -1;
+
+    if (prlsdkSendEvent(privconn, dom, VIR_DOMAIN_EVENT_UNDEFINED,
+                        VIR_DOMAIN_EVENT_UNDEFINED_REMOVED) < 0)
+        return -1;
+
+    virDomainObjListRemove(privconn->domains, dom);
+    return 0;
+}
+
+int
+prlsdkDomainManagedSaveRemove(virDomainObjPtr dom)
+{
+    vzDomObjPtr privdom = dom->privateData;
+    PRL_HANDLE job;
+
+    job = PrlVm_DropSuspendedState(privdom->sdkdom);
+    if (PRL_FAILED(waitJob(job)))
+        return -1;
+
+    return 0;
+}
+
+static int
+prlsdkExtractStatsParam(PRL_HANDLE sdkstats, const char *name, long long *val)
+{
+    PRL_HANDLE param = PRL_INVALID_HANDLE;
+    PRL_RESULT pret;
+    PRL_INT64 pval = 0;
+    int ret = -1;
+
+    pret = PrlEvent_GetParamByName(sdkstats, name, &param);
+    if (pret == PRL_ERR_NO_DATA) {
+        *val = -1;
+        ret = 0;
+        goto cleanup;
+    } else if (PRL_FAILED(pret)) {
+        logPrlError(pret);
+        goto cleanup;
+    }
+    pret = PrlEvtPrm_ToInt64(param, &pval);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    *val = pval;
+    ret = 0;
+
+ cleanup:
+    PrlHandle_Free(param);
+    return ret;
+}
+
+#define PARALLELS_STATISTICS_TIMEOUT (60 * 1000)
+
+static int
+prlsdkGetStatsParam(virDomainObjPtr dom, const char *name, long long *val)
+{
+    vzDomObjPtr privdom = dom->privateData;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+    unsigned long long now;
+
+    if (privdom->cache.stats != PRL_INVALID_HANDLE) {
+        // reset count to keep subscribtion
+        privdom->cache.count = 0;
+        return prlsdkExtractStatsParam(privdom->cache.stats, name, val);
+    }
+
+    if (privdom->cache.count == -1) {
+        job = PrlVm_SubscribeToPerfStats(privdom->sdkdom, NULL);
+        if (PRL_FAILED(waitJob(job)))
+            goto error;
+    }
+
+    // change state to subscribed in case of unsubscribed
+    // or reset count so we stop unsubscribe attempts
+    privdom->cache.count = 0;
+
+    if (virTimeMillisNow(&now) < 0) {
+        virReportSystemError(errno, "%s", _("Unable to get current time"));
+        goto error;
+    }
+
+    while (privdom->cache.stats == PRL_INVALID_HANDLE) {
+        if (virCondWaitUntil(&privdom->cache.cond, &dom->parent.lock,
+                        now + PARALLELS_STATISTICS_TIMEOUT) < 0) {
+            if (errno == ETIMEDOUT) {
+                virReportError(VIR_ERR_OPERATION_TIMEOUT, "%s",
+                               _("Timeout on waiting statistics event."));
+                goto error;
+            } else {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("Unable to wait on monitor condition"));
+                goto error;
+            }
+        }
+    }
+
+    return prlsdkExtractStatsParam(privdom->cache.stats, name, val);
+ error:
+    return -1;
+}
+
+int
+prlsdkGetBlockStats(virDomainObjPtr dom, virDomainDiskDefPtr disk, virDomainBlockStatsPtr stats)
+{
+    virDomainDeviceDriveAddressPtr address;
+    int idx;
+    const char *prefix;
+    int ret = -1;
+    char *name = NULL;
+
+    address = &disk->info.addr.drive;
+    switch (disk->bus) {
+    case VIR_DOMAIN_DISK_BUS_IDE:
+        prefix = "ide";
+        idx = address->bus * 2 + address->unit;
+        break;
+    case VIR_DOMAIN_DISK_BUS_SATA:
+        prefix = "sata";
+        idx = address->unit;
+        break;
+    case VIR_DOMAIN_DISK_BUS_SCSI:
+        prefix = "scsi";
+        idx = address->unit;
+        break;
+    default:
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                   _("Unknown disk bus: %X"), disk->bus);
+        goto cleanup;
+    }
+
+
+#define PRLSDK_GET_STAT_PARAM(VAL, TYPE, NAME)                          \
+    if (virAsprintf(&name, "devices.%s%d.%s", prefix, idx, NAME) < 0)   \
+        goto cleanup;                                                   \
+    if (prlsdkGetStatsParam(dom, name, &stats->VAL) < 0)                \
+        goto cleanup;                                                   \
+    VIR_FREE(name);
+
+    PARALLELS_BLOCK_STATS_FOREACH(PRLSDK_GET_STAT_PARAM)
+
+#undef PRLSDK_GET_STAT_PARAM
+
+    ret = 0;
+
+ cleanup:
+
+    VIR_FREE(name);
+    return ret;
+}
diff --git a/src/vz/vz_sdk.h b/src/vz/vz_sdk.h
new file mode 100644 (file)
index 0000000..dd4fecf
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * vz_sdk.h: core driver functions for managing
+ * Parallels Cloud Server hosts
+ *
+ * Copyright (C) 2014 Parallels, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <Parallels.h>
+
+#include "vz_utils.h"
+
+int prlsdkInit(void);
+void prlsdkDeinit(void);
+int prlsdkConnect(vzConnPtr privconn);
+void prlsdkDisconnect(vzConnPtr privconn);
+int
+prlsdkLoadDomains(vzConnPtr privconn);
+virDomainObjPtr
+prlsdkAddDomain(vzConnPtr privconn, const unsigned char *uuid);
+int prlsdkUpdateDomain(vzConnPtr privconn, virDomainObjPtr dom);
+int prlsdkSubscribeToPCSEvents(vzConnPtr privconn);
+void prlsdkUnsubscribeFromPCSEvents(vzConnPtr privconn);
+PRL_RESULT prlsdkStart(PRL_HANDLE sdkdom);
+PRL_RESULT prlsdkKill(PRL_HANDLE sdkdom);
+PRL_RESULT prlsdkStop(PRL_HANDLE sdkdom);
+PRL_RESULT prlsdkPause(PRL_HANDLE sdkdom);
+PRL_RESULT prlsdkResume(PRL_HANDLE sdkdom);
+PRL_RESULT prlsdkSuspend(PRL_HANDLE sdkdom);
+
+typedef PRL_RESULT (*prlsdkChangeStateFunc)(PRL_HANDLE sdkdom);
+int
+prlsdkDomainChangeState(virDomainPtr domain,
+                        prlsdkChangeStateFunc chstate);
+int
+prlsdkDomainChangeStateLocked(vzConnPtr privconn,
+                              virDomainObjPtr dom,
+                              prlsdkChangeStateFunc chstate);
+int
+prlsdkApplyConfig(virConnectPtr conn,
+                  virDomainObjPtr dom,
+                  virDomainDefPtr new);
+int prlsdkCreateVm(virConnectPtr conn, virDomainDefPtr def);
+int prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def);
+int
+prlsdkUnregisterDomain(vzConnPtr privconn, virDomainObjPtr dom);
+int
+prlsdkDomainManagedSaveRemove(virDomainObjPtr dom);
+int
+prlsdkAttachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk);
+int
+prlsdkDetachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk);
+int
+prlsdkGetBlockStats(virDomainObjPtr dom, virDomainDiskDefPtr disk, virDomainBlockStatsPtr stats);
diff --git a/src/vz/vz_storage.c b/src/vz/vz_storage.c
new file mode 100644 (file)
index 0000000..7183db4
--- /dev/null
@@ -0,0 +1,1654 @@
+/*
+ * vz_storage.c: core driver functions for managing
+ * Parallels Cloud Server hosts
+ *
+ * Copyright (C) 2013-2014 Red Hat, Inc.
+ * Copyright (C) 2012 Parallels, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <dirent.h>
+#include <sys/statvfs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "datatypes.h"
+#include "dirname.h"
+#include "viralloc.h"
+#include "configmake.h"
+#include "virstoragefile.h"
+#include "virerror.h"
+#include "virfile.h"
+#include "vz_utils.h"
+#include "virstring.h"
+
+#define VIR_FROM_THIS VIR_FROM_PARALLELS
+
+#define vzPoolNotFoundError(pool_name)                    \
+    virReportError(VIR_ERR_INVALID_ARG,                          \
+                   _("pool '%s' not found"), pool_name);
+
+static virStorageVolDefPtr
+vzStorageVolDefineXML(virStoragePoolObjPtr pool, const char *xmldesc,
+                             const char *xmlfile, bool is_new);
+static virStorageVolPtr
+vzStorageVolLookupByPath(virConnectPtr conn, const char *path);
+
+static int
+vzStoragePoolGetAlloc(virStoragePoolDefPtr def);
+
+static void
+vzStorageLock(virStorageDriverStatePtr driver)
+{
+    virMutexLock(&driver->lock);
+}
+
+static void
+vzStorageUnlock(virStorageDriverStatePtr driver)
+{
+    virMutexUnlock(&driver->lock);
+}
+
+int
+vzStorageClose(virConnectPtr conn)
+{
+    vzConnPtr privconn = conn->privateData;
+
+    if (!privconn)
+        return 0;
+
+    virStorageDriverStatePtr storageState = privconn->storageState;
+    privconn->storageState = NULL;
+
+    if (!storageState)
+        return 0;
+
+    vzStorageLock(storageState);
+    virStoragePoolObjListFree(&privconn->pools);
+    VIR_FREE(storageState->configDir);
+    VIR_FREE(storageState->autostartDir);
+    vzStorageUnlock(storageState);
+    virMutexDestroy(&storageState->lock);
+    VIR_FREE(storageState);
+
+    return 0;
+}
+
+static int
+vzFindVolumes(virStoragePoolObjPtr pool)
+{
+    DIR *dir;
+    struct dirent *ent;
+    char *path = NULL;
+    int ret = -1;
+    int direrr;
+
+    if (!(dir = opendir(pool->def->target.path))) {
+        virReportSystemError(errno,
+                             _("cannot open path '%s'"),
+                             pool->def->target.path);
+        return -1;
+    }
+
+    while ((direrr = virDirRead(dir, &ent, pool->def->target.path)) > 0) {
+        if (!virFileHasSuffix(ent->d_name, ".xml"))
+            continue;
+
+        if (!(path = virFileBuildPath(pool->def->target.path,
+                                      ent->d_name, NULL)))
+            goto cleanup;
+        if (!vzStorageVolDefineXML(pool, NULL, path, false))
+            goto cleanup;
+
+        VIR_FREE(path);
+    }
+    if (direrr < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(path);
+    closedir(dir);
+    return ret;
+
+}
+
+/*
+ * Generate unique pool name by path
+ */
+static char *vzMakePoolName(virConnectPtr conn, const char *path)
+{
+    vzConnPtr privconn = conn->privateData;
+    char *name;
+    size_t i;
+
+    for (i = 0; i < UINT_MAX; i++) {
+        bool found = false;
+        size_t j;
+
+        if ((!i && VIR_STRDUP(name, path) < 0) ||
+            (i && virAsprintf(&name, "%s-%zu", path, i) < 0))
+            return NULL;
+
+        for (j = 0; j < strlen(name); j++)
+            if (name[j] == '/')
+                name[j] = '-';
+
+        for (j = 0; j < privconn->pools.count; j++) {
+            if (STREQ(name, privconn->pools.objs[j]->def->name)) {
+                found = true;
+                break;
+            }
+        }
+
+        if (!found)
+            return name;
+
+        VIR_FREE(name);
+    }
+
+    return NULL;
+}
+
+static virStoragePoolObjPtr
+vzPoolCreateByPath(virConnectPtr conn, const char *path)
+{
+    vzConnPtr privconn = conn->privateData;
+    virStoragePoolObjListPtr pools = &privconn->pools;
+    virStoragePoolDefPtr def;
+    virStoragePoolObjPtr pool = NULL;
+
+    if (VIR_ALLOC(def) < 0)
+        goto error;
+
+    if (!(def->name = vzMakePoolName(conn, path)))
+        goto error;
+
+    if (virUUIDGenerate(def->uuid)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Can't generate UUID"));
+        goto error;
+    }
+
+    def->type = VIR_STORAGE_POOL_DIR;
+    if (VIR_STRDUP(def->target.path, path) < 0)
+        goto error;
+
+    if (!(pool = virStoragePoolObjAssignDef(pools, def)))
+        goto error;
+
+    if (virStoragePoolObjSaveDef(privconn->storageState, pool, def) < 0) {
+        virStoragePoolObjRemove(pools, pool);
+        goto error;
+    }
+
+    virStoragePoolObjUnlock(pool);
+
+    return pool;
+ error:
+    virStoragePoolDefFree(def);
+    if (pool)
+        virStoragePoolObjUnlock(pool);
+    return NULL;
+}
+
+/*
+ * Create pool of type VIR_STORAGE_POOL_DIR with
+ * path to the VM, if it does not exist.
+ */
+static virStoragePoolObjPtr
+vzPoolAddByDomain(virConnectPtr conn, virDomainObjPtr dom)
+{
+    vzConnPtr privconn = conn->privateData;
+    vzDomObjPtr pdom = dom->privateData;
+    virStoragePoolObjListPtr pools = &privconn->pools;
+    char *poolPath;
+    virStoragePoolObjPtr pool = NULL;
+    size_t j;
+
+    poolPath = mdir_name(pdom->home);
+    if (!poolPath) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    for (j = 0; j < pools->count; j++) {
+        if (STREQ(poolPath, pools->objs[j]->def->target.path)) {
+            pool = pools->objs[j];
+            break;
+        }
+    }
+
+    if (!pool)
+        pool = vzPoolCreateByPath(conn, poolPath);
+
+    VIR_FREE(poolPath);
+    return pool;
+}
+
+static int vzDiskDescParseNode(xmlDocPtr xml,
+                                      xmlNodePtr root,
+                                      virStorageVolDefPtr def)
+{
+    xmlXPathContextPtr ctxt = NULL;
+    int ret = -1;
+
+    if (STRNEQ((const char *)root->name, "Parallels_disk_image")) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       "%s", _("unknown root element for storage pool"));
+        goto cleanup;
+    }
+
+    ctxt = xmlXPathNewContext(xml);
+    if (ctxt == NULL) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    ctxt->node = root;
+
+    if (virXPathULongLong("string(./Disk_Parameters/Disk_size)",
+                          ctxt, &def->target.capacity) < 0) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       "%s", _("failed to get disk size from "
+                               "the disk descriptor xml"));
+        goto cleanup;
+    }
+
+    def->target.capacity <<= 9;
+    def->target.allocation = def->target.capacity;
+    ret = 0;
+ cleanup:
+    xmlXPathFreeContext(ctxt);
+    return ret;
+
+}
+
+static int vzDiskDescParse(const char *path, virStorageVolDefPtr def)
+{
+    xmlDocPtr xml;
+    int ret = -1;
+
+    if (!(xml = virXMLParse(path, NULL, NULL)))
+        return -1;
+
+    ret = vzDiskDescParseNode(xml, xmlDocGetRootElement(xml), def);
+    xmlFreeDoc(xml);
+    return ret;
+}
+
+static int vzAddDiskVolume(virStoragePoolObjPtr pool,
+                                  virDomainObjPtr dom,
+                                  const char *diskName,
+                                  const char *diskPath,
+                                  const char *diskDescPath)
+{
+    virStorageVolDefPtr def = NULL;
+
+    if (VIR_ALLOC(def))
+        goto error;
+
+    if (virAsprintf(&def->name, "%s-%s", dom->def->name, diskName) < 0)
+        goto error;
+
+    def->type = VIR_STORAGE_VOL_FILE;
+
+    if (vzDiskDescParse(diskDescPath, def) < 0)
+        goto error;
+
+    if (!(def->target.path = realpath(diskPath, NULL)))
+        goto no_memory;
+
+    if (VIR_STRDUP(def->key, def->target.path) < 0)
+        goto error;
+
+    if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, def) < 0)
+        goto error;
+
+    return 0;
+ no_memory:
+    virReportOOMError();
+ error:
+    virStorageVolDefFree(def);
+    return -1;
+}
+
+static int vzFindVmVolumes(virStoragePoolObjPtr pool,
+                                  virDomainObjPtr dom)
+{
+    vzDomObjPtr pdom = dom->privateData;
+    DIR *dir;
+    struct dirent *ent;
+    char *diskPath = NULL, *diskDescPath = NULL;
+    struct stat sb;
+    int ret = -1;
+    int direrr;
+
+    if (!(dir = opendir(pdom->home))) {
+        virReportSystemError(errno,
+                             _("cannot open path '%s'"),
+                             pdom->home);
+        return ret;
+    }
+
+    while ((direrr = virDirRead(dir, &ent, pdom->home)) > 0) {
+        VIR_FREE(diskPath);
+        VIR_FREE(diskDescPath);
+
+        if (!(diskPath = virFileBuildPath(pdom->home, ent->d_name, NULL)))
+            goto cleanup;
+
+        if (lstat(diskPath, &sb) < 0) {
+            virReportSystemError(errno,
+                                 _("cannot stat path '%s'"),
+                                 ent->d_name);
+            goto cleanup;
+        }
+
+        if (!S_ISDIR(sb.st_mode))
+            continue;
+
+        if (!(diskDescPath = virFileBuildPath(diskPath,
+                                              "DiskDescriptor", ".xml")))
+            goto cleanup;
+
+        if (!virFileExists(diskDescPath))
+            continue;
+
+        /* here we know, that ent->d_name is a disk image directory */
+
+        if (vzAddDiskVolume(pool, dom, ent->d_name,
+                                   diskPath, diskDescPath))
+            goto cleanup;
+    }
+    if (direrr < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(diskPath);
+    VIR_FREE(diskDescPath);
+    closedir(dir);
+    return ret;
+
+}
+
+static int
+vzPoolsAdd(virDomainObjPtr dom,
+                  void *opaque)
+{
+    virConnectPtr conn = opaque;
+    virStoragePoolObjPtr pool;
+
+    if (!(pool = vzPoolAddByDomain(conn, dom)))
+        return -1;
+
+    if (vzFindVmVolumes(pool, dom))
+        return -1;
+
+    return 0;
+}
+
+static int vzLoadPools(virConnectPtr conn)
+{
+    vzConnPtr privconn = conn->privateData;
+    virStorageDriverStatePtr storageState = privconn->storageState;
+    char *base = NULL;
+    size_t i;
+
+    if (VIR_STRDUP(base, SYSCONFDIR "/libvirt") < 0)
+        goto error;
+
+    /* Configuration path is /etc/libvirt/parallels-storage/... . */
+    if (virAsprintf(&storageState->configDir,
+                    "%s/parallels-storage", base) == -1)
+        goto error;
+
+    if (virAsprintf(&storageState->autostartDir,
+                    "%s/parallels-storage/autostart", base) == -1)
+        goto error;
+
+    VIR_FREE(base);
+
+    if (virStoragePoolLoadAllConfigs(&privconn->pools,
+                                     storageState->configDir,
+                                     storageState->autostartDir) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Failed to load pool configs"));
+        goto error;
+    }
+
+    if (virDomainObjListForEach(privconn->domains, vzPoolsAdd, conn) < 0)
+        goto error;
+
+    for (i = 0; i < privconn->pools.count; i++) {
+        virStoragePoolObjLock(privconn->pools.objs[i]);
+        virStoragePoolObjPtr pool;
+
+        pool = privconn->pools.objs[i];
+        pool->active = 1;
+
+        if (vzStoragePoolGetAlloc(pool->def) < 0)
+            goto error;
+
+        if (vzFindVolumes(pool) < 0)
+            goto error;
+
+        virStoragePoolObjUnlock(privconn->pools.objs[i]);
+    }
+
+    return 0;
+
+ error:
+    VIR_FREE(base);
+    return -1;
+}
+
+virDrvOpenStatus
+vzStorageOpen(virConnectPtr conn,
+                     unsigned int flags)
+{
+    vzConnPtr privconn = conn->privateData;
+    virStorageDriverStatePtr storageState;
+    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
+
+    if (STRNEQ(conn->driver->name, "vz") &&
+        STRNEQ(conn->driver->name, "Parallels"))
+        return VIR_DRV_OPEN_DECLINED;
+
+    if (VIR_ALLOC(storageState) < 0)
+        return VIR_DRV_OPEN_ERROR;
+
+    if (virMutexInit(&storageState->lock) < 0) {
+        VIR_FREE(storageState);
+        return VIR_DRV_OPEN_ERROR;
+    }
+
+    privconn->storageState = storageState;
+    vzStorageLock(storageState);
+
+    if (vzLoadPools(conn))
+        goto error;
+
+    vzStorageUnlock(storageState);
+
+    return VIR_DRV_OPEN_SUCCESS;
+
+ error:
+    vzStorageUnlock(storageState);
+    vzStorageClose(conn);
+    return VIR_DRV_OPEN_ERROR;
+}
+
+static int
+vzConnectNumOfStoragePools(virConnectPtr conn)
+{
+    vzConnPtr privconn = conn->privateData;
+    int numActive = 0;
+    size_t i;
+
+    vzDriverLock(privconn);
+    for (i = 0; i < privconn->pools.count; i++)
+        if (virStoragePoolObjIsActive(privconn->pools.objs[i]))
+            numActive++;
+    vzDriverUnlock(privconn);
+
+    return numActive;
+}
+
+static int
+vzConnectListStoragePools(virConnectPtr conn, char **const names, int nnames)
+{
+    vzConnPtr privconn = conn->privateData;
+    int n = 0;
+    size_t i;
+
+    vzDriverLock(privconn);
+    memset(names, 0, sizeof(*names) * nnames);
+    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
+        virStoragePoolObjLock(privconn->pools.objs[i]);
+        if (virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
+            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
+            virStoragePoolObjUnlock(privconn->pools.objs[i]);
+            goto error;
+        }
+        virStoragePoolObjUnlock(privconn->pools.objs[i]);
+    }
+    vzDriverUnlock(privconn);
+
+    return n;
+
+ error:
+    for (n = 0; n < nnames; n++)
+        VIR_FREE(names[n]);
+    vzDriverUnlock(privconn);
+    return -1;
+}
+
+static int
+vzConnectNumOfDefinedStoragePools(virConnectPtr conn)
+{
+    vzConnPtr privconn = conn->privateData;
+    int numInactive = 0;
+    size_t i;
+
+    vzDriverLock(privconn);
+    for (i = 0; i < privconn->pools.count; i++) {
+        virStoragePoolObjLock(privconn->pools.objs[i]);
+        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]))
+            numInactive++;
+        virStoragePoolObjUnlock(privconn->pools.objs[i]);
+    }
+    vzDriverUnlock(privconn);
+
+    return numInactive;
+}
+
+static int
+vzConnectListDefinedStoragePools(virConnectPtr conn,
+                                        char **const names, int nnames)
+{
+    vzConnPtr privconn = conn->privateData;
+    int n = 0;
+    size_t i;
+
+    vzDriverLock(privconn);
+    memset(names, 0, sizeof(*names) * nnames);
+    for (i = 0; i < privconn->pools.count && n < nnames; i++) {
+        virStoragePoolObjLock(privconn->pools.objs[i]);
+        if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) &&
+            VIR_STRDUP(names[n++], privconn->pools.objs[i]->def->name) < 0) {
+            virStoragePoolObjUnlock(privconn->pools.objs[i]);
+            goto error;
+        }
+        virStoragePoolObjUnlock(privconn->pools.objs[i]);
+    }
+    vzDriverUnlock(privconn);
+
+    return n;
+
+ error:
+    for (n = 0; n < nnames; n++)
+        VIR_FREE(names[n]);
+    vzDriverUnlock(privconn);
+    return -1;
+}
+
+
+static int
+vzStoragePoolIsActive(virStoragePoolPtr pool)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr obj;
+    int ret = -1;
+
+    vzDriverLock(privconn);
+    obj = virStoragePoolObjFindByUUID(&privconn->pools, pool->uuid);
+    vzDriverUnlock(privconn);
+    if (!obj) {
+        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
+        goto cleanup;
+    }
+    ret = virStoragePoolObjIsActive(obj);
+
+ cleanup:
+    if (obj)
+        virStoragePoolObjUnlock(obj);
+    return ret;
+}
+
+static int
+vzStoragePoolIsPersistent(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
+{
+    return 1;
+}
+
+static virStoragePoolPtr
+vzStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+{
+    vzConnPtr privconn = conn->privateData;
+    virStoragePoolObjPtr pool;
+    virStoragePoolPtr ret = NULL;
+
+    vzDriverLock(privconn);
+    pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid);
+    vzDriverUnlock(privconn);
+
+    if (pool == NULL) {
+        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
+        goto cleanup;
+    }
+
+    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+                            NULL, NULL);
+
+ cleanup:
+    if (pool)
+        virStoragePoolObjUnlock(pool);
+    return ret;
+}
+
+static virStoragePoolPtr
+vzStoragePoolLookupByName(virConnectPtr conn, const char *name)
+{
+    vzConnPtr privconn = conn->privateData;
+    virStoragePoolObjPtr pool;
+    virStoragePoolPtr ret = NULL;
+
+    vzDriverLock(privconn);
+    pool = virStoragePoolObjFindByName(&privconn->pools, name);
+    vzDriverUnlock(privconn);
+
+    if (pool == NULL) {
+        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
+        goto cleanup;
+    }
+
+    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+                            NULL, NULL);
+
+ cleanup:
+    if (pool)
+        virStoragePoolObjUnlock(pool);
+    return ret;
+}
+
+static virStoragePoolPtr
+vzStoragePoolLookupByVolume(virStorageVolPtr vol)
+{
+    return vzStoragePoolLookupByName(vol->conn, vol->pool);
+}
+
+/*
+ * Fill capacity, available and allocation
+ * fields in pool definition.
+ */
+static int
+vzStoragePoolGetAlloc(virStoragePoolDefPtr def)
+{
+    struct statvfs sb;
+
+    if (statvfs(def->target.path, &sb) < 0) {
+        virReportSystemError(errno,
+                             _("cannot statvfs path '%s'"),
+                             def->target.path);
+        return -1;
+    }
+
+    def->capacity = ((unsigned long long)sb.f_frsize *
+                     (unsigned long long)sb.f_blocks);
+    def->available = ((unsigned long long)sb.f_bfree *
+                      (unsigned long long)sb.f_frsize);
+    def->allocation = def->capacity - def->available;
+
+    return 0;
+}
+
+static virStoragePoolPtr
+vzStoragePoolDefineXML(virConnectPtr conn,
+                              const char *xml, unsigned int flags)
+{
+    vzConnPtr privconn = conn->privateData;
+    virStoragePoolDefPtr def;
+    virStoragePoolObjPtr pool = NULL;
+    virStoragePoolPtr ret = NULL;
+
+    virCheckFlags(0, NULL);
+
+    vzDriverLock(privconn);
+    if (!(def = virStoragePoolDefParseString(xml)))
+        goto cleanup;
+
+    if (def->type != VIR_STORAGE_POOL_DIR) {
+        virReportError(VIR_ERR_NO_SUPPORT, "%s",
+                       _("Only local directories are supported"));
+        goto cleanup;
+    }
+
+    if (virStoragePoolObjIsDuplicate(&privconn->pools, def, 0) < 0)
+        goto cleanup;
+
+    if (virStoragePoolSourceFindDuplicate(conn, &privconn->pools, def) < 0)
+        goto cleanup;
+
+    if (vzStoragePoolGetAlloc(def))
+        goto cleanup;
+
+    if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
+        goto cleanup;
+
+    if (virStoragePoolObjSaveDef(privconn->storageState, pool, def) < 0) {
+        virStoragePoolObjRemove(&privconn->pools, pool);
+        def = NULL;
+        goto cleanup;
+    }
+    def = NULL;
+
+    if (VIR_STRDUP(pool->configFile, "\0") < 0)
+        goto cleanup;
+
+    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+                            NULL, NULL);
+
+ cleanup:
+    virStoragePoolDefFree(def);
+    if (pool)
+        virStoragePoolObjUnlock(pool);
+    vzDriverUnlock(privconn);
+    return ret;
+}
+
+static int
+vzStoragePoolUndefine(virStoragePoolPtr pool)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    int ret = -1;
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto cleanup;
+    }
+
+    if (virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("storage pool '%s' is still active"), pool->name);
+        goto cleanup;
+    }
+
+    if (virStoragePoolObjDeleteDef(privpool) < 0)
+        goto cleanup;
+
+    VIR_FREE(privpool->configFile);
+
+    virStoragePoolObjRemove(&privconn->pools, privpool);
+    ret = 0;
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    vzDriverUnlock(privconn);
+    return ret;
+}
+
+static int
+vzStoragePoolCreate(virStoragePoolPtr pool, unsigned int flags)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    int ret = -1;
+
+    virCheckFlags(0, -1);
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto cleanup;
+    }
+
+    if (virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("storage pool '%s' is already active"), pool->name);
+        goto cleanup;
+    }
+
+    privpool->active = 1;
+    ret = 0;
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+static int
+vzStoragePoolDestroy(virStoragePoolPtr pool)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    int ret = -1;
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto cleanup;
+    }
+
+    if (!virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("storage pool '%s' is not active"), pool->name);
+        goto cleanup;
+    }
+
+    if (privpool->configFile == NULL) {
+        virStoragePoolObjRemove(&privconn->pools, privpool);
+        privpool = NULL;
+    }
+    ret = 0;
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    vzDriverUnlock(privconn);
+    return ret;
+}
+
+static int
+vzStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    int ret = -1;
+
+    virCheckFlags(0, -1);
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto cleanup;
+    }
+
+    if (!virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("storage pool '%s' is not active"), pool->name);
+        goto cleanup;
+    }
+    ret = 0;
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+
+static int
+vzStoragePoolGetInfo(virStoragePoolPtr pool, virStoragePoolInfoPtr info)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    int ret = -1;
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto cleanup;
+    }
+
+    memset(info, 0, sizeof(virStoragePoolInfo));
+    if (privpool->active)
+        info->state = VIR_STORAGE_POOL_RUNNING;
+    else
+        info->state = VIR_STORAGE_POOL_INACTIVE;
+    info->capacity = privpool->def->capacity;
+    info->allocation = privpool->def->allocation;
+    info->available = privpool->def->available;
+    ret = 0;
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+static char *
+vzStoragePoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    char *ret = NULL;
+
+    virCheckFlags(0, NULL);
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto cleanup;
+    }
+
+    ret = virStoragePoolDefFormat(privpool->def);
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+static int
+vzStoragePoolGetAutostart(virStoragePoolPtr pool, int *autostart)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    int ret = -1;
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto cleanup;
+    }
+
+    if (!privpool->configFile) {
+        *autostart = 0;
+    } else {
+        *autostart = privpool->autostart;
+    }
+    ret = 0;
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+static int
+vzStoragePoolSetAutostart(virStoragePoolPtr pool, int autostart)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    int ret = -1;
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto cleanup;
+    }
+
+    if (!privpool->configFile) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s", _("pool has no config file"));
+        goto cleanup;
+    }
+
+    privpool->autostart = (autostart != 0);
+    ret = 0;
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+static int
+vzStoragePoolNumOfVolumes(virStoragePoolPtr pool)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    int ret = -1;
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto cleanup;
+    }
+
+    if (!virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("storage pool '%s' is not active"), pool->name);
+        goto cleanup;
+    }
+
+    ret = privpool->volumes.count;
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+static int
+vzStoragePoolListVolumes(virStoragePoolPtr pool,
+                                char **const names, int maxnames)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    int n = 0;
+    size_t i = 0;
+
+    memset(names, 0, maxnames * sizeof(*names));
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto error;
+    }
+
+
+    if (!virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                 _("storage pool '%s' is not active"), pool->name);
+        goto error;
+    }
+
+    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
+        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
+            goto error;
+    }
+
+    virStoragePoolObjUnlock(privpool);
+    return n;
+
+ error:
+    for (n = 0; n < maxnames; n++)
+        VIR_FREE(names[i]);
+
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return -1;
+}
+
+static virStorageVolPtr
+vzStorageVolLookupByName(virStoragePoolPtr pool,
+                                   const char *name)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    virStorageVolDefPtr privvol;
+    virStorageVolPtr ret = NULL;
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto cleanup;
+    }
+
+
+    if (!virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("storage pool '%s' is not active"), pool->name);
+        goto cleanup;
+    }
+
+    privvol = virStorageVolDefFindByName(privpool, name);
+
+    if (!privvol) {
+        virReportError(VIR_ERR_NO_STORAGE_VOL,
+                       _("no storage vol with matching name '%s'"), name);
+        goto cleanup;
+    }
+
+    ret = virGetStorageVol(pool->conn, privpool->def->name,
+                           privvol->name, privvol->key,
+                           NULL, NULL);
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+
+static virStorageVolPtr
+vzStorageVolLookupByKey(virConnectPtr conn, const char *key)
+{
+    vzConnPtr privconn = conn->privateData;
+    size_t i;
+    virStorageVolPtr ret = NULL;
+
+    vzDriverLock(privconn);
+    for (i = 0; i < privconn->pools.count; i++) {
+        virStoragePoolObjLock(privconn->pools.objs[i]);
+        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
+            virStorageVolDefPtr privvol =
+                virStorageVolDefFindByKey(privconn->pools.objs[i], key);
+
+            if (privvol) {
+                ret = virGetStorageVol(conn,
+                                       privconn->pools.objs[i]->def->name,
+                                       privvol->name, privvol->key,
+                                       NULL, NULL);
+                virStoragePoolObjUnlock(privconn->pools.objs[i]);
+                break;
+            }
+        }
+        virStoragePoolObjUnlock(privconn->pools.objs[i]);
+    }
+    vzDriverUnlock(privconn);
+
+    if (!ret)
+        virReportError(VIR_ERR_NO_STORAGE_VOL,
+                       _("no storage vol with matching key '%s'"), key);
+
+    return ret;
+}
+
+virStorageVolPtr
+vzStorageVolLookupByPathLocked(virConnectPtr conn, const char *path)
+{
+    vzConnPtr privconn = conn->privateData;
+    size_t i;
+    virStorageVolPtr ret = NULL;
+
+    for (i = 0; i < privconn->pools.count; i++) {
+        virStoragePoolObjLock(privconn->pools.objs[i]);
+        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
+            virStorageVolDefPtr privvol =
+                virStorageVolDefFindByPath(privconn->pools.objs[i], path);
+
+            if (privvol) {
+                ret = virGetStorageVol(conn,
+                                       privconn->pools.objs[i]->def->name,
+                                       privvol->name, privvol->key,
+                                       NULL, NULL);
+                virStoragePoolObjUnlock(privconn->pools.objs[i]);
+                break;
+            }
+        }
+        virStoragePoolObjUnlock(privconn->pools.objs[i]);
+    }
+
+    if (!ret)
+        virReportError(VIR_ERR_NO_STORAGE_VOL,
+                       _("no storage vol with matching path '%s'"), path);
+
+    return ret;
+}
+
+static virStorageVolPtr
+vzStorageVolLookupByPath(virConnectPtr conn, const char *path)
+{
+    vzConnPtr privconn = conn->privateData;
+    virStorageVolPtr ret = NULL;
+
+    vzDriverLock(privconn);
+    ret = vzStorageVolLookupByPathLocked(conn, path);
+    vzDriverUnlock(privconn);
+
+    return ret;
+}
+
+static virStorageVolDefPtr
+vzStorageVolDefineXML(virStoragePoolObjPtr pool,
+                             const char *xmldesc,
+                             const char *xmlfile, bool is_new)
+{
+    virStorageVolDefPtr privvol = NULL;
+    virStorageVolDefPtr ret = NULL;
+    char *xml_path = NULL;
+
+    if (xmlfile)
+        privvol = virStorageVolDefParseFile(pool->def, xmlfile, 0);
+    else
+        privvol = virStorageVolDefParseString(pool->def, xmldesc, 0);
+
+    if (privvol == NULL)
+        goto cleanup;
+
+    if (virStorageVolDefFindByName(pool, privvol->name)) {
+        virReportError(VIR_ERR_OPERATION_FAILED,
+                       "%s", _("storage vol already exists"));
+        goto cleanup;
+    }
+
+    if (is_new) {
+        /* Make sure enough space */
+        if ((pool->def->allocation + privvol->target.allocation) >
+            pool->def->capacity) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Not enough free space in pool for volume '%s'"),
+                           privvol->name);
+            goto cleanup;
+        }
+    }
+
+    if (virAsprintf(&privvol->target.path, "%s/%s",
+                    pool->def->target.path, privvol->name) < 0)
+        goto cleanup;
+
+    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0)
+        goto cleanup;
+
+    if (is_new) {
+        xml_path = vzAddFileExt(privvol->target.path, ".xml");
+        if (!xml_path)
+            goto cleanup;
+
+        if (virXMLSaveFile(xml_path, NULL, "volume-create", xmldesc)) {
+            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                           _("Can't create file with volume description"));
+            goto cleanup;
+        }
+
+        pool->def->allocation += privvol->target.allocation;
+        pool->def->available = (pool->def->capacity -
+                                pool->def->allocation);
+    }
+
+    if (VIR_APPEND_ELEMENT_COPY(pool->volumes.objs,
+                                pool->volumes.count, privvol) < 0)
+        goto cleanup;
+
+    ret = privvol;
+    privvol = NULL;
+
+ cleanup:
+    virStorageVolDefFree(privvol);
+    VIR_FREE(xml_path);
+    return ret;
+}
+
+static virStorageVolPtr
+vzStorageVolCreateXML(virStoragePoolPtr pool,
+                                const char *xmldesc, unsigned int flags)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    virStorageVolPtr ret = NULL;
+    virStorageVolDefPtr privvol = NULL;
+
+    virCheckFlags(0, NULL);
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto cleanup;
+    }
+
+    if (!virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("storage pool '%s' is not active"), pool->name);
+        goto cleanup;
+    }
+
+    privvol = vzStorageVolDefineXML(privpool, xmldesc, NULL, true);
+    if (!privvol)
+        goto cleanup;
+
+    ret = virGetStorageVol(pool->conn, privpool->def->name,
+                           privvol->name, privvol->key,
+                           NULL, NULL);
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+static virStorageVolPtr
+vzStorageVolCreateXMLFrom(virStoragePoolPtr pool,
+                                    const char *xmldesc,
+                                    virStorageVolPtr clonevol,
+                                    unsigned int flags)
+{
+    vzConnPtr privconn = pool->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    virStorageVolDefPtr privvol = NULL, origvol = NULL;
+    virStorageVolPtr ret = NULL;
+
+    virCheckFlags(0, NULL);
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(pool->name);
+        goto cleanup;
+    }
+
+    if (!virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("storage pool '%s' is not active"), pool->name);
+        goto cleanup;
+    }
+
+    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
+    if (privvol == NULL)
+        goto cleanup;
+
+    if (virStorageVolDefFindByName(privpool, privvol->name)) {
+        virReportError(VIR_ERR_OPERATION_FAILED,
+                       "%s", _("storage vol already exists"));
+        goto cleanup;
+    }
+
+    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
+    if (!origvol) {
+        virReportError(VIR_ERR_NO_STORAGE_VOL,
+                       _("no storage vol with matching name '%s'"),
+                       clonevol->name);
+        goto cleanup;
+    }
+
+    /* Make sure enough space */
+    if ((privpool->def->allocation + privvol->target.allocation) >
+        privpool->def->capacity) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Not enough free space in pool for volume '%s'"),
+                       privvol->name);
+        goto cleanup;
+    }
+    privpool->def->available = (privpool->def->capacity -
+                                privpool->def->allocation);
+
+    if (virAsprintf(&privvol->target.path, "%s/%s",
+                    privpool->def->target.path, privvol->name) == -1)
+        goto cleanup;
+
+    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0)
+        goto cleanup;
+
+    privpool->def->allocation += privvol->target.allocation;
+    privpool->def->available = (privpool->def->capacity -
+                                privpool->def->allocation);
+
+    if (VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
+                                privpool->volumes.count, privvol) < 0)
+        goto cleanup;
+
+    ret = virGetStorageVol(pool->conn, privpool->def->name,
+                           privvol->name, privvol->key,
+                           NULL, NULL);
+    privvol = NULL;
+
+ cleanup:
+    virStorageVolDefFree(privvol);
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+int vzStorageVolDefRemove(virStoragePoolObjPtr privpool,
+                                    virStorageVolDefPtr privvol)
+{
+    int ret = -1;
+    char *xml_path = NULL;
+    size_t i;
+
+    privpool->def->allocation -= privvol->target.allocation;
+    privpool->def->available = (privpool->def->capacity -
+                                privpool->def->allocation);
+
+    for (i = 0; i < privpool->volumes.count; i++) {
+        if (privpool->volumes.objs[i] == privvol) {
+            xml_path = vzAddFileExt(privvol->target.path, ".xml");
+            if (!xml_path)
+                goto cleanup;
+
+            if (unlink(xml_path)) {
+                virReportError(VIR_ERR_OPERATION_FAILED,
+                               _("Can't remove file '%s'"), xml_path);
+                goto cleanup;
+            }
+
+            virStorageVolDefFree(privvol);
+
+            VIR_DELETE_ELEMENT(privpool->volumes.objs, i, privpool->volumes.count);
+            break;
+        }
+    }
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(xml_path);
+    return ret;
+}
+
+static int
+vzStorageVolDelete(virStorageVolPtr vol, unsigned int flags)
+{
+    vzConnPtr privconn = vol->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    virStorageVolDefPtr privvol;
+    int ret = -1;
+
+    virCheckFlags(0, -1);
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(vol->pool);
+        goto cleanup;
+    }
+
+
+    privvol = virStorageVolDefFindByName(privpool, vol->name);
+
+    if (privvol == NULL) {
+        virReportError(VIR_ERR_NO_STORAGE_VOL,
+                       _("no storage vol with matching name '%s'"), vol->name);
+        goto cleanup;
+    }
+
+    if (!virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("storage pool '%s' is not active"), vol->pool);
+        goto cleanup;
+    }
+
+
+    if (vzStorageVolDefRemove(privpool, privvol))
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+
+static int
+vzStorageVolTypeForPool(int pooltype)
+{
+
+    switch (pooltype) {
+        case VIR_STORAGE_POOL_DIR:
+        case VIR_STORAGE_POOL_FS:
+        case VIR_STORAGE_POOL_NETFS:
+            return VIR_STORAGE_VOL_FILE;
+ default:
+            return VIR_STORAGE_VOL_BLOCK;
+    }
+}
+
+static int
+vzStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr info)
+{
+    vzConnPtr privconn = vol->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    virStorageVolDefPtr privvol;
+    int ret = -1;
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(vol->pool);
+        goto cleanup;
+    }
+
+    privvol = virStorageVolDefFindByName(privpool, vol->name);
+
+    if (privvol == NULL) {
+        virReportError(VIR_ERR_NO_STORAGE_VOL,
+                       _("no storage vol with matching name '%s'"), vol->name);
+        goto cleanup;
+    }
+
+    if (!virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("storage pool '%s' is not active"), vol->pool);
+        goto cleanup;
+    }
+
+    memset(info, 0, sizeof(*info));
+    info->type = vzStorageVolTypeForPool(privpool->def->type);
+    info->capacity = privvol->target.capacity;
+    info->allocation = privvol->target.allocation;
+    ret = 0;
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+static char *
+vzStorageVolGetXMLDesc(virStorageVolPtr vol, unsigned int flags)
+{
+    vzConnPtr privconn = vol->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    virStorageVolDefPtr privvol;
+    char *ret = NULL;
+
+    virCheckFlags(0, NULL);
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(vol->pool);
+        goto cleanup;
+    }
+
+    privvol = virStorageVolDefFindByName(privpool, vol->name);
+
+    if (privvol == NULL) {
+        virReportError(VIR_ERR_NO_STORAGE_VOL,
+                       _("no storage vol with matching name '%s'"), vol->name);
+        goto cleanup;
+    }
+
+    if (!virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("storage pool '%s' is not active"), vol->pool);
+        goto cleanup;
+    }
+
+    ret = virStorageVolDefFormat(privpool->def, privvol);
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+static char *
+vzStorageVolGetPath(virStorageVolPtr vol)
+{
+    vzConnPtr privconn = vol->conn->privateData;
+    virStoragePoolObjPtr privpool;
+    virStorageVolDefPtr privvol;
+    char *ret = NULL;
+
+    vzDriverLock(privconn);
+    privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool);
+    vzDriverUnlock(privconn);
+
+    if (privpool == NULL) {
+        vzPoolNotFoundError(vol->pool);
+        goto cleanup;
+    }
+
+    privvol = virStorageVolDefFindByName(privpool, vol->name);
+
+    if (privvol == NULL) {
+        virReportError(VIR_ERR_NO_STORAGE_VOL,
+                       _("no storage vol with matching name '%s'"), vol->name);
+        goto cleanup;
+    }
+
+    if (!virStoragePoolObjIsActive(privpool)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("storage pool '%s' is not active"), vol->pool);
+        goto cleanup;
+    }
+
+    ignore_value(VIR_STRDUP(ret, privvol->target.path));
+
+ cleanup:
+    if (privpool)
+        virStoragePoolObjUnlock(privpool);
+    return ret;
+}
+
+virStorageDriver vzStorageDriver = {
+    .name = "Parallels",
+
+    .connectNumOfStoragePools = vzConnectNumOfStoragePools,   /* 0.10.0 */
+    .connectListStoragePools = vzConnectListStoragePools,   /* 0.10.0 */
+    .connectNumOfDefinedStoragePools = vzConnectNumOfDefinedStoragePools,     /* 0.10.0 */
+    .connectListDefinedStoragePools = vzConnectListDefinedStoragePools,     /* 0.10.0 */
+    .storagePoolLookupByName = vzStoragePoolLookupByName,     /* 0.10.0 */
+    .storagePoolLookupByUUID = vzStoragePoolLookupByUUID,     /* 0.10.0 */
+    .storagePoolLookupByVolume = vzStoragePoolLookupByVolume, /* 0.10.0 */
+    .storagePoolDefineXML = vzStoragePoolDefineXML,      /* 0.10.0 */
+    .storagePoolUndefine = vzStoragePoolUndefine,     /* 0.10.0 */
+    .storagePoolCreate = vzStoragePoolCreate,  /* 0.10.0 */
+    .storagePoolDestroy = vzStoragePoolDestroy,       /* 0.10.0 */
+    .storagePoolRefresh = vzStoragePoolRefresh,       /* 0.10.0 */
+    .storagePoolGetInfo = vzStoragePoolGetInfo,       /* 0.10.0 */
+    .storagePoolGetXMLDesc = vzStoragePoolGetXMLDesc, /* 0.10.0 */
+    .storagePoolGetAutostart = vzStoragePoolGetAutostart,     /* 0.10.0 */
+    .storagePoolSetAutostart = vzStoragePoolSetAutostart,     /* 0.10.0 */
+    .storagePoolNumOfVolumes = vzStoragePoolNumOfVolumes,       /* 0.10.0 */
+    .storagePoolListVolumes = vzStoragePoolListVolumes,       /* 0.10.0 */
+
+    .storageVolLookupByName = vzStorageVolLookupByName,    /* 0.10.0 */
+    .storageVolLookupByKey = vzStorageVolLookupByKey,      /* 0.10.0 */
+    .storageVolLookupByPath = vzStorageVolLookupByPath,    /* 0.10.0 */
+    .storageVolCreateXML = vzStorageVolCreateXML,  /* 0.10.0 */
+    .storageVolCreateXMLFrom = vzStorageVolCreateXMLFrom,  /* 0.10.0 */
+    .storageVolDelete = vzStorageVolDelete,        /* 0.10.0 */
+    .storageVolGetInfo = vzStorageVolGetInfo,      /* 0.10.0 */
+    .storageVolGetXMLDesc = vzStorageVolGetXMLDesc,        /* 0.10.0 */
+    .storageVolGetPath = vzStorageVolGetPath,      /* 0.10.0 */
+    .storagePoolIsActive = vzStoragePoolIsActive,     /* 0.10.0 */
+    .storagePoolIsPersistent = vzStoragePoolIsPersistent,     /* 0.10.0 */
+};
diff --git a/src/vz/vz_utils.c b/src/vz/vz_utils.c
new file mode 100644 (file)
index 0000000..08b7f5a
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * vz_utils.c: core driver functions for managing
+ * Parallels Cloud Server hosts
+ *
+ * Copyright (C) 2012 Parallels, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include <stdarg.h>
+
+#include "vircommand.h"
+#include "virerror.h"
+#include "viralloc.h"
+#include "virjson.h"
+#include "vz_utils.h"
+#include "virstring.h"
+#include "datatypes.h"
+
+#define VIR_FROM_THIS VIR_FROM_PARALLELS
+
+/**
+ * vzDomObjFromDomain:
+ * @domain: Domain pointer that has to be looked up
+ *
+ * This function looks up @domain and returns the appropriate virDomainObjPtr
+ * that has to be unlocked by virObjectUnlock().
+ *
+ * Returns the domain object without incremented reference counter which is locked
+ * on success, NULL otherwise.
+ */
+virDomainObjPtr
+vzDomObjFromDomain(virDomainPtr domain)
+{
+    virDomainObjPtr vm;
+    vzConnPtr privconn = domain->conn->privateData;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+    vm = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
+    if (!vm) {
+        virUUIDFormat(domain->uuid, uuidstr);
+        virReportError(VIR_ERR_NO_DOMAIN,
+                       _("no domain with matching uuid '%s' (%s)"),
+                       uuidstr, domain->name);
+        return NULL;
+    }
+
+    return vm;
+
+}
+
+/**
+ * vzDomObjFromDomainRef:
+ * @domain: Domain pointer that has to be looked up
+ *
+ * This function looks up @domain and returns the appropriate virDomainObjPtr
+ * that has to be released by calling virDomainObjEndAPI().
+ *
+ * Returns the domain object with incremented reference counter which is locked
+ * on success, NULL otherwise.
+ */
+virDomainObjPtr
+vzDomObjFromDomainRef(virDomainPtr domain)
+{
+    virDomainObjPtr vm;
+    vzConnPtr privconn = domain->conn->privateData;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+    vm = virDomainObjListFindByUUIDRef(privconn->domains, domain->uuid);
+    if (!vm) {
+        virUUIDFormat(domain->uuid, uuidstr);
+        virReportError(VIR_ERR_NO_DOMAIN,
+                       _("no domain with matching uuid '%s' (%s)"),
+                       uuidstr, domain->name);
+        return NULL;
+    }
+
+    return vm;
+}
+
+static int
+vzDoCmdRun(char **outbuf, const char *binary, va_list list)
+{
+    virCommandPtr cmd = virCommandNewVAList(binary, list);
+    int ret = -1;
+
+    if (outbuf)
+        virCommandSetOutputBuffer(cmd, outbuf);
+
+    if (virCommandRun(cmd, NULL) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    virCommandFree(cmd);
+    if (ret && outbuf)
+        VIR_FREE(*outbuf);
+    return ret;
+}
+
+/*
+ * Run command and parse its JSON output, return
+ * pointer to virJSONValue or NULL in case of error.
+ */
+virJSONValuePtr
+vzParseOutput(const char *binary, ...)
+{
+    char *outbuf;
+    virJSONValuePtr jobj = NULL;
+    va_list list;
+    int ret;
+
+    va_start(list, binary);
+    ret = vzDoCmdRun(&outbuf, binary, list);
+    va_end(list);
+    if (ret)
+        return NULL;
+
+    jobj = virJSONValueFromString(outbuf);
+    if (!jobj)
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("invalid output from prlctl: %s"), outbuf);
+
+    VIR_FREE(outbuf);
+    return jobj;
+}
+
+/*
+ * Run command and return its output, pointer to
+ * buffer or NULL in case of error. Caller os responsible
+ * for freeing the buffer.
+ */
+char *
+vzGetOutput(const char *binary, ...)
+{
+    char *outbuf;
+    va_list list;
+    int ret;
+
+    va_start(list, binary);
+    ret = vzDoCmdRun(&outbuf, binary, list);
+    va_end(list);
+    if (ret)
+        return NULL;
+
+    return outbuf;
+}
+
+/*
+ * Run prlctl command and check for errors
+ *
+ * Return value is 0 in case of success, else - -1
+ */
+int
+vzCmdRun(const char *binary, ...)
+{
+    int ret;
+    va_list list;
+
+    va_start(list, binary);
+    ret = vzDoCmdRun(NULL, binary, list);
+    va_end(list);
+
+    return ret;
+}
+
+/*
+ * Return new file path in malloced string created by
+ * concatenating first and second function arguments.
+ */
+char *
+vzAddFileExt(const char *path, const char *ext)
+{
+    char *new_path = NULL;
+    size_t len = strlen(path) + strlen(ext) + 1;
+
+    if (VIR_ALLOC_N(new_path, len) < 0)
+        return NULL;
+
+    if (!virStrcpy(new_path, path, len)) {
+        VIR_FREE(new_path);
+        return NULL;
+    }
+    strcat(new_path, ext);
+
+    return new_path;
+}
diff --git a/src/vz/vz_utils.h b/src/vz/vz_utils.h
new file mode 100644 (file)
index 0000000..9b46bf9
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * vz_utils.h: core driver functions for managing
+ * Parallels Cloud Server hosts
+ *
+ * Copyright (C) 2012 Parallels, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef PARALLELS_UTILS_H
+# define PARALLELS_UTILS_H
+
+# include <Parallels.h>
+
+# include "driver.h"
+# include "conf/domain_conf.h"
+# include "conf/storage_conf.h"
+# include "conf/domain_event.h"
+# include "conf/network_conf.h"
+# include "virthread.h"
+# include "virjson.h"
+
+# define vzParseError()                                                 \
+    virReportErrorHelper(VIR_FROM_TEST, VIR_ERR_OPERATION_FAILED, __FILE__,    \
+                     __FUNCTION__, __LINE__, _("Can't parse prlctl output"))
+
+# define IS_CT(def)  (def->os.type == VIR_DOMAIN_OSTYPE_EXE)
+
+# define vzDomNotFoundError(domain)                               \
+    do {                                                                 \
+        char uuidstr[VIR_UUID_STRING_BUFLEN];                            \
+        virUUIDFormat(domain->uuid, uuidstr);                            \
+        virReportError(VIR_ERR_NO_DOMAIN,                                \
+                       _("no domain with matching uuid '%s'"), uuidstr); \
+    } while (0)
+
+# define PARALLELS_DOMAIN_ROUTED_NETWORK_NAME   "Routed"
+# define PARALLELS_DOMAIN_BRIDGED_NETWORK_NAME  "Bridged"
+
+# define PARALLELS_REQUIRED_HOSTONLY_NETWORK "Host-Only"
+# define PARALLELS_HOSTONLY_NETWORK_TYPE "host-only"
+# define PARALLELS_REQUIRED_BRIDGED_NETWORK  "Bridged"
+# define PARALLELS_BRIDGED_NETWORK_TYPE  "bridged"
+
+struct _vzConn {
+    virMutex lock;
+
+    /* Immutable pointer, self-locking APIs */
+    virDomainObjListPtr domains;
+
+    PRL_HANDLE server;
+    virStoragePoolObjList pools;
+    virNetworkObjListPtr networks;
+    virCapsPtr caps;
+    virDomainXMLOptionPtr xmlopt;
+    virObjectEventStatePtr domainEventState;
+    virStorageDriverStatePtr storageState;
+    const char *drivername;
+};
+
+typedef struct _vzConn vzConn;
+typedef struct _vzConn *vzConnPtr;
+
+struct _vzCountersCache {
+    PRL_HANDLE stats;
+    virCond cond;
+    // -1 - unsubscribed
+    // > -1 - subscribed
+    int count;
+};
+
+typedef struct _vzCountersCache vzCountersCache;
+
+struct vzDomObj {
+    int id;
+    char *uuid;
+    char *home;
+    PRL_HANDLE sdkdom;
+    vzCountersCache cache;
+};
+
+typedef struct vzDomObj *vzDomObjPtr;
+
+virDrvOpenStatus vzStorageOpen(virConnectPtr conn, unsigned int flags);
+int vzStorageClose(virConnectPtr conn);
+extern virStorageDriver vzStorageDriver;
+
+virDrvOpenStatus vzNetworkOpen(virConnectPtr conn, unsigned int flags);
+int vzNetworkClose(virConnectPtr conn);
+extern virNetworkDriver vzNetworkDriver;
+
+virDomainObjPtr vzDomObjFromDomain(virDomainPtr domain);
+virDomainObjPtr vzDomObjFromDomainRef(virDomainPtr domain);
+
+virJSONValuePtr vzParseOutput(const char *binary, ...)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_SENTINEL;
+char * vzGetOutput(const char *binary, ...)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_SENTINEL;
+int vzCmdRun(const char *binary, ...)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_SENTINEL;
+char * vzAddFileExt(const char *path, const char *ext);
+void vzDriverLock(vzConnPtr driver);
+void vzDriverUnlock(vzConnPtr driver);
+virStorageVolPtr vzStorageVolLookupByPathLocked(virConnectPtr conn,
+                                                       const char *path);
+int vzStorageVolDefRemove(virStoragePoolObjPtr privpool,
+                                 virStorageVolDefPtr privvol);
+
+# define PARALLELS_BLOCK_STATS_FOREACH(OP)                                   \
+             OP(rd_req, VIR_DOMAIN_BLOCK_STATS_READ_REQ, "read_requests")    \
+             OP(rd_bytes, VIR_DOMAIN_BLOCK_STATS_READ_BYTES, "read_total")   \
+             OP(wr_req, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ, "write_requests")  \
+             OP(wr_bytes, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES, "write_total")
+
+#endif