#!/usr/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"
        ;;
(destroy-common)
        ACTION="Destroy compute/controller common containers and volumes"
        PLAYBOOK="${BASEDIR}/ansible/destroy-common.yml"
        ;;
(destroy-vhs-controller)
        ACTION="Destroy VHS Controller"
        PLAYBOOK="${BASEDIR}/ansible/destroy-vhs-controller.yml"
        ;;
(destroy-vhs-node)
        ACTION="Destroy VHS Node"
        PLAYBOOK="${BASEDIR}/ansible/destroy-vhs-node.yml"
        ;;
(forget-rabbitmq-nodes)
        ACTION="Forget RabbitMQ nodes"
        PLAYBOOK="${BASEDIR}/ansible/forget-rabbitmq-nodes.yml"
        ;;
(grow-rabbitmq-quorum)
        ACTION="Grow RabbitMQ quorum"
        PLAYBOOK="${BASEDIR}/ansible/grow-rabbitmq-quorum.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-libvirt)
        ACTION="Deploying Libvirt"
        PLAYBOOK="${BASEDIR}/ansible/deploy-libvirt.yml"
        ;;
(deploy-openstack-exporter)
        ACTION="Deploying OpenStack Exporter"
        PLAYBOOK="${BASEDIR}/ansible/deploy-openstack-exporter.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-placement)
        ACTION="Deploying Placement"
        PLAYBOOK="${BASEDIR}/ansible/deploy-placement.yml"
        ;;
(deploy-rabbitmq)
        ACTION="Deploying RabbitMQ"
        PLAYBOOK="${BASEDIR}/ansible/deploy-rabbitmq.yml"
        ;;
(rebuild-rabbitmq)
        ACTION="Rebuild RabbitMQ node and join it into the cluster"
        PLAYBOOK="${BASEDIR}/ansible/rebuild-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"
        ;;
(deploy-ceilometer)
        ACTION="Deploying Ceilometer"
        PLAYBOOK="${BASEDIR}/ansible/deploy-ceilometer.yml"
        ;;
(deploy-gnocchi)
        ACTION="Deploying Gnocchi"
        PLAYBOOK="${BASEDIR}/ansible/deploy-gnocchi.yml"
        ;;
(deploy-magnum)
        ACTION="Deploying Magnum"
        PLAYBOOK="${BASEDIR}/ansible/deploy-magnum.yml"
        ;;
(deploy-octavia)
        ACTION="Deploying Octavia"
        PLAYBOOK="${BASEDIR}/ansible/deploy-octavia.yml"
        ;;
(deploy-barbican)
        ACTION="Deploying Barbican"
        PLAYBOOK="${BASEDIR}/ansible/deploy-barbican.yml"
        ;;
(deploy-freezer)
        ACTION="Deploying Freezer"
        PLAYBOOK="${BASEDIR}/ansible/deploy-freezer.yml"
        ;;
(deploy-watcher)
        ACTION="Deploying Watcher"
        PLAYBOOK="${BASEDIR}/ansible/deploy-watcher.yml"
        ;;
(deploy-manila)
        ACTION="Deploying Manila"
        PLAYBOOK="${BASEDIR}/ansible/deploy-manila.yml"
        ;;
(deploy-vporter)
        ACTION="Deploying vPorter"
        PLAYBOOK="${BASEDIR}/ansible/deploy-vporter.yml"
	;;
(deploy-vhs-controller)
        ACTION="Deploying VHS Controller"
        PLAYBOOK="${BASEDIR}/ansible/deploy-vhs-controller.yml"
        ;;
(deploy-vhs-node)
        ACTION="Deploying VHS Node"
        PLAYBOOK="${BASEDIR}/ansible/deploy-vhs-node.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-cinder)
        ACTION="Reconfiguring Cinder"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-cinder.yml"
        ;;
(reconfigure-glance)
        ACTION="Reconfiguring Glance"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-glance.yml"
        ;;
(reconfigure-neutron)
        ACTION="Reconfiguring Neutron"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-neutron.yml"
        ;;
(reconfigure-magnum)
        ACTION="Reconfiguring Magnum"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-magnum.yml"
        ;;
(reconfigure-octavia)
        ACTION="Reconfiguring Octavia"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-octavia.yml"
        ;;
(reconfigure-placement)
        ACTION="Reconfiguring Placement"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-placement.yml"
        ;;
(reconfigure-ceilometer)
        ACTION="Reconfiguring Ceilometer"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-ceilometer.yml"
        ;;
(reconfigure-freezer)
        ACTION="Reconfiguring Freezer"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-freezer.yml"
        ;;
(reconfigure-watcher)
        ACTION="Reconfiguring Watcher"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-watcher.yml"
        ;;
(reconfigure-manila)
        ACTION="Reconfiguring Manila"
        PLAYBOOK="${BASEDIR}/ansible/reconfigure-manila.yml"
        ;;
(restart-octavia)
        ACTION="Restart Octavia"
        PLAYBOOK="${BASEDIR}/ansible/restart-octavia.yml"
        ;;
(cleanup-stale-images)
        ACTION="Cleanup stale images"
        PLAYBOOK="${BASEDIR}/ansible/cleanup-stale-images.yml"
        ;;
(self-upgrade)
        ACTION="Self upgrade"
        PLAYBOOK="${BASEDIR}/ansible/self-upgrade.yml"
        ;;
(reassign-magnum-clusters)
        ACTION="Reassign magnum clusters"
        PLAYBOOK="${BASEDIR}/ansible/reassign-magnum-clusters.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="Stopping OpenStack containers"
        EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=stop -e kolla_serial=${ANSIBLE_SERIAL}"
        ;;
(remove)
        ACTION="Removing OpenStack containers"
        EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=remove -e kolla_serial=${ANSIBLE_SERIAL}"
        ;;
(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"
        ;;
(deploy-mtail)
        ACTION="Deploying mtail"
        PLAYBOOK="${BASEDIR}/ansible/deploy-mtail.yml"
        ;;
(destroy-management)
        ACTION="Destroy management node containers"
        PLAYBOOK="${BASEDIR}/ansible/destroy-management.yml"
        ;;
(copy-certificates)
        ACTION="Copying certificate files"
        PLAYBOOK="${BASEDIR}/ansible/copy-certificates.yml"
        ;;
(wa-disable-ovs-probe)
        ACTION="Increase inactivity_probe for ovs"
        PLAYBOOK="${BASEDIR}/ansible/wa-disable-ovs-probe.yml"
        ;;
(*)     usage
        exit 0
        ;;
esac

# kolla-ansible should be executed under vstoradmin user
if [ $(whoami) != "vstoradmin" ]; then
    echo "kolla-ansible must be executed under vstoradmin user"
    exit 1
fi

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
