-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
156 lines (127 loc) · 5.15 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"""Main module of kytos/pathfinder Kytos Network Application."""
from flask import jsonify, request
from kytos.core import KytosNApp, log, rest
from kytos.core.helpers import listen_to
import traceback
# pylint: disable=import-error
# from napps.kytos.pathfinder.graph import KytosGraph
from graph import KytosGraph
# pylint: enable=import-error
class Main(KytosNApp):
"""
Main class of kytos/pathfinder NApp.
This class is the entry point for this napp.
"""
def setup(self):
"""Create a graph to handle the nodes and edges."""
self.graph = KytosGraph()
self._topology = None
def execute(self):
"""Do nothing."""
def shutdown(self):
"""Shutdown the napp."""
def _filter_paths(self, paths, desired, undesired):
"""
Apply filters to the paths list.
Make sure that each path in the list has all the desired links and none
of the undesired ones.
"""
filtered_paths = []
if desired:
for link_id in desired:
try:
endpoint_a = self._topology.links[link_id].endpoint_a.id
endpoint_b = self._topology.links[link_id].endpoint_b.id
except KeyError:
return []
for path in paths:
head = path['hops'][:-1]
tail = path['hops'][1:]
if (((endpoint_a, endpoint_b) in zip(head, tail)) or
((endpoint_b, endpoint_a) in zip(head, tail))):
filtered_paths.append(path)
else:
filtered_paths = paths
if undesired:
for link_id in undesired:
try:
endpoint_a = self._topology.links[link_id].endpoint_a.id
endpoint_b = self._topology.links[link_id].endpoint_b.id
except KeyError:
continue
for path in paths:
head = path['hops'][:-1]
tail = path['hops'][1:]
if (((endpoint_a, endpoint_b) in zip(head, tail)) or
((endpoint_b, endpoint_a) in zip(head, tail))):
filtered_paths.remove(path)
return filtered_paths
@rest('v2/', methods=['POST'])
def shortest_path(self):
"""Calculate the best path between the source and destination."""
data = request.get_json()
desired = data.get('desired_links')
undesired = data.get('undesired_links')
parameter = data.get('parameter')
paths = []
for path in self.graph.shortest_paths(data['source'],
data['destination'],
parameter):
paths.append({'hops': path})
paths = self._filter_paths(paths, desired, undesired)
return jsonify({'paths': paths})
@rest('v2/path-exact-delay', methods=['POST'])
def path_exact_delay(self):
"""
Calculate the path with the exact delay
between the source and destination.
"""
data = request.get_json()
source = data.get('source')
destination = data.get('destination')
delay = data.get('delay')
graph_data = {}
try:
result = self.graph.exact_path(delay, source, destination)
except Exception:
return jsonify({"exception": str(traceback.format_exc())})
graph_data["Exact Path Result"] = result
return jsonify(graph_data)
@rest('v2/best-constrained-paths', methods=['POST'])
def shortest_constrained_path(self):
"""
Get the set of shortest paths between the source and destination.
"""
data = request.get_json()
source = data.get('source')
destination = data.get('destination')
base_metrics = data.get('base_metrics', {})
fle_metrics = data.get('flexible_metrics', {})
minimum_hits = data.get('minimum_flexible_hits')
try:
paths = self.graph.constrained_flexible_paths(source, destination,
minimum_hits,
base=base_metrics,
flexible=fle_metrics)
return jsonify(paths)
except TypeError as err:
return jsonify({"error": str(err)}), 400
except Exception as err:
return jsonify({"error": str(err)}), 500
@listen_to('kytos.topology.updated')
def update_topology(self, event):
"""
Update the graph when the network topology was updated.
Clear the current graph and create a new with the most topology updated.
"""
if 'topology' not in event.content:
return
try:
topology = event.content['topology']
self._topology = topology
self.graph.update_topology(topology)
log.debug('Topology graph updated.')
except TypeError as err:
log.debug(err)
except Exception as err:
log.debug(err)