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@xxxxxxxxxx> --- 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