e8bc66d50aac706a1cbdb9ef9118f9309eb3ca29
[VSoRC/.git] / js / topology.js
1 /*
2  * Copyright (C) 2014 SDN Hub
3  *
4  * Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3.
5  * You may not use this file except in compliance with this License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.gnu.org/licenses/gpl-3.0.txt
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
13  * implied.
14  */
15
16 var switchList = {};
17 var hostList = {};
18 var hostSwitchLinkList = [];
19
20 var url = "http://" + location.hostname + ":8080";
21 var graph = new joint.dia.Graph;
22 var erd = joint.shapes.erd;
23
24 var element = function(elm, x, y, label) {
25     var cell = new elm({ position: { x: x, y: y }, size: { width: 150, height: 30 },
26               attrs: { text: { text: label }}});
27
28         cell.attr({
29                   rect: { fill: '#2C3E50', rx: 5, ry: 5, 'stroke-width': 2, stroke: 'black' },
30               text: {
31                   fill: 'white',
32                   'font-size': 16, 'font-weight': 'bold', 'font-variant': 'small-caps', 'text-transform': 'capitalize'
33               }
34           });
35     graph.addCell(cell);
36     return cell;
37 };
38
39 var link = function(elm1, elm2) {
40
41     var cell = new erd.Line({ source: { id: elm1.id }, target: { id: elm2.id },
42         attrs : { '.connection': { stroke: 'blue' } },
43         labels: [{ text: {'font-size': 10 } },
44                  { text: {'font-size': 10 } }]
45     });
46
47     try {
48         graph.addCell(cell);
49     } catch (e) {
50       console.log(e);
51     }
52     return cell;
53 };
54
55 var getSwitchDesc = function(dpid) {
56     var ofctl_dpid = parseInt(dpid, 16);
57     $.getJSON(url.concat("/stats/desc/").concat(ofctl_dpid), function(descs){
58             $.each(descs, function(key, value){
59             var valueJson = JSON.stringify(value);
60             var switchDesc = JSON.parse(valueJson);
61
62             switchList[dpid]['desc'] = switchDesc;
63         });
64     }).then(setSwitchTooltip);
65 };
66
67 var getDom = function(modelId) {
68     var elems = document.getElementsByClassName("element");
69     for (i=0;i < elems.length; i++) {
70         dom = document.getElementById(elems[i].id);
71         if (modelId == dom.getAttribute("model-id"))
72             return dom;
73     }
74     return undefined;
75 };
76
77 var setSwitchTooltip = function() {
78     $.each(switchList, function(dpid, value) {
79         var rectDom = getDom(value.element.id);
80         if (rectDom != undefined && value.desc != undefined) {
81             value['tooltip'] = new joint.ui.Tooltip({
82                     target: rectDom,
83                     content: '<span>Switch ' + value['name'] + '</span>' +
84                              '<hr><table>' +
85                              '<tr><td>H/w type:</td><td>' + value.desc.hw_desc + '</td></tr>' +
86                              '<tr><td>S/w version:</td><td>' + value.desc.sw_desc + '</td></tr>' +
87                              '<tr><td>Vendor:</td><td>' + value.desc.mfr_desc + '</td></tr>' +
88                              '<tr><td>Serial #:</td><td>' + value.desc.serial_num + '</td></tr>' +
89                              '<tr><td>Description:</td><td>' + value.desc.dp_desc + '</td></tr>' +
90                              '</table>',
91                     top: rectDom,
92                     direction: 'top'
93             });
94         }
95     });
96 };
97
98 var hostCleanup = function(currentHosts) {
99     $.each(hostList, function(key, value){
100         value.tooltip.remove();
101         try {
102         value.link.remove();
103       } catch (e) {
104         console.log(e);
105       }
106         if (!(key in currentHosts))
107             value.element.remove();
108     });
109 };
110
111 var drawHosts = function() {
112         srcSwitch = {};
113         dstSwitch = {};
114
115         $.getJSON(url.concat("/v1.0/hosts"), function(hosts){
116         //Remove old tooltips and host links
117         hostCleanup(hosts);
118
119             $.each(hosts, function(key, value){
120             //Do all common stuff for an IP
121             if (!(key in hostList))
122                 hostList[key] = {};
123
124             if (!('element' in hostList[key])) {
125                 var x = 1000, y=1000;
126                 var cell = new erd.Normal({ position: { x: x, y: y }, attrs: { text: { text: key }}});
127                 graph.addCell(cell);
128
129                 hostList[key]['element'] = cell;
130                 hostList[key]['dom'] = getDom(cell.id);
131             }
132
133             hostList[key]['entry'] = value;
134             var hostDom = hostList[key]['dom'];
135             var cell = hostList[key]['element'];
136
137             if (value.dpid in switchList && hostDom != undefined) {
138                 var date = new Date(value.timestamp * 1000);
139                 var dateStr = (date.getMonth() + 1) + "/" +
140                                date.getDate() + "/" +
141                                date.getFullYear() + " " +
142                                date.getHours() + ":" +
143                                date.getMinutes() + ":" +
144                                date.getSeconds();
145
146                 hostList[key]['tooltip'] = new joint.ui.Tooltip({
147                         target: hostDom,
148                         content: '<table>' +
149                                  '<tr><td>IP:</td><td>' + key + '</td></tr>' +
150                                  '<tr><td>MAC:</td><td>' + value.mac + '</td></tr>' +
151                                  '<tr><td>Assoc switch:</td><td>' + value.dpid + '</td></tr>' +
152                                  '<tr><td>Assoc port:</td><td>' + value.port + '</td></tr>' +
153                                  '<tr><td>Time seen:</td><td>' + dateStr + '</td></tr>' +
154                                  '</table>',
155                         top: hostDom,
156                         direction: 'top'
157                 });
158                 
159                 try{
160                 hostList[key]['link'] =link(switchList[value.dpid]['element'], cell);
161               }catch(e){
162                 console.log(e);
163               }
164             }
165                 });
166     try {
167         joint.layout.DirectedGraph.layout(graph, { setLinkVertices: false, edgeSep: 20, rankSep: 80, nodeSep: 50 });
168       } catch (e) {
169         console.log(e)
170       }
171         });
172 };
173
174 var drawLinks = function() {
175         srcSwitch = {};
176         dstSwitch = {};
177         $.getJSON(url.concat("/v1.0/topology/links"), function(links){
178             $.each(links, function(key, value){
179             var valueJson = JSON.stringify(value);
180             var obj = JSON.parse(valueJson);
181
182             var portname = obj.src.name;
183
184
185             link(switchList[obj.src.dpid]['element'],
186                  switchList[obj.dst.dpid]['element']).cardinality(portname);
187                 });
188     try{
189         joint.layout.DirectedGraph.layout(graph, { setLinkVertices: false, edgeSep: 20, rankSep: 80, nodeSep: 80 });
190       } catch (e) {
191         console.log(e)
192       }
193         }).then(drawHosts);
194 }
195
196 $(function()  {
197     var paperScroller = new joint.ui.PaperScroller;
198
199     var paper = new joint.dia.Paper({
200             el: paperScroller.el,
201             width: 2400,
202             height: 800,
203             model: graph
204     });
205
206     paperScroller.options.paper = paper;
207     $('#paper-container').append(paperScroller.render().el);
208     paper.on('blank:pointerdown', paperScroller.startPanning);
209
210 $.getJSON(url.concat("/v1.0/topology/switches"), function(switches){
211         var counter = 0;
212     $.each(switches, function(index, value){
213                 var valueJson = JSON.stringify(value);
214         var obj = JSON.parse(valueJson);
215
216         switchList[obj.dpid] = {}
217
218         var switchName = obj.dpid;
219         switchList[obj.dpid]['name'] = switchName;
220
221         var x = 200 + 150 * (index % 4);
222         var y = 100 + 150 * Math.floor(index/4);
223
224         //console.log("DPID: " + obj.dpid + " X = "+x + " Y = "+y)
225                     switchList[obj.dpid]['element'] = element(joint.shapes.basic.Rect, x, y, switchName);
226
227         getSwitchDesc(obj.dpid);
228         //console.log(switchList[obj.dpid]['element'])
229
230     });
231 }).then(drawLinks);
232
233 paper.on('cell:pointerdown',
234     function(cellView, evt, x, y) {
235         $.each(switchList, function(key, value) {
236           if (value.id == cellView.model.id) {
237             console.log("Clicked " + key);
238           }
239         });
240 });
241
242 var drawHostIntervalD = setInterval(function(){drawHosts()}, 10000);
243
244 });
245 /*
246 graph.on('change:position', function(cell) {
247     var parentId = cell.get('parent');
248     if (!parentId) return;
249
250     var parent = graph.getCell(parentId);
251     var parentBbox = parent.getBBox();
252     var cellBbox = cell.getBBox();
253
254     if (parentBbox.containsPoint(cellBbox.origin()) &&
255         parentBbox.containsPoint(cellBbox.topRight()) &&
256         parentBbox.containsPoint(cellBbox.corner()) &&
257         parentBbox.containsPoint(cellBbox.bottomLeft())) {
258
259         // All the four corners of the child are inside
260         // the parent area.
261         return;
262     }
263
264     // Revert the child position.
265     cell.set('position', cell.previous('position'));
266 });*/