Merge lp:~gnuoy/charm-helpers/stable-dc-leader into lp:~openstack-charmers/charm-helpers/stable-1604

Proposed by Liam Young
Status: Merged
Merged at revision: 366
Proposed branch: lp:~gnuoy/charm-helpers/stable-dc-leader
Merge into: lp:~openstack-charmers/charm-helpers/stable-1604
Diff against target: 118 lines (+69/-0)
2 files modified
charmhelpers/contrib/hahelpers/cluster.py (+25/-0)
tests/contrib/hahelpers/test_cluster_utils.py (+44/-0)
To merge this branch: bzr merge lp:~gnuoy/charm-helpers/stable-dc-leader
Reviewer Review Type Date Requested Status
James Page Approve
Review via email: mp+259216@code.launchpad.net
To post a comment you must log in.
367. By Liam Young

Fix is_crm_dc return false if the cluster is not yet formed as it is not leader if there is no cluster up

Revision history for this message
James Page (james-page) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'charmhelpers/contrib/hahelpers/cluster.py'
2--- charmhelpers/contrib/hahelpers/cluster.py 2015-02-16 14:26:57 +0000
3+++ charmhelpers/contrib/hahelpers/cluster.py 2015-05-15 09:44:38 +0000
4@@ -52,6 +52,8 @@
5 bool_from_string,
6 )
7
8+DC_RESOURCE_NAME = 'DC'
9+
10
11 class HAIncompleteConfig(Exception):
12 pass
13@@ -95,6 +97,27 @@
14 return False
15
16
17+def is_crm_dc():
18+ """
19+ Determine leadership by querying the pacemaker Designated Controller
20+ """
21+ cmd = ['crm', 'status']
22+ try:
23+ status = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
24+ if not isinstance(status, six.text_type):
25+ status = six.text_type(status, "utf-8")
26+ except subprocess.CalledProcessError:
27+ return False
28+ current_dc = ''
29+ for line in status.split('\n'):
30+ if line.startswith('Current DC'):
31+ # Current DC: juju-lytrusty-machine-2 (168108163) - partition with quorum
32+ current_dc = line.split(':')[1].split()[0]
33+ if current_dc == get_unit_hostname():
34+ return True
35+ return False
36+
37+
38 @retry_on_exception(5, base_delay=2, exc_type=CRMResourceNotFound)
39 def is_crm_leader(resource, retry=False):
40 """
41@@ -104,6 +127,8 @@
42 We allow this operation to be retried to avoid the possibility of getting a
43 false negative. See LP #1396246 for more info.
44 """
45+ if resource == DC_RESOURCE_NAME:
46+ return is_crm_dc()
47 cmd = ['crm', 'resource', 'show', resource]
48 try:
49 status = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
50
51=== modified file 'tests/contrib/hahelpers/test_cluster_utils.py'
52--- tests/contrib/hahelpers/test_cluster_utils.py 2015-01-06 15:28:29 +0000
53+++ tests/contrib/hahelpers/test_cluster_utils.py 2015-05-15 09:44:38 +0000
54@@ -6,6 +6,24 @@
55
56 import charmhelpers.contrib.hahelpers.cluster as cluster_utils
57
58+CRM_STATUS = b'''
59+Last updated: Thu May 14 14:46:35 2015
60+Last change: Thu May 14 14:43:51 2015 via crmd on juju-trusty-machine-1
61+Stack: corosync
62+Current DC: juju-trusty-machine-2 (168108171) - partition with quorum
63+Version: 1.1.10-42f2063
64+3 Nodes configured
65+4 Resources configured
66+
67+
68+Online: [ juju-trusty-machine-1 juju-trusty-machine-2 juju-trusty-machine-3 ]
69+
70+ Resource Group: grp_percona_cluster
71+ res_mysql_vip (ocf::heartbeat:IPaddr2): Started juju-trusty-machine-1
72+ Clone Set: cl_mysql_monitor [res_mysql_monitor]
73+ Started: [ juju-trusty-machine-1 juju-trusty-machine-2 juju-trusty-machine-3 ]
74+'''
75+
76
77 class ClusterUtilsTests(TestCase):
78 def setUp(self):
79@@ -41,6 +59,26 @@
80 self.assertFalse(cluster_utils.is_clustered())
81
82 @patch('subprocess.check_output')
83+ def test_is_crm_dc(self, check_output):
84+ '''It determines its unit is leader'''
85+ self.get_unit_hostname.return_value = 'juju-trusty-machine-2'
86+ check_output.return_value = CRM_STATUS
87+ self.assertTrue(cluster_utils.is_crm_dc())
88+
89+ @patch('subprocess.check_output')
90+ def test_is_crm_dc_no_cluster(self, check_output):
91+ '''It is not leader if there is no cluster up'''
92+ check_output.side_effect = CalledProcessError(1, 'crm')
93+ self.assertFalse(cluster_utils.is_crm_dc())
94+
95+ @patch('subprocess.check_output')
96+ def test_is_crm_dc_false(self, check_output):
97+ '''It determines its unit is leader'''
98+ self.get_unit_hostname.return_value = 'juju-trusty-machine-1'
99+ check_output.return_value = CRM_STATUS
100+ self.assertFalse(cluster_utils.is_crm_dc())
101+
102+ @patch('subprocess.check_output')
103 def test_is_crm_leader(self, check_output):
104 '''It determines its unit is leader'''
105 self.get_unit_hostname.return_value = 'node1'
106@@ -79,6 +117,12 @@
107 self.assertFalse(cluster_utils.is_crm_leader('vip'))
108 self.assertFalse(mock_time.called)
109
110+ @patch.object(cluster_utils, 'is_crm_dc')
111+ def test_is_crm_leader_dc_resource(self, _is_crm_dc):
112+ '''Call out to is_crm_dc'''
113+ cluster_utils.is_crm_leader(cluster_utils.DC_RESOURCE_NAME)
114+ _is_crm_dc.assert_called_with()
115+
116 def test_peer_units(self):
117 '''It lists all peer units for cluster relation'''
118 peers = ['peer_node/1', 'peer_node/2']

Subscribers

People subscribed via source and target branches