# lib/rpc_backend
# Interface for interactig with different rpc backend
# rpc backend settings

# Dependencies:
# ``functions`` file
# ``RABBIT_{HOST|PASSWORD}`` must be defined when RabbitMQ is used

# ``stack.sh`` calls the entry points in this order:
#
# check_rpc_backend
# install_rpc_backend
# restart_rpc_backend
# iniset_rpc_backend

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


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


# Make sure we only have one rpc backend enabled.
# Also check the specified rpc backend is available on your platform.
function check_rpc_backend() {
    local rpc_needed=1
    # We rely on the fact that filenames in lib/* match the service names
    # that can be passed as arguments to is_service_enabled.
    # We check for a call to iniset_rpc_backend in these files, meaning
    # the service needs a backend.
    rpc_candidates=$(grep -rl iniset_rpc_backend $TOP_DIR/lib/ | awk -F/ '{print $NF}')
    for c in ${rpc_candidates}; do
        if is_service_enabled $c; then
            rpc_needed=0
            break
        fi
    done
    local rpc_backend_cnt=0
    for svc in qpid zeromq rabbit; do
        is_service_enabled $svc &&
        ((rpc_backend_cnt++))
    done
    if [ "$rpc_backend_cnt" -gt 1 ]; then
        echo "ERROR: only one rpc backend may be enabled,"
        echo "       set only one of 'rabbit', 'qpid', 'zeromq'"
        echo "       via ENABLED_SERVICES."
    elif [ "$rpc_backend_cnt" == 0 ] && [ "$rpc_needed" == 0 ]; then
        echo "ERROR: at least one rpc backend must be enabled,"
        echo "       set one of 'rabbit', 'qpid', 'zeromq'"
        echo "       via ENABLED_SERVICES."
    fi

    if is_service_enabled qpid && ! qpid_is_supported; then
        die $LINENO "Qpid support is not available for this version of your distribution."
    fi
}

# clean up after rpc backend - eradicate all traces so changing backends
# produces a clean switch
function cleanup_rpc_backend {
    if is_service_enabled rabbit; then
        # Obliterate rabbitmq-server
        uninstall_package rabbitmq-server
        sudo killall epmd
        if is_ubuntu; then
            # And the Erlang runtime too
            sudo aptitude purge -y ~nerlang
        fi
    elif is_service_enabled qpid; then
        if is_fedora; then
            uninstall_package qpid-cpp-server
        elif is_ubuntu; then
            uninstall_package qpidd
        else
            exit_distro_not_supported "qpid installation"
        fi
    elif is_service_enabled zeromq; then
        if is_fedora; then
            uninstall_package zeromq python-zmq redis
        elif is_ubuntu; then
            uninstall_package libzmq1 python-zmq redis-server
        elif is_suse; then
            uninstall_package libzmq1 python-pyzmq redis
        else
            exit_distro_not_supported "zeromq installation"
        fi

        # Necessary directory for socket location.
        sudo mkdir -p /var/run/openstack
        sudo chown $STACK_USER /var/run/openstack
    fi
}

# install rpc backend
function install_rpc_backend() {
    if is_service_enabled rabbit; then
        # Install rabbitmq-server
        # the temp file is necessary due to LP: #878600
        tfile=$(mktemp)
        install_package rabbitmq-server > "$tfile" 2>&1
        cat "$tfile"
        rm -f "$tfile"
    elif is_service_enabled qpid; then
        if is_fedora; then
            install_package qpid-cpp-server
            if [[ $DISTRO =~ (rhel6) ]]; then
               # RHEL6 leaves "auth=yes" in /etc/qpidd.conf, it needs to
               # be no or you get GSS authentication errors as it
               # attempts to default to this.
                sudo sed -i.bak 's/^auth=yes$/auth=no/' /etc/qpidd.conf
            fi
        elif is_ubuntu; then
            install_package qpidd
            sudo sed -i '/PLAIN/!s/mech_list: /mech_list: PLAIN /' /etc/sasl2/qpidd.conf
            sudo chmod o+r /etc/qpid/qpidd.sasldb
        else
            exit_distro_not_supported "qpid installation"
        fi
    elif is_service_enabled zeromq; then
        # NOTE(ewindisch): Redis is not strictly necessary
        # but there is a matchmaker driver that works
        # really well & out of the box for multi-node.
        if is_fedora; then
            install_package zeromq python-zmq redis
        elif is_ubuntu; then
            install_package libzmq1 python-zmq redis-server
        elif is_suse; then
            install_package libzmq1 python-pyzmq redis
        else
            exit_distro_not_supported "zeromq installation"
        fi
    fi
}

# restart the rpc backend
function restart_rpc_backend() {
    if is_service_enabled rabbit; then
        # Start rabbitmq-server
        echo_summary "Starting RabbitMQ"
        if is_fedora || is_suse; then
            # service is not started by default
            restart_service rabbitmq-server
        fi
        # change the rabbit password since the default is "guest"
        sudo rabbitmqctl change_password guest $RABBIT_PASSWORD
        if is_service_enabled n-cell; then
            # Add partitioned access for the child cell
            if [ -z `sudo rabbitmqctl list_vhosts | grep child_cell` ]; then
                sudo rabbitmqctl add_vhost child_cell
                sudo rabbitmqctl set_permissions -p child_cell guest ".*" ".*" ".*"
            fi
        fi
    elif is_service_enabled qpid; then
        echo_summary "Starting qpid"
        restart_service qpidd
    fi
}

# iniset cofiguration
function iniset_rpc_backend() {
    local package=$1
    local file=$2
    local section=$3
    if is_service_enabled zeromq; then
        iniset $file $section rpc_backend ${package}.openstack.common.rpc.impl_zmq
        iniset $file $section rpc_zmq_matchmaker \
            ${package}.openstack.common.rpc.matchmaker_redis.MatchMakerRedis
        # Set MATCHMAKER_REDIS_HOST if running multi-node.
        MATCHMAKER_REDIS_HOST=${MATCHMAKER_REDIS_HOST:-127.0.0.1}
        iniset $file matchmaker_redis host $MATCHMAKER_REDIS_HOST
    elif is_service_enabled qpid || [ -n "$QPID_HOST" ]; then
        iniset $file $section rpc_backend ${package}.openstack.common.rpc.impl_qpid
        iniset $file $section qpid_hostname ${QPID_HOST:-$SERVICE_HOST}
        if is_ubuntu; then
            QPID_PASSWORD=`sudo strings /etc/qpid/qpidd.sasldb | grep -B1 admin | head -1`
            iniset $file $section qpid_password $QPID_PASSWORD
            iniset $file $section qpid_username admin
        fi
    elif is_service_enabled rabbit || { [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; }; then
        iniset $file $section rpc_backend ${package}.openstack.common.rpc.impl_kombu
        iniset $file $section rabbit_host $RABBIT_HOST
        iniset $file $section rabbit_password $RABBIT_PASSWORD
    fi
}

# Check if qpid can be used on the current distro.
# qpid_is_supported
function qpid_is_supported() {
    if [[ -z "$DISTRO" ]]; then
        GetDistro
    fi

    # Qpid was introduced to Ubuntu in precise, disallow it on oneiric; it is
    # not in openSUSE either right now.
    ( ! ([[ "$DISTRO" = "oneiric" ]] || is_suse) )
}


# Restore xtrace
$XTRACE

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