[libvirt] [PATCH 01/21] Added missing virBufferFreeAndReset on the query buffer to free some memory

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 13 +++++++++++++ src/hyperv/hyperv_wmi.c | 15 +++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index aed9307..372ff39 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -201,6 +201,7 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags VIR_FREE(username); VIR_FREE(password); hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query); return result; } @@ -254,6 +255,7 @@ hypervConnectGetHostname(virConnectPtr conn) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query); return hostname; } @@ -352,6 +354,7 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); hypervFreeObject(priv, (hypervObject *)processorList); + virBufferFreeAndReset(&query); return result; } @@ -396,6 +399,7 @@ hypervConnectListDomains(virConnectPtr conn, int *ids, int maxids) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystemList); + virBufferFreeAndReset(&query); return success ? count : -1; } @@ -432,6 +436,7 @@ hypervConnectNumOfDomains(virConnectPtr conn) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystemList); + virBufferFreeAndReset(&query); return success ? count : -1; } @@ -464,6 +469,7 @@ hypervDomainLookupByID(virConnectPtr conn, int id) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query); return domain; } @@ -500,6 +506,7 @@ hypervDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query); return domain; } @@ -533,6 +540,7 @@ hypervDomainLookupByName(virConnectPtr conn, const char *name) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query); return domain; } @@ -748,6 +756,7 @@ hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); hypervFreeObject(priv, (hypervObject *)processorSettingData); hypervFreeObject(priv, (hypervObject *)memorySettingData); + virBufferFreeAndReset(&query); return result; } @@ -915,6 +924,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 +981,7 @@ hypervConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxn } hypervFreeObject(priv, (hypervObject *)computerSystemList); + virBufferFreeAndReset(&query); return count; } @@ -1007,6 +1018,7 @@ hypervConnectNumOfDefinedDomains(virConnectPtr conn) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystemList); + virBufferFreeAndReset(&query); return success ? count : -1; } @@ -1346,6 +1358,7 @@ hypervConnectListAllDomains(virConnectPtr conn, } hypervFreeObject(priv, (hypervObject *)computerSystemList); + virBufferFreeAndReset(&query); return ret; } diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index acb705c..d93abd9 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -526,6 +526,7 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain, VIR_FREE(returnValue); VIR_FREE(instanceID); hypervFreeObject(priv, (hypervObject *)concreteJob); + virBufferFreeAndReset(&query); return result; } @@ -646,13 +647,14 @@ int hypervMsvmComputerSystemFromDomain(virDomainPtr domain, Msvm_ComputerSystem **computerSystem) { + int result = -1; hypervPrivate *priv = domain->conn->privateData; char uuid_string[VIR_UUID_STRING_BUFLEN]; virBuffer query = VIR_BUFFER_INITIALIZER; if (computerSystem == NULL || *computerSystem != NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); - return -1; + goto cleanup; } virUUIDFormat(domain->uuid, uuid_string); @@ -663,16 +665,21 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain, virBufferAsprintf(&query, "and Name = \"%s\"", uuid_string); if (hypervGetMsvmComputerSystemList(priv, &query, computerSystem) < 0) { - return -1; + goto cleanup; } if (*computerSystem == NULL) { virReportError(VIR_ERR_NO_DOMAIN, _("No domain with UUID %s"), uuid_string); - return -1; + goto cleanup; } - return 0; + result = 0; + + cleanup: + virBufferFreeAndReset(&query); + + return result; } -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 55 +++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.input | 37 +++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.py | 4 +-- 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 372ff39..f2017c3 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1232,6 +1232,7 @@ hypervDomainManagedSaveRemove(virDomainPtr domain, unsigned int flags) } + #define MATCH(FLAG) (flags & (FLAG)) static int hypervConnectListAllDomains(virConnectPtr conn, @@ -1366,6 +1367,59 @@ hypervConnectListAllDomains(virConnectPtr conn, +static int +hypervConnectGetVersion(virConnectPtr conn, unsigned long *version) +{ + int result = -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; + } + + result = 0; + + cleanup: + hypervFreeObject(priv, (hypervObject *)datafile); + virBufferFreeAndReset(&query); + + return result; +} + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, @@ -1402,6 +1456,7 @@ static virDriver hypervDriver = { .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */ .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */ .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */ + .connectGetVersion = hypervConnectGetVersion, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 97f9dff..6b969df 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -296,3 +296,40 @@ 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 diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index f767d54..1011719 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" -- 1.9.1

