From nobody Tue Feb 10 15:28:24 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) client-ip=170.10.133.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.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=riseup.net ARC-Seal: i=1; a=rsa-sha256; t=1692211683; cv=none; d=zohomail.com; s=zohoarc; b=ACQIikIyk2jm4jEtcdW/1kyD1mHSncp/wlDRlQkoM9YDBAysBXwDFke5kNE9vWwvMTq3cIxZax+l5Cg1MrX6KUoCAx1bnvi/5SMbYoovC7MwcxX2k3cZw6xcyhRES2IiAiQ8vIrjCZqFX/BZd8WaGhiV99xHUl+oVV17kgtXsBw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1692211683; 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=DBTAmTBhYA3RHbDJSMaCsBuY2JgyoYVtBtHqZKItAXI=; b=OxTKV7qAl/7+xj9HUiAKBJEJYSjhwEGkYax7DhUm0zWSBjbWoAIIKHc64MraGwudq3e2EwuWLaMDRBk1/K0x067hVORpzfVJcku7oEZ6ZmkDTEBKMvG3BUdf8JUcFEsqbYzRwnxlZ0NclF3/W60qLHXBAshWoDsRXsYpLQGrNJI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.zohomail.com with SMTPS id 1692211683556748.245749855467; Wed, 16 Aug 2023 11:48:03 -0700 (PDT) Received: from mimecast-mx02.redhat.com (66.187.233.73 [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-16-NMqnNHUkNk2KTlgsf5HoSw-1; Wed, 16 Aug 2023 14:47:55 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 173C93C0BE36; Wed, 16 Aug 2023 18:47:52 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id C8883C15BBA; Wed, 16 Aug 2023 18:47:50 +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 AA20119465BA; Wed, 16 Aug 2023 18:47:45 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 7132E194658F for ; Wed, 16 Aug 2023 18:47:42 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 503AEC15BAE; Wed, 16 Aug 2023 18:47:42 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast05.extmail.prod.ext.rdu2.redhat.com [10.11.55.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 48280C15BAD for ; Wed, 16 Aug 2023 18:47:42 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id CD66A85CBE7 for ; Wed, 16 Aug 2023 18:47:41 +0000 (UTC) Received: from mx0.riseup.net (mx0.riseup.net [198.252.153.6]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-253-BjBcpML2PTaX-Ud06toR_Q-1; Wed, 16 Aug 2023 14:47:39 -0400 Received: from fews01-sea.riseup.net (fews01-sea-pn.riseup.net [10.0.1.109]) (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 mx0.riseup.net (Postfix) with ESMTPS id 4RQxvt50Yfz9t6Y for ; Wed, 16 Aug 2023 18:47:38 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by fews01-sea.riseup.net (Postfix) with ESMTPSA id 4RQxvs4HZ5zJntv; Wed, 16 Aug 2023 18:47:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1692211682; 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=DBTAmTBhYA3RHbDJSMaCsBuY2JgyoYVtBtHqZKItAXI=; b=Vb1XvvPgh96fXj4DjKQjfm/+0a0JiJGmZZY1+LxjQhmbprFHhYtqmSiiohcpkbTPH/duNZ x+4TaPUdw3LgHaGNP+W1MYrjDvaeA+3Kc+ZUJR5mIr93yInewY60gAkiJyLGlQryjOeZgJ ZU2OHkaeg31/DJev4OhBvrsQXQ0ja7k= X-MC-Unique: NMqnNHUkNk2KTlgsf5HoSw-1 X-Original-To: libvir-list@listman.corp.redhat.com X-MC-Unique: BjBcpML2PTaX-Ud06toR_Q-1 X-Riseup-User-ID: C0BBC1E67D0BE7D9C7AB42E84BB5CE3800A92E379807DA5FA44D4F3062241FD1 From: K Shiva Kiran To: libvir-list@redhat.com Subject: [libvirt PATCH v2 4/7] virsh exposure of Network Metadata APIs Date: Thu, 17 Aug 2023 00:17:12 +0530 Message-ID: <20230816184715.101243-5-shiva_kr@riseup.net> In-Reply-To: <20230816184715.101243-1-shiva_kr@riseup.net> References: <20230816184715.101243-1-shiva_kr@riseup.net> MIME-Version: 1.0 X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 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: K Shiva Kiran Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: riseup.net Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1692211685101100005 Content-Type: text/plain; charset="utf-8"; x-default="true" Adds two new commands and a new option: - 'net-desc' to show/modify network title and description. - 'net-metadata' to show/modify network metadata. - Option '--title' for 'net-list' to print corresponding network titles in an additional column. - Documentation for all the above. - XML Fallback function `virshNetworkGetXMLFromNet` for title and description for compatibility with hosts running older versions of libvirtd. Signed-off-by: K Shiva Kiran --- docs/manpages/virsh.rst | 77 ++++++++ tools/virsh-network.c | 411 ++++++++++++++++++++++++++++++++++++++-- tools/virsh-util.c | 25 +++ tools/virsh-util.h | 9 + 4 files changed, 511 insertions(+), 11 deletions(-) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index f4e5a0bd62..673812036d 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -5566,6 +5566,7 @@ to get a description of the XML network format used b= y libvirt. Optionally, the format of the input XML file can be validated against an internal RNG schema with *--validate*. =20 + net-define ---------- =20 @@ -5581,6 +5582,38 @@ Optionally, the format of the input XML file can be = validated against an internal RNG schema with *--validate*. =20 =20 +net-desc +-------- + +**Syntax:** + +:: + + net-desc network [[--live] [--config] | + [--current]] [--title] [--edit] [--new-desc + New description or title message] + +Show or modify description and title of a network. These values are user +fields that allow storing arbitrary textual data to allow easy +identification of networks. Title should be short, although it's not enfor= ced. +(See also ``net-metadata`` that works with XML based network metadata.) + +Flags *--live* or *--config* select whether this command works on live +or persistent definitions of the network. If both *--live* and *--config* +are specified, the *--config* option takes precedence on getting the curre= nt +description and both live configuration and config are updated while setti= ng +the description. *--current* is exclusive and implied if none of these was +specified. + +Flag *--edit* specifies that an editor with the contents of current +description or title should be opened and the contents saved back afterwar= ds. + +Flag *--title* selects operation on the title field instead of description. + +If neither of *--edit* and *--new-desc* are specified the note or descript= ion +is displayed instead of being modified. + + net-destroy ----------- =20 @@ -5689,6 +5722,7 @@ net-list { [--table] | --name | --uuid } [--persistent] [<--transient>] [--autostart] [<--no-autostart>] + [--title] =20 Returns the list of active networks, if *--all* is specified this will also include defined but inactive networks, if *--inactive* is specified only t= he @@ -5703,12 +5737,55 @@ instead of names. Flag *--table* specifies that the= legacy table-formatted output should be used. This is the default. All of these are mutually exclusive. =20 +If *--title* is specified, then the short network description (title) is +printed in an extra column. This flag is usable only with the default +*--table* output. + NOTE: When talking to older servers, this command is forced to use a serie= s of API calls with an inherent race, where a pool might not be listed or might= appear more than once if it changed state between calls while the list was being collected. Newer servers do not have this problem. =20 =20 +net-metadata +------------ + +**Syntax:** + +:: + + net-metadata network [[--live] [--config] | [--current]] + [--edit] [uri] [key] [set] [--remove] + +Show or modify custom XML metadata of a network. The metadata is a user +defined XML that allows storing arbitrary XML data in the network definiti= on. +Multiple separate custom metadata pieces can be stored in the network XML. +The pieces are identified by a private XML namespace provided via the +*uri* argument. (See also ``net-desc`` that works with textual metadata of +a network, such as title and description.) + +Flags *--live* or *--config* select whether this command works on live +or persistent definitions of the network. If both *--live* and *--config* +are specified, the *--config* option takes precedence on getting the curre= nt +description and both live configuration and config are updated while setti= ng +the description. *--current* is exclusive and implied if none of these was +specified. + +Flag *--remove* specifies that the metadata element specified by the *uri* +argument should be removed rather than updated. + +Flag *--edit* specifies that an editor with the metadata identified by the +*uri* argument should be opened and the contents saved back afterwards. +Otherwise the new contents can be provided via the *set* argument. + +When setting metadata via *--edit* or *set* the *key* argument must be +specified and is used to prefix the custom elements to bind them +to the private namespace. + +If neither of *--edit* and *set* are specified the XML metadata correspond= ing +to the *uri* namespace is displayed instead of being modified. + + net-name -------- =20 diff --git a/tools/virsh-network.c b/tools/virsh-network.c index 42b7dba761..5a5cd15e24 100644 --- a/tools/virsh-network.c +++ b/tools/virsh-network.c @@ -330,6 +330,353 @@ cmdNetworkDestroy(vshControl *ctl, const vshCmd *cmd) return ret; } =20 +/* + * "net-desc" command + */ +static const vshCmdInfo info_network_desc[] =3D { + {.name =3D "help", + .data =3D N_("show or set network's description or title") + }, + {.name =3D "desc", + .data =3D N_("Allows setting or modifying the description or title of= a network.") + }, + {.name =3D NULL} +}; + +static const vshCmdOptDef opts_network_desc[] =3D { + VIRSH_COMMON_OPT_NETWORK_FULL(0), + VIRSH_COMMON_OPT_LIVE(N_("modify/get running state")), + VIRSH_COMMON_OPT_CONFIG(N_("modify/get persistent configuration")), + VIRSH_COMMON_OPT_CURRENT(N_("modify/get current state configuration")), + {.name =3D "title", + .type =3D VSH_OT_BOOL, + .help =3D N_("modify/get the title instead of description") + }, + {.name =3D "edit", + .type =3D VSH_OT_BOOL, + .help =3D N_("open an editor to modify the description") + }, + {.name =3D "new-desc", + .type =3D VSH_OT_ARGV, + .help =3D N_("message") + }, + {.name =3D NULL} +}; + +/* extract description or title from network xml */ +static char * +virshGetNetworkDescription(vshControl *ctl, virNetworkPtr net, + bool title, unsigned int flags) +{ + char *desc =3D NULL; + g_autoptr(xmlDoc) doc =3D NULL; + g_autoptr(xmlXPathContext) ctxt =3D NULL; + int type; + + if (title) + type =3D VIR_NETWORK_METADATA_TITLE; + else + type =3D VIR_NETWORK_METADATA_DESCRIPTION; + + if ((desc =3D virNetworkGetMetadata(net, type, NULL, flags))) { + return desc; + } else { + int errCode =3D virGetLastErrorCode(); + + if (errCode =3D=3D VIR_ERR_NO_NETWORK_METADATA) { + desc =3D g_strdup(""); + vshResetLibvirtError(); + return desc; + } + + if (errCode !=3D VIR_ERR_NO_SUPPORT) + return desc; + } + + /* fall back to xml */ + if (virshNetworkGetXMLFromNet(ctl, net, flags, &doc, &ctxt) < 0) + return NULL; + + if (title) + desc =3D virXPathString("string(./title[1])", ctxt); + else + desc =3D virXPathString("string(./description[1])", ctxt); + + if (!desc) + desc =3D g_strdup(""); + + return desc; +} + +static bool +cmdNetworkDesc(vshControl *ctl, const vshCmd *cmd) +{ + g_autoptr(virshNetwork) net =3D NULL; + bool config =3D vshCommandOptBool(cmd, "config"); + bool live =3D vshCommandOptBool(cmd, "live"); + bool current =3D vshCommandOptBool(cmd, "current"); + + bool title =3D vshCommandOptBool(cmd, "title"); + bool edit =3D vshCommandOptBool(cmd, "edit"); + + int type; + g_autofree char *descArg =3D NULL; + const vshCmdOpt *opt =3D NULL; + g_auto(virBuffer) buf =3D VIR_BUFFER_INITIALIZER; + unsigned int flags =3D VIR_NETWORK_UPDATE_AFFECT_CURRENT; + unsigned int queryflags =3D 0; + + VSH_EXCLUSIVE_OPTIONS_VAR(current, live); + VSH_EXCLUSIVE_OPTIONS_VAR(current, config); + + if (config) { + flags |=3D VIR_NETWORK_UPDATE_AFFECT_CONFIG; + queryflags |=3D VIR_NETWORK_XML_INACTIVE; + } + if (live) + flags |=3D VIR_NETWORK_UPDATE_AFFECT_LIVE; + + if (!(net =3D virshCommandOptNetwork(ctl, cmd, NULL))) + return false; + + if (title) + type =3D VIR_NETWORK_METADATA_TITLE; + else + type =3D VIR_NETWORK_METADATA_DESCRIPTION; + + while ((opt =3D vshCommandOptArgv(ctl, cmd, opt))) + virBufferAsprintf(&buf, "%s ", opt->data); + + virBufferTrim(&buf, " "); + + descArg =3D virBufferContentAndReset(&buf); + + if (edit || descArg) { + g_autofree char *descNet =3D NULL; + g_autofree char *descNew =3D NULL; + + if (!(descNet =3D virshGetNetworkDescription(ctl, net, title, quer= yflags))) + return false; + + if (!descArg) + descArg =3D g_strdup(descNet); + + if (edit) { + g_autoptr(vshTempFile) tmp =3D NULL; + g_autofree char *desc_edited =3D NULL; + char *tmpstr; + + /* Create and open the temporary file. */ + if (!(tmp =3D vshEditWriteToTempFile(ctl, descArg))) + return false; + + /* Start the editor. */ + if (vshEditFile(ctl, tmp) =3D=3D -1) + return false; + + /* Read back the edited file. */ + if (!(desc_edited =3D vshEditReadBackFile(ctl, tmp))) + return false; + + /* strip a possible newline at the end of file; some + * editors enforce a newline, this makes editing the title + * more convenient */ + if (title && + (tmpstr =3D strrchr(desc_edited, '\n')) && + *(tmpstr+1) =3D=3D '\0') + *tmpstr =3D '\0'; + + /* Compare original XML with edited. Has it changed at all? */ + if (STREQ(descNet, desc_edited)) { + if (title) + vshPrintExtra(ctl, "%s", _("Network title not changed\= n")); + else + vshPrintExtra(ctl, "%s", _("Network description not ch= anged\n")); + + return true; + } + + descNew =3D g_steal_pointer(&desc_edited); + } else { + descNew =3D g_steal_pointer(&descArg); + } + + if (virNetworkSetMetadata(net, type, descNew, NULL, NULL, flags) <= 0) { + if (title) + vshError(ctl, "%s", _("Failed to set new network title")); + else + vshError(ctl, "%s", _("Failed to set new network descripti= on")); + + return false; + } + + if (title) + vshPrintExtra(ctl, "%s", _("Network title updated successfully= ")); + else + vshPrintExtra(ctl, "%s", _("Network description updated succes= sfully")); + + } else { + g_autofree char *desc =3D virshGetNetworkDescription(ctl, net, tit= le, queryflags); + if (!desc) + return false; + + if (strlen(desc) > 0) { + vshPrint(ctl, "%s", desc); + } else { + if (title) + vshPrintExtra(ctl, _("No title for network: %1$s"), virNet= workGetName(net)); + else + vshPrintExtra(ctl, _("No description for network: %1$s"), = virNetworkGetName(net)); + } + } + + return true; +} + +/* + * "net-metadata" command + */ +static const vshCmdInfo info_network_metadata[] =3D { + {.name =3D "help", + .data =3D N_("show or set network's custom XML metadata") + }, + {.name =3D "desc", + .data =3D N_("Shows or modifies the XML metadata of a network.") + }, + {.name =3D NULL} +}; + +static const vshCmdOptDef opts_network_metadata[] =3D { + VIRSH_COMMON_OPT_NETWORK_FULL(0), + {.name =3D "uri", + .type =3D VSH_OT_DATA, + .flags =3D VSH_OFLAG_REQ, + .help =3D N_("URI of the namespace") + }, + VIRSH_COMMON_OPT_LIVE(N_("modify/get running state")), + VIRSH_COMMON_OPT_CONFIG(N_("modify/get persistent configuration")), + VIRSH_COMMON_OPT_CURRENT(N_("modify/get current state configuration")), + {.name =3D "edit", + .type =3D VSH_OT_BOOL, + .help =3D N_("use an editor to change the metadata") + }, + {.name =3D "key", + .type =3D VSH_OT_STRING, + .help =3D N_("key to be used as a namespace identifier"), + }, + {.name =3D "set", + .type =3D VSH_OT_STRING, + .completer =3D virshCompleteEmpty, + .help =3D N_("new metadata to set"), + }, + {.name =3D "remove", + .type =3D VSH_OT_BOOL, + .help =3D N_("remove the metadata corresponding to an uri") + }, + {.name =3D NULL} +}; + +/* helper to add new metadata using the --edit option */ +static char * +virshNetworkGetEditMetadata(vshControl *ctl G_GNUC_UNUSED, + virNetworkPtr net, + const char *uri, + unsigned int flags) +{ + char *ret; + + if (!(ret =3D virNetworkGetMetadata(net, VIR_NETWORK_METADATA_ELEMENT, + uri, flags))) { + vshResetLibvirtError(); + ret =3D g_strdup("\n"); + } + + return ret; +} + +static bool +cmdNetworkMetadata(vshControl *ctl, const vshCmd *cmd) +{ + g_autoptr(virshNetwork) net =3D NULL; + g_autoptr(xmlXPathContext) ctxt =3D NULL; + bool config =3D vshCommandOptBool(cmd, "config"); + bool live =3D vshCommandOptBool(cmd, "live"); + bool current =3D vshCommandOptBool(cmd, "current"); + bool edit =3D vshCommandOptBool(cmd, "edit"); + bool rem =3D vshCommandOptBool(cmd, "remove"); + const char *set =3D NULL; + const char *uri =3D NULL; + const char *key =3D NULL; + unsigned int flags =3D VIR_NETWORK_UPDATE_AFFECT_CURRENT; + bool ret =3D false; + + VSH_EXCLUSIVE_OPTIONS_VAR(current, live); + VSH_EXCLUSIVE_OPTIONS_VAR(current, config); + VSH_EXCLUSIVE_OPTIONS("edit", "set"); + VSH_EXCLUSIVE_OPTIONS("remove", "set"); + VSH_EXCLUSIVE_OPTIONS("remove", "edit"); + + if (config) + flags |=3D VIR_NETWORK_UPDATE_AFFECT_CONFIG; + if (live) + flags |=3D VIR_NETWORK_UPDATE_AFFECT_LIVE; + + if (!(net =3D virshCommandOptNetwork(ctl, cmd, NULL))) + return false; + + if (vshCommandOptStringReq(ctl, cmd, "uri", &uri) < 0 || + vshCommandOptStringReq(ctl, cmd, "key", &key) < 0 || + vshCommandOptStringReq(ctl, cmd, "set", &set) < 0) + return false; + + if ((set || edit) && !key) { + vshError(ctl, "%s", + _("namespace key is required when modifying metadata")); + return false; + } + + if (set || rem) { + if (virNetworkSetMetadata(net, VIR_NETWORK_METADATA_ELEMENT, + set, key, uri, flags)) + return false; + + if (rem) + vshPrintExtra(ctl, "%s\n", _("Metadata removed")); + else + vshPrintExtra(ctl, "%s\n", _("Metadata modified")); + } else if (edit) { +#define EDIT_GET_XML \ + virshNetworkGetEditMetadata(ctl, net, uri, flags) +#define EDIT_NOT_CHANGED \ + do { \ + vshPrintExtra(ctl, "%s", _("Metadata not changed")); \ + ret =3D true; \ + goto edit_cleanup; \ + } while (0) + +#define EDIT_DEFINE \ + (virNetworkSetMetadata(net, VIR_NETWORK_METADATA_ELEMENT, doc_edit= ed, \ + key, uri, flags) =3D=3D 0) +#include "virsh-edit.c" + + vshPrintExtra(ctl, "%s\n", _("Metadata modified")); + } else { + g_autofree char *data =3D NULL; + g_autoptr(xmlDoc) doc =3D NULL; + /* get */ + if (!(data =3D virNetworkGetMetadata(net, VIR_NETWORK_METADATA_ELE= MENT, + uri, flags))) + return false; + + vshPrint(ctl, "%s\n", data); + } + + ret =3D true; + + cleanup: + return ret; +} + /* * "net-dumpxml" command */ @@ -708,6 +1055,10 @@ static const vshCmdOptDef opts_network_list[] =3D { .type =3D VSH_OT_BOOL, .help =3D N_("list table (default)") }, + {.name =3D "title", + .type =3D VSH_OT_BOOL, + .help =3D N_("show network title") + }, {.name =3D NULL} }; =20 @@ -721,6 +1072,7 @@ cmdNetworkList(vshControl *ctl, const vshCmd *cmd G_GN= UC_UNUSED) size_t i; bool ret =3D false; bool optName =3D vshCommandOptBool(cmd, "name"); + bool optTitle =3D vshCommandOptBool(cmd, "title"); bool optTable =3D vshCommandOptBool(cmd, "table"); bool optUUID =3D vshCommandOptBool(cmd, "uuid"); char uuid[VIR_UUID_STRING_BUFLEN]; @@ -754,8 +1106,12 @@ cmdNetworkList(vshControl *ctl, const vshCmd *cmd G_G= NUC_UNUSED) return false; =20 if (optTable) { - table =3D vshTableNew(_("Name"), _("State"), _("Autostart"), - _("Persistent"), NULL); + if (optTitle) + table =3D vshTableNew(_("Name"), _("State"), _("Autostart"), + _("Persistent"), _("Title"), NULL); + else + table =3D vshTableNew(_("Name"), _("State"), _("Autostart"), + _("Persistent"), NULL); if (!table) goto cleanup; } @@ -771,16 +1127,37 @@ cmdNetworkList(vshControl *ctl, const vshCmd *cmd G_= GNUC_UNUSED) else autostartStr =3D is_autostart ? _("yes") : _("no"); =20 - if (vshTableRowAppend(table, - virNetworkGetName(network), - virNetworkIsActive(network) ? - _("active") : _("inactive"), - autostartStr, - virNetworkIsPersistent(network) ? - _("yes") : _("no"), - NULL) < 0) - goto cleanup; + if (optTitle) { + g_autofree char *title =3D NULL; + + if (!(title =3D virshGetNetworkDescription(ctl, network, t= rue, 0))) + goto cleanup; + if (vshTableRowAppend(table, + virNetworkGetName(network), + virNetworkIsActive(network) ? + _("active") : _("inactive"), + autostartStr, + virNetworkIsPersistent(network) ? + _("yes") : _("no"), + title, + NULL) < 0) + goto cleanup; + + } else { + if (vshTableRowAppend(table, + virNetworkGetName(network), + virNetworkIsActive(network) ? + _("active") : _("inactive"), + autostartStr, + virNetworkIsPersistent(network) ? + _("yes") : _("no"), + NULL) < 0) + goto cleanup; + + } + } else if (optUUID) { + if (virNetworkGetUUIDString(network, uuid) < 0) { vshError(ctl, "%s", _("Failed to get network's UUID")); goto cleanup; @@ -1825,6 +2202,12 @@ const vshCmdDef networkCmds[] =3D { .info =3D info_network_define, .flags =3D 0 }, + {.name =3D "net-desc", + .handler =3D cmdNetworkDesc, + .opts =3D opts_network_desc, + .info =3D info_network_desc, + .flags =3D 0 + }, {.name =3D "net-destroy", .handler =3D cmdNetworkDestroy, .opts =3D opts_network_destroy, @@ -1867,6 +2250,12 @@ const vshCmdDef networkCmds[] =3D { .info =3D info_network_list, .flags =3D 0 }, + {.name =3D "net-metadata", + .handler =3D cmdNetworkMetadata, + .opts =3D opts_network_metadata, + .info =3D info_network_metadata, + .flags =3D 0 + }, {.name =3D "net-name", .handler =3D cmdNetworkName, .opts =3D opts_network_name, diff --git a/tools/virsh-util.c b/tools/virsh-util.c index 61e403a636..fb6327613a 100644 --- a/tools/virsh-util.c +++ b/tools/virsh-util.c @@ -398,6 +398,31 @@ virshDomainGetXMLFromDom(vshControl *ctl, } =20 =20 +int +virshNetworkGetXMLFromNet(vshControl *ctl, + virNetworkPtr net, + unsigned int flags, + xmlDocPtr *xml, + xmlXPathContextPtr *ctxt) +{ + g_autofree char *desc =3D NULL; + + if (!(desc =3D virNetworkGetXMLDesc(net, flags))) { + vshError(ctl, _("Failed to get network description xml")); + return -1; + } + + *xml =3D virXMLParseStringCtxt(desc, _("(network_definition)"), ctxt); + + if (!(*xml)) { + vshError(ctl, _("Failed to parse network description xml")); + return -1; + } + + return 0; +} + + int virshDomainGetXML(vshControl *ctl, const vshCmd *cmd, diff --git a/tools/virsh-util.h b/tools/virsh-util.h index 0f81a2771b..2386847072 100644 --- a/tools/virsh-util.h +++ b/tools/virsh-util.h @@ -143,6 +143,15 @@ virshDomainGetXMLFromDom(vshControl *ctl, ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) G_GNUC_WARN_UNUSED_RESULT; =20 +int +virshNetworkGetXMLFromNet(vshControl *ctl, + virNetworkPtr net, + unsigned int flags, + xmlDocPtr *xml, + xmlXPathContextPtr *ctxt) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4) + ATTRIBUTE_NONNULL(5) G_GNUC_WARN_UNUSED_RESULT; + int virshDomainGetXML(vshControl *ctl, const vshCmd *cmd, --=20 2.41.0