# lib/horizon
# Functions to control the configuration and operation of the horizon service

# Dependencies:
#
# - ``functions`` file
# - ``apache`` file
# - ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined

# ``stack.sh`` calls the entry points in this order:
#
# - install_horizon
# - configure_horizon
# - init_horizon
# - start_horizon
# - stop_horizon
# - cleanup_horizon

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


# Defaults
# --------

# Set up default directories
GITDIR["django_openstack_auth"]=$DEST/django_openstack_auth

HORIZON_DIR=$DEST/horizon

# local_settings.py is used to customize Dashboard settings.
# The example file in Horizon repo is used by default.
HORIZON_SETTINGS=${HORIZON_SETTINGS:-$HORIZON_DIR/openstack_dashboard/local/local_settings.py.example}

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


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

# utility method of setting python option
function _horizon_config_set {
    local file=$1
    local section=$2
    local option=$3
    local value=$4

    if [ -z "$section" ]; then
        sed -e "/^$option/d" -i $local_settings
        echo -e "\n$option=$value" >> $file
    elif grep -q "^$section" $file; then
        local line=$(sed -ne "/^$section/,/^}/ { /^ *'$option':/ p; }" $file)
        if [ -n "$line" ]; then
            sed -i -e "/^$section/,/^}/ s/^\( *'$option'\) *:.*$/\1: $value,/" $file
        else
            sed -i -e "/^$section/a\    '$option': $value," $file
        fi
    else
        echo -e "\n\n$section = {\n    '$option': $value,\n}" >> $file
    fi
}



# Entry Points
# ------------

# cleanup_horizon() - Remove residual data files, anything left over from previous
# runs that a clean run would need to clean up
function cleanup_horizon {
    if [[ is_fedora && $DISTRO =~ (rhel6) ]]; then
        # If ``/usr/bin/node`` points into ``$DEST``
        # we installed it via ``install_nodejs``
        if [[ $(readlink -f /usr/bin/node) =~ ($DEST) ]]; then
            sudo rm /usr/bin/node
        fi
    fi

    local horizon_conf=$(apache_site_config_for horizon)
    sudo rm -f $horizon_conf
}

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

    # Compile message catalogs.
    # Horizon is installed as develop mode, so we can compile here.
    # Message catalog compilation is handled by Django admin script,
    # so compiling them after the installation avoids Django installation twice.
    (cd $HORIZON_DIR; ./run_tests.sh -N --compilemessages)
}

# init_horizon() - Initialize databases, etc.
function init_horizon {
    # ``local_settings.py`` is used to override horizon default settings.
    local local_settings=$HORIZON_DIR/openstack_dashboard/local/local_settings.py
    cp $HORIZON_SETTINGS $local_settings

    _horizon_config_set $local_settings "" COMPRESS_OFFLINE True

    _horizon_config_set $local_settings "" OPENSTACK_HOST \"${KEYSTONE_SERVICE_HOST}\"
    _horizon_config_set $local_settings "" OPENSTACK_KEYSTONE_URL "\"${KEYSTONE_SERVICE_PROTOCOL}://${KEYSTONE_SERVICE_HOST}:${KEYSTONE_SERVICE_PORT}/v2.0\""
    if [[ -n "$KEYSTONE_TOKEN_HASH_ALGORITHM" ]]; then
        _horizon_config_set $local_settings "" OPENSTACK_TOKEN_HASH_ALGORITHM \""$KEYSTONE_TOKEN_HASH_ALGORITHM"\"
    fi

    if [ -f $SSL_BUNDLE_FILE ]; then
        _horizon_config_set $local_settings "" OPENSTACK_SSL_CACERT \"${SSL_BUNDLE_FILE}\"
    fi

    # Create an empty directory that apache uses as docroot
    sudo mkdir -p $HORIZON_DIR/.blackhole

    local horizon_conf=$(apache_site_config_for horizon)

    # Configure apache to run horizon
    sudo sh -c "sed -e \"
        s,%USER%,$APACHE_USER,g;
        s,%GROUP%,$APACHE_GROUP,g;
        s,%HORIZON_DIR%,$HORIZON_DIR,g;
        s,%APACHE_NAME%,$APACHE_NAME,g;
        s,%DEST%,$DEST,g;
    \" $FILES/apache-horizon.template >$horizon_conf"

    if is_ubuntu; then
        disable_apache_site 000-default
        sudo touch $horizon_conf
    elif is_fedora; then
        sudo sed '/^Listen/s/^.*$/Listen 0.0.0.0:80/' -i /etc/httpd/conf/httpd.conf
    elif is_suse; then
        : # nothing to do
    else
        exit_distro_not_supported "horizon apache configuration"
    fi
    enable_apache_site horizon

    # Remove old log files that could mess with how devstack detects whether Horizon
    # has been successfully started (see start_horizon() and functions::screen_it())
    # and run_process
    sudo rm -f /var/log/$APACHE_NAME/horizon_*

    # Setup alias for django-admin which could be different depending on distro
    local django_admin
    if type -p django-admin > /dev/null; then
        django_admin=django-admin
    else
        django_admin=django-admin.py
    fi

    DJANGO_SETTINGS_MODULE=openstack_dashboard.settings $django_admin collectstatic --noinput
    DJANGO_SETTINGS_MODULE=openstack_dashboard.settings $django_admin compress --force

}

# install_django_openstack_auth() - Collect source and prepare
function install_django_openstack_auth {
    if use_library_from_git "django_openstack_auth"; then
        local dir=${GITDIR["django_openstack_auth"]}
        git_clone_by_name "django_openstack_auth"
        # Compile message catalogs before installation
        _prepare_message_catalog_compilation
        (cd $dir; python setup.py compile_catalog)
        setup_dev_lib "django_openstack_auth"
    fi
    # if we aren't using this library from git, then we just let it
    # get dragged in by the horizon setup.
}

# install_horizon() - Collect source and prepare
function install_horizon {
    # Apache installation, because we mark it NOPRIME
    install_apache_wsgi

    git_clone $HORIZON_REPO $HORIZON_DIR $HORIZON_BRANCH $HORIZON_TAG
}

# start_horizon() - Start running processes, including screen
function start_horizon {
    restart_apache_server
    tail_log horizon /var/log/$APACHE_NAME/horizon_error.log
}

# stop_horizon() - Stop running processes (non-screen)
function stop_horizon {
    stop_apache_server
}

# NOTE: It can be moved to common functions, but it is only used by compilation
# of django_openstack_auth catalogs at the moment.
function _prepare_message_catalog_compilation {
    local babel_package=$(grep ^Babel $REQUIREMENTS_DIR/global-requirements.txt)
    pip_install "$babel_package"
}


# Restore xtrace
$XTRACE

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