#!/bin/bash
#
# lib/placement
# 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

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

# Defaults
# --------

PLACEMENT_DIR=$DEST/placement
PLACEMENT_CONF_DIR=/etc/placement
PLACEMENT_CONF=$PLACEMENT_CONF_DIR/placement.conf
PLACEMENT_AUTH_STRATEGY=${PLACEMENT_AUTH_STRATEGY:-keystone}
# Placement virtual environment
if [[ ${USE_VENV} = True ]]; then
    PROJECT_VENV["placement"]=${PLACEMENT_DIR}.venv
    PLACEMENT_BIN_DIR=${PROJECT_VENV["placement"]}/bin
else
    PLACEMENT_BIN_DIR=$(get_python_exec_prefix)
fi
PLACEMENT_UWSGI=$PLACEMENT_BIN_DIR/placement-api
PLACEMENT_UWSGI_CONF=$PLACEMENT_CONF_DIR/placement-uwsgi.ini

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}

# Flag to set the oslo_policy.enforce_scope and oslo_policy.enforce_new_defaults.
# This is used to switch the Placement API policies scope and new defaults.
# By Default, these flag are False.
# For more detail: https://docs.openstack.org/oslo.policy/latest/configuration/index.html#oslo_policy.enforce_scope
PLACEMENT_ENFORCE_SCOPE=$(trueorfalse False PLACEMENT_ENFORCE_SCOPE)

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

# Test if any placement services are enabled
# is_placement_enabled
function is_placement_enabled {
    [[ ,${ENABLED_SERVICES} =~ ,"placement-api" ]] && return 0
    return 1
}

# 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 placement-api)
    remove_uwsgi_config "$PLACEMENT_UWSGI_CONF" "placement-api"
}

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

    if [[ ${USE_VENV} = True ]]; then
        venv_path="python-path=${PROJECT_VENV["placement"]}/lib/$(python_version)/site-packages"
        placement_bin_dir=${PROJECT_VENV["placement"]}/bin
    fi

    sudo cp $FILES/apache-placement-api.template $placement_api_apache_conf
    sudo sed -e "
        s|%APACHE_NAME%|$APACHE_NAME|g;
        s|%PUBLICWSGI%|$placement_bin_dir/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
}

# create_placement_conf() - Write config
function create_placement_conf {
    rm -f $PLACEMENT_CONF
    iniset $PLACEMENT_CONF placement_database connection `database_connection_url placement`
    iniset $PLACEMENT_CONF DEFAULT debug "$ENABLE_DEBUG_LOG_LEVEL"
    iniset $PLACEMENT_CONF api auth_strategy $PLACEMENT_AUTH_STRATEGY
    configure_keystone_authtoken_middleware $PLACEMENT_CONF placement
    setup_logging $PLACEMENT_CONF
}

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

    if [[ "$WSGI_MODE" == "uwsgi" ]]; then
        write_uwsgi_config "$PLACEMENT_UWSGI_CONF" "$PLACEMENT_UWSGI" "/placement"
    else
        _config_placement_apache_wsgi
    fi
    if [[ "$PLACEMENT_ENFORCE_SCOPE" == "True" || "$ENFORCE_SCOPE" == "True" ]]; then
        iniset $PLACEMENT_CONF oslo_policy enforce_new_defaults True
        iniset $PLACEMENT_CONF oslo_policy enforce_scope True
    else
        iniset $PLACEMENT_CONF oslo_policy enforce_new_defaults False
        iniset $PLACEMENT_CONF oslo_policy enforce_scope False
    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
function init_placement {
    recreate_database placement
    $PLACEMENT_BIN_DIR/placement-manage db sync
    create_placement_accounts
}

# install_placement() - Collect source and prepare
function install_placement {
    install_apache_wsgi
    # Install the openstackclient placement client plugin for CLI
    pip_install_gr osc-placement
    git_clone $PLACEMENT_REPO $PLACEMENT_DIR $PLACEMENT_BRANCH
    setup_develop $PLACEMENT_DIR
}

# start_placement_api() - Start the API processes ahead of other things
function start_placement_api {
    if [[ "$WSGI_MODE" == "uwsgi" ]]; then
        run_process "placement-api" "$(which uwsgi) --procname-prefix placement --ini $PLACEMENT_UWSGI_CONF"
    else
        enable_apache_site placement-api
        restart_apache_server
    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_process "placement-api"
    else
        disable_apache_site placement-api
        restart_apache_server
    fi
}

# Restore xtrace
$_XTRACE_LIB_PLACEMENT

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