Signed-off-by: Dmitry Guryanov <dguryanov(a)parallels.com>
---
cfg.mk | 1 +
configure.ac | 23 ++++
docs/drvpvs.html.in | 28 +++++
include/libvirt/virterror.h | 1 +
libvirt.spec.in | 7 +
mingw32-libvirt.spec.in | 6 +
po/POTFILES.in | 1 +
src/Makefile.am | 21 ++++
src/conf/domain_conf.c | 3 +-
src/conf/domain_conf.h | 1 +
src/driver.h | 1 +
src/libvirt.c | 12 ++
src/pvs/pvs_driver.c | 272 +++++++++++++++++++++++++++++++++++++++++++
src/pvs/pvs_driver.h | 51 ++++++++
src/util/virterror.c | 3 +
15 files changed, 430 insertions(+), 1 deletions(-)
create mode 100644 docs/drvpvs.html.in
create mode 100644 src/pvs/pvs_driver.c
create mode 100644 src/pvs/pvs_driver.h
diff --git a/cfg.mk b/cfg.mk
index 71e9a1d..ca6c0a5 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -502,6 +502,7 @@ msg_gen_function += PHYP_ERROR
msg_gen_function += VIR_ERROR
msg_gen_function += VMX_ERROR
msg_gen_function += XENXS_ERROR
+msg_gen_function += PVS_ERROR
msg_gen_function += eventReportError
msg_gen_function += ifaceError
msg_gen_function += interfaceReportError
diff --git a/configure.ac b/configure.ac
index 53c9b34..1b3ce08 100644
--- a/configure.ac
+++ b/configure.ac
@@ -330,6 +330,8 @@ AC_ARG_WITH([esx],
AC_HELP_STRING([--with-esx], [add ESX support
@<:@default=check@:>@]),[],[with_esx=check])
AC_ARG_WITH([hyperv],
AC_HELP_STRING([--with-hyperv], [add Hyper-V support
@<:@default=check@:>@]),[],[with_hyperv=check])
+AC_ARG_WITH([pvs],
+ AC_HELP_STRING([--with-pvs], [add Parallels Virtuozzo Server support
@<:@default=check@:>@]),[],[with_pvs=check])
AC_ARG_WITH([test],
AC_HELP_STRING([--with-test], [add test driver support
@<:@default=yes@:>@]),[],[with_test=yes])
AC_ARG_WITH([remote],
@@ -794,6 +796,26 @@ fi
AM_CONDITIONAL([WITH_LXC], [test "$with_lxc" = "yes"])
dnl
+dnl Checks for the PVS driver
+dnl
+
+if test "$with_pvs" = "check"; then
+ with_pvs=$with_linux
+ if test ! $(uname -i) = 'x86_64'; then
+ with_pvs=no
+ fi
+fi
+
+if test "$with_pvs" = "yes" && test "$with_linux" =
"no"; then
+ AC_MSG_ERROR([The PVS driver can be enabled on Linux only.])
+fi
+
+if test "$with_pvs" = "yes"; then
+ AC_DEFINE_UNQUOTED([WITH_PVS], 1, [whether PVS driver is enabled])
+fi
+AM_CONDITIONAL([WITH_PVS], [test "$with_pvs" = "yes"])
+
+dnl
dnl check for shell that understands <> redirection without truncation,
dnl needed by src/qemu/qemu_monitor_{text,json}.c.
dnl
@@ -2681,6 +2703,7 @@ AC_MSG_NOTICE([ LXC: $with_lxc])
AC_MSG_NOTICE([ PHYP: $with_phyp])
AC_MSG_NOTICE([ ESX: $with_esx])
AC_MSG_NOTICE([ Hyper-V: $with_hyperv])
+AC_MSG_NOTICE([ PVS: $with_pvs])
AC_MSG_NOTICE([ Test: $with_test])
AC_MSG_NOTICE([ Remote: $with_remote])
AC_MSG_NOTICE([ Network: $with_network])
diff --git a/docs/drvpvs.html.in b/docs/drvpvs.html.in
new file mode 100644
index 0000000..dae3c77
--- /dev/null
+++ b/docs/drvpvs.html.in
@@ -0,0 +1,28 @@
+<html><body>
+ <h1>Parallels Virtuozzo Server driver</h1>
+ <ul id="toc"></ul>
+ <p>
+ The libvirt PVS driver can manage Parallels Virtuozzo Server starting from 6.0
version.
+ </p>
+
+
+ <h2><a name="project">Project Links</a></h2>
+ <ul>
+ <li>
+ The <a
href="http://www.parallels.com/products/server/baremetal/sp/"&g...
Virtuozzo Server</a> Virtualization Solution.
+ </li>
+ </ul>
+
+
+ <h2><a name="uri">Connections to the Parallels Virtuozzo Server
driver</a></h2>
+ <p>
+ The libvirt PVS driver is a single-instance privileged driver, with a driver name
of 'pvs'. Some example connection URIs for the libvirt driver are:
+ </p>
+<pre>
+pvs:///default (local access)
+pvs+unix:///default (local access)
+pvs://example.com/default (remote access, TLS/x509)
+pvs+tcp://example.com/default (remote access, SASl/Kerberos)
+pvs+ssh://root@example.com/default (remote access, SSH tunnelled)
+</pre>
+</body></html>
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index e04d29e..8a7e8ba 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -87,6 +87,7 @@ typedef enum {
VIR_FROM_CAPABILITIES = 44, /* Error from capabilities */
VIR_FROM_URI = 45, /* Error from URI handling */
VIR_FROM_AUTH = 46, /* Error from auth handling */
+ VIR_FROM_PVS = 47, /* Error from PVS */
} virErrorDomain;
diff --git a/libvirt.spec.in b/libvirt.spec.in
index e7e0a55..a4e2460 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -65,6 +65,7 @@
%define with_esx 0%{!?_without_esx:1}
%define with_hyperv 0%{!?_without_hyperv:1}
%define with_xenapi 0%{!?_without_xenapi:1}
+%define with_pvs 0%{!?_without_pvs:1}
# Then the secondary host drivers, which run inside libvirtd
%define with_network 0%{!?_without_network:%{server_drivers}}
@@ -124,6 +125,7 @@
%define with_xenapi 0
%define with_libxl 0
%define with_hyperv 0
+%define with_pvs 0
%endif
# Although earlier Fedora has systemd, libvirt still used sysvinit
@@ -790,6 +792,10 @@ of recent versions of Linux (and other OSes).
%define _without_vmware --without-vmware
%endif
+%if ! %{with_pvs}
+%define _without_pvs --without-pvs
+%endif
+
%if ! %{with_polkit}
%define _without_polkit --without-polkit
%endif
@@ -920,6 +926,7 @@ autoreconf -if
%{?_without_esx} \
%{?_without_hyperv} \
%{?_without_vmware} \
+ %{?_without_pvs} \
%{?_without_network} \
%{?_with_rhel5_api} \
%{?_without_storage_fs} \
diff --git a/mingw32-libvirt.spec.in b/mingw32-libvirt.spec.in
index 4d23c75..7d82bc2 100644
--- a/mingw32-libvirt.spec.in
+++ b/mingw32-libvirt.spec.in
@@ -18,6 +18,7 @@
# missing libwsman, so can't build hyper-v
%define with_hyperv 0%{!?_without_hyperv:0}
%define with_xenapi 0%{!?_without_xenapi:1}
+%define with_pvs 0%{!?_without_pvs:0}
# RHEL ships ESX but not PowerHypervisor, HyperV, or libxenserver (xenapi)
%if 0%{?rhel}
@@ -92,6 +93,10 @@ MinGW Windows libvirt virtualization library.
%define _without_xenapi --without-xenapi
%endif
+%if ! %{with_pvs}
+%define _without_pvs --without-pvs
+%endif
+
%if 0%{?enable_autotools}
autoreconf -if
%endif
@@ -113,6 +118,7 @@ autoreconf -if
%{?_without_esx} \
%{?_without_hyperv} \
--without-vmware \
+ --without-pvs \
--without-netcf \
--without-audit \
--without-dtrace
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4c49200..fb70cf7 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -164,6 +164,7 @@ src/xenapi/xenapi_driver.c
src/xenapi/xenapi_utils.c
src/xenxs/xen_sxpr.c
src/xenxs/xen_xm.c
+src/pvs/pvs_driver.c
tools/console.c
tools/libvirt-guests.init.sh
tools/virsh.c
diff --git a/src/Makefile.am b/src/Makefile.am
index a2aae9d..3cbd385 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -465,6 +465,10 @@ HYPERV_DRIVER_EXTRA_DIST = \
hyperv/hyperv_wmi_generator.py \
$(HYPERV_DRIVER_GENERATED)
+PVS_DRIVER_SOURCES = \
+ pvs/pvs_driver.h \
+ pvs/pvs_driver.c
+
NETWORK_DRIVER_SOURCES = \
network/bridge_driver.h network/bridge_driver.c
@@ -930,6 +934,22 @@ endif
libvirt_driver_hyperv_la_SOURCES = $(HYPERV_DRIVER_SOURCES)
endif
+if WITH_PVS
+if WITH_DRIVER_MODULES
+mod_LTLIBRARIES += libvirt_driver_pvs.la
+else
+noinst_LTLIBRARIES += libvirt_driver_pvs.la
+libvirt_la_BUILT_LIBADD += libvirt_driver_pvs.la
+endif
+libvirt_driver_pvs_la_CFLAGS = -I$(top_srcdir)/src/conf $(AM_CFLAGS)
+libvirt_driver_pvs_la_LDFLAGS = $(AM_LDFLAGS)
+if WITH_DRIVER_MODULES
+libvirt_driver_pvs_la_LIBADD = ../gnulib/lib/libgnu.la
+libvirt_driver_pvs_la_LDFLAGS += -module -avoid-version
+endif
+libvirt_driver_pvs_la_SOURCES = $(PVS_DRIVER_SOURCES)
+endif
+
if WITH_NETWORK
if WITH_DRIVER_MODULES
mod_LTLIBRARIES += libvirt_driver_network.la
@@ -1130,6 +1150,7 @@ EXTRA_DIST += \
$(ESX_DRIVER_EXTRA_DIST) \
$(HYPERV_DRIVER_SOURCES) \
$(HYPERV_DRIVER_EXTRA_DIST) \
+ $(PVS_DRIVER_SOURCES) \
$(NETWORK_DRIVER_SOURCES) \
$(INTERFACE_DRIVER_SOURCES) \
$(STORAGE_DRIVER_SOURCES) \
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5ab052a..136474b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -93,7 +93,8 @@ VIR_ENUM_IMPL(virDomainVirt, VIR_DOMAIN_VIRT_LAST,
"vmware",
"hyperv",
"vbox",
- "phyp")
+ "phyp",
+ "pvs")
VIR_ENUM_IMPL(virDomainBoot, VIR_DOMAIN_BOOT_LAST,
"fd",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 0eed60e..7983e11 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -157,6 +157,7 @@ enum virDomainVirtType {
VIR_DOMAIN_VIRT_HYPERV,
VIR_DOMAIN_VIRT_VBOX,
VIR_DOMAIN_VIRT_PHYP,
+ VIR_DOMAIN_VIRT_PVS,
VIR_DOMAIN_VIRT_LAST,
};
diff --git a/src/driver.h b/src/driver.h
index 03d249b..1bcbd46 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -31,6 +31,7 @@ typedef enum {
VIR_DRV_VMWARE = 13,
VIR_DRV_LIBXL = 14,
VIR_DRV_HYPERV = 15,
+ VIR_DRV_PVS = 16,
} virDrvNo;
diff --git a/src/libvirt.c b/src/libvirt.c
index 93ec817..deae2c7 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -76,6 +76,9 @@
# ifdef WITH_XENAPI
# include "xenapi/xenapi_driver.h"
# endif
+# ifdef WITH_PVS
+# include "pvs/pvs_driver.h"
+# endif
#endif
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -454,6 +457,9 @@ virInitialize(void)
# ifdef WITH_XENAPI
virDriverLoadModule("xenapi");
# endif
+# ifdef WITH_PVS
+ virDriverLoadModule("pvs");
+# endif
# ifdef WITH_REMOTE
virDriverLoadModule("remote");
# endif
@@ -485,6 +491,9 @@ virInitialize(void)
# ifdef WITH_XENAPI
if (xenapiRegister() == -1) return -1;
# endif
+# ifdef WITH_PVS
+ if (pvsRegister() == -1) return -1;
+# endif
# ifdef WITH_REMOTE
if (remoteRegister () == -1) return -1;
# endif
@@ -1214,6 +1223,9 @@ do_open (const char *name,
#ifndef WITH_XENAPI
STRCASEEQ(ret->uri->scheme, "xenapi") ||
#endif
+#ifndef WITH_PVS
+ STRCASEEQ(ret->uri->scheme, "pvs") ||
+#endif
false)) {
virReportErrorHelper(VIR_FROM_NONE, VIR_ERR_INVALID_ARG,
__FILE__, __FUNCTION__, __LINE__,
diff --git a/src/pvs/pvs_driver.c b/src/pvs/pvs_driver.c
new file mode 100644
index 0000000..289bb7f
--- /dev/null
+++ b/src/pvs/pvs_driver.c
@@ -0,0 +1,272 @@
+/*
+ * pvs_driver.c: core driver functions for managing
+ * Parallels Virtuozzo 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#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/utsname.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <sys/statvfs.h>
+
+#include "datatypes.h"
+#include "virterror_internal.h"
+#include "memory.h"
+#include "util.h"
+#include "logging.h"
+#include "command.h"
+#include "configmake.h"
+#include "storage_file.h"
+#include "nodeinfo.h"
+#include "json.h"
+
+#include "pvs_driver.h"
+
+#define VIR_FROM_THIS VIR_FROM_PVS
+
+static virCapsPtr pvsBuildCapabilities(void);
+static int pvsClose(virConnectPtr conn);
+
+static void
+pvsDriverLock(pvsConnPtr driver)
+{
+ virMutexLock(&driver->lock);
+}
+
+static void
+pvsDriverUnlock(pvsConnPtr driver)
+{
+ virMutexUnlock(&driver->lock);
+}
+
+static int
+pvsDefaultConsoleType(const char *ostype ATTRIBUTE_UNUSED)
+{
+ return VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
+}
+
+static virCapsPtr
+pvsBuildCapabilities(void)
+{
+ virCapsPtr caps;
+ virCapsGuestPtr guest;
+ struct utsname utsname;
+ uname(&utsname);
+
+ if ((caps = virCapabilitiesNew(utsname.machine, 0, 0)) == NULL)
+ goto no_memory;
+
+ if (nodeCapsInitNUMA(caps) < 0)
+ goto no_memory;
+
+ virCapabilitiesSetMacPrefix(caps, (unsigned char[]) {
+ 0x42, 0x1C, 0x00});
+
+ if ((guest = virCapabilitiesAddGuest(caps, "hvm", "x86_64",
+ 64, "parallels",
+ NULL, 0, NULL)) == NULL)
+ goto no_memory;
+
+ if (virCapabilitiesAddGuestDomain(guest,
+ "pvs", NULL, NULL, 0, NULL) == NULL)
+ goto no_memory;
+
+ caps->defaultConsoleTargetType = pvsDefaultConsoleType;
+ return caps;
+
+ no_memory:
+ virReportOOMError();
+ virCapabilitiesFree(caps);
+ return NULL;
+}
+
+static char *
+pvsGetCapabilities(virConnectPtr conn)
+{
+ pvsConnPtr privconn = conn->privateData;
+ char *xml;
+
+ pvsDriverLock(privconn);
+ if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL)
+ virReportOOMError();
+ pvsDriverUnlock(privconn);
+ return xml;
+}
+
+static int
+pvsOpenDefault(virConnectPtr conn)
+{
+ pvsConnPtr privconn;
+
+ if (VIR_ALLOC(privconn) < 0) {
+ virReportOOMError();
+ return VIR_DRV_OPEN_ERROR;
+ }
+ if (virMutexInit(&privconn->lock) < 0) {
+ pvsError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("cannot initialize mutex"));
+ goto error;
+ }
+
+ pvsDriverLock(privconn);
+ conn->privateData = privconn;
+ pvsDriverUnlock(privconn);
+
+ if (!(privconn->caps = pvsBuildCapabilities()))
+ goto error;
+
+ if (virDomainObjListInit(&privconn->domains) < 0)
+ goto error;
+
+ return VIR_DRV_OPEN_SUCCESS;
+
+ error:
+ virDomainObjListDeinit(&privconn->domains);
+ virCapabilitiesFree(privconn->caps);
+ virStoragePoolObjListFree(&privconn->pools);
+ pvsDriverUnlock(privconn);
+ conn->privateData = NULL;
+ VIR_FREE(privconn);
+ return VIR_DRV_OPEN_ERROR;
+}
+
+static virDrvOpenStatus
+pvsOpen(virConnectPtr conn,
+ virConnectAuthPtr auth ATTRIBUTE_UNUSED, unsigned int flags)
+{
+ int ret;
+ pvsConnPtr privconn;
+ char *tmp;
+
+ virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
+
+ if (!conn->uri)
+ return VIR_DRV_OPEN_DECLINED;
+
+ if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "pvs"))
+ 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 (!conn->uri->path
+ || conn->uri->path[0] == '\0'
+ || (conn->uri->path[0] == '/' && conn->uri->path[1]
== '\0')) {
+ pvsError(VIR_ERR_INVALID_ARG,
+ "%s", _("pvsOpen: supply a path or use
pvs:///default"));
+ return VIR_DRV_OPEN_ERROR;
+ }
+
+ if (STREQ(conn->uri->path, "/default"))
+ ret = pvsOpenDefault(conn);
+ else
+ return VIR_DRV_OPEN_DECLINED;
+
+ tmp = virFindFileInPath(PRLCTL);
+ if (!tmp) {
+ pvsError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Can't find prlctl command in the PATH env"));
+ return VIR_DRV_OPEN_ERROR;
+ }
+
+ if (ret != VIR_DRV_OPEN_SUCCESS)
+ return ret;
+
+ privconn = conn->privateData;
+ pvsDriverLock(privconn);
+ privconn->domainEventState = virDomainEventStateNew();
+ if (!privconn->domainEventState) {
+ pvsDriverUnlock(privconn);
+ pvsClose(conn);
+ return VIR_DRV_OPEN_ERROR;
+ }
+
+ pvsDriverUnlock(privconn);
+ return VIR_DRV_OPEN_SUCCESS;
+}
+
+static int
+pvsClose(virConnectPtr conn)
+{
+ pvsConnPtr privconn = conn->privateData;
+
+ pvsDriverLock(privconn);
+ virCapabilitiesFree(privconn->caps);
+ virDomainObjListDeinit(&privconn->domains);
+ virDomainEventStateFree(privconn->domainEventState);
+ conn->privateData = NULL;
+
+ pvsDriverUnlock(privconn);
+ virMutexDestroy(&privconn->lock);
+
+ VIR_FREE(privconn);
+ return 0;
+}
+
+static int
+pvsGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *hvVer)
+{
+ /* TODO */
+ *hvVer = 6;
+ return 0;
+}
+
+static virDriver pvsDriver = {
+ .no = VIR_DRV_PVS,
+ .name = "PVS",
+ .open = pvsOpen, /* 0.9.12 */
+ .close = pvsClose, /* 0.9.12 */
+ .version = pvsGetVersion, /* 0.9.12 */
+ .getHostname = virGetHostname, /* 0.9.12 */
+ .nodeGetInfo = nodeGetInfo, /* 0.9.12 */
+ .getCapabilities = pvsGetCapabilities, /* 0.9.12 */
+};
+
+/**
+ * pvsRegister:
+ *
+ * Registers the pvs driver
+ */
+int
+pvsRegister(void)
+{
+ if (virRegisterDriver(&pvsDriver) < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/src/pvs/pvs_driver.h b/src/pvs/pvs_driver.h
new file mode 100644
index 0000000..d15161f
--- /dev/null
+++ b/src/pvs/pvs_driver.h
@@ -0,0 +1,51 @@
+/*
+ * pvs_driver.c: core driver functions for managing
+ * Parallels Virtuozzo 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef PVS_DRIVER_H
+# define PVS_DRIVER_H
+
+
+#include "domain_conf.h"
+#include "storage_conf.h"
+#include "domain_event.h"
+
+#define pvsError(code, ...) \
+ virReportErrorHelper(VIR_FROM_TEST, code, __FILE__, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+#define PRLCTL "prlctl"
+
+
+struct _pvsConn {
+ virMutex lock;
+ virDomainObjList domains;
+ virStoragePoolObjList pools;
+ virCapsPtr caps;
+ virDomainEventStatePtr domainEventState;
+};
+
+typedef struct _pvsConn pvsConn;
+
+typedef struct _pvsConn *pvsConnPtr;
+
+int pvsRegister(void);
+
+#endif
diff --git a/src/util/virterror.c b/src/util/virterror.c
index ff9a36f..4976c08 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -175,6 +175,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
case VIR_FROM_HYPERV:
dom = "Hyper-V ";
break;
+ case VIR_FROM_PVS:
+ dom = "Parallels Virtuozzo Server ";
+ break;
case VIR_FROM_CAPABILITIES:
dom = "Capabilities ";
break;
--
1.7.1