From 675f70c73baf428c537091d454c162185a407f6e Mon Sep 17 00:00:00 2001 From: Nikolay Stanchev <ns17@it-innovation.soton.ac.uk> Date: Tue, 27 Mar 2018 08:39:23 +0100 Subject: [PATCH] [ Issue #61 ] - monitoring endpoint configuration test --- clmctest/monitoring/LineProtocolGenerator.py | 29 ++++++ clmctest/monitoring/test_endpoint_config.py | 97 ++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 clmctest/monitoring/test_endpoint_config.py diff --git a/clmctest/monitoring/LineProtocolGenerator.py b/clmctest/monitoring/LineProtocolGenerator.py index 1b19c3c..416a144 100644 --- a/clmctest/monitoring/LineProtocolGenerator.py +++ b/clmctest/monitoring/LineProtocolGenerator.py @@ -87,6 +87,35 @@ def generate_ipendpoint_route(resource, requests, latency, time): return result +def generate_mc_endpoint_config(state, cpu, mem, storage, statePeriod, time): + """ + generates a measurement + + :param cpu: the number of CPUs of VM endpoint + :param mem: memory of VM endpoint + :param storage: storage capacity of VM endpoint + :param state: the state that was monitored (e.g. placing, booting or connecting) + :param statePeriod: the period of time, the IP endpoint was in this state + :param time: time of measurement + :return: dictionary object representing the data to post to influx + """ + + result = [{"measurement": "mcEndpointConfig", + "tags": + { + "state": state + }, + "fields": + {"cpus": cpu, + "memory": mem, + "storage": storage, + "statePeriod": statePeriod, + }, + "time": _getNSTime(time)}] + + return result + + # InfluxDB likes to have time-stamps in nanoseconds def _getNSTime(time): # Convert to nano-seconds diff --git a/clmctest/monitoring/test_endpoint_config.py b/clmctest/monitoring/test_endpoint_config.py new file mode 100644 index 0000000..244b7ca --- /dev/null +++ b/clmctest/monitoring/test_endpoint_config.py @@ -0,0 +1,97 @@ +#!/usr/bin/python3 + +import pytest +from influxdb import InfluxDBClient +import clmctest.monitoring.LineProtocolGenerator as lp +import random +import time + + +""" +Tests the monitoring of endpoints' configuration states - currently based on model with three states (placing -> booting -> connecting) +""" + + +state_delays = [{'placing': random.randint(75, 125)/10, 'booting': random.randint(75, 125)/10, 'connecting': random.randint(75, 125)/10}, + {'placing': random.randint(75, 125)/10, 'booting': random.randint(75, 125)/10, 'connecting': random.randint(75, 125)/10}] # Random initialization of state periods +measurement_name = 'mcEndpointConfig' # measurement name for configuration of media components' endpoints + + +@pytest.mark.parametrize("query, result", [ + ('SELECT "state", "statePeriod", "cpus", "memory", "storage" FROM "CLMCMetrics"."autogen"."mcEndpointConfig" WHERE ipendpoint=\'adaptive_streaming_I1_apache1\' and sf=\'adaptive_streaming\'', + {'placing': {"state": "placing", "statePeriod": state_delays[0]['placing'], "cpus": 1, "memory": 2048, "storage": '10GB'}, + 'booting': {"state": "booting", "statePeriod": state_delays[0]['booting'], "cpus": 1, "memory": 2048, "storage": '10GB'}, + 'connecting': {"state": "connecting", "statePeriod": state_delays[0]['connecting'], "cpus": 1, "memory": 2048, "storage": '10GB'}}), + ('SELECT "state", "statePeriod", "cpus", "memory", "storage" FROM "CLMCMetrics"."autogen"."mcEndpointConfig" WHERE ipendpoint=\'adaptive_streaming_I1_apache2\' and sf=\'adaptive_streaming\'' , + {'placing': {"state": "placing", "statePeriod": state_delays[1]['placing'], "cpus": 1, "memory": 2048, "storage": '10GB'}, + 'booting': {"state": "booting", "statePeriod": state_delays[1]['booting'], "cpus": 1, "memory": 2048, "storage": '10GB'}, + 'connecting': {"state": "connecting", "statePeriod": state_delays[1]['connecting'], "cpus": 1, "memory": 2048, "storage": '10GB'}}) +]) +def test_endpoint_config(query, result, get_db_client): + """ + :param query: query under test for the endpoint configuration state + :param result: expected result of executed query + :param get_db_client: the InfluxDB client fixture from conftest.py + """ + + print("\n") # blank line for formatting purposes + + measurements = get_db_client.query(query, raise_errors=False).get_points() + + assert all(map(lambda measurement: compare(measurement, result), measurements)), "Comparison failure for query:\n{0}".format(query) + + print("Successfully passed test for query:\n{0}".format(query)) + + +@pytest.fixture(scope='module', autouse=True) +def generate_states_data(streaming_sim_config, get_db_client): + """ + Sends configuration state data to influx for the two mc endpoints + + :param streaming_sim_config: the configuration fixture from conftest.py + :param get_db_client: the influx db client + """ + + global state_delays + global measurement_name + + if measurement_name in (measurement['name'] for measurement in get_db_client.get_list_measurements()): + get_db_client.drop_measurement(measurement_name) # clear DB measurement from previous test if exists + + time.sleep(2) + + for i in range(1, 3): + measurement_time = 1 + for state in state_delays[i-1].keys(): + epURL = streaming_sim_config['hosts'][i]['ip_address'] # endpoint URL + mc_EndpointID = streaming_sim_config['hosts'][i]['ipendpoint_id'] + cpu = streaming_sim_config['hosts'][i]['cpus'] + mem = streaming_sim_config['hosts'][i]['memory'] + disk = streaming_sim_config['hosts'][i]['disk'] + + db_name = streaming_sim_config['hosts'][i]['database_name'] + db_client = InfluxDBClient(host=epURL, port=8186, database=db_name, timeout=10) + + period = state_delays[i-1].get(state) + print("Endpoint - {0}, state - {1}, period - {2}s".format(mc_EndpointID, state, period)) + + db_client.write_points(lp.generate_mc_endpoint_config(state, cpu, mem, disk, period, measurement_time)) + measurement_time += period + + time.sleep(10) + + +def compare(actual_measurement, measurement_dict): + """ + Auxiliary function to check whether the measurements are the same, excluding the time stamp field + + :param actual_measurement: the actual measurement from Influx (the one with a time stamp + :param measurement_dict: the dictionary of expected measurements + :return: True for equality and False otherwise + """ + + actual_measurement.pop('time') + # get the measurement state we are comparing and fetch it from the dictionary of expected measurements + expected_measurement = measurement_dict.get(actual_measurement.get('state')) + + return actual_measurement == expected_measurement -- GitLab