Merge lp:~aluria/charms/trusty/collectd/charm-collectd-allinone into lp:~canonical-bootstack/charms/trusty/collectd/pre-layer

Proposed by Alvaro Uria
Status: Merged
Merged at revision: 27
Proposed branch: lp:~aluria/charms/trusty/collectd/charm-collectd-allinone
Merge into: lp:~canonical-bootstack/charms/trusty/collectd/pre-layer
Diff against target: 656 lines (+340/-80)
10 files modified
config.yaml (+0/-24)
hooks/collectd_contexts.py (+94/-2)
hooks/collectd_hooks.py (+32/-42)
hooks/collectd_utils.py (+59/-2)
templates/default.tmpl (+10/-0)
templates/openstack.conf.tmpl (+62/-0)
templates/write_http.conf.tmpl (+8/-0)
unit_tests/test_collectd_contexts.py (+61/-4)
unit_tests/test_collectd_hooks.py (+5/-4)
unit_tests/test_collectd_utils.py (+9/-2)
To merge this branch: bzr merge lp:~aluria/charms/trusty/collectd/charm-collectd-allinone
Reviewer Review Type Date Requested Status
Legacy - Canonical WTFB Pending
Review via email: mp+281401@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'config.yaml'
2--- config.yaml 2015-12-10 15:09:45 +0000
3+++ config.yaml 2015-12-29 16:06:20 +0000
4@@ -42,30 +42,6 @@
5 type: string
6 default: '/metrics'
7 description: "Path under which to expose Prometheus metrics"
8- openstack-enable-keystone:
9- type: boolean
10- default: true
11- description: "load keystone plugin"
12- openstack-keystone-vip:
13- type: string
14- default: '172.20.168.103'
15- description: "keystone entrypoint"
16- openstack-keystone-port:
17- type: int
18- default: 5000
19- description: "port where keystone is listening"
20- openstack-username:
21- type: string
22- default: 'admin'
23- description: "keystone admin user"
24- openstack-password:
25- type: string
26- default: 'xe5iej2AiSaed5Tu'
27- description: "keystone admin password"
28- openstack-tenant-name:
29- type: string
30- default: 'admin'
31- description: "keystone admin tenant"
32 openstack-keystone-verbose:
33 type: string
34 default: 'False'
35
36=== modified file 'hooks/collectd_contexts.py'
37--- hooks/collectd_contexts.py 2015-12-10 17:25:19 +0000
38+++ hooks/collectd_contexts.py 2015-12-29 16:06:20 +0000
39@@ -4,18 +4,110 @@
40 #from charmhelpers.fetch import apt_install, filter_installed_packages
41 from charmhelpers.core.hookenv import (
42 config,
43+ log,
44+ related_units,
45+ relation_get,
46+ relation_ids,
47 )
48
49 from socket import gethostname
50
51
52 class CollectdContext(object):
53- interfaces = ['target']
54
55 def __call__(self):
56+ conf = config()
57 ctxt = {
58 'hostname': gethostname(),
59- 'interval': config('interval'),
60+ 'interval': conf['interval'],
61+ }
62+
63+ return ctxt
64+
65+
66+class CollectdExporterContext(object):
67+ interfaces = ['target']
68+
69+ def __call__(self):
70+ conf = config()
71+ ctxt = {
72+ 'host': conf['host'],
73+ 'port': conf['port'],
74+ 'push_path': conf['push-path'],
75+ 'format': conf['format'],
76+ 'store_rates': conf['store-rates']
77+ }
78+
79+ return ctxt
80+
81+
82+class CollectdExporterDefaultContext(object):
83+ interfaces = ['target']
84+
85+ def __call__(self):
86+ conf = config()
87+ ctxt = {
88+ 'host': conf['host'],
89+ 'port': conf['port'],
90+ 'push_path': conf['push-path'],
91+ 'telemetry_path': conf['telemetry-path']
92+ }
93+
94+ return ctxt
95+
96+
97+class CollectdOpenstackContext(object):
98+ interfaces = ['identity-admin']
99+
100+ def keystone_values(self):
101+ """{u'service_region': u'RegionOne', u'service_password': u'XXXXXXXX',
102+ u'service_port': u'5000', u'private-address': u'10.XX.XX.XXX',
103+ u'service_hostname': u'10.XX.XX.XXX', u'service_username': u'admin',
104+ u'service_tenant_name': u'Admin'}
105+ """
106+ r_id = relation_ids('identity-admin')
107+ if len(r_id) != 1:
108+ log('keystone:identity-admin changed but not rel-id found')
109+ return None
110+
111+ r_unit = related_units(r_id[0])
112+ if r_unit:
113+ settings = relation_get(unit=r_unit[0], rid=r_id[0])
114+ log('settings(rid={})=> {}'.format(str(r_id[0]), settings))
115+ if 'service_password' in settings:
116+ hostname = settings.get('service_hostname', None)
117+ port = settings.get('service_port', None)
118+ username = settings.get('service_username', None)
119+ passwd = settings.get('service_password', None)
120+ tenantname = settings.get('service_tenant_name', None)
121+ else:
122+ return None
123+
124+ if hostname and port and username and passwd and tenantname:
125+ return (hostname, port, username, passwd, tenantname)
126+ else:
127+ return None
128+
129+ def __call__(self):
130+ conf = config()
131+ ks_vals = self.keystone_values()
132+ if ks_vals and len(filter(lambda x: x, ks_vals)) == len(ks_vals):
133+ enable_ks = True
134+ else:
135+ enable_ks = False
136+ ks_vals = (None, None, None, None, None)
137+
138+ ctxt = {
139+ 'enable_keystone': enable_ks,
140+ 'keystone_vip': ks_vals[0],
141+ 'keystone_port': ks_vals[1],
142+ 'username': ks_vals[2],
143+ 'password': ks_vals[3],
144+ 'tenant_name': ks_vals[4],
145+ 'keystone_verbose': conf['openstack-keystone-verbose'],
146+ 'debug': conf['openstack-debug'],
147+ 'allocation_ratio_cores': conf['openstack-allocation-ratio-cores'],
148+ 'allocation_ratio_ram': conf['openstack-allocation-ratio-ram']
149 }
150
151 return ctxt
152
153=== modified file 'hooks/collectd_hooks.py'
154--- hooks/collectd_hooks.py 2015-12-11 17:29:48 +0000
155+++ hooks/collectd_hooks.py 2015-12-29 16:06:20 +0000
156@@ -9,9 +9,9 @@
157 #INFO,
158 #ERROR,
159 #local_unit,
160- relation_ids,
161- relation_get,
162- related_units,
163+ #relation_ids,
164+ #relation_get,
165+ #related_units,
166 relation_set,
167 #service_name,
168 unit_get,
169@@ -26,7 +26,7 @@
170 )
171
172 from charmhelpers.fetch import (
173- #add_source,
174+ add_source,
175 apt_install,
176 #apt_purge,
177 apt_update,
178@@ -38,31 +38,33 @@
179
180 from collectd_utils import (
181 determine_packages,
182+ determine_exporter_packages,
183+ determine_openstack_packages,
184 juju_log,
185 register_configs,
186 restart_map,
187 )
188
189-#from socket import gethostname
190-
191 hooks = Hooks()
192-#CONFIGS = register_configs()
193
194
195 @hooks.hook()
196 def install():
197 execd_preinstall()
198+ if config('source'):
199+ for s in config('source').split(';'):
200+ add_source(s)
201 apt_update()
202 apt_install(determine_packages(), fatal=True)
203
204
205 @hooks.hook('start')
206 def start():
207+ if is_relation_made('target'):
208+ service_start('collectd-exporter-prometheus')
209+
210 service_start('collectd')
211
212- if is_relation_made('target'):
213- service_start('collectd-exporter-prometheus')
214-
215
216 @hooks.hook('stop')
217 def stop():
218@@ -72,7 +74,7 @@
219 service_stop('collectd-exporter-prometheus')
220
221
222-@hooks.hook('config-changed')
223+@hooks.hook('config-changed', 'upgrade-charm')
224 @restart_on_change(restart_map())
225 def config_changed():
226 register_configs()
227@@ -83,24 +85,36 @@
228 if is_relation_made('target'):
229 juju_log('config-changed for collectd-exporter-prometheus')
230
231- if is_relation_made('identity-service'):
232+ if is_relation_made('identity-admin'):
233 juju_log('config-changed for collectd-openstack')
234
235
236-@hooks.hook('upgrade-charm')
237-def upgrade_charm():
238- pass
239-
240-
241 # prometheus <-> collectd
242 # collectd-exporter IP:port
243-@hooks.hook('target-relation-changed', 'target-relation-joined')
244+@hooks.hook('target-relation-changed')
245 def target_relation():
246 if is_relation_made('target'):
247 host = unit_get('public-address')
248 conf = config()
249 if conf['exporter-host'] != '127.0.0.1':
250 relation_set(host=str(host), port=conf['exporter-port'])
251+ register_configs()
252+
253+
254+@hooks.hook('target-relation-joined')
255+def target_joined():
256+ if is_relation_made('target'):
257+ apt_install(determine_exporter_packages(), fatal=True)
258+ target_relation()
259+
260+
261+@hooks.hook('identity-admin-relation-joined')
262+def keystone_joined():
263+ if is_relation_made('identity-admin'):
264+ apt_install(determine_openstack_packages(), fatal=True)
265+ register_configs()
266+ juju_log('collectd-openstack module should be loaded with the '
267+ 'info provided by keystone:identity-admin')
268
269
270 # collectd <-> keystone
271@@ -108,33 +122,9 @@
272 @hooks.hook('identity-admin-relation-changed')
273 @restart_on_change(restart_map())
274 def identity_admin_relation_changed():
275- #CONFIGS.write_all()
276 keystone_joined()
277
278
279-@hooks.hook('identity-admin-relation-joined')
280-def keystone_joined():
281- """
282- service_hostname
283- service_port
284- service_username
285- service_tenant_name
286- service_region
287- service_password
288- """
289- r_id = relation_ids('identity-admin')
290- if len(r_id) != 1:
291- juju_log('keystone:identity-admin changed by not rel-id found')
292- return
293-
294- for r_unit in related_units(r_id[0]):
295- settings = relation_get(unit=r_unit, rid=r_id[0])
296- juju_log('settings(rid={})=> {}'.format(str(r_id[0]), settings))
297-
298- juju_log('collectd-openstack module should be loaded with the '
299- 'info provided by keystone:identity-admin')
300-
301-
302 def main():
303 try:
304 hooks.execute(sys.argv)
305
306=== modified file 'hooks/collectd_utils.py'
307--- hooks/collectd_utils.py 2015-12-10 17:25:19 +0000
308+++ hooks/collectd_utils.py 2015-12-29 16:06:20 +0000
309@@ -24,6 +24,7 @@
310 from charmhelpers.core.hookenv import (
311 #charm_dir,
312 #config,
313+ is_relation_made,
314 log,
315 #related_units,
316 #relation_ids,
317@@ -37,6 +38,9 @@
318
319 from collectd_contexts import (
320 CollectdContext,
321+ CollectdExporterContext,
322+ CollectdExporterDefaultContext,
323+ CollectdOpenstackContext,
324 )
325
326 TEMPLATES = 'templates/'
327@@ -45,9 +49,23 @@
328 'collectd-core',
329 ]
330
331+COLLECTD_EXPORTER_PACKAGES = [
332+ 'canonical-bootstack-collectd-exporter',
333+]
334+
335+COLLECTD_OPENSTACK_PACKAGES = [
336+ 'canonical-bootstack-collectd-openstack',
337+]
338+
339 COLLECTD_CONF_DIR = "/etc/collectd"
340 COLLECTD_CONF = '%s/collectd.conf' % COLLECTD_CONF_DIR
341-
342+COLLECTD_CONF_INC = '%s/collectd.d' % COLLECTD_CONF_DIR
343+
344+
345+COLLECTD_EXPORTER_CONF = '%s/write_http.conf' % COLLECTD_CONF_INC
346+COLLECTD_EXPORTER_DEFAULT = '/etc/default/collectd-exporter-prometheus'
347+
348+COLLECTD_OPENSTACK_CONF = '%s/openstack.conf' % COLLECTD_CONF_INC
349
350 BASE_RESOURCE_MAP = {
351 COLLECTD_CONF: {
352@@ -56,6 +74,26 @@
353 },
354 }
355
356+EXPORTER_RESOURCE_MAP = {
357+ COLLECTD_EXPORTER_CONF: {
358+ 'services': ['collectd'],
359+ 'templates': ['write_http.conf.tmpl'],
360+ 'contexts': [CollectdExporterContext()],
361+ },
362+ COLLECTD_EXPORTER_DEFAULT: {
363+ 'services': ['collectd-exporter-prometheus'],
364+ 'templates': ['default.tmpl'],
365+ 'contexts': [CollectdExporterDefaultContext()],
366+ },
367+}
368+
369+OPENSTACK_RESOURCE_MAP = {
370+ COLLECTD_OPENSTACK_CONF: {
371+ 'services': ['collectd'],
372+ 'contexts': [CollectdOpenstackContext()],
373+ },
374+}
375+
376
377 def juju_log(msg):
378 log('[collectd] {}'.format(msg))
379@@ -66,7 +104,16 @@
380 Dynamically generate a map of resources that will be managed for a single
381 hook execution.
382 '''
383- resource_map = deepcopy(BASE_RESOURCE_MAP)
384+ d_resource = {}
385+ d_resource.update(BASE_RESOURCE_MAP)
386+
387+ if is_relation_made('target'):
388+ d_resource.update(EXPORTER_RESOURCE_MAP)
389+
390+ if is_relation_made('identity-admin'):
391+ d_resource.update(OPENSTACK_RESOURCE_MAP)
392+
393+ resource_map = deepcopy(d_resource)
394
395 return resource_map
396
397@@ -103,3 +150,13 @@
398 packages = [] + BASE_PACKAGES
399
400 return packages
401+
402+
403+def determine_exporter_packages():
404+ packages = [] + COLLECTD_EXPORTER_PACKAGES
405+ return packages
406+
407+
408+def determine_openstack_packages():
409+ packages = [] + COLLECTD_OPENSTACK_PACKAGES
410+ return packages
411
412=== added file 'templates/default.tmpl'
413--- templates/default.tmpl 1970-01-01 00:00:00 +0000
414+++ templates/default.tmpl 2015-12-29 16:06:20 +0000
415@@ -0,0 +1,10 @@
416+# Defaults for canonical-bootstack-collectd-exporter initscript
417+#
418+
419+# Path under which to accept POST requests from collectd.
420+PUSH_PATH='{{ push_path }}'
421+# Address on which to expose metrics and web interface.
422+LISTEN_ADDR='{{ host }}:{{ port }}'
423+# Path under which to expose Prometheus metrics.
424+TELEMETRY_PATH='{{ telemetry_path }}'
425+
426
427=== added file 'templates/openstack.conf.tmpl'
428--- templates/openstack.conf.tmpl 1970-01-01 00:00:00 +0000
429+++ templates/openstack.conf.tmpl 2015-12-29 16:06:20 +0000
430@@ -0,0 +1,62 @@
431+TypesDB "/usr/share/collectd/types.db"
432+TypesDB "/usr/share/collectd/ostypes.db"
433+<LoadPlugin "python">
434+ Globals true
435+</LoadPlugin>
436+
437+<Plugin "python">
438+ ModulePath "/usr/lib/collectd/plugins/openstack"
439+
440+ Import "keystone_plugin"
441+ <Module "keystone_plugin">
442+ Username "{{ username }}"
443+ Password "{{ password }}"
444+ TenantName "{{ tenant_name }}"
445+ AuthURL "http://{{ keystone_vip }}:{{ keystone_port }}/v2.0"
446+ Verbose "{{ keystone_verbose }}"
447+ Debug "{{ debug }}"
448+ </Module>
449+ Import "cinder_plugin"
450+ <Module "cinder_plugin">
451+ Username "{{ username }}"
452+ Password "{{ password }}"
453+ TenantName "{{ tenant_name }}"
454+ AuthURL "http://{{ keystone_vip }}:{{ keystone_port }}/v2.0"
455+ Verbose "{{ keystone_verbose }}"
456+ Debug "{{ debug }}"
457+ </Module>
458+ Import "glance_plugin"
459+ <Module "glance_plugin">
460+ Username "{{ username }}"
461+ Password "{{ password }}"
462+ TenantName "{{ tenant_name }}"
463+ AuthURL "http://{{ keystone_vip }}:{{ keystone_port }}/v2.0"
464+ Verbose "{{ keystone_verbose }}"
465+ Debug "{{ debug }}"
466+ </Module>
467+ Import "neutron_plugin"
468+ <Module "neutron_plugin">
469+ Username "{{ username }}"
470+ Password "{{ password }}"
471+ TenantName "{{ tenant_name }}"
472+ AuthURL "http://{{ keystone_vip }}:{{ keystone_port }}/v2.0"
473+ Verbose "{{ keystone_verbose }}"
474+ Debug "{{ debug }}"
475+ </Module>
476+ Import "nova_plugin"
477+ <Module "nova_plugin">
478+ Username "{{ username }}"
479+ Password "{{ password }}"
480+ TenantName "{{ tenant_name }}"
481+ AuthURL "http://{{ keystone_vip }}:{{ keystone_port }}/v2.0"
482+ Verbose "{{ keystone_verbose }}"
483+ Debug "{{ debug }}"
484+ AllocationRatioCores "{{ allocation_ratio_cores }}"
485+ AllocationRatioRam "{{ allocation_ratio_ram }}"
486+ ReservedNodeCores "0"
487+ ReservedNodeRamMB "0"
488+ ReservedCores "0"
489+ ReservedRamMB "0"
490+ </Module>
491+</Plugin>
492+#
493
494=== added file 'templates/write_http.conf.tmpl'
495--- templates/write_http.conf.tmpl 1970-01-01 00:00:00 +0000
496+++ templates/write_http.conf.tmpl 2015-12-29 16:06:20 +0000
497@@ -0,0 +1,8 @@
498+LoadPlugin write_http
499+<Plugin write_http>
500+ <URL "http://127.0.0.1:{{ port }}{{ push_path }}">
501+ Format "{{ format }}"
502+ StoreRates {{ store_rates }}
503+ </URL>
504+</Plugin>
505+#
506
507=== modified file 'unit_tests/test_collectd_contexts.py'
508--- unit_tests/test_collectd_contexts.py 2015-12-10 17:25:19 +0000
509+++ unit_tests/test_collectd_contexts.py 2015-12-29 16:06:20 +0000
510@@ -1,5 +1,6 @@
511 import collectd_contexts as contexts
512 import os
513+from collections import defaultdict
514
515 os.environ['JUJU_UNIT_NAME'] = 'collectd'
516 #import collectd_utils as utils
517@@ -13,6 +14,9 @@
518 TO_PATCH = [
519 'gethostname',
520 'config',
521+ 'related_units',
522+ 'relation_get',
523+ 'relation_ids',
524 ]
525
526
527@@ -22,11 +26,64 @@
528 super(TestCollectdContext, self).setUp(contexts, TO_PATCH)
529
530 def test_collectd_context(self):
531- #self.relation_ids.return_value = ['target:0']
532 self.gethostname.return_value = '1'
533- self.config.return_value = '1'
534- #service = 'mycollectd'
535- #self.service_name.return_value = service
536+ self.config.return_value = defaultdict(lambda: '1')
537 self.assertEquals(contexts.CollectdContext()(),
538 {'hostname': '1',
539 'interval': '1'})
540+
541+ def test_collectd_exporter_context(self):
542+ self.config.return_value = defaultdict(lambda: '1')
543+ self.assertEquals(contexts.CollectdExporterContext()(),
544+ {'host': '1',
545+ 'port': '1',
546+ 'push_path': '1',
547+ 'format': '1',
548+ 'store_rates': '1'})
549+
550+ def test_collectd_exporter_default_context(self):
551+ self.gethostname.return_value = '1'
552+ self.config.return_value = defaultdict(lambda: '1')
553+ self.assertEquals(contexts.CollectdExporterDefaultContext()(),
554+ {'host': '1',
555+ 'port': '1',
556+ 'push_path': '1',
557+ 'telemetry_path': '1'})
558+
559+ def test_collectd_openstack_context(self):
560+ self.relation_ids.return_value = ['identity-admin:0']
561+ self.related_units.return_value = ['collectd/0']
562+ self.relation_get.return_value = {'service_hostname': '1',
563+ 'service_port': '1',
564+ 'service_username': '1',
565+ 'service_password': '1',
566+ 'service_tenant_name': '1'}
567+ self.config.return_value = defaultdict(lambda: '1')
568+ self.assertEquals(contexts.CollectdOpenstackContext()(),
569+ {'enable_keystone': True,
570+ 'keystone_vip': '1',
571+ 'keystone_port': '1',
572+ 'username': '1',
573+ 'password': '1',
574+ 'tenant_name': '1',
575+ 'keystone_verbose': '1',
576+ 'debug': '1',
577+ 'allocation_ratio_cores': '1',
578+ 'allocation_ratio_ram': '1'})
579+
580+ def test_collectd_openstack_context_nodata(self):
581+ self.relation_ids.return_value = ['identity-admin:0']
582+ self.related_units.return_value = ['collectd/0']
583+ self.relation_get.return_value = {}
584+ self.config.return_value = defaultdict(lambda: '1')
585+ self.assertEquals(contexts.CollectdOpenstackContext()(),
586+ {'enable_keystone': False,
587+ 'keystone_vip': None,
588+ 'keystone_port': None,
589+ 'username': None,
590+ 'password': None,
591+ 'tenant_name': None,
592+ 'keystone_verbose': '1',
593+ 'debug': '1',
594+ 'allocation_ratio_cores': '1',
595+ 'allocation_ratio_ram': '1'})
596
597=== modified file 'unit_tests/test_collectd_hooks.py'
598--- unit_tests/test_collectd_hooks.py 2015-12-10 17:25:19 +0000
599+++ unit_tests/test_collectd_hooks.py 2015-12-29 16:06:20 +0000
600@@ -34,12 +34,12 @@
601 'register_configs',
602 'restart_map',
603 # charmhelpers.core.hookenv
604- #'config',
605+ 'config',
606 'is_relation_made',
607- 'relation_get',
608- 'relation_ids',
609+ #'relation_get',
610+ #'relation_ids',
611 'relation_set',
612- 'related_units',
613+ #'related_units',
614 'unit_get',
615 # charmhelpers.core.host
616 'apt_install',
617@@ -57,5 +57,6 @@
618 def test_correct_install_packages(self):
619 'It installs the correct packages based on what is determined'
620 self.determine_packages.return_value = ['collectd']
621+ self.config.return_value = ''
622 hooks.hooks.execute(['hooks/install'])
623 self.apt_install.assert_called_with(['collectd'], fatal=True)
624
625=== modified file 'unit_tests/test_collectd_utils.py'
626--- unit_tests/test_collectd_utils.py 2015-12-10 17:25:19 +0000
627+++ unit_tests/test_collectd_utils.py 2015-12-29 16:06:20 +0000
628@@ -14,6 +14,7 @@
629 # helpers.core.hookenv
630 #'config',
631 'log',
632+ 'is_relation_made',
633 # fetch
634 #'add_source',
635 #'apt_update',
636@@ -38,12 +39,18 @@
637
638 def test_creates_restart_map_all_enabled(self):
639 'It creates correct restart map when all services enabled'
640+ self.is_relation_made.return_value = True
641 ex_map = OrderedDict([
642 ('/etc/collectd/collectd.conf', ['collectd']),
643+ ('/etc/collectd/collectd.d/write_http.conf', ['collectd']),
644+ ('/etc/default/collectd-exporter-prometheus',
645+ ['collectd-exporter-prometheus']),
646+ ('/etc/collectd/collectd.d/openstack.conf', ['collectd']),
647 ])
648 self.assertEquals(collectd_utils.restart_map(), ex_map)
649
650 def test_list_services(self):
651 'It returns a list of services associate with this charm'
652- ex_list = ['collectd']
653- self.assertEquals(collectd_utils.services(), ex_list)
654+ self.is_relation_made.return_value = True
655+ ex_list = ['collectd', 'collectd-exporter-prometheus']
656+ self.assertEquals(sorted(collectd_utils.services()), sorted(ex_list))

Subscribers

People subscribed via source and target branches