[PATCH v3 0/9] more Hyper-V APIs

This set of patches adds several new APIs and fixes several others. Changes since v2: * adapted to all of Michal's recent changes * enabled usage of g_autoptr for hypervInvokeParamsList * avoid overwriting errors from hypervGetWmiClass() * use switch statements instead of if for v1/v2 parameter differences * added a helper function for domainReboot and domainReset * removed translation for the shutdown reason * changed the name of the constant for domainManagedSave on v2 to reflect the wording in Microsoft's documentation Matt Coleman (9): hyperv: enable usage of g_autoptr for hypervInvokeParamsList hyperv: avoid overwriting errors from hypervGetWmiClass() hyperv: implement domainSetAutostart hyperv: implement nodeGetFreeMemory hyperv: implement domainReboot and domainReset hyperv: implement domainShutdown and domainShutdownFlags hyperv: fix domainSuspend and domainResume on Hyper-V V2 hyperv: fix domainManagedSave on Hyper-V V2 news: more Hyper-V APIs NEWS.rst | 7 +- src/hyperv/hyperv_driver.c | 353 ++++++++++++++++++++++---- src/hyperv/hyperv_wmi.h | 1 + src/hyperv/hyperv_wmi_classes.h | 3 + src/hyperv/hyperv_wmi_generator.input | 78 ++++++ 5 files changed, 391 insertions(+), 51 deletions(-) -- 2.27.0

Signed-off-by: Matt Coleman <matt@datto.com> --- src/hyperv/hyperv_driver.c | 14 +++++--------- src/hyperv/hyperv_wmi.h | 1 + 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 9ec2b879fc..8f0cccdacd 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1619,7 +1619,7 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int codeset, Msvm_ComputerSystem *computerSystem = NULL; Msvm_Keyboard *keyboard = NULL; g_auto(virBuffer) query = VIR_BUFFER_INITIALIZER; - hypervInvokeParamsListPtr params = NULL; + g_autoptr(hypervInvokeParamsList) params = NULL; char keycodeStr[VIR_INT64_STR_BUFLEN]; virCheckFlags(0, -1); @@ -1672,10 +1672,8 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int codeset, goto cleanup; } - if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0) { - hypervFreeInvokeParams(params); + if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0) goto cleanup; - } if (hypervInvokeMethod(priv, ¶ms, NULL) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not press key %d"), @@ -1699,10 +1697,8 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int codeset, goto cleanup; } - if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0) { - hypervFreeInvokeParams(params); + if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0) goto cleanup; - } if (hypervInvokeMethod(priv, ¶ms, NULL) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not release key %s"), @@ -1730,7 +1726,7 @@ hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory, char uuid_string[VIR_UUID_STRING_BUFLEN]; hypervPrivate *priv = domain->conn->privateData; char *memory_str = NULL; - hypervInvokeParamsListPtr params = NULL; + g_autoptr(hypervInvokeParamsList) params = NULL; unsigned long memory_mb = VIR_ROUND_UP(VIR_DIV_UP(memory, 1024), 2); Msvm_VirtualSystemSettingData *vssd = NULL; Msvm_MemorySettingData *memsd = NULL; @@ -1814,7 +1810,7 @@ hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory, VIR_FREE(memory_str); hypervFreeObject(priv, (hypervObject *)vssd); hypervFreeObject(priv, (hypervObject *)memsd); - hypervFreeInvokeParams(params); + return result; } diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h index fa8e48a70e..3a623e99fa 100644 --- a/src/hyperv/hyperv_wmi.h +++ b/src/hyperv/hyperv_wmi.h @@ -135,6 +135,7 @@ hypervInvokeParamsListPtr hypervCreateInvokeParamsList(hypervPrivate *priv, const char *method, const char *selector, hypervWmiClassInfoListPtr obj); void hypervFreeInvokeParams(hypervInvokeParamsListPtr params); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(hypervInvokeParamsList, hypervFreeInvokeParams); int hypervAddSimpleParam(hypervInvokeParamsListPtr params, const char *name, const char *value); -- 2.27.0

