#!/bin/bash # # lib/rpc_backend # Interface for installing RabbitMQ on the system # Dependencies: # # - ``functions`` file # - ``RABBIT_{HOST|PASSWORD|USERID}`` 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 (stable interface) # # Note: if implementing an out of tree plugin for an RPC backend, you # should install all services through normal plugin methods, then # redefine ``iniset_rpc_backend`` in your code. That's the one portion # of this file which is a standard interface. # Save trace setting _XTRACE_RPC_BACKEND=$(set +o | grep xtrace) set +o xtrace RABBIT_USERID=${RABBIT_USERID:-stackrabbit} if is_service_enabled rabbit; then RABBIT_HOST=${RABBIT_HOST:-$SERVICE_HOST} fi # Functions # --------- # 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 fi } # install rpc backend function install_rpc_backend { if is_service_enabled rabbit; then # Install rabbitmq-server install_package rabbitmq-server if is_suse; then install_package rabbitmq-server-plugins # the default systemd socket activation only listens on the loopback interface # which causes rabbitmq to try to start its own epmd sudo mkdir -p /etc/systemd/system/epmd.socket.d cat </dev/null [Socket] ListenStream= ListenStream=[::]:4369 EOF sudo systemctl daemon-reload sudo systemctl restart epmd.socket epmd.service fi if is_fedora || is_suse; then # NOTE(jangutter): If rabbitmq is not running (as in a fresh # install) then rabbit_setuser triggers epmd@0.0.0.0.socket with # socket activation. This fails the first time and does not get # cleared. It is benign, but the workaround is to start rabbitmq a # bit earlier for RPM based distros. sudo systemctl --now enable rabbitmq-server fi 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 # NOTE(tonyb): Extend the original retry logic to only restart rabbitmq # every second time around the loop. # See: https://bugs.launchpad.net/devstack/+bug/1449056 for details on # why this is needed. This can bee seen on vivid and Debian unstable # (May 2015) # TODO(tonyb): Remove this when Debian and Ubuntu have a fixed systemd # service file. local i for i in `seq 20`; do local rc=0 [[ $i -eq "20" ]] && die $LINENO "Failed to set rabbitmq password" if [[ $(( i % 2 )) == "0" ]] ; then 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 # NOTE(frickler): Remove the default guest user sudo rabbitmqctl delete_user guest || true fi } # adds a vhost to the rpc backend function rpc_backend_add_vhost { local vhost="$1" if is_service_enabled rabbit; then if [ -z `sudo rabbitmqctl list_vhosts | grep $vhost` ]; then sudo rabbitmqctl add_vhost $vhost sudo rabbitmqctl set_permissions -p $vhost $RABBIT_USERID ".*" ".*" ".*" fi else echo 'RPC backend does not support vhosts' return 1 fi } # Returns the address of the RPC backend in URL format. function get_transport_url { local virtual_host=$1 if is_service_enabled rabbit || { [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; }; then echo "rabbit://$RABBIT_USERID:$RABBIT_PASSWORD@$RABBIT_HOST:5672/$virtual_host" fi } # Returns the address of the Notification backend in URL format. This # should be used to set the transport_url option in the # oslo_messaging_notifications group. function get_notification_url { local virtual_host=$1 if is_service_enabled rabbit || { [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; }; then echo "rabbit://$RABBIT_USERID:$RABBIT_PASSWORD@$RABBIT_HOST:5672/$virtual_host" fi } # iniset configuration function iniset_rpc_backend { local package=$1 local file=$2 local section=${3:-DEFAULT} local virtual_host=$4 if is_service_enabled rabbit || { [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; }; then iniset $file $section transport_url $(get_transport_url "$virtual_host") 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 } 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" ".*" ".*" ".*" } # Restore xtrace $_XTRACE_RPC_BACKEND # Tell emacs to use shell-script-mode ## Local variables: ## mode: shell-script ## End: