diff --git a/src/service/clmcservice/graphapi/tests.py b/src/service/clmcservice/graphapi/tests.py index f3519dc8fc5a57a399f2261df297433b68653b4b..d55d002983ee9d8b0855d4f68d7281a9c3f9fc74 100644 --- a/src/service/clmcservice/graphapi/tests.py +++ b/src/service/clmcservice/graphapi/tests.py @@ -118,15 +118,9 @@ class TestGraphAPI(object): "request_size_field": "mean(avg_request_size)", "response_size_field": "mean(avg_response_size)"}) body = dumps(dict(service_function_chain="sfc", service_function_chain_instance="sfc_1", service_functions=service_functions)) request = testing.DummyRequest() - request.params["from_timestamp"] = 12341412 - request.params["to_timestamp"] = 12341412 request.body = body.encode(request.charset) - error_raised = False - try: + with pytest.raises(HTTPBadRequest, message="A bad request error must have been raised in case of missing timestamp parameters."): GraphAPI(request).build_temporal_graph() - except HTTPBadRequest: - error_raised = True - assert error_raised, "A bad request error must have been raised in case of invalid URL parameters." # Create a valid build request and send it to the API endpoint service_functions = dict(nginx={"measurement_name": "nginx", "response_time_field": "mean(avg_processing_time)", @@ -134,10 +128,10 @@ class TestGraphAPI(object): minio={"measurement_name": "minio_http", "response_time_field": "mean(total_processing_time)/mean(total_requests_count)", "request_size_field": "mean(total_requests_size)/mean(total_requests_count)", "response_size_field": "mean(total_response_size)/mean(total_requests_count)"}) build_json_body = dict(service_function_chain="test_sfc", service_function_chain_instance="test_sfc_premium", service_functions=service_functions) + build_json_body["from"] = from_timestamp + build_json_body["to"] = to_timestamp body = dumps(build_json_body) request = testing.DummyRequest() - request.params["from"] = from_timestamp - request.params["to"] = to_timestamp request.body = body.encode(request.charset) response = GraphAPI(request).build_temporal_graph() graph_subresponse = response.pop("graph") @@ -193,10 +187,10 @@ class TestGraphAPI(object): apache={"measurement_name": "apache", "response_time_field": "mean(avg_processing_time)", "request_size_field": "mean(avg_request_size)", "response_size_field": "mean(avg_response_size)"}) build_json_body = dict(service_function_chain="test_sfc", service_function_chain_instance="test_sfc_non_premium", service_functions=service_functions) + build_json_body["from"] = from_timestamp + build_json_body["to"] = to_timestamp body = dumps(build_json_body) request = testing.DummyRequest() - request.params["from"] = from_timestamp - request.params["to"] = to_timestamp request.body = body.encode(request.charset) response = GraphAPI(request).build_temporal_graph() graph_subresponse = response.pop("graph") @@ -330,10 +324,10 @@ class TestGraphAPI(object): minio={"measurement_name": "minio_http", "response_time_field": "mean(total_processing_time)/mean(total_requests_count)", "request_size_field": "mean(total_requests_size)/mean(total_requests_count)", "response_size_field": "mean(total_response_size)/mean(total_requests_count)"}) build_json_body = dict(service_function_chain="test_sfc", service_function_chain_instance="test_sfc_premium", service_functions=service_functions) + build_json_body["from"] = from_timestamp + build_json_body["to"] = to_timestamp body = dumps(build_json_body) request = testing.DummyRequest() - request.params["from"] = from_timestamp - request.params["to"] = to_timestamp request.body = body.encode(request.charset) response = GraphAPI(request).build_temporal_graph() graph_subresponse = response.pop("graph") @@ -401,10 +395,10 @@ class TestGraphAPI(object): apache={"measurement_name": "apache", "response_time_field": "mean(avg_processing_time)", "request_size_field": "mean(avg_request_size)", "response_size_field": "mean(avg_response_size)"}) build_json_body = dict(service_function_chain="test_sfc", service_function_chain_instance="test_sfc_non_premium", service_functions=service_functions) + build_json_body["from"] = from_timestamp + build_json_body["to"] = to_timestamp body = dumps(build_json_body) request = testing.DummyRequest() - request.params["from"] = from_timestamp - request.params["to"] = to_timestamp request.body = body.encode(request.charset) response = GraphAPI(request).build_temporal_graph() graph_subresponse = response.pop("graph") diff --git a/src/service/clmcservice/graphapi/utilities.py b/src/service/clmcservice/graphapi/utilities.py index 4117b22976ef8330c69c9599ab810fae3d0d7520..9149613701fb11cc0e46908e2dda8d376b1ea69f 100644 --- a/src/service/clmcservice/graphapi/utilities.py +++ b/src/service/clmcservice/graphapi/utilities.py @@ -29,8 +29,7 @@ import logging GRAPH_ROUND_TRIP_TIME_URL_PARAMS = ("startpoint", "endpoint") -GRAPH_BUILD_URL_PARAMS = ("from", "to") -GRAPH_BUILD_QUERY_PARAMS = {"service_function_chain", "service_function_chain_instance", "service_functions"} +GRAPH_BUILD_QUERY_PARAMS = {"from", "to", "service_function_chain", "service_function_chain_instance", "service_functions"} GRAPH_BUILD_SF_QUERY_PARAMS = {"response_time_field", "request_size_field", "response_size_field", "measurement_name"} INFLUX_QUERY_TEMPLATE = 'SELECT {0} AS mean_response_time, {1} AS mean_request_size, {2} AS mean_response_size FROM "{3}"."{4}".{5} WHERE "flame_sfc"=\'{6}\' and "flame_sfci"=\'{7}\' and time>={8} and time<{9} GROUP BY "flame_sfe", "flame_location", "flame_sf"' @@ -100,33 +99,12 @@ def validate_json_queries_body(body): assert type(query_data) == dict, "Each service function must be associated with a respective JSON object." assert GRAPH_BUILD_SF_QUERY_PARAMS == set(query_data.keys()), "Invalid query data for service function {0} in the JSON query document".format(sf) - return body - - -def validate_graph_url_params(params): - """ - Validates the request url parameters used in building a temporal graph. - - :param params: the parameters dictionary to validate - :return: the validated parameters - :raise AssertionError: for invalid parameters - """ + assert type(body["from"]) == int, "'from' parameter must be a timestamp integer" + assert body["from"] > 0, "'from' parameter must be a positive timestamp integer" + assert type(body["to"]) == int, "'to' parameter must be a timestamp integer" + assert body["to"] > body["from"], "'to' parameter timestamp must be greater than 'from' parameter timestamp" - global GRAPH_BUILD_URL_PARAMS - - url_params = {} - for param in GRAPH_BUILD_URL_PARAMS: - assert param in params, "Incorrect url parameters - required url query parameter '{0}' is not found in the request parameters.".format(param) - url_params[param] = params[param] - - try: - # convert timestamps to integers - url_params['from'] = int(url_params['from']) - url_params['to'] = int(url_params['to']) - except ValueError: - assert False, "Invalid URL timestamp parameters" - - return url_params + return body def validate_graph_rtt_params(params): diff --git a/src/service/clmcservice/graphapi/views.py b/src/service/clmcservice/graphapi/views.py index a604d433dff62f545a61cee1d7f77d146f616e7f..9bac0e146306b5e86d6dcd935c81f58d219befc5 100644 --- a/src/service/clmcservice/graphapi/views.py +++ b/src/service/clmcservice/graphapi/views.py @@ -23,8 +23,8 @@ """ -from clmcservice.graphapi.utilities import validate_json_queries_body, validate_graph_url_params, \ - build_network_graph, delete_network_graph, build_temporal_subgraph, delete_temporal_subgraph, validate_graph_rtt_params, RTT_CYPHER_QUERY_TEMPLATE +from clmcservice.graphapi.utilities import validate_json_queries_body, RTT_CYPHER_QUERY_TEMPLATE, \ + build_network_graph, delete_network_graph, build_temporal_subgraph, delete_temporal_subgraph, validate_graph_rtt_params from influxdb import InfluxDBClient from py2neo import Graph from pyramid.httpexceptions import HTTPBadRequest, HTTPNotFound, HTTPServiceUnavailable, HTTPNotImplemented @@ -57,9 +57,8 @@ class GraphAPI(object): def build_temporal_graph(self): """ An API endpoint to build a temporal graph and store it in neo4j based on the posted JSON query document. - The request parameters must also include URL query parameters defining the time range for which the graph must be generated. - :raises HTTPBadRequest: if request body is not a valid JSON with the queries per service function or if request URL doesn't contain the required URL query parameters + :raises HTTPBadRequest: if request body is not a valid JSON with the queries per service function :return: A JSON document containing the posted request body, along with meta data about the built graph (time range and uuid, which can then be reused for other API calls) """ @@ -69,11 +68,6 @@ class GraphAPI(object): except AssertionError as e: raise HTTPBadRequest("Bad request content: {0}".format(e.args)) - try: - params = validate_graph_url_params(self.request.params) - except AssertionError as e: - raise HTTPBadRequest("Request URL format is incorrect: {0}".format(e.args)) - graph = Graph(host=self.request.registry.settings['neo4j_host'], password=self.request.registry.settings['neo4j_password']) influx_client = InfluxDBClient(host=self.request.registry.settings['influx_host'], port=self.request.registry.settings['influx_port'], timeout=10) @@ -81,8 +75,8 @@ class GraphAPI(object): if database_name not in [db["name"] for db in influx_client.get_list_database()]: raise HTTPBadRequest("Database for service function chain {0} not found.".format(database_name)) - from_timestamp = params['from'] * 10**9 - to_timestamp = params['to'] * 10**9 + from_timestamp = json_queries['from'] * 10**9 + to_timestamp = json_queries['to'] * 10**9 request_id = str(uuid4())