diff --git a/src/service/clmcservice/graphapi/tests.py b/src/service/clmcservice/graphapi/tests.py index 12c662897f0092170351dc05baf56c971faf0323..6f2ee88fc19382991654592b5661a0e5349a15ce 100644 --- a/src/service/clmcservice/graphapi/tests.py +++ b/src/service/clmcservice/graphapi/tests.py @@ -284,20 +284,20 @@ class TestGraphAPI(object): assert set([node["name"] for node in graph_db.nodes.match("ServiceFunctionChainInstance")]) == {"test_sfc_premium", "test_sfc_non_premium"}, "Service function chain instances must not be deleted" assert set([node["name"] for node in graph_db.nodes.match("ServiceFunctionChain")]) == {"test_sfc"}, "Service function chains must not be deleted" - @pytest.mark.parametrize("graph_id, endpoint, compute_node, error_type, error_msg", [ + @pytest.mark.parametrize("graph_id, endpoint, startpoint, error_type, error_msg", [ ('e8cd4768-47dd-48cd-9c74-7f8926ddbad8', None, None, HTTPBadRequest, "HTTP Bad Request must be thrown in case of missing or invalid url parameters"), ('e8cd4768-47dd-48cd-9c74-7f8926ddbad8', None, "nginx", HTTPBadRequest, "HTTP Bad Request must be thrown in case of missing or invalid url parameters"), ('e8cd4768-47dd-48cd-9c74-7f8926ddbad8', "nginx_1_ep1", None, HTTPBadRequest, "HTTP Bad Request must be thrown in case of missing or invalid url parameters"), ('random-uuid', "nginx_1_ep1", "nginx", HTTPNotFound, "HTTP Not Found error must be thrown for an endpoint node with incorrect request ID"), ('random-uuid', "minio_1_ep1", "minio", HTTPNotFound, "HTTP Not Found error must be thrown for an endpoint node with incorrect request ID"), ]) - def test_rtt_error_handling(self, graph_id, endpoint, compute_node, error_type, error_msg): + def test_rtt_error_handling(self, graph_id, endpoint, startpoint, error_type, error_msg): """ Tests the error handling of the graph round trip time API endpoint - achieved by sending erroneous input in the request and verifying the appropriate error type has been returned. :param graph_id: the UUID of the subgraph :param endpoint: endpoint ID - :param compute_node: compute node ID + :param startpoint: the start node ID :param error_type: error type to expect as a response :param error_msg: error message in case of a test failure """ @@ -306,8 +306,8 @@ class TestGraphAPI(object): request.matchdict["graph_id"] = graph_id if endpoint is not None: request.params["endpoint"] = endpoint - if compute_node is not None: - request.params["compute_node"] = compute_node + if startpoint is not None: + request.params["startpoint"] = startpoint error_raised = False try: GraphAPI(request).run_rtt_query() @@ -356,7 +356,7 @@ class TestGraphAPI(object): request = testing.DummyRequest() request.matchdict["graph_id"] = request_id request.params["endpoint"] = "nginx_1_ep1" - request.params["compute_node"] = "DC0" + request.params["startpoint"] = "DC0" error_raised = False try: GraphAPI(request).run_rtt_query() @@ -367,7 +367,7 @@ class TestGraphAPI(object): request = testing.DummyRequest() request.matchdict["graph_id"] = request_id request.params["endpoint"] = "apache_1_ep1" - request.params["compute_node"] = "DC1" + request.params["startpoint"] = "DC1" error_raised = False try: GraphAPI(request).run_rtt_query() @@ -384,7 +384,7 @@ class TestGraphAPI(object): request = testing.DummyRequest() request.matchdict["graph_id"] = request_id request.params["endpoint"] = endpoint - request.params["compute_node"] = dc + request.params["startpoint"] = dc response = GraphAPI(request).run_rtt_query() # approximation is used to avoid long float numbers retrieved from influx, the test case ensures the results are different enough so that approximation of +-1 is good enough for testing assert response.pop("round_trip_time") == pytest.approx(rtt, 1), "Incorrect RTT response" @@ -419,7 +419,7 @@ class TestGraphAPI(object): request = testing.DummyRequest() request.matchdict["graph_id"] = request_id request.params["endpoint"] = endpoint - request.params["compute_node"] = dc + request.params["startpoint"] = dc response = GraphAPI(request).run_rtt_query() # approximation is used to avoid long float numbers retrieved from influx, the test case ensures the results are different enough so that approximation of +-1 is good enough for testing assert response.pop("request_size") == pytest.approx(request_size, 1), "Incorrect RTT response" diff --git a/src/service/clmcservice/graphapi/views.py b/src/service/clmcservice/graphapi/views.py index b60ccf2e2c1d6cd1c4a9897552fe2a4d8525bc80..a604d433dff62f545a61cee1d7f77d146f616e7f 100644 --- a/src/service/clmcservice/graphapi/views.py +++ b/src/service/clmcservice/graphapi/views.py @@ -136,20 +136,34 @@ class GraphAPI(object): if reference_node is None: raise HTTPNotFound("No subgraph found associated with the request ID {0}".format(graph_id)) - startpoint_node = all_nodes.match("Switch", "Cluster", name=startpoint_node_label).first() # match a switch or cluster node as a path start point + # match a switch or cluster node as a path start point and capture the type of the node + startpoint_node = all_nodes.match("Switch", name=startpoint_node_label).first() if startpoint_node is None: - raise HTTPNotFound("Starting point node {0} doesn't exist.".format(startpoint_node_label)) + startpoint_node = all_nodes.match("Cluster", name=startpoint_node_label).first() + if startpoint_node is None: + # no match with Swtich/Cluster node + raise HTTPNotFound("Starting point node {0} doesn't exist.".format(startpoint_node_label)) + else: + # a match with a Cluster node + startpoint_node_type = "Cluster" + else: + # a match with a Switch node + startpoint_node_type = "Switch" endpoint_node = all_nodes.match("Endpoint", name=endpoint_node_label, uuid=graph_id).first() if endpoint_node is None: raise HTTPNotFound("Endpoint node {0} doesn't exist.".format(endpoint_node_label)) - startpoint_node_type = "Cluster" if startpoint_node.has_label("Cluster") else "Switch" - - query_to_execute = RTT_CYPHER_QUERY_TEMPLATE.format(startpoint_node_type, startpoint_node_label, endpoint_node_label, graph_id) - log.info("Executing cypher query: {0}".format(query_to_execute)) - data = graph.run(query_to_execute).data() # returns a list of dictionaries, each dictionary represents a row in the result - result = data[0] + # check if the endpoint is hosted by the compute node before running the RTT cypher query + hosted_by_node = graph.relationships.match(nodes=(endpoint_node, None), r_type="hostedBy").first().end_node + if hosted_by_node["name"] == startpoint_node["name"]: + result = {"forward_latencies": [], "reverse_latencies": [], "response_time": endpoint_node["response_time"], + "request_size": endpoint_node["request_size"], "response_size": endpoint_node["response_size"]} + else: + query_to_execute = RTT_CYPHER_QUERY_TEMPLATE.format(startpoint_node_type, startpoint_node_label, endpoint_node_label, graph_id) + log.info("Executing cypher query: {0}".format(query_to_execute)) + data = graph.run(query_to_execute).data() # returns a list of dictionaries, each dictionary represents a row in the result + result = data[0] sf_node = graph.match(nodes=(None, endpoint_node), r_type="realisedBy").first().start_node if sf_node is None: