Merge lp:~hopem/charms/trusty/percona-cluster/fix-peerstore-passwd-lp1451890-stable-backport into lp:~openstack-charmers-archive/charms/trusty/percona-cluster/trunk

Proposed by Edward Hope-Morley
Status: Merged
Merged at revision: 58
Proposed branch: lp:~hopem/charms/trusty/percona-cluster/fix-peerstore-passwd-lp1451890-stable-backport
Merge into: lp:~openstack-charmers-archive/charms/trusty/percona-cluster/trunk
Diff against target: 330 lines (+109/-27)
10 files modified
charm-helpers.yaml (+1/-1)
hooks/charmhelpers/contrib/charmsupport/nrpe.py (+3/-1)
hooks/charmhelpers/contrib/database/mysql.py (+32/-11)
hooks/charmhelpers/core/hookenv.py (+40/-1)
hooks/charmhelpers/core/host.py (+5/-1)
hooks/charmhelpers/core/services/helpers.py (+2/-2)
hooks/charmhelpers/core/strutils.py (+2/-2)
hooks/charmhelpers/core/unitdata.py (+1/-1)
tests/charmhelpers/contrib/amulet/utils.py (+8/-1)
tests/charmhelpers/contrib/openstack/amulet/deployment.py (+15/-6)
To merge this branch: bzr merge lp:~hopem/charms/trusty/percona-cluster/fix-peerstore-passwd-lp1451890-stable-backport
Reviewer Review Type Date Requested Status
Liam Young (community) Approve
Review via email: mp+258416@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 #4138 percona-cluster for hopem mp258416
    UNIT OK: passed

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

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

charm_lint_check #4413 percona-cluster for hopem mp258416
    LINT FAIL: lint-test failed

LINT Results (max last 2 lines):
make: *** [lint] Error 1
ERROR:root:Make target returned non-zero.

Full lint test output: http://paste.ubuntu.com/10998254/
Build: http://10.245.162.77:8080/job/charm_lint_check/4413/

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

charm_amulet_test #4012 percona-cluster for hopem mp258416
    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/10998257/
Build: http://10.245.162.77:8080/job/charm_amulet_test/4012/

Revision history for this message
Liam Young (gnuoy) wrote :

Approve

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'charm-helpers.yaml'
2--- charm-helpers.yaml 2015-04-24 10:07:10 +0000
3+++ charm-helpers.yaml 2015-05-06 17:02:00 +0000
4@@ -1,4 +1,4 @@
5-branch: lp:~openstack-charmers/charm-helpers/stable
6+branch: lp:~hopem/charm-helpers/fix-peerstore-passwd-lp1451890-stable-backport
7 destination: hooks/charmhelpers
8 include:
9 - core
10
11=== modified file 'hooks/charmhelpers/contrib/charmsupport/nrpe.py'
12--- hooks/charmhelpers/contrib/charmsupport/nrpe.py 2015-02-20 00:30:39 +0000
13+++ hooks/charmhelpers/contrib/charmsupport/nrpe.py 2015-05-06 17:02:00 +0000
14@@ -247,7 +247,9 @@
15
16 service('restart', 'nagios-nrpe-server')
17
18- for rid in relation_ids("local-monitors"):
19+ monitor_ids = relation_ids("local-monitors") + \
20+ relation_ids("nrpe-external-master")
21+ for rid in monitor_ids:
22 relation_set(relation_id=rid, monitors=yaml.dump(monitors))
23
24
25
26=== modified file 'hooks/charmhelpers/contrib/database/mysql.py'
27--- hooks/charmhelpers/contrib/database/mysql.py 2015-04-21 09:29:08 +0000
28+++ hooks/charmhelpers/contrib/database/mysql.py 2015-05-06 17:02:00 +0000
29@@ -6,7 +6,7 @@
30 import os
31 import glob
32
33-from string import upper
34+# from string import upper
35
36 from charmhelpers.core.host import (
37 mkdir,
38@@ -21,6 +21,7 @@
39 log,
40 DEBUG,
41 INFO,
42+ WARNING,
43 )
44 from charmhelpers.fetch import (
45 apt_install,
46@@ -142,12 +143,13 @@
47 log("Excluding %s from peer migration" % (f), level=DEBUG)
48 continue
49
50- _key = os.path.basename(f)
51+ key = os.path.basename(f)
52 with open(f, 'r') as passwd:
53 _value = passwd.read().strip()
54
55 try:
56- peer_store(_key, _value)
57+ peer_store(key, _value)
58+
59 if self.delete_ondisk_passwd_file:
60 os.unlink(f)
61 except ValueError:
62@@ -185,19 +187,38 @@
63
64 return _password
65
66+ def passwd_keys(self, username):
67+ """Generator to return keys used to store passwords in peer store.
68+
69+ NOTE: we support both legacy and new format to support mysql
70+ charm prior to refactor. This is necessary to avoid LP 1451890.
71+ """
72+ keys = []
73+ if username == 'mysql':
74+ log("Bad username '%s'" % (username), level=WARNING)
75+
76+ if username:
77+ # IMPORTANT: *newer* format must be returned first
78+ keys.append('mysql-%s.passwd' % (username))
79+ keys.append('%s.passwd' % (username))
80+ else:
81+ keys.append('mysql.passwd')
82+
83+ for key in keys:
84+ yield key
85+
86 def get_mysql_password(self, username=None, password=None):
87 """Retrieve, generate or store a mysql password for the provided
88 username using peer relation cluster."""
89 excludes = []
90
91- # First check peer relation
92- if username:
93- _key = 'mysql-{}.passwd'.format(username)
94- else:
95- _key = 'mysql.passwd'
96-
97+ # First check peer relation.
98 try:
99- _password = peer_retrieve(_key)
100+ for key in self.passwd_keys(username):
101+ _password = peer_retrieve(key)
102+ if _password:
103+ break
104+
105 # If root password available don't update peer relation from local
106 if _password and not username:
107 excludes.append(self.root_passwd_file_template)
108@@ -348,7 +369,7 @@
109 key, mem = line.split(':', 2)
110 if key == 'MemTotal':
111 mtot, modifier = mem.strip().split(' ')
112- return '%s%s' % (mtot, upper(modifier[0]))
113+ return '%s%s' % (mtot, modifier[0].upper())
114
115 def parse_config(self):
116 """Parse charm configuration and calculate values for config files."""
117
118=== modified file 'hooks/charmhelpers/core/hookenv.py'
119--- hooks/charmhelpers/core/hookenv.py 2015-02-04 18:56:00 +0000
120+++ hooks/charmhelpers/core/hookenv.py 2015-05-06 17:02:00 +0000
121@@ -20,11 +20,13 @@
122 # Authors:
123 # Charm Helpers Developers <juju@lists.ubuntu.com>
124
125+from __future__ import print_function
126 import os
127 import json
128 import yaml
129 import subprocess
130 import sys
131+import errno
132 from subprocess import CalledProcessError
133
134 import six
135@@ -87,7 +89,18 @@
136 if not isinstance(message, six.string_types):
137 message = repr(message)
138 command += [message]
139- subprocess.call(command)
140+ # Missing juju-log should not cause failures in unit tests
141+ # Send log output to stderr
142+ try:
143+ subprocess.call(command)
144+ except OSError as e:
145+ if e.errno == errno.ENOENT:
146+ if level:
147+ message = "{}: {}".format(level, message)
148+ message = "juju-log: {}".format(message)
149+ print(message, file=sys.stderr)
150+ else:
151+ raise
152
153
154 class Serializable(UserDict):
155@@ -566,3 +579,29 @@
156 def charm_dir():
157 """Return the root directory of the current charm"""
158 return os.environ.get('CHARM_DIR')
159+
160+
161+@cached
162+def action_get(key=None):
163+ """Gets the value of an action parameter, or all key/value param pairs"""
164+ cmd = ['action-get']
165+ if key is not None:
166+ cmd.append(key)
167+ cmd.append('--format=json')
168+ action_data = json.loads(subprocess.check_output(cmd).decode('UTF-8'))
169+ return action_data
170+
171+
172+def action_set(values):
173+ """Sets the values to be returned after the action finishes"""
174+ cmd = ['action-set']
175+ for k, v in list(values.items()):
176+ cmd.append('{}={}'.format(k, v))
177+ subprocess.check_call(cmd)
178+
179+
180+def action_fail(message):
181+ """Sets the action status to failed and sets the error message.
182+
183+ The results set by action_set are preserved."""
184+ subprocess.check_call(['action-fail', message])
185
186=== modified file 'hooks/charmhelpers/core/host.py'
187--- hooks/charmhelpers/core/host.py 2015-03-03 02:26:12 +0000
188+++ hooks/charmhelpers/core/host.py 2015-05-06 17:02:00 +0000
189@@ -339,12 +339,16 @@
190 def pwgen(length=None):
191 """Generate a random pasword."""
192 if length is None:
193+ # A random length is ok to use a weak PRNG
194 length = random.choice(range(35, 45))
195 alphanumeric_chars = [
196 l for l in (string.ascii_letters + string.digits)
197 if l not in 'l0QD1vAEIOUaeiou']
198+ # Use a crypto-friendly PRNG (e.g. /dev/urandom) for making the
199+ # actual password
200+ random_generator = random.SystemRandom()
201 random_chars = [
202- random.choice(alphanumeric_chars) for _ in range(length)]
203+ random_generator.choice(alphanumeric_chars) for _ in range(length)]
204 return(''.join(random_chars))
205
206
207
208=== modified file 'hooks/charmhelpers/core/services/helpers.py'
209--- hooks/charmhelpers/core/services/helpers.py 2015-03-03 02:26:12 +0000
210+++ hooks/charmhelpers/core/services/helpers.py 2015-05-06 17:02:00 +0000
211@@ -139,7 +139,7 @@
212
213 def __init__(self, *args, **kwargs):
214 self.required_keys = ['host', 'user', 'password', 'database']
215- super(HttpRelation).__init__(self, *args, **kwargs)
216+ RelationContext.__init__(self, *args, **kwargs)
217
218
219 class HttpRelation(RelationContext):
220@@ -154,7 +154,7 @@
221
222 def __init__(self, *args, **kwargs):
223 self.required_keys = ['host', 'port']
224- super(HttpRelation).__init__(self, *args, **kwargs)
225+ RelationContext.__init__(self, *args, **kwargs)
226
227 def provide_data(self):
228 return {
229
230=== modified file 'hooks/charmhelpers/core/strutils.py'
231--- hooks/charmhelpers/core/strutils.py 2015-02-25 17:29:36 +0000
232+++ hooks/charmhelpers/core/strutils.py 2015-05-06 17:02:00 +0000
233@@ -33,9 +33,9 @@
234
235 value = value.strip().lower()
236
237- if value in ['y', 'yes', 'true', 't']:
238+ if value in ['y', 'yes', 'true', 't', 'on']:
239 return True
240- elif value in ['n', 'no', 'false', 'f']:
241+ elif value in ['n', 'no', 'false', 'f', 'off']:
242 return False
243
244 msg = "Unable to interpret string value '%s' as boolean" % (value)
245
246=== modified file 'hooks/charmhelpers/core/unitdata.py'
247--- hooks/charmhelpers/core/unitdata.py 2015-02-25 17:29:36 +0000
248+++ hooks/charmhelpers/core/unitdata.py 2015-05-06 17:02:00 +0000
249@@ -443,7 +443,7 @@
250 data = hookenv.execution_environment()
251 self.conf = conf_delta = self.kv.delta(data['conf'], 'config')
252 self.rels = rels_delta = self.kv.delta(data['rels'], 'rels')
253- self.kv.set('env', data['env'])
254+ self.kv.set('env', dict(data['env']))
255 self.kv.set('unit', data['unit'])
256 self.kv.set('relid', data.get('relid'))
257 return conf_delta, rels_delta
258
259=== modified file 'tests/charmhelpers/contrib/amulet/utils.py'
260--- tests/charmhelpers/contrib/amulet/utils.py 2015-04-15 14:23:37 +0000
261+++ tests/charmhelpers/contrib/amulet/utils.py 2015-05-06 17:02:00 +0000
262@@ -79,6 +79,9 @@
263 for k, v in six.iteritems(commands):
264 for cmd in v:
265 output, code = k.run(cmd)
266+ self.log.debug('{} `{}` returned '
267+ '{}'.format(k.info['unit_name'],
268+ cmd, code))
269 if code != 0:
270 return "command `{}` returned {}".format(cmd, str(code))
271 return None
272@@ -86,7 +89,11 @@
273 def _get_config(self, unit, filename):
274 """Get a ConfigParser object for parsing a unit's config file."""
275 file_contents = unit.file_contents(filename)
276- config = ConfigParser.ConfigParser()
277+
278+ # NOTE(beisner): by default, ConfigParser does not handle options
279+ # with no value, such as the flags used in the mysql my.cnf file.
280+ # https://bugs.python.org/issue7005
281+ config = ConfigParser.ConfigParser(allow_no_value=True)
282 config.readfp(io.StringIO(file_contents))
283 return config
284
285
286=== modified file 'tests/charmhelpers/contrib/openstack/amulet/deployment.py'
287--- tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-04-17 10:04:59 +0000
288+++ tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-05-06 17:02:00 +0000
289@@ -46,15 +46,22 @@
290 stable or next branches for the other_services."""
291 base_charms = ['mysql', 'mongodb']
292
293+ if self.series in ['precise', 'trusty']:
294+ base_series = self.series
295+ else:
296+ base_series = self.current_next
297+
298 if self.stable:
299 for svc in other_services:
300- temp = 'lp:charms/{}'
301- svc['location'] = temp.format(svc['name'])
302+ temp = 'lp:charms/{}/{}'
303+ svc['location'] = temp.format(base_series,
304+ svc['name'])
305 else:
306 for svc in other_services:
307 if svc['name'] in base_charms:
308- temp = 'lp:charms/{}'
309- svc['location'] = temp.format(svc['name'])
310+ temp = 'lp:charms/{}/{}'
311+ svc['location'] = temp.format(base_series,
312+ svc['name'])
313 else:
314 temp = 'lp:~openstack-charmers/charms/{}/{}/next'
315 svc['location'] = temp.format(self.current_next,
316@@ -99,10 +106,12 @@
317 Return an integer representing the enum value of the openstack
318 release.
319 """
320+ # Must be ordered by OpenStack release (not by Ubuntu release):
321 (self.precise_essex, self.precise_folsom, self.precise_grizzly,
322 self.precise_havana, self.precise_icehouse,
323- self.trusty_icehouse, self.trusty_juno, self.trusty_kilo,
324- self.utopic_juno, self.vivid_kilo) = range(10)
325+ self.trusty_icehouse, self.trusty_juno, self.utopic_juno,
326+ self.trusty_kilo, self.vivid_kilo) = range(10)
327+
328 releases = {
329 ('precise', None): self.precise_essex,
330 ('precise', 'cloud:precise-folsom'): self.precise_folsom,

Subscribers

People subscribed via source and target branches

to status/vote changes: