Quoting Daniel P. Berrange (berrange@xxxxxxxxxx): > On Thu, Oct 06, 2011 at 08:30:55AM -0500, Serge E. Hallyn wrote: > > Quoting Daniel P. Berrange (berrange@xxxxxxxxxx): > > > On Wed, Oct 05, 2011 at 03:17:47PM -0500, Serge E. Hallyn wrote: > > > > Hi, > > > > > > > > I've been trying out a bash autocompletion file by Geoff Low (slight hack > > > > by me, don't blame him for my hack), and it's working pretty nicely. > > > > I'm not sure where to put it in the git tree, but it seems like it'd be > > > > nice to have upstream? > > > > > > David Lutterkort previously suggested this > > > > > > https://www.redhat.com/archives/libvir-list/2007-October/msg00231.html > > > > > > And I didn't ever notice that and so wrote one myself > > > > > > https://www.redhat.com/archives/libvir-list/2008-July/msg00175.html > > > https://www.redhat.com/archives/libvir-list/2008-July/msg00177.html > > > > > > Neither ever got committed. There were some things I didn't much like > > > about mine, but I can't really remember now. > > > > > > Third time lucky perhaps :-) > > > > So the things you didn't much like must not have been *too* bad? :) > > Are you going to make some changes and resubmit, or would you like > > me to test (and port as needed) the above patches first? > > I don't have time right now to update my own patches. You, or anyone > else, are free to take them forward as desired... Well I've got the patch ported so that it mostly works - autocompletes for commands and vm names at least. (ugly patch against 0.9.8 attached just for conversation) But I can't figure out how one should do uri completion. Any hints on where to get such a list now? thanks, -serge Index: libvirt-0.9.8/include/libvirt/libvirt.h =================================================================== --- libvirt-0.9.8.orig/include/libvirt/libvirt.h 2011-12-08 06:58:49.000000000 +0000 +++ libvirt-0.9.8/include/libvirt/libvirt.h 2012-02-08 03:52:16.008232120 +0000 @@ -1065,6 +1065,7 @@ unsigned int flags); int virConnectRef (virConnectPtr conn); int virConnectClose (virConnectPtr conn); +char ** virConnectURIs (int *nuris); const char * virConnectGetType (virConnectPtr conn); int virConnectGetVersion (virConnectPtr conn, unsigned long *hvVer); Index: libvirt-0.9.8/include/libvirt/libvirt.h.in =================================================================== --- libvirt-0.9.8.orig/include/libvirt/libvirt.h.in 2011-12-06 08:38:51.000000000 +0000 +++ libvirt-0.9.8/include/libvirt/libvirt.h.in 2012-02-08 03:52:35.132225305 +0000 @@ -1065,6 +1065,7 @@ unsigned int flags); int virConnectRef (virConnectPtr conn); int virConnectClose (virConnectPtr conn); +char ** virConnectURIs (int *nuris); const char * virConnectGetType (virConnectPtr conn); int virConnectGetVersion (virConnectPtr conn, unsigned long *hvVer); Index: libvirt-0.9.8/libvirt.spec.in =================================================================== --- libvirt-0.9.8.orig/libvirt.spec.in 2011-12-08 06:54:48.000000000 +0000 +++ libvirt-0.9.8/libvirt.spec.in 2012-02-08 03:54:03.300230906 +0000 @@ -1050,6 +1050,7 @@ %{_unitdir}/libvirtd.service %endif %doc daemon/libvirtd.upstart +%{_sysconfdir}/bash_completion.d/virsh %config(noreplace) %{_sysconfdir}/sysconfig/libvirtd %config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf %if 0%{?fedora} >= 14 || 0%{?rhel} >= 6 Index: libvirt-0.9.8/src/Makefile.am =================================================================== --- libvirt-0.9.8.orig/src/Makefile.am 2012-02-08 03:46:38.000000000 +0000 +++ libvirt-0.9.8/src/Makefile.am 2012-02-08 20:51:04.340232096 +0000 @@ -22,7 +22,9 @@ $(COVERAGE_CFLAGS) AM_LDFLAGS = $(COVERAGE_LDFLAGS) -EXTRA_DIST = $(conf_DATA) util/keymaps.csv +bashdir = $(sysconfdir)/bash_completion.d + +EXTRA_DIST = $(conf_DATA) util/keymaps.csv virsh.bash BUILT_SOURCES = CLEANFILES = @@ -1584,6 +1586,8 @@ $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/default.xml && \ rm $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/default.xml.t; } endif + $(MKDIR_P) "$(DESTDIR)$(bashdir)" + $(INSTALL_DATA) "$(srcdir)/virsh.bash" "$(DESTDIR)$(bashdir)/virsh" uninstall-local:: rmdir "$(DESTDIR)$(localstatedir)/cache/libvirt" ||: @@ -1621,6 +1625,7 @@ rmdir "$(DESTDIR)$(localstatedir)/run/libvirt/network" ||: endif rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt" ||: + rm -f "$(DESTDIR)$(bashdir)/virsh" ||: CLEANFILES += *.gcov .libs/*.gcda .libs/*.gcno *.gcno *.gcda *.i *.s DISTCLEANFILES += $(GENERATED_SYM_FILES) Index: libvirt-0.9.8/src/libvirt.c =================================================================== --- libvirt-0.9.8.orig/src/libvirt.c 2011-12-08 02:26:59.000000000 +0000 +++ libvirt-0.9.8/src/libvirt.c 2012-02-09 04:13:30.168233577 +0000 @@ -1317,6 +1317,77 @@ } /** + * virConnectURIs: + * @nuris: pointer to an integer in which to store the number of URIS + * + * This functions returns the list of available connection + * URIs. The caller is responsible for freeing the returned + * strings, and the array they're stored in. + * + * Returns the URIs in case of success or NULL case of error. + */ +char ** +virConnectURIs(int *nuris) +{ + char **ret = NULL; + int i; + int n = 0; + + if (!initialized) + if (virInitialize() < 0) + return NULL; + + for (i = 0; i < virDriverTabCount; i++) { + virConnectPtr conn; + int res; + + printf("URI %d: 1, name %s\n", i, virDriverTab[i]->name); + conn = virGetConnect(); + if (!conn) + goto no_memory; + printf("URI %d: 2\n", i); + res = virDriverTab[i]->open (conn, NULL, 0); + printf("URI %d: 3\n", i); + if (res != VIR_DRV_OPEN_SUCCESS) + goto next; + printf("URI %d: 4\n", i); + if (!conn->uri) + goto next; + printf("URI %d: 5\n", i); + if (VIR_REALLOC_N(ret, n+1) < 0) { + printf("URI %d: 6\n", i); + virConnectClose(conn); + goto no_memory; + } + printf("URI %d: 7, conn->uri is\n", i, conn->uri); + if ((ret[n++] = strdup(conn->uri)) == NULL) { + printf("URI %d: 8\n", i); + virConnectClose(conn); + goto no_memory; + } + printf("URI %d: 9\n", i); +next: + printf("URI %d: 10\n", i); + virConnectClose(conn); + } + + *nuris = n; + printf("URI %d: 11\n", *nuris); + for (i=0; i<n; i++) + printf("uri %d: %s\n", i, ret[i]); + return ret; + +no_memory: + printf("URI %d: 12\n", *nuris); + for (i = 0 ; i < n ; i++) + VIR_FREE(ret[i]); + VIR_FREE(ret); + *nuris = 0; + virLibConnError(VIR_ERR_NO_MEMORY, __FUNCTION__); + return NULL; +} + +/** * virConnectOpen: * @name: URI of the hypervisor * Index: libvirt-0.9.8/src/libvirt_public.syms =================================================================== --- libvirt-0.9.8.orig/src/libvirt_public.syms 2011-12-02 03:59:50.000000000 +0000 +++ libvirt-0.9.8/src/libvirt_public.syms 2012-02-08 04:03:52.360265205 +0000 @@ -506,6 +506,7 @@ virDomainGetBlockIoTune; virDomainSetBlockIoTune; virNodeSuspendForDuration; + virConnectURIs; } LIBVIRT_0.9.7; # .... define new API here using predicted next version number .... Index: libvirt-0.9.8/src/virsh.bash =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-0.9.8/src/virsh.bash 2012-02-08 22:56:26.536232538 +0000 @@ -0,0 +1,83 @@ +_virsh() +{ + local cur prev cmd cmd_index arg arg_index i results skipconn + local virsh="$1" + local canonical=0 + + COMPREPLY=() + cur="$2" + prev="$3" + + if [[ $COMP_CWORD > 1 && ${COMP_WORDS[COMP_CWORD-1]} = '--connect' ]]; then + results="$($virsh _complete-uri)" || nets="" + fi + + skipconn=0 + if [ -z "$results" ]; then + # searching for the command name + for ((i=1; $i<=$COMP_CWORD; i++)); do + if [[ ${COMP_WORDS[i]} != -* ]]; then + if [[ ${COMP_WORDS[i-1]} = '--connect' ]]; then + echo "${COMP_WORDS[i]}" | grep '///' >/dev/null 2>&1 + test "$?" = 1 && skipconn=1 + test "$skipconn" = 0 && virsh="$virsh ${COMP_WORDS[i-1]} ${COMP_WORDS[i]}" + else + if [[ $i < $COMP_CWORD ]]; then + cmd="${COMP_WORDS[i]}" + cmd_index=$i + arg_index=`expr $COMP_CWORD - $cmd_index` + break + fi + fi + fi + done + + if [[ "$cur" == -* ]]; then + # Generate args - global or command specific + results="$($virsh _complete-command options "$cmd")" + else + if [ -z "$cmd" ]; then + # No command set, so generate list of all commands + results="$($virsh _complete-command commands)" || commands="" + else + # Command set, to generate command specific args + n=0 + for i in "$($virsh _complete-command arguments "$cmd")" + do + n=`expr $n + 1` + if [ $n = $arg_index ]; then + arg=$i + break + fi + done + + case $arg in + file) + COMPREPLY=(${COMPREPLY[@]:-} $(compgen -o "default" -- "$cur")) + ;; + + domain) + test "$skipconn" = 0 && results="$($virsh _complete-domain)" || doms="" + ;; + + network) + test "$skipconn" = 0 && results="$($virsh _complete-network)" || nets="" + ;; + + pool) + test "$skipconn" = 0 && results="$($virsh _complete-pool)" || nets="" + ;; + + uri) + results="$($virsh _complete-uri)" || nets="" + ;; + esac + fi + fi + fi + if [ ! -z "$results" ]; then + COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$results' -- "$cur")) + fi +} + +complete -F _virsh virsh Index: libvirt-0.9.8/tools/virsh.c =================================================================== --- libvirt-0.9.8.orig/tools/virsh.c 2012-02-08 03:46:38.000000000 +0000 +++ libvirt-0.9.8/tools/virsh.c 2012-02-08 22:31:14.928233016 +0000 @@ -623,6 +623,414 @@ */ /* + * "_compcmds" command + */ +static vshCmdInfo info_compcommand[] = { + {"syntax", "_complete-command [commands|arguments|options] [<command>]"}, + {"help", gettext_noop("print shell completion data")}, + {"desc", gettext_noop("Prints data useful for shell autocompletion of commands.")}, + + {NULL, NULL} +}; + +static vshCmdOptDef opts_compcommand[] = { + {"type", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("type of data")}, + {"cmd", VSH_OT_DATA, 0, gettext_noop("command name")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdCompCommand(vshControl * ctl, const vshCmd * cmd) +{ + const char *type; + const char *name; + + if (vshCommandOptString(cmd, "type", &type) <= 0) + type = "commands"; + if (vshCommandOptString(cmd, "cmd", &name) <= 0) + name = NULL; + + if (STREQ(type, "commands")) { + const vshCmdGrp *grp; + const vshCmdDef *def; + for (grp = cmdGroups; grp->name; grp++) { + for (def = grp->commands; def->name; def++) + if (def->name[0] != '_') + vshPrint(ctl, "%s\n", def->name); + } + } else if (STREQ(type, "options")) { + if (name) { + const vshCmdDef *def = vshCmddefSearch(name); + if (!def) { + vshError(ctl, _("command '%s' doesn't exist"), name); + return false; + } else if (def->opts) { + const vshCmdOptDef *opt; + for (opt = def->opts; opt->name; opt++) + if (opt->type == VSH_OT_BOOL || + opt->type == VSH_OT_INT || + opt->type == VSH_OT_STRING) + vshPrint(ctl, "--%s\n", opt->name); + } + } else { + vshPrint(ctl, + "-c\n--connect\n" + "-r\n--readonly\n" + "-d\n--debug\n" + "-h\n--help\n" + "-q\n--quiet\n" + "-t\n--timing\n" + "-l\n--log\n" + "-v\n--version\n"); + } + } else if (STREQ(type, "arguments")) { + if (!name) { + vshError(ctl, "%s", _("no command specified")); + return false; + } else { + const vshCmdDef *def = vshCmddefSearch(name); + if (!def) { + vshError(ctl, _("command '%s' doesn't exist"), name); + return false; + } else if (def->opts) { + const vshCmdOptDef *opt; + for (opt = def->opts; opt->name; opt++) + if (opt->type == VSH_OT_DATA) + vshPrint(ctl, "%s\n", opt->name); + } + } + } + return true; +} + +/* + * "_compuris" command + */ +static vshCmdInfo info_compuri[] = { + {"syntax", "_complete-uri"}, + {"help", gettext_noop("print shell completion data for URIs")}, + {"desc", gettext_noop("Prints data useful for shell autocompletion of URIs.")}, + + {NULL, NULL} +}; + +static vshCmdOptDef opts_compuri[] = { + {NULL, 0, 0, NULL} +}; + +static bool +cmdCompUri(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) +{ + char **uris = NULL; + int nuris, i; + + uris = virConnectURIs(&nuris); + if (!uris) { + vshError(ctl, "%s", _("Failed to list connection URIs")); + return false; + } + for (i = 0 ; i < nuris ; i++) { + vshPrint(ctl, "%s\n", uris[i]); + free(uris[i]); + } + + free(uris); + return true; +} +/* + * "_compdomains" command + */ +static vshCmdInfo info_compdomain[] = { + {"syntax", "_complete-domain"}, + {"help", gettext_noop("print shell completion data for domains")}, + {"desc", gettext_noop("Prints data useful for shell autocompletion of domains.")}, + + {NULL, NULL} +}; + +static vshCmdOptDef opts_compdomain[] = { + {NULL, 0, 0, NULL} +}; + +static bool +cmdCompDomain(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) +{ + int *ids = NULL; + char **names = NULL; + int maxname = 0, maxid = 0, i; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + maxid = virConnectNumOfDomains(ctl->conn); + if (maxid < 0) { + vshError(ctl, "%s", _("Failed to list active domains")); + return false; + } + if (maxid) { + ids = vshMalloc(ctl, sizeof(int) * maxid); + + if ((maxid = virConnectListDomains(ctl->conn, &ids[0], maxid)) < 0) { + vshError(ctl, "%s", _("Failed to list active domains")); + free(ids); + return false; + } + + qsort(&ids[0], maxid, sizeof(int), idsorter); + } + maxname = virConnectNumOfDefinedDomains(ctl->conn); + if (maxname < 0) { + vshError(ctl, "%s", _("Failed to list inactive domains")); + free(ids); + return false; + } + if (maxname) { + names = vshMalloc(ctl, sizeof(char *) * maxname); + + if ((maxname = virConnectListDefinedDomains(ctl->conn, names, maxname)) < 0) { + vshError(ctl, "%s", _("Failed to list inactive domains")); + free(ids); + free(names); + return false; + } + + qsort(&names[0], maxname, sizeof(char*), namesorter); + } + + for (i = 0; i < maxid; i++) { + char uuid[VIR_UUID_STRING_BUFLEN]; + virDomainPtr dom = virDomainLookupByID(ctl->conn, ids[i]); + /* this kind of work with domains is not atomic operation */ + if (!dom) + continue; + virDomainGetUUIDString(dom, uuid); + vshPrint(ctl, "%d\n%s\n%s\n", + virDomainGetID(dom), + virDomainGetName(dom), + uuid); + virDomainFree(dom); + } + for (i = 0; i < maxname; i++) { + char uuid[VIR_UUID_STRING_BUFLEN]; + virDomainPtr dom = virDomainLookupByName(ctl->conn, names[i]); + + /* this kind of work with domains is not atomic operation */ + if (!dom) { + free(names[i]); + continue; + } + virDomainGetUUIDString(dom, uuid); + vshPrint(ctl, "%s\n%s\n", + virDomainGetName(dom), + uuid); + virDomainFree(dom); + free(names[i]); + } + free(ids); + free(names); + return true; +} + +/* + * "_compnetworks" command + */ +static vshCmdInfo info_compnetwork[] = { + {"syntax", "_complete-network"}, + {"help", gettext_noop("print shell completion data for networks")}, + {"desc", gettext_noop("Prints data useful for shell autocompletion of networks.")}, + + {NULL, NULL} +}; + +static vshCmdOptDef opts_compnetwork[] = { + {NULL, 0, 0, NULL} +}; + +static bool +cmdCompNetwork(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) +{ + char **activeNames = NULL, **inactiveNames = NULL; + int maxactive = 0, maxinactive = 0, i; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + maxactive = virConnectNumOfNetworks(ctl->conn); + if (maxactive < 0) { + vshError(ctl, "%s", _("Failed to list active networks")); + return false; + } + if (maxactive) { + activeNames = vshMalloc(ctl, sizeof(char *) * maxactive); + + if ((maxactive = virConnectListNetworks(ctl->conn, activeNames, + maxactive)) < 0) { + vshError(ctl, "%s", _("Failed to list active networks")); + free(activeNames); + return false; + } + + qsort(&activeNames[0], maxactive, sizeof(char *), namesorter); + } + maxinactive = virConnectNumOfDefinedNetworks(ctl->conn); + if (maxinactive < 0) { + vshError(ctl, "%s", _("Failed to list inactive networks")); + free(activeNames); + return false; + } + if (maxinactive) { + inactiveNames = vshMalloc(ctl, sizeof(char *) * maxinactive); + + if ((maxinactive = virConnectListDefinedNetworks(ctl->conn, inactiveNames, maxinactive)) < 0) { + vshError(ctl, "%s", _("Failed to list inactive networks")); + free(activeNames); + free(inactiveNames); + return false; + } + + qsort(&inactiveNames[0], maxinactive, sizeof(char*), namesorter); + } + + for (i = 0; i < maxactive; i++) { + char uuid[VIR_UUID_STRING_BUFLEN]; + virNetworkPtr network = virNetworkLookupByName(ctl->conn, activeNames[i]); + + /* this kind of work with networks is not atomic operation */ + if (!network) { + free(activeNames[i]); + continue; + } + virNetworkGetUUIDString(network, uuid); + vshPrint(ctl, "%s\n%s\n", + virNetworkGetName(network), + uuid); + virNetworkFree(network); + free(activeNames[i]); + } + for (i = 0; i < maxinactive; i++) { + char uuid[VIR_UUID_STRING_BUFLEN]; + virNetworkPtr network = virNetworkLookupByName(ctl->conn, inactiveNames[i]); + + /* this kind of work with networks is not atomic operation */ + if (!network) { + free(inactiveNames[i]); + continue; + } + virNetworkGetUUIDString(network, uuid); + vshPrint(ctl, "%s\n%s\n", + virNetworkGetName(network), + uuid); + + virNetworkFree(network); + free(inactiveNames[i]); + } + free(activeNames); + free(inactiveNames); + + return true; +} + + +/* + * "_comppools" command + */ +static vshCmdInfo info_comppool[] = { + {"syntax", "_complete-pool"}, + {"help", gettext_noop("print shell completion data for pools")}, + {"desc", gettext_noop("Prints data useful for shell autocompletion of pools.")}, + + {NULL, NULL} +}; + +static vshCmdOptDef opts_comppool[] = { + {NULL, 0, 0, NULL} +}; + +static bool +cmdCompPool(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) +{ + char **activeNames = NULL, **inactiveNames = NULL; + int maxactive = 0, maxinactive = 0, i; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + maxactive = virConnectNumOfStoragePools(ctl->conn); + if (maxactive < 0) { + vshError(ctl, "%s", _("Failed to list active pools")); + return false; + } + if (maxactive) { + activeNames = vshMalloc(ctl, sizeof(char *) * maxactive); + + if ((maxactive = virConnectListStoragePools(ctl->conn, activeNames, + maxactive)) < 0) { + vshError(ctl, "%s", _("Failed to list active pools")); + free(activeNames); + return false; + } + + qsort(&activeNames[0], maxactive, sizeof(char *), namesorter); + } + maxinactive = virConnectNumOfDefinedStoragePools(ctl->conn); + if (maxinactive < 0) { + vshError(ctl, "%s", _("Failed to list inactive pools")); + free(activeNames); + return false; + } + if (maxinactive) { + inactiveNames = vshMalloc(ctl, sizeof(char *) * maxinactive); + + if ((maxinactive = virConnectListDefinedStoragePools(ctl->conn, inactiveNames, maxinactive)) < 0) { + vshError(ctl, "%s", _("Failed to list inactive pools")); + free(activeNames); + free(inactiveNames); + return false; + } + + qsort(&inactiveNames[0], maxinactive, sizeof(char*), namesorter); + } + + for (i = 0; i < maxactive; i++) { + char uuid[VIR_UUID_STRING_BUFLEN]; + virStoragePoolPtr pool = virStoragePoolLookupByName(ctl->conn, activeNames[i]); + + /* this kind of work with pools is not atomic operation */ + if (!pool) { + free(activeNames[i]); + continue; + } + virStoragePoolGetUUIDString(pool, uuid); + vshPrint(ctl, "%s\n%s\n", + virStoragePoolGetName(pool), + uuid); + virStoragePoolFree(pool); + free(activeNames[i]); + } + for (i = 0; i < maxinactive; i++) { + char uuid[VIR_UUID_STRING_BUFLEN]; + virStoragePoolPtr pool = virStoragePoolLookupByName(ctl->conn, inactiveNames[i]); + + /* this kind of work with pools is not atomic operation */ + if (!pool) { + free(inactiveNames[i]); + continue; + } + virStoragePoolGetUUIDString(pool, uuid); + vshPrint(ctl, "%s\n%s\n", + virStoragePoolGetName(pool), + uuid); + + virStoragePoolFree(pool); + free(inactiveNames[i]); + } + free(activeNames); + free(inactiveNames); + + return true; +} + +/* * "help" command */ static const vshCmdInfo info_help[] = { @@ -654,7 +1062,8 @@ grp->keyword); for (def = grp->commands; def->name; def++) - vshPrint(ctl, " %-30s %s\n", def->name, + if (def->name[0] != '_') + vshPrint(ctl, " %-30s %s\n", def->name, _(vshCmddefGetInfo(def, "help"))); vshPrint(ctl, "\n"); @@ -15335,6 +15744,11 @@ }; static const vshCmdDef virshCmds[] = { + {"_complete-command", cmdCompCommand, opts_compcommand, info_compcommand, VSH_CMD_FLAG_NOCONNECT}, + {"_complete-uri", cmdCompUri, opts_compuri, info_compuri, VSH_CMD_FLAG_NOCONNECT}, + {"_complete-domain", cmdCompDomain, opts_compdomain, info_compdomain, VSH_CMD_FLAG_NOCONNECT}, + {"_complete-network", cmdCompNetwork, opts_compnetwork, info_compnetwork, VSH_CMD_FLAG_NOCONNECT}, + {"_complete-pool", cmdCompPool, opts_comppool, info_comppool, VSH_CMD_FLAG_NOCONNECT}, {"cd", cmdCd, opts_cd, info_cd, VSH_CMD_FLAG_NOCONNECT}, {"echo", cmdEcho, opts_echo, info_echo, VSH_CMD_FLAG_NOCONNECT}, {"exit", cmdQuit, NULL, info_quit, VSH_CMD_FLAG_NOCONNECT}, @@ -16606,6 +17020,7 @@ vshCommandArgvParse(vshControl *ctl, int nargs, char **argv) { vshCommandParser parser; + bool ret; if (nargs <= 0) return false; @@ -16613,7 +17028,20 @@ parser.arg_pos = argv; parser.arg_end = argv + nargs; parser.getNextArg = vshCommandArgvGetArg; - return vshCommandParse(ctl, &parser); + ret = vshCommandParse(ctl, &parser); + + /* Special case 'help' to avoid virConnectOpen */ + if (ctl->cmd && + ctl->cmd->def && + ctl->cmd->def->name && + (STREQ(ctl->cmd->def->name, "help") || + STREQ(ctl->cmd->def->name, "_complete-command") || + STREQ(ctl->cmd->def->name, "_complete-uri"))) { + ret = vshCommandRun(ctl, ctl->cmd); + exit(ret ? EXIT_SUCCESS : EXIT_FAILURE); + } + + return ret; } /* ---------------------- Index: libvirt-0.9.8/python/generator.py =================================================================== --- libvirt-0.9.8.orig/python/generator.py 2011-12-02 03:59:49.000000000 +0000 +++ libvirt-0.9.8/python/generator.py 2012-02-08 20:01:59.268229464 +0000 @@ -224,6 +224,7 @@ qemu_functions_failed = [] functions_skipped = [ "virConnectListDomains", + "virConnectURIs", ] qemu_functions_skipped = [] @@ -340,6 +341,7 @@ 'virConnectGetVersion', 'virConnectGetLibVersion', 'virConnectListDomainsID', + 'virConnectURIs', 'virConnectListDefinedDomains', 'virConnectListNetworks', 'virConnectListDefinedNetworks', @@ -428,6 +430,7 @@ # functions than those already listed skip_function = ( 'virConnectListDomains', # Python API is called virConectListDomainsID for unknown reasons + 'virConnectURIs', 'virConnSetErrorFunc', # Not used in Python API XXX is this a bug ? 'virResetError', # Not used in Python API XXX is this a bug ? 'virGetVersion', # Python C code is manually written Index: libvirt-0.9.8/src/Makefile.in =================================================================== --- libvirt-0.9.8.orig/src/Makefile.in 2012-02-08 03:46:38.000000000 +0000 +++ libvirt-0.9.8/src/Makefile.in 2012-02-08 20:51:29.580231787 +0000 @@ -2548,6 +2548,8 @@ AM_LDFLAGS = $(COVERAGE_LDFLAGS) +bashdir = $(sysconfdir)/bash_completion.d + # Add all conditional sources just in case... EXTRA_DIST = $(conf_DATA) util/keymaps.csv $(srcdir)/util/virkeymaps.h \ $(srcdir)/util/keymaps.csv $(srcdir)/util/virkeycode-mapgen.py \ @@ -2586,7 +2588,7 @@ rpc/gensystemtap.pl rpc/virnetprotocol.x \ rpc/virkeepaliveprotocol.x $(am__append_137) $(am__append_139) \ $(STORAGE_HELPER_DISK_SOURCES) $(LXC_CONTROLLER_SOURCES) \ - $(SECURITY_DRIVER_APPARMOR_HELPER_SOURCES) + $(SECURITY_DRIVER_APPARMOR_HELPER_SOURCES) virsh.bash BUILT_SOURCES = $(ESX_DRIVER_GENERATED) $(HYPERV_DRIVER_GENERATED) \ $(GENERATED_SYM_FILES) $(am__append_128) $(am__append_133) \ $(VIR_NET_RPC_GENERATED) @@ -7016,6 +7018,8 @@ @WITH_NETWORK_TRUE@ cp $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/default.xml.t \ @WITH_NETWORK_TRUE@ $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/default.xml && \ @WITH_NETWORK_TRUE@ rm $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/default.xml.t; } + $(MKDIR_P) "$(DESTDIR)$(bashdir)" + $(INSTALL_DATA) "$(srcdir)/virsh.bash" "$(DESTDIR)$(bashdir)/virsh" uninstall-local:: rmdir "$(DESTDIR)$(localstatedir)/cache/libvirt" ||: @@ -7041,6 +7045,7 @@ @WITH_NETWORK_TRUE@ rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/network" ||: @WITH_NETWORK_TRUE@ rmdir "$(DESTDIR)$(localstatedir)/run/libvirt/network" ||: rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt" ||: + rm -f "$(DESTDIR)$(bashdir)/virsh" ||: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list