Refactoring: Made complete codebase PEP8 compatible.
[osm/vim-emu.git] / src / emuvim / api / rest / monitor.py
1 # Copyright (c) 2015 SONATA-NFV and Paderborn University
2 # ALL RIGHTS RESERVED.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 # Neither the name of the SONATA-NFV, Paderborn University
17 # nor the names of its contributors may be used to endorse or promote
18 # products derived from this software without specific prior written
19 # permission.
20 #
21 # This work has been performed in the framework of the SONATA project,
22 # funded by the European Commission under Grant number 671517 through
23 # the Horizon 2020 and 5G-PPP programmes. The authors would like to
24 # acknowledge the contributions of their colleagues of the SONATA
25 # partner consortium (www.sonata-nfv.eu).
26 #
27 # Distributed Cloud Emulator (dcemulator)
28 # Networking and monitoring functions
29 # (c) 2015 by Steven Van Rossem <steven.vanrossem@intec.ugent.be>
30 import logging
31 from flask_restful import Resource
32 from flask import request
33
34 logging.basicConfig()
35
36 CORS_HEADER = {'Access-Control-Allow-Origin': '*'}
37
38 net = None
39
40
41 class MonitorInterfaceAction(Resource):
42 """
43 Monitor the counters of a VNF interface
44 :param vnf_name: name of the VNF to be monitored
45 :param vnf_interface: name of the VNF interface to be monitored
46 :param metric: tx_bytes, rx_bytes, tx_packets, rx_packets
47 :return: message string indicating if the monitor action is succesful or not
48 """
49 global net
50
51 def put(self):
52 logging.debug("REST CALL: start monitor VNF interface")
53 # get URL parameters
54 data = request.args
55 if data is None:
56 data = {}
57 vnf_name = data.get("vnf_name")
58 vnf_interface = data.get("vnf_interface", None)
59 metric = data.get("metric", 'tx_packets')
60 cookie = data.get("cookie")
61
62 try:
63 if cookie:
64 c = net.monitor_agent.setup_flow(
65 vnf_name, vnf_interface, metric, cookie)
66 else:
67 c = net.monitor_agent.setup_metric(
68 vnf_name, vnf_interface, metric)
69 # return monitor message response
70 return str(c), 200, CORS_HEADER
71 except Exception as ex:
72 logging.exception("API error.")
73 return ex.message, 500, CORS_HEADER
74
75 def delete(self):
76 logging.debug("REST CALL: stop monitor VNF interface")
77 # get URL parameters
78 data = request.args
79 if data is None:
80 data = {}
81 vnf_name = data.get("vnf_name")
82 vnf_interface = data.get("vnf_interface", None)
83 metric = data.get("metric", 'tx_packets')
84 cookie = data.get("cookie")
85
86 try:
87 if cookie:
88 c = net.monitor_agent.stop_flow(
89 vnf_name, vnf_interface, metric, cookie)
90 else:
91 c = net.monitor_agent.stop_metric(
92 vnf_name, vnf_interface, metric)
93 # return monitor message response
94 return str(c), 200, CORS_HEADER
95 except Exception as ex:
96 logging.exception("API error.")
97 return ex.message, 500, CORS_HEADER
98
99
100 class MonitorFlowAction(Resource):
101 """
102 Monitor the counters of a specific flow
103 :param vnf_name: name of the VNF to be monitored
104 :param vnf_interface: name of the VNF interface to be monitored
105 :param metric: tx_bytes, rx_bytes, tx_packets, rx_packets
106 :param cookie: specific identifier of flows to monitor
107 :return: message string indicating if the monitor action is succesful or not
108 """
109 global net
110
111 def put(self):
112 logging.debug("REST CALL: start monitor VNF interface")
113 # get URL parameters
114 data = request.args
115 if data is None:
116 data = {}
117 vnf_name = data.get("vnf_name")
118 vnf_interface = data.get("vnf_interface", None)
119 metric = data.get("metric", 'tx_packets')
120 cookie = data.get("cookie", 0)
121
122 try:
123 c = net.monitor_agent.setup_flow(
124 vnf_name, vnf_interface, metric, cookie)
125 # return monitor message response
126 return str(c), 200, CORS_HEADER
127 except Exception as ex:
128 logging.exception("API error.")
129 return ex.message, 500, CORS_HEADER
130
131 def delete(self):
132 logging.debug("REST CALL: stop monitor VNF interface")
133 # get URL parameters
134 data = request.args
135 if data is None:
136 data = {}
137 vnf_name = data.get("vnf_name")
138 vnf_interface = data.get("vnf_interface", None)
139 metric = data.get("metric", 'tx_packets')
140 cookie = data.get("cookie", 0)
141
142 try:
143 c = net.monitor_agent.stop_flow(
144 vnf_name, vnf_interface, metric, cookie)
145 # return monitor message response
146 return str(c), 200, CORS_HEADER
147 except Exception as ex:
148 logging.exception("API error.")
149 return ex.message, 500, CORS_HEADER
150
151
152 class MonitorLinkAction(Resource):
153 """
154 Add or remove flow monitoring on chains between VNFs.
155 These chain links are implemented as flow entries in the networks' SDN switches.
156 The monitoring is an extra flow entry on top of the existing chain, with a specific match. (preserving the chaining)
157 The counters of this new monitoring flow are exported
158 :param vnf_src_name: VNF name of the source of the link
159 :param vnf_dst_name: VNF name of the destination of the link
160 :param vnf_src_interface: VNF interface name of the source of the link
161 :param vnf_dst_interface: VNF interface name of the destination of the link
162 :param weight: weight of the link (can be useful for routing calculations)
163 :param match: OpenFlow match format of the flow entry
164 :param bidirectional: boolean value if the link needs to be implemented from src to dst and back
165 :param cookie: cookie value, identifier of the flow entry to be installed.
166 :param priority: integer indicating the priority of the flow entry
167 :param skip_vlan_tag: boolean to indicate whether a new vlan tag should be created for this chain
168 :param monitor: boolean to indicate whether a new vlan tag should be created for this chain
169 :param monitor_placement: 'tx'=place the monitoring flowrule at the beginning of the chain, 'rx'=place at the end of the chain
170 :param metric: tx_packet_rate, tx_byte_rate, rx_packet_rate, rx_byte_rate
171 :return: message string indicating if the chain action is succesful or not
172 """
173
174 # the global net is set from the topology file, and connected via
175 # connectDCNetwork function in rest_api_endpoint.py
176 global net
177
178 def put(self):
179 logging.debug("REST CALL: monitor link flow add")
180
181 try:
182 command = 'add-flow'
183 return self._MonitorLinkAction(command=command)
184 except Exception as ex:
185 logging.exception("API error.")
186 return ex.message, 500, CORS_HEADER
187
188 def delete(self):
189 logging.debug("REST CALL: monitor link flow remove")
190
191 try:
192 command = 'del-flows'
193 return self._MonitorLinkAction(command=command)
194 except Exception as ex:
195 logging.exception("API error.")
196 return ex.message, 500, CORS_HEADER
197
198 def _MonitorLinkAction(self, command=None):
199 # call DCNetwork method, not really datacenter specific API for now...
200 # no check if vnfs are really connected to this datacenter...
201
202 try:
203 # check json payload
204 logging.debug("json: {}".format(request.json))
205 logging.debug("args: {}".format(request.args))
206
207 data = request.json
208 if data is None:
209 data = request.args
210 if data is None:
211 data = {}
212
213 vnf_src_name = data.get("vnf_src_name")
214 vnf_dst_name = data.get("vnf_dst_name")
215 vnf_src_interface = data.get("vnf_src_interface")
216 vnf_dst_interface = data.get("vnf_dst_interface")
217 weight = data.get("weight")
218 match = data.get("match")
219 bidirectional = data.get("bidirectional")
220 cookie = data.get("cookie")
221 priority = data.get("priority")
222 skip_vlan_tag = data.get("skip_vlan_tag")
223 monitor = data.get("monitor")
224 monitor_placement = data.get("monitor_placement")
225
226 # first install monitor flow
227 c1 = net.setChain(
228 vnf_src_name, vnf_dst_name,
229 vnf_src_interface=vnf_src_interface,
230 vnf_dst_interface=vnf_dst_interface,
231 cmd=command,
232 weight=weight,
233 match=match,
234 bidirectional=bidirectional,
235 cookie=cookie,
236 priority=priority,
237 skip_vlan_tag=skip_vlan_tag,
238 monitor=monitor,
239 monitor_placement=monitor_placement)
240
241 # then export monitor flow
242 metric = data.get("metric")
243 if 'rx' in monitor_placement:
244 vnf_name = vnf_dst_name
245 vnf_interface = vnf_dst_interface
246 elif 'tx' in monitor_placement:
247 vnf_name = vnf_src_name
248 vnf_interface = vnf_src_interface
249
250 c2 = 'command unknown'
251 if command == 'add-flow':
252 c2 = net.monitor_agent.setup_flow(
253 vnf_name, vnf_interface, metric, cookie)
254 elif command == 'del-flows':
255 c2 = net.monitor_agent.stop_flow(
256 vnf_name, vnf_interface, metric, cookie)
257
258 # return setChain response
259 return (str(c1) + " " + str(c2)), 200, CORS_HEADER
260 except Exception as ex:
261 logging.exception("API error.")
262 return ex.message, 500, CORS_HEADER
263
264
265 class MonitorSkewAction(Resource):
266 """
267 Monitor the counters of a VNF interface
268 :param vnf_name: name of the VNF to be monitored
269 :param resource: the resource to be monitored (cpu, mem, ...)
270 :return: message string indicating if the monitor action is succesful or not
271 """
272 global net
273
274 def put(self):
275 logging.debug("REST CALL: start monitor skewness")
276 # get URL parameters
277 data = request.args
278 if data is None:
279 data = {}
280 vnf_name = data.get("vnf_name")
281 resource_name = data.get("resource_name", 'cpu')
282 try:
283 # configure skewmon
284 c = net.monitor_agent.update_skewmon(
285 vnf_name, resource_name, action='start')
286
287 # return monitor message response
288 return str(c), 200, CORS_HEADER
289 except Exception as ex:
290 logging.exception("API error.")
291 return ex.message, 500, CORS_HEADER
292
293 def delete(self):
294 logging.debug("REST CALL: stop monitor skewness")
295 # get URL parameters
296 data = request.args
297 if data is None:
298 data = {}
299 vnf_name = data.get("vnf_name")
300 resource_name = data.get("resource_name", 'cpu')
301 try:
302 # configure skewmon
303 c = net.monitor_agent.update_skewmon(
304 vnf_name, resource_name, action='stop')
305
306 # return monitor message response
307 return str(c), 200, CORS_HEADER
308 except Exception as ex:
309 logging.exception("API error.")
310 return ex.message, 500, CORS_HEADER
311
312
313 class MonitorTerminal(Resource):
314 """
315 start a terminal for the selected VNFs
316 :param vnf_list: list of names of the VNFs to start a terminal from (all VNFs if None)
317 :return: message string indicating if the monitor action is succesful or not
318 """
319 global net
320
321 def get(self):
322 # get URL parameters
323 data = request.args
324 if data is None:
325 data = {}
326 vnf_list = data.get("vnf_list")
327 logging.debug("REST CALL: start terminal for: {}".format(vnf_list))
328 try:
329 # start terminals
330 c = net.monitor_agent.term(vnf_list)
331
332 # return monitor message response
333 return str(c), 200, CORS_HEADER
334 except Exception as ex:
335 logging.exception("API error.")
336 return ex.message, 500, CORS_HEADER