Merge lp:~adam-collard/charms/trusty/swift-storage/fix-service-status into lp:~openstack-charmers-archive/charms/trusty/swift-storage/next
- Trusty Tahr (14.04)
- fix-service-status
- Merge into next
Status: | Merged |
---|---|
Merged at revision: | 73 |
Proposed branch: | lp:~adam-collard/charms/trusty/swift-storage/fix-service-status |
Merge into: | lp:~openstack-charmers-archive/charms/trusty/swift-storage/next |
Diff against target: |
543 lines (+178/-93) 11 files modified
charmhelpers/cli/__init__.py (+1/-5) charmhelpers/cli/commands.py (+4/-4) charmhelpers/contrib/openstack/amulet/deployment.py (+2/-2) charmhelpers/contrib/openstack/utils.py (+51/-14) charmhelpers/contrib/storage/linux/utils.py (+3/-2) charmhelpers/core/hookenv.py (+1/-20) charmhelpers/core/host.py (+2/-2) charmhelpers/fetch/__init__.py (+8/-0) tests/basic_deployment.py (+20/-21) tests/charmhelpers/contrib/amulet/utils.py (+84/-21) tests/charmhelpers/contrib/openstack/amulet/deployment.py (+2/-2) |
To merge this branch: | bzr merge lp:~adam-collard/charms/trusty/swift-storage/fix-service-status |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Liam Young (community) | Approve | ||
Review via email: mp+268228@code.launchpad.net |
Commit message
Description of the change
Sync charm-helpers and use the (new-ish) validate_
- 75. By Adam Collard
-
Fix typo
uosci-testing-bot (uosci-testing-bot) wrote : | # |
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #7596 swift-storage-next for adam-collard mp268228
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #8195 swift-storage-next for adam-collard mp268228
LINT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #7597 swift-storage-next for adam-collard mp268228
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #5840 swift-storage-next for adam-collard mp268228
AMULET FAIL: amulet-test failed
AMULET Results (max last 2 lines):
make: *** [test] Error 1
ERROR:root:Make target returned non-zero.
Full amulet test output: http://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #5841 swift-storage-next for adam-collard mp268228
AMULET OK: passed
Build: http://
Preview Diff
1 | === modified file 'charmhelpers/cli/__init__.py' | |||
2 | --- charmhelpers/cli/__init__.py 2015-07-31 13:11:32 +0000 | |||
3 | +++ charmhelpers/cli/__init__.py 2015-08-17 13:36:14 +0000 | |||
4 | @@ -152,15 +152,11 @@ | |||
5 | 152 | arguments = self.argument_parser.parse_args() | 152 | arguments = self.argument_parser.parse_args() |
6 | 153 | argspec = inspect.getargspec(arguments.func) | 153 | argspec = inspect.getargspec(arguments.func) |
7 | 154 | vargs = [] | 154 | vargs = [] |
8 | 155 | kwargs = {} | ||
9 | 156 | for arg in argspec.args: | 155 | for arg in argspec.args: |
10 | 157 | vargs.append(getattr(arguments, arg)) | 156 | vargs.append(getattr(arguments, arg)) |
11 | 158 | if argspec.varargs: | 157 | if argspec.varargs: |
12 | 159 | vargs.extend(getattr(arguments, argspec.varargs)) | 158 | vargs.extend(getattr(arguments, argspec.varargs)) |
17 | 160 | if argspec.keywords: | 159 | output = arguments.func(*vargs) |
14 | 161 | for kwarg in argspec.keywords.items(): | ||
15 | 162 | kwargs[kwarg] = getattr(arguments, kwarg) | ||
16 | 163 | output = arguments.func(*vargs, **kwargs) | ||
18 | 164 | if getattr(arguments.func, '_cli_test_command', False): | 160 | if getattr(arguments.func, '_cli_test_command', False): |
19 | 165 | self.exit_code = 0 if output else 1 | 161 | self.exit_code = 0 if output else 1 |
20 | 166 | output = '' | 162 | output = '' |
21 | 167 | 163 | ||
22 | === modified file 'charmhelpers/cli/commands.py' | |||
23 | --- charmhelpers/cli/commands.py 2015-07-31 13:11:32 +0000 | |||
24 | +++ charmhelpers/cli/commands.py 2015-08-17 13:36:14 +0000 | |||
25 | @@ -26,7 +26,7 @@ | |||
26 | 26 | """ | 26 | """ |
27 | 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. |
28 | 28 | """ | 28 | """ |
33 | 29 | import host # noqa | 29 | from . import host # noqa |
34 | 30 | import benchmark # noqa | 30 | from . import benchmark # noqa |
35 | 31 | import unitdata # noqa | 31 | from . import unitdata # noqa |
36 | 32 | from charmhelpers.core import hookenv # noqa | 32 | from . import hookenv # noqa |
37 | 33 | 33 | ||
38 | === modified file 'charmhelpers/contrib/openstack/amulet/deployment.py' | |||
39 | --- charmhelpers/contrib/openstack/amulet/deployment.py 2015-07-29 10:49:43 +0000 | |||
40 | +++ charmhelpers/contrib/openstack/amulet/deployment.py 2015-08-17 13:36:14 +0000 | |||
41 | @@ -44,7 +44,7 @@ | |||
42 | 44 | Determine if the local branch being tested is derived from its | 44 | Determine if the local branch being tested is derived from its |
43 | 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 |
44 | 46 | stable or next branches for the other_services.""" | 46 | stable or next branches for the other_services.""" |
46 | 47 | base_charms = ['mysql', 'mongodb'] | 47 | base_charms = ['mysql', 'mongodb', 'nrpe'] |
47 | 48 | 48 | ||
48 | 49 | if self.series in ['precise', 'trusty']: | 49 | if self.series in ['precise', 'trusty']: |
49 | 50 | base_series = self.series | 50 | base_series = self.series |
50 | @@ -81,7 +81,7 @@ | |||
51 | 81 | 'ceph-osd', 'ceph-radosgw'] | 81 | 'ceph-osd', 'ceph-radosgw'] |
52 | 82 | # Most OpenStack subordinate charms do not expose an origin option | 82 | # Most OpenStack subordinate charms do not expose an origin option |
53 | 83 | # as that is controlled by the principle. | 83 | # as that is controlled by the principle. |
55 | 84 | ignore = ['cinder-ceph', 'hacluster', 'neutron-openvswitch'] | 84 | ignore = ['cinder-ceph', 'hacluster', 'neutron-openvswitch', 'nrpe'] |
56 | 85 | 85 | ||
57 | 86 | if self.openstack: | 86 | if self.openstack: |
58 | 87 | for svc in services: | 87 | for svc in services: |
59 | 88 | 88 | ||
60 | === modified file 'charmhelpers/contrib/openstack/utils.py' | |||
61 | --- charmhelpers/contrib/openstack/utils.py 2015-07-29 10:49:43 +0000 | |||
62 | +++ charmhelpers/contrib/openstack/utils.py 2015-08-17 13:36:14 +0000 | |||
63 | @@ -24,6 +24,7 @@ | |||
64 | 24 | import json | 24 | import json |
65 | 25 | import os | 25 | import os |
66 | 26 | import sys | 26 | import sys |
67 | 27 | import re | ||
68 | 27 | 28 | ||
69 | 28 | import six | 29 | import six |
70 | 29 | import yaml | 30 | import yaml |
71 | @@ -69,7 +70,6 @@ | |||
72 | 69 | DISTRO_PROPOSED = ('deb http://archive.ubuntu.com/ubuntu/ %s-proposed ' | 70 | DISTRO_PROPOSED = ('deb http://archive.ubuntu.com/ubuntu/ %s-proposed ' |
73 | 70 | 'restricted main multiverse universe') | 71 | 'restricted main multiverse universe') |
74 | 71 | 72 | ||
75 | 72 | |||
76 | 73 | UBUNTU_OPENSTACK_RELEASE = OrderedDict([ | 73 | UBUNTU_OPENSTACK_RELEASE = OrderedDict([ |
77 | 74 | ('oneiric', 'diablo'), | 74 | ('oneiric', 'diablo'), |
78 | 75 | ('precise', 'essex'), | 75 | ('precise', 'essex'), |
79 | @@ -118,6 +118,34 @@ | |||
80 | 118 | ('2.3.0', 'liberty'), | 118 | ('2.3.0', 'liberty'), |
81 | 119 | ]) | 119 | ]) |
82 | 120 | 120 | ||
83 | 121 | # >= Liberty version->codename mapping | ||
84 | 122 | PACKAGE_CODENAMES = { | ||
85 | 123 | 'nova-common': OrderedDict([ | ||
86 | 124 | ('12.0.0', 'liberty'), | ||
87 | 125 | ]), | ||
88 | 126 | 'neutron-common': OrderedDict([ | ||
89 | 127 | ('7.0.0', 'liberty'), | ||
90 | 128 | ]), | ||
91 | 129 | 'cinder-common': OrderedDict([ | ||
92 | 130 | ('7.0.0', 'liberty'), | ||
93 | 131 | ]), | ||
94 | 132 | 'keystone': OrderedDict([ | ||
95 | 133 | ('8.0.0', 'liberty'), | ||
96 | 134 | ]), | ||
97 | 135 | 'horizon-common': OrderedDict([ | ||
98 | 136 | ('8.0.0', 'liberty'), | ||
99 | 137 | ]), | ||
100 | 138 | 'ceilometer-common': OrderedDict([ | ||
101 | 139 | ('5.0.0', 'liberty'), | ||
102 | 140 | ]), | ||
103 | 141 | 'heat-common': OrderedDict([ | ||
104 | 142 | ('5.0.0', 'liberty'), | ||
105 | 143 | ]), | ||
106 | 144 | 'glance-common': OrderedDict([ | ||
107 | 145 | ('11.0.0', 'liberty'), | ||
108 | 146 | ]), | ||
109 | 147 | } | ||
110 | 148 | |||
111 | 121 | DEFAULT_LOOPBACK_SIZE = '5G' | 149 | DEFAULT_LOOPBACK_SIZE = '5G' |
112 | 122 | 150 | ||
113 | 123 | 151 | ||
114 | @@ -201,20 +229,29 @@ | |||
115 | 201 | error_out(e) | 229 | error_out(e) |
116 | 202 | 230 | ||
117 | 203 | vers = apt.upstream_version(pkg.current_ver.ver_str) | 231 | vers = apt.upstream_version(pkg.current_ver.ver_str) |
118 | 232 | match = re.match('^(\d)\.(\d)\.(\d)', vers) | ||
119 | 233 | if match: | ||
120 | 234 | vers = match.group(0) | ||
121 | 204 | 235 | ||
135 | 205 | try: | 236 | # >= Liberty independent project versions |
136 | 206 | if 'swift' in pkg.name: | 237 | if (package in PACKAGE_CODENAMES and |
137 | 207 | swift_vers = vers[:5] | 238 | vers in PACKAGE_CODENAMES[package]): |
138 | 208 | if swift_vers not in SWIFT_CODENAMES: | 239 | return PACKAGE_CODENAMES[package][vers] |
139 | 209 | # Deal with 1.10.0 upward | 240 | else: |
140 | 210 | swift_vers = vers[:6] | 241 | # < Liberty co-ordinated project versions |
141 | 211 | return SWIFT_CODENAMES[swift_vers] | 242 | try: |
142 | 212 | else: | 243 | if 'swift' in pkg.name: |
143 | 213 | vers = vers[:6] | 244 | swift_vers = vers[:5] |
144 | 214 | return OPENSTACK_CODENAMES[vers] | 245 | if swift_vers not in SWIFT_CODENAMES: |
145 | 215 | except KeyError: | 246 | # Deal with 1.10.0 upward |
146 | 216 | e = 'Could not determine OpenStack codename for version %s' % vers | 247 | swift_vers = vers[:6] |
147 | 217 | error_out(e) | 248 | return SWIFT_CODENAMES[swift_vers] |
148 | 249 | else: | ||
149 | 250 | vers = vers[:6] | ||
150 | 251 | return OPENSTACK_CODENAMES[vers] | ||
151 | 252 | except KeyError: | ||
152 | 253 | e = 'Could not determine OpenStack codename for version %s' % vers | ||
153 | 254 | error_out(e) | ||
154 | 218 | 255 | ||
155 | 219 | 256 | ||
156 | 220 | def get_os_version_package(pkg, fatal=True): | 257 | def get_os_version_package(pkg, fatal=True): |
157 | 221 | 258 | ||
158 | === modified file 'charmhelpers/contrib/storage/linux/utils.py' | |||
159 | --- charmhelpers/contrib/storage/linux/utils.py 2015-07-29 10:49:43 +0000 | |||
160 | +++ charmhelpers/contrib/storage/linux/utils.py 2015-08-17 13:36:14 +0000 | |||
161 | @@ -43,9 +43,10 @@ | |||
162 | 43 | 43 | ||
163 | 44 | :param block_device: str: Full path of block device to clean. | 44 | :param block_device: str: Full path of block device to clean. |
164 | 45 | ''' | 45 | ''' |
165 | 46 | # https://github.com/ceph/ceph/commit/fdd7f8d83afa25c4e09aaedd90ab93f3b64a677b | ||
166 | 46 | # sometimes sgdisk exits non-zero; this is OK, dd will clean up | 47 | # sometimes sgdisk exits non-zero; this is OK, dd will clean up |
169 | 47 | call(['sgdisk', '--zap-all', '--mbrtogpt', | 48 | call(['sgdisk', '--zap-all', '--', block_device]) |
170 | 48 | '--clear', block_device]) | 49 | call(['sgdisk', '--clear', '--mbrtogpt', '--', block_device]) |
171 | 49 | dev_end = check_output(['blockdev', '--getsz', | 50 | dev_end = check_output(['blockdev', '--getsz', |
172 | 50 | block_device]).decode('UTF-8') | 51 | block_device]).decode('UTF-8') |
173 | 51 | gpt_end = int(dev_end.split()[0]) - 100 | 52 | gpt_end = int(dev_end.split()[0]) - 100 |
174 | 52 | 53 | ||
175 | === modified file 'charmhelpers/core/hookenv.py' | |||
176 | --- charmhelpers/core/hookenv.py 2015-08-03 14:00:44 +0000 | |||
177 | +++ charmhelpers/core/hookenv.py 2015-08-17 13:36:14 +0000 | |||
178 | @@ -34,23 +34,6 @@ | |||
179 | 34 | import tempfile | 34 | import tempfile |
180 | 35 | from subprocess import CalledProcessError | 35 | from subprocess import CalledProcessError |
181 | 36 | 36 | ||
182 | 37 | try: | ||
183 | 38 | from charmhelpers.cli import cmdline | ||
184 | 39 | except ImportError as e: | ||
185 | 40 | # due to the anti-pattern of partially synching charmhelpers directly | ||
186 | 41 | # into charms, it's possible that charmhelpers.cli is not available; | ||
187 | 42 | # if that's the case, they don't really care about using the cli anyway, | ||
188 | 43 | # so mock it out | ||
189 | 44 | if str(e) == 'No module named cli': | ||
190 | 45 | class cmdline(object): | ||
191 | 46 | @classmethod | ||
192 | 47 | def subcommand(cls, *args, **kwargs): | ||
193 | 48 | def _wrap(func): | ||
194 | 49 | return func | ||
195 | 50 | return _wrap | ||
196 | 51 | else: | ||
197 | 52 | raise | ||
198 | 53 | |||
199 | 54 | import six | 37 | import six |
200 | 55 | if not six.PY3: | 38 | if not six.PY3: |
201 | 56 | from UserDict import UserDict | 39 | from UserDict import UserDict |
202 | @@ -91,6 +74,7 @@ | |||
203 | 91 | res = func(*args, **kwargs) | 74 | res = func(*args, **kwargs) |
204 | 92 | cache[key] = res | 75 | cache[key] = res |
205 | 93 | return res | 76 | return res |
206 | 77 | wrapper._wrapped = func | ||
207 | 94 | return wrapper | 78 | return wrapper |
208 | 95 | 79 | ||
209 | 96 | 80 | ||
210 | @@ -190,7 +174,6 @@ | |||
211 | 190 | return os.environ.get('JUJU_RELATION', None) | 174 | return os.environ.get('JUJU_RELATION', None) |
212 | 191 | 175 | ||
213 | 192 | 176 | ||
214 | 193 | @cmdline.subcommand() | ||
215 | 194 | @cached | 177 | @cached |
216 | 195 | def relation_id(relation_name=None, service_or_unit=None): | 178 | def relation_id(relation_name=None, service_or_unit=None): |
217 | 196 | """The relation ID for the current or a specified relation""" | 179 | """The relation ID for the current or a specified relation""" |
218 | @@ -216,13 +199,11 @@ | |||
219 | 216 | return os.environ.get('JUJU_REMOTE_UNIT', None) | 199 | return os.environ.get('JUJU_REMOTE_UNIT', None) |
220 | 217 | 200 | ||
221 | 218 | 201 | ||
222 | 219 | @cmdline.subcommand() | ||
223 | 220 | def service_name(): | 202 | def service_name(): |
224 | 221 | """The name service group this unit belongs to""" | 203 | """The name service group this unit belongs to""" |
225 | 222 | return local_unit().split('/')[0] | 204 | return local_unit().split('/')[0] |
226 | 223 | 205 | ||
227 | 224 | 206 | ||
228 | 225 | @cmdline.subcommand() | ||
229 | 226 | @cached | 207 | @cached |
230 | 227 | def remote_service_name(relid=None): | 208 | def remote_service_name(relid=None): |
231 | 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)""" |
232 | 229 | 210 | ||
233 | === modified file 'charmhelpers/core/host.py' | |||
234 | --- charmhelpers/core/host.py 2015-07-29 10:49:43 +0000 | |||
235 | +++ charmhelpers/core/host.py 2015-08-17 13:36:14 +0000 | |||
236 | @@ -72,7 +72,7 @@ | |||
237 | 72 | stopped = service_stop(service_name) | 72 | stopped = service_stop(service_name) |
238 | 73 | # XXX: Support systemd too | 73 | # XXX: Support systemd too |
239 | 74 | override_path = os.path.join( | 74 | override_path = os.path.join( |
241 | 75 | init_dir, '{}.conf.override'.format(service_name)) | 75 | init_dir, '{}.override'.format(service_name)) |
242 | 76 | with open(override_path, 'w') as fh: | 76 | with open(override_path, 'w') as fh: |
243 | 77 | fh.write("manual\n") | 77 | fh.write("manual\n") |
244 | 78 | return stopped | 78 | return stopped |
245 | @@ -86,7 +86,7 @@ | |||
246 | 86 | if init_dir is None: | 86 | if init_dir is None: |
247 | 87 | init_dir = "/etc/init" | 87 | init_dir = "/etc/init" |
248 | 88 | override_path = os.path.join( | 88 | override_path = os.path.join( |
250 | 89 | init_dir, '{}.conf.override'.format(service_name)) | 89 | init_dir, '{}.override'.format(service_name)) |
251 | 90 | if os.path.exists(override_path): | 90 | if os.path.exists(override_path): |
252 | 91 | os.unlink(override_path) | 91 | os.unlink(override_path) |
253 | 92 | started = service_start(service_name) | 92 | started = service_start(service_name) |
254 | 93 | 93 | ||
255 | === modified file 'charmhelpers/fetch/__init__.py' | |||
256 | --- charmhelpers/fetch/__init__.py 2015-07-29 10:49:43 +0000 | |||
257 | +++ charmhelpers/fetch/__init__.py 2015-08-17 13:36:14 +0000 | |||
258 | @@ -90,6 +90,14 @@ | |||
259 | 90 | 'kilo/proposed': 'trusty-proposed/kilo', | 90 | 'kilo/proposed': 'trusty-proposed/kilo', |
260 | 91 | 'trusty-kilo/proposed': 'trusty-proposed/kilo', | 91 | 'trusty-kilo/proposed': 'trusty-proposed/kilo', |
261 | 92 | 'trusty-proposed/kilo': 'trusty-proposed/kilo', | 92 | 'trusty-proposed/kilo': 'trusty-proposed/kilo', |
262 | 93 | # Liberty | ||
263 | 94 | 'liberty': 'trusty-updates/liberty', | ||
264 | 95 | 'trusty-liberty': 'trusty-updates/liberty', | ||
265 | 96 | 'trusty-liberty/updates': 'trusty-updates/liberty', | ||
266 | 97 | 'trusty-updates/liberty': 'trusty-updates/liberty', | ||
267 | 98 | 'liberty/proposed': 'trusty-proposed/liberty', | ||
268 | 99 | 'trusty-liberty/proposed': 'trusty-proposed/liberty', | ||
269 | 100 | 'trusty-proposed/liberty': 'trusty-proposed/liberty', | ||
270 | 93 | } | 101 | } |
271 | 94 | 102 | ||
272 | 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 |
273 | 96 | 104 | ||
274 | === modified file 'tests/basic_deployment.py' | |||
275 | --- tests/basic_deployment.py 2015-04-16 21:31:35 +0000 | |||
276 | +++ tests/basic_deployment.py 2015-08-17 13:36:14 +0000 | |||
277 | @@ -1,5 +1,3 @@ | |||
278 | 1 | #!/usr/bin/python | ||
279 | 2 | |||
280 | 3 | import amulet | 1 | import amulet |
281 | 4 | import swiftclient | 2 | import swiftclient |
282 | 5 | 3 | ||
283 | @@ -122,29 +120,30 @@ | |||
284 | 122 | def test_services(self): | 120 | def test_services(self): |
285 | 123 | """Verify the expected services are running on the corresponding | 121 | """Verify the expected services are running on the corresponding |
286 | 124 | service units.""" | 122 | service units.""" |
299 | 125 | swift_storage_services = ['status swift-account', | 123 | swift_storage_services = ['swift-account', |
300 | 126 | 'status swift-account-auditor', | 124 | 'swift-account-auditor', |
301 | 127 | 'status swift-account-reaper', | 125 | 'swift-account-reaper', |
302 | 128 | 'status swift-account-replicator', | 126 | 'swift-account-replicator', |
303 | 129 | 'status swift-container', | 127 | 'swift-container', |
304 | 130 | 'status swift-container-auditor', | 128 | 'swift-container-auditor', |
305 | 131 | 'status swift-container-replicator', | 129 | 'swift-container-replicator', |
306 | 132 | 'status swift-container-updater', | 130 | 'swift-container-updater', |
307 | 133 | 'status swift-object', | 131 | 'swift-object', |
308 | 134 | 'status swift-object-auditor', | 132 | 'swift-object-auditor', |
309 | 135 | 'status swift-object-replicator', | 133 | 'swift-object-replicator', |
310 | 136 | 'status swift-object-updater'] | 134 | 'swift-object-updater'] |
311 | 137 | if self._get_openstack_release() >= self.precise_icehouse: | 135 | if self._get_openstack_release() >= self.precise_icehouse: |
318 | 138 | swift_storage_services.append('status swift-container-sync') | 136 | swift_storage_services.append('swift-container-sync') |
319 | 139 | commands = { | 137 | service_names = { |
320 | 140 | self.mysql_sentry: ['status mysql'], | 138 | self.mysql_sentry: ['mysql'], |
321 | 141 | self.keystone_sentry: ['status keystone'], | 139 | self.keystone_sentry: ['keystone'], |
322 | 142 | self.glance_sentry: ['status glance-registry', 'status glance-api'], | 140 | self.glance_sentry: [ |
323 | 143 | self.swift_proxy_sentry: ['status swift-proxy'], | 141 | 'glance-registry', 'glance-api'], |
324 | 142 | self.swift_proxy_sentry: ['swift-proxy'], | ||
325 | 144 | self.swift_storage_sentry: swift_storage_services | 143 | self.swift_storage_sentry: swift_storage_services |
326 | 145 | } | 144 | } |
327 | 146 | 145 | ||
329 | 147 | ret = u.validate_services(commands) | 146 | ret = u.validate_services_by_name(service_names) |
330 | 148 | if ret: | 147 | if ret: |
331 | 149 | amulet.raise_status(amulet.FAIL, msg=ret) | 148 | amulet.raise_status(amulet.FAIL, msg=ret) |
332 | 150 | 149 | ||
333 | 151 | 150 | ||
334 | === modified file 'tests/charmhelpers/contrib/amulet/utils.py' | |||
335 | --- tests/charmhelpers/contrib/amulet/utils.py 2015-07-29 10:49:43 +0000 | |||
336 | +++ tests/charmhelpers/contrib/amulet/utils.py 2015-08-17 13:36:14 +0000 | |||
337 | @@ -14,17 +14,23 @@ | |||
338 | 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 |
339 | 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/>. |
340 | 16 | 16 | ||
341 | 17 | import amulet | ||
342 | 18 | import ConfigParser | ||
343 | 19 | import distro_info | ||
344 | 20 | import io | 17 | import io |
345 | 18 | import json | ||
346 | 21 | import logging | 19 | import logging |
347 | 22 | import os | 20 | import os |
348 | 23 | import re | 21 | import re |
350 | 24 | import six | 22 | import subprocess |
351 | 25 | import sys | 23 | import sys |
352 | 26 | import time | 24 | import time |
354 | 27 | import urlparse | 25 | |
355 | 26 | import amulet | ||
356 | 27 | import distro_info | ||
357 | 28 | import six | ||
358 | 29 | from six.moves import configparser | ||
359 | 30 | if six.PY3: | ||
360 | 31 | from urllib import parse as urlparse | ||
361 | 32 | else: | ||
362 | 33 | import urlparse | ||
363 | 28 | 34 | ||
364 | 29 | 35 | ||
365 | 30 | class AmuletUtils(object): | 36 | class AmuletUtils(object): |
366 | @@ -142,19 +148,23 @@ | |||
367 | 142 | 148 | ||
368 | 143 | for service_name in services_list: | 149 | for service_name in services_list: |
369 | 144 | if (self.ubuntu_releases.index(release) >= systemd_switch or | 150 | if (self.ubuntu_releases.index(release) >= systemd_switch or |
372 | 145 | service_name == "rabbitmq-server"): | 151 | service_name in ['rabbitmq-server', 'apache2']): |
373 | 146 | # init is systemd | 152 | # init is systemd (or regular sysv) |
374 | 147 | cmd = 'sudo service {} status'.format(service_name) | 153 | cmd = 'sudo service {} status'.format(service_name) |
375 | 154 | output, code = sentry_unit.run(cmd) | ||
376 | 155 | service_running = code == 0 | ||
377 | 148 | elif self.ubuntu_releases.index(release) < systemd_switch: | 156 | elif self.ubuntu_releases.index(release) < systemd_switch: |
378 | 149 | # init is upstart | 157 | # init is upstart |
379 | 150 | cmd = 'sudo status {}'.format(service_name) | 158 | cmd = 'sudo status {}'.format(service_name) |
380 | 159 | output, code = sentry_unit.run(cmd) | ||
381 | 160 | service_running = code == 0 and "start/running" in output | ||
382 | 151 | 161 | ||
383 | 152 | output, code = sentry_unit.run(cmd) | ||
384 | 153 | self.log.debug('{} `{}` returned ' | 162 | self.log.debug('{} `{}` returned ' |
385 | 154 | '{}'.format(sentry_unit.info['unit_name'], | 163 | '{}'.format(sentry_unit.info['unit_name'], |
386 | 155 | cmd, code)) | 164 | cmd, code)) |
389 | 156 | if code != 0: | 165 | if not service_running: |
390 | 157 | return "command `{}` returned {}".format(cmd, str(code)) | 166 | return u"command `{}` returned {} {}".format( |
391 | 167 | cmd, output, str(code)) | ||
392 | 158 | return None | 168 | return None |
393 | 159 | 169 | ||
394 | 160 | def _get_config(self, unit, filename): | 170 | def _get_config(self, unit, filename): |
395 | @@ -164,7 +174,7 @@ | |||
396 | 164 | # NOTE(beisner): by default, ConfigParser does not handle options | 174 | # NOTE(beisner): by default, ConfigParser does not handle options |
397 | 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. |
398 | 166 | # https://bugs.python.org/issue7005 | 176 | # https://bugs.python.org/issue7005 |
400 | 167 | config = ConfigParser.ConfigParser(allow_no_value=True) | 177 | config = configparser.ConfigParser(allow_no_value=True) |
401 | 168 | config.readfp(io.StringIO(file_contents)) | 178 | config.readfp(io.StringIO(file_contents)) |
402 | 169 | return config | 179 | return config |
403 | 170 | 180 | ||
404 | @@ -450,15 +460,20 @@ | |||
405 | 450 | cmd, code, output)) | 460 | cmd, code, output)) |
406 | 451 | return None | 461 | return None |
407 | 452 | 462 | ||
409 | 453 | def get_process_id_list(self, sentry_unit, process_name): | 463 | def get_process_id_list(self, sentry_unit, process_name, |
410 | 464 | expect_success=True): | ||
411 | 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 |
412 | 455 | for a single process name. | 466 | for a single process name. |
413 | 456 | 467 | ||
415 | 457 | :param sentry_unit: Pointer to amulet sentry instance (juju unit) | 468 | :param sentry_unit: Amulet sentry instance (juju unit) |
416 | 458 | :param process_name: Process name | 469 | :param process_name: Process name |
417 | 470 | :param expect_success: If False, expect the PID to be missing, | ||
418 | 471 | raise if it is present. | ||
419 | 459 | :returns: List of process IDs | 472 | :returns: List of process IDs |
420 | 460 | """ | 473 | """ |
422 | 461 | cmd = 'pidof {}'.format(process_name) | 474 | cmd = 'pidof -x {}'.format(process_name) |
423 | 475 | if not expect_success: | ||
424 | 476 | cmd += " || exit 0 && exit 1" | ||
425 | 462 | output, code = sentry_unit.run(cmd) | 477 | output, code = sentry_unit.run(cmd) |
426 | 463 | if code != 0: | 478 | if code != 0: |
427 | 464 | msg = ('{} `{}` returned {} ' | 479 | msg = ('{} `{}` returned {} ' |
428 | @@ -467,14 +482,23 @@ | |||
429 | 467 | amulet.raise_status(amulet.FAIL, msg=msg) | 482 | amulet.raise_status(amulet.FAIL, msg=msg) |
430 | 468 | return str(output).split() | 483 | return str(output).split() |
431 | 469 | 484 | ||
433 | 470 | def get_unit_process_ids(self, unit_processes): | 485 | def get_unit_process_ids(self, unit_processes, expect_success=True): |
434 | 471 | """Construct a dict containing unit sentries, process names, and | 486 | """Construct a dict containing unit sentries, process names, and |
436 | 472 | process IDs.""" | 487 | process IDs. |
437 | 488 | |||
438 | 489 | :param unit_processes: A dictionary of Amulet sentry instance | ||
439 | 490 | to list of process names. | ||
440 | 491 | :param expect_success: if False expect the processes to not be | ||
441 | 492 | running, raise if they are. | ||
442 | 493 | :returns: Dictionary of Amulet sentry instance to dictionary | ||
443 | 494 | of process names to PIDs. | ||
444 | 495 | """ | ||
445 | 473 | pid_dict = {} | 496 | pid_dict = {} |
447 | 474 | for sentry_unit, process_list in unit_processes.iteritems(): | 497 | for sentry_unit, process_list in six.iteritems(unit_processes): |
448 | 475 | pid_dict[sentry_unit] = {} | 498 | pid_dict[sentry_unit] = {} |
449 | 476 | for process in process_list: | 499 | for process in process_list: |
451 | 477 | pids = self.get_process_id_list(sentry_unit, process) | 500 | pids = self.get_process_id_list( |
452 | 501 | sentry_unit, process, expect_success=expect_success) | ||
453 | 478 | pid_dict[sentry_unit].update({process: pids}) | 502 | pid_dict[sentry_unit].update({process: pids}) |
454 | 479 | return pid_dict | 503 | return pid_dict |
455 | 480 | 504 | ||
456 | @@ -488,7 +512,7 @@ | |||
457 | 488 | return ('Unit count mismatch. expected, actual: {}, ' | 512 | return ('Unit count mismatch. expected, actual: {}, ' |
458 | 489 | '{} '.format(len(expected), len(actual))) | 513 | '{} '.format(len(expected), len(actual))) |
459 | 490 | 514 | ||
461 | 491 | for (e_sentry, e_proc_names) in expected.iteritems(): | 515 | for (e_sentry, e_proc_names) in six.iteritems(expected): |
462 | 492 | e_sentry_name = e_sentry.info['unit_name'] | 516 | e_sentry_name = e_sentry.info['unit_name'] |
463 | 493 | if e_sentry in actual.keys(): | 517 | if e_sentry in actual.keys(): |
464 | 494 | a_proc_names = actual[e_sentry] | 518 | a_proc_names = actual[e_sentry] |
465 | @@ -507,11 +531,23 @@ | |||
466 | 507 | '{}'.format(e_proc_name, a_proc_name)) | 531 | '{}'.format(e_proc_name, a_proc_name)) |
467 | 508 | 532 | ||
468 | 509 | a_pids_length = len(a_pids) | 533 | a_pids_length = len(a_pids) |
471 | 510 | if e_pids_length != a_pids_length: | 534 | fail_msg = ('PID count mismatch. {} ({}) expected, actual: ' |
470 | 511 | return ('PID count mismatch. {} ({}) expected, actual: ' | ||
472 | 512 | '{}, {} ({})'.format(e_sentry_name, e_proc_name, | 535 | '{}, {} ({})'.format(e_sentry_name, e_proc_name, |
473 | 513 | e_pids_length, a_pids_length, | 536 | e_pids_length, a_pids_length, |
474 | 514 | a_pids)) | 537 | a_pids)) |
475 | 538 | |||
476 | 539 | # If expected is not bool, ensure PID quantities match | ||
477 | 540 | if not isinstance(e_pids_length, bool) and \ | ||
478 | 541 | a_pids_length != e_pids_length: | ||
479 | 542 | return fail_msg | ||
480 | 543 | # If expected is bool True, ensure 1 or more PIDs exist | ||
481 | 544 | elif isinstance(e_pids_length, bool) and \ | ||
482 | 545 | e_pids_length is True and a_pids_length < 1: | ||
483 | 546 | return fail_msg | ||
484 | 547 | # If expected is bool False, ensure 0 PIDs exist | ||
485 | 548 | elif isinstance(e_pids_length, bool) and \ | ||
486 | 549 | e_pids_length is False and a_pids_length != 0: | ||
487 | 550 | return fail_msg | ||
488 | 515 | else: | 551 | else: |
489 | 516 | self.log.debug('PID check OK: {} {} {}: ' | 552 | self.log.debug('PID check OK: {} {} {}: ' |
490 | 517 | '{}'.format(e_sentry_name, e_proc_name, | 553 | '{}'.format(e_sentry_name, e_proc_name, |
491 | @@ -531,3 +567,30 @@ | |||
492 | 531 | return 'Dicts within list are not identical' | 567 | return 'Dicts within list are not identical' |
493 | 532 | 568 | ||
494 | 533 | return None | 569 | return None |
495 | 570 | |||
496 | 571 | def run_action(self, unit_sentry, action, | ||
497 | 572 | _check_output=subprocess.check_output): | ||
498 | 573 | """Run the named action on a given unit sentry. | ||
499 | 574 | |||
500 | 575 | _check_output parameter is used for dependency injection. | ||
501 | 576 | |||
502 | 577 | @return action_id. | ||
503 | 578 | """ | ||
504 | 579 | unit_id = unit_sentry.info["unit_name"] | ||
505 | 580 | command = ["juju", "action", "do", "--format=json", unit_id, action] | ||
506 | 581 | self.log.info("Running command: %s\n" % " ".join(command)) | ||
507 | 582 | output = _check_output(command, universal_newlines=True) | ||
508 | 583 | data = json.loads(output) | ||
509 | 584 | action_id = data[u'Action queued with id'] | ||
510 | 585 | return action_id | ||
511 | 586 | |||
512 | 587 | def wait_on_action(self, action_id, _check_output=subprocess.check_output): | ||
513 | 588 | """Wait for a given action, returning if it completed or not. | ||
514 | 589 | |||
515 | 590 | _check_output parameter is used for dependency injection. | ||
516 | 591 | """ | ||
517 | 592 | command = ["juju", "action", "fetch", "--format=json", "--wait=0", | ||
518 | 593 | action_id] | ||
519 | 594 | output = _check_output(command, universal_newlines=True) | ||
520 | 595 | data = json.loads(output) | ||
521 | 596 | return data.get(u"status") == "completed" | ||
522 | 534 | 597 | ||
523 | === modified file 'tests/charmhelpers/contrib/openstack/amulet/deployment.py' | |||
524 | --- tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-07-29 10:49:43 +0000 | |||
525 | +++ tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-08-17 13:36:14 +0000 | |||
526 | @@ -44,7 +44,7 @@ | |||
527 | 44 | Determine if the local branch being tested is derived from its | 44 | Determine if the local branch being tested is derived from its |
528 | 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 |
529 | 46 | stable or next branches for the other_services.""" | 46 | stable or next branches for the other_services.""" |
531 | 47 | base_charms = ['mysql', 'mongodb'] | 47 | base_charms = ['mysql', 'mongodb', 'nrpe'] |
532 | 48 | 48 | ||
533 | 49 | if self.series in ['precise', 'trusty']: | 49 | if self.series in ['precise', 'trusty']: |
534 | 50 | base_series = self.series | 50 | base_series = self.series |
535 | @@ -81,7 +81,7 @@ | |||
536 | 81 | 'ceph-osd', 'ceph-radosgw'] | 81 | 'ceph-osd', 'ceph-radosgw'] |
537 | 82 | # Most OpenStack subordinate charms do not expose an origin option | 82 | # Most OpenStack subordinate charms do not expose an origin option |
538 | 83 | # as that is controlled by the principle. | 83 | # as that is controlled by the principle. |
540 | 84 | ignore = ['cinder-ceph', 'hacluster', 'neutron-openvswitch'] | 84 | ignore = ['cinder-ceph', 'hacluster', 'neutron-openvswitch', 'nrpe'] |
541 | 85 | 85 | ||
542 | 86 | if self.openstack: | 86 | if self.openstack: |
543 | 87 | for svc in services: | 87 | for svc in services: |
charm_lint_check #8194 swift-storage-next for adam-collard mp268228
LINT OK: passed
Build: http:// 10.245. 162.77: 8080/job/ charm_lint_ check/8194/