Skip to content
Snippets Groups Projects
Commit 99a513a3 authored by Nikolay Stanchev's avatar Nikolay Stanchev
Browse files

Updates GraphAPI to also build UEs in the network topology

parent 7cfb7a8c
No related branches found
No related tags found
No related merge requests found
......@@ -82,6 +82,12 @@ clusters = {
"127.0.0.6": "DC6"
}
ues = {
"127.0.0.1": "ue1",
"127.0.0.3": "ue3",
"127.0.0.6": "ue6"
}
@pytest.fixture(scope='module', autouse=True)
def db_testing_data():
......@@ -105,8 +111,8 @@ def db_testing_data():
# create the physical infrastructure subgraph
dbs = influx.get_list_database()
switch_count, cluster_count = build_network_graph(graph, switches, links, clusters)
assert switch_count == 6 and cluster_count == 6, "Network graph build failure"
switch_count, cluster_count, ues_count = build_network_graph(graph, switches, links, clusters, ues)
assert switch_count == 6 and cluster_count == 6 and ues_count == 3, "Network graph build failure"
# check if exists ( if so, clear ) or create the test DB in influx
if test_db_name in dbs:
......
......@@ -106,6 +106,9 @@ class TestGraphAPI(object):
from_timestamp, to_timestamp, graph_db = db_testing_data
ue_nodes = set([node["name"] for node in graph_db.nodes.match("UserEquipment")])
assert ue_nodes == set("ue" + str(i) for i in [1, 3, 6]), "UE nodes have not been created"
dc_nodes = set([node["name"] for node in graph_db.nodes.match("Cluster")])
assert dc_nodes == set("DC" + str(i) for i in range(1, 7)), "Compute nodes must have been created by the db_testing_data fixture"
......@@ -457,7 +460,7 @@ class TestGraphAPI(object):
request = testing.DummyRequest()
response = GraphAPI(request).delete_network_topology()
assert response == {"deleted_switches_count": 6, "deleted_clusters_count": 6}
assert response == {"deleted_switches_count": 6, "deleted_clusters_count": 6, "deleted_ues_count": 3}
@staticmethod
def check_exist_relationship(relationships_tuple, graph, uuid):
......
......@@ -290,7 +290,7 @@ def delete_temporal_subgraph(graph, subgraph_id):
return nodes_matched
def build_network_graph(graph, switches, links, clusters):
def build_network_graph(graph, switches, links, clusters, ues):
"""
A function used to build the network topology in the neo4j graph given the collection of switches, links and clusters.
......@@ -298,10 +298,13 @@ def build_network_graph(graph, switches, links, clusters):
:param switches: a collection of all switches in the topology - mapping between the DPID of the switch and its IP address
:param links: a collection of all switch-to-switch links in the network topology - JSON format, list of objects, each object must have "src-switch", "dst-switch" and "latency" as keys
:param clusters: a collection of all clusters and the IP address of the service router that they are connected to - mapping between an IP address of a service router and a cluster identifier
:param ues: a collection of all ues and the IP address of the service router that they are connected to - mapping between an IP address of a servicer router and a ue identifier
"""
new_switches_count = 0
new_clusters_count = 0
new_ues_count = 0
for link in links:
# get the DPID of the source switch
source = link["src-switch"]
......@@ -329,23 +332,41 @@ def build_network_graph(graph, switches, links, clusters):
# create the link between the two nodes
find_or_create_edge(graph, "linkedTo", from_node, to_node, latency=latency)
# check whether the source service router connects a particular cluster
if source in clusters:
cluster_name = clusters[source]
cluster_node, created = find_or_create_node(graph, "Cluster", return_created=True, name=cluster_name)
if created:
new_clusters_count += 1
find_or_create_edge(graph, "linkedTo", cluster_node, from_node, latency=0)
# check whether the source service router connects a particular cluster or a particular UE
if create_node_from_mapping(graph, from_node, source, clusters, "Cluster"):
new_clusters_count += 1
if create_node_from_mapping(graph, from_node, source, ues, "UserEquipment"):
new_ues_count += 1
# check whether the destination service router connects a particular cluster or a particular UE
if create_node_from_mapping(graph, to_node, destination, clusters, "Cluster"):
new_clusters_count += 1
if create_node_from_mapping(graph, to_node, destination, ues, "UserEquipment"):
new_ues_count += 1
return new_switches_count, new_clusters_count, new_ues_count
# check whether the destination service router connects a particular cluster
if destination in clusters:
cluster_name = clusters[destination]
cluster_node, created = find_or_create_node(graph, "Cluster", return_created=True, name=cluster_name)
if created:
new_clusters_count += 1
find_or_create_edge(graph, "linkedTo", cluster_node, to_node, latency=0)
def create_node_from_mapping(graph, node, node_ip, mapping, new_node_type):
"""
Creates an additional node of a given type if a mapping from a switch node is found.
:param graph: the neo4j graph database client
:param node: the original node
:param node_ip: the original node's IP address
:param mapping: the mapping object (dictionary from IP address to identifier)
:param new_node_type: the type of the new node to be created
return new_switches_count, new_clusters_count
:return: True if new node was created and False otherwise
"""
if node_ip in mapping:
new_node_name = mapping[node_ip]
new_node, created = find_or_create_node(graph, new_node_type, return_created=True, name=new_node_name)
find_or_create_edge(graph, "linkedTo", new_node, node, latency=0)
return created
return False
def delete_network_graph(graph):
......@@ -359,21 +380,28 @@ def delete_network_graph(graph):
log.info("Deleting Switch nodes.".format())
subgraph = graph.nodes.match("Switch")
deleted_switches = 0
deleted_switches = len(subgraph)
for node in subgraph:
graph.delete(node)
deleted_switches += 1
log.info("Deleted {0} Switch nodes.".format(deleted_switches))
log.info("Deleting Cluster nodes.")
subgraph = graph.nodes.match("Cluster")
deleted_clusters = 0
deleted_clusters = len(subgraph)
for node in subgraph:
graph.delete(node)
deleted_clusters += 1
log.info("Deleted {0} Cluster nodes.".format(deleted_clusters))
return deleted_switches, deleted_clusters
log.info("Deleting UserEquipment nodes.")
subgraph = graph.nodes.match("UserEquipment")
deleted_ues = len(subgraph)
for node in subgraph:
graph.delete(node)
log.info("Deleted {0} UserEquipment nodes.".format(deleted_clusters))
return deleted_switches, deleted_clusters, deleted_ues
......@@ -302,22 +302,33 @@ class GraphAPI(object):
raise HTTPNotImplemented("The SDN controller failed to return a valid JSON response when querying for the network topology.")
# TODO this is a temporary solution - currently the service router to clusters mapping is read from a file (which must be manually prepared beforehand)
clusters_file = self.request.registry.settings["network_configuration_path"]
clusters_file = self.request.registry.settings["network_clusters_path"]
try:
with open(clusters_file) as fh:
clusters = load(fh)
except Exception as e:
log.error("Unexpected error: {0}".format(e))
log.error("No service_router-to-cluster mapping was found while building the network topology.")
log.error("No service-router-to-cluster mapping was found while building the network topology.")
clusters = {}
# TODO this is a temporary solution - currently the service router to ues mapping is read from a file (which must be manually prepared beforehand)
ues_file = self.request.registry.settings["network_ues_path"]
try:
with open(ues_file) as fh:
ues = load(fh)
except Exception as e:
log.error("Unexpected error: {0}".format(e))
log.error("No ue-to-cluster mapping was found while building the network topology.")
ues = {}
# build the network graph and retrieve the number of switch nodes and cluster nodes that were created
tmp_switch_count, tmp_clusters_count = build_network_graph(graph, switches, external_links, clusters)
switch_count, clusters_count = build_network_graph(graph, switches, local_links, clusters)
tmp_switch_count, tmp_clusters_count, tmp_ues_count = build_network_graph(graph, switches, external_links, clusters, ues)
switch_count, clusters_count, ues_count = build_network_graph(graph, switches, local_links, clusters, ues)
switch_count += tmp_switch_count
clusters_count += tmp_clusters_count
ues_count += tmp_ues_count
return {"new_switches_count": switch_count, "new_clusters_count": clusters_count}
return {"new_switches_count": switch_count, "new_clusters_count": clusters_count, "new_ues_count": ues_count}
@view_config(route_name='graph_network_topology', request_method='DELETE')
def delete_network_topology(self):
......@@ -329,6 +340,6 @@ class GraphAPI(object):
graph = Graph(host=self.request.registry.settings['neo4j_host'], password=self.request.registry.settings['neo4j_password']) # connect to the neo4j graph db
deleted_switches, deleted_clusters = delete_network_graph(graph)
deleted_switches, deleted_clusters, deleted_ues = delete_network_graph(graph)
return {"deleted_switches_count": deleted_switches, "deleted_clusters_count": deleted_clusters}
return {"deleted_switches_count": deleted_switches, "deleted_clusters_count": deleted_clusters, "deleted_ues_count": deleted_ues}
......@@ -15,7 +15,9 @@ pyramid.includes = pyramid_debugtoolbar pyramid_exclog
exclog.ignore =
network_configuration_path = /opt/clmc/src/service/resources/GraphAPI/network_clusters.json
network_clusters_path = /opt/clmc/src/service/resources/GraphAPI/network_clusters.json
network_ues_path = /opt/clmc/src/service/resources/GraphAPI/network_ues.json
# 10000 Mb/s = 10 Gb/s
network_bandwidth = 10000
......
......@@ -15,7 +15,9 @@ pyramid.includes = pyramid_exclog
exclog.ignore =
network_configuration_path = /opt/clmc/src/service/resources/GraphAPI/network_clusters.json
network_clusters_path = /opt/clmc/src/service/resources/GraphAPI/network_clusters.json
network_ues_path = /opt/clmc/src/service/resources/GraphAPI/network_ues.json
# 10000 Mb/s = 10 Gb/s
network_bandwidth = 10000
......
{
"172.20.231.3": "ue20",
"172.20.231.22": "ue22",
"172.20.231.7": "ue23",
"172.20.231.19": "ue24"
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment