Merge lp:~gnuoy/charms/trusty/nrpe/sibling-subordinate into lp:charms/trusty/nrpe

Proposed by Liam Young on 2016-03-14
Status: Merged
Merge reported by: David Ames
Merged at revision: not available
Proposed branch: lp:~gnuoy/charms/trusty/nrpe/sibling-subordinate
Merge into: lp:charms/trusty/nrpe
Diff against target: 476 lines (+144/-199)
6 files modified
Makefile (+1/-1)
README.md (+20/-0)
hooks/nrpe_helpers.py (+69/-54)
tests/10-tests (+54/-12)
tests/11-monitors-configurations (+0/-60)
tests/13-monitors-config (+0/-72)
To merge this branch: bzr merge lp:~gnuoy/charms/trusty/nrpe/sibling-subordinate
Reviewer Review Type Date Requested Status
David Ames Approve on 2016-03-22
Review Queue (community) automated testing Approve on 2016-03-22
charmers 2016-03-14 Pending
Review via email: mp+288888@code.launchpad.net

Description of the Change

Add support for multiple charms to be related to nrpe via the nrpe, juju-info or local-monitors relation. This is useful when joining an additional local subordinate to this charm. See README changes.

To post a comment you must log in.
Review Queue (review-queue) wrote :

This item has failed automated testing! Results available here http://juju-ci.vapour.ws:8080/job/charm-bundle-test-aws/3192/

review: Needs Fixing (automated testing)
David Ames (thedac) wrote :

Liam running a manual amulet test fails:

2016-03-18 15:08:25 Deploying services...
2016-03-18 15:09:37 Config specifies num units for subordinate: nrpe
2016-03-18 15:09:39 Adding relations...
2016-03-18 15:09:40 Adding relation nrpe:local-monitors <-> mysql:local-monitors
Traceback (most recent call last):
  File "/usr/bin/juju-deployer", line 9, in <module>
    load_entry_point('juju-deployer==0.6.4', 'console_scripts', 'juju-deployer')()
  File "/usr/lib/python2.7/dist-packages/deployer/cli.py", line 135, in main
    run()
  File "/usr/lib/python2.7/dist-packages/deployer/cli.py", line 234, in run
    importer.Importer(env, deployment, options).run()
  File "/usr/lib/python2.7/dist-packages/deployer/action/importer.py", line 325, in run
    rels_created = self.add_relations()
  File "/usr/lib/python2.7/dist-packages/deployer/action/importer.py", line 235, in add_relations
    self.env.add_relation(end_a, end_b)
  File "/usr/lib/python2.7/dist-packages/deployer/env/go.py", line 51, in add_relation
    return self.client.add_relation(endpoint_a, endpoint_b)
  File "/usr/lib/python2.7/dist-packages/jujuclient.py", line 1122, in add_relation
    'Endpoints': [endpoint_a, endpoint_b]
  File "/usr/lib/python2.7/dist-packages/jujuclient.py", line 317, in _rpc
    raise EnvError(result)
jujuclient.EnvError: <Env Error - Details:
 { u'Error': u'cannot add relation "nrpe:local-monitors mysql:local-monitors": principal and subordinate services\' series
must match',
    u'RequestId': 1,
    u'Response': { }}
 >
E
======================================================================
ERROR: setUpClass (__main__.TestDeployment)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/10-tests", line 28, in setUpClass
    cls.deployment.setup(timeout=900)
  File "/usr/lib/python2.7/dist-packages/amulet/deployer.py", line 430, in setup
    subprocess.check_call(shlex.split(cmd))
  File "/usr/lib/python2.7/subprocess.py", line 541, in check_call
    raise CalledProcessError(retcode, cmd)
CalledProcessError: Command '['juju-deployer', '-W', '-c', '/tmp/amulet-juju-deployer-IiT6ij/deployer-schema.json', '-e', 'th
edac-laptop', '-t', '1000', 'thedac-laptop']' returned non-zero exit status 1

