blob: 33ab03d664f8da49bb6f25a59d16516a450d1b27 [file] [log] [blame]
Sean Daguee263c822014-12-05 14:25:28 -05001#!/bin/bash
2#
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +09003# lib/rpc_backend
Dean Troyerdc97cb72015-03-28 08:20:50 -05004# Interface for interactig with different RPC backends
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +09005
6# Dependencies:
Adam Spiers6a5aa7c2013-10-24 11:27:02 +01007#
8# - ``functions`` file
Abhishek Chandad5b74c62014-12-12 02:15:55 +05309# - ``RABBIT_{HOST|PASSWORD|USERID}`` must be defined when RabbitMQ is used
Kenneth Giusti7e58c062014-07-23 16:44:37 -040010# - ``RPC_MESSAGING_PROTOCOL`` option for configuring the messaging protocol
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +090011
12# ``stack.sh`` calls the entry points in this order:
13#
Adam Spiers6a5aa7c2013-10-24 11:27:02 +010014# - check_rpc_backend
15# - install_rpc_backend
16# - restart_rpc_backend
17# - iniset_rpc_backend
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +090018
19# Save trace setting
20XTRACE=$(set +o | grep xtrace)
21set +o xtrace
22
Sean Dague53753292014-12-04 19:38:15 -050023RPC_MESSAGING_PROTOCOL=${RPC_MESSAGING_PROTOCOL:-0.9}
24
25# TODO(sdague): RPC backend selection is super wonky because we treat
26# messaging server as a service, which it really isn't for multi host
27QPID_HOST=${QPID_HOST:-}
Dean Troyercc6b4432013-04-08 15:38:03 -050028
Dean Troyerdc97cb72015-03-28 08:20:50 -050029
Dean Troyercc6b4432013-04-08 15:38:03 -050030# Functions
31# ---------
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +090032
33# Make sure we only have one rpc backend enabled.
34# Also check the specified rpc backend is available on your platform.
Ian Wienandaee18c72014-02-21 15:35:08 +110035function check_rpc_backend {
Dean Troyer3ef23bc2014-07-25 14:56:22 -050036 local c svc
37
Matthieu Huin7a7a4662013-04-15 17:13:41 +020038 local rpc_needed=1
39 # We rely on the fact that filenames in lib/* match the service names
40 # that can be passed as arguments to is_service_enabled.
41 # We check for a call to iniset_rpc_backend in these files, meaning
42 # the service needs a backend.
Vishvananda Ishaya78a53d92013-05-09 17:20:31 -070043 rpc_candidates=$(grep -rl iniset_rpc_backend $TOP_DIR/lib/ | awk -F/ '{print $NF}')
Matthieu Huin7a7a4662013-04-15 17:13:41 +020044 for c in ${rpc_candidates}; do
45 if is_service_enabled $c; then
46 rpc_needed=0
47 break
48 fi
49 done
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +090050 local rpc_backend_cnt=0
51 for svc in qpid zeromq rabbit; do
52 is_service_enabled $svc &&
Dean Troyerffd17682014-08-02 16:07:03 -050053 (( rpc_backend_cnt++ )) || true
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +090054 done
55 if [ "$rpc_backend_cnt" -gt 1 ]; then
56 echo "ERROR: only one rpc backend may be enabled,"
57 echo " set only one of 'rabbit', 'qpid', 'zeromq'"
58 echo " via ENABLED_SERVICES."
Matthieu Huin7a7a4662013-04-15 17:13:41 +020059 elif [ "$rpc_backend_cnt" == 0 ] && [ "$rpc_needed" == 0 ]; then
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +090060 echo "ERROR: at least one rpc backend must be enabled,"
61 echo " set one of 'rabbit', 'qpid', 'zeromq'"
62 echo " via ENABLED_SERVICES."
63 fi
64
65 if is_service_enabled qpid && ! qpid_is_supported; then
Nachi Ueno07115eb2013-02-26 12:38:18 -080066 die $LINENO "Qpid support is not available for this version of your distribution."
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +090067 fi
68}
69
Dean Troyer995eb922013-03-07 16:11:40 -060070# clean up after rpc backend - eradicate all traces so changing backends
71# produces a clean switch
72function cleanup_rpc_backend {
73 if is_service_enabled rabbit; then
74 # Obliterate rabbitmq-server
75 uninstall_package rabbitmq-server
Sean Dague9a413ab2015-02-04 12:44:18 -050076 # in case it's not actually running, /bin/true at the end
77 sudo killall epmd || sudo killall -9 epmd || /bin/true
Dean Troyer995eb922013-03-07 16:11:40 -060078 if is_ubuntu; then
79 # And the Erlang runtime too
Sahid Orentino Ferdjaouie9648272014-02-23 18:55:51 +010080 apt_get purge -y erlang*
Dean Troyer995eb922013-03-07 16:11:40 -060081 fi
82 elif is_service_enabled qpid; then
83 if is_fedora; then
zhhuabj5595fdc2013-05-08 18:27:20 +080084 uninstall_package qpid-cpp-server
Dean Troyer995eb922013-03-07 16:11:40 -060085 elif is_ubuntu; then
86 uninstall_package qpidd
87 else
88 exit_distro_not_supported "qpid installation"
89 fi
90 elif is_service_enabled zeromq; then
91 if is_fedora; then
Li Mad3ca1412014-12-21 23:36:43 -080092 uninstall_package zeromq python-zmq
93 if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
94 uninstall_package redis python-redis
95 fi
Dean Troyer995eb922013-03-07 16:11:40 -060096 elif is_ubuntu; then
Li Mad3ca1412014-12-21 23:36:43 -080097 uninstall_package libzmq1 python-zmq
98 if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
99 uninstall_package redis-server python-redis
100 fi
Dean Troyer995eb922013-03-07 16:11:40 -0600101 elif is_suse; then
Li Mad3ca1412014-12-21 23:36:43 -0800102 uninstall_package libzmq1 python-pyzmq
103 if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
104 uninstall_package redis python-redis
105 fi
Dean Troyer995eb922013-03-07 16:11:40 -0600106 else
107 exit_distro_not_supported "zeromq installation"
108 fi
109 fi
Kenneth Giusti7e58c062014-07-23 16:44:37 -0400110
111 # Remove the AMQP 1.0 messaging libraries
112 if [ "$RPC_MESSAGING_PROTOCOL" == "AMQP1" ]; then
113 if is_fedora; then
114 uninstall_package qpid-proton-c-devel
115 uninstall_package python-qpid-proton
116 fi
117 # TODO(kgiusti) ubuntu cleanup
118 fi
Dean Troyer995eb922013-03-07 16:11:40 -0600119}
120
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900121# install rpc backend
Ian Wienandaee18c72014-02-21 15:35:08 +1100122function install_rpc_backend {
Kenneth Giusti7e58c062014-07-23 16:44:37 -0400123 # Regardless of the broker used, if AMQP 1.0 is configured load
124 # the necessary messaging client libraries for oslo.messaging
125 if [ "$RPC_MESSAGING_PROTOCOL" == "AMQP1" ]; then
126 if is_fedora; then
127 install_package qpid-proton-c-devel
128 install_package python-qpid-proton
129 elif is_ubuntu; then
130 # TODO(kgiusti) The QPID AMQP 1.0 protocol libraries
131 # are not yet in the ubuntu repos. Enable these installs
132 # once they are present:
133 #install_package libqpid-proton2-dev
134 #install_package python-qpid-proton
135 # Also add 'uninstall' directives in cleanup_rpc_backend()!
136 exit_distro_not_supported "QPID AMQP 1.0 Proton libraries"
137 else
138 exit_distro_not_supported "QPID AMQP 1.0 Proton libraries"
139 fi
140 # Install pyngus client API
141 # TODO(kgiusti) can remove once python qpid bindings are
142 # available on all supported platforms _and_ pyngus is added
143 # to the requirements.txt file in oslo.messaging
Sean Dague60996b12015-04-08 09:06:49 -0400144 pip_install_gr pyngus
Kenneth Giusti7e58c062014-07-23 16:44:37 -0400145 fi
146
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900147 if is_service_enabled rabbit; then
148 # Install rabbitmq-server
Ian Wienand7ccf4e02014-07-23 14:24:11 +1000149 install_package rabbitmq-server
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900150 elif is_service_enabled qpid; then
151 if is_fedora; then
zhhuabj5595fdc2013-05-08 18:27:20 +0800152 install_package qpid-cpp-server
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900153 elif is_ubuntu; then
154 install_package qpidd
155 else
156 exit_distro_not_supported "qpid installation"
157 fi
Kenneth Giusti062a3c32014-09-30 10:14:08 -0400158 _configure_qpid
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900159 elif is_service_enabled zeromq; then
160 if is_fedora; then
Li Mad3ca1412014-12-21 23:36:43 -0800161 install_package zeromq python-zmq
162 if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
163 install_package redis python-redis
164 fi
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900165 elif is_ubuntu; then
Li Mad3ca1412014-12-21 23:36:43 -0800166 install_package libzmq1 python-zmq
167 if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
168 install_package redis-server python-redis
169 fi
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900170 elif is_suse; then
Li Mad3ca1412014-12-21 23:36:43 -0800171 install_package libzmq1 python-pyzmq
172 if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
173 install_package redis python-redis
174 fi
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900175 else
176 exit_distro_not_supported "zeromq installation"
177 fi
Vincent Hou93a7a502013-09-27 06:16:54 -0400178 # Necessary directory for socket location.
179 sudo mkdir -p /var/run/openstack
180 sudo chown $STACK_USER /var/run/openstack
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900181 fi
Kenneth Giustia1875b72014-09-15 14:21:55 -0400182
183 # If using the QPID broker, install the QPID python client API
184 if is_service_enabled qpid || [ -n "$QPID_HOST" ]; then
185 install_package python-qpid
186 fi
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900187}
188
189# restart the rpc backend
Ian Wienandaee18c72014-02-21 15:35:08 +1100190function restart_rpc_backend {
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900191 if is_service_enabled rabbit; then
192 # Start rabbitmq-server
193 echo_summary "Starting RabbitMQ"
Ben Nemecec5918f2014-01-30 16:07:23 +0000194 # NOTE(bnemec): Retry initial rabbitmq configuration to deal with
195 # the fact that sometimes it fails to start properly.
Ian Wienand64b56a52014-12-16 09:53:36 +1100196 # Reference: https://bugzilla.redhat.com/show_bug.cgi?id=1144100
Tony Breeds6bc905c2015-05-15 12:51:43 +1000197 # NOTE(tonyb): Extend the orginal retry logic to only restart rabbitmq
198 # every second time around the loop.
199 # See: https://bugs.launchpad.net/devstack/+bug/1449056 for details on
200 # why this is needed. This can bee seen on vivid and Debian unstable
201 # (May 2015)
202 # TODO(tonyb): Remove this when Debian and Ubuntu have a fixed systemd
203 # service file.
Dean Troyer3ef23bc2014-07-25 14:56:22 -0500204 local i
Tony Breeds6bc905c2015-05-15 12:51:43 +1000205 for i in `seq 20`; do
Ian Wienand64b56a52014-12-16 09:53:36 +1100206 local rc=0
207
Tony Breeds6bc905c2015-05-15 12:51:43 +1000208 [[ $i -eq "20" ]] && die $LINENO "Failed to set rabbitmq password"
Ian Wienand64b56a52014-12-16 09:53:36 +1100209
Tony Breeds6bc905c2015-05-15 12:51:43 +1000210 if [[ $(( i % 2 )) == "0" ]] ; then
211 restart_service rabbitmq-server
212 fi
Ian Wienand64b56a52014-12-16 09:53:36 +1100213
214 rabbit_setuser "$RABBIT_USERID" "$RABBIT_PASSWORD" || rc=$?
215 if [ $rc -ne 0 ]; then
216 continue
217 fi
218
Ben Nemecec5918f2014-01-30 16:07:23 +0000219 # change the rabbit password since the default is "guest"
Ian Wienand64b56a52014-12-16 09:53:36 +1100220 sudo rabbitmqctl change_password \
221 $RABBIT_USERID $RABBIT_PASSWORD || rc=$?
222 if [ $rc -ne 0 ]; then
223 continue;
224 fi
225
226 break
Ben Nemecec5918f2014-01-30 16:07:23 +0000227 done
Kieran Spearfb2a3ae2013-03-11 23:55:49 +0000228 if is_service_enabled n-cell; then
229 # Add partitioned access for the child cell
230 if [ -z `sudo rabbitmqctl list_vhosts | grep child_cell` ]; then
231 sudo rabbitmqctl add_vhost child_cell
Abhishek Chandad5b74c62014-12-12 02:15:55 +0530232 sudo rabbitmqctl set_permissions -p child_cell $RABBIT_USERID ".*" ".*" ".*"
Kieran Spearfb2a3ae2013-03-11 23:55:49 +0000233 fi
234 fi
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900235 elif is_service_enabled qpid; then
236 echo_summary "Starting qpid"
237 restart_service qpidd
238 fi
239}
240
gordon chungb6197e62015-02-12 15:33:35 -0500241# builds transport url string
242function get_transport_url {
243 if is_service_enabled qpid || [ -n "$QPID_HOST" ]; then
244 echo "qpid://$QPID_USERNAME:$QPID_PASSWORD@$QPID_HOST:5672/"
245 elif is_service_enabled rabbit || { [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; }; then
246 echo "rabbit://$RABBIT_USERID:$RABBIT_PASSWORD@$RABBIT_HOST:5672/"
247 fi
248}
249
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900250# iniset cofiguration
Ian Wienandaee18c72014-02-21 15:35:08 +1100251function iniset_rpc_backend {
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900252 local package=$1
253 local file=$2
Brant Knudson2dd110c2015-03-14 12:39:14 -0500254 local section=${3:-DEFAULT}
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900255 if is_service_enabled zeromq; then
Li Mace1524d2014-12-21 00:46:34 -0800256 iniset $file $section rpc_backend "zmq"
Li Mac24b3992014-12-21 23:51:40 -0800257 iniset $file $section rpc_zmq_host `hostname`
258 if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
Li Ma0f20ad42015-03-23 23:05:15 -0700259 iniset $file $section rpc_zmq_matchmaker "redis"
Li Mac24b3992014-12-21 23:51:40 -0800260 MATCHMAKER_REDIS_HOST=${MATCHMAKER_REDIS_HOST:-127.0.0.1}
261 iniset $file matchmaker_redis host $MATCHMAKER_REDIS_HOST
262 else
263 die $LINENO "Other matchmaker drivers not supported"
264 fi
Jason Dillaman056df822013-07-01 08:52:13 -0400265 elif is_service_enabled qpid || [ -n "$QPID_HOST" ]; then
Kenneth Giusti7e58c062014-07-23 16:44:37 -0400266 # For Qpid use the 'amqp' oslo.messaging transport when AMQP 1.0 is used
267 if [ "$RPC_MESSAGING_PROTOCOL" == "AMQP1" ]; then
268 iniset $file $section rpc_backend "amqp"
269 else
Li Ma529f8112015-01-23 03:10:49 -0800270 iniset $file $section rpc_backend "qpid"
Kenneth Giusti7e58c062014-07-23 16:44:37 -0400271 fi
Attila Fazekasa3dc3992013-07-11 11:26:35 +0200272 iniset $file $section qpid_hostname ${QPID_HOST:-$SERVICE_HOST}
Kenneth Giusti062a3c32014-09-30 10:14:08 -0400273 if [ -n "$QPID_USERNAME" ]; then
274 iniset $file $section qpid_username $QPID_USERNAME
Eoghan Glynn8c11f562013-03-01 12:09:01 +0000275 iniset $file $section qpid_password $QPID_PASSWORD
Eoghan Glynn8c11f562013-03-01 12:09:01 +0000276 fi
jiajun xu4a30b842013-01-22 11:49:03 +0800277 elif is_service_enabled rabbit || { [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; }; then
Li Ma529f8112015-01-23 03:10:49 -0800278 iniset $file $section rpc_backend "rabbit"
Joe Gordond01ff962015-03-23 15:05:39 -0700279 iniset $file oslo_messaging_rabbit rabbit_hosts $RABBIT_HOST
280 iniset $file oslo_messaging_rabbit rabbit_password $RABBIT_PASSWORD
281 iniset $file oslo_messaging_rabbit rabbit_userid $RABBIT_USERID
Mehdi Abaakouk7cf7a8f2015-04-09 11:46:56 +0200282 if [ -n "$RABBIT_HEARTBEAT_TIMEOUT_THRESHOLD" ]; then
283 iniset $file oslo_messaging_rabbit heartbeat_timeout_threshold $RABBIT_HEARTBEAT_TIMEOUT_THRESHOLD
284 fi
285 if [ -n "$RABBIT_HEARTBEAT_RATE" ]; then
286 iniset $file oslo_messaging_rabbit heartbeat_rate $RABBIT_HEARTBEAT_RATE
287 fi
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900288 fi
289}
290
291# Check if qpid can be used on the current distro.
292# qpid_is_supported
Ian Wienandaee18c72014-02-21 15:35:08 +1100293function qpid_is_supported {
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900294 if [[ -z "$DISTRO" ]]; then
295 GetDistro
296 fi
297
Sean Dague2bb483d2014-01-03 09:41:27 -0500298 # Qpid is not in openSUSE
299 ( ! is_suse )
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900300}
301
Abhishek Chandad5b74c62014-12-12 02:15:55 +0530302function rabbit_setuser {
303 local user="$1" pass="$2" found="" out=""
304 out=$(sudo rabbitmqctl list_users) ||
305 { echo "failed to list users" 1>&2; return 1; }
306 found=$(echo "$out" | awk '$1 == user { print $1 }' "user=$user")
307 if [ "$found" = "$user" ]; then
308 sudo rabbitmqctl change_password "$user" "$pass" ||
309 { echo "failed changing pass for '$user'" 1>&2; return 1; }
310 else
311 sudo rabbitmqctl add_user "$user" "$pass" ||
312 { echo "failed changing pass for $user"; return 1; }
313 fi
314 sudo rabbitmqctl set_permissions "$user" ".*" ".*" ".*"
315}
316
Kenneth Giusti062a3c32014-09-30 10:14:08 -0400317# Set up the various configuration files used by the qpidd broker
318function _configure_qpid {
319
320 # the location of the configuration files have changed since qpidd 0.14
321 local qpid_conf_file
322 if [ -e /etc/qpid/qpidd.conf ]; then
323 qpid_conf_file=/etc/qpid/qpidd.conf
324 elif [ -e /etc/qpidd.conf ]; then
325 qpid_conf_file=/etc/qpidd.conf
326 else
327 exit_distro_not_supported "qpidd.conf file not found!"
328 fi
329
330 # force the ACL file to a known location
331 local qpid_acl_file=/etc/qpid/qpidd.acl
332 if [ ! -e $qpid_acl_file ]; then
333 sudo mkdir -p -m 755 `dirname $qpid_acl_file`
334 sudo touch $qpid_acl_file
335 sudo chmod o+r $qpid_acl_file
336 fi
337 sudo sed -i.bak '/^acl-file=/d' $qpid_conf_file
338 echo "acl-file=$qpid_acl_file" | sudo tee --append $qpid_conf_file
339
340 sudo sed -i '/^auth=/d' $qpid_conf_file
341 if [ -z "$QPID_USERNAME" ]; then
342 # no QPID user configured, so disable authentication
343 # and access control
344 echo "auth=no" | sudo tee --append $qpid_conf_file
345 cat <<EOF | sudo tee $qpid_acl_file
346acl allow all all
347EOF
348 else
349 # Configure qpidd to use PLAIN authentication, and add
350 # QPID_USERNAME to the ACL:
351 echo "auth=yes" | sudo tee --append $qpid_conf_file
352 if [ -z "$QPID_PASSWORD" ]; then
353 read_password QPID_PASSWORD "ENTER A PASSWORD FOR QPID USER $QPID_USERNAME"
354 fi
355 # Create ACL to allow $QPID_USERNAME full access
356 cat <<EOF | sudo tee $qpid_acl_file
357group admin ${QPID_USERNAME}@QPID
358acl allow admin all
359acl deny all all
360EOF
361 # Add user to SASL database
362 if is_ubuntu; then
363 install_package sasl2-bin
364 elif is_fedora; then
365 install_package cyrus-sasl-lib
Mehdi Abaakoukd1e3ff12015-02-10 17:54:53 +0100366 install_package cyrus-sasl-plain
Kenneth Giusti062a3c32014-09-30 10:14:08 -0400367 fi
368 local sasl_conf_file=/etc/sasl2/qpidd.conf
369 sudo sed -i.bak '/PLAIN/!s/mech_list: /mech_list: PLAIN /' $sasl_conf_file
370 local sasl_db=`sudo grep sasldb_path $sasl_conf_file | cut -f 2 -d ":" | tr -d [:blank:]`
371 if [ ! -e $sasl_db ]; then
372 sudo mkdir -p -m 755 `dirname $sasl_db`
373 fi
374 echo $QPID_PASSWORD | sudo saslpasswd2 -c -p -f $sasl_db -u QPID $QPID_USERNAME
375 sudo chmod o+r $sasl_db
376 fi
377
378 # If AMQP 1.0 is specified, ensure that the version of the
379 # broker can support AMQP 1.0 and configure the queue and
380 # topic address patterns used by oslo.messaging.
381 if [ "$RPC_MESSAGING_PROTOCOL" == "AMQP1" ]; then
382 QPIDD=$(type -p qpidd)
383 if ! $QPIDD --help | grep -q "queue-patterns"; then
384 exit_distro_not_supported "qpidd with AMQP 1.0 support"
385 fi
386 if ! grep -q "queue-patterns=exclusive" $qpid_conf_file; then
387 cat <<EOF | sudo tee --append $qpid_conf_file
388queue-patterns=exclusive
389queue-patterns=unicast
390topic-patterns=broadcast
391EOF
392 fi
393 fi
394}
Dean Troyercc6b4432013-04-08 15:38:03 -0500395
Akihiro MOTOKIb0f1c382013-01-13 17:58:12 +0900396# Restore xtrace
397$XTRACE
Sean Dague584d90e2013-03-29 14:34:53 -0400398
Adam Spiers6a5aa7c2013-10-24 11:27:02 +0100399# Tell emacs to use shell-script-mode
400## Local variables:
401## mode: shell-script
402## End: