From nobody Sun Oct 5 01:50:00 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=1758791338; cv=none; d=zohomail.com; s=zohoarc; b=lBwXWsMR4mMaE6eJroB+OA8ttxLEKaFPQjbPcv006ILNjc2bB5rJ3ICwet9Dk4YEd5sYRHC+WrzGibYVp5awu1FhX2PwJxBe3v+qdy3udZCYQNaaG74V+sPHMu/4F4T5qoaRQG7lVSeLVnda5yOT1SjlROTEnBJp2m9SDe8zfSc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1758791338; 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:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id; bh=kqVGcXFR4T38RbP1r5MOgBpXI3OHTtWZ7Y9EaUOEl1o=; b=PL1++YVJIYmEyqNwxWnFvdDuDfvUtTf9TNTtLiYznp2MCep6cA8jgfFpHIrWr9pqkdrujuq+idbwVOQetFEsd6YLcCv8ClCkc6odl00tY3texbKkFfgYZ3kaC8+3CcZp04DTVrckXNdyWrdGykKVZiJxxVw+Z+p6vzNE+KEW69g= 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 17587913384083.998483505586478; Thu, 25 Sep 2025 02:08:58 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 993) id 7A7D741B30; Thu, 25 Sep 2025 05:08:57 -0400 (EDT) Received: from [172.19.199.14] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 38B0D43FAD; Thu, 25 Sep 2025 04:56:59 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 993) id 1BD3E41C95; Thu, 25 Sep 2025 04:56:46 -0400 (EDT) Received: from relay.virtuozzo.com (relay.virtuozzo.com [130.117.225.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 82E9341C95 for ; Thu, 25 Sep 2025 04:56:37 -0400 (EDT) Received: from [130.117.225.5] (helo=dev012.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1v1hlu-00DyxO-30; Thu, 25 Sep 2025 10:56:34 +0200 X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-3.1 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-ID:Date:Subject:From: Content-Type; bh=kqVGcXFR4T38RbP1r5MOgBpXI3OHTtWZ7Y9EaUOEl1o=; b=GDmVxd3BlIrh 5BMa057QewLTRVdf++YgYGxov7TD+jf/zng2wtTSdGfNi9bp2CcWStOuXykyc6kFduwM6c60j3Hxp 8tL0sULt55Y790ULtJwFsEraZ83mnp+8CD97njm+GoJQczi6JjkndE/JX05fw8Z5CIxAoOjbiTCIf OJR21X99xYXGiwdmKcumHc3qMbU0wQnI33bwsI0+bT+JG9bQWK3DFhcJLbX8bF1ibBpkg18aIE6Y0 7gHrRcSwYoObNj7mHp37M0fF/KJS5nByWYEe9Uk/qtegTelanqIhNNh5dwRC0TeUFpD2KLvdVopJq hqZi+vJGkxztFvTjHC9qRQ==; To: devel@lists.libvirt.org Subject: [PATCH 3/3] tools: virsh: introduce blockrebase-params cmd Date: Thu, 25 Sep 2025 11:53:11 +0300 Message-ID: <20250925085627.102886-4-nikolai.barybin@virtuozzo.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250925085627.102886-1-nikolai.barybin@virtuozzo.com> References: <20250925085627.102886-1-nikolai.barybin@virtuozzo.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Message-ID-Hash: YK3EEYQNXQOVREUNR3IPZB55KDDDCAN4 X-Message-ID-Hash: YK3EEYQNXQOVREUNR3IPZB55KDDDCAN4 X-MailFrom: nikolai.barybin@virtuozzo.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: den@virtuozzo.com 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: From: Nikolai Barybin via Devel Reply-To: Nikolai Barybin X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1758791341006116600 Content-Type: text/plain; charset="utf-8" Signed-off-by: Nikolai Barybin --- docs/manpages/virsh.rst | 39 ++++++++++ tools/virsh-domain.c | 160 ++++++++++++++++++++++++++++++++++++++++ tools/vsh.c | 14 ++++ tools/vsh.h | 2 + 4 files changed, 215 insertions(+) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index bcb5495ed9..16c4f5d28d 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -1626,6 +1626,45 @@ on the *bandwidth* argument see the corresponding se= ction for the ``blockjob`` command. =20 =20 +blockrebase-params +------------------ + +**Syntax:** + +:: + + blockrebase-params domain path [bandwidth] [base] + [--wait [--verbose] [--timeout seconds] [--async]] + [--keep-relative] + +Populate a disk from its backing image chain. By default, this command +flattens the entire chain; but if *base* is specified, containing the +name of one of the backing files in the chain, then that file becomes +the new backing file and only the intermediate portion of the chain is +pulled. Once all requested data from the backing image chain has been +pulled, the disk no longer depends on that portion of the backing chain. + +By default, this command returns as soon as possible, and data for +the entire disk is pulled in the background; the progress of the +operation can be checked with ``blockjob``. However, if *--wait* is +specified, then this command will block until the operation completes, +or cancel the operation if the optional *timeout* in seconds elapses +or SIGINT is sent (usually with ``Ctrl-C``). Using *--verbose* along +with *--wait* will produce periodic status updates. If job cancellation +is triggered, *--async* will return control to the user as fast as +possible, otherwise the command may continue to block a little while +longer until the job is done cleaning up. + +Using the *--keep-relative* flag will keep the backing chain names +relative. + +*path* specifies fully-qualified path of the disk; it corresponds +to a unique target name () or source file () for one of the disk devices attached to *domain* (see +also ``domblklist`` for listing these names). +*bandwidth* specifies copying bandwidth limit in Bytes/s. + + blockresize ----------- =20 diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 6e18d195e6..9023f8f72d 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -3306,6 +3306,160 @@ cmdBlockpull(vshControl *ctl, const vshCmd *cmd) return ret; } =20 +/* + * "blockrebase-params" command + */ +static const vshCmdInfo info_blockrebase_params =3D { + .help =3D N_("Populate a disk from its backing image."), + .desc =3D N_("Populate a disk from its backing image."), +}; + +static const vshCmdOptDef opts_blockrebase_params[] =3D { + VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE), + {.name =3D "path", + .type =3D VSH_OT_STRING, + .positional =3D true, + .required =3D true, + .completer =3D virshDomainDiskTargetCompleter, + .help =3D N_("fully-qualified path of disk") + }, + {.name =3D "bandwidth", + .type =3D VSH_OT_INT, + .unwanted_positional =3D true, + .help =3D N_("bandwidth limit in bytes/s") + }, + {.name =3D "base", + .type =3D VSH_OT_STRING, + .unwanted_positional =3D true, + .completer =3D virshDomainBlockjobBaseTopCompleter, + .help =3D N_("path of backing file in chain specifying a new base") + }, + {.name =3D "wait", + .type =3D VSH_OT_BOOL, + .help =3D N_("wait for job to finish") + }, + {.name =3D "verbose", + .type =3D VSH_OT_BOOL, + .help =3D N_("with --wait, display the progress") + }, + {.name =3D "timeout", + .type =3D VSH_OT_INT, + .unwanted_positional =3D true, + .help =3D N_("with --wait, abort if rebase exceeds timeout (in second= s)") + }, + {.name =3D "async", + .type =3D VSH_OT_BOOL, + .help =3D N_("with --wait, don't wait for cancel to finish") + }, + {.name =3D "keep-relative", + .type =3D VSH_OT_BOOL, + .help =3D N_("keep the backing chain relatively referenced") + }, + {.name =3D NULL} +}; + +static bool +cmdBlockrebaseParams(vshControl *ctl, const vshCmd *cmd) +{ + g_autoptr(virshDomain) dom =3D NULL; + bool ret =3D false; + bool blocking =3D vshCommandOptBool(cmd, "wait"); + bool verbose =3D vshCommandOptBool(cmd, "verbose"); + bool async =3D vshCommandOptBool(cmd, "async"); + int timeout =3D 0; + const char *path =3D NULL; + const char *base =3D NULL; + unsigned long long bandwidth =3D 0; + unsigned int flags =3D 0; + virshBlockJobWaitData *bjWait =3D NULL; + int nparams =3D 0; + int maxparams =3D 0; + virTypedParameterPtr params =3D NULL; + + VSH_REQUIRE_OPTION("verbose", "wait"); + VSH_REQUIRE_OPTION("async", "wait"); + + if (vshCommandOptString(ctl, cmd, "path", &path) < 0) + return false; + + if (vshCommandOptString(ctl, cmd, "base", &base) < 0) + return false; + + if (vshBlockRebaseParamsOptionBandwidth(cmd, &bandwidth) < 0) + return false; + + if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) + return false; + + if (vshCommandOptBool(cmd, "keep-relative")) + flags |=3D VIR_DOMAIN_BLOCK_REBASE_PARAMS_RELATIVE; + + if (!(dom =3D virshCommandOptDomain(ctl, cmd, NULL))) + return false; + + if (blocking && + !(bjWait =3D virshBlockJobWaitInit(ctl, dom, path, _("Block Rebase= Params"), + verbose, timeout, async))) + goto cleanup; + + if (base && + virTypedParamsAddString(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLOCK_REBASE_PARAM_BASE, + base) < 0) { + vshError(ctl, _("failed to add param %1$s:%2$s to params list"), + VIR_DOMAIN_BLOCK_REBASE_PARAM_BASE, base); + goto cleanup; + } + + if (bandwidth > 0 && + virTypedParamsAddULLong(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLOCK_REBASE_PARAM_BANDWIDTH, + bandwidth) < 0) { + vshError(ctl, _("failed to add param %1$s:%2$llu to params list"), + VIR_DOMAIN_BLOCK_REBASE_PARAM_BANDWIDTH, bandwidth); + goto cleanup; + } + + if (virDomainBlockRebaseParams(dom, path, params, nparams, flags) < 0) + goto cleanup; + + if (!blocking) { + vshPrintExtra(ctl, "%s", _("Block Rebase started")); + ret =3D true; + goto cleanup; + } + + /* Execution continues here only if --wait or friends were specified */ + switch (virshBlockJobWait(bjWait)) { + case -1: + goto cleanup; + + case VIR_DOMAIN_BLOCK_JOB_CANCELED: + vshPrintExtra(ctl, "\n%s", _("Rebase aborted")); + goto cleanup; + break; + + case VIR_DOMAIN_BLOCK_JOB_FAILED: + vshPrintExtra(ctl, "\n%s", _("Rebase failed")); + goto cleanup; + break; + + case VIR_DOMAIN_BLOCK_JOB_READY: + case VIR_DOMAIN_BLOCK_JOB_COMPLETED: + vshPrintExtra(ctl, "\n%s", _("Rebase complete")); + break; + } + + ret =3D true; + + cleanup: + virshBlockJobWaitFree(bjWait); + virTypedParamsFree(params, nparams); + params =3D NULL; + nparams =3D 0; + return ret; +} + /* * "blockresize" command */ @@ -13976,6 +14130,12 @@ const vshCmdDef domManagementCmds[] =3D { .info =3D &info_blockpull, .flags =3D 0 }, + {.name =3D "blockrebase-params", + .handler =3D cmdBlockrebaseParams, + .opts =3D opts_blockrebase_params, + .info =3D &info_blockrebase_params, + .flags =3D 0 + }, {.name =3D "blockresize", .handler =3D cmdBlockresize, .opts =3D opts_blockresize, diff --git a/tools/vsh.c b/tools/vsh.c index 4aacc5feac..480b54b572 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -1346,6 +1346,20 @@ vshBlockJobOptionBandwidth(vshControl *ctl, } =20 =20 +int +vshBlockRebaseParamsOptionBandwidth(const vshCmd *cmd, + unsigned long long *bandwidth) +{ + vshCmdOpt *arg; + int ret; + + if ((ret =3D vshCommandOpt(cmd, "bandwidth", &arg, true)) <=3D 0) + return ret; + + return virStrToLong_ull(arg->data, NULL, 10, bandwidth); +} + + /** * vshCommandRun: * @ctl: virt shell data diff --git a/tools/vsh.h b/tools/vsh.h index bd2494e899..0f79c32d41 100644 --- a/tools/vsh.h +++ b/tools/vsh.h @@ -287,6 +287,8 @@ int vshBlockJobOptionBandwidth(vshControl *ctl, const vshCmd *cmd, bool bytes, unsigned long *bandwidth); +int vshBlockRebaseParamsOptionBandwidth(const vshCmd *cmd, + unsigned long long *bandwidth); bool vshCommandOptBool(const vshCmd *cmd, const char *name); int vshCommandRun(vshControl *ctl, const vshCmd *cmd); bool vshCommandStringParse(vshControl *ctl, char *cmdstr, --=20 2.43.5