532 lines
17 KiB
Bash
Executable File
532 lines
17 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# This script can be used to interact with kolla via ansible.
|
|
|
|
function check_environment_coherence {
|
|
local ansible_path
|
|
ansible_path=$(which ansible)
|
|
|
|
if [[ $? -ne 0 ]]; then
|
|
echo "ERROR: Ansible is not installed in the current (virtual) environment." >&2
|
|
exit 1
|
|
fi
|
|
|
|
local ansible_shebang_line
|
|
ansible_shebang_line=$(head -n1 "$ansible_path")
|
|
|
|
if ! echo "$ansible_shebang_line" | egrep "^#!" &>/dev/null; then
|
|
echo "ERROR: Ansible script is malformed (missing shebang line)." >&2
|
|
exit 1
|
|
fi
|
|
|
|
local ansible_python_cmdline
|
|
# NOTE(yoctozepto): may have multiple parts
|
|
ansible_python_cmdline=${ansible_shebang_line#\#\!}
|
|
ansible_python_version=$($ansible_python_cmdline -c 'import sys; print(str(sys.version_info[0])+"."+str(sys.version_info[1]))')
|
|
|
|
if ! $ansible_python_cmdline --version &>/dev/null; then
|
|
echo "ERROR: Ansible Python is not functional." >&2
|
|
echo "Tried '$ansible_python_cmdline'" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Check for existence of kolla_ansible module using Ansible's Python.
|
|
if ! $ansible_python_cmdline -c 'import kolla_ansible' &>/dev/null; then
|
|
echo "ERROR: kolla_ansible has to be available in the Ansible PYTHONPATH." >&2
|
|
echo "Please install both in the same (virtual) environment." >&2
|
|
exit 1
|
|
fi
|
|
|
|
local ansible_version_output
|
|
ansible_full_version=$($ansible_python_cmdline -c 'import ansible; print(ansible.__version__)')
|
|
|
|
if [[ $? -ne 0 ]]; then
|
|
echo "ERROR: Failed to obtain Ansible version:" >&2
|
|
echo "$ansible_full_version" >&2
|
|
exit 1
|
|
fi
|
|
|
|
local ansible_version
|
|
ansible_version=$(echo "$ansible_full_version" | egrep -o '^[0-9]+\.[0-9]+')
|
|
|
|
if [[ $? -ne 0 ]]; then
|
|
echo "ERROR: Failed to parse Ansible version:" >&2
|
|
echo "$ansible_full_version" >&2
|
|
exit 1
|
|
fi
|
|
|
|
local ANSIBLE_VERSION_MIN=2.10
|
|
local ANSIBLE_VERSION_MAX=2.11
|
|
|
|
if [[ $(printf "%s\n" "$ANSIBLE_VERSION_MIN" "$ANSIBLE_VERSION_MAX" "$ansible_version" | sort -V | head -n1) != "$ANSIBLE_VERSION_MIN" ]] ||
|
|
[[ $(printf "%s\n" "$ANSIBLE_VERSION_MIN" "$ANSIBLE_VERSION_MAX" "$ansible_version" | sort -V | tail -n1) != "$ANSIBLE_VERSION_MAX" ]]; then
|
|
echo "ERROR: Ansible version should be between $ANSIBLE_VERSION_MIN and $ANSIBLE_VERSION_MAX. Current version is $ANSIBLE_VERSION_HOST which is not supported."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
function find_base_dir {
|
|
local dir_name
|
|
local python_dir
|
|
dir_name=$(dirname "$0")
|
|
# NOTE(yoctozepto): Fix the case where dir_name is a symlink and VIRTUAL_ENV might not be. This
|
|
# happens with pyenv-virtualenv, see https://bugs.launchpad.net/kolla-ansible/+bug/1903887
|
|
dir_name=$(readlink -e "$dir_name")
|
|
python_dir="python${ansible_python_version}"
|
|
if [ -z "$SNAP" ]; then
|
|
if [[ ${dir_name} == "/usr/bin" ]]; then
|
|
if test -f /usr/lib/${python_dir}/*-packages/kolla-ansible.egg-link; then
|
|
# Editable install.
|
|
BASEDIR="$(head -n1 /usr/lib/${python_dir}/*-packages/kolla-ansible.egg-link)"
|
|
else
|
|
BASEDIR=/usr/share/kolla-ansible
|
|
fi
|
|
elif [[ ${dir_name} == "/usr/local/bin" ]]; then
|
|
if test -f /usr/local/lib/${python_dir}/*-packages/kolla-ansible.egg-link; then
|
|
# Editable install.
|
|
BASEDIR="$(head -n1 /usr/local/lib/${python_dir}/*-packages/kolla-ansible.egg-link)"
|
|
else
|
|
BASEDIR=/usr/local/share/kolla-ansible
|
|
fi
|
|
elif [[ ${dir_name} == ~/.local/bin ]]; then
|
|
if test -f ~/.local/lib/${python_dir}/*-packages/kolla-ansible.egg-link; then
|
|
# Editable install.
|
|
BASEDIR="$(head -n1 ~/.local/lib/${python_dir}/*-packages/kolla-ansible.egg-link)"
|
|
else
|
|
BASEDIR=~/.local/share/kolla-ansible
|
|
fi
|
|
elif [[ -n ${VIRTUAL_ENV} ]] && [[ ${dir_name} == "$(readlink -e "${VIRTUAL_ENV}/bin")" ]]; then
|
|
if test -f ${VIRTUAL_ENV}/lib/${python_dir}/site-packages/kolla-ansible.egg-link; then
|
|
# Editable install.
|
|
BASEDIR="$(head -n1 ${VIRTUAL_ENV}/lib/${python_dir}/*-packages/kolla-ansible.egg-link)"
|
|
else
|
|
BASEDIR="${VIRTUAL_ENV}/share/kolla-ansible"
|
|
fi
|
|
else
|
|
# Running from sources (repo).
|
|
BASEDIR="$(dirname ${dir_name})"
|
|
fi
|
|
else
|
|
BASEDIR="$SNAP/share/kolla-ansible"
|
|
fi
|
|
}
|
|
|
|
function process_cmd {
|
|
echo "$ACTION : $CMD"
|
|
$CMD
|
|
if [[ $? -ne 0 ]]; then
|
|
echo "Command failed $CMD"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
function usage {
|
|
cat <<EOF
|
|
Usage: $0 COMMAND [options]
|
|
|
|
Options:
|
|
--inventory, -i <inventory_path> Specify path to ansible inventory file. \
|
|
Can be specified multiple times to pass multiple inventories.
|
|
--playbook, -p <playbook_path> Specify path to ansible playbook file
|
|
--configdir <config_path> Specify path to directory with globals.yml
|
|
--key -k <key_path> Specify path to ansible vault keyfile
|
|
--help, -h Show this usage information
|
|
--tags, -t <tags> Only run plays and tasks tagged with these values
|
|
--skip-tags <tags> Only run plays and tasks whose tags do not match these values
|
|
--extra, -e <ansible variables> Set additional variables as key=value or YAML/JSON passed to ansible-playbook
|
|
--passwords <passwords_path> Specify path to the passwords file
|
|
--limit <host> Specify host to run plays
|
|
--forks <forks> Number of forks to run Ansible with
|
|
--vault-id <@prompt or path> Specify @prompt or password file (Ansible >= 2.4)
|
|
--ask-vault-pass Ask for vault password
|
|
--vault-password-file <path> Specify password file for vault decrypt
|
|
--check, -C Don't make any changes and try to predict some of the changes that may occur instead
|
|
--diff, -D Show differences in ansible-playbook changed tasks
|
|
--verbose, -v Increase verbosity of ansible-playbook
|
|
|
|
Environment variables:
|
|
EXTRA_OPTS Additional arguments to pass to ansible-playbook
|
|
|
|
Commands:
|
|
prechecks Do pre-deployment checks for hosts
|
|
check Do post-deployment smoke tests
|
|
mariadb_recovery Recover a completely stopped mariadb cluster
|
|
mariadb_backup Take a backup of MariaDB databases
|
|
--full (default)
|
|
--incremental
|
|
monasca_cleanup Remove unused containers for the Monasca service
|
|
bootstrap-servers Bootstrap servers with kolla deploy dependencies
|
|
destroy Destroy Kolla containers, volumes and host configuration
|
|
--include-images to also destroy Kolla images
|
|
--include-dev to also destroy dev mode repos
|
|
deploy Deploy and start all kolla containers
|
|
deploy-bifrost Deploy and start bifrost container
|
|
deploy-servers Enroll and deploy servers with bifrost
|
|
deploy-containers Only deploy and start containers (no config updates or bootstrapping)
|
|
gather-facts Gather Ansible facts
|
|
post-deploy Do post deploy on deploy node
|
|
pull Pull all images for containers (only pulls, no running container changes)
|
|
reconfigure Reconfigure OpenStack service
|
|
stop Stop Kolla containers
|
|
certificates Generate self-signed certificate for TLS *For Development Only*
|
|
octavia-certificates Generate certificates for octavia deployment
|
|
upgrade Upgrades existing OpenStack Environment
|
|
upgrade-bifrost Upgrades an existing bifrost container
|
|
genconfig Generate configuration files for enabled OpenStack services
|
|
prune-images Prune orphaned Kolla images
|
|
chrony-cleanup Clean up disabled chrony containers
|
|
EOF
|
|
}
|
|
|
|
function bash_completion {
|
|
cat <<EOF
|
|
--inventory -i
|
|
--playbook -p
|
|
--configdir
|
|
--key -k
|
|
--help -h
|
|
--skip-tags
|
|
--tags -t
|
|
--extra -e
|
|
--passwords
|
|
--limit
|
|
--forks
|
|
--vault-id
|
|
--ask-vault-pass
|
|
--vault-password-file
|
|
--check -C
|
|
--diff -D
|
|
--verbose -v
|
|
prechecks
|
|
check
|
|
mariadb_recovery
|
|
mariadb_backup
|
|
monasca_cleanup
|
|
bootstrap-servers
|
|
destroy
|
|
deploy
|
|
deploy-bifrost
|
|
deploy-containers
|
|
deploy-servers
|
|
gather-facts
|
|
post-deploy
|
|
pull
|
|
reconfigure
|
|
stop
|
|
certificates
|
|
octavia-certificates
|
|
upgrade
|
|
upgrade-bifrost
|
|
genconfig
|
|
prune-images
|
|
EOF
|
|
}
|
|
|
|
check_environment_coherence
|
|
|
|
SHORT_OPTS="hi:p:t:k:e:CD:v"
|
|
LONG_OPTS="help,inventory:,playbook:,skip-tags:,tags:,key:,extra:,check,diff,verbose,configdir:,passwords:,limit:,forks:,vault-id:,ask-vault-pass,vault-password-file:,yes-i-really-really-mean-it,include-images,include-dev:,full,incremental"
|
|
|
|
RAW_ARGS="$*"
|
|
ARGS=$(getopt -o "${SHORT_OPTS}" -l "${LONG_OPTS}" --name "$0" -- "$@") || { usage >&2; exit 2; }
|
|
|
|
eval set -- "$ARGS"
|
|
|
|
find_base_dir
|
|
|
|
INVENTORY="${BASEDIR}/ansible/inventory/all-in-one"
|
|
PLAYBOOK="${BASEDIR}/ansible/site.yml"
|
|
VERBOSITY=
|
|
EXTRA_OPTS=${EXTRA_OPTS}
|
|
CONFIG_DIR="/etc/kolla"
|
|
DANGER_CONFIRM=
|
|
INCLUDE_IMAGES=
|
|
INCLUDE_DEV=
|
|
BACKUP_TYPE="full"
|
|
# Serial is not recommended and disabled by default. Users can enable it by
|
|
# configuring ANSIBLE_SERIAL variable.
|
|
ANSIBLE_SERIAL=${ANSIBLE_SERIAL:-0}
|
|
INVENTORIES=()
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
|
|
(--inventory|-i)
|
|
INVENTORIES+=("$2")
|
|
shift 2
|
|
;;
|
|
|
|
(--playbook|-p)
|
|
PLAYBOOK="$2"
|
|
shift 2
|
|
;;
|
|
|
|
(--skip-tags)
|
|
EXTRA_OPTS="$EXTRA_OPTS --skip-tags $2"
|
|
shift 2
|
|
;;
|
|
|
|
(--tags|-t)
|
|
EXTRA_OPTS="$EXTRA_OPTS --tags $2"
|
|
shift 2
|
|
;;
|
|
|
|
(--check|-C)
|
|
EXTRA_OPTS="$EXTRA_OPTS --check"
|
|
shift 1
|
|
;;
|
|
|
|
(--diff|-D)
|
|
EXTRA_OPTS="$EXTRA_OPTS --diff"
|
|
shift 1
|
|
;;
|
|
|
|
(--verbose|-v)
|
|
VERBOSITY="$VERBOSITY --verbose"
|
|
shift 1
|
|
;;
|
|
|
|
(--configdir)
|
|
CONFIG_DIR="$2"
|
|
shift 2
|
|
;;
|
|
|
|
(--yes-i-really-really-mean-it)
|
|
if [[ ${RAW_ARGS} =~ "$1" ]]
|
|
then
|
|
DANGER_CONFIRM="$1"
|
|
fi
|
|
shift 1
|
|
;;
|
|
|
|
(--include-images)
|
|
INCLUDE_IMAGES="$1"
|
|
shift 1
|
|
;;
|
|
|
|
(--include-dev)
|
|
INCLUDE_DEV="$1"
|
|
shift 1
|
|
;;
|
|
|
|
(--key|-k)
|
|
VAULT_PASS_FILE="$2"
|
|
EXTRA_OPTS="$EXTRA_OPTS --vault-password-file=$VAULT_PASS_FILE"
|
|
shift 2
|
|
;;
|
|
|
|
(--extra|-e)
|
|
EXTRA_OPTS="$EXTRA_OPTS -e $2"
|
|
shift 2
|
|
;;
|
|
|
|
(--passwords)
|
|
PASSWORDS_FILE="$2"
|
|
shift 2
|
|
;;
|
|
|
|
(--limit)
|
|
EXTRA_OPTS="$EXTRA_OPTS --limit $2"
|
|
shift 2
|
|
;;
|
|
|
|
(--forks)
|
|
EXTRA_OPTS="$EXTRA_OPTS --forks $2"
|
|
shift 2
|
|
;;
|
|
|
|
(--vault-id)
|
|
EXTRA_OPTS="$EXTRA_OPTS --vault-id $2"
|
|
shift 2
|
|
;;
|
|
|
|
(--ask-vault-pass)
|
|
VERBOSITY="$EXTRA_OPTS --ask-vault-pass"
|
|
shift 1
|
|
;;
|
|
|
|
(--vault-password-file)
|
|
EXTRA_OPTS="$EXTRA_OPTS --vault-password-file $2"
|
|
shift 2
|
|
;;
|
|
|
|
(--full)
|
|
BACKUP_TYPE="full"
|
|
shift 1
|
|
;;
|
|
|
|
(--incremental)
|
|
BACKUP_TYPE="incremental"
|
|
shift 1
|
|
;;
|
|
|
|
(--help|-h)
|
|
usage
|
|
shift
|
|
exit 0
|
|
;;
|
|
|
|
(--)
|
|
shift
|
|
break
|
|
;;
|
|
|
|
(*)
|
|
echo "error"
|
|
exit 3
|
|
;;
|
|
esac
|
|
done
|
|
|
|
case "$1" in
|
|
|
|
(prechecks)
|
|
ACTION="Pre-deployment checking"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=precheck"
|
|
;;
|
|
(check)
|
|
ACTION="Post-deployment checking"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=check"
|
|
;;
|
|
(mariadb_recovery)
|
|
ACTION="Attempting to restart mariadb cluster"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy"
|
|
PLAYBOOK="${BASEDIR}/ansible/mariadb_recovery.yml"
|
|
;;
|
|
(mariadb_backup)
|
|
ACTION="Backup MariaDB databases"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=backup -e mariadb_backup_type=${BACKUP_TYPE}"
|
|
PLAYBOOK="${BASEDIR}/ansible/mariadb_backup.yml"
|
|
;;
|
|
(monasca_cleanup)
|
|
ACTION="Cleanup unused Monasca services"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=cleanup"
|
|
PLAYBOOK="${BASEDIR}/ansible/monasca_cleanup.yml"
|
|
;;
|
|
(destroy)
|
|
ACTION="Destroy Kolla containers, volumes and host configuration"
|
|
PLAYBOOK="${BASEDIR}/ansible/destroy.yml"
|
|
if [[ "${INCLUDE_IMAGES}" == "--include-images" ]]; then
|
|
EXTRA_OPTS="$EXTRA_OPTS -e destroy_include_images=yes"
|
|
fi
|
|
if [[ "${INCLUDE_DEV}" == "--include-dev" ]]; then
|
|
EXTRA_OPTS="$EXTRA_OPTS -e destroy_include_dev=yes"
|
|
fi
|
|
if [[ "${DANGER_CONFIRM}" != "--yes-i-really-really-mean-it" ]]; then
|
|
cat << EOF
|
|
WARNING:
|
|
This will PERMANENTLY DESTROY all deployed kolla containers, volumes and host configuration.
|
|
There is no way to recover from this action. To confirm, please add the following option:
|
|
--yes-i-really-really-mean-it
|
|
EOF
|
|
exit 1
|
|
fi
|
|
;;
|
|
(bootstrap-servers)
|
|
ACTION="Bootstrapping servers"
|
|
PLAYBOOK="${BASEDIR}/ansible/kolla-host.yml"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=bootstrap-servers"
|
|
;;
|
|
(deploy)
|
|
ACTION="Deploying Playbooks"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy"
|
|
;;
|
|
(deploy-bifrost)
|
|
ACTION="Deploying Bifrost"
|
|
PLAYBOOK="${BASEDIR}/ansible/bifrost.yml"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy"
|
|
;;
|
|
(deploy-containers)
|
|
ACTION="Deploying Containers"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy-containers"
|
|
;;
|
|
(deploy-servers)
|
|
ACTION="Deploying servers with bifrost"
|
|
PLAYBOOK="${BASEDIR}/ansible/bifrost.yml"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy-servers"
|
|
;;
|
|
(gather-facts)
|
|
ACTION="Gathering Ansible facts"
|
|
PLAYBOOK="${BASEDIR}/ansible/gather-facts.yml"
|
|
;;
|
|
(post-deploy)
|
|
ACTION="Post-Deploying Playbooks"
|
|
PLAYBOOK="${BASEDIR}/ansible/post-deploy.yml"
|
|
;;
|
|
(pull)
|
|
ACTION="Pulling Docker images"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=pull"
|
|
;;
|
|
(upgrade)
|
|
ACTION="Upgrading OpenStack Environment"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=upgrade -e kolla_serial=${ANSIBLE_SERIAL}"
|
|
;;
|
|
(upgrade-bifrost)
|
|
ACTION="Upgrading Bifrost"
|
|
PLAYBOOK="${BASEDIR}/ansible/bifrost.yml"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=upgrade"
|
|
;;
|
|
(reconfigure)
|
|
ACTION="Reconfigure OpenStack service"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=reconfigure -e kolla_serial=${ANSIBLE_SERIAL}"
|
|
;;
|
|
(stop)
|
|
ACTION="Stop Kolla containers"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=stop"
|
|
if [[ "${DANGER_CONFIRM}" != "--yes-i-really-really-mean-it" ]]; then
|
|
cat << EOF
|
|
WARNING:
|
|
This will stop all deployed kolla containers, limit with tags is possible and also with
|
|
skip_stop_containers variable. To confirm, please add the following option:
|
|
--yes-i-really-really-mean-it
|
|
EOF
|
|
exit 1
|
|
fi
|
|
;;
|
|
(certificates)
|
|
ACTION="Generate TLS Certificates"
|
|
PLAYBOOK="${BASEDIR}/ansible/certificates.yml"
|
|
;;
|
|
(octavia-certificates)
|
|
ACTION="Generate octavia Certificates"
|
|
PLAYBOOK="${BASEDIR}/ansible/octavia-certificates.yml"
|
|
;;
|
|
(genconfig)
|
|
ACTION="Generate configuration files for enabled OpenStack services"
|
|
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=config"
|
|
;;
|
|
(prune-images)
|
|
ACTION="Prune orphaned Kolla images"
|
|
PLAYBOOK="${BASEDIR}/ansible/prune-images.yml"
|
|
if [[ "${DANGER_CONFIRM}" != "--yes-i-really-really-mean-it" ]]; then
|
|
cat << EOF
|
|
WARNING:
|
|
This will PERMANENTLY DELETE all orphaned kolla images. To confirm, please add the following option:
|
|
--yes-i-really-really-mean-it
|
|
EOF
|
|
exit 1
|
|
fi
|
|
;;
|
|
(chrony-cleanup)
|
|
ACTION="Cleanup disabled chrony containers"
|
|
PLAYBOOK="${BASEDIR}/ansible/chrony-cleanup.yml"
|
|
;;
|
|
(bash-completion)
|
|
bash_completion
|
|
exit 0
|
|
;;
|
|
(*) usage
|
|
exit 3
|
|
;;
|
|
esac
|
|
|
|
GLOBALS_DIR="${CONFIG_DIR}/globals.d"
|
|
EXTRA_GLOBALS=$(find ${GLOBALS_DIR} -maxdepth 1 -type f -name '*.yml' -printf ' -e @%p' 2>/dev/null)
|
|
PASSWORDS_FILE="${PASSWORDS_FILE:-${CONFIG_DIR}/passwords.yml}"
|
|
CONFIG_OPTS="-e @${CONFIG_DIR}/globals.yml ${EXTRA_GLOBALS} -e @${PASSWORDS_FILE} -e CONFIG_DIR=${CONFIG_DIR}"
|
|
CMD="ansible-playbook $CONFIG_OPTS $EXTRA_OPTS $PLAYBOOK $VERBOSITY"
|
|
for INVENTORY in ${INVENTORIES[@]}; do
|
|
CMD="${CMD} --inventory $INVENTORY"
|
|
done
|
|
process_cmd
|