From nobody Sat Feb 7 17:19:41 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) client-ip=170.10.129.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1655393835; cv=none; d=zohomail.com; s=zohoarc; b=kHfeYoeJ07QsUduPsxtXmb2DfbsITNxmYeXOzZREFMtH3w9iwC9DAYId2/fhCUx+oM4tVVb2rQyhli+s6AVnbMPObaD0VkRJNzj+h4t9tEbeiM/sfhrh0HQgrfMjKbGrzeB+U7uS1Fli9O4ue10GGyXMJAvT9TmSFGXNKFyi8Ys= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1655393835; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=f6BphaxXhVWengZi4NZOzEenNVjz3vKvfyOmU0gCF48=; b=Z8+XZ4TWJrTz4nBJNxByIKFpnrcMl+DEE6xZn1+y5r4EsQoTnx05Y6l+ad+1YGdoM4wB5bEX+aaSE8pOInRlFlvd1K1D01G3RPKaZILMriZpS0Exio8kaWWfIhUBWXtxePbfsRWN4bcvEhwxbQS6MA7vbuRRWanH3BaguIz6pVo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by mx.zohomail.com with SMTPS id 1655393835733555.0924470964837; Thu, 16 Jun 2022 08:37:15 -0700 (PDT) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-19-bnSCpY42MciSj5gqe5sSaw-1; Thu, 16 Jun 2022 11:37:05 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 09C3F8339A2; Thu, 16 Jun 2022 15:37:01 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 977231415106; Thu, 16 Jun 2022 15:36:57 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 68974194705F; Thu, 16 Jun 2022 15:36:57 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 79240194706C for ; Thu, 16 Jun 2022 15:36:56 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 6BAE52166B29; Thu, 16 Jun 2022 15:36:56 +0000 (UTC) Received: from localhost.localdomain.com (unknown [10.33.36.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id B77D72166B26; Thu, 16 Jun 2022 15:36:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1655393834; h=from:from:sender:sender: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:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=f6BphaxXhVWengZi4NZOzEenNVjz3vKvfyOmU0gCF48=; b=NlUpjx01yG4VL5gDiokp8rgHHNlOynrpoVkFfTq7O1bpDhKlQ7Appuoizook4bh88eVwKo u/7rqgGGK70H2eA18xNd6D5+lnCExuh9IYlLlUfYPtY33XPm2eItumKc8tmIrJ+9MJ7q+I 11XwOzOHxj5VPDR9RPHC/gmM249Xerg= X-MC-Unique: bnSCpY42MciSj5gqe5sSaw-1 X-Original-To: libvir-list@listman.corp.redhat.com From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Subject: [libvirt PATCH 1/2] tools: add helper method for printing an XML document Date: Thu, 16 Jun 2022 16:36:52 +0100 Message-Id: <20220616153653.1046960-2-berrange@redhat.com> In-Reply-To: <20220616153653.1046960-1-berrange@redhat.com> References: <20220616153653.1046960-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Stephen Finucane Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 2.85 on 10.11.54.7 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1655393837632100001 The trivial case of fully printing an XML document is boring, but this helper does more by allowing an XPath expression to be given. It will then print just the subset of nodes which match the expression. It either print each match as a standalone XML doc or can put them into one new XML doc wrapped woith ... Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- tools/virsh-util.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh-util.h | 7 ++++++ 2 files changed, 66 insertions(+) diff --git a/tools/virsh-util.c b/tools/virsh-util.c index dc6ed7a86d..8b06091be8 100644 --- a/tools/virsh-util.c +++ b/tools/virsh-util.c @@ -437,3 +437,62 @@ virshDomainBlockJobToString(int type) const char *str =3D virshDomainBlockJobTypeToString(type); return str ? _(str) : _("Unknown job"); } + +bool +virshDumpXML(vshControl *ctl, + const char *xml, + const char *url, + const char *xpath, + bool wrap) +{ + g_autoptr(xmlDoc) doc =3D NULL; + g_autoptr(xmlXPathContext) ctxt =3D NULL; + g_autofree xmlNodePtr *nodes =3D NULL; + int nnodes =3D 0; + size_t i; + int oldblanks; + + if (xpath =3D=3D NULL) { + vshPrint(ctl, "%s", xml); + return true; + } + + oldblanks =3D xmlKeepBlanksDefault(0); + doc =3D virXMLParseString(xml, url); + xmlKeepBlanksDefault(oldblanks); + if (!doc) + return false; + + if (!(ctxt =3D virXMLXPathContextNew(doc))) + return false; + + if ((nnodes =3D virXPathNodeSet(xpath, ctxt, &nodes)) < 0) { + return false; + } + + if (wrap) { + g_autoptr(xmlDoc) newdoc =3D xmlNewDoc((xmlChar *)"1.0"); + xmlNodePtr newroot =3D xmlNewNode(NULL, (xmlChar *)"nodes"); + g_autofree char *xmlbit =3D NULL; + + xmlDocSetRootElement(newdoc, newroot); + + for (i =3D 0; i < nnodes; i++) { + g_autoptr(xmlNode) copy =3D xmlDocCopyNode(nodes[i], newdoc, 1= ); + if (!xmlAddChild(newroot, copy)) + return false; + + copy =3D NULL; + } + + xmlbit =3D virXMLNodeToString(doc, newroot); + vshPrint(ctl, "%s\n", xmlbit); + } else { + for (i =3D 0; i < nnodes; i++) { + g_autofree char *xmlbit =3D virXMLNodeToString(doc, nodes[i]); + vshPrint(ctl, "%s\n", xmlbit); + } + } + + return true; +} diff --git a/tools/virsh-util.h b/tools/virsh-util.h index 4d4fe6c01e..0f81a2771b 100644 --- a/tools/virsh-util.h +++ b/tools/virsh-util.h @@ -156,3 +156,10 @@ VIR_ENUM_DECL(virshDomainBlockJob); =20 const char * virshDomainBlockJobToString(int type); + +bool +virshDumpXML(vshControl *ctl, + const char *xml, + const char *url, + const char *xpath, + bool wrap); --=20 2.36.1 From nobody Sat Feb 7 17:19:41 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) client-ip=170.10.129.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1655393884; cv=none; d=zohomail.com; s=zohoarc; b=I5cqdT6WTweTpPZRtVgws7RUTaLaciiNqcFpDLBVW8uOC+YlrPnaPgZQ4cQacNj6kTjzbSVAA2xIb7G/5pyCC84JoNymaOExqm5jHYNbtoM0+jalC0fpBXaMcz5yzV2OPbALSeyX0DEYvFbC14ro3GyUJ52yaETft9fpxCjBeCA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1655393884; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=E4eb8OyIahnwwAYwG25taR+zM9JnqC/E+FYvTsA2pMI=; b=aGhZRox1OXsXbqpCcGVj6yYECRh42AZ++mUvoPpIgfnV2674uBjSb6ZMrHTlWU2IHWcUnbJ5/Sf+l841IJWCEcctc1wGoEwodhJPQGxLsXyL04+63nhoxvfxW14elsoonEBLEvjEeQyKNMd7wQxoCXhd9dCauNlio/tGEb0EnkE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by mx.zohomail.com with SMTPS id 1655393884031874.7031559555107; Thu, 16 Jun 2022 08:38:04 -0700 (PDT) Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-19-qmi6xCDHPhaFiALZ7QNONw-1; Thu, 16 Jun 2022 11:37:05 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 0CC203C0E223; Thu, 16 Jun 2022 15:37:01 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id F3E1410725; Thu, 16 Jun 2022 15:36:59 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id AEBDB1947061; Thu, 16 Jun 2022 15:36:59 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 2225E194705A for ; Thu, 16 Jun 2022 15:36:58 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 05BF12166B2C; Thu, 16 Jun 2022 15:36:58 +0000 (UTC) Received: from localhost.localdomain.com (unknown [10.33.36.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id AAE642166B29; Thu, 16 Jun 2022 15:36:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1655393882; h=from:from:sender:sender: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:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=E4eb8OyIahnwwAYwG25taR+zM9JnqC/E+FYvTsA2pMI=; b=L/Qo4qVcAgf66wQwZyjHcHkK104BuoFvjxCd4aWLyVq3NtsTzyjcnVWOfT83QRpGplxMYW Tyy++ZjK3tpL6r5+uzoEkTXB6skWPFYQRk5JL/HzRwh0i+QYKK/cTHOR3uEZa3G6KETmUO QORIdTuEeHvM7wpM+Qync+Qu8/eiJFA= X-MC-Unique: qmi6xCDHPhaFiALZ7QNONw-1 X-Original-To: libvir-list@listman.corp.redhat.com From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Subject: [libvirt PATCH 2/2] tools: add '--xpath EXPRESSION --wrap' args to all dumpxml commands Date: Thu, 16 Jun 2022 16:36:53 +0100 Message-Id: <20220616153653.1046960-3-berrange@redhat.com> In-Reply-To: <20220616153653.1046960-1-berrange@redhat.com> References: <20220616153653.1046960-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Stephen Finucane Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1655393885982100001 While you can chain the virsh output up to a later 'xmllint' or 'xpath' command, integrating it into virsh avoids needs for installing extra binaries which we've often found to be missing on production installs of libvirt. It also gives better response if the initial virsh command hits an error, as you don't get an aborted pipeline. $ virsh pool-dumpxml --xpath //permissions default 0711 1000 1000 If multiple nodes match, they are emitted individually: $ virsh dumpxml --xpath '//devices/*/address[@type=3D"pci"]' --wrap demo
...snip...
but if intending to post-process the output further, the results can be wrapped in a parent node $ virsh dumpxml --xpath '//devices/*/address[@type=3D"pci"]' --wrap demo
...snip...
Fixes https://gitlab.com/libvirt/libvirt/-/issues/244 Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- docs/manpages/virsh.rst | 138 ++++++++++++++++++++++++++++++++++----- tools/virsh-backup.c | 17 ++++- tools/virsh-checkpoint.c | 17 ++++- tools/virsh-domain.c | 55 +++++++++++++--- tools/virsh-interface.c | 22 +++++-- tools/virsh-network.c | 47 +++++++++---- tools/virsh-nodedev.c | 17 ++++- tools/virsh-nwfilter.c | 51 ++++++++++----- tools/virsh-pool.c | 27 +++++--- tools/virsh-secret.c | 18 ++++- tools/virsh-snapshot.c | 17 ++++- tools/virsh-volume.c | 28 +++++--- 12 files changed, 370 insertions(+), 84 deletions(-) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 580245adb1..4701791b04 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -1959,10 +1959,16 @@ backup-dumpxml =20 :: =20 - backup-dumpxml domain + backup-dumpxml [--xpath EXPRESSION] [--wrap] domain =20 Output XML describing the current backup job. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. =20 domiflist --------- @@ -2652,7 +2658,8 @@ dumpxml =20 :: =20 - dumpxml domain [--inactive] [--security-info] [--update-cpu] [--migrata= ble] + dumpxml [--inactive] [--security-info] [--update-cpu] [--migratable] + [--xpath EXPRESSION] [--wrap] domain =20 Output the domain information as an XML dump to stdout, this format can be= used by the ``create`` command. Additional options affecting the XML dump may be @@ -2665,6 +2672,13 @@ migrations, i.e., compatible with older libvirt rele= ases and possibly amended with internal run-time options. This option may automatically enable other options (*--update-cpu*, *--security-info*, ...) as necessary. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 edit ---- @@ -3090,12 +3104,19 @@ managedsave-dumpxml =20 :: =20 - managedsave-dumpxml domain [--security-info] + managedsave-dumpxml [--security-info] [--xpath EXPRESSION] [--wrap] dom= ain =20 Extract the domain XML that was in effect at the time the saved state file *file* was created with the ``managedsave`` command. Using *--security-info* will also include security sensitive information. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 managedsave-edit ---------------- @@ -3890,12 +3911,19 @@ save-image-dumpxml =20 :: =20 - save-image-dumpxml file [--security-info] + save-image-dumpxml [--security-info] [--xpath EXPRESSION] [--wrap] file =20 Extract the domain XML that was in effect at the time the saved state file *file* was created with the ``save`` command. Using *--security-info* will also include security sensitive information. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 save-image-edit --------------- @@ -5244,7 +5272,7 @@ nodedev-dumpxml =20 :: =20 - nodedev-dumpxml device + nodedev-dumpxml [--xpath EXPRESSION] [--wrap] device =20 Dump a XML representation for the given node device, including such information as the device name, which bus owns the device, the @@ -5253,6 +5281,13 @@ libvirt (such as whether device reset is supported).= *device* can be either device name or wwn pair in "wwnn,wwpn" format (only works for HBA). =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 nodedev-info ------------ @@ -5433,13 +5468,20 @@ net-dumpxml =20 :: =20 - net-dumpxml network [--inactive] + net-dumpxml [--inactive] [--xpath EXPRESSION] [--wrap] network =20 =20 Output the virtual network information as an XML dump to stdout. If *--inactive* is specified, then physical functions are not expanded into their associated virtual functions. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 net-edit -------- @@ -5695,10 +5737,17 @@ net-port-dumpxml =20 :: =20 - net-port-dumpxml network port + net-port-dumpxml [--xpath EXPRESSION] [--wrap] network port =20 Output the network port information as an XML dump to stdout. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 net-port-delete --------------- @@ -5782,12 +5831,19 @@ iface-dumpxml =20 :: =20 - iface-dumpxml interface [--inactive] + iface-dumpxml [--inactive] [--xpath EXPRESSION] [--wrap] interface =20 Output the host interface information as an XML dump to stdout. If *--inactive* is specified, then the output reflects the persistent state of the interface that will be used the next time it is started. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 iface-edit ---------- @@ -6258,12 +6314,19 @@ pool-dumpxml =20 :: =20 - pool-dumpxml [--inactive] pool-or-uuid + pool-dumpxml [--inactive] [--xpath EXPRESSION] [--wrap] pool-or-uuid =20 Returns the XML information about the *pool* object. *--inactive* tells virsh to dump pool configuration that will be used on next start of the pool as opposed to the current pool configuration. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 pool-edit --------- @@ -6750,7 +6813,8 @@ vol-dumpxml =20 :: =20 - vol-dumpxml vol-name-or-key-or-path [--pool pool-or-uuid] + vol-dumpxml [--pool pool-or-uuid] [--xpath EXPRESSION] [--wrap] + vol-name-or-key-or-path =20 Output the volume information as an XML dump to stdout. =20 @@ -6762,6 +6826,13 @@ is in. If the volume name is provided instead of the= key or path, then providing the pool is necessary to find the volume to be uploaded into; otherwise, the first volume found by the key or path will be used. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 vol-info -------- @@ -6949,10 +7020,17 @@ secret-dumpxml =20 :: =20 - secret-dumpxml secret + secret-dumpxml [--xpath EXPRESSION] [--wrap] secret =20 Output properties of *secret* (specified by its UUID) as an XML dump to st= dout. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 secret-event ------------ @@ -7370,12 +7448,20 @@ snapshot-dumpxml =20 :: =20 - snapshot-dumpxml domain snapshot [--security-info] + snapshot-dumpxml [--security-info] [--xpath EXPRESSION] [--wrap] + domain snapshot =20 Output the snapshot XML for the domain's snapshot named *snapshot*. Using *--security-info* will also include security sensitive information. Use ``snapshot-current`` to easily access the XML of the current snapshot. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 snapshot-parent --------------- @@ -7655,7 +7741,8 @@ checkpoint-dumpxml =20 :: =20 - checkpoint-dumpxml domain checkpoint [--security-info] [--no-domain] [-= -size] + checkpoint-dumpxml [--security-info] [--no-domain] [--size] + [--xpath EXPRESSION] [--wrap] domain checkpoint =20 Output the checkpoint XML for the domain's checkpoint named *checkpoint*. Using @@ -7671,6 +7758,13 @@ space). Note that some hypervisors may require that = *domain* is running when Using *--no-domain* will omit the element from the output for a more compact view. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 checkpoint-parent ----------------- @@ -7773,10 +7867,17 @@ nwfilter-dumpxml =20 :: =20 - nwfilter-dumpxml nwfilter-name + nwfilter-dumpxml [--xpath EXPRESSION] [--wrap] nwfilter-name =20 Output the network filter XML. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 nwfilter-edit ------------- @@ -7876,11 +7977,18 @@ nwfilter-binding-dumpxml =20 :: =20 - nwfilter-binding-dumpxml port-name + nwfilter-binding-dumpxml [--xpath EXPRESSION] [--wrap] port-name =20 Output the network filter binding XML for the network device called ``port-name``. =20 +If the **--xpath** argument provides an XPath expression, it will be +evaluated against the output XML and only those matching nodes will +be printed. The default behaviour is to print each matching node as +a standalone document, however, for ease of additional processing, +the **--wrap** argument will cause the matching node to be wrapped +in a common root node. + =20 HYPERVISOR-SPECIFIC COMMANDS =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D diff --git a/tools/virsh-backup.c b/tools/virsh-backup.c index 7bac1923a6..db122abc09 100644 --- a/tools/virsh-backup.c +++ b/tools/virsh-backup.c @@ -115,6 +115,15 @@ static const vshCmdInfo info_backup_dumpxml[] =3D { =20 static const vshCmdOptDef opts_backup_dumpxml[] =3D { VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE), + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -124,15 +133,19 @@ cmdBackupDumpXML(vshControl *ctl, { g_autoptr(virshDomain) dom =3D NULL; g_autofree char *xml =3D NULL; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 if (!(dom =3D virshCommandOptDomain(ctl, cmd, NULL))) return false; =20 + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) + return false; + if (!(xml =3D virDomainBackupGetXMLDesc(dom, 0))) return false; =20 - vshPrint(ctl, "%s", xml); - return true; + return virshDumpXML(ctl, xml, "domain-backup", xpath, wrap); } =20 =20 diff --git a/tools/virsh-checkpoint.c b/tools/virsh-checkpoint.c index 8ad37ece69..59f9b08e37 100644 --- a/tools/virsh-checkpoint.c +++ b/tools/virsh-checkpoint.c @@ -854,6 +854,15 @@ static const vshCmdOptDef opts_checkpoint_dumpxml[] = =3D { .type =3D VSH_OT_BOOL, .help =3D N_("include backup size estimate in XML dump") }, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -866,6 +875,8 @@ cmdCheckpointDumpXML(vshControl *ctl, g_autoptr(virshDomainCheckpoint) checkpoint =3D NULL; g_autofree char *xml =3D NULL; unsigned int flags =3D 0; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 if (vshCommandOptBool(cmd, "security-info")) flags |=3D VIR_DOMAIN_CHECKPOINT_XML_SECURE; @@ -877,6 +888,9 @@ cmdCheckpointDumpXML(vshControl *ctl, if (!(dom =3D virshCommandOptDomain(ctl, cmd, NULL))) return false; =20 + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) + return false; + if (virshLookupCheckpoint(ctl, cmd, "checkpointname", dom, &checkpoint, &name) < 0) return false; @@ -884,8 +898,7 @@ cmdCheckpointDumpXML(vshControl *ctl, if (!(xml =3D virDomainCheckpointGetXMLDesc(checkpoint, flags))) return false; =20 - vshPrint(ctl, "%s", xml); - return true; + return virshDumpXML(ctl, xml, "domain-checkpoint", xpath, wrap); } =20 =20 diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 06ed6ba9cf..1c9703563a 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -4528,6 +4528,15 @@ static const vshCmdOptDef opts_save_image_dumpxml[] = =3D { .type =3D VSH_OT_BOOL, .help =3D N_("include security sensitive information in XML dump") }, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -4538,6 +4547,8 @@ cmdSaveImageDumpxml(vshControl *ctl, const vshCmd *cm= d) unsigned int flags =3D 0; g_autofree char *xml =3D NULL; virshControl *priv =3D ctl->privData; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 if (vshCommandOptBool(cmd, "security-info")) flags |=3D VIR_DOMAIN_XML_SECURE; @@ -4545,12 +4556,14 @@ cmdSaveImageDumpxml(vshControl *ctl, const vshCmd *= cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &file) < 0) return false; =20 + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) + return false; + xml =3D virDomainSaveImageGetXMLDesc(priv->conn, file, flags); if (!xml) return false; =20 - vshPrint(ctl, "%s", xml); - return true; + return virshDumpXML(ctl, xml, "domain-save-image", xpath, wrap); } =20 /* @@ -4947,6 +4960,15 @@ static const vshCmdOptDef opts_managed_save_dumpxml[= ] =3D { .type =3D VSH_OT_BOOL, .help =3D N_("include security sensitive information in XML dump") }, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -4956,6 +4978,8 @@ cmdManagedSaveDumpxml(vshControl *ctl, const vshCmd *= cmd) g_autoptr(virshDomain) dom =3D NULL; unsigned int flags =3D 0; g_autofree char *xml =3D NULL; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 if (vshCommandOptBool(cmd, "security-info")) flags |=3D VIR_DOMAIN_XML_SECURE; @@ -4963,11 +4987,13 @@ cmdManagedSaveDumpxml(vshControl *ctl, const vshCmd= *cmd) if (!(dom =3D virshCommandOptDomain(ctl, cmd, NULL))) return false; =20 + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) + return false; + if (!(xml =3D virDomainManagedSaveGetXMLDesc(dom, flags))) return false; =20 - vshPrint(ctl, "%s", xml); - return true; + return virshDumpXML(ctl, xml, "domain-save-image", xpath, wrap); } =20 /* @@ -10434,6 +10460,15 @@ static const vshCmdOptDef opts_dumpxml[] =3D { .type =3D VSH_OT_BOOL, .help =3D N_("provide XML suitable for migrations") }, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -10441,12 +10476,14 @@ static bool cmdDumpXML(vshControl *ctl, const vshCmd *cmd) { g_autoptr(virshDomain) dom =3D NULL; - g_autofree char *dump =3D NULL; + g_autofree char *xml =3D NULL; unsigned int flags =3D 0; bool inactive =3D vshCommandOptBool(cmd, "inactive"); bool secure =3D vshCommandOptBool(cmd, "security-info"); bool update =3D vshCommandOptBool(cmd, "update-cpu"); bool migratable =3D vshCommandOptBool(cmd, "migratable"); + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 if (inactive) flags |=3D VIR_DOMAIN_XML_INACTIVE; @@ -10460,11 +10497,13 @@ cmdDumpXML(vshControl *ctl, const vshCmd *cmd) if (!(dom =3D virshCommandOptDomain(ctl, cmd, NULL))) return false; =20 - if (!(dump =3D virDomainGetXMLDesc(dom, flags))) + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) return false; =20 - vshPrint(ctl, "%s", dump); - return true; + if (!(xml =3D virDomainGetXMLDesc(dom, flags))) + return false; + + return virshDumpXML(ctl, xml, "domain", xpath, wrap); } =20 /* diff --git a/tools/virsh-interface.c b/tools/virsh-interface.c index 55d3532c55..b29ffc9bef 100644 --- a/tools/virsh-interface.c +++ b/tools/virsh-interface.c @@ -470,6 +470,16 @@ static const vshCmdOptDef opts_interface_dumpxml[] =3D= { .type =3D VSH_OT_BOOL, .help =3D N_("show inactive defined XML") }, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, + {.name =3D NULL} }; =20 @@ -477,7 +487,9 @@ static bool cmdInterfaceDumpXML(vshControl *ctl, const vshCmd *cmd) { g_autoptr(virshInterface) iface =3D NULL; - g_autofree char *dump =3D NULL; + g_autofree char *xml =3D NULL; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; unsigned int flags =3D 0; =20 if (vshCommandOptBool(cmd, "inactive")) @@ -486,11 +498,13 @@ cmdInterfaceDumpXML(vshControl *ctl, const vshCmd *cm= d) if (!(iface =3D virshCommandOptInterface(ctl, cmd, NULL))) return false; =20 - if (!(dump =3D virInterfaceGetXMLDesc(iface, flags))) + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) return false; =20 - vshPrint(ctl, "%s", dump); - return true; + if (!(xml =3D virInterfaceGetXMLDesc(iface, flags))) + return false; + + return virshDumpXML(ctl, xml, "interface", xpath, wrap); } =20 /* diff --git a/tools/virsh-network.c b/tools/virsh-network.c index 97a160f772..99ced6ccc6 100644 --- a/tools/virsh-network.c +++ b/tools/virsh-network.c @@ -349,6 +349,15 @@ static const vshCmdOptDef opts_network_dumpxml[] =3D { .type =3D VSH_OT_BOOL, .help =3D N_("show inactive defined XML") }, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -356,8 +365,10 @@ static bool cmdNetworkDumpXML(vshControl *ctl, const vshCmd *cmd) { g_autoptr(virshNetwork) network =3D NULL; - g_autofree char *dump =3D NULL; + g_autofree char *xml =3D NULL; unsigned int flags =3D 0; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 if (!(network =3D virshCommandOptNetwork(ctl, cmd, NULL))) return false; @@ -365,12 +376,13 @@ cmdNetworkDumpXML(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "inactive")) flags |=3D VIR_NETWORK_XML_INACTIVE; =20 - if (!(dump =3D virNetworkGetXMLDesc(network, flags))) { + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) return false; - } =20 - vshPrint(ctl, "%s", dump); - return true; + if (!(xml =3D virNetworkGetXMLDesc(network, flags))) + return false; + + return virshDumpXML(ctl, xml, "network", xpath, wrap); } =20 /* @@ -1542,6 +1554,15 @@ static const vshCmdInfo info_network_port_dumpxml[] = =3D { static const vshCmdOptDef opts_network_port_dumpxml[] =3D { VIRSH_COMMON_OPT_NETWORK_FULL(VIR_CONNECT_LIST_NETWORKS_ACTIVE), VIRSH_COMMON_OPT_NETWORK_PORT(0), + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -1551,8 +1572,10 @@ cmdNetworkPortDumpXML(vshControl *ctl, const vshCmd = *cmd) g_autoptr(virshNetwork) network =3D NULL; virNetworkPortPtr port =3D NULL; bool ret =3D true; - g_autofree char *dump =3D NULL; + g_autofree char *xml =3D NULL; unsigned int flags =3D 0; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 if (!(network =3D virshCommandOptNetwork(ctl, cmd, NULL))) goto cleanup; @@ -1560,13 +1583,13 @@ cmdNetworkPortDumpXML(vshControl *ctl, const vshCmd= *cmd) if (!(port =3D virshCommandOptNetworkPort(ctl, cmd, network, NULL))) goto cleanup; =20 - dump =3D virNetworkPortGetXMLDesc(port, flags); + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) + return false; =20 - if (dump !=3D NULL) { - vshPrint(ctl, "%s", dump); - } else { - ret =3D false; - } + if (!(xml =3D virNetworkPortGetXMLDesc(port, flags))) + goto cleanup; + + ret =3D virshDumpXML(ctl, xml, "network-port", xpath, wrap); =20 cleanup: if (port) diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c index 90066249af..72516c89c3 100644 --- a/tools/virsh-nodedev.c +++ b/tools/virsh-nodedev.c @@ -566,6 +566,15 @@ static const vshCmdOptDef opts_node_device_dumpxml[] = =3D { .help =3D N_("device name or wwn pair in 'wwnn,wwpn' format"), .completer =3D virshNodeDeviceNameCompleter, }, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -575,10 +584,15 @@ cmdNodeDeviceDumpXML(vshControl *ctl, const vshCmd *c= md) g_autoptr(virshNodeDevice) device =3D NULL; g_autofree char *xml =3D NULL; const char *device_value =3D NULL; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 if (vshCommandOptStringReq(ctl, cmd, "device", &device_value) < 0) return false; =20 + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) + return false; + device =3D vshFindNodeDevice(ctl, device_value); =20 if (!device) @@ -587,8 +601,7 @@ cmdNodeDeviceDumpXML(vshControl *ctl, const vshCmd *cmd) if (!(xml =3D virNodeDeviceGetXMLDesc(device, 0))) return false; =20 - vshPrint(ctl, "%s\n", xml); - return true; + return virshDumpXML(ctl, xml, "node-device", xpath, wrap); } =20 /* diff --git a/tools/virsh-nwfilter.c b/tools/virsh-nwfilter.c index 5a9e57e3f5..ff7f6f4026 100644 --- a/tools/virsh-nwfilter.c +++ b/tools/virsh-nwfilter.c @@ -186,6 +186,15 @@ static const vshCmdOptDef opts_nwfilter_dumpxml[] =3D { .help =3D N_("network filter name or uuid"), .completer =3D virshNWFilterNameCompleter, }, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -193,20 +202,20 @@ static bool cmdNWFilterDumpXML(vshControl *ctl, const vshCmd *cmd) { g_autoptr(virshNWFilter) nwfilter =3D NULL; - bool ret =3D true; - g_autofree char *dump =3D NULL; + g_autofree char *xml =3D NULL; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 if (!(nwfilter =3D virshCommandOptNWFilter(ctl, cmd, NULL))) return false; =20 - dump =3D virNWFilterGetXMLDesc(nwfilter, 0); - if (dump !=3D NULL) { - vshPrint(ctl, "%s", dump); - } else { - ret =3D false; - } + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) + return false; =20 - return ret; + if (!(xml =3D virNWFilterGetXMLDesc(nwfilter, 0))) + return false; + + return virshDumpXML(ctl, xml, "nwfilter", xpath, wrap); } =20 static int @@ -599,6 +608,15 @@ static const vshCmdOptDef opts_nwfilter_binding_dumpxm= l[] =3D { .help =3D N_("network filter binding portdev"), .completer =3D virshNWFilterBindingNameCompleter, }, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -607,18 +625,19 @@ cmdNWFilterBindingDumpXML(vshControl *ctl, const vshC= md *cmd) { virNWFilterBindingPtr binding; bool ret =3D true; - g_autofree char *dump =3D NULL; + g_autofree char *xml =3D NULL; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 if (!(binding =3D virshCommandOptNWFilterBinding(ctl, cmd, NULL))) return false; =20 - dump =3D virNWFilterBindingGetXMLDesc(binding, 0); - if (dump !=3D NULL) { - vshPrint(ctl, "%s", dump); - } else { - ret =3D false; - } + if (!(xml =3D virNWFilterBindingGetXMLDesc(binding, 0))) + goto cleanup; =20 + ret =3D virshDumpXML(ctl, xml, "nwfilter-binding", xpath, wrap); + + cleanup: virNWFilterBindingFree(binding); return ret; } diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c index 7e7a8d511f..4fb6875a98 100644 --- a/tools/virsh-pool.c +++ b/tools/virsh-pool.c @@ -776,6 +776,15 @@ static const vshCmdOptDef opts_pool_dumpxml[] =3D { .type =3D VSH_OT_BOOL, .help =3D N_("show inactive defined XML") }, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -783,10 +792,11 @@ static bool cmdPoolDumpXML(vshControl *ctl, const vshCmd *cmd) { g_autoptr(virshStoragePool) pool =3D NULL; - bool ret =3D true; bool inactive =3D vshCommandOptBool(cmd, "inactive"); unsigned int flags =3D 0; - g_autofree char *dump =3D NULL; + g_autofree char *xml =3D NULL; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 if (inactive) flags |=3D VIR_STORAGE_XML_INACTIVE; @@ -794,14 +804,13 @@ cmdPoolDumpXML(vshControl *ctl, const vshCmd *cmd) if (!(pool =3D virshCommandOptPool(ctl, cmd, "pool", NULL))) return false; =20 - dump =3D virStoragePoolGetXMLDesc(pool, flags); - if (dump !=3D NULL) { - vshPrint(ctl, "%s", dump); - } else { - ret =3D false; - } + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) + return false; =20 - return ret; + if (!(xml =3D virStoragePoolGetXMLDesc(pool, flags))) + return false; + + return virshDumpXML(ctl, xml, "pool", xpath, wrap); } =20 static int diff --git a/tools/virsh-secret.c b/tools/virsh-secret.c index 842647cb17..79fa3faf5a 100644 --- a/tools/virsh-secret.c +++ b/tools/virsh-secret.c @@ -138,6 +138,15 @@ static const vshCmdOptDef opts_secret_dumpxml[] =3D { .help =3D N_("secret UUID"), .completer =3D virshSecretUUIDCompleter, }, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -147,16 +156,21 @@ cmdSecretDumpXML(vshControl *ctl, const vshCmd *cmd) virSecretPtr secret; bool ret =3D false; g_autofree char *xml =3D NULL; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 secret =3D virshCommandOptSecret(ctl, cmd, NULL); if (secret =3D=3D NULL) return false; =20 + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) + return false; + xml =3D virSecretGetXMLDesc(secret, 0); if (xml =3D=3D NULL) goto cleanup; - vshPrint(ctl, "%s", xml); - ret =3D true; + + ret =3D virshDumpXML(ctl, xml, "secret", xpath, wrap); =20 cleanup: virshSecretFree(secret); diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c index 7cd76f39e2..73854d2486 100644 --- a/tools/virsh-snapshot.c +++ b/tools/virsh-snapshot.c @@ -1608,6 +1608,15 @@ static const vshCmdOptDef opts_snapshot_dumpxml[] = =3D { .type =3D VSH_OT_BOOL, .help =3D N_("include security sensitive information in XML dump") }, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -1619,6 +1628,8 @@ cmdSnapshotDumpXML(vshControl *ctl, const vshCmd *cmd) g_autoptr(virshDomainSnapshot) snapshot =3D NULL; g_autofree char *xml =3D NULL; unsigned int flags =3D 0; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; =20 if (vshCommandOptBool(cmd, "security-info")) flags |=3D VIR_DOMAIN_XML_SECURE; @@ -1632,11 +1643,13 @@ cmdSnapshotDumpXML(vshControl *ctl, const vshCmd *c= md) if (!(snapshot =3D virDomainSnapshotLookupByName(dom, name, 0))) return false; =20 + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) + return false; + if (!(xml =3D virDomainSnapshotGetXMLDesc(snapshot, flags))) return false; =20 - vshPrint(ctl, "%s", xml); - return true; + return virshDumpXML(ctl, xml, "domain-snapshot", xpath, wrap); } =20 /* diff --git a/tools/virsh-volume.c b/tools/virsh-volume.c index 503acda874..bf72d8135f 100644 --- a/tools/virsh-volume.c +++ b/tools/virsh-volume.c @@ -1159,6 +1159,15 @@ static const vshCmdInfo info_vol_dumpxml[] =3D { static const vshCmdOptDef opts_vol_dumpxml[] =3D { VIRSH_COMMON_OPT_VOL_FULL, VIRSH_COMMON_OPT_POOL_OPTIONAL, + {.name =3D "xpath", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("xpath expression to filter the XML document") + }, + {.name =3D "wrap", + .type =3D VSH_OT_BOOL, + .help =3D N_("wrap xpath results in an common root element"), + }, {.name =3D NULL} }; =20 @@ -1166,21 +1175,20 @@ static bool cmdVolDumpXML(vshControl *ctl, const vshCmd *cmd) { g_autoptr(virshStorageVol) vol =3D NULL; - bool ret =3D true; - char *dump; + bool wrap =3D vshCommandOptBool(cmd, "wrap"); + const char *xpath =3D NULL; + g_autofree char *xml =3D NULL; =20 if (!(vol =3D virshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) return false; =20 - dump =3D virStorageVolGetXMLDesc(vol, 0); - if (dump !=3D NULL) { - vshPrint(ctl, "%s", dump); - VIR_FREE(dump); - } else { - ret =3D false; - } + if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0) + return false; =20 - return ret; + if (!(xml =3D virStorageVolGetXMLDesc(vol, 0))) + return false; + + return virshDumpXML(ctl, xml, "volume", xpath, wrap); } =20 static int --=20 2.36.1