# 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_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 ]; 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-daemon
        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
        elif is_ubuntu; then
            uninstall_package libzmq1 python-zmq
        elif is_suse; then
            uninstall_package libzmq1 python-pyzmq
        else
            exit_distro_not_supported "zeromq installation"
        fi
    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-daemon
        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
        if is_fedora; then
            install_package zeromq python-zmq
        elif is_ubuntu; then
            install_package libzmq1 python-zmq
        elif is_suse; then
            install_package libzmq1 python-pyzmq
        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
    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
    elif is_service_enabled qpid; then
        iniset $file $section rpc_backend ${package}.openstack.common.rpc.impl_qpid
        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:
