[libvirt] [PATCHv2] network: check for invalid forward delay time
by Erik Skultety
When spanning tree protocol is allowed in bridge settings, forward delay
value is set as well (default is 0 if omitted). Until now, there was no
check for delay value validity. Delay makes sense only as a positive
numerical value.
Note: However, even if you provide positive numerical value, brctl
utility only uses values from range <2,30>, so the number provided can
be modified (kernel most likely) to fall within this range.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1125764
---
docs/schemas/network.rng | 2 +-
src/conf/network_conf.c | 38 +++++++++++++++++++++++---------------
src/util/virxml.c | 2 +-
3 files changed, 25 insertions(+), 17 deletions(-)
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 0e7da89..ab41814 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -62,7 +62,7 @@
<optional>
<attribute name="delay">
- <data type="integer"/>
+ <data type="unsignedLong"/>
</attribute>
</optional>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 9571ee1..e9ea746 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -2003,7 +2003,7 @@ static virNetworkDefPtr
virNetworkDefParseXML(xmlXPathContextPtr ctxt)
{
virNetworkDefPtr def;
- char *tmp;
+ char *tmp = NULL;
char *stp = NULL;
xmlNodePtr *ipNodes = NULL;
xmlNodePtr *routeNodes = NULL;
@@ -2037,7 +2037,6 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
}
} else {
if (virUUIDParse(tmp, def->uuid) < 0) {
- VIR_FREE(tmp);
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("malformed uuid element"));
goto error;
@@ -2078,8 +2077,16 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
stp = virXPathString("string(./bridge[1]/@stp)", ctxt);
def->stp = (stp && STREQ(stp, "off")) ? false : true;
- if (virXPathULong("string(./bridge[1]/@delay)", ctxt, &def->delay) < 0)
- def->delay = 0;
+ tmp = virXPathString("string(./bridge[1]/@delay)", ctxt);
+ if (tmp) {
+ if (virStrToLong_ulp(tmp, NULL, 10, &def->delay) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid delay value in network '%s'"),
+ def->name);
+ goto error;
+ }
+ }
+ VIR_FREE(tmp);
tmp = virXPathString("string(./mac[1]/@address)", ctxt);
if (tmp) {
@@ -2087,14 +2094,12 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
virReportError(VIR_ERR_XML_ERROR,
_("Invalid bridge mac address '%s' in network '%s'"),
tmp, def->name);
- VIR_FREE(tmp);
goto error;
}
if (virMacAddrIsMulticast(&def->mac)) {
virReportError(VIR_ERR_XML_ERROR,
_("Invalid multicast bridge mac address '%s' in network '%s'"),
tmp, def->name);
- VIR_FREE(tmp);
goto error;
}
VIR_FREE(tmp);
@@ -2126,9 +2131,9 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
goto error;
/* parse each portgroup */
for (i = 0; i < nPortGroups; i++) {
- int ret = virNetworkPortGroupParseXML(&def->portGroups[i],
- portGroupNodes[i], ctxt);
- if (ret < 0)
+ if (virNetworkPortGroupParseXML(&def->portGroups[i],
+ portGroupNodes[i],
+ ctxt) < 0)
goto error;
def->nPortGroups++;
}
@@ -2147,9 +2152,10 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
goto error;
/* parse each addr */
for (i = 0; i < nIps; i++) {
- int ret = virNetworkIPDefParseXML(def->name, ipNodes[i],
- ctxt, &def->ips[i]);
- if (ret < 0)
+ if (virNetworkIPDefParseXML(def->name,
+ ipNodes[i],
+ ctxt,
+ &def->ips[i]) < 0)
goto error;
def->nips++;
}
@@ -2168,9 +2174,10 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
goto error;
/* parse each definition */
for (i = 0; i < nRoutes; i++) {
- int ret = virNetworkRouteDefParseXML(def->name, routeNodes[i],
- ctxt, &def->routes[i]);
- if (ret < 0)
+ if (virNetworkRouteDefParseXML(def->name,
+ routeNodes[i],
+ ctxt,
+ &def->routes[i]) < 0)
goto error;
def->nroutes++;
}
@@ -2289,6 +2296,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
return def;
error:
+ VIR_FREE(tmp);
VIR_FREE(routeNodes);
VIR_FREE(stp);
virNetworkDefFree(def);
diff --git a/src/util/virxml.c b/src/util/virxml.c
index cc4a85c..a91da05 100644
--- a/src/util/virxml.c
+++ b/src/util/virxml.c
@@ -420,7 +420,7 @@ virXPathULongLong(const char *xpath,
}
/**
- * virXPathULongLong:
+ * virXPathLongLong:
* @xpath: the XPath string to evaluate
* @ctxt: an XPath context
* @value: the returned long long value
--
1.9.3
10 years, 3 months
[libvirt] [PATCH] openvz: fixed an config file parsing error
by Hongbin Lu
The OpenVZ driver reported an error on parsing some OpenVZ config
parameters (e.g. diskspace). This issue is due to the driver made
two incorrect assumptions about the value of the parameters:
1. Assume paramaeter is just a number (without unit suffix).
2. Assume the number is an integer.
Actually, an OpenVZ config parameter may consist of a scalar and
a unit, and the scalar is not necessary an integer (e.g. 2.2G).
This patch is for fixing this issue.
---
src/openvz/openvz_conf.c | 109 +++++++++++++++++++++++++++++++++++++++++-----
src/util/virutil.c | 84 ++++++++++++++++++++++++-----------
src/util/virutil.h | 3 +
3 files changed, 157 insertions(+), 39 deletions(-)
diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c
index 856c9f5..0b163b4 100644
--- a/src/openvz/openvz_conf.c
+++ b/src/openvz/openvz_conf.c
@@ -51,6 +51,7 @@
#include "virfile.h"
#include "vircommand.h"
#include "virstring.h"
+#include "c-ctype.h"
#define VIR_FROM_THIS VIR_FROM_OPENVZ
@@ -127,6 +128,32 @@ int openvzExtractVersion(struct openvz_driver *driver)
}
+/* Split a string, which is a config parameter, into a scalar and a unit.
+ * Recognized unit:
+ * - Gigabyte: 'G' or 'g'
+ * - Megabyte: 'M' or 'm'
+ * - Kilobyte: 'K' or 'k'
+ * - Page: 'P' or 'g' */
+static int
+openvzParseParamUnit(char* str, char *unit)
+{
+ char last;
+ int len = strlen(str);
+
+ if (len == 0)
+ return -1;
+
+ last = c_tolower(str[len - 1]);
+ if (last == 'g' || last == 'm' || last == 'k' || last == 'p') {
+ str[len - 1] = '\0';
+ if (unit)
+ *unit = last;
+ }
+
+ return 0;
+}
+
+
/* Parse config values of the form barrier:limit into barrier and limit */
static int
openvzParseBarrierLimit(const char* value,
@@ -146,7 +173,59 @@ openvzParseBarrierLimit(const char* value,
goto error;
} else {
if (barrier != NULL) {
- if (virStrToLong_ull(token, NULL, 10, barrier))
+ if (openvzParseParamUnit(token, NULL) < 0)
+ goto error;
+
+ if (virStrToLong_ull(token, NULL, 10, barrier) < 0)
+ goto error;
+ }
+ }
+ token = strtok_r(NULL, ":", &saveptr);
+ if (token == NULL) {
+ goto error;
+ } else {
+ if (limit != NULL) {
+ if (openvzParseParamUnit(token, NULL) < 0)
+ goto error;
+
+ if (virStrToLong_ull(token, NULL, 10, limit) < 0)
+ goto error;
+ }
+ }
+ ret = 0;
+ error:
+ VIR_FREE(str);
+ return ret;
+}
+
+
+/* Just like openvzParseBarrierLimit, above, but produce "double"
+ * barrier and limit. This version also outputs the units of barrier
+ * and limit, which are bunit and lunit, if they are present.*/
+static int
+openvzParseBarrierLimitDouble(const char* value,
+ double *barrier,
+ double *limit,
+ char *bunit,
+ char *lunit)
+{
+ char *token;
+ char *saveptr = NULL;
+ char *str;
+ int ret = -1;
+
+ if (VIR_STRDUP(str, value) < 0)
+ goto error;
+
+ token = strtok_r(str, ":", &saveptr);
+ if (token == NULL) {
+ goto error;
+ } else {
+ if (barrier != NULL) {
+ if (openvzParseParamUnit(token, bunit) < 0)
+ goto error;
+
+ if (virStrToDouble(token, NULL, barrier) < 0)
goto error;
}
}
@@ -155,7 +234,10 @@ openvzParseBarrierLimit(const char* value,
goto error;
} else {
if (limit != NULL) {
- if (virStrToLong_ull(token, NULL, 10, limit))
+ if (openvzParseParamUnit(token, lunit) < 0)
+ goto error;
+
+ if (virStrToDouble(token, NULL, limit) < 0)
goto error;
}
}
@@ -352,7 +434,8 @@ openvzReadFSConf(virDomainDefPtr def,
char *veid_str = NULL;
char *temp = NULL;
const char *param;
- unsigned long long barrier, limit;
+ double barrier, limit;
+ char bunit, lunit;
ret = openvzReadVPSConfigParam(veid, "OSTEMPLATE", &temp);
if (ret < 0) {
@@ -396,21 +479,23 @@ openvzReadFSConf(virDomainDefPtr def,
param = "DISKSPACE";
ret = openvzReadVPSConfigParam(veid, param, &temp);
if (ret > 0) {
- if (openvzParseBarrierLimit(temp, &barrier, &limit)) {
+ bunit = 'k'; /* default unit is kilobyte */
+ lunit = 'k'; /* default unit is kilobyte */
+
+ if (openvzParseBarrierLimitDouble(temp, &barrier, &limit, &bunit, &lunit)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not read '%s' from config for container %d"),
param, veid);
goto error;
} else {
- /* Ensure that we can multiply by 1024 without overflowing. */
- if (barrier > ULLONG_MAX / 1024 ||
- limit > ULLONG_MAX / 1024) {
- virReportSystemError(VIR_ERR_OVERFLOW, "%s",
- _("Unable to parse quota"));
+ if (virScaleDouble(&barrier, &bunit) < 0)
goto error;
- }
- fs->space_soft_limit = barrier * 1024; /* unit is bytes */
- fs->space_hard_limit = limit * 1024; /* unit is bytes */
+
+ if (virScaleDouble(&limit, &lunit) < 0)
+ goto error;
+
+ fs->space_soft_limit = (unsigned long long)barrier;
+ fs->space_hard_limit = (unsigned long long)limit;
}
}
diff --git a/src/util/virutil.c b/src/util/virutil.c
index 2edbec5..3b6e617 100644
--- a/src/util/virutil.c
+++ b/src/util/virutil.c
@@ -268,28 +268,12 @@ virHexToBin(unsigned char c)
}
}
-/* Scale an integer VALUE in-place by an optional case-insensitive
- * SUFFIX, defaulting to SCALE if suffix is NULL or empty (scale is
- * typically 1 or 1024). Recognized suffixes include 'b' or 'bytes',
- * as well as power-of-two scaling via binary abbreviations ('KiB',
- * 'MiB', ...) or their one-letter counterpart ('k', 'M', ...), and
- * power-of-ten scaling via SI abbreviations ('KB', 'MB', ...).
- * Ensure that the result does not exceed LIMIT. Return 0 on success,
- * -1 with error message raised on failure. */
int
-virScaleInteger(unsigned long long *value, const char *suffix,
- unsigned long long scale, unsigned long long limit)
+virSuffixToScale(const char *suffix, unsigned long long *scale)
{
- if (!suffix || !*suffix) {
- if (!scale) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("invalid scale %llu"), scale);
- return -1;
- }
- suffix = "";
- } else if (STRCASEEQ(suffix, "b") || STRCASEEQ(suffix, "byte") ||
+ if (STRCASEEQ(suffix, "b") || STRCASEEQ(suffix, "byte") ||
STRCASEEQ(suffix, "bytes")) {
- scale = 1;
+ *scale = 1;
} else {
int base;
@@ -299,28 +283,28 @@ virScaleInteger(unsigned long long *value, const char *suffix,
base = 1000;
} else {
virReportError(VIR_ERR_INVALID_ARG,
- _("unknown suffix '%s'"), suffix);
+ _("unknown suffix '%s'"), suffix);
return -1;
}
- scale = 1;
+ *scale = 1;
switch (c_tolower(*suffix)) {
case 'e':
- scale *= base;
+ *scale *= base;
/* fallthrough */
case 'p':
- scale *= base;
+ *scale *= base;
/* fallthrough */
case 't':
- scale *= base;
+ *scale *= base;
/* fallthrough */
case 'g':
- scale *= base;
+ *scale *= base;
/* fallthrough */
case 'm':
- scale *= base;
+ *scale *= base;
/* fallthrough */
case 'k':
- scale *= base;
+ *scale *= base;
break;
default:
virReportError(VIR_ERR_INVALID_ARG,
@@ -329,6 +313,34 @@ virScaleInteger(unsigned long long *value, const char *suffix,
}
}
+ return 0;
+}
+
+/* Scale an integer VALUE in-place by an optional case-insensitive
+ * SUFFIX, defaulting to SCALE if suffix is NULL or empty (scale is
+ * typically 1 or 1024). Recognized suffixes include 'b' or 'bytes',
+ * as well as power-of-two scaling via binary abbreviations ('KiB',
+ * 'MiB', ...) or their one-letter counterpart ('k', 'M', ...), and
+ * power-of-ten scaling via SI abbreviations ('KB', 'MB', ...).
+ * Ensure that the result does not exceed LIMIT. Return 0 on success,
+ * -1 with error message raised on failure. */
+int
+virScaleInteger(unsigned long long *value, const char *suffix,
+ unsigned long long scale, unsigned long long limit)
+{
+ if (!suffix || !*suffix) {
+ if (!scale) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid scale %llu"), scale);
+ return -1;
+ }
+ suffix = "";
+ } else if (virSuffixToScale(suffix, &scale) < 0) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("unable to parse suffix '%s'"), suffix);
+ return -1;
+ }
+
if (*value && *value > (limit / scale)) {
virReportError(VIR_ERR_OVERFLOW, _("value too large: %llu%s"),
*value, suffix);
@@ -338,6 +350,24 @@ virScaleInteger(unsigned long long *value, const char *suffix,
return 0;
}
+/* Just like virScaleInteger, above, but produce an "double" value. */
+int
+virScaleDouble(double *value, const char *suffix)
+{
+ unsigned long long scale;
+
+ if (!suffix || !*suffix)
+ return -1;
+
+ if (virSuffixToScale(suffix, &scale) < 0) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("unable to parse suffix '%s'"), suffix);
+ return -1;
+ }
+ *value *= scale;
+ return 0;
+}
+
/**
* virParseNumber:
diff --git a/src/util/virutil.h b/src/util/virutil.h
index 89b7923..d74b581 100644
--- a/src/util/virutil.h
+++ b/src/util/virutil.h
@@ -57,6 +57,9 @@ int virScaleInteger(unsigned long long *value, const char *suffix,
unsigned long long scale, unsigned long long limit)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+int virScaleDouble(double *value, const char *suffix)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
int virHexToBin(unsigned char c);
int virParseNumber(const char **str);
--
1.7.1
10 years, 3 months
[libvirt] [PATCH] virprocess: Introduce our own setns() wrapper
by Michal Privoznik
>From time to time weird bugreports occur on the list, e.g [1].
Even though the kernel supports setns syscall, there's an older
glibc in the system that misses a wrapper over the syscall.
Hence, after the configure phase we think there's no setns
support in the system, which is obviously wrong. On the other
hand, we can't rely on linux distributions to provide newer glibc
soon. Therefore we need to introduce the wrapper on or own.
1: https://www.redhat.com/archives/libvir-list/2014-September/msg00492.html
Signed-off-by: Stephan Sachse <ste.sachse(a)gmail.com>
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
The original patch was ACKed already, I've just rebased it to the
current master, and moved the wrapper declaration into
virprocess.c as we don't need to pollute the header file. I've
pushed this then.
src/util/virprocess.c | 57 ++++++++++++++++++++++-----------------------------
1 file changed, 24 insertions(+), 33 deletions(-)
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 97cce4f..b6fcbac 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -27,6 +27,8 @@
#include <errno.h>
#include <stdlib.h>
#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/syscall.h>
#if HAVE_SETRLIMIT
# include <sys/time.h>
# include <sys/resource.h>
@@ -60,6 +62,28 @@
VIR_LOG_INIT("util.process");
+/*
+ * Workaround older glibc. While kernel may support the setns
+ * syscall, the glibc wrapper might not exist. If that's the
+ * case, use our own.
+ */
+#ifndef __NR_setns
+# if defined(__x86_64__)
+# define __NR_setns 308
+# elif defined(__i386__)
+# define __NR_setns 346
+# else
+# error "__NR_setns is not defined"
+# endif
+#endif
+
+#ifndef HAVE_SETNS
+static inline int setns(int fd, int nstype)
+{
+ return syscall(__NR_setns, fd, nstype);
+}
+#endif /* HAVE_SETNS */
+
/**
* virProcessTranslateStatus:
* @status: child exit status to translate
@@ -559,7 +583,6 @@ int virProcessGetAffinity(pid_t pid ATTRIBUTE_UNUSED,
#endif /* HAVE_SCHED_GETAFFINITY */
-#if HAVE_SETNS
int virProcessGetNamespaces(pid_t pid,
size_t *nfdlist,
int **fdlist)
@@ -630,26 +653,6 @@ int virProcessSetNamespaces(size_t nfdlist,
}
return 0;
}
-#else /* ! HAVE_SETNS */
-int virProcessGetNamespaces(pid_t pid,
- size_t *nfdlist ATTRIBUTE_UNUSED,
- int **fdlist ATTRIBUTE_UNUSED)
-{
- virReportSystemError(ENOSYS,
- _("Cannot get namespaces for %llu"),
- (unsigned long long)pid);
- return -1;
-}
-
-
-int virProcessSetNamespaces(size_t nfdlist ATTRIBUTE_UNUSED,
- int *fdlist ATTRIBUTE_UNUSED)
-{
- virReportSystemError(ENOSYS, "%s",
- _("Cannot set namespaces"));
- return -1;
-}
-#endif /* ! HAVE_SETNS */
#if HAVE_PRLIMIT
static int
@@ -905,7 +908,6 @@ int virProcessGetStartTime(pid_t pid,
#endif
-#ifdef HAVE_SETNS
static int virProcessNamespaceHelper(int errfd,
pid_t pid,
virProcessNamespaceCallback cb,
@@ -992,17 +994,6 @@ virProcessRunInMountNamespace(pid_t pid,
VIR_FORCE_CLOSE(errfd[1]);
return ret;
}
-#else /* !HAVE_SETNS */
-int
-virProcessRunInMountNamespace(pid_t pid ATTRIBUTE_UNUSED,
- virProcessNamespaceCallback cb ATTRIBUTE_UNUSED,
- void *opaque ATTRIBUTE_UNUSED)
-{
- virReportSystemError(ENOSYS, "%s",
- _("Mount namespaces are not available on this platform"));
- return -1;
-}
-#endif
/**
--
1.8.5.5
10 years, 3 months
[libvirt] [PATCH] node_device_udev: Try harder to get human readable vendor:product
by Lubomir Rintel
The manufacurer and product from USB device itself are usually not particularly
useful -- they tend to be missing, or ugly (all-uppercase, padded with spaces,
etc.). Prefer what's in the usb id database and fall back to descriptors only
if the device is too now to be in database.
---
Before: http://v3.sk/~lkundrak/virt/old.png
After: http://v3.sk/~lkundrak/virt/libvirt.png
src/node_device/node_device_udev.c | 27 +++++++++++++++++++++------
1 file changed, 21 insertions(+), 6 deletions(-)
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 0fe474d..53792f0 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -580,6 +580,7 @@ static int udevProcessUSBDevice(struct udev_device *device,
{
union _virNodeDevCapData *data = &def->caps->data;
int ret = -1;
+ int err;
if (udevGetUintProperty(device,
"BUSNUM",
@@ -602,10 +603,17 @@ static int udevProcessUSBDevice(struct udev_device *device,
goto out;
}
- if (udevGetStringSysfsAttr(device,
- "manufacturer",
- &data->usb_dev.vendor_name) == PROPERTY_ERROR) {
+ err = udevGetStringProperty(device,
+ "ID_VENDOR_FROM_DATABASE",
+ &data->usb_dev.vendor_name);
+ if (err == PROPERTY_ERROR)
goto out;
+ if (err == PROPERTY_MISSING) {
+ if (udevGetStringSysfsAttr(device,
+ "manufacturer",
+ &data->usb_dev.vendor_name) == PROPERTY_ERROR) {
+ goto out;
+ }
}
if (udevGetUintProperty(device,
@@ -615,10 +623,17 @@ static int udevProcessUSBDevice(struct udev_device *device,
goto out;
}
- if (udevGetStringSysfsAttr(device,
- "product",
- &data->usb_dev.product_name) == PROPERTY_ERROR) {
+ err = udevGetStringProperty(device,
+ "ID_MODEL_FROM_DATABASE",
+ &data->usb_dev.product_name);
+ if (err == PROPERTY_ERROR)
goto out;
+ if (err == PROPERTY_MISSING) {
+ if (udevGetStringSysfsAttr(device,
+ "product",
+ &data->usb_dev.product_name) == PROPERTY_ERROR) {
+ goto out;
+ }
}
if (udevGenerateDeviceName(device, def, NULL) != 0) {
--
1.9.3
10 years, 3 months
[libvirt] [PATCH v2 0/5] Introduce new cputune event
by Pavel Hrdina
This patch series introduce new cputune event to inform
management applications about every change of cputune values
for running domains.
The first patch introduces a new string helper virSnprintf
and the second patch cleans up the virDomanDef structure.
There is missing documentation for all events so the documentation
for this event will be part of the patches to document all events.
Changes from v1:
- new virSnprintf helper
- complete cleanup of virDomainDef structure
- cputune event now uses virTypedParameter
Pavel Hrdina (5):
introduce virSnprintf helper
domain_conf: separate structures from virDomainDef
event: introduce new event for cputune
add an example how to use cputune event
cputune_event: queue the event for cputune updates
daemon/remote.c | 45 ++++++++++++++++++
examples/object-events/event-test.c | 52 +++++++++++++++++++-
include/libvirt/libvirt.h.in | 19 ++++++++
src/conf/domain_conf.h | 94 ++++++++++++++++++++++---------------
src/conf/domain_event.c | 84 +++++++++++++++++++++++++++++++++
src/conf/domain_event.h | 9 ++++
src/libvirt_private.syms | 3 ++
src/qemu/qemu_cgroup.c | 18 ++++++-
src/qemu/qemu_driver.c | 73 ++++++++++++++++++++++++++++
src/remote/remote_driver.c | 41 ++++++++++++++++
src/remote/remote_protocol.x | 14 +++++-
src/remote_protocol-structs | 9 ++++
src/util/virstring.c | 25 ++++++++++
src/util/virstring.h | 20 ++++++++
tools/virsh-domain.c | 33 +++++++++++++
15 files changed, 499 insertions(+), 40 deletions(-)
--
1.8.5.5
10 years, 3 months
[libvirt] [PATCH V2 0/2] cpu: Handle only high order 16 bits of PVR for IBM Power processors
by Pradipta Kr. Banerjee
IBM Power processors encode PVR as CPU family in high order 16 bits and a CPU
version in lower 16 bits. Since there is no significant change in behavior
between versions, there is no point adding every single CPU version in
cpu_map.xml. Qemu for ppc64 already have the necessary changes.
V2:
- Incorporate Martin comments from V1
- Rewrite the cpu_map.xml for IBM Power processors
Pradipta Kr. Banerjee (2):
Handle only high order 16 bits for PVR
Update cputest test cases for the updated IBM Power processor models
src/cpu/cpu_map.xml | 22 ++++++++--------------
src/cpu/cpu_powerpc.c | 7 ++++++-
tests/cputest.c | 4 ++--
tests/cputestdata/ppc64-baseline-1-result.xml | 2 +-
.../ppc64-baseline-incompatible-vendors.xml | 4 ++--
.../ppc64-baseline-no-vendor-result.xml | 2 +-
tests/cputestdata/ppc64-baseline-no-vendor.xml | 2 +-
tests/cputestdata/ppc64-exact.xml | 2 +-
tests/cputestdata/ppc64-guest-nofallback.xml | 2 +-
tests/cputestdata/ppc64-guest.xml | 2 +-
.../ppc64-host+guest,ppc_models-result.xml | 2 +-
...st-nofallback,ppc_models,POWER7_v2.1-result.xml | 5 -----
tests/cputestdata/ppc64-host.xml | 2 +-
tests/cputestdata/ppc64-strict.xml | 2 +-
.../qemuxml2argv-pseries-cpu-exact.args | 4 ++--
.../qemuxml2argv-pseries-cpu-exact.xml | 2 +-
16 files changed, 30 insertions(+), 36 deletions(-)
delete mode 100644 tests/cputestdata/ppc64-host+guest-nofallback,ppc_models,POWER7_v2.1-result.xml
--
1.9.3
10 years, 3 months
[libvirt] [PATCH] New features implemented in hyperv libvirt driver (Bull)
by Yves Vinter
Authors: Simon Rastello (Bull), Adrien Kantcheff (Bull), Yves Vinter (Bull)
Summary of new added features by modules:
hyperv_driver.c
- hypervDomainDefineXML
- hypervDomainCreateXML
- hypervDomainUndefine
- hypervDomainUndefineFlags
- hypervDomainShutdown
- hypervDomainShutdownFlags
- hypervDomainGetVcpus
- hypervDomainGetVcpusFlags
- hypervConnectGetMaxVcpus
- hypervDomainGetMaxVcpus
- hypervDomainSetVcpus
- hypervDomainSetVcpusFlags
- hypervDomainSetMemory
- hypervDomainSetMemoryFlags
- hypervDomainSetMaxMemory
- hypervNodeGetFreeMemory
- hypervDomainAttachDevice
- hypervDomainAttachDeviceFlags
- hypervDomainGetSchedulerParameters
- hypervDomainGetSchedulerParametersFlags
- hypervDomainGetSchedulerType
- hypervConnectGetCapabilities
- hypervConnectGetVersion
- hypervDomainSetAutostart
- hypervDomainGetAutostart
hyperv_network.c
- hypervConnectNumOfNetworks
- hypervConnectListNetworks
- hypervConnectNumOfDefinedNetworks
- hypervConnectListDefinedNetworks
- hypervNetworkLookupByName
- hypervNetworkGetXMLDesc
hyperv_private.h
- Add mutex to protect against concurrent calls
(the openwsman library being not thread-safe,
as reported in issue #10 Simultaneous WsMan queries)
- Add virDomainXMLOptionPtr to parse Domain XML
hyperv_wmi.h
- Structures for passing complex arguments:
objects, EPR (end point references) and embedded instances
hyperv_wmi.c
- Methods to invoke WMI methods with complex arguments
hyperv_wmi_generator.input
- CIM_DataFile
- Win32_ComputerSystemProduct
- Msvm_VirtualSystemManagementService
- Msvm_VirtualSystemGlobalSettingData
- Msvm_ResourceAllocationSettingData
- Msvm_AllocationCapabilities
- Msvm_VirtualSwitch
- Msvm_SwitchPort
- Msvm_SyntheticEthernetPortSettingData
- Msvm_VirtualSwitchManagementService
- Win32_OperatingSystem
- Win32_PerfFormattedData_HvStats_HyperVHypervisorVirtualProcessor
- Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
hyperv_wmi_generator.py
- Add CIM_DataFile class header to be generated
- Add tab classes and types to be generated
- Add a function to print header types
openwsman.h
- Add ws_xml_create_doc function prototype
- Add xml_parser_get_root function prototype
Reported-by: Yves Vinter <yves.vinter(a)bull.net>
---
diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index aed9307..bdf45a7 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -42,6 +42,12 @@
#include "openwsman.h"
#include "virstring.h"
+/* Bull */
+#include "virtypedparam.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
#define VIR_FROM_THIS VIR_FROM_HYPERV
VIR_LOG_INIT("hyperv.hyperv_driver");
@@ -58,12 +64,97 @@ hypervFreePrivate(hypervPrivate **priv)
wsmc_release((*priv)->client);
}
+ /* Bull */
+ pthread_mutex_destroy(&(*priv)->mutex);
+
hypervFreeParsedUri(&(*priv)->parsedUri);
VIR_FREE(*priv);
}
+/* Bull */
+static int
+hypervLookupHostSystemBiosUuid(hypervPrivate *priv, unsigned char *uuid)
+{
+ Win32_ComputerSystemProduct *computerSystem = NULL;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ int result = -1;
+
+ virBufferAddLit(&query, WIN32_COMPUTERSYSTEMPRODUCT_WQL_SELECT);
+
+ if (hypervGetWin32ComputerSystemProductList(priv, &query, &computerSystem) < 0) {
+ goto cleanup;
+ }
+
+ if (computerSystem == NULL) {
+ virReportError(VIR_ERR_NO_DOMAIN,
+ _("Unable to get Win32_ComputerSystemProduct"));
+ goto cleanup;
+ }
+
+ if (virUUIDParse(computerSystem->data->UUID, uuid) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse UUID from string '%s'"),
+ computerSystem->data->UUID);
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
+ return result;
+}
+
+
+
+/* Bull */
+static virCapsPtr hypervCapsInit(hypervPrivate *priv)
+{
+ virCapsPtr caps = NULL;
+ virCapsGuestPtr guest = NULL;
+
+ caps = virCapabilitiesNew(VIR_ARCH_X86_64, 1, 1);
+
+ if (caps == NULL) {
+ virReportOOMError();
+ return NULL;
+ }
+ //virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x0c, 0x29 });
+
+ if (hypervLookupHostSystemBiosUuid(priv,caps->host.host_uuid) < 0) {
+ goto failure;
+ }
+
+ /* i686 */
+ guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_I686, NULL, NULL, 0, NULL);
+ if (guest == NULL) {
+ goto failure;
+ }
+ if (virCapabilitiesAddGuestDomain(guest, "hyperv", NULL, NULL, 0, NULL) == NULL) {
+ goto failure;
+ }
+
+ /* x86_64 */
+ guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_X86_64, NULL, NULL, 0, NULL);
+ if (guest == NULL) {
+ goto failure;
+ }
+ if (virCapabilitiesAddGuestDomain(guest, "hyperv", NULL, NULL, 0, NULL) == NULL) {
+ goto failure;
+ }
+
+ return caps;
+
+ failure:
+ virObjectUnref(caps);
+ return NULL;
+}
+
+
+
static virDrvOpenStatus
hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
{
@@ -108,12 +199,17 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags
return VIR_DRV_OPEN_ERROR;
}
- /* Require auth */
- if (auth == NULL || auth->cb == NULL) {
- virReportError(VIR_ERR_INVALID_ARG, "%s",
- _("Missing or invalid auth pointer"));
- return VIR_DRV_OPEN_ERROR;
- }
+ /* Require auth */
+ /* Bull - if auth is null, auth=virConnectAuthPtrDefault */
+ if (auth == NULL)
+ auth = virConnectAuthPtrDefault;
+ else {
+ if (auth->cb == NULL) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Missing or invalid auth pointer"));
+ return VIR_DRV_OPEN_ERROR;
+ }
+ }
/* Allocate per-connection private data */
if (VIR_ALLOC(priv) < 0)
@@ -192,14 +288,28 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags
goto cleanup;
}
+ /* Bull - Setup capabilities */
+ priv->caps = hypervCapsInit(priv);
+ if (priv->caps == NULL) {
+ goto cleanup;
+ }
+
+ /* Bull - Init xmlopt to parse Domain XML */
+ priv->xmlopt = virDomainXMLOptionNew(NULL, NULL, NULL);
+
conn->privateData = priv;
- priv = NULL;
+
+ /* Bull */
+ pthread_mutex_init(&priv->mutex, NULL);
+
+ priv = NULL;
result = VIR_DRV_OPEN_SUCCESS;
cleanup:
hypervFreePrivate(&priv);
VIR_FREE(username);
VIR_FREE(password);
+ virBufferFreeAndReset(&query);
hypervFreeObject(priv, (hypervObject *)computerSystem);
return result;
@@ -254,6 +364,7 @@ hypervConnectGetHostname(virConnectPtr conn)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
return hostname;
}
@@ -352,6 +463,7 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
hypervFreeObject(priv, (hypervObject *)processorList);
+ virBufferFreeAndReset(&query);
return result;
}
@@ -396,6 +508,7 @@ hypervConnectListDomains(virConnectPtr conn, int *ids, int maxids)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return success ? count : -1;
}
@@ -432,6 +545,7 @@ hypervConnectNumOfDomains(virConnectPtr conn)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return success ? count : -1;
}
@@ -464,6 +578,7 @@ hypervDomainLookupByID(virConnectPtr conn, int id)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
return domain;
}
@@ -500,6 +615,7 @@ hypervDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
return domain;
}
@@ -533,6 +649,7 @@ hypervDomainLookupByName(virConnectPtr conn, const char *name)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
return domain;
}
@@ -748,6 +865,7 @@ hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
hypervFreeObject(priv, (hypervObject *)processorSettingData);
hypervFreeObject(priv, (hypervObject *)memorySettingData);
+ virBufferFreeAndReset(&query);
return result;
}
@@ -915,6 +1033,7 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
hypervFreeObject(priv, (hypervObject *)processorSettingData);
hypervFreeObject(priv, (hypervObject *)memorySettingData);
+ virBufferFreeAndReset(&query);
return xml;
}
@@ -971,6 +1090,7 @@ hypervConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxn
}
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return count;
}
@@ -1007,6 +1127,7 @@ hypervConnectNumOfDefinedDomains(virConnectPtr conn)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return success ? count : -1;
}
@@ -1346,6 +1467,7 @@ hypervConnectListAllDomains(virConnectPtr conn,
}
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return ret;
}
@@ -1353,6 +1475,1767 @@ hypervConnectListAllDomains(virConnectPtr conn,
+/* Bull */
+static int
+hypervConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
+{
+ int res = -1;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_ProcessorSettingData *processorSettingData = NULL;
+
+ /* Get Msvm_ProcessorSettingData maximum definition */
+ virBufferAddLit(&query, "SELECT * FROM Msvm_ProcessorSettingData "
+ "WHERE InstanceID LIKE 'Microsoft:Definition%Maximum'");
+
+ if (hypervGetMsvmProcessorSettingDataList(priv, &query, &processorSettingData) < 0) {
+ goto cleanup;
+ }
+
+ if (processorSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get maximum definition of Msvm_ProcessorSettingData"));
+ goto cleanup;
+ }
+
+ res = processorSettingData->data->SocketCount *
+ processorSettingData->data->ProcessorsPerSocket;
+
+ cleanup:
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) processorSettingData);
+ return res;
+}
+
+
+
+/* Bull */
+static int
+hypervDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
+{
+ int ret = -1;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ Msvm_ComputerSystem *computerSystem = NULL;
+ Msvm_ProcessorSettingData *processorSettingData = NULL;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |VIR_DOMAIN_VCPU_CONFIG |VIR_DOMAIN_VCPU_MAXIMUM, -1);
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ /* Get Msvm_ComputerSystem */
+ if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
+ goto cleanup;
+ }
+
+ // If @flags includes VIR_DOMAIN_VCPU_LIVE,
+ // this will query a running domain (which will fail if domain is not active)
+ if (flags & VIR_DOMAIN_VCPU_LIVE) {
+ if (computerSystem->data->EnabledState != MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not active"));
+ goto cleanup;
+ }
+ }
+
+ // If @flags includes VIR_DOMAIN_VCPU_MAXIMUM, then the maximum virtual CPU limit is queried
+ if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
+ ret = hypervConnectGetMaxVcpus(domain->conn, NULL);
+ goto cleanup;
+ }
+
+ /* Get Msvm_VirtualSystemSettingData */
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
+ &virtualSystemSettingData) < 0) {
+ goto cleanup;
+ }
+ if (virtualSystemSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain %s"),
+ "Msvm_VirtualSystemSettingData", computerSystem->data->ElementName);
+ goto cleanup;
+ }
+
+ /* Get Msvm_ProcessorSettingData */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
+ "ResultClass = Msvm_ProcessorSettingData",
+ virtualSystemSettingData->data->InstanceID);
+ if (hypervGetMsvmProcessorSettingDataList(priv, &query,
+ &processorSettingData) < 0) {
+ goto cleanup;
+ }
+ if (processorSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain %s"),
+ "Msvm_ProcessorSettingData", computerSystem->data->ElementName);
+ goto cleanup;
+ }
+
+ ret = processorSettingData->data->VirtualQuantity;
+
+cleanup:
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)processorSettingData);
+ return ret;
+}
+
+
+
+/* Bull */
+static int
+hypervDomainGetMaxVcpus(virDomainPtr dom)
+{
+ // If the guest is inactive, this is basically the same as virConnectGetMaxVcpus()
+ return (hypervDomainIsActive(dom)) ?
+ hypervDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |VIR_DOMAIN_VCPU_MAXIMUM))
+ : hypervConnectGetMaxVcpus(dom->conn, NULL);
+}
+
+
+
+/* Bull */
+static int
+hypervDomainShutdownFlags(virDomainPtr domain, unsigned int flags)
+{
+ int result = -1;
+ hypervPrivate *priv = domain->conn->privateData;
+ Msvm_ComputerSystem *computerSystem = NULL;
+ bool in_transition = false;
+
+ virCheckFlags(0, -1);
+
+ if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
+ goto cleanup;
+ }
+
+ if (!hypervIsMsvmComputerSystemActive(computerSystem, &in_transition) ||
+ in_transition) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("Domain is not active or is in state transition"));
+ goto cleanup;
+ }
+
+ result = hypervInvokeMsvmComputerSystemRequestStateChange
+ (domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_DISABLED);
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ return result;
+}
+
+
+
+/* Bull */
+static int hypervDomainShutdown(virDomainPtr dom)
+{
+ return hypervDomainShutdownFlags(dom, 0);
+}
+
+
+
+/* Bull */
+static int
+hypervDomainGetSchedulerParametersFlags(virDomainPtr dom, virTypedParameterPtr params,
+ int *nparams, unsigned int flags)
+{
+ hypervPrivate *priv = dom->conn->privateData;
+ Msvm_ComputerSystem *computerSystem = NULL;
+ Msvm_ProcessorSettingData *processorSettingData = NULL;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ int ret = -1;
+ int saved_nparams = 0;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |VIR_DOMAIN_AFFECT_CONFIG |VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+ /* We don't return strings, and thus trivially support this flag. */
+ flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
+
+ virUUIDFormat(dom->uuid, uuid_string);
+
+ /* Get Msvm_ComputerSystem */
+ if (hypervMsvmComputerSystemFromDomain(dom, &computerSystem) < 0) { goto cleanup;}
+
+ /* Get Msvm_VirtualSystemSettingData */
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
+ &virtualSystemSettingData) < 0) {
+ goto cleanup;
+ }
+
+ if (virtualSystemSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for domain %s"),
+ "Msvm_VirtualSystemSettingData",
+ computerSystem->data->ElementName);
+ goto cleanup;
+ }
+
+ /* Get Msvm_ProcessorSettingData */
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
+ "ResultClass = Msvm_ProcessorSettingData",
+ virtualSystemSettingData->data->InstanceID);
+
+ if (hypervGetMsvmProcessorSettingDataList(priv, &query,
+ &processorSettingData) < 0) {
+ goto cleanup;
+ }
+
+ if (processorSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain %s"),
+ "Msvm_ProcessorSettingData",computerSystem->data->ElementName);
+ goto cleanup;
+ }
+
+ if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_SCHEDULER_LIMIT,
+ VIR_TYPED_PARAM_LLONG, processorSettingData->data->Limit) < 0)
+ goto cleanup;
+ saved_nparams++;
+
+ if (*nparams > saved_nparams) {
+ if (virTypedParameterAssign(¶ms[1],VIR_DOMAIN_SCHEDULER_RESERVATION,
+ VIR_TYPED_PARAM_LLONG, processorSettingData->data->Reservation) < 0)
+ goto cleanup;
+ saved_nparams++;
+ }
+
+ if (*nparams > saved_nparams) {
+ if (virTypedParameterAssign(¶ms[2],VIR_DOMAIN_SCHEDULER_WEIGHT,
+ VIR_TYPED_PARAM_UINT, processorSettingData->data->Weight) < 0)
+ goto cleanup;
+ saved_nparams++;
+ }
+
+ *nparams = saved_nparams;
+
+ ret = 0;
+
+cleanup:
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)processorSettingData);
+ virBufferFreeAndReset(&query);
+ return ret;
+}
+
+
+
+/* Bull */
+static int
+hypervDomainGetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params, int *nparams)
+{
+ return hypervDomainGetSchedulerParametersFlags(dom, params, nparams, VIR_DOMAIN_AFFECT_CURRENT);
+}
+
+
+
+/* Bull */
+static char*
+hypervDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED, int *nparams)
+{
+ char *type = strdup("allocation");
+
+ if (type == NULL) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ if (nparams != NULL) {
+ *nparams = 3; /* reservation, limit, weight */
+ }
+
+ return type;
+}
+
+
+
+/* Bull */
+static char*
+hypervConnectGetCapabilities(virConnectPtr conn)
+{
+ hypervPrivate *priv = conn->privateData;
+ char *xml = virCapabilitiesFormatXML(priv->caps);
+
+ if (xml == NULL) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ return xml;
+}
+
+
+/* Bull */
+static int
+hypervConnectGetVersion(virConnectPtr conn, unsigned long *version)
+{
+ int ret = -1;
+ hypervPrivate *priv = conn->privateData;
+ CIM_DataFile *datafile = NULL;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ char * p;
+
+ virBufferAddLit(&query, " Select * from CIM_DataFile where Name='c:\\\\windows\\\\system32\\\\vmms.exe' ");
+
+ if (hypervGetCIMDataFileList(priv, &query, &datafile) < 0) {goto cleanup;}
+
+ // check the result of convertion
+ if (datafile == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for domain %s"),
+ "Msvm_VirtualSystemSettingData",
+ datafile->data->Version);
+ goto cleanup;
+ }
+
+ /* Delete release number and last digit of build number 1.1.111x.xxxx */
+ p=strrchr(datafile->data->Version,'.');
+ datafile->data->Version[p-datafile->data->Version-1] = '\0';
+
+ /*Parse Version String to Long*/
+ if (virParseVersionString(datafile->data->Version,
+ version, true) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse version number from '%s'"),
+ datafile->data->Version);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)datafile);
+ //VIR_FREE(p);
+ virBufferFreeAndReset(&query);
+ return ret;
+}
+
+
+
+/* Bull */
+static unsigned long long
+hypervNodeGetFreeMemory(virConnectPtr conn)
+{
+ unsigned long long res = 0;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Win32_OperatingSystem *operatingSystem = NULL;
+
+ /* Get Win32_OperatingSystem */
+ virBufferAddLit(&query, WIN32_OPERATINGSYSTEM_WQL_SELECT);
+
+ if (hypervGetWin32OperatingSystemList(priv, &query, &operatingSystem) < 0) {
+ goto cleanup;
+ }
+
+ if (operatingSystem == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get Win32_OperatingSystem"));
+ goto cleanup;
+ }
+
+ // return free memory in bytes
+ res = operatingSystem->data->FreePhysicalMemory * 1024;
+
+ cleanup:
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) operatingSystem);
+ return res;
+}
+
+
+
+/* Bull */
+static int
+hypervDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
+ unsigned char *cpumaps, int maplen)
+{
+ int count = 0, i;
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
+ *hypervVirtualProcessor = NULL;
+
+ //FIXME: no information stored in cpumaps
+ if (cpumaps != NULL) {
+ cpumaps = (unsigned char *) calloc(maxinfo, maplen);
+ }
+
+ /* Loop for each vCPU */
+ for (i = 0; i < maxinfo; i++) {
+
+ /* Get vCPU stats */
+ hypervFreeObject(priv, (hypervObject *)hypervVirtualProcessor);
+ hypervVirtualProcessor = NULL;
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query,
+ WIN32_PERFRAWDATA_HVSTATS_HYPERVHYPERVISORVIRTUALPROCESSOR_WQL_SELECT);
+ // Attribute Name format : <domain_name>:Hv VP <vCPU_number>
+ virBufferAsprintf(&query, "where Name = \"%s:Hv VP %d\"", domain->name, i);
+
+ if (hypervGetWin32PerfRawDataHvStatsHyperVHypervisorVirtualProcessorList(
+ priv, &query, &hypervVirtualProcessor) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get stats on vCPU #%d"), i);
+ continue;
+ }
+
+ /* Fill structure info */
+ info[i].number = i;
+ if (hypervVirtualProcessor == NULL) {
+ info[i].state = VIR_VCPU_OFFLINE;
+ info[i].cpuTime = 0LLU;
+ info[i].cpu = -1;
+ } else {
+ info[i].state = VIR_VCPU_RUNNING;
+ info[i].cpuTime = hypervVirtualProcessor->data->PercentTotalRunTime;
+ info[i].cpu = i;
+ }
+
+ count++;
+ }
+
+ hypervFreeObject(priv, (hypervObject *)hypervVirtualProcessor);
+ virBufferFreeAndReset(&query);
+ return count;
+}
+
+
+
+static int
+hypervDomainSetAutostart(virDomainPtr domain, int autostart)
+{
+ int res = -1;
+ invokeXmlParam *params;
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ virBuffer queryVssd = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ properties_t *tab_props;
+ eprParam eprparam;
+ embeddedParam embeddedparam;
+ int nb_params;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService";
+ // Convert autostart integer to string
+ const int n = snprintf(NULL, 0, "%u", autostart);
+ char autostart_str[n+1];
+ sprintf(autostart_str, "%u", autostart);
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ /* PREPARE EPR PARAM */
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"",uuid_string);
+ eprparam.query = &query;
+ eprparam.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ /* PREPARE EMBEDDED PARAM */
+ virBufferAsprintf(&queryVssd,
+ "associators of "
+ "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &queryVssd,
+ &virtualSystemSettingData) < 0) {
+ goto cleanup;
+ }
+
+ embeddedparam.nbProps = 2;
+ tab_props = (properties_t *) malloc(embeddedparam.nbProps * sizeof(properties_t));
+ (*tab_props).name = "AutomaticStartupAction";
+ //(*tab_props).val = autostart ? "1" : "2";;
+ (*tab_props).val = autostart_str;
+ (*(tab_props+1)).name = "InstanceID";
+ (*(tab_props+1)).val = virtualSystemSettingData->data->InstanceID;
+
+ embeddedparam.instanceName = "Msvm_VirtualSystemGlobalSettingData";
+ embeddedparam.prop_t = tab_props;
+
+ /* CREATE invokeXmlParam tab */
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "ComputerSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam;
+ (*(params+1)).name = "SystemSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam;
+
+ res = hypervInvokeMethod(priv, params, nb_params, "ModifyVirtualSystem",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector);
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ VIR_FREE(tab_props);
+ VIR_FREE(params);
+ virBufferFreeAndReset(&query);
+ virBufferFreeAndReset(&queryVssd);
+ return res;
+}
+
+
+
+static int
+hypervDomainGetAutostart(virDomainPtr domain, int *autostart)
+{
+ int res = -1;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemGlobalSettingData *vsgsd = NULL;
+
+ virUUIDFormat(domain->uuid, uuid_string);
+ virBufferAddLit(&query, MSVM_VIRTUALSYSTEMGLOBALSETTINGDATA_WQL_SELECT);
+ virBufferAsprintf(&query, "where SystemName = \"%s\"", uuid_string);
+
+ if (hypervGetMsvmVirtualSystemGlobalSettingDataList(priv,
+ &query, &vsgsd) < 0) {
+ goto cleanup;
+ }
+
+ *autostart = vsgsd->data->AutomaticStartupAction;
+ res = 0;
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)vsgsd);
+ virBufferFreeAndReset(&query);
+ return res;
+}
+
+
+
+static int
+hypervDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
+{
+ int res = -1;
+ invokeXmlParam *params;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ properties_t *tab_props;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ virBuffer query2 = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ Msvm_MemorySettingData *memorySettingData = NULL;
+ eprParam eprparam;
+ embeddedParam embeddedparam;
+ int nb_params;
+ const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService";
+ // Convert memory to string in Mb
+ const unsigned long memoryMb = memory/1024;
+ const int n = snprintf(NULL, 0, "%lu", memoryMb);
+ char memory_str[n+1];
+ sprintf(memory_str, "%lu", memoryMb);
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ VIR_DEBUG("memory=%sMb, uuid=%s", memory_str, uuid_string);
+
+ // PREPARE EPR PARAM
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"",uuid_string);
+ eprparam.query = &query;
+ eprparam.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE EMBEDDED PARAM 1
+ /* Get Msvm_VirtualSystemSettingData */
+ virBufferAsprintf(&query2,
+ "associators of "
+ "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query2,
+ &virtualSystemSettingData) < 0) {
+ goto cleanup;
+ }
+
+ /* Get Msvm_MemorySettingData */
+ virBufferFreeAndReset(&query2);
+ virBufferAsprintf(&query2,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
+ "ResultClass = Msvm_MemorySettingData",
+ virtualSystemSettingData->data->InstanceID);
+
+ if (hypervGetMsvmMemorySettingDataList(priv, &query2,
+ &memorySettingData) < 0) {
+ goto cleanup;
+ }
+
+ embeddedparam.nbProps = 2;
+ tab_props = (properties_t *) malloc(embeddedparam.nbProps * sizeof(properties_t));
+ (*tab_props).name = "Limit";
+ (*tab_props).val = memory_str;
+ (*(tab_props+1)).name = "InstanceID";
+ (*(tab_props+1)).val = memorySettingData->data->InstanceID;
+ embeddedparam.instanceName = "Msvm_MemorySettingData";
+ embeddedparam.prop_t = tab_props;
+ embeddedparam.nbProps = 2;
+
+ // CREATE invokeXmlParam
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+
+ (*params).name = "ComputerSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam;
+ (*(params+1)).name = "ResourceSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam;
+
+ res = hypervInvokeMethod(priv, params, nb_params, "ModifyVirtualSystemResources",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector);
+
+ cleanup:
+ VIR_FREE(tab_props);
+ VIR_FREE(params);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)memorySettingData);
+ virBufferFreeAndReset(&query);
+ virBufferFreeAndReset(&query2);
+ return res;
+}
+
+
+
+/* Bull */
+/*
+ * Create the attribute __PATH for the RASD object. The attribute is build like this:
+ * \\<host_name>\root\virtualization:Msvm_ResourceAllocationSettingData.InstanceID="<rasdInstanceID>"
+ * where backslashes in rasdInstanceID are doubled
+ */
+static int
+hypervGetResourceAllocationSettingDataPATH(virDomainPtr domain, char *rasdInstanceID, char **__path)
+{
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_ComputerSystem *computerSystem = NULL;
+ char *strTemp = NULL;
+ int ret = -1, i = 0, j = 0, n = 0;
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ /* Get host name */
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_HostedDependency "
+ "ResultClass = Msvm_ComputerSystem",
+ uuid_string);
+ if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) {
+ goto cleanup;
+ }
+ if (computerSystem == NULL) {
+ virReportError(VIR_ERR_NO_DOMAIN, _("No domain with UUID %s"), uuid_string);
+ goto cleanup;
+ }
+
+ /* Double the blackslashes */
+ //FIXME: normally there are only 2 backslashes in rasdInstanceID
+ /* Count the number of backslash character */
+ strTemp = strchr(rasdInstanceID, '\\');
+ while (strTemp != NULL) {
+ n++;
+ strTemp = strchr(++strTemp, '\\');
+ }
+ strTemp = (char *) malloc(strlen(rasdInstanceID) + (n * sizeof(char)) + 1);
+ while (rasdInstanceID[i] != '\0') {
+ strTemp[j] = rasdInstanceID[i];
+ if (rasdInstanceID[i] == '\\') {
+ j++;
+ strTemp[j] = '\\';
+ }
+ i++;
+ j++;
+ }
+
+ /* Create the attribute __PATH */
+ //FIXME: ret is allocated with 255 characters (static value)
+ *__path = (char *) malloc(sizeof(*__path) * 255);
+ sprintf(*__path, "\\\\");
+ strcat(*__path, computerSystem->data->ElementName);
+ strcat(*__path, "\\root\\virtualization:Msvm_ResourceAllocationSettingData.InstanceID=\"");
+ strcat(*__path, strTemp);
+ strcat(*__path, "\"");
+
+ ret = 0;
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
+ free(strTemp);
+ return ret;
+}
+
+
+
+/* Bull */
+/*
+ * Create the attribute __PATH for the SwitchPort object. The attribute is build like this:
+ * \\<host_name>\root\virtualization:Msvm_SwitchPort.CreationClassName="Msvm_SwitchPort",
+ * Name="<switchPortName>",SystemCreationClassName="Msvm_VirtualSwitch",
+ * SystemName="<virtualSwitchSystemName>"
+ */
+static int
+hypervGetSwitchPortPATH(virDomainPtr domain, char *switchPortName,
+ char *virtualSwitchSystemName, char **__path)
+{
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_ComputerSystem *computerSystem = NULL;
+ char *strTemp = NULL;
+ int ret = -1;
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ /* Get host name */
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_HostedDependency "
+ "ResultClass = Msvm_ComputerSystem",
+ uuid_string);
+ if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) {
+ goto cleanup;
+ }
+ if (computerSystem == NULL) {
+ virReportError(VIR_ERR_NO_DOMAIN,
+ _("No domain with UUID %s"), uuid_string);
+ goto cleanup;
+ }
+
+
+ /* Create the attribute __PATH */
+ //FIXME: ret is allocated with 511 characters (static value)
+ *__path = (char *) malloc(sizeof(*__path) * 511);
+ sprintf(*__path,
+ "\\\\%s\\root\\virtualization:Msvm_SwitchPort.CreationClassName=\"Msvm_SwitchPort\","
+ "Name=\"%s\",SystemCreationClassName=\"Msvm_VirtualSwitch\",SystemName=\"%s\"",
+ computerSystem->data->ElementName, switchPortName, virtualSwitchSystemName);
+
+ ret = 0;
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
+ free(strTemp);
+ return ret;
+}
+
+
+
+/* Bull */
+/*
+ * Memory size in KiB
+ */
+static int
+hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ int res = -1, nb_params;
+ const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService";
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ invokeXmlParam *params;
+ properties_t *tab_props;
+ eprParam eprparam;
+ embeddedParam embeddedparam;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ Msvm_MemorySettingData *memorySettingData = NULL;
+ // Convert memory to string in Mb
+ const unsigned long memoryMb = memory/1024;
+ const int n = snprintf(NULL, 0, "%lu", memoryMb);
+ char memory_str[n+1];
+ sprintf(memory_str, "%lu", memoryMb);
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ VIR_DEBUG("memory=%sMb, uuid=%s", memory_str, uuid_string);
+
+ /* Get Msvm_VirtualSystemSettingData */
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
+ &virtualSystemSettingData) < 0) {
+ goto cleanup;
+ }
+
+ /* Get Msvm_MemorySettingData */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
+ "ResultClass = Msvm_MemorySettingData",
+ virtualSystemSettingData->data->InstanceID);
+ if (hypervGetMsvmMemorySettingDataList(priv, &query,
+ &memorySettingData) < 0) {
+ goto cleanup;
+ }
+
+ // PREPARE EPR PARAM
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"",uuid_string);
+ eprparam.query = &query;
+ eprparam.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE EMBEDDED PARAM
+ embeddedparam.nbProps = 2;
+ tab_props = (properties_t *) malloc(embeddedparam.nbProps * sizeof(properties_t));
+ (*tab_props).name = "VirtualQuantity";
+ (*tab_props).val = memory_str;
+ (*(tab_props+1)).name = "InstanceID";
+ (*(tab_props+1)).val = memorySettingData->data->InstanceID;
+ embeddedparam.instanceName = "Msvm_MemorySettingData";
+ embeddedparam.prop_t = tab_props;
+
+ // CREATE invokeXmlParam
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "ComputerSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam;
+ (*(params+1)).name = "ResourceSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam;
+
+ if (hypervInvokeMethod(priv, params, nb_params, "ModifyVirtualSystemResources",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not set domain memory"));
+ goto cleanup;
+ }
+
+ res = 0;
+
+ cleanup:
+ VIR_FREE(tab_props);
+ VIR_FREE(params);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)memorySettingData);
+ virBufferFreeAndReset(&query);
+ return res;
+}
+
+
+/* Bull */
+static int
+hypervDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+ return hypervDomainSetMemoryFlags(domain, memory, 0);
+}
+
+
+/* Bull */
+static int
+hypervDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ int res = -1;
+ invokeXmlParam *params;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ properties_t *tab_props;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ Msvm_ProcessorSettingData *processorSettingData = NULL;
+ eprParam eprparam;
+ embeddedParam embeddedparam;
+ int nb_params;
+ const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService";
+ // Convert nvcpus to string
+ const int n = snprintf(NULL, 0, "%u", nvcpus);
+ char nvcpus_str[n+1];
+ sprintf(nvcpus_str, "%u", nvcpus);
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ VIR_DEBUG("nvcpus=%s, uuid=%s", nvcpus_str, uuid_string);
+
+ /* Get Msvm_VirtualSystemSettingData */
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
+ &virtualSystemSettingData) < 0) {
+ goto cleanup;
+ }
+
+ /* Get Msvm_ProcessorSettingData */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
+ "ResultClass = Msvm_ProcessorSettingData",
+ virtualSystemSettingData->data->InstanceID);
+
+ if (hypervGetMsvmProcessorSettingDataList(priv, &query,
+ &processorSettingData) < 0) {
+ goto cleanup;
+ }
+
+ if (processorSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup Msvm_ProcessorSettingData for domain %s"),
+ virtualSystemSettingData->data->ElementName);
+ goto cleanup;
+ }
+
+ // PREPARE EPR PARAM
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"",uuid_string);
+ eprparam.query = &query;
+ eprparam.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE EMBEDDED PARAM
+ embeddedparam.nbProps = 2;
+ tab_props = (properties_t *) malloc(embeddedparam.nbProps * sizeof(properties_t));
+ (*tab_props).name = "VirtualQuantity";
+ (*tab_props).val = nvcpus_str;
+ (*(tab_props+1)).name = "InstanceID";
+ (*(tab_props+1)).val = processorSettingData->data->InstanceID;
+ embeddedparam.instanceName = "Msvm_ProcessorSettingData";
+ embeddedparam.prop_t = tab_props;
+
+ // CREATE invokeXmlParam
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "ComputerSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam;
+ (*(params+1)).name = "ResourceSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam;
+
+ if (hypervInvokeMethod(priv, params, nb_params, "ModifyVirtualSystemResources",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not set domain vcpus"));
+ goto cleanup;
+ }
+
+ res = 0;
+
+ cleanup:
+ VIR_FREE(tab_props);
+ VIR_FREE(params);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)processorSettingData);
+ virBufferFreeAndReset(&query);
+ return res;
+}
+
+
+
+/* Bull */
+static int
+hypervDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
+{
+ return hypervDomainSetVcpusFlags(domain, nvcpus, 0);
+}
+
+
+
+/* Bull */
+static int
+hypervDomainAttachDisk(virDomainPtr domain, virDomainDiskDefPtr disk)
+{
+ int ret = -1, nb_params;
+ const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService";
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ char *ideRasdPath = NULL, *newDiskDrivePath = NULL;
+ char *ideControler, *ideControlerAddr;
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ Msvm_ResourceAllocationSettingData *resourceAllocationSettingData = NULL;
+ Msvm_ResourceAllocationSettingData *resourceAllocationSettingData2 = NULL;
+ Msvm_ResourceAllocationSettingData *resourceAllocationSettingData3 = NULL;
+ Msvm_ResourceAllocationSettingData *resourceAllocationSettingData4 = NULL;
+ Msvm_ResourceAllocationSettingData *ideRasd = NULL;
+ Msvm_ResourceAllocationSettingData *diskRasd = NULL;
+ Msvm_ResourceAllocationSettingData *newDiskDrive = NULL;
+ Msvm_AllocationCapabilities *allocationCapabilities = NULL;
+ Msvm_AllocationCapabilities *allocationCapabilities2 = NULL;
+ invokeXmlParam *params;
+ properties_t *tab_props;
+ eprParam eprparam1, eprparam2;
+ embeddedParam embeddedparam1, embeddedparam2;
+
+ /* Initialization */
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ // Set IDE Controler 0 or 1 and address 0 or 1
+ ideControler = (char *) malloc(sizeof(char)+1);
+ ideControlerAddr = (char *) malloc(sizeof(char)+1);
+ if (strcmp(disk->dst, "hda") == 0) {
+ sprintf(ideControler, "%d", 0);
+ sprintf(ideControlerAddr, "%d", 0);
+ } else if (strcmp(disk->dst, "hdb") == 0) {
+ sprintf(ideControler, "%d", 0);
+ sprintf(ideControlerAddr, "%d", 1);
+ } else if (strcmp(disk->dst, "hdc") == 0) {
+ sprintf(ideControler, "%d", 1);
+ sprintf(ideControlerAddr, "%d", 0);
+ } else if (strcmp(disk->dst, "hdd") == 0) {
+ sprintf(ideControler, "%d", 1);
+ sprintf(ideControlerAddr, "%d", 1);
+ } else {
+ // IDE Controler 0 and address 0 by default
+ sprintf(ideControler, "%d", 0);
+ sprintf(ideControlerAddr, "%d", 0);
+ }
+
+ VIR_DEBUG("src=%s, dst=IDE Controller %s:%s, uuid=%s",
+ disk->src->path, ideControler, ideControlerAddr, uuid_string);
+
+ /* Get the current VM settings object */
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
+ &virtualSystemSettingData) < 0) {
+ goto cleanup;
+ }
+
+ /* Get the settings for IDE Controller on the VM */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
+ "ResultClass = Msvm_ResourceAllocationSettingData",
+ virtualSystemSettingData->data->InstanceID);
+ if (hypervGetMsvmResourceAllocationSettingDataList(priv, &query,
+ &resourceAllocationSettingData) < 0) {
+ goto cleanup;
+ }
+ ideRasd = resourceAllocationSettingData;
+ while (ideRasd != NULL) {
+ if (ideRasd->data->ResourceType == 5 &&
+ strcmp(ideRasd->data->Address, ideControler) == 0) {
+ // IDE Controller 0 or 1
+ break;
+ }
+ ideRasd = ideRasd->next;
+ }
+ if (ideRasd == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find IDE Controller %s"), ideControler);
+ goto cleanup;
+ }
+
+ /* Get the settings for 'Microsoft Synthetic Disk Drive' */
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_ALLOCATIONCAPABILITIES_WQL_SELECT);
+ virBufferAddLit(&query, "WHERE ResourceSubType = 'Microsoft Synthetic Disk Drive'");
+ if (hypervGetMsvmAllocationCapabilitiesList(priv, &query,
+ &allocationCapabilities) < 0) {
+ goto cleanup;
+ }
+
+ /* Get default values for 'Microsoft Synthetic Disk Drive' */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_AllocationCapabilities.InstanceID=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineCapabilities "
+ "ResultClass = Msvm_ResourceAllocationSettingData",
+ allocationCapabilities->data->InstanceID);
+ if (hypervGetMsvmResourceAllocationSettingDataList(priv, &query,
+ &resourceAllocationSettingData2) < 0) {
+ goto cleanup;
+ }
+ diskRasd = resourceAllocationSettingData2;
+ while (diskRasd != NULL) {
+ if (strstr(diskRasd->data->InstanceID, "Default") != NULL) {
+ // Default values
+ break;
+ }
+ diskRasd = diskRasd->next;
+ }
+ if (diskRasd == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not get default values for 'Microsoft Synthetic Disk Drive'"));
+ goto cleanup;
+ }
+
+ /* Create the attribute _PATH for the RASD object */
+ if (hypervGetResourceAllocationSettingDataPATH(domain,
+ ideRasd->data->InstanceID, &ideRasdPath) < 0) {
+ goto cleanup;
+ }
+
+ /* Add default disk drive */
+ // PREPARE EPR PARAM
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"", uuid_string);
+ eprparam1.query = &query;
+ eprparam1.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE EMBEDDED PARAM 1
+ embeddedparam1.nbProps = 4;
+ tab_props = (properties_t *) malloc(embeddedparam1.nbProps * sizeof(properties_t));
+ (*tab_props).name = "Parent";
+ (*tab_props).val = ideRasdPath;
+ (*(tab_props+1)).name = "Address";
+ (*(tab_props+1)).val = ideControlerAddr;
+ (*(tab_props+2)).name = "ResourceType";
+ (*(tab_props+2)).val = "22";
+ (*(tab_props+3)).name = "ResourceSubType";
+ (*(tab_props+3)).val = diskRasd->data->ResourceSubType;
+ embeddedparam1.instanceName = MSVM_RESOURCEALLOCATIONSETTINGDATA_CLASSNAME;
+ embeddedparam1.prop_t = tab_props;
+
+ // CREATE invokeXmlParam tab
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "TargetSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam1;
+ (*(params+1)).name = "ResourceSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam1;
+
+ if (hypervInvokeMethod(priv, params, nb_params, "AddVirtualSystemResources",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add default disk drive"));
+ goto cleanup;
+ }
+
+ /* Get the instance of the new default drive disk */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
+ "ResultClass = Msvm_ResourceAllocationSettingData",
+ virtualSystemSettingData->data->InstanceID);
+ if (hypervGetMsvmResourceAllocationSettingDataList(priv, &query,
+ &resourceAllocationSettingData3) < 0) {
+ goto cleanup;
+ }
+ newDiskDrive = resourceAllocationSettingData3;
+ while (newDiskDrive != NULL) {
+ if (newDiskDrive->data->ResourceType == 22 &&
+ strcmp(newDiskDrive->data->ResourceSubType,
+ "Microsoft Synthetic Disk Drive") == 0) {
+ break;
+ }
+ newDiskDrive = newDiskDrive->next;
+ }
+ if (newDiskDrive == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not find 'Microsoft Synthetic Disk Drive'"));
+ goto cleanup;
+ }
+
+ /* Get the settings for 'Microsoft Virtual Hard Disk' */
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_ALLOCATIONCAPABILITIES_WQL_SELECT);
+ virBufferAddLit(&query, "WHERE ResourceSubType = 'Microsoft Virtual Hard Disk'");
+ if (hypervGetMsvmAllocationCapabilitiesList(priv, &query,
+ &allocationCapabilities2) < 0) {
+ goto cleanup;
+ }
+
+ /* Get default values for 'Microsoft Virtual Hard Drive' */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_AllocationCapabilities.InstanceID=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineCapabilities "
+ "ResultClass = Msvm_ResourceAllocationSettingData",
+ allocationCapabilities2->data->InstanceID);
+ if (hypervGetMsvmResourceAllocationSettingDataList(priv, &query,
+ &resourceAllocationSettingData4) < 0) {
+ goto cleanup;
+ }
+ diskRasd = resourceAllocationSettingData4;
+ while (diskRasd != NULL) {
+ if (strstr(diskRasd->data->InstanceID, "Default") != NULL) {
+ // Default values
+ break;
+ }
+ diskRasd = diskRasd->next;
+ }
+ if (diskRasd == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not get default values for 'Microsoft Virtual Hard Drive'"));
+ goto cleanup;
+ }
+
+ /* Create the attribute _PATH for the RASD object */
+ if (hypervGetResourceAllocationSettingDataPATH(domain,
+ newDiskDrive->data->InstanceID, &newDiskDrivePath) < 0) {
+ goto cleanup;
+ }
+
+ /* Add the new VHD */
+ // PREPARE EPR PARAM 2
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"", uuid_string);
+ eprparam2.query = &query;
+ eprparam2.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE EMBEDDED PARAM 2
+ VIR_FREE(tab_props);
+ embeddedparam2.nbProps = 4;
+ tab_props = (properties_t *) malloc(embeddedparam2.nbProps * sizeof(properties_t));
+ (*tab_props).name = "Parent";
+ (*tab_props).val = newDiskDrivePath;
+ (*(tab_props+1)).name = "Connection";
+ (*(tab_props+1)).val = disk->src->path;
+ (*(tab_props+2)).name = "ResourceType";
+ (*(tab_props+2)).val = "21";
+ (*(tab_props+3)).name = "ResourceSubType";
+ (*(tab_props+3)).val = diskRasd->data->ResourceSubType;
+ embeddedparam2.instanceName = MSVM_RESOURCEALLOCATIONSETTINGDATA_CLASSNAME;
+ embeddedparam2.prop_t = tab_props;
+
+ // CREATE invokeXmlParam tab
+ VIR_FREE(params);
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "TargetSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam2;
+ (*(params+1)).name = "ResourceSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam2;
+
+ if (hypervInvokeMethod(priv, params, nb_params, "AddVirtualSystemResources",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not attach hard disk drive"));
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ free(ideRasdPath);
+ free(newDiskDrivePath);
+ virBufferFreeAndReset(&query);
+ if (!tab_props)
+ VIR_FREE(tab_props);
+ if (!params)
+ VIR_FREE(params);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)resourceAllocationSettingData);
+ hypervFreeObject(priv, (hypervObject *)resourceAllocationSettingData2);
+ hypervFreeObject(priv, (hypervObject *)resourceAllocationSettingData3);
+ hypervFreeObject(priv, (hypervObject *)resourceAllocationSettingData4);
+ hypervFreeObject(priv, (hypervObject *)allocationCapabilities);
+ hypervFreeObject(priv, (hypervObject *)allocationCapabilities2);
+
+ return ret;
+}
+
+
+
+/* Bull */
+static int
+hypervDomainAttachNetwork(virDomainPtr domain, virDomainNetDefPtr net)
+{
+ int ret = -1, nb_params;
+ const char *selector1 = "CreationClassName=Msvm_VirtualSwitchManagementService";
+ const char *selector2 = "CreationClassName=Msvm_VirtualSystemManagementService";
+ char uuid_string[VIR_UUID_STRING_BUFLEN], guid_string[VIR_UUID_STRING_BUFLEN];
+ unsigned char guid[VIR_UUID_BUFLEN];
+ char *virtualSystemIdentifiers = NULL, *switchPortPATH = NULL;
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ eprParam eprparam1, eprparam2;
+ simpleParam simpleparam1, simpleparam2, simpleparam3;
+ embeddedParam embeddedparam;
+ properties_t *tab_props;
+ invokeXmlParam *params;
+ Msvm_SwitchPort *switchPort = NULL;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ /* Initialization */
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ VIR_DEBUG("network=%s, uuid=%s", net->data.network.name, uuid_string);
+
+ /* Create virtual switch port */
+ // PREPARE EPR PARAM 1
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where ElementName = \"%s\"", net->data.network.name);
+ eprparam1.query = &query;
+ eprparam1.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE SIMPLE PARAMS
+ virUUIDGenerate(guid);
+ virUUIDFormat(guid, guid_string);
+ simpleparam1.value = guid_string;
+ simpleparam2.value = "Dynamic Ethernet Switch Port";
+ simpleparam3.value = "";
+
+ // CREATE invokeXmlParam tab
+ nb_params = 4;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "VirtualSwitch";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam1;
+ (*(params+1)).name = "Name";
+ (*(params+1)).type = SIMPLE_PARAM;
+ (*(params+1)).param = &simpleparam1;
+ (*(params+2)).name = "FriendlyName";
+ (*(params+2)).type = SIMPLE_PARAM;
+ (*(params+2)).param = &simpleparam2;
+ (*(params+3)).name = "ScopeOfResidence";
+ (*(params+3)).type = SIMPLE_PARAM;
+ (*(params+3)).param = &simpleparam3;
+
+ if (hypervInvokeMethod(priv, params, nb_params, "CreateSwitchPort",
+ MSVM_VIRTUALSWITCHMANAGEMENTSERVICE_RESOURCE_URI, selector1) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not create port for virtual switch '%s'"), net->data.network.name);
+ goto cleanup;
+ }
+
+ /* Get a reference of the switch port created previously */
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_SWITCHPORT_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"", guid_string);
+ if (hypervGetMsvmSwitchPortList(priv, &query, &switchPort) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Method hypervGetMsvmSwitchPortList failed with query=%s"), query.e);
+ goto cleanup;
+ }
+ if (switchPort == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get switch port with Name=%s"), guid_string);
+ goto cleanup;
+ }
+
+ /* Get a reference of the given virtual switch */
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where ElementName = \"%s\"", net->data.network.name);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitch) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Method hypervGetMsvmVirtualSwitchList failed with query=%s"), query.e);
+ goto cleanup;
+ }
+ if (virtualSwitch == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get virtual switch '%s'"), net->data.network.name);
+ goto cleanup;
+ }
+
+ /* Add the synthetic ethernet port to the VM */
+ // PREPARE EPR PARAM 2
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"", uuid_string);
+ eprparam2.query = &query;
+ eprparam2.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE EMBEDDED PARAM
+ virUUIDGenerate(guid);
+ virUUIDFormat(guid, guid_string);
+ virtualSystemIdentifiers = (char *) malloc(sizeof(char) * (strlen(guid_string) + 3));
+ sprintf(virtualSystemIdentifiers, "{%s}", guid_string);
+ hypervGetSwitchPortPATH(domain, switchPort->data->Name,
+ virtualSwitch->data->Name, &switchPortPATH);
+ embeddedparam.nbProps = 5;
+ tab_props = (properties_t *) malloc(embeddedparam.nbProps * sizeof(properties_t));
+ (*tab_props).name = "Connection";
+ (*tab_props).val = switchPortPATH;
+ (*(tab_props+1)).name = "ElementName";
+ (*(tab_props+1)).val = "Network Adapter";
+ (*(tab_props+2)).name = "VirtualSystemIdentifiers";
+ (*(tab_props+2)).val = virtualSystemIdentifiers;
+ (*(tab_props+3)).name = "ResourceType";
+ (*(tab_props+3)).val = "10";
+ (*(tab_props+4)).name = "ResourceSubType";
+ (*(tab_props+4)).val = "Microsoft Synthetic Ethernet Port";
+ embeddedparam.instanceName = MSVM_SYNTHETICETHERNETPORTSETTINGDATA_CLASSNAME;
+ embeddedparam.prop_t = tab_props;
+
+ // CREATE invokeXmlParam tab
+ VIR_FREE(params);
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "TargetSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam2;
+ (*(params+1)).name = "ResourceSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam;
+
+ if (hypervInvokeMethod(priv, params, nb_params, "AddVirtualSystemResources",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector2) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not attach the network"));
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ free(virtualSystemIdentifiers);
+ free(switchPortPATH);
+ virBufferFreeAndReset(&query);
+ if (!tab_props)
+ VIR_FREE(tab_props);
+ if (!params)
+ VIR_FREE(params);
+ hypervFreeObject(priv, (hypervObject *)switchPort);
+ hypervFreeObject(priv, (hypervObject *)virtualSwitch);
+ return ret;
+}
+
+
+
+/* Bull */
+static int
+hypervDomainAttachDeviceFlags(virDomainPtr domain, const char *xml,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ int ret = -1;
+ hypervPrivate *priv = domain->conn->privateData;
+ virDomainDefPtr def = NULL;
+ virDomainDeviceDefPtr dev = NULL;
+ char *xmlDomain = NULL;
+
+ // Get domain definition
+ if ((xmlDomain = hypervDomainGetXMLDesc(domain, 0)) == NULL) {
+ goto cleanup;
+ }
+ if ((def = virDomainDefParseString(xmlDomain, priv->caps, priv->xmlopt,
+ 1 << VIR_DOMAIN_VIRT_HYPERV, VIR_DOMAIN_XML_INACTIVE)) == NULL) {
+ goto cleanup;
+ }
+
+ // Get domain device definition
+ if ((dev = virDomainDeviceDefParse(xml, def, priv->caps,
+ priv->xmlopt, VIR_DOMAIN_XML_INACTIVE)) == NULL) {
+ goto cleanup;
+ }
+
+ switch (dev->type) {
+ /* Device = disk */
+ case VIR_DOMAIN_DEVICE_DISK:
+ if (hypervDomainAttachDisk(domain, dev->data.disk) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not attach disk"));
+ goto cleanup;
+ }
+ VIR_DEBUG("Disk attached");
+ break;
+
+ /* Device = network */
+ case VIR_DOMAIN_DEVICE_NET:
+ if (hypervDomainAttachNetwork(domain, dev->data.net) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not attach network"));
+ goto cleanup;
+ }
+ VIR_DEBUG("Network attached");
+ break;
+
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Device attachment of type %d is not implemented"), dev->type);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ free(xmlDomain);
+ return ret;
+}
+
+
+
+/* Bull */
+static int
+hypervDomainAttachDevice(virDomainPtr domain, const char *xml)
+{
+ return hypervDomainAttachDeviceFlags(domain, xml, 0);
+}
+
+
+
+/* Bull */
+static virDomainPtr
+hypervDomainDefineXML(virConnectPtr conn, const char *xml)
+{
+ hypervPrivate *priv = conn->privateData;
+ virDomainDefPtr def = NULL;
+ virDomainPtr domain = NULL;
+ invokeXmlParam *params = NULL;
+ properties_t *tab_props = NULL;
+ embeddedParam embeddedparam;
+ int nb_params, i;
+ const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService";
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+
+ // Parsing XML
+ if ((def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
+ 1 << VIR_DOMAIN_VIRT_HYPERV, VIR_DOMAIN_XML_INACTIVE)) == NULL) {
+ goto cleanup;
+ }
+
+ /* Create the VM if not exists */
+ if (!(def->uuid != NULL &&
+ (domain = hypervDomainLookupByUUID(conn, def->uuid)) != NULL)) {
+
+ // PREPARE EMBEDDED PARAM
+ /* Edit only VM name */
+ //FIXME: cannot edit VM UUID
+ embeddedparam.nbProps = 1;
+ tab_props = (properties_t *) malloc(embeddedparam.nbProps * sizeof(properties_t));
+ (*tab_props).name = "ElementName";
+ (*tab_props).val = def->name;
+ embeddedparam.instanceName = "Msvm_VirtualSystemGlobalSettingData";
+ embeddedparam.prop_t = tab_props;
+
+ // CREATE invokeXmlParam
+ nb_params = 1;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "SystemSettingData";
+ (*params).type = EMBEDDED_PARAM;
+ (*params).param = &embeddedparam;
+
+ /* Create VM */
+ if (hypervInvokeMethod(priv, params, nb_params, "DefineVirtualSystem",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not create new domain %s"), def->name);
+ goto cleanup;
+ }
+
+ // Get domain pointer
+ domain = hypervDomainLookupByName(conn, def->name);
+
+ VIR_DEBUG("Domain created: name=%s, uuid=%s",
+ domain->name, virUUIDFormat(domain->uuid, uuid_string));
+ }
+
+ /* Set VM maximum memory */
+ if (def->mem.max_balloon > 0) {
+ if (hypervDomainSetMaxMemory(domain, def->mem.max_balloon) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not set VM maximum memory"));
+ }
+ }
+
+ /* Set VM memory */
+ if (def->mem.cur_balloon > 0) {
+ if (hypervDomainSetMemory(domain, def->mem.cur_balloon) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not set VM memory"));
+ }
+ }
+
+ /* Set VM vcpus */
+ if (def->vcpus > 0) {
+ if (hypervDomainSetVcpus(domain, def->vcpus) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not set VM vCPUs"));
+ }
+ }
+
+ /* Attach networks */
+ for (i = 0; i < def->nnets; i++) {
+ if (hypervDomainAttachNetwork(domain, def->nets[i]) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not attach network"));
+ }
+ }
+
+ /* Attach disks */
+ for (i = 0; i < def->ndisks; i++) {
+ if (hypervDomainAttachDisk(domain, def->disks[i]) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not attach disk"));
+ }
+ }
+
+ cleanup:
+ if (tab_props != NULL)
+ VIR_FREE(tab_props);
+ if (params != NULL)
+ VIR_FREE(params);
+ return domain;
+}
+
+
+
+/* Bull */
+static virDomainPtr
+hypervDomainCreateXML(virConnectPtr conn, const char *xmlDesc, unsigned int flags)
+{
+ virDomainPtr domain;
+
+ virCheckFlags(VIR_DOMAIN_NONE |VIR_DOMAIN_START_PAUSED |VIR_DOMAIN_START_AUTODESTROY, NULL);
+
+ // Create new domain
+ domain = hypervDomainDefineXML(conn, xmlDesc);
+
+ // Start domain
+ if (hypervInvokeMsvmComputerSystemRequestStateChange(domain,
+ MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_ENABLED) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not start the domain %s"), domain->name);
+ return domain;
+ }
+
+ // If the VIR_DOMAIN_START_PAUSED flag is set,
+ // the guest domain will be started, but its CPUs will remain paused
+ if (flags & VIR_DOMAIN_START_PAUSED) {
+ if (hypervDomainSuspend(domain) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not pause the domain %s"), domain->name);
+ }
+ }
+
+ // If the VIR_DOMAIN_START_AUTODESTROY flag is set,
+ // the guest domain will be automatically destroyed
+ // when the virConnectPtr object is finally released
+ if (flags & VIR_DOMAIN_START_AUTODESTROY) {
+ //FIXME: wait till virConnectPtr is released
+ if (hypervDomainDestroy(domain) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not destroy the domain %s"), domain->name);
+ }
+ }
+
+ return domain;
+}
+
+
+
+/* Bull */
+static int
+hypervDomainUndefineFlags(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
+{
+ int result = -1, nb_params;
+ const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService";
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ invokeXmlParam *params;
+ eprParam eprparam;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_ComputerSystem *computerSystem = NULL;
+
+ virCheckFlags(0, -1);
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
+ goto cleanup;
+ }
+
+ /* Shutdown the VM if not disabled */
+ if (computerSystem->data->EnabledState !=
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_DISABLED) {
+ if (hypervDomainShutdown(domain) < 0) {
+ goto cleanup;
+ }
+ }
+
+ /* Deleting the VM */
+
+ // PREPARE EPR PARAM
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"", uuid_string);
+ eprparam.query = &query;
+ eprparam.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // CREATE invokeXmlParam tab
+ nb_params = 1;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "ComputerSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam;
+
+ // DESTROY VM
+ if (hypervInvokeMethod(priv, params, nb_params, "DestroyVirtualSystem",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not delete domain"));
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ virBufferFreeAndReset(&query);
+ if (!params)
+ VIR_FREE(params);
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ return result;
+}
+
+
+
+/* Bull */
+static int
+hypervDomainUndefine(virDomainPtr domain)
+{
+ return hypervDomainUndefineFlags(domain, 0);
+}
+
+
static virDriver hypervDriver = {
.no = VIR_DRV_HYPERV,
@@ -1389,6 +3272,33 @@ static virDriver hypervDriver = {
.domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
.domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
.connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
+
+ /* Bull */
+ .domainGetVcpusFlags = hypervDomainGetVcpusFlags, /* 1.2.9 */
+ .domainGetMaxVcpus = hypervDomainGetMaxVcpus, /* 1.2.9 */
+ .domainShutdown = hypervDomainShutdown, /* 1.2.9 */
+ .domainShutdownFlags = hypervDomainShutdownFlags, /* 1.2.9 */
+ .domainGetSchedulerParametersFlags = hypervDomainGetSchedulerParametersFlags, /* 1.2.9 */
+ .domainGetSchedulerParameters = hypervDomainGetSchedulerParameters, /* 1.2.9 */
+ .domainGetSchedulerType = hypervDomainGetSchedulerType, /* 1.2.9 */
+ .connectGetCapabilities = hypervConnectGetCapabilities, /* 1.2.9 */
+ .connectGetVersion = hypervConnectGetVersion, /* 1.2.9 */
+ .domainSetAutostart = hypervDomainSetAutostart, /* 1.2.9 */
+ .domainSetMaxMemory = hypervDomainSetMaxMemory, /* 1.2.9 */
+ .domainDefineXML = hypervDomainDefineXML, /* 1.2.9 */
+ .domainSetMemory = hypervDomainSetMemory, /* 1.2.9 */
+ .domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* 1.2.9 */
+ .domainSetVcpus = hypervDomainSetVcpus, /* 1.2.9 */
+ .domainSetVcpusFlags = hypervDomainSetVcpusFlags, /* 1.2.9 */
+ .domainAttachDevice = hypervDomainAttachDevice, /* 1.2.9 */
+ .domainAttachDeviceFlags = hypervDomainAttachDeviceFlags, /* 1.2.9 */
+ .connectGetMaxVcpus = hypervConnectGetMaxVcpus, /* 1.2.9 */
+ .domainCreateXML = hypervDomainCreateXML, /* 1.2.9 */
+ .nodeGetFreeMemory = hypervNodeGetFreeMemory, /* 1.2.9 */
+ .domainGetVcpus = hypervDomainGetVcpus, /* 1.2.9 */
+ .domainUndefine = hypervDomainUndefine, /* 1.2.9 */
+ .domainUndefineFlags = hypervDomainUndefineFlags, /* 1.2.9 */
+ .domainGetAutostart = hypervDomainGetAutostart, /* 1.2.9 */
};
diff --git a/src/hyperv/hyperv_network_driver.c b/src/hyperv/hyperv_network_driver.c
index 6f54f44..dd89207 100644
--- a/src/hyperv/hyperv_network_driver.c
+++ b/src/hyperv/hyperv_network_driver.c
@@ -29,6 +29,11 @@
#include "viruuid.h"
#include "hyperv_network_driver.h"
+/* Bull */
+#include "virstring.h"
+#include "hyperv_wmi.h"
+#include "network_conf.h"
+
#define VIR_FROM_THIS VIR_FROM_HYPERV
@@ -60,11 +65,254 @@ hypervNetworkClose(virConnectPtr conn)
}
+/* Bull */
+static int
+hypervConnectNumOfNetworks(virConnectPtr conn)
+{
+ int ret = -1, count = 0;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSwitch *virtualSwitchList = NULL;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where HealthState = %d", 5);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitchList) < 0) {
+ goto cleanup;
+ }
+
+ for (virtualSwitch = virtualSwitchList; virtualSwitch != NULL;
+ virtualSwitch = virtualSwitch->next) {
+ count++;
+ }
+
+ ret = count;
+
+ cleanup:
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) virtualSwitchList);
+ return ret;
+}
+
+
+/* Bull */
+static int
+hypervConnectListNetworks(virConnectPtr conn, char **const names, int maxnames)
+{
+ int i, count = 0;
+ bool success = false;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSwitch *virtualSwitchList = NULL;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ if (maxnames <= 0) {
+ return 0;
+ }
+
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where HealthState = %d", 5);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitchList) < 0) {
+ goto cleanup;
+ }
+
+ for (virtualSwitch = virtualSwitchList; virtualSwitch != NULL;
+ virtualSwitch = virtualSwitch->next) {
+ if (VIR_STRDUP(names[count], virtualSwitch->data->ElementName) < 0) {
+ goto cleanup;
+ }
+ count++;
+ if (count >= maxnames) {
+ break;
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ if (!success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+ count = -1;
+ }
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) virtualSwitchList);
+ return count;
+}
+
+
+/* Bull */
+static int
+hypervConnectNumOfDefinedNetworks(virConnectPtr conn)
+{
+ int ret = -1, count = 0;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSwitch *virtualSwitchList = NULL;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where HealthState <> %d", 5);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitchList) < 0) {
+ goto cleanup;
+ }
+
+ for (virtualSwitch = virtualSwitchList; virtualSwitch != NULL;
+ virtualSwitch = virtualSwitch->next) {
+ count++;
+ }
+
+ ret = count;
+
+ cleanup:
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) virtualSwitchList);
+ return ret;
+}
+
+
+/* Bull */
+static int
+hypervConnectListDefinedNetworks(virConnectPtr conn, char **const names, int maxnames)
+{
+ int i, count = 0;
+ bool success = false;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSwitch *virtualSwitchList = NULL;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ if (maxnames <= 0) {
+ return 0;
+ }
+
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where HealthState <> %d", 5);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitchList) < 0) {
+ goto cleanup;
+ }
+
+ for (virtualSwitch = virtualSwitchList; virtualSwitch != NULL;
+ virtualSwitch = virtualSwitch->next) {
+ if (VIR_STRDUP(names[count], virtualSwitch->data->ElementName) < 0) {
+ goto cleanup;
+ }
+ count++;
+ if (count >= maxnames) {
+ break;
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ if (!success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+ count = -1;
+ }
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) virtualSwitchList);
+ return count;
+}
+
+
+/* Bull */
+static virNetworkPtr
+hypervNetworkLookupByName(virConnectPtr conn, const char *name)
+{
+ virNetworkPtr network = NULL;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where Description = \"%s\" and ElementName = \"%s\"",
+ "Microsoft Virtual Switch", name);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitch) < 0) {
+ goto cleanup;
+ }
+ if (virtualSwitch == NULL) {
+ virReportError(VIR_ERR_NO_NETWORK,
+ _("No network found with name %s"), name);
+ goto cleanup;
+ }
+
+ hypervMsvmVirtualSwitchToNetwork(conn, virtualSwitch, &network);
+
+ cleanup:
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) virtualSwitch);
+ return network;
+}
+
+
+/* Bull */
+static char *
+hypervNetworkGetXMLDesc(virNetworkPtr network, unsigned int flags)
+{
+ char *xml = NULL;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = network->conn->privateData;
+ virNetworkDefPtr def = NULL;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ /* Flags checked by virNetworkDefFormat */
+
+ if (VIR_ALLOC(def) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ virUUIDFormat(network->uuid, uuid_string);
+
+ /* Get Msvm_VirtualSwitch */
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"", uuid_string);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitch) < 0) {
+ goto cleanup;
+ }
+ if (virtualSwitch == NULL) {
+ virReportError(VIR_ERR_NO_NETWORK,
+ _("No network found with UUID %s"), uuid_string);
+ goto cleanup;
+ }
+
+ /* Fill struct */
+ if (virUUIDParse(virtualSwitch->data->Name, def->uuid) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse UUID from string '%s'"),
+ virtualSwitch->data->Name);
+ return NULL;
+ }
+
+ if (VIR_STRDUP(def->name, virtualSwitch->data->ElementName) < 0)
+ goto cleanup;
+
+ xml = virNetworkDefFormat(def, flags);
+
+ cleanup:
+ virNetworkDefFree(def);
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *)virtualSwitch);
+ return xml;
+}
static virNetworkDriver hypervNetworkDriver = {
.name = "Hyper-V",
.networkOpen = hypervNetworkOpen, /* 0.9.5 */
.networkClose = hypervNetworkClose, /* 0.9.5 */
+
+ /* Bull */
+ .connectNumOfNetworks = hypervConnectNumOfNetworks, /* 1.2.9 */
+ .connectListNetworks = hypervConnectListNetworks, /* 1.2.9 */
+ .connectNumOfDefinedNetworks = hypervConnectNumOfDefinedNetworks, /* 1.2.9 */
+ .connectListDefinedNetworks = hypervConnectListDefinedNetworks, /* 1.2.9 */
+ .networkLookupByName = hypervNetworkLookupByName, /* 1.2.9 */
+ .networkGetXMLDesc = hypervNetworkGetXMLDesc, /* 1.2.9 */
};
diff --git a/src/hyperv/hyperv_private.h b/src/hyperv/hyperv_private.h
index 574bb5f..c543f1a 100644
--- a/src/hyperv/hyperv_private.h
+++ b/src/hyperv/hyperv_private.h
@@ -28,11 +28,26 @@
# include "hyperv_util.h"
# include "openwsman.h"
+/* Bull */
+# include "capabilities.h"
+#include "domain_conf.h"
+
+/* Bull - Add mutex to protect against concurrent calls
+ (OpenWsMan client API is not thread-safe) */
+#ifndef WIN32
+# include <pthread.h>
+#endif
+
typedef struct _hypervPrivate hypervPrivate;
struct _hypervPrivate {
hypervParsedUri *parsedUri;
WsManClient *client;
+
+ /* Bull */
+ pthread_mutex_t mutex;
+ virCapsPtr caps;
+ virDomainXMLOptionPtr xmlopt; /* to parse Domain XML */
};
#endif /* __HYPERV_PRIVATE_H__ */
diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index acb705c..c0ea00b 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -1,3 +1,4 @@
+
/*
* hyperv_wmi.c: general WMI over WSMAN related functions and structures for
* managing Microsoft Hyper-V hosts
@@ -33,16 +34,704 @@
#include "hyperv_wmi.h"
#include "virstring.h"
+/* Bull */
+# include <wsman-xml-api.h>
+# include <wsman-client.h>
+# include <wsman-client-transport.h>
+# include <wsman-soap.h>
+# include <libxml/tree.h>
+# include "hyperv_wmi_classes_attr.generated.h"
+
#define WS_SERIALIZER_FREE_MEM_WORKS 0
-#define ROOT_CIMV2 \
- "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*"
+#define VIR_FROM_THIS VIR_FROM_HYPERV
-#define ROOT_VIRTUALIZATION \
- "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/*"
+/* Bull */
+/* #define DUMP_REQUEST 1 */
-#define VIR_FROM_THIS VIR_FROM_HYPERV
+/* Bull */
+/* Create XML structure */
+int
+hypervCreateXmlStruct(const char *methodName, const char *classURI,
+ WsXmlDocH *xmlDocRoot, WsXmlNodeH *xmlNodeMethod)
+{
+
+ virBuffer method_buff = VIR_BUFFER_INITIALIZER;
+ char *methodNameInput = NULL;
+
+ virBufferAsprintf(&method_buff, "%s_INPUT", methodName);
+ methodNameInput = virBufferContentAndReset(&method_buff);
+
+ if (methodNameInput == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not create Xml Doc"));
+ goto cleanup;
+ }
+
+ *xmlDocRoot = ws_xml_create_doc(NULL, methodNameInput);
+ if (*xmlDocRoot == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not create Xml Doc with given parameter xmlDocRoot"));
+ goto cleanup;
+ }
+
+ *xmlNodeMethod = xml_parser_get_root(*xmlDocRoot);
+ if (*xmlNodeMethod == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get xmlDocRoot root node"));
+ goto cleanup;
+ }
+
+ //add namespace to xmlNodeMethode
+ ws_xml_set_ns(*xmlNodeMethod, classURI, "p");
+
+ VIR_FREE(methodNameInput);
+ return 0;
+
+ cleanup:
+
+ VIR_FREE(methodNameInput);
+ if (*xmlDocRoot != NULL) {
+ ws_xml_destroy_doc(*xmlDocRoot);
+ *xmlDocRoot = NULL;
+ }
+ return -1;
+}
+
+
+/* Bull */
+/* Get attribute type of a given attribute */
+const char *
+hypervGetPropType(const char * className, const char *attrName)
+{
+ const char * res = NULL;
+ int i,y;
+
+ i = 0;
+ while ( cimClasses[i].name[0] != '\0') {
+ if(strcmp(cimClasses[i].name,className ) == 0){
+ y = 0;
+ while ( cimClasses[i].cimTypesPtr[y].name[0] != '\0') {
+ if(strcmp(cimClasses[i].cimTypesPtr[y].name,attrName ) == 0){
+ res = cimClasses[i].cimTypesPtr[y].type;
+ break;
+ }
+ y++;
+ }
+ break;
+ }
+ i++;
+ }
+ return res;
+}
+
+
+/* Bull */
+/* Adding an Embedded Instance node to a parent node given in parameter */
+int
+hypervAddEmbeddedParam(properties_t *prop_t, int nbProps, const char *paramName,
+ const char *instanceName, const char *classURI, WsXmlNodeH *parentNode)
+{
+
+ int result = -1;
+ WsXmlNodeH xmlNodeInstance = NULL;
+ WsXmlNodeH xmlNodeProperty = NULL;
+ WsXmlNodeH xmlNodeParam = NULL;
+ WsXmlNodeH xmlNodeArray = NULL;
+ WsXmlDocH xmlDocTemp = NULL;
+ WsXmlDocH xmlDocCdata = NULL;
+ xmlBufferPtr xmlBufferNode = NULL;
+ const xmlChar *xmlCharCdataContent = NULL;
+ xmlNodePtr xmlNodeCdata = NULL;
+ int len = 0;
+ int i = 0;
+ char* type = NULL;
+ bool isArray = false;
+ char* typeTmp = NULL;
+ int n = 0;
+
+ /* Add child to given parent node*/
+ xmlNodeParam = ws_xml_add_child(*parentNode, classURI, paramName, NULL);
+ if (xmlNodeParam == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not add child node to xmlNodeParam"));
+ goto cleanup;
+ }
+
+ /* Create temp Xml doc */
+ /* INSTANCE node */
+ xmlDocTemp = ws_xml_create_doc(NULL, "INSTANCE");
+ if (xmlDocTemp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not create temporary Xml doc"));
+ goto cleanup;
+ }
+
+ xmlNodeInstance = xml_parser_get_root(xmlDocTemp);
+ if (xmlNodeInstance == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get root of temporary Xml doc"));
+ goto cleanup;
+ }
+
+ /* Add CLASSNAME node to INSTANCE node */
+ if (ws_xml_add_node_attr(xmlNodeInstance, NULL, "CLASSNAME", instanceName) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add attribute to node "));
+ goto cleanup;
+ }
+
+ /* Property nodes */
+ while (i < nbProps) {
+
+ if (prop_t[i].name == NULL && prop_t[i].val == NULL ) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get properties from array "));
+ goto cleanup;
+ }
+
+ type = (char *)hypervGetPropType(instanceName,prop_t[i].name);
+ if (type == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get properties from array "));
+ goto cleanup;
+ }
+
+ /* Check if the attribute is an array or not */
+ if (strstr(type, "[]") != NULL) {
+ // The attribute is an array
+ isArray = true;
+ // Remove "[]" from the type
+ n = strlen(type) - 2;
+ typeTmp = (char *) malloc(sizeof(char) * (n+1));
+ strncpy(typeTmp, type, n);
+ type = (char *) malloc(sizeof(char) * (n+1));
+ strcpy(type, typeTmp);
+ free(typeTmp);
+ } else {
+ isArray = false;
+ }
+
+ xmlNodeProperty = ws_xml_add_child(xmlNodeInstance, NULL,
+ (isArray)?"PROPERTY.ARRAY":"PROPERTY", NULL);
+ if (xmlNodeProperty == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add child to node"));
+ goto cleanup;
+ }
+
+ if (ws_xml_add_node_attr(xmlNodeProperty, NULL, "NAME", prop_t[i].name) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add attribute to node"));
+ goto cleanup;
+ }
+
+ if (ws_xml_add_node_attr(xmlNodeProperty, NULL, "TYPE", type) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add attribute to node"));
+ goto cleanup;
+ }
+
+ /* Add the node VALUE.ARRAY if the attribute is an array */
+ if (isArray) {
+ xmlNodeArray = ws_xml_add_child(xmlNodeProperty, NULL, "VALUE.ARRAY", NULL);
+ if (xmlNodeArray == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add child to node"));
+ goto cleanup;
+ }
+ }
+
+ if (ws_xml_add_child((isArray)?xmlNodeArray:xmlNodeProperty, NULL, "VALUE",prop_t[i].val) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add child to node"));
+ goto cleanup;
+ }
+
+ xmlNodeArray = NULL;
+ xmlNodeProperty = NULL;
+ i++;
+ }
+
+ /* Create CDATA node */
+ xmlBufferNode = xmlBufferCreate();
+ if (xmlNodeDump(xmlBufferNode,(xmlDocPtr)xmlDocTemp->parserDoc , (xmlNodePtr) xmlNodeInstance, 0, 0) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get root of temporary Xml doc"));
+ goto cleanup;
+ }
+
+ len = xmlBufferLength(xmlBufferNode);
+ xmlCharCdataContent = xmlBufferContent(xmlBufferNode);
+ xmlNodeCdata = xmlNewCDataBlock ((xmlDocPtr)xmlDocCdata, xmlCharCdataContent, len );
+ if (xmlNodeCdata == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get root of temporary Xml doc"));
+ goto cleanup;
+ }
+ /*adding CDATA node child to the root node of the main doc given*/
+ if (xmlAddChild((xmlNodePtr)xmlNodeParam, xmlNodeCdata ) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get root of temporary Xml doc"));
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ ws_xml_destroy_doc(xmlDocCdata);
+ ws_xml_destroy_doc(xmlDocTemp);
+ //VIR_FREE((char*)type);
+ if (xmlBufferNode != NULL){
+ xmlBufferFree(xmlBufferNode);
+ }
+
+ return result;
+}
+
+
+/* Bull */
+/* Adding an Simple param node to a parent node given in parameter */
+int
+hypervAddSimpleParam(const char *paramName, const char* value,
+ const char *classURI, WsXmlNodeH *parentNode)
+{
+
+ int result = -1;
+ WsXmlNodeH xmlNodeParam = NULL;
+
+ xmlNodeParam = ws_xml_add_child(*parentNode, classURI, paramName, value);
+ if (xmlNodeParam == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not create simple param"));
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ return result;
+}
+
+
+/* Bull */
+/* Adding EPR param node to a parent node given in parameter */
+int
+hypervAddEprParam(const char *paramName, virBufferPtr query, const char *root,
+ const char *classURI, WsXmlNodeH *parentNode, WsXmlDocH doc, hypervPrivate *priv)
+{
+
+ int result = -1;
+ WsXmlNodeH xmlNodeParam = NULL;
+ WsXmlNodeH xmlNodTemp = NULL;
+ WsXmlNodeH xmlNodeAdr = NULL;
+ WsXmlNodeH xmlNodeRef = NULL;
+ WsXmlDocH xmlDocResponse = NULL;
+ WsXmlNsH ns = NULL;
+ client_opt_t *options = NULL;
+ filter_t *filter = NULL;
+ char *enumContext = NULL;
+ char *query_string;
+ xmlNodePtr xmlNodeAdrPtr = NULL;
+ xmlNodePtr xmlNodeRefPtr = NULL;
+ xmlDocPtr docPtr = (xmlDocPtr) doc->parserDoc;
+
+ /* Request options and filter */
+ options = wsmc_options_init();
+
+ wsmc_set_action_option(options, FLAG_ENUMERATION_ENUM_EPR);
+
+ query_string = virBufferContentAndReset(query);
+ filter = filter_create_simple(WSM_WQL_FILTER_DIALECT,query_string);
+ if (filter == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not create filter"));
+ goto cleanup;
+ }
+
+ /* Invoke enumerate action*/
+ xmlDocResponse = wsmc_action_enumerate(priv->client,root, options, filter);
+
+ /* Check return value */
+ if (hyperyVerifyResponse(priv->client, xmlDocResponse, "enumeration") < 0) {
+ goto cleanup;
+ }
+
+ /* Get enumerate conext*/
+ enumContext = wsmc_get_enum_context(xmlDocResponse);
+
+ ws_xml_destroy_doc(xmlDocResponse);
+
+
+ /* Invoke pull action*/
+ xmlDocResponse = wsmc_action_pull(priv->client, classURI, options, filter, enumContext);
+
+ /* Check return value */
+ if (hyperyVerifyResponse(priv->client, xmlDocResponse, "pull") < 0) {
+ goto cleanup;
+ }
+
+ /* Extract EPR nodes childs */
+ xmlNodTemp = ws_xml_get_soap_body(xmlDocResponse);
+ if (xmlNodTemp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup SOAP body"));
+ goto cleanup;
+ }
+
+ xmlNodTemp = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ENUMERATION, WSENUM_PULL_RESP);
+ if (xmlNodTemp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup pull response"));
+ goto cleanup;
+ }
+
+ xmlNodTemp = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ENUMERATION, WSENUM_ITEMS);
+ if (xmlNodTemp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup pull response items"));
+ goto cleanup;
+ }
+
+ xmlNodTemp = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ADDRESSING, WSA_EPR);
+ if (xmlNodTemp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup pull response item EPR"));
+ goto cleanup;
+ }
+
+ xmlNodeAdr = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ADDRESSING, WSA_ADDRESS);
+ if (xmlNodeAdr == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup pull response item ADDRESS"));
+ goto cleanup;
+ }
+ xmlNodeAdrPtr = xmlDocCopyNode((xmlNodePtr) xmlNodeAdr, docPtr, 1);
+ if (xmlNodeAdrPtr == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not copy item ADDRESS"));
+ goto cleanup;
+ }
+
+ xmlNodeRef = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ADDRESSING, WSA_REFERENCE_PARAMETERS);
+ if (xmlNodeRef == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup pull response item REFERENCE PARAMETERS"));
+ goto cleanup;
+ }
+ xmlNodeRefPtr = xmlDocCopyNode((xmlNodePtr) xmlNodeRef, docPtr, 1);
+ if (xmlNodeRefPtr == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not copy item REFERENCE PARAMETERS"));
+ goto cleanup;
+ }
+
+ /* Build XmlDoc with adding previous EPR nodes childs */
+ xmlNodeParam = ws_xml_add_child(*parentNode, classURI, paramName, NULL);
+ if (xmlNodeParam == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not add child node to xmlNodeParam"));
+ goto cleanup;
+ }
+
+/*
+ The folowing line has been commented because of a memory corruption issue reported in the openwsman library
+ [ issue #43 - xml_parser_ns_add: alloc item size, not pointer size ]
+ xmlNodeSetLang((xmlNodePtr) xmlNodeParam, BAD_CAST "en-US");
+*/
+ ns = ws_xml_ns_add(xmlNodeParam, "http://schemas.xmlsoap.org/ws/2004/08/addressing", "a");
+ if (ns == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not set namespace adressing to xmlNodeParam"));
+ goto cleanup;
+ }
+
+ ns = NULL;
+ ns = ws_xml_ns_add(xmlNodeParam, "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd", "w");
+ if (ns == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not set namespace wsman to xmlNodeParam"));
+ goto cleanup;
+ }
+
+ if (xmlAddChild( (xmlNodePtr)*parentNode,(xmlNodePtr) xmlNodeParam) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not add child to xml parent node"));
+ goto cleanup;
+ }
+
+ if (xmlAddChild( (xmlNodePtr)xmlNodeParam, xmlNodeAdrPtr) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not add child to xml parent node"));
+ goto cleanup;
+ }
+
+ if (xmlAddChild( (xmlNodePtr)xmlNodeParam, xmlNodeRefPtr) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not add child to xml parent node"));
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ if (options != NULL) {
+ wsmc_options_destroy(options);
+ }
+ if (filter != NULL) {
+ filter_destroy(filter);
+ }
+ ws_xml_destroy_doc(xmlDocResponse);
+ VIR_FREE(enumContext);
+ VIR_FREE(query_string);
+
+ return result;
+}
+
+
+/* Bull */
+/* Call wsmc_action_invoke() function of OpenWsman API with XML tree given in parameters*/
+int
+hypervInvokeMethodXml(hypervPrivate *priv,WsXmlDocH xmlDocRoot,
+ const char *methodName, const char *ressourceURI, const char *selector)
+{
+
+ int result = -1;
+ int returnCode;
+ char *instanceID = NULL;
+ char *xpath_expr_string = NULL;
+ char *returnValue = NULL;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ virBuffer xpath_expr_buff = VIR_BUFFER_INITIALIZER;
+ client_opt_t *options = NULL;
+ WsXmlDocH response;
+ Msvm_ConcreteJob *concreteJob = NULL;
+ bool completed = false;
+ bool locked;
+
+ options = wsmc_options_init();
+
+ wsmc_add_selectors_from_str(options, selector);
+
+#ifdef DUMP_REQUEST
+ wsmc_set_action_option(options, FLAG_DUMP_REQUEST);
+#endif
+
+ /* Invoke action */
+ response = wsmc_action_invoke(priv->client,ressourceURI,options,methodName,xmlDocRoot);
+
+ virBufferAsprintf(&xpath_expr_buff, "/s:Envelope/s:Body/p:%s_OUTPUT/p:ReturnValue", methodName);
+ xpath_expr_string = virBufferContentAndReset(&xpath_expr_buff);
+
+ if (xpath_expr_string == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "ReturnValue", "RequestStateChange");
+ goto cleanup;
+ }
+
+ /* Check return value */
+ returnValue = ws_xml_get_xpath_value(response, xpath_expr_string);
+
+ xpath_expr_string = NULL;
+
+ if (returnValue == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "ReturnValue", "RequestStateChange");
+ goto cleanup;
+ }
+
+ if (virStrToLong_i(returnValue, NULL, 10, &returnCode) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse return code from '%s'"), returnValue);
+ goto cleanup;
+ }
+
+ if (returnCode == CIM_RETURNCODE_TRANSITION_STARTED) {
+
+ virBufferAsprintf(&xpath_expr_buff, "/s:Envelope/s:Body/p:%s_OUTPUT/p:Job/a:ReferenceParameters/w:SelectorSet/w:Selector[@Name='InstanceID']", methodName);
+ xpath_expr_string = virBufferContentAndReset(&xpath_expr_buff);
+
+ if (xpath_expr_string == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "InstanceID", "RequestStateChange");
+ goto cleanup;
+ }
+
+ /* Get concrete job object */
+ instanceID = ws_xml_get_xpath_value(response, xpath_expr_string);
+
+ if (instanceID == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "InstanceID", "RequestStateChange");
+ goto cleanup;
+ }
+
+ /* Unlock mutex */
+ /* hypervGetMsvmConcreteJobList calls hypervEnumAndPull which also tries to lock priv->mutex */
+ pthread_mutex_unlock(&priv->mutex);
+ locked = false;
+ /* FIXME: Poll every 100ms until the job completes or fails. There
+ * seems to be no other way than polling. */
+ while (!completed) {
+ virBufferAddLit(&query, MSVM_CONCRETEJOB_WQL_SELECT);
+ virBufferAsprintf(&query, "where InstanceID = \"%s\"", instanceID);
+
+ if (hypervGetMsvmConcreteJobList(priv, &query, &concreteJob) < 0) {
+ goto cleanup;
+ }
+
+ if (concreteJob == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "Msvm_ConcreteJob", "RequestStateChange");
+ goto cleanup;
+ }
+
+ switch (concreteJob->data->JobState) {
+ case MSVM_CONCRETEJOB_JOBSTATE_NEW:
+ case MSVM_CONCRETEJOB_JOBSTATE_STARTING:
+ case MSVM_CONCRETEJOB_JOBSTATE_RUNNING:
+ case MSVM_CONCRETEJOB_JOBSTATE_SHUTTING_DOWN:
+ hypervFreeObject(priv, (hypervObject *)concreteJob);
+ concreteJob = NULL;
+
+ usleep(100 * 1000);
+ continue;
+
+ case MSVM_CONCRETEJOB_JOBSTATE_COMPLETED:
+ completed = true;
+ break;
+
+ case MSVM_CONCRETEJOB_JOBSTATE_TERMINATED:
+ case MSVM_CONCRETEJOB_JOBSTATE_KILLED:
+ case MSVM_CONCRETEJOB_JOBSTATE_EXCEPTION:
+ case MSVM_CONCRETEJOB_JOBSTATE_SERVICE:
+ goto cleanup;
+
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Concrete job for %s invocation is in unknown state"),
+ "RequestStateChange");
+ goto cleanup;
+ }
+ }
+ } else if (returnCode != CIM_RETURNCODE_COMPLETED_WITH_NO_ERROR) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Invocation of %s returned an error: %s (%d)"),
+ "RequestStateChange", hypervReturnCodeToString(returnCode),
+ returnCode);
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ if (options != NULL) {
+ wsmc_options_destroy(options);
+ }
+ ws_xml_destroy_doc(response);
+ VIR_FREE(returnValue);
+ VIR_FREE(instanceID);
+ VIR_FREE(xpath_expr_string);
+ hypervFreeObject(priv, (hypervObject *)concreteJob);
+
+ if (locked == true) pthread_mutex_unlock(&priv->mutex);
+
+ return result;
+}
+
+
+/* Bull */
+/* Generate a XML tree with all param_t given in parameters */
+int
+hypervInvokeMethod(hypervPrivate *priv, invokeXmlParam *param_t, int nbParameters,
+ const char* methodName, const char* providerURI, const char *selector)
+{
+
+ int res = -1;
+ WsXmlDocH doc = NULL;
+ WsXmlNodeH methodNode = NULL;
+ eprParam *epr;
+ embeddedParam *embedded;
+ simpleParam *simple;
+ int i =0;
+
+ if (hypervCreateXmlStruct(methodName,providerURI,&doc,&methodNode) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not create xml base structure"));
+ goto cleanup;
+ }
+
+ while ( i < nbParameters) {
+ switch (param_t[i].type){
+ case EPR_PARAM:
+ epr = (eprParam*)param_t[i].param;
+ if (hypervAddEprParam(param_t[i].name, epr->query,epr->wmiProviderURI,providerURI,&methodNode,doc,priv) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add EPR param to xml base structure "));
+ goto cleanup;
+ }
+ break;
+ case EMBEDDED_PARAM:
+ embedded = (embeddedParam*)param_t[i].param;
+ if (hypervAddEmbeddedParam(embedded->prop_t,embedded->nbProps,param_t[i].name,embedded->instanceName,providerURI,&methodNode) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add embedded instance param to xml base structure "));
+ goto cleanup;
+ }
+ break;
+ case SIMPLE_PARAM:
+ simple = (simpleParam*)param_t[i].param;
+ if (hypervAddSimpleParam(param_t[i].name,simple->value,providerURI,&methodNode) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add embedded instance param to xml base structure "));
+ goto cleanup;
+ }
+ break;
+ }
+ i++;
+ }
+
+ if (hypervInvokeMethodXml(priv,doc,methodName,providerURI,selector) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Error during invocation action"));
+ goto cleanup;
+ }
+
+ res = 0;
+
+ cleanup:
+ if (doc != NULL)
+ ws_xml_destroy_doc(doc);
+
+ return res;
+}
int
@@ -128,8 +817,13 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
return -1;
}
- if (virBufferCheckError(query) < 0)
+ if (virBufferError(query)) {
+ virReportOOMError();
return -1;
+ }
+
+ /* Bull - Lock mutex */
+ pthread_mutex_lock(&priv->mutex);
serializerContext = wsmc_get_serialization_context(priv->client);
@@ -258,6 +952,9 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
ws_xml_destroy_doc(response);
VIR_FREE(enumContext);
hypervFreeObject(priv, head);
+
+ /* Bull - Unlock mutex */
+ pthread_mutex_unlock(&priv->mutex);
return result;
}
@@ -403,8 +1100,13 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
virBuffer query = VIR_BUFFER_INITIALIZER;
Msvm_ConcreteJob *concreteJob = NULL;
bool completed = false;
-
+ bool locked; /* Bull */
+
virUUIDFormat(domain->uuid, uuid_string);
+
+ /* Bull - Lock mutex */
+ pthread_mutex_lock(&priv->mutex);
+ locked = true;
if (virAsprintf(&selector, "Name=%s&CreationClassName=Msvm_ComputerSystem",
uuid_string) < 0 ||
@@ -456,6 +1158,11 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
"InstanceID", "RequestStateChange");
goto cleanup;
}
+
+ /* Bull - Unlock mutex */
+ /* hypervGetMsvmConcreteJobList calls hypervEnumAndPull which also tries to lock priv->mutex */
+ pthread_mutex_unlock(&priv->mutex);
+ locked = false;
/* FIXME: Poll every 100ms until the job completes or fails. There
* seems to be no other way than polling. */
@@ -527,6 +1234,9 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
VIR_FREE(instanceID);
hypervFreeObject(priv, (hypervObject *)concreteJob);
+ /* Bull - Unlock mutex */
+ if (locked == true) pthread_mutex_unlock(&priv->mutex);
+
return result;
}
@@ -676,5 +1386,32 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
}
+/* Bull */
+int
+hypervMsvmVirtualSwitchToNetwork(virConnectPtr conn,
+ Msvm_VirtualSwitch *virtualSwitch, virNetworkPtr *network)
+{
+ unsigned char uuid[VIR_UUID_BUFLEN];
+
+ if (network == NULL || *network != NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (virUUIDParse(virtualSwitch->data->Name, uuid) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse UUID from string '%s'"),
+ virtualSwitch->data->Name);
+ return -1;
+ }
+
+ *network = virGetNetwork(conn, virtualSwitch->data->ElementName, uuid);
+
+ if (*network == NULL) {
+ return -1;
+ }
+
+ return 0;
+}
#include "hyperv_wmi.generated.c"
diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h
index 5fbbbac..9a4f920 100644
--- a/src/hyperv/hyperv_wmi.h
+++ b/src/hyperv/hyperv_wmi.h
@@ -24,11 +24,76 @@
#ifndef __HYPERV_WMI_H__
# define __HYPERV_WMI_H__
+#define ROOT_CIMV2 \
+ "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*"
+
+#define ROOT_VIRTUALIZATION \
+ "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/*"
+
# include "virbuffer.h"
# include "hyperv_private.h"
# include "hyperv_wmi_classes.h"
# include "openwsman.h"
+/* Bull */
+#define EPR_PARAM 0
+#define SIMPLE_PARAM 1
+#define EMBEDDED_PARAM 2
+
+
+/* Bull */
+
+typedef struct _invokeXmlParam invokeXmlParam;
+struct _invokeXmlParam{
+ const char *name;
+ int type;
+ void *param;
+};
+
+typedef struct _eprParam eprParam;
+struct _eprParam{
+ virBufferPtr query;
+ const char *wmiProviderURI;
+};
+
+typedef struct _simpleParam simpleParam;
+struct _simpleParam{
+ const char *value;
+};
+
+typedef struct _properties_t properties_t;
+struct _properties_t{
+ const char *name;
+ const char *val;
+};
+
+typedef struct _embeddedParam embeddedParam;
+struct _embeddedParam{
+ const char *instanceName;
+ properties_t *prop_t;
+ int nbProps;
+};
+
+int
+hypervCreateXmlStruct(const char *methodName,const char *classURI,WsXmlDocH *xmlDocRoot, WsXmlNodeH *xmlNodeMethod);
+
+const char *
+hypervGetPropType(const char * className, const char *attrName);
+
+int
+hypervAddEmbeddedParam(properties_t *prop_t,int nbProps, const char *paramName, const char *instanceName,const char *classURI, WsXmlNodeH *parentNode);
+
+int
+hypervAddSimpleParam(const char *paramName, const char* value, const char *classURI, WsXmlNodeH *parentNode);
+
+int
+hypervAddEprParam(const char *paramName, virBufferPtr query,const char *root,const char *classURI, WsXmlNodeH *parentNode, WsXmlDocH doc, hypervPrivate *priv);
+
+int
+hypervInvokeMethodXml(hypervPrivate *priv,WsXmlDocH xmlDocRoot,const char *methodName,const char *ressourceURI, const char *selector);
+
+int
+hypervInvokeMethod(hypervPrivate *priv, invokeXmlParam *parameters, int nbParameters,const char* methodName, const char* providerURI, const char *selector);
typedef struct _hypervObject hypervObject;
@@ -53,7 +118,7 @@ int hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query,
const char *resourceUri, const char *className,
hypervObject **list);
-void hypervFreeObject(hypervPrivate *priv, hypervObject *object);
+void hypervFreeObject(hypervPrivate *priv ATTRIBUTE_UNUSED, hypervObject *object);
@@ -114,6 +179,15 @@ int hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
Msvm_ComputerSystem **computerSystem);
+/* Bull */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Msvm_VirtualSwitch
+ */
+
+int hypervMsvmVirtualSwitchToNetwork(virConnectPtr conn,
+ Msvm_VirtualSwitch *virtualSwitch, virNetworkPtr *network);
+
# include "hyperv_wmi.generated.h"
diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input
index 97f9dff..7f828d3 100644
--- a/src/hyperv/hyperv_wmi_generator.input
+++ b/src/hyperv/hyperv_wmi_generator.input
@@ -12,8 +12,8 @@
# ...
# end
#
-# Allowed values for <type> are: boolean, string, datetime, int8, int16,
-# int32, int64, uint8, uint16, uint32 and uint64
+# Allowed values for <type> are: boolean, string, datetime, sint8, sint16,
+# sint32, sint64, uint8, uint16, uint32 and uint64
#
# The property <name> can be followed by [] to define a dynamic array.
#
@@ -72,8 +72,8 @@ class Msvm_ConcreteJob
datetime ElapsedTime
uint32 JobRunTimes
uint8 RunMonth
- int8 RunDay
- int8 RunDayOfWeek
+ sint8 RunDay
+ sint8 RunDayOfWeek
datetime RunStartInterval
uint16 LocalOrUtcTime
datetime UntilTime
@@ -196,7 +196,7 @@ class Win32_ComputerSystem
string Caption
uint16 ChassisBootupState
string CreationClassName
- int16 CurrentTimeZone
+ sint16 CurrentTimeZone
boolean DaylightInEffect
string Description
string DNSHostName
@@ -219,7 +219,7 @@ class Win32_ComputerSystem
uint8 OEMLogoBitmap[]
string OEMStringArray[]
boolean PartOfDomain
- int64 PauseAfterReset
+ sint64 PauseAfterReset
uint16 PCSystemType
uint16 PowerManagementCapabilities[]
boolean PowerManagementSupported
@@ -229,8 +229,8 @@ class Win32_ComputerSystem
string PrimaryOwnerContact
string PrimaryOwnerName
uint16 ResetCapability
- int16 ResetCount
- int16 ResetLimit
+ sint16 ResetCount
+ sint16 ResetLimit
string Roles[]
string Status
string SupportContactDescription[]
@@ -296,3 +296,517 @@ class Win32_Processor
string Version
uint32 VoltageCaps
end
+
+
+class CIM_DataFile
+ uint32 AccessMask
+ boolean Archive
+ string Caption
+ boolean Compressed
+ string CompressionMethod
+ string CreationClassName
+ datetime CreationDate
+ string CSCreationClassName
+ string CSName
+ string Description
+ string Drive
+ string EightDotThreeFileName
+ boolean Encrypted
+ string EncryptionMethod
+ string Extension
+ string FileName
+ uint64 FileSize
+ string FileType
+ string FSCreationClassName
+ string FSName
+ boolean Hidden
+ datetime InstallDate
+ uint64 InUseCount
+ datetime LastAccessed
+ datetime LastModified
+ string Manufacturer
+ string Name
+ string Path
+ boolean Readable
+ string Status
+ boolean System
+ string Version
+ boolean Writeable
+end
+
+
+class Win32_ComputerSystemProduct
+ string Caption
+ string Description
+ string IdentifyingNumber
+ string Name
+ string SKUNumber
+ string UUID
+ string Vendor
+ string Version
+end
+
+class Msvm_VirtualSystemManagementService
+ string Caption
+ string Description
+ string ElementName
+ datetime InstallDate
+ uint16 OperationalStatus
+ string StatusDescriptions
+ string Status
+ uint16 HealthState
+ uint16 EnabledState
+ string OtherEnabledState
+ uint16 RequestedState
+ uint16 EnabledDefault
+ datetime TimeOfLastStateChange
+ string SystemCreationClassName
+ string SystemName
+ string CreationClassName
+ string Name
+ string PrimaryOwnerName
+ string PrimaryOwnerContact
+ string StartMode
+ boolean Started
+end
+
+class Msvm_VirtualSystemGlobalSettingData
+ string Caption
+ string Description
+ string ElementName
+ string InstanceID
+ string SystemName
+ uint16 SettingType
+ uint16 VirtualSystemType
+ string OtherVirtualSystemType
+ boolean AutoActivate
+ datetime CreationTime
+ string ExternalDataRoot
+ string SnapshotDataRoot
+ uint16 AutomaticStartupAction
+ datetime AutomaticStartupActionDelay
+ uint16 AutomaticShutdownAction
+ uint16 AutomaticRecoveryAction
+ string AdditionalRecoveryInformation
+ string ScopeOfResidence
+ uint32 DebugChannelId
+ boolean AllowFullSCSICommandSet
+ string Version
+end
+
+class Msvm_ResourceAllocationSettingData
+ string Caption
+ string Description
+ string InstanceID
+ string ElementName
+ uint16 ResourceType
+ string OtherResourceType
+ string ResourceSubType
+ string PoolID
+ uint16 ConsumerVisibility
+ string HostResource[]
+ string AllocationUnits
+ uint64 VirtualQuantity
+ uint64 Reservation
+ uint64 Limit
+ uint32 Weight
+ boolean AutomaticAllocation
+ boolean AutomaticDeallocation
+ string Parent
+ string Connection[]
+ string Address
+ uint16 MappingBehavior
+ string VirtualSystemIdentifiers[]
+end
+
+class Msvm_AllocationCapabilities
+ string Caption
+ string Description
+ string ElementName
+ string InstanceID
+ string OtherResourceType
+ uint16 RequestTypesSupported
+ string ResourceSubType
+ uint16 ResourceType
+ uint16 SharingMode
+ uint16 SupportedAddStates[]
+ uint16 SupportedRemoveStates[]
+end
+
+class Msvm_VirtualSwitch
+ string Caption
+ string Description
+ string ElementName
+ datetime InstallDate
+ uint16 OperationalStatus[]
+ string StatusDescriptions[]
+ string Status
+ uint16 HealthState
+ uint16 EnabledState
+ string OtherEnabledState
+ uint16 RequestedState
+ uint16 EnabledDefault
+ datetime TimeOfLastStateChange
+ string CreationClassName
+ string Name
+ string PrimaryOwnerContact
+ string PrimaryOwnerName
+ string Roles[]
+ string NameFormat
+ string OtherIdentifyingInfo[]
+ string IdentifyingDescriptions[]
+ uint16 Dedicated[]
+ string OtherDedicatedDescriptions[]
+ uint16 ResetCapability
+ uint16 PowerManagementCapabilities[]
+ string ScopeOfResidence
+ uint32 NumLearnableAddresses
+ uint32 MaxVMQOffloads
+ uint32 MaxChimneyOffloads
+end
+
+class Msvm_SwitchPort
+ string Caption
+ string ElementName
+ datetime InstallDate
+ string StatusDescriptions[]
+ string Status
+ uint16 HealthState
+ string OtherEnabledState
+ uint16 RequestedState
+ uint16 EnabledDefault
+ string SystemCreationClassName
+ string SystemName
+ string CreationClassName
+ string Description
+ uint16 OperationalStatus[]
+ uint16 EnabledState
+ datetime TimeOfLastStateChange
+ string Name
+ string NameFormat
+ uint16 ProtocolType
+ uint16 ProtocolIFType
+ string OtherTypeDescription
+ boolean BroadcastResetSupported
+ uint16 PortNumber
+ string ScopeOfResidence
+ uint32 VMQOffloadWeight
+ uint32 ChimneyOffloadWeight
+ uint32 VMQOffloadUsage
+ uint32 ChimneyOffloadUsage
+ uint32 VMQOffloadLimit
+ uint32 ChimneyOffloadLimit
+ boolean AllowMacSpoofing
+end
+
+class Msvm_SyntheticEthernetPortSettingData
+ string Caption
+ string Description
+ string InstanceID
+ string ElementName
+ uint16 ResourceType
+ string OtherResourceType
+ string ResourceSubType
+ string PoolID
+ uint16 ConsumerVisibility
+ string HostResource[]
+ string AllocationUnits
+ uint64 VirtualQuantity
+ uint64 Reservation
+ uint64 Limit
+ uint32 Weight
+ boolean AutomaticAllocation
+ boolean AutomaticDeallocation
+ string Parent
+ string Connection[]
+ string Address
+ uint16 MappingBehavior
+ string VirtualSystemIdentifiers[]
+ boolean StaticMacAddress
+end
+
+class Msvm_VirtualSwitchManagementService
+ string Caption
+ string Description
+ string ElementName
+ datetime InstallDate
+ uint16 OperationalStatus[]
+ string StatusDescriptions[]
+ string Status
+ uint16 HealthState
+ uint16 EnabledState
+ string OtherEnabledState
+ uint16 RequestedState
+ uint16 EnabledDefault
+ datetime TimeOfLastStateChange
+ string SystemCreationClassName
+ string SystemName
+ string CreationClassName
+ string Name
+ string PrimaryOwnerName
+ string PrimaryOwnerContact
+ string StartMode
+ boolean Started
+end
+
+class Win32_OperatingSystem
+ string BootDevice
+ string BuildNumber
+ string BuildType
+ string Caption
+ string CodeSet
+ string CountryCode
+ string CreationClassName
+ string CSCreationClassName
+ string CSDVersion
+ string CSName
+ sint16 CurrentTimeZone
+ boolean DataExecutionPrevention_Available
+ boolean DataExecutionPrevention_32BitApplications
+ boolean DataExecutionPrevention_Drivers
+ uint8 DataExecutionPrevention_SupportPolicy
+ boolean Debug
+ string Description
+ boolean Distributed
+ uint32 EncryptionLevel
+ uint8 ForegroundApplicationBoost
+ uint64 FreePhysicalMemory
+ uint64 FreeSpaceInPagingFiles
+ uint64 FreeVirtualMemory
+ datetime InstallDate
+ uint32 LargeSystemCache
+ datetime LastBootUpTime
+ datetime LocalDateTime
+ string Locale
+ string Manufacturer
+ uint32 MaxNumberOfProcesses
+ uint64 MaxProcessMemorySize
+ string MUILanguages[]
+ string Name
+ uint32 NumberOfLicensedUsers
+ uint32 NumberOfProcesses
+ uint32 NumberOfUsers
+ uint32 OperatingSystemSKU
+ string Organization
+ string OSArchitecture
+ uint32 OSLanguage
+ uint32 OSProductSuite
+ uint16 OSType
+ string OtherTypeDescription
+ boolean PAEEnabled
+ string PlusProductID
+ string PlusVersionNumber
+ boolean PortableOperatingSystem
+ boolean Primary
+ uint32 ProductType
+ string RegisteredUser
+ string SerialNumber
+ uint16 ServicePackMajorVersion
+ uint16 ServicePackMinorVersion
+ uint64 SizeStoredInPagingFiles
+ string Status
+ uint32 SuiteMask
+ string SystemDevice
+ string SystemDirectory
+ string SystemDrive
+ uint64 TotalSwapSpaceSize
+ uint64 TotalVirtualMemorySize
+ uint64 TotalVisibleMemorySize
+ string Version
+ string WindowsDirectory
+end
+
+class Win32_PerfFormattedData_HvStats_HyperVHypervisorVirtualProcessor
+ uint64 AddressDomainFlushesPersec
+ uint64 AddressSpaceEvictionsPersec
+ uint64 AddressSpaceFlushesPersec
+ uint64 AddressSpaceSwitchesPersec
+ uint64 APICEOIAccessesPersec
+ uint64 APICIPIsSentPersec
+ uint64 APICMMIOAccessesPersec
+ uint64 APICSelfIPIsSentPersec
+ uint64 APICTPRAccessesPersec
+ string Caption
+ uint64 ControlRegisterAccessesCost
+ uint64 ControlRegisterAccessesPersec
+ uint64 CPUIDInstructionsCost
+ uint64 CPUIDInstructionsPersec
+ uint64 CPUWaitTimePerDispatch
+ uint64 DebugRegisterAccessesCost
+ uint64 DebugRegisterAccessesPersec
+ string Description
+ uint64 EmulatedInstructionsCost
+ uint64 EmulatedInstructionsPersec
+ uint64 ExternalInterruptsCost
+ uint64 ExternalInterruptsPersec
+ uint64 Frequency_Object
+ uint64 Frequency_PerfTime
+ uint64 Frequency_Sys100NS
+ uint64 GlobalGVARangeFlushesPersec
+ uint64 GPASpaceHypercallsPersec
+ uint64 GuestPageTableMapsPersec
+ uint64 HardwareInterruptsPersec
+ uint64 HLTInstructionsCost
+ uint64 HLTInstructionsPersec
+ uint64 HypercallsCost
+ uint64 HypercallsPersec
+ uint64 IOInstructionsCost
+ uint64 IOInstructionsPersec
+ uint64 IOInterceptMessagesPersec
+ uint64 LargePageTLBFillsPersec
+ uint64 LocalFlushedGVARangesPersec
+ uint64 LogicalProcessorDispatchesPersec
+ uint64 LogicalProcessorHypercallsPersec
+ uint64 LogicalProcessorMigrationsPersec
+ uint64 LongSpinWaitHypercallsPersec
+ uint64 MemoryInterceptMessagesPersec
+ uint64 MSRAccessesCost
+ uint64 MSRAccessesPersec
+ uint64 MWAITInstructionsCost
+ uint64 MWAITInstructionsPersec
+ string Name
+ uint64 NestedPageFaultInterceptsCost
+ uint64 NestedPageFaultInterceptsPersec
+ uint64 OtherHypercallsPersec
+ uint64 OtherInterceptsCost
+ uint64 OtherInterceptsPersec
+ uint64 OtherMessagesPersec
+ uint64 PageFaultInterceptsCost
+ uint64 PageFaultInterceptsPersec
+ uint64 PageInvalidationsCost
+ uint64 PageInvalidationsPersec
+ uint64 PageTableAllocationsPersec
+ uint64 PageTableEvictionsPersec
+ uint64 PageTableReclamationsPersec
+ uint64 PageTableResetsPersec
+ uint64 PageTableValidationsPersec
+ uint64 PageTableWriteInterceptsPersec
+ uint64 PendingInterruptsCost
+ uint64 PendingInterruptsPersec
+ uint64 PercentGuestRunTime
+ uint64 PercentHypervisorRunTime
+ uint64 PercentRemoteRunTime
+ uint64 PercentTotalRunTime
+ uint64 ReflectedGuestPageFaultsPersec
+ uint64 SmallPageTLBFillsPersec
+ uint64 SyntheticInterruptHypercallsPersec
+ uint64 SyntheticInterruptsPersec
+ uint64 Timestamp_Object
+ uint64 Timestamp_PerfTime
+ uint64 Timestamp_Sys100NS
+ uint64 TotalInterceptsCost
+ uint64 TotalInterceptsPersec
+ uint64 TotalMessagesPersec
+ uint64 VirtualInterruptHypercallsPersec
+ uint64 VirtualInterruptsPersec
+ uint64 VirtualMMUHypercallsPersec
+ uint64 VirtualProcessorHypercallsPersec
+end
+
+class Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
+ uint64 AddressDomainFlushesPersec
+ uint64 AddressSpaceEvictionsPersec
+ uint64 AddressSpaceFlushesPersec
+ uint64 AddressSpaceSwitchesPersec
+ uint64 APICEOIAccessesPersec
+ uint64 APICIPIsSentPersec
+ uint64 APICMMIOAccessesPersec
+ uint64 APICSelfIPIsSentPersec
+ uint64 APICTPRAccessesPersec
+ string Caption
+ uint64 ControlRegisterAccessesCost
+ uint64 ControlRegisterAccessesCost_Base
+ uint64 ControlRegisterAccessesPersec
+ uint64 CPUIDInstructionsCost
+ uint64 CPUIDInstructionsCost_Base
+ uint64 CPUIDInstructionsPersec
+ uint64 CPUWaitTimePerDispatch
+ uint64 CPUWaitTimePerDispatch_Base
+ uint64 DebugRegisterAccessesCost
+ uint64 DebugRegisterAccessesCost_Base
+ uint64 DebugRegisterAccessesPersec
+ string Description
+ uint64 EmulatedInstructionsCost
+ uint64 EmulatedInstructionsCost_Base
+ uint64 EmulatedInstructionsPersec
+ uint64 ExternalInterruptsCost
+ uint64 ExternalInterruptsCost_Base
+ uint64 ExternalInterruptsPersec
+ uint64 Frequency_Object
+ uint64 Frequency_PerfTime
+ uint64 Frequency_Sys100NS
+ uint64 GlobalGVARangeFlushesPersec
+ uint64 GPASpaceHypercallsPersec
+ uint64 GuestPageTableMapsPersec
+ uint64 HardwareInterruptsPersec
+ uint64 HLTInstructionsCost
+ uint64 HLTInstructionsCost_Base
+ uint64 HLTInstructionsPersec
+ uint64 HypercallsCost
+ uint64 HypercallsCost_Base
+ uint64 HypercallsPersec
+ uint64 IOInstructionsCost
+ uint64 IOInstructionsCost_Base
+ uint64 IOInstructionsPersec
+ uint64 IOInterceptMessagesPersec
+ uint64 LargePageTLBFillsPersec
+ uint64 LocalFlushedGVARangesPersec
+ uint64 LogicalProcessorDispatchesPersec
+ uint64 LogicalProcessorHypercallsPersec
+ uint64 LogicalProcessorMigrationsPersec
+ uint64 LongSpinWaitHypercallsPersec
+ uint64 MemoryInterceptMessagesPersec
+ uint64 MSRAccessesCost
+ uint64 MSRAccessesCost_Base
+ uint64 MSRAccessesPersec
+ uint64 MWAITInstructionsCost
+ uint64 MWAITInstructionsCost_Base
+ uint64 MWAITInstructionsPersec
+ string Name
+ uint64 NestedPageFaultInterceptsCost
+ uint64 NestedPageFaultInterceptsCost_Base
+ uint64 NestedPageFaultInterceptsPersec
+ uint64 OtherHypercallsPersec
+ uint64 OtherInterceptsCost
+ uint64 OtherInterceptsCost_Base
+ uint64 OtherInterceptsPersec
+ uint64 OtherMessagesPersec
+ uint64 PageFaultInterceptsCost
+ uint64 PageFaultInterceptsCost_Base
+ uint64 PageFaultInterceptsPersec
+ uint64 PageInvalidationsCost
+ uint64 PageInvalidationsCost_Base
+ uint64 PageInvalidationsPersec
+ uint64 PageTableAllocationsPersec
+ uint64 PageTableEvictionsPersec
+ uint64 PageTableReclamationsPersec
+ uint64 PageTableResetsPersec
+ uint64 PageTableValidationsPersec
+ uint64 PageTableWriteInterceptsPersec
+ uint64 PendingInterruptsCost
+ uint64 PendingInterruptsCost_Base
+ uint64 PendingInterruptsPersec
+ uint64 PercentGuestRunTime
+ uint64 PercentGuestRunTime_Base
+ uint64 PercentHypervisorRunTime
+ uint64 PercentHypervisorRunTime_Base
+ uint64 PercentRemoteRunTime
+ uint64 PercentRemoteRunTime_Base
+ uint64 PercentTotalRunTime
+ uint64 PercentTotalRunTime_Base
+ uint64 ReflectedGuestPageFaultsPersec
+ uint64 SmallPageTLBFillsPersec
+ uint64 SyntheticInterruptHypercallsPersec
+ uint64 SyntheticInterruptsPersec
+ uint64 Timestamp_Object
+ uint64 Timestamp_PerfTime
+ uint64 Timestamp_Sys100NS
+ uint64 TotalInterceptsCost
+ uint64 TotalInterceptsCost_Base
+ uint64 TotalInterceptsPersec
+ uint64 TotalMessagesPersec
+ uint64 VirtualInterruptHypercallsPersec
+ uint64 VirtualInterruptsPersec
+ uint64 VirtualMMUHypercallsPersec
+ uint64 VirtualProcessorHypercallsPersec
+end
\ No newline at end of file
diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py
index f767d54..dcaf090 100755
--- a/src/hyperv/hyperv_wmi_generator.py
+++ b/src/hyperv/hyperv_wmi_generator.py
@@ -68,7 +68,8 @@ class Class:
header += "\n"
header += "#define %s_RESOURCE_URI \\\n" % name_upper
- if self.name.startswith("Win32_"):
+ #Bull
+ if self.name.startswith("Win32_") or self.name.startswith("CIM_DataFile"):
header += " \"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/%s\"\n" % self.name
else:
header += " \"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/%s\"\n" % self.name
@@ -113,7 +114,8 @@ class Class:
% (self.name.replace("_", ""), self.name)
source += "{\n"
- if self.name.startswith("Win32_"):
+ #Bull
+ if self.name.startswith("Win32_") or self.name.startswith("CIM_DataFile"):
source += " return hypervEnumAndPull(priv, query, ROOT_CIMV2,\n"
else:
source += " return hypervEnumAndPull(priv, query, ROOT_VIRTUALIZATION,\n"
@@ -149,15 +151,34 @@ class Class:
return source
-
+ #Bull
+ def generate_tab_classes(self):
+ tab_class = " {(\"%s" % self.name
+ tab_class += "\"),cimTypes_%s" % self.name
+ tab_class += "}"
+
+ return tab_class
+
+ #Bull
+ def generate_tabs_types(self):
+ tab_types = "CimTypes cimTypes_%s[] = {\n" % self.name
+ for property in self.properties[:-1]:
+ tab_types += property.generate_type_tab()
+ tab_types += ",\n"
+ property = self.properties[len(self.properties)-1]
+ tab_types += property.generate_type_tab()
+ tab_types += ",\n\t{(\"\\0\"),(\"\\0\")}\n};\n"
+
+ return tab_types
+
class Property:
typemap = {"boolean" : "BOOL",
"string" : "STR",
"datetime" : "STR",
- "int8" : "INT8",
- "int16" : "INT16",
- "int32" : "INT32",
- "int64" : "INT64",
+ "sint8" : "INT8",
+ "sint16" : "INT16",
+ "sint32" : "INT32",
+ "sint64" : "INT64",
"uint8" : "UINT8",
"uint16" : "UINT16",
"uint32" : "UINT32",
@@ -189,7 +210,16 @@ class Property:
return " SER_NS_%s(%s_RESOURCE_URI, \"%s\", 1),\n" \
% (Property.typemap[self.type], class_name.upper(), self.name)
-
+ #Bull
+ def generate_type_tab(self):
+ tab_class = " {(\"%s" % self.name
+ tab_class += "\"),(\"%s" % self.type
+ #Adrien
+ #If the attribute is an array, "[]" is added at the end of the type
+ if self.is_array:
+ tab_class += "[]"
+ tab_class += "\")}"
+ return tab_class
def open_and_print(filename):
if filename.startswith("./"):
@@ -238,7 +268,20 @@ def parse_class(block):
return Class(name=name, properties=properties)
-
+#Bull
+def print_type_header():
+ header_types = "struct cimTypes{\n"
+ header_types += " const char *name;\n"
+ header_types += " const char *type;\n"
+ header_types += "};\n"
+ header_types += "typedef struct cimTypes CimTypes;\n\n"
+ header_types += "struct cimClasses{\n"
+ header_types += " const char *name;\n"
+ header_types += " CimTypes *cimTypesPtr;\n"
+ header_types += "};\n"
+ header_types += "typedef struct cimClasses CimClasses;\n\n"
+
+ return header_types
def main():
if "srcdir" in os.environ:
@@ -253,6 +296,9 @@ def main():
classes_typedef = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes.generated.typedef"))
classes_header = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes.generated.h"))
classes_source = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes.generated.c"))
+
+ #Bull
+ classes_test_header = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes_attr.generated.h"))
# parse input file
number = 0
@@ -294,6 +340,10 @@ def main():
classes_typedef.write(notice)
classes_header.write(notice)
classes_source.write(notice)
+
+ #Bull
+ classes_test_header.write(notice)
+ classes_test_header.write(print_type_header())
names = classes_by_name.keys()
names.sort()
@@ -304,8 +354,17 @@ def main():
classes_typedef.write(classes_by_name[name].generate_classes_typedef())
classes_header.write(classes_by_name[name].generate_classes_header())
classes_source.write(classes_by_name[name].generate_classes_source())
-
-
+
+ #Bull
+ for name in names:
+ classes_test_header.write(classes_by_name[name].generate_tabs_types())
+ classes_test_header.write("CimClasses cimClasses[] = {\n")
+ for name in names[:-1]:
+ classes_test_header.write(classes_by_name[name].generate_tab_classes())
+ classes_test_header.write(",\n")
+ last_name = names[len(names)-1]
+ classes_test_header.write(classes_by_name[last_name].generate_tab_classes())
+ classes_test_header.write(",\n\t{(\"\\0\"),NULL}\n};")
if __name__ == "__main__":
main()
diff --git a/src/hyperv/openwsman.h b/src/hyperv/openwsman.h
index f66ed86..49b3e39 100644
--- a/src/hyperv/openwsman.h
+++ b/src/hyperv/openwsman.h
@@ -44,3 +44,7 @@
# endif
#endif /* __OPENWSMAN_H__ */
+
+/*wsman-xml.h*/
+WsXmlDocH ws_xml_create_doc( const char *rootNsUri, const char *rootName);
+WsXmlNodeH xml_parser_get_root(WsXmlDocH doc);
10 years, 3 months
[libvirt] Hyervisor Features elements
by bancfc@openmailbox.org
Hello. Under Hypevisor Features for Domain elements, I noticed new
features being added like
<kvm>
<hidden state='on'/>
</kvm>
Probably more will be added later I am guessing.
-Is this a performance feature?
-Can it also be applied to qemu only machine templates? (I don't use
qemu only, but maintain templates for both that's the reason for asking)
10 years, 3 months
[libvirt] [PATCH] storage: zfs: implement pool build and delete
by Roman Bogorodskiy
Provide an implementation for buildPool and deletePool operations for
the ZFS storage backend.
---
docs/schemas/storagepool.rng | 1 +
src/storage/storage_backend_zfs.c | 57 +++++++++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+)
diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
index 908cc11..da8e1f3 100644
--- a/docs/schemas/storagepool.rng
+++ b/docs/schemas/storagepool.rng
@@ -386,6 +386,7 @@
<element name='source'>
<interleave>
<ref name='sourceinfoname'/>
+ <ref name='sourceinfodev'/>
</interleave>
</element>
</define>
diff --git a/src/storage/storage_backend_zfs.c b/src/storage/storage_backend_zfs.c
index d8201ac..9482706 100644
--- a/src/storage/storage_backend_zfs.c
+++ b/src/storage/storage_backend_zfs.c
@@ -325,6 +325,61 @@ virStorageBackendZFSDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
return ret;
}
+static int
+virStorageBackendZFSBuildPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ unsigned int flags)
+{
+ virCommandPtr cmd = NULL;
+ size_t i;
+ int ret = -1;
+
+ virCheckFlags(0, -1);
+
+ if (pool->def->source.ndevice == 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("missing source devices"));
+ return -1;
+ }
+
+ cmd = virCommandNewArgList(ZPOOL, "create",
+ pool->def->source.name, NULL);
+
+ for (i = 0; i < pool->def->source.ndevice; i++)
+ virCommandAddArg(cmd, pool->def->source.devices[i].path);
+
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ virCommandFree(cmd);
+ return ret;
+}
+
+static int
+virStorageBackendZFSDeletePool(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ unsigned int flags)
+{
+ virCommandPtr cmd = NULL;
+ int ret = -1;
+
+ virCheckFlags(0, -1);
+
+ cmd = virCommandNewArgList(ZPOOL, "destroy",
+ pool->def->source.name, NULL);
+
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ virCommandFree(cmd);
+ return ret;
+}
virStorageBackend virStorageBackendZFS = {
.type = VIR_STORAGE_POOL_ZFS,
@@ -333,6 +388,8 @@ virStorageBackend virStorageBackendZFS = {
.refreshPool = virStorageBackendZFSRefreshPool,
.createVol = virStorageBackendZFSCreateVol,
.deleteVol = virStorageBackendZFSDeleteVol,
+ .buildPool = virStorageBackendZFSBuildPool,
+ .deletePool = virStorageBackendZFSDeletePool,
.uploadVol = virStorageBackendVolUploadLocal,
.downloadVol = virStorageBackendVolDownloadLocal,
};
--
2.0.2
10 years, 3 months
[libvirt] Question : Configuring a VM with backing 1G huge pages across 2 NUMA nodes
by Vinod, Chegu
Hi Michal,
'have a kernel+qemu+libvirt setup with all recent upstream bits on a given host & was trying to configure a VM with backing 1G huge pages...spanning 2 NUMA nodes.
The host had 3 1G huge pages on each of the 2 NUMA nodes :
# cat /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages
3
# cat /sys/devices/system/node/node1/hugepages/hugepages-1048576kB/nr_hugepages
3
And I had the following in the /etc/fstab
hugetlbfs /hugepages_1G hugetlbfs pagesize=1GB 0 0
I added the following entries in the xml file for the 4G/4vcpu VM
<memoryBacking>
<hugepages>
<page size='1048576' unit='KiB' nodeset='0'/>
<page size='1048576' unit='KiB' nodeset='1'/>
</hugepages>
</memoryBacking>
<vcpu placement='static'>4</vcpu>
<cputune>
<vcpupin vcpu='0' cpuset='0'/>
<vcpupin vcpu='1' cpuset='1'/>
<vcpupin vcpu='2' cpuset='8'/>
<vcpupin vcpu='3' cpuset='9'/>
</cputune>
....
<numatune>
<memory node="strict" nodeset="0-1"/>
</numatune>
....
<cpu>
<numa>
<cell id='0' cpus='0-1' memory='2097152'/>
<cell id='1' cpus='2-3' memory='2097152'/>
</numa>
</cpu>
The resulting qemu command looked like this :
/usr/local/bin/qemu-system-x86_64 -name vm1 -S -machine pc-i440fx-2.2,accel=kvm,usb=off \
-m 4096 -realtime mlock=off -smp 4,sockets=4,cores=1,threads=1 \
-object memory-backend-file,prealloc=yes,mem-path=/hugepages_1G/libvirt/qemu,size=2048M,id=ram-node0,host-nodes=0-1,policy=bind -numa node,nodeid=0,cpus=0-1,memdev=ram-node0 \
-object memory-backend-file,prealloc=yes,mem-path=/hugepages_1G/libvirt/qemu,size=2048M,id=ram-node1,host-nodes=0-1,policy=bind -numa node,nodeid=1,cpus=2-3,memdev=ram-node1 \
....
There were 3 1G pages available on each NUMA node on the host as shown above... and I noticed that the VM got backed by 3 1G pages from node0 and 1 1G page from node1.
#cat /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/free_hugepages
0
# cat /sys/devices/system/node/node1/hugepages/hugepages-1048576kB/free_hugepages
2
Not sure if this was expected behavior given the options I specified in the xml file ? If yes...Is there some additional option to specify (in the XML file) such that only a given number of 1Gig huge pages per node are picked to back the VM (i.e. in the above case just 2 1G from each node) ?
Thanks!
Vinod
10 years, 3 months