Merge lp:~gnuoy/charms/trusty/keystone/add-nrpe-checks into lp:~openstack-charmers-archive/charms/trusty/keystone/next

Proposed by Liam Young
Status: Merged
Merged at revision: 100
Proposed branch: lp:~gnuoy/charms/trusty/keystone/add-nrpe-checks
Merge into: lp:~openstack-charmers-archive/charms/trusty/keystone/next
Diff against target: 734 lines (+551/-15)
11 files modified
charm-helpers-hooks.yaml (+1/-0)
config.yaml (+11/-0)
hooks/charmhelpers/contrib/charmsupport/nrpe.py (+308/-0)
hooks/charmhelpers/contrib/charmsupport/volumes.py (+159/-0)
hooks/charmhelpers/contrib/openstack/utils.py (+6/-0)
hooks/charmhelpers/contrib/unison/__init__.py (+29/-14)
hooks/charmhelpers/fetch/__init__.py (+8/-1)
hooks/keystone_hooks.py (+17/-0)
hooks/keystone_utils.py (+8/-0)
metadata.yaml (+3/-0)
unit_tests/test_keystone_hooks.py (+1/-0)
To merge this branch: bzr merge lp:~gnuoy/charms/trusty/keystone/add-nrpe-checks
Reviewer Review Type Date Requested Status
Liam Young (community) Approve
Review via email: mp+246152@code.launchpad.net

Description of the change

Add nrpe support. Based on branch from bradm with a few tweaks

To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #673 keystone-next for gnuoy mp246152
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/673/

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

charm_unit_test #702 keystone-next for gnuoy mp246152
    UNIT OK: passed

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

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

charm_amulet_test #858 keystone-next for gnuoy mp246152
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/858/

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

<jamespage> gnuoy, as they are re-syncs + tweaks to the nrpe stuff in the charms, I'm happy to give a conditional +1 across the board based on osci checking things out OK
<gnuoy> jamespage, I'll take that! thanks
...
<gnuoy> jamespage, osci is still working through. But on the subject of those mps, does your +1 stand for branches with no amulet tests?
<jamespage> gnuoy, yes

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'charm-helpers-hooks.yaml'
2--- charm-helpers-hooks.yaml 2014-12-19 10:21:34 +0000
3+++ charm-helpers-hooks.yaml 2015-01-12 14:00:09 +0000
4@@ -13,3 +13,4 @@
5 - contrib.peerstorage
6 - contrib.network.ip
7 - contrib.python.packages
8+ - contrib.charmsupport
9
10=== modified file 'config.yaml'
11--- config.yaml 2014-12-12 10:41:10 +0000
12+++ config.yaml 2015-01-12 14:00:09 +0000
13@@ -226,3 +226,14 @@
14 The CPU core multiplier to use when configuring worker processes for
15 Keystone. By default, the number of workers for each daemon is set to
16 twice the number of CPU cores a service unit has.
17+ nagios_context:
18+ default: "juju"
19+ type: string
20+ description: |
21+ Used by the nrpe-external-master subordinate charm.
22+ A string that will be prepended to instance name to set the host name
23+ in nagios. So for instance the hostname would be something like:
24+ juju-myservice-0
25+ If you're running multiple environments with the same services in them
26+ this allows you to differentiate between them.
27+
28
29=== added directory 'files'
30=== added directory 'hooks/charmhelpers/contrib/charmsupport'
31=== added file 'hooks/charmhelpers/contrib/charmsupport/__init__.py'
32=== added file 'hooks/charmhelpers/contrib/charmsupport/nrpe.py'
33--- hooks/charmhelpers/contrib/charmsupport/nrpe.py 1970-01-01 00:00:00 +0000
34+++ hooks/charmhelpers/contrib/charmsupport/nrpe.py 2015-01-12 14:00:09 +0000
35@@ -0,0 +1,308 @@
36+"""Compatibility with the nrpe-external-master charm"""
37+# Copyright 2012 Canonical Ltd.
38+#
39+# Authors:
40+# Matthew Wedgwood <matthew.wedgwood@canonical.com>
41+
42+import subprocess
43+import pwd
44+import grp
45+import os
46+import re
47+import shlex
48+import yaml
49+
50+from charmhelpers.core.hookenv import (
51+ config,
52+ local_unit,
53+ log,
54+ relation_ids,
55+ relation_set,
56+ relations_of_type,
57+)
58+
59+from charmhelpers.core.host import service
60+
61+# This module adds compatibility with the nrpe-external-master and plain nrpe
62+# subordinate charms. To use it in your charm:
63+#
64+# 1. Update metadata.yaml
65+#
66+# provides:
67+# (...)
68+# nrpe-external-master:
69+# interface: nrpe-external-master
70+# scope: container
71+#
72+# and/or
73+#
74+# provides:
75+# (...)
76+# local-monitors:
77+# interface: local-monitors
78+# scope: container
79+
80+#
81+# 2. Add the following to config.yaml
82+#
83+# nagios_context:
84+# default: "juju"
85+# type: string
86+# description: |
87+# Used by the nrpe subordinate charms.
88+# A string that will be prepended to instance name to set the host name
89+# in nagios. So for instance the hostname would be something like:
90+# juju-myservice-0
91+# If you're running multiple environments with the same services in them
92+# this allows you to differentiate between them.
93+# nagios_servicegroups:
94+# default: ""
95+# type: string
96+# description: |
97+# A comma-separated list of nagios servicegroups.
98+# If left empty, the nagios_context will be used as the servicegroup
99+#
100+# 3. Add custom checks (Nagios plugins) to files/nrpe-external-master
101+#
102+# 4. Update your hooks.py with something like this:
103+#
104+# from charmsupport.nrpe import NRPE
105+# (...)
106+# def update_nrpe_config():
107+# nrpe_compat = NRPE()
108+# nrpe_compat.add_check(
109+# shortname = "myservice",
110+# description = "Check MyService",
111+# check_cmd = "check_http -w 2 -c 10 http://localhost"
112+# )
113+# nrpe_compat.add_check(
114+# "myservice_other",
115+# "Check for widget failures",
116+# check_cmd = "/srv/myapp/scripts/widget_check"
117+# )
118+# nrpe_compat.write()
119+#
120+# def config_changed():
121+# (...)
122+# update_nrpe_config()
123+#
124+# def nrpe_external_master_relation_changed():
125+# update_nrpe_config()
126+#
127+# def local_monitors_relation_changed():
128+# update_nrpe_config()
129+#
130+# 5. ln -s hooks.py nrpe-external-master-relation-changed
131+# ln -s hooks.py local-monitors-relation-changed
132+
133+
134+class CheckException(Exception):
135+ pass
136+
137+
138+class Check(object):
139+ shortname_re = '[A-Za-z0-9-_]+$'
140+ service_template = ("""
141+#---------------------------------------------------
142+# This file is Juju managed
143+#---------------------------------------------------
144+define service {{
145+ use active-service
146+ host_name {nagios_hostname}
147+ service_description {nagios_hostname}[{shortname}] """
148+ """{description}
149+ check_command check_nrpe!{command}
150+ servicegroups {nagios_servicegroup}
151+}}
152+""")
153+
154+ def __init__(self, shortname, description, check_cmd):
155+ super(Check, self).__init__()
156+ # XXX: could be better to calculate this from the service name
157+ if not re.match(self.shortname_re, shortname):
158+ raise CheckException("shortname must match {}".format(
159+ Check.shortname_re))
160+ self.shortname = shortname
161+ self.command = "check_{}".format(shortname)
162+ # Note: a set of invalid characters is defined by the
163+ # Nagios server config
164+ # The default is: illegal_object_name_chars=`~!$%^&*"|'<>?,()=
165+ self.description = description
166+ self.check_cmd = self._locate_cmd(check_cmd)
167+
168+ def _locate_cmd(self, check_cmd):
169+ search_path = (
170+ '/usr/lib/nagios/plugins',
171+ '/usr/local/lib/nagios/plugins',
172+ )
173+ parts = shlex.split(check_cmd)
174+ for path in search_path:
175+ if os.path.exists(os.path.join(path, parts[0])):
176+ command = os.path.join(path, parts[0])
177+ if len(parts) > 1:
178+ command += " " + " ".join(parts[1:])
179+ return command
180+ log('Check command not found: {}'.format(parts[0]))
181+ return ''
182+
183+ def write(self, nagios_context, hostname, nagios_servicegroups=None):
184+ nrpe_check_file = '/etc/nagios/nrpe.d/{}.cfg'.format(
185+ self.command)
186+ with open(nrpe_check_file, 'w') as nrpe_check_config:
187+ nrpe_check_config.write("# check {}\n".format(self.shortname))
188+ nrpe_check_config.write("command[{}]={}\n".format(
189+ self.command, self.check_cmd))
190+
191+ if not os.path.exists(NRPE.nagios_exportdir):
192+ log('Not writing service config as {} is not accessible'.format(
193+ NRPE.nagios_exportdir))
194+ else:
195+ self.write_service_config(nagios_context, hostname,
196+ nagios_servicegroups)
197+
198+ def write_service_config(self, nagios_context, hostname,
199+ nagios_servicegroups=None):
200+ for f in os.listdir(NRPE.nagios_exportdir):
201+ if re.search('.*{}.cfg'.format(self.command), f):
202+ os.remove(os.path.join(NRPE.nagios_exportdir, f))
203+
204+ if not nagios_servicegroups:
205+ nagios_servicegroups = nagios_context
206+
207+ templ_vars = {
208+ 'nagios_hostname': hostname,
209+ 'nagios_servicegroup': nagios_servicegroups,
210+ 'description': self.description,
211+ 'shortname': self.shortname,
212+ 'command': self.command,
213+ }
214+ nrpe_service_text = Check.service_template.format(**templ_vars)
215+ nrpe_service_file = '{}/service__{}_{}.cfg'.format(
216+ NRPE.nagios_exportdir, hostname, self.command)
217+ with open(nrpe_service_file, 'w') as nrpe_service_config:
218+ nrpe_service_config.write(str(nrpe_service_text))
219+
220+ def run(self):
221+ subprocess.call(self.check_cmd)
222+
223+
224+class NRPE(object):
225+ nagios_logdir = '/var/log/nagios'
226+ nagios_exportdir = '/var/lib/nagios/export'
227+ nrpe_confdir = '/etc/nagios/nrpe.d'
228+
229+ def __init__(self, hostname=None):
230+ super(NRPE, self).__init__()
231+ self.config = config()
232+ self.nagios_context = self.config['nagios_context']
233+ if 'nagios_servicegroups' in self.config:
234+ self.nagios_servicegroups = self.config['nagios_servicegroups']
235+ else:
236+ self.nagios_servicegroups = 'juju'
237+ self.unit_name = local_unit().replace('/', '-')
238+ if hostname:
239+ self.hostname = hostname
240+ else:
241+ self.hostname = "{}-{}".format(self.nagios_context, self.unit_name)
242+ self.checks = []
243+
244+ def add_check(self, *args, **kwargs):
245+ self.checks.append(Check(*args, **kwargs))
246+
247+ def write(self):
248+ try:
249+ nagios_uid = pwd.getpwnam('nagios').pw_uid
250+ nagios_gid = grp.getgrnam('nagios').gr_gid
251+ except:
252+ log("Nagios user not set up, nrpe checks not updated")
253+ return
254+
255+ if not os.path.exists(NRPE.nagios_logdir):
256+ os.mkdir(NRPE.nagios_logdir)
257+ os.chown(NRPE.nagios_logdir, nagios_uid, nagios_gid)
258+
259+ nrpe_monitors = {}
260+ monitors = {"monitors": {"remote": {"nrpe": nrpe_monitors}}}
261+ for nrpecheck in self.checks:
262+ nrpecheck.write(self.nagios_context, self.hostname,
263+ self.nagios_servicegroups)
264+ nrpe_monitors[nrpecheck.shortname] = {
265+ "command": nrpecheck.command,
266+ }
267+
268+ service('restart', 'nagios-nrpe-server')
269+
270+ for rid in relation_ids("local-monitors"):
271+ relation_set(relation_id=rid, monitors=yaml.dump(monitors))
272+
273+
274+def get_nagios_hostcontext(relation_name='nrpe-external-master'):
275+ """
276+ Query relation with nrpe subordinate, return the nagios_host_context
277+
278+ :param str relation_name: Name of relation nrpe sub joined to
279+ """
280+ for rel in relations_of_type(relation_name):
281+ if 'nagios_hostname' in rel:
282+ return rel['nagios_host_context']
283+
284+
285+def get_nagios_hostname(relation_name='nrpe-external-master'):
286+ """
287+ Query relation with nrpe subordinate, return the nagios_hostname
288+
289+ :param str relation_name: Name of relation nrpe sub joined to
290+ """
291+ for rel in relations_of_type(relation_name):
292+ if 'nagios_hostname' in rel:
293+ return rel['nagios_hostname']
294+
295+
296+def get_nagios_unit_name(relation_name='nrpe-external-master'):
297+ """
298+ Return the nagios unit name prepended with host_context if needed
299+
300+ :param str relation_name: Name of relation nrpe sub joined to
301+ """
302+ host_context = get_nagios_hostcontext(relation_name)
303+ if host_context:
304+ unit = "%s:%s" % (host_context, local_unit())
305+ else:
306+ unit = local_unit()
307+ return unit
308+
309+
310+def add_init_service_checks(nrpe, services, unit_name):
311+ """
312+ Add checks for each service in list
313+
314+ :param NRPE nrpe: NRPE object to add check to
315+ :param list services: List of services to check
316+ :param str unit_name: Unit name to use in check description
317+ """
318+ for svc in services:
319+ upstart_init = '/etc/init/%s.conf' % svc
320+ sysv_init = '/etc/init.d/%s' % svc
321+ if os.path.exists(upstart_init):
322+ nrpe.add_check(
323+ shortname=svc,
324+ description='process check {%s}' % unit_name,
325+ check_cmd='check_upstart_job %s' % svc
326+ )
327+ elif os.path.exists(sysv_init):
328+ cronpath = '/etc/cron.d/nagios-service-check-%s' % svc
329+ cron_file = ('*/5 * * * * root '
330+ '/usr/local/lib/nagios/plugins/check_exit_status.pl '
331+ '-s /etc/init.d/%s status > '
332+ '/var/lib/nagios/service-check-%s.txt\n' % (svc,
333+ svc)
334+ )
335+ f = open(cronpath, 'w')
336+ f.write(cron_file)
337+ f.close()
338+ nrpe.add_check(
339+ shortname=svc,
340+ description='process check {%s}' % unit_name,
341+ check_cmd='check_status_file.py -f '
342+ '/var/lib/nagios/service-check-%s.txt' % svc,
343+ )
344
345=== added file 'hooks/charmhelpers/contrib/charmsupport/volumes.py'
346--- hooks/charmhelpers/contrib/charmsupport/volumes.py 1970-01-01 00:00:00 +0000
347+++ hooks/charmhelpers/contrib/charmsupport/volumes.py 2015-01-12 14:00:09 +0000
348@@ -0,0 +1,159 @@
349+'''
350+Functions for managing volumes in juju units. One volume is supported per unit.
351+Subordinates may have their own storage, provided it is on its own partition.
352+
353+Configuration stanzas::
354+
355+ volume-ephemeral:
356+ type: boolean
357+ default: true
358+ description: >
359+ If false, a volume is mounted as sepecified in "volume-map"
360+ If true, ephemeral storage will be used, meaning that log data
361+ will only exist as long as the machine. YOU HAVE BEEN WARNED.
362+ volume-map:
363+ type: string
364+ default: {}
365+ description: >
366+ YAML map of units to device names, e.g:
367+ "{ rsyslog/0: /dev/vdb, rsyslog/1: /dev/vdb }"
368+ Service units will raise a configure-error if volume-ephemeral
369+ is 'true' and no volume-map value is set. Use 'juju set' to set a
370+ value and 'juju resolved' to complete configuration.
371+
372+Usage::
373+
374+ from charmsupport.volumes import configure_volume, VolumeConfigurationError
375+ from charmsupport.hookenv import log, ERROR
376+ def post_mount_hook():
377+ stop_service('myservice')
378+ def post_mount_hook():
379+ start_service('myservice')
380+
381+ if __name__ == '__main__':
382+ try:
383+ configure_volume(before_change=pre_mount_hook,
384+ after_change=post_mount_hook)
385+ except VolumeConfigurationError:
386+ log('Storage could not be configured', ERROR)
387+
388+'''
389+
390+# XXX: Known limitations
391+# - fstab is neither consulted nor updated
392+
393+import os
394+from charmhelpers.core import hookenv
395+from charmhelpers.core import host
396+import yaml
397+
398+
399+MOUNT_BASE = '/srv/juju/volumes'
400+
401+
402+class VolumeConfigurationError(Exception):
403+ '''Volume configuration data is missing or invalid'''
404+ pass
405+
406+
407+def get_config():
408+ '''Gather and sanity-check volume configuration data'''
409+ volume_config = {}
410+ config = hookenv.config()
411+
412+ errors = False
413+
414+ if config.get('volume-ephemeral') in (True, 'True', 'true', 'Yes', 'yes'):
415+ volume_config['ephemeral'] = True
416+ else:
417+ volume_config['ephemeral'] = False
418+
419+ try:
420+ volume_map = yaml.safe_load(config.get('volume-map', '{}'))
421+ except yaml.YAMLError as e:
422+ hookenv.log("Error parsing YAML volume-map: {}".format(e),
423+ hookenv.ERROR)
424+ errors = True
425+ if volume_map is None:
426+ # probably an empty string
427+ volume_map = {}
428+ elif not isinstance(volume_map, dict):
429+ hookenv.log("Volume-map should be a dictionary, not {}".format(
430+ type(volume_map)))
431+ errors = True
432+
433+ volume_config['device'] = volume_map.get(os.environ['JUJU_UNIT_NAME'])
434+ if volume_config['device'] and volume_config['ephemeral']:
435+ # asked for ephemeral storage but also defined a volume ID
436+ hookenv.log('A volume is defined for this unit, but ephemeral '
437+ 'storage was requested', hookenv.ERROR)
438+ errors = True
439+ elif not volume_config['device'] and not volume_config['ephemeral']:
440+ # asked for permanent storage but did not define volume ID
441+ hookenv.log('Ephemeral storage was requested, but there is no volume '
442+ 'defined for this unit.', hookenv.ERROR)
443+ errors = True
444+
445+ unit_mount_name = hookenv.local_unit().replace('/', '-')
446+ volume_config['mountpoint'] = os.path.join(MOUNT_BASE, unit_mount_name)
447+
448+ if errors:
449+ return None
450+ return volume_config
451+
452+
453+def mount_volume(config):
454+ if os.path.exists(config['mountpoint']):
455+ if not os.path.isdir(config['mountpoint']):
456+ hookenv.log('Not a directory: {}'.format(config['mountpoint']))
457+ raise VolumeConfigurationError()
458+ else:
459+ host.mkdir(config['mountpoint'])
460+ if os.path.ismount(config['mountpoint']):
461+ unmount_volume(config)
462+ if not host.mount(config['device'], config['mountpoint'], persist=True):
463+ raise VolumeConfigurationError()
464+
465+
466+def unmount_volume(config):
467+ if os.path.ismount(config['mountpoint']):
468+ if not host.umount(config['mountpoint'], persist=True):
469+ raise VolumeConfigurationError()
470+
471+
472+def managed_mounts():
473+ '''List of all mounted managed volumes'''
474+ return filter(lambda mount: mount[0].startswith(MOUNT_BASE), host.mounts())
475+
476+
477+def configure_volume(before_change=lambda: None, after_change=lambda: None):
478+ '''Set up storage (or don't) according to the charm's volume configuration.
479+ Returns the mount point or "ephemeral". before_change and after_change
480+ are optional functions to be called if the volume configuration changes.
481+ '''
482+
483+ config = get_config()
484+ if not config:
485+ hookenv.log('Failed to read volume configuration', hookenv.CRITICAL)
486+ raise VolumeConfigurationError()
487+
488+ if config['ephemeral']:
489+ if os.path.ismount(config['mountpoint']):
490+ before_change()
491+ unmount_volume(config)
492+ after_change()
493+ return 'ephemeral'
494+ else:
495+ # persistent storage
496+ if os.path.ismount(config['mountpoint']):
497+ mounts = dict(managed_mounts())
498+ if mounts.get(config['mountpoint']) != config['device']:
499+ before_change()
500+ unmount_volume(config)
501+ mount_volume(config)
502+ after_change()
503+ else:
504+ before_change()
505+ mount_volume(config)
506+ after_change()
507+ return config['mountpoint']
508
509=== modified file 'hooks/charmhelpers/contrib/openstack/utils.py'
510--- hooks/charmhelpers/contrib/openstack/utils.py 2014-12-19 10:21:34 +0000
511+++ hooks/charmhelpers/contrib/openstack/utils.py 2015-01-12 14:00:09 +0000
512@@ -53,6 +53,7 @@
513 ('saucy', 'havana'),
514 ('trusty', 'icehouse'),
515 ('utopic', 'juno'),
516+ ('vivid', 'kilo'),
517 ])
518
519
520@@ -64,6 +65,7 @@
521 ('2013.2', 'havana'),
522 ('2014.1', 'icehouse'),
523 ('2014.2', 'juno'),
524+ ('2015.1', 'kilo'),
525 ])
526
527 # The ugly duckling
528@@ -84,6 +86,7 @@
529 ('2.0.0', 'juno'),
530 ('2.1.0', 'juno'),
531 ('2.2.0', 'juno'),
532+ ('2.2.1', 'kilo'),
533 ])
534
535 DEFAULT_LOOPBACK_SIZE = '5G'
536@@ -289,6 +292,9 @@
537 'juno': 'trusty-updates/juno',
538 'juno/updates': 'trusty-updates/juno',
539 'juno/proposed': 'trusty-proposed/juno',
540+ 'kilo': 'trusty-updates/kilo',
541+ 'kilo/updates': 'trusty-updates/kilo',
542+ 'kilo/proposed': 'trusty-proposed/kilo',
543 }
544
545 try:
546
547=== modified file 'hooks/charmhelpers/contrib/unison/__init__.py'
548--- hooks/charmhelpers/contrib/unison/__init__.py 2014-12-19 10:21:34 +0000
549+++ hooks/charmhelpers/contrib/unison/__init__.py 2015-01-12 14:00:09 +0000
550@@ -228,7 +228,12 @@
551 return hosts
552
553
554-def sync_path_to_host(path, host, user, verbose=False, cmd=None, gid=None):
555+def sync_path_to_host(path, host, user, verbose=False, cmd=None, gid=None,
556+ fatal=False):
557+ """Sync path to an specific peer host
558+
559+ Propagates exception if operation fails and fatal=True.
560+ """
561 cmd = cmd or copy(BASE_CMD)
562 if not verbose:
563 cmd.append('-silent')
564@@ -245,20 +250,30 @@
565 run_as_user(user, cmd, gid)
566 except:
567 log('Error syncing remote files')
568-
569-
570-def sync_to_peer(host, user, paths=None, verbose=False, cmd=None, gid=None):
571- '''Sync paths to an specific host'''
572+ if fatal:
573+ raise
574+
575+
576+def sync_to_peer(host, user, paths=None, verbose=False, cmd=None, gid=None,
577+ fatal=False):
578+ """Sync paths to an specific peer host
579+
580+ Propagates exception if any operation fails and fatal=True.
581+ """
582 if paths:
583 for p in paths:
584- sync_path_to_host(p, host, user, verbose, cmd, gid)
585-
586-
587-def sync_to_peers(peer_interface, user, paths=None,
588- verbose=False, cmd=None, gid=None):
589- '''Sync all hosts to an specific path'''
590- '''The type of group is integer, it allows user has permissions to '''
591- '''operate a directory have a different group id with the user id.'''
592+ sync_path_to_host(p, host, user, verbose, cmd, gid, fatal)
593+
594+
595+def sync_to_peers(peer_interface, user, paths=None, verbose=False, cmd=None,
596+ gid=None, fatal=False):
597+ """Sync all hosts to an specific path
598+
599+ The type of group is integer, it allows user has permissions to
600+ operate a directory have a different group id with the user id.
601+
602+ Propagates exception if any operation fails and fatal=True.
603+ """
604 if paths:
605 for host in collect_authed_hosts(peer_interface):
606- sync_to_peer(host, user, paths, verbose, cmd, gid)
607+ sync_to_peer(host, user, paths, verbose, cmd, gid, fatal)
608
609=== modified file 'hooks/charmhelpers/fetch/__init__.py'
610--- hooks/charmhelpers/fetch/__init__.py 2014-12-19 10:21:34 +0000
611+++ hooks/charmhelpers/fetch/__init__.py 2015-01-12 14:00:09 +0000
612@@ -64,9 +64,16 @@
613 'trusty-juno/updates': 'trusty-updates/juno',
614 'trusty-updates/juno': 'trusty-updates/juno',
615 'juno/proposed': 'trusty-proposed/juno',
616- 'juno/proposed': 'trusty-proposed/juno',
617 'trusty-juno/proposed': 'trusty-proposed/juno',
618 'trusty-proposed/juno': 'trusty-proposed/juno',
619+ # Kilo
620+ 'kilo': 'trusty-updates/kilo',
621+ 'trusty-kilo': 'trusty-updates/kilo',
622+ 'trusty-kilo/updates': 'trusty-updates/kilo',
623+ 'trusty-updates/kilo': 'trusty-updates/kilo',
624+ 'kilo/proposed': 'trusty-proposed/kilo',
625+ 'trusty-kilo/proposed': 'trusty-proposed/kilo',
626+ 'trusty-proposed/kilo': 'trusty-proposed/kilo',
627 }
628
629 # The order of this list is very important. Handlers should be listed in from
630
631=== modified file 'hooks/keystone_hooks.py'
632--- hooks/keystone_hooks.py 2014-12-16 23:48:42 +0000
633+++ hooks/keystone_hooks.py 2015-01-12 14:00:09 +0000
634@@ -51,6 +51,7 @@
635 register_configs,
636 relation_list,
637 restart_map,
638+ services,
639 CLUSTER_RES,
640 KEYSTONE_CONF,
641 SSH_USER,
642@@ -79,6 +80,8 @@
643 )
644 from charmhelpers.contrib.openstack.context import ADDRESS_TYPES
645
646+from charmhelpers.contrib.charmsupport import nrpe
647+
648 hooks = Hooks()
649 CONFIGS = register_configs()
650
651@@ -111,6 +114,7 @@
652
653 save_script_rc()
654 configure_https()
655+ update_nrpe_config()
656 CONFIGS.write_all()
657 if eligible_leader(CLUSTER_RES):
658 migrate_database()
659@@ -375,6 +379,7 @@
660 group='keystone',
661 peer_interface='cluster',
662 ensure_local_user=True)
663+ update_nrpe_config()
664 synchronize_ca()
665 if eligible_leader(CLUSTER_RES):
666 log('Cluster leader - ensuring endpoint configuration'
667@@ -389,6 +394,18 @@
668 CONFIGS.write_all()
669
670
671+@hooks.hook('nrpe-external-master-relation-joined',
672+ 'nrpe-external-master-relation-changed')
673+def update_nrpe_config():
674+ # python-dbus is used by check_upstart_job
675+ apt_install('python-dbus')
676+ hostname = nrpe.get_nagios_hostname()
677+ current_unit = nrpe.get_nagios_unit_name()
678+ nrpe_setup = nrpe.NRPE(hostname=hostname)
679+ nrpe.add_init_service_checks(nrpe_setup, services(), current_unit)
680+ nrpe_setup.write()
681+
682+
683 def main():
684 try:
685 hooks.execute(sys.argv)
686
687=== modified file 'hooks/keystone_utils.py'
688--- hooks/keystone_utils.py 2014-12-19 10:21:34 +0000
689+++ hooks/keystone_utils.py 2015-01-12 14:00:09 +0000
690@@ -226,6 +226,14 @@
691 if v['services']])
692
693
694+def services():
695+ ''' Returns a list of services associate with this charm '''
696+ _services = []
697+ for v in restart_map().values():
698+ _services = _services + v
699+ return list(set(_services))
700+
701+
702 def determine_ports():
703 '''Assemble a list of API ports for services we are managing'''
704 ports = [config('admin-port'), config('service-port')]
705
706=== added symlink 'hooks/nrpe-external-master-relation-changed'
707=== target is u'keystone_hooks.py'
708=== added symlink 'hooks/nrpe-external-master-relation-joined'
709=== target is u'keystone_hooks.py'
710=== modified file 'metadata.yaml'
711--- metadata.yaml 2014-12-16 20:15:03 +0000
712+++ metadata.yaml 2015-01-12 14:00:09 +0000
713@@ -7,6 +7,9 @@
714 implements OpenStack’s Identity API.
715 categories: ["misc"]
716 provides:
717+ nrpe-external-master:
718+ interface: nrpe-external-master
719+ scope: container
720 identity-service:
721 interface: keystone
722 identity-notifications:
723
724=== modified file 'unit_tests/test_keystone_hooks.py'
725--- unit_tests/test_keystone_hooks.py 2014-12-17 17:54:26 +0000
726+++ unit_tests/test_keystone_hooks.py 2015-01-12 14:00:09 +0000
727@@ -56,6 +56,7 @@
728 'ensure_initial_admin',
729 'add_service_to_keystone',
730 'synchronize_ca',
731+ 'update_nrpe_config',
732 # other
733 'check_call',
734 'execd_preinstall',

Subscribers

People subscribed via source and target branches