[hopem,r=gnuoy]

Provide min-cluster-size config option to get
round clustering races until we have leadership
election support in Juju. Also ensure that
cookie is only distributed by the leader.
This commit is contained in:
Edward Hope-Morley 2015-04-20 09:20:19 +01:00
commit c499ab55cb
3 changed files with 56 additions and 2 deletions

View File

@ -166,3 +166,9 @@ options:
order for this charm to function correctly, the privacy extension must be
disabled and a non-temporary address must be configured/available on
your network interface.
min-cluster-size:
type: int
default:
description: |
Minimum number of units expected to exist before charm will attempt to
form a rabbitmq cluster.

View File

@ -194,6 +194,26 @@ def amqp_changed(relation_id=None, remote_unit=None):
relation_settings=relation_settings)
def is_sufficient_peers():
"""If min-cluster-size has been provided, check that we have sufficient
number of peers to proceed with creating rabbitmq cluster.
"""
min_size = config('min-cluster-size')
if min_size:
size = 0
for rid in relation_ids('cluster'):
size = len(related_units(rid))
# Include this unit
size += 1
if min_size > size:
log("Insufficient number of peer units to form cluster "
"(expected=%s, got=%s)" % (min_size, size), level=INFO)
return False
return True
@hooks.hook('cluster-relation-joined')
def cluster_joined(relation_id=None):
if config('prefer-ipv6'):
@ -240,8 +260,13 @@ def cluster_joined(relation_id=None):
log('erlang cookie missing from %s' % rabbit.COOKIE_PATH,
level=ERROR)
return
cookie = open(rabbit.COOKIE_PATH, 'r').read().strip()
peer_store('cookie', cookie)
if not is_sufficient_peers():
return
if is_elected_leader('res_rabbitmq_vip'):
cookie = open(rabbit.COOKIE_PATH, 'r').read().strip()
peer_store('cookie', cookie)
@hooks.hook('cluster-relation-changed')
@ -262,6 +287,11 @@ def cluster_changed():
whitelist = [a for a in rdata.keys() if a not in blacklist]
peer_echo(includes=whitelist)
if not is_sufficient_peers():
# Stop rabbit until leader has finished configuring
service_stop('rabbitmq-server')
return
# sync the cookie with peers if necessary
update_cookie()
@ -276,6 +306,7 @@ def cluster_changed():
if rabbit.cluster_with():
# resync nrpe user after clustering
update_nrpe_checks()
# If cluster has changed peer db may have changed so run amqp_changed
# to sync any changes
for rid in relation_ids('amqp'):

View File

@ -129,3 +129,20 @@ class RelationUtil(TestCase):
mock_peer_store_and_set.assert_called_with(
relation_settings={'private-address': ipv6_addr},
relation_id=None)
@patch.object(rabbitmq_server_relations, 'related_units')
@patch.object(rabbitmq_server_relations, 'relation_ids')
@patch.object(rabbitmq_server_relations, 'config')
def test_is_sufficient_peers(self, mock_config, mock_relation_ids,
mock_related_units):
_config = {'min-cluster-size': None}
mock_config.side_effect = lambda key: _config.get(key)
self.assertTrue(rabbitmq_server_relations.is_sufficient_peers())
mock_relation_ids.return_value = ['cluster:0']
mock_related_units.return_value = ['test/0']
_config = {'min-cluster-size': 3}
self.assertFalse(rabbitmq_server_relations.is_sufficient_peers())
mock_related_units.return_value = ['test/0', 'test/1']
self.assertTrue(rabbitmq_server_relations.is_sufficient_peers())