omf_web 0.9.6 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +168 -13
- data/bin/omf-web-basic +3 -3
- data/doc/index.md +205 -0
- data/example/NOT_WORKING/brooklyn/brooklyn_server.rb +2 -2
- data/example/NOT_WORKING/frisbee/data_sources/parse_log.rb +1 -1
- data/example/NOT_WORKING/frisbee/viz_server.rb +1 -1
- data/example/NOT_WORKING/gec12/gec12_demo_server.rb +1 -1
- data/example/NOT_WORKING/gec12/visualization.rb +2 -2
- data/example/NOT_WORKING/network/network_server.rb +2 -2
- data/example/NOT_WORKING/wimax/test.rb +2 -2
- data/example/NOT_WORKING/wimax/viz_server.rb +2 -2
- data/example/bridge/auth_basic.rb +75 -0
- data/example/bridge/config.ru +101 -0
- data/example/bridge/configure/configure_widget.rb +32 -0
- data/example/bridge/data_sources/sensor-sqlite.rb +28 -6
- data/example/bridge/data_sources/test31.sq3 +0 -0
- data/example/bridge/htdocs/{js/graph → graph/js}/bridge.js +2 -2
- data/example/bridge/htdocs/{js/graph → graph/js}/event_line_chart.js +7 -6
- data/example/bridge/htdocs/{js/graph → graph/js}/event_table.js +13 -5
- data/example/bridge/htdocs/template/login.html +23 -0
- data/example/bridge/viz_server.rb +3 -5
- data/example/bridge/widgets/configure.yaml +12 -0
- data/example/bridge/widgets/login.yaml +16 -0
- data/example/bridge/{overview.yaml → widgets/overview.yaml} +7 -4
- data/example/demo/data_sources/animals.rb +1 -1
- data/example/demo/data_sources/downloads.rb +1 -1
- data/example/demo/data_sources/generator.rb +1 -1
- data/example/demo/data_sources/histogram.rb +1 -1
- data/example/demo/data_sources/mobile_network.rb +4 -3
- data/example/demo/data_sources/movies.rb +1 -1
- data/example/demo/data_sources/network.rb +4 -3
- data/example/demo/data_sources/returns.rb +1 -1
- data/example/demo/data_sources/static_network.rb +4 -3
- data/example/demo/data_sources/walk.rb +1 -1
- data/example/demo/demo_viz_server.rb +1 -1
- data/example/demo/widgets/linked_graphs_tab.yaml +1 -1
- data/example/openflow-gec15/README.md +21 -0
- data/example/openflow-gec15/code_tab.yaml +36 -0
- data/example/openflow-gec15/dashboard_tab.yaml +72 -0
- data/example/openflow-gec15/doc/screenshot.png +0 -0
- data/example/openflow-gec15/exp_source.rb +104 -0
- data/example/openflow-gec15/of_viz_server.rb +63 -0
- data/example/openflow-gec15/openflow-demo.sq3 +0 -0
- data/example/openflow-gec15/raw_tab.yaml +37 -0
- data/example/openflow-gec15/repository/of-exp.rb +12 -0
- data/example/openflow-gec15/repository/sample.md +52 -0
- data/example/openflow-gec15/repository/trema-ctl6.rb +148 -0
- data/example/simple/README.md +2 -0
- data/example/simple/data_sources/gimi31.sq3 +0 -0
- data/example/simple/data_sources/ping_source.rb +56 -0
- data/example/simple/simple_viz_server.rb +39 -0
- data/example/simple/widgets/charts_tab.yaml +38 -0
- data/lib/omf-web/config.ru +31 -3
- data/lib/omf-web/data_source_proxy.rb +29 -26
- data/lib/omf-web/rack/session_authenticator.rb +93 -0
- data/lib/omf-web/rack/tab_mapper.rb +10 -5
- data/lib/omf-web/rack/websocket_handler.rb +17 -6
- data/lib/omf-web/theme/abstract_page.rb +1 -1
- data/lib/omf-web/theme/bright/flow_renderer.rb +2 -2
- data/lib/omf-web/theme/bright/layout_renderer.rb +15 -0
- data/lib/omf-web/theme/bright/mustache_renderer.rb +29 -0
- data/lib/omf-web/theme/bright/one_column_renderer.rb +2 -2
- data/lib/omf-web/theme/bright/page.rb +33 -8
- data/lib/omf-web/theme/bright/tabbed_renderer.rb +2 -3
- data/lib/omf-web/theme/bright/two_columns_renderer.rb +3 -4
- data/lib/omf-web/version.rb +1 -1
- data/lib/omf-web/widget/code_widget.rb +0 -7
- data/lib/omf-web/widget/layout/two_columns_layout.rb +3 -2
- data/lib/omf-web/widget/mustache_widget.rb +44 -0
- data/lib/omf-web/widget.rb +14 -1
- data/lib/omf_common/lobject.rb +6 -3
- data/omf_web.gemspec +3 -1
- data/share/htdocs/graph/js/abstract_nv_chart.js +14 -4
- data/share/htdocs/graph/js/abstract_widget.js +5 -4
- data/share/htdocs/graph/js/line_chart3.js +2 -0
- data/share/htdocs/graph/js/map2.js +3 -3
- data/share/htdocs/graph/js/network2.js +51 -19
- data/share/htdocs/graph/js/scatter_plot.js +6 -2
- data/share/htdocs/graph/js/table2.js +5 -2
- data/share/htdocs/js/data_source2.js +40 -8
- data/share/htdocs/js/mustache.js +29 -0
- data/share/htdocs/theme/abstract/abstract.js +10 -3
- data/share/htdocs/vendor/mustache-0.7.0/CHANGES +21 -0
- data/share/htdocs/vendor/mustache-0.7.0/LICENSE +10 -0
- data/share/htdocs/vendor/mustache-0.7.0/README.md +374 -0
- data/share/htdocs/vendor/mustache-0.7.0/jquery.mustache.js +635 -0
- data/share/htdocs/vendor/mustache-0.7.0/mustache.js +612 -0
- data/share/htdocs/vendor/nv_d3/js/nv.d3.js +9 -1
- data/share/htdocs/vendor/raphael-2.1.0/raphael.js +5815 -0
- metadata +74 -9
- data/DESIGN_NOTES.txt +0 -56
@@ -0,0 +1,101 @@
|
|
1
|
+
|
2
|
+
require 'rackamole'
|
3
|
+
require 'omf_common/lobject'
|
4
|
+
|
5
|
+
use ::Rack::ShowExceptions
|
6
|
+
#use ::Rack::Lint
|
7
|
+
#use Rack::Mole, :app_name => "Bridge"
|
8
|
+
|
9
|
+
OMF::Web::Runner.instance.life_cycle(:pre_rackup)
|
10
|
+
options = OMF::Web::Runner.instance.options
|
11
|
+
|
12
|
+
require 'omf-web/rack/session_authenticator'
|
13
|
+
use OMF::Web::Rack::SessionAuthenticator, #:expire_after => 10,
|
14
|
+
:login_url => '/tab/login',
|
15
|
+
:no_session => ['^/resource/', '^/login', '^/logout']
|
16
|
+
|
17
|
+
class Authenticator < OMF::Common::LObject
|
18
|
+
def self.signon(email, pw, remember)
|
19
|
+
OMF::Web::Rack::SessionAuthenticator.authenticate
|
20
|
+
OMF::Web::Rack::SessionAuthenticator[:name] = email
|
21
|
+
info "Authenticated '#{email}' (#{Thread.current["sessionID"]})"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
map "/resource" do
|
26
|
+
require 'omf-web/rack/multi_file'
|
27
|
+
run OMF::Web::Rack::MultiFile.new(options[:static_dirs])
|
28
|
+
end
|
29
|
+
|
30
|
+
map '/_ws' do
|
31
|
+
begin
|
32
|
+
require 'omf-web/rack/websocket_handler'
|
33
|
+
run OMF::Web::Rack::WebsocketHandler.new #:backend => { :debug => true }
|
34
|
+
rescue Exception => ex
|
35
|
+
OMF::Common::Loggable.logger('web').error "#{ex}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
map '/_update' do
|
40
|
+
require 'omf-web/rack/update_handler'
|
41
|
+
run OMF::Web::Rack::UpdateHandler.new
|
42
|
+
end
|
43
|
+
|
44
|
+
map '/_content' do
|
45
|
+
require 'omf-web/rack/content_handler'
|
46
|
+
run OMF::Web::Rack::ContentHandler.new
|
47
|
+
end
|
48
|
+
|
49
|
+
map "/tab" do
|
50
|
+
require 'omf-web/rack/tab_mapper'
|
51
|
+
run OMF::Web::Rack::TabMapper.new(options)
|
52
|
+
end
|
53
|
+
|
54
|
+
map "/widget" do
|
55
|
+
require 'omf-web/rack/widget_mapper'
|
56
|
+
run OMF::Web::Rack::WidgetMapper.new(options)
|
57
|
+
end
|
58
|
+
|
59
|
+
map '/login' do
|
60
|
+
handler = Proc.new do |env|
|
61
|
+
req = ::Rack::Request.new(env)
|
62
|
+
#puts ">>> post?: #{req.post?} - #{req.params.inspect}"
|
63
|
+
if req.post?
|
64
|
+
email = req.params["email"]
|
65
|
+
pw = req.params["password"]
|
66
|
+
remember = req.params["remember"] == "on"
|
67
|
+
Authenticator.signon(email, pw, remember)
|
68
|
+
end
|
69
|
+
[301, {'Location' => '/tab', "Content-Type" => ""}, ['Next window!']]
|
70
|
+
end
|
71
|
+
run handler
|
72
|
+
end
|
73
|
+
|
74
|
+
map '/logout' do
|
75
|
+
handler = Proc.new do |env|
|
76
|
+
OMF::Web::Rack::SessionAuthenticator.logout
|
77
|
+
[301, {'Location' => '/tab', "Content-Type" => ""}, ['Next window!']]
|
78
|
+
end
|
79
|
+
run handler
|
80
|
+
end
|
81
|
+
|
82
|
+
map "/" do
|
83
|
+
handler = Proc.new do |env|
|
84
|
+
req = ::Rack::Request.new(env)
|
85
|
+
case req.path_info
|
86
|
+
when '/'
|
87
|
+
[301, {'Location' => '/tab', "Content-Type" => ""}, ['Next window!']]
|
88
|
+
when '/favicon.ico'
|
89
|
+
[301, {'Location' => '/resource/image/favicon.ico', "Content-Type" => ""}, ['Next window!']]
|
90
|
+
else
|
91
|
+
OMF::Common::Loggable.logger('rack').warn "Can't handle request '#{req.path_info}'"
|
92
|
+
[401, {"Content-Type" => ""}, "Sorry!"]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
run handler
|
96
|
+
end
|
97
|
+
|
98
|
+
OMF::Web::Runner.instance.life_cycle(:post_rackup)
|
99
|
+
|
100
|
+
|
101
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'omf-web/widget/abstract_widget'
|
2
|
+
|
3
|
+
|
4
|
+
# Implements a widget to configure the state of the system
|
5
|
+
#
|
6
|
+
class ConfigureWidget < AbstractWidget
|
7
|
+
|
8
|
+
attr_reader :name, :opts #:base_id
|
9
|
+
|
10
|
+
|
11
|
+
# opts
|
12
|
+
#
|
13
|
+
def initialize(opts = {})
|
14
|
+
end
|
15
|
+
|
16
|
+
# This is the DOM id which should be used by the renderer for this widget.
|
17
|
+
# We need to keep this here as various renderes at various levels may need
|
18
|
+
# to get a reference to it to allow for such functionalities as
|
19
|
+
# hiding, stacking, ...
|
20
|
+
# def dom_id
|
21
|
+
# "w#{object_id.abs}"
|
22
|
+
# end
|
23
|
+
|
24
|
+
def content()
|
25
|
+
OMF::Web::Theme.require 'data_renderer'
|
26
|
+
OMF::Web::Theme::DataRenderer.new(self, @opts)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
end # class
|
@@ -1,8 +1,26 @@
|
|
1
1
|
require 'omf_web'
|
2
2
|
require 'omf_common/lobject'
|
3
|
-
require '
|
4
|
-
require '
|
3
|
+
require 'omf_oml/table'
|
4
|
+
require 'omf_oml/sql_source'
|
5
5
|
|
6
|
+
class LazySlicableTable < OMF::Common::LObject
|
7
|
+
|
8
|
+
attr_reader :name
|
9
|
+
# attr_accessor :max_size
|
10
|
+
attr_reader :schema
|
11
|
+
# attr_reader :offset
|
12
|
+
|
13
|
+
def initialize(name, schema, &block)
|
14
|
+
@name = name
|
15
|
+
@schema = schema
|
16
|
+
@block = block
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_sliced_table(col_name, col_value, table_opts = {})
|
20
|
+
@block.call(col_name, col_value, table_opts)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
6
24
|
|
7
25
|
class BridgeSensor < OMF::Common::LObject
|
8
26
|
attr_reader :table
|
@@ -14,8 +32,12 @@ class BridgeSensor < OMF::Common::LObject
|
|
14
32
|
# oml_sender_id INTEGER, oml_seq INTEGER, oml_ts_client REAL, oml_ts_server REAL, "eventID" TEXT, "sensorID" TEXT, "time" REAL, "x" REAL, "y" REAL, "z" REAL, "v1" REAL, "v2" REAL
|
15
33
|
def process_acceleration(stream)
|
16
34
|
#puts stream.class
|
17
|
-
@table = stream.to_table(:
|
18
|
-
|
35
|
+
@table = stream.to_table(:sensors_raw, :include_oml_internals => true)
|
36
|
+
|
37
|
+
#OMF::Web.register_datasource @table
|
38
|
+
OMF::Web.register_datasource(LazySlicableTable.new(:sensors, @table.schema) do |col_name, col_value, table_opts|
|
39
|
+
@table.create_sliced_table(col_name, col_value, table_opts)
|
40
|
+
end)
|
19
41
|
end
|
20
42
|
|
21
43
|
def process_health(stream)
|
@@ -32,7 +54,7 @@ class BridgeSensor < OMF::Common::LObject
|
|
32
54
|
#ep = OMF::OML::OmlSqlSource.new(@db_name, :offset => -500, :check_interval => 1.0)
|
33
55
|
ep = OMF::OML::OmlSqlSource.new(@db_name, :check_interval => 3.0)
|
34
56
|
ep.on_new_stream() do |stream|
|
35
|
-
#puts stream.inspect
|
57
|
+
#puts "NEW STREAM: #{stream.inspect}"
|
36
58
|
case stream.stream_name
|
37
59
|
when 'SydneyHarbourBridge_acceleration'
|
38
60
|
process_acceleration(stream)
|
@@ -60,7 +82,7 @@ class BridgeSensor < OMF::Common::LObject
|
|
60
82
|
loop do
|
61
83
|
#2012-07-21-17:03:25|node49|0.600000023841858
|
62
84
|
ev_id = Time.now.iso8601
|
63
|
-
[['node47', 0, '2012-07-21-
|
85
|
+
[['node47', 0, '2012-07-21-17:04:22'], ['node48', 0.2, ev_id], ['node49', 0.6, ev_id]].each do |r|
|
64
86
|
joint_id, health, ev_id = r
|
65
87
|
table.add_row [0, seq_no, 0.0, 0.0, ev_id, joint_id, health]
|
66
88
|
end
|
File without changes
|
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
L.provide('OML.bridge', ["graph/abstract_chart", "#OML.abstract_chart"
|
2
|
+
L.provide('OML.bridge', ["graph/js/abstract_chart", "#OML.abstract_chart"],
|
3
3
|
|
4
4
|
function () {
|
5
5
|
|
@@ -29,7 +29,7 @@ L.provide('OML.bridge', ["graph/abstract_chart", "#OML.abstract_chart", ["/resou
|
|
29
29
|
|
30
30
|
var self = this;
|
31
31
|
OHUB.bind("bridge.event_selected", function(evt) {
|
32
|
-
var joint_id = evt.
|
32
|
+
var joint_id = evt.datum[evt.schema.jointID.index];
|
33
33
|
self.redraw_sensor_locator(joint_id);
|
34
34
|
});
|
35
35
|
},
|
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
|
-
L.provide('OML.event_line_chart', ["graph/
|
2
|
+
L.provide('OML.event_line_chart', ["graph/js/line_chart3", "#OML.line_chart3"], function () {
|
3
3
|
|
4
|
-
OML.event_line_chart = OML.
|
4
|
+
OML.event_line_chart = OML.line_chart3.extend({
|
5
5
|
defaults: function() {
|
6
6
|
return this.deep_defaults({
|
7
7
|
}, OML.event_line_chart .__super__.defaults.call(this));
|
@@ -14,8 +14,8 @@ L.provide('OML.event_line_chart', ["graph/line_chart2", "#OML.line_chart2"], fun
|
|
14
14
|
|
15
15
|
var self = this;
|
16
16
|
OHUB.bind("bridge.event_selected", function(evt) {
|
17
|
-
self.event_id = evt.
|
18
|
-
self.joint_id = evt.
|
17
|
+
self.event_id = evt.datum[evt.schema.eventID.index];
|
18
|
+
self.joint_id = evt.datum[evt.schema.jointID.index];
|
19
19
|
self.update();
|
20
20
|
});
|
21
21
|
},
|
@@ -25,12 +25,13 @@ L.provide('OML.event_line_chart', ["graph/line_chart2", "#OML.line_chart2"], fun
|
|
25
25
|
if (! eid) return;
|
26
26
|
|
27
27
|
var data;
|
28
|
-
if ((data = this.data_source.
|
28
|
+
if ((data = this.data_source.rows()) == null) {
|
29
29
|
throw "Missing events array in data source"
|
30
30
|
}
|
31
31
|
|
32
|
+
var ei = this.schema.eventID.index;
|
32
33
|
data = _.filter(data, function(r) {
|
33
|
-
return r[
|
34
|
+
return r[ei] == eid;
|
34
35
|
})
|
35
36
|
if (data.length == 0) return;
|
36
37
|
this.redraw(data);
|
@@ -1,8 +1,16 @@
|
|
1
1
|
|
2
|
-
L.provide('
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
// L.provide('slickgrid/checkbox', [
|
3
|
+
// 'vendor/slickgrid/slick.core.js',
|
4
|
+
// 'vendor/slickgrid/slick.formatters.js',
|
5
|
+
// 'vendor/slickgrid/slick.editors.js',
|
6
|
+
// 'vendor/slickgrid/plugins/slick.rowselectionmodel.js',
|
7
|
+
// 'vendor/slickgrid/slick.grid.js',
|
8
|
+
// 'vendor/slickgrid/slick.dataview.js',
|
9
|
+
|
10
|
+
L.provide('OML.event_table', ["graph/js/table2", "#OML.table2",
|
11
|
+
'vendor/slickgrid/plugins/slick.checkboxselectcolumn.js',
|
12
|
+
'css/bridge.css'
|
13
|
+
], function () {
|
6
14
|
|
7
15
|
OML.event_table = OML.table2.extend({
|
8
16
|
decl_properties: [
|
@@ -27,7 +35,7 @@ L.provide('OML.event_table', ["graph/table2", "#OML.table2", [
|
|
27
35
|
var row = self.data[rindex];
|
28
36
|
var event_id = row[self.schema.eventID.index];
|
29
37
|
if (event_id) {
|
30
|
-
OHUB.trigger("bridge.event_selected", {
|
38
|
+
OHUB.trigger("bridge.event_selected", {datum: row, schema: self.schema});
|
31
39
|
}
|
32
40
|
});
|
33
41
|
},
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
<form class="form-horizontal" action="/login" method="post">
|
3
|
+
<div class="control-group">
|
4
|
+
<label class="control-label" for="inputEmail">Email</label>
|
5
|
+
<div class="controls">
|
6
|
+
<input type="text" id="inputEmail" name="email" placeholder="Email">
|
7
|
+
</div>
|
8
|
+
</div>
|
9
|
+
<div class="control-group">
|
10
|
+
<label class="control-label" for="inputPassword">Password</label>
|
11
|
+
<div class="controls">
|
12
|
+
<input type="password" id="inputPassword" name="password" placeholder="Password">
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
<div class="control-group">
|
16
|
+
<div class="controls">
|
17
|
+
<label class="checkbox">
|
18
|
+
<input type="checkbox" name="remember"> Remember me
|
19
|
+
</label>
|
20
|
+
<button type="submit" class="btn">Sign in</button>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
</form>
|
@@ -11,9 +11,9 @@ OMF::Common::Loggable.init_log 'bridge', :searchPath => File.dirname(__FILE__)
|
|
11
11
|
# If set, create fake sensor events
|
12
12
|
$fake_bridge_events = false
|
13
13
|
# Path to OML database
|
14
|
-
$oml_database = 'example/bridge/data_sources/test3.sq3'
|
14
|
+
$oml_database = 'sqlite://example/bridge/data_sources/test3.sq3'
|
15
15
|
|
16
|
-
require '
|
16
|
+
require 'omf_oml/table'
|
17
17
|
|
18
18
|
def load_environment
|
19
19
|
|
@@ -22,10 +22,8 @@ def load_environment
|
|
22
22
|
end
|
23
23
|
|
24
24
|
require 'yaml'
|
25
|
-
Dir.glob("#{File.dirname(__FILE__)}/*.yaml").each do |fn|
|
26
|
-
next if fn.match /log4r.yaml/
|
25
|
+
Dir.glob("#{File.dirname(__FILE__)}/widgets/*.yaml").each do |fn|
|
27
26
|
OMF::Common::LObject.debug "Load yaml file '#{fn}'"
|
28
|
-
|
29
27
|
h = YAML.load_file(fn)
|
30
28
|
if w = h['widget']
|
31
29
|
OMF::Web.register_widget w
|
@@ -54,6 +54,13 @@ widget:
|
|
54
54
|
title: Sensor Reading
|
55
55
|
data_source:
|
56
56
|
name: sensors
|
57
|
+
# Only fetch a 'slice' of the underlying data source. A slice
|
58
|
+
# is defined by specific value in the 'slice_column' of all rows
|
59
|
+
slice:
|
60
|
+
slice_column: eventID
|
61
|
+
event:
|
62
|
+
name: bridge.event_selected
|
63
|
+
key: eventID
|
57
64
|
mapping:
|
58
65
|
x_axis: time
|
59
66
|
y_axis:
|
@@ -75,7 +82,3 @@ widget:
|
|
75
82
|
top: 10
|
76
83
|
left: 60
|
77
84
|
right: 20
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
|
5
|
-
require '
|
6
|
-
require '
|
5
|
+
require 'omf_oml/network'
|
6
|
+
require 'omf_oml/table'
|
7
7
|
|
8
8
|
include OMF::OML
|
9
9
|
|
@@ -19,7 +19,8 @@ nw.link_schema [[:load, :float]]
|
|
19
19
|
l = nw.create_link :l01, :n0, :m1, :load => 0.8
|
20
20
|
|
21
21
|
require 'omf_web'
|
22
|
-
OMF::Web.register_datasource nw, :index => :id
|
22
|
+
OMF::Web.register_datasource nw.to_table(:nodes, :index => :id)
|
23
|
+
OMF::Web.register_datasource nw.to_table(:links, :index => :id)
|
23
24
|
|
24
25
|
# Move mobile node
|
25
26
|
Thread.new do
|
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
3
|
+
require 'omf_oml/network'
|
4
|
+
require 'omf_oml/table'
|
5
5
|
|
6
6
|
include OMF::OML
|
7
7
|
|
@@ -17,7 +17,8 @@ nw.create_link :l12, :n1, :n2, :load => 0.4
|
|
17
17
|
nw.create_link :l21, :n2, :n1, :load => 0.9
|
18
18
|
|
19
19
|
require 'omf_web'
|
20
|
-
OMF::Web.register_datasource nw
|
20
|
+
OMF::Web.register_datasource nw.to_table(:nodes, :index => :id)
|
21
|
+
OMF::Web.register_datasource nw.to_table(:links, :index => :id)
|
21
22
|
|
22
23
|
# opts = {
|
23
24
|
# #:data_sources => table,
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
|
5
|
-
require '
|
6
|
-
require '
|
5
|
+
require 'omf_oml/network'
|
6
|
+
require 'omf_oml/table'
|
7
7
|
|
8
8
|
include OMF::OML
|
9
9
|
|
@@ -23,7 +23,8 @@ links << nw.create_link(:l23, :n2, :n3, :ts => 0, :load => 0.5)
|
|
23
23
|
links << nw.create_link(:l24, :n2, :n4, :ts => 0, :load => 0.75)
|
24
24
|
|
25
25
|
require 'omf_web'
|
26
|
-
OMF::Web.register_datasource nw, :index => :id
|
26
|
+
OMF::Web.register_datasource nw.to_table(:nodes, :index => :id)
|
27
|
+
OMF::Web.register_datasource nw.to_table(:links, :index => :id)
|
27
28
|
|
28
29
|
# Create a table which serves the history of an individual link as a slice
|
29
30
|
#
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Openflow Demo at GEC'15
|
2
|
+
|
3
|
+
This directory contains most of the code used for our Openflow demo at GEC'15.
|
4
|
+
|
5
|
+
The following will start the visualization front-end:
|
6
|
+
|
7
|
+
cd OMF_WEB_HOME
|
8
|
+
ruby1.9 -I lib example/openflow-gec15/of_viz_server.rb start
|
9
|
+
|
10
|
+
If you want to run it in **pure** demo mode, then add the '--local-testing' flag before the 'start' command.
|
11
|
+
|
12
|
+
This will start a web server at port 3000. Point your browser there and you should see somthing like:
|
13
|
+
|
14
|
+
![Screenshot of dashboard](https://raw.github.com/mytestbed/omf_web/master/example/openflow-gec15/doc/screenshot.png "Screenshot")
|
15
|
+
|
16
|
+
Clicking on the 'Code' tab will show the 'OIDL' script describing the experiment, and the 'Trema' code of the Openflow controller
|
17
|
+
used in the experiment.
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
# Simple tab showing a line chart with supporting table
|
5
|
+
#
|
6
|
+
|
7
|
+
widget:
|
8
|
+
id: code
|
9
|
+
name: Code
|
10
|
+
top_level: true
|
11
|
+
priority: 600
|
12
|
+
type: layout/tabbed
|
13
|
+
widgets:
|
14
|
+
|
15
|
+
|
16
|
+
- name: OIDL
|
17
|
+
type: code
|
18
|
+
width: 1.0
|
19
|
+
#height: 800
|
20
|
+
content:
|
21
|
+
url: file:code:of-exp.rb
|
22
|
+
|
23
|
+
- name: Trema
|
24
|
+
type: code
|
25
|
+
width: 1.0
|
26
|
+
#height: 800
|
27
|
+
content:
|
28
|
+
url: file:code:trema-ctl6.rb
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
# Define a 'dashboard' consisting of two columns of widgets
|
4
|
+
#
|
5
|
+
|
6
|
+
widget:
|
7
|
+
id: linked_graphs
|
8
|
+
name: Dashboard
|
9
|
+
top_level: true
|
10
|
+
priority: 800
|
11
|
+
type: layout/two_columns/50_50
|
12
|
+
left:
|
13
|
+
- name: Network
|
14
|
+
type: data/network2
|
15
|
+
width: 1.0
|
16
|
+
height: 1.0
|
17
|
+
data_source:
|
18
|
+
name: network
|
19
|
+
unique_column: id # only use the latest link and row descriptions
|
20
|
+
dynamic: true
|
21
|
+
mapping:
|
22
|
+
nodes:
|
23
|
+
x:
|
24
|
+
property: x
|
25
|
+
y:
|
26
|
+
property: y
|
27
|
+
radius: 20
|
28
|
+
links:
|
29
|
+
stroke_width:
|
30
|
+
property: rate
|
31
|
+
scale: 1e-4
|
32
|
+
min: 3
|
33
|
+
max: 20
|
34
|
+
stroke_color:
|
35
|
+
property: load
|
36
|
+
max: 1.0
|
37
|
+
color: green_yellow80_red()
|
38
|
+
margin:
|
39
|
+
left: 30
|
40
|
+
right: 30
|
41
|
+
#interaction_mode: click # click on link to create event
|
42
|
+
|
43
|
+
|
44
|
+
right:
|
45
|
+
- name: Link Stats
|
46
|
+
type: data/line_chart3
|
47
|
+
#area: true # color the area between line and zero line
|
48
|
+
width: 1.0
|
49
|
+
height: 0.8
|
50
|
+
data_source:
|
51
|
+
name: link_history
|
52
|
+
mapping:
|
53
|
+
x_axis: ts
|
54
|
+
y_axis:
|
55
|
+
property: rate
|
56
|
+
#max: 1
|
57
|
+
group_by: name
|
58
|
+
axis:
|
59
|
+
x:
|
60
|
+
ticks:
|
61
|
+
format: 's'
|
62
|
+
#type: time
|
63
|
+
legend: Time (sec)
|
64
|
+
transition: 0
|
65
|
+
y:
|
66
|
+
min: 0
|
67
|
+
legend: Rate (bps)
|
68
|
+
ticks:
|
69
|
+
format: 's'
|
70
|
+
transition: 0
|
71
|
+
margin:
|
72
|
+
left: 100
|
Binary file
|