# lib/solum

# Dependencies:
# ``functions`` file
# ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined
# ``ADMIN_{TENANT_NAME|PASSWORD}`` must be defined

# ``stack.sh`` calls the entry points in this order:
#
# install_solum
# install_solumclient
# configure_solum
# start_solum
# stop_solum

# Save trace setting
XTRACE=$(set +o | grep xtrace)
set +o xtrace

# Defaults
# --------

# Set up default repos
SOLUM_REPO=${SOLUM_REPO:-${GIT_BASE}/openstack/solum.git}
SOLUM_BRANCH=${SOLUM_BRANCH:-master}
SOLUMCLIENT_REPO=${SOLUMCLIENT_REPO:-${GIT_BASE}/openstack/python-solumclient.git}
SOLUMCLIENT_BRANCH=${SOLUMCLIENT_BRANCH:-master}

# Set up default directories
SOLUM_DIR=$DEST/solum
SOLUMCLIENT_DIR=$DEST/python-solumclient
SOLUM_CONF_DIR=${SOLUM_CONF_DIR:-/etc/solum}
SOLUM_CONF_FILE=solum.conf
ADMIN_TENANT_NAME=${ADMIN_TENANT_NAME:-admin}
ADMIN_NAME=${ADMIN_NAME:-admin}
ADMIN_PASSWORD=${ADMIN_PASSWORD:-nova}
SOLUM_DEBUG=${SOLUM_DEBUG:-True}
SOLUM_USER=solum
SOLUM_AUTH_CACHE_DIR=${SOLUM_AUTH_CACHE_DIR:-/var/cache/solum}
SOLUM_INSTALL_CEDARISH=${SOLUM_INSTALL_CEDARISH:-False}

