# 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
        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
            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
        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
        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
    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:
