For testing we can need to disable or change the rate of the heartbeat Currently we have to set the value manually in each componments or to write multiple [[post-config|$<APP>_CONF]] section in local.conf. This change will allow to configure all componments at once with only two lines. Also, we don't set default values to continue to use oslo.messaging defaults. Change-Id: Ieaca60ca1cd6d7455b66ce490a9b023df431e9c3
		
			
				
	
	
		
			397 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			397 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
#!/bin/bash
 | 
						|
#
 | 
						|
# lib/rpc_backend
 | 
						|
# Interface for interactig with different RPC backends
 | 
						|
 | 
						|
# Dependencies:
 | 
						|
#
 | 
						|
# - ``functions`` file
 | 
						|
# - ``RABBIT_{HOST|PASSWORD|USERID}`` must be defined when RabbitMQ is used
 | 
						|
# - ``RPC_MESSAGING_PROTOCOL`` option for configuring the messaging protocol
 | 
						|
 | 
						|
# ``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
 | 
						|
 | 
						|
RPC_MESSAGING_PROTOCOL=${RPC_MESSAGING_PROTOCOL:-0.9}
 | 
						|
 | 
						|
# TODO(sdague): RPC backend selection is super wonky because we treat
 | 
						|
# messaging server as a service, which it really isn't for multi host
 | 
						|
QPID_HOST=${QPID_HOST:-}
 | 
						|
 | 
						|
 | 
						|
# 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 c svc
 | 
						|
 | 
						|
    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++ )) || true
 | 
						|
    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
 | 
						|
        # in case it's not actually running, /bin/true at the end
 | 
						|
        sudo killall epmd || sudo killall -9 epmd || /bin/true
 | 
						|
        if is_ubuntu; then
 | 
						|
            # And the Erlang runtime too
 | 
						|
            apt_get purge -y erlang*
 | 
						|
        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
 | 
						|
            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
 | 
						|
                uninstall_package redis python-redis
 | 
						|
            fi
 | 
						|
        elif is_ubuntu; then
 | 
						|
            uninstall_package libzmq1 python-zmq
 | 
						|
            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
 | 
						|
                uninstall_package redis-server python-redis
 | 
						|
            fi
 | 
						|
        elif is_suse; then
 | 
						|
            uninstall_package libzmq1 python-pyzmq
 | 
						|
            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
 | 
						|
                uninstall_package redis python-redis
 | 
						|
            fi
 | 
						|
        else
 | 
						|
            exit_distro_not_supported "zeromq installation"
 | 
						|
        fi
 | 
						|
    fi
 | 
						|
 | 
						|
    # Remove the AMQP 1.0 messaging libraries
 | 
						|
    if [ "$RPC_MESSAGING_PROTOCOL" == "AMQP1" ]; then
 | 
						|
        if is_fedora; then
 | 
						|
            uninstall_package qpid-proton-c-devel
 | 
						|
            uninstall_package python-qpid-proton
 | 
						|
        fi
 | 
						|
        # TODO(kgiusti) ubuntu cleanup
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# install rpc backend
 | 
						|
function install_rpc_backend {
 | 
						|
    # Regardless of the broker used, if AMQP 1.0 is configured load
 | 
						|
    # the necessary messaging client libraries for oslo.messaging
 | 
						|
    if [ "$RPC_MESSAGING_PROTOCOL" == "AMQP1" ]; then
 | 
						|
        if is_fedora; then
 | 
						|
            install_package qpid-proton-c-devel
 | 
						|
            install_package python-qpid-proton
 | 
						|
        elif is_ubuntu; then
 | 
						|
            # TODO(kgiusti) The QPID AMQP 1.0 protocol libraries
 | 
						|
            # are not yet in the ubuntu repos. Enable these installs
 | 
						|
            # once they are present:
 | 
						|
            #install_package libqpid-proton2-dev
 | 
						|
            #install_package python-qpid-proton
 | 
						|
            # Also add 'uninstall' directives in cleanup_rpc_backend()!
 | 
						|
            exit_distro_not_supported "QPID AMQP 1.0 Proton libraries"
 | 
						|
        else
 | 
						|
            exit_distro_not_supported "QPID AMQP 1.0 Proton libraries"
 | 
						|
        fi
 | 
						|
        # Install pyngus client API
 | 
						|
        # TODO(kgiusti) can remove once python qpid bindings are
 | 
						|
        # available on all supported platforms _and_ pyngus is added
 | 
						|
        # to the requirements.txt file in oslo.messaging
 | 
						|
        pip_install_gr pyngus
 | 
						|
    fi
 | 
						|
 | 
						|
    if is_service_enabled rabbit; then
 | 
						|
        # Install rabbitmq-server
 | 
						|
        install_package rabbitmq-server
 | 
						|
    elif is_service_enabled qpid; then
 | 
						|
        if is_fedora; then
 | 
						|
            install_package qpid-cpp-server
 | 
						|
        elif is_ubuntu; then
 | 
						|
            install_package qpidd
 | 
						|
        else
 | 
						|
            exit_distro_not_supported "qpid installation"
 | 
						|
        fi
 | 
						|
        _configure_qpid
 | 
						|
    elif is_service_enabled zeromq; then
 | 
						|
        if is_fedora; then
 | 
						|
            install_package zeromq python-zmq
 | 
						|
            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
 | 
						|
                install_package redis python-redis
 | 
						|
            fi
 | 
						|
        elif is_ubuntu; then
 | 
						|
            install_package libzmq1 python-zmq
 | 
						|
            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
 | 
						|
                install_package redis-server python-redis
 | 
						|
            fi
 | 
						|
        elif is_suse; then
 | 
						|
            install_package libzmq1 python-pyzmq
 | 
						|
            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
 | 
						|
                install_package redis python-redis
 | 
						|
            fi
 | 
						|
        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
 | 
						|
 | 
						|
    # If using the QPID broker, install the QPID python client API
 | 
						|
    if is_service_enabled qpid || [ -n "$QPID_HOST" ]; then
 | 
						|
        install_package python-qpid
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# restart the rpc backend
 | 
						|
function restart_rpc_backend {
 | 
						|
    if is_service_enabled rabbit; then
 | 
						|
        # Start rabbitmq-server
 | 
						|
        echo_summary "Starting RabbitMQ"
 | 
						|
        # NOTE(bnemec): Retry initial rabbitmq configuration to deal with
 | 
						|
        # the fact that sometimes it fails to start properly.
 | 
						|
        # Reference: https://bugzilla.redhat.com/show_bug.cgi?id=1144100
 | 
						|
        local i
 | 
						|
        for i in `seq 10`; do
 | 
						|
            local rc=0
 | 
						|
 | 
						|
            [[ $i -eq "10" ]] && die $LINENO "Failed to set rabbitmq password"
 | 
						|
 | 
						|
            if is_fedora || is_suse; then
 | 
						|
                # service is not started by default
 | 
						|
                restart_service rabbitmq-server
 | 
						|
            fi
 | 
						|
 | 
						|
            rabbit_setuser "$RABBIT_USERID" "$RABBIT_PASSWORD" || rc=$?
 | 
						|
            if [ $rc -ne 0 ]; then
 | 
						|
                continue
 | 
						|
            fi
 | 
						|
 | 
						|
            # change the rabbit password since the default is "guest"
 | 
						|
            sudo rabbitmqctl change_password \
 | 
						|
                $RABBIT_USERID $RABBIT_PASSWORD || rc=$?
 | 
						|
            if [ $rc -ne 0 ]; then
 | 
						|
                continue;
 | 
						|
            fi
 | 
						|
 | 
						|
            break
 | 
						|
        done
 | 
						|
        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 $RABBIT_USERID ".*" ".*" ".*"
 | 
						|
            fi
 | 
						|
        fi
 | 
						|
    elif is_service_enabled qpid; then
 | 
						|
        echo_summary "Starting qpid"
 | 
						|
        restart_service qpidd
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# builds transport url string
 | 
						|
function get_transport_url {
 | 
						|
    if is_service_enabled qpid || [ -n "$QPID_HOST" ]; then
 | 
						|
        echo "qpid://$QPID_USERNAME:$QPID_PASSWORD@$QPID_HOST:5672/"
 | 
						|
    elif is_service_enabled rabbit || { [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; }; then
 | 
						|
        echo "rabbit://$RABBIT_USERID:$RABBIT_PASSWORD@$RABBIT_HOST:5672/"
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# iniset cofiguration
 | 
						|
function iniset_rpc_backend {
 | 
						|
    local package=$1
 | 
						|
    local file=$2
 | 
						|
    local section=${3:-DEFAULT}
 | 
						|
    if is_service_enabled zeromq; then
 | 
						|
        iniset $file $section rpc_backend "zmq"
 | 
						|
        iniset $file $section rpc_zmq_host `hostname`
 | 
						|
        if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
 | 
						|
            iniset $file $section rpc_zmq_matchmaker "redis"
 | 
						|
            MATCHMAKER_REDIS_HOST=${MATCHMAKER_REDIS_HOST:-127.0.0.1}
 | 
						|
            iniset $file matchmaker_redis host $MATCHMAKER_REDIS_HOST
 | 
						|
        else
 | 
						|
            die $LINENO "Other matchmaker drivers not supported"
 | 
						|
        fi
 | 
						|
    elif is_service_enabled qpid || [ -n "$QPID_HOST" ]; then
 | 
						|
        # For Qpid use the 'amqp' oslo.messaging transport when AMQP 1.0 is used
 | 
						|
        if [ "$RPC_MESSAGING_PROTOCOL" == "AMQP1" ]; then
 | 
						|
            iniset $file $section rpc_backend "amqp"
 | 
						|
        else
 | 
						|
            iniset $file $section rpc_backend "qpid"
 | 
						|
        fi
 | 
						|
        iniset $file $section qpid_hostname ${QPID_HOST:-$SERVICE_HOST}
 | 
						|
        if [ -n "$QPID_USERNAME" ]; then
 | 
						|
            iniset $file $section qpid_username $QPID_USERNAME
 | 
						|
            iniset $file $section qpid_password $QPID_PASSWORD
 | 
						|
        fi
 | 
						|
    elif is_service_enabled rabbit || { [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; }; then
 | 
						|
        iniset $file $section rpc_backend "rabbit"
 | 
						|
        iniset $file oslo_messaging_rabbit rabbit_hosts $RABBIT_HOST
 | 
						|
        iniset $file oslo_messaging_rabbit rabbit_password $RABBIT_PASSWORD
 | 
						|
        iniset $file oslo_messaging_rabbit rabbit_userid $RABBIT_USERID
 | 
						|
        if [ -n "$RABBIT_HEARTBEAT_TIMEOUT_THRESHOLD" ]; then
 | 
						|
            iniset $file oslo_messaging_rabbit heartbeat_timeout_threshold $RABBIT_HEARTBEAT_TIMEOUT_THRESHOLD
 | 
						|
        fi
 | 
						|
        if [ -n "$RABBIT_HEARTBEAT_RATE" ]; then
 | 
						|
            iniset $file oslo_messaging_rabbit heartbeat_rate $RABBIT_HEARTBEAT_RATE
 | 
						|
        fi
 | 
						|
    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 is not in openSUSE
 | 
						|
    ( ! is_suse )
 | 
						|
}
 | 
						|
 | 
						|
function rabbit_setuser {
 | 
						|
    local user="$1" pass="$2" found="" out=""
 | 
						|
    out=$(sudo rabbitmqctl list_users) ||
 | 
						|
        { echo "failed to list users" 1>&2; return 1; }
 | 
						|
    found=$(echo "$out" | awk '$1 == user { print $1 }' "user=$user")
 | 
						|
    if [ "$found" = "$user" ]; then
 | 
						|
        sudo rabbitmqctl change_password "$user" "$pass" ||
 | 
						|
            { echo "failed changing pass for '$user'" 1>&2; return 1; }
 | 
						|
    else
 | 
						|
        sudo rabbitmqctl add_user "$user" "$pass" ||
 | 
						|
            { echo "failed changing pass for $user"; return 1; }
 | 
						|
    fi
 | 
						|
    sudo rabbitmqctl set_permissions "$user" ".*" ".*" ".*"
 | 
						|
}
 | 
						|
 | 
						|
# Set up the various configuration files used by the qpidd broker
 | 
						|
function _configure_qpid {
 | 
						|
 | 
						|
    # the location of the configuration files have changed since qpidd 0.14
 | 
						|
    local qpid_conf_file
 | 
						|
    if [ -e /etc/qpid/qpidd.conf ]; then
 | 
						|
        qpid_conf_file=/etc/qpid/qpidd.conf
 | 
						|
    elif [ -e /etc/qpidd.conf ]; then
 | 
						|
        qpid_conf_file=/etc/qpidd.conf
 | 
						|
    else
 | 
						|
        exit_distro_not_supported "qpidd.conf file not found!"
 | 
						|
    fi
 | 
						|
 | 
						|
    # force the ACL file to a known location
 | 
						|
    local qpid_acl_file=/etc/qpid/qpidd.acl
 | 
						|
    if [ ! -e $qpid_acl_file ]; then
 | 
						|
        sudo mkdir -p -m 755 `dirname $qpid_acl_file`
 | 
						|
        sudo touch $qpid_acl_file
 | 
						|
        sudo chmod o+r $qpid_acl_file
 | 
						|
    fi
 | 
						|
    sudo sed -i.bak '/^acl-file=/d' $qpid_conf_file
 | 
						|
    echo "acl-file=$qpid_acl_file" | sudo tee --append $qpid_conf_file
 | 
						|
 | 
						|
    sudo sed -i '/^auth=/d' $qpid_conf_file
 | 
						|
    if [ -z "$QPID_USERNAME" ]; then
 | 
						|
        # no QPID user configured, so disable authentication
 | 
						|
        # and access control
 | 
						|
        echo "auth=no" | sudo tee --append $qpid_conf_file
 | 
						|
        cat <<EOF | sudo tee $qpid_acl_file
 | 
						|
acl allow all all
 | 
						|
EOF
 | 
						|
    else
 | 
						|
        # Configure qpidd to use PLAIN authentication, and add
 | 
						|
        # QPID_USERNAME to the ACL:
 | 
						|
        echo "auth=yes" | sudo tee --append $qpid_conf_file
 | 
						|
        if [ -z "$QPID_PASSWORD" ]; then
 | 
						|
            read_password QPID_PASSWORD "ENTER A PASSWORD FOR QPID USER $QPID_USERNAME"
 | 
						|
        fi
 | 
						|
        # Create ACL to allow $QPID_USERNAME full access
 | 
						|
        cat <<EOF | sudo tee $qpid_acl_file
 | 
						|
group admin ${QPID_USERNAME}@QPID
 | 
						|
acl allow admin all
 | 
						|
acl deny all all
 | 
						|
EOF
 | 
						|
        # Add user to SASL database
 | 
						|
        if is_ubuntu; then
 | 
						|
            install_package sasl2-bin
 | 
						|
        elif is_fedora; then
 | 
						|
            install_package cyrus-sasl-lib
 | 
						|
            install_package cyrus-sasl-plain
 | 
						|
        fi
 | 
						|
        local sasl_conf_file=/etc/sasl2/qpidd.conf
 | 
						|
        sudo sed -i.bak '/PLAIN/!s/mech_list: /mech_list: PLAIN /' $sasl_conf_file
 | 
						|
        local sasl_db=`sudo grep sasldb_path $sasl_conf_file | cut -f 2 -d ":" | tr -d [:blank:]`
 | 
						|
        if [ ! -e $sasl_db ]; then
 | 
						|
            sudo mkdir -p -m 755 `dirname $sasl_db`
 | 
						|
        fi
 | 
						|
        echo $QPID_PASSWORD | sudo saslpasswd2 -c -p -f $sasl_db -u QPID $QPID_USERNAME
 | 
						|
        sudo chmod o+r $sasl_db
 | 
						|
    fi
 | 
						|
 | 
						|
    # If AMQP 1.0 is specified, ensure that the version of the
 | 
						|
    # broker can support AMQP 1.0 and configure the queue and
 | 
						|
    # topic address patterns used by oslo.messaging.
 | 
						|
    if [ "$RPC_MESSAGING_PROTOCOL" == "AMQP1" ]; then
 | 
						|
        QPIDD=$(type -p qpidd)
 | 
						|
        if ! $QPIDD --help | grep -q "queue-patterns"; then
 | 
						|
            exit_distro_not_supported "qpidd with AMQP 1.0 support"
 | 
						|
        fi
 | 
						|
        if ! grep -q "queue-patterns=exclusive" $qpid_conf_file; then
 | 
						|
            cat <<EOF | sudo tee --append $qpid_conf_file
 | 
						|
queue-patterns=exclusive
 | 
						|
queue-patterns=unicast
 | 
						|
topic-patterns=broadcast
 | 
						|
EOF
 | 
						|
        fi
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# Restore xtrace
 | 
						|
$XTRACE
 | 
						|
 | 
						|
# Tell emacs to use shell-script-mode
 | 
						|
## Local variables:
 | 
						|
## mode: shell-script
 | 
						|
## End:
 |