Merge lp:~brad-marshall/charms/trusty/ceilometer-agent/add-nrpe-checks into lp:~openstack-charmers-archive/charms/trusty/ceilometer-agent/trunk

Proposed by Brad Marshall
Status: Merged
Merged at revision: 46
Proposed branch: lp:~brad-marshall/charms/trusty/ceilometer-agent/add-nrpe-checks
Merge into: lp:~openstack-charmers-archive/charms/trusty/ceilometer-agent/trunk
Diff against target: 560 lines (+459/-1)
7 files modified
charm-helpers.yaml (+1/-0)
config.yaml (+10/-0)
hooks/ceilometer_hooks.py (+59/-1)
hooks/ceilometer_utils.py (+8/-0)
hooks/charmhelpers/contrib/charmsupport/nrpe.py (+222/-0)
hooks/charmhelpers/contrib/charmsupport/volumes.py (+156/-0)
metadata.yaml (+3/-0)
To merge this branch: bzr merge lp:~brad-marshall/charms/trusty/ceilometer-agent/add-nrpe-checks
Reviewer Review Type Date Requested Status
Liam Young (community) Disapprove
Billy Olsen Needs Fixing
Review via email: mp+242041@code.launchpad.net

Description of the change

Add nagios checks to ceilometer-agent, similar to the others I've done.

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

UOSCI bot says:
charm_lint_check #1122 trusty-ceilometer-agent for brad-marshall mp242041
    LINT OK: passed

LINT Results (max last 5 lines):
INFO:root:Workspace dir: /var/lib/jenkins/workspace/charm_lint_check
INFO:root:Reading file: Makefile
INFO:root:Searching for: ['@flake8']
INFO:root:command: make -f Makefile lint
  W: metadata name (ceilometer-agent) must match directory name (trusty-ceilometer-agent) exactly for local deployment.

Full lint test output: http://paste.ubuntu.com/9066692/
Build: http://10.98.191.181:8080/job/charm_lint_check/1122/

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

UOSCI bot says:
charm_unit_test #956 trusty-ceilometer-agent for brad-marshall mp242041
    UNIT FAIL: unit-test failed

UNIT Results (max last 5 lines):
  hooks/ceilometer_utils 43 4 91% 99-102
  TOTAL 126 33 74%
  Ran 11 tests in 0.132s
  FAILED (errors=3)
  make: *** [test] Error 1

Full unit test output: http://paste.ubuntu.com/9066693/
Build: http://10.98.191.181:8080/job/charm_unit_test/956/

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

UOSCI bot says:
charm_amulet_test #464 trusty-ceilometer-agent for brad-marshall mp242041
    AMULET FAIL: amulet-test missing

AMULET Results (max last 5 lines):
INFO:root:Workspace dir: /var/lib/jenkins/workspace/charm_amulet_test
INFO:root:Reading file: Makefile
INFO:root:Searching for: ['@juju test']
INFO:root:Search string not found in makefile target commands.
ERROR:root:No make target was executed.

Full amulet test output: http://paste.ubuntu.com/9066694/
Build: http://10.98.191.181:8080/job/charm_amulet_test/464/

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

UOSCI bot says:
charm_lint_check #1246 trusty-ceilometer-agent for brad-marshall mp242041
    LINT OK: passed

LINT Results (max last 5 lines):
INFO:root:Reading file: Makefile
INFO:root:Searching for: ['@flake8']
INFO:root:command: make -f Makefile lint
  W: metadata name (ceilometer-agent) must match directory name (trusty-ceilometer-agent) exactly for local deployment.
  I: Categories are being deprecated in favor of tags. Please rename the "categories" field to "tags".

Full lint test output: http://paste.ubuntu.com/9281277/
Build: http://10.98.191.181:8080/job/charm_lint_check/1246/

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

UOSCI bot says:
charm_unit_test #1080 trusty-ceilometer-agent for brad-marshall mp242041
    UNIT FAIL: unit-test failed

UNIT Results (max last 5 lines):
  hooks/ceilometer_utils 43 4 91% 99-102
  TOTAL 126 33 74%
  Ran 11 tests in 0.105s
  FAILED (errors=3)
  make: *** [test] Error 1

Full unit test output: http://paste.ubuntu.com/9281279/
Build: http://10.98.191.181:8080/job/charm_unit_test/1080/

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

