blob: 288692cec1e1b79904fcd1c72705f8a9adc3ed32 [file] [log] [blame]
Naoki Shiotad5d0e942014-03-27 18:57:32 -07001#! /usr/bin/env python
2import pprint
3import os
4import sys
5import subprocess
6import json
7import argparse
8import io
9import time
10import random
11import re
12from urllib2 import Request, urlopen, URLError, HTTPError
13
14from flask import Flask, json, Response, render_template, make_response, request
15
16# paths for local access
17ONOS_DIR = os.getenv("HOME") + "/ONOS"
18ONOS_SCRIPTS_DIR = ONOS_DIR + "/scripts"
19ONS2014_DEMO_SCRIPTS_DIR = ONOS_DIR + "/sample/ONS2014demo/scripts"
20ONS2014_DEMO_WEB_DIR = ONOS_DIR + "/sample/ONS2014demo/web"
21LINK_FILE = ONS2014_DEMO_SCRIPTS_DIR + "/link.json"
22CONFIG_FILE = ONS2014_DEMO_SCRIPTS_DIR + "/config.json"
23
24# paths for remote access
25REMOTE_DEMO_SCRIPTS_DIR = "ONOS/sample/ONS2014demo/scripts"
26
27## Global Var for this proxy script setting.
28# "0.0.0.0" means any interface
29ProxyIP="0.0.0.0"
30ProxyPort=9000
31
32## Global Var for ON.Lab local REST ##
33RestIP="localhost"
34RestPort=8080
35ONOS_DEFAULT_HOST="localhost" ;# Has to set if LB=False
36DEBUG=1
37
38pp = pprint.PrettyPrinter(indent=4)
39app = Flask(__name__)
40
41def read_config():
42 global LB, TESTBED, controllers, core_switches, ONOS_GUI3_HOST, ONOS_GUI3_CONTROL_HOST
43 f = open(CONFIG_FILE)
44 conf = json.load(f)
45 LB = conf['LB']
46 TESTBED = conf['TESTBED']
47 controllers = conf['controllers']
48 core_switches=conf['core_switches']
49 ONOS_GUI3_HOST=conf['ONOS_GUI3_HOST']
50 ONOS_GUI3_CONTROL_HOST=conf['ONOS_GUI3_CONTROL_HOST']
51 f.close()
52
53def read_link_def():
54 global link_def
55 f=open(LINK_FILE)
56 try:
57 link_def=json.load(f)
58 f.close()
59 except:
60 print "Can't read link def file (link.json)"
61 sys.exit(1)
62
63def get_link_ports(src_dpid, dst_dpid):
64 ret = (-1, -1)
65 for link in link_def:
66 if link['src-switch'] == src_dpid and link['dst-switch'] == dst_dpid:
67 ret = (link['src-port'], link['dst-port'])
68 break
69 return ret
70
71## Worker Functions ##
72def log_error(txt):
73 print '%s' % (txt)
74
75def debug(txt):
76 if DEBUG:
77 print '%s' % (txt)
78
79### File Fetch ###
80@app.route('/', methods=['GET'])
81@app.route('/<filename>', methods=['GET'])
82@app.route('/js/<filename>', methods=['GET'])
83@app.route('/d3/<filename>', methods=['GET'])
84@app.route('/css/<filename>', methods=['GET'])
85@app.route('/assets/<filename>', methods=['GET'])
86@app.route('/data/<filename>', methods=['GET'])
87def return_file(filename="index.html"):
88 if request.path == "/":
89 fullpath = ONS2014_DEMO_WEB_DIR + "/index.html"
90 else:
91 fullpath = ONS2014_DEMO_WEB_DIR + "/" + str(request.path)[1:]
92
93 try:
94 open(fullpath)
95 except:
96 response = make_response("Cannot find a file: %s" % (fullpath), 500)
97 response.headers["Content-type"] = "text/html"
98 return response
99
100 response = make_response(open(fullpath).read())
101 suffix = fullpath.split(".")[-1]
102
103 if suffix == "html" or suffix == "htm":
104 response.headers["Content-type"] = "text/html"
105 elif suffix == "js":
106 response.headers["Content-type"] = "application/javascript"
107 elif suffix == "css":
108 response.headers["Content-type"] = "text/css"
109 elif suffix == "png":
110 response.headers["Content-type"] = "image/png"
111 elif suffix == "svg":
112 response.headers["Content-type"] = "image/svg+xml"
113
114 return response
115
116## Proxy ##
117@app.route("/proxy/gui/link/<cmd>/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>")
118def proxy_link_change(cmd, src_dpid, src_port, dst_dpid, dst_port):
119 url = "%s/gui/link/%s/%s/%s/%s/%s" % (ONOS_GUI3_CONTROL_HOST, cmd, src_dpid, src_port, dst_dpid, dst_port)
120 try:
121 response = urlopen(url)
122 result = response.read()
123 except:
124 result = ""
125 print "REST IF has issue %s" % url
126
127 resp = Response(result, status=200, mimetype='application/json')
128 return resp
129
130@app.route("/proxy/gui/switchctrl/<cmd>")
131def proxy_switch_controller_setting(cmd):
132 url = "%s/gui/switchctrl/%s" % (ONOS_GUI3_CONTROL_HOST, cmd)
133 try:
134 response = urlopen(url)
135 result = response.read()
136 except:
137 result = ""
138 print "REST IF has issue %s" % url
139
140 resp = Response(result, status=200, mimetype='application/json')
141 return resp
142
143@app.route("/proxy/gui/switch/<cmd>/<dpid>")
144def proxy_switch_status_change(cmd, dpid):
145 url = "%s/gui/switch/%s/%s" % (ONOS_GUI3_CONTROL_HOST, cmd, dpid)
146 try:
147 response = urlopen(url)
148 result = response.read()
149 except:
150 result = ""
151 print "REST IF has issue %s" % url
152
153 resp = Response(result, status=200, mimetype='application/json')
154 return resp
155
156@app.route("/proxy/gui/controller/<cmd>/<controller_name>")
157def proxy_controller_status_change(cmd, controller_name):
158 url = "%s/gui/controller/%s/%s" % (ONOS_GUI3_CONTROL_HOST, cmd, controller_name)
159 try:
160 response = urlopen(url)
161 result = response.read()
162 except:
163 result = ""
164 print "REST IF has issue %s" % url
165
166 resp = Response(result, status=200, mimetype='application/json')
167 return resp
168
169@app.route("/proxy/gui/addflow/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>/<srcMAC>/<dstMAC>")
170def proxy_add_flow(src_dpid, src_port, dst_dpid, dst_port, srcMAC, dstMAC):
171 try:
172 url = "%s/gui/addflow/%s/%s/%s/%s/%s/%s" % (ONOS_GUI3_CONTROL_HOST, src_dpid, src_port, dst_dpid, dst_port, srcMAC, dstMAC)
173 #print "proxy gui addflow " + url
174 (code, result) = get_json(url)
175 except:
176 print "REST IF has issue %s" % url
177 print "Result %s" % result
178 exit()
179
180 resp = Response(result, status=200, mimetype='application/json')
181 return resp
182
183@app.route("/proxy/gui/delflow/<flow_id>")
184def proxy_del_flow(flow_id):
185 url = "%s/gui/delflow/%s" % (ONOS_GUI3_CONTROL_HOST, flow_id)
186 try:
187 response = urlopen(url)
188 result = response.read()
189 except:
190 result = ""
191 print "REST IF has issue %s" % url
192
193 resp = Response(result, status=200, mimetype='application/json')
194 return resp
195
196@app.route("/proxy/gui/iperf/start/<flow_id>/<duration>/<samples>")
197def proxy_iperf_start(flow_id,duration,samples):
198 url = "%s/gui/iperf/start/%s/%s/%s" % (ONOS_GUI3_CONTROL_HOST, flow_id, duration, samples)
199 try:
200 response = urlopen(url)
201 result = response.read()
202 except:
203 result = ""
204 print "REST IF has issue %s" % url
205
206 resp = Response(result, status=200, mimetype='application/json')
207 return resp
208
209@app.route("/proxy/gui/iperf/rate/<flow_id>")
210def proxy_iperf_rate(flow_id):
211 url = "%s/gui/iperf/rate/%s" % (ONOS_GUI3_CONTROL_HOST, flow_id)
212 try:
213 response = urlopen(url)
214 result = response.read()
215 except:
216 result = ""
217 print "REST IF has issue %s" % url
218
219 resp = Response(result, status=200, mimetype='application/json')
220 return resp
221
222@app.route("/proxy/gui/reset")
223def proxy_gui_reset():
224 url = "%s/gui/reset" % (ONOS_GUI3_CONTROL_HOST)
225 try:
226 response = urlopen(url)
227 result = response.read()
228 except:
229 result = ""
230 print "REST IF has issue %s" % url
231
232 resp = Response(result, status=200, mimetype='application/json')
233 return resp
234
235@app.route("/proxy/gui/scale")
236def proxy_gui_scale():
237 url = "%s/gui/scale" % (ONOS_GUI3_CONTROL_HOST)
238 try:
239 response = urlopen(url)
240 result = response.read()
241 except:
242 result = ""
243 print "REST IF has issue %s" % url
244
245 resp = Response(result, status=200, mimetype='application/json')
246 return resp
247
248###### ONOS REST API ##############################
249## Worker Func ###
250def get_json(url):
251 code = 200;
252 try:
253 response = urlopen(url)
254 except URLError, e:
255 print "get_json: REST IF %s has issue. Reason: %s" % (url, e.reason)
256 result = ""
257 return (500, result)
258 except HTTPError, e:
259 print "get_json: REST IF %s has issue. Code %s" % (url, e.code)
260 result = ""
261 return (e.code, result)
262
263 result = response.read()
264# parsedResult = json.loads(result)
265 return (code, result)
266
267def pick_host():
268 if LB == True:
269 nr_host=len(controllers)
270 r=random.randint(0, nr_host - 1)
271 host=controllers[r]
272 else:
273 host=ONOS_DEFAULT_HOST
274
275 return "http://" + host + ":8080"
276
277## Switch ##
Yuta HIGUCHI42d7f1b2014-05-28 09:19:49 -0700278@app.route("/wm/onos/topology/switches")
Naoki Shiotad5d0e942014-03-27 18:57:32 -0700279def switches():
280 if request.args.get('proxy') == None:
281 host = pick_host()
282 else:
283 host = ONOS_GUI3_HOST
284
Yuta HIGUCHI42d7f1b2014-05-28 09:19:49 -0700285 url ="%s/wm/onos/topology/switches" % (host)
Naoki Shiotad5d0e942014-03-27 18:57:32 -0700286 (code, result) = get_json(url)
287
288 resp = Response(result, status=code, mimetype='application/json')
289 return resp
290
291## Link ##
Yuta HIGUCHI42d7f1b2014-05-28 09:19:49 -0700292@app.route("/wm/onos/topology/links")
Naoki Shiotad5d0e942014-03-27 18:57:32 -0700293def links():
294 if request.args.get('proxy') == None:
295 host = pick_host()
296 else:
297 host = ONOS_GUI3_HOST
298
Yuta HIGUCHI42d7f1b2014-05-28 09:19:49 -0700299 url ="%s/wm/onos/topology/links" % (host)
Naoki Shiotad5d0e942014-03-27 18:57:32 -0700300 (code, result) = get_json(url)
301
302 resp = Response(result, status=code, mimetype='application/json')
303 return resp
304
305## FlowSummary ##
306@app.route("/wm/onos/flows/getsummary/<start>/<range>/json")
307def flows(start, range):
308 if request.args.get('proxy') == None:
309 host = pick_host()
310 else:
311 host = ONOS_GUI3_HOST
312
313 url ="%s/wm/onos/flows/getsummary/%s/%s/json" % (host, start, range)
314 (code, result) = get_json(url)
315
316 resp = Response(result, status=code, mimetype='application/json')
317 return resp
318
319@app.route("/wm/onos/registry/controllers/json")
320def registry_controllers():
321 if request.args.get('proxy') == None:
322 host = pick_host()
323 else:
324 host = ONOS_GUI3_HOST
325
326 url= "%s/wm/onos/registry/controllers/json" % (host)
327 (code, result) = get_json(url)
328
329 resp = Response(result, status=code, mimetype='application/json')
330 return resp
331
332
333@app.route("/wm/onos/registry/switches/json")
334def registry_switches():
335 if request.args.get('proxy') == None:
336 host = pick_host()
337 else:
338 host = ONOS_GUI3_HOST
339
340 url="%s/wm/onos/registry/switches/json" % (host)
341 (code, result) = get_json(url)
342
343 resp = Response(result, status=code, mimetype='application/json')
344 return resp
345
346def node_id(switch_array, dpid):
347 id = -1
348 for i, val in enumerate(switch_array):
349 if val['name'] == dpid:
350 id = i
351 break
352
353 return id
354
355## API for ON.Lab local GUI ##
356@app.route('/topology', methods=['GET'])
357def topology_for_gui():
358 try:
Yuta HIGUCHI42d7f1b2014-05-28 09:19:49 -0700359 url="http://%s:%s/wm/onos/topology/switches" % (RestIP, RestPort)
Naoki Shiotad5d0e942014-03-27 18:57:32 -0700360 (code, result) = get_json(url)
361 parsedResult = json.loads(result)
362 except:
363 log_error("REST IF has issue: %s" % url)
364 log_error("%s" % result)
365 return
366
367 topo = {}
368 switches = []
369 links = []
370 devices = []
371
372 for v in parsedResult:
373 if v.has_key('dpid'):
374# if v.has_key('dpid') and str(v['state']) == "ACTIVE":#;if you want only ACTIVE nodes
375 dpid = str(v['dpid'])
376 state = str(v['state'])
377 sw = {}
378 sw['name']=dpid
379 sw['group']= -1
380
381 if state == "INACTIVE":
382 sw['group']=0
383 switches.append(sw)
384
385 try:
386 url="http://%s:%s/wm/onos/registry/switches/json" % (RestIP, RestPort)
387 (code, result) = get_json(url)
388 parsedResult = json.loads(result)
389 except:
390 log_error("REST IF has issue: %s" % url)
391 log_error("%s" % result)
392
393 for key in parsedResult:
394 dpid = key
395 ctrl = parsedResult[dpid][0]['controllerId']
396 sw_id = node_id(switches, dpid)
397 if sw_id != -1:
398 if switches[sw_id]['group'] != 0:
399 switches[sw_id]['group'] = controllers.index(ctrl) + 1
400
401 try:
Yuta HIGUCHI42d7f1b2014-05-28 09:19:49 -0700402 url = "http://%s:%s/wm/onos/topology/links" % (RestIP, RestPort)
Naoki Shiotad5d0e942014-03-27 18:57:32 -0700403 (code, result) = get_json(url)
404 parsedResult = json.loads(result)
405 except:
406 log_error("REST IF has issue: %s" % url)
407 log_error("%s" % result)
408 return
409# sys.exit(0)
410
411 for v in parsedResult:
412 link = {}
413 if v.has_key('dst-switch'):
414 dst_dpid = str(v['dst-switch'])
415 dst_id = node_id(switches, dst_dpid)
416 if v.has_key('src-switch'):
417 src_dpid = str(v['src-switch'])
418 src_id = node_id(switches, src_dpid)
419 link['source'] = src_id
420 link['target'] = dst_id
421
422 #onpath = 0
423 #for (s,d) in path:
424 # if s == v['src-switch'] and d == v['dst-switch']:
425 # onpath = 1
426 # break
427 #link['type'] = onpath
428
429 links.append(link)
430
431 topo['nodes'] = switches
432 topo['links'] = links
433
434 js = json.dumps(topo)
435 resp = Response(js, status=200, mimetype='application/json')
436 return resp
437
438@app.route("/wm/floodlight/topology/toporoute/<v1>/<p1>/<v2>/<p2>/json")
439def shortest_path(v1, p1, v2, p2):
440 try:
Yuta HIGUCHI42d7f1b2014-05-28 09:19:49 -0700441 url = "http://%s:%s/wm/onos/topology/switches" % (RestIP, RestPort)
Naoki Shiotad5d0e942014-03-27 18:57:32 -0700442 (code, result) = get_json(url)
443 parsedResult = json.loads(result)
444 except:
445 log_error("REST IF has issue: %s" % command)
446 log_error("%s" % result)
447 return
448
449 topo = {}
450 switches = []
451 links = []
452
453 for v in parsedResult:
454 if v.has_key('dpid'):
455 dpid = str(v['dpid'])
456 state = str(v['state'])
457 sw = {}
458 sw['name']=dpid
459 if str(v['state']) == "ACTIVE":
460 if dpid[-2:-1] == "a":
461 sw['group']=1
462 if dpid[-2:-1] == "b":
463 sw['group']=2
464 if dpid[-2:-1] == "c":
465 sw['group']=3
466 if str(v['state']) == "INACTIVE":
467 sw['group']=0
468
469 switches.append(sw)
470
471 try:
472 url = "http://%s:%s/wm/onos/topology/route/%s/%s/%s/%s/json" % (RestIP, RestPort, v1, p1, v2, p2)
473 (code, result) = get_json(url)
474 parsedResult = json.loads(result)
475 except:
476 log_error("No route")
477 parsedResult = []
478
479 path = [];
480 for i, v in enumerate(parsedResult):
481 if i < len(parsedResult) - 1:
482 sdpid= parsedResult['flowEntries'][i]['dpid']['value']
483 ddpid= parsedResult['flowEntries'][i+1]['dpid']['value']
484 path.append( (sdpid, ddpid))
485
486 try:
Yuta HIGUCHI42d7f1b2014-05-28 09:19:49 -0700487 url = "http://%s:%s/wm/onos/topology/links" % (RestIP, RestPort)
Naoki Shiotad5d0e942014-03-27 18:57:32 -0700488 (code, result) = get_json(url)
489 parsedResult = json.loads(result)
490 except:
491 log_error("REST IF has issue: %s" % command)
492 log_error("%s" % result)
493 return
494
495 for v in parsedResult:
496 link = {}
497 if v.has_key('dst-switch'):
498 dst_dpid = str(v['dst-switch'])
499 dst_id = node_id(switches, dst_dpid)
500 if v.has_key('src-switch'):
501 src_dpid = str(v['src-switch'])
502 src_id = node_id(switches, src_dpid)
503 link['source'] = src_id
504 link['target'] = dst_id
505 onpath = 0
506 for (s,d) in path:
507 if s == v['src-switch'] and d == v['dst-switch']:
508 onpath = 1
509 break
510
511 link['type'] = onpath
512 links.append(link)
513
514 topo['nodes'] = switches
515 topo['links'] = links
516
517 js = json.dumps(topo)
518 resp = Response(js, status=200, mimetype='application/json')
519 return resp
520
521@app.route("/wm/floodlight/core/controller/switches/json")
522def query_switch():
523 try:
Yuta HIGUCHI42d7f1b2014-05-28 09:19:49 -0700524 url = "http://%s:%s/wm/onos/topology/switches" % (RestIP, RestPort)
Naoki Shiotad5d0e942014-03-27 18:57:32 -0700525 (code, result) = get_json(url)
526 parsedResult = json.loads(result)
527 except:
528 log_error("REST IF has issue: %s" % url)
529 log_error("%s" % result)
530 return
531# sys.exit(0)
532
533# print command
534# print result
535 switches_ = []
536 for v in parsedResult:
537 if v.has_key('dpid'):
538 if v.has_key('dpid') and str(v['state']) == "ACTIVE":#;if you want only ACTIVE nodes
539 dpid = str(v['dpid'])
540 state = str(v['state'])
541 sw = {}
542 sw['dpid']=dpid
543 sw['active']=state
544 switches_.append(sw)
545
546# pp.pprint(switches_)
547 js = json.dumps(switches_)
548 resp = Response(js, status=200, mimetype='application/json')
549 return resp
550
551## return fake stat for now
552@app.route("/wm/floodlight/core/switch/<switchId>/<statType>/json")
553def switch_stat(switchId, statType):
554 if statType == "desc":
555 desc=[{"length":1056,"serialNumber":"None","manufacturerDescription":"Nicira Networks, Inc.","hardwareDescription":"Open vSwitch","softwareDescription":"1.4.0+build0","datapathDescription":"None"}]
556 ret = {}
557 ret[switchId]=desc
558 elif statType == "aggregate":
559 aggr = {"packetCount":0,"byteCount":0,"flowCount":0}
560 ret = {}
561 ret[switchId]=aggr
562 else:
563 ret = {}
564
565 js = json.dumps(ret)
566 resp = Response(js, status=200, mimetype='application/json')
567 return resp
568
569@app.route("/controller_status")
570def controller_status():
571 url= "http://%s:%d/wm/onos/registry/controllers/json" % (RestIP, RestPort)
572 (code, result) = get_json(url)
573 parsedResult = json.loads(result)
574
575 cont_status=[]
576 for i in controllers:
577 status={}
578 if i in parsedResult:
579 onos=1
580 else:
581 onos=0
582 status["name"]=i
583 status["onos"]=onos
584 status["cassandra"]=0
585 cont_status.append(status)
586
587 js = json.dumps(cont_status)
588 resp = Response(js, status=200, mimetype='application/json')
589 return resp
590
591
592### Command ###
593@app.route("/gui/controller/<cmd>/<controller_name>")
594def controller_status_change(cmd, controller_name):
595 if (TESTBED == "hw"):
596 start_onos="/home/admin/bin/onos start %s" % (controller_name[-1:])
597# start_onos="/home/admin/bin/onos start %s > /tmp/debug " % (controller_name[-1:])
598 stop_onos="/home/admin/bin/onos stop %s" % (controller_name[-1:])
599# stop_onos="/home/admin/bin/onos stop %s > /tmp/debug " % (controller_name[-1:])
600# print "Debug: Controller command %s called %s" % (cmd, controller_name)
601 else:
602 # No longer use -i to specify keys (use .ssh/config to specify it)
603 start_onos="ssh %s \"cd ONOS; ./onos.sh core start\"" % (controller_name)
604 stop_onos="ssh %s \"cd ONOS; ./onos.sh core stop\"" % (controller_name)
605# start_onos="ssh -i ~/.ssh/onlabkey.pem %s ONOS/start-onos.sh start" % (controller_name)
606# stop_onos="ssh -i ~/.ssh/onlabkey.pem %s ONOS/start-onos.sh stop" % (controller_name)
607
608 if cmd == "up":
609 result=os.popen(start_onos).read()
610 ret = "controller %s is up: %s" % (controller_name, result)
611 elif cmd == "down":
612 result=os.popen(stop_onos).read()
613 ret = "controller %s is down: %s" % (controller_name, result)
614
615 return ret
616
617@app.route("/gui/switchctrl/<cmd>")
618def switch_controller_setting(cmd):
619 if cmd =="local":
620 print "All aggr switches connects to local controller only"
621 result=""
622 if (TESTBED == "sw"):
623 for i in range(1, len(controllers)):
624 cmd_string="ssh %s 'cd %s; ./ctrl-local.sh'" % (controllers[i], REMOTE_DEMO_SCRIPTS_DIR)
625 result += os.popen(cmd_string).read()
626 else:
627 cmd_string="cd; switch local > /tmp/watch"
628 result += os.popen(cmd_string).read()
629 elif cmd =="all":
630 print "All aggr switches connects to all controllers except for core controller"
631 result=""
632 if (TESTBED == "sw"):
633 for i in range(1, len(controllers)):
634 cmd_string="ssh %s 'cd %s; ./ctrl-add-ext.sh'" % (controllers[i], REMOTE_DEMO_SCRIPTS_DIR)
635# cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd %s; ./ctrl-add-ext.sh'" % (controllers[i], REMOTE_DEMO_SCRIPTS_DIR)
636 print "cmd is: "+cmd_string
637 result += os.popen(cmd_string).read()
638 else:
639 cmd_string="/home/admin/bin/switch all > /tmp/watch"
640 result += os.popen(cmd_string).read()
641
642 return result
643
644@app.route("/gui/reset")
645def reset_demo():
646 if (TESTBED == "hw"):
647 cmd_string="cd ~/bin; ./demo-reset-hw.sh > /tmp/watch &"
648 else:
649 cmd_string="cd %s; ./demo-reset-sw.sh > /tmp/watch &" % (REMOTE_DEMO_SCRIPTS_DIR)
650 os.popen(cmd_string)
651 return "Reset"
652
653@app.route("/gui/scale")
654def scale_demo():
655 if (TESTBED == "hw"):
656 cmd_string="cd ~/bin; ~/bin/demo-scale-out-hw.sh > /tmp/watch &"
657 else:
658 cmd_string="cd %s; ./demo-scale-out-sw.sh > /tmp/watch &" % (REMOTE_DEMO_SCRIPTS_DIR)
659 os.popen(cmd_string)
660 return "scale"
661
662@app.route("/gui/switch/<cmd>/<dpid>")
663def switch_status_change(cmd, dpid):
664 result = ""
665 if (TESTBED == "hw"):
666 return result
667
668 r = re.compile(':')
669 dpid = re.sub(r, '', dpid)
670 host=controllers[0]
671 cmd_string="ssh %s 'cd %s; ./switch.sh %s %s'" % (host, REMOTE_DEMO_SCRIPTS_DIR, dpid, cmd)
672# cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd %s; ./switch.sh %s %s'" % (host, REMOTE_DEMO_SCRIPTS_DIR, dpid, cmd)
673 get_status="ssh -i ~/.ssh/onlabkey.pem %s 'cd %s; ./switch.sh %s'" % (host, REMOTE_DEMO_SCRIPTS_DIR, dpid)
674 print "cmd_string"
675
676 if cmd =="up" or cmd=="down":
677 print "make dpid %s %s" % (dpid, cmd)
678 os.popen(cmd_string)
679 result=os.popen(get_status).read()
680
681 return result
682
683#* Link Up
684#http://localhost:9000/gui/link/up/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>
685@app.route("/gui/link/up/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>")
686def link_up(src_dpid, src_port, dst_dpid, dst_port):
687 result = ""
688
689 if (TESTBED == "sw"):
690 result = link_up_sw(src_dpid, src_port, dst_dpid, dst_port)
691 else:
692 result = link_up_hw(src_dpid, src_port, dst_dpid, dst_port)
693 return result
694
695# Link up on software testbed
696def link_up_sw(src_dpid, src_port, dst_dpid, dst_port):
697
698 cmd = 'up'
699 result=""
700 for dpid in (src_dpid, dst_dpid):
701 if dpid in core_switches:
702 host = controllers[0]
703 else:
704 hostid=int(dpid.split(':')[-2])
705 host = controllers[hostid-1]
706
707 if dpid == src_dpid:
708 (port, dontcare) = get_link_ports(dpid, dst_dpid)
709 else:
710 (port, dontcare) = get_link_ports(dpid, src_dpid)
711
712# cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd %s; ./link.sh %s %s %s'" % (host, REMOTE_DEMO_SCRIPTS_DIR, dpid, port, cmd)
713 cmd_string="ssh %s 'cd %s; ./link.sh %s %s %s'" % (host, REMOTE_DEMO_SCRIPTS_DIR, dpid, port, cmd)
714 print cmd_string
715 res=os.popen(cmd_string).read()
716 result = result + ' ' + res
717
718 return result
719
720# if hostid == 2 :
721# src_ports = [51]
722# else :
723# src_ports = [26]
724#
725# for port in src_ports :
726# cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd %s; ./link.sh %s %s %s'" % (host, REMOTE_DEMO_SCRIPTS_DIR, dpid, port, cmd)
727# print cmd_string
728# res=os.popen(cmd_string).read()
729
730
731
732# Link up on hardware testbed
733def link_up_hw(src_dpid, src_port, dst_dpid, dst_port):
734
735 port1 = src_port
736 port2 = dst_port
737 if src_dpid == "00:00:00:00:ba:5e:ba:11":
738 if dst_dpid == "00:00:00:08:a2:08:f9:01":
739 port1 = 24
740 port2 = 24
741 elif dst_dpid == "00:01:00:16:97:08:9a:46":
742 port1 = 23
743 port2 = 23
744 elif src_dpid == "00:00:00:00:ba:5e:ba:13":
745 if dst_dpid == "00:00:20:4e:7f:51:8a:35":
746 port1 = 22
747 port2 = 22
748 elif dst_dpid == "00:00:00:00:00:00:ba:12":
749 port1 = 23
750 port2 = 23
751 elif src_dpid == "00:00:00:00:00:00:ba:12":
752 if dst_dpid == "00:00:00:00:ba:5e:ba:13":
753 port1 = 23
754 port2 = 23
755 elif dst_dpid == "00:00:00:08:a2:08:f9:01":
756 port1 = 22
757 port2 = 22
758 elif dst_dpid == "00:00:20:4e:7f:51:8a:35":
759 port1 = 24
760 port2 = 21
761 elif src_dpid == "00:01:00:16:97:08:9a:46":
762 if dst_dpid == "00:00:00:00:ba:5e:ba:11":
763 port1 = 23
764 port2 = 23
765 elif dst_dpid == "00:00:20:4e:7f:51:8a:35":
766 port1 = 24
767 port2 = 24
768 elif src_dpid == "00:00:00:08:a2:08:f9:01":
769 if dst_dpid == "00:00:00:00:ba:5e:ba:11":
770 port1 = 24
771 port2 = 24
772 elif dst_dpid == "00:00:00:00:00:00:ba:12":
773 port1 = 22
774 port2 = 22
775 elif dst_dpid == "00:00:20:4e:7f:51:8a:35":
776 port1 = 23
777 port2 = 23
778 elif src_dpid == "00:00:20:4e:7f:51:8a:35":
779 if dst_dpid == "00:00:00:00:00:00:ba:12":
780 port1 = 21
781 port2 = 24
782 elif dst_dpid == "00:00:00:00:ba:5e:ba:13":
783 port1 = 22
784 port2 = 22
785 elif dst_dpid == "00:01:00:16:97:08:9a:46":
786 port1 = 24
787 port2 = 24
788 elif dst_dpid == "00:00:00:08:a2:08:f9:01":
789 port1 = 23
790 port2 = 23
791
792 cmd = 'up'
793 result=""
794 host = controllers[0]
795 cmd_string="%s/link-hw.sh %s %s %s " % (ONS2014_DEMO_SCRIPTS_DIR, src_dpid, port1, cmd)
796 print cmd_string
797 res=os.popen(cmd_string).read()
798 result = result + ' ' + res
799 cmd_string="%s/link-hw.sh %s %s %s " % (ONS2014_DEMO_SCRIPTS_DIR, dst_dpid, port2, cmd)
800 print cmd_string
801 res=os.popen(cmd_string).read()
802 result = result + ' ' + res
803
804
805 return result
806
807
808#* Link Down
809#http://localhost:9000/gui/link/down/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>
810@app.route("/gui/link/<cmd>/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>")
811def link_down(cmd, src_dpid, src_port, dst_dpid, dst_port):
812
813 if src_dpid in core_switches:
814 host = controllers[0]
815 else:
816 hostid=int(src_dpid.split(':')[-2])
817 host = controllers[hostid-1]
818
819 if (TESTBED == "sw"):
820 cmd_string="ssh %s 'cd %s; ./link.sh %s %s %s'" % (host, REMOTE_DEMO_SCRIPTS_DIR, src_dpid, src_port, cmd)
821 else:
822 if ( src_dpid == "00:00:00:08:a2:08:f9:01" ):
823 cmd_string="%s/link-hw.sh %s %s %s " % (ONS2014_DEMO_SCRIPTS_DIR, dst_dpid, dst_port, cmd)
824 else:
825 cmd_string="%s/link-hw.sh %s %s %s " % (ONS2014_DEMO_SCRIPTS_DIR, src_dpid, src_port, cmd)
826 print cmd_string
827
828 result=os.popen(cmd_string).read()
829
830 return result
831
832#* Create Flow
833#http://localhost:9000/gui/addflow/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>/<srcMAC>/<dstMAC>
834#1 FOOBAR 00:00:00:00:00:00:01:01 1 00:00:00:00:00:00:01:0b 1 matchSrcMac 00:00:00:00:00:00 matchDstMac 00:01:00:00:00:00
835@app.route("/gui/addflow/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>/<srcMAC>/<dstMAC>")
836def add_flow(src_dpid, src_port, dst_dpid, dst_port, srcMAC, dstMAC):
837 host = pick_host()
838 url ="%s/wm/onos/flows/getsummary/%s/%s/json" % (host, 0, 0)
839 (code, result) = get_json(url)
840 parsedResult = json.loads(result)
841 if len(parsedResult) > 0:
842 if parsedResult[-1].has_key('flowId'):
843 flow_nr = int(parsedResult[-1]['flowId']['value'], 16)
844 else:
845 flow_nr = -1 # first flow
846 print "first flow"
847
848 flow_nr += 1
849 command = "%s/add_flow.py -m onos %d %s %s %s %s %s matchSrcMac %s matchDstMac %s" % (ONOS_SCRIPTS_DIR, flow_nr, "dummy", src_dpid, src_port, dst_dpid, dst_port, srcMAC, dstMAC)
850 flow_nr += 1
851 command1 = "%s/add_flow.py -m onos %d %s %s %s %s %s matchSrcMac %s matchDstMac %s" % (ONOS_SCRIPTS_DIR, flow_nr, "dummy", dst_dpid, dst_port, src_dpid, src_port, dstMAC, srcMAC)
852 print "add flow: %s, %s" % (command, command1)
853 errcode = os.popen(command).read()
854 errcode1 = os.popen(command1).read()
855 ret=command+":"+errcode+" "+command1+":"+errcode1
856 print ret
857 return ret
858
859#* Delete Flow
860#http://localhost:9000/gui/delflow/<flow_id>
861@app.route("/gui/delflow/<flow_id>")
862def del_flow(flow_id):
863 command = "%s/delete_flow.py %s" % (ONOS_SCRIPTS_DIR, flow_id)
864 print command
865 errcode = os.popen(command).read()
866 return errcode
867
868#* Start Iperf Througput
869#http://localhost:9000/gui/iperf/start/<flow_id>/<duration>
870@app.route("/gui/iperf/start/<flow_id>/<duration>/<samples>")
871def iperf_start(flow_id,duration,samples):
872 url = "http://%s:%s/wm/onos/flows/get/%s/json" % (RestIP, RestPort, flow_id)
873 try:
874 response = urlopen(url)
875 result = response.read()
876 if len(result) == 0:
877 print "No Flow found"
878 return "Flow %s not found" % (flow_id);
879 except:
880 print "REST IF has issue %s" % url
881 return "REST IF has issue %s" % url
882
883 parsedResult = json.loads(result)
884
885 flowId = int(parsedResult['flowId']['value'], 16)
886 src_dpid = parsedResult['dataPath']['srcPort']['dpid']['value']
887 src_port = parsedResult['dataPath']['srcPort']['port']['value']
888 dst_dpid = parsedResult['dataPath']['dstPort']['dpid']['value']
889 dst_port = parsedResult['dataPath']['dstPort']['port']['value']
890# print "FlowPath: (flowId = %s src = %s/%s dst = %s/%s" % (flowId, src_dpid, src_port, dst_dpid, dst_port)
891
892 if src_dpid in core_switches:
893 src_host = controllers[0]
894 else:
895 hostid=int(src_dpid.split(':')[-2])
896 if TESTBED == "hw":
897 src_host = "mininet%i" % hostid
898 else:
899 src_host = controllers[hostid-1]
900
901 if dst_dpid in core_switches:
902 dst_host = controllers[0]
903 else:
904 hostid=int(dst_dpid.split(':')[-2])
905 if TESTBED == "hw":
906 dst_host = "mininet%i" % hostid
907 else:
908 dst_host = controllers[hostid-1]
909
910# /runiperf.sh <flowid> <src_dpid> <dst_dpid> hw:svr|sw:svr|hw:client|sw:client <proto>/<duration>/<interval>/<samples>
911 protocol="udp"
912 interval=0.1
913 if TESTBED == "hw":
914 cmd_string="dsh -w %s 'cd %s; " % (dst_host, REMOTE_DEMO_SCRIPTS_DIR)
915 else:
916 cmd_string="ssh %s 'cd %s; " % (dst_host, REMOTE_DEMO_SCRIPTS_DIR)
917 cmd_string += "./runiperf.sh %d %s %s %s:%s %s/%s/%s/%s'" % (flowId, src_dpid, dst_dpid, TESTBED, "svr", protocol, duration, interval, samples)
918 print cmd_string
919 os.popen(cmd_string)
920
921 if TESTBED == "hw":
922 cmd_string="dsh -w %s 'cd %s; " % (src_host, REMOTE_DEMO_SCRIPTS_DIR)
923 else:
924 cmd_string="ssh %s 'cd %s;" % (src_host, REMOTE_DEMO_SCRIPTS_DIR)
925 cmd_string+="./runiperf.sh %d %s %s %s:%s %s/%s/%s/%s'" % (flowId, src_dpid, dst_dpid, TESTBED, "client", protocol, duration, interval, samples)
926 print cmd_string
927 os.popen(cmd_string)
928
929 return cmd_string
930
931
932#* Get Iperf Throughput
933#http://localhost:9000/gui/iperf/rate/<flow_id>
934@app.route("/gui/iperf/rate/<flow_id>")
935def iperf_rate(flow_id):
936 url = "http://%s:%s/wm/onos/flows/get/%s/json" % (RestIP, RestPort, flow_id)
937 try:
938 response = urlopen(url)
939 result = response.read()
940 if len(result) == 0:
941 return "no such iperf flow (flowid %s)" % flow_id
942 except:
943 print "REST IF has issue %s" % url
944 exit
945
946 parsedResult = json.loads(result)
947
948 flowId = int(parsedResult['flowId']['value'], 16)
949 src_dpid = parsedResult['dataPath']['srcPort']['dpid']['value']
950 src_port = parsedResult['dataPath']['srcPort']['port']['value']
951 dst_dpid = parsedResult['dataPath']['dstPort']['dpid']['value']
952 dst_port = parsedResult['dataPath']['dstPort']['port']['value']
953
954 if dst_dpid in core_switches:
955 host = controllers[0]
956 else:
957 hostid=int(dst_dpid.split(':')[-2])
958 if TESTBED == "hw":
959 host = "mininet%i" % hostid
960 else:
961 host = controllers[hostid-1]
962
963 url="http://%s:%s/log/iperfsvr_%s.out" % (host, 9000, flow_id)
964 try:
965 response = urlopen(url)
966 result = response.read()
967 except:
968 print "REST IF has issue %s" % url
969 return
970
971 if re.match("Cannot", result):
972 resp = Response(result, status=400, mimetype='text/html')
973 return "no iperf file found (host %s flowid %s): %s" % (host, flow_id, result)
974 else:
975 resp = Response(result, status=200, mimetype='application/json')
976 return resp
977
978if __name__ == "__main__":
979 random.seed()
980 read_config()
981 read_link_def()
982 if len(sys.argv) > 1 and sys.argv[1] == "-d":
983 # for debugging
984 #add_flow("00:00:00:00:00:00:02:02", 1, "00:00:00:00:00:00:03:02", 1, "00:00:00:00:02:02", "00:00:00:00:03:0c")
985 #proxy_link_change("up", "00:00:00:00:ba:5e:ba:11", 1, "00:00:00:00:00:00:00:00", 1)
986 #proxy_link_change("down", "00:00:20:4e:7f:51:8a:35", 1, "00:00:00:00:00:00:00:00", 1)
987 #proxy_link_change("up", "00:00:00:00:00:00:02:03", 1, "00:00:00:00:00:00:00:00", 1)
988 #proxy_link_change("down", "00:00:00:00:00:00:07:12", 1, "00:00:00:00:00:00:00:00", 1)
989 #print "-- query all switches --"
990 #query_switch()
991 #print "-- query topo --"
992 #topology_for_gui()
993 ##print "-- query all links --"
994 ##query_links()
995 #print "-- query all devices --"
996 #devices()
997 #links()
998 #switches()
999 #reset_demo()
1000 pass
1001 else:
1002 app.debug = True
1003 app.run(threaded=True, host=ProxyIP, port=ProxyPort)