diff --git a/src/main/images/Floodlight Icons.sketch/Data b/src/main/images/Floodlight Icons.sketch/Data new file mode 100644 index 0000000000000000000000000000000000000000..bb5c893b9e5d4172708bd150a5c1137548333db9 Binary files /dev/null and b/src/main/images/Floodlight Icons.sketch/Data differ diff --git a/src/main/images/Floodlight Icons.sketch/QuickLook/Preview.png b/src/main/images/Floodlight Icons.sketch/QuickLook/Preview.png new file mode 100644 index 0000000000000000000000000000000000000000..77fc493ec2b292f44d48e5a360f0459b45dab267 Binary files /dev/null and b/src/main/images/Floodlight Icons.sketch/QuickLook/Preview.png differ diff --git a/src/main/images/Floodlight Icons.sketch/QuickLook/Thumbnail.png b/src/main/images/Floodlight Icons.sketch/QuickLook/Thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..942c917bac3f2f0d351c47e4ad18001e31c4132d Binary files /dev/null and b/src/main/images/Floodlight Icons.sketch/QuickLook/Thumbnail.png differ diff --git a/src/main/images/README b/src/main/images/README new file mode 100644 index 0000000000000000000000000000000000000000..46da010ef7e73c2732a4d86d65089c11f4df2f61 --- /dev/null +++ b/src/main/images/README @@ -0,0 +1 @@ +These icons were created with Sketch, available at http://www.bohemiancoding.com/sketch/ diff --git a/src/main/resources/web/img/server.png b/src/main/resources/web/img/server.png new file mode 100644 index 0000000000000000000000000000000000000000..341c73d1712d246b14dd84c5234f8b344e346238 Binary files /dev/null and b/src/main/resources/web/img/server.png differ diff --git a/src/main/resources/web/img/switch.png b/src/main/resources/web/img/switch.png new file mode 100644 index 0000000000000000000000000000000000000000..d241d92d74d012aa886823a597936b7dcab759c3 Binary files /dev/null and b/src/main/resources/web/img/switch.png differ diff --git a/src/main/resources/web/js/views/topology.js b/src/main/resources/web/js/views/topology.js index a5988b4fce4df9a1d1586052a3f22a2b62051dbc..77129aa3fb1e19c773a5bb61cc44be0e15f377ce 100644 --- a/src/main/resources/web/js/views/topology.js +++ b/src/main/resources/web/js/views/topology.js @@ -19,84 +19,92 @@ window.TopologyView = Backbone.View.extend({ this.template = _.template(tpl.get('topology')); this.model.bind("change", this.render, this); this.hosts = this.options.hosts.models; - this.host_links = new Array(); + this.host_links = []; }, render:function (eventName) { $(this.el).html(this.template()); - // code from D3 force-directed graph example since there's no other docs var width = 900, - height = 600; // might as well make it square + height = 600; var color = d3.scale.category20(); var force = d3.layout.force() - .charge(-240) - .linkDistance(100) - .size([width, height]); + .charge(-500) + .linkDistance(200) + .size([width, height]); var svg = d3.select("#topology-graph").append("svg") - .attr("width", width) - .attr("height", height); + .attr("width", width) + .attr("height", height); if(this.model.nodes) { - for (var i = 0; i < this.model.nodes.length; i++) { - this.model.nodes[i].group = 1; - this.model.nodes[i].id = this.model.nodes[i].name; - } - - for (var i = 0; i < this.hosts.length; i++) { - host = this.hosts[i]; - if (host.attributes['ipv4'].length > 0) { - host.name = host.attributes['ipv4'][0] + "\n" + host.id; - } else { - host.name = host.id; + for (var i = 0; i < this.model.nodes.length; i++) { + this.model.nodes[i].group = 1; + this.model.nodes[i].id = this.model.nodes[i].name; } - host.group = 2; - //console.log(host); - } - - var all_nodes = this.model.nodes.concat(this.hosts); - - var all_nodes_map = new Array(); - - _.each(all_nodes, function(n) { - all_nodes_map[n.id] = n; - }); - - for (var i = 0; i < this.hosts.length; i++) { - host = this.hosts[i]; - for (var j = 0; j < host.attributes['attachmentPoint'].length; j++) { - var link = {source:all_nodes_map[host.id], - target:all_nodes_map[host.attributes['attachmentPoint'][j]['switchDPID']], - value:10}; - //console.log(link); - if ( link.source && link.target) { - this.host_links.push(link); - } else { - console.log("Error: skipping link with undefined stuff!") - } + + for (var i = 0; i < this.hosts.length; i++) { + host = this.hosts[i]; + if (host.attributes['ipv4'].length > 0) { + host.name = host.attributes['ipv4'][0] + "\n" + host.id; + } else { + host.name = host.id; + } + host.group = 2; + //console.log(host); } - } - - var all_links = this.model.links.concat(this.host_links); - - force.nodes(all_nodes).links(all_links).start(); - var link = svg.selectAll("line.link").data(all_links).enter() - .append("line").attr("class", "link") - .style("stroke", function (d) { return "black"; }); - var node = svg.selectAll("circle.node").data(all_nodes) - .enter().append("circle") - .attr("class", "node") - .attr("r", 20) - .style("fill", function(d) { return color(d.group); }) - .call(force.drag); - node.append("title").text(function(d) { return d.name; }); - force.on("tick", function() { - link.attr("x1", function(d) { return d.source.x; }) - .attr("y1", function(d) { return d.source.y; }) - .attr("x2", function(d) { return d.target.x; }) - .attr("y2", function(d) { return d.target.y; }); - - node.attr("cx", function(d) { return d.x; }) - .attr("cy", function(d) { return d.y; }); - }); + + var all_nodes = this.model.nodes.concat(this.hosts); + + var all_nodes_map = []; + + _.each(all_nodes, function(n) { + all_nodes_map[n.id] = n; + }); + + for (var i = 0; i < this.hosts.length; i++) { + host = this.hosts[i]; + //for (var j = 0; j < host.attributes['attachmentPoint'].length; j++) { + for (var j = 0; j < 1; j++) { // FIXME hack to ignore multiple APs + var link = {source:all_nodes_map[host.id], + target:all_nodes_map[host.attributes['attachmentPoint'][j]['switchDPID']], + value:10}; + //console.log(link); + if ( link.source && link.target) { + this.host_links.push(link); + } else { + console.log("Error: skipping link with undefined stuff!") + } + } + } + + var all_links = this.model.links.concat(this.host_links); + + force.nodes(all_nodes).links(all_links).start(); + var link = svg.selectAll("line.link").data(all_links).enter() + .append("line").attr("class", "link") + .style("stroke", function (d) { return "black"; }); + var node = svg.selectAll(".node").data(all_nodes) + .enter().append("g") + .attr("class", "node") + .call(force.drag); + + node.append("image") + .attr("xlink:href", function (d) {return d.group==1 ? "/ui/img/switch.png" : "/ui/img/server.png"}) + .attr("x", -16).attr("y", -16) + .attr("width", 32).attr("height", 32); + node.append("text").attr("dx", 20).attr("dy", ".35em") + .text(function(d) { return d.name }); + node.on("click", function (d) { + // TODO we could add some functionality here + console.log('clicked '+d.name); + }); + node.append("title").text(function(d) { return d.name; }); + force.on("tick", function() { + link.attr("x1", function(d) { return d.source.x; }) + .attr("y1", function(d) { return d.source.y; }) + .attr("x2", function(d) { return d.target.x; }) + .attr("y2", function(d) { return d.target.y; }); + node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); + + }); } return this; }