This command can be used to view/modify the `<title>` and
`<description>` fields of the NWFilter object.
Signed-off-by: K Shiva Kiran <shiva_kr(a)riseup.net>
---
tools/virsh-nwfilter.c | 209 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 209 insertions(+)
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}
};
--
2.42.0