tripleo-image-elements/elements/rabbitmq-server/os-refresh-config/post-configure.d/40-rabbitmq

102 lines
3.4 KiB
Bash
Executable File

#!/bin/bash
set -eux
[ -d /mnt/state/var/log/rabbitmq ] || install -d -D -m 0770 -o rabbitmq -g rabbitmq /mnt/state/var/log/rabbitmq
os-svc-enable -n rabbitmq-server
os-svc-restart -n rabbitmq-server
# Cluster setup
# Why not using auto-configuration of cluster (specifying 'cluster_nodes' in
# rabbitmq.conf):
# 1) This is not robust because when joining a node, it iterates
# through all nodes and joins to first available node, if no suitable node is
# found, joining node is started standalone.
# 2) This is done only for fresh nodes (first start, or reset db).
# 3) You might end up with multiple different clusters A joins with B, C joins
# with D
#
# When joining a node into rabbitmq cluster:
# - if this node is already in cluster with current master[1] node, do nothing
# - iterate through all nodes and check if there is a node which is in a
# cluster[2], if such node exists, join to this node
# - if no existing cluster is found:
# - if this is master node, start this node standalone
# - if it's not master node, try to join with master node otherwise fail (if
# fail we retry on next os-refresh-config run)
#
# [1] master node is first node in alphabetically sorted list of 'rabbit.nodes'
# [2] cluster is any cluster with at least 2 running nodes
function is_in_cluster() {
local node=$1
# Returns true if the list following "running_nodes" in rabbitmqctl
# cluster_status contains at least two nodes.
rabbitmqctl -n rabbit@$node cluster_status|grep -q "running_nodes,\[[^]]\+,"
}
function join_with() {
local node=$1
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@$node || return 1
rabbitmqctl start_app
}
LOCAL=$(hostname -s)
# TODO - nodes are comma separated hostnames, there is probably no type for this
NODES=$(os-apply-config --key rabbit.nodes --type raw --key-default '' | sed 's/,/\n/g')
MASTER=$(echo "$NODES"|sort -n|head -1)
# Heat can return hostname with capital letters, cloud-init converts to lowercase. Make sure
# we can compare them in a case-insensitive manor:
LOCAL=${LOCAL,,}
NODES=${NODES,,}
MASTER=${MASTER,,}
if [ -n "$NODES" ];then
if os-is-bootstrap-host; then
# if this is master node which is already clustered, do nothing
if is_in_cluster $LOCAL; then
exit 0
fi
else
# if this node is already in cluster with current master node, do nothing
if rabbitmqctl cluster_status|grep -q "$MASTER"; then
exit 0
fi
fi
JOINED_WITH=''
# find another node which is already clustered and try join with it
for NODE in $NODES;do
if [ ! "$NODE" = "$LOCAL" ] && is_in_cluster $NODE; then
if join_with $NODE; then
JOINED_WITH=$NODE
break
fi
fi
done
if [ -z "$JOINED_WITH"]; then
# if there is no existing cluster yet and this is master node, start this
# node standalone (other nodes will join to this one)
if os-is-bootstrap-host; then
rabbitmqctl start_app
else
if ! join_with $MASTER; then
echo "failed to join this node into cluster"
exit 1
fi
fi
fi
# wait until rabbitmq node is up
timeout 3 rabbitmqctl wait /var/run/rabbitmq/pid
# make sure that all queues (except those with auto-generated names) are
# mirrored across all nodes in running:
rabbitmqctl set_policy HA '^(?!amq\.).*' '{"ha-mode": "all"}'
fi