Ok, here is a patch which works for me. (I do see that I'll need to
change some of the files edited to deal with the pre-autoconf tree,
but I wanted to get it out there)
I considered adding a name field to the virDriver entries, but the
WITH_REMOTE combinations would get trick, and the cheap way I did it
here has its own advantages.
If this looks generally ok, and if noone else gets to it first, the
next time I have some time I'll send a patch against the uptodate git
tree.
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-14 16:07:54.145332561 +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-14 16:07:54.145332561 +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-14 16:07:54.145332561 +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-14 16:04:38.000000000 +0000
+++ libvirt-0.9.8/src/Makefile.am 2012-02-14 16:07:54.145332561 +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-14 16:51:20.997376629 +0000
@@ -1316,6 +1316,43 @@
return NULL;
}
+char *v_uris[] = {
+#ifdef WITH_XEN
+ "xen://",
+#ifdef WITH_REMOTE
+ "xen+ssh://",
+#endif
+#endif
+#ifdef WITH_LXC
+ "lxc://",
+#endif
+#ifdef WITH_QEMU
+ "qemu://",
+#ifdef WITH_REMOTE
+ "qemu+unix://",
+ "qemu+tls://",
+ "qemu+ssh://",
+#endif
+#endif
+};
+
+/**
+ * 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)
+{
+ *nuris = ARRAY_CARDINALITY(v_uris);
+ return v_uris;
+}
+
/**
* 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-14 16:07:54.149332488 +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-14 16:07:54.149332488 +0000
@@ -0,0 +1,89 @@
+_virsh()
+{
+ local cur prev cmd cmd_index arg arg_index i results skipconn
+ local virsh="$1"
+ local canonical=0
+
+ COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
+
+ COMPREPLY=()
+ cur="$2"
+ prev="$3"
+
+ if [ $COMP_CWORD > 1 ]; then
+ c="${COMP_WORDS[COMP_CWORD-1]}"
+ if [ $c = '-c' -o $c = '--connect' ]; then
+ results="$($virsh _complete-uri)" || nets=""
+ fi
+ 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
+ c="${COMP_WORDS[i-1]}"
+ if [[ $c == '-c' || $c == '--connect' ]]; then
+ test "$?" = 1 && skipconn=1
+ test "$skipconn" -eq 0 && virsh="$virsh
${COMP_WORDS[i-1]} ${COMP_WORDS[i]}"
+ cmd=""
+ 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-14 16:04:38.000000000 +0000
+++ libvirt-0.9.8/tools/virsh.c 2012-02-14 16:07:54.153332478 +0000
@@ -623,6 +623,411 @@
*/
/*
+ * "_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]);
+
+ 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 +1059,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 +15741,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 +17017,7 @@
vshCommandArgvParse(vshControl *ctl, int nargs, char **argv)
{
vshCommandParser parser;
+ bool ret;
if (nargs <= 0)
return false;
@@ -16613,7 +17025,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-14 16:07:54.153332478 +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-14 16:04:38.000000000 +0000
+++ libvirt-0.9.8/src/Makefile.in 2012-02-14 16:07:54.153332478 +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.