This command can be used to view/modify the `<title>` and
`<description>` fields of the Network filter object.
Signed-off-by: K Shiva Kiran <shiva_kr(a)riseup.net>
---
docs/manpages/virsh.rst | 40 ++++++++
tools/virsh-nwfilter.c | 209 ++++++++++++++++++++++++++++++++++++++++
tools/virsh-util.c | 25 +++++
tools/virsh-util.h | 9 ++
4 files changed, 283 insertions(+)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index 4ae3bb4d93..3c7cbf1e11 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -8134,6 +8134,46 @@ The editor used can be supplied by the ``$VISUAL`` or ``$EDITOR``
environment
variables, and defaults to ``vi``.
+nwfilter-desc
+-------------
+
+**Syntax:**
+
+::
+
+ nwfilter-desc [--nwfilter] nwfilter-name
+ [--title] [--edit] [--remove]
+ [--new-desc new-value]
+
+Show or modify description and title of a network filter.
+
+These values are user fields that allow storing arbitrary textual data to
+allow easy identification of network filters.
+Title should be short, although it's not enforced.
+(See also ``nwfilter-metadata`` that works with XML based network filter metadata.)
+
+- *--title*
+
+ Specifies to operate on the title field instead of description.
+
+- *--edit*
+
+ Opens an editor with the current title or description.
+ Modifications to the contents will be saved back.
+ Alternatively, the new contents can be provided via the *--new-desc* option.
+
+- *--remove*
+
+ Removes the title or description field.
+
+- *--new-desc*
+
+ Stores the provided title/description string.
+
+If neither of *--edit* or *--new-desc* are specified, the title or description
+is displayed instead of being modified.
+
+
NWFILTER BINDING COMMANDS
=========================
diff --git a/tools/virsh-nwfilter.c b/tools/virsh-nwfilter.c
index 92b2b7b3bc..615d126def 100644
--- a/tools/virsh-nwfilter.c
+++ b/tools/virsh-nwfilter.c
@@ -26,6 +26,7 @@
#include "viralloc.h"
#include "virfile.h"
#include "vsh-table.h"
+#include "virxml.h"
virNWFilterPtr
virshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd,
@@ -345,6 +346,53 @@ virshNWFilterListCollect(vshControl *ctl,
return list;
}
+/* extract description or title from nwfilter xml */
+static char *
+virshGetNWFilterDescription(vshControl *ctl, virNWFilterPtr nwfilter,
+ bool title, unsigned int flags,
+ unsigned int queryflags)
+{
+ char *desc = NULL;
+ g_autoptr(xmlDoc) doc = NULL;
+ g_autoptr(xmlXPathContext) ctxt = NULL;
+ int type;
+
+ if (title)
+ type = VIR_NWFILTER_METADATA_TITLE;
+ else
+ type = VIR_NWFILTER_METADATA_DESCRIPTION;
+
+ if ((desc = virNWFilterGetMetadata(nwfilter, type, NULL, flags))) {
+ return desc;
+ } else {
+ int errCode = virGetLastErrorCode();
+
+ if (errCode == VIR_ERR_NO_NWFILTER_METADATA) {
+ desc = g_strdup("");
+ vshResetLibvirtError();
+ return desc;
+ }
+
+ if (errCode != VIR_ERR_NO_SUPPORT)
+ return desc;
+ }
+
+ /* fall back to xml */
+ if (virshNWFilterGetXMLFromNWFilter(ctl, nwfilter, queryflags, &doc, &ctxt)
< 0)
+ return NULL;
+
+ if (title)
+ desc = virXPathString("string(./title[1])", ctxt);
+ else
+ desc = virXPathString("string(./description[1])", ctxt);
+
+ if (!desc)
+ desc = g_strdup("");
+
+ return desc;
+}
+
+
/*
* "nwfilter-list" command
*/
@@ -768,6 +816,161 @@ cmdNWFilterBindingList(vshControl *ctl, const vshCmd *cmd
G_GNUC_UNUSED)
}
+/*
+ * "nwfilter-desc" command
+ */
+static const vshCmdInfo info_nwfilter_desc[] = {
+ {.name = "help",
+ .data = N_("show or set network filter's description or title")
+ },
+ {.name = "desc",
+ .data = N_("Allows setting or modifying the description or title of a network
filter.")
+ },
+ {.name = NULL}
+};
+
+static const vshCmdOptDef opts_nwfilter_desc[] = {
+ {.name = "nwfilter",
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_REQ,
+ .help = N_("network filter name or uuid"),
+ .completer = virshNWFilterNameCompleter,
+ },
+ {.name = "title",
+ .type = VSH_OT_BOOL,
+ .help = N_("modify/get the title instead of description")
+ },
+ {.name = "edit",
+ .type = VSH_OT_BOOL,
+ .help = N_("open an editor to modify the description")
+ },
+ {.name = "remove",
+ .type = VSH_OT_BOOL,
+ .help = N_("remove the element")
+ },
+ {.name = "new-desc",
+ .type = VSH_OT_ARGV,
+ .help = N_("message")
+ },
+ {.name = NULL}
+};
+
+static bool
+cmdNWFilterDesc(vshControl *ctl, const vshCmd *cmd)
+{
+ g_autoptr(virshNWFilter) nwfilter = NULL;
+ bool title = vshCommandOptBool(cmd, "title");
+ bool edit = vshCommandOptBool(cmd, "edit");
+ bool remove = vshCommandOptBool(cmd, "remove");
+ int type;
+ g_autofree char *descArg = NULL;
+ const vshCmdOpt *opt = NULL;
+ g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+ unsigned int flags = 0;
+ unsigned int queryflags = 0;
+
+ VSH_EXCLUSIVE_OPTIONS("remove", "edit");
+
+ if (!(nwfilter = virshCommandOptNWFilter(ctl, cmd, NULL)))
+ return false;
+
+ if (title)
+ type = VIR_NWFILTER_METADATA_TITLE;
+ else
+ type = VIR_NWFILTER_METADATA_DESCRIPTION;
+
+
+ while ((opt = vshCommandOptArgv(ctl, cmd, opt)))
+ virBufferAsprintf(&buf, "%s ", opt->data);
+
+ virBufferTrim(&buf, " ");
+
+ descArg = virBufferContentAndReset(&buf);
+
+ if (remove) {
+
+ if (descArg) {
+ vshPrintExtra(ctl, "unexpected data: \'%s\'", descArg);
+ return false;
+ }
+
+ if (virNWFilterSetMetadata(nwfilter, type, "", NULL, NULL, flags) <
0)
+ goto error;
+
+ vshPrintExtra(ctl, "%s removed successfully", title ? "Title"
: "Description");
+
+ } else if (edit || descArg) {
+
+ g_autofree char *descNWFilter = NULL;
+ g_autofree char *descNew = NULL;
+
+ if (!(descNWFilter = virshGetNWFilterDescription(ctl, nwfilter,
+ title, flags, queryflags)))
+ return false;
+
+ if (!descArg)
+ descArg = g_strdup(descNWFilter);
+
+ if (edit) {
+ g_autoptr(vshTempFile) tmp = NULL;
+ g_autofree char *desc_edited = NULL;
+ char *tmpstr;
+
+ /* Create and open a temporary file. */
+ if (!(tmp = vshEditWriteToTempFile(ctl, descArg)))
+ return false;
+
+ /* Start the editor. */
+ if (vshEditFile(ctl, tmp) == -1)
+ return false;
+
+ /* Read back the edited file. */
+ if (!(desc_edited = vshEditReadBackFile(ctl, tmp)))
+ return false;
+
+ /* strip a possible newline at the end */
+ if (title &&
+ (tmpstr = strrchr(desc_edited, '\n')) &&
+ *(tmpstr+1) == '\0')
+ *tmpstr = '\0';
+
+ /* Check whether XML has changed */
+ if (STREQ(descNWFilter, desc_edited)) {
+ vshPrintExtra(ctl, "Network filter %s has not changed", title ?
"title" : "description");
+ return true;
+ }
+
+ descNew = g_steal_pointer(&desc_edited);
+
+ } else {
+ descNew = g_steal_pointer(&descArg);
+ }
+
+ if (virNWFilterSetMetadata(nwfilter, type, descNew, NULL, NULL, flags) < 0)
+ goto error;
+
+ vshPrintExtra(ctl, "Network filter %s updated successfully", title ?
"title" : "description");
+
+ } else {
+ g_autofree char *desc = virshGetNWFilterDescription(ctl, nwfilter, title, flags,
queryflags);
+ if (!desc)
+ return false;
+
+ if (strlen(desc) > 0) {
+ vshPrint(ctl, "%s", desc);
+ } else {
+ vshPrintExtra(ctl, _("No %1$s for network filter: %2$s"), title ?
"title" : "description", virNWFilterGetName(nwfilter));
+ }
+ }
+
+ return true;
+
+ error:
+ vshError(ctl, "Failed to set %s for network filter", title ?
"title" : "description");
+ return false;
+}
+
+
const vshCmdDef nwfilterCmds[] = {
{.name = "nwfilter-define",
.handler = cmdNWFilterDefine,
@@ -823,5 +1026,11 @@ const vshCmdDef nwfilterCmds[] = {
.info = info_nwfilter_binding_list,
.flags = 0
},
+ {.name = "nwfilter-desc",
+ .handler = cmdNWFilterDesc,
+ .opts = opts_nwfilter_desc,
+ .info = info_nwfilter_desc,
+ .flags = 0
+ },
{.name = NULL}
};
diff --git a/tools/virsh-util.c b/tools/virsh-util.c
index fb6327613a..c3af770c29 100644
--- a/tools/virsh-util.c
+++ b/tools/virsh-util.c
@@ -423,6 +423,31 @@ virshNetworkGetXMLFromNet(vshControl *ctl,
}
+int
+virshNWFilterGetXMLFromNWFilter(vshControl *ctl,
+ virNWFilterPtr nwfilter,
+ unsigned int flags,
+ xmlDocPtr *xml,
+ xmlXPathContextPtr *ctxt)
+{
+ g_autofree char *desc = NULL;
+
+ if (!(desc = virNWFilterGetXMLDesc(nwfilter, flags))) {
+ vshError(ctl, _("Failed to get nwfilter description xml"));
+ return -1;
+ }
+
+ *xml = virXMLParseStringCtxt(desc, _("(nwfilter_definition)"), ctxt);
+
+ if (!(*xml)) {
+ vshError(ctl, _("Failed to parse nwfilter 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 2386847072..4cad3d7eb9 100644
--- a/tools/virsh-util.h
+++ b/tools/virsh-util.h
@@ -152,6 +152,15 @@ virshNetworkGetXMLFromNet(vshControl *ctl,
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4)
ATTRIBUTE_NONNULL(5) G_GNUC_WARN_UNUSED_RESULT;
+int
+virshNWFilterGetXMLFromNWFilter(vshControl *ctl,
+ virNWFilterPtr nwfilter,
+ 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,
--
2.42.0