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

Proposed by Liam Young
Status: Merged
Merged at revision: 134
Proposed branch: lp:~gnuoy/charms/trusty/nova-cloud-controller/add-nrpe-checks
Merge into: lp:~openstack-charmers-archive/charms/trusty/nova-cloud-controller/next
Diff against target: 654 lines (+516/-3)
9 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/fetch/__init__.py (+8/-1)
hooks/nova_cc_hooks.py (+19/-2)
metadata.yaml (+3/-0)
unit_tests/test_nova_cc_hooks.py (+1/-0)
To merge this branch: bzr merge lp:~gnuoy/charms/trusty/nova-cloud-controller/add-nrpe-checks
Reviewer Review Type Date Requested Status
Liam Young (community) Approve
Review via email: mp+246154@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 #675 nova-cloud-controller-next for gnuoy mp246154
    LINT OK: passed

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

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

charm_unit_test #704 nova-cloud-controller-next for gnuoy mp246154
    UNIT FAIL: unit-test failed

UNIT Results (max last 2 lines):
  FAILED (errors=2)
  make: *** [unit_test] Error 1

Full unit test output: http://paste.ubuntu.com/9718529/
Build: http://10.245.162.77:8080/job/charm_unit_test/704/

135. By Liam Young

Fix unit tests

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

charm_lint_check #679 nova-cloud-controller-next for gnuoy mp246154
    LINT OK: passed

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

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

charm_unit_test #708 nova-cloud-controller-next for gnuoy mp246154
    UNIT OK: passed

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

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

charm_amulet_test #860 nova-cloud-controller-next for gnuoy mp246154
    AMULET OK: passed

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

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

Subscribers

People subscribed via source and target branches