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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

# -*- coding: us-ascii -*- 

""" 

install_osc +------------------------> render_config+--------------> do_restart 

^ + ^ 

conf_kst_user+---> save_creds +-----------+ v | 

create_endpoints +-----+ 

 

Available states: 

identity-credentials.available: kst creds available 

identity-credentials.connected: kst relation joined 

nrpe-external-master.available: nrpe relation joined 

openstack-service-checks.configured: render_config allowed 

openstack-service-checks.endpoints.configured: create_endpoints allowed 

openstack-service-checks.installed: install_osc entrypoint 

openstack-service-checks.started: if not set, restart nagios-nrpe-server 

openstack-service-checks.stored-creds: kst creds available for the unit 

""" 

import base64 

import subprocess 

 

from charmhelpers.core import hookenv, host, unitdata 

from charms.reactive import clear_flag, set_flag, when, when_not 

 

from lib_openstack_service_checks import ( 

OSCHelper, 

OSCCredentialsError, 

OSCEndpointError 

) 

 

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

helper = OSCHelper() 

 

 

@when_not('openstack-service-checks.installed') 

@when('nrpe-external-master.available') 

def install_openstack_service_checks(): 

"""Entry point to start configuring the unit 

 

Triggered if related to the nrpe-external-master relation. 

Some relation data can be initialized if the application is related to 

keystone. 

""" 

set_flag('openstack-service-checks.installed') 

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

 

 

@when_not('identity-credentials.available') 

@when('identity-credentials.connected') 

def configure_ident_username(keystone): 

"""Requests a user to the Identity Service 

""" 

username = 'nagios' 

keystone.request_credentials(username) 

clear_flag('openstack-service-checks.stored-creds') 

 

 

@when_not('openstack-service-checks.stored-creds') 

@when('identity-credentials.available') 

def save_creds(keystone): 

"""Collect and save credentials from Keystone relation. 

 

Get credentials from the Keystone relation, 

reformat them into something the Keystone client can use, and 

save them into the unitdata. 

""" 

creds = {'username': keystone.credentials_username(), 

'password': keystone.credentials_password(), 

'region': keystone.region(), 

} 

if keystone.api_version() == '3': 

api_url = 'v3' 

try: 

domain = keystone.domain() 

except AttributeError: 

domain = 'service_domain' 

# keystone relation sends info back with funny names, fix here 

creds.update({'project_name': keystone.credentials_project(), 

'auth_version': '3', 

'user_domain_name': domain, 

'project_domain_name': domain}) 

else: 

api_url = 'v2.0' 

creds['tenant_name'] = keystone.credentials_project() 

 

creds['auth_url'] = '{proto}://{host}:{port}/{api_url}'.format( 

proto=keystone.auth_protocol(), host=keystone.auth_host(), 

port=keystone.auth_port(), api_url=api_url) 

 

helper.store_keystone_credentials(creds) 

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

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

 

 

@when_not('identity-credentials.connected') 

@when_not('identity-credentials.available') 

@when('openstack-service-checks.stored-creds') 

def allow_keystone_store_overwrite(): 

"""Allow unitdata overwrite if keystone relation is recycled. 

""" 

clear_flag('openstack-service-checks.stored-creds') 

 

 

def get_credentials(): 

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

 

If config 'os-credentials' is set, return it. Otherwise look for a 

keystonecreds relation data. 

""" 

try: 

creds = helper.get_os_credentials() 

except OSCCredentialsError as error: 

creds = helper.get_keystone_credentials() 

if not creds: 

hookenv.log('render_config: No credentials yet, skipping') 

hookenv.status_set('blocked', 

'Missing os-credentials vars: {}'.format(error)) 

return 

return creds 

 

 

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

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

def render_config(): 

"""Render nrpe checks from the templates 

 

This code is only triggered after the nrpe relation is set. If a relation 

with keystone is later set, it will be re-triggered. On the other hand, 

if a keystone relation exists but not a nrpe relation, it won't be run. 

 

Furthermore, juju config os-credentials take precedence over keystone 

related data. 

""" 

def block_tls_failure(error): 

hookenv.log('update-ca-certificates failed: {}'.format(error), 

hookenv.ERROR) 

hookenv.status_set('blocked', 

'update-ca-certificates error. check logs') 

return 

 

creds = get_credentials() 

if not creds: 

return 

 

# Fix TLS 

if helper.charm_config['trusted_ssl_ca'].strip(): 

trusted_ssl_ca = helper.charm_config['trusted_ssl_ca'].strip() 

hookenv.log('Writing ssl ca cert:{}'.format(trusted_ssl_ca)) 

cert_content = base64.b64decode(trusted_ssl_ca).decode() 

try: 

with open(CERT_FILE, 'w') as fd: 

fd.write(cert_content) 

subprocess.call(['/usr/sbin/update-ca-certificates']) 

 

except subprocess.CalledProcessError as error: 

block_tls_failure(error) 

return 

except PermissionError as error: 

block_tls_failure(error) 

return 

 

hookenv.log('render_config: Got credentials for' 

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

 

try: 

helper.render_checks(creds) 

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

except OSCEndpointError as error: 

hookenv.log(error) 

 

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

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

 

 

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

@when('openstack-service-checks.configured') 

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

def configure_nrpe_endpoints(): 

"""Create an NRPE check for each Keystone catalog endpoint. 

 

Read the Keystone catalog, and create a check for each endpoint listed. 

If there is a healthcheck endpoint for the API, use that URL. Otherwise, 

check the url '/'. 

 

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

""" 

creds = get_credentials() 

if not creds: 

return 

 

try: 

helper.create_endpoint_checks(creds) 

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

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

except OSCEndpointError as error: 

hookenv.log(error) 

 

 

@when('openstack-service-checks.configured') 

@when_not('openstack-service-checks.started') 

def do_restart(): 

hookenv.log('Reloading nagios-nrpe-server') 

host.service_restart('nagios-nrpe-server') 

hookenv.status_set('active', 'Unit is ready') 

set_flag('openstack-service-checks.started') 

 

 

@when('config.changed.os-credentials') 

@when('nrpe-external-master.available') 

def do_reconfigure_nrpe(): 

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

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

 

 

@when_not('nrpe-external-master.available') 

def missing_nrpe(): 

"""Avoid a user action to be missed or overwritten by another hook 

""" 

if hookenv.hook_name() != 'update-status': 

hookenv.status_set('blocked', 'Missing relations: nrpe') 

 

 

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

@when('nrpe-external-master.available') 

def parse_hooks(): 

if hookenv.hook_name() == 'upgrade-charm': 

# Check if creds storage needs to be migrated 

# Old key: keystone-relation-creds 

# New key: keystonecreds 

kv = unitdata.kv() 

creds = kv.get('keystonecreds') 

old_creds = kv.get('keystone-relation-creds') 

if old_creds and not creds: 

# This set of creds needs an update to a newer format 

creds = { 

'username': old_creds['credentials_username'], 

'password': old_creds['credentials_password'], 

'project_name': old_creds['credentials_project'], 

'tenant_name': old_creds['credentials_project'], 

'user_domain_name': old_creds.get('credentials_user_domain'), 

'project_domain_name': old_creds.get('credentials_project_domain'), 

} 

kv.set('keystonecreds', creds) 

 

if old_creds: 

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

 

# render configs again 

do_reconfigure_nrpe()