#!/bin/bash
#
# Functions to control the configuration and operation of the **Placement** service

# Dependencies:
#
# - ``functions`` file
# - ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined
# - ``FILES``

# ``stack.sh`` calls the entry points in this order:
#
# - install_placement
# - cleanup_placement
# - configure_placement
# - init_placement
# - start_placement
# - stop_placement

# Defaults
# --------

PLACEMENT_REPO=${PLACEMENT_REPO:-${GIT_BASE}/openstack/nova.git}
PLACEMENT_BRANCH=${PLACEMENT_BRANCH:-master}
PLACEMENT_DIR=$DEST/nova

PLACEMENT_CONF_DIR=/etc/nova
PLACEMENT_CONF=$PLACEMENT_CONF_DIR/nova.conf
PLACEMENT_AUTH_STRATEGY=${PLACEMENT_AUTH_STRATEGY:-placement}
PLACEMENT_BIN_DIR=$(get_python_exec_prefix)
PLACEMENT_UWSGI=$PLACEMENT_BIN_DIR/nova-placement-api
PLACEMENT_UWSGI_CONF=$PLACEMENT_CONF_DIR/placement-uwsgi.ini

# The placement service can optionally use a separate database
# connection. Set PLACEMENT_DB_ENABLED to True to use it.
# NOTE(cdent): This functionality depends on some code that is not
# yet merged in nova but is coming soon.
PLACEMENT_DB_ENABLED=$(trueorfalse False PLACEMENT_DB_ENABLED)

if is_service_enabled tls-proxy; then
    PLACEMENT_SERVICE_PROTOCOL="https"
fi

