mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-26 20:12:04 +00:00

Since the `lxc` binary is actually provided by lxd, the main bash-completion file needs to be moved away to not conflict with a bash completion file provided for the `lxc` binary by lxd. Signed-off-by: Antonio Terceiro <terceiro@debian.org>
1268 lines
32 KiB
Bash
1268 lines
32 KiB
Bash
# lxc-* commands completion
|
|
|
|
__lxc_names() {
|
|
declare -a names
|
|
case ${words[0]} in
|
|
lxc-attach | lxc-cgroup | lxc-checkpoint | lxc-console | lxc-device | lxc-freeze | lxc-stop )
|
|
mapfile -t names < <(command lxc-ls --running -1)
|
|
;;
|
|
lxc-destroy | lxc-execute | lxc-snapshot | lxc-start )
|
|
mapfile -t names < <(command lxc-ls --stopped -1)
|
|
;;
|
|
lxc-copy | lxc-info | lxc-monitor | lxc-wait )
|
|
mapfile -t names < <(command lxc-ls --defined -1)
|
|
;;
|
|
lxc-autostart | lxc-create | lxc-checkconfig | lxc-config | lxc-ls | \
|
|
lxc-top | lxc-unshare | lxc-update-config | lxc-usernsexec )
|
|
;;
|
|
lxc-unfreeze )
|
|
mapfile -t names < <(command lxc-ls --frozen -1)
|
|
;;
|
|
*)
|
|
# If we are running as an alias or symlink with different name,
|
|
# fallback to old behaviour.
|
|
mapfile -t names < <(command lxc-ls -1)
|
|
;;
|
|
esac
|
|
|
|
COMPREPLY=()
|
|
for i in "${!names[@]}"; do
|
|
# For composed names with spaces escaped by '\'.
|
|
names[${i}]=$(command printf "%q" "${names[${i}]}")
|
|
if [[ -n $(compgen -W "${names[${i}]}" -- "${cur}") ]]; then
|
|
COMPREPLY+=("${names[${i}]}")
|
|
fi
|
|
done
|
|
}
|
|
|
|
__lxc_check_name_present() {
|
|
mapfile -t names < <(command lxc-ls -1)
|
|
local -r shortoptnamexp="^-[0-9A-Za-mo-z]*n[0-9A-Za-mo-z]*$"
|
|
local container
|
|
local param
|
|
local parsed
|
|
# Current word on command line, minus double/single quote and backslash.
|
|
local -r current="${cur//[\\\"\']}"
|
|
# If `--name` or `-n` are present, then a container name should be available.
|
|
for i in "${!words[@]}"; do
|
|
param="${words[${i}]}"
|
|
# Parse names from command line when space is escaped by backslash.
|
|
parsed="${param//[\\\"\']}"
|
|
if [[ ${parsed} =~ ^--name(=(.*))?$ ]]; then
|
|
if [[ -n "${BASH_REMATCH[2]}" ]]; then
|
|
container="${BASH_REMATCH[2]}"
|
|
else
|
|
container="${words[${i}+1]}"
|
|
fi
|
|
command printf "%q" "${container}"
|
|
return 0
|
|
elif [[ ${parsed} =~ ${shortoptnamexp} ]]; then
|
|
command printf "%q" "${words[${i}+1]}"
|
|
return 0
|
|
fi
|
|
for name in "${names[@]}"; do
|
|
if [[ "${parsed}" == "${name}" ]] && [[ "${current}" != "${parsed}" ]]; then
|
|
command printf "%q" "${name}"
|
|
return 0
|
|
fi
|
|
done
|
|
done
|
|
return 1
|
|
}
|
|
|
|
__lxc_append_name() {
|
|
local -r name=$(__lxc_check_name_present)
|
|
if [[ -z "${name}" ]]; then
|
|
__lxc_names
|
|
fi
|
|
}
|
|
|
|
__lxc_get_snapshots() {
|
|
local -r container=$(__lxc_check_name_present)
|
|
[[ -z "${container}" ]] && return
|
|
mapfile -t snaps < <(command lxc-snapshot --name="${container}" --list)
|
|
local -r nosnapxp="^No snapshots$"
|
|
if [[ ! "${snaps[*]}" =~ ${nosnapxp} ]]; then
|
|
for i in "${!snaps[@]}"; do
|
|
read -r -e -a line <<< "${snaps[${i}]}"
|
|
command printf "%s " "${line[0]}"
|
|
done
|
|
fi
|
|
}
|
|
|
|
__lxc_common_opt() {
|
|
# End of options.
|
|
if [[ "${words[*]}" =~ ' -- ' ]]; then
|
|
return 1
|
|
fi
|
|
|
|
case ${prev} in
|
|
--help | -h | -\? | --usage | --version )
|
|
return 1
|
|
;;
|
|
--lxcpath | -P )
|
|
_filedir -d
|
|
return 1
|
|
;;
|
|
--logfile | -o )
|
|
_filedir log
|
|
return 1
|
|
;;
|
|
--logpriority | -l )
|
|
COMPREPLY=( $( compgen -W 'FATAL CRIT WARN ERROR NOTICE INFO DEBUG' -- "${cur}" ) )
|
|
return 1
|
|
;;
|
|
--quiet | -q )
|
|
# Only flags.
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
__lxc_concat_array_sep() {
|
|
local -r sep="${1}"
|
|
local concat
|
|
for word in "${@:2}"; do
|
|
if [[ "${word}" == "${sep}" ]]; then
|
|
concat+="${word}"
|
|
else
|
|
concat+="${word}${sep}"
|
|
fi
|
|
done
|
|
command printf "%s" "${concat}"
|
|
}
|
|
|
|
__lxc_check_completion_avail() {
|
|
local -r word="${1}"
|
|
local -r pattern="^${word}"
|
|
for w in "${@:2}"; do
|
|
if [[ "${w}" =~ ${pattern} ]] && [[ "${w}" != "${word}" ]]; then
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
__lxc_array_has_duplicates() {
|
|
declare -A unique
|
|
for word in "${@}"; do
|
|
if [[ -z "${unique[${word}]}" ]]; then
|
|
unique["${word}"]="${word}"
|
|
else
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
__lxc_check_word_in_array() {
|
|
local -r word="${1}"
|
|
for w in "${@:2}"; do
|
|
if [[ "${w}" == "${word}" ]]; then
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
__lxc_piped_args() {
|
|
local -r currentWord="${1}"
|
|
local -r sep="${2}"
|
|
declare -a completionWords=("${@:3}")
|
|
# Remove double/single quote and backslash from current completion parameter.
|
|
IFS=$"${sep}" read -r -e -a current <<< "${currentWord//[\\\"\']}"
|
|
|
|
# Add separator back to current in case it is part of completion list.
|
|
for i in "${!current[@]}"; do
|
|
if [[ -z "${current[${i}]}" ]]; then
|
|
current["${i}"]="${sep}"
|
|
fi
|
|
done
|
|
|
|
# Remove words from completion already added to argument.
|
|
declare -a minuslast=("${current[@]::${#current[@]}-1}")
|
|
declare -a completion=("${completionWords[@]}")
|
|
for i in "${!completion[@]}"; do
|
|
if __lxc_check_word_in_array "${completion[${i}]}" "${minuslast[@]}"; then
|
|
command unset -v 'completion[${i}]'
|
|
fi
|
|
done
|
|
completion=("${completion[@]}")
|
|
|
|
# Check if words from argument are uniquely part of completion.
|
|
if __lxc_array_has_duplicates "${minuslast[@]}"; then
|
|
return
|
|
fi
|
|
declare -a allcomps=("${completionWords[@]}")
|
|
for i in "${!minuslast[@]}"; do
|
|
if ! __lxc_check_word_in_array "${minuslast[${i}]}" "${allcomps[@]}"; then
|
|
return
|
|
fi
|
|
done
|
|
|
|
# Actual completion array.
|
|
declare -a extcompletion
|
|
local -r nparts="${#current[@]}"
|
|
|
|
if [[ "${nparts}" -gt 0 ]]; then
|
|
local prefix=$(__lxc_concat_array_sep "${sep}" "${current[@]::${nparts}-1}")
|
|
local -r lastword="${current[${nparts}-1]}"
|
|
if __lxc_check_completion_avail "${lastword}" "${completion[@]}"; then
|
|
for comp in "${completion[@]}"; do
|
|
extcompletion+=("\"${prefix}${comp}\"")
|
|
done
|
|
fi
|
|
# TAB after quotes to complete for next value.
|
|
if ! __lxc_array_has_duplicates "${current[@]}" && __lxc_check_word_in_array "${lastword}" "${allcomps[@]}"; then
|
|
if ! __lxc_check_completion_avail "${lastword}" "${completion[@]}" || [[ "${#currentWord}" -lt "${#sep}" ]] || [[ "${currentWord: -${#sep}}" == "${sep}" ]]; then
|
|
prefix=$(__lxc_concat_array_sep "${sep}" "${current[@]}")
|
|
for comp in "${completion[@]}"; do
|
|
[[ "${comp}" == "${lastword}" ]] && continue
|
|
if [[ "${comp}" != "${sep}" ]]; then
|
|
extcompletion+=("\"${prefix}${comp}\"")
|
|
else
|
|
# Trailing sep.
|
|
extcompletion+=("\"${prefix}\"")
|
|
[[ "${#completion[@]}" -gt 2 ]] && extcompletion+=("\"${prefix}${comp}\"")
|
|
fi
|
|
done
|
|
fi
|
|
fi
|
|
else # [[ "${nparts}" -eq 0 ]]
|
|
for word in "${allcomps[@]}"; do
|
|
extcompletion+=("${word}")
|
|
done
|
|
fi
|
|
|
|
COMPREPLY=( $( compgen -P '"' -S '"' -W "$(command echo -e ${extcompletion[@]})" -- "${cur}" ) )
|
|
[[ "${#extcompletion[@]}" -gt 1 ]] && compopt -o nospace
|
|
}
|
|
|
|
__lxc_get_selinux_contexts() {
|
|
declare -a sepolicies=()
|
|
local sepolicy
|
|
# Check for SElinux tool.
|
|
if ! command -v semanage > /dev/null 2>&1; then
|
|
return
|
|
fi
|
|
# Skip header + following empty line.
|
|
mapfile -s 2 -t output < <(command semanage fcontext -l 2>/dev/null)
|
|
local -r none="<<None>>"
|
|
for line in "${output[@]}"; do
|
|
if [[ "${line}" =~ "SELinux Distribution fcontext Equivalence" ]]; then
|
|
break
|
|
fi
|
|
read -r -e -a current <<< "${line}"
|
|
if [[ "${#current[@]}" -gt 0 ]]; then
|
|
sepolicy="${current[${#current[@]}-1]}"
|
|
[[ ! "${sepolicy}" =~ ${none} ]] && sepolicies+=("${sepolicy}")
|
|
fi
|
|
done
|
|
# Default context.
|
|
sepolicies+=("unconfined_u:object_r:default_t:s0")
|
|
COMPREPLY=( $( compgen -P'"' -S'"' -W "${sepolicies[*]}" -- "${cur}" ) )
|
|
}
|
|
|
|
_lxc_attach() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile | -f )
|
|
_filedir
|
|
return
|
|
;;
|
|
--pty-log | -L )
|
|
_filedir log
|
|
return
|
|
;;
|
|
--arch | -a )
|
|
# https://github.com/lxc/lxc/blob/stable-4.0/src/tests/arch_parse.c#L37
|
|
COMPREPLY=( $( compgen -W 'arm armel armhf armv7l athlon i386 i486 i586 i686 linux32 mips mipsel ppc powerpc x86 aarch64 amd64 arm64 linux64 mips64 mips64el ppc64 ppc64el ppc64le powerpc64 riscv64 s390x x86_64' -- "${cur}" ) )
|
|
return
|
|
;;
|
|
--elevated-privileges | -e )
|
|
__lxc_piped_args "${cur}" '|' CGROUP CAP LSM
|
|
return
|
|
;;
|
|
--namespaces | -s )
|
|
__lxc_piped_args "${cur}" '|' MOUNT PID UTSNAME IPC USER NETWORK
|
|
return
|
|
;;
|
|
--remount-sys-proc | -R | --keep-env | --clear-env )
|
|
# Only flags.
|
|
;;
|
|
--set-var | -v )
|
|
# custom VAR=VALUE
|
|
return
|
|
;;
|
|
--keep-var )
|
|
COMPREPLY=( $( compgen -A variable -- "${cur}" ) )
|
|
return
|
|
;;
|
|
--uid | -u )
|
|
_uids
|
|
return
|
|
;;
|
|
--gid | -g )
|
|
_gids
|
|
return
|
|
;;
|
|
--context | -c )
|
|
__lxc_get_selinux_contexts
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_attach lxc-attach
|
|
|
|
__lxc_get_groups() {
|
|
declare -A groups
|
|
local key
|
|
declare -a linegroups
|
|
# Discard "GROUPS" header and lines without any groups (with only '-').
|
|
mapfile -s 1 -t lines < <(command lxc-ls -f --fancy-format GROUPS | command sed -e '/^-/d')
|
|
for line in "${lines[@]}"; do
|
|
line=$(command echo -e "${line}" | command sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
|
|
IFS=$',' read -r -e -a linegroups <<< "${line}"
|
|
for entry in "${linegroups[@]}"; do
|
|
key=$(command printf "%q" "${entry}")
|
|
groups+=(["${key}"]=1)
|
|
done
|
|
done
|
|
declare -a output=("${!groups[@]}")
|
|
command printf "%s" "${output[*]}"
|
|
}
|
|
|
|
_lxc_autostart() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--reboot | -r | --shutdown | -s | --kill | -k | --list | -L | --all | -a | --ignore-auto | -A )
|
|
# Only flags.
|
|
;;
|
|
--timeout | -t )
|
|
COMPREPLY=( $( compgen -P "${cur}" -W "{0..9}" ) )
|
|
compopt -o nospace
|
|
return
|
|
;;
|
|
--groups | -g )
|
|
__lxc_piped_args "${cur}" ',' $( __lxc_get_groups ) ','
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
} &&
|
|
complete -F _lxc_autostart lxc-autostart
|
|
|
|
__lxc_cgroup_v2() {
|
|
declare -a stateObjects
|
|
local -r path="${1}"
|
|
[[ ! -f "${path}/cgroup.controllers" ]] && return
|
|
for controller in $(<"${path}/cgroup.controllers"); do
|
|
for so in "${path}/${controller}".*; do
|
|
[[ ! -f "${so}" ]] && continue
|
|
stateObjects+=("${so##*/}")
|
|
done
|
|
done
|
|
command printf "%s" "${stateObjects[*]}"
|
|
}
|
|
|
|
__lxc_cgroup_v1() {
|
|
declare -a stateObjects
|
|
local -r path="${1}"
|
|
local prefix
|
|
for controller in "${path}"/*; do
|
|
[[ ! -d "${controller}" ]] && continue
|
|
prefix="${controller##*/}"
|
|
for so in "${controller}/${prefix}".*; do
|
|
[[ ! -f "${so}" ]] && continue
|
|
stateObjects+=("${so##*/}")
|
|
done
|
|
done
|
|
command printf "%s" "${stateObjects[*]}"
|
|
}
|
|
|
|
__lxc_cgroup_state_object() {
|
|
local -r name="${1}"
|
|
local -r cgroupPath="/sys/fs/cgroup"
|
|
local output
|
|
local -r userSlicePath="${cgroupPath}/user.slice"
|
|
local -r lxcPayloadPath="${cgroupPath}/lxc.payload.${name}"
|
|
if [[ -d "${userSlicePath}" ]]; then
|
|
# cgroup_v2 + user.slice
|
|
read -r -e -a output <<< $(__lxc_cgroup_v2 "${userSlicePath}")
|
|
elif [[ -d "${lxcPayloadPath}" ]]; then
|
|
# cgroup_v2 + lxc.payload
|
|
read -r -e -a output <<< $(__lxc_cgroup_v2 "${lxcPayloadPath}")
|
|
else
|
|
# cgroup_v1
|
|
read -r -e -a output <<< $(__lxc_cgroup_v1 "${cgroupPath}")
|
|
fi
|
|
|
|
# Check if state-object is present already.
|
|
for w in "${words[@]}"; do
|
|
if [[ "${cur}" != "${w}" ]] && __lxc_check_word_in_array "${w}" "${output[@]}"; then
|
|
return
|
|
elif [[ "${cur}" == "${w}" ]] && ! __lxc_check_completion_avail "${w}" "${output[@]}"; then
|
|
return
|
|
fi
|
|
done
|
|
|
|
COMPREPLY=( $( compgen -W "${output[*]}" -- "${cur}" ) )
|
|
}
|
|
|
|
_lxc_cgroup() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile )
|
|
_filedir
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
|
|
local -r custom=$(__lxc_check_name_present)
|
|
if [[ -n "${custom}" ]]; then
|
|
__lxc_cgroup_state_object "${custom}"
|
|
else
|
|
__lxc_append_name
|
|
fi
|
|
} &&
|
|
complete -F _lxc_cgroup lxc-cgroup
|
|
|
|
_lxc_checkpoint() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile )
|
|
_filedir
|
|
return
|
|
;;
|
|
--restore | -r | --stop | -s | --verbose | -v | --daemon | -d | --foreground | -F )
|
|
# Only flags.
|
|
;;
|
|
--checkpoint-dir | -D )
|
|
_filedir -d
|
|
return
|
|
;;
|
|
--action-script | -A )
|
|
_filedir
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_checkpoint lxc-checkpoint
|
|
|
|
_lxc_config() {
|
|
local cur prev words cword split
|
|
_init_completion -s -n : || return
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '-l' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
COMPREPLY=( $( compgen -W "$( command lxc-config -l )" -- "${cur}" ) )
|
|
} &&
|
|
complete -F _lxc_config lxc-config
|
|
|
|
_lxc_console() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile )
|
|
_filedir
|
|
return
|
|
;;
|
|
--escape | -e )
|
|
COMPREPLY+=( $( compgen -P "'" -S "'" -W "^{a..z} {a..z}" -- "${cur}" ) )
|
|
return
|
|
;;
|
|
--tty | -t )
|
|
COMPREPLY=( $( compgen -P "${cur}" -W "{0..9}" ) )
|
|
compopt -o nospace
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_console lxc-console
|
|
|
|
__lxc_backing_stores() {
|
|
COMPREPLY=( $( compgen -W 'best btrfs dir loop lvm nbd overlay overlayfs rbd zfs' -- "${cur}" ) )
|
|
}
|
|
|
|
__lxc_size_unit() {
|
|
if [[ -n "${cur}" ]] && [[ ! "${cur}" =~ ^[0-9]+$ ]]; then
|
|
return
|
|
fi
|
|
# Size.
|
|
if [[ -z "${cur}" ]]; then
|
|
COMPREPLY=( $( compgen -P "${cur}" -W "{1..9}" ) )
|
|
else
|
|
COMPREPLY=( $( compgen -P "${cur}" -W "{0..9}" ) )
|
|
# Unit
|
|
COMPREPLY+=( $( compgen -P "${cur}" -W "$( command echo ${@})" ) )
|
|
fi
|
|
compopt -o nospace
|
|
}
|
|
|
|
_lxc_copy() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile )
|
|
_filedir
|
|
return
|
|
;;
|
|
--newname | -N | --mount | -m )
|
|
return
|
|
;;
|
|
--newpath | -p )
|
|
_filedir -d
|
|
return
|
|
;;
|
|
--rename | -R | --snapshot | -s | --allowrunning | -a | --foreground | -F | --daemon | -d | --tmpfs | -t | --keepname | -K | --keepdata | -D | --keepmac | -M )
|
|
# Only flags.
|
|
;;
|
|
--backingstorage | -B )
|
|
__lxc_backing_stores
|
|
return
|
|
;;
|
|
--fssize | -L )
|
|
__lxc_size_unit K M G T
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_copy lxc-copy
|
|
|
|
__lxc_templates() {
|
|
COMPREPLY=( $( compgen -W "$(command ls @LXCTEMPLATEDIR@/ | command sed -e 's|^lxc-||' )" -- "${cur}" ) )
|
|
}
|
|
|
|
_lxc_create() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile )
|
|
_filedir
|
|
return
|
|
;;
|
|
--config | -f )
|
|
_filedir
|
|
return
|
|
;;
|
|
--template | -t )
|
|
__lxc_templates
|
|
return
|
|
;;
|
|
--bdev | -B )
|
|
__lxc_backing_stores
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
} &&
|
|
complete -F _lxc_create lxc-create
|
|
|
|
_lxc_destroy() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile )
|
|
_filedir
|
|
return
|
|
;;
|
|
--force | -f | --snapshots | -s )
|
|
# Only flags.
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_destroy lxc-destroy
|
|
|
|
_lxc_device() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
case ${prev} in
|
|
-h )
|
|
return
|
|
;;
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
add )
|
|
_available_interfaces
|
|
COMPREPLY+=( $( compgen -f -d -X "!*/?*" -- "${cur:-/dev/}" ) )
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_device lxc-device
|
|
|
|
_lxc_execute() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile | -f )
|
|
_filedir
|
|
return
|
|
;;
|
|
--define | -s )
|
|
# @TODO: list values from source code.
|
|
# tag=value
|
|
# https://github.com/lxc/lxc/blob/stable-4.0/src/lxc/confile.c#L178
|
|
return
|
|
;;
|
|
--daemon | -d )
|
|
# Only flags.
|
|
;;
|
|
--uid | -u )
|
|
_uids
|
|
return
|
|
;;
|
|
--gid | -g )
|
|
_gids
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_execute lxc-execute
|
|
|
|
_lxc_freeze() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile | -f )
|
|
_filedir
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_freeze lxc-freeze
|
|
|
|
_lxc_info() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile )
|
|
_filedir
|
|
return
|
|
;;
|
|
--config | -c )
|
|
# @TODO: list values from source code.
|
|
# tag
|
|
# https://github.com/lxc/lxc/blob/stable-4.0/src/lxc/confile.c#L178
|
|
return
|
|
;;
|
|
--ips | -i | --pid | -p | --stats | -S | --no-humanize | -H | --state | -s )
|
|
# Only flags.
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_info lxc-info
|
|
|
|
_lxc_ls() {
|
|
local cur prev words cword split
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--line | -1 | --fancy | -f | --active | --frozen | --running | --stopped | --defined )
|
|
# Only flags.
|
|
;;
|
|
--fancy-format | -F )
|
|
__lxc_piped_args "${cur}" ',' NAME STATE PID RAM SWAP AUTOSTART GROUPS INTERFACE IPV4 IPV6 UNPRIVILEGED
|
|
return
|
|
;;
|
|
--groups | -g )
|
|
__lxc_piped_args "${cur}" ',' $( __lxc_get_groups ) ','
|
|
return
|
|
;;
|
|
--nesting )
|
|
COMPREPLY=( $( compgen -P "${cur}" -W "{0..9}" ) )
|
|
compopt -o nospace
|
|
return
|
|
;;
|
|
--filter )
|
|
# POSIX extended regular expression.
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
} &&
|
|
complete -F _lxc_ls lxc-ls
|
|
|
|
_lxc_monitor() {
|
|
local cur prev words cword split
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--quit | -Q )
|
|
# Only flags.
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_monitor lxc-monitor
|
|
|
|
_lxc_snapshot() {
|
|
local cur prev words cword split
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile )
|
|
_filedir
|
|
return
|
|
;;
|
|
--comment | -c )
|
|
_filedir
|
|
return
|
|
;;
|
|
--destroy | -d )
|
|
COMPREPLY=( $( compgen -W 'ALL $( __lxc_get_snapshots )' -- "${cur}" ) )
|
|
return
|
|
;;
|
|
--list | -L | --showcomments | -C )
|
|
# Only flags.
|
|
;;
|
|
--restore | -r )
|
|
COMPREPLY=( $( compgen -W '$( __lxc_get_snapshots )' -- "${cur}" ) )
|
|
return
|
|
;;
|
|
--newname | -N )
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_snapshot lxc-snapshot
|
|
|
|
_lxc_start() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--daemon | -d | --foreground | -F | --close-all-fds | -C )
|
|
# Only flags.
|
|
;;
|
|
--pidfile | -p )
|
|
_filedir pid
|
|
return
|
|
;;
|
|
--rcfile | -f )
|
|
_filedir
|
|
return
|
|
;;
|
|
--console | -c )
|
|
# Output devices, such as /dev/tty*
|
|
_filedir
|
|
return
|
|
;;
|
|
--console-log | -L)
|
|
_filedir
|
|
return
|
|
;;
|
|
--define | -s )
|
|
# @TODO: list values from source code.
|
|
# tag=value
|
|
# https://github.com/lxc/lxc/blob/stable-4.0/src/lxc/confile.c#L178
|
|
return
|
|
;;
|
|
--share-net | --share-ipc | --share-uts )
|
|
_pids
|
|
COMPREPLY+=( $( compgen -W "$( command lxc-ls --active )" -- "${cur}" ) )
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
|
|
# Needed due to weird `_parse_help` output for the `--share-*` options.
|
|
COMPREPLY=( $( compgen -W '${COMPREPLY[@]/--share-} --share-net --share-ipc --share-uts' -- "${cur}" ) )
|
|
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_start lxc-start
|
|
|
|
_lxc_stop() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile )
|
|
_filedir
|
|
return
|
|
;;
|
|
--reboot | -r | --kill | -k | --nokill | --nolock | --nowait | -W )
|
|
# Only flags.
|
|
;;
|
|
--timeout | -t )
|
|
COMPREPLY=( $( compgen -P "${cur}" -W "{0..9}" ) )
|
|
compopt -o nospace
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_stop lxc-stop
|
|
|
|
_lxc_top() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--batch | -b | --reverse | -r )
|
|
# Only flags.
|
|
;;
|
|
--delay | -d )
|
|
COMPREPLY=( $( compgen -P "${cur}" -W "{0..9}" ) )
|
|
compopt -o nospace
|
|
return
|
|
;;
|
|
--sort | -s )
|
|
COMPREPLY=( $( compgen -W 'n c b m k' -- "${cur}" ) )
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
} &&
|
|
complete -F _lxc_top lxc-top
|
|
|
|
_lxc_unfreeze() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile )
|
|
_filedir
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_unfreeze lxc-unfreeze
|
|
|
|
_lxc_unshare() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--namespaces | -s )
|
|
__lxc_piped_args "${cur}" '|' MOUNT PID UTSNAME IPC USER NETWORK
|
|
return
|
|
;;
|
|
--user | -u )
|
|
_uids
|
|
return
|
|
;;
|
|
--hostname | -H )
|
|
return
|
|
;;
|
|
--ifname | -i )
|
|
_available_interfaces
|
|
return
|
|
;;
|
|
--daemon | -d | --remount | -M )
|
|
# Only flags.
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
} &&
|
|
complete -F _lxc_unshare lxc-unshare
|
|
|
|
_lxc_update_config() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
case ${prev} in
|
|
--help | -h )
|
|
return
|
|
;;
|
|
--config | -c )
|
|
_filedir
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
} &&
|
|
complete -F _lxc_update_config lxc-update-config
|
|
|
|
__lxc_id_mapping() {
|
|
local -r tmp="${cur//[^:]}"
|
|
if [[ "${#tmp}" -eq 0 ]]; then
|
|
COMPREPLY=( $( compgen -W "u: g: b:" -- "${cur}" ) )
|
|
fi
|
|
compopt -o nospace
|
|
}
|
|
|
|
_lxc_usernsexec() {
|
|
local cur prev words cword split
|
|
COMPREPLY=()
|
|
_init_completion -s -n : || return
|
|
|
|
# End of options.
|
|
if [[ "${words[*]}" =~ ' -- ' ]]; then
|
|
return
|
|
fi
|
|
|
|
case ${prev} in
|
|
-h )
|
|
return
|
|
;;
|
|
-m )
|
|
# ^[ugb]:[0-9]+:[0-9]+(:[0-9]+)?$
|
|
__lxc_id_mapping
|
|
return
|
|
;;
|
|
-s )
|
|
# Only flags.
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '-h -m -s' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
fi
|
|
} &&
|
|
complete -F _lxc_usernsexec lxc-usernsexec
|
|
|
|
_lxc_wait() {
|
|
local cur prev words cword split
|
|
_init_completion -s -n : || return
|
|
|
|
__lxc_common_opt || return
|
|
|
|
case ${prev} in
|
|
--name | -n )
|
|
__lxc_names
|
|
return
|
|
;;
|
|
--rcfile )
|
|
_filedir
|
|
return
|
|
;;
|
|
--state | -s )
|
|
__lxc_piped_args "${cur}" '|' STOPPED STARTING RUNNING STOPPING ABORTING FREEZING FROZEN THAWED
|
|
return
|
|
;;
|
|
--timeout | -t )
|
|
COMPREPLY=( $( compgen -P "${cur}" -W "{0..9}" ) )
|
|
compopt -o nospace
|
|
return
|
|
;;
|
|
esac
|
|
|
|
$split && return
|
|
|
|
if [[ ${cur} == -* ]]; then
|
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "${cur}" ) )
|
|
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
|
return
|
|
fi
|
|
__lxc_append_name
|
|
} &&
|
|
complete -F _lxc_wait lxc-wait
|
|
|
|
# ex: filetype=sh
|