blob: a3bd51cf813623a3b3b17b0d067cd52bc15bf8b9 [file] [log] [blame]
Pankaj Berdec4ae4b82013-01-12 09:56:47 -08001#! /usr/bin/python
2
3import os
4import sys
5import subprocess
6import json
7import argparse
8import io
9import time
10
11from flask import Flask, json, Response, render_template, make_response, request
12
13RestIP="127.0.0.1"
14RestPort=8182
15DBName="titan-netmap"
16
17app = Flask(__name__)
18
19## Define static link and switch data for now (will be replaced by the one dynamically quering Network DB ##
20#links_=[{"src-switch":"00:00:00:00:00:00:00:06","src-port":3,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:09","dst-port":4,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:08","src-port":4,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:06","dst-port":2,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:07","src-port":4,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:06","dst-port":1,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:06","src-port":1,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:07","dst-port":4,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:03","src-port":4,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:02","dst-port":1,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:0b","src-port":4,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:0a","dst-port":1,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:01","src-port":1,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:02","dst-port":4,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:01","src-port":2,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:06","dst-port":4,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:0d","src-port":4,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:0a","dst-port":3,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:06","src-port":2,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:08","dst-port":4,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:02","src-port":2,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:04","dst-port":4,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:09","src-port":4,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:06","dst-port":3,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:04","src-port":4,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:02","dst-port":2,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:0c","src-port":4,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:0a","dst-port":2,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:06","src-port":4,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:01","dst-port":2,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:01","src-port":3,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:0a","dst-port":4,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:0a","src-port":1,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:0b","dst-port":4,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:05","src-port":4,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:02","dst-port":3,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:02","src-port":4,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:01","dst-port":1,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:0a","src-port":4,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:01","dst-port":3,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:02","src-port":3,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:05","dst-port":4,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:0a","src-port":2,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:0c","dst-port":4,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:02","src-port":1,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:03","dst-port":4,"dst-port-state":0,"type":"internal"},{"src-switch":"00:00:00:00:00:00:00:0a","src-port":3,"src-port-state":0,"dst-switch":"00:00:00:00:00:00:00:0d","dst-port":4,"dst-port-state":0,"type":"internal"}]
21
22#switches_= [{"dpid":"00:00:00:00:00:00:00:0c"},{"dpid":"00:00:00:00:00:00:00:06"},{"dpid":"00:00:00:00:00:00:00:0d"},{"dpid":"00:00:00:00:00:00:00:05"},{"dpid":"00:00:00:00:00:00:00:07"},{"dpid":"00:00:00:00:00:00:00:08"},{"dpid":"00:00:00:00:00:00:00:09"},{"dpid":"00:00:00:00:00:00:00:02"},{"dpid":"00:00:00:00:00:00:00:0a"},{"dpid":"00:00:00:00:00:00:00:01"},{"dpid":"00:00:00:00:00:00:00:03"},{"dpid":"00:00:00:00:00:00:00:0b"},{"dpid":"00:00:00:00:00:00:00:04"}]
23
24
25## File Fetch ##
26@app.route('/ui/img/<filename>', methods=['GET'])
27@app.route('/img/<filename>', methods=['GET'])
28@app.route('/css/<filename>', methods=['GET'])
29@app.route('/js/models/<filename>', methods=['GET'])
30@app.route('/js/views/<filename>', methods=['GET'])
31@app.route('/js/<filename>', methods=['GET'])
32@app.route('/lib/<filename>', methods=['GET'])
33@app.route('/', methods=['GET'])
34@app.route('/<filename>', methods=['GET'])
35@app.route('/tpl/<filename>', methods=['GET'])
36def return_file(filename="index.html"):
37 if request.path == "/":
38 fullpath = "./index.html"
39 else:
40 fullpath = str(request.path)[1:]
41
42 response = make_response(open(fullpath).read())
43 suffix = fullpath.split(".")[-1]
44
45 if suffix == "html" or suffix == "htm":
46 response.headers["Content-type"] = "text/html"
47 elif suffix == "js":
48 response.headers["Content-type"] = "application/javascript"
49 elif suffix == "css":
50 response.headers["Content-type"] = "text/css"
51 elif suffix == "png":
52 response.headers["Content-type"] = "image/png"
53
54 return response
55
56## REST API ##
57#@app.route("/wm/topology/links/json")
58#def links():
59# global links_
60# js = json.dumps(links_)
61# resp = Response(js, status=200, mimetype='application/json')
62# return resp
63
64#@app.route("/wm/core/controller/switches/json")
65#def switches():
66# global switches_
67# js = json.dumps(switches_)
68# resp = Response(js, status=200, mimetype='application/json')
69# return resp
70
71@app.route("/wm/device/")
72def devices():
73 ret = []
74 js = json.dumps(ret)
75 resp = Response(js, status=200, mimetype='application/json')
76 return resp
77
78## return fake stat for now
79@app.route("/wm/core/switch/<switchId>/<statType>/json")
80def switch_stat(switchId, statType):
81 if statType == "desc":
82 desc=[{"length":1056,"serialNumber":"None","manufacturerDescription":"Nicira Networks, Inc.","hardwareDescription":"Open vSwitch","softwareDescription":"1.4.0+build0","datapathDescription":"None"}]
83 ret = {}
84 ret[switchId]=desc
85 elif statType == "aggregate":
86 aggr = {"packetCount":0,"byteCount":0,"flowCount":0}
87 ret = {}
88 ret[switchId]=aggr
89 else:
90 ret = {}
91
92 js = json.dumps(ret)
93 resp = Response(js, status=200, mimetype='application/json')
94 return resp
95
96@app.route("/wm/core/controller/switches/json")
97def query_switch():
98 try:
99 command = "curl -s http://%s:%s/graphs/%s/vertices" % (RestIP, RestPort, DBName)
100 result = os.popen(command).read()
101 parsedResult = json.loads(result)['results']
102 except:
103 log_error("REST IF has issue")
104 exit
105
106 switches_ = []
107 for v in parsedResult:
108 if v['type'] == "switch":
109 dpid = str(v['dpid'])[1:-1] ;# removing quotation
110 sw = {}
111 sw['dpid']=dpid
112 switches_.append(sw)
113
114 print switches_
115 js = json.dumps(switches_)
116 resp = Response(js, status=200, mimetype='application/json')
117 return resp
118
119@app.route("/wm/topology/links/json")
120def query_links():
121 try:
122 command = "curl -s http://%s:%s/graphs/%s/edges" % (RestIP, RestPort, DBName)
123 result = os.popen(command).read()
124 parsedResult = json.loads(result)['results']
125 except:
126 log_error("REST IF has issue")
127 exit
128
129 switches_ = []
130 for v in parsedResult:
131 if v['_label'] == "link":
132 srcport = v['_inV']
133 dstport = v['_outV']
134 (sport, sdpid) = get_port_switch(srcport)
135 (dport, ddpid) = get_port_switch(dstport)
136 link = {}
137 link["src-switch"]=sdpid[1:-1]
138 link["src-port"]=sport
139 link["src-port-state"]=0
140 link["dst-switch"]=ddpid[1:-1]
141 link["dst-port"]=dport
142 link["dst-port-state"]=0
143 link["type"]="internal"
144 switches_.append(link)
145
146 print switches_
147 js = json.dumps(switches_)
148 resp = Response(js, status=200, mimetype='application/json')
149 return resp
150
151def get_port_switch(vertex):
152 try:
153 command = "curl -s http://%s:%s/graphs/%s/vertices/%d" % (RestIP, RestPort, DBName, vertex)
154 result = os.popen(command).read()
155 parsedResult = json.loads(result)['results']
156 except:
157 log_error("REST IF has issue")
158 exit
159
160 port_number = parsedResult['number']
161 vertex_id = parsedResult['_id']
162 switch_dpid = portid_to_switch_dpid(vertex_id)
163
164 return (port_number, switch_dpid)
165
166def portid_to_switch_dpid(vertex):
167 try:
168 command = "curl -s http://%s:%s/graphs/%s/vertices/%d/in" % (RestIP, RestPort, DBName, vertex)
169 result = os.popen(command).read()
170 parsedResult = json.loads(result)['results']
171 except:
172 log_error("REST IF has issue")
173 exit
174
175 for v in parsedResult:
176 if v['type'] == "switch":
177 sw_dpid = v['dpid']
178 break
179
180 return sw_dpid
181
182def id_to_dpid(vertex):
183 try:
184 command = "curl -s http://%s:%s/graphs/%s/vertices/%d" % (RestIP, RestPort, DBName, vertex)
185 result = os.popen(command).read()
186 parsedResult = json.loads(result)['results']
187 except:
188 log_error("REST IF has issue")
189 exit
190
191 if parsedResult['type'] != "switch":
192 print "not a switch vertex"
193 exit
194 else:
195 sw_dpid = parsedResult['dpid']
196
197 return sw_dpid
198
199
200if __name__ == "__main__":
201 app.debug = True
202 app.run(host="0.0.0.0", port=9000)
203# query_switch()
204# query_links()