From nobody Tue Jan 21 07:43:44 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1736366109130583.1294027960545; Wed, 8 Jan 2025 11:55:09 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id 2477C13B3; Wed, 8 Jan 2025 14:55:08 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id B15A513B1; Wed, 8 Jan 2025 14:44:25 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 0D9E91452; Wed, 8 Jan 2025 14:44:02 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 198B91489 for ; Wed, 8 Jan 2025 14:43:34 -0500 (EST) Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-264-RSyQEZ_DO2OdDuRQDYjxnA-1; Wed, 08 Jan 2025 14:43:32 -0500 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5240A19560B0 for ; Wed, 8 Jan 2025 19:43:31 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.103]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 775B0300018D; Wed, 8 Jan 2025 19:43:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.5 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1736365413; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AO1qfBGCG9VSI0GAy61IR5y39l9Yxe4wTJsjkgqDCx0=; b=L4cVC/7ptM7sEc0sJMlNV+6Mz4TaUlopuiY0aiVfIbqkJdBSmaao6BTOOLIYAhuuxqAn+1 oHT0ihqZg2vwhNlh88O/nslrQIMCZtbKyZ1Cq5mmoeOvXQ+UoqwLqJGRAYsnaOZcnAdQMr 9dV3VvJiOYnk7Rhbhi1BvBEe8aOGS2o= X-MC-Unique: RSyQEZ_DO2OdDuRQDYjxnA-1 X-Mimecast-MFC-AGG-ID: RSyQEZ_DO2OdDuRQDYjxnA From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: devel@lists.libvirt.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Subject: [PATCH 24/26] admin: add 'daemon-shutdown' command Date: Wed, 8 Jan 2025 19:42:57 +0000 Message-ID: <20250108194259.1171990-25-berrange@redhat.com> In-Reply-To: <20250108194259.1171990-1-berrange@redhat.com> References: <20250108194259.1171990-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: -ZcNRJP6mmG0yfzMkrVdC_Tv8fyAMiWt-0RQJ7DrfZc_1736365411 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: QFMDI3H5OA7UHNZDKVIEJ4YIWSH43ZZM X-Message-ID-Hash: QFMDI3H5OA7UHNZDKVIEJ4YIWSH43ZZM X-MailFrom: berrange@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1736366110671116600 Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Daniel P. Berrang=C3=A9 --- include/libvirt/libvirt-admin.h | 13 +++++++++ src/admin/admin_protocol.x | 11 +++++++- src/admin/admin_server_dispatch.c | 13 +++++++++ src/admin/libvirt-admin.c | 33 +++++++++++++++++++++++ src/admin/libvirt_admin_public.syms | 5 ++++ src/rpc/virnetdaemon.c | 4 +++ tools/virt-admin.c | 41 +++++++++++++++++++++++++++++ 7 files changed, 119 insertions(+), 1 deletion(-) diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admi= n.h index ae4703f89b..1926202e97 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -484,6 +484,19 @@ int virAdmConnectSetDaemonTimeout(virAdmConnectPtr con= n, unsigned int timeout, unsigned int flags); =20 +/** + * virAdmConnectDaemonShutdownFlags: + * + * Since: 11.0.0 + */ +typedef enum { + /* Preserve state before shutting down daemon (Since: 11.0.0) */ + VIR_DAEMON_SHUTDOWN_PRESERVE =3D (1 << 0), +} virAdmConnectDaemonShutdownFlags; + +int virAdmConnectDaemonShutdown(virAdmConnectPtr conn, + unsigned int flags); + # ifdef __cplusplus } # endif diff --git a/src/admin/admin_protocol.x b/src/admin/admin_protocol.x index f3130efd2d..cf5707e62e 100644 --- a/src/admin/admin_protocol.x +++ b/src/admin/admin_protocol.x @@ -219,6 +219,10 @@ struct admin_connect_set_daemon_timeout_args { unsigned int flags; }; =20 +struct admin_connect_daemon_shutdown_args { + unsigned int flags; +}; + /* Define the program number, protocol version and procedure numbers here.= */ const ADMIN_PROGRAM =3D 0x06900690; const ADMIN_PROTOCOL_VERSION =3D 1; @@ -334,5 +338,10 @@ enum admin_procedure { /** * @generate: both */ - ADMIN_PROC_CONNECT_SET_DAEMON_TIMEOUT =3D 19 + ADMIN_PROC_CONNECT_SET_DAEMON_TIMEOUT =3D 19, + + /** + * @generate: both + */ + ADMIN_PROC_CONNECT_DAEMON_SHUTDOWN =3D 20 }; diff --git a/src/admin/admin_server_dispatch.c b/src/admin/admin_server_dis= patch.c index ae8a8d4fa6..092cc790e6 100644 --- a/src/admin/admin_server_dispatch.c +++ b/src/admin/admin_server_dispatch.c @@ -474,6 +474,19 @@ adminConnectSetDaemonTimeout(virNetDaemon *dmn, return virNetDaemonAutoShutdown(dmn, timeout); } =20 +static int +adminConnectDaemonShutdown(virNetDaemon *dmn, + unsigned int flags) +{ + virCheckFlags(VIR_DAEMON_SHUTDOWN_PRESERVE, -1); + + if (flags & VIR_DAEMON_SHUTDOWN_PRESERVE) + virNetDaemonPreserve(dmn); + + virNetDaemonQuit(dmn); + + return 0; +} =20 static int adminDispatchConnectGetLoggingOutputs(virNetServer *server G_GNUC_UNUSED, diff --git a/src/admin/libvirt-admin.c b/src/admin/libvirt-admin.c index 3c756eb376..1e2446135c 100644 --- a/src/admin/libvirt-admin.c +++ b/src/admin/libvirt-admin.c @@ -1357,3 +1357,36 @@ virAdmConnectSetDaemonTimeout(virAdmConnectPtr conn, =20 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.0.0 + */ +int +virAdmConnectDaemonShutdown(virAdmConnectPtr conn, + unsigned int flags) +{ + int ret; + + VIR_DEBUG("conn=3D%p, flags=3D0x%x", conn, flags); + + virResetLastError(); + virCheckAdmConnectReturn(conn, -1); + + if ((ret =3D remoteAdminConnectDaemonShutdown(conn, flags)) < 0) { + virDispatchError(NULL); + return -1; + } + + return ret; +} diff --git a/src/admin/libvirt_admin_public.syms b/src/admin/libvirt_admin_= public.syms index 17930e4fac..d39656bc53 100644 --- a/src/admin/libvirt_admin_public.syms +++ b/src/admin/libvirt_admin_public.syms @@ -53,3 +53,8 @@ LIBVIRT_ADMIN_8.6.0 { global: virAdmConnectSetDaemonTimeout; } LIBVIRT_ADMIN_3.0.0; + +LIBVIRT_ADMIN_11.0.0 { + global: + virAdmConnectDaemonShutdown; +} LIBVIRT_ADMIN_8.6.0; diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c index d1d7bae569..8cc7af1182 100644 --- a/src/rpc/virnetdaemon.c +++ b/src/rpc/virnetdaemon.c @@ -815,8 +815,10 @@ virNetDaemonRun(virNetDaemon *dmn) } } =20 + VIR_DEBUG("Main loop exited"); if (dmn->graceful) { virThreadJoin(&shutdownThread); + VIR_DEBUG("Graceful shutdown complete"); } else { VIR_WARN("Make forcefull daemon shutdown"); exit(EXIT_FAILURE); @@ -946,6 +948,8 @@ virNetDaemonSetShutdownCallbacks(virNetDaemon *dmn, { VIR_LOCK_GUARD lock =3D virObjectLockGuard(dmn); =20 + VIR_DEBUG("Shutdown callbacks preserve=3D%p prepare=3D%p wait=3D%p", + preserveCb, prepareCb, waitCb); dmn->shutdownPreserveCb =3D preserveCb; dmn->shutdownPrepareCb =3D prepareCb; dmn->shutdownWaitCb =3D waitCb; diff --git a/tools/virt-admin.c b/tools/virt-admin.c index 325b7aa827..54dc36a564 100644 --- a/tools/virt-admin.c +++ b/tools/virt-admin.c @@ -1077,6 +1077,41 @@ cmdDaemonTimeout(vshControl *ctl, const vshCmd *cmd) } =20 =20 +/* -------------------------- + * Command daemon-shutdown + * -------------------------- + */ +static const vshCmdInfo info_daemon_shutdown =3D { + .help =3D N_("stop the daemon"), + .desc =3D N_("stop the daemon"), +}; + +static const vshCmdOptDef opts_daemon_shutdown[] =3D { + {.name =3D "preserve", + .type =3D VSH_OT_BOOL, + .required =3D false, + .positional =3D false, + .help =3D N_("preserve state before shutting down"), + }, + {.name =3D NULL} +}; + +static bool +cmdDaemonShutdown(vshControl *ctl, const vshCmd *cmd) +{ + vshAdmControl *priv =3D ctl->privData; + unsigned int flags =3D 0; + + if (vshCommandOptBool(cmd, "preserve")) + flags |=3D 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[] =3D { .info =3D &info_daemon_timeout, .flags =3D 0 }, + {.name =3D "daemon-shutdown", + .handler =3D cmdDaemonShutdown, + .opts =3D opts_daemon_shutdown, + .info =3D &info_daemon_shutdown, + .flags =3D 0 + }, {.name =3D NULL} }; =20 --=20 2.47.1