Merge lp:~1chb1n/charms/trusty/percona-cluster/liberty-prep into lp:~openstack-charmers-archive/charms/trusty/percona-cluster/next
- Trusty Tahr (14.04)
- liberty-prep
- Merge into next
Proposed by
Ryan Beisner
Status: | Merged |
---|---|
Merged at revision: | 72 |
Proposed branch: | lp:~1chb1n/charms/trusty/percona-cluster/liberty-prep |
Merge into: | lp:~openstack-charmers-archive/charms/trusty/percona-cluster/next |
Diff against target: |
809 lines (+342/-111) 17 files modified
Makefile (+8/-9) hooks/charmhelpers/cli/__init__.py (+1/-5) hooks/charmhelpers/cli/commands.py (+4/-4) hooks/charmhelpers/cli/hookenv.py (+23/-0) hooks/charmhelpers/core/hookenv.py (+1/-20) hooks/charmhelpers/core/host.py (+89/-13) hooks/charmhelpers/core/hugepage.py (+62/-0) hooks/charmhelpers/core/services/helpers.py (+18/-2) hooks/charmhelpers/fetch/__init__.py (+8/-0) metadata.yaml (+1/-1) tests/00-setup (+16/-29) tests/basic_deployment.py (+1/-1) tests/charmhelpers/contrib/amulet/utils.py (+84/-21) tests/charmhelpers/contrib/openstack/amulet/deployment.py (+2/-2) tests/tests.yaml (+19/-0) unit_tests/test_percona_hooks.py (+3/-2) unit_tests/test_percona_utils.py (+2/-2) |
To merge this branch: | bzr merge lp:~1chb1n/charms/trusty/percona-cluster/liberty-prep |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Liam Young (community) | Approve | ||
Review via email: mp+269210@code.launchpad.net |
Commit message
Description of the change
Sync charm-helpers for liberty cloud archive support; Also update makefile, update c-h sync yaml, update tests dir, update amulet test dependencies - to be consistent with other os-charms. Clean up old existing lint in unit tests.
To post a comment you must log in.
Revision history for this message
Ryan Beisner (1chb1n) : | # |
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : | # |
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #8757 percona-
LINT OK: passed
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #6034 percona-
AMULET OK: passed
Build: http://
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'Makefile' | |||
2 | --- Makefile 2015-07-22 11:17:09 +0000 | |||
3 | +++ Makefile 2015-08-26 13:24:25 +0000 | |||
4 | @@ -3,18 +3,17 @@ | |||
5 | 3 | export PYTHONPATH := hooks | 3 | export PYTHONPATH := hooks |
6 | 4 | 4 | ||
7 | 5 | lint: | 5 | lint: |
9 | 6 | @flake8 --exclude hooks/charmhelpers hooks | 6 | @flake8 --exclude hooks/charmhelpers,tests/charmhelpers \ |
10 | 7 | hooks unit_tests tests | ||
11 | 7 | @charm proof | 8 | @charm proof |
12 | 8 | 9 | ||
13 | 9 | unit_test: | ||
14 | 10 | @$(PYTHON) /usr/bin/nosetests --nologcapture unit_tests | ||
15 | 11 | |||
16 | 12 | test: | 10 | test: |
17 | 11 | @# Bundletester expects unit tests here. | ||
18 | 12 | @$(PYTHON) /usr/bin/nosetests -v --nologcapture --with-coverage unit_tests | ||
19 | 13 | |||
20 | 14 | functional_test: | ||
21 | 13 | @echo Starting amulet tests... | 15 | @echo Starting amulet tests... |
22 | 14 | #NOTE(beisner): can remove -v after bug 1320357 is fixed | ||
23 | 15 | # https://bugs.launchpad.net/amulet/+bug/1320357 | ||
24 | 16 | @juju test -v -p AMULET_HTTP_PROXY,AMULET_OS_VIP --timeout 2700 | 16 | @juju test -v -p AMULET_HTTP_PROXY,AMULET_OS_VIP --timeout 2700 |
25 | 17 | #echo "Tests disables; http://pad.lv/1446169" | ||
26 | 18 | 17 | ||
27 | 19 | bin/charm_helpers_sync.py: | 18 | bin/charm_helpers_sync.py: |
28 | 20 | @mkdir -p bin | 19 | @mkdir -p bin |
29 | @@ -22,8 +21,8 @@ | |||
30 | 22 | > bin/charm_helpers_sync.py | 21 | > bin/charm_helpers_sync.py |
31 | 23 | 22 | ||
32 | 24 | sync: bin/charm_helpers_sync.py | 23 | sync: bin/charm_helpers_sync.py |
34 | 25 | @$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers.yaml | 24 | @$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-hooks.yaml |
35 | 26 | @$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-tests.yaml | 25 | @$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-tests.yaml |
36 | 27 | 26 | ||
38 | 28 | publish: lint | 27 | publish: lint test |
39 | 29 | bzr push lp:charms/trusty/percona-cluster | 28 | bzr push lp:charms/trusty/percona-cluster |
40 | 30 | 29 | ||
41 | === renamed file 'charm-helpers.yaml' => 'charm-helpers-hooks.yaml' | |||
42 | === modified file 'hooks/charmhelpers/cli/__init__.py' | |||
43 | --- hooks/charmhelpers/cli/__init__.py 2015-08-03 14:52:57 +0000 | |||
44 | +++ hooks/charmhelpers/cli/__init__.py 2015-08-26 13:24:25 +0000 | |||
45 | @@ -152,15 +152,11 @@ | |||
46 | 152 | arguments = self.argument_parser.parse_args() | 152 | arguments = self.argument_parser.parse_args() |
47 | 153 | argspec = inspect.getargspec(arguments.func) | 153 | argspec = inspect.getargspec(arguments.func) |
48 | 154 | vargs = [] | 154 | vargs = [] |
49 | 155 | kwargs = {} | ||
50 | 156 | for arg in argspec.args: | 155 | for arg in argspec.args: |
51 | 157 | vargs.append(getattr(arguments, arg)) | 156 | vargs.append(getattr(arguments, arg)) |
52 | 158 | if argspec.varargs: | 157 | if argspec.varargs: |
53 | 159 | vargs.extend(getattr(arguments, argspec.varargs)) | 158 | vargs.extend(getattr(arguments, argspec.varargs)) |
58 | 160 | if argspec.keywords: | 159 | output = arguments.func(*vargs) |
55 | 161 | for kwarg in argspec.keywords.items(): | ||
56 | 162 | kwargs[kwarg] = getattr(arguments, kwarg) | ||
57 | 163 | output = arguments.func(*vargs, **kwargs) | ||
59 | 164 | if getattr(arguments.func, '_cli_test_command', False): | 160 | if getattr(arguments.func, '_cli_test_command', False): |
60 | 165 | self.exit_code = 0 if output else 1 | 161 | self.exit_code = 0 if output else 1 |
61 | 166 | output = '' | 162 | output = '' |
62 | 167 | 163 | ||
63 | === modified file 'hooks/charmhelpers/cli/commands.py' | |||
64 | --- hooks/charmhelpers/cli/commands.py 2015-08-03 14:52:57 +0000 | |||
65 | +++ hooks/charmhelpers/cli/commands.py 2015-08-26 13:24:25 +0000 | |||
66 | @@ -26,7 +26,7 @@ | |||
67 | 26 | """ | 26 | """ |
68 | 27 | Import the sub-modules which have decorated subcommands to register with chlp. | 27 | Import the sub-modules which have decorated subcommands to register with chlp. |
69 | 28 | """ | 28 | """ |
74 | 29 | import host # noqa | 29 | from . import host # noqa |
75 | 30 | import benchmark # noqa | 30 | from . import benchmark # noqa |
76 | 31 | import unitdata # noqa | 31 | from . import unitdata # noqa |
77 | 32 | from charmhelpers.core import hookenv # noqa | 32 | from . import hookenv # noqa |
78 | 33 | 33 | ||
79 | === added file 'hooks/charmhelpers/cli/hookenv.py' | |||
80 | --- hooks/charmhelpers/cli/hookenv.py 1970-01-01 00:00:00 +0000 | |||
81 | +++ hooks/charmhelpers/cli/hookenv.py 2015-08-26 13:24:25 +0000 | |||
82 | @@ -0,0 +1,23 @@ | |||
83 | 1 | # Copyright 2014-2015 Canonical Limited. | ||
84 | 2 | # | ||
85 | 3 | # This file is part of charm-helpers. | ||
86 | 4 | # | ||
87 | 5 | # charm-helpers is free software: you can redistribute it and/or modify | ||
88 | 6 | # it under the terms of the GNU Lesser General Public License version 3 as | ||
89 | 7 | # published by the Free Software Foundation. | ||
90 | 8 | # | ||
91 | 9 | # charm-helpers is distributed in the hope that it will be useful, | ||
92 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
93 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
94 | 12 | # GNU Lesser General Public License for more details. | ||
95 | 13 | # | ||
96 | 14 | # You should have received a copy of the GNU Lesser General Public License | ||
97 | 15 | # along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. | ||
98 | 16 | |||
99 | 17 | from . import cmdline | ||
100 | 18 | from charmhelpers.core import hookenv | ||
101 | 19 | |||
102 | 20 | |||
103 | 21 | cmdline.subcommand('relation-id')(hookenv.relation_id._wrapped) | ||
104 | 22 | cmdline.subcommand('service-name')(hookenv.service_name) | ||
105 | 23 | cmdline.subcommand('remote-service-name')(hookenv.remote_service_name._wrapped) | ||
106 | 0 | 24 | ||
107 | === modified file 'hooks/charmhelpers/core/hookenv.py' | |||
108 | --- hooks/charmhelpers/core/hookenv.py 2015-08-03 14:52:57 +0000 | |||
109 | +++ hooks/charmhelpers/core/hookenv.py 2015-08-26 13:24:25 +0000 | |||
110 | @@ -34,23 +34,6 @@ | |||
111 | 34 | import tempfile | 34 | import tempfile |
112 | 35 | from subprocess import CalledProcessError | 35 | from subprocess import CalledProcessError |
113 | 36 | 36 | ||
114 | 37 | try: | ||
115 | 38 | from charmhelpers.cli import cmdline | ||
116 | 39 | except ImportError as e: | ||
117 | 40 | # due to the anti-pattern of partially synching charmhelpers directly | ||
118 | 41 | # into charms, it's possible that charmhelpers.cli is not available; | ||
119 | 42 | # if that's the case, they don't really care about using the cli anyway, | ||
120 | 43 | # so mock it out | ||
121 | 44 | if str(e) == 'No module named cli': | ||
122 | 45 | class cmdline(object): | ||
123 | 46 | @classmethod | ||
124 | 47 | def subcommand(cls, *args, **kwargs): | ||
125 | 48 | def _wrap(func): | ||
126 | 49 | return func | ||
127 | 50 | return _wrap | ||
128 | 51 | else: | ||
129 | 52 | raise | ||
130 | 53 | |||
131 | 54 | import six | 37 | import six |
132 | 55 | if not six.PY3: | 38 | if not six.PY3: |
133 | 56 | from UserDict import UserDict | 39 | from UserDict import UserDict |
134 | @@ -91,6 +74,7 @@ | |||
135 | 91 | res = func(*args, **kwargs) | 74 | res = func(*args, **kwargs) |
136 | 92 | cache[key] = res | 75 | cache[key] = res |
137 | 93 | return res | 76 | return res |
138 | 77 | wrapper._wrapped = func | ||
139 | 94 | return wrapper | 78 | return wrapper |
140 | 95 | 79 | ||
141 | 96 | 80 | ||
142 | @@ -190,7 +174,6 @@ | |||
143 | 190 | return os.environ.get('JUJU_RELATION', None) | 174 | return os.environ.get('JUJU_RELATION', None) |
144 | 191 | 175 | ||
145 | 192 | 176 | ||
146 | 193 | @cmdline.subcommand() | ||
147 | 194 | @cached | 177 | @cached |
148 | 195 | def relation_id(relation_name=None, service_or_unit=None): | 178 | def relation_id(relation_name=None, service_or_unit=None): |
149 | 196 | """The relation ID for the current or a specified relation""" | 179 | """The relation ID for the current or a specified relation""" |
150 | @@ -216,13 +199,11 @@ | |||
151 | 216 | return os.environ.get('JUJU_REMOTE_UNIT', None) | 199 | return os.environ.get('JUJU_REMOTE_UNIT', None) |
152 | 217 | 200 | ||
153 | 218 | 201 | ||
154 | 219 | @cmdline.subcommand() | ||
155 | 220 | def service_name(): | 202 | def service_name(): |
156 | 221 | """The name service group this unit belongs to""" | 203 | """The name service group this unit belongs to""" |
157 | 222 | return local_unit().split('/')[0] | 204 | return local_unit().split('/')[0] |
158 | 223 | 205 | ||
159 | 224 | 206 | ||
160 | 225 | @cmdline.subcommand() | ||
161 | 226 | @cached | 207 | @cached |
162 | 227 | def remote_service_name(relid=None): | 208 | def remote_service_name(relid=None): |
163 | 228 | """The remote service name for a given relation-id (or the current relation)""" | 209 | """The remote service name for a given relation-id (or the current relation)""" |
164 | 229 | 210 | ||
165 | === modified file 'hooks/charmhelpers/core/host.py' | |||
166 | --- hooks/charmhelpers/core/host.py 2015-08-03 14:52:57 +0000 | |||
167 | +++ hooks/charmhelpers/core/host.py 2015-08-26 13:24:25 +0000 | |||
168 | @@ -72,7 +72,7 @@ | |||
169 | 72 | stopped = service_stop(service_name) | 72 | stopped = service_stop(service_name) |
170 | 73 | # XXX: Support systemd too | 73 | # XXX: Support systemd too |
171 | 74 | override_path = os.path.join( | 74 | override_path = os.path.join( |
173 | 75 | init_dir, '{}.conf.override'.format(service_name)) | 75 | init_dir, '{}.override'.format(service_name)) |
174 | 76 | with open(override_path, 'w') as fh: | 76 | with open(override_path, 'w') as fh: |
175 | 77 | fh.write("manual\n") | 77 | fh.write("manual\n") |
176 | 78 | return stopped | 78 | return stopped |
177 | @@ -86,7 +86,7 @@ | |||
178 | 86 | if init_dir is None: | 86 | if init_dir is None: |
179 | 87 | init_dir = "/etc/init" | 87 | init_dir = "/etc/init" |
180 | 88 | override_path = os.path.join( | 88 | override_path = os.path.join( |
182 | 89 | init_dir, '{}.conf.override'.format(service_name)) | 89 | init_dir, '{}.override'.format(service_name)) |
183 | 90 | if os.path.exists(override_path): | 90 | if os.path.exists(override_path): |
184 | 91 | os.unlink(override_path) | 91 | os.unlink(override_path) |
185 | 92 | started = service_start(service_name) | 92 | started = service_start(service_name) |
186 | @@ -148,6 +148,16 @@ | |||
187 | 148 | return user_info | 148 | return user_info |
188 | 149 | 149 | ||
189 | 150 | 150 | ||
190 | 151 | def user_exists(username): | ||
191 | 152 | """Check if a user exists""" | ||
192 | 153 | try: | ||
193 | 154 | pwd.getpwnam(username) | ||
194 | 155 | user_exists = True | ||
195 | 156 | except KeyError: | ||
196 | 157 | user_exists = False | ||
197 | 158 | return user_exists | ||
198 | 159 | |||
199 | 160 | |||
200 | 151 | def add_group(group_name, system_group=False): | 161 | def add_group(group_name, system_group=False): |
201 | 152 | """Add a group to the system""" | 162 | """Add a group to the system""" |
202 | 153 | try: | 163 | try: |
203 | @@ -280,6 +290,17 @@ | |||
204 | 280 | return system_mounts | 290 | return system_mounts |
205 | 281 | 291 | ||
206 | 282 | 292 | ||
207 | 293 | def fstab_mount(mountpoint): | ||
208 | 294 | """Mount filesystem using fstab""" | ||
209 | 295 | cmd_args = ['mount', mountpoint] | ||
210 | 296 | try: | ||
211 | 297 | subprocess.check_output(cmd_args) | ||
212 | 298 | except subprocess.CalledProcessError as e: | ||
213 | 299 | log('Error unmounting {}\n{}'.format(mountpoint, e.output)) | ||
214 | 300 | return False | ||
215 | 301 | return True | ||
216 | 302 | |||
217 | 303 | |||
218 | 283 | def file_hash(path, hash_type='md5'): | 304 | def file_hash(path, hash_type='md5'): |
219 | 284 | """ | 305 | """ |
220 | 285 | Generate a hash checksum of the contents of 'path' or None if not found. | 306 | Generate a hash checksum of the contents of 'path' or None if not found. |
221 | @@ -396,25 +417,80 @@ | |||
222 | 396 | return(''.join(random_chars)) | 417 | return(''.join(random_chars)) |
223 | 397 | 418 | ||
224 | 398 | 419 | ||
226 | 399 | def list_nics(nic_type): | 420 | def is_phy_iface(interface): |
227 | 421 | """Returns True if interface is not virtual, otherwise False.""" | ||
228 | 422 | if interface: | ||
229 | 423 | sys_net = '/sys/class/net' | ||
230 | 424 | if os.path.isdir(sys_net): | ||
231 | 425 | for iface in glob.glob(os.path.join(sys_net, '*')): | ||
232 | 426 | if '/virtual/' in os.path.realpath(iface): | ||
233 | 427 | continue | ||
234 | 428 | |||
235 | 429 | if interface == os.path.basename(iface): | ||
236 | 430 | return True | ||
237 | 431 | |||
238 | 432 | return False | ||
239 | 433 | |||
240 | 434 | |||
241 | 435 | def get_bond_master(interface): | ||
242 | 436 | """Returns bond master if interface is bond slave otherwise None. | ||
243 | 437 | |||
244 | 438 | NOTE: the provided interface is expected to be physical | ||
245 | 439 | """ | ||
246 | 440 | if interface: | ||
247 | 441 | iface_path = '/sys/class/net/%s' % (interface) | ||
248 | 442 | if os.path.exists(iface_path): | ||
249 | 443 | if '/virtual/' in os.path.realpath(iface_path): | ||
250 | 444 | return None | ||
251 | 445 | |||
252 | 446 | master = os.path.join(iface_path, 'master') | ||
253 | 447 | if os.path.exists(master): | ||
254 | 448 | master = os.path.realpath(master) | ||
255 | 449 | # make sure it is a bond master | ||
256 | 450 | if os.path.exists(os.path.join(master, 'bonding')): | ||
257 | 451 | return os.path.basename(master) | ||
258 | 452 | |||
259 | 453 | return None | ||
260 | 454 | |||
261 | 455 | |||
262 | 456 | def list_nics(nic_type=None): | ||
263 | 400 | '''Return a list of nics of given type(s)''' | 457 | '''Return a list of nics of given type(s)''' |
264 | 401 | if isinstance(nic_type, six.string_types): | 458 | if isinstance(nic_type, six.string_types): |
265 | 402 | int_types = [nic_type] | 459 | int_types = [nic_type] |
266 | 403 | else: | 460 | else: |
267 | 404 | int_types = nic_type | 461 | int_types = nic_type |
268 | 462 | |||
269 | 405 | interfaces = [] | 463 | interfaces = [] |
272 | 406 | for int_type in int_types: | 464 | if nic_type: |
273 | 407 | cmd = ['ip', 'addr', 'show', 'label', int_type + '*'] | 465 | for int_type in int_types: |
274 | 466 | cmd = ['ip', 'addr', 'show', 'label', int_type + '*'] | ||
275 | 467 | ip_output = subprocess.check_output(cmd).decode('UTF-8') | ||
276 | 468 | ip_output = ip_output.split('\n') | ||
277 | 469 | ip_output = (line for line in ip_output if line) | ||
278 | 470 | for line in ip_output: | ||
279 | 471 | if line.split()[1].startswith(int_type): | ||
280 | 472 | matched = re.search('.*: (' + int_type + | ||
281 | 473 | r'[0-9]+\.[0-9]+)@.*', line) | ||
282 | 474 | if matched: | ||
283 | 475 | iface = matched.groups()[0] | ||
284 | 476 | else: | ||
285 | 477 | iface = line.split()[1].replace(":", "") | ||
286 | 478 | |||
287 | 479 | if iface not in interfaces: | ||
288 | 480 | interfaces.append(iface) | ||
289 | 481 | else: | ||
290 | 482 | cmd = ['ip', 'a'] | ||
291 | 408 | ip_output = subprocess.check_output(cmd).decode('UTF-8').split('\n') | 483 | ip_output = subprocess.check_output(cmd).decode('UTF-8').split('\n') |
293 | 409 | ip_output = (line for line in ip_output if line) | 484 | ip_output = (line.strip() for line in ip_output if line) |
294 | 485 | |||
295 | 486 | key = re.compile('^[0-9]+:\s+(.+):') | ||
296 | 410 | for line in ip_output: | 487 | for line in ip_output: |
304 | 411 | if line.split()[1].startswith(int_type): | 488 | matched = re.search(key, line) |
305 | 412 | matched = re.search('.*: (' + int_type + r'[0-9]+\.[0-9]+)@.*', line) | 489 | if matched: |
306 | 413 | if matched: | 490 | iface = matched.group(1) |
307 | 414 | interface = matched.groups()[0] | 491 | iface = iface.partition("@")[0] |
308 | 415 | else: | 492 | if iface not in interfaces: |
309 | 416 | interface = line.split()[1].replace(":", "") | 493 | interfaces.append(iface) |
303 | 417 | interfaces.append(interface) | ||
310 | 418 | 494 | ||
311 | 419 | return interfaces | 495 | return interfaces |
312 | 420 | 496 | ||
313 | 421 | 497 | ||
314 | === added file 'hooks/charmhelpers/core/hugepage.py' | |||
315 | --- hooks/charmhelpers/core/hugepage.py 1970-01-01 00:00:00 +0000 | |||
316 | +++ hooks/charmhelpers/core/hugepage.py 2015-08-26 13:24:25 +0000 | |||
317 | @@ -0,0 +1,62 @@ | |||
318 | 1 | # -*- coding: utf-8 -*- | ||
319 | 2 | |||
320 | 3 | # Copyright 2014-2015 Canonical Limited. | ||
321 | 4 | # | ||
322 | 5 | # This file is part of charm-helpers. | ||
323 | 6 | # | ||
324 | 7 | # charm-helpers is free software: you can redistribute it and/or modify | ||
325 | 8 | # it under the terms of the GNU Lesser General Public License version 3 as | ||
326 | 9 | # published by the Free Software Foundation. | ||
327 | 10 | # | ||
328 | 11 | # charm-helpers is distributed in the hope that it will be useful, | ||
329 | 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
330 | 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
331 | 14 | # GNU Lesser General Public License for more details. | ||
332 | 15 | # | ||
333 | 16 | # You should have received a copy of the GNU Lesser General Public License | ||
334 | 17 | # along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. | ||
335 | 18 | |||
336 | 19 | import yaml | ||
337 | 20 | from charmhelpers.core import fstab | ||
338 | 21 | from charmhelpers.core import sysctl | ||
339 | 22 | from charmhelpers.core.host import ( | ||
340 | 23 | add_group, | ||
341 | 24 | add_user_to_group, | ||
342 | 25 | fstab_mount, | ||
343 | 26 | mkdir, | ||
344 | 27 | ) | ||
345 | 28 | |||
346 | 29 | |||
347 | 30 | def hugepage_support(user, group='hugetlb', nr_hugepages=256, | ||
348 | 31 | max_map_count=65536, mnt_point='/run/hugepages/kvm', | ||
349 | 32 | pagesize='2MB', mount=True): | ||
350 | 33 | """Enable hugepages on system. | ||
351 | 34 | |||
352 | 35 | Args: | ||
353 | 36 | user (str) -- Username to allow access to hugepages to | ||
354 | 37 | group (str) -- Group name to own hugepages | ||
355 | 38 | nr_hugepages (int) -- Number of pages to reserve | ||
356 | 39 | max_map_count (int) -- Number of Virtual Memory Areas a process can own | ||
357 | 40 | mnt_point (str) -- Directory to mount hugepages on | ||
358 | 41 | pagesize (str) -- Size of hugepages | ||
359 | 42 | mount (bool) -- Whether to Mount hugepages | ||
360 | 43 | """ | ||
361 | 44 | group_info = add_group(group) | ||
362 | 45 | gid = group_info.gr_gid | ||
363 | 46 | add_user_to_group(user, group) | ||
364 | 47 | sysctl_settings = { | ||
365 | 48 | 'vm.nr_hugepages': nr_hugepages, | ||
366 | 49 | 'vm.max_map_count': max_map_count, | ||
367 | 50 | 'vm.hugetlb_shm_group': gid, | ||
368 | 51 | } | ||
369 | 52 | sysctl.create(yaml.dump(sysctl_settings), '/etc/sysctl.d/10-hugepage.conf') | ||
370 | 53 | mkdir(mnt_point, owner='root', group='root', perms=0o755, force=False) | ||
371 | 54 | lfstab = fstab.Fstab() | ||
372 | 55 | fstab_entry = lfstab.get_entry_by_attr('mountpoint', mnt_point) | ||
373 | 56 | if fstab_entry: | ||
374 | 57 | lfstab.remove_entry(fstab_entry) | ||
375 | 58 | entry = lfstab.Entry('nodev', mnt_point, 'hugetlbfs', | ||
376 | 59 | 'mode=1770,gid={},pagesize={}'.format(gid, pagesize), 0, 0) | ||
377 | 60 | lfstab.add_entry(entry) | ||
378 | 61 | if mount: | ||
379 | 62 | fstab_mount(mnt_point) | ||
380 | 0 | 63 | ||
381 | === modified file 'hooks/charmhelpers/core/services/helpers.py' | |||
382 | --- hooks/charmhelpers/core/services/helpers.py 2015-08-03 14:52:57 +0000 | |||
383 | +++ hooks/charmhelpers/core/services/helpers.py 2015-08-26 13:24:25 +0000 | |||
384 | @@ -16,7 +16,9 @@ | |||
385 | 16 | 16 | ||
386 | 17 | import os | 17 | import os |
387 | 18 | import yaml | 18 | import yaml |
388 | 19 | |||
389 | 19 | from charmhelpers.core import hookenv | 20 | from charmhelpers.core import hookenv |
390 | 21 | from charmhelpers.core import host | ||
391 | 20 | from charmhelpers.core import templating | 22 | from charmhelpers.core import templating |
392 | 21 | 23 | ||
393 | 22 | from charmhelpers.core.services.base import ManagerCallback | 24 | from charmhelpers.core.services.base import ManagerCallback |
394 | @@ -240,27 +242,41 @@ | |||
395 | 240 | 242 | ||
396 | 241 | :param str source: The template source file, relative to | 243 | :param str source: The template source file, relative to |
397 | 242 | `$CHARM_DIR/templates` | 244 | `$CHARM_DIR/templates` |
398 | 245 | |||
399 | 243 | :param str target: The target to write the rendered template to | 246 | :param str target: The target to write the rendered template to |
400 | 244 | :param str owner: The owner of the rendered file | 247 | :param str owner: The owner of the rendered file |
401 | 245 | :param str group: The group of the rendered file | 248 | :param str group: The group of the rendered file |
402 | 246 | :param int perms: The permissions of the rendered file | 249 | :param int perms: The permissions of the rendered file |
404 | 247 | 250 | :param partial on_change_action: functools partial to be executed when | |
405 | 251 | rendered file changes | ||
406 | 248 | """ | 252 | """ |
407 | 249 | def __init__(self, source, target, | 253 | def __init__(self, source, target, |
409 | 250 | owner='root', group='root', perms=0o444): | 254 | owner='root', group='root', perms=0o444, |
410 | 255 | on_change_action=None): | ||
411 | 251 | self.source = source | 256 | self.source = source |
412 | 252 | self.target = target | 257 | self.target = target |
413 | 253 | self.owner = owner | 258 | self.owner = owner |
414 | 254 | self.group = group | 259 | self.group = group |
415 | 255 | self.perms = perms | 260 | self.perms = perms |
416 | 261 | self.on_change_action = on_change_action | ||
417 | 256 | 262 | ||
418 | 257 | def __call__(self, manager, service_name, event_name): | 263 | def __call__(self, manager, service_name, event_name): |
419 | 264 | pre_checksum = '' | ||
420 | 265 | if self.on_change_action and os.path.isfile(self.target): | ||
421 | 266 | pre_checksum = host.file_hash(self.target) | ||
422 | 258 | service = manager.get_service(service_name) | 267 | service = manager.get_service(service_name) |
423 | 259 | context = {} | 268 | context = {} |
424 | 260 | for ctx in service.get('required_data', []): | 269 | for ctx in service.get('required_data', []): |
425 | 261 | context.update(ctx) | 270 | context.update(ctx) |
426 | 262 | templating.render(self.source, self.target, context, | 271 | templating.render(self.source, self.target, context, |
427 | 263 | self.owner, self.group, self.perms) | 272 | self.owner, self.group, self.perms) |
428 | 273 | if self.on_change_action: | ||
429 | 274 | if pre_checksum == host.file_hash(self.target): | ||
430 | 275 | hookenv.log( | ||
431 | 276 | 'No change detected: {}'.format(self.target), | ||
432 | 277 | hookenv.DEBUG) | ||
433 | 278 | else: | ||
434 | 279 | self.on_change_action() | ||
435 | 264 | 280 | ||
436 | 265 | 281 | ||
437 | 266 | # Convenience aliases for templates | 282 | # Convenience aliases for templates |
438 | 267 | 283 | ||
439 | === modified file 'hooks/charmhelpers/fetch/__init__.py' | |||
440 | --- hooks/charmhelpers/fetch/__init__.py 2015-08-03 14:52:57 +0000 | |||
441 | +++ hooks/charmhelpers/fetch/__init__.py 2015-08-26 13:24:25 +0000 | |||
442 | @@ -90,6 +90,14 @@ | |||
443 | 90 | 'kilo/proposed': 'trusty-proposed/kilo', | 90 | 'kilo/proposed': 'trusty-proposed/kilo', |
444 | 91 | 'trusty-kilo/proposed': 'trusty-proposed/kilo', | 91 | 'trusty-kilo/proposed': 'trusty-proposed/kilo', |
445 | 92 | 'trusty-proposed/kilo': 'trusty-proposed/kilo', | 92 | 'trusty-proposed/kilo': 'trusty-proposed/kilo', |
446 | 93 | # Liberty | ||
447 | 94 | 'liberty': 'trusty-updates/liberty', | ||
448 | 95 | 'trusty-liberty': 'trusty-updates/liberty', | ||
449 | 96 | 'trusty-liberty/updates': 'trusty-updates/liberty', | ||
450 | 97 | 'trusty-updates/liberty': 'trusty-updates/liberty', | ||
451 | 98 | 'liberty/proposed': 'trusty-proposed/liberty', | ||
452 | 99 | 'trusty-liberty/proposed': 'trusty-proposed/liberty', | ||
453 | 100 | 'trusty-proposed/liberty': 'trusty-proposed/liberty', | ||
454 | 93 | } | 101 | } |
455 | 94 | 102 | ||
456 | 95 | # The order of this list is very important. Handlers should be listed in from | 103 | # The order of this list is very important. Handlers should be listed in from |
457 | 96 | 104 | ||
458 | === modified file 'metadata.yaml' | |||
459 | --- metadata.yaml 2013-09-19 15:58:28 +0000 | |||
460 | +++ metadata.yaml 2015-08-26 13:24:25 +0000 | |||
461 | @@ -5,7 +5,7 @@ | |||
462 | 5 | Percona XtraDB Cluster provides an active/active MySQL | 5 | Percona XtraDB Cluster provides an active/active MySQL |
463 | 6 | compatible alternative implemented using the Galera | 6 | compatible alternative implemented using the Galera |
464 | 7 | synchronous replication extensions. | 7 | synchronous replication extensions. |
466 | 8 | categories: | 8 | tags: |
467 | 9 | - databases | 9 | - databases |
468 | 10 | provides: | 10 | provides: |
469 | 11 | db: | 11 | db: |
470 | 12 | 12 | ||
471 | === renamed file 'tests/00-setup.sh' => 'tests/00-setup' | |||
472 | --- tests/00-setup.sh 2015-04-15 12:11:46 +0000 | |||
473 | +++ tests/00-setup 2015-08-26 13:24:25 +0000 | |||
474 | @@ -1,29 +1,16 @@ | |||
504 | 1 | #!/bin/bash -x | 1 | #!/bin/bash |
505 | 2 | # The script installs amulet and other tools needed for the amulet tests. | 2 | |
506 | 3 | 3 | set -ex | |
507 | 4 | # Get the status of the amulet package, this returns 0 of package is installed. | 4 | |
508 | 5 | dpkg -s amulet | 5 | sudo add-apt-repository --yes ppa:juju/stable |
509 | 6 | if [ $? -ne 0 ]; then | 6 | sudo apt-get update --yes |
510 | 7 | # Install the Amulet testing harness. | 7 | sudo apt-get install --yes amulet \ |
511 | 8 | sudo add-apt-repository -y ppa:juju/stable | 8 | python-cinderclient \ |
512 | 9 | sudo apt-get update | 9 | python-distro-info \ |
513 | 10 | sudo apt-get install -y -q amulet juju-core charm-tools | 10 | python-glanceclient \ |
514 | 11 | fi | 11 | python-heatclient \ |
515 | 12 | 12 | python-keystoneclient \ | |
516 | 13 | 13 | python-neutronclient \ | |
517 | 14 | PACKAGES="python3 python3-yaml" | 14 | python-novaclient \ |
518 | 15 | for pkg in $PACKAGES; do | 15 | python-pika \ |
519 | 16 | dpkg -s python3 | 16 | python-swiftclient |
491 | 17 | if [ $? -ne 0 ]; then | ||
492 | 18 | sudo apt-get install -y -q $pkg | ||
493 | 19 | fi | ||
494 | 20 | done | ||
495 | 21 | |||
496 | 22 | |||
497 | 23 | #if [ ! -f "$(dirname $0)/../local.yaml" ]; then | ||
498 | 24 | # echo "To run these amulet tests a vip is needed, create a file called \ | ||
499 | 25 | #local.yaml in the charm dir, this file must contain a 'vip', if you're \ | ||
500 | 26 | #using the local provider with lxc you could use a free IP from the range \ | ||
501 | 27 | #10.0.3.0/24" | ||
502 | 28 | # exit 1 | ||
503 | 29 | #fi | ||
520 | 30 | 17 | ||
521 | === modified file 'tests/basic_deployment.py' | |||
522 | --- tests/basic_deployment.py 2015-07-22 11:17:09 +0000 | |||
523 | +++ tests/basic_deployment.py 2015-08-26 13:24:25 +0000 | |||
524 | @@ -100,7 +100,7 @@ | |||
525 | 100 | 100 | ||
526 | 101 | resources = ['res_mysql_vip'] | 101 | resources = ['res_mysql_vip'] |
527 | 102 | resources += ['res_mysql_monitor:%d' % | 102 | resources += ['res_mysql_monitor:%d' % |
529 | 103 | i for i in range(self.units)] | 103 | m for m in range(self.units)] |
530 | 104 | 104 | ||
531 | 105 | assert sorted(self.get_pcmkr_resources()) == sorted(resources) | 105 | assert sorted(self.get_pcmkr_resources()) == sorted(resources) |
532 | 106 | else: | 106 | else: |
533 | 107 | 107 | ||
534 | === modified file 'tests/charmhelpers/contrib/amulet/utils.py' | |||
535 | --- tests/charmhelpers/contrib/amulet/utils.py 2015-08-03 14:52:57 +0000 | |||
536 | +++ tests/charmhelpers/contrib/amulet/utils.py 2015-08-26 13:24:25 +0000 | |||
537 | @@ -14,17 +14,23 @@ | |||
538 | 14 | # You should have received a copy of the GNU Lesser General Public License | 14 | # You should have received a copy of the GNU Lesser General Public License |
539 | 15 | # along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. | 15 | # along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. |
540 | 16 | 16 | ||
541 | 17 | import amulet | ||
542 | 18 | import ConfigParser | ||
543 | 19 | import distro_info | ||
544 | 20 | import io | 17 | import io |
545 | 18 | import json | ||
546 | 21 | import logging | 19 | import logging |
547 | 22 | import os | 20 | import os |
548 | 23 | import re | 21 | import re |
550 | 24 | import six | 22 | import subprocess |
551 | 25 | import sys | 23 | import sys |
552 | 26 | import time | 24 | import time |
554 | 27 | import urlparse | 25 | |
555 | 26 | import amulet | ||
556 | 27 | import distro_info | ||
557 | 28 | import six | ||
558 | 29 | from six.moves import configparser | ||
559 | 30 | if six.PY3: | ||
560 | 31 | from urllib import parse as urlparse | ||
561 | 32 | else: | ||
562 | 33 | import urlparse | ||
563 | 28 | 34 | ||
564 | 29 | 35 | ||
565 | 30 | class AmuletUtils(object): | 36 | class AmuletUtils(object): |
566 | @@ -142,19 +148,23 @@ | |||
567 | 142 | 148 | ||
568 | 143 | for service_name in services_list: | 149 | for service_name in services_list: |
569 | 144 | if (self.ubuntu_releases.index(release) >= systemd_switch or | 150 | if (self.ubuntu_releases.index(release) >= systemd_switch or |
572 | 145 | service_name == "rabbitmq-server"): | 151 | service_name in ['rabbitmq-server', 'apache2']): |
573 | 146 | # init is systemd | 152 | # init is systemd (or regular sysv) |
574 | 147 | cmd = 'sudo service {} status'.format(service_name) | 153 | cmd = 'sudo service {} status'.format(service_name) |
575 | 154 | output, code = sentry_unit.run(cmd) | ||
576 | 155 | service_running = code == 0 | ||
577 | 148 | elif self.ubuntu_releases.index(release) < systemd_switch: | 156 | elif self.ubuntu_releases.index(release) < systemd_switch: |
578 | 149 | # init is upstart | 157 | # init is upstart |
579 | 150 | cmd = 'sudo status {}'.format(service_name) | 158 | cmd = 'sudo status {}'.format(service_name) |
580 | 159 | output, code = sentry_unit.run(cmd) | ||
581 | 160 | service_running = code == 0 and "start/running" in output | ||
582 | 151 | 161 | ||
583 | 152 | output, code = sentry_unit.run(cmd) | ||
584 | 153 | self.log.debug('{} `{}` returned ' | 162 | self.log.debug('{} `{}` returned ' |
585 | 154 | '{}'.format(sentry_unit.info['unit_name'], | 163 | '{}'.format(sentry_unit.info['unit_name'], |
586 | 155 | cmd, code)) | 164 | cmd, code)) |
589 | 156 | if code != 0: | 165 | if not service_running: |
590 | 157 | return "command `{}` returned {}".format(cmd, str(code)) | 166 | return u"command `{}` returned {} {}".format( |
591 | 167 | cmd, output, str(code)) | ||
592 | 158 | return None | 168 | return None |
593 | 159 | 169 | ||
594 | 160 | def _get_config(self, unit, filename): | 170 | def _get_config(self, unit, filename): |
595 | @@ -164,7 +174,7 @@ | |||
596 | 164 | # NOTE(beisner): by default, ConfigParser does not handle options | 174 | # NOTE(beisner): by default, ConfigParser does not handle options |
597 | 165 | # with no value, such as the flags used in the mysql my.cnf file. | 175 | # with no value, such as the flags used in the mysql my.cnf file. |
598 | 166 | # https://bugs.python.org/issue7005 | 176 | # https://bugs.python.org/issue7005 |
600 | 167 | config = ConfigParser.ConfigParser(allow_no_value=True) | 177 | config = configparser.ConfigParser(allow_no_value=True) |
601 | 168 | config.readfp(io.StringIO(file_contents)) | 178 | config.readfp(io.StringIO(file_contents)) |
602 | 169 | return config | 179 | return config |
603 | 170 | 180 | ||
604 | @@ -450,15 +460,20 @@ | |||
605 | 450 | cmd, code, output)) | 460 | cmd, code, output)) |
606 | 451 | return None | 461 | return None |
607 | 452 | 462 | ||
609 | 453 | def get_process_id_list(self, sentry_unit, process_name): | 463 | def get_process_id_list(self, sentry_unit, process_name, |
610 | 464 | expect_success=True): | ||
611 | 454 | """Get a list of process ID(s) from a single sentry juju unit | 465 | """Get a list of process ID(s) from a single sentry juju unit |
612 | 455 | for a single process name. | 466 | for a single process name. |
613 | 456 | 467 | ||
615 | 457 | :param sentry_unit: Pointer to amulet sentry instance (juju unit) | 468 | :param sentry_unit: Amulet sentry instance (juju unit) |
616 | 458 | :param process_name: Process name | 469 | :param process_name: Process name |
617 | 470 | :param expect_success: If False, expect the PID to be missing, | ||
618 | 471 | raise if it is present. | ||
619 | 459 | :returns: List of process IDs | 472 | :returns: List of process IDs |
620 | 460 | """ | 473 | """ |
622 | 461 | cmd = 'pidof {}'.format(process_name) | 474 | cmd = 'pidof -x {}'.format(process_name) |
623 | 475 | if not expect_success: | ||
624 | 476 | cmd += " || exit 0 && exit 1" | ||
625 | 462 | output, code = sentry_unit.run(cmd) | 477 | output, code = sentry_unit.run(cmd) |
626 | 463 | if code != 0: | 478 | if code != 0: |
627 | 464 | msg = ('{} `{}` returned {} ' | 479 | msg = ('{} `{}` returned {} ' |
628 | @@ -467,14 +482,23 @@ | |||
629 | 467 | amulet.raise_status(amulet.FAIL, msg=msg) | 482 | amulet.raise_status(amulet.FAIL, msg=msg) |
630 | 468 | return str(output).split() | 483 | return str(output).split() |
631 | 469 | 484 | ||
633 | 470 | def get_unit_process_ids(self, unit_processes): | 485 | def get_unit_process_ids(self, unit_processes, expect_success=True): |
634 | 471 | """Construct a dict containing unit sentries, process names, and | 486 | """Construct a dict containing unit sentries, process names, and |
636 | 472 | process IDs.""" | 487 | process IDs. |
637 | 488 | |||
638 | 489 | :param unit_processes: A dictionary of Amulet sentry instance | ||
639 | 490 | to list of process names. | ||
640 | 491 | :param expect_success: if False expect the processes to not be | ||
641 | 492 | running, raise if they are. | ||
642 | 493 | :returns: Dictionary of Amulet sentry instance to dictionary | ||
643 | 494 | of process names to PIDs. | ||
644 | 495 | """ | ||
645 | 473 | pid_dict = {} | 496 | pid_dict = {} |
647 | 474 | for sentry_unit, process_list in unit_processes.iteritems(): | 497 | for sentry_unit, process_list in six.iteritems(unit_processes): |
648 | 475 | pid_dict[sentry_unit] = {} | 498 | pid_dict[sentry_unit] = {} |
649 | 476 | for process in process_list: | 499 | for process in process_list: |
651 | 477 | pids = self.get_process_id_list(sentry_unit, process) | 500 | pids = self.get_process_id_list( |
652 | 501 | sentry_unit, process, expect_success=expect_success) | ||
653 | 478 | pid_dict[sentry_unit].update({process: pids}) | 502 | pid_dict[sentry_unit].update({process: pids}) |
654 | 479 | return pid_dict | 503 | return pid_dict |
655 | 480 | 504 | ||
656 | @@ -488,7 +512,7 @@ | |||
657 | 488 | return ('Unit count mismatch. expected, actual: {}, ' | 512 | return ('Unit count mismatch. expected, actual: {}, ' |
658 | 489 | '{} '.format(len(expected), len(actual))) | 513 | '{} '.format(len(expected), len(actual))) |
659 | 490 | 514 | ||
661 | 491 | for (e_sentry, e_proc_names) in expected.iteritems(): | 515 | for (e_sentry, e_proc_names) in six.iteritems(expected): |
662 | 492 | e_sentry_name = e_sentry.info['unit_name'] | 516 | e_sentry_name = e_sentry.info['unit_name'] |
663 | 493 | if e_sentry in actual.keys(): | 517 | if e_sentry in actual.keys(): |
664 | 494 | a_proc_names = actual[e_sentry] | 518 | a_proc_names = actual[e_sentry] |
665 | @@ -507,11 +531,23 @@ | |||
666 | 507 | '{}'.format(e_proc_name, a_proc_name)) | 531 | '{}'.format(e_proc_name, a_proc_name)) |
667 | 508 | 532 | ||
668 | 509 | a_pids_length = len(a_pids) | 533 | a_pids_length = len(a_pids) |
671 | 510 | if e_pids_length != a_pids_length: | 534 | fail_msg = ('PID count mismatch. {} ({}) expected, actual: ' |
670 | 511 | return ('PID count mismatch. {} ({}) expected, actual: ' | ||
672 | 512 | '{}, {} ({})'.format(e_sentry_name, e_proc_name, | 535 | '{}, {} ({})'.format(e_sentry_name, e_proc_name, |
673 | 513 | e_pids_length, a_pids_length, | 536 | e_pids_length, a_pids_length, |
674 | 514 | a_pids)) | 537 | a_pids)) |
675 | 538 | |||
676 | 539 | # If expected is not bool, ensure PID quantities match | ||
677 | 540 | if not isinstance(e_pids_length, bool) and \ | ||
678 | 541 | a_pids_length != e_pids_length: | ||
679 | 542 | return fail_msg | ||
680 | 543 | # If expected is bool True, ensure 1 or more PIDs exist | ||
681 | 544 | elif isinstance(e_pids_length, bool) and \ | ||
682 | 545 | e_pids_length is True and a_pids_length < 1: | ||
683 | 546 | return fail_msg | ||
684 | 547 | # If expected is bool False, ensure 0 PIDs exist | ||
685 | 548 | elif isinstance(e_pids_length, bool) and \ | ||
686 | 549 | e_pids_length is False and a_pids_length != 0: | ||
687 | 550 | return fail_msg | ||
688 | 515 | else: | 551 | else: |
689 | 516 | self.log.debug('PID check OK: {} {} {}: ' | 552 | self.log.debug('PID check OK: {} {} {}: ' |
690 | 517 | '{}'.format(e_sentry_name, e_proc_name, | 553 | '{}'.format(e_sentry_name, e_proc_name, |
691 | @@ -531,3 +567,30 @@ | |||
692 | 531 | return 'Dicts within list are not identical' | 567 | return 'Dicts within list are not identical' |
693 | 532 | 568 | ||
694 | 533 | return None | 569 | return None |
695 | 570 | |||
696 | 571 | def run_action(self, unit_sentry, action, | ||
697 | 572 | _check_output=subprocess.check_output): | ||
698 | 573 | """Run the named action on a given unit sentry. | ||
699 | 574 | |||
700 | 575 | _check_output parameter is used for dependency injection. | ||
701 | 576 | |||
702 | 577 | @return action_id. | ||
703 | 578 | """ | ||
704 | 579 | unit_id = unit_sentry.info["unit_name"] | ||
705 | 580 | command = ["juju", "action", "do", "--format=json", unit_id, action] | ||
706 | 581 | self.log.info("Running command: %s\n" % " ".join(command)) | ||
707 | 582 | output = _check_output(command, universal_newlines=True) | ||
708 | 583 | data = json.loads(output) | ||
709 | 584 | action_id = data[u'Action queued with id'] | ||
710 | 585 | return action_id | ||
711 | 586 | |||
712 | 587 | def wait_on_action(self, action_id, _check_output=subprocess.check_output): | ||
713 | 588 | """Wait for a given action, returning if it completed or not. | ||
714 | 589 | |||
715 | 590 | _check_output parameter is used for dependency injection. | ||
716 | 591 | """ | ||
717 | 592 | command = ["juju", "action", "fetch", "--format=json", "--wait=0", | ||
718 | 593 | action_id] | ||
719 | 594 | output = _check_output(command, universal_newlines=True) | ||
720 | 595 | data = json.loads(output) | ||
721 | 596 | return data.get(u"status") == "completed" | ||
722 | 534 | 597 | ||
723 | === modified file 'tests/charmhelpers/contrib/openstack/amulet/deployment.py' | |||
724 | --- tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-08-03 14:52:57 +0000 | |||
725 | +++ tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-08-26 13:24:25 +0000 | |||
726 | @@ -44,7 +44,7 @@ | |||
727 | 44 | Determine if the local branch being tested is derived from its | 44 | Determine if the local branch being tested is derived from its |
728 | 45 | stable or next (dev) branch, and based on this, use the corresonding | 45 | stable or next (dev) branch, and based on this, use the corresonding |
729 | 46 | stable or next branches for the other_services.""" | 46 | stable or next branches for the other_services.""" |
731 | 47 | base_charms = ['mysql', 'mongodb'] | 47 | base_charms = ['mysql', 'mongodb', 'nrpe'] |
732 | 48 | 48 | ||
733 | 49 | if self.series in ['precise', 'trusty']: | 49 | if self.series in ['precise', 'trusty']: |
734 | 50 | base_series = self.series | 50 | base_series = self.series |
735 | @@ -81,7 +81,7 @@ | |||
736 | 81 | 'ceph-osd', 'ceph-radosgw'] | 81 | 'ceph-osd', 'ceph-radosgw'] |
737 | 82 | # Most OpenStack subordinate charms do not expose an origin option | 82 | # Most OpenStack subordinate charms do not expose an origin option |
738 | 83 | # as that is controlled by the principle. | 83 | # as that is controlled by the principle. |
740 | 84 | ignore = ['cinder-ceph', 'hacluster', 'neutron-openvswitch'] | 84 | ignore = ['cinder-ceph', 'hacluster', 'neutron-openvswitch', 'nrpe'] |
741 | 85 | 85 | ||
742 | 86 | if self.openstack: | 86 | if self.openstack: |
743 | 87 | for svc in services: | 87 | for svc in services: |
744 | 88 | 88 | ||
745 | === added file 'tests/tests.yaml' | |||
746 | --- tests/tests.yaml 1970-01-01 00:00:00 +0000 | |||
747 | +++ tests/tests.yaml 2015-08-26 13:24:25 +0000 | |||
748 | @@ -0,0 +1,19 @@ | |||
749 | 1 | bootstrap: true | ||
750 | 2 | reset: true | ||
751 | 3 | virtualenv: true | ||
752 | 4 | makefile: | ||
753 | 5 | - lint | ||
754 | 6 | - test | ||
755 | 7 | sources: | ||
756 | 8 | - ppa:juju/stable | ||
757 | 9 | packages: | ||
758 | 10 | - amulet | ||
759 | 11 | - python-cinderclient | ||
760 | 12 | - python-distro-info | ||
761 | 13 | - python-glanceclient | ||
762 | 14 | - python-heatclient | ||
763 | 15 | - python-keystoneclient | ||
764 | 16 | - python-neutronclient | ||
765 | 17 | - python-novaclient | ||
766 | 18 | - python-pika | ||
767 | 19 | - python-swiftclient | ||
768 | 0 | 20 | ||
769 | === modified file 'unit_tests/test_percona_hooks.py' | |||
770 | --- unit_tests/test_percona_hooks.py 2015-03-17 14:37:44 +0000 | |||
771 | +++ unit_tests/test_percona_hooks.py 2015-08-26 13:24:25 +0000 | |||
772 | @@ -36,6 +36,7 @@ | |||
773 | 36 | self.get_db_helper.return_value = helper | 36 | self.get_db_helper.return_value = helper |
774 | 37 | self.test_config.set('vip', '10.0.3.3') | 37 | self.test_config.set('vip', '10.0.3.3') |
775 | 38 | self.test_config.set('sst-password', password) | 38 | self.test_config.set('sst-password', password) |
776 | 39 | |||
777 | 39 | def f(k): | 40 | def f(k): |
778 | 40 | return self.test_config.get(k) | 41 | return self.test_config.get(k) |
779 | 41 | 42 | ||
780 | @@ -48,12 +49,12 @@ | |||
781 | 48 | 'cidr_netmask="24" ' | 49 | 'cidr_netmask="24" ' |
782 | 49 | 'nic="eth0"'), | 50 | 'nic="eth0"'), |
783 | 50 | 'res_mysql_monitor': | 51 | 'res_mysql_monitor': |
785 | 51 | hooks.RES_MONITOR_PARAMS % {'sstpass': 'ubuntu'}} | 52 | hooks.RES_MONITOR_PARAMS % {'sstpass': 'ubuntu'}} |
786 | 52 | groups = {'grp_percona_cluster': 'res_mysql_vip'} | 53 | groups = {'grp_percona_cluster': 'res_mysql_vip'} |
787 | 53 | 54 | ||
788 | 54 | clones = {'cl_mysql_monitor': 'res_mysql_monitor meta interleave=true'} | 55 | clones = {'cl_mysql_monitor': 'res_mysql_monitor meta interleave=true'} |
789 | 55 | 56 | ||
791 | 56 | colocations = {'vip_mysqld': 'inf: grp_percona_cluster cl_mysql_monitor'} | 57 | colocations = {'vip_mysqld': 'inf: grp_percona_cluster cl_mysql_monitor'} # noqa |
792 | 57 | 58 | ||
793 | 58 | locations = {'loc_percona_cluster': | 59 | locations = {'loc_percona_cluster': |
794 | 59 | 'grp_percona_cluster rule inf: writable eq 1'} | 60 | 'grp_percona_cluster rule inf: writable eq 1'} |
795 | 60 | 61 | ||
796 | === modified file 'unit_tests/test_percona_utils.py' | |||
797 | --- unit_tests/test_percona_utils.py 2015-07-29 10:21:16 +0000 | |||
798 | +++ unit_tests/test_percona_utils.py 2015-08-26 13:24:25 +0000 | |||
799 | @@ -111,8 +111,8 @@ | |||
800 | 111 | mock_log, mock_get_ipv6_addr): | 111 | mock_log, mock_get_ipv6_addr): |
801 | 112 | ipv6addr = '2001:db8:1:0:f816:3eff:fe79:cd' | 112 | ipv6addr = '2001:db8:1:0:f816:3eff:fe79:cd' |
802 | 113 | mock_get_ipv6_addr.return_value = [ipv6addr] | 113 | mock_get_ipv6_addr.return_value = [ipv6addr] |
805 | 114 | mock_rel_ids.return_value = [1,2] | 114 | mock_rel_ids.return_value = [1, 2] |
806 | 115 | mock_rel_units.return_value = [3,4] | 115 | mock_rel_units.return_value = [3, 4] |
807 | 116 | mock_get_host_ip.return_value = 'hostA' | 116 | mock_get_host_ip.return_value = 'hostA' |
808 | 117 | 117 | ||
809 | 118 | def _mock_rel_get(*args, **kwargs): | 118 | def _mock_rel_get(*args, **kwargs): |
charm_unit_test #8088 percona- cluster- next for 1chb1n mp269210
UNIT OK: passed
Build: http:// 10.245. 162.77: 8080/job/ charm_unit_ test/8088/