Python rewrite.
This commit is contained in:
parent
f7c75bc223
commit
d679930416
|
@ -1 +1 @@
|
||||||
rabbitmq-relations
|
rabbitmq-server-relations.py
|
|
@ -1 +0,0 @@
|
||||||
rabbitmq-relations
|
|
|
@ -1 +1 @@
|
||||||
rabbitmq-relations
|
rabbitmq-server-relations.py
|
|
@ -1 +1 @@
|
||||||
rabbitmq-relations
|
rabbitmq-server-relations.py
|
|
@ -1,70 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
juju-log "rabbitmq-server: Firing config hook"
|
|
||||||
|
|
||||||
export HOME=/root # (HOME is not set on first run)
|
|
||||||
RABBIT_PLUGINS=/usr/lib/rabbitmq/lib/rabbitmq_server-*/sbin/rabbitmq-plugins
|
|
||||||
if [ "`config-get management_plugin`" == "True" ]; then
|
|
||||||
$RABBIT_PLUGINS enable rabbitmq_management
|
|
||||||
open-port 55672/tcp
|
|
||||||
else
|
|
||||||
$RABBIT_PLUGINS disable rabbitmq_management
|
|
||||||
close-port 55672/tcp
|
|
||||||
fi
|
|
||||||
|
|
||||||
ssl_enabled=`config-get ssl_enabled`
|
|
||||||
|
|
||||||
cd /etc/rabbitmq
|
|
||||||
|
|
||||||
new_config=`mktemp /etc/rabbitmq/.rabbitmq.config.XXXXXX`
|
|
||||||
chgrp rabbitmq "$new_config"
|
|
||||||
chmod g+r "$new_config"
|
|
||||||
exec 3> "$new_config"
|
|
||||||
|
|
||||||
cat >&3 <<EOF
|
|
||||||
[
|
|
||||||
{rabbit, [
|
|
||||||
EOF
|
|
||||||
|
|
||||||
ssl_key_file=/etc/rabbitmq/rabbit-server-privkey.pem
|
|
||||||
ssl_cert_file=/etc/rabbitmq/rabbit-server-cert.pem
|
|
||||||
|
|
||||||
if [ "$ssl_enabled" == "True" ]; then
|
|
||||||
umask 027
|
|
||||||
config-get ssl_key > "$ssl_key_file"
|
|
||||||
config-get ssl_cert > "$ssl_cert_file"
|
|
||||||
chgrp rabbitmq "$ssl_key_file" "$ssl_cert_file"
|
|
||||||
if [ ! -s "$ssl_key_file" ]; then
|
|
||||||
juju-log "ssl_key not set - can't configure SSL"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if [ ! -s "$ssl_cert_file" ]; then
|
|
||||||
juju-log "ssl_cert not set - can't configure SSL"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
cat >&3 <<EOF
|
|
||||||
{ssl_listeners, [`config-get ssl_port`]},
|
|
||||||
{ssl_options, [
|
|
||||||
{certfile,"$ssl_cert_file"},
|
|
||||||
{keyfile,"$ssl_key_file"}
|
|
||||||
]},
|
|
||||||
open-port `config-get ssl_port`/tcp
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat >&3 <<EOF
|
|
||||||
{tcp_listeners, [5672]}
|
|
||||||
]}
|
|
||||||
].
|
|
||||||
EOF
|
|
||||||
|
|
||||||
exec 3>&-
|
|
||||||
|
|
||||||
if [ -f rabbitmq.config ]; then
|
|
||||||
mv rabbitmq.config{,.bak}
|
|
||||||
fi
|
|
||||||
|
|
||||||
mv "$new_config" rabbitmq.config
|
|
||||||
|
|
||||||
/etc/init.d/rabbitmq-server restart
|
|
|
@ -1 +1 @@
|
||||||
rabbitmq-relations
|
rabbitmq-server-relations.py
|
|
@ -1 +1 @@
|
||||||
rabbitmq-relations
|
rabbitmq-server-relations.py
|
|
@ -1 +1 @@
|
||||||
rabbitmq-relations
|
rabbitmq-server-relations.py
|
|
@ -0,0 +1,97 @@
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import utils
|
||||||
|
import apt_pkg as apt
|
||||||
|
|
||||||
|
PACKAGES = ['pwgen', 'rabbitmq-server']
|
||||||
|
|
||||||
|
RABBITMQ_CTL = '/usr/sbin/rabbitmqctl'
|
||||||
|
COOKIE_PATH = '/var/lib/rabbitmq/.erlang.cookie'
|
||||||
|
|
||||||
|
def vhost_exists(vhost):
|
||||||
|
cmd = [RABBITMQ_CTL, 'list_vhosts']
|
||||||
|
out = subprocess.check_output(cmd)
|
||||||
|
for line in out.split('\n')[1:]:
|
||||||
|
if line == vhost:
|
||||||
|
utils.juju_log('INFO', 'vhost (%s) already exists.' % vhost)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def create_vhost(vhost):
|
||||||
|
if vhost_exists(vhost):
|
||||||
|
return
|
||||||
|
cmd = [RABBITMQ_CTL, 'add_vhost', vhost]
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
utils.juju_log('INFO', 'Created new vhost (%s).' % vhost)
|
||||||
|
|
||||||
|
|
||||||
|
def user_exists(user):
|
||||||
|
cmd = [RABBITMQ_CTL, 'list_users']
|
||||||
|
out = subprocess.check_output(cmd)
|
||||||
|
for line in out.split('\n')[1:]:
|
||||||
|
_user = line.split('\t')[0]
|
||||||
|
if _user == user:
|
||||||
|
admin = line.split('\t')[1]
|
||||||
|
return True, (admin == '[administrator]')
|
||||||
|
return False, False
|
||||||
|
|
||||||
|
|
||||||
|
def create_user(user, password, admin=False):
|
||||||
|
exists, is_admin = user_exists(user)
|
||||||
|
|
||||||
|
if not exists:
|
||||||
|
cmd = [RABBITMQ_CTL, 'add_user', user, password]
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
utils.juju_log('INFO', 'Created new user (%s).' % user)
|
||||||
|
|
||||||
|
if admin == is_admin:
|
||||||
|
return
|
||||||
|
|
||||||
|
if admin:
|
||||||
|
cmd = [RABBITMQ_CTL, 'set_user_tags', user, 'administrator']
|
||||||
|
utils.juju_log('INFO', 'Granting user (%s) admin access.')
|
||||||
|
else:
|
||||||
|
cmd = [RABBITMQ_CTL, 'set_user_tags', user]
|
||||||
|
utils.juju_log('INFO', 'Revoking user (%s) admin access.')
|
||||||
|
|
||||||
|
|
||||||
|
def grant_permissions(user, vhost):
|
||||||
|
cmd = [RABBITMQ_CTL, 'set_permissions', '-p',
|
||||||
|
vhost, user, '.*', '.*', '.*']
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def service(action):
|
||||||
|
cmd = ['service', 'rabbitmq-server', action]
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def rabbit_version():
|
||||||
|
apt.init()
|
||||||
|
cache = apt.Cache()
|
||||||
|
pkg = cache['rabbitmq-server']
|
||||||
|
if pkg.current_ver:
|
||||||
|
return apt.upstream_version(pkg.current_ver.ver_str)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def cluster_with(host):
|
||||||
|
utils.juju_log('INFO', 'Clustering with remote rabbit host (%s).' % host)
|
||||||
|
vers = rabbit_version()
|
||||||
|
if vers >= '3.0.1-1':
|
||||||
|
cluster_cmd = 'join_cluster'
|
||||||
|
else:
|
||||||
|
cluster_cmd = 'cluster'
|
||||||
|
out = subprocess.check_output([RABBITMQ_CTL, 'cluster_status'])
|
||||||
|
for line in out.split('\n'):
|
||||||
|
if re.search(host, line):
|
||||||
|
utils.juju_log('INFO', 'Host already clustered with %s.' % host)
|
||||||
|
return
|
||||||
|
cmd = [RABBITMQ_CTL, 'stop_app']
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
cmd = [RABBITMQ_CTL, cluster_cmd, 'rabbit@%s' % host]
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
cmd = [RABBITMQ_CTL, 'start_app']
|
||||||
|
subprocess.check_call(cmd)
|
|
@ -1,82 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# rabbitmq-common - common formula shell functions and config variables
|
|
||||||
#
|
|
||||||
# Copyright (C) 2011 Canonical Ltd.
|
|
||||||
# Author: Adam Gandelman <adam.gandelman@canonical.com>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
RABBIT_CTL='rabbitmqctl'
|
|
||||||
|
|
||||||
ERLANG_COOKIE="/var/lib/rabbitmq/.erlang.cookie"
|
|
||||||
|
|
||||||
function user_exists {
|
|
||||||
$RABBIT_CTL list_users | grep -wq "^$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
function user_is_admin {
|
|
||||||
$RABBIT_CTL list_users | grep -w "^$1" | grep -q "administrator"
|
|
||||||
}
|
|
||||||
|
|
||||||
function vhost_exists {
|
|
||||||
$RABBIT_CTL list_vhosts | grep "^$1\$" >/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
function create_vhost {
|
|
||||||
juju-log "Creating vhost: $1"
|
|
||||||
$RABBIT_CTL add_vhost "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
function user_create {
|
|
||||||
local user="$1"
|
|
||||||
local passwd="$2"
|
|
||||||
local vhost="$3"
|
|
||||||
local admin="$4"
|
|
||||||
juju-log "rabbitmq: Creating user $1 (vhost: $3"
|
|
||||||
$RABBIT_CTL add_user "$user" "$passwd" || return 1
|
|
||||||
|
|
||||||
# grant the user all permissions on the default vhost /
|
|
||||||
# TODO: investigate sane permissions
|
|
||||||
juju-log "rabbitmq: Granting permission to $1 on vhost /"
|
|
||||||
$RABBIT_CTL set_permissions -p "$vhost" "$user" ".*" ".*" ".*"
|
|
||||||
|
|
||||||
if [[ "$admin" == "admin" ]] ; then
|
|
||||||
user_is_admin "$user" && return 0
|
|
||||||
juju-log "rabbitmq: Granting user $user admin access"
|
|
||||||
$RABBIT_CTL set_user_tags "$user" administrator || return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function rabbit_version {
|
|
||||||
echo "$(dpkg -l | grep rabbitmq-server | awk '{ print $3 }')"
|
|
||||||
}
|
|
||||||
|
|
||||||
##########################################################################
|
|
||||||
# Description: Query HA interface to determine is cluster is configured
|
|
||||||
# Returns: 0 if configured, 1 if not configured
|
|
||||||
##########################################################################
|
|
||||||
is_clustered() {
|
|
||||||
for r_id in `relation-ids ha`; do
|
|
||||||
for unit in `relation-list -r $r_id`; do
|
|
||||||
clustered=`relation-get -r $r_id clustered $unit`
|
|
||||||
if [ -n "$clustered" ]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
|
||||||
return 1
|
|
||||||
}
|
|
|
@ -1,198 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# rabbitmq-relations - relations to be used by formula, referenced
|
|
||||||
# via symlink
|
|
||||||
#
|
|
||||||
# Copyright (C) 2011 Canonical Ltd.
|
|
||||||
# Author: Adam Gandelman <adam.gandelman@canonical.com>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
CHARM_DIR=$(dirname $0)
|
|
||||||
ARG0=${0##*/}
|
|
||||||
|
|
||||||
if [[ -e $CHARM_DIR/rabbitmq-common ]] ; then
|
|
||||||
. $CHARM_DIR/rabbitmq-common
|
|
||||||
else
|
|
||||||
juju-log "rabbitmq-server: ERROR Could not load $CHARM_DIR/rabbitmq-common"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
juju-log "rabbitmq-server: Firing hook $ARG0."
|
|
||||||
|
|
||||||
function install_hook() {
|
|
||||||
[[ ! `which pwgen` ]] && apt-get -y install pwgen
|
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get -qqy \
|
|
||||||
install --no-install-recommends rabbitmq-server
|
|
||||||
rc=$?
|
|
||||||
service rabbitmq-server stop
|
|
||||||
open-port 5672/tcp
|
|
||||||
}
|
|
||||||
|
|
||||||
function amqp_changed() {
|
|
||||||
# Connecting clients should request a username and vhost.
|
|
||||||
# In reponse, we generate a password for new users,
|
|
||||||
# grant the user access on the default vhost "/",
|
|
||||||
# and tell it where to reach us.
|
|
||||||
|
|
||||||
# Skip managing rabbit queue config unless we are the
|
|
||||||
# lowest numbered unit in the service cluster.
|
|
||||||
local local_unit_id=$(echo $JUJU_UNIT_NAME | cut -d/ -f2)
|
|
||||||
local remote_unit_id=""
|
|
||||||
for relid in $(relation-ids cluster) ; do
|
|
||||||
for unit in $(relation-list -r "$relid") ; do
|
|
||||||
remote_unit_id="$(echo $unit | cut -d/ -f2)"
|
|
||||||
if [[ "$local_unit_id" -gt "$remote_unit_id" ]]; then
|
|
||||||
juju-log "amqp_changed(): Deferring amqp_changed to leader."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
local rabbit_user=`relation-get username`
|
|
||||||
local vhost=`relation-get vhost`
|
|
||||||
if [[ -z "$rabbit_user" ]] || [[ -z "$vhost" ]] ; then
|
|
||||||
juju-log "rabbitmq-server: rabbit_user||vhost not yet received from peer."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
local passwd_file="/var/lib/juju/$rabbit_user.passwd"
|
|
||||||
local password=""
|
|
||||||
if [[ -e $passwd_file ]] ; then
|
|
||||||
password=$(cat $passwd_file)
|
|
||||||
else
|
|
||||||
password=$(pwgen 10 1)
|
|
||||||
echo $password >$passwd_file
|
|
||||||
chmod 0400 $passwd_file
|
|
||||||
fi
|
|
||||||
if ! vhost_exists "$vhost" ; then
|
|
||||||
juju-log "rabbitmq-server: Creating vhost $vhost"
|
|
||||||
create_vhost "$vhost"
|
|
||||||
fi
|
|
||||||
if ! user_exists "$rabbit_user" ; then
|
|
||||||
juju-log "rabbitmq-server: Creating user $rabbit_user"
|
|
||||||
user_create "$rabbit_user" "$password" "$vhost" admin || exit 1
|
|
||||||
else
|
|
||||||
juju-log "rabbitmq-server: user $rabbit_user already exists."
|
|
||||||
fi
|
|
||||||
local remote_host="$(relation-get private-address)"
|
|
||||||
juju-log "rabbitmq-server: Returning credentials for $rabbit_user@$remote_host"
|
|
||||||
relation-set password="$password"
|
|
||||||
|
|
||||||
if is_clustered ; then
|
|
||||||
relation-set clustered="true" vip="$(config-get vip)"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function cluster_joined {
|
|
||||||
local remote_unit_id=$(echo $JUJU_REMOTE_UNIT | cut -d/ -f2)
|
|
||||||
local local_unit_id=$(echo $JUJU_UNIT_NAME | cut -d/ -f2)
|
|
||||||
[[ $local_unit_id -gt $remote_unit_id ]] && echo "Relation greater" && exit 0
|
|
||||||
if [[ ! -e $ERLANG_COOKIE ]] ; then
|
|
||||||
juju-log "rabbitmq-server: ERROR Could not find cookie at $ERLANG_COOKIE"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
relation-set cookie="$(cat $ERLANG_COOKIE)" host="$(hostname)"
|
|
||||||
}
|
|
||||||
|
|
||||||
function cluster_changed {
|
|
||||||
local remote_unit_id=$(echo $JUJU_REMOTE_UNIT | cut -d/ -f2)
|
|
||||||
local local_unit_id=$(echo $JUJU_UNIT_NAME | cut -d/ -f2)
|
|
||||||
|
|
||||||
[[ $local_unit_id -lt $remote_unit_id ]] && echo "Relation lesser" && exit 0
|
|
||||||
|
|
||||||
local remote_host=$(relation-get host)
|
|
||||||
local cookie_value=$(relation-get cookie)
|
|
||||||
|
|
||||||
[[ -z "$remote_host" ]] || [[ -z "$cookie_value" ]] && \
|
|
||||||
juju-log "rabbimtq-server: remote_host||cookie_value not yet set." &&
|
|
||||||
exit 0
|
|
||||||
|
|
||||||
# Sync the erlang cookie to that of remote host.
|
|
||||||
service rabbitmq-server stop
|
|
||||||
echo -n "$cookie_value" > $ERLANG_COOKIE
|
|
||||||
service rabbitmq-server start
|
|
||||||
|
|
||||||
# Configure clustering.
|
|
||||||
# rabbitmq apparently does not like FQDNs.
|
|
||||||
local short_host=$(echo $remote_host | sed -e 's/\./ /g' | awk '{ print $1 }')
|
|
||||||
local cur_vers=$(rabbit_version)
|
|
||||||
local cluster_cmd="cluster"
|
|
||||||
if dpkg --compare-versions "$cur_vers" ge "3.0.1-1" ; then
|
|
||||||
cluster_cmd="join_cluster"
|
|
||||||
fi
|
|
||||||
if ! rabbitmqctl cluster_status | grep -q "rabbit@$short_host" ; then
|
|
||||||
juju-log "Clustering with new rabbitmq peer @ $short_host."
|
|
||||||
rabbitmqctl stop_app
|
|
||||||
rabbitmqctl $cluster_cmd rabbit@$short_host
|
|
||||||
rabbitmqctl start_app
|
|
||||||
else
|
|
||||||
juju-log "Already clustered with rabbitmq peer @ $short_host."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function ha_joined() {
|
|
||||||
local corosync_bindiface=`config-get ha-bindiface`
|
|
||||||
local corosync_mcastport=`config-get ha-mcastport`
|
|
||||||
local vip=`config-get vip`
|
|
||||||
local vip_iface=`config-get vip_iface`
|
|
||||||
local vip_cidr=`config-get vip_cidr`
|
|
||||||
if [ -n "$vip" ] && [ -n "$vip_iface" ] && \
|
|
||||||
[ -n "$vip_cidr" ] && [ -n "$corosync_bindiface" ] && \
|
|
||||||
[ -n "$corosync_mcastport" ]; then
|
|
||||||
# TODO: This feels horrible but the data required by the hacluster
|
|
||||||
# charm is quite complex and is python ast parsed.
|
|
||||||
resources="{
|
|
||||||
'res_rabbitmq_vip':'ocf:heartbeat:IPaddr2'
|
|
||||||
}"
|
|
||||||
resource_params="{
|
|
||||||
'res_rabbitmq_vip': 'params ip=\"$vip\" cidr_netmask=\"$vip_cidr\" nic=\"$vip_iface\"'
|
|
||||||
}"
|
|
||||||
relation-set corosync_bindiface=$corosync_bindiface \
|
|
||||||
corosync_mcastport=$corosync_mcastport \
|
|
||||||
resources="$resources" resource_params="$resource_params"
|
|
||||||
else
|
|
||||||
juju-log "Insufficient configuration data to configure hacluster"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function ha_changed() {
|
|
||||||
# we may now be clustered, advertise our vip to clients if so.
|
|
||||||
if is_clustered ; then
|
|
||||||
local vip="$(config-get vip)"
|
|
||||||
juju-log "$CHARM - ha_changed(): We are now HA clustered. "\
|
|
||||||
"Advertising our VIP ($vip) to all AMQP clients."
|
|
||||||
for rid in $(relation-ids amqp) ; do
|
|
||||||
relation-set -r $rid clustered="true" vip="$vip"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
case $ARG0 in
|
|
||||||
"install") install_hook ;;
|
|
||||||
"start") service rabbitmq-server status || service rabbitmq-server start ;;
|
|
||||||
"stop") service rabbitmq-server status && service rabbitmq-server stop ;;
|
|
||||||
"amqp-relation-joined") exit 0 ;;
|
|
||||||
"amqp-relation-changed") amqp_changed ;;
|
|
||||||
"cluster-relation-joined") cluster_joined ;;
|
|
||||||
"cluster-relation-changed") cluster_changed ;;
|
|
||||||
"ha-relation-joined") ha_joined ;;
|
|
||||||
"ha-relation-changed") ha_changed ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
rc=$?
|
|
||||||
juju-log "rabbitmq-server: Hook $ARG0 complete. Exiting $rc"
|
|
||||||
exit $rc
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import rabbit_utils as rabbit
|
||||||
|
import utils
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def install():
|
||||||
|
utils.install(*rabbit.PACKAGES)
|
||||||
|
utils.expose(5672)
|
||||||
|
|
||||||
|
def amqp_changed():
|
||||||
|
l_unit_no=os.getenv('JUJU_UNIT_NAME').split('/')[1]
|
||||||
|
r_unit_no=None
|
||||||
|
for rid in utils.relation_ids('cluster'):
|
||||||
|
for unit in utils.relation_list(rid):
|
||||||
|
r_unit_no = unit.split('/')[1]
|
||||||
|
if l_unit_no > r_unit_no:
|
||||||
|
msg = 'amqp_changed(): Deferring amqp_changed to leader.'
|
||||||
|
utils.juju_log('INFO', msg)
|
||||||
|
return
|
||||||
|
|
||||||
|
rabbit_user=utils.relation_get('username')
|
||||||
|
vhost=utils.relation_get('vhost')
|
||||||
|
if None in [rabbit_user, vhost]:
|
||||||
|
utils.juju_log('INFO', 'amqp_changed(): Relation not ready.')
|
||||||
|
return
|
||||||
|
|
||||||
|
password_file = '/var/lib/juju/%s.passwd' % rabbit_user
|
||||||
|
if os.path.exists(password_file):
|
||||||
|
password = open(password_file).read().strip()
|
||||||
|
else:
|
||||||
|
cmd = ['pwgen', '64', '1']
|
||||||
|
password = subprocess.check_output(cmd).strip()
|
||||||
|
with open(password_file, 'wb') as out:
|
||||||
|
out.write(password)
|
||||||
|
|
||||||
|
rabbit.create_vhost(vhost)
|
||||||
|
rabbit.create_user(rabbit_user, password)
|
||||||
|
rabbit.grant_permissions(rabbit_user, vhost)
|
||||||
|
|
||||||
|
relation_settings = {
|
||||||
|
'password': password
|
||||||
|
}
|
||||||
|
if utils.is_clustered():
|
||||||
|
relation_settings['clustered'] = 'true'
|
||||||
|
relation_settings['vip'] = utils.config_get('vip')
|
||||||
|
utils.relation_set(**relation_settings)
|
||||||
|
|
||||||
|
|
||||||
|
def cluster_joined():
|
||||||
|
l_unit_no = os.getenv('JUJU_UNIT_NAME').split('/')[1]
|
||||||
|
r_unit_no = os.getenv('JUJU_REMOTE_UNIT').split('/')[1]
|
||||||
|
if l_unit_no > r_unit_no:
|
||||||
|
utils.juju_log('INFO', 'cluster_joined: Relation greater.')
|
||||||
|
return
|
||||||
|
rabbit.COOKIE_PATH = '/var/lib/rabbitmq/.erlang.cookie'
|
||||||
|
if not os.path.isfile(rabbit.COOKIE_PATH):
|
||||||
|
utils.juju_log('ERROR', 'erlang cookie missing from %s' %\
|
||||||
|
rabbit.COOKIE_PATH)
|
||||||
|
cookie = open(rabbit.COOKIE_PATH, 'r').read().strip()
|
||||||
|
local_hostname = subprocess.check_output(['hostname']).strip()
|
||||||
|
utils.relation_set(cookie=cookie, host=local_hostname)
|
||||||
|
|
||||||
|
|
||||||
|
def cluster_changed():
|
||||||
|
l_unit_no = os.getenv('JUJU_UNIT_NAME').split('/')[1]
|
||||||
|
r_unit_no = os.getenv('JUJU_REMOTE_UNIT').split('/')[1]
|
||||||
|
if l_unit_no < r_unit_no:
|
||||||
|
utils.juju_log('INFO', 'cluster_joined: Relation lesser.')
|
||||||
|
return
|
||||||
|
|
||||||
|
remote_host = utils.relation_get('host')
|
||||||
|
cookie = utils.relation_get('cookie')
|
||||||
|
if None in [remote_host, cookie]:
|
||||||
|
utils.juju_log('INFO',
|
||||||
|
'cluster_joined: remote_host|cookie not yet set.')
|
||||||
|
return
|
||||||
|
|
||||||
|
if open(rabbit.COOKIE_PATH, 'r').read().strip() == cookie:
|
||||||
|
utils.juju_log('INFO', 'Cookie already synchronized with peer.')
|
||||||
|
return
|
||||||
|
|
||||||
|
utils.juju_log('INFO', 'Synchronizing erlang cookie from peer.')
|
||||||
|
rabbit.service('stop')
|
||||||
|
with open(rabbit.COOKIE_PATH, 'wb') as out:
|
||||||
|
out.write(cookie)
|
||||||
|
rabbit.service('start')
|
||||||
|
rabbit.cluster_with(remote_host)
|
||||||
|
|
||||||
|
|
||||||
|
def ha_joined():
|
||||||
|
config = {}
|
||||||
|
corosync_bindiface = utils.config_get('ha-bindiface')
|
||||||
|
corosync_mcastport = utils.config_get('ha-mcastport')
|
||||||
|
vip = utils.config_get('vip')
|
||||||
|
vip_iface = utils.config_get('vip_iface')
|
||||||
|
vip_cidr = utils.config_get('vip_cidr')
|
||||||
|
if None in [corosync_bindiface, corosync_mcastport, vip, vip_iface,
|
||||||
|
vip_cidr]:
|
||||||
|
utils.juju_log('ERROR', 'Insufficient configuration data to '\
|
||||||
|
'configure hacluster.')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
relation_settings = {}
|
||||||
|
relation_settings['corosync_bindiface'] = corosync_bindiface
|
||||||
|
relation_settings['corosync_mcastport'] = corosync_mcastport
|
||||||
|
relation_settings['resources'] = {
|
||||||
|
'res_rabbitmq_vip': 'ocf:heartbeat:IPaddr2'
|
||||||
|
}
|
||||||
|
relation_settings['resource_params'] = {
|
||||||
|
'res_rabbitmq_vip': ('params ip="%s" cider_netmask="%s" nic="%s"' %\
|
||||||
|
(vip, vip_cidr, vip_iface))
|
||||||
|
}
|
||||||
|
utils.relation_set(**relation_settings)
|
||||||
|
|
||||||
|
|
||||||
|
def ha_changed():
|
||||||
|
if not utils.is_clustered:
|
||||||
|
return
|
||||||
|
vip = utils.config_get('vip')
|
||||||
|
utils.juju_log('INFO', 'ha_changed(): We are now HA clustered. '\
|
||||||
|
'Advertising our VIP (%s) to all AMQP clients.' %\
|
||||||
|
vip)
|
||||||
|
relation_settings = {'vip': vip, 'clustered': 'true'}
|
||||||
|
for rid in utils.relation_ids('amqp'):
|
||||||
|
relation_settings['rid'] = rid
|
||||||
|
utils.relation_set(**relation_settings)
|
||||||
|
|
||||||
|
|
||||||
|
hooks = {
|
||||||
|
'install': install,
|
||||||
|
'amqp-relation-changed': amqp_changed,
|
||||||
|
'cluster-relation-joined': cluster_joined,
|
||||||
|
'cluster-relation-changed': cluster_changed,
|
||||||
|
'ha-relation-joined': ha_joined,
|
||||||
|
'ha-relation-changed': ha_changed,
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.do_hooks(hooks)
|
|
@ -1 +0,0 @@
|
||||||
rabbitmq-relations
|
|
|
@ -1 +0,0 @@
|
||||||
rabbitmq-relations
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2012 Canonical Ltd.
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# James Page <james.page@ubuntu.com>
|
||||||
|
# Paul Collins <paul.collins@canonical.com>
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def do_hooks(hooks):
|
||||||
|
hook = os.path.basename(sys.argv[0])
|
||||||
|
|
||||||
|
try:
|
||||||
|
hook_func = hooks[hook]
|
||||||
|
except KeyError:
|
||||||
|
juju_log('INFO',
|
||||||
|
"This charm doesn't know how to handle '{}'.".format(hook))
|
||||||
|
else:
|
||||||
|
hook_func()
|
||||||
|
|
||||||
|
|
||||||
|
def install(*pkgs):
|
||||||
|
cmd = [
|
||||||
|
'apt-get',
|
||||||
|
'-y',
|
||||||
|
'install'
|
||||||
|
]
|
||||||
|
for pkg in pkgs:
|
||||||
|
cmd.append(pkg)
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
|
||||||
|
TEMPLATES_DIR = 'templates'
|
||||||
|
|
||||||
|
|
||||||
|
def expose(port, protocol='TCP'):
|
||||||
|
cmd = [
|
||||||
|
'open-port',
|
||||||
|
'{}/{}'.format(port, protocol)
|
||||||
|
]
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def juju_log(severity, message):
|
||||||
|
cmd = [
|
||||||
|
'juju-log',
|
||||||
|
'--log-level', severity,
|
||||||
|
message
|
||||||
|
]
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def relation_ids(relation):
|
||||||
|
cmd = [
|
||||||
|
'relation-ids',
|
||||||
|
relation
|
||||||
|
]
|
||||||
|
return subprocess.check_output(cmd).split() # IGNORE:E1103
|
||||||
|
|
||||||
|
|
||||||
|
def relation_list(rid):
|
||||||
|
cmd = [
|
||||||
|
'relation-list',
|
||||||
|
'-r', rid,
|
||||||
|
]
|
||||||
|
return subprocess.check_output(cmd).split() # IGNORE:E1103
|
||||||
|
|
||||||
|
|
||||||
|
def relation_get(attribute, unit=None, rid=None):
|
||||||
|
cmd = [
|
||||||
|
'relation-get',
|
||||||
|
]
|
||||||
|
if rid:
|
||||||
|
cmd.append('-r')
|
||||||
|
cmd.append(rid)
|
||||||
|
cmd.append(attribute)
|
||||||
|
if unit:
|
||||||
|
cmd.append(unit)
|
||||||
|
value = subprocess.check_output(cmd).strip() # IGNORE:E1103
|
||||||
|
if value == "":
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def relation_set(**kwargs):
|
||||||
|
cmd = [
|
||||||
|
'relation-set'
|
||||||
|
]
|
||||||
|
args = []
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
if k == 'rid':
|
||||||
|
cmd.append('-r')
|
||||||
|
cmd.append(v)
|
||||||
|
else:
|
||||||
|
args.append('{}={}'.format(k, v))
|
||||||
|
cmd += args
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def unit_get(attribute):
|
||||||
|
cmd = [
|
||||||
|
'unit-get',
|
||||||
|
attribute
|
||||||
|
]
|
||||||
|
value = subprocess.check_output(cmd).strip() # IGNORE:E1103
|
||||||
|
if value == "":
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def config_get(attribute):
|
||||||
|
cmd = [
|
||||||
|
'config-get',
|
||||||
|
attribute
|
||||||
|
]
|
||||||
|
value = subprocess.check_output(cmd).strip() # IGNORE:E1103
|
||||||
|
if value == "":
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def is_clustered():
|
||||||
|
for r_id in (relation_ids('ha') or []):
|
||||||
|
for unit in (relation_list(r_id) or []):
|
||||||
|
relation_data = \
|
||||||
|
relation_get_dict(relation_id=r_id,
|
||||||
|
remote_unit=unit)
|
||||||
|
if 'clustered' in relation_data:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def is_leader():
|
||||||
|
status = execute('crm resource show res_ks_vip', echo=True)[0].strip()
|
||||||
|
hostname = execute('hostname', echo=True)[0].strip()
|
||||||
|
if hostname in status:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
Loading…
Reference in New Issue