Merge lp:~hopem/charms/trusty/cinder/charm-helpers-sync-1396246 into lp:~openstack-charmers-archive/charms/trusty/cinder/next

Proposed by Edward Hope-Morley
Status: Merged
Merged at revision: 62
Proposed branch: lp:~hopem/charms/trusty/cinder/charm-helpers-sync-1396246
Merge into: lp:~openstack-charmers-archive/charms/trusty/cinder/next
Diff against target: 145 lines (+74/-16)
3 files modified
hooks/charmhelpers/contrib/hahelpers/cluster.py (+26/-12)
hooks/charmhelpers/core/decorators.py (+41/-0)
hooks/charmhelpers/core/host.py (+7/-4)
To merge this branch: bzr merge lp:~hopem/charms/trusty/cinder/charm-helpers-sync-1396246
Reviewer Review Type Date Requested Status
Corey Bryant (community) Approve
Review via email: mp+245093@code.launchpad.net
To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #276 cinder-next for hopem mp245093
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/276/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #304 cinder-next for hopem mp245093
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/304/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #439 cinder-next for hopem mp245093
    AMULET FAIL: amulet-test failed

AMULET Results (max last 2 lines):
  ERROR subprocess encountered error code 1
  make: *** [test] Error 1

Full amulet test output: http://paste.ubuntu.com/9559877/
Build: http://10.245.162.77:8080/job/charm_amulet_test/439/

Revision history for this message
Corey Bryant (corey.bryant) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hooks/charmhelpers/contrib/hahelpers/cluster.py'
2--- hooks/charmhelpers/contrib/hahelpers/cluster.py 2014-12-15 09:57:32 +0000
3+++ hooks/charmhelpers/contrib/hahelpers/cluster.py 2014-12-18 11:34:14 +0000
4@@ -13,6 +13,7 @@
5
6 import subprocess
7 import os
8+
9 from socket import gethostname as get_unit_hostname
10
11 import six
12@@ -28,12 +29,19 @@
13 WARNING,
14 unit_get,
15 )
16+from charmhelpers.core.decorators import (
17+ retry_on_exception,
18+)
19
20
21 class HAIncompleteConfig(Exception):
22 pass
23
24
25+class CRMResourceNotFound(Exception):
26+ pass
27+
28+
29 def is_elected_leader(resource):
30 """
31 Returns True if the charm executing this is the elected cluster leader.
32@@ -68,24 +76,30 @@
33 return False
34
35
36-def is_crm_leader(resource):
37+@retry_on_exception(5, base_delay=2, exc_type=CRMResourceNotFound)
38+def is_crm_leader(resource, retry=False):
39 """
40 Returns True if the charm calling this is the elected corosync leader,
41 as returned by calling the external "crm" command.
42+
43+ We allow this operation to be retried to avoid the possibility of getting a
44+ false negative. See LP #1396246 for more info.
45 """
46- cmd = [
47- "crm", "resource",
48- "show", resource
49- ]
50+ cmd = ['crm', 'resource', 'show', resource]
51 try:
52- status = subprocess.check_output(cmd).decode('UTF-8')
53+ status = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
54+ if not isinstance(status, six.text_type):
55+ status = six.text_type(status, "utf-8")
56 except subprocess.CalledProcessError:
57- return False
58- else:
59- if get_unit_hostname() in status:
60- return True
61- else:
62- return False
63+ status = None
64+
65+ if status and get_unit_hostname() in status:
66+ return True
67+
68+ if status and "resource %s is NOT running" % (resource) in status:
69+ raise CRMResourceNotFound("CRM resource %s not found" % (resource))
70+
71+ return False
72
73
74 def is_leader(resource):
75
76=== added file 'hooks/charmhelpers/core/decorators.py'
77--- hooks/charmhelpers/core/decorators.py 1970-01-01 00:00:00 +0000
78+++ hooks/charmhelpers/core/decorators.py 2014-12-18 11:34:14 +0000
79@@ -0,0 +1,41 @@
80+#
81+# Copyright 2014 Canonical Ltd.
82+#
83+# Authors:
84+# Edward Hope-Morley <opentastic@gmail.com>
85+#
86+
87+import time
88+
89+from charmhelpers.core.hookenv import (
90+ log,
91+ INFO,
92+)
93+
94+
95+def retry_on_exception(num_retries, base_delay=0, exc_type=Exception):
96+ """If the decorated function raises exception exc_type, allow num_retries
97+ retry attempts before raise the exception.
98+ """
99+ def _retry_on_exception_inner_1(f):
100+ def _retry_on_exception_inner_2(*args, **kwargs):
101+ retries = num_retries
102+ multiplier = 1
103+ while True:
104+ try:
105+ return f(*args, **kwargs)
106+ except exc_type:
107+ if not retries:
108+ raise
109+
110+ delay = base_delay * multiplier
111+ multiplier += 1
112+ log("Retrying '%s' %d more times (delay=%s)" %
113+ (f.__name__, retries, delay), level=INFO)
114+ retries -= 1
115+ if delay:
116+ time.sleep(delay)
117+
118+ return _retry_on_exception_inner_2
119+
120+ return _retry_on_exception_inner_1
121
122=== modified file 'hooks/charmhelpers/core/host.py'
123--- hooks/charmhelpers/core/host.py 2014-12-15 10:17:11 +0000
124+++ hooks/charmhelpers/core/host.py 2014-12-18 11:34:14 +0000
125@@ -162,13 +162,16 @@
126 uid = pwd.getpwnam(owner).pw_uid
127 gid = grp.getgrnam(group).gr_gid
128 realpath = os.path.abspath(path)
129- if os.path.exists(realpath):
130- if force and not os.path.isdir(realpath):
131+ path_exists = os.path.exists(realpath)
132+ if path_exists and force:
133+ if not os.path.isdir(realpath):
134 log("Removing non-directory file {} prior to mkdir()".format(path))
135 os.unlink(realpath)
136- else:
137+ os.makedirs(realpath, perms)
138+ os.chown(realpath, uid, gid)
139+ elif not path_exists:
140 os.makedirs(realpath, perms)
141- os.chown(realpath, uid, gid)
142+ os.chown(realpath, uid, gid)
143
144
145 def write_file(path, content, owner='root', group='root', perms=0o444):

Subscribers

People subscribed via source and target branches