# 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
MARCONI_API_LOG_FILE=$MARCONI_API_LOG_DIR/queues.log
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:-sqlite}


# 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 DEFAULT use_syslog $SYSLOG
    iniset $MARCONI_CONF DEFAULT log_file $MARCONI_API_LOG_FILE
    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" = 'mysql' ] || [ "$MARCONI_BACKEND" = 'postgresql' ] ; then
        iniset $MARCONI_CONF drivers storage sqlalchemy
        iniset $MARCONI_CONF 'drivers:storage:sqlalchemy' uri `database_connection_url marconi`
    elif [ "$MARCONI_BACKEND" = 'mongodb' ] ; then
        iniset $MARCONI_CONF  drivers storage mongodb
        iniset $MARCONI_CONF 'drivers:storage:mongodb' uri 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 {
    if [[ "$USE_SCREEN" = "False" ]]; then
        screen_it marconi-server "marconi-server --config-file $MARCONI_CONF --daemon"
    else
        screen_it marconi-server "marconi-server --config-file $MARCONI_CONF"
    fi

    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:
