blob: 094f122233e92912a911ed305b8a468eaeaf86f7 [file] [log] [blame]
peusterm72f09882018-05-15 17:10:27 +02001# 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>
stevenvanrossem73efd192016-06-29 01:44:07 +020030import logging
peusterm72f09882018-05-15 17:10:27 +020031from flask_restful import Resource
stevenvanrossem73efd192016-06-29 01:44:07 +020032from flask import request
stevenvanrossem73efd192016-06-29 01:44:07 +020033
peusterm5b428742017-06-16 10:08:11 +020034logging.basicConfig()
stevenvanrossem73efd192016-06-29 01:44:07 +020035
peustermdfc14602017-01-13 08:22:45 +010036CORS_HEADER = {'Access-Control-Allow-Origin': '*'}
37
stevenvanrossem73efd192016-06-29 01:44:07 +020038net = None
39
40
stevenvanrossem73efd192016-06-29 01:44:07 +020041class 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
stevenvanrossem3c544ac2017-02-08 12:11:07 +010051 def put(self):
stevenvanrossem73efd192016-06-29 01:44:07 +020052 logging.debug("REST CALL: start monitor VNF interface")
stevenvanrossem3c544ac2017-02-08 12:11:07 +010053 # 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
stevenvanrossem73efd192016-06-29 01:44:07 +020062 try:
stevenvanrossem4fac2af2016-12-22 01:26:02 +010063 if cookie:
peusterm72f09882018-05-15 17:10:27 +020064 c = net.monitor_agent.setup_flow(
65 vnf_name, vnf_interface, metric, cookie)
stevenvanrossem4fac2af2016-12-22 01:26:02 +010066 else:
peusterm72f09882018-05-15 17:10:27 +020067 c = net.monitor_agent.setup_metric(
68 vnf_name, vnf_interface, metric)
stevenvanrossem73efd192016-06-29 01:44:07 +020069 # return monitor message response
peusterm72f09882018-05-15 17:10:27 +020070 return str(c), 200, CORS_HEADER
stevenvanrossem73efd192016-06-29 01:44:07 +020071 except Exception as ex:
72 logging.exception("API error.")
peustermdfc14602017-01-13 08:22:45 +010073 return ex.message, 500, CORS_HEADER
stevenvanrossem73efd192016-06-29 01:44:07 +020074
stevenvanrossem3c544ac2017-02-08 12:11:07 +010075 def delete(self):
stevenvanrossem73efd192016-06-29 01:44:07 +020076 logging.debug("REST CALL: stop monitor VNF interface")
stevenvanrossem3c544ac2017-02-08 12:11:07 +010077 # 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
stevenvanrossem73efd192016-06-29 01:44:07 +020086 try:
stevenvanrossem4fac2af2016-12-22 01:26:02 +010087 if cookie:
peusterm72f09882018-05-15 17:10:27 +020088 c = net.monitor_agent.stop_flow(
89 vnf_name, vnf_interface, metric, cookie)
stevenvanrossem4fac2af2016-12-22 01:26:02 +010090 else:
peusterm72f09882018-05-15 17:10:27 +020091 c = net.monitor_agent.stop_metric(
92 vnf_name, vnf_interface, metric)
stevenvanrossem73efd192016-06-29 01:44:07 +020093 # return monitor message response
peustermdfc14602017-01-13 08:22:45 +010094 return str(c), 200, CORS_HEADER
stevenvanrossem73efd192016-06-29 01:44:07 +020095 except Exception as ex:
96 logging.exception("API error.")
peustermdfc14602017-01-13 08:22:45 +010097 return ex.message, 500, CORS_HEADER
stevenvanrossem73efd192016-06-29 01:44:07 +020098
99
100class 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
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100111 def put(self):
stevenvanrossem73efd192016-06-29 01:44:07 +0200112 logging.debug("REST CALL: start monitor VNF interface")
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100113 # 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
stevenvanrossem73efd192016-06-29 01:44:07 +0200122 try:
peusterm72f09882018-05-15 17:10:27 +0200123 c = net.monitor_agent.setup_flow(
124 vnf_name, vnf_interface, metric, cookie)
stevenvanrossem73efd192016-06-29 01:44:07 +0200125 # return monitor message response
peustermdfc14602017-01-13 08:22:45 +0100126 return str(c), 200, CORS_HEADER
stevenvanrossem73efd192016-06-29 01:44:07 +0200127 except Exception as ex:
128 logging.exception("API error.")
peustermdfc14602017-01-13 08:22:45 +0100129 return ex.message, 500, CORS_HEADER
stevenvanrossem73efd192016-06-29 01:44:07 +0200130
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100131 def delete(self):
stevenvanrossem73efd192016-06-29 01:44:07 +0200132 logging.debug("REST CALL: stop monitor VNF interface")
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100133 # 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
stevenvanrossem73efd192016-06-29 01:44:07 +0200142 try:
peusterm72f09882018-05-15 17:10:27 +0200143 c = net.monitor_agent.stop_flow(
144 vnf_name, vnf_interface, metric, cookie)
stevenvanrossem73efd192016-06-29 01:44:07 +0200145 # return monitor message response
peustermdfc14602017-01-13 08:22:45 +0100146 return str(c), 200, CORS_HEADER
stevenvanrossem73efd192016-06-29 01:44:07 +0200147 except Exception as ex:
148 logging.exception("API error.")
peustermdfc14602017-01-13 08:22:45 +0100149 return ex.message, 500, CORS_HEADER
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100150
peusterm72f09882018-05-15 17:10:27 +0200151
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100152class MonitorLinkAction(Resource):
153 """
stevenvanrossem9c221db2016-12-22 10:08:22 +0100154 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
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100158 :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
peusterm72f09882018-05-15 17:10:27 +0200174 # the global net is set from the topology file, and connected via
175 # connectDCNetwork function in rest_api_endpoint.py
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100176 global net
177
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100178 def put(self):
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100179 logging.debug("REST CALL: monitor link flow add")
180
181 try:
182 command = 'add-flow'
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100183 return self._MonitorLinkAction(command=command)
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100184 except Exception as ex:
185 logging.exception("API error.")
peusterm8f2063d2017-02-02 17:49:22 +0100186 return ex.message, 500, CORS_HEADER
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100187
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100188 def delete(self):
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100189 logging.debug("REST CALL: monitor link flow remove")
190
191 try:
192 command = 'del-flows'
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100193 return self._MonitorLinkAction(command=command)
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100194 except Exception as ex:
195 logging.exception("API error.")
peusterm8f2063d2017-02-02 17:49:22 +0100196 return ex.message, 500, CORS_HEADER
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100197
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100198 def _MonitorLinkAction(self, command=None):
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100199 # call DCNetwork method, not really datacenter specific API for now...
200 # no check if vnfs are really connected to this datacenter...
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100201
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100202 try:
stevenvanrossem167aa3c2017-06-01 16:45:42 +0200203 # 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
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100210 if data is None:
211 data = {}
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100212
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100213 vnf_src_name = data.get("vnf_src_name")
214 vnf_dst_name = data.get("vnf_dst_name")
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100215 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
peusterm72f09882018-05-15 17:10:27 +0200226 # first install monitor flow
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100227 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
peusterm72f09882018-05-15 17:10:27 +0200241 # then export monitor flow
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100242 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
stevenvanrossemfcd8c9b2017-01-28 15:41:14 +0100250 c2 = 'command unknown'
251 if command == 'add-flow':
peusterm72f09882018-05-15 17:10:27 +0200252 c2 = net.monitor_agent.setup_flow(
253 vnf_name, vnf_interface, metric, cookie)
stevenvanrossemfcd8c9b2017-01-28 15:41:14 +0100254 elif command == 'del-flows':
peusterm72f09882018-05-15 17:10:27 +0200255 c2 = net.monitor_agent.stop_flow(
256 vnf_name, vnf_interface, metric, cookie)
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100257
258 # return setChain response
peusterm8f2063d2017-02-02 17:49:22 +0100259 return (str(c1) + " " + str(c2)), 200, CORS_HEADER
stevenvanrossem4fac2af2016-12-22 01:26:02 +0100260 except Exception as ex:
261 logging.exception("API error.")
stevenvanrossema6ce6f32017-02-03 16:11:42 +0100262 return ex.message, 500, CORS_HEADER
stevenvanrossemb07fe362017-01-28 17:29:45 +0100263
peusterm72f09882018-05-15 17:10:27 +0200264
stevenvanrossemb07fe362017-01-28 17:29:45 +0100265class 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
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100274 def put(self):
stevenvanrossemb07fe362017-01-28 17:29:45 +0100275 logging.debug("REST CALL: start monitor skewness")
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100276 # 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')
stevenvanrossemb07fe362017-01-28 17:29:45 +0100282 try:
283 # configure skewmon
peusterm72f09882018-05-15 17:10:27 +0200284 c = net.monitor_agent.update_skewmon(
285 vnf_name, resource_name, action='start')
stevenvanrossemb07fe362017-01-28 17:29:45 +0100286
287 # return monitor message response
peusterm72f09882018-05-15 17:10:27 +0200288 return str(c), 200, CORS_HEADER
stevenvanrossemb07fe362017-01-28 17:29:45 +0100289 except Exception as ex:
290 logging.exception("API error.")
stevenvanrossemc63c5492017-05-08 16:10:13 +0200291 return ex.message, 500, CORS_HEADER
stevenvanrossemb07fe362017-01-28 17:29:45 +0100292
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100293 def delete(self):
stevenvanrossemb07fe362017-01-28 17:29:45 +0100294 logging.debug("REST CALL: stop monitor skewness")
stevenvanrossem3c544ac2017-02-08 12:11:07 +0100295 # 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')
stevenvanrossemb07fe362017-01-28 17:29:45 +0100301 try:
302 # configure skewmon
peusterm72f09882018-05-15 17:10:27 +0200303 c = net.monitor_agent.update_skewmon(
304 vnf_name, resource_name, action='stop')
stevenvanrossemb07fe362017-01-28 17:29:45 +0100305
306 # return monitor message response
peusterm8f2063d2017-02-02 17:49:22 +0100307 return str(c), 200, CORS_HEADER
stevenvanrossemb07fe362017-01-28 17:29:45 +0100308 except Exception as ex:
309 logging.exception("API error.")
stevenvanrossema6ce6f32017-02-03 16:11:42 +0100310 return ex.message, 500, CORS_HEADER
311
peusterm72f09882018-05-15 17:10:27 +0200312
stevenvanrossemc63c5492017-05-08 16:10:13 +0200313class 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
peusterm72f09882018-05-15 17:10:27 +0200333 return str(c), 200, CORS_HEADER
stevenvanrossemc63c5492017-05-08 16:10:13 +0200334 except Exception as ex:
335 logging.exception("API error.")
peusterm5b428742017-06-16 10:08:11 +0200336 return ex.message, 500, CORS_HEADER