Merge lp:~timkuhlman/charms/trusty/rsyslog/nrpe into lp:charms/trusty/rsyslog

Proposed by Tim Kuhlman
Status: Merged
Merged at revision: 22
Proposed branch: lp:~timkuhlman/charms/trusty/rsyslog/nrpe
Merge into: lp:charms/trusty/rsyslog
Diff against target: 727 lines (+627/-7)
8 files modified
charm-helpers.yaml (+2/-0)
config.yaml (+16/-0)
hooks/charmhelpers/contrib/charmsupport/__init__.py (+15/-0)
hooks/charmhelpers/contrib/charmsupport/nrpe.py (+398/-0)
hooks/charmhelpers/contrib/charmsupport/volumes.py (+175/-0)
hooks/hooks.py (+16/-6)
metadata.yaml (+3/-0)
unit_tests/test_hooks.py (+2/-1)
To merge this branch: bzr merge lp:~timkuhlman/charms/trusty/rsyslog/nrpe
Reviewer Review Type Date Requested Status
Stuart Bishop (community) Approve
Andrew McLeod (community) Needs Fixing
Adam Israel (community) Needs Fixing
Review Queue (community) automated testing Needs Fixing
Review via email: mp+292988@code.launchpad.net

Description of the change

Adds an nrpe relation and nagios check for the rsyslog daemon.

To post a comment you must log in.
Revision history for this message
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/3951/

review: Needs Fixing (automated testing)
Revision history for this message
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/3952/

review: Needs Fixing (automated testing)
Revision history for this message
Review Queue (review-queue) wrote :

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

review: Needs Fixing (automated testing)
Revision history for this message
Review Queue (review-queue) wrote :

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

review: Needs Fixing (automated testing)
Revision history for this message
Adam Israel (aisrael) wrote :

Hi Tim,

Here's the logs from my test run.

http://pastebin.ubuntu.com/16508662/

review: Needs Fixing
24. By Tim Kuhlman

Mock nrpe also

Revision history for this message
Tim Kuhlman (timkuhlman) wrote :

I pushed up a fix for the failing test.

On 05/19/2016 10:13 AM, Adam Israel wrote:
> Review: Needs Fixing
>
> Hi Tim,
>
> Here's the logs from my test run.
>
> http://pastebin.ubuntu.com/16508662/
>

--
Tim Kuhlman
CDO - IS - Foxtrot

Revision history for this message
Andrew McLeod (admcleod) wrote :

Hey Tim,

Those tests are passing now, but there are still some failures on make lint and charm-proof:

http://pastebin.ubuntu.com/16514759/

review: Needs Fixing
25. By Tim Kuhlman

Remove spaces around keyword parameters =

Revision history for this message
Tim Kuhlman (timkuhlman) wrote :

I fixed the spacing around the '=' the other import errors are interesting one those are lines I didn't touch and it seems flake8 is just fooled by the sys.path.insert of the charmhelpers that is happening at the top of the file. Likely that isn't actually needed but I am out of time to test it for sure today. If no one beats me to it I will test that tomorrow..

26. By Tim Kuhlman

Removed unneeded sys.path modifications that lint doesn't like

Revision history for this message
Stuart Bishop (stub) wrote :

