From nobody Mon Sep 14 04:49:23 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) client-ip=38.145.34.151; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1787773071; cv=none; d=zohomail.com; s=zohoarc; b=gVg4NvbXxFcWusqklP5kP70zeTisIhd7stQKpYJ5yyzhUIyC45prYXVRM+jZGv4jDJW9HRNs3L37g/swI2KE4EL70RgwNym+d2ZojlI2P1XsmpRdTyAiXHPJCiGz0yPKJYm2Ru1ZNoY39ViE9KLygHXVtiEKetSn6TVYgodDaK8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787773071; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=GvRtiN5lqa3vgVhZYkJePdCb4Qh5J/D4PJ0ZcpNonFs=; b=mNzhgpnQx8RxfPP4lqgmkuEy0oC7CDKQWgsvbbJ2Fb8L3BlT+scFEpWHm1V+UNjotff5R7lG3Rtt4POPE8nes46p0DNxdZH6k6kavzhSrsjoOj/NT6Lp3VLNI2NgvSA6lrY01pAp4XMKiE+QAdFld3c1uiR2xlT3OsswlMYzp5o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [38.145.34.151]) by mx.zohomail.com with SMTPS id 1787773071575215.19359130036844; Wed, 26 Aug 2026 12:37:51 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 993) id D911E3F881; Wed, 26 Aug 2026 15:37:49 -0400 (EDT) Received: from [172.19.199.13] (unknown [10.16.107.18]) by lists.libvirt.org (Postfix) with ESMTP id 7CA9441BA9 for ; Wed, 26 Aug 2026 15:36:26 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 993) id CE8D53F366; Wed, 26 Aug 2026 15:36:17 -0400 (EDT) Received: from fout-b6-smtp.messagingengine.com (fout-b6-smtp.messagingengine.com [202.12.124.149]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 8C5933F955 for ; Wed, 26 Aug 2026 15:36:16 -0400 (EDT) Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfout.stl.internal (Postfix) with ESMTP id CA6841D000E3; Wed, 26 Aug 2026 15:31:07 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-06.internal (MEProxy); Wed, 26 Aug 2026 15:31:07 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 26 Aug 2026 15:31:06 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-3.5 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_DNSWL_LOW,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shotor.com; h=cc :cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1787772667; x= 1787859067; bh=GvRtiN5lqa3vgVhZYkJePdCb4Qh5J/D4PJ0ZcpNonFs=; b=M OkCuCClIKpHe8vDbKTCw6p8ikRFFhMUfw+luW4OpybSWy9kMDeopxLsY5XEZNxRP divDPg8Jwk8IBZhVpT33j/z1oCqUi6+RVOZ4mbJY2OETID+8ab7fayfVB+maFiwZ lJnLLaXJZ+W11ZGZJRIDEdM0/nRtTwumSmp22hXQRTYd7aSq3NGAbDj3W3w6Sl06 QyATghXHoxjPvtWwMvv7dEy4gWjEXoUvxOHATmUMb0iJE5ofBlWCDV78YcH5dHe3 fWK3nLzRaPNWZsmJ6WhjdgLi0TFxfSTePvBwr9DO9CXDQ4rtZYkexBQo/4M4IOTe WCs/hnsJDWTIrn7YK8ALA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1787772667; x=1787859067; bh=G vRtiN5lqa3vgVhZYkJePdCb4Qh5J/D4PJ0ZcpNonFs=; b=HWWOAJZJU26OdRo0C 93AsEC4Q8CbGayUQHhmS+j93fS/oZWrlQuF7h6cjEiJBUzDk9SjPNHkINC4UOh0f l9P/CGd0DjWpX1OUUVfAA0EklQNub5Lhptr8ZPWrX86YH0YVf4MW1G+DQ627befm 86CwNAvGog4HR4pvKd5Tm8XlZdHyG/ynj44oz0op5iLuJaIN7b1MUg6nVZi2ZS/J 6duXq9AzSaVuqkRSTndb/FwnQtuCtZV4Q95oiqQZh03bKHn6h2mTbe9aj5q1pVbB sPOob0aqlY4gj6ZVQMnFOV+RlQL06paxm4/nx3EmorAnnB2LupVm90VGWgPGbtVr psf7A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFSgDNNh2YjSDXpJT63ZxSmQGXTBdCvdkEXWRXBkk5eUBUp7VfhQ6Y3zb1V6+BKCv 7KVkr0haa2ABJsx52wEpEVAPyeIjQmcLcl7slkNCrFbs0Zxts64MRfkDJAonJuRHhaEC7C s6VBnC8yNcGW8LVQbzWJ6fSI16X/EJMvbEUj4PjwUSH/uW5ThPezF6pyUx4Ihe5UMFoZFH WCPssgcug5JpoZ5fwNCHEVxhovMmVEtqJwvIByZpgYj4rX1AAyzJ7116n0NBUrs4QsN2Ym teJRBZkPq6eDvlCSp/G8zNuVtrVvjhemfX+tjwKfUIrFlUI3U75kzGLSshUGuMJ3+/ZssA 84iryyCy8zAfwsSO7AjeWg1aFQxS/AB1xZSSYb7BMC2caWBHfEQ5F4BJtEm7S6bHAntqMM UaC+zIKcj0Y/Fhb6WIaHVw5DZ1jGz68gIsGb0qUiaUg8rhgzxRnKEHipowsTMBCmb9i+vf VFk82dH+UFtya5xDXT2FtN9fELJtkvTJOKb6/8fNbVObrLWo8CHwNsWPFD7I3Asx5kZbS0 WZ/MtV3zLKqHN2qLy4a2X3A0jLuGbb9vZPN5kz2EwRTKBX0siexn05/Q2MJ15CiUfs6xTo LDJgEkd9+1X0If4bhdEuSneiri7DJYMdLmytZL61Nc7COAap/zVl4WYgWQ4g X-ME-Proxy: Feedback-ID: ib8694256:Fastmail From: shotor@shotor.com To: devel@lists.libvirt.org Subject: [PATCH] ch: Add persistent domain support Date: Wed, 26 Aug 2026 21:30:35 +0200 Message-ID: <20260826193035.3670721-1-shotor@shotor.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826084618.3447269-1-shotor@shotor.com> References: <20260826084618.3447269-1-shotor@shotor.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Message-ID-Hash: WG64GW7OWUVMMLT3RKPVELCPSUEYY34J X-Message-ID-Hash: WG64GW7OWUVMMLT3RKPVELCPSUEYY34J X-MailFrom: shotor@shotor.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: shotor X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: pass (identity @shotor.com) X-ZM-MESSAGEID: 1787773073757158500 Content-Type: text/plain; charset="utf-8" From: shotor Libvirt reports Cloud Hypervisor domains as having unknown persistence. Commit 85cf0e4f17ae added support for keeping a separate inactive definition for running domains, but it didn't persist domain definitions to disk or reload them when virtchd restarted. Meaning defined CH domains were still lost across daemon restarts and libvirt couldn't report them as persistent. Follow the approach used by the QEMU driver: save domain definitions to disk when they are defined, reload them during driver initialization, remove the stored configuration when they are undefined, and roll back the in-memory definition if saving fails. Also implement domainIsPersistent so libvirt reports the persistence state correctly. Signed-off-by: shotor --- src/ch/ch_conf.c | 13 +++++++--- src/ch/ch_conf.h | 1 + src/ch/ch_driver.c | 63 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/ch/ch_conf.c b/src/ch/ch_conf.c index 6896683b7f..793ec33a10 100644 --- a/src/ch/ch_conf.c +++ b/src/ch/ch_conf.c @@ -178,22 +178,26 @@ virCHDriverConfigNew(bool privileged) cfg->logDir =3D g_strdup_printf("%s/log/libvirt/ch", LOCALSTATEDIR= ); cfg->stateDir =3D g_strdup_printf("%s/libvirt/ch", RUNSTATEDIR); cfg->saveDir =3D g_strdup_printf("%s/lib/libvirt/ch/save", LOCALST= ATEDIR); - cfg->configDir =3D g_strdup(SYSCONFDIR "/libvirt"); + cfg->configBaseDir =3D g_strdup(SYSCONFDIR "/libvirt"); + cfg->configDir =3D g_strdup_printf("%s/ch/domains", + cfg->configBaseDir); } else { g_autofree char *rundir =3D NULL; g_autofree char *cachedir =3D NULL; - g_autofree char *configbasedir =3D NULL; + const char *configbasedir =3D NULL; =20 cachedir =3D virGetUserCacheDirectory(); - cfg->logDir =3D g_strdup_printf("%s/ch/log", cachedir); =20 rundir =3D virGetUserRuntimeDirectory(); cfg->stateDir =3D g_strdup_printf("%s/ch/run", rundir); =20 configbasedir =3D virGetUserConfigDirectory(); + cfg->saveDir =3D g_strdup_printf("%s/ch/save", configbasedir); - cfg->configDir =3D g_strdup_printf("%s/ch", configbasedir); + cfg->configBaseDir =3D g_strdup_printf("%s/ch", configbasedir); + cfg->configDir =3D g_strdup_printf("%s/domains", + cfg->configBaseDir); } =20 return cfg; @@ -211,6 +215,7 @@ virCHDriverConfigDispose(void *obj) virCHDriverConfig *cfg =3D obj; =20 g_free(cfg->stateDir); + g_free(cfg->configBaseDir); g_free(cfg->configDir); g_free(cfg->logDir); g_free(cfg->saveDir); diff --git a/src/ch/ch_conf.h b/src/ch/ch_conf.h index 1660762f2b..c3b59bba0d 100644 --- a/src/ch/ch_conf.h +++ b/src/ch/ch_conf.h @@ -51,6 +51,7 @@ struct _virCHDriverConfig { GObject parent; =20 char *stateDir; + char *configBaseDir; char *configDir; char *logDir; char *saveDir; diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c index f85f38eaf2..51c69b799a 100644 --- a/src/ch/ch_driver.c +++ b/src/ch/ch_driver.c @@ -336,11 +336,14 @@ chDomainCreate(virDomainPtr dom) } =20 static virDomainPtr -chDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int f= lags) +chDomainDefineXMLFlags(virConnectPtr conn, + const char *xml, + unsigned int flags) { virCHDriver *driver =3D conn->privateData; g_autoptr(virDomainDef) vmdef =3D NULL; g_autoptr(virDomainDef) oldDef =3D NULL; + g_autoptr(virCHDriverConfig) cfg =3D virCHDriverGetConfig(driver); virDomainObj *vm =3D NULL; virDomainPtr dom =3D NULL; virObjectEvent *event =3D NULL; @@ -382,15 +385,34 @@ chDomainDefineXMLFlags(virConnectPtr conn, const char= *xml, unsigned int flags) goto cleanup; } =20 + if (virDomainDefSave(vm->newDef ? vm->newDef : vm->def, + driver->xmlopt, + cfg->configDir) < 0) + goto cleanup; + vm->persistent =3D 1; + event =3D virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED, !oldDef ? VIR_DOMAIN_EVENT_DEFINED_ADD= ED : VIR_DOMAIN_EVENT_DEFINED_UPD= ATED); + dom =3D virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id); =20 cleanup: + if (!dom && !vmdef) { + if (oldDef) { + if (virDomainObjIsActive(vm)) + vm->newDef =3D oldDef; + else + vm->def =3D oldDef; + oldDef =3D NULL; + } else { + virCHDomainRemoveInactive(driver, vm); + } + } + virDomainObjEndAPI(&vm); virObjectEventStateQueue(driver->domainEventState, event); =20 @@ -408,6 +430,7 @@ chDomainUndefineFlags(virDomainPtr dom, unsigned int flags) { virCHDriver *driver =3D dom->conn->privateData; + g_autoptr(virCHDriverConfig) cfg =3D virCHDriverGetConfig(driver); virDomainObj *vm; virObjectEvent *event =3D NULL; int ret =3D -1; @@ -425,14 +448,18 @@ chDomainUndefineFlags(virDomainPtr dom, "%s", _("Cannot undefine transient domain")); goto cleanup; } + + if (virDomainDeleteConfig(cfg->configDir, NULL, vm) < 0) + goto cleanup; + event =3D virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED, VIR_DOMAIN_EVENT_UNDEFINED_R= EMOVED); =20 vm->persistent =3D 0; - if (!virDomainObjIsActive(vm)) { + + if (!virDomainObjIsActive(vm)) virCHDomainRemoveInactive(driver, vm); - } =20 ret =3D 0; =20 @@ -467,6 +494,24 @@ static int chDomainIsActive(virDomainPtr dom) return ret; } =20 +static int chDomainIsPersistent(virDomainPtr dom) +{ + virDomainObj *vm; + int ret =3D -1; + + if (!(vm =3D virCHDomainObjFromDomain(dom))) + goto cleanup; + + if (virDomainIsPersistentEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + ret =3D vm->persistent; + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + static int chDomainShutdownFlags(virDomainPtr dom, unsigned int flags) @@ -1493,11 +1538,20 @@ chStateInitialize(bool privileged, if (!(ch_driver->config =3D virCHDriverConfigNew(privileged))) goto cleanup; =20 - driverConf =3D g_strdup_printf("%s/ch.conf", ch_driver->config->config= Dir); + driverConf =3D g_strdup_printf("%s/ch.conf", ch_driver->config->config= BaseDir); =20 if (virCHDriverConfigLoadFile(ch_driver->config, driverConf) < 0) goto cleanup; =20 + if (virDomainObjListLoadAllConfigs(ch_driver->domains, + ch_driver->config->configDir, + NULL, + false, + ch_driver->xmlopt, + NULL, + NULL) < 0) + goto cleanup; + if (!(ch_driver->hostdevMgr =3D virHostdevManagerGetDefault())) goto cleanup; =20 @@ -2550,6 +2604,7 @@ static virHypervisorDriver chHypervisorDriver =3D { .domainGetXMLDesc =3D chDomainGetXMLDesc, /* 7.5.0 */ .domainGetInfo =3D chDomainGetInfo, /* 7.5.0 */ .domainIsActive =3D chDomainIsActive, /* 7.5.0 */ + .domainIsPersistent =3D chDomainIsPersistent, /* 12.7.0 */ .domainOpenConsole =3D chDomainOpenConsole, /* 7.8.0 */ .nodeGetInfo =3D chNodeGetInfo, /* 7.5.0 */ .domainGetVcpus =3D chDomainGetVcpus, /* 8.0.0 */ --=20 2.55.0