Merge lp:~brad-marshall/charms/trusty/quantum-gateway/add-nrpe-checks into lp:charms/trusty/quantum-gateway

Proposed by Brad Marshall
Status: Merged
Merged at revision: 81
Proposed branch: lp:~brad-marshall/charms/trusty/quantum-gateway/add-nrpe-checks
Merge into: lp:charms/trusty/quantum-gateway
Diff against target: 568 lines (+468/-0)
7 files modified
charm-helpers-hooks.yaml (+1/-0)
config.yaml (+10/-0)
hooks/charmhelpers/contrib/charmsupport/nrpe.py (+222/-0)
hooks/charmhelpers/contrib/charmsupport/volumes.py (+156/-0)
hooks/quantum_hooks.py (+68/-0)
hooks/quantum_utils.py (+8/-0)
metadata.yaml (+3/-0)
To merge this branch: bzr merge lp:~brad-marshall/charms/trusty/quantum-gateway/add-nrpe-checks
Reviewer Review Type Date Requested Status
Liam Young (community) Disapprove
Review via email: mp+241486@code.launchpad.net

Description of the change

Adds nrpe-external-master interface and adds basic nrpe checks.

To post a comment you must log in.
Revision history for this message
Ryan Beisner (1chb1n) wrote :

UOSCI bot says:
charm_lint_check #994 trusty-quantum-gateway for brad-marshall mp241486
    LINT FAIL: lint-test failed

LINT Results (max last 5 lines):
ERROR:root:Make target returned non-zero.
  hooks/quantum_hooks.py:205:80: E501 line too long (92 > 79 characters)
  hooks/quantum_hooks.py:236:22: E251 unexpected spaces around keyword / parameter equals
  hooks/quantum_hooks.py:236:24: E251 unexpected spaces around keyword / parameter equals
  make: *** [lint] Error 1

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

Revision history for this message
Ryan Beisner (1chb1n) wrote :

UOSCI bot says:
charm_unit_test #829 trusty-quantum-gateway for brad-marshall mp241486
    UNIT FAIL: unit-test failed

UNIT Results (max last 5 lines):
  hooks/quantum_utils 199 1 99% 354
  TOTAL 442 31 93%
  Ran 82 tests in 3.414s
  FAILED (errors=3)
  make: *** [unit_test] Error 1

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

Revision history for this message
Ryan Beisner (1chb1n) wrote :

UOSCI bot says:
charm_amulet_test #374 trusty-quantum-gateway for brad-marshall mp241486
    AMULET FAIL: amulet-test failed

AMULET Results (max last 5 lines):
  juju-test.conductor DEBUG : Calling "juju destroy-environment -y osci-sv05"
  WARNING cannot delete security group "juju-osci-sv05-0". Used by another environment?
  juju-test INFO : Results: 1 passed, 2 failed, 0 errored
  ERROR subprocess encountered error code 2
  make: *** [test] Error 2

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

79. By Brad Marshall

[bradm] Added sysvinit daemon monitoring, use services() instead of hard coded daemon list, pep8 fixes

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

UOSCI bot says:
charm_lint_check #1085 trusty-quantum-gateway for brad-marshall mp241486
    LINT FAIL: lint-test failed

LINT Results (max last 5 lines):
INFO:root:Searching for: ['@flake8']
INFO:root:command: make -f Makefile lint
ERROR:root:Make target returned non-zero.
  hooks/quantum_utils.py:501:1: F811 redefinition of unused 'services' from line 405
  make: *** [lint] Error 1

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

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

UOSCI bot says:
charm_unit_test #919 trusty-quantum-gateway for brad-marshall mp241486
    UNIT FAIL: unit-test failed

UNIT Results (max last 5 lines):
  hooks/quantum_utils 204 5 98% 354, 407-410
  TOTAL 459 47 90%
  Ran 82 tests in 3.445s
  FAILED (errors=3)
  make: *** [unit_test] Error 1

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

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

UOSCI bot says:
charm_amulet_test #427 trusty-quantum-gateway for brad-marshall mp241486
    AMULET FAIL: amulet-test failed

AMULET Results (max last 5 lines):
  juju-test.conductor DEBUG : Calling "juju destroy-environment -y osci-sv05"
  WARNING cannot delete security group "juju-osci-sv05-0". Used by another environment?
  juju-test INFO : Results: 1 passed, 2 failed, 0 errored
  ERROR subprocess encountered error code 2
  make: *** [test] Error 2

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

80. By Brad Marshall

[bradm] Removed puppet header from nagios_plugin module

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

UOSCI bot says:
charm_lint_check #1097 trusty-quantum-gateway for brad-marshall mp241486
    LINT FAIL: lint-test failed

LINT Results (max last 5 lines):
INFO:root:Searching for: ['@flake8']
INFO:root:command: make -f Makefile lint
ERROR:root:Make target returned non-zero.
  hooks/quantum_utils.py:501:1: F811 redefinition of unused 'services' from line 405
  make: *** [lint] Error 1

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

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

UOSCI bot says:
charm_unit_test #931 trusty-quantum-gateway for brad-marshall mp241486
    UNIT FAIL: unit-test failed

UNIT Results (max last 5 lines):
  hooks/quantum_utils 204 5 98% 354, 407-410
  TOTAL 459 47 90%
  Ran 82 tests in 3.640s
  FAILED (errors=3)
  make: *** [unit_test] Error 1

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

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

