#!/bin/bash
#
# This script can be used to interact with kolla via ansible.

function find_base_dir {
    local real_path=$(python -c "import os;print(os.path.realpath('$0'))")
    local dir_name="$(dirname "$real_path")"
    if [ -z "$SNAP" ]; then
        if [[ ${dir_name} == "/usr/bin" ]]; then
            BASEDIR=/usr/share/kolla-ansible
        elif [[ ${dir_name} == "/usr/local/bin" ]]; then
            BASEDIR=/usr/local/share/kolla-ansible
        else
            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:
    --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
    --extra, -e <ansible variables>    Set additional variables as key=value or YAML/JSON passed to ansible-playbook
    --include-images                   Destroy images during destroy task
    --verbose, -v                      Increase verbosity of ansible-playbook
    --limit <host>                     Specify host to run plays

Commands:
    prechecks           Do pre-deployment checks for hosts
    bootstrap-servers   bootstrap servers with kolla deploy dependencies
    destroy             Destroy Kolla containers, volumes and host configuration
    deploy              Deploy and start all kolla containers
    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
    upgrade             Upgrades existing OpenStack Environment
    genconfig           Generate configuration files for enabled OpenStack services
EOF
}


SHORT_OPTS="hp:t:k:e:v"
LONG_OPTS="help,playbook:,tags:,key:,extra:,verbose,configdir:,include-images,limit:"
ARGS=$(getopt -o "${SHORT_OPTS}" -l "${LONG_OPTS}" --name "$0" -- "$@") || { usage >&2; exit 2; }

eval set -- "$ARGS"

find_base_dir

PLAYBOOK="${BASEDIR}/ansible/site.yml"
VERBOSITY=
EXTRA_OPTS=${EXTRA_OPTS}
CONFIG_DIR="/etc/kolla"
INCLUDE_IMAGES=
# Serial is not recommended and disable in default. User could enable it by
# simple configure ANSIBLE_SERIAL variable
ANSIBLE_SERIAL=${ANSIBLE_SERIAL:-0}

