c24b399b7e
MatchMakerRedis is the only tested routing method for ZeroMQ driver. For others, like MatchMakerLocalhost and MatchMakerRing, it still takes some time to work on and completely test. MatchMakerRedis is enough to run under real-world deployment. Change-Id: I3b2e8e68ceebd377479d75bbb8b862ae60cfc826 Partially-Implements: blueprint zeromq
384 lines
13 KiB
Bash
384 lines
13 KiB
Bash
#!/bin/bash
|
|
#
|
|
# lib/rpc_backend
|
|
# Interface for interactig with different rpc backend
|
|
# rpc backend settings
|
|
|
|
# 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 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
|
|
}
|
|
|
|
# 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 "zmq"
|
|
iniset $file $section rpc_zmq_host `hostname`
|
|
if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
|
|
iniset $file $section rpc_zmq_matchmaker \
|
|
oslo.messaging._drivers.matchmaker_redis.MatchMakerRedis
|
|
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 $section rabbit_hosts $RABBIT_HOST
|
|
iniset $file $section rabbit_password $RABBIT_PASSWORD
|
|
iniset $file $section rabbit_userid $RABBIT_USERID
|
|
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:
|