Merge lp:~brad-marshall/charms/trusty/ceilometer-agent/add-nrpe-checks into lp:~openstack-charmers-archive/charms/trusty/ceilometer-agent/trunk
- Trusty Tahr (14.04)
- add-nrpe-checks
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 46 | ||||
Proposed branch: | lp:~brad-marshall/charms/trusty/ceilometer-agent/add-nrpe-checks | ||||
Merge into: | lp:~openstack-charmers-archive/charms/trusty/ceilometer-agent/trunk | ||||
Diff against target: |
560 lines (+459/-1) 7 files modified
charm-helpers.yaml (+1/-0) config.yaml (+10/-0) hooks/ceilometer_hooks.py (+59/-1) hooks/ceilometer_utils.py (+8/-0) hooks/charmhelpers/contrib/charmsupport/nrpe.py (+222/-0) hooks/charmhelpers/contrib/charmsupport/volumes.py (+156/-0) metadata.yaml (+3/-0) |
||||
To merge this branch: | bzr merge lp:~brad-marshall/charms/trusty/ceilometer-agent/add-nrpe-checks | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Liam Young (community) | Disapprove | ||
Billy Olsen | Needs Fixing | ||
Review via email:
|
Commit message
Description of the change
Add nagios checks to ceilometer-agent, similar to the others I've done.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
uosci-testing-bot (uosci-testing-bot) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
uosci-testing-bot (uosci-testing-bot) wrote : | # |
UOSCI bot says:
charm_unit_test #956 trusty-
UNIT FAIL: unit-test failed
UNIT Results (max last 5 lines):
hooks/
TOTAL 126 33 74%
Ran 11 tests in 0.132s
FAILED (errors=3)
make: *** [test] Error 1
Full unit test output: http://
Build: http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
uosci-testing-bot (uosci-testing-bot) wrote : | # |
UOSCI bot says:
charm_amulet_test #464 trusty-
AMULET FAIL: amulet-test missing
AMULET Results (max last 5 lines):
INFO:root:Workspace dir: /var/lib/
INFO:root:Reading file: Makefile
INFO:root:Searching for: ['@juju test']
INFO:root:Search string not found in makefile target commands.
ERROR:root:No make target was executed.
Full amulet test output: http://
Build: http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
uosci-testing-bot (uosci-testing-bot) wrote : | # |
UOSCI bot says:
charm_lint_check #1246 trusty-
LINT OK: passed
LINT Results (max last 5 lines):
INFO:root:Reading file: Makefile
INFO:root:Searching for: ['@flake8']
INFO:root:command: make -f Makefile lint
W: metadata name (ceilometer-agent) must match directory name (trusty-
I: Categories are being deprecated in favor of tags. Please rename the "categories" field to "tags".
Full lint test output: http://
Build: http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
uosci-testing-bot (uosci-testing-bot) wrote : | # |
UOSCI bot says:
charm_unit_test #1080 trusty-
UNIT FAIL: unit-test failed
UNIT Results (max last 5 lines):
hooks/
TOTAL 126 33 74%
Ran 11 tests in 0.105s
FAILED (errors=3)
make: *** [test] Error 1
Full unit test output: http://
Build: http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
uosci-testing-bot (uosci-testing-bot) wrote : | # |
UOSCI bot says:
charm_amulet_test #549 trusty-
AMULET FAIL: amulet-test missing
AMULET Results (max last 5 lines):
INFO:root:Workspace dir: /var/lib/
INFO:root:Reading file: Makefile
INFO:root:Searching for: ['@juju test']
INFO:root:Search string not found in makefile target commands.
ERROR:root:No make target was executed.
Full amulet test output: http://
Build: http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Billy Olsen (billy-olsen) wrote : | # |
Hey Brad, thanks for the submission!
I know this is similar to the NRPE code submissions for other charms, however a few comments.
- Please fix the unit tests as they are failing
- Additionally, new code has 0 unit test coverage
I'm not overly familiar with how the NRPE stuff works, but HA support is being added to the ceilometer charm which one of the services (ceilometer-
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Billy Olsen (billy-olsen) wrote : | # |
My mistake - this is on the ceilometer-agent, which doesn't have high availability - that's going into the ceilometer charm itself.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Liam Young (gnuoy) wrote : | # |
This branch is now superseded as I've taken the branch and updated it in light of the additional nrpe support that has been added to charm-helper. nrpe support has now landed in the devel charm and will be moved to stable this week
Preview Diff
1 | === modified file 'charm-helpers.yaml' |
2 | --- charm-helpers.yaml 2014-08-13 13:43:25 +0000 |
3 | +++ charm-helpers.yaml 2014-11-18 05:52:38 +0000 |
4 | @@ -7,3 +7,4 @@ |
5 | - contrib.hahelpers |
6 | - contrib.storage.linux |
7 | - contrib.network.ip |
8 | + - contrib.charmsupport |
9 | |
10 | === modified file 'config.yaml' |
11 | --- config.yaml 2014-03-31 13:51:46 +0000 |
12 | +++ config.yaml 2014-11-18 05:52:38 +0000 |
13 | @@ -14,3 +14,13 @@ |
14 | Note that updating this setting to a source that is known to |
15 | provide a later version of OpenStack will trigger a software |
16 | upgrade. |
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 | |
28 | === modified file 'hooks/ceilometer_hooks.py' |
29 | --- hooks/ceilometer_hooks.py 2014-04-01 16:53:45 +0000 |
30 | +++ hooks/ceilometer_hooks.py 2014-11-18 05:52:38 +0000 |
31 | @@ -1,6 +1,7 @@ |
32 | #!/usr/bin/python |
33 | |
34 | import sys |
35 | +import os |
36 | import json |
37 | from charmhelpers.fetch import ( |
38 | apt_install, filter_installed_packages, |
39 | @@ -10,7 +11,9 @@ |
40 | config, |
41 | Hooks, UnregisteredHookError, |
42 | log, |
43 | - relation_set |
44 | + local_unit, |
45 | + relation_set, |
46 | + relations_of_type, |
47 | ) |
48 | from charmhelpers.core.host import ( |
49 | restart_on_change, |
50 | @@ -22,12 +25,15 @@ |
51 | ) |
52 | from ceilometer_utils import ( |
53 | restart_map, |
54 | + services, |
55 | register_configs, |
56 | CEILOMETER_AGENT_PACKAGES, |
57 | NOVA_SETTINGS, |
58 | do_openstack_upgrade |
59 | ) |
60 | |
61 | +from charmhelpers.contrib.charmsupport.nrpe import NRPE |
62 | + |
63 | hooks = Hooks() |
64 | CONFIGS = register_configs() |
65 | |
66 | @@ -55,6 +61,7 @@ |
67 | @restart_on_change(restart_map()) |
68 | def ceilometer_changed(): |
69 | CONFIGS.write_all() |
70 | + update_nrpe_config() |
71 | |
72 | |
73 | @hooks.hook('config-changed') |
74 | @@ -62,8 +69,59 @@ |
75 | def config_changed(): |
76 | if openstack_upgrade_available('ceilometer-common'): |
77 | do_openstack_upgrade(CONFIGS) |
78 | + update_nrpe_config() |
79 | CONFIGS.write_all() |
80 | |
81 | + |
82 | +@hooks.hook('nrpe-external-master-relation-joined', |
83 | + 'nrpe-external-master-relation-changed') |
84 | +def update_nrpe_config(): |
85 | + # Find out if nrpe set nagios_hostname |
86 | + hostname = None |
87 | + host_context = None |
88 | + for rel in relations_of_type('nrpe-external-master'): |
89 | + if 'nagios_hostname' in rel: |
90 | + hostname = rel['nagios_hostname'] |
91 | + host_context = rel['nagios_host_context'] |
92 | + break |
93 | + nrpe = NRPE(hostname=hostname) |
94 | + apt_install('python-dbus') |
95 | + |
96 | + if host_context: |
97 | + current_unit = "%s:%s" % (host_context, local_unit()) |
98 | + else: |
99 | + current_unit = local_unit() |
100 | + |
101 | + services_to_monitor = services() |
102 | + |
103 | + for service in services_to_monitor: |
104 | + upstart_init = '/etc/init/%s.conf' % service |
105 | + sysv_init = '/etc/init.d/%s' % service |
106 | + |
107 | + if os.path.exists(upstart_init): |
108 | + nrpe.add_check( |
109 | + shortname=service, |
110 | + description='process check {%s}' % current_unit, |
111 | + check_cmd='check_upstart_job %s' % service, |
112 | + ) |
113 | + elif os.path.exists(sysv_init): |
114 | + cronpath = '/etc/cron.d/nagios-service-check-%s' % service |
115 | + cron_template = '*/5 * * * * root \ |
116 | +/usr/local/lib/nagios/plugins/check_exit_status.pl -s /etc/init.d/%s \ |
117 | +status > /var/lib/nagios/service-check-%s.txt\n' % (service, service) |
118 | + f = open(cronpath, 'w') |
119 | + f.write(cron_template) |
120 | + f.close() |
121 | + nrpe.add_check( |
122 | + shortname=service, |
123 | + description='process check {%s}' % current_unit, |
124 | + check_cmd='check_status_file.py -f \ |
125 | + /var/lib/nagios/service-check-%s.txt' % service, |
126 | + ) |
127 | + |
128 | + nrpe.write() |
129 | + |
130 | + |
131 | if __name__ == '__main__': |
132 | try: |
133 | hooks.execute(sys.argv) |
134 | |
135 | === modified file 'hooks/ceilometer_utils.py' |
136 | --- hooks/ceilometer_utils.py 2014-04-01 16:53:45 +0000 |
137 | +++ hooks/ceilometer_utils.py 2014-11-18 05:52:38 +0000 |
138 | @@ -94,6 +94,14 @@ |
139 | return _map |
140 | |
141 | |
142 | +def services(): |
143 | + ''' Returns a list of services associate with this charm ''' |
144 | + _services = [] |
145 | + for v in restart_map().values(): |
146 | + _services = _services + v |
147 | + return list(set(_services)) |
148 | + |
149 | + |
150 | def do_openstack_upgrade(configs): |
151 | """ |
152 | Perform an upgrade. Takes care of upgrading packages, rewriting |
153 | |
154 | === added directory 'hooks/charmhelpers/contrib/charmsupport' |
155 | === added file 'hooks/charmhelpers/contrib/charmsupport/__init__.py' |
156 | === added file 'hooks/charmhelpers/contrib/charmsupport/nrpe.py' |
157 | --- hooks/charmhelpers/contrib/charmsupport/nrpe.py 1970-01-01 00:00:00 +0000 |
158 | +++ hooks/charmhelpers/contrib/charmsupport/nrpe.py 2014-11-18 05:52:38 +0000 |
159 | @@ -0,0 +1,222 @@ |
160 | +"""Compatibility with the nrpe-external-master charm""" |
161 | +# Copyright 2012 Canonical Ltd. |
162 | +# |
163 | +# Authors: |
164 | +# Matthew Wedgwood <matthew.wedgwood@canonical.com> |
165 | + |
166 | +import subprocess |
167 | +import pwd |
168 | +import grp |
169 | +import os |
170 | +import re |
171 | +import shlex |
172 | +import yaml |
173 | + |
174 | +from charmhelpers.core.hookenv import ( |
175 | + config, |
176 | + local_unit, |
177 | + log, |
178 | + relation_ids, |
179 | + relation_set, |
180 | +) |
181 | + |
182 | +from charmhelpers.core.host import service |
183 | + |
184 | +# This module adds compatibility with the nrpe-external-master and plain nrpe |
185 | +# subordinate charms. To use it in your charm: |
186 | +# |
187 | +# 1. Update metadata.yaml |
188 | +# |
189 | +# provides: |
190 | +# (...) |
191 | +# nrpe-external-master: |
192 | +# interface: nrpe-external-master |
193 | +# scope: container |
194 | +# |
195 | +# and/or |
196 | +# |
197 | +# provides: |
198 | +# (...) |
199 | +# local-monitors: |
200 | +# interface: local-monitors |
201 | +# scope: container |
202 | + |
203 | +# |
204 | +# 2. Add the following to config.yaml |
205 | +# |
206 | +# nagios_context: |
207 | +# default: "juju" |
208 | +# type: string |
209 | +# description: | |
210 | +# Used by the nrpe subordinate charms. |
211 | +# A string that will be prepended to instance name to set the host name |
212 | +# in nagios. So for instance the hostname would be something like: |
213 | +# juju-myservice-0 |
214 | +# If you're running multiple environments with the same services in them |
215 | +# this allows you to differentiate between them. |
216 | +# |
217 | +# 3. Add custom checks (Nagios plugins) to files/nrpe-external-master |
218 | +# |
219 | +# 4. Update your hooks.py with something like this: |
220 | +# |
221 | +# from charmsupport.nrpe import NRPE |
222 | +# (...) |
223 | +# def update_nrpe_config(): |
224 | +# nrpe_compat = NRPE() |
225 | +# nrpe_compat.add_check( |
226 | +# shortname = "myservice", |
227 | +# description = "Check MyService", |
228 | +# check_cmd = "check_http -w 2 -c 10 http://localhost" |
229 | +# ) |
230 | +# nrpe_compat.add_check( |
231 | +# "myservice_other", |
232 | +# "Check for widget failures", |
233 | +# check_cmd = "/srv/myapp/scripts/widget_check" |
234 | +# ) |
235 | +# nrpe_compat.write() |
236 | +# |
237 | +# def config_changed(): |
238 | +# (...) |
239 | +# update_nrpe_config() |
240 | +# |
241 | +# def nrpe_external_master_relation_changed(): |
242 | +# update_nrpe_config() |
243 | +# |
244 | +# def local_monitors_relation_changed(): |
245 | +# update_nrpe_config() |
246 | +# |
247 | +# 5. ln -s hooks.py nrpe-external-master-relation-changed |
248 | +# ln -s hooks.py local-monitors-relation-changed |
249 | + |
250 | + |
251 | +class CheckException(Exception): |
252 | + pass |
253 | + |
254 | + |
255 | +class Check(object): |
256 | + shortname_re = '[A-Za-z0-9-_]+$' |
257 | + service_template = (""" |
258 | +#--------------------------------------------------- |
259 | +# This file is Juju managed |
260 | +#--------------------------------------------------- |
261 | +define service {{ |
262 | + use active-service |
263 | + host_name {nagios_hostname} |
264 | + service_description {nagios_hostname}[{shortname}] """ |
265 | + """{description} |
266 | + check_command check_nrpe!{command} |
267 | + servicegroups {nagios_servicegroup} |
268 | +}} |
269 | +""") |
270 | + |
271 | + def __init__(self, shortname, description, check_cmd): |
272 | + super(Check, self).__init__() |
273 | + # XXX: could be better to calculate this from the service name |
274 | + if not re.match(self.shortname_re, shortname): |
275 | + raise CheckException("shortname must match {}".format( |
276 | + Check.shortname_re)) |
277 | + self.shortname = shortname |
278 | + self.command = "check_{}".format(shortname) |
279 | + # Note: a set of invalid characters is defined by the |
280 | + # Nagios server config |
281 | + # The default is: illegal_object_name_chars=`~!$%^&*"|'<>?,()= |
282 | + self.description = description |
283 | + self.check_cmd = self._locate_cmd(check_cmd) |
284 | + |
285 | + def _locate_cmd(self, check_cmd): |
286 | + search_path = ( |
287 | + '/', |
288 | + os.path.join(os.environ['CHARM_DIR'], |
289 | + 'files/nrpe-external-master'), |
290 | + '/usr/lib/nagios/plugins', |
291 | + '/usr/local/lib/nagios/plugins', |
292 | + ) |
293 | + parts = shlex.split(check_cmd) |
294 | + for path in search_path: |
295 | + if os.path.exists(os.path.join(path, parts[0])): |
296 | + command = os.path.join(path, parts[0]) |
297 | + if len(parts) > 1: |
298 | + command += " " + " ".join(parts[1:]) |
299 | + return command |
300 | + log('Check command not found: {}'.format(parts[0])) |
301 | + return '' |
302 | + |
303 | + def write(self, nagios_context, hostname): |
304 | + nrpe_check_file = '/etc/nagios/nrpe.d/{}.cfg'.format( |
305 | + self.command) |
306 | + with open(nrpe_check_file, 'w') as nrpe_check_config: |
307 | + nrpe_check_config.write("# check {}\n".format(self.shortname)) |
308 | + nrpe_check_config.write("command[{}]={}\n".format( |
309 | + self.command, self.check_cmd)) |
310 | + |
311 | + if not os.path.exists(NRPE.nagios_exportdir): |
312 | + log('Not writing service config as {} is not accessible'.format( |
313 | + NRPE.nagios_exportdir)) |
314 | + else: |
315 | + self.write_service_config(nagios_context, hostname) |
316 | + |
317 | + def write_service_config(self, nagios_context, hostname): |
318 | + for f in os.listdir(NRPE.nagios_exportdir): |
319 | + if re.search('.*{}.cfg'.format(self.command), f): |
320 | + os.remove(os.path.join(NRPE.nagios_exportdir, f)) |
321 | + |
322 | + templ_vars = { |
323 | + 'nagios_hostname': hostname, |
324 | + 'nagios_servicegroup': nagios_context, |
325 | + 'description': self.description, |
326 | + 'shortname': self.shortname, |
327 | + 'command': self.command, |
328 | + } |
329 | + nrpe_service_text = Check.service_template.format(**templ_vars) |
330 | + nrpe_service_file = '{}/service__{}_{}.cfg'.format( |
331 | + NRPE.nagios_exportdir, hostname, self.command) |
332 | + with open(nrpe_service_file, 'w') as nrpe_service_config: |
333 | + nrpe_service_config.write(str(nrpe_service_text)) |
334 | + |
335 | + def run(self): |
336 | + subprocess.call(self.check_cmd) |
337 | + |
338 | + |
339 | +class NRPE(object): |
340 | + nagios_logdir = '/var/log/nagios' |
341 | + nagios_exportdir = '/var/lib/nagios/export' |
342 | + nrpe_confdir = '/etc/nagios/nrpe.d' |
343 | + |
344 | + def __init__(self, hostname=None): |
345 | + super(NRPE, self).__init__() |
346 | + self.config = config() |
347 | + self.nagios_context = self.config['nagios_context'] |
348 | + self.unit_name = local_unit().replace('/', '-') |
349 | + if hostname: |
350 | + self.hostname = hostname |
351 | + else: |
352 | + self.hostname = "{}-{}".format(self.nagios_context, self.unit_name) |
353 | + self.checks = [] |
354 | + |
355 | + def add_check(self, *args, **kwargs): |
356 | + self.checks.append(Check(*args, **kwargs)) |
357 | + |
358 | + def write(self): |
359 | + try: |
360 | + nagios_uid = pwd.getpwnam('nagios').pw_uid |
361 | + nagios_gid = grp.getgrnam('nagios').gr_gid |
362 | + except: |
363 | + log("Nagios user not set up, nrpe checks not updated") |
364 | + return |
365 | + |
366 | + if not os.path.exists(NRPE.nagios_logdir): |
367 | + os.mkdir(NRPE.nagios_logdir) |
368 | + os.chown(NRPE.nagios_logdir, nagios_uid, nagios_gid) |
369 | + |
370 | + nrpe_monitors = {} |
371 | + monitors = {"monitors": {"remote": {"nrpe": nrpe_monitors}}} |
372 | + for nrpecheck in self.checks: |
373 | + nrpecheck.write(self.nagios_context, self.hostname) |
374 | + nrpe_monitors[nrpecheck.shortname] = { |
375 | + "command": nrpecheck.command, |
376 | + } |
377 | + |
378 | + service('restart', 'nagios-nrpe-server') |
379 | + |
380 | + for rid in relation_ids("local-monitors"): |
381 | + relation_set(relation_id=rid, monitors=yaml.dump(monitors)) |
382 | |
383 | === added file 'hooks/charmhelpers/contrib/charmsupport/volumes.py' |
384 | --- hooks/charmhelpers/contrib/charmsupport/volumes.py 1970-01-01 00:00:00 +0000 |
385 | +++ hooks/charmhelpers/contrib/charmsupport/volumes.py 2014-11-18 05:52:38 +0000 |
386 | @@ -0,0 +1,156 @@ |
387 | +''' |
388 | +Functions for managing volumes in juju units. One volume is supported per unit. |
389 | +Subordinates may have their own storage, provided it is on its own partition. |
390 | + |
391 | +Configuration stanzas: |
392 | + volume-ephemeral: |
393 | + type: boolean |
394 | + default: true |
395 | + description: > |
396 | + If false, a volume is mounted as sepecified in "volume-map" |
397 | + If true, ephemeral storage will be used, meaning that log data |
398 | + will only exist as long as the machine. YOU HAVE BEEN WARNED. |
399 | + volume-map: |
400 | + type: string |
401 | + default: {} |
402 | + description: > |
403 | + YAML map of units to device names, e.g: |
404 | + "{ rsyslog/0: /dev/vdb, rsyslog/1: /dev/vdb }" |
405 | + Service units will raise a configure-error if volume-ephemeral |
406 | + is 'true' and no volume-map value is set. Use 'juju set' to set a |
407 | + value and 'juju resolved' to complete configuration. |
408 | + |
409 | +Usage: |
410 | + from charmsupport.volumes import configure_volume, VolumeConfigurationError |
411 | + from charmsupport.hookenv import log, ERROR |
412 | + def post_mount_hook(): |
413 | + stop_service('myservice') |
414 | + def post_mount_hook(): |
415 | + start_service('myservice') |
416 | + |
417 | + if __name__ == '__main__': |
418 | + try: |
419 | + configure_volume(before_change=pre_mount_hook, |
420 | + after_change=post_mount_hook) |
421 | + except VolumeConfigurationError: |
422 | + log('Storage could not be configured', ERROR) |
423 | +''' |
424 | + |
425 | +# XXX: Known limitations |
426 | +# - fstab is neither consulted nor updated |
427 | + |
428 | +import os |
429 | +from charmhelpers.core import hookenv |
430 | +from charmhelpers.core import host |
431 | +import yaml |
432 | + |
433 | + |
434 | +MOUNT_BASE = '/srv/juju/volumes' |
435 | + |
436 | + |
437 | +class VolumeConfigurationError(Exception): |
438 | + '''Volume configuration data is missing or invalid''' |
439 | + pass |
440 | + |
441 | + |
442 | +def get_config(): |
443 | + '''Gather and sanity-check volume configuration data''' |
444 | + volume_config = {} |
445 | + config = hookenv.config() |
446 | + |
447 | + errors = False |
448 | + |
449 | + if config.get('volume-ephemeral') in (True, 'True', 'true', 'Yes', 'yes'): |
450 | + volume_config['ephemeral'] = True |
451 | + else: |
452 | + volume_config['ephemeral'] = False |
453 | + |
454 | + try: |
455 | + volume_map = yaml.safe_load(config.get('volume-map', '{}')) |
456 | + except yaml.YAMLError as e: |
457 | + hookenv.log("Error parsing YAML volume-map: {}".format(e), |
458 | + hookenv.ERROR) |
459 | + errors = True |
460 | + if volume_map is None: |
461 | + # probably an empty string |
462 | + volume_map = {} |
463 | + elif not isinstance(volume_map, dict): |
464 | + hookenv.log("Volume-map should be a dictionary, not {}".format( |
465 | + type(volume_map))) |
466 | + errors = True |
467 | + |
468 | + volume_config['device'] = volume_map.get(os.environ['JUJU_UNIT_NAME']) |
469 | + if volume_config['device'] and volume_config['ephemeral']: |
470 | + # asked for ephemeral storage but also defined a volume ID |
471 | + hookenv.log('A volume is defined for this unit, but ephemeral ' |
472 | + 'storage was requested', hookenv.ERROR) |
473 | + errors = True |
474 | + elif not volume_config['device'] and not volume_config['ephemeral']: |
475 | + # asked for permanent storage but did not define volume ID |
476 | + hookenv.log('Ephemeral storage was requested, but there is no volume ' |
477 | + 'defined for this unit.', hookenv.ERROR) |
478 | + errors = True |
479 | + |
480 | + unit_mount_name = hookenv.local_unit().replace('/', '-') |
481 | + volume_config['mountpoint'] = os.path.join(MOUNT_BASE, unit_mount_name) |
482 | + |
483 | + if errors: |
484 | + return None |
485 | + return volume_config |
486 | + |
487 | + |
488 | +def mount_volume(config): |
489 | + if os.path.exists(config['mountpoint']): |
490 | + if not os.path.isdir(config['mountpoint']): |
491 | + hookenv.log('Not a directory: {}'.format(config['mountpoint'])) |
492 | + raise VolumeConfigurationError() |
493 | + else: |
494 | + host.mkdir(config['mountpoint']) |
495 | + if os.path.ismount(config['mountpoint']): |
496 | + unmount_volume(config) |
497 | + if not host.mount(config['device'], config['mountpoint'], persist=True): |
498 | + raise VolumeConfigurationError() |
499 | + |
500 | + |
501 | +def unmount_volume(config): |
502 | + if os.path.ismount(config['mountpoint']): |
503 | + if not host.umount(config['mountpoint'], persist=True): |
504 | + raise VolumeConfigurationError() |
505 | + |
506 | + |
507 | +def managed_mounts(): |
508 | + '''List of all mounted managed volumes''' |
509 | + return filter(lambda mount: mount[0].startswith(MOUNT_BASE), host.mounts()) |
510 | + |
511 | + |
512 | +def configure_volume(before_change=lambda: None, after_change=lambda: None): |
513 | + '''Set up storage (or don't) according to the charm's volume configuration. |
514 | + Returns the mount point or "ephemeral". before_change and after_change |
515 | + are optional functions to be called if the volume configuration changes. |
516 | + ''' |
517 | + |
518 | + config = get_config() |
519 | + if not config: |
520 | + hookenv.log('Failed to read volume configuration', hookenv.CRITICAL) |
521 | + raise VolumeConfigurationError() |
522 | + |
523 | + if config['ephemeral']: |
524 | + if os.path.ismount(config['mountpoint']): |
525 | + before_change() |
526 | + unmount_volume(config) |
527 | + after_change() |
528 | + return 'ephemeral' |
529 | + else: |
530 | + # persistent storage |
531 | + if os.path.ismount(config['mountpoint']): |
532 | + mounts = dict(managed_mounts()) |
533 | + if mounts.get(config['mountpoint']) != config['device']: |
534 | + before_change() |
535 | + unmount_volume(config) |
536 | + mount_volume(config) |
537 | + after_change() |
538 | + else: |
539 | + before_change() |
540 | + mount_volume(config) |
541 | + after_change() |
542 | + return config['mountpoint'] |
543 | |
544 | === added symlink 'hooks/nrpe-external-master-relation-changed' |
545 | === target is u'ceilometer_hooks.py' |
546 | === added symlink 'hooks/nrpe-external-master-relation-joined' |
547 | === target is u'ceilometer_hooks.py' |
548 | === modified file 'metadata.yaml' |
549 | --- metadata.yaml 2013-11-29 15:34:44 +0000 |
550 | +++ metadata.yaml 2014-11-18 05:52:38 +0000 |
551 | @@ -15,6 +15,9 @@ |
552 | - miscellaneous |
553 | - openstack |
554 | provides: |
555 | + nrpe-external-master: |
556 | + interface: nrpe-external-master |
557 | + scope: container |
558 | nova-ceilometer: |
559 | interface: nova-ceilometer |
560 | scope: container |
UOSCI bot says: ceilometer- agent for brad-marshall mp242041
charm_lint_check #1122 trusty-
LINT OK: passed
LINT Results (max last 5 lines): jenkins/ workspace/ charm_lint_ check ceilometer- agent) exactly for local deployment.
INFO:root:Workspace dir: /var/lib/
INFO:root:Reading file: Makefile
INFO:root:Searching for: ['@flake8']
INFO:root:command: make -f Makefile lint
W: metadata name (ceilometer-agent) must match directory name (trusty-
Full lint test output: http:// paste.ubuntu. com/9066692/ 10.98.191. 181:8080/ job/charm_ lint_check/ 1122/
Build: http://