[libvirt] [PATCH v2 00/13] virsh completion improvement

Add more bash completions for some of virsh subcommands/subparameters. v1->v2 * Follow Michal's suggestions: - guestvcpus command: complete offlined vCPUs if --enable, complete onlined vCPUs if --disable - Added a static helper function for interface string provider, - Adjusted some needlessly complicated loops. * Refered to Peter and Michal's comments, I droped the vnc completion patches. * Concentrate on completion itself, Drop all of patches which related to macros to make review easier. Lin Ma (13): virsh: Add vcpu list completion to guestvcpus command virsh: Add logical CPU IDs completion for nodecpustats command virsh: Add serial/parallel device name completion to console command virsh-interface: Add a static helper virshInterfaceStringHelper virsh: Add interface mac completion to iface-name command virsh: Add interface name completion to iface-bridge command virsh: Add interface name completion to iface-mac command vsh: Fix completion error in case of multiple mac addresses virsh: Add mac completion to net-dhcp-leases command virsh: Move/add some of function declarations to virsh-domain.h virsh: Add signal name completion to send-process-signal command virsh: Add lifecycle type completion to set-lifecycle-action command Add lifecycle action completion to set-lifecycle-action command tools/bash-completion/vsh | 1 + tools/virsh-completer-domain.c | 190 ++++++++++++++++++++++++++++++ tools/virsh-completer-domain.h | 20 ++++ tools/virsh-completer-host.c | 31 +++++ tools/virsh-completer-host.h | 4 + tools/virsh-completer-interface.c | 34 ++++-- tools/virsh-completer-interface.h | 7 ++ tools/virsh-completer-network.c | 44 +++++++ tools/virsh-completer-network.h | 4 + tools/virsh-domain.c | 6 +- tools/virsh-domain.h | 4 + tools/virsh-host.c | 1 + tools/virsh-interface.c | 3 + tools/virsh-network.c | 15 ++- 14 files changed, 349 insertions(+), 15 deletions(-) -- 2.26.0

Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-domain.c | 75 ++++++++++++++++++++++++++++++++++ tools/virsh-completer-domain.h | 4 ++ tools/virsh-domain.c | 1 + 3 files changed, 80 insertions(+) diff --git a/tools/virsh-completer-domain.c b/tools/virsh-completer-domain.c index c657627ac1..f653471b89 100644 --- a/tools/virsh-completer-domain.c +++ b/tools/virsh-completer-domain.c @@ -30,6 +30,7 @@ #include "virstring.h" #include "virxml.h" #include "virperf.h" +#include "virbitmap.h" char ** virshDomainNameCompleter(vshControl *ctl, @@ -581,3 +582,77 @@ virshDomainCpulistCompleter(vshControl *ctl, return virshCommaStringListComplete(cpuid, (const char **)cpulist); } + +char ** +virshDomainVcpulistViaAgentCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags) +{ + virDomainPtr dom; + bool enable = vshCommandOptBool(cmd, "enable"); + bool disable = vshCommandOptBool(cmd, "disable"); + virTypedParameterPtr params = NULL; + unsigned int nparams = 0; + int dummy; + size_t i; + size_t offset = 0; + int nvcpus; + VIR_AUTOSTRINGLIST cpulist = NULL; + g_autoptr(virBitmap) vcpus = NULL; + g_autofree unsigned char *vcpumap = NULL; + g_autofree char *onlineVcpuStr = NULL; + const char *vcpuid = NULL; + char **ret = NULL; + + virCheckFlags(0, NULL); + + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) + return NULL; + + if (vshCommandOptStringQuiet(ctl, cmd, "cpulist", &vcpuid) < 0) + goto cleanup; + + /* retrieve vcpu count from the guest instead of the hypervisor */ + if ((nvcpus = virDomainGetVcpusFlags(dom, VIR_DOMAIN_VCPU_GUEST | + VIR_DOMAIN_VCPU_MAXIMUM)) < 0) + goto cleanup; + + if (!enable && !disable) { + cpulist = g_new0(char *, nvcpus + 1); + for (i = 0; i < nvcpus; i++) + cpulist[i] = g_strdup_printf("%zu", i); + } else { + if (virDomainGetGuestVcpus(dom, ¶ms, &nparams, 0) < 0) + goto cleanup; + onlineVcpuStr = vshGetTypedParamValue(ctl, ¶ms[1]); + if (virBitmapParse(onlineVcpuStr, &vcpus, nvcpus) < 0) + goto cleanup; + + if (virBitmapToData(vcpus, &vcpumap, &dummy) < 0) + goto cleanup; + if (enable) { + cpulist = g_new0(char *, nvcpus - virBitmapCountBits(vcpus) + 1); + for (i = 0; i < nvcpus; i++) { + if (VIR_CPU_USED(vcpumap, i) != 0) + continue; + + cpulist[offset++] = g_strdup_printf("%zu", i); + } + } else if (disable) { + cpulist = g_new0(char *, virBitmapCountBits(vcpus) + 1); + for (i = 0; i < nvcpus; i++) { + if (VIR_CPU_USED(vcpumap, i) == 0) + continue; + + cpulist[offset++] = g_strdup_printf("%zu", i); + } + } + } + + ret = virshCommaStringListComplete(vcpuid, (const char **)cpulist); + + cleanup: + virTypedParamsFree(params, nparams); + virshDomainFree(dom); + return ret; +} diff --git a/tools/virsh-completer-domain.h b/tools/virsh-completer-domain.h index d38efd5ea8..d5021f6aa6 100644 --- a/tools/virsh-completer-domain.h +++ b/tools/virsh-completer-domain.h @@ -90,3 +90,7 @@ char ** virshDomainVcpulistCompleter(vshControl *ctl, char ** virshDomainCpulistCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); + +char ** virshDomainVcpulistViaAgentCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 1ae936c6b2..675d96440d 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -7436,6 +7436,7 @@ static const vshCmdOptDef opts_guestvcpus[] = { VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE), {.name = "cpulist", .type = VSH_OT_STRING, + .completer = virshDomainVcpulistViaAgentCompleter, .help = N_("list of cpus to enable or disable") }, {.name = "enable", -- 2.26.0

