Coverage for reactive/openstack_service_checks.py : 0%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: us-ascii -*-
2"""
3install_osc +------------------------> render_config+--------------> do_restart
4 ^ + ^
5conf_kst_user+---> save_creds +-----------+ v |
6 create_endpoints +-----+
8Available states:
9 identity-credentials.available: kst creds available
10 identity-credentials.connected: kst relation joined
11 nrpe-external-master.available: nrpe relation joined
12 openstack-service-checks.configured: render_config allowed
13 openstack-service-checks.endpoints.configured: create_endpoints allowed
14 openstack-service-checks.installed: install_osc entrypoint
15 openstack-service-checks.started: if not set, restart nagios-nrpe-server
16 openstack-service-checks.stored-creds: kst creds available for the unit
17"""
18import base64
19import subprocess
21from charmhelpers.core import hookenv, host, unitdata
22from charms.reactive import any_flags_set, clear_flag, is_flag_set, set_flag, when, when_not
24from lib_openstack_service_checks import (
25 OSCHelper,
26 OSCCredentialsError,
27 OSCEndpointError
28)
30CERT_FILE = '/usr/local/share/ca-certificates/openstack-service-checks.crt'
31helper = OSCHelper()
34@when('config.changed')
35def config_changed():
36 clear_flag('openstack-service-checks.configured')
39@when_not('openstack-service-checks.installed')
40@when('nrpe-external-master.available')
41def install_openstack_service_checks():
42 """Entry point to start configuring the unit
44 Triggered if related to the nrpe-external-master relation.
45 Some relation data can be initialized if the application is related to
46 keystone.
47 """
48 set_flag('openstack-service-checks.installed')
49 clear_flag('openstack-service-checks.configured')
52@when_not('identity-credentials.available')
53@when('identity-credentials.connected')
54def configure_ident_username(keystone):
55 """Requests a user to the Identity Service
56 """
57 username = 'nagios'
58 keystone.request_credentials(username)
59 clear_flag('openstack-service-checks.stored-creds')
62@when_not('openstack-service-checks.stored-creds')
63@when('identity-credentials.available')
64def save_creds(keystone):
65 """Collect and save credentials from Keystone relation.
67 Get credentials from the Keystone relation,
68 reformat them into something the Keystone client can use, and
69 save them into the unitdata.
70 """
71 creds = {'username': keystone.credentials_username(),
72 'password': keystone.credentials_password(),
73 'region': keystone.region(),
74 }
75 if keystone.api_version() == '3':
76 api_url = 'v3'
77 try:
78 domain = keystone.domain()
79 except AttributeError:
80 domain = 'service_domain'
81 # keystone relation sends info back with funny names, fix here
82 creds.update({'project_name': keystone.credentials_project(),
83 'auth_version': '3',
84 'user_domain_name': domain,
85 'project_domain_name': domain})
86 else:
87 api_url = 'v2.0'
88 creds['tenant_name'] = keystone.credentials_project()
90 creds['auth_url'] = '{proto}://{host}:{port}/{api_url}'.format(
91 proto=keystone.auth_protocol(), host=keystone.auth_host(),
92 port=keystone.auth_port(), api_url=api_url)
94 helper.store_keystone_credentials(creds)
95 set_flag('openstack-service-checks.stored-creds')
96 clear_flag('openstack-service-checks.configured')
99@when_not('identity-credentials.connected')
100@when_not('identity-credentials.available')
101@when('openstack-service-checks.stored-creds')
102def allow_keystone_store_overwrite():
103 """Allow unitdata overwrite if keystone relation is recycled.
104 """
105 clear_flag('openstack-service-checks.stored-creds')
108@when('identity-credentials.available.updated')
109def update_keystone_store():
110 """when identity-service-relation-changed is triggered, update the stored credentials
111 """
112 allow_keystone_store_overwrite()
115def get_credentials():
116 """Get credential info from either config or relation data
118 If config 'os-credentials' is set, return it. Otherwise look for a
119 keystonecreds relation data.
120 """
121 try:
122 creds = helper.get_os_credentials()
123 except OSCCredentialsError as error:
124 creds = helper.get_keystone_credentials()
125 if not creds:
126 hookenv.log('render_config: No credentials yet, skipping')
127 hookenv.status_set('blocked',
128 'Missing os-credentials vars: {}'.format(error))
129 return
130 return creds
133@when('openstack-service-checks.installed')
134@when_not('openstack-service-checks.configured')
135def render_config():
136 """Render nrpe checks from the templates
138 This code is only triggered after the nrpe relation is set. If a relation
139 with keystone is later set, it will be re-triggered. On the other hand,
140 if a keystone relation exists but not a nrpe relation, it won't be run.
142 Furthermore, juju config os-credentials take precedence over keystone
143 related data.
144 """
145 def block_tls_failure(error):
146 hookenv.log('update-ca-certificates failed: {}'.format(error),
147 hookenv.ERROR)
148 hookenv.status_set('blocked',
149 'update-ca-certificates error. check logs')
150 return
152 creds = get_credentials()
153 if not creds:
154 return
156 # Fix TLS
157 if helper.charm_config['trusted_ssl_ca'].strip():
158 trusted_ssl_ca = helper.charm_config['trusted_ssl_ca'].strip()
159 hookenv.log('Writing ssl ca cert:{}'.format(trusted_ssl_ca))
160 cert_content = base64.b64decode(trusted_ssl_ca).decode()
161 try:
162 with open(CERT_FILE, 'w') as fd:
163 fd.write(cert_content)
164 subprocess.call(['/usr/sbin/update-ca-certificates'])
166 except subprocess.CalledProcessError as error:
167 block_tls_failure(error)
168 return
169 except PermissionError as error:
170 block_tls_failure(error)
171 return
173 hookenv.log('render_config: Got credentials for'
174 ' username={}'.format(creds.get('username')))
176 try:
177 helper.render_checks(creds)
178 set_flag('openstack-service-checks.endpoints.configured')
179 except OSCEndpointError as error:
180 hookenv.log(error)
182 if not helper.deploy_rally():
183 # Rally could not be installed (if enabled). No further actions taken
184 return
186 set_flag('openstack-service-checks.configured')
187 clear_flag('openstack-service-checks.started')
190@when('openstack-service-checks.installed')
191@when('openstack-service-checks.configured')
192@when_not('openstack-service-checks.endpoints.configured')
193def configure_nrpe_endpoints():
194 """Create an NRPE check for each Keystone catalog endpoint.
196 Read the Keystone catalog, and create a check for each endpoint listed.
197 If there is a healthcheck endpoint for the API, use that URL. Otherwise,
198 check the url '/'.
200 If TLS is enabled, add a check for the cert.
201 """
202 creds = get_credentials()
203 if not creds:
204 return
206 try:
207 helper.create_endpoint_checks(creds)
208 set_flag('openstack-service-checks.endpoints.configured')
209 clear_flag('openstack-service-checks.started')
210 except OSCEndpointError as error:
211 hookenv.log(error)
214@when('openstack-service-checks.configured')
215@when_not('openstack-service-checks.started')
216def do_restart():
217 hookenv.log('Reloading nagios-nrpe-server')
218 host.service_restart('nagios-nrpe-server')
219 hookenv.status_set('active', 'Unit is ready')
220 set_flag('openstack-service-checks.started')
223@when('nrpe-external-master.available')
224def do_reconfigure_nrpe():
225 os_credentials_flag = 'config.changed.os-credentials'
226 flags = ['config.changed.check_{}_urls'.format(interface) for interface in ['admin', 'internal', 'public']]
227 flags.extend(os_credentials_flag)
229 if is_flag_set('config.changed'):
230 clear_flag('openstack-service-checks.configured')
232 if any_flags_set(*flags):
233 if is_flag_set(os_credentials_flag):
234 clear_flag('openstack-service-checks.configured')
235 clear_flag('openstack-service-checks.endpoints.configured')
237 if helper.is_rally_enabled:
238 helper.reconfigure_tempest()
240 if is_flag_set('config.changed.skip-rally'):
241 helper.update_rally_checkfiles()
244@when_not('nrpe-external-master.available')
245def missing_nrpe():
246 """Avoid a user action to be missed or overwritten by another hook
247 """
248 if hookenv.hook_name() != 'update-status':
249 hookenv.status_set('blocked', 'Missing relations: nrpe')
252@when('openstack-service-checks.installed')
253@when('nrpe-external-master.available')
254def parse_hooks():
255 if hookenv.hook_name() == 'upgrade-charm':
256 # Check if creds storage needs to be migrated
257 # Old key: keystone-relation-creds
258 # New key: keystonecreds
259 kv = unitdata.kv()
260 creds = kv.get('keystonecreds')
261 old_creds = kv.get('keystone-relation-creds')
262 if old_creds and not creds:
263 # This set of creds needs an update to a newer format
264 creds = {
265 'username': old_creds['credentials_username'],
266 'password': old_creds['credentials_password'],
267 'project_name': old_creds['credentials_project'],
268 'tenant_name': old_creds['credentials_project'],
269 'user_domain_name': old_creds.get('credentials_user_domain'),
270 'project_domain_name': old_creds.get('credentials_project_domain'),
271 }
272 kv.set('keystonecreds', creds)
274 if old_creds:
275 kv.unset('keystone-relation-creds')
277 # update rally check files and plugins, which may have changed
278 helper.update_plugins()
279 helper.update_rally_checkfiles()
281 # render configs again
282 do_reconfigure_nrpe()