According to the manual:
"... When executing commands on a remote Xen Cloud Platform host, tab
completion does not normally work. However if you put the server, username, and
password in an environment variable called XE_EXTRA_ARGS on the machine from
which you are entering the commands, tab completion is enabled. See the section
called Basic xe syntax for details. ..."
However, when dealing with a large number of machines, checking/updating RC
file or environment variable at every single call sounds like a ugly way.
This patch adds the remote server (and other config options) support to xe's
bash completion functionality. It enables tab completion when xe calls a remote
server whose config can be set by command line options in "-o xxx" format or
"option=xxx" format or the mix of both. The patch should work in general
according to my limited tests, but please bear with my poor bash skills and
feel free to improve.
A few other minor bugs were also fixed during the process.
Signed-off-by: Zheng Li <dev@xxxxxxxx>
ocaml/xe-cli/bash-completion | 322
++++++++++++++++++++++++++++-----------------
1 files changed, 199 insertions(+), 123 deletions(-)
diff -r ad5ea8e64ad2 -r 7d0fb4d42e65 ocaml/xe-cli/bash-completion
--- a/ocaml/xe-cli/bash-completion Tue May 04 06:22:08 2010 +0100
+++ b/ocaml/xe-cli/bash-completion Tue May 04 07:18:23 2010 +0100
@@ -6,24 +6,76 @@
_xe()
{
- local IFS=$'\n,'
- local cur prev opts xe IFS
+ local cur prev opts xe IFS oIFS cIFS ABORT_FLAG INGORE_FLAG SKIP_FLAG
SKIP_OPTS SKIP_CONF COMP_OPWORD
+
+ oIFS=$' \t\n'
+ cIFS=$'\n,'
+
+ # The current script doesn't seem to have taken the compat mode into
consideration. Using the standard
+ # mode instead is possible but will obviously return misleading
completions, while forcing to use compat
+ # mode anyway will return message of unexpected format in most case
hence become garbage. Considering the
+ # rase usage of compat mode for interactive command (mostly as old
script), we simply disable it here.
+ ABORT_FLAG=( '-help' '--help' '--compat')
+ IGNORE_FLAG=( '--debug' '--debug-on-fail' )
+ SKIP_FLAG=( '--nossl' )
+ SKIP_OPTS=( '-s' '-p' '-u' '-pw' '-pwf' '-h' )
+ ABORT_CONF=( 'compat=' )
+ IGNORE_CONF=( 'debug=' 'debugonfail=' )
+ SKIP_CONF=( 'server=' 'port=' 'username=' 'password=' 'passwordfile='
'nossl=' )
+
+ COMP_OPWORD=-1
+ i=1
+ skip=0
+ while [ $COMP_OPWORD -lt 0 ] && [ $i -lt $COMP_CWORD ]; do
+ cont=0
+ for f in ${ABORT_FLAG[@]}; do if [[ $f == ${COMP_WORDS[i]} ]];
then return 0; fi; done
+ for f in ${IGNORE_FLAG[@]}; do if [[ $f == ${COMP_WORDS[i]} ]];
then unset COMP_WORDS[$i]; cont=1; let skip=$skip+1; break; fi; done
+ if [ $cont -gt 0 ]; then let i=$i+$cont; continue; fi
+ for f in ${SKIP_FLAG[@]}; do if [[ $f == ${COMP_WORDS[i]} ]];
then cont=1; break; fi; done
+ if [ $cont -gt 0 ]; then let i=$i+$cont; continue; fi
+ for f in ${SKIP_OPTS[@]}; do if [[ $f == ${COMP_WORDS[i]} ]];
then cont=2; break; fi; done
+ if [ $cont -gt 0 ]; then let i=$i+$cont; continue; fi
+ for f in ${ABORT_CONF[@]}; do if [[ $f ==
${COMP_WORDS[i]:0:${#f}} ]]; then return 0; fi; done
+ for f in ${IGNORE_CONF[@]}; do if [[ $f ==
${COMP_WORDS[i]:0:${#f}} ]]; then unset COMP_WORDS[$i]; cont=1; let
skip=$skip+1; break; fi; done
+ if [ $cont -gt 0 ]; then let i=$i+$cont; continue; fi
+ for f in ${SKIP_CONF[@]}; do if [[ $f ==
${COMP_WORDS[i]:0:${#f}} ]]; then cont=1; break; fi; done
+ if [ $cont -gt 0 ]; then let i=$i+$cont; continue; fi
+ COMP_OPWORD=$i
+ done
+
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
- xe=xe
-
- if [[ $COMP_CWORD == 1 ]] ; then
- opts=`${xe} help --minimal --all 2>/dev/null | sed -e 's/,/\
,/g' -e 's/$/\ /g'` && COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+
+ optargs=`echo "${ABORT_FLAG[@]} ${IGNORE_FLAG[@]} ${SKIP_FLAG[@]}
${SKIP_OPTS[@]}" | sed -e 's/\ /\ ,/g'`
+ eqargs=`echo "${ABORT_CONF[@]} ${IGNORE_CONF[@]} ${SKIP_CONF[@]}" | sed
-e 's/\ /,/g'`
+ opts="$optargs ,$eqargs"
+
+
+ if [[ $COMP_OPWORD -lt 0 ]]; then
+ xe="${COMP_WORDS[@]:0:$COMP_CWORD-$skip}"
+ else
+ xe="${COMP_WORDS[@]:0:$COMP_OPWORD-$skip}"
+ fi
+
+ if [[ $COMP_OPWORD -lt 0 ]]; then
+ for f in ${SKIP_OPTS[@]}; do if [[ $f ==
${COMP_WORDS[COMP_CWORD-1]} ]]; then return 0; fi; done
+ IFS=$oIFS
+ cmdargs=`${xe} help --minimal --all 2>/dev/null | sed -e
's/,\|&/\ ,/g'`
+ IFS=$cIFS
+ opts="$opts,$cmdargs"
+ COMPREPLY=( $(compgen -W "${opts}" -X ${cur} -- ${cur}) )
+ IFS=$oIFS
return 0
fi
-
-# parameters are passed as param=value
+
+ # parameters are passed as param=value
+
if echo ${COMP_WORDS[COMP_CWORD]} | grep "=" > /dev/null; then
local param value
- local IFS=""
+ IFS=""
param=`echo ${COMP_WORDS[COMP_CWORD]} | cut -d= -f1`
value=`echo ${COMP_WORDS[COMP_CWORD]} | cut -d= -f2`
@@ -31,202 +83,220 @@
case "$param" in
filename|file-name|license-file)
- IFS=$'\n,'
+ IFS=$cIFS
COMPREPLY=( $(compgen -f ${value}) )
return 0
;;
mode) # for pif-reconfigure-ip
- if [ "${COMP_WORDS[1]}" == "pif-reconfigure-ip"
]; then
- IFS=$'\n,'
+ if [ "${COMP_WORDS[COMP_OPWORD]}" ==
"pif-reconfigure-ip" ]; then
+ IFS=$cIFS
COMPREPLY=( $(compgen -W "dhcp ,static
,none" -- ${value}) )
fi
return 0
;;
- uuid)
- case "${COMP_WORDS[1]}" in
+ uuid)
+ case "${COMP_WORDS[COMP_OPWORD]}" in
diagnostic-vm-status) cmd=vm-list;;
diagnostic-vdi-status) cmd=vdi-list;;
- *) cmd=`echo ${COMP_WORDS[1]} | awk -F-
'/^host-cpu-/ || /^host-crashdump-/ { print $1 "-" $2 }
$0 !~ /^host-cpu-/ && $0 !~ /^host-crashdump-/ { print $1 }'`-list;;
+ *) cmd=`echo ${COMP_WORDS[COMP_OPWORD]}
| awk -F- '/^host-cpu-/ || /^host-crashdump-/ { print $1 "-" $2 }
$0 !~ /^host-cpu-/ && $0 !~ /^host-crashdump-/ { print $1 }'`-list;;
esac
- IFS=$'\n,'
+ IFS=$cIFS
COMPREPLY=( $(compgen_names "$cmd" uuid
"$value") )
return 1
;;
vm)
- IFS=$'\n,'
- COMPREPLY=( $(compgen_names vm-list name-label
"$value") )
+ IFS=$cIFS
+ COMPREPLY=( $(compgen_names vm-list name-label
"$value") )
return 0
;;
host)
- IFS=$'\n,'
+ IFS=$cIFS
COMPREPLY=( $(compgen_names host-list
name-label "$value") )
return 0
;;
params)
- val=$(final_comma_separated_param "$value")
- class=`echo ${COMP_WORDS[1]} | cut -d- -f1`
- params=`${xe} ${class}-list params=all
2>/dev/null| cut -d: -f1 | sed -e s/\(.*\)//g -e s/^\ *//g -e s/\ *$//g`
- IFS=$'\n,'
+ val=$(final_comma_separated_param "$value")
+ class=`echo ${COMP_WORDS[COMP_OPWORD]} | cut
-d- -f1`
+ IFS=$oIFS
+ params=`${xe} ${class}-list params=all
2>/dev/null | cut -d: -f1 | sed -e s/\(.*\)//g -e s/^\ *//g -e s/\ *$//g`
+ IFS=$cIFS
COMPREPLY=( $(compgen -W "$params,all" --
"$val" ) )
return 0
;;
template)
- IFS=$'\n,'
- COMPREPLY=( $(compgen_names template-list
name-label "$value") )
+ IFS=$cIFS
+ COMPREPLY=( $(compgen_names template-list
name-label "$value") )
return 0
;;
# param name is used by *-param-add
param-name)
- if echo ${COMP_WORDS[1]} | grep "param-add" >
/dev/null; then
- class=`echo ${COMP_WORDS[1]} | sed
s/-param-add//g`
+ if echo ${COMP_WORDS[COMP_OPWORD]} | grep
"param-add" > /dev/null; then
+ class=`echo ${COMP_WORDS[COMP_OPWORD]}
| sed s/-param-add//g`
+ IFS=$oIFS
paramsset=`${xe} ${class}-list
params=all 2>/dev/null | grep "SRW\|MRW" | cut -d\( -f 1 | cut -d: -f1 | sed
s/\ *//`
- IFS=$'\n,' COMPREPLY=( $(compgen -W
"${paramsset}" -- ${value}) )
+ IFS=$cIFS
+ COMPREPLY=( $(compgen -W "${paramsset}"
-- ${value}) )
return 0
fi
;;
cd-name)
- if [[ "${COMP_WORDS[1]}" == "vm-cd-add" ||
"${COMP_WORDS[1]}" == "vm-cd-insert" ]]; then
- IFS=$'\n,'
- COMPREPLY=( $(compgen_names cd-list
name-label "$value") )
+ if [[ "${COMP_WORDS[COMP_OPWORD]}" ==
"vm-cd-add" || "${COMP_WORDS[COMP_OPWORD]}" == "vm-cd-insert" ]]; then
+ IFS=$cIFS
+ COMPREPLY=( $(compgen_names cd-list
name-label "$value") )
return 0
- elif [[ "${COMP_WORDS[1]}" == "vm-cd-remove"
]]; then
- vm=`for i in ${COMP_WORDS[@]:2}; do
echo $i | grep "^vm="; done`
+ elif [[ "${COMP_WORDS[COMP_OPWORD]}" ==
"vm-cd-remove" ]]; then
+ vm=`for i in ${COMP_WORDS[@]:2}; do
echo $i | grep "^vm="; done`
+ IFS=$oIFS
local cds=`${xe} vm-cd-list "$vm"
--minimal --multiple vbd-params=vdi-name-label vdi-params=none 2>/dev/null |
sed -e "s,',$MAGIC_SQUOTE,g" -e "s,\",$MAGIC_DQUOTE,g"`
- IFS=$'\n,'
- COMPREPLY=( $(compgen_escape "$cds"
"$value") )
+ IFS=$cIFS
+ COMPREPLY=( $(compgen_escape "$cds"
"$value") )
return 0
fi
;;
on)
- IFS=$'\n,'
- COMPREPLY=( $(compgen_names host-list
name-label "$value") )
+ IFS=$cIFS
+ COMPREPLY=( $(compgen_names host-list
name-label "$value") )
return 0
;;
key)
+ IFS=$oIFS
local keys=`${xe} log-get-keys --minimal
2>/dev/null`
- IFS=$'\n,'
- COMPREPLY=( $(compgen_escape "$keys" "$value")
)
+ IFS=$cIFS
+ COMPREPLY=( $(compgen_escape "$keys" "$value") )
return 0
;;
level)
- IFS=$'\n,'
+ IFS=$cIFS
COMPREPLY=( $(compgen -W "debug ,info ,warning
,error " -- ${value}) )
return 0
;;
sr-name-label) # for vm-install
- IFS=$'\n,'
+ IFS=$cIFS
COMPREPLY=( $(compgen_names sr-list name-label
"$value") )
return 0
;;
crash-dump-SR | suspend-image-SR | default-SR)
- IFS=$'\n,'
+ IFS=$cIFS
COMPREPLY=( $(compgen_names sr-list uuid
"$value") )
return 0
;;
type) # for vbd-create/vdi-create/sr-create/sr-probe
- IFS=$'\n,'
- fst=`echo ${COMP_WORDS[1]} | cut -d- -f1`
-
+ IFS=$cIFS
+ fst=`echo ${COMP_WORDS[COMP_OPWORD]} | cut -d-
-f1`
if [[ "${fst}" == "vbd" ]]; then
- COMPREPLY=( $(compgen -W "Disk ,CD " --
${value}) )
- return 0
+ COMPREPLY=( $(compgen -W "Disk ,CD " --
${value}) )
+ return 0
elif [[ "${fst}" == "vdi" ]]; then
- COMPREPLY=( $(compgen -W "system ,user
,suspend ,crashdump " -- ${value}) )
- return 0
+ COMPREPLY=( $(compgen -W "system ,user
,suspend ,crashdump " -- ${value}) )
+ return 0
elif [[ "${fst}" == "sr" ]]; then
- COMPREPLY=( $(compgen -W "$(xe sm-list
params=type --minimal 2>/dev/null | sed 's/,/ ,/g') " -- ${value}) )
- return 0
+ IFS=$oIFS
+ local types=`${xe} sm-list params=type
--minimal 2>/dev/null | sed 's/,\|$/ &/g'`
+ IFS=$cIFS
+ COMPREPLY=( $(compgen -W "$types" --
${value}) )
+ return 0
fi
;;
entries) # for host-get-system-status
- val=$(final_comma_separated_param "$value")
- master_uuid=$(xe pool-list params=master
--minimal 2>/dev/null)
- IFS=$'\n'
- caps=$($xe host-get-system-status-capabilities
uuid="$master_uuid" 2>/dev/null | grep '<capability ' | sed -ne
's/.*<capability .* key="\([^"]*\)".*$/\1/p' | tr '\n' , | sed -e 's/,$//g' |
tr , '\n')
- # Fake "
- COMPREPLY=( $(compgen -W "$caps" -- "$val") )
- return 0
- ;;
+ val=$(final_comma_separated_param "$value")
+ IFS=$oIFS
+ master_uuid=`${xe} pool-list params=master
--minimal 2>/dev/null`
+ caps=`${xe} host-get-system-status-capabilities
uuid="$master_uuid" 2>/dev/null | grep '<capability ' | sed -ne
's/.*<capability .* key="\([^"]*\)".*$/\1/p' | tr '\n' , | sed -e 's/,\|$/\
&/g' | tr , '\n'` # Fake "
+ IFS=$cIFS
+ COMPREPLY=( $(compgen -W "$caps" -- "$val") )
+ return 0
+ ;;
output)
- case "${COMP_WORDS[1]}" in
- log-set-output)
- IFS=$'\n,'
- COMPREPLY=( $(compgen -W
"file,syslog,nil " -- ${value}) )
- ;;
- host-get-system-status)
- IFS=$'\n,'
- COMPREPLY=( $(compgen -W "tar.bz2 ,zip
" -- ${value}) )
- ;;
- esac
- return 0
- ;;
- copy-bios-strings-from) # for vm-install
- COMPREPLY=`${xe} host-list params=uuid --minimal 2>/dev/null`
- return 0
- ;;
- edition) # for host-apply-edition (licensing)
- IFS=$'\n,'
- COMPREPLY=( $(compgen -W "free ,enterprise ,platinum " --
${value}) )
- return 0
- ;;
+ case "${COMP_WORDS[COMP_OPWORD]}" in
+ log-set-output)
+ IFS=$cIFS
+ COMPREPLY=( $(compgen -W
"file:,syslog:,stderr ,nil " -- ${value}) )
+ ;;
+ host-get-system-status)
+ IFS=$cIFS
+ COMPREPLY=( $(compgen -W
"tar.bz2 ,zip " -- ${value}) )
( ...... 166 lines left ...... )
xen-api.patch
Description: Text Data
_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api
|