Merge lp:~gnuoy/charms/trusty/nova-compute/add-nrpe-checks into lp:~openstack-charmers-archive/charms/trusty/nova-compute/next
- Trusty Tahr (14.04)
- add-nrpe-checks
- Merge into next
Proposed by
Liam Young
Status: | Merged |
---|---|
Merged at revision: | 97 |
Proposed branch: | lp:~gnuoy/charms/trusty/nova-compute/add-nrpe-checks |
Merge into: | lp:~openstack-charmers-archive/charms/trusty/nova-compute/next |
Diff against target: |
846 lines (+596/-19) 14 files modified
charm-helpers-hooks.yaml (+1/-0) hooks/charmhelpers/contrib/charmsupport/nrpe.py (+308/-0) hooks/charmhelpers/contrib/charmsupport/volumes.py (+159/-0) hooks/charmhelpers/contrib/hahelpers/cluster.py (+26/-12) hooks/charmhelpers/contrib/network/ufw.py (+11/-0) hooks/charmhelpers/contrib/openstack/context.py (+1/-0) hooks/charmhelpers/contrib/openstack/neutron.py (+8/-2) hooks/charmhelpers/contrib/openstack/templates/haproxy.cfg (+2/-0) hooks/charmhelpers/contrib/openstack/utils.py (+6/-0) hooks/charmhelpers/core/decorators.py (+41/-0) hooks/charmhelpers/core/host.py (+7/-4) hooks/charmhelpers/fetch/__init__.py (+8/-1) hooks/nova_compute_hooks.py (+17/-0) unit_tests/test_nova_compute_hooks.py (+1/-0) |
To merge this branch: | bzr merge lp:~gnuoy/charms/trusty/nova-compute/add-nrpe-checks |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Liam Young (community) | Approve | ||
Review via email: mp+246158@code.launchpad.net |
Commit message
Description of the change
Add nrpe support. Based on branch from bradm with a few tweaks
To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : | # |
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #696 nova-compute-next for gnuoy mp246158
UNIT OK: passed
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #852 nova-compute-next for gnuoy mp246158
AMULET OK: passed
Revision history for this message
Liam Young (gnuoy) wrote : | # |
<jamespage> gnuoy, as they are re-syncs + tweaks to the nrpe stuff in the charms, I'm happy to give a conditional +1 across the board based on osci checking things out OK
<gnuoy> jamespage, I'll take that! thanks
...
<gnuoy> jamespage, osci is still working through. But on the subject of those mps, does your +1 stand for branches with no amulet tests?
<jamespage> gnuoy, yes
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'charm-helpers-hooks.yaml' | |||
2 | --- charm-helpers-hooks.yaml 2014-12-11 14:51:25 +0000 | |||
3 | +++ charm-helpers-hooks.yaml 2015-01-12 14:02:09 +0000 | |||
4 | @@ -11,3 +11,4 @@ | |||
5 | 11 | - contrib.network | 11 | - contrib.network |
6 | 12 | - contrib.python.packages | 12 | - contrib.python.packages |
7 | 13 | - payload.execd | 13 | - payload.execd |
8 | 14 | - contrib.charmsupport | ||
9 | 14 | 15 | ||
10 | === added directory 'files' | |||
11 | === added directory 'hooks/charmhelpers/contrib/charmsupport' | |||
12 | === added file 'hooks/charmhelpers/contrib/charmsupport/__init__.py' | |||
13 | === added file 'hooks/charmhelpers/contrib/charmsupport/nrpe.py' | |||
14 | --- hooks/charmhelpers/contrib/charmsupport/nrpe.py 1970-01-01 00:00:00 +0000 | |||
15 | +++ hooks/charmhelpers/contrib/charmsupport/nrpe.py 2015-01-12 14:02:09 +0000 | |||
16 | @@ -0,0 +1,308 @@ | |||
17 | 1 | """Compatibility with the nrpe-external-master charm""" | ||
18 | 2 | # Copyright 2012 Canonical Ltd. | ||
19 | 3 | # | ||
20 | 4 | # Authors: | ||
21 | 5 | # Matthew Wedgwood <matthew.wedgwood@canonical.com> | ||
22 | 6 | |||
23 | 7 | import subprocess | ||
24 | 8 | import pwd | ||
25 | 9 | import grp | ||
26 | 10 | import os | ||
27 | 11 | import re | ||
28 | 12 | import shlex | ||
29 | 13 | import yaml | ||
30 | 14 | |||
31 | 15 | from charmhelpers.core.hookenv import ( | ||
32 | 16 | config, | ||
33 | 17 | local_unit, | ||
34 | 18 | log, | ||
35 | 19 | relation_ids, | ||
36 | 20 | relation_set, | ||
37 | 21 | relations_of_type, | ||
38 | 22 | ) | ||
39 | 23 | |||
40 | 24 | from charmhelpers.core.host import service | ||
41 | 25 | |||
42 | 26 | # This module adds compatibility with the nrpe-external-master and plain nrpe | ||
43 | 27 | # subordinate charms. To use it in your charm: | ||
44 | 28 | # | ||
45 | 29 | # 1. Update metadata.yaml | ||
46 | 30 | # | ||
47 | 31 | # provides: | ||
48 | 32 | # (...) | ||
49 | 33 | # nrpe-external-master: | ||
50 | 34 | # interface: nrpe-external-master | ||
51 | 35 | # scope: container | ||
52 | 36 | # | ||
53 | 37 | # and/or | ||
54 | 38 | # | ||
55 | 39 | # provides: | ||
56 | 40 | # (...) | ||
57 | 41 | # local-monitors: | ||
58 | 42 | # interface: local-monitors | ||
59 | 43 | # scope: container | ||
60 | 44 | |||
61 | 45 | # | ||
62 | 46 | # 2. Add the following to config.yaml | ||
63 | 47 | # | ||
64 | 48 | # nagios_context: | ||
65 | 49 | # default: "juju" | ||
66 | 50 | # type: string | ||
67 | 51 | # description: | | ||
68 | 52 | # Used by the nrpe subordinate charms. | ||
69 | 53 | # A string that will be prepended to instance name to set the host name | ||
70 | 54 | # in nagios. So for instance the hostname would be something like: | ||
71 | 55 | # juju-myservice-0 | ||
72 | 56 | # If you're running multiple environments with the same services in them | ||
73 | 57 | # this allows you to differentiate between them. | ||
74 | 58 | # nagios_servicegroups: | ||
75 | 59 | # default: "" | ||
76 | 60 | # type: string | ||
77 | 61 | # description: | | ||
78 | 62 | # A comma-separated list of nagios servicegroups. | ||
79 | 63 | # If left empty, the nagios_context will be used as the servicegroup | ||
80 | 64 | # | ||
81 | 65 | # 3. Add custom checks (Nagios plugins) to files/nrpe-external-master | ||
82 | 66 | # | ||
83 | 67 | # 4. Update your hooks.py with something like this: | ||
84 | 68 | # | ||
85 | 69 | # from charmsupport.nrpe import NRPE | ||
86 | 70 | # (...) | ||
87 | 71 | # def update_nrpe_config(): | ||
88 | 72 | # nrpe_compat = NRPE() | ||
89 | 73 | # nrpe_compat.add_check( | ||
90 | 74 | # shortname = "myservice", | ||
91 | 75 | # description = "Check MyService", | ||
92 | 76 | # check_cmd = "check_http -w 2 -c 10 http://localhost" | ||
93 | 77 | # ) | ||
94 | 78 | # nrpe_compat.add_check( | ||
95 | 79 | # "myservice_other", | ||
96 | 80 | # "Check for widget failures", | ||
97 | 81 | # check_cmd = "/srv/myapp/scripts/widget_check" | ||
98 | 82 | # ) | ||
99 | 83 | # nrpe_compat.write() | ||
100 | 84 | # | ||
101 | 85 | # def config_changed(): | ||
102 | 86 | # (...) | ||
103 | 87 | # update_nrpe_config() | ||
104 | 88 | # | ||
105 | 89 | # def nrpe_external_master_relation_changed(): | ||
106 | 90 | # update_nrpe_config() | ||
107 | 91 | # | ||
108 | 92 | # def local_monitors_relation_changed(): | ||
109 | 93 | # update_nrpe_config() | ||
110 | 94 | # | ||
111 | 95 | # 5. ln -s hooks.py nrpe-external-master-relation-changed | ||
112 | 96 | # ln -s hooks.py local-monitors-relation-changed | ||
113 | 97 | |||
114 | 98 | |||
115 | 99 | class CheckException(Exception): | ||
116 | 100 | pass | ||
117 | 101 | |||
118 | 102 | |||
119 | 103 | class Check(object): | ||
120 | 104 | shortname_re = '[A-Za-z0-9-_]+$' | ||
121 | 105 | service_template = (""" | ||
122 | 106 | #--------------------------------------------------- | ||
123 | 107 | # This file is Juju managed | ||
124 | 108 | #--------------------------------------------------- | ||
125 | 109 | define service {{ | ||
126 | 110 | use active-service | ||
127 | 111 | host_name {nagios_hostname} | ||
128 | 112 | service_description {nagios_hostname}[{shortname}] """ | ||
129 | 113 | """{description} | ||
130 | 114 | check_command check_nrpe!{command} | ||
131 | 115 | servicegroups {nagios_servicegroup} | ||
132 | 116 | }} | ||
133 | 117 | """) | ||
134 | 118 | |||
135 | 119 | def __init__(self, shortname, description, check_cmd): | ||
136 | 120 | super(Check, self).__init__() | ||
137 | 121 | # XXX: could be better to calculate this from the service name | ||
138 | 122 | if not re.match(self.shortname_re, shortname): | ||
139 | 123 | raise CheckException("shortname must match {}".format( | ||
140 | 124 | Check.shortname_re)) | ||
141 | 125 | self.shortname = shortname | ||
142 | 126 | self.command = "check_{}".format(shortname) | ||
143 | 127 | # Note: a set of invalid characters is defined by the | ||
144 | 128 | # Nagios server config | ||
145 | 129 | # The default is: illegal_object_name_chars=`~!$%^&*"|'<>?,()= | ||
146 | 130 | self.description = description | ||
147 | 131 | self.check_cmd = self._locate_cmd(check_cmd) | ||
148 | 132 | |||
149 | 133 | def _locate_cmd(self, check_cmd): | ||
150 | 134 | search_path = ( | ||
151 | 135 | '/usr/lib/nagios/plugins', | ||
152 | 136 | '/usr/local/lib/nagios/plugins', | ||
153 | 137 | ) | ||
154 | 138 | parts = shlex.split(check_cmd) | ||
155 | 139 | for path in search_path: | ||
156 | 140 | if os.path.exists(os.path.join(path, parts[0])): | ||
157 | 141 | command = os.path.join(path, parts[0]) | ||
158 | 142 | if len(parts) > 1: | ||
159 | 143 | command += " " + " ".join(parts[1:]) | ||
160 | 144 | return command | ||
161 | 145 | log('Check command not found: {}'.format(parts[0])) | ||
162 | 146 | return '' | ||
163 | 147 | |||
164 | 148 | def write(self, nagios_context, hostname, nagios_servicegroups=None): | ||
165 | 149 | nrpe_check_file = '/etc/nagios/nrpe.d/{}.cfg'.format( | ||
166 | 150 | self.command) | ||
167 | 151 | with open(nrpe_check_file, 'w') as nrpe_check_config: | ||
168 | 152 | nrpe_check_config.write("# check {}\n".format(self.shortname)) | ||
169 | 153 | nrpe_check_config.write("command[{}]={}\n".format( | ||
170 | 154 | self.command, self.check_cmd)) | ||
171 | 155 | |||
172 | 156 | if not os.path.exists(NRPE.nagios_exportdir): | ||
173 | 157 | log('Not writing service config as {} is not accessible'.format( | ||
174 | 158 | NRPE.nagios_exportdir)) | ||
175 | 159 | else: | ||
176 | 160 | self.write_service_config(nagios_context, hostname, | ||
177 | 161 | nagios_servicegroups) | ||
178 | 162 | |||
179 | 163 | def write_service_config(self, nagios_context, hostname, | ||
180 | 164 | nagios_servicegroups=None): | ||
181 | 165 | for f in os.listdir(NRPE.nagios_exportdir): | ||
182 | 166 | if re.search('.*{}.cfg'.format(self.command), f): | ||
183 | 167 | os.remove(os.path.join(NRPE.nagios_exportdir, f)) | ||
184 | 168 | |||
185 | 169 | if not nagios_servicegroups: | ||
186 | 170 | nagios_servicegroups = nagios_context | ||
187 | 171 | |||
188 | 172 | templ_vars = { | ||
189 | 173 | 'nagios_hostname': hostname, | ||
190 | 174 | 'nagios_servicegroup': nagios_servicegroups, | ||
191 | 175 | 'description': self.description, | ||
192 | 176 | 'shortname': self.shortname, | ||
193 | 177 | 'command': self.command, | ||
194 | 178 | } | ||
195 | 179 | nrpe_service_text = Check.service_template.format(**templ_vars) | ||
196 | 180 | nrpe_service_file = '{}/service__{}_{}.cfg'.format( | ||
197 | 181 | NRPE.nagios_exportdir, hostname, self.command) | ||
198 | 182 | with open(nrpe_service_file, 'w') as nrpe_service_config: | ||
199 | 183 | nrpe_service_config.write(str(nrpe_service_text)) | ||
200 | 184 | |||
201 | 185 | def run(self): | ||
202 | 186 | subprocess.call(self.check_cmd) | ||
203 | 187 | |||
204 | 188 | |||
205 | 189 | class NRPE(object): | ||
206 | 190 | nagios_logdir = '/var/log/nagios' | ||
207 | 191 | nagios_exportdir = '/var/lib/nagios/export' | ||
208 | 192 | nrpe_confdir = '/etc/nagios/nrpe.d' | ||
209 | 193 | |||
210 | 194 | def __init__(self, hostname=None): | ||
211 | 195 | super(NRPE, self).__init__() | ||
212 | 196 | self.config = config() | ||
213 | 197 | self.nagios_context = self.config['nagios_context'] | ||
214 | 198 | if 'nagios_servicegroups' in self.config: | ||
215 | 199 | self.nagios_servicegroups = self.config['nagios_servicegroups'] | ||
216 | 200 | else: | ||
217 | 201 | self.nagios_servicegroups = 'juju' | ||
218 | 202 | self.unit_name = local_unit().replace('/', '-') | ||
219 | 203 | if hostname: | ||
220 | 204 | self.hostname = hostname | ||
221 | 205 | else: | ||
222 | 206 | self.hostname = "{}-{}".format(self.nagios_context, self.unit_name) | ||
223 | 207 | self.checks = [] | ||
224 | 208 | |||
225 | 209 | def add_check(self, *args, **kwargs): | ||
226 | 210 | self.checks.append(Check(*args, **kwargs)) | ||
227 | 211 | |||
228 | 212 | def write(self): | ||
229 | 213 | try: | ||
230 | 214 | nagios_uid = pwd.getpwnam('nagios').pw_uid | ||
231 | 215 | nagios_gid = grp.getgrnam('nagios').gr_gid | ||
232 | 216 | except: | ||
233 | 217 | log("Nagios user not set up, nrpe checks not updated") | ||
234 | 218 | return | ||
235 | 219 | |||
236 | 220 | if not os.path.exists(NRPE.nagios_logdir): | ||
237 | 221 | os.mkdir(NRPE.nagios_logdir) | ||
238 | 222 | os.chown(NRPE.nagios_logdir, nagios_uid, nagios_gid) | ||
239 | 223 | |||
240 | 224 | nrpe_monitors = {} | ||
241 | 225 | monitors = {"monitors": {"remote": {"nrpe": nrpe_monitors}}} | ||
242 | 226 | for nrpecheck in self.checks: | ||
243 | 227 | nrpecheck.write(self.nagios_context, self.hostname, | ||
244 | 228 | self.nagios_servicegroups) | ||
245 | 229 | nrpe_monitors[nrpecheck.shortname] = { | ||
246 | 230 | "command": nrpecheck.command, | ||
247 | 231 | } | ||
248 | 232 | |||
249 | 233 | service('restart', 'nagios-nrpe-server') | ||
250 | 234 | |||
251 | 235 | for rid in relation_ids("local-monitors"): | ||
252 | 236 | relation_set(relation_id=rid, monitors=yaml.dump(monitors)) | ||
253 | 237 | |||
254 | 238 | |||
255 | 239 | def get_nagios_hostcontext(relation_name='nrpe-external-master'): | ||
256 | 240 | """ | ||
257 | 241 | Query relation with nrpe subordinate, return the nagios_host_context | ||
258 | 242 | |||
259 | 243 | :param str relation_name: Name of relation nrpe sub joined to | ||
260 | 244 | """ | ||
261 | 245 | for rel in relations_of_type(relation_name): | ||
262 | 246 | if 'nagios_hostname' in rel: | ||
263 | 247 | return rel['nagios_host_context'] | ||
264 | 248 | |||
265 | 249 | |||
266 | 250 | def get_nagios_hostname(relation_name='nrpe-external-master'): | ||
267 | 251 | """ | ||
268 | 252 | Query relation with nrpe subordinate, return the nagios_hostname | ||
269 | 253 | |||
270 | 254 | :param str relation_name: Name of relation nrpe sub joined to | ||
271 | 255 | """ | ||
272 | 256 | for rel in relations_of_type(relation_name): | ||
273 | 257 | if 'nagios_hostname' in rel: | ||
274 | 258 | return rel['nagios_hostname'] | ||
275 | 259 | |||
276 | 260 | |||
277 | 261 | def get_nagios_unit_name(relation_name='nrpe-external-master'): | ||
278 | 262 | """ | ||
279 | 263 | Return the nagios unit name prepended with host_context if needed | ||
280 | 264 | |||
281 | 265 | :param str relation_name: Name of relation nrpe sub joined to | ||
282 | 266 | """ | ||
283 | 267 | host_context = get_nagios_hostcontext(relation_name) | ||
284 | 268 | if host_context: | ||
285 | 269 | unit = "%s:%s" % (host_context, local_unit()) | ||
286 | 270 | else: | ||
287 | 271 | unit = local_unit() | ||
288 | 272 | return unit | ||
289 | 273 | |||
290 | 274 | |||
291 | 275 | def add_init_service_checks(nrpe, services, unit_name): | ||
292 | 276 | """ | ||
293 | 277 | Add checks for each service in list | ||
294 | 278 | |||
295 | 279 | :param NRPE nrpe: NRPE object to add check to | ||
296 | 280 | :param list services: List of services to check | ||
297 | 281 | :param str unit_name: Unit name to use in check description | ||
298 | 282 | """ | ||
299 | 283 | for svc in services: | ||
300 | 284 | upstart_init = '/etc/init/%s.conf' % svc | ||
301 | 285 | sysv_init = '/etc/init.d/%s' % svc | ||
302 | 286 | if os.path.exists(upstart_init): | ||
303 | 287 | nrpe.add_check( | ||
304 | 288 | shortname=svc, | ||
305 | 289 | description='process check {%s}' % unit_name, | ||
306 | 290 | check_cmd='check_upstart_job %s' % svc | ||
307 | 291 | ) | ||
308 | 292 | elif os.path.exists(sysv_init): | ||
309 | 293 | cronpath = '/etc/cron.d/nagios-service-check-%s' % svc | ||
310 | 294 | cron_file = ('*/5 * * * * root ' | ||
311 | 295 | '/usr/local/lib/nagios/plugins/check_exit_status.pl ' | ||
312 | 296 | '-s /etc/init.d/%s status > ' | ||
313 | 297 | '/var/lib/nagios/service-check-%s.txt\n' % (svc, | ||
314 | 298 | svc) | ||
315 | 299 | ) | ||
316 | 300 | f = open(cronpath, 'w') | ||
317 | 301 | f.write(cron_file) | ||
318 | 302 | f.close() | ||
319 | 303 | nrpe.add_check( | ||
320 | 304 | shortname=svc, | ||
321 | 305 | description='process check {%s}' % unit_name, | ||
322 | 306 | check_cmd='check_status_file.py -f ' | ||
323 | 307 | '/var/lib/nagios/service-check-%s.txt' % svc, | ||
324 | 308 | ) | ||
325 | 0 | 309 | ||
326 | === added file 'hooks/charmhelpers/contrib/charmsupport/volumes.py' | |||
327 | --- hooks/charmhelpers/contrib/charmsupport/volumes.py 1970-01-01 00:00:00 +0000 | |||
328 | +++ hooks/charmhelpers/contrib/charmsupport/volumes.py 2015-01-12 14:02:09 +0000 | |||
329 | @@ -0,0 +1,159 @@ | |||
330 | 1 | ''' | ||
331 | 2 | Functions for managing volumes in juju units. One volume is supported per unit. | ||
332 | 3 | Subordinates may have their own storage, provided it is on its own partition. | ||
333 | 4 | |||
334 | 5 | Configuration stanzas:: | ||
335 | 6 | |||
336 | 7 | volume-ephemeral: | ||
337 | 8 | type: boolean | ||
338 | 9 | default: true | ||
339 | 10 | description: > | ||
340 | 11 | If false, a volume is mounted as sepecified in "volume-map" | ||
341 | 12 | If true, ephemeral storage will be used, meaning that log data | ||
342 | 13 | will only exist as long as the machine. YOU HAVE BEEN WARNED. | ||
343 | 14 | volume-map: | ||
344 | 15 | type: string | ||
345 | 16 | default: {} | ||
346 | 17 | description: > | ||
347 | 18 | YAML map of units to device names, e.g: | ||
348 | 19 | "{ rsyslog/0: /dev/vdb, rsyslog/1: /dev/vdb }" | ||
349 | 20 | Service units will raise a configure-error if volume-ephemeral | ||
350 | 21 | is 'true' and no volume-map value is set. Use 'juju set' to set a | ||
351 | 22 | value and 'juju resolved' to complete configuration. | ||
352 | 23 | |||
353 | 24 | Usage:: | ||
354 | 25 | |||
355 | 26 | from charmsupport.volumes import configure_volume, VolumeConfigurationError | ||
356 | 27 | from charmsupport.hookenv import log, ERROR | ||
357 | 28 | def post_mount_hook(): | ||
358 | 29 | stop_service('myservice') | ||
359 | 30 | def post_mount_hook(): | ||
360 | 31 | start_service('myservice') | ||
361 | 32 | |||
362 | 33 | if __name__ == '__main__': | ||
363 | 34 | try: | ||
364 | 35 | configure_volume(before_change=pre_mount_hook, | ||
365 | 36 | after_change=post_mount_hook) | ||
366 | 37 | except VolumeConfigurationError: | ||
367 | 38 | log('Storage could not be configured', ERROR) | ||
368 | 39 | |||
369 | 40 | ''' | ||
370 | 41 | |||
371 | 42 | # XXX: Known limitations | ||
372 | 43 | # - fstab is neither consulted nor updated | ||
373 | 44 | |||
374 | 45 | import os | ||
375 | 46 | from charmhelpers.core import hookenv | ||
376 | 47 | from charmhelpers.core import host | ||
377 | 48 | import yaml | ||
378 | 49 | |||
379 | 50 | |||
380 | 51 | MOUNT_BASE = '/srv/juju/volumes' | ||
381 | 52 | |||
382 | 53 | |||
383 | 54 | class VolumeConfigurationError(Exception): | ||
384 | 55 | '''Volume configuration data is missing or invalid''' | ||
385 | 56 | pass | ||
386 | 57 | |||
387 | 58 | |||
388 | 59 | def get_config(): | ||
389 | 60 | '''Gather and sanity-check volume configuration data''' | ||
390 | 61 | volume_config = {} | ||
391 | 62 | config = hookenv.config() | ||
392 | 63 | |||
393 | 64 | errors = False | ||
394 | 65 | |||
395 | 66 | if config.get('volume-ephemeral') in (True, 'True', 'true', 'Yes', 'yes'): | ||
396 | 67 | volume_config['ephemeral'] = True | ||
397 | 68 | else: | ||
398 | 69 | volume_config['ephemeral'] = False | ||
399 | 70 | |||
400 | 71 | try: | ||
401 | 72 | volume_map = yaml.safe_load(config.get('volume-map', '{}')) | ||
402 | 73 | except yaml.YAMLError as e: | ||
403 | 74 | hookenv.log("Error parsing YAML volume-map: {}".format(e), | ||
404 | 75 | hookenv.ERROR) | ||
405 | 76 | errors = True | ||
406 | 77 | if volume_map is None: | ||
407 | 78 | # probably an empty string | ||
408 | 79 | volume_map = {} | ||
409 | 80 | elif not isinstance(volume_map, dict): | ||
410 | 81 | hookenv.log("Volume-map should be a dictionary, not {}".format( | ||
411 | 82 | type(volume_map))) | ||
412 | 83 | errors = True | ||
413 | 84 | |||
414 | 85 | volume_config['device'] = volume_map.get(os.environ['JUJU_UNIT_NAME']) | ||
415 | 86 | if volume_config['device'] and volume_config['ephemeral']: | ||
416 | 87 | # asked for ephemeral storage but also defined a volume ID | ||
417 | 88 | hookenv.log('A volume is defined for this unit, but ephemeral ' | ||
418 | 89 | 'storage was requested', hookenv.ERROR) | ||
419 | 90 | errors = True | ||
420 | 91 | elif not volume_config['device'] and not volume_config['ephemeral']: | ||
421 | 92 | # asked for permanent storage but did not define volume ID | ||
422 | 93 | hookenv.log('Ephemeral storage was requested, but there is no volume ' | ||
423 | 94 | 'defined for this unit.', hookenv.ERROR) | ||
424 | 95 | errors = True | ||
425 | 96 | |||
426 | 97 | unit_mount_name = hookenv.local_unit().replace('/', '-') | ||
427 | 98 | volume_config['mountpoint'] = os.path.join(MOUNT_BASE, unit_mount_name) | ||
428 | 99 | |||
429 | 100 | if errors: | ||
430 | 101 | return None | ||
431 | 102 | return volume_config | ||
432 | 103 | |||
433 | 104 | |||
434 | 105 | def mount_volume(config): | ||
435 | 106 | if os.path.exists(config['mountpoint']): | ||
436 | 107 | if not os.path.isdir(config['mountpoint']): | ||
437 | 108 | hookenv.log('Not a directory: {}'.format(config['mountpoint'])) | ||
438 | 109 | raise VolumeConfigurationError() | ||
439 | 110 | else: | ||
440 | 111 | host.mkdir(config['mountpoint']) | ||
441 | 112 | if os.path.ismount(config['mountpoint']): | ||
442 | 113 | unmount_volume(config) | ||
443 | 114 | if not host.mount(config['device'], config['mountpoint'], persist=True): | ||
444 | 115 | raise VolumeConfigurationError() | ||
445 | 116 | |||
446 | 117 | |||
447 | 118 | def unmount_volume(config): | ||
448 | 119 | if os.path.ismount(config['mountpoint']): | ||
449 | 120 | if not host.umount(config['mountpoint'], persist=True): | ||
450 | 121 | raise VolumeConfigurationError() | ||
451 | 122 | |||
452 | 123 | |||
453 | 124 | def managed_mounts(): | ||
454 | 125 | '''List of all mounted managed volumes''' | ||
455 | 126 | return filter(lambda mount: mount[0].startswith(MOUNT_BASE), host.mounts()) | ||
456 | 127 | |||
457 | 128 | |||
458 | 129 | def configure_volume(before_change=lambda: None, after_change=lambda: None): | ||
459 | 130 | '''Set up storage (or don't) according to the charm's volume configuration. | ||
460 | 131 | Returns the mount point or "ephemeral". before_change and after_change | ||
461 | 132 | are optional functions to be called if the volume configuration changes. | ||
462 | 133 | ''' | ||
463 | 134 | |||
464 | 135 | config = get_config() | ||
465 | 136 | if not config: | ||
466 | 137 | hookenv.log('Failed to read volume configuration', hookenv.CRITICAL) | ||
467 | 138 | raise VolumeConfigurationError() | ||
468 | 139 | |||
469 | 140 | if config['ephemeral']: | ||
470 | 141 | if os.path.ismount(config['mountpoint']): | ||
471 | 142 | before_change() | ||
472 | 143 | unmount_volume(config) | ||
473 | 144 | after_change() | ||
474 | 145 | return 'ephemeral' | ||
475 | 146 | else: | ||
476 | 147 | # persistent storage | ||
477 | 148 | if os.path.ismount(config['mountpoint']): | ||
478 | 149 | mounts = dict(managed_mounts()) | ||
479 | 150 | if mounts.get(config['mountpoint']) != config['device']: | ||
480 | 151 | before_change() | ||
481 | 152 | unmount_volume(config) | ||
482 | 153 | mount_volume(config) | ||
483 | 154 | after_change() | ||
484 | 155 | else: | ||
485 | 156 | before_change() | ||
486 | 157 | mount_volume(config) | ||
487 | 158 | after_change() | ||
488 | 159 | return config['mountpoint'] | ||
489 | 0 | 160 | ||
490 | === modified file 'hooks/charmhelpers/contrib/hahelpers/cluster.py' | |||
491 | --- hooks/charmhelpers/contrib/hahelpers/cluster.py 2014-12-15 09:10:57 +0000 | |||
492 | +++ hooks/charmhelpers/contrib/hahelpers/cluster.py 2015-01-12 14:02:09 +0000 | |||
493 | @@ -13,6 +13,7 @@ | |||
494 | 13 | 13 | ||
495 | 14 | import subprocess | 14 | import subprocess |
496 | 15 | import os | 15 | import os |
497 | 16 | |||
498 | 16 | from socket import gethostname as get_unit_hostname | 17 | from socket import gethostname as get_unit_hostname |
499 | 17 | 18 | ||
500 | 18 | import six | 19 | import six |
501 | @@ -28,12 +29,19 @@ | |||
502 | 28 | WARNING, | 29 | WARNING, |
503 | 29 | unit_get, | 30 | unit_get, |
504 | 30 | ) | 31 | ) |
505 | 32 | from charmhelpers.core.decorators import ( | ||
506 | 33 | retry_on_exception, | ||
507 | 34 | ) | ||
508 | 31 | 35 | ||
509 | 32 | 36 | ||
510 | 33 | class HAIncompleteConfig(Exception): | 37 | class HAIncompleteConfig(Exception): |
511 | 34 | pass | 38 | pass |
512 | 35 | 39 | ||
513 | 36 | 40 | ||
514 | 41 | class CRMResourceNotFound(Exception): | ||
515 | 42 | pass | ||
516 | 43 | |||
517 | 44 | |||
518 | 37 | def is_elected_leader(resource): | 45 | def is_elected_leader(resource): |
519 | 38 | """ | 46 | """ |
520 | 39 | Returns True if the charm executing this is the elected cluster leader. | 47 | Returns True if the charm executing this is the elected cluster leader. |
521 | @@ -68,24 +76,30 @@ | |||
522 | 68 | return False | 76 | return False |
523 | 69 | 77 | ||
524 | 70 | 78 | ||
526 | 71 | def is_crm_leader(resource): | 79 | @retry_on_exception(5, base_delay=2, exc_type=CRMResourceNotFound) |
527 | 80 | def is_crm_leader(resource, retry=False): | ||
528 | 72 | """ | 81 | """ |
529 | 73 | Returns True if the charm calling this is the elected corosync leader, | 82 | Returns True if the charm calling this is the elected corosync leader, |
530 | 74 | as returned by calling the external "crm" command. | 83 | as returned by calling the external "crm" command. |
531 | 84 | |||
532 | 85 | We allow this operation to be retried to avoid the possibility of getting a | ||
533 | 86 | false negative. See LP #1396246 for more info. | ||
534 | 75 | """ | 87 | """ |
539 | 76 | cmd = [ | 88 | cmd = ['crm', 'resource', 'show', resource] |
536 | 77 | "crm", "resource", | ||
537 | 78 | "show", resource | ||
538 | 79 | ] | ||
540 | 80 | try: | 89 | try: |
542 | 81 | status = subprocess.check_output(cmd).decode('UTF-8') | 90 | status = subprocess.check_output(cmd, stderr=subprocess.STDOUT) |
543 | 91 | if not isinstance(status, six.text_type): | ||
544 | 92 | status = six.text_type(status, "utf-8") | ||
545 | 82 | except subprocess.CalledProcessError: | 93 | except subprocess.CalledProcessError: |
552 | 83 | return False | 94 | status = None |
553 | 84 | else: | 95 | |
554 | 85 | if get_unit_hostname() in status: | 96 | if status and get_unit_hostname() in status: |
555 | 86 | return True | 97 | return True |
556 | 87 | else: | 98 | |
557 | 88 | return False | 99 | if status and "resource %s is NOT running" % (resource) in status: |
558 | 100 | raise CRMResourceNotFound("CRM resource %s not found" % (resource)) | ||
559 | 101 | |||
560 | 102 | return False | ||
561 | 89 | 103 | ||
562 | 90 | 104 | ||
563 | 91 | def is_leader(resource): | 105 | def is_leader(resource): |
564 | 92 | 106 | ||
565 | === modified file 'hooks/charmhelpers/contrib/network/ufw.py' | |||
566 | --- hooks/charmhelpers/contrib/network/ufw.py 2014-12-10 20:28:56 +0000 | |||
567 | +++ hooks/charmhelpers/contrib/network/ufw.py 2015-01-12 14:02:09 +0000 | |||
568 | @@ -54,6 +54,17 @@ | |||
569 | 54 | if is_enabled(): | 54 | if is_enabled(): |
570 | 55 | return True | 55 | return True |
571 | 56 | 56 | ||
572 | 57 | if not os.path.isdir('/proc/sys/net/ipv6'): | ||
573 | 58 | # disable IPv6 support in ufw | ||
574 | 59 | hookenv.log("This machine doesn't have IPv6 enabled", level="INFO") | ||
575 | 60 | exit_code = subprocess.call(['sed', '-i', 's/IPV6=yes/IPV6=no/g', | ||
576 | 61 | '/etc/default/ufw']) | ||
577 | 62 | if exit_code == 0: | ||
578 | 63 | hookenv.log('IPv6 support in ufw disabled', level='INFO') | ||
579 | 64 | else: | ||
580 | 65 | hookenv.log("Couldn't disable IPv6 support in ufw", level="ERROR") | ||
581 | 66 | raise Exception("Couldn't disable IPv6 support in ufw") | ||
582 | 67 | |||
583 | 57 | output = subprocess.check_output(['ufw', 'enable'], | 68 | output = subprocess.check_output(['ufw', 'enable'], |
584 | 58 | env={'LANG': 'en_US', | 69 | env={'LANG': 'en_US', |
585 | 59 | 'PATH': os.environ['PATH']}) | 70 | 'PATH': os.environ['PATH']}) |
586 | 60 | 71 | ||
587 | === modified file 'hooks/charmhelpers/contrib/openstack/context.py' | |||
588 | --- hooks/charmhelpers/contrib/openstack/context.py 2014-12-15 10:28:47 +0000 | |||
589 | +++ hooks/charmhelpers/contrib/openstack/context.py 2015-01-12 14:02:09 +0000 | |||
590 | @@ -491,6 +491,7 @@ | |||
591 | 491 | ctxt['haproxy_client_timeout'] = config('haproxy-client-timeout') | 491 | ctxt['haproxy_client_timeout'] = config('haproxy-client-timeout') |
592 | 492 | 492 | ||
593 | 493 | if config('prefer-ipv6'): | 493 | if config('prefer-ipv6'): |
594 | 494 | ctxt['ipv6'] = True | ||
595 | 494 | ctxt['local_host'] = 'ip6-localhost' | 495 | ctxt['local_host'] = 'ip6-localhost' |
596 | 495 | ctxt['haproxy_host'] = '::' | 496 | ctxt['haproxy_host'] = '::' |
597 | 496 | ctxt['stat_port'] = ':::8888' | 497 | ctxt['stat_port'] = ':::8888' |
598 | 497 | 498 | ||
599 | === modified file 'hooks/charmhelpers/contrib/openstack/neutron.py' | |||
600 | --- hooks/charmhelpers/contrib/openstack/neutron.py 2014-12-15 10:28:47 +0000 | |||
601 | +++ hooks/charmhelpers/contrib/openstack/neutron.py 2015-01-12 14:02:09 +0000 | |||
602 | @@ -152,9 +152,15 @@ | |||
603 | 152 | database=config('neutron-database'), | 152 | database=config('neutron-database'), |
604 | 153 | relation_prefix='neutron', | 153 | relation_prefix='neutron', |
605 | 154 | ssl_dir=NEUTRON_CONF_DIR)], | 154 | ssl_dir=NEUTRON_CONF_DIR)], |
607 | 155 | 'services': ['calico-compute', 'bird', 'neutron-dhcp-agent'], | 155 | 'services': ['calico-felix', |
608 | 156 | 'bird', | ||
609 | 157 | 'neutron-dhcp-agent', | ||
610 | 158 | 'nova-api-metadata'], | ||
611 | 156 | 'packages': [[headers_package()] + determine_dkms_package(), | 159 | 'packages': [[headers_package()] + determine_dkms_package(), |
613 | 157 | ['calico-compute', 'bird', 'neutron-dhcp-agent']], | 160 | ['calico-compute', |
614 | 161 | 'bird', | ||
615 | 162 | 'neutron-dhcp-agent', | ||
616 | 163 | 'nova-api-metadata']], | ||
617 | 158 | 'server_packages': ['neutron-server', 'calico-control'], | 164 | 'server_packages': ['neutron-server', 'calico-control'], |
618 | 159 | 'server_services': ['neutron-server'] | 165 | 'server_services': ['neutron-server'] |
619 | 160 | } | 166 | } |
620 | 161 | 167 | ||
621 | === modified file 'hooks/charmhelpers/contrib/openstack/templates/haproxy.cfg' | |||
622 | --- hooks/charmhelpers/contrib/openstack/templates/haproxy.cfg 2014-12-15 09:10:57 +0000 | |||
623 | +++ hooks/charmhelpers/contrib/openstack/templates/haproxy.cfg 2015-01-12 14:02:09 +0000 | |||
624 | @@ -38,7 +38,9 @@ | |||
625 | 38 | {% for service, ports in service_ports.items() -%} | 38 | {% for service, ports in service_ports.items() -%} |
626 | 39 | frontend tcp-in_{{ service }} | 39 | frontend tcp-in_{{ service }} |
627 | 40 | bind *:{{ ports[0] }} | 40 | bind *:{{ ports[0] }} |
628 | 41 | {% if ipv6 -%} | ||
629 | 41 | bind :::{{ ports[0] }} | 42 | bind :::{{ ports[0] }} |
630 | 43 | {% endif -%} | ||
631 | 42 | {% for frontend in frontends -%} | 44 | {% for frontend in frontends -%} |
632 | 43 | acl net_{{ frontend }} dst {{ frontends[frontend]['network'] }} | 45 | acl net_{{ frontend }} dst {{ frontends[frontend]['network'] }} |
633 | 44 | use_backend {{ service }}_{{ frontend }} if net_{{ frontend }} | 46 | use_backend {{ service }}_{{ frontend }} if net_{{ frontend }} |
634 | 45 | 47 | ||
635 | === modified file 'hooks/charmhelpers/contrib/openstack/utils.py' | |||
636 | --- hooks/charmhelpers/contrib/openstack/utils.py 2014-12-15 10:28:47 +0000 | |||
637 | +++ hooks/charmhelpers/contrib/openstack/utils.py 2015-01-12 14:02:09 +0000 | |||
638 | @@ -53,6 +53,7 @@ | |||
639 | 53 | ('saucy', 'havana'), | 53 | ('saucy', 'havana'), |
640 | 54 | ('trusty', 'icehouse'), | 54 | ('trusty', 'icehouse'), |
641 | 55 | ('utopic', 'juno'), | 55 | ('utopic', 'juno'), |
642 | 56 | ('vivid', 'kilo'), | ||
643 | 56 | ]) | 57 | ]) |
644 | 57 | 58 | ||
645 | 58 | 59 | ||
646 | @@ -64,6 +65,7 @@ | |||
647 | 64 | ('2013.2', 'havana'), | 65 | ('2013.2', 'havana'), |
648 | 65 | ('2014.1', 'icehouse'), | 66 | ('2014.1', 'icehouse'), |
649 | 66 | ('2014.2', 'juno'), | 67 | ('2014.2', 'juno'), |
650 | 68 | ('2015.1', 'kilo'), | ||
651 | 67 | ]) | 69 | ]) |
652 | 68 | 70 | ||
653 | 69 | # The ugly duckling | 71 | # The ugly duckling |
654 | @@ -84,6 +86,7 @@ | |||
655 | 84 | ('2.0.0', 'juno'), | 86 | ('2.0.0', 'juno'), |
656 | 85 | ('2.1.0', 'juno'), | 87 | ('2.1.0', 'juno'), |
657 | 86 | ('2.2.0', 'juno'), | 88 | ('2.2.0', 'juno'), |
658 | 89 | ('2.2.1', 'kilo'), | ||
659 | 87 | ]) | 90 | ]) |
660 | 88 | 91 | ||
661 | 89 | DEFAULT_LOOPBACK_SIZE = '5G' | 92 | DEFAULT_LOOPBACK_SIZE = '5G' |
662 | @@ -289,6 +292,9 @@ | |||
663 | 289 | 'juno': 'trusty-updates/juno', | 292 | 'juno': 'trusty-updates/juno', |
664 | 290 | 'juno/updates': 'trusty-updates/juno', | 293 | 'juno/updates': 'trusty-updates/juno', |
665 | 291 | 'juno/proposed': 'trusty-proposed/juno', | 294 | 'juno/proposed': 'trusty-proposed/juno', |
666 | 295 | 'kilo': 'trusty-updates/kilo', | ||
667 | 296 | 'kilo/updates': 'trusty-updates/kilo', | ||
668 | 297 | 'kilo/proposed': 'trusty-proposed/kilo', | ||
669 | 292 | } | 298 | } |
670 | 293 | 299 | ||
671 | 294 | try: | 300 | try: |
672 | 295 | 301 | ||
673 | === added file 'hooks/charmhelpers/core/decorators.py' | |||
674 | --- hooks/charmhelpers/core/decorators.py 1970-01-01 00:00:00 +0000 | |||
675 | +++ hooks/charmhelpers/core/decorators.py 2015-01-12 14:02:09 +0000 | |||
676 | @@ -0,0 +1,41 @@ | |||
677 | 1 | # | ||
678 | 2 | # Copyright 2014 Canonical Ltd. | ||
679 | 3 | # | ||
680 | 4 | # Authors: | ||
681 | 5 | # Edward Hope-Morley <opentastic@gmail.com> | ||
682 | 6 | # | ||
683 | 7 | |||
684 | 8 | import time | ||
685 | 9 | |||
686 | 10 | from charmhelpers.core.hookenv import ( | ||
687 | 11 | log, | ||
688 | 12 | INFO, | ||
689 | 13 | ) | ||
690 | 14 | |||
691 | 15 | |||
692 | 16 | def retry_on_exception(num_retries, base_delay=0, exc_type=Exception): | ||
693 | 17 | """If the decorated function raises exception exc_type, allow num_retries | ||
694 | 18 | retry attempts before raise the exception. | ||
695 | 19 | """ | ||
696 | 20 | def _retry_on_exception_inner_1(f): | ||
697 | 21 | def _retry_on_exception_inner_2(*args, **kwargs): | ||
698 | 22 | retries = num_retries | ||
699 | 23 | multiplier = 1 | ||
700 | 24 | while True: | ||
701 | 25 | try: | ||
702 | 26 | return f(*args, **kwargs) | ||
703 | 27 | except exc_type: | ||
704 | 28 | if not retries: | ||
705 | 29 | raise | ||
706 | 30 | |||
707 | 31 | delay = base_delay * multiplier | ||
708 | 32 | multiplier += 1 | ||
709 | 33 | log("Retrying '%s' %d more times (delay=%s)" % | ||
710 | 34 | (f.__name__, retries, delay), level=INFO) | ||
711 | 35 | retries -= 1 | ||
712 | 36 | if delay: | ||
713 | 37 | time.sleep(delay) | ||
714 | 38 | |||
715 | 39 | return _retry_on_exception_inner_2 | ||
716 | 40 | |||
717 | 41 | return _retry_on_exception_inner_1 | ||
718 | 0 | 42 | ||
719 | === modified file 'hooks/charmhelpers/core/host.py' | |||
720 | --- hooks/charmhelpers/core/host.py 2014-12-15 10:28:47 +0000 | |||
721 | +++ hooks/charmhelpers/core/host.py 2015-01-12 14:02:09 +0000 | |||
722 | @@ -162,13 +162,16 @@ | |||
723 | 162 | uid = pwd.getpwnam(owner).pw_uid | 162 | uid = pwd.getpwnam(owner).pw_uid |
724 | 163 | gid = grp.getgrnam(group).gr_gid | 163 | gid = grp.getgrnam(group).gr_gid |
725 | 164 | realpath = os.path.abspath(path) | 164 | realpath = os.path.abspath(path) |
728 | 165 | if os.path.exists(realpath): | 165 | path_exists = os.path.exists(realpath) |
729 | 166 | if force and not os.path.isdir(realpath): | 166 | if path_exists and force: |
730 | 167 | if not os.path.isdir(realpath): | ||
731 | 167 | log("Removing non-directory file {} prior to mkdir()".format(path)) | 168 | log("Removing non-directory file {} prior to mkdir()".format(path)) |
732 | 168 | os.unlink(realpath) | 169 | os.unlink(realpath) |
734 | 169 | else: | 170 | os.makedirs(realpath, perms) |
735 | 171 | os.chown(realpath, uid, gid) | ||
736 | 172 | elif not path_exists: | ||
737 | 170 | os.makedirs(realpath, perms) | 173 | os.makedirs(realpath, perms) |
739 | 171 | os.chown(realpath, uid, gid) | 174 | os.chown(realpath, uid, gid) |
740 | 172 | 175 | ||
741 | 173 | 176 | ||
742 | 174 | def write_file(path, content, owner='root', group='root', perms=0o444): | 177 | def write_file(path, content, owner='root', group='root', perms=0o444): |
743 | 175 | 178 | ||
744 | === modified file 'hooks/charmhelpers/fetch/__init__.py' | |||
745 | --- hooks/charmhelpers/fetch/__init__.py 2014-12-15 10:28:47 +0000 | |||
746 | +++ hooks/charmhelpers/fetch/__init__.py 2015-01-12 14:02:09 +0000 | |||
747 | @@ -64,9 +64,16 @@ | |||
748 | 64 | 'trusty-juno/updates': 'trusty-updates/juno', | 64 | 'trusty-juno/updates': 'trusty-updates/juno', |
749 | 65 | 'trusty-updates/juno': 'trusty-updates/juno', | 65 | 'trusty-updates/juno': 'trusty-updates/juno', |
750 | 66 | 'juno/proposed': 'trusty-proposed/juno', | 66 | 'juno/proposed': 'trusty-proposed/juno', |
751 | 67 | 'juno/proposed': 'trusty-proposed/juno', | ||
752 | 68 | 'trusty-juno/proposed': 'trusty-proposed/juno', | 67 | 'trusty-juno/proposed': 'trusty-proposed/juno', |
753 | 69 | 'trusty-proposed/juno': 'trusty-proposed/juno', | 68 | 'trusty-proposed/juno': 'trusty-proposed/juno', |
754 | 69 | # Kilo | ||
755 | 70 | 'kilo': 'trusty-updates/kilo', | ||
756 | 71 | 'trusty-kilo': 'trusty-updates/kilo', | ||
757 | 72 | 'trusty-kilo/updates': 'trusty-updates/kilo', | ||
758 | 73 | 'trusty-updates/kilo': 'trusty-updates/kilo', | ||
759 | 74 | 'kilo/proposed': 'trusty-proposed/kilo', | ||
760 | 75 | 'trusty-kilo/proposed': 'trusty-proposed/kilo', | ||
761 | 76 | 'trusty-proposed/kilo': 'trusty-proposed/kilo', | ||
762 | 70 | } | 77 | } |
763 | 71 | 78 | ||
764 | 72 | # The order of this list is very important. Handlers should be listed in from | 79 | # The order of this list is very important. Handlers should be listed in from |
765 | 73 | 80 | ||
766 | === added symlink 'hooks/compute-peer-relation-joined' | |||
767 | === target is u'nova_compute_hooks.py' | |||
768 | === added symlink 'hooks/neutron-plugin-relation-changed' | |||
769 | === target is u'nova_compute_hooks.py' | |||
770 | === added symlink 'hooks/neutron-plugin-relation-departed' | |||
771 | === target is u'nova_compute_hooks.py' | |||
772 | === added symlink 'hooks/neutron-plugin-relation-joined' | |||
773 | === target is u'nova_compute_hooks.py' | |||
774 | === modified file 'hooks/nova_compute_hooks.py' | |||
775 | --- hooks/nova_compute_hooks.py 2014-12-15 10:28:47 +0000 | |||
776 | +++ hooks/nova_compute_hooks.py 2015-01-12 14:02:09 +0000 | |||
777 | @@ -48,6 +48,7 @@ | |||
778 | 48 | do_openstack_upgrade, | 48 | do_openstack_upgrade, |
779 | 49 | public_ssh_key, | 49 | public_ssh_key, |
780 | 50 | restart_map, | 50 | restart_map, |
781 | 51 | services, | ||
782 | 51 | register_configs, | 52 | register_configs, |
783 | 52 | NOVA_CONF, | 53 | NOVA_CONF, |
784 | 53 | QUANTUM_CONF, NEUTRON_CONF, | 54 | QUANTUM_CONF, NEUTRON_CONF, |
785 | @@ -65,6 +66,7 @@ | |||
786 | 65 | CEPH_SECRET_UUID, | 66 | CEPH_SECRET_UUID, |
787 | 66 | assert_libvirt_imagebackend_allowed | 67 | assert_libvirt_imagebackend_allowed |
788 | 67 | ) | 68 | ) |
789 | 69 | from charmhelpers.contrib.charmsupport import nrpe | ||
790 | 68 | from charmhelpers.core.sysctl import create as create_sysctl | 70 | from charmhelpers.core.sysctl import create as create_sysctl |
791 | 69 | 71 | ||
792 | 70 | from socket import gethostname | 72 | from socket import gethostname |
793 | @@ -114,6 +116,8 @@ | |||
794 | 114 | 116 | ||
795 | 115 | [compute_joined(rid) for rid in relation_ids('cloud-compute')] | 117 | [compute_joined(rid) for rid in relation_ids('cloud-compute')] |
796 | 116 | 118 | ||
797 | 119 | update_nrpe_config() | ||
798 | 120 | |||
799 | 117 | CONFIGS.write_all() | 121 | CONFIGS.write_all() |
800 | 118 | 122 | ||
801 | 119 | 123 | ||
802 | @@ -292,6 +296,7 @@ | |||
803 | 292 | def upgrade_charm(): | 296 | def upgrade_charm(): |
804 | 293 | for r_id in relation_ids('amqp'): | 297 | for r_id in relation_ids('amqp'): |
805 | 294 | amqp_joined(relation_id=r_id) | 298 | amqp_joined(relation_id=r_id) |
806 | 299 | update_nrpe_config() | ||
807 | 295 | 300 | ||
808 | 296 | 301 | ||
809 | 297 | @hooks.hook('nova-ceilometer-relation-changed') | 302 | @hooks.hook('nova-ceilometer-relation-changed') |
810 | @@ -300,6 +305,18 @@ | |||
811 | 300 | CONFIGS.write_all() | 305 | CONFIGS.write_all() |
812 | 301 | 306 | ||
813 | 302 | 307 | ||
814 | 308 | @hooks.hook('nrpe-external-master-relation-joined', | ||
815 | 309 | 'nrpe-external-master-relation-changed') | ||
816 | 310 | def update_nrpe_config(): | ||
817 | 311 | # python-dbus is used by check_upstart_job | ||
818 | 312 | apt_install('python-dbus') | ||
819 | 313 | hostname = nrpe.get_nagios_hostname() | ||
820 | 314 | current_unit = nrpe.get_nagios_unit_name() | ||
821 | 315 | nrpe_setup = nrpe.NRPE(hostname=hostname) | ||
822 | 316 | nrpe.add_init_service_checks(nrpe_setup, services(), current_unit) | ||
823 | 317 | nrpe_setup.write() | ||
824 | 318 | |||
825 | 319 | |||
826 | 303 | def main(): | 320 | def main(): |
827 | 304 | try: | 321 | try: |
828 | 305 | hooks.execute(sys.argv) | 322 | hooks.execute(sys.argv) |
829 | 306 | 323 | ||
830 | === added symlink 'hooks/nrpe-external-master-relation-changed' | |||
831 | === target is u'nova_compute_hooks.py' | |||
832 | === added symlink 'hooks/start' | |||
833 | === target is u'nova_compute_hooks.py' | |||
834 | === added symlink 'hooks/stop' | |||
835 | === target is u'nova_compute_hooks.py' | |||
836 | === modified file 'unit_tests/test_nova_compute_hooks.py' | |||
837 | --- unit_tests/test_nova_compute_hooks.py 2014-12-15 10:28:47 +0000 | |||
838 | +++ unit_tests/test_nova_compute_hooks.py 2015-01-12 14:02:09 +0000 | |||
839 | @@ -46,6 +46,7 @@ | |||
840 | 46 | 'register_configs', | 46 | 'register_configs', |
841 | 47 | 'disable_shell', | 47 | 'disable_shell', |
842 | 48 | 'enable_shell', | 48 | 'enable_shell', |
843 | 49 | 'update_nrpe_config', | ||
844 | 49 | # misc_utils | 50 | # misc_utils |
845 | 50 | 'ensure_ceph_keyring', | 51 | 'ensure_ceph_keyring', |
846 | 51 | 'execd_preinstall', | 52 | 'execd_preinstall', |
charm_lint_check #667 nova-compute-next for gnuoy mp246158
LINT OK: passed
Build: http:// 10.245. 162.77: 8080/job/ charm_lint_ check/667/