[libvirt] [PATCH] New features implemented in hyperv libvirt driver

Yves Vinter yves.vinter at bull.net
Thu Sep 25 12:38:30 UTC 2014


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 at 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(&params[0], VIR_DOMAIN_SCHEDULER_LIMIT,
+                                VIR_TYPED_PARAM_LLONG, processorSettingData->data->Limit) < 0)
+        goto cleanup;
+    saved_nparams++;
+    
+    if (*nparams > saved_nparams) {
+        if (virTypedParameterAssign(&params[1],VIR_DOMAIN_SCHEDULER_RESERVATION,
+                                    VIR_TYPED_PARAM_LLONG, processorSettingData->data->Reservation) < 0)
+            goto cleanup;
+        saved_nparams++;
+    }
+    
+    if (*nparams > saved_nparams) {
+        if (virTypedParameterAssign(&params[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);




More information about the libvir-list mailing list