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