From nobody Sun Dec 14 06:38:14 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=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1751547340; cv=none; d=zohomail.com; s=zohoarc; b=RXJgjP9G9zI0jcdpIPOh0Z/lFMTAIi+FGjG1OPs6iodkcS9YUbQkB8nK0jhBnoAggo74lixS8QYra0JHWPgHR/06HZsyNM9mPvCK8+X5dpyLBhME6v5L7RSfRULmjWMi1rTB+ZjEEszX9bwtfNzUOH/Ksb59/qe2UZRCUQXrQwA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751547340; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=y/KI61ctMFGX/KAQc3iWo2wsaxaDqz1jn/wHf+R6Mjk=; b=SGN8iiN08/9TdLhknp4XVLOZsCIVlDZt3RRlxZHg6S6obF7cwZRBxaJpFzOGzy8w/2kBcbxUnFe2Oo3FkSXg4qGC8eYypC1BZfeoWZkle4d72zSORWsbWpmvL3aP/FJvPkZtNIIJvOBR6QtheRdGMQYigHQHEvF03m7R9DgMrmg= ARC-Authentication-Results: i=1; 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=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1751547340213208.04466628247326; Thu, 3 Jul 2025 05:55:40 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 3D336A46; Thu, 3 Jul 2025 08:55:39 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id A2EB811EF; Thu, 3 Jul 2025 08:51:15 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 379D7A79; Thu, 3 Jul 2025 08:51:09 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.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 572B511C4 for ; Thu, 3 Jul 2025 08:50:51 -0400 (EDT) Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-17-3906mbzpPlGfzNuyZp1oRA-1; Thu, 03 Jul 2025 08:50:49 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D9FBD1808985 for ; Thu, 3 Jul 2025 12:50:48 +0000 (UTC) Received: from speedmetal.redhat.com (unknown [10.45.242.5]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 1FE45195608F for ; Thu, 3 Jul 2025 12:50:47 +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.8 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL,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=1751547051; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hV1WGN17cjtsvZIi6o0se0yqjvQWomCebvKEyKxX23Y=; b=VvdueWVzt7r/aPlCs2kFCnd92xXOZaIqIqMotR1lbPmyeZI2VUcMtUJe0kUiii/hFH7+N7 WpeQKnIhMZMvarm1FF2Ic3/H9QqzxXf0YnJf2KVolgeZ6+S3dAux6PaFCRnfMaXIa9l7XD 9e2s5wqmmHFzf+LATmZPoEBvIOkrVCI= X-MC-Unique: 3906mbzpPlGfzNuyZp1oRA-1 X-Mimecast-MFC-AGG-ID: 3906mbzpPlGfzNuyZp1oRA_1751547049 To: devel@lists.libvirt.org Subject: [PATCH 10/10] virDomainDriverAutoShutdown: Refactor selection logic for VMs Date: Thu, 3 Jul 2025 14:50:33 +0200 Message-ID: <44335670757faca58cec48c7dac36472c1912f4e.1751546915.git.pkrempa@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: r3Vr8skWxAvxwr85EotwGUlP9j1csD-kF7y6aWS2XoU_1751547049 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: RCNG3WDYHGB4M7EO5NGR264W3RRQWB7F X-Message-ID-Hash: RCNG3WDYHGB4M7EO5NGR264W3RRQWB7F X-MailFrom: pkrempa@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: From: Peter Krempa via Devel Reply-To: Peter Krempa X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1751547340947116600 Content-Type: text/plain; charset="utf-8" From: Peter Krempa Decide separately and record what shutdown modes are to be applied on given VM object rather than spreading out the logic through the code. This centralization simplifies the conditions in the worker functions and also: - provides easy way to check if the auto-shutdown code will be acting on domain object (will be used to fix attempt to auto-restore of VMs which were not selected to be acted on - will simplify further work where the desired shutdown action will be picked per-VM This refactor also fixes a bug where if restoring of the state is applied also on VMs that are not selected for action based on current logic. Signed-off-by: Peter Krempa Reviewed-by: Pavel Hrdina --- src/hypervisor/domain_driver.c | 176 +++++++++++++++++++-------------- 1 file changed, 100 insertions(+), 76 deletions(-) diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c index d8ccee40d5..7f958c087f 100644 --- a/src/hypervisor/domain_driver.c +++ b/src/hypervisor/domain_driver.c @@ -738,25 +738,32 @@ virDomainDriverAutoShutdownActive(virDomainDriverAuto= ShutdownConfig *cfg) } +enum { + VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SAVE =3D 1 >> 1, + VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SHUTDOWN =3D 1 >> 2, + VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_POWEROFF =3D 1 >> 3, + VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_RESTORE =3D 1 >> 4, +} virDomainDriverAutoShutdownModeFlag; + + static void virDomainDriverAutoShutdownDoSave(virDomainPtr *domains, - bool *transient, + unsigned int *modes, size_t numDomains, virDomainDriverAutoShutdownConfig *cfg) { g_autofree unsigned int *flags =3D g_new0(unsigned int, numDomains); + bool hasSave =3D false; size_t i; - if (cfg->trySave =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE) - return; - for (i =3D 0; i < numDomains; i++) { int state; - if ((transient[i] && cfg->trySave =3D=3D VIR_DOMAIN_DRIVER_AUTO_SH= UTDOWN_SCOPE_PERSISTENT) || - (!transient[i] && cfg->trySave =3D=3D VIR_DOMAIN_DRIVER_AUTO_S= HUTDOWN_SCOPE_TRANSIENT)) + if (!(modes[i] & VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SAVE)) continue; + hasSave =3D true; + virSystemdNotifyStatus("Suspending '%s' (%zu of %zu)", virDomainGetName(domains[i]), i + 1, numDom= ains); VIR_INFO("Suspending '%s'", virDomainGetName(domains[i])); @@ -778,9 +785,11 @@ virDomainDriverAutoShutdownDoSave(virDomainPtr *domain= s, virDomainSuspend(domains[i]); } + if (!hasSave) + return; + for (i =3D 0; i < numDomains; i++) { - if ((transient[i] && cfg->trySave =3D=3D VIR_DOMAIN_DRIVER_AUTO_SH= UTDOWN_SCOPE_PERSISTENT) || - (!transient[i] && cfg->trySave =3D=3D VIR_DOMAIN_DRIVER_AUTO_S= HUTDOWN_SCOPE_TRANSIENT)) + if (!(modes[i] & VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SAVE)) continue; virSystemdNotifyStatus("Saving '%s' (%zu of %zu)", @@ -795,31 +804,27 @@ virDomainDriverAutoShutdownDoSave(virDomainPtr *domai= ns, virDomainResume(domains[i]); continue; } - virObjectUnref(domains[i]); - domains[i] =3D NULL; + + modes[i] =3D 0; } } static void virDomainDriverAutoShutdownDoShutdown(virDomainPtr *domains, - bool *transient, + unsigned int *modes, size_t numDomains, virDomainDriverAutoShutdownConfig *c= fg) { GTimer *timer =3D NULL; + bool hasShutdown =3D false; size_t i; - if (cfg->tryShutdown =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE) - return; - for (i =3D 0; i < numDomains; i++) { - if (domains[i] =3D=3D NULL) + if (!(modes[i] & VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SHUTDOWN)) continue; - if ((transient[i] && cfg->tryShutdown =3D=3D VIR_DOMAIN_DRIVER_AUT= O_SHUTDOWN_SCOPE_PERSISTENT) || - (!transient[i] && cfg->tryShutdown =3D=3D VIR_DOMAIN_DRIVER_AU= TO_SHUTDOWN_SCOPE_TRANSIENT)) - continue; + hasShutdown =3D true; virSystemdNotifyStatus("Shutting down '%s' (%zu of %zu)", virDomainGetName(domains[i]), i + 1, numDom= ains); @@ -833,25 +838,24 @@ virDomainDriverAutoShutdownDoShutdown(virDomainPtr *d= omains, } } + if (!hasShutdown) + return; + timer =3D g_timer_new(); virSystemdNotifyStatus("Waiting %u secs for VM shutdown completion", cfg->waitShutdownSecs); VIR_INFO("Waiting %u secs for VM shutdown completion", cfg->waitShutdo= wnSecs); + while (1) { bool anyRunning =3D false; for (i =3D 0; i < numDomains; i++) { - if (!domains[i]) - continue; - - if ((transient[i] && cfg->tryShutdown =3D=3D VIR_DOMAIN_DRIVER= _AUTO_SHUTDOWN_SCOPE_PERSISTENT) || - (!transient[i] && cfg->tryShutdown =3D=3D VIR_DOMAIN_DRIVE= R_AUTO_SHUTDOWN_SCOPE_TRANSIENT)) + if (!(modes[i] & VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SHUTDOWN= )) continue; if (virDomainIsActive(domains[i]) =3D=3D 1) { anyRunning =3D true; } else { - virObjectUnref(domains[i]); - domains[i] =3D NULL; + modes[i] =3D 0; } } @@ -867,21 +871,13 @@ virDomainDriverAutoShutdownDoShutdown(virDomainPtr *d= omains, static void virDomainDriverAutoShutdownDoPoweroff(virDomainPtr *domains, - bool *transient, - size_t numDomains, - virDomainDriverAutoShutdownConfig *c= fg) + unsigned int *modes, + size_t numDomains) { size_t i; - if (cfg->poweroff =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_NONE) - return; - for (i =3D 0; i < numDomains; i++) { - if (domains[i] =3D=3D NULL) - continue; - - if ((transient[i] && cfg->poweroff =3D=3D VIR_DOMAIN_DRIVER_AUTO_S= HUTDOWN_SCOPE_PERSISTENT) || - (!transient[i] && cfg->poweroff =3D=3D VIR_DOMAIN_DRIVER_AUTO_= SHUTDOWN_SCOPE_TRANSIENT)) + if (!(modes[i] & VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_POWEROFF)) continue; virSystemdNotifyStatus("Destroying '%s' (%zu of %zu)", @@ -894,11 +890,49 @@ virDomainDriverAutoShutdownDoPoweroff(virDomainPtr *d= omains, */ virDomainDestroy(domains[i]); - virObjectUnref(domains[i]); - domains[i] =3D NULL; + modes[i] =3D 0; } } +static unsigned int +virDomainDriverAutoShutdownGetMode(virDomainPtr domain, + virDomainDriverAutoShutdownConfig *cfg) +{ + unsigned int mode =3D 0; + + if (virDomainIsPersistent(domain) =3D=3D 0) { + if (cfg->trySave =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_ALL = || + cfg->trySave =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PERS= ISTENT) + mode |=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SAVE; + + if (cfg->tryShutdown =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_= ALL || + cfg->tryShutdown =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_= PERSISTENT) + mode |=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SHUTDOWN; + + if (cfg->poweroff =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_ALL= || + cfg->poweroff =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_PER= SISTENT) + mode |=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_POWEROFF; + + /* Don't restore VMs which weren't selected for auto-shutdown */ + if (mode !=3D 0 && cfg->autoRestore) + mode |=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_RESTORE; + } else { + if (cfg->tryShutdown =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_= ALL || + cfg->tryShutdown =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_= TRANSIENT) + mode |=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_SHUTDOWN; + + if (cfg->poweroff =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_ALL= || + cfg->poweroff =3D=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_SCOPE_TRA= NSIENT) + mode |=3D VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_POWEROFF; + + if (cfg->autoRestore) + VIR_DEBUG("Cannot auto-restore transient VM '%s'", + virDomainGetName(domain)); + } + + return mode; +} + void virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg) @@ -907,7 +941,7 @@ virDomainDriverAutoShutdown(virDomainDriverAutoShutdown= Config *cfg) int numDomains =3D 0; size_t i; virDomainPtr *domains =3D NULL; - g_autofree bool *transient =3D NULL; + g_autofree unsigned int *modes =3D NULL; VIR_DEBUG("Run autoshutdown uri=3D%s trySave=3D%s tryShutdown=3D%s pow= eroff=3D%s waitShutdownSecs=3D%u saveBypassCache=3D%d autoRestore=3D%d", cfg->uri, @@ -948,58 +982,48 @@ virDomainDriverAutoShutdown(virDomainDriverAutoShutdo= wnConfig *cfg) return; if (!(conn =3D virConnectOpen(cfg->uri))) - goto cleanup; + return; if ((numDomains =3D virConnectListAllDomains(conn, &domains, VIR_CONNECT_LIST_DOMAINS_AC= TIVE)) < 0) - goto cleanup; + return; VIR_DEBUG("Auto shutdown with %d running domains", numDomains); - transient =3D g_new0(bool, numDomains); + modes =3D g_new0(unsigned int, numDomains); + for (i =3D 0; i < numDomains; i++) { - if (virDomainIsPersistent(domains[i]) =3D=3D 0) - transient[i] =3D true; + modes[i] =3D virDomainDriverAutoShutdownGetMode(domains[i], cfg); - if (cfg->autoRestore) { - if (transient[i]) { - VIR_DEBUG("Cannot auto-restore transient VM %s", - virDomainGetName(domains[i])); - } else { - VIR_DEBUG("Mark %s for autostart on next boot", - virDomainGetName(domains[i])); - if (virDomainSetAutostartOnce(domains[i], 1) < 0) { - VIR_WARN("Unable to mark domain '%s' for auto restore:= %s", - virDomainGetName(domains[i]), - virGetLastErrorMessage()); - } + if (modes[i] =3D=3D 0) { + /* VM wasn't selected for any of the shutdown modes. There's n= ot + * much we can do about that as the host is powering off, logg= ing + * at least lets admins know */ + VIR_WARN("auto-shutdown: domain '%s' not successfully shut off= by any action", + domains[i]->name); + } + + if (modes[i] & VIR_DOMAIN_DRIVER_AUTO_SHUTDOWN_MODE_RESTORE) { + VIR_DEBUG("Mark %s for autostart on next boot", + virDomainGetName(domains[i])); + if (virDomainSetAutostartOnce(domains[i], 1) < 0) { + VIR_WARN("Unable to mark domain '%s' for auto restore: %s", + virDomainGetName(domains[i]), + virGetLastErrorMessage()); } } } - virDomainDriverAutoShutdownDoSave(domains, transient, numDomains, cfg); - virDomainDriverAutoShutdownDoShutdown(domains, transient, numDomains, = cfg); - virDomainDriverAutoShutdownDoPoweroff(domains, transient, numDomains, = cfg); + virDomainDriverAutoShutdownDoSave(domains, modes, numDomains, cfg); + virDomainDriverAutoShutdownDoShutdown(domains, modes, numDomains, cfg); + virDomainDriverAutoShutdownDoPoweroff(domains, modes, numDomains); virSystemdNotifyStatus("Processed %d domains", numDomains); VIR_INFO("Processed %d domains", numDomains); - cleanup: - if (domains) { - /* Anything non-NULL in this list indicates none of - * the configured ations were successful in processing - * the domain. There's not much we can do about that - * as the host is powering off, logging at least lets - * admins know - */ - for (i =3D 0; i < numDomains; i++) { - if (domains[i] =3D=3D NULL) - continue; - VIR_WARN("auto-shutdown: domain '%s' not successfully shut off= by any action", - domains[i]->name); - virObjectUnref(domains[i]); - } - VIR_FREE(domains); - } + for (i =3D 0; i < numDomains; i++) + virObjectUnref(domains[i]); + + VIR_FREE(domains); } --=20 2.49.0