On 10/08/2014 06:33 AM, Yves Vinter wrote:
From: yvinter <yves.vinter@bull.net>
Looks like you had identity problems throughout the series. I don't mind touching up first-time contributions, but it would be nice to get it right in the future so I don't have to spend time on it.
--- src/hyperv/hyperv_driver.c | 55 +++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.input | 37 +++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.py | 4 +-- 3 files changed, 94 insertions(+), 2 deletions(-)
diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 372ff39..f2017c3 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1232,6 +1232,7 @@ hypervDomainManagedSaveRemove(virDomainPtr domain, unsigned int flags) }
+ #define MATCH(FLAG) (flags & (FLAG))
Why the added blank line?
static int hypervConnectListAllDomains(virConnectPtr conn, @@ -1366,6 +1367,59 @@ hypervConnectListAllDomains(virConnectPtr conn,
+static int
Wow, that's a lot of blank lines already there.
+hypervConnectGetVersion(virConnectPtr conn, unsigned long *version) +{ + int result = -1; + hypervPrivate *priv = conn->privateData; + CIM_DataFile *datafile = NULL;
Why the double space?
+ virBuffer query = VIR_BUFFER_INITIALIZER; + char *p; + + virBufferAddLit(&query, " Select * from CIM_DataFile where Name='c:\\\\windows\\\\system32\\\\vmms.exe' ");
Is the leading and trailing space really necessary in the string literal?
+ if (hypervGetCIMDataFileList(priv, &query, &datafile) < 0) { + goto cleanup; + }
Libvirt style says {} are not necessary for one-line bodies (qemu style would require it, but we're a bit more lenient).
+ + /* Check the result of convertion */ + if (datafile == NULL) {
It's sufficient to write 'if (datafile)' (comparison to NULL is just extra verbosity); but as that appears to be the prevailing style already in this file, I'm not going to worry about shortening it.
+ 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,'.');
This failed 'make syntax-check' due to a missing space: GEN bracket-spacing-check src/hyperv/hyperv_driver.c:1381: p = strrchr(datafile->data->Version,'.'); maint.mk: incorrect whitespace, see HACKING for rules make: *** [bracket-spacing-check] Error 1
+ 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; + } + + result = 0; + + cleanup: + hypervFreeObject(priv, (hypervObject *)datafile); + virBufferFreeAndReset(&query);
This line is not necessary if you ACK my v2 of 1/21.
+ + return result; +} + +
static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, @@ -1402,6 +1456,7 @@ static virDriver hypervDriver = { .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */ .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */ .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */ + .connectGetVersion = hypervConnectGetVersion, /* 1.2.10 */ };
I got through here in my review for now; mostly looks good other than style. When I finish the rest of the patch, I may end up just fixing it myself and pushing. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 10/08/2014 06:33 AM, Yves Vinter wrote:
From: yvinter <yves.vinter@bull.net>
--- src/hyperv/hyperv_driver.c | 55 +++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.input | 37 +++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.py | 4 +-- 3 files changed, 94 insertions(+), 2 deletions(-)
Another round of reviews; the .input and .py file look okay to me, but I spotted more issues in the .c that I didn't point out the first time around.
+static int +hypervConnectGetVersion(virConnectPtr conn, unsigned long *version) +{ + int result = -1; + hypervPrivate *priv = conn->privateData; + CIM_DataFile *datafile = NULL; + virBuffer query = VIR_BUFFER_INITIALIZER; + char *p; +
Trailing whitespace. Another thing 'make syntax-check' will flag.
+ 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 */
s/convertion/conversion/
+ if (datafile == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not lookup %s for domain %s"), + "Msvm_VirtualSystemSettingData", + datafile->data->Version);
Is this error message correct? That is, is datafile->data->Version the name of the domain you are referring to in the message?
+ 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';
This is modifying datafile->data in-place. I hope that's safe (if not, you'd have to strdup a copy that you can safely manipulate locally).
+ + /* Parse Version String to Long */ + if (virParseVersionString(datafile->data->Version,
The comment is a bit redundant with the name of the function you are calling. I'd just omit the comment. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

(1) syntax-check: I run make syntax-check and found some other "white space" or "TAB" issues (coming with subsequent patches) (2) Is this error message correct? That is, is datafile->data->Version the name of the domain you are referring to in the message? More than that: this part of code is completely wrong! datafile->data->Version shouldn't be evaluated if datafile == NULL!!!
+ if (datafile == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not lookup %s for domain %s"), + "Msvm_VirtualSystemSettingData", + datafile->data->Version
Right code is: If (datafile == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unable to get the hypervisor version")); } [ Removed the comment: /* Check the result of conversion */] (3) This is modifying datafile->data in-place. I hope that's safe (if not, you'd have to strdup a copy that you can safely manipulate locally). It is safe; datafile is a temporary object that is released at the end of hypervConnectGetVersion call. (4) The comment is a bit redundant with the name of the function you are calling. I'd just omit the comment. No problem... -----Message d'origine----- De : Eric Blake [mailto:eblake@redhat.com] Envoyé : jeudi 9 octobre 2014 00:15 À : Yves Vinter; libvir-list@redhat.com Objet : Re: [libvirt] [PATCH 02/21] Added implementation for virConnectGetVersion (required CIM_DataFile class) On 10/08/2014 06:33 AM, Yves Vinter wrote:
From: yvinter <yves.vinter@bull.net>
--- src/hyperv/hyperv_driver.c | 55 +++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.input | 37 +++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.py | 4 +-- 3 files changed, 94 insertions(+), 2 deletions(-)
Another round of reviews; the .input and .py file look okay to me, but I spotted more issues in the .c that I didn't point out the first time around.
+static int +hypervConnectGetVersion(virConnectPtr conn, unsigned long *version) { + int result = -1; + hypervPrivate *priv = conn->privateData; + CIM_DataFile *datafile = NULL; + virBuffer query = VIR_BUFFER_INITIALIZER; + char *p; +
Trailing whitespace. Another thing 'make syntax-check' will flag.
+ 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 */
s/convertion/conversion/
+ if (datafile == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not lookup %s for domain %s"), + "Msvm_VirtualSystemSettingData", + datafile->data->Version);
Is this error message correct? That is, is datafile->data->Version the name of the domain you are referring to in the message?
+ 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';
This is modifying datafile->data in-place. I hope that's safe (if not, you'd have to strdup a copy that you can safely manipulate locally).
+ + /* Parse Version String to Long */ + if (virParseVersionString(datafile->data->Version,
The comment is a bit redundant with the name of the function you are calling. I'd just omit the comment. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

From: Yves Vinter <yves.vinter@bull.net> This patch implements the virConnectGetVersion function for the hyperv libvirt driver. The value returned by this function must be formatted as "<major>.<minor>.<release>" with a maximum of 3 digits per item. Therefore, value of Microsoft hypervisor's version has been truncated as shown below: Hyper-V 2008 R2 SP1 (6.1.7601.17514): returned version is 6.1.760 Hyper-V 2012 (6.2.9200.16384): returned version is 6.2.920 A new WMI class has been added (CIM_DataFile). Signed-off-by: Yves Vinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 46 +++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.input | 37 ++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.py | 4 +-- 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 5ffcb85..fba7f38 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1352,6 +1352,51 @@ hypervConnectListAllDomains(virConnectPtr conn, #undef MATCH +static int +hypervConnectGetVersion(virConnectPtr conn, unsigned long *version) +{ + int result = -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; + + if (datafile == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get hypervisor 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'; + + 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; + } + + result = 0; + + cleanup: + hypervFreeObject(priv, (hypervObject *)datafile); + + return result; +} static virHypervisorDriver hypervDriver = { @@ -1389,6 +1434,7 @@ static virHypervisorDriver hypervDriver = { .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */ .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */ .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */ + .connectGetVersion = hypervConnectGetVersion, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 97f9dff..6b969df 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -296,3 +296,40 @@ 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 diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index f767d54..1011719 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" -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 112 ++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_private.h | 2 + src/hyperv/hyperv_wmi_generator.input | 12 ++++ 3 files changed, 126 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index f2017c3..dd56fb0 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -58,12 +58,19 @@ hypervFreePrivate(hypervPrivate **priv) wsmc_release((*priv)->client); } + if ((*priv)->caps != NULL) + virObjectUnref((*priv)->caps); + hypervFreeParsedUri(&(*priv)->parsedUri); VIR_FREE(*priv); } +/* Forward declaration of hypervCapsInit */ +static virCapsPtr hypervCapsInit(hypervPrivate *priv); + + static virDrvOpenStatus hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags) { @@ -192,6 +199,12 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags goto cleanup; } + /* Setup capabilities */ + priv->caps = hypervCapsInit(priv); + if (priv->caps == NULL) { + goto cleanup; + } + conn->privateData = priv; priv = NULL; result = VIR_DRV_OPEN_SUCCESS; @@ -1420,6 +1433,104 @@ hypervConnectGetVersion(virConnectPtr conn, unsigned long *version) } +/* Retrieves host system UUID */ +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 char* +hypervConnectGetCapabilities(virConnectPtr conn) +{ + hypervPrivate *priv = conn->privateData; + char *xml = virCapabilitiesFormatXML(priv->caps); + + if (xml == NULL) { + virReportOOMError(); + return NULL; + } + + return xml; +} + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, @@ -1457,6 +1568,7 @@ static virDriver hypervDriver = { .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */ .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */ .connectGetVersion = hypervConnectGetVersion, /* 1.2.10 */ + .connectGetCapabilities = hypervConnectGetCapabilities, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_private.h b/src/hyperv/hyperv_private.h index 574bb5f..d9aa0bd 100644 --- a/src/hyperv/hyperv_private.h +++ b/src/hyperv/hyperv_private.h @@ -26,6 +26,7 @@ # include "internal.h" # include "virerror.h" # include "hyperv_util.h" +# include "capabilities.h" # include "openwsman.h" typedef struct _hypervPrivate hypervPrivate; @@ -33,6 +34,7 @@ typedef struct _hypervPrivate hypervPrivate; struct _hypervPrivate { hypervParsedUri *parsedUri; WsManClient *client; + virCapsPtr caps; }; #endif /* __HYPERV_PRIVATE_H__ */ diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 6b969df..f1e0c81 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -333,3 +333,15 @@ class CIM_DataFile 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 -- 1.9.1

On 10/08/2014 06:33 AM, Yves Vinter wrote:
From: yvinter <yves.vinter@bull.net>
Long subject line. I'd suggest: hyperv: add implementation for virConnectGetCapabilities Done by adding the Win32_ComputerSystemProduct class.
--- src/hyperv/hyperv_driver.c | 112 ++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_private.h | 2 + src/hyperv/hyperv_wmi_generator.input | 12 ++++ 3 files changed, 126 insertions(+)
diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index f2017c3..dd56fb0 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -58,12 +58,19 @@ hypervFreePrivate(hypervPrivate **priv) wsmc_release((*priv)->client); }
+ if ((*priv)->caps != NULL) + virObjectUnref((*priv)->caps);
Dead 'if'; virObjectUnref(NULL) is safe.
+/* Forward declaration of hypervCapsInit */ +static virCapsPtr hypervCapsInit(hypervPrivate *priv);
Why do you need a forward declaration of a static function? If it's not recursive, just put the whole function body here (that may mean moving more than one function, to keep things topologically sorted; if you need to do code motion of existing functions, do it in a separate patch from where you add new code, to ease review).
+/* Retrieves host system UUID */ +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,
Is VIR_ERR_NO_DOMAIN really the right error to be using here?
+ _("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);
This virBufferFreeAndReset is not needed if you take my alternate patch for 1/21.
+ + return result; +} + + + +static virCapsPtr hypervCapsInit(hypervPrivate *priv)
Libvirt style is two blank lines between functions, and function name starting in column 1 of a line separate from the return type: 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 }); */
Might be nice to explain why this is commented out.
+} + + + +static char*
Only need two blank lines.
+hypervConnectGetCapabilities(virConnectPtr conn) +{ + hypervPrivate *priv = conn->privateData; + char *xml = virCapabilitiesFormatXML(priv->caps);
virCapabilitiesFormatXML can only return NULL on error, and it already outputs a decent error message; also, error is not always due to OOM...
+ + if (xml == NULL) { + virReportOOMError();
...so this virReportOOMError() is bogus, because it overwrites the decent message.
+ return NULL; + }
Once you realize that, you can simplify this function to: static char* hypervConnectGetCapabilities(virConnectPtr conn) { hypervPrivate *priv = conn->privateData; return virCapabilitiesFormatXML(priv->caps); } -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

(1) Long subject line. I'd suggest hyperv: add implementation for virConnectGetCapabilities Done by adding the Win32_ComputerSystemProduct class. "Done" is not the appropriate word; adding Win32_ComputerSystemProduct class was just a requirement to make the implementation. (2) Dead 'if'; virObjectUnref(NULL) is safe Stands also for patch #20 with xmlopt. (3) Why do you need a forward declaration of a static function? Just because the new code was "grouped" near the end of the file. It's not a problem to move the block of functions hypervLookupHostSystemBiosUuid & hypervCapsInit just before function hypervConnectOpen and remove this forward declaration. (4) Is VIR_ERR_NO_DOMAIN really the right error to be using here? No; it's a mistake; VIR_ERR_INTERNAL_ERROR error should be used instead. (5) Libvirt style is two blank lines between functions, and function name starting in column 1 of a line separate from the return type: In the current version of the hyperv libvirt driver, functions are actually separated by three blank lines. (6) Might be nice to explain why this is commented out. /* virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x0c, 0x29 }); */ Has been commented because virCapabilitiesSetMacPrefix does not exist. Is that something that a generic function that has been removed from the libvirt? BTY. the Mac Prefix for hyperv is 00-15-0D (7) Only need two blank lines In the current version of the hyperv libvirt driver, functions are actually separated by three blank lines. All the other functions must be reviewed then... -----Message d'origine----- De : Eric Blake [mailto:eblake@redhat.com] Envoyé : jeudi 9 octobre 2014 00:34 À : Yves Vinter; libvir-list@redhat.com Objet : Re: [libvirt] [PATCH 03/21] Added basic implementation for virConnectGetCapabilities (required Win32_ComputerSystemProduct class) On 10/08/2014 06:33 AM, Yves Vinter wrote:
From: yvinter <yves.vinter@bull.net>
Long subject line. I'd suggest: hyperv: add implementation for virConnectGetCapabilities Done by adding the Win32_ComputerSystemProduct class.
--- src/hyperv/hyperv_driver.c | 112 ++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_private.h | 2 + src/hyperv/hyperv_wmi_generator.input | 12 ++++ 3 files changed, 126 insertions(+)
diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index f2017c3..dd56fb0 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -58,12 +58,19 @@ hypervFreePrivate(hypervPrivate **priv) wsmc_release((*priv)->client); }
+ if ((*priv)->caps != NULL) + virObjectUnref((*priv)->caps);
Dead 'if'; virObjectUnref(NULL) is safe.
+/* Forward declaration of hypervCapsInit */ static virCapsPtr +hypervCapsInit(hypervPrivate *priv);
Why do you need a forward declaration of a static function? If it's not recursive, just put the whole function body here (that may mean moving more than one function, to keep things topologically sorted; if you need to do code motion of existing functions, do it in a separate patch from where you add new code, to ease review).
+/* Retrieves host system UUID */ +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,
Is VIR_ERR_NO_DOMAIN really the right error to be using here?
+ _("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);
This virBufferFreeAndReset is not needed if you take my alternate patch for 1/21.
+ + return result; +} + + + +static virCapsPtr hypervCapsInit(hypervPrivate *priv)
Libvirt style is two blank lines between functions, and function name starting in column 1 of a line separate from the return type: 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 }); */
Might be nice to explain why this is commented out.
+} + + + +static char*
Only need two blank lines.
+hypervConnectGetCapabilities(virConnectPtr conn) { + hypervPrivate *priv = conn->privateData; + char *xml = virCapabilitiesFormatXML(priv->caps);
virCapabilitiesFormatXML can only return NULL on error, and it already outputs a decent error message; also, error is not always due to OOM...
+ + if (xml == NULL) { + virReportOOMError();
...so this virReportOOMError() is bogus, because it overwrites the decent message.
+ return NULL; + }
Once you realize that, you can simplify this function to: static char* hypervConnectGetCapabilities(virConnectPtr conn) { hypervPrivate *priv = conn->privateData; return virCapabilitiesFormatXML(priv->caps); } -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 184 ++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.input | 109 ++++++++++++++++++++ 2 files changed, 293 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index dd56fb0..f734c09 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1532,6 +1532,186 @@ hypervConnectGetCapabilities(virConnectPtr conn) +static int +hypervConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) +{ + int result = -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; + } + + result = processorSettingData->data->SocketCount * processorSettingData->data->ProcessorsPerSocket; + + cleanup: + hypervFreeObject(priv, (hypervObject *) processorSettingData); + virBufferFreeAndReset(&query); + + return result; +} + + + +static int +hypervDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags) +{ + int result = -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) { + result = 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; + } + + result = processorSettingData->data->VirtualQuantity; + + cleanup: + hypervFreeObject(priv, (hypervObject *)computerSystem); + hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); + hypervFreeObject(priv, (hypervObject *)processorSettingData); + virBufferFreeAndReset(&query); + + return result; +} + + + +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 +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) && (maplen > 0)) + memset(cpumaps, 0, 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 virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -1569,6 +1749,10 @@ static virDriver hypervDriver = { .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */ .connectGetVersion = hypervConnectGetVersion, /* 1.2.10 */ .connectGetCapabilities = hypervConnectGetCapabilities, /* 1.2.10 */ + .connectGetMaxVcpus = hypervConnectGetMaxVcpus, /* 1.2.10 */ + .domainGetMaxVcpus = hypervDomainGetMaxVcpus, /* 1.2.10 */ + .domainGetVcpusFlags = hypervDomainGetVcpusFlags, /* 1.2.10 */ + .domainGetVcpus = hypervDomainGetVcpus, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index f1e0c81..8fb34e4 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -345,3 +345,112 @@ class Win32_ComputerSystemProduct string Vendor string Version 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 -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 34 ++++++++++++++++++ src/hyperv/hyperv_wmi_generator.input | 68 +++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.py | 1 + 3 files changed, 103 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index f734c09..191c7dd 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1712,6 +1712,39 @@ hypervDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, +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: + hypervFreeObject(priv, (hypervObject *) operatingSystem); + virBufferFreeAndReset(&query); + + return res; +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -1753,6 +1786,7 @@ static virDriver hypervDriver = { .domainGetMaxVcpus = hypervDomainGetMaxVcpus, /* 1.2.10 */ .domainGetVcpusFlags = hypervDomainGetVcpusFlags, /* 1.2.10 */ .domainGetVcpus = hypervDomainGetVcpus, /* 1.2.10 */ + .nodeGetFreeMemory = hypervNodeGetFreeMemory, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 8fb34e4..739be87 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -454,3 +454,71 @@ class Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor uint64 VirtualMMUHypercallsPersec uint64 VirtualProcessorHypercallsPersec 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 diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index 1011719..5010470 100755 --- a/src/hyperv/hyperv_wmi_generator.py +++ b/src/hyperv/hyperv_wmi_generator.py @@ -158,6 +158,7 @@ class Property: "int16" : "INT16", "int32" : "INT32", "int64" : "INT64", + "sint16" : "INT16", "uint8" : "UINT8", "uint16" : "UINT16", "uint32" : "UINT32", -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 191c7dd..aadadb1 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1745,6 +1745,43 @@ hypervNodeGetFreeMemory(virConnectPtr conn) +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 virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -1787,6 +1824,8 @@ static virDriver hypervDriver = { .domainGetVcpusFlags = hypervDomainGetVcpusFlags, /* 1.2.10 */ .domainGetVcpus = hypervDomainGetVcpus, /* 1.2.10 */ .nodeGetFreeMemory = hypervNodeGetFreeMemory, /* 1.2.10 */ + .domainShutdownFlags = hypervDomainShutdownFlags, /* 1.2.10 */ + .domainShutdown = hypervDomainShutdown, /* 1.2.10 */ }; -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 129 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index aadadb1..4074fb0 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -41,6 +41,7 @@ #include "hyperv_wmi.h" #include "openwsman.h" #include "virstring.h" +#include "virtypedparam.h" #define VIR_FROM_THIS VIR_FROM_HYPERV @@ -1782,6 +1783,131 @@ hypervDomainShutdown(virDomainPtr dom) +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 saved_nparams = 0; + int result = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |VIR_DOMAIN_AFFECT_CONFIG |VIR_TYPED_PARAM_STRING_OKAY, -1); + + /* We don't return strings, and thus trivially support this flag */ + flags &= ~VIR_TYPED_PARAM_STRING_OKAY; + + virUUIDFormat(dom->uuid, uuid_string); + + /* Get Msvm_ComputerSystem */ + if (hypervMsvmComputerSystemFromDomain(dom, &computerSystem) < 0) { + goto cleanup; + } + + /* Get Msvm_VirtualSystemSettingData */ + virBufferAsprintf(&query, + "associators of " + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," + "Name=\"%s\"} " + "where AssocClass = Msvm_SettingsDefineState " + "ResultClass = Msvm_VirtualSystemSettingData", + uuid_string); + + if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query, &virtualSystemSettingData) < 0) { + goto cleanup; + } + + if (virtualSystemSettingData == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not lookup %s for domain %s"), + "Msvm_VirtualSystemSettingData", + computerSystem->data->ElementName); + goto cleanup; + } + + /* Get Msvm_ProcessorSettingData */ + virBufferAsprintf(&query, + "associators of " + "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} " + "where AssocClass = Msvm_VirtualSystemSettingDataComponent " + "ResultClass = Msvm_ProcessorSettingData", + virtualSystemSettingData->data->InstanceID); + + if (hypervGetMsvmProcessorSettingDataList(priv, &query, &processorSettingData) < 0) { + goto cleanup; + } + + if (processorSettingData == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain %s"), + "Msvm_ProcessorSettingData",computerSystem->data->ElementName); + goto cleanup; + } + + if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_SCHEDULER_LIMIT, + VIR_TYPED_PARAM_LLONG, processorSettingData->data->Limit) < 0) + goto cleanup; + saved_nparams++; + + if (*nparams > saved_nparams) { + if (virTypedParameterAssign(¶ms[1],VIR_DOMAIN_SCHEDULER_RESERVATION, + VIR_TYPED_PARAM_LLONG, processorSettingData->data->Reservation) < 0) + goto cleanup; + saved_nparams++; + } + + if (*nparams > saved_nparams) { + if (virTypedParameterAssign(¶ms[2],VIR_DOMAIN_SCHEDULER_WEIGHT, + VIR_TYPED_PARAM_UINT, processorSettingData->data->Weight) < 0) + goto cleanup; + saved_nparams++; + } + + *nparams = saved_nparams; + + result = 0; + + cleanup: + hypervFreeObject(priv, (hypervObject *)computerSystem); + hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); + hypervFreeObject(priv, (hypervObject *)processorSettingData); + virBufferFreeAndReset(&query); + + return result; +} + + + +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; + + if (VIR_STRDUP(type, "allocation") < 0) { + virReportOOMError(); + return NULL; + } + + if (nparams != NULL) { + *nparams = 3; /* reservation, limit, weight */ + } + + return type; +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -1826,6 +1952,9 @@ static virDriver hypervDriver = { .nodeGetFreeMemory = hypervNodeGetFreeMemory, /* 1.2.10 */ .domainShutdownFlags = hypervDomainShutdownFlags, /* 1.2.10 */ .domainShutdown = hypervDomainShutdown, /* 1.2.10 */ + .domainGetSchedulerParametersFlags = hypervDomainGetSchedulerParametersFlags, /* 1.2.10 */ + .domainGetSchedulerParameters = hypervDomainGetSchedulerParameters, /* 1.2.10 */ + .domainGetSchedulerType = hypervDomainGetSchedulerType, /* 1.2.10 */ }; -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_network_driver.c | 33 +++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi.c | 27 +++++++++++++++++++++++++++ src/hyperv/hyperv_wmi.h | 9 +++++++++ src/hyperv/hyperv_wmi_generator.input | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) diff --git a/src/hyperv/hyperv_network_driver.c b/src/hyperv/hyperv_network_driver.c index 6f54f44..22e1144 100644 --- a/src/hyperv/hyperv_network_driver.c +++ b/src/hyperv/hyperv_network_driver.c @@ -28,6 +28,7 @@ #include "viralloc.h" #include "viruuid.h" #include "hyperv_network_driver.h" +#include "hyperv_wmi.h" #define VIR_FROM_THIS VIR_FROM_HYPERV @@ -61,10 +62,42 @@ hypervNetworkClose(virConnectPtr conn) +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: + hypervFreeObject(priv, (hypervObject *) virtualSwitch); + virBufferFreeAndReset(&query); + + return network; +} + + + static virNetworkDriver hypervNetworkDriver = { .name = "Hyper-V", .networkOpen = hypervNetworkOpen, /* 0.9.5 */ .networkClose = hypervNetworkClose, /* 0.9.5 */ + .networkLookupByName = hypervNetworkLookupByName, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index d93abd9..be84532 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -682,6 +682,33 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain, return result; } +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..acc4097 100644 --- a/src/hyperv/hyperv_wmi.h +++ b/src/hyperv/hyperv_wmi.h @@ -115,6 +115,15 @@ int hypervMsvmComputerSystemFromDomain(virDomainPtr domain, +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Msvm_VirtualSwitch + */ + +int hypervMsvmVirtualSwitchToNetwork(virConnectPtr conn, + Msvm_VirtualSwitch *virtualSwitch, virNetworkPtr *network); + + + # include "hyperv_wmi.generated.h" #endif /* __HYPERV_WMI_H__ */ diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 739be87..21420d5 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -522,3 +522,36 @@ class Win32_OperatingSystem string Version string WindowsDirectory 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 -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_network_driver.c | 57 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/hyperv/hyperv_network_driver.c b/src/hyperv/hyperv_network_driver.c index 22e1144..ee7c0b3 100644 --- a/src/hyperv/hyperv_network_driver.c +++ b/src/hyperv/hyperv_network_driver.c @@ -27,8 +27,10 @@ #include "datatypes.h" #include "viralloc.h" #include "viruuid.h" +#include "virstring.h" #include "hyperv_network_driver.h" #include "hyperv_wmi.h" +#include "network_conf.h" #define VIR_FROM_THIS VIR_FROM_HYPERV @@ -93,11 +95,66 @@ hypervNetworkLookupByName(virConnectPtr conn, const char *name) +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); + hypervFreeObject(priv, (hypervObject *)virtualSwitch); + virBufferFreeAndReset(&query); + + return xml; +} + + + static virNetworkDriver hypervNetworkDriver = { .name = "Hyper-V", .networkOpen = hypervNetworkOpen, /* 0.9.5 */ .networkClose = hypervNetworkClose, /* 0.9.5 */ .networkLookupByName = hypervNetworkLookupByName, /* 1.2.10 */ + .networkGetXMLDesc = hypervNetworkGetXMLDesc, /* 1.2.10 */ }; -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_network_driver.c | 81 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/hyperv/hyperv_network_driver.c b/src/hyperv/hyperv_network_driver.c index ee7c0b3..84267b7 100644 --- a/src/hyperv/hyperv_network_driver.c +++ b/src/hyperv/hyperv_network_driver.c @@ -149,12 +149,93 @@ hypervNetworkGetXMLDesc(virNetworkPtr network, unsigned int flags) +static int +hypervConnectNumOfNetworks(virConnectPtr conn) +{ + int result = -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++; + } + + result = count; + + cleanup: + hypervFreeObject(priv, (hypervObject *) virtualSwitchList); + virBufferFreeAndReset(&query); + + return result; +} + + + +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; + } + + hypervFreeObject(priv, (hypervObject *) virtualSwitchList); + virBufferFreeAndReset(&query); + + return count; +} + + + static virNetworkDriver hypervNetworkDriver = { .name = "Hyper-V", .networkOpen = hypervNetworkOpen, /* 0.9.5 */ .networkClose = hypervNetworkClose, /* 0.9.5 */ .networkLookupByName = hypervNetworkLookupByName, /* 1.2.10 */ .networkGetXMLDesc = hypervNetworkGetXMLDesc, /* 1.2.10 */ + .connectNumOfNetworks = hypervConnectNumOfNetworks, /* 1.2.10 */ + .connectListNetworks = hypervConnectListNetworks, /* 1.2.10 */ }; -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_network_driver.c | 81 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/hyperv/hyperv_network_driver.c b/src/hyperv/hyperv_network_driver.c index 84267b7..2063090 100644 --- a/src/hyperv/hyperv_network_driver.c +++ b/src/hyperv/hyperv_network_driver.c @@ -228,6 +228,85 @@ hypervConnectListNetworks(virConnectPtr conn, char **const names, int maxnames) +static int +hypervConnectNumOfDefinedNetworks(virConnectPtr conn) +{ + int result = -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++; + } + + result = count; + + cleanup: + hypervFreeObject(priv, (hypervObject *) virtualSwitchList); + virBufferFreeAndReset(&query); + + return result; +} + + + +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; + } + + hypervFreeObject(priv, (hypervObject *) virtualSwitchList); + virBufferFreeAndReset(&query); + + return count; +} + + + static virNetworkDriver hypervNetworkDriver = { .name = "Hyper-V", .networkOpen = hypervNetworkOpen, /* 0.9.5 */ @@ -236,6 +315,8 @@ static virNetworkDriver hypervNetworkDriver = { .networkGetXMLDesc = hypervNetworkGetXMLDesc, /* 1.2.10 */ .connectNumOfNetworks = hypervConnectNumOfNetworks, /* 1.2.10 */ .connectListNetworks = hypervConnectListNetworks, /* 1.2.10 */ + .connectNumOfDefinedNetworks = hypervConnectNumOfDefinedNetworks, /* 1.2.10 */ + .connectListDefinedNetworks = hypervConnectListDefinedNetworks, /* 1.2.10 */ }; -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_wmi.c | 666 +++++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi.h | 53 +++ src/hyperv/hyperv_wmi_generator.py | 59 ++++ src/hyperv/openwsman.h | 4 + 4 files changed, 782 insertions(+) diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index be84532..61fb540 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -22,6 +22,7 @@ */ #include <config.h> +#include <wsman-soap.h> /* Where struct _WsXmlDoc is defined (necessary to dereference WsXmlDocH type) */ #include "internal.h" #include "virerror.h" @@ -32,6 +33,7 @@ #include "hyperv_private.h" #include "hyperv_wmi.h" #include "virstring.h" +#include "hyperv_wmi_cimtypes.generated.h" #define WS_SERIALIZER_FREE_MEM_WORKS 0 @@ -383,6 +385,670 @@ hypervReturnCodeToString(int returnCode) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * hypervInvokeMethod + * Function to invoke WSMAN request with simple, EPR or embedded parameters + */ + +/* Create XML structure */ +static 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: + + virBufferFreeAndReset(&method_buff); + VIR_FREE(methodNameInput); + if (*xmlDocRoot != NULL) { + ws_xml_destroy_doc(*xmlDocRoot); + *xmlDocRoot = NULL; + } + + return -1; +} + + +/* Look for the type of a given property class and specifies if it is an array */ +static int +hypervGetPropType(const char *className, const char *propName, const char **propType, bool *isArray) +{ + int i, y; + + i = 0; + while (cimClasses[i].name[0] != '\0') { + if (STREQ(cimClasses[i].name, className)){ + y = 0; + while (cimClasses[i].cimTypesPtr[y].name[0] != '\0') { + if (STREQ(cimClasses[i].cimTypesPtr[y].name, propName)){ + *propType = cimClasses[i].cimTypesPtr[y].type; + *isArray = cimClasses[i].cimTypesPtr[y].isArray; + return 0; + } + y++; + } + break; + } + i++; + } + + return -1; +} + + +/* Adding an Simple param node to a parent node given in parameter */ +static 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 */ +static 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; + xmlNodePtr xmlNodeAdrPtr = NULL; + xmlNodePtr xmlNodeRefPtr = NULL; + WsXmlDocH xmlDocResponse = NULL; + xmlDocPtr docPtr = (xmlDocPtr) doc->parserDoc; + WsXmlNsH ns = NULL; + client_opt_t *options = NULL; + filter_t *filter = NULL; + char *enumContext = NULL; + char *query_string = NULL; + + /* Request options and filter */ + options = wsmc_options_init(); + + if (options == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not initialize options")); + goto cleanup; + } + + wsmc_set_action_option(options, FLAG_ENUMERATION_ENUM_EPR); + + query_string = virBufferContentAndReset(query); + filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string); + if (filter == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not create filter")); + goto cleanup; + } + + /* Invoke enumerate action*/ + xmlDocResponse = wsmc_action_enumerate(priv->client,root, options, filter); + + /* Check return value */ + if (hyperyVerifyResponse(priv->client, xmlDocResponse, "enumeration") < 0) { + goto cleanup; + } + + /* Get enumerate conext*/ + enumContext = wsmc_get_enum_context(xmlDocResponse); + + ws_xml_destroy_doc(xmlDocResponse); + + + /* Invoke pull action*/ + xmlDocResponse = wsmc_action_pull(priv->client, classURI, options, filter, enumContext); + + /* Check return value */ + if (hyperyVerifyResponse(priv->client, xmlDocResponse, "pull") < 0) { + goto cleanup; + } + + /* Extract EPR nodes childs */ + xmlNodTemp = ws_xml_get_soap_body(xmlDocResponse); + if (xmlNodTemp == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not lookup SOAP body")); + goto cleanup; + } + + xmlNodTemp = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ENUMERATION, WSENUM_PULL_RESP); + if (xmlNodTemp == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not lookup pull response")); + goto cleanup; + } + + xmlNodTemp = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ENUMERATION, WSENUM_ITEMS); + if (xmlNodTemp == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not lookup pull response items")); + goto cleanup; + } + + xmlNodTemp = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ADDRESSING, WSA_EPR); + if (xmlNodTemp == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not lookup pull response item EPR")); + goto cleanup; + } + + xmlNodeAdr = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ADDRESSING, WSA_ADDRESS); + if (xmlNodeAdr == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not lookup pull response item ADDRESS")); + goto cleanup; + } + xmlNodeAdrPtr = xmlDocCopyNode((xmlNodePtr) xmlNodeAdr, docPtr, 1); + if (xmlNodeAdrPtr == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not copy item ADDRESS")); + goto cleanup; + } + + xmlNodeRef = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ADDRESSING, WSA_REFERENCE_PARAMETERS); + if (xmlNodeRef == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not lookup pull response item REFERENCE PARAMETERS")); + goto cleanup; + } + xmlNodeRefPtr = xmlDocCopyNode((xmlNodePtr) xmlNodeRef, docPtr, 1); + if (xmlNodeRefPtr == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not copy item REFERENCE PARAMETERS")); + goto cleanup; + } + + /* Build XmlDoc with adding previous EPR nodes childs */ + xmlNodeParam = ws_xml_add_child(*parentNode, classURI, paramName, NULL); + if (xmlNodeParam == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not add child node to xmlNodeParam")); + goto cleanup; + } + +/* + The folowing line has been commented because of a memory corruption issue reported in the openwsman library + [ issue #43 - xml_parser_ns_add: alloc item size, not pointer size ] + xmlNodeSetLang((xmlNodePtr) xmlNodeParam, BAD_CAST "en-US"); +*/ + ns = ws_xml_ns_add(xmlNodeParam, "http://schemas.xmlsoap.org/ws/2004/08/addressing", "a"); + if (ns == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not set namespace adressing to xmlNodeParam")); + goto cleanup; + } + + ns = NULL; + ns = ws_xml_ns_add(xmlNodeParam, "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd", "w"); + if (ns == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not set namespace wsman to xmlNodeParam")); + goto cleanup; + } + + if (xmlAddChild((xmlNodePtr) *parentNode,(xmlNodePtr) xmlNodeParam) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not add child to xml parent node")); + goto cleanup; + } + + if (xmlAddChild((xmlNodePtr) xmlNodeParam, xmlNodeAdrPtr) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not add child to xml parent node")); + goto cleanup; + } + + if (xmlAddChild((xmlNodePtr) xmlNodeParam, xmlNodeRefPtr) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not add child to xml parent node")); + goto cleanup; + } + + result = 0; + + cleanup: + if (options != NULL) { + wsmc_options_destroy(options); + } + if (filter != NULL) { + filter_destroy(filter); + } + ws_xml_destroy_doc(xmlDocResponse); + VIR_FREE(enumContext); + VIR_FREE(query_string); + + return result; +} + + +/* Adding an Embedded Instance node to a parent node given in parameter */ +static 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; + const char *type = 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; + } + + if (hypervGetPropType(instanceName, prop_t[i].name, &type, &isArray) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("Could not get properties from array")); + goto cleanup; + } + + 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; + } + /* Add 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 (xmlBufferNode != NULL) + xmlBufferFree(xmlBufferNode); + + return result; +} + + +/* Call wsmc_action_invoke() function of OpenWsman API with XML tree given in parameters*/ +static 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; + + options = wsmc_options_init(); + + if (options == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not initialize options")); + goto cleanup; + } + + 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; + } + + /* 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); /* Wait 100 ms */ + 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); + + return result; +} + + +/* Calls the invoke method by passing provided parameters as an XML tree */ +int +hypervInvokeMethod(hypervPrivate *priv, invokeXmlParam *param_t, int nbParameters, + const char* methodName, const char* providerURI, const char *selector) +{ + int result = -1; + WsXmlDocH doc = NULL; + WsXmlNodeH methodNode = NULL; + simpleParam *simple; + eprParam *epr; + embeddedParam *embedded; + int i =0; + + if (hypervCreateXmlStruct(methodName,providerURI,&doc,&methodNode) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("Could not create xml base structure")); + goto cleanup; + } + + /* Process parameters among the three allowed types */ + while ( i < nbParameters) { + switch (param_t[i].type) { + 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; + 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; + } + i++; + } + + /* Call the invoke method */ + if (hypervInvokeMethodXml(priv, doc, methodName, providerURI, selector) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("Error during invocation action")); + goto cleanup; + } + + result = 0; + + cleanup: + if (doc != NULL) + ws_xml_destroy_doc(doc); + + return result; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Msvm_ComputerSystem */ diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h index acc4097..5168d04 100644 --- a/src/hyperv/hyperv_wmi.h +++ b/src/hyperv/hyperv_wmi.h @@ -94,6 +94,59 @@ const char *hypervReturnCodeToString(int returnCode); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * hypervInvokeMethod + * Function to invoke WSMAN request with simple, EPR or embedded parameters + */ + +enum _PARAM_Type { + SIMPLE_PARAM = 0, + EPR_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); + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Msvm_ComputerSystem */ diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index 5010470..7991295 100755 --- a/src/hyperv/hyperv_wmi_generator.py +++ b/src/hyperv/hyperv_wmi_generator.py @@ -101,6 +101,28 @@ class Class: return header + def generate_cimtypes_header2(self): + header = separator + header += " * %s\n" % self.name + header += " */\n" + header += "\n" + header += "CimTypes cimTypes_%s[] = {\n" % self.name + for property in self.properties: + header += property.generate_cimtypes_header2() + header += ",\n" + header += "\t{ \"\", \"\", 0 },\n};\n\n" + + return header + + + def generate_cimtypes_header3(self): + header = " { \"%s" % self.name + header += "\", cimTypes_%s" % self.name + header += " },\n" + + return header + + def generate_source(self): name_upper = self.name.upper() @@ -191,6 +213,17 @@ class Property: % (Property.typemap[self.type], class_name.upper(), self.name) + def generate_cimtypes_header2(self): + header = " { \"%s" % self.name + header += "\", \"%s\", " % self.type + if self.is_array: + header += "true" + else: + header += "false" + header += " }" + return header + + def open_and_print(filename): if filename.startswith("./"): @@ -240,6 +273,22 @@ def parse_class(block): return Class(name=name, properties=properties) +def generate_cimtypes_header1(): + header = "struct cimTypes{\n" + header += " const char *name;\n" + header += " const char *type;\n" + header += " bool isArray;\n" + header += "};\n" + header += "typedef struct cimTypes CimTypes;\n\n" + header += "struct cimClasses{\n" + header += " const char *name;\n" + header += " CimTypes *cimTypesPtr;\n" + header += "};\n" + header += "typedef struct cimClasses CimClasses;\n\n" + + return header + + def main(): if "srcdir" in os.environ: @@ -254,6 +303,7 @@ def main(): classes_typedef = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes.generated.typedef")) classes_header = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes.generated.h")) classes_source = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes.generated.c")) + cimtypes_header = open_and_print(os.path.join(output_dirname, "hyperv_wmi_cimtypes.generated.h")) # parse input file number = 0 @@ -296,6 +346,9 @@ def main(): classes_header.write(notice) classes_source.write(notice) + cimtypes_header.write(notice) + cimtypes_header.write(generate_cimtypes_header1()) + names = classes_by_name.keys() names.sort() @@ -305,6 +358,12 @@ def main(): classes_typedef.write(classes_by_name[name].generate_classes_typedef()) classes_header.write(classes_by_name[name].generate_classes_header()) classes_source.write(classes_by_name[name].generate_classes_source()) + cimtypes_header.write(classes_by_name[name].generate_cimtypes_header2()) + + cimtypes_header.write("CimClasses cimClasses[] = {\n") + for name in names: + cimtypes_header.write(classes_by_name[name].generate_cimtypes_header3()) + cimtypes_header.write("\t{ \"\", NULL },\n};\n") diff --git a/src/hyperv/openwsman.h b/src/hyperv/openwsman.h index f66ed86..27029e7 100644 --- a/src/hyperv/openwsman.h +++ b/src/hyperv/openwsman.h @@ -43,4 +43,8 @@ # define SER_NS_INT64(ns, n, x) SER_NS_INT64_FLAGS(ns, n, x, 0) # endif +/* wsman-xml.h */ +WsXmlDocH ws_xml_create_doc( const char *rootNsUri, const char *rootName); +WsXmlNodeH xml_parser_get_root(WsXmlDocH doc); + #endif /* __OPENWSMAN_H__ */ -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 103 ++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi.c | 6 -- src/hyperv/hyperv_wmi.h | 7 +++ src/hyperv/hyperv_wmi_generator.input | 50 +++++++++++++++++ 4 files changed, 160 insertions(+), 6 deletions(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 4074fb0..5c79c99 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1908,6 +1908,107 @@ hypervDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED, int *nparams) +static int +hypervDomainSetAutostart(virDomainPtr domain, int autostart) +{ + int result = -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; + if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0) + goto cleanup; + (*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; + if (VIR_ALLOC_N(params, nb_params) < 0) + goto cleanup; + (*params).name = "ComputerSystem"; + (*params).type = EPR_PARAM; + (*params).param = &eprparam; + (*(params+1)).name = "SystemSettingData"; + (*(params+1)).type = EMBEDDED_PARAM; + (*(params+1)).param = &embeddedparam; + + result = 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 result; +} + + + +static int +hypervDomainGetAutostart(virDomainPtr domain, int *autostart) +{ + int result = -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; + result = 0; + + cleanup: + hypervFreeObject(priv, (hypervObject *) vsgsd); + virBufferFreeAndReset(&query); + + return result; +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -1955,6 +2056,8 @@ static virDriver hypervDriver = { .domainGetSchedulerParametersFlags = hypervDomainGetSchedulerParametersFlags, /* 1.2.10 */ .domainGetSchedulerParameters = hypervDomainGetSchedulerParameters, /* 1.2.10 */ .domainGetSchedulerType = hypervDomainGetSchedulerType, /* 1.2.10 */ + .domainSetAutostart = hypervDomainSetAutostart, /* 1.2.10 */ + .domainGetAutostart = hypervDomainGetAutostart, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index 61fb540..f086843 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -37,12 +37,6 @@ #define WS_SERIALIZER_FREE_MEM_WORKS 0 -#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/*" - #define VIR_FROM_THIS VIR_FROM_HYPERV diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h index 5168d04..4b85b89 100644 --- a/src/hyperv/hyperv_wmi.h +++ b/src/hyperv/hyperv_wmi.h @@ -30,6 +30,13 @@ # include "openwsman.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/*" + + typedef struct _hypervObject hypervObject; diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 21420d5..79b5ee2 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -555,3 +555,53 @@ class Msvm_VirtualSwitch uint32 MaxVMQOffloads uint32 MaxChimneyOffloads 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 -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 119 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 5c79c99..0618ce1 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -2009,6 +2009,124 @@ hypervDomainGetAutostart(virDomainPtr domain, int *autostart) +/* Format a number as a string value */ +static char *num2str(unsigned long value) +{ + int sz; + char *result; + + sz = snprintf (NULL, 0, "%lu", value); + if (VIR_ALLOC_N(result, sz + 1) < 0) { + return NULL; + } + + sprintf(result, "%lu", value); + return result; +} + + + +static int +hypervDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) +{ + int result = -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 */ + memory_str = num2str(memory_mb); + if (memory_str == NULL) + goto cleanup; + + 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; + if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0) + goto cleanup; + (*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; + if (VIR_ALLOC_N(params, nb_params) < 0) + goto cleanup; + (*params).name = "ComputerSystem"; + (*params).type = EPR_PARAM; + (*params).param = &eprparam; + (*(params+1)).name = "ResourceSettingData"; + (*(params+1)).type = EMBEDDED_PARAM; + (*(params+1)).param = &embeddedparam; + + result = 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 result; +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -2058,6 +2176,7 @@ static virDriver hypervDriver = { .domainGetSchedulerType = hypervDomainGetSchedulerType, /* 1.2.10 */ .domainSetAutostart = hypervDomainSetAutostart, /* 1.2.10 */ .domainGetAutostart = hypervDomainGetAutostart, /* 1.2.10 */ + .domainSetMaxMemory = hypervDomainSetMaxMemory, /* 1.2.10 */ }; -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 112 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 0618ce1..a8d679e 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -2127,6 +2127,116 @@ hypervDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) +static int +hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory, + 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; + 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; /* Memory converted in MB */ + 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 */ + memory_str = num2str(memory_mb); + if (memory_str == NULL) + goto cleanup; + + 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; + if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0) + goto cleanup; + (*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; + if (VIR_ALLOC_N(params, nb_params) < 0) + goto cleanup; + (*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; + } + + result = 0; + + cleanup: + VIR_FREE(tab_props); + VIR_FREE(params); + VIR_FREE(memory_str); + hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); + hypervFreeObject(priv, (hypervObject *)memorySettingData); + virBufferFreeAndReset(&query); + + return result; +} + + + +static int +hypervDomainSetMemory(virDomainPtr domain, unsigned long memory) +{ + return hypervDomainSetMemoryFlags(domain, memory, 0); +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -2177,6 +2287,8 @@ static virDriver hypervDriver = { .domainSetAutostart = hypervDomainSetAutostart, /* 1.2.10 */ .domainGetAutostart = hypervDomainGetAutostart, /* 1.2.10 */ .domainSetMaxMemory = hypervDomainSetMaxMemory, /* 1.2.10 */ + .domainSetMemory = hypervDomainSetMemory, /* 1.2.10 */ + .domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* 1.2.10 */ }; -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 118 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index a8d679e..ade9db1 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -2237,6 +2237,122 @@ hypervDomainSetMemory(virDomainPtr domain, unsigned long memory) +static int +hypervDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus, + unsigned int flags ATTRIBUTE_UNUSED) +{ + int result = -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 = num2str(nvcpus); + if (nvcpus_str == NULL) + goto cleanup; + + 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; + if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0) + goto cleanup; + (*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; + if (VIR_ALLOC_N(params, nb_params) < 0) + goto cleanup; + (*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; + } + + result = 0; + + cleanup: + VIR_FREE(tab_props); + VIR_FREE(params); + VIR_FREE(nvcpus_str); + hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); + hypervFreeObject(priv, (hypervObject *)processorSettingData); + virBufferFreeAndReset(&query); + + return result; +} + + + +static int +hypervDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus) +{ + return hypervDomainSetVcpusFlags(domain, nvcpus, 0); +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -2289,6 +2405,8 @@ static virDriver hypervDriver = { .domainSetMaxMemory = hypervDomainSetMaxMemory, /* 1.2.10 */ .domainSetMemory = hypervDomainSetMemory, /* 1.2.10 */ .domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* 1.2.10 */ + .domainSetVcpus = hypervDomainSetVcpus, /* 1.2.10 */ + .domainSetVcpusFlags = hypervDomainSetVcpusFlags, /* 1.2.10 */ }; -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index ade9db1..f68eaad 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -2353,6 +2353,77 @@ hypervDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus) +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; + if (VIR_ALLOC_N(params, nb_params) < 0) + goto cleanup; + (*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: + 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, .name = "Hyper-V", @@ -2407,6 +2478,8 @@ static virDriver hypervDriver = { .domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* 1.2.10 */ .domainSetVcpus = hypervDomainSetVcpus, /* 1.2.10 */ .domainSetVcpusFlags = hypervDomainSetVcpusFlags, /* 1.2.10 */ + .domainUndefine = hypervDomainUndefine, /* 1.2.10 */ + .domainUndefineFlags = hypervDomainUndefineFlags, /* 1.2.10 */ }; -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 377 ++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.input | 41 ++++ 2 files changed, 418 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index f68eaad..cbe4397 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -2424,6 +2424,383 @@ hypervDomainUndefine(virDomainPtr domain) +/* + * Creates 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 result = -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 */ + if (VIR_ALLOC_N(strTemp, strlen(rasdInstanceID) + 1 + n) < 0) + goto cleanup; + while (rasdInstanceID[i] != '\0') { + strTemp[j] = rasdInstanceID[i]; + if (rasdInstanceID[i] == '\\') { + j++; + strTemp[j] = '\\'; + } + i++; + j++; + } + strTemp[j] = '\0'; + + /* Create the attribute __PATH */ + /* FIXME: *__path allocated with 255 characters (static value) */ + if (VIR_ALLOC_N(*__path, 255) < 0) + goto cleanup; + sprintf(*__path, "\\\\"); + strcat(*__path, computerSystem->data->ElementName); + strcat(*__path, "\\root\\virtualization:Msvm_ResourceAllocationSettingData.InstanceID=\""); + strcat(*__path, strTemp); + strcat(*__path, "\""); + + result = 0; + + cleanup: + VIR_FREE(strTemp); + hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query); + + return result; +} + + + +/* 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 associated detach method + */ +ATTRIBUTE_UNUSED static int +hypervDomainAttachDisk(virDomainPtr domain, virDomainDiskDefPtr disk) +{ + int result = -1, nb_params; + const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService"; + char uuid_string[VIR_UUID_STRING_BUFLEN]; + char *ideRasdPath = NULL, *newDiskDrivePath = NULL; + char ideControler[2], ideControlerAddr[2]; + 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; /* resourceAllocationSettingData subtree -> do not disallocate */ + Msvm_ResourceAllocationSettingData *diskRasd = NULL; /* resourceAllocationSettingData2 subtree -> do not disallocate */ + Msvm_ResourceAllocationSettingData *newDiskDrive = NULL; /* resourceAllocationSettingData3 subtree -> 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 */ + if (STREQ(disk->dst, "hda")) { + sprintf(ideControler, "%d", 0); + sprintf(ideControlerAddr, "%d", 0); + } else if (STREQ(disk->dst, "hdb")) { + sprintf(ideControler, "%d", 0); + sprintf(ideControlerAddr, "%d", 1); + } else if (STREQ(disk->dst, "hdc")) { + sprintf(ideControler, "%d", 1); + sprintf(ideControlerAddr, "%d", 0); + } else if (STREQ(disk->dst, "hdd")) { + sprintf(ideControler, "%d", 1); + sprintf(ideControlerAddr, "%d", 1); + } else { + /* IDE Controler 0 and address 0 choosen 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 && STREQ(ideRasd->data->Address, ideControler)) { + /* 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; + if (VIR_ALLOC_N(tab_props, embeddedparam1.nbProps) < 0) + goto cleanup; + (*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; + if (VIR_ALLOC_N(params, nb_params) < 0) + goto cleanup; + (*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 && + STREQ(newDiskDrive->data->ResourceSubType, "Microsoft Synthetic Disk Drive") && + STREQ(newDiskDrive->data->Parent, ideRasdPath) && + STREQ(newDiskDrive->data->Address, ideControlerAddr)) { + 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; + if (VIR_ALLOC_N(tab_props, embeddedparam2.nbProps) < 0) + goto cleanup; + (*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; + if (VIR_ALLOC_N(params, nb_params) < 0) + goto cleanup; + (*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; + } + + result = 0; + + cleanup: + VIR_FREE(ideRasdPath); + VIR_FREE(newDiskDrivePath); + VIR_FREE(tab_props); + 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 result; +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 79b5ee2..24d399f 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -605,3 +605,44 @@ class Msvm_VirtualSystemGlobalSettingData 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 -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 218 ++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.input | 87 ++++++++++++++ 2 files changed, 305 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index cbe4397..8b8e612 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -2801,6 +2801,224 @@ hypervDomainAttachDisk(virDomainPtr domain, virDomainDiskDefPtr disk) +/* + * 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; + int result = -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: *__path is allocated with 512 characters (static value) */ + if (VIR_ALLOC_N(*__path, 512) < 0) + goto cleanup; + sprintf(*__path, + "\\\\%s\\root\\virtualization:Msvm_SwitchPort.CreationClassName=\"Msvm_SwitchPort\"," + "Name=\"%s\",SystemCreationClassName=\"Msvm_VirtualSwitch\",SystemName=\"%s\"", + computerSystem->data->ElementName, switchPortName, virtualSwitchSystemName); + + result = 0; + + cleanup: + hypervFreeObject(priv, (hypervObject *) computerSystem); + virBufferFreeAndReset(&query); + return result; +} + + + +/* hypervDomainAttachNetwork + * FIXME: + * - implement associated detach method + */ +ATTRIBUTE_UNUSED static int +hypervDomainAttachNetwork(virDomainPtr domain, virDomainNetDefPtr net) +{ + int result = -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; + if (VIR_ALLOC_N(params, nb_params) < 0) + goto cleanup; + (*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); + if (hypervGetSwitchPortPATH(domain, switchPort->data->Name, virtualSwitch->data->Name, &switchPortPATH) < 0) { + goto cleanup; + } + + embeddedparam.nbProps = 5; + if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0) + goto cleanup; + (*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; + if (VIR_ALLOC_N(params, nb_params) < 0) + goto cleanup; + (*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; + } + + result = 0; + + cleanup: + VIR_FREE(virtualSystemIdentifiers); + VIR_FREE(switchPortPATH); + VIR_FREE(tab_props); + VIR_FREE(params); + hypervFreeObject(priv, (hypervObject *)switchPort); + hypervFreeObject(priv, (hypervObject *)virtualSwitch); + virBufferFreeAndReset(&query); + + return result; +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 24d399f..74e0c94 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -646,3 +646,90 @@ class Msvm_AllocationCapabilities uint16 SupportedAddStates[] uint16 SupportedRemoveStates[] 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 -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 81 +++++++++++++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_private.h | 2 ++ 2 files changed, 83 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 8b8e612..8e0d6b3 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -62,6 +62,9 @@ hypervFreePrivate(hypervPrivate **priv) if ((*priv)->caps != NULL) virObjectUnref((*priv)->caps); + if ((*priv)->xmlopt != NULL) + virObjectUnref((*priv)->xmlopt); + hypervFreeParsedUri(&(*priv)->parsedUri); VIR_FREE(*priv); } @@ -206,6 +209,9 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags goto cleanup; } + /* Init xmlopt to parse Domain XML */ + priv->xmlopt = virDomainXMLOptionNew(NULL, NULL, NULL); + conn->privateData = priv; priv = NULL; result = VIR_DRV_OPEN_SUCCESS; @@ -3019,6 +3025,79 @@ hypervDomainAttachNetwork(virDomainPtr domain, virDomainNetDefPtr net) +static int +hypervDomainAttachDeviceFlags(virDomainPtr domain, const char *xml, + unsigned int flags ATTRIBUTE_UNUSED) +{ + int result = -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; + + /* Unsupported device type */ + default: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Device attachment of type %d is not implemented"), dev->type); + goto cleanup; + } + + result = 0; + + cleanup: + virDomainDefFree(def); + virDomainDeviceDefFree(dev); + VIR_FREE(xmlDomain); + + return result; +} + + + +static int +hypervDomainAttachDevice(virDomainPtr domain, const char *xml) +{ + return hypervDomainAttachDeviceFlags(domain, xml, 0); +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -3075,6 +3154,8 @@ static virDriver hypervDriver = { .domainSetVcpusFlags = hypervDomainSetVcpusFlags, /* 1.2.10 */ .domainUndefine = hypervDomainUndefine, /* 1.2.10 */ .domainUndefineFlags = hypervDomainUndefineFlags, /* 1.2.10 */ + .domainAttachDevice = hypervDomainAttachDevice, /* 1.2.10 */ + .domainAttachDeviceFlags = hypervDomainAttachDeviceFlags, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_private.h b/src/hyperv/hyperv_private.h index d9aa0bd..2dfce6e 100644 --- a/src/hyperv/hyperv_private.h +++ b/src/hyperv/hyperv_private.h @@ -27,6 +27,7 @@ # include "virerror.h" # include "hyperv_util.h" # include "capabilities.h" +# include "domain_conf.h" # include "openwsman.h" typedef struct _hypervPrivate hypervPrivate; @@ -35,6 +36,7 @@ struct _hypervPrivate { hypervParsedUri *parsedUri; WsManClient *client; virCapsPtr caps; + virDomainXMLOptionPtr xmlopt; }; #endif /* __HYPERV_PRIVATE_H__ */ -- 1.9.1

From: yvinter <yves.vinter@bull.net> --- src/hyperv/hyperv_driver.c | 142 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 8e0d6b3..83fb605 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -3098,6 +3098,146 @@ hypervDomainAttachDevice(virDomainPtr domain, const char *xml) +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]; + + /* Parse XML domain description */ + if ((def = virDomainDefParseString(xml, priv->caps, priv->xmlopt, + 1 << VIR_DOMAIN_VIRT_HYPERV, VIR_DOMAIN_XML_INACTIVE)) == NULL) { + goto cleanup; + } + + /* Create the domain if does not exist */ + 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; + if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0) + goto cleanup; + (*tab_props).name = "ElementName"; + (*tab_props).val = def->name; + embeddedparam.instanceName = "Msvm_VirtualSystemGlobalSettingData"; + embeddedparam.prop_t = tab_props; + + /* Create invokeXmlParam */ + nb_params = 1; + if (VIR_ALLOC_N(params, nb_params) < 0) + goto cleanup; + (*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); + VIR_FREE(tab_props); + VIR_FREE(params); + + return domain; +} + + + +static virDomainPtr +hypervDomainCreateXML(virConnectPtr conn, const char *xmlDesc, unsigned int flags) +{ + virDomainPtr domain; + + virCheckFlags(VIR_DOMAIN_START_PAUSED | VIR_DOMAIN_START_AUTODESTROY, NULL); + + /* Create the new domain */ + domain = hypervDomainDefineXML(conn, xmlDesc); + if (domain == NULL) + return NULL; + + /* Start the 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); + } + } + + /* FIXME: process autodestroy flag */ + + return domain; +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -3156,6 +3296,8 @@ static virDriver hypervDriver = { .domainUndefineFlags = hypervDomainUndefineFlags, /* 1.2.10 */ .domainAttachDevice = hypervDomainAttachDevice, /* 1.2.10 */ .domainAttachDeviceFlags = hypervDomainAttachDeviceFlags, /* 1.2.10 */ + .domainDefineXML = hypervDomainDefineXML, /* 1.2.10 */ + .domainCreateXML = hypervDomainCreateXML, /* 1.2.10 */ }; -- 1.9.1

On 10/08/2014 06:33 AM, Yves Vinter wrote:
From: yvinter <yves.vinter@bull.net>
Your git config is incorrect; your email headers list your full name 'Yves Vinter' but this line means that git is trying to attribute to the authorship to your username 'yvinter'. We prefer that the git history include a full legal name rather than a username abbreviation. Long subject line; the first line of a commit message should generally be no more than about 60 characters, so that 'git log --oneline -30' still fits the information comfortably in an 80-column screen. Also, it is nice to include a 'topic:' lead-in. Ideally, the one-line summary is the "what", and then the rest of the commit message after a blank line is the "why". So I suggest: hyperv: avoid memory leaks Add missing virBufferFreeAndReset on query buffers used throughout the hyperv code. as well as mention any valgrind testing you did to prove that the leaks are fixed.
+++ b/src/hyperv/hyperv_driver.c @@ -201,6 +201,7 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags VIR_FREE(username); VIR_FREE(password); hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query);
Hmmm. query is initialized empty, until it is used in this code a few lines earlier: virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT); virBufferAddLit(&query, "where "); virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_PHYSICAL); if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) { goto cleanup; but tracing through that code, hypervGetMsvmComputerSystemList in hyperv_wmi.generated.c calls hypervEnumAndPull in hyperv_wmi.c, which in turn calls virBufferContentAndReset(query) on the success path, leaving nothing to clean up here. Okay, I see where hypervEnumAndPull can return early without cleaning query; I wonder if it would have been better to patch THAT function to guarantee that the buffer is always clean on return, rather than having to patch every single caller. In fact, after looking through the entire patch, it looks like EVERY single addition of virBufferFreeAndReset(&query) is only ever useful in any case where hypervEnumAndPull returns early. I'm going to reply to this mail with an alternative shorter patch. I don't have access to hyperv to test it under an actual valgrind run, but it compiled for me. Can you please run it through your test setup to see if it solves the issues you were initially trying to address? -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

1) Your git config is incorrect: OK; I fixed it Should I have to send again the whole set of patch? 2) > + virBufferFreeAndReset(&query); Right; there are potential paths through which the query buffer may be not released (in hypervEnumAndPull). For safety, I systematically added this line for any local virBuffer variable. I did the same for the new implemented features: (1) that indirectly uses the function hypervEnumAndPull (2) that uses the new hypervInvokeMethod to invoke WMI methods with complex parameters (after patch #12) Note that in case (2) hypervInvokeMethod don't release query buffers (those contained in EPR structures) The code could also be modified to avoid the callers to have to release their buffers. 3) I'm going to reply to this mail with an alternative shorter patch. I don't have access to hyperv to test it under an actual valgrind run, but it compiled for me. Can you please run it through your test setup to see if it solves the issues you were initially trying to address? Yes I can. De : Eric Blake [mailto:eblake@redhat.com] Envoyé : mercredi 8 octobre 2014 18:24 À : Yves Vinter; libvir-list@redhat.com Objet : Re: [libvirt] [PATCH 01/21] Added missing virBufferFreeAndReset on the query buffer to free some memory On 10/08/2014 06:33 AM, Yves Vinter wrote:
From: yvinter <yves.vinter@bull.net>
Your git config is incorrect; your email headers list your full name 'Yves Vinter' but this line means that git is trying to attribute to the authorship to your username 'yvinter'. We prefer that the git history include a full legal name rather than a username abbreviation. Long subject line; the first line of a commit message should generally be no more than about 60 characters, so that 'git log --oneline -30' still fits the information comfortably in an 80-column screen. Also, it is nice to include a 'topic:' lead-in. Ideally, the one-line summary is the "what", and then the rest of the commit message after a blank line is the "why". So I suggest: hyperv: avoid memory leaks Add missing virBufferFreeAndReset on query buffers used throughout the hyperv code. as well as mention any valgrind testing you did to prove that the leaks are fixed.
+++ b/src/hyperv/hyperv_driver.c @@ -201,6 +201,7 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags VIR_FREE(username); VIR_FREE(password); hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query);
Hmmm. query is initialized empty, until it is used in this code a few lines earlier: virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT); virBufferAddLit(&query, "where "); virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_PHYSICAL); if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) { goto cleanup; but tracing through that code, hypervGetMsvmComputerSystemList in hyperv_wmi.generated.c calls hypervEnumAndPull in hyperv_wmi.c, which in turn calls virBufferContentAndReset(query) on the success path, leaving nothing to clean up here. Okay, I see where hypervEnumAndPull can return early without cleaning query; I wonder if it would have been better to patch THAT function to guarantee that the buffer is always clean on return, rather than having to patch every single caller. In fact, after looking through the entire patch, it looks like EVERY single addition of virBufferFreeAndReset(&query) is only ever useful in any case where hypervEnumAndPull returns early. I'm going to reply to this mail with an alternative shorter patch. I don't have access to hyperv to test it under an actual valgrind run, but it compiled for me. Can you please run it through your test setup to see if it solves the issues you were initially trying to address? -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 10/09/2014 03:51 AM, Yves Vinter wrote:
1) Your git config is incorrect: OK; I fixed it Should I have to send again the whole set of patch?
At this point, you can wait for more reviews on the rest of the patches. But yes, at some point, you'll want to send a v2 of the series with all the review changes incorporated.
2) > + virBufferFreeAndReset(&query);
Right; there are potential paths through which the query buffer may be not released (in hypervEnumAndPull).
Not if you take my alternate proposed 1/21 patch.
For safety, I systematically added this line for any local virBuffer variable.
I'd rather fix the one function than have to fix every caller.
I did the same for the new implemented features: (1) that indirectly uses the function hypervEnumAndPull (2) that uses the new hypervInvokeMethod to invoke WMI methods with complex parameters (after patch #12) Note that in case (2) hypervInvokeMethod don't release query buffers (those contained in EPR structures) The code could also be modified to avoid the callers to have to release their buffers.
It's bad to have a function that releases resources only some of the time. It's better to either ALWAYS release the resources, and document that the function consumes the argument, or to NEVER release the resources, leaving it up to the caller. Since the existing code is already semi-relying on the function consuming the argument (such as when a single hyperv_driver.c function reuses a query buffer twice in the same function, possible because the first use of the query was reset before building the second use of the buffer), my choice is to have the query parameter always consumed, even on error. Less code changes that way.
3) I'm going to reply to this mail with an alternative shorter patch. I don't have access to hyperv to test it under an actual valgrind run, but it compiled for me. Can you please run it through your test setup to see if it solves the issues you were initially trying to address?
Yes I can.
De : Eric Blake [mailto:eblake@redhat.com] Envoyé : mercredi 8 octobre 2014 18:24 À : Yves Vinter; libvir-list@redhat.com Objet : Re: [libvirt] [PATCH 01/21] Added missing virBufferFreeAndReset on the query buffer to free some memory
On 10/08/2014 06:33 AM, Yves Vinter wrote:
From: yvinter <yves.vinter@bull.net>
Your git config is incorrect;...
It's okay, and even preferred, to interleave your replies (as I'm doing here), rather than top-posting. It makes it easier to follow the conversation when it is interleaved. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 10/10/2014 07:00 AM, Eric Blake wrote:
Right; there are potential paths through which the query buffer may be not released (in hypervEnumAndPull).
Not if you take my alternate proposed 1/21 patch.
For safety, I systematically added this line for any local virBuffer variable.
I'd rather fix the one function than have to fix every caller.
Hmm, did you even see my alternative proposal? I may have forgotten to cc you: https://www.redhat.com/archives/libvir-list/2014-October/msg00284.html -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

