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 <pkrempa@xxxxxxxxxx> Signed-off-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> --- src/hypervisor/domain_driver.c | 48 ++++++++++++++++++++++++++++++++++ src/hypervisor/domain_driver.h | 6 +++++ src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 47 ++++----------------------------- 4 files changed, 60 insertions(+), 42 deletions(-) diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c index b7499a376f..0ca482275f 100644 --- a/src/hypervisor/domain_driver.c +++ b/src/hypervisor/domain_driver.c @@ -712,3 +712,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 e63939e2b5..e6fec0a151 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 2364b4d312..14b128d268 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -944,51 +944,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; } -- 2.48.1