On 11/10/20 10:50 AM, Lin Ma wrote:
Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-domain.c | 75 ++++++++++++++++++++++++++++++++++ tools/virsh-completer-domain.h | 4 ++ tools/virsh-domain.c | 1 + 3 files changed, 80 insertions(+)
diff --git a/tools/virsh-completer-domain.c b/tools/virsh-completer-domain.c index c657627ac1..f653471b89 100644 --- a/tools/virsh-completer-domain.c +++ b/tools/virsh-completer-domain.c @@ -30,6 +30,7 @@ #include "virstring.h" #include "virxml.h" #include "virperf.h" +#include "virbitmap.h"
char ** virshDomainNameCompleter(vshControl *ctl, @@ -581,3 +582,77 @@ virshDomainCpulistCompleter(vshControl *ctl,
return virshCommaStringListComplete(cpuid, (const char **)cpulist); } + +char ** +virshDomainVcpulistViaAgentCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags) +{ + virDomainPtr dom; + bool enable = vshCommandOptBool(cmd, "enable"); + bool disable = vshCommandOptBool(cmd, "disable"); + virTypedParameterPtr params = NULL; + unsigned int nparams = 0; + int dummy; + size_t i; + size_t offset = 0; + int nvcpus; + VIR_AUTOSTRINGLIST cpulist = NULL; + g_autoptr(virBitmap) vcpus = NULL; + g_autofree unsigned char *vcpumap = NULL; + g_autofree char *onlineVcpuStr = NULL; + const char *vcpuid = NULL; + char **ret = NULL;
Some of these variables ^^ are used ..
+ + virCheckFlags(0, NULL); + + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) + return NULL; + + if (vshCommandOptStringQuiet(ctl, cmd, "cpulist", &vcpuid) < 0) + goto cleanup; + + /* retrieve vcpu count from the guest instead of the hypervisor */ + if ((nvcpus = virDomainGetVcpusFlags(dom, VIR_DOMAIN_VCPU_GUEST | + VIR_DOMAIN_VCPU_MAXIMUM)) < 0) + goto cleanup; + + if (!enable && !disable) { + cpulist = g_new0(char *, nvcpus + 1); + for (i = 0; i < nvcpus; i++) + cpulist[i] = g_strdup_printf("%zu", i); + } else {
.. in this body exclusively. I think it makes sense to move them here.
+ if (virDomainGetGuestVcpus(dom, ¶ms, &nparams, 0) < 0) + goto cleanup; + onlineVcpuStr = vshGetTypedParamValue(ctl, ¶ms[1]); + if (virBitmapParse(onlineVcpuStr, &vcpus, nvcpus) < 0) + goto cleanup; + + if (virBitmapToData(vcpus, &vcpumap, &dummy) < 0) + goto cleanup; + if (enable) { + cpulist = g_new0(char *, nvcpus - virBitmapCountBits(vcpus) + 1); + for (i = 0; i < nvcpus; i++) { + if (VIR_CPU_USED(vcpumap, i) != 0) + continue; + + cpulist[offset++] = g_strdup_printf("%zu", i); + } + } else if (disable) { + cpulist = g_new0(char *, virBitmapCountBits(vcpus) + 1); + for (i = 0; i < nvcpus; i++) { + if (VIR_CPU_USED(vcpumap, i) == 0) + continue; + + cpulist[offset++] = g_strdup_printf("%zu", i); + } + } + } + + ret = virshCommaStringListComplete(vcpuid, (const char **)cpulist); + + cleanup: + virTypedParamsFree(params, nparams); + virshDomainFree(dom); + return ret; +} diff --git a/tools/virsh-completer-domain.h b/tools/virsh-completer-domain.h index d38efd5ea8..d5021f6aa6 100644 --- a/tools/virsh-completer-domain.h +++ b/tools/virsh-completer-domain.h @@ -90,3 +90,7 @@ char ** virshDomainVcpulistCompleter(vshControl *ctl, char ** virshDomainCpulistCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); + +char ** virshDomainVcpulistViaAgentCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 1ae936c6b2..675d96440d 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -7436,6 +7436,7 @@ static const vshCmdOptDef opts_guestvcpus[] = { VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE), {.name = "cpulist", .type = VSH_OT_STRING, + .completer = virshDomainVcpulistViaAgentCompleter, .help = N_("list of cpus to enable or disable") }, {.name = "enable",
Michal

Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-host.c | 31 +++++++++++++++++++++++++++++++ tools/virsh-completer-host.h | 4 ++++ tools/virsh-host.c | 1 + 3 files changed, 36 insertions(+) diff --git a/tools/virsh-completer-host.c b/tools/virsh-completer-host.c index 339390aa00..685fa23fd4 100644 --- a/tools/virsh-completer-host.c +++ b/tools/virsh-completer-host.c @@ -136,3 +136,34 @@ virshCellnoCompleter(vshControl *ctl, return g_steal_pointer(&tmp); } + + +char ** +virshCpuCompleter(vshControl *ctl, + const vshCmd *cmd G_GNUC_UNUSED, + unsigned int flags) +{ + virshControlPtr priv = ctl->privData; + VIR_AUTOSTRINGLIST tmp = NULL; + size_t i; + int cpunum; + size_t offset = 0; + unsigned int online; + g_autofree unsigned char *cpumap = NULL; + + virCheckFlags(0, NULL); + + if ((cpunum = virNodeGetCPUMap(priv->conn, &cpumap, &online, 0)) < 0) + return NULL; + + tmp = g_new0(char *, online + 1); + + for (i = 0; i < cpunum; i++) { + if (VIR_CPU_USED(cpumap, i) == 0) + continue; + + tmp[offset++] = g_strdup_printf("%zu", i); + } + + return g_steal_pointer(&tmp); +} diff --git a/tools/virsh-completer-host.h b/tools/virsh-completer-host.h index 921beb7a2d..777783b908 100644 --- a/tools/virsh-completer-host.h +++ b/tools/virsh-completer-host.h @@ -29,3 +29,7 @@ char ** virshAllocpagesPagesizeCompleter(vshControl *ctl, char ** virshCellnoCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); + +char ** virshCpuCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-host.c b/tools/virsh-host.c index cda2ef4ac1..4774f76ed8 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -751,6 +751,7 @@ static const vshCmdInfo info_nodecpustats[] = { static const vshCmdOptDef opts_node_cpustats[] = { {.name = "cpu", .type = VSH_OT_INT, + .completer = virshCpuCompleter, .help = N_("prints specified cpu statistics only.") }, {.name = "percent", -- 2.26.0

On 11/10/20 10:50 AM, Lin Ma wrote:
Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-host.c | 31 +++++++++++++++++++++++++++++++ tools/virsh-completer-host.h | 4 ++++ tools/virsh-host.c | 1 + 3 files changed, 36 insertions(+)
diff --git a/tools/virsh-completer-host.c b/tools/virsh-completer-host.c index 339390aa00..685fa23fd4 100644 --- a/tools/virsh-completer-host.c +++ b/tools/virsh-completer-host.c @@ -136,3 +136,34 @@ virshCellnoCompleter(vshControl *ctl,
return g_steal_pointer(&tmp); } + + +char ** +virshCpuCompleter(vshControl *ctl, + const vshCmd *cmd G_GNUC_UNUSED, + unsigned int flags)
With so many CPU completers I think this should include Node in its name, e.g. virshNodeCpuCompleter() so that it's obvious it's completing host's CPUs. Michal

Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-domain.c | 55 ++++++++++++++++++++++++++++++++++ tools/virsh-completer-domain.h | 4 +++ tools/virsh-domain.c | 1 + 3 files changed, 60 insertions(+) diff --git a/tools/virsh-completer-domain.c b/tools/virsh-completer-domain.c index f653471b89..dc66317561 100644 --- a/tools/virsh-completer-domain.c +++ b/tools/virsh-completer-domain.c @@ -656,3 +656,58 @@ virshDomainVcpulistViaAgentCompleter(vshControl *ctl, virshDomainFree(dom); return ret; } + +char ** +virshDomainConsoleCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags) +{ + virshControlPtr priv = ctl->privData; + g_autoptr(xmlDoc) xmldoc = NULL; + g_autoptr(xmlXPathContext) ctxt = NULL; + int nserials; + int nparallels; + g_autofree xmlNodePtr *serials = NULL; + g_autofree xmlNodePtr *parallels = NULL; + size_t i; + size_t offset = 0; + VIR_AUTOSTRINGLIST tmp = NULL; + + virCheckFlags(0, NULL); + + if (!priv->conn || virConnectIsAlive(priv->conn) <= 0) + return NULL; + + if (virshDomainGetXML(ctl, cmd, 0, &xmldoc, &ctxt) < 0) + return NULL; + + nserials = virXPathNodeSet("./devices/serial", ctxt, &serials); + if (nserials < 0) + return NULL; + + nparallels = virXPathNodeSet("./devices/parallel", ctxt, ¶llels); + if (nparallels < 0) + return NULL; + + tmp = g_new0(char *, nserials + nparallels + 1); + + for (i = 0; i < nserials; i++) { + ctxt->node = serials[i]; + + if (STRNEQ(virXPathString("string(./@type)", ctxt), "pty")) + continue; + + tmp[offset++] = virXPathString("string(./alias/@name)", ctxt); + } + + for (i = 0; i < nparallels; i++) { + ctxt->node = parallels[i]; + + if (STRNEQ(virXPathString("string(./@type)", ctxt), "pty")) + continue; + + tmp[offset++] = virXPathString("string(./alias/@name)", ctxt); + } + + return g_steal_pointer(&tmp); +} diff --git a/tools/virsh-completer-domain.h b/tools/virsh-completer-domain.h index d5021f6aa6..02fea2fe94 100644 --- a/tools/virsh-completer-domain.h +++ b/tools/virsh-completer-domain.h @@ -94,3 +94,7 @@ char ** virshDomainCpulistCompleter(vshControl *ctl, char ** virshDomainVcpulistViaAgentCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); + +char ** virshDomainConsoleCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 675d96440d..022dbdca3c 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -2960,6 +2960,7 @@ static const vshCmdOptDef opts_console[] = { VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE), {.name = "devname", /* sc_prohibit_devname */ .type = VSH_OT_STRING, + .completer = virshDomainConsoleCompleter, .help = N_("character device name") }, {.name = "force", -- 2.26.0

On 11/10/20 10:50 AM, Lin Ma wrote:
Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-domain.c | 55 ++++++++++++++++++++++++++++++++++ tools/virsh-completer-domain.h | 4 +++ tools/virsh-domain.c | 1 + 3 files changed, 60 insertions(+)
diff --git a/tools/virsh-completer-domain.c b/tools/virsh-completer-domain.c index f653471b89..dc66317561 100644 --- a/tools/virsh-completer-domain.c +++ b/tools/virsh-completer-domain.c @@ -656,3 +656,58 @@ virshDomainVcpulistViaAgentCompleter(vshControl *ctl, virshDomainFree(dom); return ret; } + +char ** +virshDomainConsoleCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags) +{ + virshControlPtr priv = ctl->privData; + g_autoptr(xmlDoc) xmldoc = NULL; + g_autoptr(xmlXPathContext) ctxt = NULL; + int nserials; + int nparallels; + g_autofree xmlNodePtr *serials = NULL; + g_autofree xmlNodePtr *parallels = NULL; + size_t i; + size_t offset = 0; + VIR_AUTOSTRINGLIST tmp = NULL; + + virCheckFlags(0, NULL); + + if (!priv->conn || virConnectIsAlive(priv->conn) <= 0) + return NULL; + + if (virshDomainGetXML(ctl, cmd, 0, &xmldoc, &ctxt) < 0) + return NULL; + + nserials = virXPathNodeSet("./devices/serial", ctxt, &serials); + if (nserials < 0) + return NULL; + + nparallels = virXPathNodeSet("./devices/parallel", ctxt, ¶llels); + if (nparallels < 0) + return NULL; + + tmp = g_new0(char *, nserials + nparallels + 1); + + for (i = 0; i < nserials; i++) { + ctxt->node = serials[i]; + + if (STRNEQ(virXPathString("string(./@type)", ctxt), "pty"))
virXPathString() returns an allocated string which is leaked here ..
+ continue; + + tmp[offset++] = virXPathString("string(./alias/@name)", ctxt); + } + + for (i = 0; i < nparallels; i++) { + ctxt->node = parallels[i]; + + if (STRNEQ(virXPathString("string(./@type)", ctxt), "pty"))
.. and here.
+ continue; + + tmp[offset++] = virXPathString("string(./alias/@name)", ctxt); + } + + return g_steal_pointer(&tmp); +} diff --git a/tools/virsh-completer-domain.h b/tools/virsh-completer-domain.h index d5021f6aa6..02fea2fe94 100644 --- a/tools/virsh-completer-domain.h +++ b/tools/virsh-completer-domain.h @@ -94,3 +94,7 @@ char ** virshDomainCpulistCompleter(vshControl *ctl, char ** virshDomainVcpulistViaAgentCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); + +char ** virshDomainConsoleCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 675d96440d..022dbdca3c 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -2960,6 +2960,7 @@ static const vshCmdOptDef opts_console[] = { VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE), {.name = "devname", /* sc_prohibit_devname */ .type = VSH_OT_STRING, + .completer = virshDomainConsoleCompleter, .help = N_("character device name") }, {.name = "force",
Michal

It will be helpful to get the desired string of interface name/mac in a consistent way. Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-interface.c | 25 ++++++++++++++++--------- tools/virsh-completer-interface.h | 3 +++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/tools/virsh-completer-interface.c b/tools/virsh-completer-interface.c index 8028db8746..407021485f 100644 --- a/tools/virsh-completer-interface.c +++ b/tools/virsh-completer-interface.c @@ -25,16 +25,16 @@ #include "virsh.h" #include "virstring.h" -char ** -virshInterfaceNameCompleter(vshControl *ctl, - const vshCmd *cmd G_GNUC_UNUSED, - unsigned int flags) +static char ** +virshInterfaceStringHelper(vshControl *ctl, + const vshCmd *cmd G_GNUC_UNUSED, + unsigned int flags, + virInterfaceStringCallback cb) { virshControlPtr priv = ctl->privData; virInterfacePtr *ifaces = NULL; int nifaces = 0; size_t i = 0; - char **ret = NULL; VIR_AUTOSTRINGLIST tmp = NULL; virCheckFlags(VIR_CONNECT_LIST_INTERFACES_ACTIVE | @@ -50,15 +50,22 @@ virshInterfaceNameCompleter(vshControl *ctl, tmp = g_new0(char *, nifaces + 1); for (i = 0; i < nifaces; i++) { - const char *name = virInterfaceGetName(ifaces[i]); + const char *name = (cb)(ifaces[i]); tmp[i] = g_strdup(name); } - ret = g_steal_pointer(&tmp); - for (i = 0; i < nifaces; i++) virInterfaceFree(ifaces[i]); g_free(ifaces); - return ret; + + return g_steal_pointer(&tmp); +} + +char ** +virshInterfaceNameCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags) +{ + return virshInterfaceStringHelper(ctl, cmd, flags, virInterfaceGetName); } diff --git a/tools/virsh-completer-interface.h b/tools/virsh-completer-interface.h index 893dee5a6b..32da01e766 100644 --- a/tools/virsh-completer-interface.h +++ b/tools/virsh-completer-interface.h @@ -22,6 +22,9 @@ #include "vsh.h" +typedef const char * +(*virInterfaceStringCallback)(virInterfacePtr iface); + char ** virshInterfaceNameCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); -- 2.26.0

On 11/10/20 10:50 AM, Lin Ma wrote:
It will be helpful to get the desired string of interface name/mac in a consistent way.
Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-interface.c | 25 ++++++++++++++++--------- tools/virsh-completer-interface.h | 3 +++ 2 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/tools/virsh-completer-interface.c b/tools/virsh-completer-interface.c index 8028db8746..407021485f 100644 --- a/tools/virsh-completer-interface.c +++ b/tools/virsh-completer-interface.c @@ -25,16 +25,16 @@ #include "virsh.h" #include "virstring.h"
-char ** -virshInterfaceNameCompleter(vshControl *ctl, - const vshCmd *cmd G_GNUC_UNUSED, - unsigned int flags) +static char ** +virshInterfaceStringHelper(vshControl *ctl, + const vshCmd *cmd G_GNUC_UNUSED, + unsigned int flags, + virInterfaceStringCallback cb) { virshControlPtr priv = ctl->privData; virInterfacePtr *ifaces = NULL; int nifaces = 0; size_t i = 0; - char **ret = NULL; VIR_AUTOSTRINGLIST tmp = NULL;
virCheckFlags(VIR_CONNECT_LIST_INTERFACES_ACTIVE | @@ -50,15 +50,22 @@ virshInterfaceNameCompleter(vshControl *ctl, tmp = g_new0(char *, nifaces + 1);
for (i = 0; i < nifaces; i++) { - const char *name = virInterfaceGetName(ifaces[i]); + const char *name = (cb)(ifaces[i]);
tmp[i] = g_strdup(name); }
- ret = g_steal_pointer(&tmp); - for (i = 0; i < nifaces; i++) virInterfaceFree(ifaces[i]); g_free(ifaces); - return ret; + + return g_steal_pointer(&tmp); +} + +char ** +virshInterfaceNameCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags) +{ + return virshInterfaceStringHelper(ctl, cmd, flags, virInterfaceGetName); } diff --git a/tools/virsh-completer-interface.h b/tools/virsh-completer-interface.h index 893dee5a6b..32da01e766 100644 --- a/tools/virsh-completer-interface.h +++ b/tools/virsh-completer-interface.h @@ -22,6 +22,9 @@
#include "vsh.h"
+typedef const char * +(*virInterfaceStringCallback)(virInterfacePtr iface); +
This definition belongs to virsh-completer-interface.c because the function using it is static and thus there is no way anybody else can call it hence less header pollution. Michal

Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-interface.c | 9 +++++++++ tools/virsh-completer-interface.h | 4 ++++ tools/virsh-interface.c | 1 + 3 files changed, 14 insertions(+) diff --git a/tools/virsh-completer-interface.c b/tools/virsh-completer-interface.c index 407021485f..dea8d645cd 100644 --- a/tools/virsh-completer-interface.c +++ b/tools/virsh-completer-interface.c @@ -69,3 +69,12 @@ virshInterfaceNameCompleter(vshControl *ctl, { return virshInterfaceStringHelper(ctl, cmd, flags, virInterfaceGetName); } + +char ** +virshInterfaceMacCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags) +{ + return virshInterfaceStringHelper(ctl, cmd, flags, + virInterfaceGetMACString); +} diff --git a/tools/virsh-completer-interface.h b/tools/virsh-completer-interface.h index 32da01e766..b48ded6a12 100644 --- a/tools/virsh-completer-interface.h +++ b/tools/virsh-completer-interface.h @@ -28,3 +28,7 @@ typedef const char * char ** virshInterfaceNameCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); + +char ** virshInterfaceMacCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-interface.c b/tools/virsh-interface.c index 8cdbc6e85f..ae2b52bfc3 100644 --- a/tools/virsh-interface.c +++ b/tools/virsh-interface.c @@ -404,6 +404,7 @@ static const vshCmdOptDef opts_interface_name[] = { {.name = "interface", .type = VSH_OT_DATA, .flags = VSH_OFLAG_REQ, + .completer = virshInterfaceMacCompleter, .help = N_("interface mac") }, {.name = NULL} -- 2.26.0

On 11/10/20 10:50 AM, Lin Ma wrote:
Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-interface.c | 9 +++++++++ tools/virsh-completer-interface.h | 4 ++++ tools/virsh-interface.c | 1 + 3 files changed, 14 insertions(+)
diff --git a/tools/virsh-completer-interface.c b/tools/virsh-completer-interface.c index 407021485f..dea8d645cd 100644 --- a/tools/virsh-completer-interface.c +++ b/tools/virsh-completer-interface.c @@ -69,3 +69,12 @@ virshInterfaceNameCompleter(vshControl *ctl, { return virshInterfaceStringHelper(ctl, cmd, flags, virInterfaceGetName); } + +char ** +virshInterfaceMacCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags) +{ + return virshInterfaceStringHelper(ctl, cmd, flags, + virInterfaceGetMACString); +} diff --git a/tools/virsh-completer-interface.h b/tools/virsh-completer-interface.h index 32da01e766..b48ded6a12 100644 --- a/tools/virsh-completer-interface.h +++ b/tools/virsh-completer-interface.h @@ -28,3 +28,7 @@ typedef const char * char ** virshInterfaceNameCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); + +char ** virshInterfaceMacCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-interface.c b/tools/virsh-interface.c index 8cdbc6e85f..ae2b52bfc3 100644 --- a/tools/virsh-interface.c +++ b/tools/virsh-interface.c @@ -404,6 +404,7 @@ static const vshCmdOptDef opts_interface_name[] = { {.name = "interface", .type = VSH_OT_DATA, .flags = VSH_OFLAG_REQ, + .completer = virshInterfaceMacCompleter, .help = N_("interface mac") }, {.name = NULL}
Beautiful. Michal

Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-interface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/virsh-interface.c b/tools/virsh-interface.c index ae2b52bfc3..ae234e1e22 100644 --- a/tools/virsh-interface.c +++ b/tools/virsh-interface.c @@ -786,6 +786,7 @@ static const vshCmdOptDef opts_interface_bridge[] = { {.name = "interface", .type = VSH_OT_DATA, .flags = VSH_OFLAG_REQ, + .completer = virshInterfaceNameCompleter, .help = N_("existing interface name") }, {.name = "bridge", -- 2.26.0

Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-interface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/virsh-interface.c b/tools/virsh-interface.c index ae234e1e22..858052d341 100644 --- a/tools/virsh-interface.c +++ b/tools/virsh-interface.c @@ -441,6 +441,7 @@ static const vshCmdOptDef opts_interface_mac[] = { {.name = "interface", .type = VSH_OT_DATA, .flags = VSH_OFLAG_REQ, + .completer = virshInterfaceNameCompleter, .help = N_("interface name") }, {.name = NULL} -- 2.26.0

We know that the bash completer automatically handle colon by preceding it with an escape character backslash. While our bash autompletion file vsh completes multiple items, In case there're multiple items which have same prefix and the content of completion items contain colon(say mac address), The vsh needs to correctly hands the backslash which are added by bash completer, Otherwise the completion won't be successful. This patch fixes this problem. e.g.: # virsh domiflist --domain VM Interface Type Source Model MAC ------------------------------------------------------------- vnet0 network default virtio 52:54:00:fb:7b:f5 vnet1 bridge br0 virtio 52:54:00:80:1b:21 Before: # virsh detach-interface --domain VM --mac <TAB> # virsh detach-interface --domain VM --mac 52\:54\:00\:<TAB><TAB> After: # virsh detach-interface --domain VM --mac <TAB> # virsh detach-interface --domain VM --mac 52\:54\:00\:<TAB><TAB> 52:54:00:80:1b:21 52:54:00:fb:7b:f5 # virsh detach-interface --domain VM --mac 52\:54\:00\: Signed-off-by: Lin Ma <lma@suse.com> --- tools/bash-completion/vsh | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/bash-completion/vsh b/tools/bash-completion/vsh index 8493cad28b..fb38e8616f 100644 --- a/tools/bash-completion/vsh +++ b/tools/bash-completion/vsh @@ -39,6 +39,7 @@ _vsh_complete() fi INPUT=( "${COMP_WORDS[@]:$i:$COMP_CWORD}" ) + INPUT[-1]=${INPUT[-1]//\\:/:} # Uncomment these lines for easy debug. # echo; -- 2.26.0

Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-network.c | 44 +++++++++++++++++++++++++++++++++ tools/virsh-completer-network.h | 4 +++ tools/virsh-network.c | 15 +++++++---- 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/tools/virsh-completer-network.c b/tools/virsh-completer-network.c index 73f7115ab2..3094b9d5d6 100644 --- a/tools/virsh-completer-network.c +++ b/tools/virsh-completer-network.c @@ -174,3 +174,47 @@ virshNetworkUUIDCompleter(vshControl *ctl, g_free(nets); return ret; } + + +char ** +virshNetworkDhcpMacCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags) +{ + virshControlPtr priv = ctl->privData; + virNetworkDHCPLeasePtr *leases = NULL; + virNetworkPtr network = NULL; + int nleases; + size_t i = 0; + char **ret = NULL; + VIR_AUTOSTRINGLIST tmp = NULL; + + virCheckFlags(0, NULL); + + if (!priv->conn || virConnectIsAlive(priv->conn) <= 0) + return NULL; + + if (!(network = virshCommandOptNetwork(ctl, cmd, NULL))) + return NULL; + + if ((nleases = virNetworkGetDHCPLeases(network, NULL, &leases, flags)) < 0) + goto cleanup; + + tmp = g_new0(char *, nleases + 1); + + for (i = 0; i < nleases; i++) { + virNetworkDHCPLeasePtr lease = leases[i]; + tmp[i] = g_strdup(lease->mac); + } + + ret = g_steal_pointer(&tmp); + + cleanup: + if (leases) { + for (i = 0; i < nleases; i++) + virNetworkDHCPLeaseFree(leases[i]); + VIR_FREE(leases); + } + virNetworkFree(network); + return ret; +} diff --git a/tools/virsh-completer-network.h b/tools/virsh-completer-network.h index 8910e4525c..80df5c468e 100644 --- a/tools/virsh-completer-network.h +++ b/tools/virsh-completer-network.h @@ -37,3 +37,7 @@ char ** virshNetworkPortUUIDCompleter(vshControl *ctl, char ** virshNetworkUUIDCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); + +char ** virshNetworkDhcpMacCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-network.c b/tools/virsh-network.c index 745afc537d..30b231f7d6 100644 --- a/tools/virsh-network.c +++ b/tools/virsh-network.c @@ -61,6 +61,15 @@ .completer_flags = cflags, \ } +#define VIRSH_COMMON_OPT_NETWORK_DHCP_MAC(_helpstr, cflags) \ + {.name = "mac", \ + .type = VSH_OT_STRING, \ + .flags = VSH_OFLAG_NONE, \ + .help = _helpstr, \ + .completer = virshNetworkDhcpMacCompleter, \ + .completer_flags = cflags, \ + } + virNetworkPtr virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd, @@ -1373,11 +1382,7 @@ static const vshCmdInfo info_network_dhcp_leases[] = { static const vshCmdOptDef opts_network_dhcp_leases[] = { VIRSH_COMMON_OPT_NETWORK_FULL(VIR_CONNECT_LIST_NETWORKS_ACTIVE), - {.name = "mac", - .type = VSH_OT_STRING, - .flags = VSH_OFLAG_NONE, - .help = N_("MAC address") - }, + VIRSH_COMMON_OPT_NETWORK_DHCP_MAC(N_("MAC address"), 0), {.name = NULL} }; -- 2.26.0

On 11/10/20 10:51 AM, Lin Ma wrote:
Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-network.c | 44 +++++++++++++++++++++++++++++++++ tools/virsh-completer-network.h | 4 +++ tools/virsh-network.c | 15 +++++++---- 3 files changed, 58 insertions(+), 5 deletions(-)
diff --git a/tools/virsh-completer-network.c b/tools/virsh-completer-network.c index 73f7115ab2..3094b9d5d6 100644 --- a/tools/virsh-completer-network.c +++ b/tools/virsh-completer-network.c @@ -174,3 +174,47 @@ virshNetworkUUIDCompleter(vshControl *ctl, g_free(nets); return ret; } + + +char ** +virshNetworkDhcpMacCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags) +{ + virshControlPtr priv = ctl->privData; + virNetworkDHCPLeasePtr *leases = NULL; + virNetworkPtr network = NULL; + int nleases; + size_t i = 0; + char **ret = NULL; + VIR_AUTOSTRINGLIST tmp = NULL; + + virCheckFlags(0, NULL); + + if (!priv->conn || virConnectIsAlive(priv->conn) <= 0) + return NULL; + + if (!(network = virshCommandOptNetwork(ctl, cmd, NULL))) + return NULL; + + if ((nleases = virNetworkGetDHCPLeases(network, NULL, &leases, flags)) < 0) + goto cleanup; + + tmp = g_new0(char *, nleases + 1); + + for (i = 0; i < nleases; i++) { + virNetworkDHCPLeasePtr lease = leases[i]; + tmp[i] = g_strdup(lease->mac); + } + + ret = g_steal_pointer(&tmp); + + cleanup: + if (leases) { + for (i = 0; i < nleases; i++) + virNetworkDHCPLeaseFree(leases[i]); + VIR_FREE(leases); + } + virNetworkFree(network); + return ret; +} diff --git a/tools/virsh-completer-network.h b/tools/virsh-completer-network.h index 8910e4525c..80df5c468e 100644 --- a/tools/virsh-completer-network.h +++ b/tools/virsh-completer-network.h @@ -37,3 +37,7 @@ char ** virshNetworkPortUUIDCompleter(vshControl *ctl, char ** virshNetworkUUIDCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); + +char ** virshNetworkDhcpMacCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-network.c b/tools/virsh-network.c index 745afc537d..30b231f7d6 100644 --- a/tools/virsh-network.c +++ b/tools/virsh-network.c @@ -61,6 +61,15 @@ .completer_flags = cflags, \ }
+#define VIRSH_COMMON_OPT_NETWORK_DHCP_MAC(_helpstr, cflags) \ + {.name = "mac", \ + .type = VSH_OT_STRING, \ + .flags = VSH_OFLAG_NONE, \ + .help = _helpstr, \ + .completer = virshNetworkDhcpMacCompleter, \ + .completer_flags = cflags, \ + } +
You don't seem to use this macro anywhere else. I think we can just add .completer ...
virNetworkPtr virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd, @@ -1373,11 +1382,7 @@ static const vshCmdInfo info_network_dhcp_leases[] = {
static const vshCmdOptDef opts_network_dhcp_leases[] = { VIRSH_COMMON_OPT_NETWORK_FULL(VIR_CONNECT_LIST_NETWORKS_ACTIVE), - {.name = "mac", - .type = VSH_OT_STRING, - .flags = VSH_OFLAG_NONE, - .help = N_("MAC address")
.. here.
- }, + VIRSH_COMMON_OPT_NETWORK_DHCP_MAC(N_("MAC address"), 0), {.name = NULL} };
Michal

The upcoming patches introduce completers into virsh-completer-domain.c, They will invoke the functions which are defined in virsh-domain.c, So these functions need to be declared in virsh-domain.h. Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-domain.c | 1 - tools/virsh-domain.h | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 022dbdca3c..472b510a6b 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -8910,7 +8910,6 @@ static const vshCmdOptDef opts_send_process_signal[] = { {.name = NULL} }; -VIR_ENUM_DECL(virDomainProcessSignal); VIR_ENUM_IMPL(virDomainProcessSignal, VIR_DOMAIN_PROCESS_SIGNAL_LAST, "nop", "hup", "int", "quit", "ill", /* 0-4 */ diff --git a/tools/virsh-domain.h b/tools/virsh-domain.h index 0d59c579d4..70e2aba1b1 100644 --- a/tools/virsh-domain.h +++ b/tools/virsh-domain.h @@ -39,3 +39,7 @@ typedef enum { VIR_ENUM_DECL(virshDomainHostnameSource); extern const vshCmdDef domManagementCmds[]; + +VIR_ENUM_DECL(virDomainProcessSignal); +VIR_ENUM_DECL(virDomainLifecycle); +VIR_ENUM_DECL(virDomainLifecycleAction); -- 2.26.0

Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-domain.c | 20 ++++++++++++++++++++ tools/virsh-completer-domain.h | 4 ++++ tools/virsh-domain.c | 1 + 3 files changed, 25 insertions(+) diff --git a/tools/virsh-completer-domain.c b/tools/virsh-completer-domain.c index dc66317561..b8b6c74f8b 100644 --- a/tools/virsh-completer-domain.c +++ b/tools/virsh-completer-domain.c @@ -711,3 +711,23 @@ virshDomainConsoleCompleter(vshControl *ctl, return g_steal_pointer(&tmp); } + +char ** +virshDomainSignalCompleter(vshControl *ctl G_GNUC_UNUSED, + const vshCmd *cmd G_GNUC_UNUSED, + unsigned int flags) +{ + size_t i = 0; + VIR_AUTOSTRINGLIST tmp = NULL; + + virCheckFlags(0, NULL); + + tmp = g_new0(char *, VIR_DOMAIN_PROCESS_SIGNAL_LAST + 1); + + for (i = 0; i < VIR_DOMAIN_PROCESS_SIGNAL_LAST; i++) { + const char *name = virDomainProcessSignalTypeToString(i); + tmp[i] = g_strdup(name); + } + + return g_steal_pointer(&tmp); +} diff --git a/tools/virsh-completer-domain.h b/tools/virsh-completer-domain.h index 02fea2fe94..cdec66f23e 100644 --- a/tools/virsh-completer-domain.h +++ b/tools/virsh-completer-domain.h @@ -98,3 +98,7 @@ char ** virshDomainVcpulistViaAgentCompleter(vshControl *ctl, char ** virshDomainConsoleCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); + +char ** virshDomainSignalCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 472b510a6b..1406bb4583 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -8905,6 +8905,7 @@ static const vshCmdOptDef opts_send_process_signal[] = { {.name = "signame", .type = VSH_OT_DATA, .flags = VSH_OFLAG_REQ, + .completer = virshDomainSignalCompleter, .help = N_("the signal number or name") }, {.name = NULL} -- 2.26.0

Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-domain.c | 20 ++++++++++++++++++++ tools/virsh-completer-domain.h | 4 ++++ tools/virsh-domain.c | 1 + 3 files changed, 25 insertions(+) diff --git a/tools/virsh-completer-domain.c b/tools/virsh-completer-domain.c index b8b6c74f8b..b1b670ffc5 100644 --- a/tools/virsh-completer-domain.c +++ b/tools/virsh-completer-domain.c @@ -731,3 +731,23 @@ virshDomainSignalCompleter(vshControl *ctl G_GNUC_UNUSED, return g_steal_pointer(&tmp); } + +char ** +virshDomainLifecycleCompleter(vshControl *ctl G_GNUC_UNUSED, + const vshCmd *cmd G_GNUC_UNUSED, + unsigned int flags) +{ + size_t i = 0; + VIR_AUTOSTRINGLIST tmp = NULL; + + virCheckFlags(0, NULL); + + tmp = g_new0(char *, VIR_DOMAIN_LIFECYCLE_LAST + 1); + + for (i = 0; i < VIR_DOMAIN_LIFECYCLE_LAST; i++) { + const char *name = virDomainLifecycleTypeToString(i); + tmp[i] = g_strdup(name); + } + + return g_steal_pointer(&tmp); +} diff --git a/tools/virsh-completer-domain.h b/tools/virsh-completer-domain.h index cdec66f23e..70f6e30947 100644 --- a/tools/virsh-completer-domain.h +++ b/tools/virsh-completer-domain.h @@ -102,3 +102,7 @@ char ** virshDomainConsoleCompleter(vshControl *ctl, char ** virshDomainSignalCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); + +char ** virshDomainLifecycleCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 1406bb4583..be91bd48fc 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -5717,6 +5717,7 @@ static const vshCmdOptDef opts_setLifecycleAction[] = { {.name = "type", .type = VSH_OT_DATA, .flags = VSH_OFLAG_REQ, + .completer = virshDomainLifecycleCompleter, .help = N_("lifecycle type to modify") }, {.name = "action", -- 2.26.0

Signed-off-by: Lin Ma <lma@suse.com> --- tools/virsh-completer-domain.c | 20 ++++++++++++++++++++ tools/virsh-completer-domain.h | 4 ++++ tools/virsh-domain.c | 1 + 3 files changed, 25 insertions(+) diff --git a/tools/virsh-completer-domain.c b/tools/virsh-completer-domain.c index b1b670ffc5..a44ee65642 100644 --- a/tools/virsh-completer-domain.c +++ b/tools/virsh-completer-domain.c @@ -751,3 +751,23 @@ virshDomainLifecycleCompleter(vshControl *ctl G_GNUC_UNUSED, return g_steal_pointer(&tmp); } + +char ** +virshDomainLifecycleActionCompleter(vshControl *ctl G_GNUC_UNUSED, + const vshCmd *cmd G_GNUC_UNUSED, + unsigned int flags) +{ + size_t i = 0; + VIR_AUTOSTRINGLIST tmp = NULL; + + virCheckFlags(0, NULL); + + tmp = g_new0(char *, VIR_DOMAIN_LIFECYCLE_ACTION_LAST + 1); + + for (i = 0; i < VIR_DOMAIN_LIFECYCLE_ACTION_LAST; i++) { + const char *action = virDomainLifecycleActionTypeToString(i); + tmp[i] = g_strdup(action); + } + + return g_steal_pointer(&tmp); +} diff --git a/tools/virsh-completer-domain.h b/tools/virsh-completer-domain.h index 70f6e30947..92c57bce75 100644 --- a/tools/virsh-completer-domain.h +++ b/tools/virsh-completer-domain.h @@ -106,3 +106,7 @@ char ** virshDomainSignalCompleter(vshControl *ctl, char ** virshDomainLifecycleCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); + +char ** virshDomainLifecycleActionCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index be91bd48fc..12b35c037d 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -5723,6 +5723,7 @@ static const vshCmdOptDef opts_setLifecycleAction[] = { {.name = "action", .type = VSH_OT_DATA, .flags = VSH_OFLAG_REQ, + .completer = virshDomainLifecycleActionCompleter, .help = N_("lifecycle action to set") }, VIRSH_COMMON_OPT_DOMAIN_CONFIG, -- 2.26.0

On 11/10/20 10:50 AM, Lin Ma wrote:
Add more bash completions for some of virsh subcommands/subparameters.
v1->v2
* Follow Michal's suggestions: - guestvcpus command: complete offlined vCPUs if --enable, complete onlined vCPUs if --disable - Added a static helper function for interface string provider, - Adjusted some needlessly complicated loops. * Refered to Peter and Michal's comments, I droped the vnc completion patches. * Concentrate on completion itself, Drop all of patches which related to macros to make review easier.
Lin Ma (13): virsh: Add vcpu list completion to guestvcpus command virsh: Add logical CPU IDs completion for nodecpustats command virsh: Add serial/parallel device name completion to console command virsh-interface: Add a static helper virshInterfaceStringHelper virsh: Add interface mac completion to iface-name command virsh: Add interface name completion to iface-bridge command virsh: Add interface name completion to iface-mac command vsh: Fix completion error in case of multiple mac addresses virsh: Add mac completion to net-dhcp-leases command virsh: Move/add some of function declarations to virsh-domain.h virsh: Add signal name completion to send-process-signal command virsh: Add lifecycle type completion to set-lifecycle-action command Add lifecycle action completion to set-lifecycle-action command
tools/bash-completion/vsh | 1 + tools/virsh-completer-domain.c | 190 ++++++++++++++++++++++++++++++ tools/virsh-completer-domain.h | 20 ++++ tools/virsh-completer-host.c | 31 +++++ tools/virsh-completer-host.h | 4 + tools/virsh-completer-interface.c | 34 ++++-- tools/virsh-completer-interface.h | 7 ++ tools/virsh-completer-network.c | 44 +++++++ tools/virsh-completer-network.h | 4 + tools/virsh-domain.c | 6 +- tools/virsh-domain.h | 4 + tools/virsh-host.c | 1 + tools/virsh-interface.c | 3 + tools/virsh-network.c | 15 ++- 14 files changed, 349 insertions(+), 15 deletions(-)
I've fixed all the small problems I found and Reviewed-by: Michal Privoznik <mprivozn@redhat.com> and pushed. Michal
participants (2)
-
Lin Ma
-
Michal Privoznik