[libvirt] [PATCH v4 0/6] qemu: Introduce support for new the block_set_io_throttle parameters add in the version 1.7 of qemu.
by Matthias Gatto
This series of patches add support for bps_max, bps_rd_max, bps_wr_max,
bps_max, bps_rd_max, bps_wr_max, and iops_size in the functions qemuDomainSetBlockIoTune and qemuDomainGetBlockIoTune.
The last patch add support for these parameters to the virsh blkdeviotune command.
v2: spellfix
v3: Merge patch 1/9,2/9,5/9 together.
Change the capability detection.(patch 2/7 and 3/7).
Try to make the usage of QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX more explicit(patch 3/7).
v4: Rebase on HEAD.
Update qemu_driver to comply with Pavel's patchs.(patch 3/6)
Remove the qemu_monitor_text modification.(remove old patch 5/7)
Matthias Gatto (6):
qemu: Add defines for the news throttle options and modify the
structure _virDomainBlockIoTuneInfo.
qemu: Add the capability to detect if the qemu binary have the
capability to use bps_max and friends
qemu: Add bps_max and friends qemu driver
qemu: Add bps_max and friends QMP suport
qemu: add bps_max and friends to qemu command generation
virsh: Add bps_max and friends to virsh
include/libvirt/libvirt.h.in | 110 ++++++++++++++++
src/conf/domain_conf.c | 89 ++++++++++++-
src/conf/domain_conf.h | 7 ++
src/qemu/qemu_capabilities.c | 2 +
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 49 ++++++++
src/qemu/qemu_driver.c | 181 ++++++++++++++++++++++++++-
src/qemu/qemu_monitor.c | 10 +-
src/qemu/qemu_monitor.h | 6 +-
src/qemu/qemu_monitor_json.c | 68 ++++++++--
src/qemu/qemu_monitor_json.h | 6 +-
tests/qemucapabilitiesdata/caps_2.1.1-1.caps | 1 +
tests/qemumonitorjsontest.c | 6 +-
tools/virsh-domain.c | 119 ++++++++++++++++++
tools/virsh.pod | 10 ++
15 files changed, 634 insertions(+), 31 deletions(-)
--
1.8.3.1
10 years, 1 month
[libvirt] [PATCH] maint: Prohibit "devname" by a syntax check rules
by Peter Krempa
and tweak the code to avoid using it.
---
cfg.mk | 12 ++++++++++++
include/libvirt/libvirt.h.in | 2 +-
src/conf/interface_conf.c | 10 +++++-----
src/conf/interface_conf.h | 2 +-
src/interface/interface_backend_udev.c | 2 +-
src/qemu/qemu_monitor.c | 4 ++--
src/qemu/qemu_monitor.h | 6 +++---
src/util/virfile.c | 6 +++---
tools/virsh-domain.c | 4 ++--
tools/virt-host-validate-common.h | 2 +-
10 files changed, 31 insertions(+), 19 deletions(-)
diff --git a/cfg.mk b/cfg.mk
index ed7123b..8e99d04 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -962,6 +962,15 @@ sc_prohibit_paren_brace:
halt='Put space between closing parenthesis and opening brace' \
$(_sc_search_regexp)
+# Look for diagnostics that aren't marked for translation.
+# This won't find any for which error's format string is on a separate line.
+# The sed filters eliminate false-positives like these:
+sc_prohibit_devname:
+ @prohibit='\bdevname\b' \
+ exclude='sc_prohibit_devname' \
+ halt='avoid using 'devname' as FreeBSD exports the symbol' \
+ $(_sc_search_regexp)
+
# We don't use this feature of maint.mk.
prev_version_file = /dev/null
@@ -1146,3 +1155,6 @@ exclude_file_name_regexp--sc_prohibit_empty_first_line = \
exclude_file_name_regexp--sc_prohibit_useless_translation = \
^tests/virpolkittest.c
+
+exclude_file_name_regexp--sc_prohibit_devname = \
+ ^(tools/virsh.pod|cfg.mk|docs/.*)$$
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 5217ab3..c9018c0 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -5601,7 +5601,7 @@ typedef enum {
} virDomainConsoleFlags;
int virDomainOpenConsole(virDomainPtr dom,
- const char *devname,
+ const char *dev_name,
virStreamPtr st,
unsigned int flags);
diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c
index effe5ad..10c7c09 100644
--- a/src/conf/interface_conf.c
+++ b/src/conf/interface_conf.c
@@ -101,7 +101,7 @@ void virInterfaceDefFree(virInterfaceDefPtr def)
break;
case VIR_INTERFACE_TYPE_VLAN:
VIR_FREE(def->data.vlan.tag);
- VIR_FREE(def->data.vlan.devname);
+ VIR_FREE(def->data.vlan.dev_name);
break;
}
@@ -671,9 +671,9 @@ virInterfaceDefParseVlan(virInterfaceDefPtr def,
return -1;
}
- def->data.vlan.devname =
+ def->data.vlan.dev_name =
virXPathString("string(./interface/@name)", ctxt);
- if (def->data.vlan.devname == NULL) {
+ if (def->data.vlan.dev_name == NULL) {
virReportError(VIR_ERR_XML_ERROR,
"%s", _("vlan interface misses name attribute"));
return -1;
@@ -955,11 +955,11 @@ virInterfaceVlanDefFormat(virBufferPtr buf, const virInterfaceDef *def)
}
virBufferAsprintf(buf, "<vlan tag='%s'", def->data.vlan.tag);
- if (def->data.vlan.devname != NULL) {
+ if (def->data.vlan.dev_name != NULL) {
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
virBufferAsprintf(buf, "<interface name='%s'/>\n",
- def->data.vlan.devname);
+ def->data.vlan.dev_name);
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</vlan>\n");
} else {
diff --git a/src/conf/interface_conf.h b/src/conf/interface_conf.h
index 94c18ef..ac212fb 100644
--- a/src/conf/interface_conf.h
+++ b/src/conf/interface_conf.h
@@ -116,7 +116,7 @@ typedef struct _virInterfaceVlanDef virInterfaceVlanDef;
typedef virInterfaceVlanDef *virInterfaceVlanDefPtr;
struct _virInterfaceVlanDef {
char *tag; /* TAG for vlan */
- char *devname; /* device name for vlan */
+ char *dev_name; /* device name for vlan */
};
typedef struct _virInterfaceIpDef virInterfaceIpDef;
diff --git a/src/interface/interface_backend_udev.c b/src/interface/interface_backend_udev.c
index ecb1b2a..1dbbfe7 100644
--- a/src/interface/interface_backend_udev.c
+++ b/src/interface/interface_backend_udev.c
@@ -1015,7 +1015,7 @@ udevGetIfaceDefVlan(struct udev *udev ATTRIBUTE_UNUSED,
if (VIR_STRNDUP(ifacedef->data.vlan.tag, vid_pos, vid_len) < 0)
goto cleanup;
- if (VIR_STRNDUP(ifacedef->data.vlan.devname, dev_pos, dev_len) < 0) {
+ if (VIR_STRNDUP(ifacedef->data.vlan.dev_name, dev_pos, dev_len) < 0) {
VIR_FREE(ifacedef->data.vlan.tag);
goto cleanup;
}
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index c9929c3..00c62f7 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1821,7 +1821,7 @@ int qemuMonitorGetBlockExtent(qemuMonitorPtr mon,
unsigned long long *extent)
{
int ret;
- VIR_DEBUG("mon=%p, dev_name=%p", mon, dev_name);
+ VIR_DEBUG("mon=%p, dev_name=%s", mon, dev_name);
if (mon->json)
ret = qemuMonitorJSONGetBlockExtent(mon, dev_name, extent);
@@ -1836,7 +1836,7 @@ int qemuMonitorBlockResize(qemuMonitorPtr mon,
unsigned long long size)
{
int ret;
- VIR_DEBUG("mon=%p, devname=%p size=%llu", mon, device, size);
+ VIR_DEBUG("mon=%p, device=%s size=%llu", mon, device, size);
if (mon->json)
ret = qemuMonitorJSONBlockResize(mon, device, size);
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index f0c0b0a..63e14cc 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -333,7 +333,7 @@ int qemuMonitorBlockIOStatusToError(const char *status);
virHashTablePtr qemuMonitorGetBlockInfo(qemuMonitorPtr mon);
struct qemuDomainDiskInfo *
qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo,
- const char *devname);
+ const char *dev_name);
int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
const char *dev_name,
@@ -378,7 +378,7 @@ int qemuMonitorGetBlockExtent(qemuMonitorPtr mon,
const char *dev_name,
unsigned long long *extent);
int qemuMonitorBlockResize(qemuMonitorPtr mon,
- const char *devname,
+ const char *dev_name,
unsigned long long size);
int qemuMonitorSetVNCPassword(qemuMonitorPtr mon,
const char *password);
@@ -395,7 +395,7 @@ int qemuMonitorSetCPU(qemuMonitorPtr mon, int cpu, bool online);
/* XXX should we pass the virDomainDiskDefPtr instead
- * and hide devname details inside monitor. Reconsider
+ * and hide dev_name details inside monitor. Reconsider
* this when doing the QMP implementation
*/
int qemuMonitorEjectMedia(qemuMonitorPtr mon,
diff --git a/src/util/virfile.c b/src/util/virfile.c
index b3b8be2..c379df5 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -745,13 +745,13 @@ int virFileLoopDeviceAssociate(const char *file,
static int
-virFileNBDDeviceIsBusy(const char *devname)
+virFileNBDDeviceIsBusy(const char *dev_name)
{
char *path;
int ret = -1;
if (virAsprintf(&path, SYSFS_BLOCK_DIR "/%s/pid",
- devname) < 0)
+ dev_name) < 0)
return -1;
if (!virFileExists(path)) {
@@ -760,7 +760,7 @@ virFileNBDDeviceIsBusy(const char *devname)
else
virReportSystemError(errno,
_("Cannot check NBD device %s pid"),
- devname);
+ dev_name);
goto cleanup;
}
ret = 1;
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index ce59406..12550ff 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -2570,7 +2570,7 @@ static const vshCmdOptDef opts_console[] = {
.flags = VSH_OFLAG_REQ,
.help = N_("domain name, id or uuid")
},
- {.name = "devname",
+ {.name = "devname", /* sc_prohibit_devname */
.type = VSH_OT_STRING,
.help = N_("character device name")
},
@@ -2632,7 +2632,7 @@ cmdConsole(vshControl *ctl, const vshCmd *cmd)
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return false;
- if (vshCommandOptStringReq(ctl, cmd, "devname", &name) < 0)
+ if (vshCommandOptStringReq(ctl, cmd, "devname", &name) < 0) /* sc_prohibit_devname */
goto cleanup;
if (force)
diff --git a/tools/virt-host-validate-common.h b/tools/virt-host-validate-common.h
index a29f86c..25644dc 100644
--- a/tools/virt-host-validate-common.h
+++ b/tools/virt-host-validate-common.h
@@ -43,7 +43,7 @@ extern void virHostMsgFail(virHostValidateLevel level,
const char *hint);
extern int virHostValidateDevice(const char *hvname,
- const char *devname,
+ const char *dev_name,
virHostValidateLevel level,
const char *hint);
--
2.1.0
10 years, 1 month
[libvirt] [PATCHv2] storage: Fix logical pool fmt type
by Erik Skultety
According to our documentation logical pool supports formats 'auto' and
'lvm2'. However, in storage_conf.c we prevously defined storage pool
formats: unknown, lvm2. Due to backward compatibility reasons
documentation now refers to pool format type 'unknown' instead of 'auto'.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1123767
---
docs/schemas/storagepool.rng | 2 +-
docs/storage.html.in | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
index 2d165a3..7234ef3 100644
--- a/docs/schemas/storagepool.rng
+++ b/docs/schemas/storagepool.rng
@@ -465,7 +465,7 @@
<element name='format'>
<attribute name='type'>
<choice>
- <value>auto</value>
+ <value>unknown</value>
<value>lvm2</value>
</choice>
</attribute>
diff --git a/docs/storage.html.in b/docs/storage.html.in
index 3d2ffca..49fd862 100644
--- a/docs/storage.html.in
+++ b/docs/storage.html.in
@@ -331,7 +331,7 @@
The logical volume pool supports the following formats:
</p>
<ul>
- <li><code>auto</code> - automatically determine format</li>
+ <li><code>unknown</code> - automatically determine format</li>
<li>
<code>lvm2</code>
</li>
--
1.9.3
10 years, 1 month
[libvirt] [PATCH 0/2] Fix issues introduced by the bulk stats series.
by Peter Krempa
Patch 1/2 will be pushed soon under the trivial rule.
Patch 2/2 will be pushed soon under the build breaker rule.
Peter Krempa (2):
qemu: json: Fix missing break in error reporting function
qemu: monitor: Avoid shadowing variable "devname" on FreeBSD. Again.
src/qemu/qemu_monitor_json.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
--
2.1.0
10 years, 1 month
[libvirt] [PATCH] New features implemented in hyperv libvirt driver
by Yves Vinter
Authors: Simon Rastello (Bull), Adrien Kantcheff (Bull), Yves Vinter (Bull)
*** Summary of new features added in hyperv driver version 1.2.9 ***
- Added a mutex to prevent concurrent requests from being run simultaneously [WSMAN libray not thread-safe]
- Support of default authentication (credentials specified in ~/.config/libvirt/auth.conf)
- Support of new types of WSMAN requests involving passing complex parameters (simple types, EPR, embedded objects)
Required a new auto-generated header file to get the type of objects attributes (hyperv_wmi_classes_attr.generated.h)
- New functions:
- host management (in hyperv_driver module)
- capabilities (limited)
- domain management (in hyperv_driver module)
- domain creation from an XML description
- domain destruction
- attachment of pre-existing disk images on IDE controller
- attachment of Synthetic network devices
- memory and vcpu management (get and set methods)
- autostart, shutdown, ...
- network management (in hyperv_network_driver module)
- list available networks
- informations for a specified network
Required the declaration of new classes (in hyperv_wmi_generator.input)
- Fixed several memory leak issues
*** Important note ***
The current implementation of the driver does not support the new WMI root/virtualization/v2 name space.
It is not compatible with the last version of Hyper-V coming with Windows Server 2012 R2.
*** Detail of the updates by module ***
hyperv_driver.c
+++++++++++++++
- Support of default authentication (credentials specified in ~/.config/libvirt/auth.conf)
- Support of new libvirt functions
.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 */
- Updated libvirt functions
.connectOpen = hypervConnectOpen, /* 0.9.5 */
Support of default authentication (credentials specified in ~/.config/libvirt/auth.conf)
- New internal functions
- hypervLookupHostSystemBiosUuid
- hypervCapsInit
- hypervGetResourceAllocationSettingDataPATH
- hypervGetSwitchPortPATH
- hypervDomainAttachDisk
Used by hypervDomainAttachDevice
Currently support only attachments on the IDE controller (targets hda, hdb, hdc, hdd)
- hypervDomainAttachNetwork
Used by hypervDomainAttachDevice
Support attachment of synthetic network adapters (Legacy adapters are not supported)
- integer2string
- Notes related to devices attachments
- hypervDomainAttachDevice does not support attachment of ISO images (DVD drives)
- attachment of disk drives on the iSCSI controller is not yet supported
- devices detachment (drives or network) is not yet implemented
- networks and disk images must have been provisioned manually
- attached devices are not displayed in the domain XML description (hypervDomainGetXMLDesc)
hyperv_network_driver.c
+++++++++++++++++++++++
- Support of new libvirt function
.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 */
hyperv_private.h
++++++++++++++++
- Added Caps, XMLOption and a Mutex in the private structure
hyperv_wmi.c
++++++++++++
- Added an internal flag to dump WSMAN requests (DUMP_REQUEST)
- Support of new types of WSMAN requests involving passing complex parameters (simple types, EPR, embedded objects)
- New functions
- hypervInvokeMethod
- hypervMsvmVirtualSwitchToNetwork
Used by hypervNetworkLookupByName (hyperv_network_driver.c)
- New internal functions (used by hypervInvokeMethod)
- hypervCreateXmlStruct
- hypervGetPropType
- hypervAddEmbeddedParam
- hypervAddSimpleParam
- hypervAddEprParam
- hypervInvokeMethodXml
- Updated functions
- hypervEnumAndPull
- hypervInvokeMsvmComputerSystemRequestStateChange
Added a mutex to protect against concurrent requests
Added a call to dump WSMAN request in dump mode
hyperv_wmi.h
++++++++++++
- Added structures for passing new types of parameters (Simple, EPR, Embedded)
- Defined a new method to allow WSMAN requests with these different types of parameters (hypervInvokeMethod)
hyperv_wmi_generator.input
++++++++++++++++++++++++++
- Added new classes
- 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
+++++++++++++++++++++++
- Takes into account the CIM_DataFile class (from the root/cimv2 WMI name space)
- Generated a new header file "hyperv_wmi_classes_attr.generated.h" for getting the type of objects attributes
- Added new functions for generating this new file
- generate_tab_classes
Generates an entry for the declaration of cimClasses types
- generate_tabs_types
Generates declarations of cimTypes types
- generate_type_tab
Generates an entry for the declaration of cimTypes types
- print_type_header
Generates the declaration of structures cimClasses and cimTypes
openwsman.h
+++++++++++
- Added functions prototypes from wsman-xml.h to handle XmlDoc
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..80fbb92 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -20,7 +20,15 @@
*
*/
+/*
+ * This implementation does not support the new WMI root/virtualization/v2 namespace.
+ * It is therefore not compatible with Hyper-V v3 and Windows Server 2012 R2.
+ *
+ */
+
#include <config.h>
+#include <string.h>
+#include <stdlib.h>
#include "internal.h"
#include "datatypes.h"
@@ -41,6 +49,7 @@
#include "hyperv_wmi.h"
#include "openwsman.h"
#include "virstring.h"
+#include "virtypedparam.h"
#define VIR_FROM_THIS VIR_FROM_HYPERV
@@ -58,12 +67,100 @@ hypervFreePrivate(hypervPrivate **priv)
wsmc_release((*priv)->client);
}
+ if ((*priv)->caps != NULL)
+ virObjectUnref((*priv)->caps);
+ if ((*priv)->xmlopt != NULL)
+ virObjectUnref((*priv)->xmlopt);
+
+ /* Destroy the mutex */
+ pthread_mutex_destroy(&(*priv)->mutex);
+
hypervFreeParsedUri(&(*priv)->parsedUri);
VIR_FREE(*priv);
}
+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;
+}
+
+
+
+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 +205,16 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags
return VIR_DRV_OPEN_ERROR;
}
- /* Require auth */
- if (auth == NULL || auth->cb == NULL) {
+ /* Uses default authentification mechanism when not provided */
+ 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,7 +293,20 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags
goto cleanup;
}
+ /* Setup capabilities */
+ priv->caps = hypervCapsInit(priv);
+ if (priv->caps == NULL) {
+ goto cleanup;
+ }
+
+ /* Init xmlopt to parse Domain XML */
+ priv->xmlopt = virDomainXMLOptionNew(NULL, NULL, NULL);
+
conn->privateData = priv;
+
+ /* Initialize the mutex */
+ pthread_mutex_init(&priv->mutex, NULL);
+
priv = NULL;
result = VIR_DRV_OPEN_SUCCESS;
@@ -200,6 +314,7 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags
hypervFreePrivate(&priv);
VIR_FREE(username);
VIR_FREE(password);
+ virBufferFreeAndReset(&query);
hypervFreeObject(priv, (hypervObject *)computerSystem);
return result;
@@ -254,6 +369,7 @@ hypervConnectGetHostname(virConnectPtr conn)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
return hostname;
}
@@ -352,6 +468,7 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
hypervFreeObject(priv, (hypervObject *)processorList);
+ virBufferFreeAndReset(&query);
return result;
}
@@ -396,6 +513,7 @@ hypervConnectListDomains(virConnectPtr conn, int *ids, int maxids)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return success ? count : -1;
}
@@ -432,6 +550,7 @@ hypervConnectNumOfDomains(virConnectPtr conn)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return success ? count : -1;
}
@@ -464,6 +583,7 @@ hypervDomainLookupByID(virConnectPtr conn, int id)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
return domain;
}
@@ -500,6 +620,7 @@ hypervDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
return domain;
}
@@ -533,6 +654,7 @@ hypervDomainLookupByName(virConnectPtr conn, const char *name)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
return domain;
}
@@ -748,6 +870,7 @@ hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
hypervFreeObject(priv, (hypervObject *)processorSettingData);
hypervFreeObject(priv, (hypervObject *)memorySettingData);
+ virBufferFreeAndReset(&query);
return result;
}
@@ -783,7 +906,10 @@ hypervDomainGetState(virDomainPtr domain, int *state, int *reason,
}
-
+/* hypervDomainGetXMLDesc
+ * FIXME:
+ * - does not display attached devices (disk, nic)
+ */
static char *
hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
{
@@ -915,6 +1041,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 +1098,7 @@ hypervConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxn
}
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return count;
}
@@ -1007,6 +1135,7 @@ hypervConnectNumOfDefinedDomains(virConnectPtr conn)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return success ? count : -1;
}
@@ -1346,6 +1475,7 @@ hypervConnectListAllDomains(virConnectPtr conn,
}
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return ret;
}
@@ -1353,6 +1483,1778 @@ hypervConnectListAllDomains(virConnectPtr conn,
+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;
+}
+
+
+
+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;
+}
+
+
+
+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);
+}
+
+
+
+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;
+}
+
+
+
+static int hypervDomainShutdown(virDomainPtr dom)
+{
+ return hypervDomainShutdownFlags(dom, 0);
+}
+
+
+
+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;
+}
+
+
+
+static int
+hypervDomainGetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params, int *nparams)
+{
+ return hypervDomainGetSchedulerParametersFlags(dom, params, nparams, VIR_DOMAIN_AFFECT_CURRENT);
+}
+
+
+
+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;
+}
+
+
+
+static char*
+hypervConnectGetCapabilities(virConnectPtr conn)
+{
+ hypervPrivate *priv = conn->privateData;
+ char *xml = virCapabilitiesFormatXML(priv->caps);
+
+ if (xml == NULL) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ return xml;
+}
+
+
+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,'.');
+ if (p == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse version number from '%s'"),
+ datafile->data->Version);
+ goto cleanup;
+ }
+ p--;
+ *p = '\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);
+ virBufferFreeAndReset(&query);
+ return ret;
+}
+
+
+
+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;
+}
+
+
+
+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 = NULL;
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ virBuffer queryVssd = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ properties_t *tab_props = NULL;
+ eprParam eprparam;
+ embeddedParam embeddedparam;
+ int nb_params;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService";
+
+ 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 ? "2" : "0";
+ (*(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;
+}
+
+
+/* Convert an integer value into a string */
+static char *integer2string(unsigned long value)
+{
+ int sz;
+ char *ret;
+
+ sz = snprintf (NULL, 0, "%lu", value);
+ ret = (char *) malloc ((sz+1)*sizeof(char));
+ if (ret != NULL)
+ sprintf(ret, "%lu", value);
+
+ return ret;
+}
+
+
+static int
+hypervDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
+{
+ int res = -1;
+ invokeXmlParam *params = NULL;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ properties_t *tab_props = NULL;
+ 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";
+ unsigned long memory_mb = memory/1024;
+ char *memory_str = NULL;
+
+ // Memory value must be a multiple of 2 MB; round up it accordingly if necessary
+ if (memory_mb % 2) memory_mb++;
+
+ // Convert the memory value as a string value
+ memory_str = integer2string(memory_mb);
+
+ 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);
+ VIR_FREE(memory_str);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)memorySettingData);
+ virBufferFreeAndReset(&query);
+ virBufferFreeAndReset(&query2);
+ return res;
+}
+
+
+
+/*
+ * 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;
+ }
+
+ /* Count the number of backslash character */
+ strTemp = strchr(rasdInstanceID, '\\');
+ while (strTemp != NULL) {
+ n++;
+ strTemp = strchr(++strTemp, '\\');
+ }
+ /* Double the blackslashes */
+ strTemp = (char *) malloc(strlen(rasdInstanceID) + (n+1)*sizeof(char));
+ while (rasdInstanceID[i] != '\0') {
+ strTemp[j] = rasdInstanceID[i];
+ if (rasdInstanceID[i] == '\\') {
+ j++;
+ strTemp[j] = '\\';
+ }
+ i++;
+ j++;
+ }
+ strTemp[j] = '\0';
+
+ /* 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;
+}
+
+
+
+/*
+ * 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;
+}
+
+
+
+/*
+ * 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 = NULL;
+ properties_t *tab_props = NULL;
+ eprParam eprparam;
+ embeddedParam embeddedparam;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ Msvm_MemorySettingData *memorySettingData = NULL;
+ unsigned long memory_mb = memory/1024;
+ char *memory_str = NULL;
+
+ // Memory value must be a multiple of 2 MB; round up it accordingly if necessary
+ if (memory_mb % 2) memory_mb++;
+
+ // Convert the memory value as a string value
+ memory_str = integer2string(memory_mb);
+
+ 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);
+ VIR_FREE(memory_str);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)memorySettingData);
+ virBufferFreeAndReset(&query);
+ return res;
+}
+
+
+static int
+hypervDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+ return hypervDomainSetMemoryFlags(domain, memory, 0);
+}
+
+
+static int
+hypervDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ int res = -1;
+ invokeXmlParam *params = NULL;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ properties_t *tab_props = NULL;
+ 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";
+ char *nvcpus_str = NULL;
+
+ // Convert nvcpus as a string value
+ nvcpus_str = integer2string(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);
+ VIR_FREE(nvcpus_str);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)processorSettingData);
+ virBufferFreeAndReset(&query);
+ return res;
+}
+
+
+
+static int
+hypervDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
+{
+ return hypervDomainSetVcpusFlags(domain, nvcpus, 0);
+}
+
+
+/* hypervDomainAttachDisk
+ * FIXME:
+ * - added ressources must me removed in case of error
+ * - allow attaching disks on iSCSI (implemented only on IDE)
+ * - allow attaching ISO images (on DVD devices)
+ * - implement corresponding detach function
+ */
+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 = NULL, *ideControlerAddr = NULL;
+ 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; /* Part of resourceAllocationSettingData -> do not disallocate */
+ Msvm_ResourceAllocationSettingData *diskRasd = NULL; /* Part of resourceAllocationSettingData2 -> do not disallocate */
+ Msvm_ResourceAllocationSettingData *newDiskDrive = NULL; /* Part of resourceAllocationSettingData3 -> do not disallocate */
+ Msvm_AllocationCapabilities *allocationCapabilities = NULL;
+ Msvm_AllocationCapabilities *allocationCapabilities2 = NULL;
+ invokeXmlParam *params = NULL;
+ properties_t *tab_props = NULL;
+ 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(2*sizeof(char));
+ ideControlerAddr = (char *) malloc(2*sizeof(char));
+ 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 &&
+ strcmp(newDiskDrive->data->Parent, ideRasdPath) == 0 &&
+ strcmp(newDiskDrive->data->Address, ideControlerAddr) == 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:
+ if (ideRasdPath != NULL) VIR_FREE(ideRasdPath);
+ if (newDiskDrivePath != NULL) VIR_FREE(newDiskDrivePath);
+ if (ideControler != NULL) VIR_FREE(ideControler);
+ if (ideControlerAddr != NULL) VIR_FREE(ideControlerAddr);
+ if (tab_props != NULL) VIR_FREE(tab_props);
+ if (params != NULL) 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);
+ virBufferFreeAndReset(&query);
+
+ return ret;
+}
+
+
+
+/* hypervDomainAttachNetwork
+ * FIXME:
+ * - implement corresponding detach function
+ */
+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 = NULL;
+ invokeXmlParam *params = NULL;
+ 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((strlen(guid_string)+3) * sizeof(char));
+ 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:
+ if (virtualSystemIdentifiers != NULL) VIR_FREE(virtualSystemIdentifiers);
+ if (switchPortPATH != NULL) VIR_FREE(switchPortPATH);
+ if (tab_props!= NULL) VIR_FREE(tab_props);
+ if (params != NULL) VIR_FREE(params);
+ hypervFreeObject(priv, (hypervObject *)switchPort);
+ hypervFreeObject(priv, (hypervObject *)virtualSwitch);
+ virBufferFreeAndReset(&query);
+
+ return ret;
+}
+
+
+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:
+ virDomainDefFree(def);
+ virDomainDeviceDefFree(dev);
+ if (xmlDomain != NULL) VIR_FREE(xmlDomain);
+
+ return ret;
+}
+
+
+
+static int
+hypervDomainAttachDevice(virDomainPtr domain, const char *xml)
+{
+ return hypervDomainAttachDeviceFlags(domain, xml, 0);
+}
+
+
+
+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:
+ virDomainDefFree(def);
+ if (tab_props != NULL) VIR_FREE(tab_props);
+ if (params != NULL) VIR_FREE(params);
+
+ return domain;
+}
+
+
+
+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);
+ if (domain == NULL)
+ return NULL;
+
+ // 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;
+}
+
+
+
+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 = NULL;
+ 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:
+ if (params != NULL) VIR_FREE(params);
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
+
+ return result;
+}
+
+
+
+static int
+hypervDomainUndefine(virDomainPtr domain)
+{
+ return hypervDomainUndefineFlags(domain, 0);
+}
+
+
static virDriver hypervDriver = {
.no = VIR_DRV_HYPERV,
@@ -1389,6 +3291,31 @@ static virDriver hypervDriver = {
.domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
.domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
.connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
+ .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..ad24431 100644
--- a/src/hyperv/hyperv_network_driver.c
+++ b/src/hyperv/hyperv_network_driver.c
@@ -28,6 +28,9 @@
#include "viralloc.h"
#include "viruuid.h"
#include "hyperv_network_driver.h"
+#include "virstring.h"
+#include "hyperv_wmi.h"
+#include "network_conf.h"
#define VIR_FROM_THIS VIR_FROM_HYPERV
@@ -60,11 +63,246 @@ hypervNetworkClose(virConnectPtr conn)
}
+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;
+}
+
+
+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;
+}
+
+
+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;
+}
+
+
+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;
+}
+
+
+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;
+}
+
+
+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 */
+ .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..7c28053 100644
--- a/src/hyperv/hyperv_private.h
+++ b/src/hyperv/hyperv_private.h
@@ -27,12 +27,21 @@
# include "virerror.h"
# include "hyperv_util.h"
# include "openwsman.h"
+# include "capabilities.h"
+# include "domain_conf.h"
+
+#ifndef WIN32
+# include <pthread.h>
+#endif
typedef struct _hypervPrivate hypervPrivate;
struct _hypervPrivate {
hypervParsedUri *parsedUri;
WsManClient *client;
+ virCapsPtr caps;
+ virDomainXMLOptionPtr xmlopt; /* to parse Domain XML */
+ pthread_mutex_t mutex; /* to protect against concurrent calls (openwsman library not thread-safe) */
};
#endif /* __HYPERV_PRIVATE_H__ */
diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index acb705c..e84e208 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -33,16 +33,752 @@
#include "hyperv_wmi.h"
#include "virstring.h"
+# 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/*"
+/* Flag to dump WSMAN requests */
+#define DUMP_REQUEST 0
-#define VIR_FROM_THIS VIR_FROM_HYPERV
+/*
+ CAUTION: Special note regarding multi-threading
+ The openwsman library is not thread-safe (as reported in issue #10 "Simultaneous WsMan queries")
+ It has not been designed to allow to share the same connection for concurrent calls to wsmc_action_xxxx fonctions.
+ This implementation of this hyperv libvirt driver shares the same connection for all these calls.
+ Therefore, we have used a mutex to protect all functions that make usage of the wsmc_action_xxxx fonctions.
+*/
+
+
+/*
+ * Prototypes of internals functions
+ */
+
+const char *
+hypervGetPropType(const char * className, const char *attrName);
+
+int
+hypervCreateXmlStruct(const char *methodName, const char *classURI, WsXmlDocH *xmlDocRoot, WsXmlNodeH *xmlNodeMethod);
+
+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);
+
+
+
+/* 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;
+}
+
+
+/* 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;
+}
+
+
+/* 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;
+ char* type = NULL; /* Must not be freed */
+ char* typeCopy = NULL;
+ bool isArray = false;
+ int len = 0;
+ int i = 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; must be done on a copy
+ if (typeCopy != NULL) VIR_FREE(typeCopy);
+ typeCopy = strndup(type, strlen(type)-2);
+ type = typeCopy;
+ } 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);
+ if (typeCopy != NULL) VIR_FREE(typeCopy);
+ if (xmlBufferNode != NULL) xmlBufferFree(xmlBufferNode);
+
+ return result;
+}
+
+
+/* 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;
+}
+
+
+/* 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;
+
+ /* Protection against concurrent calls (the openwsman library is not thread-safe) */
+ pthread_mutex_lock(&priv->mutex);
+
+ /* Request options and filter */
+ options = wsmc_options_init();
+
+ if (options == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not initialize options"));
+ goto cleanup;
+ }
+
+#if DUMP_REQUEST
+ wsmc_set_action_option(options, FLAG_DUMP_REQUEST);
+#endif
+
+ 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);
+ /* Unlock the mutex */
+ pthread_mutex_unlock(&priv->mutex);
+
+ return result;
+}
+
+
+/* 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 = NULL;
+ Msvm_ConcreteJob *concreteJob = NULL;
+ bool completed = false;
+ bool locked;
+
+ /* Protection against concurrent calls (the openwsman library is not thread-safe) */
+ pthread_mutex_lock(&priv->mutex);
+ locked = true;
+
+ options = wsmc_options_init();
+
+ if (options == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not initialize options"));
+ goto cleanup;
+ }
+
+#if DUMP_REQUEST
+ wsmc_set_action_option(options, FLAG_DUMP_REQUEST);
+#endif
+
+ wsmc_add_selectors_from_str(options, selector);
+
+ /* 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);
+
+ VIR_FREE(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;
+ }
+
+ /* 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);
+ if (response != NULL)
+ ws_xml_destroy_doc(response);
+ VIR_FREE(returnValue);
+ VIR_FREE(instanceID);
+ VIR_FREE(xpath_expr_string);
+ hypervFreeObject(priv, (hypervObject *)concreteJob);
+ virBufferFreeAndReset(&query);
+ virBufferFreeAndReset(&xpath_expr_buff);
+
+ /* Unlock the mutex if needed */
+ if (locked == true) pthread_mutex_unlock(&priv->mutex);
+
+ return result;
+}
+
+
+/* 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 +864,13 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
return -1;
}
- if (virBufferCheckError(query) < 0)
+ if (virBufferError(query)) {
+ virReportOOMError();
return -1;
+ }
+
+ /* Protection against concurrent calls (the openwsman library is not thread-safe) */
+ pthread_mutex_lock(&priv->mutex);
serializerContext = wsmc_get_serialization_context(priv->client);
@@ -141,6 +882,10 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
goto cleanup;
}
+#if DUMP_REQUEST
+ wsmc_set_action_option(options, FLAG_DUMP_REQUEST);
+#endif
+
query_string = virBufferContentAndReset(query);
filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string);
@@ -259,6 +1004,9 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
VIR_FREE(enumContext);
hypervFreeObject(priv, head);
+ /* Unlock the mutex */
+ pthread_mutex_unlock(&priv->mutex);
+
return result;
}
@@ -403,9 +1151,14 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
virBuffer query = VIR_BUFFER_INITIALIZER;
Msvm_ConcreteJob *concreteJob = NULL;
bool completed = false;
+ bool locked;
virUUIDFormat(domain->uuid, uuid_string);
+ /* Protection against concurrent calls (the openwsman library is not thread-safe) */
+ pthread_mutex_lock(&priv->mutex);
+ locked = true;
+
if (virAsprintf(&selector, "Name=%s&CreationClassName=Msvm_ComputerSystem",
uuid_string) < 0 ||
virAsprintf(&properties, "RequestedState=%d", requestedState) < 0)
@@ -419,6 +1172,10 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
goto cleanup;
}
+#if DUMP_REQUEST
+ wsmc_set_action_option(options, FLAG_DUMP_REQUEST);
+#endif
+
wsmc_add_selectors_from_str(options, selector);
wsmc_add_prop_from_str(options, properties);
@@ -457,6 +1214,10 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
goto cleanup;
}
+ /* 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) {
@@ -527,12 +1288,15 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
VIR_FREE(instanceID);
hypervFreeObject(priv, (hypervObject *)concreteJob);
+ /* Unlock the mutex if needed */
+ if (locked == true) pthread_mutex_unlock(&priv->mutex);
+
return result;
}
int
hypervMsvmComputerSystemEnabledStateToDomainState
- (Msvm_ComputerSystem *computerSystem)
+(Msvm_ComputerSystem *computerSystem)
{
switch (computerSystem->data->EnabledState) {
case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN:
@@ -676,5 +1440,31 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
}
+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..f4ac319 100644
--- a/src/hyperv/hyperv_wmi.h
+++ b/src/hyperv/hyperv_wmi.h
@@ -24,11 +24,61 @@
#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"
+/*
+ * Type of parameters for hypervInvokeMethod function
+ */
+
+enum _PARAM_Type {
+ EPR_PARAM = 0,
+ SIMPLE_PARAM = 1,
+ EMBEDDED_PARAM = 2,
+};
+
+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
+hypervInvokeMethod(hypervPrivate *priv, invokeXmlParam *parameters, int nbParameters,const char* methodName, const char* providerURI, const char *selector);
typedef struct _hypervObject hypervObject;
@@ -53,7 +103,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 +164,13 @@ int hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
Msvm_ComputerSystem **computerSystem);
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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..a785df2 100755
--- a/src/hyperv/hyperv_wmi_generator.py
+++ b/src/hyperv/hyperv_wmi_generator.py
@@ -68,7 +68,7 @@ class Class:
header += "\n"
header += "#define %s_RESOURCE_URI \\\n" % name_upper
- if self.name.startswith("Win32_"):
+ 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 +113,7 @@ class Class:
% (self.name.replace("_", ""), self.name)
source += "{\n"
- if self.name.startswith("Win32_"):
+ 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 +149,32 @@ class Class:
return source
+ def generate_tab_classes(self):
+ tab_class = " {(\"%s" % self.name
+ tab_class += "\"),cimTypes_%s" % self.name
+ tab_class += "}"
+
+ return tab_class
+
+ 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 +206,14 @@ class Property:
return " SER_NS_%s(%s_RESOURCE_URI, \"%s\", 1),\n" \
% (Property.typemap[self.type], class_name.upper(), self.name)
-
+ def generate_type_tab(self):
+ tab_class = " {(\"%s" % self.name
+ tab_class += "\"),(\"%s" % self.type
+ #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 +262,19 @@ def parse_class(block):
return Class(name=name, properties=properties)
+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:
@@ -254,6 +290,8 @@ def main():
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"))
+ classes_test_header = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes_attr.generated.h"))
+
# parse input file
number = 0
classes_by_name = {}
@@ -295,6 +333,9 @@ def main():
classes_header.write(notice)
classes_source.write(notice)
+ classes_test_header.write(notice)
+ classes_test_header.write(print_type_header())
+
names = classes_by_name.keys()
names.sort()
@@ -305,7 +346,15 @@ def main():
classes_header.write(classes_by_name[name].generate_classes_header())
classes_source.write(classes_by_name[name].generate_classes_source())
-
+ 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, 1 month
[libvirt] [PATCH 0/3] Fix and improve block bulk stats
by Peter Krempa
Francesco Romani (1):
qemu: bulk stats: add block allocation information
Peter Krempa (2):
qemu: monitor: return block stats data as a hash to avoid disk mixup
qemu: monitor: Add helper function to fill physical/virtual image size
src/libvirt.c | 6 +
src/qemu/qemu_driver.c | 71 +++++++----
src/qemu/qemu_monitor.c | 31 +++--
src/qemu/qemu_monitor.h | 13 ++-
src/qemu/qemu_monitor_json.c | 273 +++++++++++++++++++++++++++++++------------
src/qemu/qemu_monitor_json.h | 6 +-
6 files changed, 286 insertions(+), 114 deletions(-)
--
2.1.0
10 years, 1 month
[libvirt] Release of libvirt 1.2.9
by Daniel Veillard
As planned the release of libvirt 1.2.9 is available, tagged in
git, signed sources and rpms are available at the usual place:
ftp://libvirt.org/libvirt/
I also pushed the libvirt-python release 1.2.9 to its own location:
ftp://libvirt.org/libvirt/python/
This release introduce some new APIs and functionalities as well as a
number of bug fixes including 2 security fixes: CVE-2014-3633 and
CVE-2014-3657 which has been pushed as part of the release. There is
also a number of improvements available.
In a nutshell users are invited to upgrade.
Features:
- Introduce virNodeAllocPages (Michal Privoznik)
- event: introduce new event for tunable values (Pavel Hrdina)
- add migration support for OpenVZ driver (Hongbin Lu)
- Add support for fetching statistics of completed jobs (Jiri Denemark)
Security:
- CVE-2014-3657: domain_conf: fix domain deadlock (Pavel Hrdina)
- CVE-2014-3633: qemu: blkiotune: Use correct definition when looking up disk (Peter Krempa)
Documentation:
- LXC: emphasis uid start of idmap only accept '0' in docs (Chen Hanxiao)
- specify vhost-net instead of net-vhost (Jianwei Hu)
- LXC: add HOME environment variable docs (Chen Hanxiao)
- update zfs documentation (Roman Bogorodskiy)
- man: virsh: Add docs for supported stats groups (Peter Krempa)
- lib: Document that virConnectGetAllDomainStats may omit some stats fields (Peter Krempa)
- lib: De-duplicate stats group documentation for all stats functions (Peter Krempa)
- util: Fix copy-paste error in virXPathLongLong description (Martin Kletzander)
- formatdomain: Update <loader/> example to match the rest (Michal Privoznik)
- virsh: desc command in --title mode mentions description instead of title (Peter Krempa)
- fix encryption format attribute in example (Ján Tomko)
Bug Fixes:
- Allow setting migration max downtime any time (Chris St. Pierre)
- qemu: monitor: return block stats data as a hash to avoid disk mixup (Peter Krempa)
- Also filter out non-migratable features out of host-passthrough (Ján Tomko)
- Don't verify CPU features with host-passthrough (Ján Tomko)
- Fix crash cpu_shares change event crash on domain startup (Ján Tomko)
- storage: Fix logical pool fmt type (Erik Skultety)
- virsh: Fix help message of allocpages (Tomoki Sekiyama)
- qemu: remove capabilities.monitor.sock when done (Guido Günther)
- conf: report error in virCPUDefParseXML (Jincheng Miao)
- Check for NULL in qemu monitor event filter (Ján Tomko)
- qemuPrepareNVRAM: Save domain after NVRAM path generation (Michal Privoznik)
- remoteNodeGetFreePages: Don't alloc args.pages.pages_val (Michal Privoznik)
- virNodeAllocPages: Disallow RO connection (Michal Privoznik)
- polkit_driver: fix possible segfault (Pavel Hrdina)
- blkdeviotune: fix bug with saving values into live XML (Pavel Hrdina)
- security: Fix labelling host devices (bz 1145968) (Cole Robinson)
- nodeinfo: fix nodeGetFreePages when max node is zero (Jincheng Miao)
- Fix bug with loading bridge name for active domain during libvirtd start (Pavel Hrdina)
- libvirt-guests: run after time-sync.target (Jim Fehlig)
- qemu: Fix memory leak in RDMA migration code (Jiri Denemark)
- nodeinfo: report error when given node is out of range (Jincheng Miao)
- virsh-host: fix pagesize unit of freepages (Jincheng Miao)
- qemu: raise an error when trying to use readonly sata disks (Giuseppe Scrivano)
- qemu: Add missing goto on rawio (John Ferlan)
- Move the FIPS detection from capabilities (Pavel Hrdina)
- virSecuritySELinuxSetTapFDLabel: Temporarily revert to old behavior (Michal Privoznik)
- audit: fix memory leak without WITH_AUDIT (Ján Tomko)
- Fixes for domains with no iothreads (Ján Tomko)
- Fix leak in x86UpdateHostModel (Ján Tomko)
- Fix libvirtd crash when removing metadata (Erik Skultety)
- qemu: Don't fail startup/attach for IOThreads if no JSON (John Ferlan)
- qemu: fix crash with shared disks (Ján Tomko)
- qemu: Honor hugepages for UMA domains (Michal Privoznik)
- conf: Disallow nonexistent NUMA nodes for hugepages (Michal Privoznik)
- domaincapstest: Run cleanly on systems missing OVMF firmware (Michal Privoznik)
- util: storage: Copy driver type when initializing chain element (Peter Krempa)
- qemu: time: Report errors if agent command fails (Peter Krempa)
- network: check negative values in bridge queues (Erik Skultety)
- openvz: fixed two memory leaks on migration code (Hongbin Lu)
- util: storage: Fix qcow(2) header parser according to docs (Peter Krempa)
- qemu: Fix call in qemuDomainSetNumaParamsLive for virCgroupNewIOThread (John Ferlan)
- qemu: Fix iothreads issue (John Ferlan)
- domain_conf: Add iothreadpin to cputune (John Ferlan)
- network: check for invalid forward delay time (Erik Skultety)
- qemu: Fix build breaker on printf directive (John Ferlan)
- daemon: Resolve Coverity FORWARD_NULL (John Ferlan)
- qemu: Resolve Coverity BAD_SIZEOF (John Ferlan)
- Resolve Coverity CHECKED_RETURN (John Ferlan)
- virsh: Resolve Coverity DEADCODE (John Ferlan)
- domain_conf: Resolve Coverity COPY_PASTE_ERROR (John Ferlan)
- virtime: Resolve Coverity DEADCODE (John Ferlan)
- remote_driver: Resolve Coverity RESOURCE_LEAK (John Ferlan)
- node_device_udev: Try harder to get human readable vendor:product (Lubomir Rintel)
- util: fix potential leak in error codepath (Martin Kletzander)
- network: try to eliminate default network conflict during package install (Laine Stump)
- libxl: Resolve Coverity CHECKED_RETURN (John Ferlan)
- qemu: Resolve Coverity FORWARD_NULL (John Ferlan)
- virfile: Resolve Coverity RESOURCE_LEAK (John Ferlan)
- virutil: Resolve Coverity RESOURCE_LEAK (John Ferlan)
- daemon: Resolve Coverity RESOURCE_LEAK (John Ferlan)
- virsh: Resolve Coverity NEGATIVE_RETURNS (John Ferlan)
- libvirt.spec: Fix permission even for libvirt-driver-qemu (Michal Privoznik)
- libxl: fix mapping of libvirt and libxl lifecycle actions (Jim Fehlig)
- nvram: Fix permissions (Michal Privoznik)
- libxl: Resolve Coverity NULL_RETURNS (John Ferlan)
- qemu: Resolve Coverity NEGATIVE_RETURNS (John Ferlan)
- qemu: Resolve Coverity NEGATIVE_RETURNS (John Ferlan)
- xen: Resolve Coverity NEGATIVE_RETURNS (John Ferlan)
- nodeinfo: Resolve Coverity NEGATIVE_RETURNS (John Ferlan)
- qemu: Resolve Coverity NEGATIVE_RETURNS (John Ferlan)
- network_conf: Resolve Coverity FORWARD_NULL (John Ferlan)
- qemu: Resolve Coverity FORWARD_NULL (John Ferlan)
- virstring: Resolve Coverity FORWARD_NULL (John Ferlan)
- network: Resolve Coverity FORWARD_NULL (John Ferlan)
- qemu: Resolve Coverity FORWARD_NULL (John Ferlan)
- lxc: Resolve Coverity FORWARD_NULL (John Ferlan)
- qemu: Resolve Coverity FORWARD_NULL (John Ferlan)
- virsh: Resolve Coverity DEADCODE (John Ferlan)
- tests: Resolve Coverity DEADCODE (John Ferlan)
- qemu: Resolve Coverity DEADCODE (John Ferlan)
- virsh: Resolve Coverity DEADCODE (John Ferlan)
- virfile: Resolve Coverity DEADCODE (John Ferlan)
- virsh: Resolve Coverity DEADCODE (John Ferlan)
- storage: Resolve Coverity OVERFLOW_BEFORE_WIDEN (John Ferlan)
- qemu: Resolve Coverity REVERSE_INULL (John Ferlan)
- vbox: Resolve Coverity UNUSED_VALUE (John Ferlan)
- storage: Resolve Coverity UNUSED_VALUE (John Ferlan)
- qemu_driver: Resolve Coverity COPY_PASTE_ERROR (John Ferlan)
- selinux: Properly check TAP FD label (Michal Privoznik)
- qemu: Silence coverity on optional migration stats (Jiri Denemark)
- qemu: panic device: check for invalid address type (Erik Skultety)
- qemu: Propagate QEMU errors during incoming migrations (Jiri Denemark)
- selinux: Avoid label reservations for type = none (Shivaprasad G Bhat)
- storage_conf: Fix libvirtd crash when defining scsi storage pool (Pradipta Kr. Banerjee)
- Don't include non-migratable features in host-model (Ján Tomko)
- conf: Fix even implicit labels (Michal Privoznik)
- apparmor: allow reading cap_last_cap (Felix Geyer)
- security: fix DH key generation when FIPS mode is on (Giuseppe Scrivano)
- lxc_container: Resolve Coverity RESOURCE_LEAK (Wang Rui)
- vircgroup: Resolve Coverity RESOURCE_LEAK (Wang Rui)
- qemu_process: Resolve Coverity RESOURCE_LEAK (Wang Rui)
- remote: Resolve Coverity RESOURCE_LEAK (Wang Rui)
- test_conf: Resolve Coverity RESOURCE_LEAK (Wang Rui)
- tests: Resolve Coverity RESOURCE_LEAK in commandhelper (Wang Rui)
- sanlock: Avoid freeing uninitialized value (Jiri Denemark)
- qemu: ensure sane umask for qemu process (Chunyan Liu)
- spec: Fix preun script for daemon (Jiri Denemark)
- remote: Fix memory leak on error path when deserializing bulk stats (Peter Krempa)
- Free ifname in testDomainGenerateIfnames (Ján Tomko)
Portability:
- qemu: monitor: Avoid shadowing variable "devname" on FreeBSD (Peter Krempa)
- lxc_monitor_protocol: Redefine xdr_uint64_t if needed (Michal Privoznik)
- Fix build without polkit (Pavel Hrdina)
- Fix MinGW build (Pavel Hrdina)
- Fix build in qemu_command (Roman Bogorodskiy)
- Fix build in qemu_capabilities (Roman Bogorodskiy)
- bhyve: tests: fix build (Roman Bogorodskiy)
- virprocess: Extend list of platforms for setns wrapper (Michal Privoznik)
- vircgroup: Fix broken builds without cgroups (John Ferlan)
- util/virprocess.c: fix MinGW build (Pavel Hrdina)
- blockjob: avoid 32-bit compilation warning (Eric Blake)
Improvements:
- Fix typo s/EMULATORIN/EMULATORPIN/ (Daniel P. Berrange)
- Rename tunable event constants (Daniel P. Berrange)
- qemu: Always re-detect backing chain (Peter Krempa)
- event_example: cleanup example code for tunable event (Pavel Hrdina)
- parallels: login to parallels SDK (Dmitry Guryanov)
- parallels: build with parallels SDK (Dmitry Guryanov)
- virnetserver: Raise log level of max_clients related messages (Michal Privoznik)
- blkdeviotune: trigger tunable event for blkdeviotune updates (Pavel Hrdina)
- tunable_event: extend debug message and tweak limit for remote message (Pavel Hrdina)
- virsh: Expose virNodeAllocPages (Michal Privoznik)
- nodeinfo: Implement nodeAllocPages (Michal Privoznik)
- virnuma: Introduce virNumaSetPagePoolSize (Michal Privoznik)
- nodeGetFreePages: Push forgotten change (Michal Privoznik)
- Convert polkit code to use DBus API instead of CLI helper (Daniel P. Berrange)
- Support passing dict by reference for dbus messages (Daniel P. Berrange)
- Convert remote daemon & acl code to use polkit API (Daniel P. Berrange)
- Convert callers to use typesafe APIs for getting identity attrs (Daniel P. Berrange)
- Convert callers to use typesafe APIs for setting identity attrs (Daniel P. Berrange)
- Add typesafe APIs for virIdentity attributes (Daniel P. Berrange)
- Add common API for doing polkit authentication (Daniel P. Berrange)
- qemu: wire up virtio-net segment offloading options (Ján Tomko)
- conf: add options for disabling segment offloading (Ján Tomko)
- storage: Improve error message when traversing backing chains (Peter Krempa)
- qemu: Report better errors from broken backing chains (Peter Krempa)
- qemu: Sanitize argument names and empty disk check in qemuDomainDetermineDiskChain (Peter Krempa)
- util: storage: Allow metadata crawler to report useful errors (Peter Krempa)
- cputune_event: queue the event for cputune updates (Pavel Hrdina)
- add an example how to use tunable event (Pavel Hrdina)
- conf: sanitize tap and vhost paths (Martin Kletzander)
- qemuBuildNumaArgStr: Discard def->cpu check (Michal Privoznik)
- nodeinfo: Prefer MIN in nodeGetFreePages (Michal Privoznik)
- domain_conf: separate structures from virDomainDef (Pavel Hrdina)
- Fix typo of virNodeGetFreePages comment (Jincheng Miao)
- qemu: Memory pre-pinning support for RDMA migration (Michael R. Hines)
- qemu: RDMA migration support (Michael R. Hines)
- qemu: Add RDMA migration capabilities (Jiri Denemark)
- qemu: Prepare support for arbitrary migration protocol (Jiri Denemark)
- qemu: Fix old tcp:host URIs more cleanly (Jiri Denemark)
- qemu: Expose additional migration statistics (Michael R. Hines)
- cpu: fix wrong single quote mark (Chen Fan)
- cpu: remove repeated word in error message (Daniel P. Berrange)
- qemu: hook: Provide hook when restoring a domain save image (Peter Krempa)
- schema: properly set tap and vhost backend attributes optional (Jianwei Hu)
- qemu: save image: Split out checks done only when editing the save img (Peter Krempa)
- qemu: save image: Split out new definition check/update (Peter Krempa)
- qemu: save image: Add possibility to return XML stored in the image (Peter Krempa)
- qemu: save image: Split out user provided XML checker (Peter Krempa)
- libxl: Drop driver lock in libxlDomainDefineXML (Jim Fehlig)
- qemu: Process the hostdev "rawio" setting (John Ferlan)
- hostdev: Add "rawio" attribute to _virDomainHostdevSubsysSCSI (John Ferlan)
- domain_conf: Change virDomainDiskDef 'rawio' to use virTristateBool (John Ferlan)
- storage: zfs: implement pool build and delete (Roman Bogorodskiy)
- qemu: Improve check for local storage (Peter Krempa)
- maint: clean up _virDomainMemoryStat (Wang Yufei)
- maint: clean up _virDomainBlockStats (Wang Yufei)
- maint: clean up _virDomainInterfaceStats (Wang Yufei)
- virsh: add options to query bulk stats group (Francesco Romani)
- qemu: bulk stats: implement block group (Francesco Romani)
- qemu: bulk stats: implement interface group (Francesco Romani)
- qemu: bulk stats: implement VCPU group (Francesco Romani)
- qemu: bulk stats: implement balloon group (Francesco Romani)
- qemu: bulk stats: implement CPU stats group (Francesco Romani)
- qemu: bulk stats: extend internal collection API (Francesco Romani)
- rpc: make daemon spawning a bit more intelligent (Martin Kletzander)
- domaincaps: Expose UEFI binary path, if it exists (Michal Privoznik)
- qemu_capabilities: Change virQEMUCapsFillDomainCaps signature (Michal Privoznik)
- qemu: add support for shared memory mapping (Martin Kletzander)
- docs, conf, schema: add support for shared memory mapping (Martin Kletzander)
- schemas: finish virTristate{Bool,Switch} transition (Martin Kletzander)
- qemu: Add support for multiple versions of 'pseries' machine type (Pradipta Kr. Banerjee)
- domaincaps: Expose UEFI capability (Michal Privoznik)
- Wire up the interface backend options (Ján Tomko)
- conf: add backend element to interfaces (Ján Tomko)
- conf: remove redundant local variable (Ján Tomko)
- conf: split out virtio net driver formatting (Ján Tomko)
- qemu: Need to check for capability before query (John Ferlan)
- cputune: allow interleaved xml (Eric Blake)
- network: detect conflicting route even if it is the final entry (Laine Stump)
- qemu: Allow pinning specific IOThreads to a CPU (John Ferlan)
- qemu_cgroup: Introduce cgroup functions for IOThreads (John Ferlan)
- qemu_domain: Add niothreadpids and iothreadpids (John Ferlan)
- vircgroup: Introduce virCgroupNewIOThread (John Ferlan)
- qemu: Issue query-iothreads and to get list of active IOThreads (John Ferlan)
- virsh: Add iothread to 'attach-disk' (John Ferlan)
- util: get rid of unnecessary umask() call (Martin Kletzander)
- remove redundant pidfile path constructions (Martin Kletzander)
- rpc: reformat the flow to make a bit more sense (Martin Kletzander)
- blockjob: allow finer bandwidth tuning for set speed (Eric Blake)
- blockcopy: add qemu implementation of new tunables (Eric Blake)
- blockcopy: add qemu implementation of new API (Eric Blake)
- blockcopy: tweak how rebase calls into copy (Eric Blake)
- virDomainUndefineFlags: Allow NVRAM unlinking (Michal Privoznik)
- virsh: Move --completed from resume to domjobinfo (Jiri Denemark)
- conf: snapshot: Don't default-snapshot empty drives (Peter Krempa)
- util: Add function to check if a virStorageSource is "empty" (Peter Krempa)
- tests: Add more test suite mock helpers (Daniel P. Berrange)
- util: Allow port allocator to skip bind() check (Daniel P. Berrange)
- qemu: remove leftover virResetLastError (Ján Tomko)
- util: storage: Convert disk locality check to switch statement (Peter Krempa)
- virprocess: Introduce our own setns() wrapper (Michal Privoznik)
- qemu: dump: Resume CPUs only when the VM is still alive (Peter Krempa)
- util: process: Don't report OOM errors in helper (Peter Krempa)
- qemu: Automatically create NVRAM store (Michal Privoznik)
- qemu: Implement extended loader and nvram (Michal Privoznik)
- conf: Extend <loader/> and introduce <nvram/> (Michal Privoznik)
- qemu: Transfer recomputed stats back to source (Jiri Denemark)
- qemu: Recompute downtime and total time when migration completes (Jiri Denemark)
- qemu: Transfer migration statistics to destination (Jiri Denemark)
- virsh: Add support for completed job stats (Jiri Denemark)
- qemu: Avoid incrementing jobs_queued if virTimeMillisNow fails (Jiri Denemark)
- Refactor job statistics (Jiri Denemark)
- virsh: additional scaled output units (Eric Blake)
- util: let virSetSockReuseAddr report unified error message (Martin Kletzander)
- blockcopy: add a way to parse disk source (Eric Blake)
- qemu: snapshot: Simplify error paths (Peter Krempa)
- qemu: snapshot: Fix snapshot function header formatting and spacing (Peter Krempa)
- qemu: snapshot: Acquire job earlier on snapshot revert/delete (Jincheng Miao)
- qemu: snapshot: Fix job handling when creating snapshots (Peter Krempa)
- qemu: Rename DEFAULT_JOB_MASK to QEMU_DEFAULT_JOB_MASK (Peter Krempa)
- blockcopy: remote implementation for new API (Eric Blake)
- blockcopy: expose new API in virsh (Eric Blake)
- maint: update to latest gnulib (Eric Blake)
- blockcopy: split out virsh implementation (Eric Blake)
- blockcopy: allow block device destination (Eric Blake)
- blockjob: add new --bytes flag to virsh blockjob (Eric Blake)
- blockjob: add new --raw flag to virsh blockjob (Eric Blake)
- blockjob: split up virsh blockjob info (Eric Blake)
- blockjob: allow finer bandwidth tuning for query (Eric Blake)
- blockjob: add new monitor json conversions (Eric Blake)
- blockjob: hoist bandwidth scaling out of monitor code (Eric Blake)
- blockjob: split out block info monitor handling (Eric Blake)
- tests: Add test cases for previous commit (Michal Privoznik)
- blockjob: split out block info driver handling (Eric Blake)
- blockjob: shuffle block rebase code (Eric Blake)
- maint: tighten curly brace syntax checking (Eric Blake)
- maint: use hanging curly braces (Eric Blake)
- maint: enforce previous if-else {} cleanups (Eric Blake)
- maint: use consistent if-else braces in remaining spots (Eric Blake)
- maint: use consistent if-else braces in lxc, vbox, phyp (Eric Blake)
- maint: use consistent if-else braces in xen and friends (Eric Blake)
- maint: use consistent if-else braces in qemu (Eric Blake)
- maint: use consistent if-else braces in conf and friends (Eric Blake)
- LXC: add HOME environment variable (Chen Hanxiao)
- tests: force FIPS testing mode with new enough GNU TLS versions (Giuseppe Scrivano)
- command: test umask support (Eric Blake)
- util: don't shadow global umask declaration (Martin Kletzander)
- util: Introduce flags field for macvtap creation (Matthew Rosato)
Cleanups:
- nodeinfo: fix version of nodeAllocPages (Tomoki Sekiyama)
- audit: remove redundant NULL assignment (Ján Tomko)
- qemu: Drop unused formatting of uuid (Peter Krempa)
- qemu_cgroup: Adjust spacing around incrementor (John Ferlan)
- qemu: dump: Fix formatting of function headers and code inline (Peter Krempa)
- virsh: domain: Clean up handling of "dom" in "save" command (Peter Krempa)
Thanks everybody who helped with this release, with ideas, reports,
patches, documentation or localizations !
Daniel
--
Daniel Veillard | Open Source and Standards, Red Hat
veillard(a)redhat.com | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
http://veillard.com/ | virtualization library http://libvirt.org/
10 years, 1 month
[libvirt] increase number of libvirt threads by starting tansient guest doamin - is it a bug?
by ustermann78@web.de
hello,
if i start a transient guest doamin via "virsh create abcd.xml" i see an additional libvirt thread and also some open files:
pstree -h `pgrep libvirtd`
libvirtd───11*[{libvirtd}]
libvirtd 3016 root 21w REG 253,0 6044 1052094 /var/log/libvirt/libxl/abcd.log
libvirtd 3016 root 22r FIFO 0,8 0t0 126124 pipe
libvirtd 3016 root 23w FIFO 0,8 0t0 126124 pipe
libvirtd 3016 root 24u REG 0,37 0 4 /proc/xen/privcmd
libvirtd 3016 root 25u unix 0xffff8807d2c3ad80 0t0 126125 socket
libvirtd 3016 root 26r FIFO 0,8 0t0 126127 pipe
libvirtd 3016 root 27w FIFO 0,8 0t0 126127 pipe
libvirtd 3016 root 28r FIFO 0,8 0t0 124783 pipe
libvirtd 3016 root 29w FIFO 0,8 0t0 124783 pipe
libvirtd 3016 root 30r FIFO 0,8 0t0 127140 pipe
libvirtd 3016 root 31w FIFO 0,8 0t0 127140 pipe
if i destroy these vm via "virsh destroy abcd", i see that the additional thread still exists and also the list of openfiles is the same.
if i start the transient guest domain again, i observe an increase in the number of libvirt threads ans also in the list of openfiles:
[root@localhost libxl]# pstree -h `pgrep libvirtd`
libvirtd───12*[{libvirtd}]
libvirtd 3016 root 21w REG 253,0 13783 1052094 /var/log/libvirt/libxl/abcd.log
libvirtd 3016 root 22r FIFO 0,8 0t0 126124 pipe
libvirtd 3016 root 23w FIFO 0,8 0t0 126124 pipe
libvirtd 3016 root 24u REG 0,37 0 4 /proc/xen/privcmd
libvirtd 3016 root 25u unix 0xffff8807d2c3ad80 0t0 126125 socket
libvirtd 3016 root 26r FIFO 0,8 0t0 126127 pipe
libvirtd 3016 root 27w FIFO 0,8 0t0 126127 pipe
libvirtd 3016 root 28r FIFO 0,8 0t0 124783 pipe
libvirtd 3016 root 29w FIFO 0,8 0t0 124783 pipe
libvirtd 3016 root 30r FIFO 0,8 0t0 127140 pipe
libvirtd 3016 root 31w FIFO 0,8 0t0 127140 pipe
libvirtd 3016 root 32w REG 253,0 13783 1052094 /var/log/libvirt/libxl/abcd.log
libvirtd 3016 root 33r FIFO 0,8 0t0 129039 pipe
libvirtd 3016 root 34w FIFO 0,8 0t0 129039 pipe
libvirtd 3016 root 35u REG 0,37 0 4 /proc/xen/privcmd
libvirtd 3016 root 36u unix 0xffff8807d398bb80 0t0 129040 socket
libvirtd 3016 root 37r FIFO 0,8 0t0 129042 pipe
libvirtd 3016 root 38w FIFO 0,8 0t0 129042 pipe
libvirtd 3016 root 39r FIFO 0,8 0t0 129043 pipe
libvirtd 3016 root 40w FIFO 0,8 0t0 129043 pipe
libvirtd 3016 root 41r FIFO 0,8 0t0 129044 pipe
libvirtd 3016 root 42w FIFO 0,8 0t0 129044 pipe
if i destroy the doamin again and define them via "virsh define abcd.xml" and start them then via "virsh start abcd", the number of libvirtd threads don´t increase again and also the number of open files is the same.
My question: is it normal that for transient guest domains the created libvirtd thread sill exists and also the open files after i destroy the doamin? or is it bug?
thanks
max
10 years, 1 month