Skip to content

Commit

Permalink
Closes #261 - update overall state even if state do not change
Browse files Browse the repository at this point in the history
Compute overall host/service state on insertion
Fix broken tests
  • Loading branch information
mohierf committed Jan 28, 2017
1 parent 4e05ec1 commit 35c0839
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 20 deletions.
88 changes: 77 additions & 11 deletions alignak_backend/app.py
Expand Up @@ -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.
Expand Down Expand Up @@ -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_'):
Expand All @@ -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']
Expand Down Expand Up @@ -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
Expand All @@ -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)

Expand Down Expand Up @@ -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
Expand Down
11 changes: 7 additions & 4 deletions test/test_hook_template.py
Expand Up @@ -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']:
Expand Down Expand Up @@ -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 = []
Expand Down
27 changes: 22 additions & 5 deletions test/test_overall_state.py
Expand Up @@ -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)
Expand All @@ -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
Expand Down

0 comments on commit 35c0839

Please sign in to comment.