Signed-off-by: Matt Coleman <matt@datto.com> --- src/hyperv/hyperv_driver.c | 64 +++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 8f0cccdacd..091b77ebc4 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -73,8 +73,10 @@ hypervGetProcessorsByName(hypervPrivate *priv, const char *name, "ResultClass = Win32_Processor", name); - if (hypervGetWmiClass(Win32_Processor, processorList) < 0 || - !processorList) { + if (hypervGetWmiClass(Win32_Processor, processorList) < 0) + return -1; + + if (!processorList) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not look up processor(s) on '%s'"), name); @@ -92,8 +94,10 @@ hypervGetActiveVirtualSystemList(hypervPrivate *priv, "WHERE " MSVM_COMPUTERSYSTEM_WQL_VIRTUAL "AND " MSVM_COMPUTERSYSTEM_WQL_ACTIVE), 0 }; - if (hypervGetWmiClass(Msvm_ComputerSystem, computerSystemList) < 0 || - !*computerSystemList) { + if (hypervGetWmiClass(Msvm_ComputerSystem, computerSystemList) < 0) + return -1; + + if (!*computerSystemList) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not look up active virtual machines")); return -1; @@ -111,8 +115,10 @@ hypervGetInactiveVirtualSystemList(hypervPrivate *priv, "WHERE " MSVM_COMPUTERSYSTEM_WQL_VIRTUAL "AND " MSVM_COMPUTERSYSTEM_WQL_INACTIVE), 0 }; - if (hypervGetWmiClass(Msvm_ComputerSystem, computerSystemList) < 0 || - !*computerSystemList) { + if (hypervGetWmiClass(Msvm_ComputerSystem, computerSystemList) < 0) + return -1; + + if (!*computerSystemList) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not look up inactive virtual machines")); return -1; @@ -127,8 +133,10 @@ hypervGetPhysicalSystemList(hypervPrivate *priv, { g_auto(virBuffer) query = { g_string_new(WIN32_COMPUTERSYSTEM_WQL_SELECT), 0 }; - if (hypervGetWmiClass(Win32_ComputerSystem, computerSystemList) < 0 || - !*computerSystemList) { + if (hypervGetWmiClass(Win32_ComputerSystem, computerSystemList) < 0) + return -1; + + if (!*computerSystemList) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not look up Win32_ComputerSystem")); return -1; @@ -148,11 +156,8 @@ hypervGetVirtualSystemByID(hypervPrivate *priv, int id, "AND ProcessID = %d", id); - if (hypervGetWmiClass(Msvm_ComputerSystem, computerSystemList) < 0) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("Could not look up virtual system with ID %d"), id); + if (hypervGetWmiClass(Msvm_ComputerSystem, computerSystemList) < 0) return -1; - } if (*computerSystemList == NULL) { virReportError(VIR_ERR_NO_DOMAIN, _("No domain with ID %d"), id); @@ -173,12 +178,8 @@ hypervGetVirtualSystemByUUID(hypervPrivate *priv, const char *uuid, "AND Name = \"%s\"", uuid); - if (hypervGetWmiClass(Msvm_ComputerSystem, computerSystemList) < 0) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("Could not look up virtual system with UUID '%s'"), - uuid); + if (hypervGetWmiClass(Msvm_ComputerSystem, computerSystemList) < 0) return -1; - } if (*computerSystemList == NULL) { virReportError(VIR_ERR_NO_DOMAIN, @@ -201,11 +202,8 @@ hypervGetVirtualSystemByName(hypervPrivate *priv, const char *name, "AND ElementName = \"%s\"", name); - if (hypervGetWmiClass(Msvm_ComputerSystem, computerSystemList) < 0) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("Could not look up virtual system named '%s'"), name); + if (hypervGetWmiClass(Msvm_ComputerSystem, computerSystemList) < 0) return -1; - } if (*computerSystemList == NULL) { virReportError(VIR_ERR_NO_DOMAIN, @@ -227,8 +225,10 @@ hypervGetVSSDFromUUID(hypervPrivate *priv, const char *uuid, "ResultClass = Msvm_VirtualSystemSettingData", uuid); - if (hypervGetWmiClass(Msvm_VirtualSystemSettingData, data) < 0 || - !*data) { + if (hypervGetWmiClass(Msvm_VirtualSystemSettingData, data) < 0) + return -1; + + if (!*data) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not look up virtual system setting data with UUID '%s'"), uuid); @@ -249,8 +249,10 @@ hypervGetProcSDByVSSDInstanceId(hypervPrivate *priv, const char *id, "ResultClass = Msvm_ProcessorSettingData", id); - if (hypervGetWmiClass(Msvm_ProcessorSettingData, data) < 0 || - !*data) { + if (hypervGetWmiClass(Msvm_ProcessorSettingData, data) < 0) + return -1; + + if (!*data) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not look up processor setting data with virtual system instance ID '%s'"), id); @@ -271,8 +273,10 @@ hypervGetMemSDByVSSDInstanceId(hypervPrivate *priv, const char *id, "ResultClass = Msvm_MemorySettingData", id); - if (hypervGetWmiClass(Msvm_MemorySettingData, data) < 0 || - !*data) { + if (hypervGetWmiClass(Msvm_MemorySettingData, data) < 0) + return -1; + + if (!*data) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not look up memory setting data with virtual system instance ID '%s'"), id); @@ -548,8 +552,10 @@ hypervConnectGetVersion(virConnectPtr conn, unsigned long *version) g_auto(virBuffer) query = { g_string_new(WIN32_OPERATINGSYSTEM_WQL_SELECT), 0 }; unsigned int major, minor, micro; - if (hypervGetWmiClass(Win32_OperatingSystem, &os) < 0 || - !os) { + if (hypervGetWmiClass(Win32_OperatingSystem, &os) < 0) + goto cleanup; + + if (!os) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not get version information for host %s"), conn->uri->server); -- 2.27.0

