Merge lp:~gnuoy/charms/trusty/ceph-radosgw/workloadstatus into lp:~openstack-charmers-archive/charms/trusty/ceph-radosgw/next
- Trusty Tahr (14.04)
- workloadstatus
- Merge into next
Status: | Merged |
---|---|
Merged at revision: | 47 |
Proposed branch: | lp:~gnuoy/charms/trusty/ceph-radosgw/workloadstatus |
Merge into: | lp:~openstack-charmers-archive/charms/trusty/ceph-radosgw/next |
Diff against target: |
830 lines (+362/-207) 6 files modified
hooks/ceph_radosgw_context.py (+92/-0) hooks/hooks.py (+14/-78) hooks/install (+1/-1) hooks/utils.py (+45/-16) unit_tests/test_ceph_radosgw_context.py (+202/-0) unit_tests/test_hooks.py (+8/-112) |
To merge this branch: | bzr merge lp:~gnuoy/charms/trusty/ceph-radosgw/workloadstatus |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
David Ames (community) | Approve | ||
Review via email: mp+273834@code.launchpad.net |
Commit message
Description of the change
- 50. By Liam Young
-
Tidyup
uosci-testing-bot (uosci-testing-bot) wrote : | # |
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #11511 ceph-radosgw-next for gnuoy mp273834
LINT OK: passed
Build: http://
Liam Young (gnuoy) wrote : | # |
This patch is a little larger than the other workload status ones because I've taken the opportunity to move the rendering of the ceph.conf over to us the templating and context helpers from charm helpers to bring it more inline with other openstack charms.
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #7214 ceph-radosgw-next for gnuoy mp273834
AMULET OK: passed
Build: http://
David Ames (thedac) wrote : | # |
This is looking good. And it was useful for me to see the addition of a context object.
I have a couple of questions in line for the benefit of my own understanding.
- 51. By Liam Young
-
Identity relation should be an optional interface for status checks as not all versions support it. Catch inconsistent auth passed back by mons
- 52. By Liam Young
-
Fix lint and add unit test to test inconsistent auths
Liam Young (gnuoy) wrote : | # |
Manually ran amulet:
juju-test INFO : Results: 6 passed, 0 failed, 0 errored
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #11660 ceph-radosgw-next for gnuoy mp273834
LINT OK: passed
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #11713 ceph-radosgw-next for gnuoy mp273834
LINT OK: passed
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #10894 ceph-radosgw-next for gnuoy mp273834
UNIT OK: passed
David Ames (thedac) wrote : | # |
Looks great, merging.
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #7278 ceph-radosgw-next for gnuoy mp273834
AMULET FAIL: amulet-test failed
AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.
Full amulet test output: http://
Build: http://
Preview Diff
1 | === modified file 'hooks/ceph_radosgw_context.py' |
2 | --- hooks/ceph_radosgw_context.py 2015-01-14 16:48:07 +0000 |
3 | +++ hooks/ceph_radosgw_context.py 2015-10-12 10:56:13 +0000 |
4 | @@ -3,6 +3,18 @@ |
5 | determine_api_port, |
6 | determine_apache_port, |
7 | ) |
8 | +from charmhelpers.core.host import cmp_pkgrevno |
9 | +from charmhelpers.core.hookenv import ( |
10 | + WARNING, |
11 | + config, |
12 | + log, |
13 | + relation_ids, |
14 | + related_units, |
15 | + relation_get, |
16 | + unit_get, |
17 | +) |
18 | +import socket |
19 | +import dns.resolver |
20 | |
21 | |
22 | class HAProxyContext(context.HAProxyContext): |
23 | @@ -27,3 +39,83 @@ |
24 | # for haproxy.conf |
25 | ctxt['service_ports'] = port_mapping |
26 | return ctxt |
27 | + |
28 | + |
29 | +class IdentityServiceContext(context.IdentityServiceContext): |
30 | + interfaces = ['identity-service'] |
31 | + |
32 | + def __call__(self): |
33 | + ctxt = super(IdentityServiceContext, self).__call__() |
34 | + if not ctxt: |
35 | + return |
36 | + |
37 | + ctxt['admin_token'] = None |
38 | + for relid in relation_ids('identity-service'): |
39 | + for unit in related_units(relid): |
40 | + if not ctxt.get('admin_token'): |
41 | + ctxt['admin_token'] = \ |
42 | + relation_get('admin_token', unit, relid) |
43 | + |
44 | + ctxt['auth_type'] = 'keystone' |
45 | + ctxt['user_roles'] = config('operator-roles') |
46 | + ctxt['cache_size'] = config('cache-size') |
47 | + ctxt['revocation_check_interval'] = config('revocation-check-interval') |
48 | + if self.context_complete(ctxt): |
49 | + return ctxt |
50 | + |
51 | + return {} |
52 | + |
53 | + |
54 | +class MonContext(context.OSContextGenerator): |
55 | + interfaces = ['ceph-radosgw'] |
56 | + |
57 | + def __call__(self): |
58 | + if not relation_ids('mon'): |
59 | + return {} |
60 | + hosts = [] |
61 | + auths = [] |
62 | + for relid in relation_ids('mon'): |
63 | + for unit in related_units(relid): |
64 | + ceph_public_addr = relation_get('ceph-public-address', unit, |
65 | + relid) |
66 | + if ceph_public_addr: |
67 | + host_ip = self.get_host_ip(ceph_public_addr) |
68 | + hosts.append('{}:6789'.format(host_ip)) |
69 | + _auth = relation_get('auth', unit, relid) |
70 | + if _auth: |
71 | + auths.append(_auth) |
72 | + if len(set(auths)) != 1: |
73 | + e = ("Inconsistent or absent auth returned by mon units. Setting " |
74 | + "auth_supported to 'none'") |
75 | + log(e, level=WARNING) |
76 | + auth = 'none' |
77 | + else: |
78 | + auth = auths[0] |
79 | + hosts.sort() |
80 | + ctxt = { |
81 | + 'auth_supported': auth, |
82 | + 'mon_hosts': ' '.join(hosts), |
83 | + 'hostname': socket.gethostname(), |
84 | + 'old_auth': cmp_pkgrevno('radosgw', "0.51") < 0, |
85 | + 'use_syslog': str(config('use-syslog')).lower(), |
86 | + 'embedded_webserver': config('use-embedded-webserver'), |
87 | + } |
88 | + |
89 | + if self.context_complete(ctxt): |
90 | + return ctxt |
91 | + |
92 | + return {} |
93 | + |
94 | + def get_host_ip(self, hostname=None): |
95 | + try: |
96 | + if not hostname: |
97 | + hostname = unit_get('private-address') |
98 | + # Test to see if already an IPv4 address |
99 | + socket.inet_aton(hostname) |
100 | + return hostname |
101 | + except socket.error: |
102 | + # This may throw an NXDOMAIN exception; in which case |
103 | + # things are badly broken so just let it kill the hook |
104 | + answers = dns.resolver.query(hostname, 'A') |
105 | + if answers: |
106 | + return answers[0].address |
107 | |
108 | === modified file 'hooks/hooks.py' |
109 | --- hooks/hooks.py 2015-09-22 13:36:25 +0000 |
110 | +++ hooks/hooks.py 2015-10-12 10:56:13 +0000 |
111 | @@ -16,13 +16,13 @@ |
112 | from charmhelpers.core.hookenv import ( |
113 | relation_get, |
114 | relation_ids, |
115 | - related_units, |
116 | config, |
117 | unit_get, |
118 | open_port, |
119 | relation_set, |
120 | log, ERROR, |
121 | Hooks, UnregisteredHookError, |
122 | + status_set, |
123 | ) |
124 | from charmhelpers.fetch import ( |
125 | apt_update, |
126 | @@ -32,20 +32,20 @@ |
127 | ) |
128 | from charmhelpers.core.host import ( |
129 | lsb_release, |
130 | - restart_on_change |
131 | + restart_on_change, |
132 | ) |
133 | from utils import ( |
134 | render_template, |
135 | - get_host_ip, |
136 | enable_pocket, |
137 | is_apache_24, |
138 | CEPHRG_HA_RES, |
139 | register_configs, |
140 | + REQUIRED_INTERFACES, |
141 | + check_optional_relations, |
142 | ) |
143 | |
144 | from charmhelpers.payload.execd import execd_preinstall |
145 | from charmhelpers.core.host import cmp_pkgrevno |
146 | -from socket import gethostname as get_unit_hostname |
147 | |
148 | from charmhelpers.contrib.network.ip import ( |
149 | get_iface_for_address, |
150 | @@ -55,7 +55,9 @@ |
151 | canonical_url, |
152 | PUBLIC, INTERNAL, ADMIN, |
153 | ) |
154 | - |
155 | +from charmhelpers.contrib.openstack.utils import ( |
156 | + set_os_workload_status, |
157 | +) |
158 | hooks = Hooks() |
159 | CONFIGS = register_configs() |
160 | |
161 | @@ -96,6 +98,7 @@ |
162 | |
163 | |
164 | def install_packages(): |
165 | + status_set('maintenance', 'Installing apt packages') |
166 | add_source(config('source'), config('key')) |
167 | if (config('use-ceph-optimised-packages') and |
168 | not config('use-embedded-webserver')): |
169 | @@ -111,37 +114,14 @@ |
170 | |
171 | @hooks.hook('install.real') |
172 | def install(): |
173 | + status_set('maintenance', 'Executing pre-install') |
174 | execd_preinstall() |
175 | enable_pocket('multiverse') |
176 | install_packages() |
177 | os.makedirs(NSS_DIR) |
178 | - |
179 | - |
180 | -def emit_cephconf(): |
181 | - # Ensure ceph directory actually exists |
182 | if not os.path.exists('/etc/ceph'): |
183 | os.makedirs('/etc/ceph') |
184 | |
185 | - cephcontext = { |
186 | - 'auth_supported': get_auth() or 'none', |
187 | - 'mon_hosts': ' '.join(get_mon_hosts()), |
188 | - 'hostname': get_unit_hostname(), |
189 | - 'old_auth': cmp_pkgrevno('radosgw', "0.51") < 0, |
190 | - 'use_syslog': str(config('use-syslog')).lower(), |
191 | - 'embedded_webserver': config('use-embedded-webserver'), |
192 | - } |
193 | - |
194 | - # Check to ensure that correct version of ceph is |
195 | - # in use |
196 | - if cmp_pkgrevno('radosgw', '0.55') >= 0: |
197 | - # Add keystone configuration if found |
198 | - ks_conf = get_keystone_conf() |
199 | - if ks_conf: |
200 | - cephcontext.update(ks_conf) |
201 | - |
202 | - with open('/etc/ceph/ceph.conf', 'w') as cephconf: |
203 | - cephconf.write(render_template('ceph.conf', cephcontext)) |
204 | - |
205 | |
206 | def emit_apacheconf(): |
207 | apachecontext = { |
208 | @@ -181,9 +161,9 @@ |
209 | '/etc/haproxy/haproxy.cfg': ['haproxy']}) |
210 | def config_changed(): |
211 | install_packages() |
212 | - emit_cephconf() |
213 | CONFIGS.write_all() |
214 | if not config('use-embedded-webserver'): |
215 | + status_set('maintenance', 'configuring apache') |
216 | emit_apacheconf() |
217 | install_www_scripts() |
218 | apache_sites() |
219 | @@ -194,57 +174,11 @@ |
220 | identity_joined(relid=r_id) |
221 | |
222 | |
223 | -def get_mon_hosts(): |
224 | - hosts = [] |
225 | - for relid in relation_ids('mon'): |
226 | - for unit in related_units(relid): |
227 | - host_ip = get_host_ip(relation_get('ceph-public-address', |
228 | - unit, relid)) |
229 | - hosts.append('{}:6789'.format(host_ip)) |
230 | - |
231 | - hosts.sort() |
232 | - return hosts |
233 | - |
234 | - |
235 | -def get_auth(): |
236 | - return get_conf('auth') |
237 | - |
238 | - |
239 | -def get_conf(name): |
240 | - for relid in relation_ids('mon'): |
241 | - for unit in related_units(relid): |
242 | - conf = relation_get(name, |
243 | - unit, relid) |
244 | - if conf: |
245 | - return conf |
246 | - return None |
247 | - |
248 | - |
249 | -def get_keystone_conf(): |
250 | - for relid in relation_ids('identity-service'): |
251 | - for unit in related_units(relid): |
252 | - ks_auth = { |
253 | - 'auth_type': 'keystone', |
254 | - 'auth_protocol': |
255 | - relation_get('auth_protocol', unit, relid) or "http", |
256 | - 'auth_host': relation_get('auth_host', unit, relid), |
257 | - 'auth_port': relation_get('auth_port', unit, relid), |
258 | - 'admin_token': relation_get('admin_token', unit, relid), |
259 | - 'user_roles': config('operator-roles'), |
260 | - 'cache_size': config('cache-size'), |
261 | - 'revocation_check_interval': |
262 | - config('revocation-check-interval') |
263 | - } |
264 | - if None not in ks_auth.itervalues(): |
265 | - return ks_auth |
266 | - return None |
267 | - |
268 | - |
269 | @hooks.hook('mon-relation-departed', |
270 | 'mon-relation-changed') |
271 | @restart_on_change({'/etc/ceph/ceph.conf': ['radosgw']}) |
272 | def mon_relation(): |
273 | - emit_cephconf() |
274 | + CONFIGS.write_all() |
275 | key = relation_get('radosgw_key') |
276 | if key: |
277 | ceph.import_radosgw_key(key) |
278 | @@ -295,7 +229,7 @@ |
279 | @hooks.hook('identity-service-relation-changed') |
280 | @restart_on_change({'/etc/ceph/ceph.conf': ['radosgw']}) |
281 | def identity_changed(): |
282 | - emit_cephconf() |
283 | + CONFIGS.write_all() |
284 | restart() |
285 | |
286 | |
287 | @@ -377,3 +311,5 @@ |
288 | hooks.execute(sys.argv) |
289 | except UnregisteredHookError as e: |
290 | log('Unknown hook {} - skipping.'.format(e)) |
291 | + set_os_workload_status(CONFIGS, REQUIRED_INTERFACES, |
292 | + charm_func=check_optional_relations) |
293 | |
294 | === modified file 'hooks/install' |
295 | --- hooks/install 2015-09-22 13:36:25 +0000 |
296 | +++ hooks/install 2015-10-12 10:56:13 +0000 |
297 | @@ -2,7 +2,7 @@ |
298 | # Wrapper to deal with newer Ubuntu versions that don't have py2 installed |
299 | # by default. |
300 | |
301 | -declare -a DEPS=('apt' 'netaddr' 'netifaces' 'pip' 'yaml') |
302 | +declare -a DEPS=('apt' 'netaddr' 'netifaces' 'pip' 'yaml' 'jinja2' 'dnspython') |
303 | |
304 | check_and_install() { |
305 | pkg="${1}-${2}" |
306 | |
307 | === modified file 'hooks/utils.py' |
308 | --- hooks/utils.py 2015-02-10 10:30:13 +0000 |
309 | +++ hooks/utils.py 2015-10-12 10:56:13 +0000 |
310 | @@ -1,4 +1,3 @@ |
311 | - |
312 | # |
313 | # Copyright 2012 Canonical Ltd. |
314 | # |
315 | @@ -10,18 +9,29 @@ |
316 | import socket |
317 | import re |
318 | import os |
319 | +import dns.resolver |
320 | +import jinja2 |
321 | from copy import deepcopy |
322 | from collections import OrderedDict |
323 | -from charmhelpers.core.hookenv import unit_get |
324 | -from charmhelpers.fetch import apt_install |
325 | +from charmhelpers.core.hookenv import unit_get, relation_ids, status_get |
326 | from charmhelpers.contrib.openstack import context, templating |
327 | +from charmhelpers.contrib.openstack.utils import set_os_workload_status |
328 | +from charmhelpers.contrib.hahelpers.cluster import get_hacluster_config |
329 | +from charmhelpers.core.host import cmp_pkgrevno |
330 | +from charmhelpers.fetch import filter_installed_packages |
331 | |
332 | import ceph_radosgw_context |
333 | |
334 | +# The interface is said to be satisfied if anyone of the interfaces in the |
335 | +# list has a complete context. |
336 | +REQUIRED_INTERFACES = { |
337 | + 'mon': ['ceph-radosgw'], |
338 | +} |
339 | CEPHRG_HA_RES = 'grp_cephrg_vips' |
340 | TEMPLATES_DIR = 'templates' |
341 | TEMPLATES = 'templates/' |
342 | HAPROXY_CONF = '/etc/haproxy/haproxy.cfg' |
343 | +CEPH_CONF = '/etc/ceph/ceph.conf' |
344 | |
345 | BASE_RESOURCE_MAP = OrderedDict([ |
346 | (HAPROXY_CONF, { |
347 | @@ -29,20 +39,12 @@ |
348 | ceph_radosgw_context.HAProxyContext()], |
349 | 'services': ['haproxy'], |
350 | }), |
351 | + (CEPH_CONF, { |
352 | + 'contexts': [ceph_radosgw_context.MonContext()], |
353 | + 'services': ['radosgw'], |
354 | + }), |
355 | ]) |
356 | |
357 | -try: |
358 | - import jinja2 |
359 | -except ImportError: |
360 | - apt_install('python-jinja2', fatal=True) |
361 | - import jinja2 |
362 | - |
363 | -try: |
364 | - import dns.resolver |
365 | -except ImportError: |
366 | - apt_install('python-dnspython', fatal=True) |
367 | - import dns.resolver |
368 | - |
369 | |
370 | def resource_map(): |
371 | ''' |
372 | @@ -58,7 +60,14 @@ |
373 | def register_configs(release='icehouse'): |
374 | configs = templating.OSConfigRenderer(templates_dir=TEMPLATES, |
375 | openstack_release=release) |
376 | - for cfg, rscs in resource_map().iteritems(): |
377 | + CONFIGS = resource_map() |
378 | + pkg = 'radosgw' |
379 | + if not filter_installed_packages([pkg]) and cmp_pkgrevno(pkg, '0.55') >= 0: |
380 | + # Add keystone configuration if found |
381 | + CONFIGS[CEPH_CONF]['contexts'].append( |
382 | + ceph_radosgw_context.IdentityServiceContext() |
383 | + ) |
384 | + for cfg, rscs in CONFIGS.iteritems(): |
385 | configs.register(cfg, rscs['contexts']) |
386 | return configs |
387 | |
388 | @@ -103,3 +112,23 @@ |
389 | return True |
390 | else: |
391 | return False |
392 | + |
393 | + |
394 | +def check_optional_relations(configs): |
395 | + required_interfaces = {} |
396 | + if relation_ids('ha'): |
397 | + required_interfaces['ha'] = ['cluster'] |
398 | + try: |
399 | + get_hacluster_config() |
400 | + except: |
401 | + return ('blocked', |
402 | + 'hacluster missing configuration: ' |
403 | + 'vip, vip_iface, vip_cidr') |
404 | + if cmp_pkgrevno('radosgw', '0.55') >= 0 and \ |
405 | + relation_ids('identity-service'): |
406 | + required_interfaces['identity'] = ['identity-service'] |
407 | + if required_interfaces: |
408 | + set_os_workload_status(configs, required_interfaces) |
409 | + return status_get() |
410 | + else: |
411 | + return 'unknown', 'No optional relations' |
412 | |
413 | === added file 'unit_tests/test_ceph_radosgw_context.py' |
414 | --- unit_tests/test_ceph_radosgw_context.py 1970-01-01 00:00:00 +0000 |
415 | +++ unit_tests/test_ceph_radosgw_context.py 2015-10-12 10:56:13 +0000 |
416 | @@ -0,0 +1,202 @@ |
417 | +from mock import patch |
418 | + |
419 | +import ceph_radosgw_context as context |
420 | + |
421 | +from test_utils import CharmTestCase |
422 | +import charmhelpers |
423 | + |
424 | +TO_PATCH = [ |
425 | + 'config', |
426 | + 'log', |
427 | + 'relation_get', |
428 | + 'relation_ids', |
429 | + 'related_units', |
430 | + 'cmp_pkgrevno', |
431 | + 'socket', |
432 | +] |
433 | + |
434 | + |
435 | +class HAProxyContextTests(CharmTestCase): |
436 | + def setUp(self): |
437 | + super(HAProxyContextTests, self).setUp(context, TO_PATCH) |
438 | + self.relation_get.side_effect = self.test_relation.get |
439 | + self.config.side_effect = self.test_config.get |
440 | + |
441 | + @patch('charmhelpers.contrib.openstack.context.unit_get') |
442 | + @patch('charmhelpers.contrib.openstack.context.local_unit') |
443 | + @patch('charmhelpers.contrib.openstack.context.get_host_ip') |
444 | + @patch('charmhelpers.contrib.openstack.context.config') |
445 | + @patch('charmhelpers.contrib.hahelpers.cluster.config_get') |
446 | + @patch('charmhelpers.contrib.openstack.context.relation_ids') |
447 | + @patch('charmhelpers.contrib.hahelpers.cluster.relation_ids') |
448 | + def test_ctxt(self, _harelation_ids, _ctxtrelation_ids, _haconfig, |
449 | + _ctxtconfig, _get_host_ip, _local_unit, _unit_get): |
450 | + _get_host_ip.return_value = '10.0.0.10' |
451 | + _unit_get.return_value = '10.0.0.10' |
452 | + _ctxtconfig.side_effect = self.test_config.get |
453 | + _haconfig.side_effect = self.test_config.get |
454 | + _harelation_ids.return_value = [] |
455 | + haproxy_context = context.HAProxyContext() |
456 | + expect = { |
457 | + 'cephradosgw_bind_port': 70, |
458 | + 'service_ports': {'cephradosgw-server': [80, 70]} |
459 | + } |
460 | + self.assertEqual(expect, haproxy_context()) |
461 | + |
462 | + |
463 | +class IdentityServiceContextTest(CharmTestCase): |
464 | + |
465 | + def setUp(self): |
466 | + super(IdentityServiceContextTest, self).setUp(context, TO_PATCH) |
467 | + self.relation_get.side_effect = self.test_relation.get |
468 | + self.config.side_effect = self.test_config.get |
469 | + |
470 | + @patch.object(charmhelpers.contrib.openstack.context, 'format_ipv6_addr') |
471 | + @patch.object(charmhelpers.contrib.openstack.context, 'context_complete') |
472 | + @patch.object(charmhelpers.contrib.openstack.context, 'relation_get') |
473 | + @patch.object(charmhelpers.contrib.openstack.context, 'related_units') |
474 | + @patch.object(charmhelpers.contrib.openstack.context, 'relation_ids') |
475 | + @patch.object(charmhelpers.contrib.openstack.context, 'log') |
476 | + def test_ids_ctxt(self, _log, _rids, _runits, _rget, _ctxt_comp, |
477 | + _format_ipv6_addr): |
478 | + self.test_config.set('operator-roles', 'Babel') |
479 | + self.test_config.set('cache-size', '42') |
480 | + self.test_config.set('revocation-check-interval', '7500000') |
481 | + self.test_relation.set({'admin_token': 'ubuntutesting'}) |
482 | + self.relation_ids.return_value = ['identity-service:5'] |
483 | + self.related_units.return_value = ['keystone/0'] |
484 | + _format_ipv6_addr.return_value = False |
485 | + _rids.return_value = 'rid1' |
486 | + _runits.return_value = 'runit' |
487 | + _ctxt_comp.return_value = True |
488 | + id_data = { |
489 | + 'service_port': 9876, |
490 | + 'service_host': '127.0.0.4', |
491 | + 'service_tenant_id': '2852107b8f8f473aaf0d769c7bbcf86b', |
492 | + 'auth_host': '127.0.0.5', |
493 | + 'auth_port': 5432, |
494 | + 'service_tenant': 'ten', |
495 | + 'service_username': 'admin', |
496 | + 'service_password': 'adminpass', |
497 | + } |
498 | + _rget.return_value = id_data |
499 | + ids_ctxt = context.IdentityServiceContext() |
500 | + expect = { |
501 | + 'admin_password': 'adminpass', |
502 | + 'admin_tenant_id': '2852107b8f8f473aaf0d769c7bbcf86b', |
503 | + 'admin_tenant_name': 'ten', |
504 | + 'admin_token': 'ubuntutesting', |
505 | + 'admin_user': 'admin', |
506 | + 'auth_host': '127.0.0.5', |
507 | + 'auth_port': 5432, |
508 | + 'auth_protocol': 'http', |
509 | + 'auth_type': 'keystone', |
510 | + 'cache_size': '42', |
511 | + 'revocation_check_interval': '7500000', |
512 | + 'service_host': '127.0.0.4', |
513 | + 'service_port': 9876, |
514 | + 'service_protocol': 'http', |
515 | + 'user_roles': 'Babel', |
516 | + } |
517 | + self.assertEqual(expect, ids_ctxt()) |
518 | + |
519 | + @patch.object(charmhelpers.contrib.openstack.context, 'format_ipv6_addr') |
520 | + @patch.object(charmhelpers.contrib.openstack.context, 'context_complete') |
521 | + @patch.object(charmhelpers.contrib.openstack.context, 'relation_get') |
522 | + @patch.object(charmhelpers.contrib.openstack.context, 'related_units') |
523 | + @patch.object(charmhelpers.contrib.openstack.context, 'relation_ids') |
524 | + @patch.object(charmhelpers.contrib.openstack.context, 'log') |
525 | + def test_ids_ctxt_no_admin_token(self, _log, _rids, _runits, _rget, |
526 | + _ctxt_comp, _format_ipv6_addr): |
527 | + self.test_config.set('operator-roles', 'Babel') |
528 | + self.test_config.set('cache-size', '42') |
529 | + self.test_config.set('revocation-check-interval', '7500000') |
530 | + self.test_relation.set({}) |
531 | + self.relation_ids.return_value = ['identity-service:5'] |
532 | + self.related_units.return_value = ['keystone/0'] |
533 | + _format_ipv6_addr.return_value = False |
534 | + _rids.return_value = 'rid1' |
535 | + _runits.return_value = 'runit' |
536 | + _ctxt_comp.return_value = True |
537 | + id_data = { |
538 | + 'service_port': 9876, |
539 | + 'service_host': '127.0.0.4', |
540 | + 'service_tenant_id': '2852107b8f8f473aaf0d769c7bbcf86b', |
541 | + 'auth_host': '127.0.0.5', |
542 | + 'auth_port': 5432, |
543 | + 'service_tenant': 'ten', |
544 | + 'service_username': 'admin', |
545 | + 'service_password': 'adminpass', |
546 | + } |
547 | + _rget.return_value = id_data |
548 | + ids_ctxt = context.IdentityServiceContext() |
549 | + self.assertEqual({}, ids_ctxt()) |
550 | + |
551 | + @patch.object(charmhelpers.contrib.openstack.context, 'relation_ids') |
552 | + @patch.object(charmhelpers.contrib.openstack.context, 'log') |
553 | + def test_ids_ctxt_no_rels(self, _log, _rids): |
554 | + _rids.return_value = [] |
555 | + ids_ctxt = context.IdentityServiceContext() |
556 | + self.assertEquals(ids_ctxt(), None) |
557 | + |
558 | + |
559 | +class MonContextTest(CharmTestCase): |
560 | + |
561 | + def setUp(self): |
562 | + super(MonContextTest, self).setUp(context, TO_PATCH) |
563 | + self.config.side_effect = self.test_config.get |
564 | + |
565 | + def test_ctxt(self): |
566 | + self.socket.gethostname.return_value = '10.0.0.10' |
567 | + mon_ctxt = context.MonContext() |
568 | + addresses = ['10.5.4.1', '10.5.4.2', '10.5.4.3'] |
569 | + |
570 | + def _relation_get(attr, unit, rid): |
571 | + if attr == 'ceph-public-address': |
572 | + return addresses.pop() |
573 | + elif attr == 'auth': |
574 | + return 'cephx' |
575 | + self.relation_get.side_effect = _relation_get |
576 | + self.relation_ids.return_value = ['mon:6'] |
577 | + self.related_units.return_value = ['ceph/0', 'ceph/1', 'ceph/2'] |
578 | + expect = { |
579 | + 'auth_supported': 'cephx', |
580 | + 'embedded_webserver': False, |
581 | + 'hostname': '10.0.0.10', |
582 | + 'mon_hosts': '10.5.4.1:6789 10.5.4.2:6789 10.5.4.3:6789', |
583 | + 'old_auth': False, |
584 | + 'use_syslog': 'false' |
585 | + } |
586 | + self.assertEqual(expect, mon_ctxt()) |
587 | + |
588 | + def test_ctxt_missing_data(self): |
589 | + self.socket.gethostname.return_value = '10.0.0.10' |
590 | + mon_ctxt = context.MonContext() |
591 | + self.relation_get.return_value = None |
592 | + self.relation_ids.return_value = ['mon:6'] |
593 | + self.related_units.return_value = ['ceph/0', 'ceph/1', 'ceph/2'] |
594 | + self.assertEqual({}, mon_ctxt()) |
595 | + |
596 | + def test_ctxt_inconsistent_auths(self): |
597 | + self.socket.gethostname.return_value = '10.0.0.10' |
598 | + mon_ctxt = context.MonContext() |
599 | + addresses = ['10.5.4.1', '10.5.4.2', '10.5.4.3'] |
600 | + auths = ['cephx', 'cephy', 'cephz'] |
601 | + |
602 | + def _relation_get(attr, unit, rid): |
603 | + if attr == 'ceph-public-address': |
604 | + return addresses.pop() |
605 | + elif attr == 'auth': |
606 | + return auths.pop() |
607 | + self.relation_get.side_effect = _relation_get |
608 | + self.relation_ids.return_value = ['mon:6'] |
609 | + self.related_units.return_value = ['ceph/0', 'ceph/1', 'ceph/2'] |
610 | + expect = { |
611 | + 'auth_supported': 'none', |
612 | + 'embedded_webserver': False, |
613 | + 'hostname': '10.0.0.10', |
614 | + 'mon_hosts': '10.5.4.1:6789 10.5.4.2:6789 10.5.4.3:6789', |
615 | + 'old_auth': False, |
616 | + 'use_syslog': 'false' |
617 | + } |
618 | + self.assertEqual(expect, mon_ctxt()) |
619 | |
620 | === modified file 'unit_tests/test_hooks.py' |
621 | --- unit_tests/test_hooks.py 2015-06-04 23:06:40 +0000 |
622 | +++ unit_tests/test_hooks.py 2015-10-12 10:56:13 +0000 |
623 | @@ -23,6 +23,7 @@ |
624 | import hooks as ceph_hooks |
625 | |
626 | TO_PATCH = [ |
627 | + 'CONFIGS', |
628 | 'add_source', |
629 | 'apt_update', |
630 | 'apt_install', |
631 | @@ -31,22 +32,20 @@ |
632 | 'cmp_pkgrevno', |
633 | 'execd_preinstall', |
634 | 'enable_pocket', |
635 | - 'get_host_ip', |
636 | 'get_iface_for_address', |
637 | 'get_netmask_for_address', |
638 | - 'get_unit_hostname', |
639 | 'glob', |
640 | 'is_apache_24', |
641 | 'log', |
642 | 'lsb_release', |
643 | 'open_port', |
644 | 'os', |
645 | - 'related_units', |
646 | 'relation_ids', |
647 | 'relation_set', |
648 | 'relation_get', |
649 | 'render_template', |
650 | 'shutil', |
651 | + 'status_set', |
652 | 'subprocess', |
653 | 'sys', |
654 | 'unit_get', |
655 | @@ -123,31 +122,6 @@ |
656 | self.enable_pocket.assert_called_with('multiverse') |
657 | self.os.makedirs.called_with('/var/lib/ceph/nss') |
658 | |
659 | - def test_emit_cephconf(self): |
660 | - _get_keystone_conf = self.patch('get_keystone_conf') |
661 | - _get_auth = self.patch('get_auth') |
662 | - _get_mon_hosts = self.patch('get_mon_hosts') |
663 | - _get_auth.return_value = 'cephx' |
664 | - _get_keystone_conf.return_value = {'keystone_key': 'keystone_value'} |
665 | - _get_mon_hosts.return_value = ['10.0.0.1:6789', '10.0.0.2:6789'] |
666 | - self.get_unit_hostname.return_value = 'bob' |
667 | - self.os.path.exists.return_value = False |
668 | - cephcontext = { |
669 | - 'auth_supported': 'cephx', |
670 | - 'mon_hosts': '10.0.0.1:6789 10.0.0.2:6789', |
671 | - 'hostname': 'bob', |
672 | - 'old_auth': False, |
673 | - 'use_syslog': 'false', |
674 | - 'keystone_key': 'keystone_value', |
675 | - 'embedded_webserver': False, |
676 | - } |
677 | - self.cmp_pkgrevno.return_value = 1 |
678 | - with patch_open() as (_open, _file): |
679 | - ceph_hooks.emit_cephconf() |
680 | - self.os.makedirs.assert_called_with('/etc/ceph') |
681 | - _open.assert_called_with('/etc/ceph/ceph.conf', 'w') |
682 | - self.render_template.assert_called_with('ceph.conf', cephcontext) |
683 | - |
684 | def test_emit_apacheconf(self): |
685 | self.is_apache_24.return_value = True |
686 | self.unit_get.return_value = '10.0.0.1' |
687 | @@ -195,7 +169,6 @@ |
688 | |
689 | def test_config_changed(self): |
690 | _install_packages = self.patch('install_packages') |
691 | - _emit_cephconf = self.patch('emit_cephconf') |
692 | _emit_apacheconf = self.patch('emit_apacheconf') |
693 | _install_www_scripts = self.patch('install_www_scripts') |
694 | _apache_sites = self.patch('apache_sites') |
695 | @@ -203,105 +176,30 @@ |
696 | _apache_reload = self.patch('apache_reload') |
697 | ceph_hooks.config_changed() |
698 | _install_packages.assert_called() |
699 | - _emit_cephconf.assert_called() |
700 | + self.CONFIGS.write_all.assert_called_with() |
701 | _emit_apacheconf.assert_called() |
702 | _install_www_scripts.assert_called() |
703 | _apache_sites.assert_called() |
704 | _apache_modules.assert_called() |
705 | _apache_reload.assert_called() |
706 | |
707 | - def test_get_mon_hosts(self): |
708 | - self.relation_ids.return_value = ['monrelid'] |
709 | - self.related_units.return_value = ['monunit'] |
710 | - |
711 | - def rel_get(k, *args): |
712 | - return {'private-address': '127.0.0.1', |
713 | - 'ceph-public-address': '10.0.0.1'}[k] |
714 | - |
715 | - self.relation_get.side_effect = rel_get |
716 | - self.get_host_ip.side_effect = lambda x: x |
717 | - self.assertEquals(ceph_hooks.get_mon_hosts(), ['10.0.0.1:6789']) |
718 | - |
719 | - def test_get_conf(self): |
720 | - self.relation_ids.return_value = ['monrelid'] |
721 | - self.related_units.return_value = ['monunit'] |
722 | - self.relation_get.return_value = 'bob' |
723 | - self.assertEquals(ceph_hooks.get_conf('key'), 'bob') |
724 | - |
725 | - def test_get_conf_nomatch(self): |
726 | - self.relation_ids.return_value = ['monrelid'] |
727 | - self.related_units.return_value = ['monunit'] |
728 | - self.relation_get.return_value = '' |
729 | - self.assertEquals(ceph_hooks.get_conf('key'), None) |
730 | - |
731 | - def test_get_auth(self): |
732 | - self.relation_ids.return_value = ['monrelid'] |
733 | - self.related_units.return_value = ['monunit'] |
734 | - self.relation_get.return_value = 'bob' |
735 | - self.assertEquals(ceph_hooks.get_auth(), 'bob') |
736 | - |
737 | - def test_get_keystone_conf(self): |
738 | - self.test_config.set('operator-roles', 'admin') |
739 | - self.test_config.set('cache-size', '42') |
740 | - self.test_config.set('revocation-check-interval', '21') |
741 | - self.relation_ids.return_value = ['idrelid'] |
742 | - self.related_units.return_value = ['idunit'] |
743 | - |
744 | - def _relation_get(key, unit, relid): |
745 | - ks_dict = { |
746 | - 'auth_protocol': 'https', |
747 | - 'auth_host': '10.0.0.2', |
748 | - 'auth_port': '8090', |
749 | - 'admin_token': 'sectocken', |
750 | - } |
751 | - return ks_dict[key] |
752 | - self.relation_get.side_effect = _relation_get |
753 | - self.assertEquals(ceph_hooks.get_keystone_conf(), { |
754 | - 'auth_type': 'keystone', |
755 | - 'auth_protocol': 'https', |
756 | - 'admin_token': 'sectocken', |
757 | - 'user_roles': 'admin', |
758 | - 'auth_host': '10.0.0.2', |
759 | - 'cache_size': '42', |
760 | - 'auth_port': '8090', |
761 | - 'revocation_check_interval': '21'}) |
762 | - |
763 | - def test_get_keystone_conf_missinginfo(self): |
764 | - self.test_config.set('operator-roles', 'admin') |
765 | - self.test_config.set('cache-size', '42') |
766 | - self.test_config.set('revocation-check-interval', '21') |
767 | - self.relation_ids.return_value = ['idrelid'] |
768 | - self.related_units.return_value = ['idunit'] |
769 | - |
770 | - def _relation_get(key, unit, relid): |
771 | - ks_dict = { |
772 | - 'auth_protocol': 'https', |
773 | - 'auth_host': '10.0.0.2', |
774 | - 'auth_port': '8090', |
775 | - } |
776 | - return ks_dict[key] if key in ks_dict else None |
777 | - self.relation_get.side_effect = _relation_get |
778 | - self.assertEquals(ceph_hooks.get_keystone_conf(), None) |
779 | - |
780 | def test_mon_relation(self): |
781 | - _emit_cephconf = self.patch('emit_cephconf') |
782 | _ceph = self.patch('ceph') |
783 | _restart = self.patch('restart') |
784 | self.relation_get.return_value = 'seckey' |
785 | ceph_hooks.mon_relation() |
786 | _restart.assert_called() |
787 | _ceph.import_radosgw_key.assert_called_with('seckey') |
788 | - _emit_cephconf.assert_called() |
789 | + self.CONFIGS.write_all.assert_called_with() |
790 | |
791 | def test_mon_relation_nokey(self): |
792 | - _emit_cephconf = self.patch('emit_cephconf') |
793 | _ceph = self.patch('ceph') |
794 | _restart = self.patch('restart') |
795 | self.relation_get.return_value = None |
796 | ceph_hooks.mon_relation() |
797 | self.assertFalse(_ceph.import_radosgw_key.called) |
798 | self.assertFalse(_restart.called) |
799 | - _emit_cephconf.assert_called() |
800 | + self.CONFIGS.write_all.assert_called_with() |
801 | |
802 | def test_gateway_relation(self): |
803 | self.unit_get.return_value = 'myserver' |
804 | @@ -374,10 +272,9 @@ |
805 | admin_url='http://myserv:80/swift') |
806 | |
807 | def test_identity_changed(self): |
808 | - _emit_cephconf = self.patch('emit_cephconf') |
809 | _restart = self.patch('restart') |
810 | ceph_hooks.identity_changed() |
811 | - _emit_cephconf.assert_called() |
812 | + self.CONFIGS.write_all.assert_called_with() |
813 | _restart.assert_called() |
814 | |
815 | @patch('charmhelpers.contrib.openstack.ip.is_clustered') |
816 | @@ -391,12 +288,11 @@ |
817 | self.assertEquals(ceph_hooks.canonical_url({}, PUBLIC), |
818 | 'http://[%s]' % ipv6_addr) |
819 | |
820 | - @patch.object(ceph_hooks, 'CONFIGS') |
821 | - def test_cluster_changed(self, configs): |
822 | + def test_cluster_changed(self): |
823 | _id_joined = self.patch('identity_joined') |
824 | self.relation_ids.return_value = ['rid'] |
825 | ceph_hooks.cluster_changed() |
826 | - configs.write_all.assert_called() |
827 | + self.CONFIGS.write_all.assert_called_with() |
828 | _id_joined.assert_called_with(relid='rid') |
829 | |
830 | def test_ha_relation_joined_no_vip(self): |
charm_unit_test #10702 ceph-radosgw-next for gnuoy mp273834
UNIT OK: passed
Build: http:// 10.245. 162.77: 8080/job/ charm_unit_ test/10702/