]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: support automatic VM managed save in system daemon
authorDaniel P. Berrangé <berrange@redhat.com>
Tue, 17 Dec 2024 17:45:05 +0000 (17:45 +0000)
committerDaniel P. Berrangé <berrange@redhat.com>
Thu, 20 Mar 2025 14:55:17 +0000 (14:55 +0000)
Currently automatic VM managed save is only performed in session
daemons, on desktop session close, or host OS shutdown request.

With this change it is possible to control shutdown behaviour for
all daemons. A recommended setup might be:

  auto_shutdown_try_save = "persistent"
  auto_shutdown_try_shutdown = "all"
  auto_shutdown_poweroff = "all"

Each setting accepts 'none', 'persistent', 'transient', and 'all'
to control what types of guest it applies to.

For historical compatibility, for the system daemon, the settings
currently default to:

  auto_shutdown_try_save = "none"
  auto_shutdown_try_shutdown = "none"
  auto_shutdown_poweroff = "none"

while for the session daemon they currently default to

  auto_shutdown_try_save = "persistent"
  auto_shutdown_try_shutdown = "none"
  auto_shutdown_poweroff = "none"

The system daemon settings should NOT be enabled if the traditional
libvirt-guests.service is already enabled.

Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
src/qemu/libvirtd_qemu.aug
src/qemu/qemu.conf.in
src/qemu/qemu_conf.c
src/qemu/qemu_conf.h
src/qemu/qemu_driver.c
src/qemu/test_libvirtd_qemu.aug.in

index 0288c2895b80b1f6d8857f557e1fee88e235c0b2..b2b36161951617a5a61047563834c47c862980eb 100644 (file)
@@ -103,6 +103,9 @@ module Libvirtd_qemu =
                  | bool_entry "auto_dump_bypass_cache"
                  | bool_entry "auto_start_bypass_cache"
                  | int_entry "auto_start_delay"
+                 | str_entry "auto_shutdown_try_save"
+                 | str_entry "auto_shutdown_try_shutdown"
+                 | str_entry "auto_shutdown_poweroff"
 
    let process_entry = str_entry "hugetlbfs_mount"
                  | str_entry "bridge_helper"
index 9354e960f1cfe1d7d0b8289a24a596bd75ba305b..ea7f905485e8b930ca4e0c7d5ec2f770e61d50e4 100644 (file)
 #
 #auto_start_delay = 0
 
+# The settings for auto shutdown actions accept one of
+# four possible options:
+#
+# * "none" - do not try to save any running VMs
+# * "persistent" - only try to save persistent running VMs
+# * "transient" - only try to save transient running VMs
+# * "all" - try to save all running VMs
+
+# Whether to perform managed save of running VMs if a host OS
+# shutdown is requested (system/session daemons), or the desktop
+# session terminates (session daemon only).
+#
+# Defaults to "persistent" for session daemons and "none"
+# for system daemons. The values "all" and "transient" are
+# not permitted for this setting, since managed save is not
+# implemented for transient VMs.
+#
+# If 'libvirt-guests.service' is enabled, then this must be
+# set to 'none' for system daemons to avoid dueling actions
+#auto_shutdown_try_save = "persistent"
+
+# As above, but with a graceful shutdown action instead of
+# managed save. If managed save is enabled, shutdown will
+# be tried only on failure to perform managed save.
+#
+# Defaults to "none"
+#
+# If 'libvirt-guests.service' is enabled, then this must be
+# set to 'none' for system daemons to avoid dueling actions
+#auto_shutdown_try_shutdown = "none"
+
+# As above, but with a forced poweroff instead of managed
+# save. If managed save or graceful shutdown are enabled,
+# forced poweroff will be tried only on failure of the
+# other options.
+#
+# Defaults to "none"
+#
+# If 'libvirt-guests.service' is enabled, then this must be
+# set to 'none' for system daemons to avoid dueling actions
+#auto_shutdown_poweroff = "none"
+
 # If provided by the host and a hugetlbfs mount point is configured,
 # a guest may request huge page backing.  When this mount point is
 # unspecified here, determination of a host mount point in /proc/mounts
index 79634511db2854cf79c2abdc15f4d9cc3579abc2..f0b0749259ae313cfbba97b237caa0935f74dd57 100644 (file)
@@ -314,6 +314,21 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
     cfg->dumpGuestCore = true;
 #endif
 
+    if (privileged) {
+        /*
+         * Defer to libvirt-guests.service.
+         *
+         * XXX, or query if libvirt-guests.service is enabled perhaps ?
+         */
+        cfg->autoShutdownTrySave = VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE;
+        cfg->autoShutdownTryShutdown = VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE;
+        cfg->autoShutdownPoweroff = VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE;
+    } else {
+        cfg->autoShutdownTrySave = VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT;
+        cfg->autoShutdownTryShutdown = VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE;
+        cfg->autoShutdownPoweroff = VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE;
+    }
+
     return g_steal_pointer(&cfg);
 }
 
@@ -659,6 +674,10 @@ virQEMUDriverConfigLoadSaveEntry(virQEMUDriverConfig *cfg,
     g_autofree char *savestr = NULL;
     g_autofree char *dumpstr = NULL;
     g_autofree char *snapstr = NULL;
+    g_autofree char *autoShutdownTrySave = NULL;
+    g_autofree char *autoShutdownTryShutdown = NULL;
+    g_autofree char *autoShutdownPoweroff = NULL;
+    int autoShutdownVal;
 
     if (virConfGetValueString(conf, "save_image_format", &savestr) < 0)
         return -1;
@@ -695,6 +714,54 @@ virQEMUDriverConfigLoadSaveEntry(virQEMUDriverConfig *cfg,
         return -1;
     if (virConfGetValueUInt(conf, "auto_start_delay", &cfg->autoStartDelayMS) < 0)
         return -1;
+    if (virConfGetValueString(conf, "auto_shutdown_try_save", &autoShutdownTrySave) < 0)
+        return -1;
+
+    if (autoShutdownTrySave != NULL) {
+        if ((autoShutdownVal =
+             virDomainDriverAutoShutdownScopeTypeFromString(autoShutdownTrySave)) < 0) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("unknown auto_shutdown_try_save '%1$s'"),
+                           autoShutdownTrySave);
+            return -1;
+        }
+        cfg->autoShutdownTrySave = autoShutdownVal;
+    }
+
+    if (cfg->autoShutdownTrySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_ALL ||
+        cfg->autoShutdownTrySave == VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_TRANSIENT) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("managed save cannot be requested for transient domains"));
+        return -1;
+    }
+
+    if (virConfGetValueString(conf, "auto_shutdown_try_shutdown", &autoShutdownTryShutdown) < 0)
+        return -1;
+
+    if (autoShutdownTryShutdown != NULL) {
+        if ((autoShutdownVal =
+             virDomainDriverAutoShutdownScopeTypeFromString(autoShutdownTryShutdown)) < 0) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("unknown auto_shutdown_try_shutdown '%1$s'"),
+                           autoShutdownTryShutdown);
+            return -1;
+        }
+        cfg->autoShutdownTryShutdown = autoShutdownVal;
+    }
+
+    if (virConfGetValueString(conf, "auto_shutdown_poweroff", &autoShutdownPoweroff) < 0)
+        return -1;
+
+    if (autoShutdownPoweroff != NULL) {
+        if ((autoShutdownVal =
+             virDomainDriverAutoShutdownScopeTypeFromString(autoShutdownPoweroff)) < 0) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("unknown auto_shutdown_poweroff '%1$s'"),
+                           autoShutdownPoweroff);
+            return -1;
+        }
+        cfg->autoShutdownPoweroff = autoShutdownVal;
+    }
 
     return 0;
 }
index bbbbd6bf67cad0eb3aad3468d993eb45ee665f03..5df9f6501e08ac23c4611322d11c2e9fcf755485 100644 (file)
@@ -43,6 +43,7 @@
 #include "virfilecache.h"
 #include "virfirmware.h"
 #include "virinhibitor.h"
+#include "domain_driver.h"
 
 #define QEMU_DRIVER_NAME "QEMU"
 
@@ -211,6 +212,9 @@ struct _virQEMUDriverConfig {
     bool autoDumpBypassCache;
     bool autoStartBypassCache;
     unsigned int autoStartDelayMS;
+    virDomainDriverAutoShutdownScope autoShutdownTrySave;
+    virDomainDriverAutoShutdownScope autoShutdownTryShutdown;
+    virDomainDriverAutoShutdownScope autoShutdownPoweroff;
 
     char *lockManagerName;
 
index 9d6523cfbca71192db1ddf8a45425c8767610dd5..8f69d0ec9ce8c5c28b79af233827c0d636353c9f 100644 (file)
@@ -966,13 +966,12 @@ qemuStateStop(void)
     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(qemu_driver);
     virDomainDriverAutoShutdownConfig ascfg = {
         .uri = cfg->uri,
-        .trySave = VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERSISTENT,
-        .tryShutdown =  VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE,
-        .poweroff = VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE
+        .trySave = cfg->autoShutdownTrySave,
+        .tryShutdown = cfg->autoShutdownTryShutdown,
+        .poweroff = cfg->autoShutdownPoweroff,
     };
 
-    if (!qemu_driver->privileged)
-        virDomainDriverAutoShutdown(&ascfg);
+    virDomainDriverAutoShutdown(&ascfg);
 
     return 0;
 }
index 8ef26a9da12e664b19431f7f1b2ac1f17a328cbf..9dd5fdb1d9b82fe55d3b3cdd0a714ad0450e02e0 100644 (file)
@@ -80,6 +80,9 @@ module Test_libvirtd_qemu =
 { "auto_dump_bypass_cache" = "0" }
 { "auto_start_bypass_cache" = "0" }
 { "auto_start_delay" = "0" }
+{ "auto_shutdown_try_save" = "persistent" }
+{ "auto_shutdown_try_shutdown" = "none" }
+{ "auto_shutdown_poweroff" = "none" }
 { "hugetlbfs_mount" = "/dev/hugepages" }
 { "bridge_helper" = "qemu-bridge-helper" }
 { "set_process_name" = "1" }