Added new test notification_crud.py. Refactored other files for code reuse

This commit is contained in:
Craig Bryant 2014-05-15 15:09:35 -06:00
parent 09341015f6
commit a46ec61d59
4 changed files with 283 additions and 32 deletions

53
tests/alarm.py Normal file
View File

@ -0,0 +1,53 @@
from __future__ import print_function
import sys
def get_state(mon_client, alarm_id):
result = get(mon_client, alarm_id)
return result['state']
def get(mon_client, alarm_id):
result = mon_client.alarms.get(**{'alarm_id': alarm_id})
return result
def disable(mon_client, alarm_id):
patch(mon_client, alarm_id, {'enabled': False})
def enable(mon_client, alarm_id):
patch(mon_client, alarm_id, {'enabled': True})
def set_state(mon_client, alarm_id, state):
patch(mon_client, alarm_id, {'state': state})
new_state = get_state(mon_client, alarm_id)
if new_state != state:
print('Expected new state %s but found %s' %
(state, new_state), file=sys.stderr)
return False
return True
def patch(mon_client, alarm_id, fields):
fields['alarm_id'] = alarm_id
mon_client.alarms.patch(**fields)
def set_optional_field(name, value, fields):
if value is not None:
fields[name] = value
def create(mon_client, name, description, expression, ok_actions,
alarm_actions, undetermined_actions):
fields = {}
fields['name'] = name
fields['expression'] = expression
set_optional_field('description', description, fields)
set_optional_field('ok_actions', ok_actions, fields)
set_optional_field('alarm_actions', alarm_actions, fields)
set_optional_field('undetermined_actions', undetermined_actions, fields)
result = mon_client.alarms.create(**fields)
return result['id']

View File

@ -8,8 +8,8 @@ import json
import subprocess
def find_notifications(alarm_id):
args = ['sudo', 'cat', '/var/mail/root']
def find_notifications(alarm_id, user):
args = ['sudo', 'cat', '/var/mail/' + user]
result = []
try:
stdout = subprocess.check_output(args)
@ -20,3 +20,30 @@ def find_notifications(alarm_id):
if alarm_id in line:
result.append(json.loads(line)['state'])
return result
def create(mon_client, name, email):
kwargs = {'name': name, 'address': email, 'type': 'EMAIL'}
result = mon_client.notifications.create(**kwargs)
return result['id']
def update(mon_client, notification_id, name, email):
kwargs = {'id': notification_id, 'name': name, 'address': email,
'type': 'EMAIL'}
result = mon_client.notifications.update(**kwargs)
return result['id']
def get(mon_client, notification_id):
kwargs = {'notification_id': notification_id}
result = mon_client.notifications.get(**kwargs)
return result
def find_by_name(mon_client, name):
result = mon_client.notifications.list(**{})
for notification in result:
if notification['name'] == name:
return notification
return None

194
tests/notification_crud.py Normal file
View File

@ -0,0 +1,194 @@
#!/usr/bin/env python
#
"""Notification Engine Test
CRUD test
"""
from __future__ import print_function
import sys
import platform
import os
import time
from monclient import client
import notification
import monclient.exc as exc
import alarm
def call_mon_api(method, fields):
try:
resp = method(**fields)
except exc.HTTPException as he:
print(he.code)
print(he.message)
sys.exit(1)
else:
return resp
def cycle_states(mon_client, alarm_id, states):
print('Cycling alarm states through %s' % (states))
for state in states:
alarm.set_state(mon_client, alarm_id, state)
def check_notification(alarm_id, user, expected_state, existing):
for i in range(0, 20):
notifications = notification.find_notifications(alarm_id, user)
if len(notifications) > existing:
break
time.sleep(1)
if len(notifications) <= existing:
print('Did not receive new notification in %d seconds for user %s' %
(i+1, user), file=sys.stderr)
return False
if (len(notifications) - existing) > 1:
print('Received %d new notifications instead of 1 for user %s' %
(len(notifications) - existing, user), file=sys.stderr)
return False
new_state = notifications[existing]
if new_state != expected_state:
print('Expected state %s for user %s but found state %s' %
(expected_state, user, new_state), file=sys.stderr)
return False
print('Found notification for state %s for user %s in %d seconds' %
(expected_state, user, i), file=sys.stderr)
return True
def find_or_create_notification(mon_client, name, email):
notif = notification.find_by_name(mon_client, name)
if notif is not None:
if notif['address'] != email:
print('Notification named %s exists but address is %s not %s' %
(name, notif['address'], email), file=sys.stderr)
return None
return notif['id']
else:
return notification.create(mon_client, name, email)
def check_notifications(alarm_id, email1, email2, email3, state1, state2,
state3, existing):
if not check_notification(alarm_id, email1, state1, existing):
return False
if not check_notification(alarm_id, email2, state2, existing):
return False
if not check_notification(alarm_id, email3, state3, existing):
return False
return True
def print_actions(state, action_ids):
addresses = []
for action_id in action_ids:
action_notification = notification.get(mon_client, action_id)
addresses.append(action_notification['address'])
print("Notification for %s state sent to %s" % (state, addresses))
def print_notification_setup(mon_client, alarm_id):
alarm_data = alarm.get(mon_client, alarm_id)
print_actions('ALARM', alarm_data['alarm_actions'])
print_actions('OK', alarm_data['ok_actions'])
print_actions('UNDETERMINED', alarm_data['undetermined_actions'])
def main():
hostname = platform.node()
if hostname == 'mini-mon':
api_host = '192.168.10.4'
elif hostname == 'kafka':
api_host = 'localhost'
else:
print('This test must be run on the kafka or mini-mon VM, aborting',
file=sys.stderr)
return 1
# Delete notification for OK.Cycle OK, ALARM, UNDETERMINED
# Ensure proper notifications got written for ALARM, UNDETERMINED
states = ['OK', 'ALARM', 'UNDETERMINED']
api_version = '2_0'
endpoint = 'http://' + api_host + ':8080/v2.0'
kwargs = {'token': '82510970543135'}
global mon_client
mon_client = client.Client(api_version, endpoint, **kwargs)
try:
# Create 3 notifications with different emails, root, kafka, mon-agent
email1 = "root"
email2 = "kafka"
email3 = "mon-agent"
notification_id_1 = find_or_create_notification(mon_client, email1,
email1 + "@localhost")
notification_id_2 = find_or_create_notification(mon_client, email2,
email2 + "@localhost")
notification_id_3 = find_or_create_notification(mon_client, email3,
email3 + "@localhost")
# Create an alarm. Cycle OK, ALARM, UNDETERMINED,
alarm_name = "Test Notifications-" + str(os.getpid())
expr = 'max(not_real_metric{}) > 10'
alarm_id = alarm.create(mon_client, alarm_name, None, expr,
notification_id_1, notification_id_2,
notification_id_3)
print('Created Alarm %s' % alarm_id)
print_notification_setup(mon_client, alarm_id)
print('Test initial cycle of Alarms')
cycle_states(mon_client, alarm_id, states)
# Ensure proper notifications got written to each
if not check_notifications(alarm_id, email1, email2, email3,
states[0], states[1], states[2], 0):
return 1
# Disable alarm. Cycle OK, ALARM, UNDETERMINED,
print('Disable Alarm')
alarm.disable(mon_client, alarm_id)
cycle_states(mon_client, alarm_id, states)
# Ensure no new notifications
if not check_notifications(alarm_id, email1, email2, email3,
states[0], states[1], states[2], 0):
return 1
# Enable alarm. Cycle OK, ALARM, UNDETERMINED
print('Enable Alarm')
alarm.enable(mon_client, alarm_id)
cycle_states(mon_client, alarm_id, states)
# Ensure proper notifications got written to each
if not check_notifications(alarm_id, email1, email2, email3,
states[0], states[1], states[2], 1):
return 1
# Switch Alarm notifications around. Cycle OK, ALARM, UNDETERMINED,
print("Switch around Alarm notifications")
alarm.patch(mon_client, alarm_id,
{'ok_actions': [notification_id_2],
'alarm_actions': [notification_id_3],
'undetermined_actions': [notification_id_1]})
print_notification_setup(mon_client, alarm_id)
cycle_states(mon_client, alarm_id, states)
# Ensure proper notifications got written to each
if not check_notifications(alarm_id, email2, email3, email1,
states[0], states[1], states[2], 2):
return 1
# Switch the email addresses around. Cycle OK, ALARM, UNDETERMINED,
# Ensure proper notifications got written to each
return 0
except exc.HTTPException as he:
print(he.code)
print(he.message)
return 1
if __name__ == "__main__":
sys.exit(main())

View File

@ -8,34 +8,17 @@ import sys
import time
from monclient import client
from notification import find_notifications
import monclient.exc as exc
def call_mon_api(method, fields):
try:
resp = method(**fields)
except exc.HTTPException as he:
print(he.code)
print(he.message)
sys.exit(1)
else:
return resp
import alarm
def find_alarm_id(mon_client):
result = call_mon_api(mon_client.alarms.list, {})
result = mon_client.alarms.list(**{})
if len(result) == 0:
print('No existing alarms, create one and rerun test', file=sys.stderr)
return None
return result[0]['id']
def get_alarm_state(mon_client, alarm_id):
result = call_mon_api(mon_client.alarms.get, {'alarm_id': alarm_id})
return result['state']
def main():
if len(sys.argv) == 1:
print('usage: %s count [alarm-id]' % sys.argv[0], file=sys.stderr)
@ -55,32 +38,26 @@ def main():
if alarm_id is None:
return 1
user = 'root'
start_time = time.time()
initial_state = get_alarm_state(mon_client, alarm_id)
initial_state = alarm.get_state(mon_client, alarm_id)
state = initial_state
fields = {'alarm_id': alarm_id}
existing_notifications = find_notifications(alarm_id)
existing_notifications = find_notifications(alarm_id, user)
notifications_sent = num_cycles * 2
for _ in range(0, notifications_sent):
if state == 'OK':
state = 'ALARM'
else:
state = 'OK'
fields['state'] = state
call_mon_api(mon_client.alarms.patch, fields)
new_state = get_alarm_state(mon_client, alarm_id)
if new_state != state:
print('Expected new state %s but found %s' %
(state, new_state), file=sys.stderr)
if not alarm.set_state(mon_client, alarm_id, state):
return 1
# time.sleep(1)
print("Took %d seconds to send %d alarm state changes" %
((time.time() - start_time), num_cycles * 2))
for i in range(0, 30):
notifications = find_notifications(alarm_id)
notifications = find_notifications(alarm_id, user)
notifications_found = len(notifications) - len(existing_notifications)
if notifications_found >= notifications_sent:
break