From 35c0839b320ad05334ca06b28768f9bab0a056ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20MOHIER?= Date: Tue, 24 Jan 2017 13:50:43 +0100 Subject: [PATCH] Closes #261 - update overall state even if state do not change Compute overall host/service state on insertion Fix broken tests --- alignak_backend/app.py | 88 +++++++++++++++++++++++++++++++++----- test/test_hook_template.py | 11 +++-- test/test_overall_state.py | 27 +++++++++--- 3 files changed, 106 insertions(+), 20 deletions(-) diff --git a/alignak_backend/app.py b/alignak_backend/app.py index 6a9579e7..ba24b0c5 100755 --- a/alignak_backend/app.py +++ b/alignak_backend/app.py @@ -1080,6 +1080,40 @@ def pre_host_patch(updates, original): del updates['_updated'] +def after_insert_host(items): + """ + Hook after host inserted. + + :param items: host fields + :type items: dict + :return: None + """ + for dummy, item in enumerate(items): + overall_state = 0 + + acknowledged = item['ls_acknowledged'] + downtimed = item['ls_downtimed'] + state = item['ls_state'] + state = state.upper() + + if acknowledged: + overall_state = 1 + elif downtimed: + overall_state = 2 + else: + if state == 'UNREACHABLE': + overall_state = 3 + elif state == 'DOWN': + overall_state = 4 + + # Do not care about services... when inserting an host, + # services are not yet existing for this host! + + # Host overall was computed, update the host overall state + lookup = {"_id": item['_id']} + patch_internal('host', {"_overall_state_id": overall_state}, False, False, **lookup) + + def pre_service_patch(updates, original): """ Hook before updating a service element. @@ -1110,9 +1144,9 @@ def pre_service_patch(updates, original): :type original: dict :return: None """ - - if '_overall_state_id' in updates: - abort(make_response("Updating _overall_state_id for a service is forbidden", 412)) + # Allow update because it must be done when inserting a service + # if '_overall_state_id' in updates: + # abort(make_response("Updating _overall_state_id for a service is forbidden", 412)) for key in updates: if key not in ['_overall_state_id', '_updated', '_realm'] and not key.startswith('ls_'): @@ -1121,11 +1155,7 @@ def pre_service_patch(updates, original): # pylint: disable=too-many-boolean-expressions if 'ls_state_type' in updates and updates['ls_state_type'] == 'HARD': # We updated the service live state, compute the new overall state - if ('ls_state' in updates and updates['ls_state'] != original['ls_state']) or \ - ('ls_acknowledged' in updates and - updates['ls_acknowledged'] != original['ls_acknowledged']) or \ - ('ls_downtimed' in updates and - updates['ls_downtimed'] != original['ls_downtimed']): + if 'ls_state' in updates or 'ls_acknowledged' in updates or 'ls_downtimed' in updates: overall_state = 0 acknowledged = original['ls_acknowledged'] @@ -1161,6 +1191,41 @@ def pre_service_patch(updates, original): del updates['_updated'] +def after_insert_service(items): + """ + Hook after service inserted. + + :param items: host fields + :type items: dict + :return: None + """ + for dummy, item in enumerate(items): + overall_state = 0 + + acknowledged = item['ls_acknowledged'] + downtimed = item['ls_downtimed'] + state = item['ls_state'] + state = state.upper() + + if acknowledged: + overall_state = 1 + elif downtimed: + overall_state = 2 + else: + if state == 'WARNING': + overall_state = 3 + elif state == 'CRITICAL': + overall_state = 4 + elif state == 'UNKNOWN': + overall_state = 3 + elif state == 'UNREACHABLE': + overall_state = 4 + + # Service overall was computed, update the service overall state + lookup = {"_id": item['_id']} + patch_internal('service', {"_overall_state_id": overall_state}, False, False, **lookup) + + def after_updated_service(updated, original): """ Hook called after a service got updated @@ -1171,9 +1236,8 @@ def after_updated_service(updated, original): :type original: dict :return: None """ - if '_overall_state_id' in updated and \ - updated['_overall_state_id'] != original['_overall_state_id']: - # Service overall state changed, we should update its host overall state + if '_overall_state_id' in updated: + # Service overall was updated, we should update its host overall state lookup = {"_id": original['host']} patch_internal('host', {"_overall_state_id": -1}, False, False, **lookup) @@ -1416,6 +1480,8 @@ def get_settings(prev_settings): app.on_pre_GET += pre_get app.on_insert_user += pre_user_post app.on_update_user += pre_user_patch +app.on_inserted_host += after_insert_host +app.on_inserted_service += after_insert_service app.on_update_host += pre_host_patch app.on_update_service += pre_service_patch app.on_updated_service += after_updated_service diff --git a/test/test_hook_template.py b/test/test_hook_template.py index b2d84b58..924892e5 100644 --- a/test/test_hook_template.py +++ b/test/test_hook_template.py @@ -135,7 +135,7 @@ def test_host_templates(self): schema = host_schema() template_fields = {} - ignore_fields = ['name', 'realm', '_realm', '_template_fields', + ignore_fields = ['name', 'realm', '_realm', '_overall_state_id', '_template_fields', '_templates', '_is_template', '_templates_with_services'] for key in schema['schema']: @@ -743,12 +743,15 @@ def test_host_services_template(self): self.assertTrue(rs[12]['_is_template']) # Now delete a template service + response = requests.get(self.endpoint + '/service/' + ret_new['_id'], + params=sort_id, auth=self.auth) + response = response.json() headers_delete = { 'Content-Type': 'application/json', - 'If-Match': ret_new['_etag'] + 'If-Match': response['_etag'] } - requests.delete(self.endpoint + '/service/' + ret_new['_id'], headers=headers_delete, - auth=self.auth) + requests.delete(self.endpoint + '/service/' + response['_id'], + headers=headers_delete, auth=self.auth) response = requests.get(self.endpoint + '/service', params=sort_id, auth=self.auth) resp = response.json() service_name = [] diff --git a/test/test_overall_state.py b/test/test_overall_state.py index 2c5726ba..e79d859a 100644 --- a/test/test_overall_state.py +++ b/test/test_overall_state.py @@ -109,24 +109,41 @@ def test_update_host(self): del data['realm'] data['_realm'] = self.realm_all requests.post(self.endpoint + '/host', json=data, headers=headers, auth=self.auth) - response = requests.get(self.endpoint + '/host', params=sort_id, auth=self.auth) + params = {'sort': '_id', 'where': json.dumps({'_is_template': True})} + response = requests.get(self.endpoint + '/host', params=params, auth=self.auth) resp = response.json() - self.assertEqual(len(resp['_items']), 2) + self.assertEqual(len(resp['_items']), 1) rh = resp['_items'] + # On host insertion, _overall_state_id field is 3, because host is UNREACHABLE + self.assertEqual(3, rh[0]['_overall_state_id']) # Add service 1 data = json.loads(open('cfg/service_srv001_ping.json').read()) - data['host'] = rh[1]['_id'] + data['host'] = rh[0]['_id'] data['check_command'] = rc[2]['_id'] data['_realm'] = self.realm_all requests.post(self.endpoint + '/service', json=data, headers=headers, auth=self.auth) + response = response.json() + response = requests.get( + self.endpoint + '/service/' + response['_id'], params=sort_id, auth=self.auth + ) + ls_service = response.json() + # On service insertion, _overall_state_id field is 3, because service is UNKNOWN + self.assertEqual(3, ls_service['_overall_state_id']) # Add service 2 data = json.loads(open('cfg/service_srv002_ping.json').read()) - data['host'] = rh[1]['_id'] + data['host'] = rh[0]['_id'] data['check_command'] = rc[2]['_id'] data['_realm'] = self.realm_all requests.post(self.endpoint + '/service', json=data, headers=headers, auth=self.auth) + response = response.json() + response = requests.get( + self.endpoint + '/service/' + response['_id'], params=sort_id, auth=self.auth + ) + ls_service = response.json() + # On service insertion, _overall_state_id field is 3, because service is UNKNOWN + self.assertEqual(3, ls_service['_overall_state_id']) # Get all services response = requests.get(self.endpoint + '/service', params=sort_id, auth=self.auth) @@ -152,7 +169,7 @@ def test_update_host(self): self.endpoint + '/service/' + service['_id'], params=sort_id, auth=self.auth ) ls_service = response.json() - # _overall_state_id field is 0 + # On service insertion, _overall_state_id field is 3, because service is UNKNOWN self.assertEqual(0, ls_service['_overall_state_id']) # Get host