/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
//PAGE flows
one.f = {};
// specify dashlets and layouts
one.f.dashlet = {
flows : {
id : 'flows',
name : 'Flow Entries'
},
nodes : {
id : 'nodes',
name : 'Nodes'
},
detail : {
id : 'detail',
name : 'Flow Detail'
}
};
one.f.menu = {
left : {
top : [
one.f.dashlet.flows
],
bottom : [
one.f.dashlet.nodes
]
},
right : {
top : [],
bottom : [
one.f.dashlet.detail
]
}
};
one.f.address = {
root : "/controller/web/flows",
flows : {
main : "/main",
flows : "/node-flows",
nodes : "/node-ports",
flow : "/flow",
deleteFlows:"/flow/deleteFlows"
}
}
/** NODES **/
one.f.nodes = {
id : {
dashlet: {
datagrid: "one_f_nodes_id_dashlet_datagrid"
}
},
registry : {},
dashlet : function($dashlet) {
var $h4 = one.lib.dashlet.header("Nodes");
$dashlet.append($h4);
one.f.nodes.ajax.dashlet(function(data) {
var $gridHTML = one.lib.dashlet.datagrid.init(one.f.nodes.id.dashlet.datagrid, {
searchable: true,
filterable: false,
pagination: true,
flexibleRowsPerPage: true
}, "table-striped table-condensed");
$dashlet.append($gridHTML);
var dataSource = one.f.nodes.data.nodesDataGrid(data);
$("#" + one.f.nodes.id.dashlet.datagrid).datagrid({dataSource: dataSource});
});
},
ajax : {
dashlet : function(callback) {
$.getJSON(one.f.address.root+one.f.address.flows.flows, function(data) {
callback(data);
});
}
},
data : {
nodesDataGrid: function(data) {
var gridData = [];
$.each(data, function(nodeName, flow) {
var nodeFlowObject = {};
nodeFlowObject["nodeName"] = nodeName;
nodeFlowObject["flows"] = flow;
nodeFlowObject["rowData"] = nodeName + flow + "-foobar";
gridData.push(nodeFlowObject);
});
var source = new StaticDataSource({
columns: [
{
property: 'nodeName',
label: 'Node',
sortable: true
},
{
property: 'flows',
label: 'Flows',
sortable: true
}
],
data: gridData,
delay: 0
});
return source;
}
},
body : {
dashlet : function(body, callback) {
var attributes = ['table-striped', 'table-bordered', 'table-hover', 'table-condensed'];
var $table = one.lib.dashlet.table.table(attributes);
var headers = ['Node', 'Flows'];
var $thead = one.lib.dashlet.table.header(headers);
$table.append($thead);
var $tbody = one.lib.dashlet.table.body(body);
$table.append($tbody);
return $table;
}
}
}
/** FLOW DETAIL **/
one.f.detail = {
id : {},
registry : {},
dashlet : function($dashlet, details) {
var $h4 = one.lib.dashlet.header("Flow Details");
$dashlet.append($h4);
// details
if (details == undefined) {
var $none = $(document.createElement('div'));
$none.addClass('none');
var $p = $(document.createElement('p'));
$p.text('Please select a flow');
$p.addClass('text-center').addClass('text-info');
$dashlet.append($none)
.append($p);
}
},
data : {
dashlet : function(data) {
var body = [];
var tr = {};
var entry = [];
entry.push(data['name']);
entry.push(data['node']);
entry.push(data['flow']['priority']);
entry.push(data['flow']['hardTimeout']);
entry.push(data['flow']['idleTimeout']);
tr.entry = entry;
body.push(tr);
return body;
},
description : function(data) {
var body = [];
var tr = {};
var entry = [];
entry.push(data['flow']['ingressPort']);
entry.push(data['flow']['etherType']);
entry.push(data['flow']['vlanId']);
entry.push(data['flow']['vlanPriority']);
entry.push(data['flow']['srcMac']);
entry.push(data['flow']['dstMac']);
entry.push(data['flow']['srcIp']);
entry.push(data['flow']['dstIp']);
entry.push(data['flow']['tosBits']);
entry.push(data['flow']['srcPort']);
entry.push(data['flow']['dstPort']);
entry.push(data['flow']['protocol']);
entry.push(data['flow']['cookie']);
tr.entry = entry;
body.push(tr);
return body;
},
actions : function(data) {
var body = [];
var tr = {};
var entry = [];
var actions = '';
$(data['flow']['actions']).each(function(index, value) {
actions += value + ', ';
});
actions = actions.slice(0,-2);
entry.push(actions);
tr.entry = entry;
body.push(tr);
return body;
}
},
body : {
dashlet : function(body) {
// create table
var header = ['Flow Name', 'Node', 'Priority', 'Hard Timeout', 'Idle Timeout'];
var $thead = one.lib.dashlet.table.header(header);
var attributes = ['table-striped', 'table-bordered', 'table-condensed'];
var $table = one.lib.dashlet.table.table(attributes);
$table.append($thead);
var $tbody = one.lib.dashlet.table.body(body);
$table.append($tbody);
return $table;
},
description : function(body) {
var header = ['Input Port', 'Ethernet Type', 'VLAN ID', 'VLAN Priority', 'Source MAC', 'Dest MAC', 'Source IP', 'Dest IP', 'TOS', 'Source Port', 'Dest Port', 'Protocol', 'Cookie'];
var $thead = one.lib.dashlet.table.header(header);
var attributes = ['table-striped', 'table-bordered', 'table-condensed'];
var $table = one.lib.dashlet.table.table(attributes);
$table.append($thead);
var $tbody = one.lib.dashlet.table.body(body);
$table.append($tbody);
return $table;
},
actions : function(body) {
var header = ['Actions'];
var $thead = one.lib.dashlet.table.header(header);
var attributes = ['table-striped', 'table-bordered', 'table-condensed'];
var $table = one.lib.dashlet.table.table(attributes);
$table.append($thead);
var $tbody = one.lib.dashlet.table.body(body);
$table.append($tbody);
return $table;
}
}
}
/** FLOW ENTRIES **/
one.f.flows = {
id : {
dashlet : {
add : "one_f_flows_id_dashlet_add",
removeMultiple : "one_f_flows_id_dashlet_removeMultiple",
remove : "one_f_flows_id_dashlet_remove",
toggle : "one_f_flows_id_dashlet_toggle",
datagrid : "one_f_flows_id_dashlet_datagrid",
selectAllFlows : "one_f_flows_id_dashlet_selectAllFlows"
},
modal : {
install : "one_f_flows_id_modal_install",
add : "one_f_flows_id_modal_add",
close : "one_f_flows_id_modal_close",
modal : "one_f_flows_id_modal_modal",
dialog : {
modal : "one_f_flows_id_modal_dialog_modal",
remove : "one_f_flows_id_modal_dialog_remove",
close : "one_f_flows_id_modal_dialog_close"
},
action : {
button : "one_f_flows_id_modal_action_button",
modal : "one_f_flows_id_modal_action_modal",
add : "one_f_flows_id_modal_action_add",
close : "one_f_flows_id_modal_action_close",
table : "one_f_flows_id_modal_action_table",
addOutputPorts : "one_f_flows_id_modal_action_addOutputPorts",
setVlanId : "one_f_flows_id_modal_action_setVlanId",
setVlanPriority : "one_f_flows_id_modal_action_setVlanPriority",
modifyDatalayerSourceAddress : "one_f_flows_id_modal_action_modifyDatalayerSourceAddress",
modifyDatalayerDestinationAddress : "one_f_flows_id_modal_action_modifyDatalayerDestinationAddress",
modifyNetworkSourceAddress : "one_f_flows_modal_action_modifyNetworkSourceAddress",
modifyNetworkDestinationAddress : "one_f_flows_modal_action_modifyNetworkDestinationAddress",
modifyTosBits : "one_f_flows_modal_action_modifyTosBits",
modifyTransportSourcePort : "one_f_flows_modal_action_modifyTransportSourcePort",
modifyTransportDestinationPort : "one_f_flows_modal_action_modifyTransportDestinationPort",
modal : {
modal : "one_f_flows_modal_action_modal_modal",
remove : "one_f_flows_modal_action_modal_remove",
cancel : "one_f_flows_modal_action_modal_cancel"
}
},
form : {
name : "one_f_flows_id_modal_form_name",
nodes : "one_f_flows_id_modal_form_nodes",
port : "one_f_flows_id_modal_form_port",
priority : "one_f_flows_id_modal_form_priority",
hardTimeout : "one_f_flows_id_modal_form_hardTimeout",
idleTimeout : "one_f_flows_id_modal_form_idleTimeout",
cookie : "one_f_flows_id_modal_form_cookie",
etherType : "one_f_flows_id_modal_form_etherType",
vlanId : "one_f_flows_id_modal_form_vlanId",
vlanPriority : "one_f_flows_id_modal_form_vlanPriority",
srcMac : "one_f_flows_id_modal_form_srcMac",
dstMac : "one_f_flows_id_modal_form_dstMac",
srcIp : "one_f_flows_id_modal_form_srcIp",
dstIp : "one_f_flows_id_modal_form_dstIp",
tosBits : "one_f_flows_id_modal_form_tosBits",
srcPort : "one_f_flows_id_modal_form_srcPort",
dstPort : "one_f_flows_id_modal_form_dstPort",
protocol : "one_f_flows_id_modal_form_protocol"
}
}
},
registry : {},
dashlet : function($dashlet, callback) {
// load body
one.f.flows.ajax.dashlet(function(data) {
var $h4 = one.lib.dashlet.header("Flow Entries");
$dashlet.append($h4);
if (one.f.flows.registry.privilege === 'WRITE') {
var button = one.lib.dashlet.button.single("Add Flow Entry", one.f.flows.id.dashlet.add, "btn-primary", "btn-mini");
var $button = one.lib.dashlet.button.button(button);
$button.click(function() {
var $modal = one.f.flows.modal.initialize();
$modal.modal();
});
$dashlet.append($button);
var button = one.lib.dashlet.button.single("Remove Flow Entry", one.f.flows.id.dashlet.removeMultiple, "btn-danger", "btn-mini");
var $button = one.lib.dashlet.button.button(button);
$button.click(function() {
var checkedCheckBoxes = $('.flowEntry[type=checkbox]:checked');
if (checkedCheckBoxes.size() === 0) {
alert('Please select at least one flow');
return false;
}
var requestData = [];
var resource = {};
checkedCheckBoxes.each(function(index, value) {
var flowEntry = {};
flowEntry['name'] = checkedCheckBoxes[index].name;
flowEntry['node'] = checkedCheckBoxes[index].getAttribute("node");
requestData.push(flowEntry);
});
resource['body'] = JSON.stringify(requestData);
$.post(one.f.address.root+one.f.address.flows.deleteFlows, resource, function(response) {
if(response == "Success") {
one.lib.alert("Flow(s) successfully removed");
} else {
one.lib.alert(response);
}
one.main.dashlet.right.bottom.empty();
one.f.detail.dashlet(one.main.dashlet.right.bottom);
one.main.dashlet.left.top.empty();
one.f.flows.dashlet(one.main.dashlet.left.top);
});
});
$dashlet.append($button);
}
var $gridHTML = one.lib.dashlet.datagrid.init(one.f.flows.id.dashlet.datagrid, {
searchable: true,
filterable: false,
pagination: true,
flexibleRowsPerPage: true
}, "table-striped table-condensed");
$dashlet.append($gridHTML);
var dataSource = one.f.flows.data.flowsDataGrid(data);
$("#" + one.f.flows.id.dashlet.datagrid).datagrid({dataSource: dataSource}).on("loaded", function() {
$("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows).click(function() {
$("#" + one.f.flows.id.dashlet.datagrid).find(':checkbox').prop('checked',
$("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows).is(':checked'));
});
$("#" + one.f.flows.id.dashlet.datagrid).find("tbody tr").each(function(index, tr) {
$tr = $(tr);
$span = $("td span", $tr);
var flowstatus = $span.data("flowstatus");
if($span.data("installinhw") != null) {
var installInHw = $span.data("installinhw").toString();
if(installInHw == "true" && flowstatus == "Success") {
$tr.addClass("success");
} else {
$tr.addClass("warning");
}
}
// attach mouseover to show pointer cursor
$tr.mouseover(function() {
$(this).css("cursor", "pointer");
});
// attach click event
$tr.click(function() {
var $td = $($(this).find("td")[1]);
var id = $td.text();
var node = $td.find("span").data("nodeid");
one.f.flows.detail(id, node);
});
$(".flowEntry").click(function(e){
if (!$('.flowEntry[type=checkbox]:not(:checked)').length) {
$("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows)
.prop("checked",
true);
} else {
$("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows)
.prop("checked",
false);
}
e.stopPropagation();
});
});
});
// details callback
if(callback != undefined) callback();
});
},
detail : function(id, node) {
// clear flow details
var $detailDashlet = one.main.dashlet.right.bottom;
$detailDashlet.empty();
var $h4 = one.lib.dashlet.header("Flow Overview");
$detailDashlet.append($h4);
// details
var flows = one.f.flows.registry.flows;
var flow;
$(flows).each(function(index, value) {
if (value['name'] == id) {
flow = value;
}
});
if (one.f.flows.registry.privilege === 'WRITE') {
// remove button
var button = one.lib.dashlet.button.single("Remove Flow", one.f.flows.id.dashlet.remove, "btn-danger", "btn-mini");
var $button = one.lib.dashlet.button.button(button);
$button.click(function() {
var $modal = one.f.flows.modal.dialog.initialize(id, node);
$modal.modal();
});
// toggle button
var toggle;
if (flow['flow']['installInHw'] == 'true' && flow['flow']['status'] == 'Success') {
toggle = one.lib.dashlet.button.single("Uninstall Flow", one.f.flows.id.dashlet.toggle, "btn-warning", "btn-mini");
} else {
toggle = one.lib.dashlet.button.single("Install Flow", one.f.flows.id.dashlet.toggle, "btn-success", "btn-mini");
}
var $toggle = one.lib.dashlet.button.button(toggle);
$toggle.click(function() {
one.f.flows.modal.ajax.toggleflow(id, node, function(data) {
if(data == "Success") {
one.main.dashlet.right.bottom.empty();
one.f.detail.dashlet(one.main.dashlet.right.bottom);
one.main.dashlet.left.top.empty();
one.f.flows.dashlet(one.main.dashlet.left.top, function() {
// checks are backwards due to stale registry
if(flow['flow']['installInHw'] == 'true') {
one.lib.alert('Uninstalled Flow');
} else {
one.lib.alert('Installed Flow');
}
one.f.flows.detail(id, node)
});
} else {
one.lib.alert('Cannot toggle flow: '+data);
}
});
});
$detailDashlet.append($button).append($toggle);
}
// append details
var body = one.f.detail.data.dashlet(flow);
var $body = one.f.detail.body.dashlet(body);
$detailDashlet.append($body);
var body = one.f.detail.data.description(flow);
var $body = one.f.detail.body.description(body);
$detailDashlet.append($body);
var body = one.f.detail.data.actions(flow);
var $body = one.f.detail.body.actions(body);
$detailDashlet.append($body);
},
modal : {
dialog : {
initialize : function(id, node) {
var h3 = "Remove Flow?";
var $p = one.f.flows.modal.dialog.body(id);
var footer = one.f.flows.modal.dialog.footer();
var $modal = one.lib.modal.spawn(one.f.flows.id.modal.dialog.modal, h3, $p, footer);
$('#'+one.f.flows.id.modal.dialog.close, $modal).click(function() {
$modal.modal('hide');
});
$('#'+one.f.flows.id.modal.dialog.remove, $modal).click(function() {
one.f.flows.modal.ajax.removeflow(id, node, function(data) {
if (data == "Success") {
$modal.modal('hide');
one.main.dashlet.right.bottom.empty();
one.f.detail.dashlet(one.main.dashlet.right.bottom);
one.main.dashlet.left.top.empty();
one.f.flows.dashlet(one.main.dashlet.left.top);
one.lib.alert('Flow removed');
} else {
one.lib.alert('Cannot remove flow: '+data);
}
});
});
return $modal;
},
footer : function() {
var footer = [];
var removeButton = one.lib.dashlet.button.single("Remove Flow", one.f.flows.id.modal.dialog.remove, "btn-danger", "");
var $removeButton = one.lib.dashlet.button.button(removeButton);
footer.push($removeButton);
var closeButton = one.lib.dashlet.button.single("Cancel", one.f.flows.id.modal.dialog.close, "", "");
var $closeButton = one.lib.dashlet.button.button(closeButton);
footer.push($closeButton);
return footer;
},
body : function(id) {
var $p = $(document.createElement('p'));
$p.append('Remove flow '+id+'?');
return $p;
}
},
initialize : function() {
var h3 = "Add Flow Entry";
var footer = one.f.flows.modal.footer();
var $modal = one.lib.modal.spawn(one.f.flows.id.modal.modal, h3, "", footer);
// bind close button
$('#'+one.f.flows.id.modal.close, $modal).click(function() {
$modal.modal('hide');
});
// bind add flow button
$('#'+one.f.flows.id.modal.add, $modal).click(function() {
one.f.flows.modal.add($modal, 'false');
});
// bind install flow button
$('#'+one.f.flows.id.modal.install, $modal).click(function() {
one.f.flows.modal.add($modal, 'true');
});
// inject body (nodePorts)
one.f.flows.modal.ajax.nodes(function(nodes, nodeports) {
var $body = one.f.flows.modal.body(nodes, nodeports);
one.lib.modal.inject.body($modal, $body);
});
return $modal;
},
add : function($modal, install) {
var result = {};
result['name'] = $('#'+one.f.flows.id.modal.form.name, $modal).val();
result['ingressPort'] = $('#'+one.f.flows.id.modal.form.port, $modal).val();
result['priority'] = $('#'+one.f.flows.id.modal.form.priority, $modal).val();
result['hardTimeout'] = $('#'+one.f.flows.id.modal.form.hardTimeout, $modal).val();
result['idleTimeout'] = $('#'+one.f.flows.id.modal.form.idleTimeout, $modal).val();
result['cookie'] = $('#'+one.f.flows.id.modal.form.cookie, $modal).val();
result['etherType'] = $('#'+one.f.flows.id.modal.form.etherType, $modal).val();
result['vlanId'] = $('#'+one.f.flows.id.modal.form.vlanId, $modal).val();
result['vlanPriority'] = $('#'+one.f.flows.id.modal.form.vlanPriority, $modal).val();
result['dlSrc'] = $('#'+one.f.flows.id.modal.form.srcMac, $modal).val();
result['dlDst'] = $('#'+one.f.flows.id.modal.form.dstMac, $modal).val();
result['nwSrc'] = $('#'+one.f.flows.id.modal.form.srcIp, $modal).val();
result['nwDst'] = $('#'+one.f.flows.id.modal.form.dstIp, $modal).val();
result['tosBits'] = $('#'+one.f.flows.id.modal.form.tosBits, $modal).val();
result['tpSrc'] = $('#'+one.f.flows.id.modal.form.srcPort, $modal).val();
result['tpDst'] = $('#'+one.f.flows.id.modal.form.dstPort, $modal).val();
result['protocol'] = $('#'+one.f.flows.id.modal.form.protocol, $modal).val();
result['installInHw'] = install;
var nodeId = $('#'+one.f.flows.id.modal.form.nodes, $modal).val();
$.each(result, function(key, value) {
if (value == "") delete result[key];
});
var action = [];
var $table = $('#'+one.f.flows.id.modal.action.table, $modal);
$($table.find('tbody').find('tr')).each(function(index, value) {
if (!$(this).find('td').hasClass('empty')) {
action.push($(value).data('action'));
}
});
result['actions'] = action;
// frontend validation
if (result['name'] == undefined) {
alert('Need flow name');
return;
}
if (nodeId == '') {
alert('Select node');
return;
}
if (action.length == 0) {
alert('Please specify an action');
return;
}
// package for ajax call
var resource = {};
resource['body'] = JSON.stringify(result);
resource['action'] = 'add';
resource['nodeId'] = nodeId;
one.f.flows.modal.ajax.saveflow(resource, function(data) {
if (data == "Success") {
$modal.modal('hide');
one.lib.alert('Flow added');
one.main.dashlet.left.top.empty();
one.f.flows.dashlet(one.main.dashlet.left.top);
} else {
alert('Could not add flow: '+data);
}
});
},
ajax : {
nodes : function(successCallback) {
$.getJSON(one.f.address.root+one.f.address.flows.nodes, function(data) {
var nodes = one.f.flows.modal.data.nodes(data);
var nodeports = data;
one.f.flows.registry['nodeports'] = nodeports;
successCallback(nodes, nodeports);
});
},
saveflow : function(resource, callback) {
$.post(one.f.address.root+one.f.address.flows.flow, resource, function(data) {
callback(data);
});
},
removeflow : function(id, node, callback) {
resource = {};
resource['action'] = 'remove';
$.post(one.f.address.root+one.f.address.flows.flow+'/'+node+'/'+id, resource, function(data) {
callback(data);
});
},
toggleflow : function(id, node, callback) {
resource = {};
resource['action'] = 'toggle';
$.post(one.f.address.root+one.f.address.flows.flow+'/'+node+'/'+id, resource, function(data) {
callback(data);
});
}
},
data : {
nodes : function(data) {
result = {};
$.each(data, function(key, value) {
result[key] = value['name'];
});
return result;
}
},
body : function(nodes, nodeports) {
var $form = $(document.createElement('form'));
var $fieldset = $(document.createElement('fieldset'));
// flow description
var $legend = one.lib.form.legend("Flow Description");
$fieldset.append($legend);
// name
var $label = one.lib.form.label("Name");
var $input = one.lib.form.input("Flow Name");
$input.attr('id', one.f.flows.id.modal.form.name);
$fieldset.append($label).append($input);
// node
var $label = one.lib.form.label("Node");
var $select = one.lib.form.select.create(nodes);
one.lib.form.select.prepend($select, { '' : 'Please Select a Node' });
$select.val($select.find("option:first").val());
$select.attr('id', one.f.flows.id.modal.form.nodes);
// bind onchange
$select.change(function() {
// retrieve port value
var node = $(this).find('option:selected').attr('value');
var $ports = $('#'+one.f.flows.id.modal.form.port);
if (node == '') {
one.lib.form.select.inject($ports, {});
return;
}
one.f.flows.registry['currentNode'] = node;
var ports = nodeports[node]['ports'];
one.lib.form.select.inject($ports, ports);
one.lib.form.select.prepend($ports, { '' : 'Please Select a Port' });
$ports.val($ports.find("option:first").val());
});
$fieldset.append($label).append($select);
// input port
var $label = one.lib.form.label("Input Port");
var $select = one.lib.form.select.create();
$select.attr('id', one.f.flows.id.modal.form.port);
$fieldset.append($label).append($select);
// priority
var $label = one.lib.form.label("Priority");
var $input = one.lib.form.input("Priority");
$input.attr('id', one.f.flows.id.modal.form.priority);
$input.val('500');
$fieldset.append($label).append($input);
// hardTimeout
var $label = one.lib.form.label("Hard Timeout");
var $input = one.lib.form.input("Hard Timeout");
$input.attr('id', one.f.flows.id.modal.form.hardTimeout);
$fieldset.append($label).append($input);
// idleTimeout
var $label = one.lib.form.label("Idle Timeout");
var $input = one.lib.form.input("Idle Timeout");
$input.attr('id', one.f.flows.id.modal.form.idleTimeout);
$fieldset.append($label).append($input);
// cookie
var $label = one.lib.form.label("Cookie");
var $input = one.lib.form.input("Cookie");
$input.attr('id', one.f.flows.id.modal.form.cookie);
$fieldset.append($label).append($input);
// layer 2
var $legend = one.lib.form.legend("Layer 2");
$fieldset.append($legend);
// etherType
var $label = one.lib.form.label("Ethernet Type");
var $input = one.lib.form.input("Ethernet Type");
$input.attr('id', one.f.flows.id.modal.form.etherType);
$input.val('0x800');
$fieldset.append($label).append($input);
// vlanId
var $label = one.lib.form.label("VLAN Identification Number");
var $input = one.lib.form.input("VLAN Identification Number");
$input.attr('id', one.f.flows.id.modal.form.vlanId);
var $help = one.lib.form.help("Range: 0 - 4095");
$fieldset.append($label).append($input).append($help);
// vlanPriority
var $label = one.lib.form.label("VLAN Priority");
var $input = one.lib.form.input("VLAN Priority");
$input.attr('id', one.f.flows.id.modal.form.vlanPriority);
var $help = one.lib.form.help("Range: 0 - 7");
$fieldset.append($label).append($input).append($help);
// srcMac
var $label = one.lib.form.label("Source MAC Address");
var $input = one.lib.form.input("Source MAC Address");
$input.attr('id', one.f.flows.id.modal.form.srcMac);
var $help = one.lib.form.help("Example: 00:11:22:aa:bb:cc");
$fieldset.append($label).append($input).append($help);
// dstMac
var $label = one.lib.form.label("Destination MAC Address");
var $input = one.lib.form.input("Destination MAC Address");
$input.attr('id', one.f.flows.id.modal.form.dstMac);
var $help = one.lib.form.help("Example: 00:11:22:aa:bb:cc");
$fieldset.append($label).append($input).append($help);
// layer 3
var $legend = one.lib.form.legend("Layer 3");
$fieldset.append($legend);
// srcIp
var $label = one.lib.form.label("Source IP Address");
var $input = one.lib.form.input("Source IP Address");
$input.attr('id', one.f.flows.id.modal.form.srcIp);
var $help = one.lib.form.help("Example: 127.0.0.1");
$fieldset.append($label).append($input).append($help);
// dstIp
var $label = one.lib.form.label("Destination IP Address");
var $input = one.lib.form.input("Destination IP Address");
$input.attr('id', one.f.flows.id.modal.form.dstIp);
var $help = one.lib.form.help("Example: 127.0.0.1");
$fieldset.append($label).append($input).append($help);
// tosBits
var $label = one.lib.form.label("TOS Bits");
var $input = one.lib.form.input("TOS Bits");
$input.attr('id', one.f.flows.id.modal.form.tosBits);
var $help = one.lib.form.help("Range: 0 - 63");
$fieldset.append($label).append($input).append($help);
// layer 4
var $legend = one.lib.form.legend("Layer 4");
$fieldset.append($legend);
// srcPort
var $label = one.lib.form.label("Source Port");
var $input = one.lib.form.input("Source Port");
$input.attr('id', one.f.flows.id.modal.form.srcPort);
var $help = one.lib.form.help("Range: 0 - 65535");
$fieldset.append($label).append($input).append($help);
// dstPort
var $label = one.lib.form.label("Destination Port");
var $input = one.lib.form.input("Destination Port");
$input.attr('id', one.f.flows.id.modal.form.dstPort);
var $help = one.lib.form.help("Range: 0 - 65535");
$fieldset.append($label).append($input).append($help);
// protocol
var $label = one.lib.form.label("Protocol");
var $input = one.lib.form.input("Protocol");
$input.attr('id', one.f.flows.id.modal.form.protocol);
$fieldset.append($label).append($input);
// actions
var $legend = one.lib.form.label("Actions");
$fieldset.append($legend);
// actions table
var tableAttributes = ["table-striped", "table-bordered", "table-condensed", "table-hover", "table-cursor"];
var $table = one.lib.dashlet.table.table(tableAttributes);
$table.attr('id', one.f.flows.id.modal.action.table);
var tableHeaders = ["Action", "Data", "Type"];
var $thead = one.lib.dashlet.table.header(tableHeaders);
var $tbody = one.lib.dashlet.table.body("", tableHeaders);
$table.append($thead).append($tbody);
// actions
var actions = {
"" : "Please Select an Action",
"drop" : "Drop",
"loopback" : "Loopback",
"flood" : "Flood",
"softwarePath" : "Software Path",
"hardwarePath" : "Hardware Path",
"controller" : "Controller",
"addOutputPorts" : "Add Output Ports",
"setVlanId" : "Set VLAN ID",
"setVlanPriority" : "Set VLAN Priority",
"stripVlanHeader" : "Strip VLAN Header",
"modifyDatalayerSourceAddress" : "Modify Datalayer Source Address",
"modifyDatalayerDestinationAddress" : "Modify Datalayer Destination Address",
"modifyNetworkSourceAddress" : "Modify Network Source Address",
"modifyNetworkDestinationAddress" :"Modify Network Destination Address",
"modifyTosBits" : "Modify TOS Bits",
"modifyTransportSourcePort" : "Modify Transport Source Port",
"modifyTransportDestinationPort" : "Modify Transport Destination Port"
};
var $select = one.lib.form.select.create(actions);
// when selecting an action
$select.change(function() {
var action = $(this).find('option:selected');
one.f.flows.modal.action.parse(action.attr('value'));
$select[0].selectedIndex = 0;
});
$fieldset.append($select).append($table);
// return
$form.append($fieldset);
return $form;
},
action : {
parse : function(option) {
switch (option) {
case "addOutputPorts" :
var h3 = "Add Output Port";
var $modal = one.f.flows.modal.action.initialize(h3, one.f.flows.modal.action.body.addOutputPorts, one.f.flows.modal.action.add.addOutputPorts);
$modal.modal();
break;
case "setVlanId" :
var h3 = "Set VLAN ID";
var placeholder = "VLAN Identification Number";
var id = one.f.flows.id.modal.action.setVlanId;
var help = "Range: 0 - 4095";
var action = 'SET_VLAN_ID';
var name = "VLAN ID";
var body = function() {
return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
};
var add = function($modal) {
one.f.flows.modal.action.add.set(name, id, action, $modal);
};
var $modal = one.f.flows.modal.action.initialize(h3, body, add);
$modal.modal();
break;
case "setVlanPriority" :
var h3 = "Set VLAN Priority";
var placeholder = "VLAN Priority";
var id = one.f.flows.id.modal.action.setVlanPriority;
var help = "Range: 0 - 7";
var action = 'SET_VLAN_PCP';
var name = "VLAN Priority";
var body = function() {
return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
};
var add = function($modal) {
one.f.flows.modal.action.add.set(name, id, action, $modal);
};
var $modal = one.f.flows.modal.action.initialize(h3, body, add);
$modal.modal();
break;
case "stripVlanHeader" :
var name = "Strip VLAN Header";
var action = 'POP_VLAN';
one.f.flows.modal.action.add.add(name, action);
break;
case "modifyDatalayerSourceAddress" :
var h3 = "Set Source MAC Address";
var placeholder = "Source MAC Address";
var id = one.f.flows.id.modal.action.modifyDatalayerSourceAddress;
var help = "Example: 00:11:22:aa:bb:cc";
var action = 'SET_DL_SRC';
var name = "Source MAC";
var body = function() {
return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
};
var add = function($modal) {
one.f.flows.modal.action.add.set(name, id, action, $modal);
};
var $modal = one.f.flows.modal.action.initialize(h3, body, add);
$modal.modal();
break;
case "modifyDatalayerDestinationAddress" :
var h3 = "Set Destination MAC Address";
var placeholder = "Destination MAC Address";
var id = one.f.flows.id.modal.action.modifyDatalayerDestinationAddress;
var help = "Example: 00:11:22:aa:bb:cc";
var action = 'SET_DL_DST';
var name = "Destination MAC";
var body = function() {
return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
};
var add = function($modal) {
one.f.flows.modal.action.add.set(name, id, action, $modal);
};
var $modal = one.f.flows.modal.action.initialize(h3, body, add);
$modal.modal();
break;
case "modifyNetworkSourceAddress" :
var h3 = "Set IP Source Address";
var placeholder = "Source IP Address";
var id = one.f.flows.id.modal.action.modifyNetworkSourceAddress;
var help = "Example: 127.0.0.1";
var action = 'SET_NW_SRC';
var name = "Source IP";
var body = function() {
return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
};
var add = function($modal) {
one.f.flows.modal.action.add.set(name, id, action, $modal);
};
var $modal = one.f.flows.modal.action.initialize(h3, body, add);
$modal.modal();
break;
case "modifyNetworkDestinationAddress" :
var h3 = "Set IP Destination Address";
var placeholder = "Destination IP Address";
var id = one.f.flows.id.modal.action.modifyNetworkDestinationAddress;
var help = "Example: 127.0.0.1";
var action = 'SET_NW_DST';
var name = "Destination IP";
var body = function() {
return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
};
var add = function($modal) {
one.f.flows.modal.action.add.set(name, id, action, $modal);
};
var $modal = one.f.flows.modal.action.initialize(h3, body, add);
$modal.modal();
break;
case "modifyTosBits" :
var h3 = "Set IPv4 ToS";
var placeholder = "IPv4 ToS";
var id = one.f.flows.id.modal.action.modifyTosBits;
var help = "Range: 0 - 63";
var action = 'SET_NW_TOS';
var name = "TOS Bits";
var body = function() {
return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
};
var add = function($modal) {
one.f.flows.modal.action.add.set(name, id, action, $modal);
};
var $modal = one.f.flows.modal.action.initialize(h3, body, add);
$modal.modal();
break;
case "modifyTransportSourcePort" :
var h3 = "Set Transport Source Port";
var placeholder = "Transport Source Port";
var id = one.f.flows.id.modal.action.modifyTransportSourcePort;
var help = "Range: 1 - 65535";
var action = 'SET_TP_SRC';
var name = "Source Port";
var body = function() {
return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
};
var add = function($modal) {
one.f.flows.modal.action.add.set(name, id, action, $modal);
};
var $modal = one.f.flows.modal.action.initialize(h3, body, add);
$modal.modal();
break;
case "modifyTransportDestinationPort" :
var h3 = "Set Transport Destination Port";
var placeholder = "Transport Destination Port";
var id = one.f.flows.id.modal.action.modifyTransportDestinationPort;
var help = "Range: 1 - 65535";
var action = 'SET_TP_DST';
var name = "Destination Port";
var body = function() {
return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
};
var add = function($modal) {
one.f.flows.modal.action.add.set(name, id, action, $modal);
};
var $modal = one.f.flows.modal.action.initialize(h3, body, add);
$modal.modal();
break;
case "drop" :
var name = "Drop";
var action = 'DROP';
one.f.flows.modal.action.add.add(name, action);
break;
case "loopback" :
var name = "Loopback";
var action = 'LOOPBACK';
one.f.flows.modal.action.add.add(name, action);
break;
case "flood" :
var name = "Flood";
var action = 'FLOOD';
one.f.flows.modal.action.add.add(name, action);
break;
case "softwarePath" :
var name = "Software Path";
var action = 'SW_PATH';
one.f.flows.modal.action.add.add(name, action);
break;
case "hardwarePath" :
var name = "Hardware Path";
var action = 'HW_PATH';
one.f.flows.modal.action.add.add(name, action);
break;
case "controller" :
var name = "Controller";
var action = 'CONTROLLER';
one.f.flows.modal.action.add.add(name, action);
break;
}
},
initialize : function(h3, bodyCallback, addCallback) {
var footer = one.f.flows.modal.action.footer();
var $body = bodyCallback();
var $modal = one.lib.modal.spawn(one.f.flows.id.modal.action.modal, h3, $body, footer);
// bind close button
$('#'+one.f.flows.id.modal.action.close, $modal).click(function() {
$modal.modal('hide');
});
// bind add flow button
$('#'+one.f.flows.id.modal.action.add, $modal).click(function() {
addCallback($modal);
});
return $modal;
},
add : {
addOutputPorts : function($modal) {
var $options = $('#'+one.f.flows.id.modal.action.addOutputPorts).find('option:selected');
var ports = '';
var pid = '';
$options.each(function(index, value) {
ports = ports+$(value).text()+", ";
pid = pid+$(value).attr('value')+",";
});
ports = ports.slice(0,-2);
pid = pid.slice(0,-1);
var $tr = one.f.flows.modal.action.table.add("Add Output Ports", ports);
$tr.attr('id', 'addOutputPorts');
$tr.data('action', 'OUTPUT='+pid);
$tr.click(function() {
one.f.flows.modal.action.add.modal.initialize(this);
});
one.f.flows.modal.action.table.append($tr);
$modal.modal('hide');
},
add : function(name, action) {
var $tr = one.f.flows.modal.action.table.add(name);
$tr.attr('id', action);
$tr.data('action', action);
$tr.click(function() {
one.f.flows.modal.action.add.modal.initialize(this);
});
one.f.flows.modal.action.table.append($tr);
},
set : function(name, id, action, $modal) {
var $input = $('#'+id);
var value = $input.val();
var $tr = one.f.flows.modal.action.table.add(name, value);
$tr.attr('id', action);
$tr.data('action', action+'='+value);
$tr.click(function() {
one.f.flows.modal.action.add.modal.initialize(this);
});
one.f.flows.modal.action.table.append($tr);
$modal.modal('hide');
},
remove : function(that) {
$(that).remove();
var $table = $('#'+one.f.flows.id.modal.action.table);
if ($table.find('tbody').find('tr').size() == 0) {
var $tr = $(document.createElement('tr'));
var $td = $(document.createElement('td'));
$td.attr('colspan', '3');
$tr.addClass('empty');
$td.text('No data available');
$tr.append($td);
$table.find('tbody').append($tr);
}
},
modal : {
initialize : function(that) {
var h3 = "Remove Action";
var footer = one.f.flows.modal.action.add.modal.footer();
var $body = one.f.flows.modal.action.add.modal.body();
var $modal = one.lib.modal.spawn(one.f.flows.id.modal.action.modal.modal, h3, $body, footer);
// bind cancel button
$('#'+one.f.flows.id.modal.action.modal.cancel, $modal).click(function() {
$modal.modal('hide');
});
// bind remove button
$('#'+one.f.flows.id.modal.action.modal.remove, $modal).click(function() {
one.f.flows.modal.action.add.remove(that);
$modal.modal('hide');
});
$modal.modal();
},
body : function() {
var $p = $(document.createElement('p'));
$p.append("Remove this action?");
return $p;
},
footer : function() {
var footer = [];
var removeButton = one.lib.dashlet.button.single("Remove Action", one.f.flows.id.modal.action.modal.remove, "btn-danger", "");
var $removeButton = one.lib.dashlet.button.button(removeButton);
footer.push($removeButton);
var cancelButton = one.lib.dashlet.button.single("Cancel", one.f.flows.id.modal.action.modal.cancel, "", "");
var $cancelButton = one.lib.dashlet.button.button(cancelButton);
footer.push($cancelButton);
return footer;
}
}
},
table : {
add : function(action, data, type) {
var $tr = $(document.createElement('tr'));
var $td = $(document.createElement('td'));
$td.append(action);
$tr.append($td);
var $td = $(document.createElement('td'));
if (data != undefined) $td.append(data);
$tr.append($td);
var $td = $(document.createElement('td'));
if (type != undefined) $td.append(type);
$tr.append($td);
return $tr;
},
append : function($tr) {
var $table = $('#'+one.f.flows.id.modal.action.table);
var $empty = $table.find('.empty').parent();
if ($empty.size() > 0) $empty.remove();
$table.append($tr);
}
},
body : {
common : function() {
var $form = $(document.createElement('form'));
var $fieldset = $(document.createElement('fieldset'));
return [$form, $fieldset];
},
addOutputPorts : function() {
var common = one.f.flows.modal.action.body.common();
var $form = common[0];
var $fieldset = common[1];
// output port
$label = one.lib.form.label("Select Output Ports");
var ports = one.f.flows.registry.nodeports[one.f.flows.registry.currentNode]['ports'];
$select = one.lib.form.select.create(ports, true);
$select.attr('id', one.f.flows.id.modal.action.addOutputPorts);
one.lib.form.select.prepend($select, {'':'Select a Port'});
$fieldset.append($label).append($select);
$form.append($fieldset);
return $form;
},
set : function(label, placeholder, id, help) {
var common = one.f.flows.modal.action.body.common();
var $form = common[0];
var $fieldset = common[1];
// input
$label = one.lib.form.label(label);
$input = one.lib.form.input(placeholder);
$input.attr('id', id);
$help = one.lib.form.help(help);
// append
$fieldset.append($label).append($input).append($help);
$form.append($fieldset);
return $form;
}
},
footer : function() {
var footer = [];
var addButton = one.lib.dashlet.button.single("Add Action", one.f.flows.id.modal.action.add, "btn-primary", "");
var $addButton = one.lib.dashlet.button.button(addButton);
footer.push($addButton);
var closeButton = one.lib.dashlet.button.single("Close", one.f.flows.id.modal.action.close, "", "");
var $closeButton = one.lib.dashlet.button.button(closeButton);
footer.push($closeButton);
return footer;
}
},
footer : function() {
var footer = [];
var installButton = one.lib.dashlet.button.single("Install Flow", one.f.flows.id.modal.install, "btn-success", "");
var $installButton = one.lib.dashlet.button.button(installButton);
footer.push($installButton);
var addButton = one.lib.dashlet.button.single("Save Flow", one.f.flows.id.modal.add, "btn-primary", "");
var $addButton = one.lib.dashlet.button.button(addButton);
footer.push($addButton);
var closeButton = one.lib.dashlet.button.single("Close", one.f.flows.id.modal.close, "", "");
var $closeButton = one.lib.dashlet.button.button(closeButton);
footer.push($closeButton);
return footer;
}
},
ajax : {
dashlet : function(callback) {
$.getJSON(one.f.address.root+one.f.address.flows.main, function(data) {
one.f.flows.registry['flows'] = data.flows;
one.f.flows.registry['privilege'] = data.privilege;
callback(data);
});
}
},
data : {
flowsDataGrid: function(data) {
var source = new StaticDataSource({
columns: [
{
property: 'selector',
label: "",
sortable: false
},
{
property: 'name',
label: 'Flow Name',
sortable: true
},
{
property: 'node',
label: 'Node',
sortable: true
}
],
data: data.flows,
formatter: function(items) {
$.each(items, function(index, item) {
var $checkbox = document.createElement("input");
$checkbox.setAttribute("type", "checkbox");
$checkbox.setAttribute("name", item.name);
$checkbox.setAttribute("node", item.node);
$checkbox.setAttribute('class','flowEntry')
item.selector = $checkbox.outerHTML;
item["name"] = '' + item["name"] + '';
});
},
delay: 0
});
return source;
},
dashlet : function(data) {
var body = [];
$(data).each(function(index, value) {
var tr = {};
var entry = [];
entry.push(value['name']);
entry.push(value['node']);
if (value['flow']['installInHw'] == 'true' && value['flow']['status'] == 'Success')
tr['type'] = ['success'];
else if (value['flow']['installInHw'] == 'false' && value['flow']['status'] == 'Success')
tr['type'] = ['warning'];
else
tr['type'] = ['warning'];
tr['entry'] = entry;
tr['id'] = value['nodeId'];
body.push(tr);
});
return body;
}
},
body : {
dashlet : function(body, callback) {
var attributes = ['table-striped', 'table-bordered', 'table-hover', 'table-condensed', 'table-cursor'];
var $table = one.lib.dashlet.table.table(attributes);
var headers = ['Flow Name', 'Node'];
var $thead = one.lib.dashlet.table.header(headers);
$table.append($thead);
var $tbody = one.lib.dashlet.table.body(body);
$table.append($tbody);
return $table;
}
}
}
/** INIT **/
// populate nav tabs
$(one.f.menu.left.top).each(function(index, value) {
var $nav = $(".nav", "#left-top");
one.main.page.dashlet($nav, value);
});
$(one.f.menu.left.bottom).each(function(index, value) {
var $nav = $(".nav", "#left-bottom");
one.main.page.dashlet($nav, value);
});
$(one.f.menu.right.bottom).each(function(index, value) {
var $nav = $(".nav", "#right-bottom");
one.main.page.dashlet($nav, value);
});
one.f.populate = function($dashlet, header) {
var $h4 = one.lib.dashlet.header(header);
$dashlet.append($h4);
};
// bind dashlet nav
$('.dash .nav a', '#main').click(function() {
// de/activation
var $li = $(this).parent();
var $ul = $li.parent();
one.lib.nav.unfocus($ul);
$li.addClass('active');
// clear respective dashlet
var $dashlet = $ul.parent().find('.dashlet');
one.lib.dashlet.empty($dashlet);
// callback based on menu
var id = $(this).attr('id');
var menu = one.f.dashlet;
switch (id) {
case menu.flows.id:
one.f.flows.dashlet($dashlet);
break;
case menu.nodes.id:
one.f.nodes.dashlet($dashlet);
break;
case menu.detail.id:
one.f.detail.dashlet($dashlet);
break;
};
});
// activate first tab on each dashlet
$('.dash .nav').each(function(index, value) {
$($(value).find('li')[0]).find('a').click();
});