-----Message d'origine----- De : Eric Blake [mailto:eblake@redhat.com] Envoyé : vendredi 10 octobre 2014 15:02 À : Yves Vinter; libvir-list@redhat.com Objet : Re: [libvirt] [PATCH 01/21] Added missing virBufferFreeAndReset on the query buffer to free some memory
On 10/10/2014 07:00 AM, Eric Blake wrote:
Right; there are potential paths through which the query buffer may be not released (in hypervEnumAndPull).
Not if you take my alternate proposed 1/21 patch.
For safety, I systematically added this line for any local virBuffer variable.
I'd rather fix the one function than have to fix every caller.
Hmm, did you even see my alternative proposal? I may have forgotten to cc you:
No I didn't. OK. I will test your alternative proposal; thanks.
https://www.redhat.com/archives/libvir-list/2014-October/msg00284.html
-- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

The function hypervEnumAndPull consumes query on success, but leaked it on failure. Rather than having to change all callers (many of them indirect callers through the generated hypervGetMsvmComputerSystemList), it was easier to just guarantee that the buffer is cleaned on return from the function. Reported by Yves Vinter. * src/hyperv/hyperv_wmi.c (hypervEnumAndPull): Don't leak query on failure. Signed-off-by: Eric Blake <eblake@redhat.com> --- src/hyperv/hyperv_wmi.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index acb705c..3027601 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -2,6 +2,7 @@ * hyperv_wmi.c: general WMI over WSMAN related functions and structures for * managing Microsoft Hyper-V hosts * + * Copyright (C) 2014 Red Hat, Inc. * Copyright (C) 2011 Matthias Bolte <matthias.bolte@googlemail.com> * Copyright (C) 2009 Michael Sievers <msievers83@googlemail.com> * @@ -105,6 +106,7 @@ hyperyVerifyResponse(WsManClient *client, WsXmlDocH response, * Object */ +/* This function guarantees that query is freed, even on failure */ int hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root, XmlSerializerInfo *serializerInfo, const char *resourceUri, @@ -123,25 +125,28 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root, XML_TYPE_PTR data = NULL; hypervObject *object; - if (list == NULL || *list != NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + if (virBufferCheckError(query) < 0) { + virBufferFreeAndReset(query); return -1; } - - if (virBufferCheckError(query) < 0) - return -1; - - serializerContext = wsmc_get_serialization_context(priv->client); - - options = wsmc_options_init(); - - if (options == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Could not initialize options")); - goto cleanup; - } - query_string = virBufferContentAndReset(query); + + if (list == NULL || *list != NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + VIR_FREE(query_string); + return -1; + } + + serializerContext = wsmc_get_serialization_context(priv->client); + + options = wsmc_options_init(); + + if (options == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not initialize options")); + goto cleanup; + } + filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string); if (filter == NULL) { -- 1.9.3

