1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-30 18:50:18 +03:00

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 <pkrempa@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2024-12-17 10:04:35 +00:00
parent f48fb17d72
commit 991a20a938
4 changed files with 60 additions and 42 deletions

View File

@ -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);
}
}

View File

@ -90,3 +90,9 @@ typedef struct _virDomainDriverAutoStartConfig {
void virDomainDriverAutoStart(virDomainObjList *domains,
virDomainDriverAutoStartConfig *cfg);
typedef struct _virDomainDriverAutoShutdownConfig {
const char *uri;
} virDomainDriverAutoShutdownConfig;
void virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg);

View File

@ -1649,6 +1649,7 @@ virDomainCgroupSetupVcpuBW;
# hypervisor/domain_driver.h
virDomainDriverAddIOThreadCheck;
virDomainDriverAutoShutdown;
virDomainDriverAutoStart;
virDomainDriverDelIOThreadCheck;
virDomainDriverGenerateMachineName;

View File

@ -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;
virDomainDriverAutoShutdown(&ascfg);
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);
}
return ret;
return 0;
}