Looks good

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'charm-helpers.yaml'
--- charm-helpers.yaml 2014-04-21 21:03:13 +0000
+++ charm-helpers.yaml 2016-05-20 17:02:41 +0000
@@ -3,3 +3,5 @@
3include:3include:
4 - core4 - core
5 - fetch5 - fetch
6 - contrib.charmsupport
7
68
=== modified file 'config.yaml'
--- config.yaml 2016-03-24 21:20:46 +0000
+++ config.yaml 2016-05-20 17:02:41 +0000
@@ -19,6 +19,22 @@
19 type: string19 type: string
20 default: "*.*"20 default: "*.*"
21 description: "Syslog style selector to specify which logs to forward. For example '*.crit' or 'auth.*'"21 description: "Syslog style selector to specify which logs to forward. For example '*.crit' or 'auth.*'"
22 nagios_context:
23 default: "juju"
24 type: string
25 description: >
26 Used by the nrpe-external-master subordinate charm.
27 A string that will be prepended to instance name to set the host name
28 in nagios. So for instance the hostname would be something like:
29 juju-rsyslog-0
30 If you're running multiple environments with the same services in them
31 this allows you to differentiate between them.
32 nagios_servicegroups:
33 default: ""
34 type: string
35 description: >
36 A comma-separated list of nagios servicegroups.
37 If left empty, the nagios_context will be used as the servicegroup
22 syslog_rotate:38 syslog_rotate:
23 type: int39 type: int
24 default: 740 default: 7
2541
=== added directory 'hooks/charmhelpers/contrib/charmsupport'
=== added file 'hooks/charmhelpers/contrib/charmsupport/__init__.py'
--- hooks/charmhelpers/contrib/charmsupport/__init__.py 1970-01-01 00:00:00 +0000
+++ hooks/charmhelpers/contrib/charmsupport/__init__.py 2016-05-20 17:02:41 +0000
@@ -0,0 +1,15 @@
1# Copyright 2014-2015 Canonical Limited.
2#
3# This file is part of charm-helpers.
4#
5# charm-helpers is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Lesser General Public License version 3 as
7# published by the Free Software Foundation.
8#
9# charm-helpers is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Lesser General Public License for more details.
13#
14# You should have received a copy of the GNU Lesser General Public License
15# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
016
=== added file 'hooks/charmhelpers/contrib/charmsupport/nrpe.py'
--- hooks/charmhelpers/contrib/charmsupport/nrpe.py 1970-01-01 00:00:00 +0000
+++ hooks/charmhelpers/contrib/charmsupport/nrpe.py 2016-05-20 17:02:41 +0000
@@ -0,0 +1,398 @@
1# Copyright 2014-2015 Canonical Limited.
2#
3# This file is part of charm-helpers.
4#
5# charm-helpers is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Lesser General Public License version 3 as
7# published by the Free Software Foundation.
8#
9# charm-helpers is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Lesser General Public License for more details.
13#
14# You should have received a copy of the GNU Lesser General Public License
15# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
16
17"""Compatibility with the nrpe-external-master charm"""
18# Copyright 2012 Canonical Ltd.
19#
20# Authors:
21# Matthew Wedgwood <matthew.wedgwood@canonical.com>
22
23import subprocess
24import pwd
25import grp
26import os
27import glob
28import shutil
29import re
30import shlex
31import yaml
32
33from charmhelpers.core.hookenv import (
34 config,
35 local_unit,
36 log,
37 relation_ids,
38 relation_set,
39 relations_of_type,
40)
41
42from charmhelpers.core.host import service
43
44# This module adds compatibility with the nrpe-external-master and plain nrpe
45# subordinate charms. To use it in your charm:
46#
47# 1. Update metadata.yaml
48#
49# provides:
50# (...)
51# nrpe-external-master:
52# interface: nrpe-external-master
53# scope: container
54#
55# and/or
56#
57# provides:
58# (...)
59# local-monitors:
60# interface: local-monitors
61# scope: container
62
63#
64# 2. Add the following to config.yaml
65#
66# nagios_context:
67# default: "juju"
68# type: string
69# description: |
70# Used by the nrpe subordinate charms.
71# A string that will be prepended to instance name to set the host name
72# in nagios. So for instance the hostname would be something like:
73# juju-myservice-0
74# If you're running multiple environments with the same services in them
75# this allows you to differentiate between them.
76# nagios_servicegroups:
77# default: ""
78# type: string
79# description: |
80# A comma-separated list of nagios servicegroups.
81# If left empty, the nagios_context will be used as the servicegroup
82#
83# 3. Add custom checks (Nagios plugins) to files/nrpe-external-master
84#
85# 4. Update your hooks.py with something like this:
86#
87# from charmsupport.nrpe import NRPE
88# (...)
89# def update_nrpe_config():
90# nrpe_compat = NRPE()
91# nrpe_compat.add_check(
92# shortname = "myservice",
93# description = "Check MyService",
94# check_cmd = "check_http -w 2 -c 10 http://localhost"
95# )
96# nrpe_compat.add_check(
97# "myservice_other",
98# "Check for widget failures",
99# check_cmd = "/srv/myapp/scripts/widget_check"
100# )
101# nrpe_compat.write()
102#
103# def config_changed():
104# (...)
105# update_nrpe_config()
106#
107# def nrpe_external_master_relation_changed():
108# update_nrpe_config()
109#
110# def local_monitors_relation_changed():
111# update_nrpe_config()
112#
113# 5. ln -s hooks.py nrpe-external-master-relation-changed
114# ln -s hooks.py local-monitors-relation-changed
115
116
117class CheckException(Exception):
118 pass
119
120
121class Check(object):
122 shortname_re = '[A-Za-z0-9-_]+$'
123 service_template = ("""
124#---------------------------------------------------
125# This file is Juju managed
126#---------------------------------------------------
127define service {{
128 use active-service
129 host_name {nagios_hostname}
130 service_description {nagios_hostname}[{shortname}] """
131 """{description}
132 check_command check_nrpe!{command}
133 servicegroups {nagios_servicegroup}
134}}
135""")
136
137 def __init__(self, shortname, description, check_cmd):
138 super(Check, self).__init__()
139 # XXX: could be better to calculate this from the service name
140 if not re.match(self.shortname_re, shortname):
141 raise CheckException("shortname must match {}".format(
142 Check.shortname_re))
143 self.shortname = shortname
144 self.command = "check_{}".format(shortname)
145 # Note: a set of invalid characters is defined by the
146 # Nagios server config
147 # The default is: illegal_object_name_chars=`~!$%^&*"|'<>?,()=
148 self.description = description
149 self.check_cmd = self._locate_cmd(check_cmd)
150
151 def _get_check_filename(self):
152 return os.path.join(NRPE.nrpe_confdir, '{}.cfg'.format(self.command))
153
154 def _get_service_filename(self, hostname):
155 return os.path.join(NRPE.nagios_exportdir,
156 'service__{}_{}.cfg'.format(hostname, self.command))
157
158 def _locate_cmd(self, check_cmd):
159 search_path = (
160 '/usr/lib/nagios/plugins',
161 '/usr/local/lib/nagios/plugins',
162 )
163 parts = shlex.split(check_cmd)
164 for path in search_path:
165 if os.path.exists(os.path.join(path, parts[0])):
166 command = os.path.join(path, parts[0])
167 if len(parts) > 1:
168 command += " " + " ".join(parts[1:])
169 return command
170 log('Check command not found: {}'.format(parts[0]))
171 return ''
172
173 def _remove_service_files(self):
174 if not os.path.exists(NRPE.nagios_exportdir):
175 return
176 for f in os.listdir(NRPE.nagios_exportdir):
177 if f.endswith('_{}.cfg'.format(self.command)):
178 os.remove(os.path.join(NRPE.nagios_exportdir, f))
179
180 def remove(self, hostname):
181 nrpe_check_file = self._get_check_filename()
182 if os.path.exists(nrpe_check_file):
183 os.remove(nrpe_check_file)
184 self._remove_service_files()
185
186 def write(self, nagios_context, hostname, nagios_servicegroups):
187 nrpe_check_file = self._get_check_filename()
188 with open(nrpe_check_file, 'w') as nrpe_check_config:
189 nrpe_check_config.write("# check {}\n".format(self.shortname))
190 nrpe_check_config.write("command[{}]={}\n".format(
191 self.command, self.check_cmd))
192
193 if not os.path.exists(NRPE.nagios_exportdir):
194 log('Not writing service config as {} is not accessible'.format(
195 NRPE.nagios_exportdir))
196 else:
197 self.write_service_config(nagios_context, hostname,
198 nagios_servicegroups)
199
200 def write_service_config(self, nagios_context, hostname,
201 nagios_servicegroups):
202 self._remove_service_files()
203
204 templ_vars = {
205 'nagios_hostname': hostname,
206 'nagios_servicegroup': nagios_servicegroups,
207 'description': self.description,
208 'shortname': self.shortname,
209 'command': self.command,
210 }
211 nrpe_service_text = Check.service_template.format(**templ_vars)
212 nrpe_service_file = self._get_service_filename(hostname)
213 with open(nrpe_service_file, 'w') as nrpe_service_config:
214 nrpe_service_config.write(str(nrpe_service_text))
215
216 def run(self):
217 subprocess.call(self.check_cmd)
218
219
220class NRPE(object):
221 nagios_logdir = '/var/log/nagios'
222 nagios_exportdir = '/var/lib/nagios/export'
223 nrpe_confdir = '/etc/nagios/nrpe.d'
224
225 def __init__(self, hostname=None):
226 super(NRPE, self).__init__()
227 self.config = config()
228 self.nagios_context = self.config['nagios_context']
229 if 'nagios_servicegroups' in self.config and self.config['nagios_servicegroups']:
230 self.nagios_servicegroups = self.config['nagios_servicegroups']
231 else:
232 self.nagios_servicegroups = self.nagios_context
233 self.unit_name = local_unit().replace('/', '-')
234 if hostname:
235 self.hostname = hostname
236 else:
237 nagios_hostname = get_nagios_hostname()
238 if nagios_hostname:
239 self.hostname = nagios_hostname
240 else:
241 self.hostname = "{}-{}".format(self.nagios_context, self.unit_name)
242 self.checks = []
243
244 def add_check(self, *args, **kwargs):
245 self.checks.append(Check(*args, **kwargs))
246
247 def remove_check(self, *args, **kwargs):
248 if kwargs.get('shortname') is None:
249 raise ValueError('shortname of check must be specified')
250
251 # Use sensible defaults if they're not specified - these are not
252 # actually used during removal, but they're required for constructing
253 # the Check object; check_disk is chosen because it's part of the
254 # nagios-plugins-basic package.
255 if kwargs.get('check_cmd') is None:
256 kwargs['check_cmd'] = 'check_disk'
257 if kwargs.get('description') is None:
258 kwargs['description'] = ''
259
260 check = Check(*args, **kwargs)
261 check.remove(self.hostname)
262
263 def write(self):
264 try:
265 nagios_uid = pwd.getpwnam('nagios').pw_uid
266 nagios_gid = grp.getgrnam('nagios').gr_gid
267 except:
268 log("Nagios user not set up, nrpe checks not updated")
269 return
270
271 if not os.path.exists(NRPE.nagios_logdir):
272 os.mkdir(NRPE.nagios_logdir)
273 os.chown(NRPE.nagios_logdir, nagios_uid, nagios_gid)
274
275 nrpe_monitors = {}
276 monitors = {"monitors": {"remote": {"nrpe": nrpe_monitors}}}
277 for nrpecheck in self.checks:
278 nrpecheck.write(self.nagios_context, self.hostname,
279 self.nagios_servicegroups)
280 nrpe_monitors[nrpecheck.shortname] = {
281 "command": nrpecheck.command,
282 }
283
284 service('restart', 'nagios-nrpe-server')
285
286 monitor_ids = relation_ids("local-monitors") + \
287 relation_ids("nrpe-external-master")
288 for rid in monitor_ids:
289 relation_set(relation_id=rid, monitors=yaml.dump(monitors))
290
291
292def get_nagios_hostcontext(relation_name='nrpe-external-master'):
293 """
294 Query relation with nrpe subordinate, return the nagios_host_context
295
296 :param str relation_name: Name of relation nrpe sub joined to
297 """
298 for rel in relations_of_type(relation_name):
299 if 'nagios_host_context' in rel:
300 return rel['nagios_host_context']
301
302
303def get_nagios_hostname(relation_name='nrpe-external-master'):
304 """
305 Query relation with nrpe subordinate, return the nagios_hostname
306
307 :param str relation_name: Name of relation nrpe sub joined to
308 """
309 for rel in relations_of_type(relation_name):
310 if 'nagios_hostname' in rel:
311 return rel['nagios_hostname']
312
313
314def get_nagios_unit_name(relation_name='nrpe-external-master'):
315 """
316 Return the nagios unit name prepended with host_context if needed
317
318 :param str relation_name: Name of relation nrpe sub joined to
319 """
320 host_context = get_nagios_hostcontext(relation_name)
321 if host_context:
322 unit = "%s:%s" % (host_context, local_unit())
323 else:
324 unit = local_unit()
325 return unit
326
327
328def add_init_service_checks(nrpe, services, unit_name):
329 """
330 Add checks for each service in list
331
332 :param NRPE nrpe: NRPE object to add check to
333 :param list services: List of services to check
334 :param str unit_name: Unit name to use in check description
335 """
336 for svc in services:
337 upstart_init = '/etc/init/%s.conf' % svc
338 sysv_init = '/etc/init.d/%s' % svc
339 if os.path.exists(upstart_init):
340 # Don't add a check for these services from neutron-gateway
341 if svc not in ['ext-port', 'os-charm-phy-nic-mtu']:
342 nrpe.add_check(
343 shortname=svc,
344 description='process check {%s}' % unit_name,
345 check_cmd='check_upstart_job %s' % svc
346 )
347 elif os.path.exists(sysv_init):
348 cronpath = '/etc/cron.d/nagios-service-check-%s' % svc
349 cron_file = ('*/5 * * * * root '
350 '/usr/local/lib/nagios/plugins/check_exit_status.pl '
351 '-s /etc/init.d/%s status > '
352 '/var/lib/nagios/service-check-%s.txt\n' % (svc,
353 svc)
354 )
355 f = open(cronpath, 'w')
356 f.write(cron_file)
357 f.close()
358 nrpe.add_check(
359 shortname=svc,
360 description='process check {%s}' % unit_name,
361 check_cmd='check_status_file.py -f '
362 '/var/lib/nagios/service-check-%s.txt' % svc,
363 )
364
365
366def copy_nrpe_checks():
367 """
368 Copy the nrpe checks into place
369
370 """
371 NAGIOS_PLUGINS = '/usr/local/lib/nagios/plugins'
372 nrpe_files_dir = os.path.join(os.getenv('CHARM_DIR'), 'hooks',
373 'charmhelpers', 'contrib', 'openstack',
374 'files')
375
376 if not os.path.exists(NAGIOS_PLUGINS):
377 os.makedirs(NAGIOS_PLUGINS)
378 for fname in glob.glob(os.path.join(nrpe_files_dir, "check_*")):
379 if os.path.isfile(fname):
380 shutil.copy2(fname,
381 os.path.join(NAGIOS_PLUGINS, os.path.basename(fname)))
382
383
384def add_haproxy_checks(nrpe, unit_name):
385 """
386 Add checks for each service in list
387
388 :param NRPE nrpe: NRPE object to add check to
389 :param str unit_name: Unit name to use in check description
390 """
391 nrpe.add_check(
392 shortname='haproxy_servers',
393 description='Check HAProxy {%s}' % unit_name,
394 check_cmd='check_haproxy.sh')
395 nrpe.add_check(
396 shortname='haproxy_queue',
397 description='Check HAProxy queue depth {%s}' % unit_name,
398 check_cmd='check_haproxy_queue_depth.sh')
0399
=== added file 'hooks/charmhelpers/contrib/charmsupport/volumes.py'
--- hooks/charmhelpers/contrib/charmsupport/volumes.py 1970-01-01 00:00:00 +0000
+++ hooks/charmhelpers/contrib/charmsupport/volumes.py 2016-05-20 17:02:41 +0000
@@ -0,0 +1,175 @@
1# Copyright 2014-2015 Canonical Limited.
2#
3# This file is part of charm-helpers.
4#
5# charm-helpers is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Lesser General Public License version 3 as
7# published by the Free Software Foundation.
8#
9# charm-helpers is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Lesser General Public License for more details.
13#
14# You should have received a copy of the GNU Lesser General Public License
15# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
16
17'''
18Functions for managing volumes in juju units. One volume is supported per unit.
19Subordinates may have their own storage, provided it is on its own partition.
20
21Configuration stanzas::
22
23 volume-ephemeral:
24 type: boolean
25 default: true
26 description: >
27 If false, a volume is mounted as sepecified in "volume-map"
28 If true, ephemeral storage will be used, meaning that log data
29 will only exist as long as the machine. YOU HAVE BEEN WARNED.
30 volume-map:
31 type: string
32 default: {}
33 description: >
34 YAML map of units to device names, e.g:
35 "{ rsyslog/0: /dev/vdb, rsyslog/1: /dev/vdb }"
36 Service units will raise a configure-error if volume-ephemeral
37 is 'true' and no volume-map value is set. Use 'juju set' to set a
38 value and 'juju resolved' to complete configuration.
39
40Usage::
41
42 from charmsupport.volumes import configure_volume, VolumeConfigurationError
43 from charmsupport.hookenv import log, ERROR
44 def post_mount_hook():
45 stop_service('myservice')
46 def post_mount_hook():
47 start_service('myservice')
48
49 if __name__ == '__main__':
50 try:
51 configure_volume(before_change=pre_mount_hook,
52 after_change=post_mount_hook)
53 except VolumeConfigurationError:
54 log('Storage could not be configured', ERROR)
55
56'''
57
58# XXX: Known limitations
59# - fstab is neither consulted nor updated
60
61import os
62from charmhelpers.core import hookenv
63from charmhelpers.core import host
64import yaml
65
66
67MOUNT_BASE = '/srv/juju/volumes'
68
69
70class VolumeConfigurationError(Exception):
71 '''Volume configuration data is missing or invalid'''
72 pass
73
74
75def get_config():
76 '''Gather and sanity-check volume configuration data'''
77 volume_config = {}
78 config = hookenv.config()
79
80 errors = False
81
82 if config.get('volume-ephemeral') in (True, 'True', 'true', 'Yes', 'yes'):
83 volume_config['ephemeral'] = True
84 else:
85 volume_config['ephemeral'] = False
86
87 try:
88 volume_map = yaml.safe_load(config.get('volume-map', '{}'))
89 except yaml.YAMLError as e:
90 hookenv.log("Error parsing YAML volume-map: {}".format(e),
91 hookenv.ERROR)
92 errors = True
93 if volume_map is None:
94 # probably an empty string
95 volume_map = {}
96 elif not isinstance(volume_map, dict):
97 hookenv.log("Volume-map should be a dictionary, not {}".format(
98 type(volume_map)))
99 errors = True
100
101 volume_config['device'] = volume_map.get(os.environ['JUJU_UNIT_NAME'])
102 if volume_config['device'] and volume_config['ephemeral']:
103 # asked for ephemeral storage but also defined a volume ID
104 hookenv.log('A volume is defined for this unit, but ephemeral '
105 'storage was requested', hookenv.ERROR)
106 errors = True
107 elif not volume_config['device'] and not volume_config['ephemeral']:
108 # asked for permanent storage but did not define volume ID
109 hookenv.log('Ephemeral storage was requested, but there is no volume '
110 'defined for this unit.', hookenv.ERROR)
111 errors = True
112
113 unit_mount_name = hookenv.local_unit().replace('/', '-')
114 volume_config['mountpoint'] = os.path.join(MOUNT_BASE, unit_mount_name)
115
116 if errors:
117 return None
118 return volume_config
119
120
121def mount_volume(config):
122 if os.path.exists(config['mountpoint']):
123 if not os.path.isdir(config['mountpoint']):
124 hookenv.log('Not a directory: {}'.format(config['mountpoint']))
125 raise VolumeConfigurationError()
126 else:
127 host.mkdir(config['mountpoint'])
128 if os.path.ismount(config['mountpoint']):
129 unmount_volume(config)
130 if not host.mount(config['device'], config['mountpoint'], persist=True):
131 raise VolumeConfigurationError()
132
133
134def unmount_volume(config):
135 if os.path.ismount(config['mountpoint']):
136 if not host.umount(config['mountpoint'], persist=True):
137 raise VolumeConfigurationError()
138
139
140def managed_mounts():
141 '''List of all mounted managed volumes'''
142 return filter(lambda mount: mount[0].startswith(MOUNT_BASE), host.mounts())
143
144
145def configure_volume(before_change=lambda: None, after_change=lambda: None):
146 '''Set up storage (or don't) according to the charm's volume configuration.
147 Returns the mount point or "ephemeral". before_change and after_change
148 are optional functions to be called if the volume configuration changes.
149 '''
150
151 config = get_config()
152 if not config:
153 hookenv.log('Failed to read volume configuration', hookenv.CRITICAL)
154 raise VolumeConfigurationError()
155
156 if config['ephemeral']:
157 if os.path.ismount(config['mountpoint']):
158 before_change()
159 unmount_volume(config)
160 after_change()
161 return 'ephemeral'
162 else:
163 # persistent storage
164 if os.path.ismount(config['mountpoint']):
165 mounts = dict(managed_mounts())
166 if mounts.get(config['mountpoint']) != config['device']:
167 before_change()
168 unmount_volume(config)
169 mount_volume(config)
170 after_change()
171 else:
172 before_change()
173 mount_volume(config)
174 after_change()
175 return config['mountpoint']
0176
=== modified file 'hooks/hooks.py'
--- hooks/hooks.py 2016-03-24 21:20:46 +0000
+++ hooks/hooks.py 2016-05-20 17:02:41 +0000
@@ -3,16 +3,11 @@
3import os3import os
4import sys4import sys
55
6_HERE = os.path.abspath(os.path.dirname(__file__))
7
8sys.path.insert(0, os.path.join(_HERE, 'charmhelpers'))
9
10from charmhelpers.core.host import (6from charmhelpers.core.host import (
11 service_start,7 service_start,
12 service_stop,8 service_stop,
13 service_restart,9 service_restart,
14)10)
15
16from charmhelpers.core.hookenv import (11from charmhelpers.core.hookenv import (
17 Hooks,12 Hooks,
18 close_port,13 close_port,
@@ -21,11 +16,12 @@
21 log as juju_log,16 log as juju_log,
22 charm_dir,17 charm_dir,
23)18)
2419from charmhelpers.contrib.charmsupport import nrpe
25from charmhelpers.fetch import (20from charmhelpers.fetch import (
26 apt_install21 apt_install
27)22)
2823
24
29DEFAULT_RSYSLOG_PORT = 51425DEFAULT_RSYSLOG_PORT = 514
30DEFAULT_RELP_PORT = 251426DEFAULT_RELP_PORT = 2514
31DEFAULT_RSYSLOG_PATH = os.path.join(os.path.sep, 'etc', 'rsyslog.d')27DEFAULT_RSYSLOG_PATH = os.path.join(os.path.sep, 'etc', 'rsyslog.d')
@@ -120,6 +116,18 @@
120 logrotate_config.write(template.render(**params))116 logrotate_config.write(template.render(**params))
121117
122118
119@hooks.hook("nrpe-external-master-relation-changed")
120@hooks.hook("local-monitors-relation-changed")
121def update_nrpe_config():
122 nrpe_compat = nrpe.NRPE()
123 nrpe_compat.add_check(
124 shortname="rsyslog",
125 description="Check rsyslog is running",
126 check_cmd="check_procs -c 1: -C rsyslogd"
127 )
128 nrpe_compat.write()
129
130
123def update_rsyslog_config(template_name, **params):131def update_rsyslog_config(template_name, **params):
124 template = get_config_template(template_name)132 template = get_config_template(template_name)
125133
@@ -142,5 +150,7 @@
142 # configuration changed, restart rsyslog150 # configuration changed, restart rsyslog
143 service_restart("rsyslog")151 service_restart("rsyslog")
144152
153 update_nrpe_config()
154
145if __name__ == "__main__":155if __name__ == "__main__":
146 hooks.execute(sys.argv)156 hooks.execute(sys.argv)
147157
=== added symlink 'hooks/nrpe-external-master-relation-changed'
=== target is u'hooks.py'
=== modified file 'metadata.yaml'
--- metadata.yaml 2014-09-04 20:51:59 +0000
+++ metadata.yaml 2016-05-20 17:02:41 +0000
@@ -23,3 +23,6 @@
23provides:23provides:
24 aggregator:24 aggregator:
25 interface: syslog25 interface: syslog
26 nrpe-external-master:
27 interface: nrpe-external-master
28 scope: container
2629
=== modified file 'unit_tests/test_hooks.py'
--- unit_tests/test_hooks.py 2016-03-28 16:16:07 +0000
+++ unit_tests/test_hooks.py 2016-05-20 17:02:41 +0000
@@ -25,7 +25,8 @@
25 "close_port",25 "close_port",
26 "juju_log",26 "juju_log",
27 "charm_dir",27 "charm_dir",
28 "config_get"28 "config_get",
29 "nrpe"
29]30]
3031
3132

Subscribers

People subscribed via source and target branches