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

Proposed by Edward Hope-Morley
Status: Merged
Merged at revision: 46
Proposed branch: lp:~hopem/charms/trusty/openstack-dashboard/charm-helpers-sync-1396246
Merge into: lp:~openstack-charmers-archive/charms/trusty/openstack-dashboard/next
Diff against target: 196 lines (+117/-16)
4 files modified
hooks/charmhelpers/contrib/hahelpers/cluster.py (+26/-12)
hooks/charmhelpers/contrib/storage/linux/ceph.py (+43/-0)
hooks/charmhelpers/core/decorators.py (+41/-0)
hooks/charmhelpers/core/host.py (+7/-4)
To merge this branch: bzr merge lp:~hopem/charms/trusty/openstack-dashboard/charm-helpers-sync-1396246
Reviewer Review Type Date Requested Status
Corey Bryant (community) Approve
Review via email: mp+245097@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 #280 openstack-dashboard-next for hopem mp245097
    LINT OK: passed

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

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

charm_unit_test #308 openstack-dashboard-next for hopem mp245097
    UNIT OK: passed

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

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

charm_amulet_test #443 openstack-dashboard-next for hopem mp245097
    AMULET FAIL: amulet-test missing

AMULET Results (max last 2 lines):
INFO:root:Search string not found in makefile target commands.
ERROR:root:No make target was executed.

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

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-10 20:28:57 +0000
3+++ hooks/charmhelpers/contrib/hahelpers/cluster.py 2014-12-18 11:35:27 +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=== modified file 'hooks/charmhelpers/contrib/storage/linux/ceph.py'
77--- hooks/charmhelpers/contrib/storage/linux/ceph.py 2014-12-10 20:28:57 +0000
78+++ hooks/charmhelpers/contrib/storage/linux/ceph.py 2014-12-18 11:35:27 +0000
79@@ -372,3 +372,46 @@
80 return None
81 else:
82 return None
83+
84+
85+class CephBrokerRq(object):
86+ """Ceph broker request.
87+
88+ Multiple operations can be added to a request and sent to the Ceph broker
89+ to be executed.
90+
91+ Request is json-encoded for sending over the wire.
92+
93+ The API is versioned and defaults to version 1.
94+ """
95+ def __init__(self, api_version=1):
96+ self.api_version = api_version
97+ self.ops = []
98+
99+ def add_op_create_pool(self, name, replica_count=3):
100+ self.ops.append({'op': 'create-pool', 'name': name,
101+ 'replicas': replica_count})
102+
103+ @property
104+ def request(self):
105+ return json.dumps({'api-version': self.api_version, 'ops': self.ops})
106+
107+
108+class CephBrokerRsp(object):
109+ """Ceph broker response.
110+
111+ Response is json-decoded and contents provided as methods/properties.
112+
113+ The API is versioned and defaults to version 1.
114+ """
115+ def __init__(self, encoded_rsp):
116+ self.api_version = None
117+ self.rsp = json.loads(encoded_rsp)
118+
119+ @property
120+ def exit_code(self):
121+ return self.rsp.get('exit-code')
122+
123+ @property
124+ def exit_msg(self):
125+ return self.rsp.get('stderr')
126
127=== added file 'hooks/charmhelpers/core/decorators.py'
128--- hooks/charmhelpers/core/decorators.py 1970-01-01 00:00:00 +0000
129+++ hooks/charmhelpers/core/decorators.py 2014-12-18 11:35:27 +0000
130@@ -0,0 +1,41 @@
131+#
132+# Copyright 2014 Canonical Ltd.
133+#
134+# Authors:
135+# Edward Hope-Morley <opentastic@gmail.com>
136+#
137+
138+import time
139+
140+from charmhelpers.core.hookenv import (
141+ log,
142+ INFO,
143+)
144+
145+
146+def retry_on_exception(num_retries, base_delay=0, exc_type=Exception):
147+ """If the decorated function raises exception exc_type, allow num_retries
148+ retry attempts before raise the exception.
149+ """
150+ def _retry_on_exception_inner_1(f):
151+ def _retry_on_exception_inner_2(*args, **kwargs):
152+ retries = num_retries
153+ multiplier = 1
154+ while True:
155+ try:
156+ return f(*args, **kwargs)
157+ except exc_type:
158+ if not retries:
159+ raise
160+
161+ delay = base_delay * multiplier
162+ multiplier += 1
163+ log("Retrying '%s' %d more times (delay=%s)" %
164+ (f.__name__, retries, delay), level=INFO)
165+ retries -= 1
166+ if delay:
167+ time.sleep(delay)
168+
169+ return _retry_on_exception_inner_2
170+
171+ return _retry_on_exception_inner_1
172
173=== modified file 'hooks/charmhelpers/core/host.py'
174--- hooks/charmhelpers/core/host.py 2014-12-10 20:28:57 +0000
175+++ hooks/charmhelpers/core/host.py 2014-12-18 11:35:27 +0000
176@@ -162,13 +162,16 @@
177 uid = pwd.getpwnam(owner).pw_uid
178 gid = grp.getgrnam(group).gr_gid
179 realpath = os.path.abspath(path)
180- if os.path.exists(realpath):
181- if force and not os.path.isdir(realpath):
182+ path_exists = os.path.exists(realpath)
183+ if path_exists and force:
184+ if not os.path.isdir(realpath):
185 log("Removing non-directory file {} prior to mkdir()".format(path))
186 os.unlink(realpath)
187- else:
188+ os.makedirs(realpath, perms)
189+ os.chown(realpath, uid, gid)
190+ elif not path_exists:
191 os.makedirs(realpath, perms)
192- os.chown(realpath, uid, gid)
193+ os.chown(realpath, uid, gid)
194
195
196 def write_file(path, content, owner='root', group='root', perms=0o444):

Subscribers

People subscribed via source and target branches