Hide keyboard shortcuts

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 +-----+ 

7 

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 

20 

21from charmhelpers.core import hookenv, host, unitdata 

22from charms.reactive import any_flags_set, clear_flag, is_flag_set, set_flag, when, when_not 

23 

24from lib_openstack_service_checks import ( 

25 OSCHelper, 

26 OSCCredentialsError, 

27 OSCEndpointError 

28) 

29 

30CERT_FILE = '/usr/local/share/ca-certificates/openstack-service-checks.crt' 

31helper = OSCHelper() 

32 

33 

34@when('config.changed') 

35def config_changed(): 

36 clear_flag('openstack-service-checks.configured') 

37 

38 

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 

43 

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') 

50 

51 

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') 

60 

61 

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. 

66 

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() 

89 

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) 

93 

94 helper.store_keystone_credentials(creds) 

95 set_flag('openstack-service-checks.stored-creds') 

96 clear_flag('openstack-service-checks.configured') 

97 

98 

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') 

106 

107 

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() 

113 

114 

115def get_credentials(): 

116 """Get credential info from either config or relation data 

117 

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 

131 

132 

133@when('openstack-service-checks.installed') 

134@when_not('openstack-service-checks.configured') 

135def render_config(): 

136 """Render nrpe checks from the templates 

137 

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. 

141 

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 

151 

152 creds = get_credentials() 

153 if not creds: 

154 return 

155 

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']) 

165 

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 

172 

173 hookenv.log('render_config: Got credentials for' 

174 ' username={}'.format(creds.get('username'))) 

175 

176 try: 

177 helper.render_checks(creds) 

178 set_flag('openstack-service-checks.endpoints.configured') 

179 except OSCEndpointError as error: 

180 hookenv.log(error) 

181 

182 if not helper.deploy_rally(): 

183 # Rally could not be installed (if enabled). No further actions taken 

184 return 

185 

186 set_flag('openstack-service-checks.configured') 

187 clear_flag('openstack-service-checks.started') 

188 

189 

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. 

195 

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 '/'. 

199 

200 If TLS is enabled, add a check for the cert. 

201 """ 

202 creds = get_credentials() 

203 if not creds: 

204 return 

205 

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) 

212 

213 

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') 

221 

222 

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) 

228 

229 if is_flag_set('config.changed'): 

230 clear_flag('openstack-service-checks.configured') 

231 

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') 

236 

237 if helper.is_rally_enabled: 

238 helper.reconfigure_tempest() 

239 

240 if is_flag_set('config.changed.skip-rally'): 

241 helper.update_rally_checkfiles() 

242 

243 

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') 

250 

251 

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) 

273 

274 if old_creds: 

275 kv.unset('keystone-relation-creds') 

276 

277 # update rally check files and plugins, which may have changed 

278 helper.update_plugins() 

279 helper.update_rally_checkfiles() 

280 

281 # render configs again 

282 do_reconfigure_nrpe()