103 lines
3.5 KiB
Bash
Executable File
103 lines
3.5 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -eux
|
|
|
|
[ -d /var/run/rabbitmq ] || install -d -D -m 0755 -o rabbitmq -g rabbitmq /var/run/rabbitmq
|
|
[ -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
|