]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
admin: add 'daemon-shutdown' command
authorDaniel P. Berrangé <berrange@redhat.com>
Tue, 7 Jan 2025 13:25:49 +0000 (13:25 +0000)
committerDaniel P. Berrangé <berrange@redhat.com>
Thu, 20 Mar 2025 14:55:17 +0000 (14:55 +0000)
The daemons are wired up to shutdown in responsible to UNIX process
signals, as well as in response to login1 dbus signals, or loss of
desktop session. The latter two options can optionally preserve state
(ie running VMs).

In non-systemd environments, as well as for testing, it would be useful
to have a way to trigger shutdown with state preservation more directly.

Thus a new admin protocol API is introduced

  virAdmConnectDaemonShutdown

which will trigger a daemon shutdown, and preserve running VMs if the
VIR_DAEMON_SHUTDOWN_PRESERVE flag is set.

It has a corresponding 'virt-admin daemon-shutdown [--preserve]' command
binding.

Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
docs/manpages/virt-admin.rst
include/libvirt/libvirt-admin.h
src/admin/admin_protocol.x
src/admin/admin_server_dispatch.c
src/admin/libvirt-admin.c
src/admin/libvirt_admin_public.syms
src/admin_protocol-structs
tools/virt-admin.c

index 54a6512ef7a04e4630b7be9b5dd5b562c5a614bb..82e9594ba655e7414cd8d0099ce22025eda34b8c 100644 (file)
@@ -326,6 +326,19 @@ Sets the daemon timeout to the value of '--timeout' argument. Use ``--timeout 0`
 to disable auto-shutdown of the daemon.
 
 
+daemon-shutdown
+---------------
+
+**Syntax:**
+
+::
+
+   daemon-shutdown [--preserve]
+
+Instruct the daemon to exit gracefully. If the ``--preserve`` flag is given,
+it will save state in the same manner that would be done on a host OS shutdown
+(privileged daemons) or a login session quit (unprivileged daemons).
+
 SERVER COMMANDS
 ===============
 
index ae4703f89bd3060004d76e730538db74921d4f34..d5c0a5bc8f8b9781dad400c5fd511ced718870e8 100644 (file)
@@ -484,6 +484,19 @@ int virAdmConnectSetDaemonTimeout(virAdmConnectPtr conn,
                                   unsigned int timeout,
                                   unsigned int flags);
 
+/**
+ * virAdmConnectDaemonShutdownFlags:
+ *
+ * Since: 11.2.0
+ */
+typedef enum {
+    /* Preserve state before shutting down daemon (Since: 11.2.0) */
+    VIR_DAEMON_SHUTDOWN_PRESERVE = (1 << 0),
+} virAdmConnectDaemonShutdownFlags;
+
+int virAdmConnectDaemonShutdown(virAdmConnectPtr conn,
+                                unsigned int flags);
+
 # ifdef __cplusplus
 }
 # endif
index f3130efd2d57d54dc9e8be96b0d9fd3dc485e405..cf5707e62e72304efddd93a2971b4cce8225bcae 100644 (file)
@@ -219,6 +219,10 @@ struct admin_connect_set_daemon_timeout_args {
     unsigned int flags;
 };
 
+struct admin_connect_daemon_shutdown_args {
+    unsigned int flags;
+};
+
 /* Define the program number, protocol version and procedure numbers here. */
 const ADMIN_PROGRAM = 0x06900690;
 const ADMIN_PROTOCOL_VERSION = 1;
@@ -334,5 +338,10 @@ enum admin_procedure {
     /**
      * @generate: both
      */
-    ADMIN_PROC_CONNECT_SET_DAEMON_TIMEOUT = 19
+    ADMIN_PROC_CONNECT_SET_DAEMON_TIMEOUT = 19,
+
+    /**
+     * @generate: both
+     */
+    ADMIN_PROC_CONNECT_DAEMON_SHUTDOWN = 20
 };
index ae8a8d4fa6950465d0e82b5ec02f43abad648e64..0eee80f6ac81580ffc1757a1cdc938e72a0e08b3 100644 (file)
@@ -474,6 +474,19 @@ adminConnectSetDaemonTimeout(virNetDaemon *dmn,
     return virNetDaemonAutoShutdown(dmn, timeout);
 }
 
+static int
+adminConnectDaemonShutdown(virNetDaemon *dmn,
+                           unsigned int flags)
+{
+    virCheckFlags(VIR_DAEMON_SHUTDOWN_PRESERVE, -1);
+
+    if (flags & VIR_DAEMON_SHUTDOWN_PRESERVE)
+        virNetDaemonStop(dmn);
+
+    virNetDaemonQuit(dmn);
+
+    return 0;
+}
 
 static int
 adminDispatchConnectGetLoggingOutputs(virNetServer *server G_GNUC_UNUSED,
index 3c756eb376a9c737c995659d0341f7a1d3b89a09..d7efac025fc263140919158873f831ddc1f89b35 100644 (file)
@@ -1357,3 +1357,36 @@ virAdmConnectSetDaemonTimeout(virAdmConnectPtr conn,
 
     return ret;
 }
+
+
+/**
+ * virAdmConnectDaemonShutdown:
+ * @conn: pointer to an active admin connection
+ * @flags: optional extra falgs
+ *
+ * Trigger shutdown of the daemon, if @flags includes
+ * VIR_DAEMON_SHUTDOWN_PRESERVE then state will be
+ * preserved before shutting down
+ *
+ * Returns 0 on success, -1 on error.
+ *
+ * Since: 11.2.0
+ */
+int
+virAdmConnectDaemonShutdown(virAdmConnectPtr conn,
+                            unsigned int flags)
+{
+    int ret;
+
+    VIR_DEBUG("conn=%p, flags=0x%x", conn, flags);
+
+    virResetLastError();
+    virCheckAdmConnectReturn(conn, -1);
+
+    if ((ret = remoteAdminConnectDaemonShutdown(conn, flags)) < 0) {
+        virDispatchError(NULL);
+        return -1;
+    }
+
+    return ret;
+}
index 17930e4fac849bd35c789adf7d085966d7db4c1c..42feba032961d1d83643893e44dd753e27603ce1 100644 (file)
@@ -53,3 +53,8 @@ LIBVIRT_ADMIN_8.6.0 {
     global:
         virAdmConnectSetDaemonTimeout;
 } LIBVIRT_ADMIN_3.0.0;
+
+LIBVIRT_ADMIN_11.2.0 {
+    global:
+        virAdmConnectDaemonShutdown;
+} LIBVIRT_ADMIN_8.6.0;
index f6988cf76de45adf6383ab89201b2f1d354c5316..a779dc22ce951994c80584d89af5c10fdd9ca470 100644 (file)
@@ -148,6 +148,9 @@ struct admin_connect_set_daemon_timeout_args {
         u_int                      timeout;
         u_int                      flags;
 };
+struct admin_connect_daemon_shutdown_args {
+        u_int                      flags;
+};
 enum admin_procedure {
         ADMIN_PROC_CONNECT_OPEN = 1,
         ADMIN_PROC_CONNECT_CLOSE = 2,
@@ -168,4 +171,5 @@ enum admin_procedure {
         ADMIN_PROC_CONNECT_SET_LOGGING_FILTERS = 17,
         ADMIN_PROC_SERVER_UPDATE_TLS_FILES = 18,
         ADMIN_PROC_CONNECT_SET_DAEMON_TIMEOUT = 19,
+        ADMIN_PROC_CONNECT_DAEMON_SHUTDOWN = 20,
 };
index 2d630984441becfe3a36b64478240d1af2c3bc6a..b701ed1fe4dddf3d41a548c01a6fd7c4f6226f74 100644 (file)
@@ -1077,6 +1077,41 @@ cmdDaemonTimeout(vshControl *ctl, const vshCmd *cmd)
 }
 
 
+/* --------------------------
+ * Command daemon-shutdown
+ * --------------------------
+ */
+static const vshCmdInfo info_daemon_shutdown = {
+    .help = N_("stop the daemon"),
+    .desc = N_("stop the daemon"),
+};
+
+static const vshCmdOptDef opts_daemon_shutdown[] = {
+    {.name = "preserve",
+     .type = VSH_OT_BOOL,
+     .required = false,
+     .positional = false,
+     .help = N_("preserve state before shutting down"),
+    },
+    {.name = NULL}
+};
+
+static bool
+cmdDaemonShutdown(vshControl *ctl, const vshCmd *cmd)
+{
+    vshAdmControl *priv = ctl->privData;
+    unsigned int flags = 0;
+
+    if (vshCommandOptBool(cmd, "preserve"))
+        flags |= VIR_DAEMON_SHUTDOWN_PRESERVE;
+
+    if (virAdmConnectDaemonShutdown(priv->conn, flags) < 0)
+        return false;
+
+    return true;
+}
+
+
 static void *
 vshAdmConnectionHandler(vshControl *ctl)
 {
@@ -1469,6 +1504,12 @@ static const vshCmdDef managementCmds[] = {
      .info = &info_daemon_timeout,
      .flags = 0
     },
+    {.name = "daemon-shutdown",
+     .handler = cmdDaemonShutdown,
+     .opts = opts_daemon_shutdown,
+     .info = &info_daemon_shutdown,
+     .flags = 0
+    },
     {.name = NULL}
 };