# Public facing bits
PLACEMENT_SERVICE_PROTOCOL=${PLACEMENT_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
PLACEMENT_SERVICE_HOST=${PLACEMENT_SERVICE_HOST:-$SERVICE_HOST}

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

# cleanup_placement() - Remove residual data files, anything left over from previous
# runs that a clean run would need to clean up
function cleanup_placement {
    sudo rm -f $(apache_site_config_for nova-placement-api)
    sudo rm -f $(apache_site_config_for placement-api)
}

# _config_placement_apache_wsgi() - Set WSGI config files
function _config_placement_apache_wsgi {
    local placement_api_apache_conf
    local venv_path=""
    local nova_bin_dir=""
    nova_bin_dir=$(get_python_exec_prefix)
    placement_api_apache_conf=$(apache_site_config_for placement-api)

    sudo cp $FILES/apache-placement-api.template $placement_api_apache_conf
    sudo sed -e "
        s|%APACHE_NAME%|$APACHE_NAME|g;
        s|%PUBLICWSGI%|$nova_bin_dir/nova-placement-api|g;
        s|%SSLENGINE%|$placement_ssl|g;
        s|%SSLCERTFILE%|$placement_certfile|g;
        s|%SSLKEYFILE%|$placement_keyfile|g;
        s|%USER%|$STACK_USER|g;
        s|%VIRTUALENV%|$venv_path|g
        s|%APIWORKERS%|$API_WORKERS|g
    " -i $placement_api_apache_conf
}

# configure_placement() - Set config files, create data dirs, etc
function configure_placement {
    sudo install -d -o $STACK_USER $PLACEMENT_CONF_DIR

    if [ "$PLACEMENT_DB_ENABLED" != False ]; then
        iniset $PLACEMENT_CONF placement_database connection `database_connection_url placement`
    else
        iniset $PLACEMENT_CONF api_database connection `database_connection_url nova_api`
    fi

    # Setup keystone_authtoken section
    iniset ${PLACEMENT_CONF} keystone_authtoken auth_uri ${KEYSTONE_SERVICE_URI}
    iniset ${PLACEMENT_CONF} keystone_authtoken project_domain_name ${SERVICE_DOMAIN_NAME}
    iniset ${PLACEMENT_CONF} keystone_authtoken project_name ${SERVICE_PROJECT_NAME}
    iniset ${PLACEMENT_CONF} keystone_authtoken user_domain_name ${SERVICE_DOMAIN_NAME}
    iniset ${PLACEMENT_CONF} keystone_authtoken username "placement"
    iniset ${PLACEMENT_CONF} keystone_authtoken password ${SERVICE_PASSWORD}
    iniset ${PLACEMENT_CONF} keystone_authtoken auth_url ${KEYSTONE_AUTH_URI}
    iniset ${PLACEMENT_CONF} keystone_authtoken auth_type "password"

    if [[ "$WSGI_MODE" == "uwsgi" ]]; then
        write_uwsgi_config "$PLACEMENT_UWSGI_CONF" "$PLACEMENT_UWSGI" "/placement"
    else
        _config_placement_apache_wsgi
    fi
}

# create_placement_accounts() - Set up required placement accounts
# and service and endpoints.
function create_placement_accounts {
    create_service_user "placement" "admin"
    local placement_api_url="$PLACEMENT_SERVICE_PROTOCOL://$PLACEMENT_SERVICE_HOST/placement"
    get_or_create_service "placement" "placement" "Placement Service"
    get_or_create_endpoint \
        "placement" \
        "$REGION_NAME" \
        "$placement_api_url"
}

# init_placement() - Create service user and endpoints
# If PLACEMENT_DB_ENABLED is true, create the separate placement db
# using, for now, the api_db migrations.
function init_placement {
    if [ "$PLACEMENT_DB_ENABLED" != False ]; then
        recreate_database placement
        time_start "dbsync"
        $MOGAN_BIN_DIR/nova-manage --config-file $PLACEMENT_CONF placement sync
        time_stop "dbsync"
    else
        recreate_database $NOVA_API_DB
        time_start "dbsync"
        $MOGAN_BIN_DIR/nova-manage --config-file $PLACEMENT_CONF api_db sync
        time_stop "dbsync"
    fi
    create_placement_accounts
}

# install_placement() - Collect source and prepare
function install_placement {
    git_clone ${PLACEMENT_REPO} ${PLACEMENT_DIR} ${PLACEMENT_BRANCH}
    setup_develop ${PLACEMENT_DIR}
    install_apache_wsgi
}

# devstack run_process will only run enabled services, so before placement
# is started as a separated service, we call our own run process.
function run_placement_process {
    local service=$1
    local command="$2"
    local group=$3
    local user=$4

    local name=$service

    time_start "run_process"
    if [[ "$USE_SYSTEMD" = "True" ]]; then
        _run_under_systemd "$name" "$command" "$group" "$user"
    elif [[ "$USE_SCREEN" = "True" ]]; then
        if [[ "$user" == "root" ]]; then
            command="sudo $command"
        fi
        screen_process "$name" "$command" "$group"
    else
        # Spawn directly without screen
        if [[ "$user" == "root" ]]; then
            command="sudo $command"
        fi
        _run_process "$name" "$command" "$group" &
    fi
    time_stop "run_process"
}

# stop_placement_process service
function stop_placement_process {
    local service=$1

    SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}

    if $SYSTEMCTL is-enabled devstack@$service.service; then
        $SYSTEMCTL stop devstack@$service.service
        $SYSTEMCTL disable devstack@$service.service
    fi

    if [[ -r $SERVICE_DIR/$SCREEN_NAME/$service.pid ]]; then
        pkill -g $(cat $SERVICE_DIR/$SCREEN_NAME/$service.pid)
        # oslo.service tends to stop actually shutting down
        # reliably in between releases because someone believes it
        # is dying too early due to some inflight work they
        # have. This is a tension. It happens often enough we're
        # going to just account for it in devstack and assume it
        # doesn't work.
        #
        # Set OSLO_SERVICE_WORKS=True to skip this block
        if [[ -z "$OSLO_SERVICE_WORKS" ]]; then
            # TODO(danms): Remove this double-kill when we have
            # this fixed in all services:
            # https://bugs.launchpad.net/oslo-incubator/+bug/1446583
            sleep 1
            # /bin/true because pkill on a non existent process returns an error
            pkill -g $(cat $SERVICE_DIR/$SCREEN_NAME/$service.pid) || /bin/true
        fi
        rm $SERVICE_DIR/$SCREEN_NAME/$service.pid
    fi
    if [[ "$USE_SCREEN" = "True" ]]; then
        # Clean up the screen window
        screen_stop_service $service
    fi
}

# start_placement_api() - Start the API processes ahead of other things
function start_placement_api {
    if [[ "$WSGI_MODE" == "uwsgi" ]]; then
        run_placement_process "placement-api" "$PLACEMENT_BIN_DIR/uwsgi --ini $PLACEMENT_UWSGI_CONF"
    else
        enable_apache_site placement-api
        restart_apache_server
        tail_log placement-api /var/log/$APACHE_NAME/placement-api.log
    fi

    echo "Waiting for placement-api to start..."
    if ! wait_for_service $SERVICE_TIMEOUT $PLACEMENT_SERVICE_PROTOCOL://$PLACEMENT_SERVICE_HOST/placement; then
        die $LINENO "placement-api did not start"
    fi
}

function start_placement {
    start_placement_api
}

# stop_placement() - Disable the api service and stop it.
function stop_placement {
    if [[ "$WSGI_MODE" == "uwsgi" ]]; then
        stop_placement_process "placement-api"
        remove_uwsgi_config "$PLACEMENT_UWSGI_CONF" "$PLACEMENT_UWSGI"
    else
        disable_apache_site placement-api
        restart_apache_server
    fi
}

# Tell emacs to use shell-script-mode
## Local variables:
## mode: shell-script
## End:
