# lib/marconi
# Install and start **Marconi** service

# To enable a minimal set of Marconi services, add the following to localrc:
#
#     enable_service marconi-server
#
# Dependencies:
# - functions
# - OS_AUTH_URL for auth in api
# - DEST set to the destination directory
# - SERVICE_PASSWORD, SERVICE_TENANT_NAME for auth in api
# - STACK_USER service user

# stack.sh
# ---------
# install_marconi
# configure_marconi
# init_marconi
# start_marconi
# stop_marconi
# cleanup_marconi

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


# Defaults
# --------

# Set up default directories
MARCONI_DIR=$DEST/marconi
MARCONICLIENT_DIR=$DEST/python-marconiclient
MARCONI_CONF_DIR=/etc/marconi
MARCONI_CONF=$MARCONI_CONF_DIR/marconi.conf
MARCONI_API_LOG_DIR=/var/log/marconi-api
MARCONI_AUTH_CACHE_DIR=${MARCONI_AUTH_CACHE_DIR:-/var/cache/marconi}

# Support potential entry-points console scripts
MARCONI_BIN_DIR=$(get_python_exec_prefix)

# Set up database backend
MARCONI_BACKEND=${MARCONI_BACKEND:-mongodb}


# Set Marconi repository
MARCONI_REPO=${MARCONI_REPO:-${GIT_BASE}/openstack/marconi.git}
MARCONI_BRANCH=${MARCONI_BRANCH:-master}

# Set client library repository
MARCONICLIENT_REPO=${MARCONICLIENT_REPO:-${GIT_BASE}/openstack/python-marconiclient.git}
MARCONICLIENT_BRANCH=${MARCONICLIENT_BRANCH:-master}

# Set Marconi Connection Info
MARCONI_SERVICE_HOST=${MARCONI_SERVICE_HOST:-$SERVICE_HOST}
MARCONI_SERVICE_PORT=${MARCONI_SERVICE_PORT:-8888}
MARCONI_SERVICE_PROTOCOL=${MARCONI_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}

# Tell Tempest this project is present
TEMPEST_SERVICES+=,marconi


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

# Test if any Marconi services are enabled
# is_marconi_enabled
function is_marconi_enabled {
    [[ ,${ENABLED_SERVICES} =~ ,"marconi-" ]] && return 0
    return 1
}

# cleanup_marconi() - Remove residual data files, anything left over from previous
# runs that a clean run would need to clean up
function cleanup_marconi() {
    if ! timeout $SERVICE_TIMEOUT sh -c "while ! mongo marconi --eval 'db.dropDatabase();'; do sleep 1; done"; then
        die $LINENO "Mongo DB did not start"
    fi
}

# configure_marconiclient() - Set config files, create data dirs, etc
function configure_marconiclient() {
    setup_develop $MARCONICLIENT_DIR
}

# configure_marconi() - Set config files, create data dirs, etc
function configure_marconi() {
    setup_develop $MARCONI_DIR

    [ ! -d $MARCONI_CONF_DIR ] && sudo mkdir -m 755 -p $MARCONI_CONF_DIR
    sudo chown $USER $MARCONI_CONF_DIR

    [ ! -d $MARCONI_API_LOG_DIR ] &&  sudo mkdir -m 755 -p $MARCONI_API_LOG_DIR
    sudo chown $USER $MARCONI_API_LOG_DIR

    iniset $MARCONI_CONF DEFAULT verbose True
    iniset $MARCONI_CONF 'drivers:transport:wsgi' bind $MARCONI_SERVICE_HOST

    iniset $MARCONI_CONF keystone_authtoken auth_protocol http
    iniset $MARCONI_CONF keystone_authtoken admin_user marconi
    iniset $MARCONI_CONF keystone_authtoken admin_password $SERVICE_PASSWORD
    iniset $MARCONI_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
    iniset $MARCONI_CONF keystone_authtoken signing_dir $MARCONI_AUTH_CACHE_DIR

    if [[ "$MARCONI_BACKEND" = 'mongodb' ]]; then
        iniset $MARCONI_CONF database connection mongodb://localhost:27017/marconi
        configure_mongodb
        cleanup_marconi
    fi
}

function configure_mongodb() {
    # Set nssize to 2GB. This increases the number of namespaces supported
    # # per database.
    if is_ubuntu; then
        sudo sed -i -e "
            s|[^ \t]*#[ \t]*\(nssize[ \t]*=.*\$\)|\1|
            s|^\(nssize[ \t]*=[ \t]*\).*\$|\1 2047|
        " /etc/mongodb.conf
        restart_service mongodb
    elif is_fedora; then
        sudo sed -i '/--nssize/!s/OPTIONS=\"/OPTIONS=\"--nssize 2047 /' /etc/sysconfig/mongod
        restart_service mongod
    fi
}

# init_marconi() - Initialize etc.
function init_marconi() {
    # Create cache dir
    sudo mkdir -p $MARCONI_AUTH_CACHE_DIR
    sudo chown $STACK_USER $MARCONI_AUTH_CACHE_DIR
    rm -f $MARCONI_AUTH_CACHE_DIR/*
}

# install_marconi() - Collect source and prepare
function install_marconi() {
    git_clone $MARCONI_REPO $MARCONI_DIR $MARCONI_BRANCH
    setup_develop $MARCONI_DIR
}

# install_marconiclient() - Collect source and prepare
function install_marconiclient() {
    git_clone $MARCONICLIENT_REPO $MARCONICLIENT_DIR $MARCONICLIENT_BRANCH
    setup_develop $MARCONICLIENT_DIR
}

# start_marconi() - Start running processes, including screen
function start_marconi() {
    screen_it marconi-server "marconi-server --config-file $MARCONI_CONF"
    echo "Waiting for Marconi to start..."
    if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- $MARCONI_SERVICE_PROTOCOL://$MARCONI_SERVICE_HOST:$MARCONI_SERVICE_PORT/v1/health; do sleep 1; done"; then
        die $LINENO "Marconi did not start"
    fi
}

# stop_marconi() - Stop running processes
function stop_marconi() {
    # Kill the marconi screen windows
    for serv in marconi-server; do
        screen -S $SCREEN_NAME -p $serv -X kill
    done
}

function create_marconi_accounts() {
    SERVICE_TENANT=$(openstack project list | awk "/ $SERVICE_TENANT_NAME / { print \$2 }")
    ADMIN_ROLE=$(openstack role list | awk "/ admin / { print \$2 }")

    MARCONI_USER=$(openstack user create \
        marconi \
        --password "$SERVICE_PASSWORD" \
        --project $SERVICE_TENANT \
        --email marconi@example.com \
        | grep " id " | get_field 2)
    openstack role add \
        $ADMIN_ROLE \
        --project $SERVICE_TENANT \
        --user $MARCONI_USER

    if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
        MARCONI_SERVICE=$(openstack service create \
            marconi \
            --type=queuing \
            --description="Marconi Service" \
            | grep " id " | get_field 2)
        openstack endpoint create \
            $MARCONI_SERVICE \
            --region RegionOne \
            --publicurl "$MARCONI_SERVICE_PROTOCOL://$MARCONI_SERVICE_HOST:$MARCONI_SERVICE_PORT" \
            --adminurl "$MARCONI_SERVICE_PROTOCOL://$MARCONI_SERVICE_HOST:$MARCONI_SERVICE_PORT" \
            --internalurl "$MARCONI_SERVICE_PROTOCOL://$MARCONI_SERVICE_HOST:$MARCONI_SERVICE_PORT"
    fi

}


# Restore xtrace
$XTRACE

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