Merge ~hloeung/content-cache-charm:nagios-monitoring into content-cache-charm:master

Proposed by Haw Loeung
Status: Merged
Approved by: Haw Loeung
Approved revision: b21b3265f1e49ba41e55325e7e44ccc4731914bd
Merged at revision: e33b2b4cb03fbe6cb7629e90086d58fd12f15545
Proposed branch: ~hloeung/content-cache-charm:nagios-monitoring
Merge into: content-cache-charm:master
Diff against target: 164 lines (+101/-1)
3 files modified
README.md (+2/-0)
reactive/content_cache.py (+55/-0)
tests/unit/test_content_cache.py (+44/-1)
Reviewer Review Type Date Requested Status
Joel Sing (community) +1 Approve
Canonical IS Reviewers Pending
Review via email: mp+364659@code.launchpad.net

Commit message

Add configuring up NRPE and shipping out nagios checks

To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Joel Sing (jsing) wrote :

LGTM, some comments inline (mostly future follow up).

review: Approve (+1)
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision e33b2b4cb03fbe6cb7629e90086d58fd12f15545

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/README.md b/README.md
2index 8ed7922..ad67998 100644
3--- a/README.md
4+++ b/README.md
5@@ -9,3 +9,5 @@ Deploy your own content distribution network (CDN).
6 # TODO
7 - add nagios check / monitoring for configurable percentage of backends down
8 - e.g. 80% critical, 50% warning
9+- add removal of NRPE checks for sites that no longer exists.
10+- add unconfigure_nagios() for when NRPE relation is destroyed/removed.
11diff --git a/reactive/content_cache.py b/reactive/content_cache.py
12index df7199f..fc6cffb 100644
13--- a/reactive/content_cache.py
14+++ b/reactive/content_cache.py
15@@ -4,6 +4,7 @@ import yaml
16 from charms import reactive
17 from charms.layer import status
18 from charmhelpers.core import hookenv, host
19+from charmhelpers.contrib.charmsupport import nrpe
20
21 from lib import nginx
22 from lib import haproxy as HAProxy
23@@ -36,6 +37,7 @@ def install():
24 def config_changed():
25 reactive.clear_flag('content_cache.haproxy.configured')
26 reactive.clear_flag('content_cache.nginx.configured')
27+ reactive.clear_flag('nagios-nrpe.configured')
28
29
30 @reactive.when('content_cache.nginx.configured', 'content_cache.haproxy.configured')
31@@ -135,6 +137,55 @@ def configure_haproxy():
32 reactive.set_flag('content_cache.haproxy.configured')
33
34
35+@reactive.when('content_cache.nginx.configured', 'content_cache.haproxy.configured')
36+@reactive.when('nrpe-external-master.available')
37+@reactive.when_not('nagios-nrpe.configured')
38+def configure_nagios():
39+ status.maintenance('setting up NRPE checks')
40+
41+ config = hookenv.config()
42+
43+ # Use charmhelpers.contrib.charmsupport's nrpe to determine hostname
44+ hostname = nrpe.get_nagios_hostname()
45+ nrpe_setup = nrpe.NRPE(hostname=hostname, primary=True)
46+
47+ conf = yaml.safe_load(config.get('sites'))
48+ cache_port = 0
49+ backend_port = 0
50+ for site in conf.keys():
51+ (cache_port, backend_port) = next_port_pair(cache_port, backend_port)
52+
53+ default_port = 80
54+ url = 'http://{}'.format(site)
55+ tls_cert_bundle_path = conf[site].get('tls-cert-bundle-path')
56+ tls = ''
57+ if tls_cert_bundle_path:
58+ default_port = 443
59+ url = 'https://{}'.format(site)
60+ tls = ' -S --sni'
61+
62+ # Listen / frontend check
63+ check_name = 'site_{}_listen'.format(generate_nagios_check_name(site))
64+ cmd = '/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -H {site} -p {port}{tls} -u {url} -j GET' \
65+ .format(site=site, port=default_port, url=url, tls=tls)
66+ nrpe_setup.add_check(check_name, '{} site listen check'.format(site), cmd)
67+
68+ # Cache layer check
69+ check_name = 'site_{}_cache'.format(generate_nagios_check_name(site))
70+ cmd = '/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -H {site} -p {cache_port} -u {url} -j GET' \
71+ .format(site=site, cache_port=cache_port, url=url)
72+ nrpe_setup.add_check(check_name, '{} cache check'.format(site), cmd)
73+
74+ # Backend proxy layer check
75+ check_name = 'site_{}_backend_proxy'.format(generate_nagios_check_name(site))
76+ cmd = '/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -H {site} -p {backend_port} -u {url} -j GET' \
77+ .format(site=site, backend_port=backend_port, url=url)
78+ nrpe_setup.add_check(check_name, '{} backend proxy check'.format(site), cmd)
79+
80+ nrpe_setup.write()
81+ reactive.set_flag('nagios-nrpe.configured')
82+
83+
84 class InvalidPortError(Exception):
85 pass
86
87@@ -164,3 +215,7 @@ def next_port_pair(cache_port, backend_port,
88 raise InvalidPortError('Dynamically allocated backend_port out of range')
89
90 return (cache_port, backend_port)
91+
92+
93+def generate_nagios_check_name(site):
94+ return site.replace('.', '_').replace('-', '_')
95diff --git a/tests/unit/test_content_cache.py b/tests/unit/test_content_cache.py
96index 13b668e..1623fe1 100644
97--- a/tests/unit/test_content_cache.py
98+++ b/tests/unit/test_content_cache.py
99@@ -41,7 +41,7 @@ class TestCharm(unittest.TestCase):
100 patcher = mock.patch('charmhelpers.core.hookenv.config')
101 self.mock_config = patcher.start()
102 self.addCleanup(patcher.stop)
103- self.mock_config.return_value = {}
104+ self.mock_config.return_value = {'nagios_context': 'juju'}
105
106 patcher = mock.patch('multiprocessing.cpu_count')
107 self.mock_cpu_count = patcher.start()
108@@ -168,6 +168,46 @@ class TestCharm(unittest.TestCase):
109 content_cache.configure_haproxy()
110 self.assertFalse(service_start_or_restart.assert_not_called())
111
112+ @mock.patch('charmhelpers.contrib.charmsupport.nrpe.get_nagios_hostname')
113+ @mock.patch('charmhelpers.contrib.charmsupport.nrpe.NRPE')
114+ def test_configure_nagios(self, nrpe, get_nagios_hostname):
115+ get_nagios_hostname.return_value = 'some-host.local'
116+ with open('tests/unit/files/config_test_config.txt', 'r', encoding='utf-8') as f:
117+ config = f.read()
118+ self.mock_config.return_value = {'sites': config}
119+ nrpe_instance_mock = nrpe(get_nagios_hostname(), primary=True)
120+ content_cache.configure_nagios()
121+ expected = [mock.call('site_site1_local_listen', 'site1.local site listen check',
122+ '/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -H site1.local -p 80'
123+ ' -u http://site1.local -j GET'),
124+ mock.call('site_site1_local_cache', 'site1.local cache check',
125+ '/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -H site1.local -p 6080'
126+ ' -u http://site1.local -j GET'),
127+ mock.call('site_site1_local_backend_proxy', 'site1.local backend proxy check',
128+ '/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -H site1.local -p 8080'
129+ ' -u http://site1.local -j GET')]
130+ self.assertFalse(nrpe_instance_mock.add_check.assert_has_calls(expected, any_order=True))
131+ expected = [mock.call('site_site2_local_listen', 'site2.local site listen check',
132+ '/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -H site2.local -p 443 -S --sni'
133+ ' -u https://site2.local -j GET'),
134+ mock.call('site_site2_local_cache', 'site2.local cache check',
135+ '/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -H site2.local -p 6081'
136+ ' -u https://site2.local -j GET'),
137+ mock.call('site_site2_local_backend_proxy', 'site2.local backend proxy check',
138+ '/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -H site2.local -p 8081'
139+ ' -u https://site2.local -j GET')]
140+ self.assertFalse(nrpe_instance_mock.add_check.assert_has_calls(expected, any_order=True))
141+ expected = [mock.call('site_site3_local_listen', 'site3.local site listen check',
142+ '/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -H site3.local -p 80'
143+ ' -u http://site3.local -j GET'),
144+ mock.call('site_site3_local_cache', 'site3.local cache check',
145+ '/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -H site3.local -p 6082'
146+ ' -u http://site3.local -j GET'),
147+ mock.call('site_site3_local_backend_proxy', 'site3.local backend proxy check',
148+ '/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -H site3.local -p 8082'
149+ ' -u http://site3.local -j GET')]
150+ self.assertFalse(nrpe_instance_mock.add_check.assert_has_calls(expected, any_order=True))
151+
152 def test_next_port_pair(self):
153 self.assertEqual(content_cache.next_port_pair(0, 0),
154 (content_cache.BASE_CACHE_PORT, content_cache.BASE_BACKEND_PORT))
155@@ -205,6 +245,9 @@ class TestCharm(unittest.TestCase):
156 content_cache.next_port_pair(0, content_cache.BACKEND_PORT_LIMIT,
157 backend_port_limit=content_cache.BASE_BACKEND_PORT+10)
158
159+ def test_generate_nagios_check_name(self):
160+ self.assertEqual(content_cache.generate_nagios_check_name('site-1.local'), 'site_1_local')
161+
162
163 if __name__ == '__main__':
164 unittest.main()

Subscribers

People subscribed via source and target branches