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

Proposed by Edward Hope-Morley
Status: Merged
Merged at revision: 66
Proposed branch: lp:~hopem/charms/trusty/neutron-api/charm-helpers-sync-1396246
Merge into: lp:~openstack-charmers-archive/charms/trusty/neutron-api/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/neutron-api/charm-helpers-sync-1396246
Reviewer Review Type Date Requested Status
Corey Bryant (community) Approve
Review via email: mp+245096@code.launchpad.net
To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #307 neutron-api-next for hopem mp245096
    UNIT OK: passed

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

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

charm_lint_check #279 neutron-api-next for hopem mp245096
    LINT OK: passed

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

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

charm_amulet_test #442 neutron-api-next for hopem mp245096
    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/9559883/
Build: http://10.245.162.77:8080/job/charm_amulet_test/442/

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
=== modified file 'hooks/charmhelpers/contrib/hahelpers/cluster.py'
--- hooks/charmhelpers/contrib/hahelpers/cluster.py 2014-12-10 20:28:52 +0000
+++ hooks/charmhelpers/contrib/hahelpers/cluster.py 2014-12-18 11:34:57 +0000
@@ -13,6 +13,7 @@
1313
14import subprocess14import subprocess
15import os15import os
16
16from socket import gethostname as get_unit_hostname17from socket import gethostname as get_unit_hostname
1718
18import six19import six
@@ -28,12 +29,19 @@
28 WARNING,29 WARNING,
29 unit_get,30 unit_get,
30)31)
32from charmhelpers.core.decorators import (
33 retry_on_exception,
34)
3135
3236
33class HAIncompleteConfig(Exception):37class HAIncompleteConfig(Exception):
34 pass38 pass
3539
3640
41class CRMResourceNotFound(Exception):
42 pass
43
44
37def is_elected_leader(resource):45def is_elected_leader(resource):
38 """46 """
39 Returns True if the charm executing this is the elected cluster leader.47 Returns True if the charm executing this is the elected cluster leader.
@@ -68,24 +76,30 @@
68 return False76 return False
6977
7078
71def is_crm_leader(resource):79@retry_on_exception(5, base_delay=2, exc_type=CRMResourceNotFound)
80def is_crm_leader(resource, retry=False):
72 """81 """
73 Returns True if the charm calling this is the elected corosync leader,82 Returns True if the charm calling this is the elected corosync leader,
74 as returned by calling the external "crm" command.83 as returned by calling the external "crm" command.
84
85 We allow this operation to be retried to avoid the possibility of getting a
86 false negative. See LP #1396246 for more info.
75 """87 """
76 cmd = [88 cmd = ['crm', 'resource', 'show', resource]
77 "crm", "resource",
78 "show", resource
79 ]
80 try:89 try:
81 status = subprocess.check_output(cmd).decode('UTF-8')90 status = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
91 if not isinstance(status, six.text_type):
92 status = six.text_type(status, "utf-8")
82 except subprocess.CalledProcessError:93 except subprocess.CalledProcessError:
83 return False94 status = None
84 else:95
85 if get_unit_hostname() in status:96 if status and get_unit_hostname() in status:
86 return True97 return True
87 else:98
88 return False99 if status and "resource %s is NOT running" % (resource) in status:
100 raise CRMResourceNotFound("CRM resource %s not found" % (resource))
101
102 return False
89103
90104
91def is_leader(resource):105def is_leader(resource):
92106
=== modified file 'hooks/charmhelpers/contrib/storage/linux/ceph.py'
--- hooks/charmhelpers/contrib/storage/linux/ceph.py 2014-12-10 20:28:52 +0000
+++ hooks/charmhelpers/contrib/storage/linux/ceph.py 2014-12-18 11:34:57 +0000
@@ -372,3 +372,46 @@
372 return None372 return None
373 else:373 else:
374 return None374 return None
375
376
377class CephBrokerRq(object):
378 """Ceph broker request.
379
380 Multiple operations can be added to a request and sent to the Ceph broker
381 to be executed.
382
383 Request is json-encoded for sending over the wire.
384
385 The API is versioned and defaults to version 1.
386 """
387 def __init__(self, api_version=1):
388 self.api_version = api_version
389 self.ops = []
390
391 def add_op_create_pool(self, name, replica_count=3):
392 self.ops.append({'op': 'create-pool', 'name': name,
393 'replicas': replica_count})
394
395 @property
396 def request(self):
397 return json.dumps({'api-version': self.api_version, 'ops': self.ops})
398
399
400class CephBrokerRsp(object):
401 """Ceph broker response.
402
403 Response is json-decoded and contents provided as methods/properties.
404
405 The API is versioned and defaults to version 1.
406 """
407 def __init__(self, encoded_rsp):
408 self.api_version = None
409 self.rsp = json.loads(encoded_rsp)
410
411 @property
412 def exit_code(self):
413 return self.rsp.get('exit-code')
414
415 @property
416 def exit_msg(self):
417 return self.rsp.get('stderr')
375418
=== added file 'hooks/charmhelpers/core/decorators.py'
--- hooks/charmhelpers/core/decorators.py 1970-01-01 00:00:00 +0000
+++ hooks/charmhelpers/core/decorators.py 2014-12-18 11:34:57 +0000
@@ -0,0 +1,41 @@
1#
2# Copyright 2014 Canonical Ltd.
3#
4# Authors:
5# Edward Hope-Morley <opentastic@gmail.com>
6#
7
8import time
9
10from charmhelpers.core.hookenv import (
11 log,
12 INFO,
13)
14
15
16def retry_on_exception(num_retries, base_delay=0, exc_type=Exception):
17 """If the decorated function raises exception exc_type, allow num_retries
18 retry attempts before raise the exception.
19 """
20 def _retry_on_exception_inner_1(f):
21 def _retry_on_exception_inner_2(*args, **kwargs):
22 retries = num_retries
23 multiplier = 1
24 while True:
25 try:
26 return f(*args, **kwargs)
27 except exc_type:
28 if not retries:
29 raise
30
31 delay = base_delay * multiplier
32 multiplier += 1
33 log("Retrying '%s' %d more times (delay=%s)" %
34 (f.__name__, retries, delay), level=INFO)
35 retries -= 1
36 if delay:
37 time.sleep(delay)
38
39 return _retry_on_exception_inner_2
40
41 return _retry_on_exception_inner_1
042
=== modified file 'hooks/charmhelpers/core/host.py'
--- hooks/charmhelpers/core/host.py 2014-12-10 20:28:52 +0000
+++ hooks/charmhelpers/core/host.py 2014-12-18 11:34:57 +0000
@@ -162,13 +162,16 @@
162 uid = pwd.getpwnam(owner).pw_uid162 uid = pwd.getpwnam(owner).pw_uid
163 gid = grp.getgrnam(group).gr_gid163 gid = grp.getgrnam(group).gr_gid
164 realpath = os.path.abspath(path)164 realpath = os.path.abspath(path)
165 if os.path.exists(realpath):165 path_exists = os.path.exists(realpath)
166 if force and not os.path.isdir(realpath):166 if path_exists and force:
167 if not os.path.isdir(realpath):
167 log("Removing non-directory file {} prior to mkdir()".format(path))168 log("Removing non-directory file {} prior to mkdir()".format(path))
168 os.unlink(realpath)169 os.unlink(realpath)
169 else:170 os.makedirs(realpath, perms)
171 os.chown(realpath, uid, gid)
172 elif not path_exists:
170 os.makedirs(realpath, perms)173 os.makedirs(realpath, perms)
171 os.chown(realpath, uid, gid)174 os.chown(realpath, uid, gid)
172175
173176
174def write_file(path, content, owner='root', group='root', perms=0o444):177def write_file(path, content, owner='root', group='root', perms=0o444):

Subscribers

People subscribed via source and target branches