2 * univbristopo: ofelia openflow topology plugin
4 * Description: plugin to view ofelia topology in myslice
5 * Requires: js/plugin.js
6 * URL: http://www.myslice.info
7 * Author: Frederic Francois <f.francois@bristol.ac.uk>
8 * Copyright: Copyright 2013-2014 Bristol University
19 topoviewer_state={mode:"edit",link_type:"non-optical"};
22 var UnivbrisTopo = Plugin.extend({
24 init: function(options, element) {
25 this._super(options, element);
26 this.listen_query(options.query_uuid);
27 jQuery('#topo_plugin').hide();
28 //console.log("topo init called");
31 new_record: function(record)
33 var urn = record['urn'];
34 var pos = urn.search('link');
37 var link = urn.substring(pos+5);
38 pos = link.search("_");
39 var head_node=link.substring(0,pos);
40 link=link.substring(pos+1);
41 pos = link.search("_");
42 var head_port=link.substring(0,pos);
43 link=link.substring(pos+1);
44 pos = link.search("_");
45 var tail_node=link.substring(0,pos);
46 link=link.substring(pos+1);
50 if (urn.search('opticalpacket')!=-1){
53 else if (urn.search('optical')!=-1){
56 else if (urn.search('compute')!=-1){
59 else if (urn.search('federation')!=-1){
65 pos = urn.search('ofam');
66 var testbed=urn.substring(pos+5);
67 testbed=testbed.substring(0, testbed.search('link')-1);
71 var src_id=addNode(head_node,testbed,"packet");
72 var dst_id=addNode(tail_node,testbed,"packet");
74 addLink(src_id,dst_id,head_port,tail_port,urn);
75 /*tmp_link['source']=src_id;
76 tmp_link['target']=dst_id;
77 tmp_link['src_port']=head_port;
78 tmp_link['dst_port']=tail_port;
79 tmp_link['value']=urn;
80 d3_links.push(tmp_link);*/
84 var src_id=addNode(head_node,testbed,"optical");
85 var dst_id=addNode(tail_node,testbed,"optical");
87 addLink(src_id,dst_id,head_port,tail_port,urn);
88 /*tmp_link['source']=src_id;
89 tmp_link['target']=dst_id;
90 tmp_link['src_port']=head_port;
91 tmp_link['dst_port']=tail_port;
92 tmp_link['value']=urn;
93 d3_links.push(tmp_link);*/
97 var src_id=addNode(head_node,testbed,"packet");
98 var dst_id=addNode(tail_node,testbed,"compute");
100 addLink(src_id,dst_id,head_port,tail_port,urn);
101 /*tmp_link['source']=src_id;
102 tmp_link['target']=dst_id;
103 tmp_link['src_port']=head_port;
104 tmp_link['dst_port']=tail_port;
105 tmp_link['value']=urn;
106 d3_links.push(tmp_link);*/
110 var src_id=addNode(head_node,testbed,"federation");
111 var dst_id=addNode(tail_node,testbed,"packet");
113 addLink(src_id,dst_id,head_port,tail_port,urn);
114 /*tmp_link['source']=src_id;
115 tmp_link['target']=dst_id;
116 tmp_link['src_port']=head_port;
117 tmp_link['dst_port']=tail_port;
118 tmp_link['value']=urn;
119 d3_links.push(tmp_link);*/
123 var src_id=addNode(head_node,testbed,"optical");
124 var dst_id=addNode(tail_node,testbed,"packet");
126 addLink(src_id,dst_id,head_port,tail_port,urn);
127 /*tmp_link['source']=src_id;
128 tmp_link['target']=dst_id;
129 tmp_link['src_port']=head_port;
130 tmp_link['dst_port']=tail_port;
131 tmp_link['value']=urn;
132 d3_links.push(tmp_link);*/
138 on_new_record: function(record)
141 this.new_record(record);
146 on_query_done: function()
148 query_itr=query_itr+1;
152 //console.log("graph all done called:"+query_itr);
155 //console.log(d3_links);
157 //$("#univbris_welcome").hide();
158 //jQuery("#univbris_flowspace_selection").show();
159 //$("#link_zoom_in").click(zoomIn(0.25));
164 var nIslands=1, //replace
166 width = parseInt($("#topo_plugin_width").css("width")); //800,//parseInt($("#topologyContainer").css("width")), /* Obtain width from container */
167 if(width==0){width=800;}
170 //Islands area generation
172 ny = Math.sqrt(nIslands/p),
173 nx = Math.ceil(p*ny),
177 if (nx*ny > nIslands){
178 if (nx > ny && (nx-1)*ny >= nIslands)
180 else if( nx <= ny && nx*(ny-1) >= nIslands)
184 var aw = Math.floor((width-(nx+1)*pad)/nx),
185 ah = Math.floor((height-(ny+1)*pad)/ny);
187 for (i=0; i<nIslands; i++){
188 tx0 = pad + (pad + aw)*(Math.floor(i%nx));
189 ty0 = pad + (pad + ah)*(Math.floor(i/nx));
190 foci[i] = {x0: tx0, x1: tx0 + aw, y0: ty0, y1: ty0 + ah};
194 function randomXToY(minVal,maxVal,floatVal){
195 var randVal = minVal+(Math.random()*(maxVal-minVal));
196 return typeof floatVal=='undefined'?Math.round(randVal):randVal.toFixed(floatVal);
199 function pEllipse(set){
200 function getDistance(p){
201 return Math.pow((p[0]-cx),2)/Math.pow(rx,2) + Math.pow((p[1]-cy),2)/Math.pow(ry,2);
207 cx = (set.x1 + set.x0)/2;
208 rx = ((set.x1 - set.x0)/2 + (set.y1 - set.y0)/2)/2;
209 cy = (set.y1 + set.y0)/2;
210 ry = (set.y1 - set.y0)/2;
213 p = [randomXToY(set.x0, set.x1), randomXToY(set.y0, set.y1) ];
225 for (i=0;i<d3_nodes.length;i++){
226 epoints.push(foci[d3_nodes[i]['group']]);
234 //console.log("nodes");
235 //console.log(d3_nodes);
236 //console.log("links");
237 //console.log(d3_links);
239 for (i=0;i<d3_nodes.length;i++){
241 node['nodeValue']=d3_nodes[i].nodeValue;
242 node['nodeName']=d3_nodes[i].nodeName;
243 node['image']=d3_nodes[i].image;
245 node['group']=d3_nodes[i].group;
246 node['location']=d3_nodes[i].location;
247 node['description']= d3_nodes[i].description;
248 node['fixed']= false;
250 if (d3_nodes[i].type == "compute"){
251 node['type']=d3_nodes[i].type + " server";
254 node['type']=d3_nodes[i].type + " switch";
256 node['available']= d3_nodes[i].available;
263 for (i=0;i<d3_links.length;i++){
265 link['source']= d3_links[i].source;
266 link['target']= d3_links[i].target;
267 link['value']= d3_links[i].value;
268 link['linknum']=d3_links[i].linknum;
275 function getLinkStyle(d, attr){
276 //rsc_ids = d.value.split("-");
277 //console.log('link with: '+d.value+" event");
278 //console.log("getlinkstyle attr:",attr);
279 //console.log("topoviewer_state:",topoviewer_state);
282 if (topoviewer_state.mode!="edit"){
288 if(d.value.search("optical")!=-1 && topoviewer_state.link_type=="optical"){ //link is optical
289 //if(topoviewer_state.link_type=="optical"){
291 var port_table=$("#univbris_foam_ports_selection__table").dataTable();
292 var nodes = $('input',port_table.fnGetNodes());
295 for(i=0;i<nodes.length;i++){
296 if (nodes[i].id==d.value){
297 nodes[i].checked=!nodes[i].checked;
298 checked=nodes[i].checked;
305 var values = {'stroke': 'black', 'stroke-width': '5px' };
306 //console.log("in mouseover return"+ JSON.stringify(values));
307 return JSON.stringify(values);
310 var values = {'stroke': '#ccc', 'stroke-width': '4px' };
311 //console.log("in mouseover return"+ JSON.stringify(values));
312 return JSON.stringify(values);
315 }else if(attr=="mouseover"){
317 var values = {'stroke': 'blue', 'stroke-width': '4px' };
318 //console.log("in mouseover return"+ JSON.stringify(values));
319 return JSON.stringify(values);
323 if( ($(":checkbox#"+rsc_ids[0]+":checked").length && rsc_ids[1].indexOf("eth") != -1) ||($(":checkbox#"+rsc_ids[0]+":checked").length && $(":checkbox#"+rsc_ids[1]+":checked").length)){
324 if (attr == "stroke")
329 if (attr == "stroke")
336 var port_table=$("#univbris_foam_ports_selection__table").dataTable();
337 var nodes = $('input',port_table.fnGetNodes());
340 for(i=0;i<nodes.length;i++){
341 if (nodes[i].id==d.value){
342 //nodes[i].checked=!nodes[i].checked;
343 checked=nodes[i].checked;
349 var values = {'stroke': 'black', 'stroke-width': '5px' };
350 //console.log("in mouseover return"+ JSON.stringify(values));
351 return JSON.stringify(values);
354 var values = {'stroke': '#ccc', 'stroke-width': '4px' };
355 //console.log("in mouseover return"+ JSON.stringify(values));
356 return JSON.stringify(values);
358 //return {'stroke': '#ccc', 'stroke-width': '2px' };
366 else{//link is not optical
367 if(topoviewer_state.link_type=="non-optical" && !(d.value.search("opticalpacket")==-1 && d.value.search("optical")!=-1) ){
369 var port_table=$("#univbris_foam_ports_selection__table").dataTable();
370 var nodes = $('input',port_table.fnGetNodes());
373 for(i=0;i<nodes.length;i++){
374 if (nodes[i].id==d.value){
375 nodes[i].checked=!nodes[i].checked;
376 checked=nodes[i].checked;
383 var values = {'stroke': 'black', 'stroke-width': '5px' };
384 //console.log("in mouseover return"+ JSON.stringify(values));
385 return JSON.stringify(values);
388 var values = {'stroke': '#ccc', 'stroke-width': '4px' };
389 //console.log("in mouseover return"+ JSON.stringify(values));
390 return JSON.stringify(values);
393 }else if(attr=="mouseover"){
395 var values = {'stroke': 'blue', 'stroke-width': '4px' };
396 //console.log("in mouseover return"+ JSON.stringify(values));
397 return JSON.stringify(values);
401 if( ($(":checkbox#"+rsc_ids[0]+":checked").length && rsc_ids[1].indexOf("eth") != -1) ||($(":checkbox#"+rsc_ids[0]+":checked").length && $(":checkbox#"+rsc_ids[1]+":checked").length)){
402 if (attr == "stroke")
407 if (attr == "stroke")
414 var port_table=$("#univbris_foam_ports_selection__table").dataTable();
415 var nodes = $('input',port_table.fnGetNodes());
418 for(i=0;i<nodes.length;i++){
419 if (nodes[i].id==d.value){
420 //nodes[i].checked=!nodes[i].checked;
421 checked=nodes[i].checked;
427 var values = {'stroke': 'black', 'stroke-width': '5px' };
428 //console.log("in mouseover return"+ JSON.stringify(values));
429 return JSON.stringify(values);
432 var values = {'stroke': '#ccc', 'stroke-width': '4px' };
433 //console.log("in mouseover return"+ JSON.stringify(values));
434 return JSON.stringify(values);
436 //return {'stroke': '#ccc', 'stroke-width': '2px' };
447 function getBaseNodeColor(d){
450 return d3.rgb(d.color.toString().toString()).darker(.15*group);
453 function getNodeCircleStyle(d, attr){
454 selected_len =0;// $(":checkbox:checked.node_id_"+d.nodeValue).length;
455 all_len = 0;//$(":checkbox:.node_id_"+d.nodeValue).length;
456 //selected_server = $(".server_node_"+d.nodeValue+".connected").length;
458 return d3.rgb(d.color.toString()).brighter(5);
459 }else if(attr=="click"){
460 if(selected_len == all_len) {
461 $(":checkbox:checked.node_id_"+d.nodeValue).click();
462 return getBaseNodeColor(d);
464 $(":checkbox:not(:checked).node_id_"+d.nodeValue).click();
465 return d3.rgb(d.color.toString()).darker(5);
467 }else if (attr == "dragstop" && selected_len == 0){
468 return getBaseNodeColor(d);
471 return getBaseNodeColor(d);
473 if (selected_len != 0){
474 return d3.rgb(d.color.toString()).darker(5);
476 return getBaseNodeColor(d);
482 function getNodesIsland(d){
484 data.nodes.forEach(function(o, i){
493 zoom_in_active = false;
494 zoom_out_active = false;
497 function zoomIn(zoom){
498 if(zoom_in_active == false && zoom_out_active == false){
499 $("#link_zoom_in img").css("background-color", "#666");
500 cur_zoom = cur_zoom + zoom;
501 zoom_in_active = true;
504 else if(zoom_in_active == true){
505 cur_zoom = cur_zoom - zoom;
506 $("#link_zoom_in img").css("background-color", "");
507 $("#target, svg, g").css("cursor", "move");
508 zoom_in_active = false;
512 cur_zoom = cur_zoom + zoom + zoom;
513 $("#link_zoom_out img").css("background-color", "");
514 $("#link_zoom_in img").css("background-color", "#666");
515 zoom_out_active = false;
516 zoom_in_active = true;
521 function zoomOut(zoom){
522 if(zoom_out_active == false && zoom_in_active == false){
523 if((cur_zoom - zoom) >0){
524 $("#link_zoom_out img").css("background-color", "#666");
525 cur_zoom = cur_zoom - zoom;
526 zoom_out_active = true;
529 $("#target, svg, g").css("cursor", "move");
532 else if(zoom_out_active == true){
533 cur_zoom = cur_zoom + zoom;
534 $("#link_zoom_out img").css("background-color", "");
535 $("#target, svg, g").css("cursor", "move");
536 zoom_out_active = false;
540 cur_zoom = cur_zoom - zoom;
541 zoom_out_active = false;
542 $("#link_zoom_in img").css("background-color", "");
543 if((cur_zoom - zoom) > 0){
544 $("#link_zoom_out img").css("background-color", "#666");
545 zoom_out_active = true;
548 $("#target, svg, g").css("cursor", "move");
553 function zoomReset(){
563 //console.log('into target clicked with zoomin:'+zoom_in_active);
565 if (zoom_in_active == true || zoom_out_active == true){
566 var mouseClick = d3.mouse(this);
567 _x = -mouseClick[0]/2;
568 _y = -mouseClick[1]/2;
569 if(zoom_out_active == true){
575 zoom_in_active = false;
576 zoom_out_active = false;
581 $('#target').click(function(){
582 //console.log('target clicked');
587 // trans=[(Math.round(width/cur_zoom) - width)/2, (Math.round(height/cur_zoom) - height)/2];
588 trans = [posx, posy];
591 .attr('x', function(d){ return d.x; })
592 .attr('y', function(d){ return d.y; })
594 "translate(" + trans +")"
595 + "scale(" + cur_zoom + ")");
596 $("#link_zoom_in img").css("background-color","");
597 $("#link_zoom_out img").css("background-color","");
598 $("#target, svg, g").css("cursor", "move");
601 //Global position of the canvas
605 /* Translation - bound to drag behavior */
606 dragMap = function(d) {
607 //No drag while zoom option active
608 if(zoom_in_active == false && zoom_out_active == false){
611 svg.attr('x', function(d) { return d.x; })
612 .attr('y', function(d) { return d.y; })
613 .attr("transform", "translate(" + posx + "," + posy + ") scale (" + cur_zoom + ")");
618 /* Instantiation General parameters*/
620 color = d3.scale.category10().domain(d3.range(nIslands)),
621 radius = d3.scale.sqrt().range([0, 12]);
623 svg = d3.select("#target")
626 .attr("pointer-events", "all")
627 .attr("width", width)
628 .attr("height", height)
630 .call(d3.behavior.drag().on("drag", dragMap))
631 .append("svg:g").on("zoom", redraw)
632 .attr("cursor", "move")
635 var nodes = data.nodes;
636 // Set color for each node
637 nodes.forEach(function(d) {
638 if (d.available != "False") {
639 d.color = color(d.group%nIslands);
645 var links = data.links;
647 // Modified version (Carolina)
648 var force = d3.layout.force()
649 .gravity(1/(2*nIslands))
650 .distance(200/nIslands)
652 .size([width, height])
659 var EMPTY_ISLAND = "Island with no resources";
661 //XXX:Very ugly, needs improvement
663 for (i = 0; i< nIslands; i++){
664 islandsLocs[i] = EMPTY_ISLAND;
668 for (i = 0; i< nodes.length; i++){
669 nodeInitialPos[i] = [nodes[i].x, nodes[i].y];
670 if (islandsLocs[nodes[i].group] == EMPTY_ISLAND){
671 islandsLocs[nodes[i].group] = nodes[i].location;
676 for (i = 0; i< nIslands; i++){
677 dataislands[i] = {rx: (aw/2 + ah/2)/2, ry: ah/2, cx:(foci[i].x0+foci[i].x1)/2, cy:(foci[i].y0+foci[i].y1)/2, group: i, location: islandsLocs[i]};
680 var islands = svg.selectAll(".island")
683 .attr("class", "island")
685 var iellipses = islands.append("ellipse")
686 .attr("rx", function(d) { return d.rx; })
687 .attr("ry", function(d) { return d.ry; })
688 .attr("cx",function(d) { return d.cx; })
689 .attr("cy", function(d) { return d.cy; })
690 .style("fill", function(d) { return color(d.group%nIslands); })
691 .style("stroke", function(d) { return color(d.group%nIslands);})
692 .style("opacity", 0.3)
693 .style("stroke-opacity", 0.7)
695 var ilabels = islands.append("text")
696 .attr("text-anchor", "middle")
697 .attr("y", function(d){ return d.cy + d.ry*0.9})
698 .attr("x", function(d){ return d.cx})
699 .attr("font-color", function(d) { return d3.rgb(color(d.group%nIslands)).darker(5); })
701 .style("cursor", "default")
702 .text(function(d) { return d.location });
704 //First ellipse animation on startup
707 var link = svg.selectAll(".link")
709 .enter().append("path")
710 .attr("class", "link").style({'fill': 'black','stroke': "#ccc", 'stroke-width': "4px" });
712 link.on("click", function(d) {
713 d3.select(this).style(JSON.parse(getLinkStyle(d, "click")));
717 link.on("mouseover", function(d) {
718 //console.log(getLinkStyle(d, "mouseover"));
719 d3.select(this).style(JSON.parse(getLinkStyle(d, "mouseover")));
720 // d3.select(this).style({'stroke': "blue", 'stroke-width': "3px" })
724 link.on("mouseout", function(d) {
725 //console.log("mouseout");
726 d3.select(this).style(JSON.parse(getLinkStyle(d, "mouseout")));
727 // d3.select(this).style({'stroke': "#CCC", 'stroke-width': "2px" })
731 var node = svg.selectAll(".node")
734 .attr("class", "node")
736 .call(d3.behavior.drag()
737 .on("dragstart", function(d, i, e) {
741 .on("drag", function(d, i) {
746 d3.select(this).selectAll("circle").style("stroke", function(d){return getNodeCircleStyle(d, "drag");})
749 .on("dragend", function(d, i) {
750 // d.fixed = true; // of course set the node to fixed so the force does not include the node in its auto positioning stuff //with the force.stop() it won't autopositioning, allowing to regroup the nodes
751 d3.select(this).selectAll("circle").style("stroke", function(d){return getNodeCircleStyle(d, "dragstop");})
758 node.append("circle")
759 .attr("r", function(d) { return d.radius; })
760 .style("stroke", function(d){return getNodeCircleStyle(d, "stroke");})
761 .style("fill", function(d){return getNodeCircleStyle(d, "fill");});
764 .attr("xlink:href", function (d) { return d.image; })
769 .attr("opacity", function(d) { return d.available=="False"?0.8:1; })
774 .text(function(d) { return d.name });
776 node.on("mouseover", function (d, i){
777 //tooltip.show(get_node_info_formated(d));
778 // Ugly hack to decode HTML
779 //$('<div/>').html(d.description).text()
780 tooltip.show(d.description);
781 $("#selected_node_info").html("Selected " + d.type + ": " + d.nodeName + " at " + d.location);
782 $("#selected_node_info").css("background-color", d.color );
783 $("#selected_node_info").css("text-shadow", "-3px 2px 4px #eee");
784 $("#selected_node_info").show();
787 .on("mouseout", function() {
788 $("#selected_node_info").css("background-color", "#ebf5ff");
789 //$("#selected_node_info").hide()
792 .on("click", function(d) {
793 /* Only available AMs can be selected */
794 if (d.available != "False") {
795 //checkTopologyLoops(d);
796 d3.select(this).selectAll("circle").style("stroke", function(d){return getNodeCircleStyle(d, "click");});
800 //Number of nodes in each Island
802 for(i=0; i<nIslands; i++){
803 qNodes[i] = getNodesIsland(i);
805 var grav = 0.008 * nx * ny;
807 force.on("tick", function(e){
808 var k = grav * e.alpha;
811 // Adjust K colliding factor
812 $.each(data.nodes, function(i, n){
813 if (node_groups[n.group] == undefined) {
814 node_groups[n.group] = 1;
816 node_groups[n.group] += 1;
820 data.nodes.forEach(function(o, i){
822 // Dumb hack: limit expansion through #nodes
823 if (node_groups[o.group] >= 10) {
824 fact = Math.floor(node_groups[o.group]/10);
828 // Carolina: when there are few nodes, avoid them to stay too far away from the center
829 // AND when there are so many nodes avoid them to stay too near each others
830 if(qNodes[o.group] < 5){
836 o.y += k * fact * qNodes[o.group] * ((dataislands[o.group].cy) - o.y);
837 o.x += k * fact * qNodes[o.group] * ((dataislands[o.group].cx) - o.x);
842 node.each(collide(.5));
843 node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")";})
844 .attr("cx", function(d) { return d.x; })
845 .attr("cy", function(d) { return d.y; });
847 /*link.attr("x1", function(d) { return d.source.x; })
848 .attr("y1", function(d) { return d.source.y; })
849 .attr("x2", function(d) { return d.target.x; })
850 .attr("y2", function(d) { return d.target.y; });
852 link.attr("d", function(d) {
853 var dx = d.target.x - d.source.x,
854 dy = d.target.y - d.source.y,
856 //dr = 50/d.linknum; //linknum is defined above
857 dr = Math.sqrt(dx * dx + dy * dy)/d.linknum;
858 // console.log("printing d:");
860 //return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
861 return "M" + d.source.x + "," + d.source.y +
862 "A" + dr + "," + dr + " 0 0 1," + d.target.x + "," + d.target.y +
863 "A" + dr + "," + dr + " 0 0 0," + d.source.x + "," + d.source.y;
867 function redrawNodes(){
868 node.selectAll("circle").style("stroke", function(d){return getNodeCircleStyle(d, "stroke");});
869 link.style({'fill': 'black','stroke': "#00BFFF", 'stroke-width': "5px" });//"stroke", function(d) {return getLinkStyle(d, "stroke");});
870 //link.style("stroke-width", function(d) {return getLinkStyle(d, "stroke-width");});
877 /*link.attr("x1", function(d) { return d.source.x; })
878 .attr("y1", function(d) { return d.source.y; })
879 .attr("x2", function(d) { return d.target.x; })
880 .attr("y2", function(d) { return d.target.y; });
883 node.each(collide(.5));
884 node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
888 link.attr("d", function(d) {
889 var dx = d.target.x - d.source.x,
890 dy = d.target.y - d.source.y,
891 dr = Math.sqrt(dx * dx + dy * dy)/d.linknum;
892 //dr = 50/d.linknum; //linknum is defined above
893 //console.log("target:"+d.target.nodeName+" source:" +d.source.nodeName+" link_no: "+dr);
894 //dr = 75;//Math.sqrt(dx * dx + dy * dy);
895 //return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
896 return "M" + d.source.x + "," + d.source.y +
897 "A" + dr + "," + dr + " 0 0 1," + d.target.x + "," + d.target.y +
898 "A" + dr + "," + dr + " 0 0 0," + d.source.x + "," + d.source.y;
908 iellipses.attr("rx", function(d) { return d.rx; })
909 .style("display","block")
910 .attr("ry", function(d) { return d.ry; })
911 .attr("cx",function(d) { return d.cx; })
912 .attr("cy", function(d) { return d.cy; })
913 .style("fill", function(d) { return color(d.group%nIslands); })
914 .style("stroke", function(d) { return color(d.group%nIslands);})
915 .style("opacity", 0.3)
916 .style("stroke-opacity", 0.7)
918 ilabels.attr("text-anchor", "middle")
919 .attr("y", function(d){ return d.cy + d.ry*0.9})
920 .attr("x", function(d){ return d.cx})
921 .attr("font-color", function(d) { return d3.rgb(color(d.group%nIslands)).darker(5); })
923 .text(function(d) { return d.location });
925 iellipses.transition()
926 .style("stroke-width",3)
927 .style("stroke", function(d) { return d3.rgb(color(d.group%nIslands)).brighter(10);})
929 iellipses.transition()
944 function collide(alpha) {
945 var quadtree = d3.geom.quadtree(nodes);
947 var r = d.radius + radius.domain()[1] + padding,
952 quadtree.visit(function(quad, x1, y1, x2, y2) {
953 if (quad.point && (quad.point !== d)) {
954 var x = d.x - quad.point.x,
955 y = d.y - quad.point.y,
956 l = Math.sqrt(x * x + y * y),
957 r = d.radius + quad.point.radius + (d.color !== quad.point.color) * padding;
959 l = (l - r) / l * alpha;
974 //$("#link_zoom_in").onclick(zoomIn(0.25));
976 $("#topo_regroup").unbind('click');
977 $("#topo_regroup").click(function(e){
982 $("#link_zoom_reset").unbind('click');
983 $("#link_zoom_reset").click(function(e){
989 $("#link_zoom_in").unbind('click');
990 $("#link_zoom_in").click(function(e){
992 //console.log("zoom current value:");
993 //console.log(cur_zoom);
994 $("#target, svg, g").css("cursor", "url('../../static/img/zoomin.png'),auto");
996 //console.log(zoom_in_active);
1000 $("#link_zoom_out").unbind('click');
1001 $("#link_zoom_out").click(function(e){
1003 $("#target, svg, g").css("cursor", "url('../../static/img/zoomout.png'),auto" );
1007 $("#target, svg, g").css("cursor", "crosshair");
1009 //jQuery('#topo_plugin').hide();
1012 }, //end of function of on all query done
1014 //jQuery('#complete-univbris_topology').hide();
1018 $.plugin('UnivbrisTopo', UnivbrisTopo);
1020 function addNode(node_dpid,location,node_type){
1023 for(i=0;i<d3_nodes.length;i++){
1025 // console.log("adding node");
1026 // console.log(d3_nodes[i]);
1028 if(d3_nodes[i].nodeName==node_dpid){
1036 node['nodeValue']=12;
1037 node['nodeName']=node_dpid;
1038 node['type']=node_type;
1039 if (node_type=="compute"){
1040 node['image']='../../static/img/server-tiny.png';
1042 else if (node_type=="optical"){
1043 node['image']='../../static/img/oswitch-tiny.png';
1045 }else if (node_type=="federation"){
1046 node['image']='../../static/img/switch-tiny2.png';
1049 node['image']='../../static/img/switch-tiny.png';
1054 node['location']=location;
1055 node['description']= "";
1056 node['fixed']= false;
1058 node['available']= true;
1059 d3_nodes.push(node);
1060 return d3_nodes.length-1;
1065 }; //end of add node function
1068 function addLink(source,target,src_port,dst_port,value){
1071 for(i=0;i<d3_links.length;i++){
1072 //if(d3_links[i].source==source && d3_links[i].target==target && d3_links[i].src_port==src_port && d3_links[i].dst_port==dst_port && d3_links[i].value==value){
1073 if((d3_links[i].source==source && d3_links[i].target==target && d3_links[i].src_port==src_port && d3_links[i].dst_port==dst_port) ||
1074 (d3_links[i].source==target && d3_links[i].target==source && d3_links[i].src_port==dst_port && d3_links[i].dst_port==src_port)){
1080 if (found == false){
1082 tmp_link['source']=source;
1083 tmp_link['target']=target;
1084 tmp_link['src_port']=src_port;
1085 tmp_link['dst_port']=dst_port;
1086 tmp_link['value']=value;
1087 tmp_link['linknum']=1;
1088 d3_links.push(tmp_link);
1093 function calLinkNum(){
1094 /* d3_links.sort(function(a,b) {
1095 if (a.source > b.source) {return 1;}
1096 else if (a.source < b.source) {return -1;}
1098 if (a.target > b.target) {return 1;}
1099 if (a.target < b.target) {return -1;}
1104 for (var i=0; i<d3_nodes.length; i++){
1105 for (var i1=0; i1<d3_nodes.length; i1++){
1108 for (var i2=0; i2<d3_links.length; i2++){
1109 if ((d3_links[i2].source ==i &&
1110 d3_links[i2].target ==i1) || (d3_links[i2].source ==i1 &&
1111 d3_links[i2].target ==i)){
1112 d3_links[i2].linknum = num_link;
1120 /* for (var i=0; i<d3_links.length; i++) {
1122 d3_links[i].source == d3_links[i-1].source &&
1123 d3_links[i].target == d3_links[i-1].target) {
1124 d3_links[i].linknum = d3_links[i-1].linknum + 1;
1126 else {d3_links[i].linknum = 1;};
1135 function describeNodes(){
1136 for(i=0;i<d3_nodes.length;i++){
1137 if(d3_nodes[i].type=="packet" || d3_nodes[i].type=="optical" || d3_nodes[i].type=="federation"){
1138 d3_nodes[i].description="<strong>Switch Datapath ID: <br> "+d3_nodes[i].nodeName+" </strong><br><strong>Connections:</strong><br>"
1139 for(i1=0;i1<d3_links.length;i1++){
1140 if(d3_links[i1].source==i){
1141 d3_nodes[i].description+="<strong>• Port "+d3_links[i1].src_port+ " </strong>to Switch " + d3_nodes[d3_links[i1].target].nodeName + " at port "+ d3_links[i1].dst_port+"<br>";
1143 else if(d3_links[i1].target==i){
1144 d3_nodes[i].description+="<strong>• Port "+ d3_links[i1].dst_port + " </strong>to Switch " + d3_nodes[d3_links[i1].source].nodeName + " at port "+ d3_links[i1].src_port+"<br>";
1150 else if (d3_nodes[i].type=="compute"){
1151 d3_nodes[i].description="<strong>Virtualization server name: <br>"+d3_nodes[i].nodeName+"</strong><br><strong>Connections:</strong><br>";
1152 for(i1=0;i1<d3_links.length;i1++){
1153 if(d3_links[i1].source==i){
1154 d3_nodes[i].description+="<strong>• Port "+d3_links[i1].src_port+ " </strong>to Switch " + d3_nodes[d3_links[i1].target].nodeName + " at port "+ d3_links[i1].dst_port+"<br>";
1155 //console.log(d3_links[i1],d3_nodes[d3_links[i1].target]);
1157 if(d3_links[i1].target==i){
1158 d3_nodes[i].description+="<strong>• Port "+ d3_links[i1].dst_port + " </strong>to Switch " + d3_nodes[d3_links[i1].source].nodeName + " at port "+ d3_links[i1].src_port+"<br>";
1159 //console.log(d3_links[i1],d3_nodes[d3_links[i1].source]);
1172 //if(d3_nodes[i].nodeName==node_dpid){