On 10/08/2014 10:29 AM, Eric Blake wrote:
The function hypervEnumAndPull consumes query on success, but leaked it on failure. Rather than having to change all callers (many of them indirect callers through the generated hypervGetMsvmComputerSystemList), it was easier to just guarantee that the buffer is cleaned on return from the function.
Reported by Yves Vinter.
* src/hyperv/hyperv_wmi.c (hypervEnumAndPull): Don't leak query on failure.
Signed-off-by: Eric Blake <eblake@redhat.com> --- src/hyperv/hyperv_wmi.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-)
Yves gave me an off-list ACK for this patch, so I've pushed it. With this in place, it would be easier if you rebase your remaining patches on top of this and repost them for review. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

From: Yves Vinter <yves.vinter@bull.net> This serie of 21 patches implements new functionalities in the libvirt hyperv driver. PATCH 01/21: hyperv: avoid query memleaks on failure PATCH 02/21: hyperv: implementation of virConnectGetVersion PATCH 03/21: hyperv: implementation of virConnectGetCapabilities PATCH 04/21: hyperv: implementation of virDomainGetVcpus and virConnectGetMaxVcpus PATCH 05/21: hyperv: implementation of virNodeGetFreeMemory PATCH 06/21: hyperv: implementation of virDomainShutdown and virDomainShutdownFlags PATCH 07/21: hyperv: implementation of virDomainGetSchedulerType and virDomainGetSchedulerParameters PATCH 08/21: hyperv: implementation of virNetworkLookupByName PATCH 09/21: hyperv: implementation of virNetworkGetXMLDesc PATCH 10/21: hyperv: implementation of virConnectNumOfNetworks and virConnectListNetworks PATCH 11/21: hyperv: implementation of virConnectNumOfDefinedNetworks and virConnectListDefinedNetworks PATCH 12/21: hyperv: implementation of hypervInvokeMethod to handle complex parameters PATCH 13/21: hyperv: implementation of virDomainSetAutostart and virDomainGetAutostart PATCH 14/21: hyperv: implementation of virDomainSetMaxMemory PATCH 15/21: hyperv: implementation of virDomainSetMemory and virDomainSetMemoryFlags PATCH 16/21: hyperv: implementation of virDomainSetVcpus and virDomainSetVcpusFlags PATCH 17/21: hyperv: implementation of virDomainUndefine and virDomainUndefineFlags PATCH 18/21: hyperv: implementation of internal function hypervDomainAttachDisk PATCH 19/21: hyperv: implementation of internal function hypervDomainAttachNetwork PATCH 20/21: hyperv: implementation of virDomainAttachDevice and virDomainAttachDeviceFlags PATCH 21/21: hyperv: implementation of virDomainDefineXML and virDomainCreateXML A first version of this serie of patch has been submitted; the first 3 patches have already been reviewed by Eric. Based on the remarks after this 3 reviews, I will produce a V2 for the whole set of patches. I suggest to submit V2 versions patch after patch, only after the previous one has been approved and pushed in the main branch. Patch V2 01/21 has already been pushed by Eric. I've post patch V2 02/21 and wait for any new comment or the final approval. Once approved, I will post patch V2 03/21, and so on... Thanks, Yves.
participants (2)
-
Eric Blake
-
Yves Vinter