Files
charm-rabbitmq-server/hooks/rabbit_utils.py
2014-01-09 11:32:21 +01:00

239 lines
7.1 KiB
Python

import os
import pwd
import grp
import re
import subprocess
import glob
import lib.utils as utils
import lib.unison as unison
import lib.cluster_utils as cluster
import apt_pkg as apt
PACKAGES = ['pwgen', 'rabbitmq-server', 'python-amqplib', 'unison']
RABBITMQ_CTL = '/usr/sbin/rabbitmqctl'
COOKIE_PATH = '/var/lib/rabbitmq/.erlang.cookie'
ENV_CONF = '/etc/rabbitmq/rabbitmq-env.conf'
RABBITMQ_CONF = '/etc/rabbitmq/rabbitmq.config'
SSH_USER = 'juju_rabbit'
RABBIT_USER = 'rabbitmq'
LIB_PATH = '/var/lib/rabbitmq/'
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'
cmd = [RABBITMQ_CTL, 'set_policy HA \'^(?!amq\.).*\' '
'\'{"ha-mode": "all"}\'']
subprocess.check_call(cmd)
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)
def set_node_name(name):
# update or append RABBITMQ_NODENAME to environment config.
# rabbitmq.conf.d is not present on all releases, so use or create
# rabbitmq-env.conf instead.
if not os.path.isfile(ENV_CONF):
utils.juju_log('INFO', '%s does not exist, creating.' % ENV_CONF)
with open(ENV_CONF, 'wb') as out:
out.write('RABBITMQ_NODENAME=%s\n' % name)
return
out = []
f = False
for line in open(ENV_CONF).readlines():
if line.strip().startswith('RABBITMQ_NODENAME'):
f = True
line = 'RABBITMQ_NODENAME=%s\n' % name
out.append(line)
if not f:
out.append('RABBITMQ_NODENAME=%s\n' % name)
utils.juju_log('INFO', 'Updating %s, RABBITMQ_NODENAME=%s' %
(ENV_CONF, name))
with open(ENV_CONF, 'wb') as conf:
conf.write(''.join(out))
def get_node_name():
if not os.path.exists(ENV_CONF):
return None
env_conf = open(ENV_CONF, 'r').readlines()
node_name = None
for l in env_conf:
if l.startswith('RABBITMQ_NODENAME'):
node_name = l.split('=')[1].strip()
return node_name
def _manage_plugin(plugin, action):
os.environ['HOME'] = '/root'
_rabbitmq_plugins = \
glob.glob('/usr/lib/rabbitmq/lib/rabbitmq_server-*'
'/sbin/rabbitmq-plugins')[0]
subprocess.check_call([_rabbitmq_plugins, action, plugin])
def enable_plugin(plugin):
_manage_plugin(plugin, 'enable')
def disable_plugin(plugin):
_manage_plugin(plugin, 'disable')
ssl_key_file = "/etc/rabbitmq/rabbit-server-privkey.pem"
ssl_cert_file = "/etc/rabbitmq/rabbit-server-cert.pem"
def enable_ssl(ssl_key, ssl_cert, ssl_port):
uid = pwd.getpwnam("root").pw_uid
gid = grp.getgrnam("rabbitmq").gr_gid
with open(ssl_key_file, 'w') as key_file:
key_file.write(ssl_key)
os.chmod(ssl_key_file, 0640)
os.chown(ssl_key_file, uid, gid)
with open(ssl_cert_file, 'w') as cert_file:
cert_file.write(ssl_cert)
os.chmod(ssl_cert_file, 0640)
os.chown(ssl_cert_file, uid, gid)
with open(RABBITMQ_CONF, 'w') as rmq_conf:
rmq_conf.write(utils.render_template(os.path.basename(RABBITMQ_CONF),
{"ssl_port": ssl_port,
"ssl_cert_file": ssl_cert_file,
"ssl_key_file": ssl_key_file}))
def execute(cmd, die=False, echo=False):
""" Executes a command
if die=True, script will exit(1) if command does not return 0
if echo=True, output of command will be printed to stdout
returns a tuple: (stdout, stderr, return code)
"""
p = subprocess.Popen(cmd.split(" "),
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout = ""
stderr = ""
def print_line(l):
if echo:
print l.strip('\n')
sys.stdout.flush()
for l in iter(p.stdout.readline, ''):
print_line(l)
stdout += l
for l in iter(p.stderr.readline, ''):
print_line(l)
stderr += l
p.communicate()
rc = p.returncode
if die and rc != 0:
error_out("ERROR: command %s return non-zero.\n" % cmd)
return (stdout, stderr, rc)
def synchronize_service_credentials():
'''
Broadcast service credentials to peers or consume those that have been
broadcasted by peer, depending on hook context.
'''
if not os.path.isdir(LIB_PATH):
return
peers = cluster.peer_units()
if peers and not cluster.oldest_peer(peers):
utils.juju_log('INFO', 'Deferring action to oldest service unit.')
return
utils.juju_log('INFO', 'Synchronizing service passwords to all peers.')
unison.sync_to_peers(peer_interface='cluster',
paths=[LIB_PATH], user=SSH_USER,
verbose=True)