Charmsync Leadership election
This commit is contained in:
parent
ce9668fcf8
commit
696d32ae02
@ -1,4 +1,4 @@
|
||||
branch: lp:charm-helpers
|
||||
branch: lp:~le-charmers/charm-helpers/leadership-election
|
||||
destination: hooks/charmhelpers
|
||||
include:
|
||||
- core
|
||||
|
@ -44,6 +44,7 @@ from charmhelpers.core.hookenv import (
|
||||
ERROR,
|
||||
WARNING,
|
||||
unit_get,
|
||||
is_leader as juju_is_leader
|
||||
)
|
||||
from charmhelpers.core.decorators import (
|
||||
retry_on_exception,
|
||||
@ -66,12 +67,18 @@ def is_elected_leader(resource):
|
||||
Returns True if the charm executing this is the elected cluster leader.
|
||||
|
||||
It relies on two mechanisms to determine leadership:
|
||||
1. If the charm is part of a corosync cluster, call corosync to
|
||||
1. If juju is sufficiently new and leadership election is supported,
|
||||
the is_leader command will be used.
|
||||
2. If the charm is part of a corosync cluster, call corosync to
|
||||
determine leadership.
|
||||
2. If the charm is not part of a corosync cluster, the leader is
|
||||
3. If the charm is not part of a corosync cluster, the leader is
|
||||
determined as being "the alive unit with the lowest unit numer". In
|
||||
other words, the oldest surviving unit.
|
||||
"""
|
||||
try:
|
||||
return juju_is_leader()
|
||||
except NotImplementedError:
|
||||
pass
|
||||
if is_clustered():
|
||||
if not is_crm_leader(resource):
|
||||
log('Deferring action to CRM leader.', level=INFO)
|
||||
|
@ -19,9 +19,11 @@ from charmhelpers.core.hookenv import relation_id as current_relation_id
|
||||
from charmhelpers.core.hookenv import (
|
||||
is_relation_made,
|
||||
relation_ids,
|
||||
relation_get,
|
||||
relation_get as _relation_get,
|
||||
local_unit,
|
||||
relation_set,
|
||||
relation_set as _relation_set,
|
||||
leader_get,
|
||||
leader_set,
|
||||
)
|
||||
|
||||
|
||||
@ -54,6 +56,26 @@ def some_hook():
|
||||
"""
|
||||
|
||||
|
||||
def relation_set(relation_settings=None, relation_id=None, **kwargs):
|
||||
try:
|
||||
if relation_id and relation_id in relation_ids('cluster'):
|
||||
return leader_set(settings=relation_settings, **kwargs)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
except NotImplementedError:
|
||||
return _relation_set(relation_settings=relation_settings, **kwargs)
|
||||
|
||||
|
||||
def relation_get(attribute=None, rid=None, unit=None):
|
||||
try:
|
||||
if relation_id and relation_id in relation_ids('cluster'):
|
||||
return leader_get(attribute)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
except NotImplementedError:
|
||||
return _relation_get(attribute=attribute, rid=rid, unit=unit)
|
||||
|
||||
|
||||
def peer_retrieve(key, relation_name='cluster'):
|
||||
"""Retrieve a named key from peer relation `relation_name`."""
|
||||
cluster_rels = relation_ids(relation_name)
|
||||
|
@ -566,3 +566,62 @@ class Hooks(object):
|
||||
def charm_dir():
|
||||
"""Return the root directory of the current charm"""
|
||||
return os.environ.get('CHARM_DIR')
|
||||
|
||||
|
||||
def translate_exc(from_exc, to_exc):
|
||||
def inner_translate_exc1(f):
|
||||
def inner_translate_exc2(*args, **kwargs):
|
||||
try:
|
||||
return f(*args, **kwargs)
|
||||
except from_exc:
|
||||
raise to_exc
|
||||
|
||||
return inner_translate_exc2
|
||||
|
||||
return inner_translate_exc1
|
||||
|
||||
|
||||
@translate_exc(from_exc=CalledProcessError, to_exc=NotImplementedError)
|
||||
def is_leader():
|
||||
"""Does the current unit hold the juju leadership
|
||||
|
||||
Uses juju to determine whether the current unit is the leader of its peers
|
||||
"""
|
||||
try:
|
||||
leader = json.loads(
|
||||
subprocess.check_output(['is-leader', '--format=json'])
|
||||
)
|
||||
return (leader is True)
|
||||
except ValueError:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@cached
|
||||
@translate_exc(from_exc=CalledProcessError, to_exc=NotImplementedError)
|
||||
def leader_get(attribute=None):
|
||||
"""Juju leader get value(s)"""
|
||||
cmd = ['leader-get', '--format=json'] + [attribute or '-']
|
||||
try:
|
||||
return json.loads(subprocess.check_output(cmd).decode('UTF-8'))
|
||||
except ValueError:
|
||||
return None
|
||||
except CalledProcessError as e:
|
||||
if e.returncode == 2:
|
||||
return None
|
||||
|
||||
raise
|
||||
|
||||
|
||||
@translate_exc(from_exc=CalledProcessError, to_exc=NotImplementedError)
|
||||
def leader_set(settings=None, **kwargs):
|
||||
"""Juju leader set value(s)"""
|
||||
cmd = ['leader-set']
|
||||
settings = settings or {}
|
||||
settings.update(kwargs)
|
||||
for k, v in settings.iteritems():
|
||||
if v is None:
|
||||
cmd.append('{}='.format(k))
|
||||
else:
|
||||
cmd.append('{}={}'.format(k, v))
|
||||
|
||||
subprocess.check_call(cmd)
|
||||
|
Loading…
x
Reference in New Issue
Block a user