UOSCI bot says:
charm_amulet_test #439 trusty-quantum-gateway for brad-marshall mp241486
    AMULET FAIL: amulet-test failed

AMULET Results (max last 5 lines):
  juju-test.conductor DEBUG : Calling "juju destroy-environment -y osci-sv05"
  WARNING cannot delete security group "juju-osci-sv05-0". Used by another environment?
  juju-test INFO : Results: 1 passed, 2 failed, 0 errored
  ERROR subprocess encountered error code 2
  make: *** [test] Error 2

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

81. By Brad Marshall

[bradm] Removed nagios check files that were moved to nrpe-external-master charm

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

UOSCI bot says:
charm_lint_check #1113 trusty-quantum-gateway for brad-marshall mp241486
    LINT FAIL: lint-test failed

LINT Results (max last 5 lines):
INFO:root:command: make -f Makefile lint
ERROR:root:Make target returned non-zero.
  hooks/quantum_hooks.py:239:13: F841 local variable 'checkpath' is assigned to but never used
  hooks/quantum_utils.py:501:1: F811 redefinition of unused 'services' from line 405
  make: *** [lint] Error 1

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

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

UOSCI bot says:
charm_unit_test #947 trusty-quantum-gateway for brad-marshall mp241486
    UNIT FAIL: unit-test failed

UNIT Results (max last 5 lines):
  hooks/quantum_utils 204 5 98% 354, 407-410
  TOTAL 459 47 90%
  Ran 82 tests in 3.301s
  FAILED (errors=3)
  make: *** [unit_test] Error 1

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

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

UOSCI bot says:
charm_amulet_test #455 trusty-quantum-gateway for brad-marshall mp241486
    AMULET FAIL: amulet-test failed

AMULET Results (max last 5 lines):
  WARNING cannot delete security group "juju-osci-sv05". Used by another environment?
  WARNING cannot delete security group "juju-osci-sv05-0". Used by another environment?
  juju-test INFO : Results: 0 passed, 2 failed, 1 errored
  ERROR subprocess encountered error code 2
  make: *** [test] Error 2

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

82. By Brad Marshall

[bradm] Add network namespace checks

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

UOSCI bot says:
charm_lint_check #1141 trusty-quantum-gateway for brad-marshall mp241486
    LINT FAIL: lint-test failed

LINT Results (max last 5 lines):
INFO:root:Searching for: ['@flake8']
INFO:root:command: make -f Makefile lint
ERROR:root:Make target returned non-zero.
  hooks/quantum_utils.py:501:1: F811 redefinition of unused 'services' from line 405
  make: *** [lint] Error 1

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

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

UOSCI bot says:
charm_unit_test #975 trusty-quantum-gateway for brad-marshall mp241486
    UNIT FAIL: unit-test failed

UNIT Results (max last 5 lines):
  hooks/quantum_utils 204 5 98% 354, 407-410
  TOTAL 464 52 89%
  Ran 82 tests in 3.753s
  FAILED (errors=3)
  make: *** [unit_test] Error 1

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

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

UOSCI bot says:
charm_amulet_test #483 trusty-quantum-gateway for brad-marshall mp241486
    AMULET FAIL: amulet-test failed

AMULET Results (max last 5 lines):
  juju-test.conductor DEBUG : Calling "juju destroy-environment -y osci-sv07"
  WARNING cannot delete security group "juju-osci-sv07-0". Used by another environment?
  juju-test INFO : Results: 1 passed, 2 failed, 0 errored
  ERROR subprocess encountered error code 2
  make: *** [test] Error 2

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

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

UOSCI bot says:
charm_lint_check #1247 trusty-quantum-gateway for brad-marshall mp241486
    LINT FAIL: lint-test failed

LINT Results (max last 5 lines):
INFO:root:Searching for: ['@flake8']
INFO:root:command: make -f Makefile lint
ERROR:root:Make target returned non-zero.
  hooks/quantum_utils.py:501:1: F811 redefinition of unused 'services' from line 405
  make: *** [lint] Error 1

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

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

UOSCI bot says:
charm_unit_test #1081 trusty-quantum-gateway for brad-marshall mp241486
    UNIT FAIL: unit-test failed

UNIT Results (max last 5 lines):
  hooks/quantum_utils 204 5 98% 354, 407-410
  TOTAL 464 52 89%
  Ran 82 tests in 3.144s
  FAILED (errors=3)
  make: *** [unit_test] Error 1

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

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

UOSCI bot says:
charm_amulet_test #550 trusty-quantum-gateway for brad-marshall mp241486
    AMULET FAIL: amulet-test failed

AMULET Results (max last 5 lines):
  juju-test.conductor DEBUG : Calling "juju destroy-environment -y osci-sv05"
  WARNING cannot delete security group "juju-osci-sv05-0". Used by another environment?
  juju-test INFO : Results: 1 passed, 2 failed, 0 errored
  ERROR subprocess encountered error code 2
  make: *** [test] Error 2

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

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

Thank for the mp. The new nrpe support is very gratefully received !

I've taken this branch and centralised the common code between this and the other nrpe branches and moved it to charm-helpers. To land it I created a new branch from this one which has now been merged into the 'next' charm. The 'next' charms will overwrite the stable ones in a couple of weeks.

review: Disapprove

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

Subscribers

People subscribed via source and target branches