Moved the smoke test to the ci repo and cleaned up old tests.
Change-Id: Ic6e24dc1166b8bf7461103b5ebe2d47c14ccf4fa
This commit is contained in:
parent
0b53dbfb9b
commit
3c0775570a
@ -19,7 +19,7 @@
|
||||
apt: name=python-virtualenv
|
||||
tasks:
|
||||
- name: Setup the monasca cli credentials in the default environment
|
||||
copy: src=tests/env.sh dest=/etc/profile.d/monasca_cli.sh owner=root group=root mode=0644
|
||||
copy: src=env.sh dest=/etc/profile.d/monasca_cli.sh owner=root group=root mode=0644
|
||||
tags:
|
||||
- cli
|
||||
- name: Update cli
|
||||
|
@ -46,7 +46,7 @@
|
||||
alive_test: ssh
|
||||
tasks:
|
||||
- name: Setup the monasca cli credentials in the default environment
|
||||
copy: src=tests/env.sh dest=/etc/profile.d/monasca_cli.sh owner=root group=root mode=0644
|
||||
copy: src=env.sh dest=/etc/profile.d/monasca_cli.sh owner=root group=root mode=0644
|
||||
tags:
|
||||
- cli
|
||||
- name: Update cli
|
||||
@ -82,5 +82,4 @@
|
||||
roles:
|
||||
- {role: monasca-default-alarms, tags: [alarms]}
|
||||
|
||||
- include: smoke2.yml
|
||||
- include: smoke.yml
|
||||
|
36
smoke.yml
36
smoke.yml
@ -1,8 +1,38 @@
|
||||
- hosts: mini-mon
|
||||
sudo: yes
|
||||
vars:
|
||||
host_ip: "{{mini_mon}}"
|
||||
test_base: /opt/monasca/
|
||||
test_url: https://api.github.com/repos/hpcloud-mon/monasca-ci/tarball/master
|
||||
tasks:
|
||||
- name: Fetch the monasca-ci tests
|
||||
get_url: dest="{{test_base}}/monasca-ci.tar.gz" url="{{test_url}}"
|
||||
register: download
|
||||
|
||||
- name: UI - Uncompress the monasca-ci tar
|
||||
unarchive: copy=no dest="{{test_base}}" src="{{test_base}}/monasca-ci.tar.gz"
|
||||
when: download | changed
|
||||
# In Ansible 1.8 this was in the unarchive output, in 2.0 there is list_files option you can add to unarchive but in 1.9 we must use this
|
||||
# command to discover the tar dir. This method will work for the other versions also.
|
||||
- name: Discover the tar path
|
||||
command: tar -tzf "{{test_base}}/monasca-ci.tar.gz"
|
||||
register: tarpath
|
||||
|
||||
- name: Install the influxdb python library
|
||||
pip: name=influxdb virtualenv="{{monasca_virtualenv_dir}}"
|
||||
when: database_type == 'influxdb'
|
||||
|
||||
- name: Copy the template locally
|
||||
fetch: src="{{test_base}}/{{tarpath.stdout_lines[0]}}/tests/smoke/smoke2_configs.py.j2" dest=tests/ flat=yes
|
||||
- name: Populate config vars
|
||||
template: src="tests/smoke2_configs.py.j2" dest="{{test_base}}/{{tarpath.stdout_lines[0]}}/tests/smoke/smoke2_configs.py"
|
||||
|
||||
- name: Run the smoke2 test
|
||||
command: "{{monasca_virtualenv_dir}}/bin/python {{test_base}}/{{tarpath.stdout_lines[0]}}/tests/smoke/smoke2.py"
|
||||
register: smoke2
|
||||
- debug: var=smoke2.stdout_lines
|
||||
|
||||
- name: Run the smoke test
|
||||
command: /vagrant/tests/smoke.py
|
||||
environment:
|
||||
PATH: "{{ansible_env.PATH}}:{{monasca_virtualenv_dir}}/bin"
|
||||
command: "{{monasca_virtualenv_dir}}/bin/python {{test_base}}/{{tarpath.stdout_lines[0]}}/tests/smoke/smoke.py"
|
||||
register: smoke
|
||||
- debug: var=smoke.stdout_lines
|
||||
|
33
smoke2.yml
33
smoke2.yml
@ -1,33 +0,0 @@
|
||||
- hosts: mini-mon
|
||||
sudo: yes
|
||||
vars:
|
||||
host_ip: "{{mini_mon}}"
|
||||
test_base: /opt/monasca/
|
||||
test_url: https://api.github.com/repos/hpcloud-mon/monasca-ci/tarball/master
|
||||
tasks:
|
||||
- name: Fetch the monasca-ci tests
|
||||
get_url: dest="{{test_base}}/monasca-ci.tar.gz" url="{{test_url}}"
|
||||
register: download
|
||||
|
||||
- name: UI - Uncompress the monasca-ci tar
|
||||
unarchive: copy=no dest="{{test_base}}" src="{{test_base}}/monasca-ci.tar.gz"
|
||||
when: download | changed
|
||||
# In Ansible 1.8 this was in the unarchive output, in 2.0 there is list_files option you can add to unarchive but in 1.9 we must use this
|
||||
# command to discover the tar dir. This method will work for the other versions also.
|
||||
- name: Discover the tar path
|
||||
command: tar -tzf "{{test_base}}/monasca-ci.tar.gz"
|
||||
register: tarpath
|
||||
|
||||
- name: Install the influxdb python library
|
||||
pip: name=influxdb virtualenv="{{monasca_virtualenv_dir}}"
|
||||
when: database_type == 'influxdb'
|
||||
|
||||
- name: Copy the template locally
|
||||
fetch: src="{{test_base}}/{{tarpath.stdout_lines[0]}}/tests/smoke/smoke2_configs.py.j2" dest=tests/ flat=yes
|
||||
- name: Populate config vars
|
||||
template: src="tests/smoke2_configs.py.j2" dest="{{test_base}}/{{tarpath.stdout_lines[0]}}/tests/smoke/smoke2_configs.py"
|
||||
|
||||
- name: Run the smoke2 test
|
||||
command: "{{monasca_virtualenv_dir}}/bin/python {{test_base}}/{{tarpath.stdout_lines[0]}}/tests/smoke/smoke2.py"
|
||||
register: smoke2
|
||||
- debug: var=smoke2.stdout_lines
|
@ -1,3 +0,0 @@
|
||||
# Test notifications
|
||||
- run smoke.py from within the mini-mon vm for a full test of Monasca
|
||||
- env.sh can be sourced to set the proper env for using the python-monascaclient
|
@ -1,65 +0,0 @@
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
#
|
||||
"""
|
||||
Utility methods for CRUD of alarms
|
||||
"""
|
||||
|
||||
|
||||
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, {'actions_enabled': False})
|
||||
|
||||
|
||||
def enable(mon_client, alarm_id):
|
||||
patch(mon_client, alarm_id, {'actions_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=None,
|
||||
alarm_actions=None, undetermined_actions=None):
|
||||
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']
|
||||
|
||||
|
||||
def find_alarm_byname(mon_client, alarm_name):
|
||||
alarms = mon_client.alarms.list(**{})
|
||||
for alarm in alarms:
|
||||
if alarm['name'] == alarm_name:
|
||||
return alarm
|
||||
return None
|
@ -1,158 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
""" Threshold Engine Test
|
||||
CRUD test
|
||||
"""
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import cli_wrapper
|
||||
import utils
|
||||
|
||||
|
||||
def output_metrics(alarm_id, expected_state, metrics):
|
||||
print('Generating metrics, waiting for state change to %s' %
|
||||
expected_state)
|
||||
hostnames = ['AA', 'BB', 'CC']
|
||||
for x in range(0, 90):
|
||||
for metric in metrics:
|
||||
metric_name = metric[0]
|
||||
dimensions = metric[1]
|
||||
args = ['metric-create', '--dimensions']
|
||||
hostname = hostnames[x % len(hostnames)]
|
||||
args.append(dimensions + ',' + 'hostname=' + hostname)
|
||||
args.append(metric_name)
|
||||
args.append('42')
|
||||
cli_wrapper.run_mon_cli(args, useJson=False)
|
||||
|
||||
state = cli_wrapper.get_alarm_state(alarm_id)
|
||||
if state == expected_state:
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
if state != expected_state:
|
||||
print('Did not change to state %s instead was %s in %d seconds' %
|
||||
(expected_state, state, x), file=sys.stderr)
|
||||
return False
|
||||
|
||||
print('Changed to state %s in %d seconds' % (state, x))
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
utils.setup_cli()
|
||||
|
||||
alarm_name = 'alarm_crud'
|
||||
metric_name = 'alarm_crud'
|
||||
base_dimension = 'service=alarm_test'
|
||||
expression = 'max(%s{%s}) > 0' % (metric_name, base_dimension)
|
||||
description = alarm_name + ' Description'
|
||||
cli_wrapper.delete_alarm_if_exists(alarm_name)
|
||||
|
||||
# Add Alarm
|
||||
alarm_id = cli_wrapper.create_alarm(alarm_name, expression,
|
||||
description=description)
|
||||
print('Created Alarm with id %s' % alarm_id)
|
||||
|
||||
# Ensure it is created in the right state
|
||||
initial_state = 'UNDETERMINED'
|
||||
if not utils.check_alarm_state(alarm_id, initial_state):
|
||||
return 1
|
||||
|
||||
states = []
|
||||
states.append(initial_state)
|
||||
|
||||
# List Alarms, make sure new one shows up
|
||||
alarm_json = cli_wrapper.find_alarm_by_name(alarm_name)
|
||||
if alarm_json is None:
|
||||
print('Did not find alarm named %s using alarm-list' %
|
||||
alarm_name, file=sys.stderr)
|
||||
return 1
|
||||
|
||||
if alarm_id != alarm_json['id']:
|
||||
print('Alarm %s has wrong id, expected %s but was %s' %
|
||||
(alarm_name, alarm_id, alarm_json['id']), file=sys.stderr)
|
||||
return 1
|
||||
|
||||
# Output metrics that will cause it to go ALARM
|
||||
# Wait for it to change to ALARM
|
||||
if not output_metrics(alarm_id, 'ALARM', [[metric_name, base_dimension]]):
|
||||
return 1
|
||||
|
||||
states.append('ALARM')
|
||||
|
||||
# Modify Alarm by adding new expression that will cause it to go OK
|
||||
print('Modify Alarm expression so it will go to OK')
|
||||
new_metric_name = 'other_metric'
|
||||
new_dimension = 'dim=42'
|
||||
new_expression = '%s and max(%s{%s}) > 100' % (expression,
|
||||
new_metric_name,
|
||||
new_dimension)
|
||||
|
||||
alarm_json = cli_wrapper.patch_alarm(alarm_id, '--expression',
|
||||
new_expression)
|
||||
if alarm_json['expression'] != new_expression:
|
||||
print('Did not change expression to %s instead was %s' %
|
||||
(new_expression, alarm_json['expression']), file=sys.stderr)
|
||||
return 1
|
||||
|
||||
# Output metrics that will cause it to go OK
|
||||
# Wait for it to change to OK
|
||||
|
||||
if not output_metrics(alarm_id, 'OK', [[metric_name, base_dimension],
|
||||
[new_metric_name, new_dimension]]):
|
||||
return 1
|
||||
|
||||
states.append('OK')
|
||||
|
||||
# Modify Alarm by deleting expression that will cause Alarm to go ALARM
|
||||
print('Delete Alarm sub expression so it will go to ALARM')
|
||||
cli_wrapper.patch_alarm(alarm_id, '--expression', expression)
|
||||
|
||||
# Output metrics that will cause it to go ALARM
|
||||
# Wait for it to change to ALARM
|
||||
print('Output extra dimensions to make sure match occurs')
|
||||
extra_dimension = base_dimension + ',Extra=More'
|
||||
if not output_metrics(alarm_id, 'ALARM',
|
||||
[[metric_name, extra_dimension]]):
|
||||
return 1
|
||||
|
||||
states.append('ALARM')
|
||||
|
||||
# Modify Alarm by setting alarm state to OK
|
||||
print('Set Alarm to OK, wait for transition back to ALARM')
|
||||
|
||||
cli_wrapper.change_alarm_state(alarm_id, 'OK')
|
||||
states.append('OK')
|
||||
|
||||
# Output metrics that will cause it to go back to ALARM
|
||||
# Wait for it to change to ALARM
|
||||
if not output_metrics(alarm_id, 'ALARM',
|
||||
[[metric_name, base_dimension],
|
||||
[new_metric_name, new_dimension]]):
|
||||
return 1
|
||||
|
||||
states.append('ALARM')
|
||||
|
||||
# Query History
|
||||
# Delete ALARM
|
||||
print('Delete alarm')
|
||||
cli_wrapper.run_mon_cli(['alarm-delete', alarm_id], useJson=False)
|
||||
|
||||
# Ensure it can't be queried
|
||||
if cli_wrapper.find_alarm_by_name(alarm_name) is not None:
|
||||
print('Still found alarm %s after it was deleted' % alarm_name,
|
||||
file=sys.stderr)
|
||||
return 1
|
||||
|
||||
# Query History, ensure they still show up
|
||||
if not utils.check_alarm_history(alarm_id, states):
|
||||
return 1
|
||||
|
||||
# Success
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
@ -1,110 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
""" Wrapper code for running the CLI as a process.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import subprocess
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
def find_obj_for_name(object_json, name):
|
||||
for obj in object_json:
|
||||
this_name = obj['name']
|
||||
if name == this_name:
|
||||
return obj
|
||||
return None
|
||||
|
||||
|
||||
def find_alarm_definition_by_name(name):
|
||||
alarm_json = run_mon_cli(['alarm-definition-list'])
|
||||
return find_obj_for_name(alarm_json, name)
|
||||
|
||||
|
||||
def delete_alarm_definition_if_exists(name):
|
||||
alarm_json = find_alarm_definition_by_name(name)
|
||||
if alarm_json:
|
||||
run_mon_cli(['alarm-definition-delete', alarm_json['id']],
|
||||
useJson=False)
|
||||
|
||||
|
||||
def delete_notification_if_exists(notification_name):
|
||||
notification_json = run_mon_cli(['notification-list'])
|
||||
notification = find_obj_for_name(notification_json, notification_name)
|
||||
if notification:
|
||||
run_mon_cli(['notification-delete', notification['id']], useJson=False)
|
||||
|
||||
|
||||
def run_mon_cli(args, useJson=True):
|
||||
if useJson:
|
||||
args.insert(0, '--json')
|
||||
args.insert(0, 'monasca')
|
||||
env = os.environ.copy()
|
||||
env['PYTHONIOENCODING'] = "utf-8"
|
||||
try:
|
||||
stdout = subprocess.check_output(args, env=env)
|
||||
if useJson:
|
||||
return json.loads(stdout)
|
||||
else:
|
||||
return stdout
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(e, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def create_notification(notification_name,
|
||||
notification_addr,
|
||||
notification_type):
|
||||
print('Creating notification')
|
||||
result_json = run_mon_cli(['notification-create', notification_name,
|
||||
notification_type, notification_addr])
|
||||
|
||||
# Parse out id
|
||||
notification_id = result_json['id']
|
||||
return notification_id
|
||||
|
||||
|
||||
def get_alarm_state(alarm_id):
|
||||
result_json = run_mon_cli(['alarm-show', alarm_id])
|
||||
return result_json['state']
|
||||
|
||||
|
||||
def change_alarm_state(alarm_id, new_state):
|
||||
print('Changing Alarm state to %s' % new_state)
|
||||
result_json = run_mon_cli(['alarm-patch', alarm_id, "--state", new_state])
|
||||
if result_json['state'] != new_state:
|
||||
print('Alarm patch failed, expected state of %s but was %s' %
|
||||
(result_json['state'], new_state), file=sys.stderr)
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def find_alarms_for_definition(alarm_definition_id):
|
||||
result_json = run_mon_cli(['alarm-list', "--alarm-definition",
|
||||
alarm_definition_id])
|
||||
return [alarm['id'] for alarm in result_json]
|
||||
|
||||
|
||||
def create_alarm_definition(name, expression, description=None,
|
||||
ok_notif_id=None, alarm_notif_id=None,
|
||||
undetermined_notif_id=None):
|
||||
args = ['alarm-definition-create']
|
||||
add_argument_if_given(args, '--description', description)
|
||||
add_argument_if_given(args, '--alarm-actions', alarm_notif_id)
|
||||
add_argument_if_given(args, '--ok-actions', ok_notif_id)
|
||||
add_argument_if_given(args, '--undetermined-actions',
|
||||
undetermined_notif_id)
|
||||
args.append(name)
|
||||
args.append(expression)
|
||||
print('Creating alarm definition')
|
||||
result_json = run_mon_cli(args)
|
||||
|
||||
# Parse out id
|
||||
return result_json['id']
|
||||
|
||||
|
||||
def add_argument_if_given(args, arg, value):
|
||||
if value is not None:
|
||||
args.append(arg)
|
||||
args.append(value)
|
@ -1,94 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
"""measurements
|
||||
"""
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import time
|
||||
import pytz
|
||||
from datetime import datetime
|
||||
from monascaclient import client
|
||||
import monascaclient.exc as exc
|
||||
import utils
|
||||
|
||||
|
||||
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 create_timestamp(seconds):
|
||||
utcTimestamp = pytz.utc.localize(datetime.utcfromtimestamp(seconds))
|
||||
return utcTimestamp.strftime("%Y-%m-%dT%H:%M:%S%z")
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) == 1:
|
||||
print('usage: %s metric_name count' % sys.argv[0], file=sys.stderr)
|
||||
return 1
|
||||
|
||||
mon_client = utils.create_mon_client()
|
||||
|
||||
metric_start_time = time.time()
|
||||
metric_name = sys.argv[1]
|
||||
num_metrics_to_send = int(sys.argv[2])
|
||||
dimensions = {'Test_Send': 'Number_1'} # Should be arg
|
||||
start_time = time.time()
|
||||
fields = {'name': metric_name}
|
||||
fields['dimensions'] = dimensions
|
||||
for val in range(0, num_metrics_to_send):
|
||||
fields['value'] = str(val)
|
||||
fields['timestamp'] = time.time()
|
||||
call_mon_api(mon_client.metrics.create, fields)
|
||||
# time.sleep(1)
|
||||
|
||||
print("Took %d seconds to send %d measurements" %
|
||||
((time.time() - start_time), num_metrics_to_send))
|
||||
metric_end_time = time.time()
|
||||
# API requires end time to be greater than start time
|
||||
if (metric_end_time - metric_start_time) < 1:
|
||||
metric_end_time = metric_start_time + 1
|
||||
start_timestamp = create_timestamp(metric_start_time)
|
||||
end_timestamp = create_timestamp(metric_end_time)
|
||||
fields = {'name': metric_name}
|
||||
fields['dimensions'] = dimensions
|
||||
fields['start_time'] = start_timestamp
|
||||
fields['end_time'] = end_timestamp
|
||||
for i in range(0, 30):
|
||||
result = call_mon_api(mon_client.metrics.list_measurements, fields)
|
||||
if len(result) > 0:
|
||||
measurements = result[0]['measurements']
|
||||
if len(measurements) >= num_metrics_to_send:
|
||||
break
|
||||
print('Found %d of %d metrics so far' %
|
||||
(len(measurements), num_metrics_to_send))
|
||||
time.sleep(1)
|
||||
|
||||
if len(result) == 0:
|
||||
print('Did not receive any metrics in %d seconds' % i, file=sys.stderr)
|
||||
return 1
|
||||
|
||||
if len(measurements) != num_metrics_to_send:
|
||||
print('Expected %d measurements but found %d' %
|
||||
(num_metrics_to_send, len(measurements)), file=sys.stderr)
|
||||
return 1
|
||||
print('Took %d seconds for metrics to fully arrive' % i)
|
||||
expected = num_metrics_to_send - 1
|
||||
result = 0
|
||||
for index in range(num_metrics_to_send, 0):
|
||||
value = measurements[index]
|
||||
if value[2] != expected:
|
||||
print('Expected %d but found %d for %d' %
|
||||
(expected, value[2], index), file=sys.stderr)
|
||||
expected = expected - 1
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
@ -1,32 +0,0 @@
|
||||
from __future__ import print_function
|
||||
|
||||
"""
|
||||
Utility methods for notifications
|
||||
"""
|
||||
|
||||
|
||||
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
|
@ -1,171 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
"""Notification Engine Test
|
||||
CRUD test
|
||||
"""
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import notification
|
||||
import monascaclient.exc as exc
|
||||
import alarm
|
||||
import utils
|
||||
|
||||
|
||||
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 = utils.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(mon_client, 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(mon_client, 'ALARM', alarm_data['alarm_actions'])
|
||||
print_actions(mon_client, 'OK', alarm_data['ok_actions'])
|
||||
print_actions(mon_client, 'UNDETERMINED',
|
||||
alarm_data['undetermined_actions'])
|
||||
|
||||
|
||||
def main():
|
||||
if not utils.ensure_has_notification_engine():
|
||||
return 1
|
||||
|
||||
# Delete notification for OK.Cycle OK, ALARM, UNDETERMINED
|
||||
# Ensure proper notifications got written for ALARM, UNDETERMINED
|
||||
|
||||
states = ['OK', 'ALARM', 'UNDETERMINED']
|
||||
mon_client = utils.create_mon_client()
|
||||
|
||||
try:
|
||||
# Create 3 notifications with different emails, root, kafka,
|
||||
# and monasca-agent
|
||||
email1 = "root"
|
||||
email2 = "kafka"
|
||||
email3 = "monasca-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())
|
@ -1,78 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
"""Notification Engine Test
|
||||
Cycle the state of an Alarm the given number of times
|
||||
"""
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import time
|
||||
import notification
|
||||
import alarm
|
||||
import utils
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) == 1:
|
||||
print('usage: %s count [alarm-id]' % sys.argv[0], file=sys.stderr)
|
||||
return 1
|
||||
|
||||
if not utils.ensure_has_notification_engine():
|
||||
return 1
|
||||
|
||||
mon_client = utils.create_mon_client()
|
||||
num_cycles = int(sys.argv[1])
|
||||
|
||||
alarm_name = 'notification_cycleTest'
|
||||
alarm_json = alarm.find_alarm_byname(mon_client, alarm_name)
|
||||
if alarm_json is not None:
|
||||
alarm_id = alarm_json['id']
|
||||
else:
|
||||
existing = notification.find_by_name(mon_client, alarm_name)
|
||||
if existing is not None:
|
||||
notification_id = existing['id']
|
||||
else:
|
||||
notification_id = notification.create(mon_client, alarm_name,
|
||||
"root@localhost")
|
||||
alarm_id = alarm.create(mon_client, alarm_name, None, 'max(cc) > 100',
|
||||
notification_id, notification_id,
|
||||
notification_id)
|
||||
|
||||
user = 'root'
|
||||
start_time = time.time()
|
||||
initial_state = alarm.get_state(mon_client, alarm_id)
|
||||
state = initial_state
|
||||
|
||||
existing_notifications = utils.find_notifications(alarm_id, user)
|
||||
notifications_sent = num_cycles * 2
|
||||
for _ in range(0, notifications_sent):
|
||||
if state == 'OK':
|
||||
state = 'ALARM'
|
||||
else:
|
||||
state = 'OK'
|
||||
if not alarm.set_state(mon_client, alarm_id, state):
|
||||
return 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 = utils.find_notifications(alarm_id, user)
|
||||
notifications_found = len(notifications) - len(existing_notifications)
|
||||
if notifications_found >= notifications_sent:
|
||||
break
|
||||
print('Found %d of %d expected notifications so far' %
|
||||
(notifications_found, notifications_sent))
|
||||
time.sleep(1)
|
||||
|
||||
if notifications_found < notifications_sent:
|
||||
print('Expected %d notifications but found %d' %
|
||||
(notifications_sent, notifications_found), file=sys.stderr)
|
||||
return 1
|
||||
|
||||
print('Took %d seconds for notifications to fully arrive' % i)
|
||||
result = 0
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
357
tests/smoke.py
357
tests/smoke.py
@ -1,357 +0,0 @@
|
||||
#!/opt/monasca/bin/python
|
||||
#
|
||||
"""smoke
|
||||
Runs a smoke test of the monitoring installation on mini-mon to ensure
|
||||
the components (other than the UI) are functioning. The code tests these
|
||||
components:
|
||||
1. Agent - ensures metrics are being sent to API
|
||||
2. API - ensures alarm definitions can created, listed, etc. Ensure
|
||||
metrics and alarms can be queried
|
||||
3. CLI - used to talk to the API
|
||||
4. Persister - ensures metrics and alarm history has been persisted
|
||||
in database because API can query them
|
||||
5. Threshold Engine - ensures alarms are created and change state
|
||||
6. Notification Engine - ensures email notifications are sent to the
|
||||
local system
|
||||
This must be run on either the mini-mon VM for the single VM mode or
|
||||
on the kafka VM in the multi VM mode.
|
||||
|
||||
If the tests are to be run in a different environment other than mini-mon,
|
||||
the environment variables below can be set and the smoke will use those
|
||||
instead of the mini-mon credentials and settings:
|
||||
|
||||
OS_USERNAME
|
||||
OS_PASSWORD
|
||||
OS_PROJECT_NAME
|
||||
OS_AUTH_URL
|
||||
|
||||
TODO:
|
||||
1. Add more logic to give ideas of why a particular step failed, for
|
||||
example, alarm did not get created because metrics weren't being
|
||||
received
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import cli_wrapper
|
||||
import utils
|
||||
import datetime
|
||||
import psutil
|
||||
import smoke_configs
|
||||
|
||||
config = smoke_configs.test_config["default"]
|
||||
|
||||
|
||||
# parse command line arguments
|
||||
def parse_commandline_args():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-c', '--config', nargs='?', default='default',
|
||||
help='select configuration <CONFIG>')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def set_config(config_name):
|
||||
global config
|
||||
try:
|
||||
config = smoke_configs.test_config[config_name]
|
||||
print('Using {} Configuration'.format(config_name))
|
||||
return True
|
||||
except KeyError:
|
||||
print('Could not find config "{}"'.format(config_name), file=sys.stderr)
|
||||
return False
|
||||
|
||||
|
||||
def get_metrics(name, dimensions, since):
|
||||
dimensions_arg = ''
|
||||
for key, value in dimensions.iteritems():
|
||||
if dimensions_arg != '':
|
||||
dimensions_arg = dimensions_arg + ','
|
||||
dimensions_arg = dimensions_arg + key + '=' + value
|
||||
return cli_wrapper.run_mon_cli(['measurement-list', '--dimensions',
|
||||
dimensions_arg, name, since])
|
||||
|
||||
|
||||
def cleanup(notification_name, alarm_definition_name):
|
||||
cli_wrapper.delete_alarm_definition_if_exists(alarm_definition_name)
|
||||
cli_wrapper.delete_notification_if_exists(notification_name)
|
||||
|
||||
|
||||
def wait_for_alarm_state_change(alarm_id, old_state):
|
||||
# Wait for it to change state
|
||||
print('Waiting for alarm to change state from {}'.format(old_state))
|
||||
for x in range(0, 250):
|
||||
time.sleep(1)
|
||||
state = cli_wrapper.get_alarm_state(alarm_id)
|
||||
if state != old_state:
|
||||
print('Alarm state changed to {} in {} seconds'.format(state, x))
|
||||
return state
|
||||
print('State never changed from {} in {} seconds'.format(old_state, x),
|
||||
file=sys.stderr)
|
||||
return None
|
||||
|
||||
|
||||
def check_notifications(alarm_id, state_changes):
|
||||
print("Checking Notification Engine")
|
||||
if not os.path.isfile('/etc/monasca/notification.yaml'):
|
||||
print('Notification Engine not installed on this VM,' +
|
||||
' skipping Notifications test',
|
||||
file=sys.stderr)
|
||||
return False
|
||||
|
||||
notifications = utils.find_notifications(alarm_id, "root")
|
||||
if len(notifications) != len(state_changes):
|
||||
print('Expected {} notifications but only found {}'.format(
|
||||
len(state_changes), len(notifications)), file=sys.stderr)
|
||||
return False
|
||||
|
||||
index = 0
|
||||
for expected in state_changes:
|
||||
actual = notifications[index]
|
||||
if actual != expected:
|
||||
print('Expected {} but found {} for state change {}'.format(
|
||||
expected, actual, index+1), file=sys.stderr)
|
||||
return False
|
||||
index = index + 1
|
||||
print('Received email notifications as expected')
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def count_metrics(metric_name, metric_dimensions, since):
|
||||
# Query how many metrics there are for the Alarm
|
||||
metric_json = get_metrics(metric_name, metric_dimensions, since)
|
||||
if len(metric_json) == 0:
|
||||
print('No measurements received for metric {}{} '.format(
|
||||
metric_name, metric_dimensions), file=sys.stderr)
|
||||
return None
|
||||
|
||||
return len(metric_json[0]['measurements'])
|
||||
|
||||
|
||||
def ensure_at_least(actual, desired):
|
||||
if actual < desired:
|
||||
time.sleep(desired - actual)
|
||||
|
||||
|
||||
def wait_for_alarm_creation(alarm_def_id):
|
||||
print('Waiting for alarm to be created for Alarm Definition {}'.format(alarm_def_id))
|
||||
for x in range(0, 30):
|
||||
time.sleep(1)
|
||||
alarms = cli_wrapper.find_alarms_for_definition(alarm_def_id)
|
||||
if len(alarms) == 1:
|
||||
print('Alarm was created in {} seconds'.format(x))
|
||||
return alarms[0]
|
||||
elif len(alarms) > 1:
|
||||
print('{} Alarms were created. Only expected 1'.format(len(alarms)),
|
||||
file=sys.stderr)
|
||||
return None
|
||||
|
||||
print('Alarm was not created for Alarm Definition {} in {} seconds'.format(
|
||||
alarm_def_id, x), file=sys.stderr)
|
||||
return None
|
||||
|
||||
|
||||
def smoke_test():
|
||||
notification_name = config['notification']['name']
|
||||
notification_addr = config['notification']['addr']
|
||||
notification_type = config['notification']['type']
|
||||
alarm_definition_name = config['alarm']['name']
|
||||
metric_name = config['metric']['name']
|
||||
metric_dimensions = config['metric']['dimensions']
|
||||
statsd_metric_name = config['statsd_metric']['name']
|
||||
statsd_metric_dimensions = config['statsd_metric']['dimensions']
|
||||
|
||||
cleanup(notification_name, alarm_definition_name)
|
||||
|
||||
# Query how many metrics there are for the Alarm
|
||||
hour_ago = datetime.datetime.now() - datetime.timedelta(hours=1)
|
||||
hour_ago_str = hour_ago.strftime('%Y-%m-%dT%H:%M:%S')
|
||||
print('Getting metrics for {}{} '.format(metric_name, metric_dimensions))
|
||||
initial_num_metrics = count_metrics(metric_name, metric_dimensions,
|
||||
hour_ago_str)
|
||||
|
||||
if initial_num_metrics is None or initial_num_metrics == 0:
|
||||
msg = ('No metric {} with dimensions {} received in last hour'.format(
|
||||
metric_name, metric_dimensions))
|
||||
return False, msg
|
||||
|
||||
print('Getting metrics for {}{} '.format(statsd_metric_name, statsd_metric_dimensions))
|
||||
initial_statsd_num_metrics = count_metrics(statsd_metric_name, statsd_metric_dimensions, hour_ago_str)
|
||||
|
||||
# statsd metrics may not have been sent yet, which will return None from the CLI wrapper
|
||||
if initial_statsd_num_metrics is None:
|
||||
initial_statsd_num_metrics = 0
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
# Create Notification through CLI
|
||||
notif_id = cli_wrapper.create_notification(notification_name,
|
||||
notification_addr,
|
||||
notification_type)
|
||||
|
||||
# Create Alarm through CLI
|
||||
expression = config['alarm']['expression']
|
||||
description = config['alarm']['description']
|
||||
alarm_def_id = cli_wrapper.create_alarm_definition(
|
||||
alarm_definition_name,
|
||||
expression,
|
||||
description=description,
|
||||
ok_notif_id=notif_id,
|
||||
alarm_notif_id=notif_id,
|
||||
undetermined_notif_id=notif_id)
|
||||
|
||||
# Wait for an alarm to be created
|
||||
alarm_id = wait_for_alarm_creation(alarm_def_id)
|
||||
|
||||
if alarm_id is None:
|
||||
received_num_metrics = count_metrics(metric_name, metric_dimensions,
|
||||
hour_ago_str)
|
||||
if received_num_metrics == initial_num_metrics:
|
||||
print('Did not receive any {}{} metrics while waiting'.format(metric_name,metric_dimensions))
|
||||
else:
|
||||
delta = received_num_metrics - initial_num_metrics
|
||||
print('Received {} {} metrics while waiting'.format(delta, metric_name))
|
||||
return False, 'Alarm creation error'
|
||||
|
||||
# Ensure it is created in the right state
|
||||
initial_state = 'UNDETERMINED'
|
||||
if not utils.check_alarm_state(alarm_id, initial_state):
|
||||
msg = 'Alarm is in an invalid initial state'
|
||||
return False, msg
|
||||
states = []
|
||||
states.append(initial_state)
|
||||
state = wait_for_alarm_state_change(alarm_id, initial_state)
|
||||
if state is None:
|
||||
msg = 'Alarm is in an invalid state'
|
||||
return False, msg
|
||||
|
||||
if state != 'ALARM':
|
||||
print('Wrong final state, expected ALARM but was {}'.format(state),
|
||||
file=sys.stderr)
|
||||
msg = 'Alarm is in an invalid final state'
|
||||
return False, msg
|
||||
states.append(state)
|
||||
|
||||
new_state = 'OK'
|
||||
states.append(new_state)
|
||||
if not cli_wrapper.change_alarm_state(alarm_id, new_state):
|
||||
msg = 'Unable to change Alarm state'
|
||||
return False, msg
|
||||
|
||||
# There is a bug in the API which allows this to work. Soon that
|
||||
# will be fixed and this will fail
|
||||
if len(sys.argv) > 1:
|
||||
final_state = 'ALARM'
|
||||
states.append(final_state)
|
||||
|
||||
state = wait_for_alarm_state_change(alarm_id, new_state)
|
||||
if state is None:
|
||||
msg = 'Alarm is in an unknown state'
|
||||
return False, msg
|
||||
|
||||
if state != final_state:
|
||||
msg = ('Wrong final state, expected {} but was {}'.format(final_state, state))
|
||||
return False, msg
|
||||
|
||||
# If the alarm changes state too fast, then there isn't time for the new
|
||||
# metric to arrive. Unlikely, but it has been seen
|
||||
ensure_at_least(time.time() - start_time, 35)
|
||||
change_time = time.time() - start_time
|
||||
|
||||
final_num_metrics = count_metrics(metric_name, metric_dimensions,
|
||||
hour_ago_str)
|
||||
if final_num_metrics <= initial_num_metrics:
|
||||
msg = ('No new metrics received for {}{} in {} seconds'.format(metric_name, metric_dimensions, change_time))
|
||||
return False, msg
|
||||
print('Received {} metrics in {} seconds'.format((final_num_metrics - initial_num_metrics), change_time))
|
||||
if not utils.check_alarm_history(alarm_id, states):
|
||||
msg = 'Invalid alarm history'
|
||||
return False, msg
|
||||
|
||||
# Notifications are only sent out for the changes, so omit the first state
|
||||
if not check_notifications(alarm_id, states[1:]):
|
||||
msg = 'Could not find correct notifications for alarm {}'.format(alarm_id)
|
||||
return False, msg
|
||||
|
||||
# Check that monasca statsd is sending metrics
|
||||
# Metrics may take some time to arrive
|
||||
print('Waiting for statsd metrics')
|
||||
for x in range(0,30):
|
||||
final_statsd_num_metrics = count_metrics(statsd_metric_name, statsd_metric_dimensions, hour_ago_str)
|
||||
if final_statsd_num_metrics > initial_statsd_num_metrics:
|
||||
break
|
||||
if x >= 29:
|
||||
msg = 'No metrics received for statsd metric {}{} in {} seconds'.format(
|
||||
statsd_metric_name, statsd_metric_dimensions, time.time() - start_time)
|
||||
return False, msg
|
||||
time.sleep(1)
|
||||
print('Received {0} metrics for {1}{2} in {3} seconds'.format(final_statsd_num_metrics - initial_statsd_num_metrics,
|
||||
statsd_metric_name,
|
||||
statsd_metric_dimensions,
|
||||
time.time() - start_time))
|
||||
|
||||
msg = ''
|
||||
return True, msg
|
||||
|
||||
|
||||
def find_processes():
|
||||
"""Find_process is meant to validate that all the required processes
|
||||
are running before starting the smoke test """
|
||||
process_missing = []
|
||||
process_list = config['system_vars']['expected_processes']
|
||||
|
||||
for process in process_list:
|
||||
process_found_flag = False
|
||||
|
||||
for item in psutil.process_iter():
|
||||
for cmd in item.cmdline():
|
||||
if process in cmd:
|
||||
process_found_flag = True
|
||||
break
|
||||
|
||||
if not process_found_flag:
|
||||
process_missing.append(process)
|
||||
|
||||
if len(process_missing) > 0: # if processes were not found
|
||||
print ('Process = {} Not Found'.format(process_missing))
|
||||
return False
|
||||
else:
|
||||
print ('All Mini-Mon Processes Found')
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
# May be able to delete this test because the find_process check should
|
||||
# validate the notification engine present.
|
||||
if not utils.ensure_has_notification_engine():
|
||||
return 1
|
||||
|
||||
utils.setup_cli()
|
||||
|
||||
# parse the command line arguments
|
||||
cmd_args = parse_commandline_args()
|
||||
|
||||
if not set_config(cmd_args.config):
|
||||
return 1
|
||||
|
||||
print('*****VERIFYING HOST ENVIRONMENT*****')
|
||||
if find_processes():
|
||||
print('*****BEGIN TEST*****')
|
||||
complete, msg = smoke_test()
|
||||
if not complete:
|
||||
print('*****TEST FAILED*****', file=sys.stderr)
|
||||
print(msg, file=sys.stderr)
|
||||
return 1
|
||||
else:
|
||||
return 1
|
||||
|
||||
cleanup(config['notification']['name'], config['alarm']['name'])
|
||||
print('*****TEST COMPLETE*****')
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
@ -1,74 +0,0 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
"""configurations for smoke test"""
|
||||
|
||||
import subprocess
|
||||
|
||||
system_vars = {
|
||||
'default': { # the default configuration, assumes monasca-vagrant setup
|
||||
'expected_processes': ('monasca-persister', 'monasca-notification',
|
||||
'kafka', 'zookeeper.jar', 'monasca-api',
|
||||
'apache-storm', 'mysqld'),
|
||||
'mail_host': 'localhost',
|
||||
'metric_host': subprocess.check_output(['hostname', '-f']).strip()},
|
||||
}
|
||||
|
||||
|
||||
test_config = {
|
||||
'default': { # the default configuration,
|
||||
# simple test of each component of monasca-vagrant
|
||||
'system_vars': system_vars['default'],
|
||||
|
||||
'notification': {
|
||||
'name': u'Monasca Smoke Test Ā',
|
||||
'addr': 'root@'+system_vars['default']['mail_host'],
|
||||
'type': 'EMAIL'},
|
||||
|
||||
'alarm': {
|
||||
'name': u'high cpu and load Ա',
|
||||
'expression': 'max(cpu.system_perc) > 0 and ' +
|
||||
'max(load.avg_1_min{hostname=' +
|
||||
system_vars['default']['metric_host'] +
|
||||
'}) > 0',
|
||||
'description': u'System CPU Utilization exceeds 1% and ' +
|
||||
u'Load exceeds 3 per measurement period ἀ'},
|
||||
|
||||
'metric': {
|
||||
'name': 'load.avg_1_min',
|
||||
'dimensions': {'hostname':
|
||||
system_vars['default']['metric_host']}},
|
||||
|
||||
'statsd_metric': {
|
||||
'name': 'monasca.sent_smtp_count',
|
||||
'dimensions': {'hostname':
|
||||
system_vars['default']['metric_host']}}
|
||||
},
|
||||
|
||||
'webhook': {
|
||||
'system_vars': system_vars['default'],
|
||||
|
||||
'notification': {
|
||||
'name': 'Smoke Test Webhook',
|
||||
'addr': 'http://127.0.0.1:8080',
|
||||
'type': 'WEBHOOK'},
|
||||
|
||||
'alarm': {
|
||||
'name': 'high cpu and load',
|
||||
'expression': 'max(cpu.system_perc) > 0 and ' +
|
||||
'max(load.avg_1_min{hostname=' +
|
||||
system_vars['default']['metric_host'] +
|
||||
'}) > 0',
|
||||
'description': 'System CPU Utilization exceeds 1% and ' +
|
||||
'Load exceeds 3 per measurement period'},
|
||||
'metric': {
|
||||
'name': 'load.avg_1_min',
|
||||
'dimensions': {'hostname':
|
||||
system_vars['default']['metric_host']}},
|
||||
|
||||
'statsd_metric': {
|
||||
'name': 'monasca.sent_smtp_count',
|
||||
'dimensions': {'hostname':
|
||||
system_vars['default']['metric_host']}}
|
||||
|
||||
}
|
||||
}
|
157
tests/utils.py
157
tests/utils.py
@ -1,157 +0,0 @@
|
||||
from __future__ import print_function
|
||||
import cli_wrapper
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from monascaclient import client
|
||||
from monasca_agent.common.keystone import Keystone
|
||||
|
||||
"""
|
||||
Utility methods for testing
|
||||
"""
|
||||
|
||||
|
||||
OS_USERNAME = 'mini-mon'
|
||||
OS_PASSWORD = 'password'
|
||||
OS_PROJECT_NAME = 'mini-mon'
|
||||
OS_AUTH_URL = 'http://192.168.10.5:35357/v3/'
|
||||
|
||||
|
||||
def check_alarm_history(alarm_id, states):
|
||||
transitions = len(states) - 1
|
||||
print('Checking Alarm History')
|
||||
# May take some time for Alarm history to flow all the way through
|
||||
for _ in range(0, 20):
|
||||
result_json = cli_wrapper.run_mon_cli(['alarm-history', alarm_id])
|
||||
if len(result_json) >= transitions:
|
||||
break
|
||||
time.sleep(4)
|
||||
|
||||
result = True
|
||||
if transitions != len(result_json):
|
||||
print('Wrong number of history entries, expected %d but was %d' %
|
||||
(transitions, len(result_json)), file=sys.stderr)
|
||||
return False
|
||||
# Alarm history is sorted by date
|
||||
index = 0
|
||||
for i in range(0, transitions):
|
||||
old_state = states[i]
|
||||
new_state = states[i+1]
|
||||
alarm_json = result_json[index]
|
||||
if not check_expected(old_state, alarm_json['old_state'], 'old_state',
|
||||
i):
|
||||
result = False
|
||||
if not check_expected(new_state, alarm_json['new_state'], 'new_state',
|
||||
i):
|
||||
result = False
|
||||
if not check_expected(alarm_id, alarm_json['alarm_id'], 'alarm_id',
|
||||
i):
|
||||
result = False
|
||||
index = index + 1
|
||||
|
||||
if result:
|
||||
print('Alarm History is OK')
|
||||
return result
|
||||
|
||||
|
||||
def check_expected(expected, actual, what, index):
|
||||
if (expected == actual):
|
||||
return True
|
||||
print('Wrong %s for alarm history expected %s but was %s transition %d' %
|
||||
(what, expected, actual, index+1), file=sys.stderr)
|
||||
return False
|
||||
|
||||
|
||||
def check_alarm_state(alarm_id, expected):
|
||||
state = cli_wrapper.get_alarm_state(alarm_id)
|
||||
if state != expected:
|
||||
print('Wrong initial alarm state, expected %s but is %s' %
|
||||
(expected, state))
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def get_api_host():
|
||||
# Determine if we are running on multiple VMs or just the one
|
||||
if os.path.isfile('/etc/mon/mon-api-config.yml'):
|
||||
return 'localhost'
|
||||
else:
|
||||
return '192.168.10.4'
|
||||
|
||||
|
||||
def set_if_not_env(name, default):
|
||||
if name not in os.environ:
|
||||
os.environ[name] = default
|
||||
elif default != os.environ[name]:
|
||||
print('%s already set to %s' % (name, os.environ[name]))
|
||||
|
||||
|
||||
def setup_cli():
|
||||
api_host = get_api_host()
|
||||
|
||||
# These need to be set because we are invoking the CLI as a process
|
||||
set_if_not_env('OS_USERNAME', OS_USERNAME)
|
||||
set_if_not_env('OS_PASSWORD', OS_PASSWORD)
|
||||
set_if_not_env('OS_PROJECT_NAME', OS_PROJECT_NAME)
|
||||
set_if_not_env('OS_AUTH_URL', OS_AUTH_URL)
|
||||
os.environ['http_proxy'] = ''
|
||||
os.environ['https_proxy'] = ''
|
||||
os.environ['HTTP_PROXY'] = ''
|
||||
os.environ['HTTPS_PROXY'] = ''
|
||||
|
||||
|
||||
def create_mon_client():
|
||||
api_host = get_api_host()
|
||||
|
||||
token = get_token(OS_USERNAME, OS_PASSWORD, OS_PROJECT_NAME,
|
||||
OS_AUTH_URL)
|
||||
|
||||
api_version = '2_0'
|
||||
endpoint = 'http://' + api_host + ':8080/v2.0'
|
||||
kwargs = {'token': token}
|
||||
return client.Client(api_version, endpoint, **kwargs)
|
||||
|
||||
|
||||
def get_token(os_username, os_password, os_project_name, os_auth_url):
|
||||
kwargs = { 'keystone_url': os_auth_url,
|
||||
'username': os_username,
|
||||
'password': os_password,
|
||||
'project_domain_name':os_project_name}
|
||||
keystone = Keystone(kwargs)
|
||||
|
||||
return keystone.refresh_token()
|
||||
|
||||
|
||||
def ensure_has_notification_engine():
|
||||
if not os.path.isfile('/etc/monasca/notification.yaml'):
|
||||
print('Must be run on a VM with Notification Engine installed',
|
||||
file=sys.stderr)
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def find_notifications(alarm_id, user):
|
||||
args = ['sudo', 'cat', '/var/mail/' + user]
|
||||
result = []
|
||||
env = os.environ.copy()
|
||||
env['PYTHONIOENCODING'] = "utf-8"
|
||||
try:
|
||||
stdout = subprocess.check_output(args, env=env)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(e, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
previous = ''
|
||||
for line in stdout.splitlines():
|
||||
# Get the state; the alarm_id always follows the state message
|
||||
line = unicode(line, "utf-8")
|
||||
if alarm_id in line:
|
||||
""" In the notification message the state verb is framed by
|
||||
'transitioned to the ' and ' state'
|
||||
"""
|
||||
result.append(re.search('transitioned to the (.+?) state',
|
||||
previous).group(1))
|
||||
previous = line
|
||||
return result
|
Loading…
Reference in New Issue
Block a user