~james-page/charms/trusty/ceilometer/tox

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/contrib/hahelpers/cluster.py

  • Committer: james.page at ubuntu
  • Date: 2015-06-09 09:52:34 UTC
  • mfrom: (71.1.16 ceilometer)
  • Revision ID: james.page@ubuntu.com-20150609095234-4lh9wjhjjso5bszo
Add support for leader-election

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
    ERROR,
45
45
    WARNING,
46
46
    unit_get,
 
47
    is_leader as juju_is_leader
47
48
)
48
49
from charmhelpers.core.decorators import (
49
50
    retry_on_exception,
52
53
    bool_from_string,
53
54
)
54
55
 
 
56
DC_RESOURCE_NAME = 'DC'
 
57
 
55
58
 
56
59
class HAIncompleteConfig(Exception):
57
60
    pass
66
69
    Returns True if the charm executing this is the elected cluster leader.
67
70
 
68
71
    It relies on two mechanisms to determine leadership:
69
 
        1. If the charm is part of a corosync cluster, call corosync to
 
72
        1. If juju is sufficiently new and leadership election is supported,
 
73
        the is_leader command will be used.
 
74
        2. If the charm is part of a corosync cluster, call corosync to
70
75
        determine leadership.
71
 
        2. If the charm is not part of a corosync cluster, the leader is
 
76
        3. If the charm is not part of a corosync cluster, the leader is
72
77
        determined as being "the alive unit with the lowest unit numer". In
73
78
        other words, the oldest surviving unit.
74
79
    """
 
80
    try:
 
81
        return juju_is_leader()
 
82
    except NotImplementedError:
 
83
        log('Juju leadership election feature not enabled'
 
84
            ', using fallback support',
 
85
            level=WARNING)
 
86
 
75
87
    if is_clustered():
76
88
        if not is_crm_leader(resource):
77
89
            log('Deferring action to CRM leader.', level=INFO)
95
107
    return False
96
108
 
97
109
 
 
110
def is_crm_dc():
 
111
    """
 
112
    Determine leadership by querying the pacemaker Designated Controller
 
113
    """
 
114
    cmd = ['crm', 'status']
 
115
    try:
 
116
        status = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
 
117
        if not isinstance(status, six.text_type):
 
118
            status = six.text_type(status, "utf-8")
 
119
    except subprocess.CalledProcessError:
 
120
        return False
 
121
    current_dc = ''
 
122
    for line in status.split('\n'):
 
123
        if line.startswith('Current DC'):
 
124
            # Current DC: juju-lytrusty-machine-2 (168108163) - partition with quorum
 
125
            current_dc = line.split(':')[1].split()[0]
 
126
    if current_dc == get_unit_hostname():
 
127
        return True
 
128
    return False
 
129
 
 
130
 
98
131
@retry_on_exception(5, base_delay=2, exc_type=CRMResourceNotFound)
99
132
def is_crm_leader(resource, retry=False):
100
133
    """
104
137
    We allow this operation to be retried to avoid the possibility of getting a
105
138
    false negative. See LP #1396246 for more info.
106
139
    """
 
140
    if resource == DC_RESOURCE_NAME:
 
141
        return is_crm_dc()
107
142
    cmd = ['crm', 'resource', 'show', resource]
108
143
    try:
109
144
        status = subprocess.check_output(cmd, stderr=subprocess.STDOUT)