while [ "$#" -gt 0 ]; do
    case "$1" in

    (--playbook|-p)
            PLAYBOOK="$2"
            shift 2
            ;;

    (--tags|-t)
            EXTRA_OPTS="$EXTRA_OPTS --tags $2"
            shift 2
            ;;

    (--verbose|-v)
            VERBOSITY="$VERBOSITY --verbose"
            shift 1
            ;;

    (--configdir)
            CONFIG_DIR="$2"
            shift 2
            ;;

    (--include-images)
            INCLUDE_IMAGES="$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
            ;;

    (--limit)
            EXTRA_OPTS="$EXTRA_OPTS --limit $2"
            shift 2
            ;;

    (--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"
        ;;
(destroy)
        ACTION="Destroy deployment"
        PLAYBOOK="${BASEDIR}/ansible/destroy-all.yml"
        if [[ "${INCLUDE_IMAGES}" == "--include-images" ]]; then
            EXTRA_OPTS="$EXTRA_OPTS -e destroy_images=yes"
        fi
        ;;
(destroy-compute)
        ACTION="Destroy compute containers and volumes"
        PLAYBOOK="${BASEDIR}/ansible/destroy-compute.yml"
        ;;
(destroy-controller)
        ACTION="Destroy controller containers and volumes"
        PLAYBOOK="${BASEDIR}/ansible/destroy-controller.yml"
        ;;
(bootstrap-servers)
        ACTION="Bootstrapping servers"
        PLAYBOOK="${BASEDIR}/ansible/kolla-host.yml"
        ;;
(deploy)
        ACTION="Deploying Playbooks"
        EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy"
        ;;
(post-deploy)
        ACTION="Post-Deploying Playbooks"
        PLAYBOOK="${BASEDIR}/ansible/post-deploy.yml"
        ;;
(deploy-cinder)
        ACTION="Deploying Cinder"
        PLAYBOOK="${BASEDIR}/ansible/deploy-cinder.yml"
        ;;
(deploy-cron)
        ACTION="Deploying Cron"
        PLAYBOOK="${BASEDIR}/ansible/deploy-cron.yml"
        ;;
(deploy-glance)
        ACTION="Deploying Glance"
        PLAYBOOK="${BASEDIR}/ansible/deploy-glance.yml"
        ;;
(deploy-nginx)
        ACTION="Deploying Load Balancer"
        PLAYBOOK="${BASEDIR}/ansible/deploy-nginx.yml"
        ;;
(deploy-horizon)
        ACTION="Deploying Horizon"
        PLAYBOOK="${BASEDIR}/ansible/deploy-horizon.yml"
        ;;
(deploy-libvirt)
        ACTION="Deploying Libvirt"
        PLAYBOOK="${BASEDIR}/ansible/deploy-libvirt.yml"
        ;;
(deploy-memcached)
        ACTION="Deploying Memcached"
        PLAYBOOK="${BASEDIR}/ansible/deploy-memcached.yml"
        ;;
(deploy-neutron)
        ACTION="Deploying Neutron"
        PLAYBOOK="${BASEDIR}/ansible/deploy-neutron.yml"
        ;;
(deploy-nova)
        ACTION="Deploying Nova"
        PLAYBOOK="${BASEDIR}/ansible/deploy-nova.yml"
        ;;
(deploy-rabbitmq)
        ACTION="Deploying RabbitMQ"
        PLAYBOOK="${BASEDIR}/ansible/deploy-rabbitmq.yml"
        ;;
(deploy-tempest)
        ACTION="Deploying Tempest"
        PLAYBOOK="${BASEDIR}/ansible/deploy-tempest.yml"
        ;;
(deploy-heat)
        ACTION="Deploying Heat"
        PLAYBOOK="${BASEDIR}/ansible/deploy-heat.yml"
        ;;
(deploy-beholder)
        ACTION="Deploying Beholder"
        PLAYBOOK="${BASEDIR}/ansible/deploy-beholder.yml"
        ;;
(deploy-registry)
        ACTION="Deploying Registry"
        PLAYBOOK="${BASEDIR}/ansible/deploy-registry.yml"
        ;;
(update-registry)
        ACTION="Updating Registry"
        PLAYBOOK="${BASEDIR}/ansible/update-registry.yml"
        ;;
(copy-pkey)
        ACTION="Copying ansible private key"
        PLAYBOOK="${BASEDIR}/ansible/copy-pkey.yml"
        ;;
(reconfigure-neutron-ovs-agent)
        ACTION="Reconfiguring Neutron OVS agent"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-neutron-ovs-agent.yml"
        ;;
(reconfigure-neutron-server)
        ACTION="Reconfiguring Neutron Server"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-neutron-server.yml"
        ;;
(reconfigure-nova)
        ACTION="Reconfiguring Nova"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-nova.yml"
        ;;
(reconfigure-nginx)
        ACTION="Reconfiguring Load Balancer"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-nginx.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}"
        ;;
(reconfigure)
        ACTION="Reconfigure OpenStack service"
        EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=reconfigure -e kolla_serial=${ANSIBLE_SERIAL}"
        ;;
(stop)
        ACTION="Stop Kolla containers"
        PLAYBOOK="${BASEDIR}/ansible/stop.yml"
        ;;
(genconfig)
        ACTION="Generate configuration files for enabled OpenStack services"
        EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=config"
        ;;
(configure-keystone)
        ACTION="Configure Keystone"
        PLAYBOOK="${BASEDIR}/ansible/configure-keystone.yml"
        ;;
(*)     usage
        exit 0
        ;;
esac

ANSIBLE_PLAYBOOK="ansible-playbook"
CONFIG_OPTS="-e CONFIG_DIR=${CONFIG_DIR}"
INVENTORY="-i ${CONFIG_DIR}/vstorage-backend.py"

VERSIONS_FILE="${CONFIG_DIR}/versions.yml"
if [ -f "$VERSIONS_FILE" ]; then
    CONFIG_OPTS="${CONFIG_OPTS} -e @${VERSIONS_FILE}"
fi

PASSWORDS_FILE="${CONFIG_DIR}/passwords.yml"
if [ -f "$PASSWORDS_FILE" ]; then
    CONFIG_OPTS="${CONFIG_OPTS} -e @${PASSWORDS_FILE}"
fi

CMD="${ANSIBLE_PLAYBOOK} ${INVENTORY} ${CONFIG_OPTS} ${EXTRA_OPTS} ${PLAYBOOK} ${VERBOSITY}"
process_cmd