UOSCI bot says:
charm_amulet_test #549 trusty-ceilometer-agent for brad-marshall mp242041
    AMULET FAIL: amulet-test missing

AMULET Results (max last 5 lines):
INFO:root:Workspace dir: /var/lib/jenkins/workspace/charm_amulet_test
INFO:root:Reading file: Makefile
INFO:root:Searching for: ['@juju test']
INFO:root:Search string not found in makefile target commands.
ERROR:root:No make target was executed.

Full amulet test output: http://paste.ubuntu.com/9281368/
Build: http://10.98.191.181:8080/job/charm_amulet_test/549/

Revision history for this message
Billy Olsen (billy-olsen) wrote :

Hey Brad, thanks for the submission!
I know this is similar to the NRPE code submissions for other charms, however a few comments.

- Please fix the unit tests as they are failing
- Additionally, new code has 0 unit test coverage

I'm not overly familiar with how the NRPE stuff works, but HA support is being added to the ceilometer charm which one of the services (ceilometer-central-agent) is running in an active/standby mode. Since this code monitors all the services, what are the impacts when n-1 nodes are reporting this service as down?

review: Needs Fixing
Revision history for this message
Billy Olsen (billy-olsen) wrote :

My mistake - this is on the ceilometer-agent, which doesn't have high availability - that's going into the ceilometer charm itself.

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

This branch is now superseded as I've taken the branch and updated it in light of the additional nrpe support that has been added to charm-helper. nrpe support has now landed in the devel charm and will be moved to stable this week