Co-authored-by: Sri Ramanujam <sramanujam@datto.com> Signed-off-by: Matt Coleman <matt@datto.com> --- src/hyperv/hyperv_driver.c | 85 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 091b77ebc4..1521cf4244 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1316,6 +1316,90 @@ hypervDomainGetAutostart(virDomainPtr domain, int *autostart) +static int +hypervDomainSetAutostart(virDomainPtr domain, int autostart) +{ + int result = -1; + char uuid_string[VIR_UUID_STRING_BUFLEN]; + hypervPrivate *priv = domain->conn->privateData; + Msvm_VirtualSystemSettingData *vssd = NULL; + g_autoptr(hypervInvokeParamsList) params = NULL; + g_auto(virBuffer) eprQuery = VIR_BUFFER_INITIALIZER; + g_autoptr(virHashTable) autostartParam = NULL; + const char *methodName = NULL; + hypervWmiClassInfoListPtr embeddedParamClass = NULL; + const char *enabledValue = NULL, *disabledValue = NULL; + const char *embeddedParamName = NULL; + + switch (priv->wmiVersion) { + case HYPERV_WMI_VERSION_V1: + methodName = "ModifyVirtualSystem"; + embeddedParamClass = Msvm_VirtualSystemGlobalSettingData_WmiInfo; + enabledValue = "2"; + disabledValue = "0"; + embeddedParamName = "SystemSettingData"; + break; + case HYPERV_WMI_VERSION_V2: + methodName = "ModifySystemSettings"; + embeddedParamClass = Msvm_VirtualSystemSettingData_WmiInfo; + enabledValue = "4"; + disabledValue = "2"; + embeddedParamName = "SystemSettings"; + break; + } + + virUUIDFormat(domain->uuid, uuid_string); + + if (hypervGetVSSDFromUUID(priv, uuid_string, &vssd) < 0) + goto cleanup; + + params = hypervCreateInvokeParamsList(priv, methodName, + MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR, + Msvm_VirtualSystemManagementService_WmiInfo); + + if (!params) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create params")); + goto cleanup; + } + + if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) { + virBufferEscapeSQL(&eprQuery, + MSVM_COMPUTERSYSTEM_WQL_SELECT "WHERE Name = '%s'", + uuid_string); + + if (hypervAddEprParam(params, "ComputerSystem", priv, &eprQuery, + Msvm_ComputerSystem_WmiInfo) < 0) + goto cleanup; + } + + autostartParam = hypervCreateEmbeddedParam(priv, embeddedParamClass); + + if (hypervSetEmbeddedProperty(autostartParam, "AutomaticStartupAction", + autostart ? enabledValue : disabledValue) < 0) + goto cleanup; + + if (hypervSetEmbeddedProperty(autostartParam, "InstanceID", vssd->data.common->InstanceID) < 0) + goto cleanup; + + if (hypervAddEmbeddedParam(params, priv, embeddedParamName, &autostartParam, + embeddedParamClass) < 0) + goto cleanup; + + if (hypervInvokeMethod(priv, ¶ms, NULL) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set autostart")); + goto cleanup; + } + + result = 0; + + cleanup: + hypervFreeObject(priv, (hypervObject *)vssd); + + return result; +} + + + static int hypervConnectIsEncrypted(virConnectPtr conn) { @@ -1857,6 +1941,7 @@ static virHypervisorDriver hypervHypervisorDriver = { .domainCreate = hypervDomainCreate, /* 0.9.5 */ .domainCreateWithFlags = hypervDomainCreateWithFlags, /* 0.9.5 */ .domainGetAutostart = hypervDomainGetAutostart, /* 6.9.0 */ + .domainSetAutostart = hypervDomainSetAutostart, /* 6.9.0 */ .connectIsEncrypted = hypervConnectIsEncrypted, /* 0.9.5 */ .connectIsSecure = hypervConnectIsSecure, /* 0.9.5 */ .domainIsActive = hypervDomainIsActive, /* 0.9.5 */ -- 2.27.0

On 10/21/20 10:46 AM, Matt Coleman wrote:
Co-authored-by: Sri Ramanujam <sramanujam@datto.com> Signed-off-by: Matt Coleman <matt@datto.com> --- src/hyperv/hyperv_driver.c | 85 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+)
diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 091b77ebc4..1521cf4244 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1316,6 +1316,90 @@ hypervDomainGetAutostart(virDomainPtr domain, int *autostart)
+static int +hypervDomainSetAutostart(virDomainPtr domain, int autostart) +{ + int result = -1; + char uuid_string[VIR_UUID_STRING_BUFLEN]; + hypervPrivate *priv = domain->conn->privateData; + Msvm_VirtualSystemSettingData *vssd = NULL; + g_autoptr(hypervInvokeParamsList) params = NULL; + g_auto(virBuffer) eprQuery = VIR_BUFFER_INITIALIZER; + g_autoptr(virHashTable) autostartParam = NULL; + const char *methodName = NULL; + hypervWmiClassInfoListPtr embeddedParamClass = NULL; + const char *enabledValue = NULL, *disabledValue = NULL; + const char *embeddedParamName = NULL; + + switch (priv->wmiVersion) { + case HYPERV_WMI_VERSION_V1: + methodName = "ModifyVirtualSystem"; + embeddedParamClass = Msvm_VirtualSystemGlobalSettingData_WmiInfo; + enabledValue = "2"; + disabledValue = "0"; + embeddedParamName = "SystemSettingData"; + break; + case HYPERV_WMI_VERSION_V2: + methodName = "ModifySystemSettings"; + embeddedParamClass = Msvm_VirtualSystemSettingData_WmiInfo; + enabledValue = "4"; + disabledValue = "2"; + embeddedParamName = "SystemSettings"; + break; + } + + virUUIDFormat(domain->uuid, uuid_string); + + if (hypervGetVSSDFromUUID(priv, uuid_string, &vssd) < 0) + goto cleanup; + + params = hypervCreateInvokeParamsList(priv, methodName, + MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR, + Msvm_VirtualSystemManagementService_WmiInfo); + + if (!params) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create params")); + goto cleanup; + } + + if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) { + virBufferEscapeSQL(&eprQuery, + MSVM_COMPUTERSYSTEM_WQL_SELECT "WHERE Name = '%s'", + uuid_string); + + if (hypervAddEprParam(params, "ComputerSystem", priv, &eprQuery, + Msvm_ComputerSystem_WmiInfo) < 0) + goto cleanup; + } + + autostartParam = hypervCreateEmbeddedParam(priv, embeddedParamClass); + + if (hypervSetEmbeddedProperty(autostartParam, "AutomaticStartupAction", + autostart ? enabledValue : disabledValue) < 0) + goto cleanup; + + if (hypervSetEmbeddedProperty(autostartParam, "InstanceID", vssd->data.common->InstanceID) < 0) + goto cleanup; + + if (hypervAddEmbeddedParam(params, priv, embeddedParamName, &autostartParam, + embeddedParamClass) < 0)
Nit pick - when you have to break an if() condition like this then the second line should be longer than the first one. Like this: if (hypervAddEmbeddedParam(params, priv, embeddedParamName, &autostartParam, embeddedParamClass) < 0)
+ goto cleanup; + + if (hypervInvokeMethod(priv, ¶ms, NULL) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set autostart"));
No need to report error here because hypervInvokeMethod() already reported one for us. And unfortunately we don't have stacked error messages, so this would just overwrite the error reported earlier. Michal

On Oct 21, 2020, at 7:01 AM, Michal Privoznik <mprivozn@redhat.com> wrote:
On 10/21/20 10:46 AM, Matt Coleman wrote:
+ if (hypervInvokeMethod(priv, ¶ms, NULL) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set autostart"));
No need to report error here because hypervInvokeMethod() already reported one for us. And unfortunately we don't have stacked error messages, so this would just overwrite the error reported earlier.
I keep forgetting that this overwrites any previously-reported error. Feel free to remove this, or I can do it in a later commit. -- Matt

Co-authored-by: Sri Ramanujam <sramanujam@datto.com> Signed-off-by: Matt Coleman <matt@datto.com> --- src/hyperv/hyperv_driver.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 1521cf4244..7387be1ab7 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1400,6 +1400,33 @@ hypervDomainSetAutostart(virDomainPtr domain, int autostart) +static unsigned long long +hypervNodeGetFreeMemory(virConnectPtr conn) +{ + unsigned long long freeMemoryBytes = 0; + hypervPrivate *priv = conn->privateData; + Win32_OperatingSystem *operatingSystem = NULL; + g_auto(virBuffer) query = { g_string_new(WIN32_OPERATINGSYSTEM_WQL_SELECT), 0 }; + + if (hypervGetWmiClass(Win32_OperatingSystem, &operatingSystem) < 0) + return 0; + + if (!operatingSystem) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get free memory for host %s"), + conn->uri->server); + return 0; + } + + freeMemoryBytes = operatingSystem->data.common->FreePhysicalMemory * 1024; + + hypervFreeObject(priv, (hypervObject *)operatingSystem); + + return freeMemoryBytes; +} + + + static int hypervConnectIsEncrypted(virConnectPtr conn) { @@ -1942,6 +1969,7 @@ static virHypervisorDriver hypervHypervisorDriver = { .domainCreateWithFlags = hypervDomainCreateWithFlags, /* 0.9.5 */ .domainGetAutostart = hypervDomainGetAutostart, /* 6.9.0 */ .domainSetAutostart = hypervDomainSetAutostart, /* 6.9.0 */ + .nodeGetFreeMemory = hypervNodeGetFreeMemory, /* 6.9.0 */ .connectIsEncrypted = hypervConnectIsEncrypted, /* 0.9.5 */ .connectIsSecure = hypervConnectIsSecure, /* 0.9.5 */ .domainIsActive = hypervDomainIsActive, /* 0.9.5 */ -- 2.27.0

Co-authored-by: Sri Ramanujam <sramanujam@datto.com> Signed-off-by: Matt Coleman <matt@datto.com> --- src/hyperv/hyperv_driver.c | 38 +++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_classes.h | 1 + 2 files changed, 39 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 7387be1ab7..4bddc86273 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -286,6 +286,24 @@ hypervGetMemSDByVSSDInstanceId(hypervPrivate *priv, const char *id, return 0; } +static int +hypervRequestStateChange(virDomainPtr domain, int state) +{ + int result = -1; + hypervPrivate *priv = domain->conn->privateData; + Msvm_ComputerSystem *computerSystem = NULL; + + if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) + goto cleanup; + + result = hypervInvokeMsvmComputerSystemRequestStateChange(domain, state); + + cleanup: + hypervFreeObject(priv, (hypervObject *)computerSystem); + + return result; +} + /* @@ -923,6 +941,24 @@ hypervDomainResume(virDomainPtr domain) +static int +hypervDomainReboot(virDomainPtr domain, unsigned int flags) +{ + virCheckFlags(0, -1); + return hypervRequestStateChange(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_REBOOT); +} + + + +static int +hypervDomainReset(virDomainPtr domain, unsigned int flags) +{ + virCheckFlags(0, -1); + return hypervRequestStateChange(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_RESET); +} + + + static int hypervDomainDestroyFlags(virDomainPtr domain, unsigned int flags) { @@ -1957,6 +1993,8 @@ static virHypervisorDriver hypervHypervisorDriver = { .domainLookupByName = hypervDomainLookupByName, /* 0.9.5 */ .domainSuspend = hypervDomainSuspend, /* 0.9.5 */ .domainResume = hypervDomainResume, /* 0.9.5 */ + .domainReboot = hypervDomainReboot, /* 6.9.0 */ + .domainReset = hypervDomainReset, /* 6.9.0 */ .domainDestroy = hypervDomainDestroy, /* 0.9.5 */ .domainDestroyFlags = hypervDomainDestroyFlags, /* 0.9.5 */ .domainGetOSType = hypervDomainGetOSType, /* 0.9.5 */ diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h index d32711589a..7f4159dd8e 100644 --- a/src/hyperv/hyperv_wmi_classes.h +++ b/src/hyperv/hyperv_wmi_classes.h @@ -74,6 +74,7 @@ enum _Msvm_ComputerSystem_RequestedState { MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_ENABLED = 2, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_DISABLED = 3, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_REBOOT = 10, + MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_RESET = 11, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_PAUSED = 32768, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_SUSPENDED = 32769, }; -- 2.27.0

On 10/21/20 10:46 AM, Matt Coleman wrote:
Co-authored-by: Sri Ramanujam <sramanujam@datto.com> Signed-off-by: Matt Coleman <matt@datto.com> --- src/hyperv/hyperv_driver.c | 38 +++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_classes.h | 1 + 2 files changed, 39 insertions(+)
diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 7387be1ab7..4bddc86273 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -286,6 +286,24 @@ hypervGetMemSDByVSSDInstanceId(hypervPrivate *priv, const char *id, return 0; }
+static int +hypervRequestStateChange(virDomainPtr domain, int state) +{ + int result = -1; + hypervPrivate *priv = domain->conn->privateData; + Msvm_ComputerSystem *computerSystem = NULL; + + if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) + goto cleanup; +
Should we also check if the domain is running? That is, the same check as hypervDomainSuspend() does with @computerSystem? I can copy the check locally, before pushing.
+ result = hypervInvokeMsvmComputerSystemRequestStateChange(domain, state); + + cleanup: + hypervFreeObject(priv, (hypervObject *)computerSystem); + + return result; +} +
Michal

On Oct 21, 2020, at 7:01 AM, Michal Privoznik <mprivozn@redhat.com> wrote:
On 10/21/20 10:46 AM, Matt Coleman wrote:
+ if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) + goto cleanup; +
Should we also check if the domain is running? That is, the same check as hypervDomainSuspend() does with @computerSystem? I can copy the check locally, before pushing.
In its current form, it throws this error if you attempt to `virsh reboot` or `virsh reset` a VM that is powered off: error: Failed to reset domain Fedora Workstation error: internal error: Invocation of RequestStateChange returned an error: Invalid state for this operation (32775) If you'd prefer a friendlier error message, feel free to copy the check from hypervDomainSuspend(). -- Matt

On 10/21/20 1:10 PM, Matt Coleman wrote:
On Oct 21, 2020, at 7:01 AM, Michal Privoznik <mprivozn@redhat.com> wrote:
On 10/21/20 10:46 AM, Matt Coleman wrote:
+ if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) + goto cleanup; +
Should we also check if the domain is running? That is, the same check as hypervDomainSuspend() does with @computerSystem? I can copy the check locally, before pushing.
In its current form, it throws this error if you attempt to `virsh reboot` or `virsh reset` a VM that is powered off:
error: Failed to reset domain Fedora Workstation error: internal error: Invocation of RequestStateChange returned an error: Invalid state for this operation (32775)
If you'd prefer a friendlier error message, feel free to copy the check from hypervDomainSuspend().
My aim is to use hypervRequestStateChange() from other places (like suspend). I'll copy the check since it will make the intended change easier. Thanks, Michal

Co-authored-by: Sri Ramanujam <sramanujam@datto.com> Signed-off-by: Matt Coleman <matt@datto.com> --- src/hyperv/hyperv_driver.c | 77 ++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.input | 78 +++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 4bddc86273..791f34444d 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -941,6 +941,81 @@ hypervDomainResume(virDomainPtr domain) +static int +hypervDomainShutdownFlags(virDomainPtr domain, unsigned int flags) +{ + int result = -1; + hypervPrivate *priv = domain->conn->privateData; + Msvm_ComputerSystem *computerSystem = NULL; + Msvm_ShutdownComponent *shutdown = NULL; + bool in_transition = false; + char uuid[VIR_UUID_STRING_BUFLEN]; + g_auto(virBuffer) query = VIR_BUFFER_INITIALIZER; + g_autoptr(hypervInvokeParamsList) params = NULL; + g_autofree char *selector = NULL; + + virCheckFlags(0, -1); + + virUUIDFormat(domain->uuid, uuid); + + 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 in state transition")); + goto cleanup; + } + + virBufferEscapeSQL(&query, MSVM_SHUTDOWNCOMPONENT_WQL_SELECT "WHERE SystemName = '%s'", uuid); + + if (hypervGetWmiClass(Msvm_ShutdownComponent, &shutdown) < 0 || + !shutdown) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("Could not get Msvm_ShutdownComponent for domain with UUID '%s'"), + uuid); + goto cleanup; + } + + selector = g_strdup_printf("CreationClassName=\"Msvm_ShutdownComponent\"&DeviceID=\"%s\"&" + "SystemCreationClassName=\"Msvm_ComputerSystem\"&SystemName=\"%s\"", + shutdown->data.common->DeviceID, uuid); + + params = hypervCreateInvokeParamsList(priv, "InitiateShutdown", selector, + Msvm_ShutdownComponent_WmiInfo); + + hypervAddSimpleParam(params, "Force", "False"); + + /* "Reason" is not translated because the Hyper-V administrator may not + * know the libvirt user's language. They may not know English, either, + * but this makes it consistent, at least. */ + hypervAddSimpleParam(params, "Reason", "Planned shutdown via libvirt"); + + if (hypervInvokeMethod(priv, ¶ms, NULL) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not shutdown domain with UUID '%s'"), uuid); + goto cleanup; + } + + result = 0; + + cleanup: + hypervFreeObject(priv, (hypervObject *) computerSystem); + hypervFreeObject(priv, (hypervObject *) shutdown); + + return result; +} + + + +static int +hypervDomainShutdown(virDomainPtr domain) +{ + return hypervDomainShutdownFlags(domain, 0); +} + + + static int hypervDomainReboot(virDomainPtr domain, unsigned int flags) { @@ -1993,6 +2068,8 @@ static virHypervisorDriver hypervHypervisorDriver = { .domainLookupByName = hypervDomainLookupByName, /* 0.9.5 */ .domainSuspend = hypervDomainSuspend, /* 0.9.5 */ .domainResume = hypervDomainResume, /* 0.9.5 */ + .domainShutdown = hypervDomainShutdown, /* 6.9.0 */ + .domainShutdownFlags = hypervDomainShutdownFlags, /* 6.9.0 */ .domainReboot = hypervDomainReboot, /* 6.9.0 */ .domainReset = hypervDomainReset, /* 6.9.0 */ .domainDestroy = hypervDomainDestroy, /* 0.9.5 */ diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index bbca550790..1377138a12 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -1072,3 +1072,81 @@ class v2/Msvm_Keyboard uint16 Password boolean UnicodeSupported end + + +class Msvm_ShutdownComponent + string Caption + string Description + string ElementName + datetime InstallDate + string Name + 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 DeviceID + boolean PowerManagementSupported + uint16 PowerManagementCapabilities[] + uint16 Availability + uint16 StatusInfo + uint32 LastErrorCode + string ErrorDescription + boolean ErrorCleared + string OtherIdentifyingInfo[] + uint64 PowerOnHours + uint64 TotalPowerOnHours + string IdentifyingDescriptions[] + uint16 AdditionalAvailability[] + uint64 MaxQuiesceTime + uint16 LocationIndicator +end + + +class v2/Msvm_ShutdownComponent + string InstanceID + string Caption + string Description + string ElementName + datetime InstallDate + string Name + uint16 OperationalStatus[] + string StatusDescriptions[] + string Status + uint16 HealthState + uint16 CommunicationStatus + uint16 DetailedStatus + uint16 OperatingStatus + uint16 PrimaryStatus + uint16 EnabledState + string OtherEnabledState + uint16 RequestedState + uint16 EnabledDefault + datetime TimeOfLastStateChange + uint16 AvailableRequestedStates[] + uint16 TransitioningToState + string SystemCreationClassName + string SystemName + string CreationClassName + string DeviceID + boolean PowerManagementSupported + uint16 PowerManagementCapabilities[] + uint16 Availability + uint16 StatusInfo + uint32 LastErrorCode + string ErrorDescription + boolean ErrorCleared + string OtherIdentifyingInfo[] + uint64 PowerOnHours + uint64 TotalPowerOnHours + string IdentifyingDescriptions[] + uint16 AdditionalAvailability[] + uint64 MaxQuiesceTime +end -- 2.27.0

On 10/21/20 10:46 AM, Matt Coleman wrote:
Co-authored-by: Sri Ramanujam <sramanujam@datto.com> Signed-off-by: Matt Coleman <matt@datto.com> --- src/hyperv/hyperv_driver.c | 77 ++++++++++++++++++++++++++ src/hyperv/hyperv_wmi_generator.input | 78 +++++++++++++++++++++++++++ 2 files changed, 155 insertions(+)
diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 4bddc86273..791f34444d 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -941,6 +941,81 @@ hypervDomainResume(virDomainPtr domain)
+static int +hypervDomainShutdownFlags(virDomainPtr domain, unsigned int flags) +{ + int result = -1; + hypervPrivate *priv = domain->conn->privateData; + Msvm_ComputerSystem *computerSystem = NULL; + Msvm_ShutdownComponent *shutdown = NULL; + bool in_transition = false; + char uuid[VIR_UUID_STRING_BUFLEN]; + g_auto(virBuffer) query = VIR_BUFFER_INITIALIZER; + g_autoptr(hypervInvokeParamsList) params = NULL; + g_autofree char *selector = NULL; + + virCheckFlags(0, -1); + + virUUIDFormat(domain->uuid, uuid); + + 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 in state transition")); + goto cleanup; + } + + virBufferEscapeSQL(&query, MSVM_SHUTDOWNCOMPONENT_WQL_SELECT "WHERE SystemName = '%s'", uuid); + + if (hypervGetWmiClass(Msvm_ShutdownComponent, &shutdown) < 0 || + !shutdown) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("Could not get Msvm_ShutdownComponent for domain with UUID '%s'"), + uuid); + goto cleanup; + } + + selector = g_strdup_printf("CreationClassName=\"Msvm_ShutdownComponent\"&DeviceID=\"%s\"&" + "SystemCreationClassName=\"Msvm_ComputerSystem\"&SystemName=\"%s\"", + shutdown->data.common->DeviceID, uuid); + + params = hypervCreateInvokeParamsList(priv, "InitiateShutdown", selector, + Msvm_ShutdownComponent_WmiInfo); + + hypervAddSimpleParam(params, "Force", "False"); + + /* "Reason" is not translated because the Hyper-V administrator may not + * know the libvirt user's language. They may not know English, either, + * but this makes it consistent, at least. */ + hypervAddSimpleParam(params, "Reason", "Planned shutdown via libvirt"); + + if (hypervInvokeMethod(priv, ¶ms, NULL) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not shutdown domain with UUID '%s'"), uuid);
Again, no need to overwrite the error message.
+ goto cleanup; + } + + result = 0; + + cleanup: + hypervFreeObject(priv, (hypervObject *) computerSystem); + hypervFreeObject(priv, (hypervObject *) shutdown); + + return result; +}
Michal

On Oct 21, 2020, at 7:01 AM, Michal Privoznik <mprivozn@redhat.com> wrote:
On 10/21/20 10:46 AM, Matt Coleman wrote:
+ if (hypervInvokeMethod(priv, ¶ms, NULL) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not shutdown domain with UUID '%s'"), uuid);
Again, no need to overwrite the error message.
As I mentioned in the other thread, feel free to remove this line, or I can fix it in a separate commit. -- Matt

Signed-off-by: Matt Coleman <matt@datto.com> --- src/hyperv/hyperv_driver.c | 34 ++++++++++++++++++++++++--------- src/hyperv/hyperv_wmi_classes.h | 1 + 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 791f34444d..4c70af6496 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -891,19 +891,26 @@ hypervDomainSuspend(virDomainPtr domain) int result = -1; hypervPrivate *priv = domain->conn->privateData; Msvm_ComputerSystem *computerSystem = NULL; + int requestedState; + + switch (priv->wmiVersion) { + case HYPERV_WMI_VERSION_V1: + requestedState = MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_PAUSED; + break; + case HYPERV_WMI_VERSION_V2: + requestedState = MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_QUIESCE; + break; + } if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) goto cleanup; - if (computerSystem->data.common->EnabledState != - MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("Domain is not active")); + if (computerSystem->data.common->EnabledState != MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not active")); goto cleanup; } - result = hypervInvokeMsvmComputerSystemRequestStateChange - (domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_PAUSED); + result = hypervInvokeMsvmComputerSystemRequestStateChange(domain, requestedState); cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); @@ -919,12 +926,21 @@ hypervDomainResume(virDomainPtr domain) int result = -1; hypervPrivate *priv = domain->conn->privateData; Msvm_ComputerSystem *computerSystem = NULL; + int expectedState; + + switch (priv->wmiVersion) { + case HYPERV_WMI_VERSION_V1: + expectedState = MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSED; + break; + case HYPERV_WMI_VERSION_V2: + expectedState = MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_QUIESCE; + break; + } if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) - goto cleanup; + return -1; - if (computerSystem->data.common->EnabledState != - MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSED) { + if (computerSystem->data.common->EnabledState != expectedState) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not paused")); goto cleanup; diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h index 7f4159dd8e..0074d8889e 100644 --- a/src/hyperv/hyperv_wmi_classes.h +++ b/src/hyperv/hyperv_wmi_classes.h @@ -73,6 +73,7 @@ enum _Msvm_ComputerSystem_EnabledState { enum _Msvm_ComputerSystem_RequestedState { MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_ENABLED = 2, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_DISABLED = 3, + MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_QUIESCE = 9, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_REBOOT = 10, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_RESET = 11, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_PAUSED = 32768, -- 2.27.0

On Oct 21, 2020, at 4:46 AM, Matt Coleman <mcoleman@datto.com> wrote:
+ int requestedState;
This caused GitLab CI failures that didn't happen on my local builds. This should be squashed in... =================================================================== --- src/hyperv/hyperv_driver.c (revision 156ebef03c01146a0bab294a0db8f3bd2f707d96) +++ src/hyperv/hyperv_driver.c (revision 37c994da34f77d41a06f75e4d1272b671dd16b94) @@ -891,7 +891,7 @@ int result = -1; hypervPrivate *priv = domain->conn->privateData; Msvm_ComputerSystem *computerSystem = NULL; - int requestedState; + int requestedState = -1; /* dummy value: this must be set later in the function */ switch (priv->wmiVersion) { case HYPERV_WMI_VERSION_V1: @@ -926,7 +926,7 @@ int result = -1; hypervPrivate *priv = domain->conn->privateData; Msvm_ComputerSystem *computerSystem = NULL; - int expectedState; + int expectedState = -1; /* dummy value: this must be set later in the function */ switch (priv->wmiVersion) { case HYPERV_WMI_VERSION_V1:

On 10/21/20 11:40 AM, Matt Coleman wrote:
On Oct 21, 2020, at 4:46 AM, Matt Coleman <mcoleman@datto.com> wrote:
+ int requestedState;
This caused GitLab CI failures that didn't happen on my local builds.
This should be squashed in... =================================================================== --- src/hyperv/hyperv_driver.c (revision 156ebef03c01146a0bab294a0db8f3bd2f707d96) +++ src/hyperv/hyperv_driver.c (revision 37c994da34f77d41a06f75e4d1272b671dd16b94) @@ -891,7 +891,7 @@ int result = -1; hypervPrivate *priv = domain->conn->privateData; Msvm_ComputerSystem *computerSystem = NULL; - int requestedState; + int requestedState = -1; /* dummy value: this must be set later in the function */
switch (priv->wmiVersion) { case HYPERV_WMI_VERSION_V1: @@ -926,7 +926,7 @@ int result = -1; hypervPrivate *priv = domain->conn->privateData; Msvm_ComputerSystem *computerSystem = NULL; - int expectedState; + int expectedState = -1; /* dummy value: this must be set later in the function */
switch (priv->wmiVersion) { case HYPERV_WMI_VERSION_V1:
I don't think these comments are necessary. All init values are dummy and must be set later in the function :-) Michal

Signed-off-by: Matt Coleman <matt@datto.com> --- src/hyperv/hyperv_driver.c | 13 +++++++++++-- src/hyperv/hyperv_wmi_classes.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 4c70af6496..a077146e35 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1643,6 +1643,16 @@ hypervDomainManagedSave(virDomainPtr domain, unsigned int flags) hypervPrivate *priv = domain->conn->privateData; Msvm_ComputerSystem *computerSystem = NULL; bool in_transition = false; + int requestedState; + + switch (priv->wmiVersion) { + case HYPERV_WMI_VERSION_V1: + requestedState = MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_SUSPENDED; + break; + case HYPERV_WMI_VERSION_V2: + requestedState = MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_OFFLINE; + break; + } virCheckFlags(0, -1); @@ -1656,8 +1666,7 @@ hypervDomainManagedSave(virDomainPtr domain, unsigned int flags) goto cleanup; } - result = hypervInvokeMsvmComputerSystemRequestStateChange - (domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_SUSPENDED); + result = hypervInvokeMsvmComputerSystemRequestStateChange(domain, requestedState); cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h index 0074d8889e..b9d8dfcf38 100644 --- a/src/hyperv/hyperv_wmi_classes.h +++ b/src/hyperv/hyperv_wmi_classes.h @@ -73,6 +73,7 @@ enum _Msvm_ComputerSystem_EnabledState { enum _Msvm_ComputerSystem_RequestedState { MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_ENABLED = 2, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_DISABLED = 3, + MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_OFFLINE = 6, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_QUIESCE = 9, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_REBOOT = 10, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_RESET = 11, -- 2.27.0

On Oct 21, 2020, at 4:46 AM, Matt Coleman <mcoleman@datto.com> wrote:
+ int requestedState;
This caused GitLab CI failures that didn't happen on my local builds. This should be squashed in... =================================================================== --- src/hyperv/hyperv_driver.c (revision 4839b7ab5dbd1240773cad00edd57b511b3db286) +++ src/hyperv/hyperv_driver.c (revision bb65d324c00d7d4f8a4102f98343af2139d4ef45) @@ -1643,7 +1643,7 @@ hypervPrivate *priv = domain->conn->privateData; Msvm_ComputerSystem *computerSystem = NULL; bool in_transition = false; - int requestedState; + int requestedState = -1; /* dummy value: this must be set later in the function */ switch (priv->wmiVersion) { case HYPERV_WMI_VERSION_V1:

Signed-off-by: Matt Coleman <matt@datto.com> --- NEWS.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/NEWS.rst b/NEWS.rst index bc35458f38..d0454b7840 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -22,8 +22,11 @@ v6.9.0 (unreleased) * hyperv: implement new APIs The ``virConnectGetCapabilities()``, ``virConnectGetMaxVcpus()``, - ``virConnectGetVersion()``, and ``virDomainGetAutostart()`` APIs have been - implemented in the Hyper-V driver. + ``virConnectGetVersion()``, ``virDomainGetAutostart()``, + ``virDomainSetAutostart()``, ``virNodeGetFreeMemory()``, + ``virDomainReboot()``, ``virDomainReset()``, ``virDomainShutdown()``, and + ``virDomainShutdownFlags()`` APIs have been implemented in the Hyper-V + driver. * bhyve: implement virtio-9p filesystem support -- 2.27.0

On 10/21/20 10:46 AM, Matt Coleman wrote:
This set of patches adds several new APIs and fixes several others.
Changes since v2: * adapted to all of Michal's recent changes * enabled usage of g_autoptr for hypervInvokeParamsList * avoid overwriting errors from hypervGetWmiClass() * use switch statements instead of if for v1/v2 parameter differences * added a helper function for domainReboot and domainReset * removed translation for the shutdown reason * changed the name of the constant for domainManagedSave on v2 to reflect the wording in Microsoft's documentation
Matt Coleman (9): hyperv: enable usage of g_autoptr for hypervInvokeParamsList hyperv: avoid overwriting errors from hypervGetWmiClass() hyperv: implement domainSetAutostart hyperv: implement nodeGetFreeMemory hyperv: implement domainReboot and domainReset hyperv: implement domainShutdown and domainShutdownFlags hyperv: fix domainSuspend and domainResume on Hyper-V V2 hyperv: fix domainManagedSave on Hyper-V V2 news: more Hyper-V APIs
NEWS.rst | 7 +- src/hyperv/hyperv_driver.c | 353 ++++++++++++++++++++++---- src/hyperv/hyperv_wmi.h | 1 + src/hyperv/hyperv_wmi_classes.h | 3 + src/hyperv/hyperv_wmi_generator.input | 78 ++++++ 5 files changed, 391 insertions(+), 51 deletions(-)
Patches look good. But please reply to my question in 5/9 so that I can push. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal

On 10/21/20 1:01 PM, Michal Privoznik wrote:
On 10/21/20 10:46 AM, Matt Coleman wrote:
This set of patches adds several new APIs and fixes several others.
Changes since v2: * adapted to all of Michal's recent changes * enabled usage of g_autoptr for hypervInvokeParamsList * avoid overwriting errors from hypervGetWmiClass() * use switch statements instead of if for v1/v2 parameter differences * added a helper function for domainReboot and domainReset * removed translation for the shutdown reason * changed the name of the constant for domainManagedSave on v2 to reflect the wording in Microsoft's documentation
Matt Coleman (9): hyperv: enable usage of g_autoptr for hypervInvokeParamsList hyperv: avoid overwriting errors from hypervGetWmiClass() hyperv: implement domainSetAutostart hyperv: implement nodeGetFreeMemory hyperv: implement domainReboot and domainReset hyperv: implement domainShutdown and domainShutdownFlags hyperv: fix domainSuspend and domainResume on Hyper-V V2 hyperv: fix domainManagedSave on Hyper-V V2 news: more Hyper-V APIs
NEWS.rst | 7 +- src/hyperv/hyperv_driver.c | 353 ++++++++++++++++++++++---- src/hyperv/hyperv_wmi.h | 1 + src/hyperv/hyperv_wmi_classes.h | 3 + src/hyperv/hyperv_wmi_generator.input | 78 ++++++ 5 files changed, 391 insertions(+), 51 deletions(-)
Patches look good. But please reply to my question in 5/9 so that I can push.
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Pushed now. Michal
participants (2)
-
Matt Coleman
-
Michal Privoznik