[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-API] [PATCH] Add remote server support for xe's bash completion feature
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 ...... ) Attachment:
xen-api.patch _______________________________________________ xen-api mailing list xen-api@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/mailman/listinfo/xen-api
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |