Whamcloud - gitweb
LU-13225 utils: bash completion for lfs and lctl
[fs/lustre-release.git] / lustre / scripts / bash-completion / lustre
1 _lustre_cmds()
2 {
3         local cmd="$1"
4         local sub="$2"
5
6         # "--list-command" prints commands in columns and truncates long ones
7         "$cmd" "$sub" --non-existent-option |
8                 sed -e 1d -e '$d' -e 's/"//g' -e /=/d -e /exit/d -e /quit/d
9 }
10
11 _lustre_long_opts()
12 {
13         local cmd="$1"
14         local sub="$2"
15         local subsub="$3"
16
17         # strip off usage message decoration and leave long opts
18         if [[ -n "$subsub" ]]; then
19                 "$cmd" "$sub" help "$subsub" |& grep -owE -- '--[-a-zA-Z0]*'
20         else
21                 "$cmd" help "$sub" |& sed -e 1d | grep -owE -- '--[-a-zA-Z0]*'
22         fi
23         # several commands take the same options as setstripe, except --delete
24         case "$sub$subsub" in
25         migrate|mirrorcreate|mirrorextend)
26                 _lustre_long_opts "$cmd" setstripe | grep -v -- --delete
27         esac
28 }
29
30 _lustre_short_opts()
31 {
32         local cmd="$1"
33         local sub="$2"
34         local subsub="$3"
35
36         # strip off usage message decoration and leave short opts
37         if [[ -n "$subsub" ]]; then
38                 "$cmd" "$sub" help "$subsub" |& grep -owE -- '-[-a-zA-Z0]'
39         else
40                 "$cmd" help "$sub" |& grep -owE -- '-[-a-zA-Z0]'
41         fi
42         # several commands take the same options as setstripe, except -d
43         case "$sub$subsub" in
44         migrate|mirrorextend|mirrorextend)
45                 _lustre_short_opts "$cmd" setstripe | grep -v -- -d
46         esac
47 }
48
49 _lustre_comp_flags()
50 {
51         local cmd=$1
52         local flags
53
54         flags=$("$cmd" help find |& tr "<>[],}" " " |
55                 grep -- '--component-flags {' | cut -d\{ -f2)
56         if [[ -z "$flags" ]]; then
57                 local version=($("$cmd" --version))
58
59                 case "${version[1]}" in
60                 2.13*) flags="init stale prefer offline nosync extension";;
61                 2.12*|2.11*) flags="init stale prefer offline nosync";;
62                 *) flags="init";;
63                 esac
64         fi
65         echo $flags
66 }
67
68 _lustre_mountpoints()
69 {
70         findmnt --list -t lustre -n -o TARGET
71 }
72
73 _lustre_mount_fsnames()
74 {
75         local mountpoint
76
77         # FIXME: will fail if newlines in $mountpoint, why would anyone do that?
78         _lustre_mountpoints | while read mountpoint; do
79                 lfs getname -n "$mountpoint" 2> /dev/null
80         done
81 }
82
83 _lustre_devices()
84 {
85         lctl device_list | awk '{ print $4 }'
86 }
87
88 _lustre_fsnames()
89 {
90         local mountpoint="${1:-'.'}"
91
92         local fsname=$(lfs getname -n "$mountpoint" 2>/dev/null)
93
94         [[ -n "$fsname" ]] && echo "$fsname" || _lustre_mount_fsnames
95 }
96
97 _lustre_layouts()
98 {
99         "$cmd" help find |& tr "[]," " " | grep -- --layout | sed "s/.*-L //"
100 }
101
102 _lustre_mdts()
103 {
104         lfs mdts $1 | grep _UUID | sed -e "s/[0-9]*: //" -e "s/_UUID.*//"
105 }
106
107 _lustre_osts()
108 {
109         lfs osts $1 | grep _UUID | sed -e "s/[0-9]*: //" -e "s/_UUID.*//"
110 }
111
112 _lustre_pools()
113 {
114         if [[ -d "$1" ]]; then
115                 "$cmd" pool_list $1 2> /dev/null | grep -v "[Pp]ools from" |
116                         cut -d. -f2
117                 return 0
118         fi
119
120         for fsname in $(_lustre_fsnames $1); do
121                 "$cmd" pool_list $fsname 2> /dev/null | grep -v "[Pp]ools from"
122         done
123 }
124
125 _lfs()
126 {
127         local cur prev words cword
128         local mountpoint cmd sub find_opts
129
130         COMPREPLY=()
131         # allow different versions of bash_completion to work
132         if declare -F _init_completion > /dev/null; then
133                 # this provides more functionality, but is only in v2.x
134                 _init_completion || return
135         else
136                 # this is compatible with both v1.3 and v2.x
137                 _get_comp_words_by_ref cur prev words cword
138         fi
139
140         cmd="${words[0]}"
141         sub="${words[1]}"
142         [[ "$sub" == "mirror" || "$sub" == "pcc" ]] && subsub="${words[2]}"
143         if [[ "$cword" == "1" || "$prev" == "help" ]]; then
144                 COMPREPLY+=($(compgen -W '$(_lustre_cmds "$cmd")' -- "$cur"))
145                 return 0
146         fi
147
148         case "$cur" in
149         --*)
150                 COMPREPLY+=($(compgen -W '$(_lustre_long_opts "$cmd" "$sub" "$subsub")' -- "$cur"))
151                 return 0
152                 ;;
153         -*)
154                 # lfs find allows "-longopt" for compatibility with find(1)
155                 [[ "$sub" == "find" ]] && find_opts=$(_lustre_long_opts "$cmd" find)
156                 COMPREPLY+=($(compgen -W '$(_lustre_short_opts "$cmd" "$sub" "$subsub") ${find_opts//--/-}' -- "$cur"))
157                 return 0
158                 ;;
159         esac
160
161         case "$sub" in
162         check)
163                 [[ -n "$cur" ]] && return 0
164                 COMPREPLY+=($(compgen -W '$("$cmd" help check |& grep usage |
165                                             sed -e "s/[<>|]/ /g" \
166                                                 -e "s/.*check //")' -- "$cur"))
167                 return 0
168                 ;;
169         df)
170                 mapfile -t COMPREPLY < <(
171                         _lustre_mountpoints | grep -- "^$cur" | sed 's/ /\\ /g'
172                 )
173                 return 0
174                 ;;
175         find)
176                 [[ -d "${words[2]}" ]] && mountpoint="${words[2]}"
177                 case "${prev/--/-}" in
178                 -component-flags|-comp-flags)
179                         # FIXME: this should allow a comma-separated list
180                         COMPREPLY+=($(compgen -W '$(_lustre_comp_flags)' -- "$cur"))
181                         return 0
182                         ;;
183                 -g|-group)
184                         COMPREPLY+=($(compgen -g -- "$cur"))
185                         return 0
186                         ;;
187                 -L|-layout)
188                         COMPREPLY+=($(compgen -W '$(_lustre_layouts)' -- "$cur"))
189                         return 0
190                         ;;
191                 -m|-mdt)
192                         # FIXME: this should allow a comma-separated list
193                         COMPREPLY+=($(compgen -W '$(_lustre_mdts "$mountpoint")' -- "$cur"))
194                         return 0
195                         ;;
196                 -O|-ost)
197                         # FIXME: this should allow a comma-separated list
198                         COMPREPLY+=($(compgen -W '$(_lustre_osts "$mountpoint")' -- "$cur"))
199                         return 0
200                         ;;
201                 -pool)
202                         COMPREPLY+=($(compgen -W '$(_lustre_pools "$mountpoint")' -- "$cur"))
203                         return 0
204                         ;;
205                 -t|-type)
206                         COMPREPLY+=($(compgen -W 'b c d f l p s' -- "$cur"))
207                         return 0
208                         ;;
209                 -u|-user)
210                         COMPREPLY+=($(compgen -u -- "$cur"))
211                         return 0
212                         ;;
213                 esac
214                 if [ -z "$mountpoint" ]; then
215                         mapfile -t COMPREPLY < <(
216                                 _lustre_mountpoints | grep -- "^$cur" |
217                                         sed -e 's/ /\\ /g'
218                         )
219                         return 0
220                 fi
221                 ;;
222         mirror)
223                 if [[ "$prev" == "$sub" ]]; then
224                         COMPREPLY+=($(compgen -W '$(_lustre_cmds "$cmd" "$sub")' -- "$cur"))
225                         return 0
226                 fi
227                 ;;
228         pcc)
229                 if [[ "$prev" == "$sub" ]]; then
230                         COMPREPLY+=($(compgen -W '$(_lustre_cmds "$cmd" "$sub")' -- "$cur"))
231                         return 0
232                 fi
233                 ;;
234         pool_list)
235                 COMPREPLY+=($(compgen -W '$(_lustre_fsnames
236                                             _lustre_pools)' -- "$cur"))
237                 return 0
238                 ;;
239         setstripe)
240                 case "$prev" in
241                 --component-flags|--comp-flags)
242                         # only subset allowed, easier to list than exclude for now
243                         # COMPREPLY+=($(compgen -W '$(_lustre_comp_flags)' -- "$cur"))
244                         # FIXME: this should allow a comma-separated list
245                         COMPREPLY+=($(compgen -W 'nosync prefer' -- "$cur"))
246                         return 0
247                         ;;
248                 -p|--pool)
249                         COMPREPLY+=($(compgen -W '$(_lustre_pools)' -- "$cur"))
250                         return 0
251                         ;;
252                 esac
253                 ;;
254         esac
255
256         _filedir
257         return 0
258 } &&
259 complete -F _lfs lfs
260
261 _lctl()
262 {
263         local cur prev words cword
264
265         COMPREPLY=()
266         # allow different versions of bash_completion to work
267         if declare -F _init_completion > /dev/null; then
268                 # this provides more functionality, but is only in v2.x
269                 _init_completion || return
270         else
271                 # this is compatible with both v1.3 and v2.x
272                 _get_comp_words_by_ref cur prev words cword
273         fi
274
275         cmd="${words[0]}"
276         sub="${words[1]}"
277         [[ "$sub" == "--device" && $cword -ge 4 ]] && sub="${words[3]}"
278
279         if [[ "$cword" == "1" || "$prev" == "help" ]]; then
280                 COMPREPLY+=($(compgen -W '$(_lustre_cmds "$cmd")' -- "$cur"))
281                 return 0
282         fi
283
284         case "$cur" in
285         --*)
286                 COMPREPLY+=($(compgen -W '$(_lustre_long_opts "$cmd" "$sub")' -- "$cur"))
287                 return 0
288                 ;;
289         -*)
290                 COMPREPLY+=($(compgen -W '$(_lustre_short_opts "$cmd" "$sub")' -- "$cur"))
291                 return 0
292                 ;;
293         esac
294
295         case "$sub" in
296         --device)
297                 if [[ "$cword" == "2" ]]; then
298                         COMPREPLY+=($(compgen -W '$(_lustre_devices)' -- "$cur"))
299                 elif [[ "$cword" == "3" ]]; then
300                         COMPREPLY+=($(compgen -W '$(_lustre_cmds "$cmd")' -- "$cur"))
301                 fi
302                 return 0
303                 ;;
304         get_param|list_param|set_param)
305                 local filter="s/=$//"
306                 [[ "$sub" == "set_param" ]] && filter="/[^=/]$/d"
307                 mapfile -t COMPREPLY < <(
308                     "$cmd" list_param -F "${cur#[\"\']}*" 2>/dev/null |
309                     sed -e "$filter" -e 's#/$#.#' \
310                         -e "s#^${cur//\*/[^.]*}#$cur#"
311                 )
312                 compopt -o nospace
313
314                 return 0
315                 ;;
316         pcc)
317                 if [[ "$prev" == "$sub" ]]; then
318                         COMPREPLY+=($(compgen -W '$(_lustre_cmds "$cmd" "$sub")' -- "$cur"))
319                         return 0
320                 fi
321                 ;;
322         pool_list)
323                 if [[ "$cword" == "2" ]]; then
324                         COMPREPLY+=($(compgen -W '$(_lustre_mountpoints
325                                                     _lustre_fsnames
326                                                     _lustre_pools)' -- "$cur"))
327                         return 0
328                 fi
329                 ;;
330         pool_destroy)
331                 if [[ "$cword" == "2" ]]; then
332                         COMPREPLY+=($(compgen -W '$(_lustre_pools)' -- "$cur"))
333                         return 0
334                 fi
335                 return 0
336                 ;;
337         pool_add|pool_remove)
338                 if [[ "$cword" == "2" ]]; then
339                         COMPREPLY+=($(compgen -W '$(_lustre_pools)' -- "$cur"))
340                         return 0
341                 elif [[ "$cword" == "3" ]]; then
342                         COMPREPLY+=($(compgen -W '$(_lustre_osts)' -- "$cur"))
343                         return 0
344                 fi
345                 return 0
346                 ;;
347         esac
348 } &&
349 complete -F _lctl lctl