Merge lp:~gnuoy/charms/trusty/nova-compute/add-nrpe-checks into lp:~openstack-charmers-archive/charms/trusty/nova-compute/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
Reviewer Review Type Date Requested Status
Liam Young (community) Approve
Review via email: mp+246158@code.launchpad.net

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 :

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/

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

Build: http://10.245.162.77:8080/job/charm_unit_test/696/

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

Build: http://10.245.162.77:8080/job/charm_amulet_test/852/

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
=== modified file 'charm-helpers-hooks.yaml'
--- charm-helpers-hooks.yaml 2014-12-11 14:51:25 +0000
+++ charm-helpers-hooks.yaml 2015-01-12 14:02:09 +0000
@@ -11,3 +11,4 @@
11 - contrib.network11 - contrib.network
12 - contrib.python.packages12 - contrib.python.packages
13 - payload.execd13 - payload.execd
14 - contrib.charmsupport
1415
=== added directory 'files'
=== added directory 'hooks/charmhelpers/contrib/charmsupport'
=== added file 'hooks/charmhelpers/contrib/charmsupport/__init__.py'
=== 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 2015-01-12 14:02:09 +0000
@@ -0,0 +1,308 @@
1"""Compatibility with the nrpe-external-master charm"""
2# Copyright 2012 Canonical Ltd.
3#
4# Authors:
5# Matthew Wedgwood <matthew.wedgwood@canonical.com>
6
7import subprocess
8import pwd
9import grp
10import os
11import re
12import shlex
13import yaml
14
15from charmhelpers.core.hookenv import (
16 config,
17 local_unit,
18 log,
19 relation_ids,
20 relation_set,
21 relations_of_type,
22)
23
24from charmhelpers.core.host import service
25
26# This module adds compatibility with the nrpe-external-master and plain nrpe
27# subordinate charms. To use it in your charm:
28#
29# 1. Update metadata.yaml
30#
31# provides:
32# (...)
33# nrpe-external-master:
34# interface: nrpe-external-master
35# scope: container
36#
37# and/or
38#
39# provides:
40# (...)
41# local-monitors:
42# interface: local-monitors
43# scope: container
44
45#
46# 2. Add the following to config.yaml
47#
48# nagios_context:
49# default: "juju"
50# type: string
51# description: |
52# Used by the nrpe subordinate charms.
53# A string that will be prepended to instance name to set the host name
54# in nagios. So for instance the hostname would be something like:
55# juju-myservice-0
56# If you're running multiple environments with the same services in them
57# this allows you to differentiate between them.
58# nagios_servicegroups:
59# default: ""
60# type: string
61# description: |
62# A comma-separated list of nagios servicegroups.
63# If left empty, the nagios_context will be used as the servicegroup
64#
65# 3. Add custom checks (Nagios plugins) to files/nrpe-external-master
66#
67# 4. Update your hooks.py with something like this:
68#
69# from charmsupport.nrpe import NRPE
70# (...)
71# def update_nrpe_config():
72# nrpe_compat = NRPE()
73# nrpe_compat.add_check(
74# shortname = "myservice",
75# description = "Check MyService",
76# check_cmd = "check_http -w 2 -c 10 http://localhost"
77# )
78# nrpe_compat.add_check(
79# "myservice_other",
80# "Check for widget failures",
81# check_cmd = "/srv/myapp/scripts/widget_check"
82# )
83# nrpe_compat.write()
84#
85# def config_changed():
86# (...)
87# update_nrpe_config()
88#
89# def nrpe_external_master_relation_changed():
90# update_nrpe_config()
91#
92# def local_monitors_relation_changed():
93# update_nrpe_config()
94#
95# 5. ln -s hooks.py nrpe-external-master-relation-changed
96# ln -s hooks.py local-monitors-relation-changed
97
98
99class CheckException(Exception):
100 pass
101
102
103class Check(object):
104 shortname_re = '[A-Za-z0-9-_]+$'
105 service_template = ("""
106#---------------------------------------------------
107# This file is Juju managed
108#---------------------------------------------------
109define service {{
110 use active-service
111 host_name {nagios_hostname}
112 service_description {nagios_hostname}[{shortname}] """
113 """{description}
114 check_command check_nrpe!{command}
115 servicegroups {nagios_servicegroup}
116}}
117""")
118
119 def __init__(self, shortname, description, check_cmd):
120 super(Check, self).__init__()
121 # XXX: could be better to calculate this from the service name
122 if not re.match(self.shortname_re, shortname):
123 raise CheckException("shortname must match {}".format(
124 Check.shortname_re))
125 self.shortname = shortname
126 self.command = "check_{}".format(shortname)
127 # Note: a set of invalid characters is defined by the
128 # Nagios server config
129 # The default is: illegal_object_name_chars=`~!$%^&*"|'<>?,()=
130 self.description = description
131 self.check_cmd = self._locate_cmd(check_cmd)
132
133 def _locate_cmd(self, check_cmd):
134 search_path = (
135 '/usr/lib/nagios/plugins',
136 '/usr/local/lib/nagios/plugins',
137 )
138 parts = shlex.split(check_cmd)
139 for path in search_path:
140 if os.path.exists(os.path.join(path, parts[0])):
141 command = os.path.join(path, parts[0])
142 if len(parts) > 1:
143 command += " " + " ".join(parts[1:])
144 return command
145 log('Check command not found: {}'.format(parts[0]))
146 return ''
147
148 def write(self, nagios_context, hostname, nagios_servicegroups=None):
149 nrpe_check_file = '/etc/nagios/nrpe.d/{}.cfg'.format(
150 self.command)
151 with open(nrpe_check_file, 'w') as nrpe_check_config:
152 nrpe_check_config.write("# check {}\n".format(self.shortname))
153 nrpe_check_config.write("command[{}]={}\n".format(
154 self.command, self.check_cmd))
155
156 if not os.path.exists(NRPE.nagios_exportdir):
157 log('Not writing service config as {} is not accessible'.format(
158 NRPE.nagios_exportdir))
159 else:
160 self.write_service_config(nagios_context, hostname,
161 nagios_servicegroups)
162
163 def write_service_config(self, nagios_context, hostname,
164 nagios_servicegroups=None):
165 for f in os.listdir(NRPE.nagios_exportdir):
166 if re.search('.*{}.cfg'.format(self.command), f):
167 os.remove(os.path.join(NRPE.nagios_exportdir, f))
168
169 if not nagios_servicegroups:
170 nagios_servicegroups = nagios_context
171
172 templ_vars = {
173 'nagios_hostname': hostname,
174 'nagios_servicegroup': nagios_servicegroups,
175 'description': self.description,
176 'shortname': self.shortname,
177 'command': self.command,
178 }
179 nrpe_service_text = Check.service_template.format(**templ_vars)
180 nrpe_service_file = '{}/service__{}_{}.cfg'.format(
181 NRPE.nagios_exportdir, hostname, self.command)
182 with open(nrpe_service_file, 'w') as nrpe_service_config:
183 nrpe_service_config.write(str(nrpe_service_text))
184
185 def run(self):
186 subprocess.call(self.check_cmd)
187
188
189class NRPE(object):
190 nagios_logdir = '/var/log/nagios'
191 nagios_exportdir = '/var/lib/nagios/export'
192 nrpe_confdir = '/etc/nagios/nrpe.d'
193
194 def __init__(self, hostname=None):
195 super(NRPE, self).__init__()
196 self.config = config()
197 self.nagios_context = self.config['nagios_context']
198 if 'nagios_servicegroups' in self.config:
199 self.nagios_servicegroups = self.config['nagios_servicegroups']
200 else:
201 self.nagios_servicegroups = 'juju'
202 self.unit_name = local_unit().replace('/', '-')
203 if hostname:
204 self.hostname = hostname
205 else:
206 self.hostname = "{}-{}".format(self.nagios_context, self.unit_name)
207 self.checks = []
208
209 def add_check(self, *args, **kwargs):
210 self.checks.append(Check(*args, **kwargs))
211
212 def write(self):
213 try:
214 nagios_uid = pwd.getpwnam('nagios').pw_uid
215 nagios_gid = grp.getgrnam('nagios').gr_gid
216 except:
217 log("Nagios user not set up, nrpe checks not updated")
218 return
219
220 if not os.path.exists(NRPE.nagios_logdir):
221 os.mkdir(NRPE.nagios_logdir)
222 os.chown(NRPE.nagios_logdir, nagios_uid, nagios_gid)
223
224 nrpe_monitors = {}
225 monitors = {"monitors": {"remote": {"nrpe": nrpe_monitors}}}
226 for nrpecheck in self.checks:
227 nrpecheck.write(self.nagios_context, self.hostname,
228 self.nagios_servicegroups)
229 nrpe_monitors[nrpecheck.shortname] = {
230 "command": nrpecheck.command,
231 }
232
233 service('restart', 'nagios-nrpe-server')
234
235 for rid in relation_ids("local-monitors"):
236 relation_set(relation_id=rid, monitors=yaml.dump(monitors))
237
238
239def get_nagios_hostcontext(relation_name='nrpe-external-master'):
240 """
241 Query relation with nrpe subordinate, return the nagios_host_context
242
243 :param str relation_name: Name of relation nrpe sub joined to
244 """
245 for rel in relations_of_type(relation_name):
246 if 'nagios_hostname' in rel:
247 return rel['nagios_host_context']
248
249
250def get_nagios_hostname(relation_name='nrpe-external-master'):
251 """
252 Query relation with nrpe subordinate, return the nagios_hostname
253
254 :param str relation_name: Name of relation nrpe sub joined to
255 """
256 for rel in relations_of_type(relation_name):
257 if 'nagios_hostname' in rel:
258 return rel['nagios_hostname']
259
260
261def get_nagios_unit_name(relation_name='nrpe-external-master'):
262 """
263 Return the nagios unit name prepended with host_context if needed
264
265 :param str relation_name: Name of relation nrpe sub joined to
266 """
267 host_context = get_nagios_hostcontext(relation_name)
268 if host_context:
269 unit = "%s:%s" % (host_context, local_unit())
270 else:
271 unit = local_unit()
272 return unit
273
274
275def add_init_service_checks(nrpe, services, unit_name):
276 """
277 Add checks for each service in list
278
279 :param NRPE nrpe: NRPE object to add check to
280 :param list services: List of services to check
281 :param str unit_name: Unit name to use in check description
282 """
283 for svc in services:
284 upstart_init = '/etc/init/%s.conf' % svc
285 sysv_init = '/etc/init.d/%s' % svc
286 if os.path.exists(upstart_init):
287 nrpe.add_check(
288 shortname=svc,
289 description='process check {%s}' % unit_name,
290 check_cmd='check_upstart_job %s' % svc
291 )
292 elif os.path.exists(sysv_init):
293 cronpath = '/etc/cron.d/nagios-service-check-%s' % svc
294 cron_file = ('*/5 * * * * root '
295 '/usr/local/lib/nagios/plugins/check_exit_status.pl '
296 '-s /etc/init.d/%s status > '
297 '/var/lib/nagios/service-check-%s.txt\n' % (svc,
298 svc)
299 )
300 f = open(cronpath, 'w')
301 f.write(cron_file)
302 f.close()
303 nrpe.add_check(
304 shortname=svc,
305 description='process check {%s}' % unit_name,
306 check_cmd='check_status_file.py -f '
307 '/var/lib/nagios/service-check-%s.txt' % svc,
308 )
0309
=== 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 2015-01-12 14:02:09 +0000
@@ -0,0 +1,159 @@
1'''
2Functions for managing volumes in juju units. One volume is supported per unit.
3Subordinates may have their own storage, provided it is on its own partition.
4
5Configuration stanzas::
6
7 volume-ephemeral:
8 type: boolean
9 default: true
10 description: >
11 If false, a volume is mounted as sepecified in "volume-map"
12 If true, ephemeral storage will be used, meaning that log data
13 will only exist as long as the machine. YOU HAVE BEEN WARNED.
14 volume-map:
15 type: string
16 default: {}
17 description: >
18 YAML map of units to device names, e.g:
19 "{ rsyslog/0: /dev/vdb, rsyslog/1: /dev/vdb }"
20 Service units will raise a configure-error if volume-ephemeral
21 is 'true' and no volume-map value is set. Use 'juju set' to set a
22 value and 'juju resolved' to complete configuration.
23
24Usage::
25
26 from charmsupport.volumes import configure_volume, VolumeConfigurationError
27 from charmsupport.hookenv import log, ERROR
28 def post_mount_hook():
29 stop_service('myservice')
30 def post_mount_hook():
31 start_service('myservice')
32
33 if __name__ == '__main__':
34 try:
35 configure_volume(before_change=pre_mount_hook,
36 after_change=post_mount_hook)
37 except VolumeConfigurationError:
38 log('Storage could not be configured', ERROR)
39
40'''
41
42# XXX: Known limitations
43# - fstab is neither consulted nor updated
44
45import os
46from charmhelpers.core import hookenv
47from charmhelpers.core import host
48import yaml
49
50
51MOUNT_BASE = '/srv/juju/volumes'
52
53
54class VolumeConfigurationError(Exception):
55 '''Volume configuration data is missing or invalid'''
56 pass
57
58
59def get_config():
60 '''Gather and sanity-check volume configuration data'''
61 volume_config = {}
62 config = hookenv.config()
63
64 errors = False
65
66 if config.get('volume-ephemeral') in (True, 'True', 'true', 'Yes', 'yes'):
67 volume_config['ephemeral'] = True
68 else:
69 volume_config['ephemeral'] = False
70
71 try:
72 volume_map = yaml.safe_load(config.get('volume-map', '{}'))
73 except yaml.YAMLError as e:
74 hookenv.log("Error parsing YAML volume-map: {}".format(e),
75 hookenv.ERROR)
76 errors = True
77 if volume_map is None:
78 # probably an empty string
79 volume_map = {}
80 elif not isinstance(volume_map, dict):
81 hookenv.log("Volume-map should be a dictionary, not {}".format(
82 type(volume_map)))
83 errors = True
84
85 volume_config['device'] = volume_map.get(os.environ['JUJU_UNIT_NAME'])
86 if volume_config['device'] and volume_config['ephemeral']:
87 # asked for ephemeral storage but also defined a volume ID
88 hookenv.log('A volume is defined for this unit, but ephemeral '
89 'storage was requested', hookenv.ERROR)
90 errors = True
91 elif not volume_config['device'] and not volume_config['ephemeral']:
92 # asked for permanent storage but did not define volume ID
93 hookenv.log('Ephemeral storage was requested, but there is no volume '
94 'defined for this unit.', hookenv.ERROR)
95 errors = True
96
97 unit_mount_name = hookenv.local_unit().replace('/', '-')
98 volume_config['mountpoint'] = os.path.join(MOUNT_BASE, unit_mount_name)
99
100 if errors:
101 return None
102 return volume_config
103
104
105def mount_volume(config):
106 if os.path.exists(config['mountpoint']):
107 if not os.path.isdir(config['mountpoint']):
108 hookenv.log('Not a directory: {}'.format(config['mountpoint']))
109 raise VolumeConfigurationError()
110 else:
111 host.mkdir(config['mountpoint'])
112 if os.path.ismount(config['mountpoint']):
113 unmount_volume(config)
114 if not host.mount(config['device'], config['mountpoint'], persist=True):
115 raise VolumeConfigurationError()
116
117
118def unmount_volume(config):
119 if os.path.ismount(config['mountpoint']):
120 if not host.umount(config['mountpoint'], persist=True):
121 raise VolumeConfigurationError()
122
123
124def managed_mounts():
125 '''List of all mounted managed volumes'''
126 return filter(lambda mount: mount[0].startswith(MOUNT_BASE), host.mounts())
127
128
129def configure_volume(before_change=lambda: None, after_change=lambda: None):
130 '''Set up storage (or don't) according to the charm's volume configuration.
131 Returns the mount point or "ephemeral". before_change and after_change
132 are optional functions to be called if the volume configuration changes.
133 '''
134
135 config = get_config()
136 if not config:
137 hookenv.log('Failed to read volume configuration', hookenv.CRITICAL)
138 raise VolumeConfigurationError()
139
140 if config['ephemeral']:
141 if os.path.ismount(config['mountpoint']):
142 before_change()
143 unmount_volume(config)
144 after_change()
145 return 'ephemeral'
146 else:
147 # persistent storage
148 if os.path.ismount(config['mountpoint']):
149 mounts = dict(managed_mounts())
150 if mounts.get(config['mountpoint']) != config['device']:
151 before_change()
152 unmount_volume(config)
153 mount_volume(config)
154 after_change()
155 else:
156 before_change()
157 mount_volume(config)
158 after_change()
159 return config['mountpoint']
0160
=== modified file 'hooks/charmhelpers/contrib/hahelpers/cluster.py'
--- hooks/charmhelpers/contrib/hahelpers/cluster.py 2014-12-15 09:10:57 +0000
+++ hooks/charmhelpers/contrib/hahelpers/cluster.py 2015-01-12 14:02:09 +0000
@@ -13,6 +13,7 @@
1313
14import subprocess14import subprocess
15import os15import os
16
16from socket import gethostname as get_unit_hostname17from socket import gethostname as get_unit_hostname
1718
18import six19import six
@@ -28,12 +29,19 @@
28 WARNING,29 WARNING,
29 unit_get,30 unit_get,
30)31)
32from charmhelpers.core.decorators import (
33 retry_on_exception,
34)
3135
3236
33class HAIncompleteConfig(Exception):37class HAIncompleteConfig(Exception):
34 pass38 pass
3539
3640
41class CRMResourceNotFound(Exception):
42 pass
43
44
37def is_elected_leader(resource):45def is_elected_leader(resource):
38 """46 """
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.
@@ -68,24 +76,30 @@
68 return False76 return False
6977
7078
71def is_crm_leader(resource):79@retry_on_exception(5, base_delay=2, exc_type=CRMResourceNotFound)
80def is_crm_leader(resource, retry=False):
72 """81 """
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,
74 as returned by calling the external "crm" command.83 as returned by calling the external "crm" command.
84
85 We allow this operation to be retried to avoid the possibility of getting a
86 false negative. See LP #1396246 for more info.
75 """87 """
76 cmd = [88 cmd = ['crm', 'resource', 'show', resource]
77 "crm", "resource",
78 "show", resource
79 ]
80 try:89 try:
81 status = subprocess.check_output(cmd).decode('UTF-8')90 status = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
91 if not isinstance(status, six.text_type):
92 status = six.text_type(status, "utf-8")
82 except subprocess.CalledProcessError:93 except subprocess.CalledProcessError:
83 return False94 status = None
84 else:95
85 if get_unit_hostname() in status:96 if status and get_unit_hostname() in status:
86 return True97 return True
87 else:98
88 return False99 if status and "resource %s is NOT running" % (resource) in status:
100 raise CRMResourceNotFound("CRM resource %s not found" % (resource))
101
102 return False
89103
90104
91def is_leader(resource):105def is_leader(resource):
92106
=== modified file 'hooks/charmhelpers/contrib/network/ufw.py'
--- hooks/charmhelpers/contrib/network/ufw.py 2014-12-10 20:28:56 +0000
+++ hooks/charmhelpers/contrib/network/ufw.py 2015-01-12 14:02:09 +0000
@@ -54,6 +54,17 @@
54 if is_enabled():54 if is_enabled():
55 return True55 return True
5656
57 if not os.path.isdir('/proc/sys/net/ipv6'):
58 # disable IPv6 support in ufw
59 hookenv.log("This machine doesn't have IPv6 enabled", level="INFO")
60 exit_code = subprocess.call(['sed', '-i', 's/IPV6=yes/IPV6=no/g',
61 '/etc/default/ufw'])
62 if exit_code == 0:
63 hookenv.log('IPv6 support in ufw disabled', level='INFO')
64 else:
65 hookenv.log("Couldn't disable IPv6 support in ufw", level="ERROR")
66 raise Exception("Couldn't disable IPv6 support in ufw")
67
57 output = subprocess.check_output(['ufw', 'enable'],68 output = subprocess.check_output(['ufw', 'enable'],
58 env={'LANG': 'en_US',69 env={'LANG': 'en_US',
59 'PATH': os.environ['PATH']})70 'PATH': os.environ['PATH']})
6071
=== modified file 'hooks/charmhelpers/contrib/openstack/context.py'
--- hooks/charmhelpers/contrib/openstack/context.py 2014-12-15 10:28:47 +0000
+++ hooks/charmhelpers/contrib/openstack/context.py 2015-01-12 14:02:09 +0000
@@ -491,6 +491,7 @@
491 ctxt['haproxy_client_timeout'] = config('haproxy-client-timeout')491 ctxt['haproxy_client_timeout'] = config('haproxy-client-timeout')
492492
493 if config('prefer-ipv6'):493 if config('prefer-ipv6'):
494 ctxt['ipv6'] = True
494 ctxt['local_host'] = 'ip6-localhost'495 ctxt['local_host'] = 'ip6-localhost'
495 ctxt['haproxy_host'] = '::'496 ctxt['haproxy_host'] = '::'
496 ctxt['stat_port'] = ':::8888'497 ctxt['stat_port'] = ':::8888'
497498
=== modified file 'hooks/charmhelpers/contrib/openstack/neutron.py'
--- hooks/charmhelpers/contrib/openstack/neutron.py 2014-12-15 10:28:47 +0000
+++ hooks/charmhelpers/contrib/openstack/neutron.py 2015-01-12 14:02:09 +0000
@@ -152,9 +152,15 @@
152 database=config('neutron-database'),152 database=config('neutron-database'),
153 relation_prefix='neutron',153 relation_prefix='neutron',
154 ssl_dir=NEUTRON_CONF_DIR)],154 ssl_dir=NEUTRON_CONF_DIR)],
155 'services': ['calico-compute', 'bird', 'neutron-dhcp-agent'],155 'services': ['calico-felix',
156 'bird',
157 'neutron-dhcp-agent',
158 'nova-api-metadata'],
156 'packages': [[headers_package()] + determine_dkms_package(),159 'packages': [[headers_package()] + determine_dkms_package(),
157 ['calico-compute', 'bird', 'neutron-dhcp-agent']],160 ['calico-compute',
161 'bird',
162 'neutron-dhcp-agent',
163 'nova-api-metadata']],
158 'server_packages': ['neutron-server', 'calico-control'],164 'server_packages': ['neutron-server', 'calico-control'],
159 'server_services': ['neutron-server']165 'server_services': ['neutron-server']
160 }166 }
161167
=== modified file 'hooks/charmhelpers/contrib/openstack/templates/haproxy.cfg'
--- hooks/charmhelpers/contrib/openstack/templates/haproxy.cfg 2014-12-15 09:10:57 +0000
+++ hooks/charmhelpers/contrib/openstack/templates/haproxy.cfg 2015-01-12 14:02:09 +0000
@@ -38,7 +38,9 @@
38{% for service, ports in service_ports.items() -%}38{% for service, ports in service_ports.items() -%}
39frontend tcp-in_{{ service }}39frontend tcp-in_{{ service }}
40 bind *:{{ ports[0] }}40 bind *:{{ ports[0] }}
41 {% if ipv6 -%}
41 bind :::{{ ports[0] }}42 bind :::{{ ports[0] }}
43 {% endif -%}
42 {% for frontend in frontends -%}44 {% for frontend in frontends -%}
43 acl net_{{ frontend }} dst {{ frontends[frontend]['network'] }}45 acl net_{{ frontend }} dst {{ frontends[frontend]['network'] }}
44 use_backend {{ service }}_{{ frontend }} if net_{{ frontend }}46 use_backend {{ service }}_{{ frontend }} if net_{{ frontend }}
4547
=== modified file 'hooks/charmhelpers/contrib/openstack/utils.py'
--- hooks/charmhelpers/contrib/openstack/utils.py 2014-12-15 10:28:47 +0000
+++ hooks/charmhelpers/contrib/openstack/utils.py 2015-01-12 14:02:09 +0000
@@ -53,6 +53,7 @@
53 ('saucy', 'havana'),53 ('saucy', 'havana'),
54 ('trusty', 'icehouse'),54 ('trusty', 'icehouse'),
55 ('utopic', 'juno'),55 ('utopic', 'juno'),
56 ('vivid', 'kilo'),
56])57])
5758
5859
@@ -64,6 +65,7 @@
64 ('2013.2', 'havana'),65 ('2013.2', 'havana'),
65 ('2014.1', 'icehouse'),66 ('2014.1', 'icehouse'),
66 ('2014.2', 'juno'),67 ('2014.2', 'juno'),
68 ('2015.1', 'kilo'),
67])69])
6870
69# The ugly duckling71# The ugly duckling
@@ -84,6 +86,7 @@
84 ('2.0.0', 'juno'),86 ('2.0.0', 'juno'),
85 ('2.1.0', 'juno'),87 ('2.1.0', 'juno'),
86 ('2.2.0', 'juno'),88 ('2.2.0', 'juno'),
89 ('2.2.1', 'kilo'),
87])90])
8891
89DEFAULT_LOOPBACK_SIZE = '5G'92DEFAULT_LOOPBACK_SIZE = '5G'
@@ -289,6 +292,9 @@
289 'juno': 'trusty-updates/juno',292 'juno': 'trusty-updates/juno',
290 'juno/updates': 'trusty-updates/juno',293 'juno/updates': 'trusty-updates/juno',
291 'juno/proposed': 'trusty-proposed/juno',294 'juno/proposed': 'trusty-proposed/juno',
295 'kilo': 'trusty-updates/kilo',
296 'kilo/updates': 'trusty-updates/kilo',
297 'kilo/proposed': 'trusty-proposed/kilo',
292 }298 }
293299
294 try:300 try:
295301
=== added file 'hooks/charmhelpers/core/decorators.py'
--- hooks/charmhelpers/core/decorators.py 1970-01-01 00:00:00 +0000
+++ hooks/charmhelpers/core/decorators.py 2015-01-12 14:02:09 +0000
@@ -0,0 +1,41 @@
1#
2# Copyright 2014 Canonical Ltd.
3#
4# Authors:
5# Edward Hope-Morley <opentastic@gmail.com>
6#
7
8import time
9
10from charmhelpers.core.hookenv import (
11 log,
12 INFO,
13)
14
15
16def retry_on_exception(num_retries, base_delay=0, exc_type=Exception):
17 """If the decorated function raises exception exc_type, allow num_retries
18 retry attempts before raise the exception.
19 """
20 def _retry_on_exception_inner_1(f):
21 def _retry_on_exception_inner_2(*args, **kwargs):
22 retries = num_retries
23 multiplier = 1
24 while True:
25 try:
26 return f(*args, **kwargs)
27 except exc_type:
28 if not retries:
29 raise
30
31 delay = base_delay * multiplier
32 multiplier += 1
33 log("Retrying '%s' %d more times (delay=%s)" %
34 (f.__name__, retries, delay), level=INFO)
35 retries -= 1
36 if delay:
37 time.sleep(delay)
38
39 return _retry_on_exception_inner_2
40
41 return _retry_on_exception_inner_1
042
=== modified file 'hooks/charmhelpers/core/host.py'
--- hooks/charmhelpers/core/host.py 2014-12-15 10:28:47 +0000
+++ hooks/charmhelpers/core/host.py 2015-01-12 14:02:09 +0000
@@ -162,13 +162,16 @@
162 uid = pwd.getpwnam(owner).pw_uid162 uid = pwd.getpwnam(owner).pw_uid
163 gid = grp.getgrnam(group).gr_gid163 gid = grp.getgrnam(group).gr_gid
164 realpath = os.path.abspath(path)164 realpath = os.path.abspath(path)
165 if os.path.exists(realpath):165 path_exists = os.path.exists(realpath)
166 if force and not os.path.isdir(realpath):166 if path_exists and force:
167 if not os.path.isdir(realpath):
167 log("Removing non-directory file {} prior to mkdir()".format(path))168 log("Removing non-directory file {} prior to mkdir()".format(path))
168 os.unlink(realpath)169 os.unlink(realpath)
169 else:170 os.makedirs(realpath, perms)
171 os.chown(realpath, uid, gid)
172 elif not path_exists:
170 os.makedirs(realpath, perms)173 os.makedirs(realpath, perms)
171 os.chown(realpath, uid, gid)174 os.chown(realpath, uid, gid)
172175
173176
174def write_file(path, content, owner='root', group='root', perms=0o444):177def write_file(path, content, owner='root', group='root', perms=0o444):
175178
=== modified file 'hooks/charmhelpers/fetch/__init__.py'
--- hooks/charmhelpers/fetch/__init__.py 2014-12-15 10:28:47 +0000
+++ hooks/charmhelpers/fetch/__init__.py 2015-01-12 14:02:09 +0000
@@ -64,9 +64,16 @@
64 'trusty-juno/updates': 'trusty-updates/juno',64 'trusty-juno/updates': 'trusty-updates/juno',
65 'trusty-updates/juno': 'trusty-updates/juno',65 'trusty-updates/juno': 'trusty-updates/juno',
66 'juno/proposed': 'trusty-proposed/juno',66 'juno/proposed': 'trusty-proposed/juno',
67 'juno/proposed': 'trusty-proposed/juno',
68 'trusty-juno/proposed': 'trusty-proposed/juno',67 'trusty-juno/proposed': 'trusty-proposed/juno',
69 'trusty-proposed/juno': 'trusty-proposed/juno',68 'trusty-proposed/juno': 'trusty-proposed/juno',
69 # Kilo
70 'kilo': 'trusty-updates/kilo',
71 'trusty-kilo': 'trusty-updates/kilo',
72 'trusty-kilo/updates': 'trusty-updates/kilo',
73 'trusty-updates/kilo': 'trusty-updates/kilo',
74 'kilo/proposed': 'trusty-proposed/kilo',
75 'trusty-kilo/proposed': 'trusty-proposed/kilo',
76 'trusty-proposed/kilo': 'trusty-proposed/kilo',
70}77}
7178
72# The order of this list is very important. Handlers should be listed in from79# The order of this list is very important. Handlers should be listed in from
7380
=== added symlink 'hooks/compute-peer-relation-joined'
=== target is u'nova_compute_hooks.py'
=== added symlink 'hooks/neutron-plugin-relation-changed'
=== target is u'nova_compute_hooks.py'
=== added symlink 'hooks/neutron-plugin-relation-departed'
=== target is u'nova_compute_hooks.py'
=== added symlink 'hooks/neutron-plugin-relation-joined'
=== target is u'nova_compute_hooks.py'
=== modified file 'hooks/nova_compute_hooks.py'
--- hooks/nova_compute_hooks.py 2014-12-15 10:28:47 +0000
+++ hooks/nova_compute_hooks.py 2015-01-12 14:02:09 +0000
@@ -48,6 +48,7 @@
48 do_openstack_upgrade,48 do_openstack_upgrade,
49 public_ssh_key,49 public_ssh_key,
50 restart_map,50 restart_map,
51 services,
51 register_configs,52 register_configs,
52 NOVA_CONF,53 NOVA_CONF,
53 QUANTUM_CONF, NEUTRON_CONF,54 QUANTUM_CONF, NEUTRON_CONF,
@@ -65,6 +66,7 @@
65 CEPH_SECRET_UUID,66 CEPH_SECRET_UUID,
66 assert_libvirt_imagebackend_allowed67 assert_libvirt_imagebackend_allowed
67)68)
69from charmhelpers.contrib.charmsupport import nrpe
68from charmhelpers.core.sysctl import create as create_sysctl70from charmhelpers.core.sysctl import create as create_sysctl
6971
70from socket import gethostname72from socket import gethostname
@@ -114,6 +116,8 @@
114116
115 [compute_joined(rid) for rid in relation_ids('cloud-compute')]117 [compute_joined(rid) for rid in relation_ids('cloud-compute')]
116118
119 update_nrpe_config()
120
117 CONFIGS.write_all()121 CONFIGS.write_all()
118122
119123
@@ -292,6 +296,7 @@
292def upgrade_charm():296def upgrade_charm():
293 for r_id in relation_ids('amqp'):297 for r_id in relation_ids('amqp'):
294 amqp_joined(relation_id=r_id)298 amqp_joined(relation_id=r_id)
299 update_nrpe_config()
295300
296301
297@hooks.hook('nova-ceilometer-relation-changed')302@hooks.hook('nova-ceilometer-relation-changed')
@@ -300,6 +305,18 @@
300 CONFIGS.write_all()305 CONFIGS.write_all()
301306
302307
308@hooks.hook('nrpe-external-master-relation-joined',
309 'nrpe-external-master-relation-changed')
310def update_nrpe_config():
311 # python-dbus is used by check_upstart_job
312 apt_install('python-dbus')
313 hostname = nrpe.get_nagios_hostname()
314 current_unit = nrpe.get_nagios_unit_name()
315 nrpe_setup = nrpe.NRPE(hostname=hostname)
316 nrpe.add_init_service_checks(nrpe_setup, services(), current_unit)
317 nrpe_setup.write()
318
319
303def main():320def main():
304 try:321 try:
305 hooks.execute(sys.argv)322 hooks.execute(sys.argv)
306323
=== added symlink 'hooks/nrpe-external-master-relation-changed'
=== target is u'nova_compute_hooks.py'
=== added symlink 'hooks/start'
=== target is u'nova_compute_hooks.py'
=== added symlink 'hooks/stop'
=== target is u'nova_compute_hooks.py'
=== modified file 'unit_tests/test_nova_compute_hooks.py'
--- unit_tests/test_nova_compute_hooks.py 2014-12-15 10:28:47 +0000
+++ unit_tests/test_nova_compute_hooks.py 2015-01-12 14:02:09 +0000
@@ -46,6 +46,7 @@
46 'register_configs',46 'register_configs',
47 'disable_shell',47 'disable_shell',
48 'enable_shell',48 'enable_shell',
49 'update_nrpe_config',
49 # misc_utils50 # misc_utils
50 'ensure_ceph_keyring',51 'ensure_ceph_keyring',
51 'execd_preinstall',52 'execd_preinstall',

Subscribers

People subscribed via source and target branches