From: Daniel P. Berrangé Date: Tue, 17 Dec 2024 10:04:35 +0000 (+0000) Subject: hypervisor: move support for auto-shutdown out of QEMU driver X-Git-Tag: v11.2.0-rc1~87 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=991a20a938fdd14498efc73faa871bf3e337bfe9;p=thirdparty%2Flibvirt.git hypervisor: move support for auto-shutdown out of QEMU driver This is a move of the code that currently exists in the QEMU driver, into the common layer that can be used by multiple drivers. The code currently supports performing managed save of all running guests, ignoring any failures. Reviewed-by: Peter Krempa Signed-off-by: Daniel P. Berrangé --- diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c index 29ba358477..5dfa211fae 100644 --- a/src/hypervisor/domain_driver.c +++ b/src/hypervisor/domain_driver.c @@ -713,3 +713,51 @@ virDomainDriverAutoStart(virDomainObjList *domains, virDomainObjListForEach(domains, false, virDomainDriverAutoStartOne, &state); } + + +void +virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg) +{ + g_autoptr(virConnect) conn = NULL; + int numDomains = 0; + size_t i; + int state; + virDomainPtr *domains = NULL; + g_autofree unsigned int *flags = NULL; + + if (!(conn = virConnectOpen(cfg->uri))) + goto cleanup; + + if ((numDomains = virConnectListAllDomains(conn, + &domains, + VIR_CONNECT_LIST_DOMAINS_ACTIVE)) < 0) + goto cleanup; + + flags = g_new0(unsigned int, numDomains); + + /* First we pause all VMs to make them stop dirtying + pages, etc. We remember if any VMs were paused so + we can restore that on resume. */ + for (i = 0; i < numDomains; i++) { + flags[i] = VIR_DOMAIN_SAVE_RUNNING; + if (virDomainGetState(domains[i], &state, NULL, 0) == 0) { + if (state == VIR_DOMAIN_PAUSED) + flags[i] = VIR_DOMAIN_SAVE_PAUSED; + } + virDomainSuspend(domains[i]); + } + + /* Then we save the VMs to disk */ + for (i = 0; i < numDomains; i++) + if (virDomainManagedSave(domains[i], flags[i]) < 0) + VIR_WARN("Unable to perform managed save of '%s': %s", + virDomainGetName(domains[i]), + virGetLastErrorMessage()); + + cleanup: + if (domains) { + for (i = 0; i < numDomains; i++) + virObjectUnref(domains[i]); + VIR_FREE(domains); + } +} diff --git a/src/hypervisor/domain_driver.h b/src/hypervisor/domain_driver.h index f81d436c2c..f36db5c6f0 100644 --- a/src/hypervisor/domain_driver.h +++ b/src/hypervisor/domain_driver.h @@ -90,3 +90,9 @@ typedef struct _virDomainDriverAutoStartConfig { void virDomainDriverAutoStart(virDomainObjList *domains, virDomainDriverAutoStartConfig *cfg); + +typedef struct _virDomainDriverAutoShutdownConfig { + const char *uri; +} virDomainDriverAutoShutdownConfig; + +void virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f4ec26eba3..4b888c63f1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1649,6 +1649,7 @@ virDomainCgroupSetupVcpuBW; # hypervisor/domain_driver.h virDomainDriverAddIOThreadCheck; +virDomainDriverAutoShutdown; virDomainDriverAutoStart; virDomainDriverDelIOThreadCheck; virDomainDriverGenerateMachineName; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d87d38c4b9..5f0f456184 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -963,51 +963,14 @@ qemuStateReload(void) static int qemuStateStop(void) { - int ret = -1; - g_autoptr(virConnect) conn = NULL; - int numDomains = 0; - size_t i; - int state; - virDomainPtr *domains = NULL; - g_autofree unsigned int *flags = NULL; g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(qemu_driver); + virDomainDriverAutoShutdownConfig ascfg = { + .uri = cfg->uri, + }; - if (!(conn = virConnectOpen(cfg->uri))) - goto cleanup; - - if ((numDomains = virConnectListAllDomains(conn, - &domains, - VIR_CONNECT_LIST_DOMAINS_ACTIVE)) < 0) - goto cleanup; - - flags = g_new0(unsigned int, numDomains); - - /* First we pause all VMs to make them stop dirtying - pages, etc. We remember if any VMs were paused so - we can restore that on resume. */ - for (i = 0; i < numDomains; i++) { - flags[i] = VIR_DOMAIN_SAVE_RUNNING; - if (virDomainGetState(domains[i], &state, NULL, 0) == 0) { - if (state == VIR_DOMAIN_PAUSED) - flags[i] = VIR_DOMAIN_SAVE_PAUSED; - } - virDomainSuspend(domains[i]); - } - - ret = 0; - /* Then we save the VMs to disk */ - for (i = 0; i < numDomains; i++) - if (virDomainManagedSave(domains[i], flags[i]) < 0) - ret = -1; - - cleanup: - if (domains) { - for (i = 0; i < numDomains; i++) - virObjectUnref(domains[i]); - VIR_FREE(domains); - } + virDomainDriverAutoShutdown(&ascfg); - return ret; + return 0; }