Merge lp:~clint-fewbar/charms/precise/nagios/add-monitors-2 into lp:charms/nagios

Proposed by Clint Byrum
Status: Merged
Approved by: Mark Mims
Approved revision: 38
Merged at revision: 8
Proposed branch: lp:~clint-fewbar/charms/precise/nagios/add-monitors-2
Merge into: lp:charms/nagios
Diff against target: 809 lines (+517/-163)
16 files modified
.bzrignore (+1/-0)
README (+18/-5)
config.yaml (+8/-0)
example.monitors.yaml (+30/-0)
hooks/common.py (+222/-54)
hooks/install (+16/-1)
hooks/monitors-relation-changed (+125/-0)
hooks/mymonitors-relation-joined (+17/-0)
hooks/nagios-relation-broken (+0/-12)
hooks/nagios-relation-changed (+0/-79)
hooks/nagios-relation-departed (+0/-10)
hooks/test-common.py (+50/-0)
hooks/upgrade-charm (+14/-1)
metadata.yaml (+4/-0)
monitors.yaml (+11/-0)
revision (+1/-1)
To merge this branch: bzr merge lp:~clint-fewbar/charms/precise/nagios/add-monitors-2
Reviewer Review Type Date Requested Status
Mark Mims (community) Approve
Review via email: mp+117999@code.launchpad.net

Commit message

A significant refactor of the charm's relations.

* Deprecate the 'monitoring' interface - never used in any other charm in the official store.
* Adds the 'monitors' interface to communicate complex monitoring information.
* Reworks to use 'pynag' library (embedded in a deb) for nagios configuration editting.
* Adds 'extraconfig' option for users to add extra config options.
* Enables 'external commands' so that checks can be rescheduled by an administrator.

Description of the change

A significant refactor of the charm's relations.

* Deprecate the 'monitoring' interface - never used in any other charm in the official store.
* Adds the 'monitors' interface to communicate complex monitoring information.
* Reworks to use 'pynag' library (embedded in a deb) for Nagios configuration editing.
* Adds 'extraconfig' option for users to add extra config options.
* Enables 'external commands' so that checks can be rescheduled by an administrator.

To post a comment you must log in.
Revision history for this message
Clint Byrum (clint-fewbar) wrote :

For an example of the changes needed to add remote and local monitors, see

https://code.launchpad.net/~clint-fewbar/charms/precise/mysql/add-monitors/+merge/118000

Revision history for this message
Mark Mims (mark-mims) wrote :

Please add default user/pass instructions...
maybe mention how to use `juju ssh nagios/0 sudo cat /var/lib/juju/nagios.passwd`

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file '.bzrignore'
--- .bzrignore 1970-01-01 00:00:00 +0000
+++ .bzrignore 2012-08-02 21:28:44 +0000
@@ -0,0 +1,1 @@
1data
02
=== modified file 'README'
--- README 2012-05-14 07:24:34 +0000
+++ README 2012-08-02 21:28:44 +0000
@@ -10,8 +10,21 @@
1010
11This should result in your Nagios monitoring all of the service units.11This should result in your Nagios monitoring all of the service units.
1212
13TODO:13monitors interface
14- Add a nagios-nrpe subordinate charm to make it easier to use local14==================
15 plugins via NRPE15
16- Create a proper 'monitoring' interface that charms can use to define16The monitors interface expects three fields:
17 what they want monitored remotely.17
18* monitors - YAML matching the monitors yaml spec. See
19 example.monitors.yaml for more information.
20* target-id - Assign any monitors to this target host definition.
21* target-address - Optional, specifies the host of the target to
22 monitor. This must be specified by at least one unit so that the
23 intended target-id will be monitorable.
24
25nrpe
26====
27
28There is an NRPE subordinate charm which must be used for any local
29monitors. See the 'nrpe' charm's README for information on how to
30make use of it.
1831
=== added file 'config.yaml'
--- config.yaml 1970-01-01 00:00:00 +0000
+++ config.yaml 2012-08-02 21:28:44 +0000
@@ -0,0 +1,8 @@
1options:
2 extraconfig:
3 type: string
4 default: ""
5 description: |
6 Any additional nagios configuration you would like to
7 add can be set into this element. It will be placed in
8 /etc/nagios3/conf.d/extra.cfg
09
=== added directory 'debs'
=== added file 'debs/pynag_0.4.2-1_all.deb'
1Binary files debs/pynag_0.4.2-1_all.deb 1970-01-01 00:00:00 +0000 and debs/pynag_0.4.2-1_all.deb 2012-08-02 21:28:44 +0000 differ10Binary files debs/pynag_0.4.2-1_all.deb 1970-01-01 00:00:00 +0000 and debs/pynag_0.4.2-1_all.deb 2012-08-02 21:28:44 +0000 differ
=== added file 'example.monitors.yaml'
--- example.monitors.yaml 1970-01-01 00:00:00 +0000
+++ example.monitors.yaml 2012-08-02 21:28:44 +0000
@@ -0,0 +1,30 @@
1# Version of the spec, mostly ignored but 0.3 is the current one
2version: '0.3'
3# Dict with just 'local' and 'remote' as parts
4monitors:
5 # local monitors need an agent to be handled. See nrpe charm for
6 # some example implementations
7 local:
8 # procrunning checks for a running process named X (no path)
9 procrunning:
10 # Multiple procrunning can be defined, this is the "name" of it
11 nagios3:
12 min: 1
13 max: 1
14 executable: nagios3
15 # Remote monitors can be polled directly by a remote system
16 remote:
17 # do a request on the HTTP protocol
18 http:
19 nagios:
20 port: 80
21 path: /nagios3/
22 # expected status response (otherwise just look for 200)
23 status: 'HTTP/1.1 401'
24 # Use as the Host: header (the server address will still be used to connect() to)
25 host: www.fewbar.com
26 mysql:
27 # Named basic check
28 basic:
29 username: monitors
30 password: abcdefg123456
031
=== modified file 'hooks/common.py'
--- hooks/common.py 2012-05-14 23:48:24 +0000
+++ hooks/common.py 2012-08-02 21:28:44 +0000
@@ -2,7 +2,26 @@
2import socket2import socket
3import os3import os
4import os.path4import os.path
55import re
6import sqlite3
7import shutil
8import tempfile
9
10from pynag import Model
11
12INPROGRESS_DIR = '/etc/nagios3-inprogress'
13INPROGRESS_CFG = '/etc/nagios3-inprogress/nagios.cfg'
14INPROGRESS_CONF_D = '/etc/nagios3-inprogress/conf.d'
15CHARM_CFG = '/etc/nagios3-inprogress/conf.d/charm.cfg'
16MAIN_NAGIOS_BAK = '/etc/nagios3.bak'
17MAIN_NAGIOS_DIR = '/etc/nagios3'
18MAIN_NAGIOS_CFG = '/etc/nagios3/nagios.cfg'
19PLUGIN_PATH = '/usr/lib/nagios/plugins'
20
21Model.cfg_file = INPROGRESS_CFG
22Model.pynag_directory = INPROGRESS_CONF_D
23
24reduce_RE = re.compile('[\W_]')
625
7def check_ip(n):26def check_ip(n):
8 try:27 try:
@@ -28,59 +47,208 @@
28 if check_ip(hostname):47 if check_ip(hostname):
29 # Some providers don't provide hostnames, so use the remote unit name.48 # Some providers don't provide hostnames, so use the remote unit name.
30 ip_address = hostname49 ip_address = hostname
31 hostname = remote_unit.replace('/','-')
32 else:50 else:
33 ip_address = socket.getaddrinfo(hostname, None)[0][4][0]51 ip_address = socket.getaddrinfo(hostname, None)[0][4][0]
34 return (ip_address, hostname)52 return (ip_address, remote_unit.replace('/', '-'))
3553
36# relationId-hostname-config.cfg54
37host_config_path_template = '/etc/nagios3/conf.d/%s-%s-config.cfg'55def refresh_hostgroups():
3856 """ Not the most efficient thing but since we're only
39hostgroup_template = """57 parsing what is already on disk here its not too bad """
40define hostgroup {58 hosts = [ x['host_name'] for x in Model.Host.objects.all if x['host_name'] ]
41 hostgroup_name %(name)s59
42 alias %(alias)s60 hgroups = {}
43 members %(members)s61 for host in hosts:
44}62 try:
45"""63 (service, unit_id) = host.rsplit('-', 1)
46hostgroup_path_template = '/etc/nagios3/conf.d/%s-hostgroup.cfg'64 except ValueError:
4765 continue
4866 if service in hgroups:
49def remove_hostgroup(relation_id):67 hgroups[service].append(host)
50 hostgroup_path = hostgroup_path_template % (relation_id)
51 if os.path.exists(hostgroup_path):
52 os.unlink(hostgroup_path)
53
54
55def handle_hostgroup(relation_id):
56 p = subprocess.Popen(["relation-list","-r",relation_id],
57 stdout=subprocess.PIPE)
58 services = {}
59 for unit in p.stdout:
60 unit = unit.strip()
61 service_name = unit.strip().split('/')[0]
62 (_, hostname) = get_ip_and_hostname(unit, relation_id)
63 if service_name in services:
64 services[service_name].add(hostname)
65 else:68 else:
66 services[service_name] = set([hostname])69 hgroups[service] = [host]
67 p.communicate()70
68 if p.returncode != 0:71 # Find existing autogenerated
69 raise RuntimeError('relation-list failed with code %d' % p.returncode)72 auto_hgroups = Model.Hostgroup.objects.filter(notes__contains='#autogenerated#')
7073 auto_hgroups = [ x.get_attribute('hostgroup_name') for x in auto_hgroups ]
71 hostgroup_path = hostgroup_path_template % (relation_id)74
72 for service, members in services.iteritems():75 # Delete the ones not in hgroups
73 with open(hostgroup_path, 'w') as outfile:76 to_delete = set(auto_hgroups).difference(set(hgroups.keys()))
74 outfile.write(hostgroup_template % {'name': service,77 for hgroup_name in to_delete:
75 'alias': service, 'members': ','.join(members)})78 try:
7679 hgroup = Model.Hostgroup.objects.get_by_shortname(hgroup_name)
77def refresh_hostgroups(relation_name):80 hgroup.delete()
78 p = subprocess.Popen(["relation-ids",relation_name],81 except ValueError:
79 stdout=subprocess.PIPE)82 pass
80 relids = [ relation_id.strip() for relation_id in p.stdout ]83
81 for relation_id in relids:84 for hgroup_name, members in hgroups.iteritems():
82 remove_hostgroup(relation_id)85 try:
83 handle_hostgroup(relation_id)86 hgroup = Model.Hostgroup.objects.get_by_shortname(hgroup_name)
84 p.communicate()87 except ValueError:
85 if p.returncode != 0:88 hgroup = Model.Hostgroup()
86 raise RuntimeError('relation-ids failed with code %d' % p.returncode)89 hgroup.set_filename(CHARM_CFG)
90 hgroup.set_attribute('hostgroup_name', hgroup_name)
91 hgroup.set_attribute('notes', '#autogenerated#')
92
93 hgroup.set_attribute('members', ','.join(members))
94 hgroup.save()
95
96
97def _make_check_command(args):
98 args = [str(arg) for arg in args]
99 # There is some worry of collision, but the uniqueness of the initial
100 # command should be enough.
101 signature = reduce_RE.sub('_', ''.join(
102 [os.path.basename(arg) for arg in args]))
103 Model.Command.objects.reload_cache()
104 try:
105 cmd = Model.Command.objects.get_by_shortname(signature)
106 except ValueError:
107 cmd = Model.Command()
108 cmd.set_attribute('command_name', signature)
109 cmd.set_attribute('command_line', ' '.join(args))
110 cmd.save()
111 return signature
112
113def _extend_args(args, cmd_args, switch, value):
114 args.append(value)
115 cmd_args.extend((switch, '"$ARG%d$"' % len(args)))
116
117def customize_http(service, name, extra):
118 args = []
119 cmd_args = []
120 plugin = os.path.join(PLUGIN_PATH, 'check_http')
121 port = extra.get('port', 80)
122 path = extra.get('path', '/')
123 args = [port, path]
124 cmd_args = [plugin, '-p', '"$ARG1$"', '-u', '"$ARG2$"']
125 if 'status' in extra:
126 _extend_args(args, cmd_args, '-e', extra['status'])
127 if 'host' in extra:
128 _extend_args(args, cmd_args, '-H', extra['host'])
129 cmd_args.extend(('-I', '$HOSTADDRESS$'))
130 else:
131 cmd_args.extend(('-H', '$HOSTADDRESS$'))
132 check_command = _make_check_command(cmd_args)
133 cmd = '%s!%s' % (check_command, '!'.join([str(x) for x in args]))
134 service.set_attribute('check_command', cmd)
135 return True
136
137
138def customize_mysql(service, name, extra):
139 plugin = os.path.join(PLUGIN_PATH, 'check_mysql')
140 args = []
141 cmd_args = [plugin,'-H', '$HOSTADDRESS$']
142 if 'user' in extra:
143 _extend_args(args, cmd_args, '-u', extra['user'])
144 if 'password' in extra:
145 _extend_args(args, cmd_args, '-p', extra['password'])
146 check_command = _make_check_command(cmd_args)
147 cmd = '%s!%s' % (check_command, '!'.join([str(x) for x in args]))
148 service.set_attribute('check_command', cmd)
149 return True
150
151
152def customize_nrpe(service, name, extra):
153 plugin = os.path.join(PLUGIN_PATH, 'check_nrpe')
154 args = []
155 cmd_args = [plugin,'-H', '$HOSTADDRESS$']
156 if name in ('mem','swap'):
157 cmd_args.extend(('-c', 'check_%s' % name))
158 elif 'command' in extra:
159 cmd_args.extend(('-c', extra['command']))
160 else:
161 return False
162 check_command = _make_check_command(cmd_args)
163 cmd = '%s!%s' % (check_command, '!'.join([str(x) for x in args]))
164 service.set_attribute('check_command', cmd)
165 return True
166
167
168def customize_service(service, family, name, extra):
169 customs = { 'http': customize_http,
170 'mysql': customize_mysql,
171 'nrpe': customize_nrpe}
172 if family in customs:
173 return customs[family](service, name, extra)
174 return False
175
176
177def get_pynag_host(target_id, owner_unit=None, owner_relation=None):
178 try:
179 host = Model.Host.objects.get_by_shortname(target_id)
180 except ValueError:
181 host = Model.Host()
182 host.set_filename(CHARM_CFG)
183 host.set_attribute('host_name', target_id)
184 host.set_attribute('use', 'generic-host')
185 host.save()
186 host = Model.Host.objects.get_by_shortname(target_id)
187 apply_host_policy(target_id, owner_unit, owner_relation)
188 return host
189
190
191def get_pynag_service(target_id, service_name):
192 services = Model.Service.objects.filter(host_name=target_id,
193 service_description=service_name)
194 if len(services) == 0:
195 service = Model.Service()
196 service.set_filename(CHARM_CFG)
197 service.set_attribute('service_description', service_name)
198 service.set_attribute('host_name', target_id)
199 service.set_attribute('use', 'generic-service')
200 else:
201 service = services[0]
202 return service
203
204
205def apply_host_policy(target_id, owner_unit, owner_relation):
206 ssh_service = get_pynag_service(target_id, 'SSH')
207 ssh_service.set_attribute('check_command', 'check_ssh')
208 ssh_service.save()
209
210
211def get_valid_relations():
212 for x in subprocess.Popen(['relation-ids', 'monitors'],
213 stdout=subprocess.PIPE).stdout:
214 yield x.strip()
215 for x in subprocess.Popen(['relation-ids', 'nagios'],
216 stdout=subprocess.PIPE).stdout:
217 yield x.strip()
218
219
220def get_valid_units(relation_id):
221 for x in subprocess.Popen(['relation-list', '-r', relation_id],
222 stdout=subprocess.PIPE).stdout:
223 yield x.strip()
224
225
226def _replace_in_config(find_me, replacement):
227 with open(INPROGRESS_CFG) as cf:
228 with tempfile.NamedTemporaryFile(dir=INPROGRESS_DIR, delete=False) as new_cf:
229 for line in cf:
230 new_cf.write(line.replace(find_me, replacement))
231 new_cf.flush()
232 os.chmod(new_cf.name, 0644)
233 os.unlink(INPROGRESS_CFG)
234 os.rename(new_cf.name, INPROGRESS_CFG)
235
236
237def initialize_inprogress_config():
238 if os.path.exists(INPROGRESS_DIR):
239 shutil.rmtree(INPROGRESS_DIR)
240 shutil.copytree(MAIN_NAGIOS_DIR, INPROGRESS_DIR)
241 _replace_in_config(MAIN_NAGIOS_DIR, INPROGRESS_DIR)
242 if os.path.exists(CHARM_CFG):
243 os.unlink(CHARM_CFG)
244
245
246def flush_inprogress_config():
247 if not os.path.exists(INPROGRESS_DIR):
248 return
249 _replace_in_config(INPROGRESS_DIR, MAIN_NAGIOS_DIR)
250 if os.path.exists(MAIN_NAGIOS_BAK):
251 shutil.rmtree(MAIN_NAGIOS_BAK)
252 if os.path.exists(MAIN_NAGIOS_DIR):
253 shutil.move(MAIN_NAGIOS_DIR, MAIN_NAGIOS_BAK)
254 shutil.move(INPROGRESS_DIR, MAIN_NAGIOS_DIR)
87255
=== added symlink 'hooks/config-changed'
=== target is u'upgrade-charm'
=== modified file 'hooks/install'
--- hooks/install 2012-05-13 23:04:19 +0000
+++ hooks/install 2012-08-02 21:28:44 +0000
@@ -17,7 +17,22 @@
17echo nagios3-cgi nagios3/adminpassword-repeat password $PASSWORD | debconf-set-selections17echo nagios3-cgi nagios3/adminpassword-repeat password $PASSWORD | debconf-set-selections
1818
19DEBIAN_FRONTEND=noninteractive apt-get -qy \19DEBIAN_FRONTEND=noninteractive apt-get -qy \
20 install nagios3 nagios-plugins python-cheetah dnsutils debconf-utils20 install nagios3 nagios-plugins python-cheetah dnsutils debconf-utils nagios-nrpe-plugin
21
22# Ideally these would be moved into the distro ASAP
23if [ -d debs ] ; then
24 dpkg -i debs/*.deb
25fi
26
27# enable external commands per README.Debian file
28if ! grep '^check_external_commands=1$' /etc/nagios3/nagios.cfg ; then
29 echo check_external_commands=1 >> /etc/nagios3/nagios.cfg
30fi
31# || :'s are for idempotency
32service nagios3 stop || :
33dpkg-statoverride --update --add nagios www-data 2710 /var/lib/nagios3/rw || :
34dpkg-statoverride --update --add nagios nagios 751 /var/lib/nagios3 || :
35service nagios3 start
2136
22# For the admin interface37# For the admin interface
23open-port 8038open-port 80
2439
=== removed symlink 'hooks/legacy-relation-changed'
=== target was u'nagios-relation-changed'
=== removed symlink 'hooks/legacy-relation-departed'
=== target was u'nagios-relation-departed'
=== added symlink 'hooks/monitors-relation-broken'
=== target is u'monitors-relation-changed'
=== added file 'hooks/monitors-relation-changed'
--- hooks/monitors-relation-changed 1970-01-01 00:00:00 +0000
+++ hooks/monitors-relation-changed 2012-08-02 21:28:44 +0000
@@ -0,0 +1,125 @@
1#!/usr/bin/python
2# monitors-relation-changed - Process monitors.yaml into remote nagios monitors
3# Copyright Canonical 2012 Canonical Ltd. All Rights Reserved
4# Author: Clint Byrum <clint.byrum@canonical.com>
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19import sys
20import os
21import subprocess
22import yaml
23import json
24import re
25import string
26
27
28from common import (customize_service, get_pynag_host,
29 get_pynag_service, refresh_hostgroups,
30 get_valid_relations, get_valid_units,
31 initialize_inprogress_config, flush_inprogress_config)
32
33
34def main(argv):
35 # Note that one can pass in args positionally, 'monitors.yaml targetid
36 # and target-address' so the hook can be tested without being in a hook
37 # context.
38 #
39 if len(argv) > 1:
40 relation_settings = {'monitors': open(argv[1]).read(),
41 'target-id': argv[2]}
42 if len(argv) > 3:
43 relation_settings['target-address'] = argv[3]
44 all_relations = {'monitors:99': {'testing/0': relation_settings}}
45 else:
46 all_relations = {}
47 for relid in get_valid_relations():
48 (relname, relnum) = relid.split(':')
49 for unit in get_valid_units(relid):
50 relation_settings = json.loads(
51 subprocess.check_output(['relation-get', '--format=json',
52 '-r', relid,
53 '-',unit]).strip())
54
55 if relation_settings is None or relation_settings == '':
56 continue
57
58 if relname == 'monitors':
59 if ('monitors' not in relation_settings
60 or 'target-id' not in relation_settings):
61 continue
62 else:
63 # Fake it for the more generic 'nagios' relation'
64 relation_settings['target-id'] = unit.replace('/','-')
65 relation_settings['target-address'] = relation_settings['private-address']
66 relation_settings['monitors'] = {'monitors': {'remote': {} } }
67
68 if relid not in all_relations:
69 all_relations[relid] = {}
70
71 all_relations[relid][unit] = relation_settings
72
73 # Hack to work around http://pad.lv/1025478
74 targets_with_addresses = set()
75 for relid, units in all_relations.iteritems():
76 for unit, relation_settings in units.iteritems():
77 if 'target-address' in relation_settings:
78 targets_with_addresses.add(relation_settings['target-id'])
79 new_all_relations = {}
80 for relid, units in all_relations.iteritems():
81 for unit, relation_settings in units.iteritems():
82 if relation_settings['target-id'] in targets_with_addresses:
83 if relid not in new_all_relations:
84 new_all_relations[relid] = {}
85 new_all_relations[relid][unit] = relation_settings
86 all_relations = new_all_relations
87
88 initialize_inprogress_config()
89 for relid, units in all_relations.iteritems():
90 apply_relation_config(relid, units)
91 refresh_hostgroups()
92 flush_inprogress_config()
93 os.system('service nagios3 reload')
94
95def apply_relation_config(relid, units):
96 for unit, relation_settings in units.iteritems():
97 monitors = relation_settings['monitors']
98 target_id = relation_settings['target-id']
99 # If not set, we don't mess with it, as multiple services may feed
100 # monitors in for a particular address. Generally a primary will set this
101 # to its own private-address
102 target_address = relation_settings.get('target-address', None)
103
104 if type(monitors) != dict:
105 monitors = yaml.safe_load(monitors)
106
107 # Output nagios config
108 host = get_pynag_host(target_id)
109
110 if target_address is not None:
111 host.set_attribute('address', target_address)
112 host.save()
113
114 for mon_family, mons in monitors['monitors']['remote'].iteritems():
115 for mon_name, mon in mons.iteritems():
116 service_name = '%s-%s' % (target_id, mon_name)
117 service = get_pynag_service(target_id, service_name)
118 if customize_service(service, mon_family, mon_name, mon):
119 service.save()
120 else:
121 print('Ignoring %s due to unknown family %s' % (mon_name,
122 mon_family))
123
124if __name__ == '__main__':
125 main(sys.argv)
0126
=== added symlink 'hooks/monitors-relation-departed'
=== target is u'monitors-relation-changed'
=== added file 'hooks/mymonitors-relation-joined'
--- hooks/mymonitors-relation-joined 1970-01-01 00:00:00 +0000
+++ hooks/mymonitors-relation-joined 2012-08-02 21:28:44 +0000
@@ -0,0 +1,17 @@
1#!/bin/bash
2if [ -n "$JUJU_RELATION_ID" ] ; then
3 # single relation joined
4 rels=$JUJU_RELATION_ID
5else
6 # Refresh from upgrade or some other place
7 rels=`relation-ids mymonitors`
8fi
9
10target_id=${JUJU_UNIT_NAME//\//-}
11
12for rel in $rels ; do
13 relation-set -r $rel \
14 monitors="`cat monitors.yaml`" \
15 target-address=`unit-get private-address` \
16 target-id=$target_id
17done
018
=== added symlink 'hooks/nagios-relation-broken'
=== target is u'monitors-relation-changed'
=== removed file 'hooks/nagios-relation-broken'
--- hooks/nagios-relation-broken 2012-05-14 07:15:54 +0000
+++ hooks/nagios-relation-broken 1970-01-01 00:00:00 +0000
@@ -1,12 +0,0 @@
1#!/usr/bin/python
2import glob
3import os
4
5import common
6
7common.remove_hostgroup(os.environ['JUJU_RELATION_ID'])
8glob_target = common.host_config_path_template % (os.environ['JUJU_RELATION_ID'], '*')
9print 'Removing relation config files: %s' % (glob_target)
10for oldconfig in glob.glob(glob_target):
11 print 'Removing %s' % (oldconfig)
12 os.unlink(oldconfig)
130
=== added symlink 'hooks/nagios-relation-changed'
=== target is u'monitors-relation-changed'
=== removed file 'hooks/nagios-relation-changed'
--- hooks/nagios-relation-changed 2012-05-14 07:15:54 +0000
+++ hooks/nagios-relation-changed 1970-01-01 00:00:00 +0000
@@ -1,79 +0,0 @@
1#!/usr/bin/env python
2
3import string
4import sys
5import os
6import os.path
7import yaml
8import subprocess
9from common import *
10
11from Cheetah.Template import Template
12
13def write_service_template(service, host, description, command):
14 service = service.replace("__hostname__", host)
15 service = service.replace("__description__", description)
16 service = service.replace("__command__", command)
17 return service
18
19def write_host_template(host, hostname, ip_address):
20 host = host.replace("__hostname__", hostname)
21 host = host.replace("__alias__", hostname)
22 host = host.replace("__address__", ip_address)
23 return host
24
25
26def main():
27 for var in ['JUJU_REMOTE_UNIT', 'JUJU_RELATION_ID']:
28 if var not in os.environ:
29 print "%s must be set" % (var)
30 return 1
31 relation_id = os.environ["JUJU_RELATION_ID"]
32 relation_name = os.path.basename(sys.argv[0]).split('-')[0]
33 remote_unit = os.environ["JUJU_REMOTE_UNIT"]
34
35 service_name, _ = remote_unit.split("/")
36 (ip_address, hostname) = get_ip_and_hostname(remote_unit)
37
38 nagios_service = ""
39 host_template = """
40 define host {
41 use generic-host ; Name of host template to use
42 host_name __hostname__
43 alias __alias__
44 address __address__
45 }
46"""
47 service_template = """
48 define service {
49 use generic-service ; Name of service template to use
50 host_name __hostname__
51 service_description __description__
52 check_command __command__
53 }
54"""
55
56 # write a single host
57 host_template = write_host_template(host_template, hostname, ip_address)
58 nagios_service += host_template
59
60 # all hosts should be running SSH
61 nagios_service += write_service_template(service_template, hostname, 'SSH', 'check_ssh')
62
63 namespace = {'hostname': hostname, 'nagios_config':nagios_service}
64 t = Template(open('hooks/templates/nagios.tmpl').read(), searchList=[namespace])
65 config_file = host_config_path_template % (relation_id, hostname)
66 f = open(config_file, 'w')
67 f.write(str(t))
68 f.close()
69
70 refresh_hostgroups(relation_name)
71
72 print "Restarting nagios"
73 subprocess.call(["service", "nagios3", "restart"])
74 return 0
75
76if __name__ == '__main__':
77 sys.exit(main())
78
79
800
=== added symlink 'hooks/nagios-relation-departed'
=== target is u'monitors-relation-changed'
=== removed file 'hooks/nagios-relation-departed'
--- hooks/nagios-relation-departed 2012-05-14 07:15:54 +0000
+++ hooks/nagios-relation-departed 1970-01-01 00:00:00 +0000
@@ -1,10 +0,0 @@
1#!/usr/bin/python
2
3import common
4import os
5
6relation_id = os.environ['JUJU_RELATION_ID']
7(_,hostname) = common.get_ip_and_hostname(os.environ['JUJU_REMOTE_UNIT'])
8os.unlink(common.host_config_path_template % (relation_id, hostname))
9common.refresh_hostgroups(os.path.basename(sys.argv[0]).split('-')[0])
10subprocess.call(['service','nagios3','restart'])
110
=== added file 'hooks/test-common.py'
--- hooks/test-common.py 1970-01-01 00:00:00 +0000
+++ hooks/test-common.py 2012-08-02 21:28:44 +0000
@@ -0,0 +1,50 @@
1from common import ObjectTagCollection
2import os
3
4from tempfile import NamedTemporaryFile
5
6""" This is meant to test the ObjectTagCollection bits. It should
7 probably be made into a proper unit test. """
8
9x = ObjectTagCollection('test-units')
10y = ObjectTagCollection('test-relids')
11
12o = NamedTemporaryFile(delete=False)
13o2 = NamedTemporaryFile(delete=False)
14o3 = NamedTemporaryFile(delete=True)
15o.write('some content')
16o.flush()
17
18x.tag_object(o.name, 'box-9')
19x.tag_object(o.name, 'nrpe-1')
20y.tag_object(o.name, 'monitors:2')
21x.tag_object(o2.name, 'box-10')
22x.tag_object(o2.name, 'nrpe-2')
23y.tag_object(o2.name, 'monitors:2')
24x.tag_object(o3.name, 'other-0')
25y.tag_object(o3.name, 'monitors:3')
26x.untag_object(o.name, 'box-9')
27x.cleanup_untagged()
28
29if not os.path.exists(o.name):
30 raise RuntimeError(o.name)
31
32x.kill_tag('nrpe-1')
33x.cleanup_untagged()
34
35if os.path.exists(o.name):
36 raise RuntimeError(o.name)
37
38if not os.path.exists(o2.name):
39 raise RuntimeError(o2.name)
40
41y.kill_tag('monitors:2')
42y.cleanup_untagged(['monitors:1','monitors:3'])
43
44if os.path.exists(o.name):
45 raise RuntimeError(o2.name)
46
47if os.path.exists(o2.name):
48 raise RuntimeError(o2.name)
49
50x.destroy()
051
=== modified file 'hooks/upgrade-charm'
--- hooks/upgrade-charm 2012-05-14 07:15:54 +0000
+++ hooks/upgrade-charm 2012-08-02 21:28:44 +0000
@@ -1,2 +1,15 @@
1#!/bin/sh1#!/bin/sh
2juju-log -l WARNING 'Relations have been radically changed. Its best to remove any existing relationships and re-establish them.'2set -e
3legacy_relations="`relation-ids legacy`"
4if [ -n "$legacy_relations" ] ; then
5 juju-log -l WARNING 'Relations have been radically changed. The monitoring interface is not supported anymore.'
6 juju-log -l WARNING 'Please use the generic juju-info or the monitors interface'
7fi
8if [ -n "`config-get extraconfig`" ] ; then
9 config-get extraconfig > /etc/nagios3/conf.d/extra.cfg
10else
11 rm -f /etc/nagios3/conf.d/extra.cfg
12fi
13# Refresh these hooks entirely
14hooks/mymonitors-relation-joined
15hooks/monitors-relation-changed
316
=== modified file 'metadata.yaml'
--- metadata.yaml 2012-05-22 22:10:53 +0000
+++ metadata.yaml 2012-08-02 21:28:44 +0000
@@ -8,8 +8,12 @@
8provides:8provides:
9 website:9 website:
10 interface: http10 interface: http
11 mymonitors:
12 interface: monitors
11requires:13requires:
12 legacy:14 legacy:
13 interface: monitoring15 interface: monitoring
14 nagios:16 nagios:
15 interface: juju-info17 interface: juju-info
18 monitors:
19 interface: monitors
1620
=== added file 'monitors.yaml'
--- monitors.yaml 1970-01-01 00:00:00 +0000
+++ monitors.yaml 2012-08-02 21:28:44 +0000
@@ -0,0 +1,11 @@
1version: '0.3'
2monitors:
3 local:
4 procrunning:
5 min: 1
6 name: '/usr/sbin/nagios3'
7 remote:
8 http:
9 nagios:
10 path: /nagios3/
11 status: 'HTTP/1.1 401'
012
=== modified file 'revision'
--- revision 2012-05-14 23:48:24 +0000
+++ revision 2012-08-02 21:28:44 +0000
@@ -1,1 +1,1 @@
122140

Subscribers

People subscribed via source and target branches

to all changes: