Co-authored-by: Sri Ramanujam <sramanujam(a)datto.com>
Signed-off-by: Matt Coleman <matt(a)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