review: Disapprove

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'charm-helpers.yaml'
2--- charm-helpers.yaml 2014-08-13 13:43:25 +0000
3+++ charm-helpers.yaml 2014-11-18 05:52:38 +0000
4@@ -7,3 +7,4 @@
5 - contrib.hahelpers
6 - contrib.storage.linux
7 - contrib.network.ip
8+ - contrib.charmsupport
9
10=== modified file 'config.yaml'
11--- config.yaml 2014-03-31 13:51:46 +0000
12+++ config.yaml 2014-11-18 05:52:38 +0000
13@@ -14,3 +14,13 @@
14 Note that updating this setting to a source that is known to
15 provide a later version of OpenStack will trigger a software
16 upgrade.
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=== modified file 'hooks/ceilometer_hooks.py'
29--- hooks/ceilometer_hooks.py 2014-04-01 16:53:45 +0000
30+++ hooks/ceilometer_hooks.py 2014-11-18 05:52:38 +0000
31@@ -1,6 +1,7 @@
32 #!/usr/bin/python
33
34 import sys
35+import os
36 import json
37 from charmhelpers.fetch import (
38 apt_install, filter_installed_packages,
39@@ -10,7 +11,9 @@
40 config,
41 Hooks, UnregisteredHookError,
42 log,
43- relation_set
44+ local_unit,
45+ relation_set,
46+ relations_of_type,
47 )
48 from charmhelpers.core.host import (
49 restart_on_change,
50@@ -22,12 +25,15 @@
51 )
52 from ceilometer_utils import (
53 restart_map,
54+ services,
55 register_configs,
56 CEILOMETER_AGENT_PACKAGES,
57 NOVA_SETTINGS,
58 do_openstack_upgrade
59 )
60
61+from charmhelpers.contrib.charmsupport.nrpe import NRPE
62+
63 hooks = Hooks()
64 CONFIGS = register_configs()
65
66@@ -55,6 +61,7 @@
67 @restart_on_change(restart_map())
68 def ceilometer_changed():
69 CONFIGS.write_all()
70+ update_nrpe_config()
71
72
73 @hooks.hook('config-changed')
74@@ -62,8 +69,59 @@
75 def config_changed():
76 if openstack_upgrade_available('ceilometer-common'):
77 do_openstack_upgrade(CONFIGS)
78+ update_nrpe_config()
79 CONFIGS.write_all()
80
81+
82+@hooks.hook('nrpe-external-master-relation-joined',
83+ 'nrpe-external-master-relation-changed')
84+def update_nrpe_config():
85+ # Find out if nrpe set nagios_hostname
86+ hostname = None
87+ host_context = None
88+ for rel in relations_of_type('nrpe-external-master'):
89+ if 'nagios_hostname' in rel:
90+ hostname = rel['nagios_hostname']
91+ host_context = rel['nagios_host_context']
92+ break
93+ nrpe = NRPE(hostname=hostname)
94+ apt_install('python-dbus')
95+
96+ if host_context:
97+ current_unit = "%s:%s" % (host_context, local_unit())
98+ else:
99+ current_unit = local_unit()
100+
101+ services_to_monitor = services()
102+
103+ for service in services_to_monitor:
104+ upstart_init = '/etc/init/%s.conf' % service
105+ sysv_init = '/etc/init.d/%s' % service
106+
107+ if os.path.exists(upstart_init):
108+ nrpe.add_check(
109+ shortname=service,
110+ description='process check {%s}' % current_unit,
111+ check_cmd='check_upstart_job %s' % service,
112+ )
113+ elif os.path.exists(sysv_init):
114+ cronpath = '/etc/cron.d/nagios-service-check-%s' % service
115+ cron_template = '*/5 * * * * root \
116+/usr/local/lib/nagios/plugins/check_exit_status.pl -s /etc/init.d/%s \
117+status > /var/lib/nagios/service-check-%s.txt\n' % (service, service)
118+ f = open(cronpath, 'w')
119+ f.write(cron_template)
120+ f.close()
121+ nrpe.add_check(
122+ shortname=service,
123+ description='process check {%s}' % current_unit,
124+ check_cmd='check_status_file.py -f \
125+ /var/lib/nagios/service-check-%s.txt' % service,
126+ )
127+
128+ nrpe.write()
129+
130+
131 if __name__ == '__main__':
132 try:
133 hooks.execute(sys.argv)
134
135=== modified file 'hooks/ceilometer_utils.py'
136--- hooks/ceilometer_utils.py 2014-04-01 16:53:45 +0000
137+++ hooks/ceilometer_utils.py 2014-11-18 05:52:38 +0000
138@@ -94,6 +94,14 @@
139 return _map
140
141
142+def services():
143+ ''' Returns a list of services associate with this charm '''
144+ _services = []
145+ for v in restart_map().values():
146+ _services = _services + v
147+ return list(set(_services))
148+
149+
150 def do_openstack_upgrade(configs):
151 """
152 Perform an upgrade. Takes care of upgrading packages, rewriting
153
154=== added directory 'hooks/charmhelpers/contrib/charmsupport'
155=== added file 'hooks/charmhelpers/contrib/charmsupport/__init__.py'
156=== added file 'hooks/charmhelpers/contrib/charmsupport/nrpe.py'
157--- hooks/charmhelpers/contrib/charmsupport/nrpe.py 1970-01-01 00:00:00 +0000
158+++ hooks/charmhelpers/contrib/charmsupport/nrpe.py 2014-11-18 05:52:38 +0000
159@@ -0,0 +1,222 @@
160+"""Compatibility with the nrpe-external-master charm"""
161+# Copyright 2012 Canonical Ltd.
162+#
163+# Authors:
164+# Matthew Wedgwood <matthew.wedgwood@canonical.com>
165+
166+import subprocess
167+import pwd
168+import grp
169+import os
170+import re
171+import shlex
172+import yaml
173+
174+from charmhelpers.core.hookenv import (
175+ config,
176+ local_unit,
177+ log,
178+ relation_ids,
179+ relation_set,
180+)
181+
182+from charmhelpers.core.host import service
183+
184+# This module adds compatibility with the nrpe-external-master and plain nrpe
185+# subordinate charms. To use it in your charm:
186+#
187+# 1. Update metadata.yaml
188+#
189+# provides:
190+# (...)
191+# nrpe-external-master:
192+# interface: nrpe-external-master
193+# scope: container
194+#
195+# and/or
196+#
197+# provides:
198+# (...)
199+# local-monitors:
200+# interface: local-monitors
201+# scope: container
202+
203+#
204+# 2. Add the following to config.yaml
205+#
206+# nagios_context:
207+# default: "juju"
208+# type: string
209+# description: |
210+# Used by the nrpe subordinate charms.
211+# A string that will be prepended to instance name to set the host name
212+# in nagios. So for instance the hostname would be something like:
213+# juju-myservice-0
214+# If you're running multiple environments with the same services in them
215+# this allows you to differentiate between them.
216+#
217+# 3. Add custom checks (Nagios plugins) to files/nrpe-external-master
218+#
219+# 4. Update your hooks.py with something like this:
220+#
221+# from charmsupport.nrpe import NRPE
222+# (...)
223+# def update_nrpe_config():
224+# nrpe_compat = NRPE()
225+# nrpe_compat.add_check(
226+# shortname = "myservice",
227+# description = "Check MyService",
228+# check_cmd = "check_http -w 2 -c 10 http://localhost"
229+# )
230+# nrpe_compat.add_check(
231+# "myservice_other",
232+# "Check for widget failures",
233+# check_cmd = "/srv/myapp/scripts/widget_check"
234+# )
235+# nrpe_compat.write()
236+#
237+# def config_changed():
238+# (...)
239+# update_nrpe_config()
240+#
241+# def nrpe_external_master_relation_changed():
242+# update_nrpe_config()
243+#
244+# def local_monitors_relation_changed():
245+# update_nrpe_config()
246+#
247+# 5. ln -s hooks.py nrpe-external-master-relation-changed
248+# ln -s hooks.py local-monitors-relation-changed
249+
250+
251+class CheckException(Exception):
252+ pass
253+
254+
255+class Check(object):
256+ shortname_re = '[A-Za-z0-9-_]+$'
257+ service_template = ("""
258+#---------------------------------------------------
259+# This file is Juju managed
260+#---------------------------------------------------
261+define service {{
262+ use active-service
263+ host_name {nagios_hostname}
264+ service_description {nagios_hostname}[{shortname}] """
265+ """{description}
266+ check_command check_nrpe!{command}
267+ servicegroups {nagios_servicegroup}
268+}}
269+""")
270+
271+ def __init__(self, shortname, description, check_cmd):
272+ super(Check, self).__init__()
273+ # XXX: could be better to calculate this from the service name
274+ if not re.match(self.shortname_re, shortname):
275+ raise CheckException("shortname must match {}".format(
276+ Check.shortname_re))
277+ self.shortname = shortname
278+ self.command = "check_{}".format(shortname)
279+ # Note: a set of invalid characters is defined by the
280+ # Nagios server config
281+ # The default is: illegal_object_name_chars=`~!$%^&*"|'<>?,()=
282+ self.description = description
283+ self.check_cmd = self._locate_cmd(check_cmd)
284+
285+ def _locate_cmd(self, check_cmd):
286+ search_path = (
287+ '/',
288+ os.path.join(os.environ['CHARM_DIR'],
289+ 'files/nrpe-external-master'),
290+ '/usr/lib/nagios/plugins',
291+ '/usr/local/lib/nagios/plugins',
292+ )
293+ parts = shlex.split(check_cmd)
294+ for path in search_path:
295+ if os.path.exists(os.path.join(path, parts[0])):
296+ command = os.path.join(path, parts[0])
297+ if len(parts) > 1:
298+ command += " " + " ".join(parts[1:])
299+ return command
300+ log('Check command not found: {}'.format(parts[0]))
301+ return ''
302+
303+ def write(self, nagios_context, hostname):
304+ nrpe_check_file = '/etc/nagios/nrpe.d/{}.cfg'.format(
305+ self.command)
306+ with open(nrpe_check_file, 'w') as nrpe_check_config:
307+ nrpe_check_config.write("# check {}\n".format(self.shortname))
308+ nrpe_check_config.write("command[{}]={}\n".format(
309+ self.command, self.check_cmd))
310+
311+ if not os.path.exists(NRPE.nagios_exportdir):
312+ log('Not writing service config as {} is not accessible'.format(
313+ NRPE.nagios_exportdir))
314+ else:
315+ self.write_service_config(nagios_context, hostname)
316+
317+ def write_service_config(self, nagios_context, hostname):
318+ for f in os.listdir(NRPE.nagios_exportdir):
319+ if re.search('.*{}.cfg'.format(self.command), f):
320+ os.remove(os.path.join(NRPE.nagios_exportdir, f))
321+
322+ templ_vars = {
323+ 'nagios_hostname': hostname,
324+ 'nagios_servicegroup': nagios_context,
325+ 'description': self.description,
326+ 'shortname': self.shortname,
327+ 'command': self.command,
328+ }
329+ nrpe_service_text = Check.service_template.format(**templ_vars)
330+ nrpe_service_file = '{}/service__{}_{}.cfg'.format(
331+ NRPE.nagios_exportdir, hostname, self.command)
332+ with open(nrpe_service_file, 'w') as nrpe_service_config:
333+ nrpe_service_config.write(str(nrpe_service_text))
334+
335+ def run(self):
336+ subprocess.call(self.check_cmd)
337+
338+
339+class NRPE(object):
340+ nagios_logdir = '/var/log/nagios'
341+ nagios_exportdir = '/var/lib/nagios/export'
342+ nrpe_confdir = '/etc/nagios/nrpe.d'
343+
344+ def __init__(self, hostname=None):
345+ super(NRPE, self).__init__()
346+ self.config = config()
347+ self.nagios_context = self.config['nagios_context']
348+ self.unit_name = local_unit().replace('/', '-')
349+ if hostname:
350+ self.hostname = hostname
351+ else:
352+ self.hostname = "{}-{}".format(self.nagios_context, self.unit_name)
353+ self.checks = []
354+
355+ def add_check(self, *args, **kwargs):
356+ self.checks.append(Check(*args, **kwargs))
357+
358+ def write(self):
359+ try:
360+ nagios_uid = pwd.getpwnam('nagios').pw_uid
361+ nagios_gid = grp.getgrnam('nagios').gr_gid
362+ except:
363+ log("Nagios user not set up, nrpe checks not updated")
364+ return
365+
366+ if not os.path.exists(NRPE.nagios_logdir):
367+ os.mkdir(NRPE.nagios_logdir)
368+ os.chown(NRPE.nagios_logdir, nagios_uid, nagios_gid)
369+
370+ nrpe_monitors = {}
371+ monitors = {"monitors": {"remote": {"nrpe": nrpe_monitors}}}
372+ for nrpecheck in self.checks:
373+ nrpecheck.write(self.nagios_context, self.hostname)
374+ nrpe_monitors[nrpecheck.shortname] = {
375+ "command": nrpecheck.command,
376+ }
377+
378+ service('restart', 'nagios-nrpe-server')
379+
380+ for rid in relation_ids("local-monitors"):
381+ relation_set(relation_id=rid, monitors=yaml.dump(monitors))
382
383=== added file 'hooks/charmhelpers/contrib/charmsupport/volumes.py'
384--- hooks/charmhelpers/contrib/charmsupport/volumes.py 1970-01-01 00:00:00 +0000
385+++ hooks/charmhelpers/contrib/charmsupport/volumes.py 2014-11-18 05:52:38 +0000
386@@ -0,0 +1,156 @@
387+'''
388+Functions for managing volumes in juju units. One volume is supported per unit.
389+Subordinates may have their own storage, provided it is on its own partition.
390+
391+Configuration stanzas:
392+ volume-ephemeral:
393+ type: boolean
394+ default: true
395+ description: >
396+ If false, a volume is mounted as sepecified in "volume-map"
397+ If true, ephemeral storage will be used, meaning that log data
398+ will only exist as long as the machine. YOU HAVE BEEN WARNED.
399+ volume-map:
400+ type: string
401+ default: {}
402+ description: >
403+ YAML map of units to device names, e.g:
404+ "{ rsyslog/0: /dev/vdb, rsyslog/1: /dev/vdb }"
405+ Service units will raise a configure-error if volume-ephemeral
406+ is 'true' and no volume-map value is set. Use 'juju set' to set a
407+ value and 'juju resolved' to complete configuration.
408+
409+Usage:
410+ from charmsupport.volumes import configure_volume, VolumeConfigurationError
411+ from charmsupport.hookenv import log, ERROR
412+ def post_mount_hook():
413+ stop_service('myservice')
414+ def post_mount_hook():
415+ start_service('myservice')
416+
417+ if __name__ == '__main__':
418+ try:
419+ configure_volume(before_change=pre_mount_hook,
420+ after_change=post_mount_hook)
421+ except VolumeConfigurationError:
422+ log('Storage could not be configured', ERROR)
423+'''
424+
425+# XXX: Known limitations
426+# - fstab is neither consulted nor updated
427+
428+import os
429+from charmhelpers.core import hookenv
430+from charmhelpers.core import host
431+import yaml
432+
433+
434+MOUNT_BASE = '/srv/juju/volumes'
435+
436+
437+class VolumeConfigurationError(Exception):
438+ '''Volume configuration data is missing or invalid'''
439+ pass
440+
441+
442+def get_config():
443+ '''Gather and sanity-check volume configuration data'''
444+ volume_config = {}
445+ config = hookenv.config()
446+
447+ errors = False
448+
449+ if config.get('volume-ephemeral') in (True, 'True', 'true', 'Yes', 'yes'):
450+ volume_config['ephemeral'] = True
451+ else:
452+ volume_config['ephemeral'] = False
453+
454+ try:
455+ volume_map = yaml.safe_load(config.get('volume-map', '{}'))
456+ except yaml.YAMLError as e:
457+ hookenv.log("Error parsing YAML volume-map: {}".format(e),
458+ hookenv.ERROR)
459+ errors = True
460+ if volume_map is None:
461+ # probably an empty string
462+ volume_map = {}
463+ elif not isinstance(volume_map, dict):
464+ hookenv.log("Volume-map should be a dictionary, not {}".format(
465+ type(volume_map)))
466+ errors = True
467+
468+ volume_config['device'] = volume_map.get(os.environ['JUJU_UNIT_NAME'])
469+ if volume_config['device'] and volume_config['ephemeral']:
470+ # asked for ephemeral storage but also defined a volume ID
471+ hookenv.log('A volume is defined for this unit, but ephemeral '
472+ 'storage was requested', hookenv.ERROR)
473+ errors = True
474+ elif not volume_config['device'] and not volume_config['ephemeral']:
475+ # asked for permanent storage but did not define volume ID
476+ hookenv.log('Ephemeral storage was requested, but there is no volume '
477+ 'defined for this unit.', hookenv.ERROR)
478+ errors = True
479+
480+ unit_mount_name = hookenv.local_unit().replace('/', '-')
481+ volume_config['mountpoint'] = os.path.join(MOUNT_BASE, unit_mount_name)
482+
483+ if errors:
484+ return None
485+ return volume_config
486+
487+
488+def mount_volume(config):
489+ if os.path.exists(config['mountpoint']):
490+ if not os.path.isdir(config['mountpoint']):
491+ hookenv.log('Not a directory: {}'.format(config['mountpoint']))
492+ raise VolumeConfigurationError()
493+ else:
494+ host.mkdir(config['mountpoint'])
495+ if os.path.ismount(config['mountpoint']):
496+ unmount_volume(config)
497+ if not host.mount(config['device'], config['mountpoint'], persist=True):
498+ raise VolumeConfigurationError()
499+
500+
501+def unmount_volume(config):
502+ if os.path.ismount(config['mountpoint']):
503+ if not host.umount(config['mountpoint'], persist=True):
504+ raise VolumeConfigurationError()
505+
506+
507+def managed_mounts():
508+ '''List of all mounted managed volumes'''
509+ return filter(lambda mount: mount[0].startswith(MOUNT_BASE), host.mounts())
510+
511+
512+def configure_volume(before_change=lambda: None, after_change=lambda: None):
513+ '''Set up storage (or don't) according to the charm's volume configuration.
514+ Returns the mount point or "ephemeral". before_change and after_change
515+ are optional functions to be called if the volume configuration changes.
516+ '''
517+
518+ config = get_config()
519+ if not config:
520+ hookenv.log('Failed to read volume configuration', hookenv.CRITICAL)
521+ raise VolumeConfigurationError()
522+
523+ if config['ephemeral']:
524+ if os.path.ismount(config['mountpoint']):
525+ before_change()
526+ unmount_volume(config)
527+ after_change()
528+ return 'ephemeral'
529+ else:
530+ # persistent storage
531+ if os.path.ismount(config['mountpoint']):
532+ mounts = dict(managed_mounts())
533+ if mounts.get(config['mountpoint']) != config['device']:
534+ before_change()
535+ unmount_volume(config)
536+ mount_volume(config)
537+ after_change()
538+ else:
539+ before_change()
540+ mount_volume(config)
541+ after_change()
542+ return config['mountpoint']
543
544=== added symlink 'hooks/nrpe-external-master-relation-changed'
545=== target is u'ceilometer_hooks.py'
546=== added symlink 'hooks/nrpe-external-master-relation-joined'
547=== target is u'ceilometer_hooks.py'
548=== modified file 'metadata.yaml'
549--- metadata.yaml 2013-11-29 15:34:44 +0000
550+++ metadata.yaml 2014-11-18 05:52:38 +0000
551@@ -15,6 +15,9 @@
552 - miscellaneous
553 - openstack
554 provides:
555+ nrpe-external-master:
556+ interface: nrpe-external-master
557+ scope: container
558 nova-ceilometer:
559 interface: nova-ceilometer
560 scope: container

Subscribers

People subscribed via source and target branches