SOLUM_SERVICE_HOST=${SOLUM_SERVICE_HOST:-$SERVICE_HOST}
SOLUM_SERVICE_PORT=${SOLUM_SERVICE_PORT:-9777}
SOLUM_BUILDER_SERVICE_PORT=${SOLUM_BUILDER_SERVICE_PORT:-9778}
SOLUM_SERVICE_PROTOCOL=${SOLUM_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
SOLUM_IMAGE_FORMAT=${SOLUM_IMAGE_FORMAT:-'docker'}

SOLUM_MAX_ATTEMPTS=${SOLUM_MAX_ATTEMPTS:-2000}
SOLUM_WAIT_INTERVAL=${SOLUM_WAIT_INTERVAL:-1}
SOLUM_GROWTH_FACTOR=${SOLUM_GROWTH_FACTOR:-1.1}

SOLUM_DRONE_URL=${SOLUM_DRONE_URL:-http://downloads.drone.io/master/drone.deb}
SOLUM_INSTALL_DRONE=${SOLUM_INSTALL_DRONE:-False}

SOLUM_PROJ_DIR=${SOLUM_PROJ_DIR:-/opt/stack/solum}

SOLUM_INSTALL_DOCKER_REGISTRY=${SOLUM_INSTALL_DOCKER_REGISTRY:-False}
SOLUM_DEPLOYMENT_MECHANISM=${SOLUM_DEPLOYMENT_MECHANISM:-'docker_on_nova'}

# Support entry points installation of console scripts
if [[ -d $SOLUM_DIR/bin ]]; then
    SOLUM_BIN_DIR=$SOLUM_DIR/bin
else
    SOLUM_BIN_DIR=$(get_python_exec_prefix)
fi

# Functions
# ---------

# create_solum_service_and_endpoint() - Set up required solum service and endpoint
function create_solum_service_and_endpoint() {
    SOLUM_UPDATE_ROLE=$(openstack role create \
        solum_assembly_update \
        | grep " id " | get_field 2)

    # Give the role to the demo and admin users so they can use git push
    # in either of the projects created by devstack
    openstack role add $SOLUM_UPDATE_ROLE --project demo --user demo
    openstack role add $SOLUM_UPDATE_ROLE --project demo --user admin
    openstack role add $SOLUM_UPDATE_ROLE --project admin --user admin

    if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
        SOLUM_SERVICE=$(openstack service create application_deployment \
            --name=solum \
            --description="Solum" \
            | grep " id " | get_field 2)
        openstack endpoint create --region RegionOne $SOLUM_SERVICE public "$SOLUM_SERVICE_PROTOCOL://$SOLUM_SERVICE_HOST:$SOLUM_SERVICE_PORT"
        openstack endpoint create --region RegionOne $SOLUM_SERVICE admin "$SOLUM_SERVICE_PROTOCOL://$SOLUM_SERVICE_HOST:$SOLUM_SERVICE_PORT"
        openstack endpoint create --region RegionOne $SOLUM_SERVICE internal "$SOLUM_SERVICE_PROTOCOL://$SOLUM_SERVICE_HOST:$SOLUM_SERVICE_PORT"

        SOLUM_BUILDER_SERVICE=$(openstack service create image_builder \
            --name=solum \
            --description="Solum Image Builder" \
            | grep " id " | get_field 2)

        openstack endpoint create --region RegionOne $SOLUM_BUILDER_SERVICE public "$SOLUM_SERVICE_PROTOCOL://$SOLUM_SERVICE_HOST:$SOLUM_BUILDER_SERVICE_PORT"
        openstack endpoint create --region RegionOne $SOLUM_BUILDER_SERVICE admin "$SOLUM_SERVICE_PROTOCOL://$SOLUM_SERVICE_HOST:$SOLUM_BUILDER_SERVICE_PORT"
        openstack endpoint create --region RegionOne $SOLUM_BUILDER_SERVICE internal "$SOLUM_SERVICE_PROTOCOL://$SOLUM_SERVICE_HOST:$SOLUM_BUILDER_SERVICE_PORT"

    fi
}

# configure_solum() - Set config files, create data dirs, etc
function configure_solum() {

    if [[ ! -d $SOLUM_CONF_DIR ]]; then
        sudo mkdir -p $SOLUM_CONF_DIR
    fi
    sudo chown $STACK_USER $SOLUM_CONF_DIR

    # To support private github repos, do not perform host key check for github.com
    # Need this change on solum-worker instances
    STACK_USER_SSH_DIR=/home/$STACK_USER/.ssh
    if [[ ! -d $STACK_USER_SSH_DIR ]]; then
        sudo mkdir -p $STACK_USER_SSH_DIR
    fi
    sudo chown $STACK_USER $STACK_USER_SSH_DIR
    echo -e "Host github.com\n\tStrictHostKeyChecking no\n" > $STACK_USER_SSH_DIR/config

    # Generate sample config and configure common parameters.
    mkdir -p /tmp/solum
    pushd $SOLUM_DIR
        OUTPUTDIR=/tmp/solum/ ./tools/config/generate_sample.sh
    popd
    cp /tmp/solum/solum.conf.sample $SOLUM_CONF_DIR/$SOLUM_CONF_FILE

    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE DEFAULT debug $SOLUM_DEBUG

    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE DEFAULT use_syslog $SYSLOG

    # make trace visible
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE DEFAULT logging_context_format_string "%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s] s%(message)s %(support_trace)s"

    # Setup keystone_authtoken section
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE keystone_authtoken auth_host $KEYSTONE_AUTH_HOST
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE keystone_authtoken auth_port $KEYSTONE_AUTH_PORT
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE keystone_authtoken cafile $KEYSTONE_SSL_CA
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE keystone_authtoken auth_uri $KEYSTONE_SERVICE_URI/v2.0
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE keystone_authtoken admin_tenant_name service
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE keystone_authtoken admin_user $SOLUM_USER
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE keystone_authtoken admin_password $ADMIN_PASSWORD
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE keystone_authtoken signing_dir $SOLUM_AUTH_CACHE_DIR

    # configure the database.
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE database connection `database_connection_url solum`

    # configure the api servers to listen on
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE api host $SOLUM_SERVICE_HOST
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE api port $SOLUM_SERVICE_PORT
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE builder host $SOLUM_SERVICE_HOST
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE builder port $SOLUM_BUILDER_SERVICE_PORT

    # configure assembly handler to create appropriate image format
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE api image_format $SOLUM_IMAGE_FORMAT

    # common rpc settings
    iniset_rpc_backend solum $SOLUM_CONF_DIR/$SOLUM_CONF_FILE DEFAULT

    # service rpc settings
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE conductor topic solum-conductor
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE deployer topic solum-deployer
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE deployer handler heat
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE worker topic solum-worker
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE worker handler shell
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE worker proj_dir $SOLUM_PROJ_DIR

    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE deployer max_attempts $SOLUM_MAX_ATTEMPTS
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE deployer wait_interval $SOLUM_WAIT_INTERVAL
    iniset $SOLUM_CONF_DIR/$SOLUM_CONF_FILE deployer growth_factor $SOLUM_GROWTH_FACTOR

    # configure AllHostsFilter in /etc/nova/nova.conf
    iniset /etc/nova/nova.conf DEFAULT scheduler_default_filters AllHostsFilter

}

#register solum user in Keystone
function add_solum_user() {

    local SERVICE_TENANT=$(openstack project list | awk "/ $SERVICE_TENANT_NAME / { print \$2 }")
    echo "SERVICE_TENANT=$SERVICE_TENANT"

    # Register new service user as other services do
    SOLUM_USER_ID=$(openstack user create $SOLUM_USER \
       --password=$ADMIN_PASSWORD \
       --project $SERVICE_TENANT \
       --email=$SOLUM_USER@example.com \
       | grep " id " | get_field 2)

    local ADMIN_ROLE=$(openstack role list | awk "/ admin / { print \$2 }")
    echo "ADMIN_ROLE=$ADMIN_ROLE"

     openstack role add \
       --project $SERVICE_TENANT \
       --user $SOLUM_USER_ID \
       $ADMIN_ROLE
}

function add_additional_solum_users() {

    SOLUM_UPDATE_ROLE=$(openstack role show \
        solum_assembly_update \
        | grep " id " | get_field 2)

    ROLE_ID=$(openstack role create solum_user \
              | grep " id " | get_field 2)
    for _LETTER in a b c; do
        local TENANTNAME=solum_tenant_$_LETTER
        openstack project create \
            --description "Solum user tenant ${_LETTER^^}" \
            $TENANTNAME

        local USERNAME=solum_user_$_LETTER
        openstack user create \
            --password solum \
            --project $TENANTNAME \
            $USERNAME

        openstack role add $SOLUM_UPDATE_ROLE --project $TENANTNAME --user $USERNAME
        openstack role add $SOLUM_UPDATE_ROLE --project $TENANTNAME --user admin
    done
}

#create_solum_cache_dir() - Setup keystone signing folder
function create_solum_cache_dir() {
    sudo mkdir -p $SOLUM_AUTH_CACHE_DIR
    sudo chown $STACK_USER $SOLUM_AUTH_CACHE_DIR
    sudo chmod 700 $SOLUM_AUTH_CACHE_DIR
    rm -f $SOLUM_AUTH_CACHE_DIR/*
}

# init_solum() - Initialize databases, etc.
function init_solum() {
    recreate_database solum utf8
    # Run Solum db migrations
    solum-db-manage --config-file $SOLUM_CONF_DIR/$SOLUM_CONF_FILE upgrade head
    create_solum_cache_dir

    # NOTE (devkulkarni): Barbican is causing failures such as below
    # http://logs.openstack.org/33/206633/2/check/gate-solum-devstack-dsvm/933cbc3/logs/devstacklog.txt.gz#_2015-08-03_17_13_40_858
    # So temorarily commenting out barbican related code below.

    # if is_service_enabled barbican; then
    #    # Fix barbican configuration
    #    BARBICAN_API_CONF="/etc/barbican/barbican.conf"
    #    BARBICAN_HOST_HREF=$(iniget $BARBICAN_API_CONF DEFAULT host_href)
    #    BARBICAN_HOST_HREF=${BARBICAN_HOST_HREF/localhost/$SERVICE_HOST}
    #    iniset $BARBICAN_API_CONF DEFAULT host_href $BARBICAN_HOST_HREF
    #    if is_running barbican; then
    #        # NOTE(ravips): barbican.{pid,failure} is removed to overcome current
    #        # limitations of stop_barbican. stop_barbican calls screen_stop() only
    #        # to remove the pid but not to kill the process and this causes pkill
    #        # in screen_stop to return non-zero exit code which is trapped by
    #        # devstack/stack.sh
    #        if [ -f $SERVICE_DIR/$SCREEN_NAME/barbican.pid ]; then
    #            rm $SERVICE_DIR/$SCREEN_NAME/barbican.pid
    #        fi
    #        stop_barbican
    #        if [ -f $SERVICE_DIR/$SCREEN_NAME/barbican.failure ]; then
    #            rm $SERVICE_DIR/$SCREEN_NAME/barbican.failure
    #        fi
    #        start_barbican
    #    fi
    # fi
}

# install_solumclient() - Collect source and prepare
function install_solumclient {
    # TODO(ravips): We need this until solum gets into devstack
    ERROR_ON_CLONE=False
    git_clone $SOLUMCLIENT_REPO $SOLUMCLIENT_DIR $SOLUMCLIENT_BRANCH
    setup_develop $SOLUMCLIENT_DIR
}

# install_solum() - Collect source and prepare
function install_solum() {
    # Install package requirements
    install_package expect

    git_clone $SOLUM_REPO $SOLUM_DIR $SOLUM_BRANCH
    # When solum is re-listed in openstack/requirements/projects.txt we
    # should change setup_package back to setup_develop.
    setup_package $SOLUM_DIR -e
}

# install_drone() - Install drone, but disable service
function install_drone() {
    if [[ $SOLUM_INSTALL_DRONE == 'True' ]]; then
        if [[ $os_VENDOR != 'Ubuntu' ]]; then
            echo 'Drone is currently only supported on Ubuntu'
            exit 1
        fi
        if [[ ! -e /usr/local/bin/drone ]]; then
            wget -O /tmp/drone.deb ${SOLUM_DRONE_URL}
            sudo dpkg -i /tmp/drone.deb
            rm /tmp/drone.deb
            sudo initctl stop drone || true
            sudo rm -f /etc/init/drone.conf || true
        fi
    fi
}

# install_docker() - Install Docker
function install_docker() {
    chmod +x $SOLUM_DIR/contrib/lp-cedarish/docker/get_docker_io.sh
    sudo $SOLUM_DIR/contrib/lp-cedarish/docker/get_docker_io.sh
    solum_install_docker_registry
}

# install_lp-cedarish() - Install tooling to support cedarish LP
function install_lp-cedarish() {
    $SOLUM_DIR/contrib/lp-cedarish/docker/prepare
    install_drone
}

# install_lp-dockerfile() - Install tooling to support dockerfile LP
function install_lp-dockerfile() {
    if [[ $SOLUM_IMAGE_FORMAT == 'docker' ]]; then
        $SOLUM_DIR/contrib/lp-dockerfile/docker/prepare
        install_drone
    else
        echo does not support VMs
        exit 1
    fi
}

# install_lp-chef() - Install tooling to support chef LP
function install_lp-chef() {
    if [[ $SOLUM_IMAGE_FORMAT == 'docker' ]]; then
        $SOLUM_DIR/contrib/lp-chef/docker/prepare
        install_drone
    else
        echo does not support VMs
        exit 1
    fi
}

# start_solum() - Start running processes, including screen
function start_solum() {
    screen_it solum-api "cd $SOLUM_DIR && $SOLUM_BIN_DIR/solum-api --config-file $SOLUM_CONF_DIR/$SOLUM_CONF_FILE"
    screen_it solum-conductor "cd $SOLUM_DIR && $SOLUM_BIN_DIR/solum-conductor --config-file $SOLUM_CONF_DIR/$SOLUM_CONF_FILE"
    screen_it solum-deployer "cd $SOLUM_DIR && $SOLUM_BIN_DIR/solum-deployer --config-file $SOLUM_CONF_DIR/$SOLUM_CONF_FILE"
    screen_it solum-worker "cd $SOLUM_DIR && $SOLUM_BIN_DIR/solum-worker --config-file $SOLUM_CONF_DIR/$SOLUM_CONF_FILE"

    if [[ $SOLUM_IMAGE_FORMAT == 'vm' ]]; then
        install_docker
        solum_install_start_docker_registry
        solum_install_core_os
    fi
}

# stop_solum() - Stop running processes
function stop_solum() {
    # Kill the solum screen windows
    screen -S $SCREEN_NAME -p solum-api -X kill
    screen -S $SCREEN_NAME -p solum-conductor -X kill
    screen -S $SCREEN_NAME -p solum-deployer -X kill
    screen -S $SCREEN_NAME -p solum-worker -X kill

    if [[ $SOLUM_IMAGE_FORMAT == 'vm' ]]; then
        solum_stop_docker_registry
    fi
}

# install_docker_registry() - Install and Start Docker Registry
solum_install_start_docker_registry() {
     sudo $SOLUM_DIR/contrib/devstack/install-start-docker-reg.sh
}

solum_stop_docker_registry() {
    screen -S $SCREEN_NAME -p docker-registry -X kill
}

solum_install_core_os() {
  wget http://alpha.release.core-os.net/amd64-usr/current/coreos_production_openstack_image.img.bz2
  bunzip2 coreos_production_openstack_image.img.bz2
  glance image-create --name coreos --container-format bare --disk-format qcow2 --file coreos_production_openstack_image.img
}

# Restore xtrace
$XTRACE

# Local variables:
# mode: shell-script
# End:
