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.
Files changed (91) hide show
  1. data/README.md +168 -13
  2. data/bin/omf-web-basic +3 -3
  3. data/doc/index.md +205 -0
  4. data/example/NOT_WORKING/brooklyn/brooklyn_server.rb +2 -2
  5. data/example/NOT_WORKING/frisbee/data_sources/parse_log.rb +1 -1
  6. data/example/NOT_WORKING/frisbee/viz_server.rb +1 -1
  7. data/example/NOT_WORKING/gec12/gec12_demo_server.rb +1 -1
  8. data/example/NOT_WORKING/gec12/visualization.rb +2 -2
  9. data/example/NOT_WORKING/network/network_server.rb +2 -2
  10. data/example/NOT_WORKING/wimax/test.rb +2 -2
  11. data/example/NOT_WORKING/wimax/viz_server.rb +2 -2
  12. data/example/bridge/auth_basic.rb +75 -0
  13. data/example/bridge/config.ru +101 -0
  14. data/example/bridge/configure/configure_widget.rb +32 -0
  15. data/example/bridge/data_sources/sensor-sqlite.rb +28 -6
  16. data/example/bridge/data_sources/test31.sq3 +0 -0
  17. data/example/bridge/htdocs/{js/graph → graph/js}/bridge.js +2 -2
  18. data/example/bridge/htdocs/{js/graph → graph/js}/event_line_chart.js +7 -6
  19. data/example/bridge/htdocs/{js/graph → graph/js}/event_table.js +13 -5
  20. data/example/bridge/htdocs/template/login.html +23 -0
  21. data/example/bridge/viz_server.rb +3 -5
  22. data/example/bridge/widgets/configure.yaml +12 -0
  23. data/example/bridge/widgets/login.yaml +16 -0
  24. data/example/bridge/{overview.yaml → widgets/overview.yaml} +7 -4
  25. data/example/demo/data_sources/animals.rb +1 -1
  26. data/example/demo/data_sources/downloads.rb +1 -1
  27. data/example/demo/data_sources/generator.rb +1 -1
  28. data/example/demo/data_sources/histogram.rb +1 -1
  29. data/example/demo/data_sources/mobile_network.rb +4 -3
  30. data/example/demo/data_sources/movies.rb +1 -1
  31. data/example/demo/data_sources/network.rb +4 -3
  32. data/example/demo/data_sources/returns.rb +1 -1
  33. data/example/demo/data_sources/static_network.rb +4 -3
  34. data/example/demo/data_sources/walk.rb +1 -1
  35. data/example/demo/demo_viz_server.rb +1 -1
  36. data/example/demo/widgets/linked_graphs_tab.yaml +1 -1
  37. data/example/openflow-gec15/README.md +21 -0
  38. data/example/openflow-gec15/code_tab.yaml +36 -0
  39. data/example/openflow-gec15/dashboard_tab.yaml +72 -0
  40. data/example/openflow-gec15/doc/screenshot.png +0 -0
  41. data/example/openflow-gec15/exp_source.rb +104 -0
  42. data/example/openflow-gec15/of_viz_server.rb +63 -0
  43. data/example/openflow-gec15/openflow-demo.sq3 +0 -0
  44. data/example/openflow-gec15/raw_tab.yaml +37 -0
  45. data/example/openflow-gec15/repository/of-exp.rb +12 -0
  46. data/example/openflow-gec15/repository/sample.md +52 -0
  47. data/example/openflow-gec15/repository/trema-ctl6.rb +148 -0
  48. data/example/simple/README.md +2 -0
  49. data/example/simple/data_sources/gimi31.sq3 +0 -0
  50. data/example/simple/data_sources/ping_source.rb +56 -0
  51. data/example/simple/simple_viz_server.rb +39 -0
  52. data/example/simple/widgets/charts_tab.yaml +38 -0
  53. data/lib/omf-web/config.ru +31 -3
  54. data/lib/omf-web/data_source_proxy.rb +29 -26
  55. data/lib/omf-web/rack/session_authenticator.rb +93 -0
  56. data/lib/omf-web/rack/tab_mapper.rb +10 -5
  57. data/lib/omf-web/rack/websocket_handler.rb +17 -6
  58. data/lib/omf-web/theme/abstract_page.rb +1 -1
  59. data/lib/omf-web/theme/bright/flow_renderer.rb +2 -2
  60. data/lib/omf-web/theme/bright/layout_renderer.rb +15 -0
  61. data/lib/omf-web/theme/bright/mustache_renderer.rb +29 -0
  62. data/lib/omf-web/theme/bright/one_column_renderer.rb +2 -2
  63. data/lib/omf-web/theme/bright/page.rb +33 -8
  64. data/lib/omf-web/theme/bright/tabbed_renderer.rb +2 -3
  65. data/lib/omf-web/theme/bright/two_columns_renderer.rb +3 -4
  66. data/lib/omf-web/version.rb +1 -1
  67. data/lib/omf-web/widget/code_widget.rb +0 -7
  68. data/lib/omf-web/widget/layout/two_columns_layout.rb +3 -2
  69. data/lib/omf-web/widget/mustache_widget.rb +44 -0
  70. data/lib/omf-web/widget.rb +14 -1
  71. data/lib/omf_common/lobject.rb +6 -3
  72. data/omf_web.gemspec +3 -1
  73. data/share/htdocs/graph/js/abstract_nv_chart.js +14 -4
  74. data/share/htdocs/graph/js/abstract_widget.js +5 -4
  75. data/share/htdocs/graph/js/line_chart3.js +2 -0
  76. data/share/htdocs/graph/js/map2.js +3 -3
  77. data/share/htdocs/graph/js/network2.js +51 -19
  78. data/share/htdocs/graph/js/scatter_plot.js +6 -2
  79. data/share/htdocs/graph/js/table2.js +5 -2
  80. data/share/htdocs/js/data_source2.js +40 -8
  81. data/share/htdocs/js/mustache.js +29 -0
  82. data/share/htdocs/theme/abstract/abstract.js +10 -3
  83. data/share/htdocs/vendor/mustache-0.7.0/CHANGES +21 -0
  84. data/share/htdocs/vendor/mustache-0.7.0/LICENSE +10 -0
  85. data/share/htdocs/vendor/mustache-0.7.0/README.md +374 -0
  86. data/share/htdocs/vendor/mustache-0.7.0/jquery.mustache.js +635 -0
  87. data/share/htdocs/vendor/mustache-0.7.0/mustache.js +612 -0
  88. data/share/htdocs/vendor/nv_d3/js/nv.d3.js +9 -1
  89. data/share/htdocs/vendor/raphael-2.1.0/raphael.js +5815 -0
  90. metadata +74 -9
  91. data/DESIGN_NOTES.txt +0 -56
@@ -0,0 +1,104 @@
1
+ require 'omf_web'
2
+ require 'omf_common/lobject'
3
+ require 'omf_oml/network'
4
+ require 'omf_oml/table'
5
+ require 'omf_oml/sql_source'
6
+
7
+ require 'em-postgresql-sequel'
8
+
9
+
10
+ include OMF::OML
11
+
12
+ class ExpDB < OMF::Common::LObject
13
+
14
+
15
+ def initialize(db_opts)
16
+ @db_opts = db_opts
17
+ init_network
18
+ end
19
+
20
+ def init_network
21
+ @nw = nw = OmlNetwork.new('network')
22
+ nw.node_schema [[:x, :float], [:y, :float]]
23
+ nw.create_node :n0, :x => 0.5, :y => 0.8
24
+ nw.create_node :n1, :x => 0.2, :y => 0.5
25
+ nw.create_node :n2, :x => 0.8, :y => 0.5
26
+ nw.create_node :n3, :x => 0.8, :y => 0.2
27
+
28
+ nw.link_schema [[:ts, :float], [:bytes, :int], [:rate, :float], [:load, :float]]
29
+ @links = {}
30
+ @links[:l20] = nw.create_link(:l20, :n2, :n0, :ts => 0, :bytes => 0, :rate => 0, :load => 0)
31
+ @links[:l10] = nw.create_link(:l10, :n1, :n0, :ts => 0, :bytes => 0, :rate => 0, :load => 0)
32
+ @links[:l21] = nw.create_link(:l21, :n2, :n1, :ts => 0, :bytes => 0, :rate => 0, :load => 0)
33
+ @links[:l32] = nw.create_link(:l32, :n3, :n2, :ts => 0, :bytes => 0, :rate => 0, :load => 0)
34
+
35
+
36
+ OMF::Web.register_datasource nw.to_table(:nodes, :index => :id)
37
+ OMF::Web.register_datasource nw.to_table(:links, :index => :id)
38
+ @link_history = nw.to_table(:links, :max_size => 100)
39
+ OMF::Web.register_datasource @link_history, :name => 'link_history'
40
+ end
41
+
42
+ def setup_nmetric(stream)
43
+ schema = stream.schema
44
+ t = OMF::OML::OmlTable.new(:nmetric, schema, :max_size => 1000)
45
+ ts_i = schema.index_for_col(:oml_ts_server)
46
+ name_i = schema.index_for_col(:name)
47
+ tx_i = schema.index_for_col(:tx_bytes)
48
+ rx_i = schema.index_for_col(:rx_bytes)
49
+
50
+ def process(l, ts, bytes, max_rate)
51
+ if (delta_t = ts - l[:ts]) > 0
52
+ old_v = l[:bytes]
53
+ delta_v = bytes >= old_v ? bytes - old_v : bytes
54
+ l[:ts] = ts
55
+ l[:bytes] = bytes
56
+ l[:rate] = rate = 1.0 * delta_v / delta_t
57
+ #l[:rate] = rate = 230000
58
+ l[:load] = 1.0 * rate / max_rate
59
+ end
60
+ end
61
+
62
+ stream.on_new_tuple() do |v|
63
+ r = v.to_a(true)
64
+ #puts "RRR >> #{r.inspect}"
65
+ t.add_row(r)
66
+ ts = r[ts_i]; name = r[name_i].to_sym; tx = r[tx_i]; rx = r[rx_i]
67
+ #puts "VVV(#{ts}) >> #{v.row.inspect}"
68
+ @nw.transaction do
69
+ case name
70
+ when :eth0
71
+ process @links[:l20], ts, tx, 120e3 #1e6
72
+ when :wlan0
73
+ process @links[:l21], ts, tx, 4e6
74
+ process @links[:l10], ts, tx, 4e6
75
+ when :wlan1
76
+ process @links[:l32], ts, rx, 4e6
77
+ end
78
+ end
79
+ sleep 0.5 if ts > 7300
80
+ end
81
+
82
+ # nw.transaction do
83
+ # links.each_with_index do |l, i|
84
+ # l[:ts] = ts
85
+ # l[:load] = rand() * frac + i * frac
86
+ # end
87
+ # end
88
+
89
+ OMF::Web.register_datasource t
90
+ end
91
+
92
+ def run
93
+ ep = OMF::OML::OmlSqlSource.new(@db_opts, :check_interval => 3.0)
94
+ ep.on_new_stream() do |stream|
95
+ info "Stream: #{stream.stream_name}"
96
+ if stream.stream_name == 'nmetrics_net_if'
97
+ setup_nmetric(stream)
98
+ end
99
+ end
100
+ ep.run
101
+ self
102
+ end
103
+
104
+ end
@@ -0,0 +1,63 @@
1
+
2
+ require 'omf_common/lobject'
3
+ OMF::Common::Loggable.init_log 'of-demo'
4
+
5
+
6
+ require 'omf_oml/table'
7
+
8
+ $testing_database = 'sqlite://example/openflow-gec15/openflow-demo.sq3'
9
+ $oml_database = 'postgres://norbit.npc.nicta.com.au/openflow-demo?user=oml2&password=omlisgoodforyou'
10
+
11
+ def load_environment
12
+ require 'omf-web/content/file_repository'
13
+ OMF::Web::FileContentRepository.register_file_repo(:code, File.join(File.dirname(__FILE__), 'repository'), true)
14
+
15
+
16
+ Dir.glob("#{File.dirname(__FILE__)}/*_source.rb").each do |fn|
17
+ load fn
18
+ end
19
+
20
+ require 'yaml'
21
+ Dir.glob("#{File.dirname(__FILE__)}/*_tab.yaml").each do |fn|
22
+ h = YAML.load_file(fn)
23
+ if w = h['widget']
24
+ OMF::Web.register_widget w
25
+ else
26
+ MObject.error "Don't know what to do with '#{fn}'"
27
+ end
28
+ end
29
+
30
+ # Start database adapter
31
+ EM.next_tick do
32
+ EM::run do
33
+ wv = ExpDB.new($oml_database)
34
+ wv.run
35
+ end
36
+ end
37
+ end
38
+
39
+
40
+ # Configure the web server
41
+ #
42
+ opts = {
43
+ :app_name => 'ov_demo',
44
+ :page_title => 'Dynamic Routing',
45
+ :handlers => {
46
+ # delay connecting to databases to AFTER we may run as daemon
47
+ :pre_rackup => lambda { load_environment },
48
+ :pre_parse => lambda do |p|
49
+ p.separator ""
50
+ p.separator "DEMO options:"
51
+ p.on("--local-testing", "If set, use local database for testing [#{$testing_database}]") do
52
+ $oml_database = $testing_database
53
+ end
54
+ p.on("--oml-database DATABASE", "Database containing measurement data [#{$oml_database}]") do |f|
55
+ $oml_database = f
56
+ end
57
+ p.separator ""
58
+ end
59
+
60
+ }
61
+ }
62
+ require 'omf_web'
63
+ OMF::Web.start(opts)
@@ -0,0 +1,37 @@
1
+
2
+
3
+
4
+ # Simple tab showing a line chart with supporting table
5
+ #
6
+
7
+ widget:
8
+ id: raw
9
+ name: Raw
10
+ top_level: true
11
+ priority: 200
12
+ type: layout/tabbed
13
+ widgets:
14
+
15
+ # - name: Ping Line
16
+ # type: data/line_chart3
17
+ # data_source:
18
+ # name: ping
19
+ # mapping:
20
+ # x_axis:
21
+ # property: oml_ts_client
22
+ # y_axis:
23
+ # property: rtt
24
+ # max: 2.0
25
+ # group_by: link
26
+
27
+ - name: Link
28
+ type: data/table2
29
+ data_source:
30
+ name: link_history
31
+
32
+ - name: NMetric
33
+ type: data/table2
34
+ data_source:
35
+ name: nmetric
36
+
37
+
@@ -0,0 +1,12 @@
1
+ defProperty('wired', 'omf.nicta.node2', "Wired node (endpoint)") # baseline.ndz
2
+ defGroup('ap', property.ap) do |node|
3
 
1
4
  # wlan0 is not part of OVS
2
5
  # the IP address is the GRE tunnel endpoint
3
6
  node.net.w0.mode = "adhoc"
4
7
  node.net.w0.type = 'g'
5
8
  node.net.w0.channel = "6"
6
9
  node.net.w0.essid = "adhoc"
7
10
  node.net.w0.ip = "172.16.2.1"
11
+ # wlan1 is part of OVS
8
12
  node.net.w1.mode = "master"
9
13
  node.net.w1.type = 'g'
10
14
  node.net.w1.channel = "10"
11
15
  node.net.w1.essid = "ap"
12
16
 
13
17
  onNodeUp do |n|
14
18
  n.exec("ifconfig br-int up; ovs-vsctl set controller br-int connection-mode=out-of-band; ifconfig eth0 0")
15
19
  n.exec("ovs-vsctl add-port br-int gre1 -- set interface gre1 type=gre options:remote_ip=172.16.2.2")
16
20
  n.exec("ovs-vsctl add-port br-int eth0")
17
21
  n.exec("ovs-vsctl add-port br-int wlan1")
18
22
  n.exec("while true; do timeout 10 nmetrics-oml2 -s 2 -i eth0 --oml-server tcp:10.0.0.200:5000 --oml-exp-id 1 --oml-id 1 --oml-text; done")
19
23
  #n.exec("/root/monitor_ovs_ports.rb --oml-id ap --oml-server tcp:norbit.npc.nicta.com.au:5000")
20
24
  end
21
25
 
26
+ defGroup('adhoc', property.adhoc) do |node|
22
27
 
23
28
  # wlan0 is not part of OVS
24
29
  # the IP address is the GRE tunnel endpoint
25
30
  node.net.w0.mode = "adhoc"
26
31
  node.net.w0.type = 'g'
27
32
  node.net.w0.channel = "6"
28
33
  node.net.w0.essid = "adhoc"
29
34
  node.net.w0.ip = "172.16.2.2"
30
35
 
31
36
  onNodeUp do |n|
32
37
  n.exec("ifconfig br-int up; ovs-vsctl set controller br-int connection-mode=out-of-band; ifconfig eth0 0")
33
38
  n.exec("ovs-vsctl add-port br-int gre1 -- set interface gre1 type=gre options:remote_ip=172.16.2.1")
34
39
  n.exec("ovs-vsctl add-port br-int eth0")
35
40
  #n.exec("/root/monitor_ovs_ports.rb --oml-id adhoc --oml-server tcp:norbit.npc.nicta.com.au:5000")
36
41
  end
42
+ defGroup('wireless', property.wireless) do |node|
37
43
  # no OVS on this node
38
44
  node.net.w0.mode = "managed"
39
45
  node.net.w0.type = 'g'
40
46
  node.net.w0.channel = "10"
41
47
  node.net.w0.essid = "ap"
42
48
  node.net.w0.ip = "172.16.1.4"
43
49
  node.addApplication("test:app:otg2", :id => 'flow1') do |app|
44
50
  app.setProperty('cbr:rate', 800000)
45
51
  app.setProperty('udp:local_host', '172.16.1.4')
46
52
  app.setProperty('udp:dst_host', '172.16.1.1')
47
53
  app.setProperty('udp:dst_port', 3000)
48
54
  app.measure('udp_out', :samples => 1)
49
55
  end
50
56
 
51
57
  node.addApplication("test:app:otg2", :id => 'flow2') do |app|
52
58
  app.setProperty('cbr:rate', 800000)
53
59
  app.setProperty('udp:local_host', '172.16.1.4')
54
60
  app.setProperty('udp:dst_host', '172.16.1.1')
55
61
  app.setProperty('udp:dst_port', 3000)
56
62
  app.measure('udp_out', :samples => 1)
57
63
  end
64
+ defGroup('wired', property.wired) do |node|
58
65
  node.addApplication("test:app:otr2") do |app|
59
66
  app.setProperty('udp:local_host', '172.16.1.1')
60
67
  app.setProperty('udp:local_port', 3000)
61
68
  app.measure('udp_in', :samples => 1)
62
69
  end
70
+ # no OVS on this node
63
71
  node.net.e0.ip = "172.16.1.1"
72
+ onEvent(:ALL_UP) do |event|
64
73
  allGroups.exec("sysctl -w net.ipv6.conf.all.disable_ipv6=1")
74
+ group("wired").startApplications
65
75
  info "Start your OpenFlow controller now!"
76
+ while true
66
77
  info "Starting flow 1"
67
78
  group("wireless").startApplication('flow1')
68
79
  sleep 10
69
80
  info "Starting flow 2"
70
81
  group("wireless").startApplication('flow2')
71
82
  sleep 10
72
83
  info "Stopping flow 1. Flow 2 should now re-route over flow 1's path"
73
84
  group("wireless").stopApplication('flow1')
74
85
  sleep 20
75
86
  info "Starting flow 1. Should use secondary path now."
76
87
  group("wireless").startApplication('flow1')
77
88
  sleep 20
78
89
  info "Stopping flow 2"
79
90
  group("wireless").stopApplication('flow2')
80
91
  info "Stopping flow 1"
81
92
  group("wireless").stopApplication('flow1')
82
93
  sleep 10
83
94
  info "Restarting experiment cycle"
84
95
  end
96
+
97
+
@@ -0,0 +1,52 @@
1
+ title: Lorem ipsum dolor sit
2
+
3
+ # Lorem ipsum dolor sit
4
+
5
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin
6
+ sollicitudin nibh eu ligula lobortis ornare. Sed nibh nibh,
7
+ ullamcorper at vehicula ac, molestie ac nunc. Duis sodales, nisi vel
8
+ pellentesque imperdiet, nisi massa accumsan lorem, gravida scelerisque
9
+ velit est vitae eros. Suspendisse eu lacinia elit.
10
+
11
+ \[
12
+ \sum_{n=1}^\infty \frac{1}{n}
13
+ \text{ is divergent, but }
14
+ \lim_{n \to \infty} \sum_{i=1}^n \frac{1}{i} - \ln n \text{exists.}
15
+ \]
16
+
17
+ Suspendisse laoreet, lacus quis dignissim volutpat, dolor augue convallis lectus,
18
+ ac consectetur yyyy sem iaculis diam. Donec iaculis mattis iaculis.
19
+ Curabitur ut nisl in sapien semper ullamcorper in id turpis. Vivamus
20
+ sed sapien justo, ac scelerisque nibh. Sed eget quam velit. Lorem
21
+ ipsum dolor sit amet, consectetur adipiscing elit.
22
+
23
+ {{{
24
+ widget:
25
+ title: Fusce vehicula sapien
26
+ type: data/pie_chart2
27
+ data_sources: animals
28
+ mapping:
29
+ value: count
30
+ fill_color: category10()
31
+ label: name
32
+ width: 0.6
33
+ margin:
34
+ left: 0
35
+ right: 0
36
+ top: 0
37
+ bottom: 0
38
+ }}}
39
+
40
+ Aliquam tortor elit, condimentum et tincidunt vitae, consequat id
41
+ lacus. Fusce vehicula sapien sed leo varius at dictum purus
42
+ consectetur. Vestibulum sit amet nisl nisl. Suspendisse bibendum
43
+ iaculis rhoncus. Vivamus elementum lacinia metus, vitae fringilla diam
44
+ commodo et.
45
+
46
+ ### Cras ut volutpat magna
47
+
48
+ Integer pharetra pellentesque
49
+ interdum. Nunc diam quam, volutpat a iaculis pellentesque, aliquet a
50
+ mauris. Praesent quam purus, mattis ullamcorper sagittis a, feugiat
51
+ non lorem.
52
+
@@ -0,0 +1,148 @@
1
+ require 'rubygems'
2
+ require 'omf-oml/endpoint'
3
+ require 'omf-oml/table'
4
+ require 'omf_common/lobject'
5
+
6
+ OMLPORT=5000
7
+ # threshold for transmitted bytes/s on AP's eth0 interface
8
+ # when exceeded, route new flows through secondary path
9
+ PRIMARY_THRESHOLD=100000
10
+
11
+ class OFDemo < Controller
12
+
13
+ add_timer_event :check_flows, 3, :periodic
14
+
15
+ def start
16
+ @switches = {"ap" => 0x32d0cfcb0, "adhoc" => 0x32d081a16, "of1" => 0x2320ca156c}
17
+ @ports = Hash.new
18
+ @detour=false
19
+ @lastflow=0
20
+
21
+ OMF::Common::Loggable.init_log File.basename($0).split('.')[0]
22
+ ep = OMF::OML::OmlEndpoint.new(OMLPORT, '0.0.0.0')
23
+ ep.on_new_stream() do |name, stream|
24
+ #puts "New stream: #{name}::#{stream}"
25
+ txcount=0
26
+ first=true
27
+ stream.on_new_tuple() do |t|
28
+ tx=t.to_a[11].to_i
29
+ if first
30
+ first=false
31
+ next
32
+ end
33
+ #puts "New tuple: #{t.to_a.inspect}"
34
+ txc=tx-txcount
35
+ txcount=tx
36
+ @detour = txc > PRIMARY_THRESHOLD
37
+ puts "AP eth0 reports #{txc} bytes/s, saturated: #{@detour}"
38
+ end
39
+ end
40
+ ep.run(true)
41
+ end
42
+
43
+ def switch_ready dpid
44
+ puts "Switch #{@switches.index(dpid)} (#{dpid.to_hex}) has signed in"
45
+ send_message dpid, FeaturesRequest.new
46
+ end
47
+
48
+ def features_reply dpid, message
49
+ @ports[dpid] = Hash.new
50
+ # read port name and number from the features_reply
51
+ message.ports.each do | p |
52
+ #puts "#{@switches.index(d)} : #{p.name} = #{p.number}"
53
+ @ports[dpid][p.name] = p.number
54
+ end
55
+ end
56
+
57
+ def packet_in dpid, message
58
+ # drop it if we don't now the switch or its ports (yet)
59
+ return if @switches.index(dpid).nil? or @ports[dpid].nil?
60
+
61
+ arp_error="Unidentified ARP traffic. You may have started the controller too early, please restart it."
62
+
63
+ # handle ARP traffic manually to avoid packet storm in our circular topology
64
+ if message.arp?
65
+ if @switches.index(dpid)=="ap"
66
+ if message.in_port==@ports[dpid]['wlan1']
67
+ packet_out dpid, message, @ports[dpid]['eth0']
68
+ elsif message.in_port==@ports[dpid]['eth0']
69
+ packet_out dpid, message, @ports[dpid]['wlan1']
70
+ else
71
+ puts arp_error
72
+ end
73
+ elsif @switches.index(dpid)=="of1"
74
+ if message.in_port==2
75
+ packet_out dpid, message, 3
76
+ elsif message.in_port==3
77
+ packet_out dpid, message, 2
78
+ else
79
+ puts arp_error
80
+ end
81
+ end
82
+ return
83
+ end
84
+
85
+ # from now on we are only interested on IPv4 packets arriving on AP over wlan1
86
+ return if !message.ipv4? or @switches.index(dpid)!="ap" or message.in_port!=@ports[dpid]['wlan1']
87
+
88
+ # slow down adding of flows
89
+ # t=Time.now.to_i
90
+ # if t-@lastflow > 2
91
+ # @lastflow=t
92
+ # else
93
+ # return
94
+ # end
95
+
96
+ # add the flow on AP after adding all the others to avoid loss of inital packets
97
+ if @detour
98
+ puts "Adding flow over secondary path"
99
+ # broken due to trema bug
100
+ #flow_mod @switches["adhoc"], message, @ports[dpid]['eth0']
101
+ #flow_mod @switches["of1"], message, 2
102
+ flow_mod dpid, message, @ports[dpid]['gre1']
103
+ else
104
+ puts "Adding flow over primary path"
105
+ # broken due to trema bug
106
+ #flow_mod @switches["of1"], message, 2
107
+ flow_mod dpid, message, @ports[dpid]['eth0']
108
+ end
109
+
110
+ end
111
+
112
+ # periodically check if the throughput on primary path is below threshold
113
+ # if yes, remove flows that currently use secondary path
114
+ def check_flows
115
+ return if @ports[@switches["ap"]].nil?
116
+ if !@detour
117
+ puts "Deleting flows on switch #{@switches["ap"].to_hex} with out_port #{@ports[@switches["ap"]]['gre1']}"
118
+ send_flow_mod_delete(
119
+ @switches["ap"].to_i,
120
+ :actions => ActionOutput.new( :port => @ports[@switches["ap"]]['gre1'] )
121
+ )
122
+ end
123
+ end
124
+
125
+ ##############################################################################
126
+ private
127
+ ##############################################################################
128
+
129
+ def flow_mod datapath_id, message, port_no
130
+ #p Match.from( message, [ :dl_type, :nw_proto ] )
131
+ send_flow_mod_add(
132
+ datapath_id,
133
+ :match => Match.from( message ),
134
+ :actions => ActionOutput.new( :port => port_no ),
135
+ :idle_timeout => 2
136
+ )
137
+ end
138
+
139
+ def packet_out datapath_id, message, port_no
140
+ send_packet_out(
141
+ datapath_id,
142
+ :packet_in => message,
143
+ :actions => ActionOutput.new( :port => port_no )
144
+ )
145
+ end
146
+
147
+ end
148
+
@@ -0,0 +1,2 @@
1
+
2
+ Essentially the 'Hello World' example of a viz server. Taking data out of a database and putting it into a graph.
@@ -0,0 +1,56 @@
1
+ require 'omf_web'
2
+ require 'omf_common/lobject'
3
+ require 'omf_oml/table'
4
+ require 'omf_oml/sql_source'
5
+
6
+
7
+ class PingDB < OMF::Common::LObject
8
+
9
+ LINKS = {'Source1::192.168.4.11' => 'link 4',
10
+ 'Source1::192.168.5.11' => 'link 5',
11
+ 'Source2::192.168.1.13' => 'link 1',
12
+ 'Source2::192.168.2.10' => 'link 2',
13
+ 'Source2::192.168.4.10' => 'link 4',
14
+ 'Source3::192.168.2.12' => 'link 2',
15
+ 'Source3::192.168.3.12' => 'link 3',
16
+ 'Source3::192.168.5.12' => 'link 5',
17
+ 'Source3::192.168.6.12' => 'link 6',
18
+ 'Source4::192.168.1.13' => 'link 1',
19
+ 'Source4::192.168.3.12' => 'link 3',
20
+ 'Source5::192.168.6.12' => 'link 6'
21
+ }
22
+
23
+ def initialize(db_name)
24
+ @db_name = db_name
25
+ end
26
+
27
+ def setup_table(stream)
28
+ schema = stream.schema.clone
29
+ schema.insert_column_at(0, :link)
30
+ puts stream.schema.names.inspect
31
+
32
+ t = OMF::OML::OmlTable.new(:ping, schema)
33
+ stream.on_new_tuple() do |v|
34
+ r = v.to_a(true)
35
+ link_name = "#{v[:oml_sender]}::#{v[:dest_addr]}"
36
+ #r.insert 0, LINKS[link_name] || "XXX - #{link_name}"
37
+ r.insert 0, link_name
38
+ t.add_row(r)
39
+ end
40
+ OMF::Web.register_datasource t
41
+ end
42
+
43
+ def run
44
+ ep = OMF::OML::OmlSqlSource.new(@db_name, :check_interval => 3.0)
45
+ ep.on_new_stream() do |stream|
46
+ info "Stream: #{stream.stream_name}"
47
+ if stream.stream_name == 'pingmonitor_myping'
48
+ setup_table(stream)
49
+ end
50
+ end
51
+ ep.run
52
+ self
53
+ end
54
+
55
+ end
56
+ wv = PingDB.new('sqlite://example/simple/data_sources/gimi31.sq3').run()
@@ -0,0 +1,39 @@
1
+
2
+ require 'omf_common/lobject'
3
+ OMF::Common::Loggable.init_log 'simple'
4
+
5
+
6
+ require 'omf_oml/table'
7
+
8
+ def load_environment
9
+ require 'omf-web/content/file_repository'
10
+
11
+
12
+ Dir.glob("#{File.dirname(__FILE__)}/data_sources/*.rb").each do |fn|
13
+ load fn
14
+ end
15
+
16
+ require 'yaml'
17
+ Dir.glob("#{File.dirname(__FILE__)}/widgets/*.yaml").each do |fn|
18
+ h = YAML.load_file(fn)
19
+ if w = h['widget']
20
+ OMF::Web.register_widget w
21
+ else
22
+ MObject.error "Don't know what to do with '#{fn}'"
23
+ end
24
+ end
25
+ end
26
+
27
+
28
+ # Configure the web server
29
+ #
30
+ opts = {
31
+ :app_name => 'simple',
32
+ :page_title => 'Simple Demo',
33
+ :handlers => {
34
+ # delay connecting to databases to AFTER we may run as daemon
35
+ :pre_rackup => lambda { load_environment },
36
+ }
37
+ }
38
+ require 'omf_web'
39
+ OMF::Web.start(opts)
@@ -0,0 +1,38 @@
1
+
2
+
3
+
4
+ # Simple tab showing a line chart with supporting table
5
+ #
6
+
7
+ widget:
8
+ id: main
9
+ name: Main
10
+ top_level: true
11
+ priority: 900
12
+ type: layout/tabbed
13
+ widgets:
14
+
15
+ - name: Ping Line
16
+ type: data/line_chart3
17
+ data_source:
18
+ name: ping
19
+ mapping:
20
+ x_axis:
21
+ property: oml_ts_client
22
+ y_axis:
23
+ property: rtt
24
+ max: 2.0
25
+ group_by: link
26
+ axis:
27
+ x:
28
+ legend: Time (sec)
29
+ y:
30
+ legend: RTT (ms)
31
+
32
+
33
+ - name: Table
34
+ type: data/table2
35
+ data_source:
36
+ name: ping
37
+
38
+
@@ -7,6 +7,12 @@ use ::Rack::ShowExceptions
7
7
  OMF::Web::Runner.instance.life_cycle(:pre_rackup)
8
8
  options = OMF::Web::Runner.instance.options
9
9
 
10
+ require 'omf-web/rack/session_authenticator'
11
+ use OMF::Web::Rack::SessionAuthenticator, #:expire_after => 10,
12
+ #:login_url => '/tab/login',
13
+ :no_session => ['^/resource/', '^/login', '^/logout']
14
+
15
+
10
16
  map "/resource" do
11
17
  require 'omf-web/rack/multi_file'
12
18
  run OMF::Web::Rack::MultiFile.new(options[:static_dirs])
@@ -36,11 +42,33 @@ map "/tab" do
36
42
  run OMF::Web::Rack::TabMapper.new(options)
37
43
  end
38
44
 
39
- map "/widget" do
40
- require 'omf-web/rack/widget_mapper'
41
- run OMF::Web::Rack::WidgetMapper.new(options)
45
+ # map "/widget" do
46
+ # require 'omf-web/rack/widget_mapper'
47
+ # run OMF::Web::Rack::WidgetMapper.new(options)
48
+ # end
49
+
50
+ map '/login' do
51
+ handler = Proc.new do |env|
52
+ # req = ::Rack::Request.new(env)
53
+ # #puts ">>> post?: #{req.post?} - #{req.params.inspect}"
54
+ # if req.post?
55
+ # email = req.params["email"]
56
+ # pw = req.params["password"]
57
+ # remember = req.params["remember"] == "on"
58
+ # Authenticator.signon(email, pw, remember)
59
+ # end
60
+ [301, {'Location' => '/tab', "Content-Type" => ""}, ['Next window!']]
61
+ end
62
+ run handler
42
63
  end
43
64
 
65
+ map '/logout' do
66
+ handler = Proc.new do |env|
67
+ OMF::Web::Rack::SessionAuthenticator.logout
68
+ [301, {'Location' => '/tab', "Content-Type" => ""}, ['Next window!']]
69
+ end
70
+ run handler
71
+ end
44
72
 
45
73
  map "/" do
46
74
  handler = Proc.new do |env|