----------------------------------------------------------------------
Ran 0 tests in 77.503s

FAILED (errors=1)

review: Needs Fixing
Review Queue (review-queue) wrote :

This item has failed automated testing! Results available here http://juju-ci.vapour.ws:8080/job/charm-bundle-test-aws/3230/

review: Needs Fixing (automated testing)
44. By Liam Young on 2016-03-20

Fix bug which was stopping local checks being rendered

45. By Liam Young on 2016-03-20

Merge tests/11-monitors-configurations tests/13-monitors-config into tests/10-tests. Promote 14-basic-nrpe-external-master to me run from Makefile along with 10-tests. Fix bug causing checks with a _default prefix being defined on the monitors relation

46. By Liam Young on 2016-03-20

Remove debug print

David Ames (thedac) wrote :

I have manually run the amulet tests successfully.

+1 from me.

We may still need to figure out why the automated testing is having problems.

review: Approve
Review Queue (review-queue) wrote :

The results (PASS) are in and available here: http://juju-ci.vapour.ws:8080/job/charm-bundle-test-lxc/3230/

review: Approve (automated testing)
David Ames (thedac) wrote :

Approved as a ~charmer(s)

Merging.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2015-04-19 07:52:43 +0000
3+++ Makefile 2016-03-20 13:11:29 +0000
4@@ -25,4 +25,4 @@
5 # raise_status() messages to stderr:
6 # https://bugs.launchpad.net/amulet/+bug/1320357
7 @juju test -v -p AMULET_HTTP_PROXY --timeout 900 \
8- 00-setup 10-tests
9+ 00-setup 10-tests 14-basic-nrpe-external-master
10
11=== modified file 'README.md'
12--- README.md 2015-03-23 09:45:10 +0000
13+++ README.md 2016-03-20 13:11:29 +0000
14@@ -27,6 +27,26 @@
15 section and finally it can request external monitors are setup by using one of
16 the other remote types. See "Monitors yaml" below.
17
18+Other Subordinate Charms
19+========================
20+
21+If another subordinate charm deployed to the same principle has a
22+local-monitors or nrpe-external-master relation then it can also be related to
23+the local nrpe charm. For example,
24+
25+echo -e "glance:\n vip: 10.5.106.1" > glance.yaml
26+juju deploy -n3 --config glance.yaml glance
27+juju deploy hacluster glance-hacluster
28+juju deploy nrpe glance-nrpe
29+juju deploy nagios
30+juju add-relation glance glance-hacluster
31+juju add-relation glance-nrpe:monitors nagios:monitors
32+juju add-relation glance glance-nrpe
33+juju add-relation glance-hacluster glance-nrpe
34+
35+The glance-hacluster charm will pass montioring information to glance-nrpe
36+which will amalgamate all montior definitions before passing them to nagios
37+
38 Check sources
39 =============
40
41
42=== modified file 'hooks/nrpe_helpers.py'
43--- hooks/nrpe_helpers.py 2016-02-10 13:01:51 +0000
44+++ hooks/nrpe_helpers.py 2016-03-20 13:11:29 +0000
45@@ -6,16 +6,42 @@
46 from charmhelpers.core import hookenv
47
48
49-class MonitorsRelation(helpers.RelationContext):
50- name = 'monitors'
51- interface = 'monitors'
52-
53- def __init__(self, *args, **kwargs):
54- self.principle_relation = PrincipleRelation()
55- super(MonitorsRelation, self).__init__(*args, **kwargs)
56-
57- def is_ready(self):
58- return self.principle_relation.is_ready()
59+class Monitors(dict):
60+ """ Represent the list of checks that a remote Nagios can query converting
61+ local check to ones that can be queried remotely
62+ """
63+
64+ def __init__(self, version='0.3'):
65+ self['monitors'] = {
66+ 'local': {},
67+ 'remote': {
68+ 'nrpe': {}
69+ }
70+ }
71+ self['version'] = version
72+
73+ def add_monitors(self, mdict, monitor_label='default'):
74+ if not mdict or not mdict.get('monitors'):
75+ return
76+
77+ for checktype in mdict['monitors'].get('remote', []):
78+ check_details = mdict['monitors']['remote'][checktype]
79+ if self['monitors']['remote'].get(checktype):
80+ self['monitors']['remote'][checktype].update(check_details)
81+ else:
82+ self['monitors']['remote'][checktype] = check_details
83+
84+ if mdict['monitors'].get('local'):
85+ self['monitors']['local'].update(mdict['monitors'].get('local'))
86+ for checktype in mdict['monitors']['local']:
87+ check_details = self.convert_local_checks(
88+ mdict['monitors']['local'],
89+ monitor_label,
90+ )
91+ self['monitors']['remote']['nrpe'].update(check_details)
92+
93+ def add_nrpe_check(self, check_name, command):
94+ self['monitors']['remote']['nrpe'][check_name] = {'command': command}
95
96 def convert_local_checks(self, monitors, monitor_src):
97 """ Convert check from local checks to remote nrpe checks
98@@ -35,23 +61,31 @@
99 {'command': check_def['cmd_name']}
100 return mons
101
102+
103+class MonitorsRelation(helpers.RelationContext):
104+ name = 'monitors'
105+ interface = 'monitors'
106+
107+ def __init__(self, *args, **kwargs):
108+ self.principle_relation = PrincipleRelation()
109+ super(MonitorsRelation, self).__init__(*args, **kwargs)
110+
111+ def is_ready(self):
112+ return self.principle_relation.is_ready()
113+
114 def get_subordinate_monitors(self):
115 """ Return default monitors defined by this charm """
116- monitors = {
117- 'monitors': {
118- 'remote': {
119- 'nrpe': {}
120- }
121- }
122- }
123+ monitors = Monitors()
124 for check in SubordinateCheckDefinitions()['checks']:
125- monitors['monitors']['remote']['nrpe'][check['cmd_name']] = \
126- {'command': check['cmd_name']}
127+ monitors.add_nrpe_check(check['cmd_name'], check['cmd_name'])
128 return monitors
129
130 def get_user_defined_monitors(self):
131 """ Return monitors defined by monitors config option """
132- return yaml.safe_load(hookenv.config('monitors'))
133+ monitors = Monitors()
134+ monitors.add_monitors(yaml.safe_load(hookenv.config('monitors')),
135+ 'user')
136+ return monitors
137
138 def get_principle_monitors(self):
139 """ Return monitors passed by relation with principle """
140@@ -70,37 +104,14 @@
141 """ Return monitor dict of all monitors merged together and local
142 monitors converted to remote nrpe checks
143 """
144- monitors = {
145- 'monitors': {
146- 'remote': {
147- 'nrpe': {}
148- }
149- }
150- }
151- monitor_dicts = self.get_monitor_dicts()
152- for monitor_src in monitor_dicts.keys():
153- monitor_dict = monitor_dicts[monitor_src]
154- if not monitor_dict or 'monitors' not in monitor_dict:
155- continue
156- if 'remote' in monitor_dict['monitors']:
157- remote_mons = monitor_dict['monitors']['remote']
158- for checktype in remote_mons.keys():
159- if checktype in monitors['monitors']['remote']:
160- monitors['monitors']['remote'][checktype].update(
161- remote_mons[checktype]
162- )
163- else:
164- monitors['monitors']['remote'][checktype] = \
165- remote_mons[checktype]
166- if 'local' in monitor_dict['monitors']:
167- monitors['monitors']['remote']['nrpe'].update(
168- self.convert_local_checks(
169- monitor_dict['monitors']['local'],
170- monitor_src,
171- )
172- )
173- monitors['version'] = '0.3'
174- return monitors
175+ all_monitors = Monitors()
176+ all_monitors.add_monitors(self.get_principle_monitors(), 'principle')
177+ all_monitors.add_monitors(
178+ self.get_subordinate_monitors(),
179+ str(hookenv.config("sub_postfix"))
180+ )
181+ all_monitors.add_monitors(self.get_user_defined_monitors(), 'user')
182+ return all_monitors
183
184 def get_data(self):
185 super(MonitorsRelation, self).get_data()
186@@ -149,11 +160,15 @@
187 return nagios_hostname
188
189 def get_monitors(self):
190- """ Return monitors passed by principle charm """
191+ """ Return monitors passed by services on the self.interface relation
192+ """
193 if not self.is_ready():
194 return
195- if 'monitors' in self[self.name][0]:
196- return yaml.load(self[self.name][0]['monitors'])
197+ monitors = Monitors()
198+ for rel in self[self.name]:
199+ if rel.get('monitors'):
200+ monitors.add_monitors(yaml.load(rel['monitors']), 'principle')
201+ return monitors
202
203 def provide_data(self):
204 # Provide this data to principals because get_nagios_hostname expects
205
206=== modified file 'tests/10-tests'
207--- tests/10-tests 2016-02-11 10:24:41 +0000
208+++ tests/10-tests 2016-03-20 13:11:29 +0000
209@@ -1,9 +1,10 @@
210 #!/usr/bin/python
211
212 import amulet
213+import yaml
214 import unittest
215 import time
216-import yaml
217+import requests
218 from charmhelpers.contrib.amulet.utils import (
219 AmuletUtils,
220 )
221@@ -245,11 +246,12 @@
222 self.check_nrpe_setting(**test_config)
223
224 def test_sub_postfix(self):
225- sentry = self.deployment.sentry['nrpe'][0]
226+ check_cmd = ('/usr/lib/nagios/plugins/check_disk -u GB -w 25% -c 20% '
227+ '-K 5% -p /')
228 test_config = {
229 'filename': '/etc/nagios/nrpe.d/check_disk_root_testing.cfg',
230- 'expected_settings': {'command[check_disk_root]': '/usr/lib/nagios/plugins/check_disk -u GB -w 25% -c 20% -K 5% -p /'},
231- 'juju_kv': { 'sub_postfix': '_testing'},
232+ 'expected_settings': {'command[check_disk_root]': check_cmd},
233+ 'juju_kv': {'sub_postfix': '_testing'},
234 'filedelim': '=',
235 }
236 self.check_nrpe_setting(**test_config)
237@@ -259,7 +261,10 @@
238 test_config = {
239 'filename': '/etc/nagios/nrpe.d/check_disk_root_sub.cfg',
240 'expected_settings': {chk_key: '-u GB -w 5% -c 1% -K 10% -p /'},
241- 'juju_kv': {'disk_root': '-u GB -w 5% -c 1% -K 10%'}
242+ 'juju_kv': {
243+ 'disk_root': '-u GB -w 5% -c 1% -K 10%',
244+ 'sub_postfix': '_sub',
245+ }
246 }
247 self.check_nrpe_setting(**test_config)
248
249@@ -269,7 +274,10 @@
250 test_config = {
251 'filename': '/etc/nagios/nrpe.d/check_zombie_procs_sub.cfg',
252 'expected_settings': {chk_key: '-w 6 -c 12 -s Z'},
253- 'juju_kv': {'zombies': '-w 6 -c 12 -s Z'}
254+ 'juju_kv': {
255+ 'zombies': '-w 6 -c 12 -s Z',
256+ 'sub_postfix': '_sub',
257+ }
258 }
259 self.check_nrpe_setting(**test_config)
260
261@@ -279,7 +287,10 @@
262 test_config = {
263 'filename': '/etc/nagios/nrpe.d/check_total_procs_sub.cfg',
264 'expected_settings': {chk_key: '-w 40 -c 60'},
265- 'juju_kv': {'procs': '-w 40 -c 60'}
266+ 'juju_kv': {
267+ 'procs': '-w 40 -c 60',
268+ 'sub_postfix': '_sub',
269+ }
270 }
271 self.check_nrpe_setting(**test_config)
272
273@@ -288,7 +299,10 @@
274 test_config = {
275 'filename': '/etc/nagios/nrpe.d/check_load_sub.cfg',
276 'expected_settings': {chk_key: '-w 9,9,9 -c 16,16,16'},
277- 'juju_kv': {'load': '-w 9,9,9 -c 16,16,16'}
278+ 'juju_kv': {
279+ 'load': '-w 9,9,9 -c 16,16,16',
280+ 'sub_postfix': '_sub',
281+ }
282 }
283 self.check_nrpe_setting(**test_config)
284
285@@ -297,7 +311,10 @@
286 test_config = {
287 'filename': '/etc/nagios/nrpe.d/check_users_sub.cfg',
288 'expected_settings': {chk_key: '-w 40 -c 50'},
289- 'juju_kv': {'users': '-w 40 -c 50'}
290+ 'juju_kv': {
291+ 'users': '-w 40 -c 50',
292+ 'sub_postfix': '_sub',
293+ }
294 }
295 self.check_nrpe_setting(**test_config)
296
297@@ -306,9 +323,34 @@
298 test_config = {
299 'filename': '/etc/nagios/nrpe.d/check_swap_sub.cfg',
300 'expected_settings': {chk_key: '-w 5% -c 1%'},
301- 'juju_kv': {'swap': '-w 5% -c 1%'}
302- }
303- self.check_nrpe_setting(**test_config)
304+ 'juju_kv': {
305+ 'swap': '-w 5% -c 1%',
306+ 'sub_postfix': '_sub',
307+ }
308+ }
309+ self.check_nrpe_setting(**test_config)
310+
311+ def test_nrpe_monitors_config(self):
312+ chk_key = 'command[check_swap]=/usr/lib/nagios/plugins/check_procs'
313+ test_config = {
314+ 'filename': '/etc/nagios/nrpe.d/check_proc_mysqld_principle.cfg',
315+ 'expected_settings': {chk_key: '-w 1 -c 1 -C mysqld'},
316+ 'juju_kv': {},
317+ }
318+ self.check_nrpe_setting(**test_config)
319+
320+ def test_nagios_monitors_response(self):
321+ # look for mysql_database requests
322+ sentry = self.deployment.sentry['nagios'][0]
323+ nagpwd = sentry.file_contents('/var/lib/juju/nagios.passwd').strip()
324+ host_url = ("http://%s/cgi-bin/nagios3/status.cgi?"
325+ "host=all")
326+ r = requests.get(host_url % sentry.info['public-address'],
327+ auth=('nagiosadmin', nagpwd))
328+ if not r.text.find('check_proc_mysqld_principle'):
329+ amulet.raise_status(amulet.ERROR,
330+ msg='Nagios is not monitoring the' +
331+ ' hosts it supposed to.')
332
333
334 if __name__ == '__main__':
335
336=== removed file 'tests/11-monitors-configurations'
337--- tests/11-monitors-configurations 2016-02-03 22:17:17 +0000
338+++ tests/11-monitors-configurations 1970-01-01 00:00:00 +0000
339@@ -1,60 +0,0 @@
340-#!/usr/bin/python3
341-
342-import amulet
343-import requests
344-
345-seconds = 20000
346-
347-d = amulet.Deployment(series='trusty')
348-
349-d.add('nagios')
350-d.add('mysql')
351-d.add('nrpe')
352-
353-d.configure('mysql', {'dataset-size': '10%'})
354-d.relate('nagios:monitors', 'mysql:monitors')
355-d.relate('nrpe:monitors', 'nagios:monitors')
356-d.relate('nrpe:local-monitors', 'mysql:local-monitors')
357-
358-d.expose('nagios')
359-
360-try:
361- d.setup(timeout=seconds)
362-except amulet.helpers.TimeoutError:
363- amulet.raise_status(amulet.SKIP, msg="Environment wasn't stood up in time")
364-except:
365- raise
366-
367-
368-##
369-# Set relationship aliases
370-##
371-mysql_unit = d.sentry['mysql'][0]
372-nagios_unit = d.sentry['nagios'][0]
373-
374-
375-def test_nrpe_monitors_config():
376- # look for procrunning in nrpe config
377- try:
378- mysql_unit.file_contents('/etc/nagios/nrpe.d/'
379- 'check_proc_mysqld_principle.cfg')
380- except IOError as e:
381- amulet.raise_status(amulet.ERROR,
382- msg="procrunning config not found. Error:" +
383- e.args[1])
384-
385-
386-def test_nagios_monitors_response():
387- # look for mysql_database requests
388- nagpwd = nagios_unit.file_contents('/var/lib/juju/nagios.passwd').strip()
389- host_url = ("http://%s/cgi-bin/nagios3/status.cgi?"
390- "host=mysql-0")
391- r = requests.get(host_url % nagios_unit.info['public-address'],
392- auth=('nagiosadmin', nagpwd))
393- if not r.text.find('mysql-0-basic'):
394- amulet.raise_status(amulet.ERROR,
395- msg='Nagios is not monitoring the' +
396- ' hosts it supposed to.')
397-
398-test_nrpe_monitors_config()
399-test_nagios_monitors_response()
400
401=== removed file 'tests/13-monitors-config'
402--- tests/13-monitors-config 2016-02-03 22:17:17 +0000
403+++ tests/13-monitors-config 1970-01-01 00:00:00 +0000
404@@ -1,72 +0,0 @@
405-#!/usr/bin/python3
406-
407-import amulet
408-import requests
409-
410-seconds = 20000
411-
412-d = amulet.Deployment(series='trusty')
413-
414-d.add('nagios')
415-d.add('mysql')
416-d.add('nrpe')
417-
418-d.configure('mysql', {'dataset-size': '10%'})
419-d.relate('nagios:monitors', 'mysql:monitors')
420-d.relate('nrpe:monitors', 'nagios:monitors')
421-d.relate('nrpe:local-monitors', 'mysql:local-monitors')
422-
423-d.configure('nrpe', {
424- 'monitors': """
425- version: '0.3'
426- monitors:
427- remote: {}
428- local:
429- processcount:
430- all:
431- max: 100
432- """
433-})
434-
435-d.expose('nagios')
436-
437-try:
438- d.setup(timeout=seconds)
439-except amulet.helpers.TimeoutError:
440- amulet.raise_status(amulet.SKIP, msg="Environment wasn't stood up in time")
441-except:
442- raise
443-
444-
445-##
446-# Set relationship aliases
447-##
448-mysql_unit = d.sentry['mysql'][0]
449-nagios_unit = d.sentry['nagios'][0]
450-
451-
452-def test_nrpe_monitors_config():
453- # look for procrunning in nrpe config
454- try:
455- mysql_unit.file_contents('/etc/nagios/nrpe.d/'
456- 'check_proc_mysqld_principle.cfg')
457- except IOError as e:
458- amulet.raise_status(amulet.ERROR,
459- msg="procrunning config not found. Error:" +
460- e.args[1])
461-
462-
463-def test_nagios_monitors_response():
464- # look for mysql_database requests
465- nagpwd = nagios_unit.file_contents('/var/lib/juju/nagios.passwd').strip()
466- host_url = ("http://%s/cgi-bin/nagios3/status.cgi?"
467- "host=mysql-0")
468- r = requests.get(host_url % nagios_unit.info['public-address'],
469- auth=('nagiosadmin', nagpwd))
470- if not r.text.find('processcount'):
471- amulet.raise_status(amulet.ERROR,
472- msg='Nagios is not monitoring the' +
473- ' hosts it supposed to.')
474-
475-test_nrpe_monitors_config()
476-test_nagios_monitors_response()

Subscribers

People subscribed via source and target branches

to all changes: