mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-30 18:50:18 +03:00
hypervisor: custom shutdown actions for transient vs persistent VMs
It may be desirable to treat transient VMs differently from persistent VMs. For example, while performing managed save on persistent VMs makes sense, the same not usually true of transient VMs, since by their nature they will have no config to restore from. This also lets us fix a long standing problem with incorrectly attempting to perform managed save on transient VMs. Reviewed-by: Peter Krempa <pkrempa@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
f4f5e6bdc4
commit
84bb136c31
@ -35,6 +35,13 @@
|
||||
|
||||
VIR_LOG_INIT("hypervisor.domain_driver");
|
||||
|
||||
VIR_ENUM_IMPL(virDomainDriverAutoShutdownScope,
|
||||
VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_LAST,
|
||||
"none",
|
||||
"persistent",
|
||||
"transient",
|
||||
"all");
|
||||
|
||||
char *
|
||||
virDomainDriverGenerateRootHash(const char *drivername,
|
||||
const char *root)
|
||||
@ -722,9 +729,13 @@ virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg)
|
||||
int numDomains = 0;
|
||||
size_t i;
|
||||
virDomainPtr *domains = NULL;
|
||||
g_autofree bool *transient = NULL;
|
||||
|
||||
VIR_DEBUG("Run autoshutdown uri=%s trySave=%d tryShutdown=%d poweroff=%d waitShutdownSecs=%u",
|
||||
cfg->uri, cfg->trySave, cfg->tryShutdown, cfg->poweroff,
|
||||
VIR_DEBUG("Run autoshutdown uri=%s trySave=%s tryShutdown=%s poweroff=%s waitShutdownSecs=%u",
|
||||
cfg->uri,
|
||||
virDomainDriverAutoShutdownScopeTypeToString(cfg->trySave),
|
||||
virDomainDriverAutoShutdownScopeTypeToString(cfg->tryShutdown),
|
||||
virDomainDriverAutoShutdownScopeTypeToString(cfg->poweroff),
|
||||
cfg->waitShutdownSecs);
|
||||
|
||||
/*
|
||||
@ -741,6 +752,25 @@ virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg)
|
||||
if (cfg->waitShutdownSecs <= 0)
|
||||
cfg->waitShutdownSecs = 30;
|
||||
|
||||
/* We expect the hypervisor driver to enforce this when loading
|
||||
* their config file, but in case some bad setting gets through,
|
||||
* disabling saving of transient VMs since it is a guaranteed
|
||||
* error scenario...
|
||||
*/
|
||||
if (cfg->trySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_ALL ||
|
||||
cfg->trySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_TRANSIENT) {
|
||||
VIR_WARN("auto-shutdown: managed save not supported for transient VMs");
|
||||
cfg->trySave = (cfg->trySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_ALL ?
|
||||
VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT :
|
||||
VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE);
|
||||
}
|
||||
|
||||
/* Short-circuit if all actions are disabled */
|
||||
if (cfg->trySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE &&
|
||||
cfg->tryShutdown == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE &&
|
||||
cfg->poweroff == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE)
|
||||
return;
|
||||
|
||||
if (!(conn = virConnectOpen(cfg->uri)))
|
||||
goto cleanup;
|
||||
|
||||
@ -750,10 +780,22 @@ virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg)
|
||||
goto cleanup;
|
||||
|
||||
VIR_DEBUG("Auto shutdown with %d running domains", numDomains);
|
||||
if (cfg->trySave) {
|
||||
|
||||
transient = g_new0(bool, numDomains);
|
||||
for (i = 0; i < numDomains; i++) {
|
||||
if (virDomainIsPersistent(domains[i]) == 0)
|
||||
transient[i] = true;
|
||||
}
|
||||
|
||||
if (cfg->trySave != VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE) {
|
||||
g_autofree unsigned int *flags = g_new0(unsigned int, numDomains);
|
||||
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))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Pause all VMs to make them stop dirtying pages,
|
||||
* so save is quicker. We remember if any VMs were
|
||||
@ -782,11 +824,16 @@ virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg)
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg->tryShutdown) {
|
||||
if (cfg->tryShutdown != VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE) {
|
||||
GTimer *timer = NULL;
|
||||
for (i = 0; i < numDomains; i++) {
|
||||
if (domains[i] == NULL)
|
||||
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;
|
||||
|
||||
if (virDomainShutdown(domains[i]) < 0) {
|
||||
VIR_WARN("auto-shutdown: unable to request graceful shutdown of '%s': %s",
|
||||
domains[i]->name,
|
||||
@ -802,6 +849,10 @@ virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg)
|
||||
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))
|
||||
continue;
|
||||
|
||||
if (virDomainIsActive(domains[i]) == 1) {
|
||||
anyRunning = true;
|
||||
} else {
|
||||
@ -819,10 +870,15 @@ virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg)
|
||||
g_timer_destroy(timer);
|
||||
}
|
||||
|
||||
if (cfg->poweroff) {
|
||||
if (cfg->poweroff != VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE) {
|
||||
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))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* NB might fail if we gave up on waiting for
|
||||
* virDomainShutdown, but it then completed anyway,
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "virhostdev.h"
|
||||
#include "virpci.h"
|
||||
#include "virdomainobjlist.h"
|
||||
#include "virenum.h"
|
||||
|
||||
char *
|
||||
virDomainDriverGenerateRootHash(const char *drivername,
|
||||
@ -91,11 +92,22 @@ typedef struct _virDomainDriverAutoStartConfig {
|
||||
void virDomainDriverAutoStart(virDomainObjList *domains,
|
||||
virDomainDriverAutoStartConfig *cfg);
|
||||
|
||||
typedef enum {
|
||||
VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE,
|
||||
VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT,
|
||||
VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_TRANSIENT,
|
||||
VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_ALL,
|
||||
|
||||
VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_LAST,
|
||||
} virDomainDriverAutoShutdownScope;
|
||||
|
||||
VIR_ENUM_DECL(virDomainDriverAutoShutdownScope);
|
||||
|
||||
typedef struct _virDomainDriverAutoShutdownConfig {
|
||||
const char *uri;
|
||||
bool trySave;
|
||||
bool tryShutdown;
|
||||
bool poweroff;
|
||||
virDomainDriverAutoShutdownScope trySave;
|
||||
virDomainDriverAutoShutdownScope tryShutdown;
|
||||
virDomainDriverAutoShutdownScope poweroff;
|
||||
unsigned int waitShutdownSecs; /* Seconds to wait for VM to shutdown
|
||||
* before moving onto next action.
|
||||
* If 0 a default is used (currently 30 secs)
|
||||
|
@ -1650,6 +1650,8 @@ virDomainCgroupSetupVcpuBW;
|
||||
# hypervisor/domain_driver.h
|
||||
virDomainDriverAddIOThreadCheck;
|
||||
virDomainDriverAutoShutdown;
|
||||
virDomainDriverAutoShutdownScopeTypeFromString;
|
||||
virDomainDriverAutoShutdownScopeTypeToString;
|
||||
virDomainDriverAutoStart;
|
||||
virDomainDriverDelIOThreadCheck;
|
||||
virDomainDriverGenerateMachineName;
|
||||
|
@ -966,9 +966,9 @@ qemuStateStop(void)
|
||||
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(qemu_driver);
|
||||
virDomainDriverAutoShutdownConfig ascfg = {
|
||||
.uri = cfg->uri,
|
||||
.trySave = true,
|
||||
.tryShutdown = false,
|
||||
.poweroff = false,
|
||||
.trySave = VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT,
|
||||
.tryShutdown = VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE,
|
||||
.poweroff = VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE
|
||||
};
|
||||
|
||||
if (!qemu_driver->privileged)
|
||||
|
Loading…
x
Reference in New Issue
Block a user