537532931d
This makes a bunch of variable cleanups that will let -o nounset function, for the time being we hide nounset behind another setting variable so that it's not on by default. Because this is bash, and things are only executed on demand, this probably only works in the config it was run in. Expect cleaning up all the paths to be something that takes quite a while. This also includes a new set of unit tests around the trueorfalse function, because my change in how it worked, didn't. Tests are good m'kay. Change-Id: I71a896623ea9e1f042a73dc0678ce85acf0dc87d
381 lines
13 KiB
Bash
381 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
|
|
sudo killall epmd || sudo killall -9 epmd
|
|
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
|
|
# NOTE(ewindisch): Redis is not strictly necessary
|
|
# but there is a matchmaker driver that works
|
|
# really well & out of the box for multi-node.
|
|
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_matchmaker \
|
|
oslo.messaging._drivers.matchmaker_redis.MatchMakerRedis
|
|
# Set MATCHMAKER_REDIS_HOST if running multi-node.
|
|
MATCHMAKER_REDIS_HOST=${MATCHMAKER_REDIS_HOST:-127.0.0.1}
|
|
iniset $file matchmaker_redis host $MATCHMAKER_REDIS_HOST
|
|
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 ${package}.openstack.common.rpc.impl_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 ${package}.openstack.common.rpc.impl_kombu
|
|
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
|
|
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:
|