Added webservices forwarding script for UI
diff --git a/web/js/views/flow.js b/web/js/views/flow.js
new file mode 100644
index 0000000..65e0b71
--- /dev/null
+++ b/web/js/views/flow.js
@@ -0,0 +1,69 @@
+/*
+ Copyright 2012 IBM
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+// not used for now
+window.FlowView = Backbone.View.extend({
+
+ initialize:function () {
+ this.template = _.template(tpl.get('flow'));
+ this.model.bind("change", this.render, this);
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template(this.model.toJSON()));
+ return this;
+ }
+
+});
+
+window.FlowListItemView = Backbone.View.extend({
+
+ tagName:"tr",
+
+ initialize:function () {
+ this.template = _.template(tpl.get('flow-list-item'));
+ this.model.bind("change", this.render, this);
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template(this.model.toJSON()));
+ return this;
+ }
+
+});
+
+// TODO throughput (bps) and pps sparklines would be nice here
+// TODO hovering over a MAC address could show a compact view of that host
+window.FlowListView = Backbone.View.extend({
+
+ initialize:function () {
+ this.template = _.template(tpl.get('flow-list'));
+ this.model.bind("change", this.render, this);
+ this.model.bind("add", this.render, this);
+ },
+
+ render:function (eventName) {
+ // console.log("rendering flow list view: " + this.model.models.length);
+ $(this.el).html(this.template({nflows:this.model.length}));
+ _.each(this.model.models, function (f) {
+ $(this.el).find('table.flow-table > tbody')
+ .append(new FlowListItemView({model:f}).render().el);
+ }, this);
+ return this;
+ },
+
+});
+
diff --git a/web/js/views/header.js b/web/js/views/header.js
new file mode 100644
index 0000000..65e49dd
--- /dev/null
+++ b/web/js/views/header.js
@@ -0,0 +1,49 @@
+/*
+ Copyright 2012 IBM
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+window.HeaderView = Backbone.View.extend({
+
+ initialize:function () {
+ this.template = _.template(tpl.get('header'));
+ // this.searchResults = new HostCollection();
+ // this.searchresultsView = new SearchListView({model:this.searchResults, className:'dropdown-menu'});
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template());
+ $('#live-updates', this.el).change(function () {
+ updating = $(this).is(':checked');
+ })
+ // $('.navbar-search', this.el).append(this.searchresultsView.render().el);
+ return this;
+ },
+
+ events:{
+ "keyup .search-query":"search"
+ },
+
+ search:function (event) {
+// var key = event.target.value;
+ var key = $('#searchText').val();
+ console.log('search ' + key);
+ // TODO search the host and switch lists
+ this.searchResults.findByName(key);
+ setTimeout(function () {
+ $('#searchForm').addClass('open');
+ });
+ }
+
+});
\ No newline at end of file
diff --git a/web/js/views/home.js b/web/js/views/home.js
new file mode 100644
index 0000000..0283002
--- /dev/null
+++ b/web/js/views/home.js
@@ -0,0 +1,41 @@
+/*
+ Copyright 2012 IBM
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+window.HomeView = Backbone.View.extend({
+
+ initialize:function () {
+ // console.log('Initializing Home View');
+ this.template = _.template(tpl.get('home'));
+ },
+
+ events:{
+ "click #showMeBtn":"showMeBtnClick"
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template());
+ var stats = new Status();
+ $(this.el).find('#controller-status').html(new StatusView({model:stats}).render().el);
+ $(this.el).find('#switch-list').html(new SwitchListView({model:swl}).render().el);
+ $(this.el).find('#host-list').html(new HostListView({model:hl}).render().el);
+ return this;
+ },
+
+ showMeBtnClick:function () {
+ app.headerView.search();
+ }
+
+});
\ No newline at end of file
diff --git a/web/js/views/host.js b/web/js/views/host.js
new file mode 100644
index 0000000..705703a
--- /dev/null
+++ b/web/js/views/host.js
@@ -0,0 +1,67 @@
+/*
+ Copyright 2012 IBM
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+window.HostView = Backbone.View.extend({
+
+ initialize:function () {
+ this.template = _.template(tpl.get('host'));
+ this.model.bind("change", this.render, this);
+ this.model.bind("add", this.render, this);
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template(this.model.toJSON()));
+ return this;
+ }
+
+});
+
+window.HostListView = Backbone.View.extend({
+
+ initialize:function () {
+ var self = this;
+ this.template = _.template(tpl.get('host-list'));
+ this.model.bind("change", this.render, this);
+ this.model.bind("add", this.render, this);
+ this.model.bind("remove", this.render, this);
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template({nhosts:hl.length}));
+ _.each(this.model.models, function (h) {
+ $(this.el).find('table.host-table > tbody')
+ .append(new HostListItemView({model:h}).render().el);
+ }, this);
+ return this;
+ }
+});
+
+window.HostListItemView = Backbone.View.extend({
+
+ tagName:"tr",
+
+ initialize:function () {
+ this.template = _.template(tpl.get('host-list-item'));
+ this.model.bind("change", this.render, this);
+ this.model.bind("destroy", this.close, this);
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template(this.model.toJSON()));
+ return this;
+ }
+
+});
\ No newline at end of file
diff --git a/web/js/views/port.js b/web/js/views/port.js
new file mode 100644
index 0000000..e9aadb9
--- /dev/null
+++ b/web/js/views/port.js
@@ -0,0 +1,70 @@
+/*
+ Copyright 2012 IBM
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+// not used for now
+window.PortView = Backbone.View.extend({
+
+ initialize:function () {
+ this.template = _.template(tpl.get('port'));
+ this.model.bind("change", this.render, this);
+ //this.model.bind("destroy", this.close, this);
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template(this.model.toJSON()));
+ return this;
+ }
+
+});
+
+window.PortListItemView = Backbone.View.extend({
+
+ tagName:"tr",
+
+ initialize:function () {
+ this.template = _.template(tpl.get('port-list-item'));
+ this.model.bind("change", this.render, this);
+ //this.model.bind("destroy", this.close, this);
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template(this.model.toJSON()));
+ return this;
+ }
+
+});
+
+// TODO throughput sparklines would be nice here
+window.PortListView = Backbone.View.extend({
+
+ initialize:function () {
+ this.template = _.template(tpl.get('port-list'));
+ this.model.bind("change", this.render, this);
+ this.model.bind("add", this.render, this);
+ },
+
+ render:function (eventName) {
+ // console.log("rendering port list view");
+ $(this.el).html(this.template({nports:this.model.length}));
+ _.each(this.model.models, function (p) {
+ $(this.el).find('table.port-table > tbody')
+ .append(new PortListItemView({model:p}).render().el);
+ }, this);
+ return this;
+ },
+
+});
+
diff --git a/web/js/views/status.js b/web/js/views/status.js
new file mode 100644
index 0000000..52c6c1c
--- /dev/null
+++ b/web/js/views/status.js
@@ -0,0 +1,30 @@
+/*
+ Copyright 2012 IBM
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+window.StatusView = Backbone.View.extend({
+
+ initialize:function () {
+ this.template = _.template(tpl.get('status'));
+ this.model.bind("change", this.render, this);
+ },
+
+ render:function (eventName) {
+ // console.log("rendering status");
+ $(this.el).html(this.template(this.model.toJSON()));
+ //$(this.el).html(this.template());
+ return this;
+ }
+});
\ No newline at end of file
diff --git a/web/js/views/switch.js b/web/js/views/switch.js
new file mode 100644
index 0000000..d457633
--- /dev/null
+++ b/web/js/views/switch.js
@@ -0,0 +1,73 @@
+/*
+ Copyright 2012 IBM
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+window.SwitchView = Backbone.View.extend({
+
+ initialize:function () {
+ this.template = _.template(tpl.get('switch'));
+ this.model.bind("change", this.render, this);
+ //this.model.bind("destroy", this.close, this);
+
+ // some parts of the model are large and are only needed in detail view
+ this.model.loadPorts();
+ this.model.loadFlows();
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template(this.model.toJSON()));
+ $(this.el).find('#port-list').html(new PortListView({model:this.model.ports}).render().el);
+ $(this.el).find('#flow-list').html(new FlowListView({model:this.model.flows}).render().el);
+ return this;
+ }
+
+});
+
+window.SwitchListItemView = Backbone.View.extend({
+
+ tagName:"tr",
+
+ initialize:function () {
+ this.template = _.template(tpl.get('switch-list-item'));
+ this.model.bind("change", this.render, this);
+ //this.model.bind("destroy", this.close, this);
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template(this.model.toJSON()));
+ return this;
+ }
+
+});
+
+window.SwitchListView = Backbone.View.extend({
+
+ initialize:function () {
+ this.template = _.template(tpl.get('switch-list'));
+ this.model.bind("change", this.render, this);
+ this.model.bind("remove", this.render, this);
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template({nswitches:swl.length}));
+ _.each(this.model.models, function (sw) {
+ $(this.el).find('table.switch-table > tbody')
+ .append(new SwitchListItemView({model:sw}).render().el);
+ }, this);
+ return this;
+ },
+
+});
+
diff --git a/web/js/views/topology.js b/web/js/views/topology.js
new file mode 100644
index 0000000..77129aa
--- /dev/null
+++ b/web/js/views/topology.js
@@ -0,0 +1,111 @@
+/*
+ Copyright 2012 IBM
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+window.TopologyView = Backbone.View.extend({
+ initialize:function () {
+ this.template = _.template(tpl.get('topology'));
+ this.model.bind("change", this.render, this);
+ this.hosts = this.options.hosts.models;
+ this.host_links = [];
+ },
+
+ render:function (eventName) {
+ $(this.el).html(this.template());
+ var width = 900,
+ height = 600;
+ var color = d3.scale.category20();
+ var force = d3.layout.force()
+ .charge(-500)
+ .linkDistance(200)
+ .size([width, height]);
+ var svg = d3.select("#topology-graph").append("svg")
+ .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;
+ }
+ host.group = 2;
+ //console.log(host);
+ }
+
+ 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;
+ }
+});