- virSystemdCreateMachine: Document @maxthreds (RHEL-95361) - cgroup: Unexport 'virDomainCgroupInitCgroup' (RHEL-95361) - qemu: conf: Store 'autoShutdown' config in virDomainDriverAutoShutdownConfig (RHEL-95361) - hypervisor: domain: Extract logic for auto shutdown to virDomainDriverAutoShutdownActive (RHEL-95361) - virSystemdCreateMachine: Add flag to invert machined unit dependencies (RHEL-95361) - cgroup: Plumb the 'daemonDomainShutdown' parameter of 'virSystemdCreateMachine' to drivers (RHEL-95361) - qemu: Fix auto-shutdown of qemu VMs by the qemu driver (RHEL-95361) - hypervisor: Split out individual steps out of virDomainDriverAutoShutdown (RHEL-95196) - virDomainDriverAutoShutdownDoSave: Don't attempt to save transient VMs (RHEL-95196) - virDomainDriverAutoShutdown: Refactor selection logic for VMs (RHEL-95196) - tls: Don't require 'keyEncipherment' to be enabled altoghther (RHEL-100711) - kbase: tlscerts: Drop 'encryption_key' feature request (RHEL-100711) - tests: virnettls*test: Drop use of GNUTLS_KEY_KEY_ENCIPHERMENT (RHEL-100711) - qemu_tpm: Rename qemuTPMHasSharedStorage -> qemuTPMDomainHasSharedStorage (RHEL-80155) - qemu_tpm: Extract per-TPM functionality from qemuTPMDomainHasSharedStorage (RHEL-80155) - qemu_tpm: Only warn about missing locking feature on shared filesystems (RHEL-80155) Resolves: RHEL-100711, RHEL-80155, RHEL-95196, RHEL-95361
333 lines
13 KiB
Diff
333 lines
13 KiB
Diff
From 518d76ea990261580c502657e4bf7b9dea22b21e Mon Sep 17 00:00:00 2001
|
|
Message-ID: <518d76ea990261580c502657e4bf7b9dea22b21e.1752837271.git.jdenemar@redhat.com>
|
|
From: Peter Krempa <pkrempa@redhat.com>
|
|
Date: Tue, 1 Jul 2025 17:19:46 +0200
|
|
Subject: [PATCH] virDomainDriverAutoShutdown: Refactor selection logic for VMs
|
|
|
|
Decide separately and record what shutdown modes are to be applied on
|
|
given VM object rather than spreading out the logic through the code.
|
|
|
|
This centralization simplifies the conditions in the worker functions
|
|
and also:
|
|
- provides easy way to check if the auto-shutdown code will be acting
|
|
on domain object (will be used to fix attempt to auto-restore of
|
|
VMs which were not selected to be acted on
|
|
- will simplify further work where the desired shutdown action will be
|
|
picked per-VM
|
|
|
|
This refactor also fixes a bug where if restoring of the state is
|
|
applied also on VMs that are not selected for action based on current
|
|
logic.
|
|
|
|
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
|
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
|
|
(cherry picked from commit 1c2295fbafab12cb3f943aab8bd015e167cad533)
|
|
|
|
https://issues.redhat.com/browse/RHEL-95196
|
|
---
|
|
src/hypervisor/domain_driver.c | 178 +++++++++++++++++++--------------
|
|
1 file changed, 101 insertions(+), 77 deletions(-)
|
|
|
|
diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c
|
|
index d8ccee40d5..88fb87023a 100644
|
|
--- a/src/hypervisor/domain_driver.c
|
|
+++ b/src/hypervisor/domain_driver.c
|
|
@@ -738,25 +738,32 @@ virDomainDriverAutoShutdownActive(virDomainDriverAutoShutdownConfig *cfg)
|
|
}
|
|
|
|
|
|
+enum {
|
|
+ VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SAVE = 1 << 1,
|
|
+ VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SHUTDOWN = 1 << 2,
|
|
+ VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_POWEROFF = 1 << 3,
|
|
+ VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_RESTORE = 1 << 4,
|
|
+} virDomainDriverAutoShutdownModeFlag;
|
|
+
|
|
+
|
|
static void
|
|
virDomainDriverAutoShutdownDoSave(virDomainPtr *domains,
|
|
- bool *transient,
|
|
+ unsigned int *modes,
|
|
size_t numDomains,
|
|
virDomainDriverAutoShutdownConfig *cfg)
|
|
{
|
|
g_autofree unsigned int *flags = g_new0(unsigned int, numDomains);
|
|
+ bool hasSave = false;
|
|
size_t i;
|
|
|
|
- if (cfg->trySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE)
|
|
- return;
|
|
-
|
|
for (i = 0; i < numDomains; i++) {
|
|
int state;
|
|
|
|
- if ((transient[i] && cfg->trySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT) ||
|
|
- (!transient[i] && cfg->trySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_TRANSIENT))
|
|
+ if (!(modes[i] & VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SAVE))
|
|
continue;
|
|
|
|
+ hasSave = true;
|
|
+
|
|
virSystemdNotifyStatus("Suspending '%s' (%zu of %zu)",
|
|
virDomainGetName(domains[i]), i + 1, numDomains);
|
|
VIR_INFO("Suspending '%s'", virDomainGetName(domains[i]));
|
|
@@ -778,9 +785,11 @@ virDomainDriverAutoShutdownDoSave(virDomainPtr *domains,
|
|
virDomainSuspend(domains[i]);
|
|
}
|
|
|
|
+ if (!hasSave)
|
|
+ return;
|
|
+
|
|
for (i = 0; i < numDomains; i++) {
|
|
- if ((transient[i] && cfg->trySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT) ||
|
|
- (!transient[i] && cfg->trySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_TRANSIENT))
|
|
+ if (!(modes[i] & VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SAVE))
|
|
continue;
|
|
|
|
virSystemdNotifyStatus("Saving '%s' (%zu of %zu)",
|
|
@@ -795,31 +804,27 @@ virDomainDriverAutoShutdownDoSave(virDomainPtr *domains,
|
|
virDomainResume(domains[i]);
|
|
continue;
|
|
}
|
|
- virObjectUnref(domains[i]);
|
|
- domains[i] = NULL;
|
|
+
|
|
+ modes[i] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
virDomainDriverAutoShutdownDoShutdown(virDomainPtr *domains,
|
|
- bool *transient,
|
|
+ unsigned int *modes,
|
|
size_t numDomains,
|
|
virDomainDriverAutoShutdownConfig *cfg)
|
|
{
|
|
GTimer *timer = NULL;
|
|
+ bool hasShutdown = false;
|
|
size_t i;
|
|
|
|
- if (cfg->tryShutdown == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE)
|
|
- return;
|
|
-
|
|
for (i = 0; i < numDomains; i++) {
|
|
- if (domains[i] == NULL)
|
|
+ if (!(modes[i] & VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SHUTDOWN))
|
|
continue;
|
|
|
|
- if ((transient[i] && cfg->tryShutdown == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT) ||
|
|
- (!transient[i] && cfg->tryShutdown == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_TRANSIENT))
|
|
- continue;
|
|
+ hasShutdown = true;
|
|
|
|
virSystemdNotifyStatus("Shutting down '%s' (%zu of %zu)",
|
|
virDomainGetName(domains[i]), i + 1, numDomains);
|
|
@@ -833,25 +838,24 @@ virDomainDriverAutoShutdownDoShutdown(virDomainPtr *domains,
|
|
}
|
|
}
|
|
|
|
+ if (!hasShutdown)
|
|
+ return;
|
|
+
|
|
timer = g_timer_new();
|
|
virSystemdNotifyStatus("Waiting %u secs for VM shutdown completion",
|
|
cfg->waitShutdownSecs);
|
|
VIR_INFO("Waiting %u secs for VM shutdown completion", cfg->waitShutdownSecs);
|
|
+
|
|
while (1) {
|
|
bool anyRunning = false;
|
|
for (i = 0; i < numDomains; i++) {
|
|
- if (!domains[i])
|
|
- continue;
|
|
-
|
|
- if ((transient[i] && cfg->tryShutdown == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT) ||
|
|
- (!transient[i] && cfg->tryShutdown == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_TRANSIENT))
|
|
+ if (!(modes[i] & VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SHUTDOWN))
|
|
continue;
|
|
|
|
if (virDomainIsActive(domains[i]) == 1) {
|
|
anyRunning = true;
|
|
} else {
|
|
- virObjectUnref(domains[i]);
|
|
- domains[i] = NULL;
|
|
+ modes[i] = 0;
|
|
}
|
|
}
|
|
|
|
@@ -867,21 +871,13 @@ virDomainDriverAutoShutdownDoShutdown(virDomainPtr *domains,
|
|
|
|
static void
|
|
virDomainDriverAutoShutdownDoPoweroff(virDomainPtr *domains,
|
|
- bool *transient,
|
|
- size_t numDomains,
|
|
- virDomainDriverAutoShutdownConfig *cfg)
|
|
+ unsigned int *modes,
|
|
+ size_t numDomains)
|
|
{
|
|
size_t i;
|
|
|
|
- if (cfg->poweroff == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE)
|
|
- return;
|
|
-
|
|
for (i = 0; i < numDomains; i++) {
|
|
- if (domains[i] == NULL)
|
|
- continue;
|
|
-
|
|
- if ((transient[i] && cfg->poweroff == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT) ||
|
|
- (!transient[i] && cfg->poweroff == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_TRANSIENT))
|
|
+ if (!(modes[i] & VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_POWEROFF))
|
|
continue;
|
|
|
|
virSystemdNotifyStatus("Destroying '%s' (%zu of %zu)",
|
|
@@ -894,11 +890,49 @@ virDomainDriverAutoShutdownDoPoweroff(virDomainPtr *domains,
|
|
*/
|
|
virDomainDestroy(domains[i]);
|
|
|
|
- virObjectUnref(domains[i]);
|
|
- domains[i] = NULL;
|
|
+ modes[i] = 0;
|
|
}
|
|
}
|
|
|
|
+static unsigned int
|
|
+virDomainDriverAutoShutdownGetMode(virDomainPtr domain,
|
|
+ virDomainDriverAutoShutdownConfig *cfg)
|
|
+{
|
|
+ unsigned int mode = 0;
|
|
+
|
|
+ if (virDomainIsPersistent(domain) != 0) {
|
|
+ if (cfg->trySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_ALL ||
|
|
+ cfg->trySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT)
|
|
+ mode |= VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SAVE;
|
|
+
|
|
+ if (cfg->tryShutdown == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_ALL ||
|
|
+ cfg->tryShutdown == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT)
|
|
+ mode |= VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SHUTDOWN;
|
|
+
|
|
+ if (cfg->poweroff == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_ALL ||
|
|
+ cfg->poweroff == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT)
|
|
+ mode |= VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_POWEROFF;
|
|
+
|
|
+ /* Don't restore VMs which weren't selected for auto-shutdown */
|
|
+ if (mode != 0 && cfg->autoRestore)
|
|
+ mode |= VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_RESTORE;
|
|
+ } else {
|
|
+ if (cfg->tryShutdown == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_ALL ||
|
|
+ cfg->tryShutdown == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_TRANSIENT)
|
|
+ mode |= VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SHUTDOWN;
|
|
+
|
|
+ if (cfg->poweroff == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_ALL ||
|
|
+ cfg->poweroff == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_TRANSIENT)
|
|
+ mode |= VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_POWEROFF;
|
|
+
|
|
+ if (cfg->autoRestore)
|
|
+ VIR_DEBUG("Cannot auto-restore transient VM '%s'",
|
|
+ virDomainGetName(domain));
|
|
+ }
|
|
+
|
|
+ return mode;
|
|
+}
|
|
+
|
|
|
|
void
|
|
virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg)
|
|
@@ -907,7 +941,7 @@ virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg)
|
|
int numDomains = 0;
|
|
size_t i;
|
|
virDomainPtr *domains = NULL;
|
|
- g_autofree bool *transient = NULL;
|
|
+ g_autofree unsigned int *modes = NULL;
|
|
|
|
VIR_DEBUG("Run autoshutdown uri=%s trySave=%s tryShutdown=%s poweroff=%s waitShutdownSecs=%u saveBypassCache=%d autoRestore=%d",
|
|
cfg->uri,
|
|
@@ -948,58 +982,48 @@ virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg)
|
|
return;
|
|
|
|
if (!(conn = virConnectOpen(cfg->uri)))
|
|
- goto cleanup;
|
|
+ return;
|
|
|
|
if ((numDomains = virConnectListAllDomains(conn,
|
|
&domains,
|
|
VIR_CONNECT_LIST_DOMAINS_ACTIVE)) < 0)
|
|
- goto cleanup;
|
|
+ return;
|
|
|
|
VIR_DEBUG("Auto shutdown with %d running domains", numDomains);
|
|
|
|
- transient = g_new0(bool, numDomains);
|
|
- for (i = 0; i < numDomains; i++) {
|
|
- if (virDomainIsPersistent(domains[i]) == 0)
|
|
- transient[i] = true;
|
|
+ modes = g_new0(unsigned int, numDomains);
|
|
|
|
- if (cfg->autoRestore) {
|
|
- if (transient[i]) {
|
|
- VIR_DEBUG("Cannot auto-restore transient VM %s",
|
|
- virDomainGetName(domains[i]));
|
|
- } else {
|
|
- VIR_DEBUG("Mark %s for autostart on next boot",
|
|
- virDomainGetName(domains[i]));
|
|
- if (virDomainSetAutostartOnce(domains[i], 1) < 0) {
|
|
- VIR_WARN("Unable to mark domain '%s' for auto restore: %s",
|
|
- virDomainGetName(domains[i]),
|
|
- virGetLastErrorMessage());
|
|
- }
|
|
+ for (i = 0; i < numDomains; i++) {
|
|
+ modes[i] = virDomainDriverAutoShutdownGetMode(domains[i], cfg);
|
|
+
|
|
+ if (modes[i] == 0) {
|
|
+ /* VM wasn't selected for any of the shutdown modes. There's not
|
|
+ * much we can do about that as the host is powering off, logging
|
|
+ * at least lets admins know */
|
|
+ VIR_WARN("auto-shutdown: domain '%s' not successfully shut off by any action",
|
|
+ domains[i]->name);
|
|
+ }
|
|
+
|
|
+ if (modes[i] & VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_RESTORE) {
|
|
+ VIR_DEBUG("Mark '%s' for autostart on next boot",
|
|
+ virDomainGetName(domains[i]));
|
|
+ if (virDomainSetAutostartOnce(domains[i], 1) < 0) {
|
|
+ VIR_WARN("Unable to mark domain '%s' for auto restore: %s",
|
|
+ virDomainGetName(domains[i]),
|
|
+ virGetLastErrorMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
- virDomainDriverAutoShutdownDoSave(domains, transient, numDomains, cfg);
|
|
- virDomainDriverAutoShutdownDoShutdown(domains, transient, numDomains, cfg);
|
|
- virDomainDriverAutoShutdownDoPoweroff(domains, transient, numDomains, cfg);
|
|
+ virDomainDriverAutoShutdownDoSave(domains, modes, numDomains, cfg);
|
|
+ virDomainDriverAutoShutdownDoShutdown(domains, modes, numDomains, cfg);
|
|
+ virDomainDriverAutoShutdownDoPoweroff(domains, modes, numDomains);
|
|
|
|
virSystemdNotifyStatus("Processed %d domains", numDomains);
|
|
VIR_INFO("Processed %d domains", numDomains);
|
|
|
|
- cleanup:
|
|
- if (domains) {
|
|
- /* Anything non-NULL in this list indicates none of
|
|
- * the configured ations were successful in processing
|
|
- * the domain. There's not much we can do about that
|
|
- * as the host is powering off, logging at least lets
|
|
- * admins know
|
|
- */
|
|
- for (i = 0; i < numDomains; i++) {
|
|
- if (domains[i] == NULL)
|
|
- continue;
|
|
- VIR_WARN("auto-shutdown: domain '%s' not successfully shut off by any action",
|
|
- domains[i]->name);
|
|
- virObjectUnref(domains[i]);
|
|
- }
|
|
- VIR_FREE(domains);
|
|
- }
|
|
+ for (i = 0; i < numDomains; i++)
|
|
+ virObjectUnref(domains[i]);
|
|
+
|
|
+ VIR_FREE(domains);
|
|
}
|
|
--
|
|
2.50.1
|