omf_web 0.9.7 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/README.md +1 -1
- data/bin/omf_web_demo +3 -0
- data/bin/omf_web_demo.sh +0 -0
- data/doc/tutorial/tut01/hello_world.rb +27 -0
- data/doc/tutorial/tut02/hello_graph.rb +85 -0
- data/doc/tutorial/tut03/hello_database.rb +69 -0
- data/doc/tutorial/tut03/nmetric.sq3 +0 -0
- data/example/bridge/config.ru +2 -1
- data/example/demo/data_sources/downloads.csv +96 -1
- data/example/demo/demo_viz_server.rb +46 -28
- data/example/openflow-gec15/README.md +2 -0
- data/example/openflow-gec15/doc/gec15_topo.png +0 -0
- data/example/openflow-gec15/exp_source.rb +48 -9
- data/example/openflow-gec15/of_viz_server.rb +1 -1
- data/example/openflow-gec15/repository/of-exp.rb +117 -12
- data/example/openflow-gec15/repository/trema-ctl6.rb +2 -2
- data/example/simple/README.md +29 -1
- data/example/simple/data_sources/ping_source.rb +2 -2
- data/lib/irods4r/directory.rb +49 -0
- data/lib/irods4r/file.rb +53 -0
- data/lib/irods4r/icommands.rb +63 -0
- data/lib/irods4r.rb +34 -0
- data/lib/omf-web/content/content_proxy.rb +14 -5
- data/lib/omf-web/content/file_repository.rb +36 -75
- data/lib/omf-web/content/git_repository.rb +39 -35
- data/lib/omf-web/content/irods_repository.rb +191 -0
- data/lib/omf-web/content/repository.rb +84 -21
- data/lib/omf-web/content/static_repository.rb +61 -0
- data/lib/omf-web/data_source_proxy.rb +3 -3
- data/lib/omf-web/rack/session_authenticator.rb +67 -35
- data/lib/omf-web/rack/tab_mapper.rb +2 -1
- data/lib/omf-web/rack/websocket_handler.rb +49 -10
- data/lib/omf-web/session_store.rb +9 -8
- data/lib/omf-web/theme/bright/page.rb +1 -1
- data/lib/omf-web/thin/runner.rb +18 -5
- data/lib/omf-web/version.rb +1 -1
- data/lib/omf-web/widget/text/maruku/output/to_html.rb +8 -2
- data/lib/omf_web.rb +17 -2
- data/omf_web.gemspec +0 -1
- data/share/htdocs/graph/js/abstract_widget.js +3 -1
- data/share/htdocs/graph/js/barchart_brush.js +240 -0
- data/share/htdocs/js/data_source2.js +4 -1
- data/share/htdocs/js/mustache.js +17 -11
- data/share/htdocs/theme/bright/css/bright.css +1 -1
- data/share/htdocs/vendor/{bootstrap-2.1.1 → bootstrap-2.3.1}/css/bootstrap-responsive.css +56 -5
- data/share/htdocs/vendor/bootstrap-2.3.1/css/bootstrap-responsive.min.css +9 -0
- data/share/htdocs/vendor/{bootstrap-2.1.1 → bootstrap-2.3.1}/css/bootstrap.css +856 -472
- data/share/htdocs/vendor/bootstrap-2.3.1/css/bootstrap.min.css +9 -0
- data/share/htdocs/vendor/{bootstrap-2.1.1 → bootstrap-2.3.1}/img/glyphicons-halflings-white.png +0 -0
- data/share/htdocs/vendor/{bootstrap-2.1.1 → bootstrap-2.3.1}/img/glyphicons-halflings.png +0 -0
- data/share/htdocs/vendor/{bootstrap-2.1.1 → bootstrap-2.3.1}/js/bootstrap.js +427 -178
- data/share/htdocs/vendor/bootstrap-2.3.1/js/bootstrap.min.js +6 -0
- data/share/htdocs/vendor/jquery-tipsy/css/tipsy.css +25 -0
- data/share/htdocs/vendor/jquery-tipsy/js/jquery.tipsy.js +258 -0
- metadata +27 -14
- data/bin/omf-web-basic +0 -235
- data/share/htdocs/vendor/.DS_Store +0 -0
- data/share/htdocs/vendor/bootstrap-2.1.1/css/bootstrap-responsive.min.css +0 -9
- data/share/htdocs/vendor/bootstrap-2.1.1/css/bootstrap.min.css +0 -9
- data/share/htdocs/vendor/bootstrap-2.1.1/js/bootstrap.min.js +0 -6
- data/share/htdocs/vendor/jquery-ui-1.8.23/index.html +0 -383
@@ -1,12 +1,117 @@
|
|
1
|
-
defProperty('wired', 'omf.nicta.node2', "Wired node (endpoint)") # baseline.ndz
|
2
|
-
defGroup('ap', property.ap) do |node|
|
3
1
|
|
4
2
|
# wlan0 is not part of OVS
|
5
3
|
# the IP address is the GRE tunnel endpoint
|
6
4
|
node.net.w0.mode = "adhoc"
|
7
5
|
node.net.w0.type = 'g'
|
8
6
|
node.net.w0.channel = "6"
|
9
7
|
node.net.w0.essid = "adhoc"
|
10
8
|
node.net.w0.ip = "172.16.2.1"
|
11
|
-
# wlan1 is part of OVS
|
12
9
|
node.net.w1.mode = "master"
|
13
10
|
node.net.w1.type = 'g'
|
14
11
|
node.net.w1.channel = "10"
|
15
12
|
node.net.w1.essid = "ap"
|
16
13
|
|
17
14
|
onNodeUp do |n|
|
18
15
|
n.exec("ifconfig br-int up; ovs-vsctl set controller br-int connection-mode=out-of-band; ifconfig eth0 0")
|
19
16
|
n.exec("ovs-vsctl add-port br-int gre1 -- set interface gre1 type=gre options:remote_ip=172.16.2.2")
|
20
17
|
n.exec("ovs-vsctl add-port br-int eth0")
|
21
18
|
n.exec("ovs-vsctl add-port br-int wlan1")
|
22
19
|
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")
|
23
20
|
#n.exec("/root/monitor_ovs_ports.rb --oml-id ap --oml-server tcp:norbit.npc.nicta.com.au:5000")
|
24
21
|
end
|
25
22
|
|
26
|
-
defGroup('adhoc', property.adhoc) do |node|
|
27
23
|
|
28
24
|
# wlan0 is not part of OVS
|
29
25
|
# the IP address is the GRE tunnel endpoint
|
30
26
|
node.net.w0.mode = "adhoc"
|
31
27
|
node.net.w0.type = 'g'
|
32
28
|
node.net.w0.channel = "6"
|
33
29
|
node.net.w0.essid = "adhoc"
|
34
30
|
node.net.w0.ip = "172.16.2.2"
|
35
31
|
|
36
32
|
onNodeUp do |n|
|
37
33
|
n.exec("ifconfig br-int up; ovs-vsctl set controller br-int connection-mode=out-of-band; ifconfig eth0 0")
|
38
34
|
n.exec("ovs-vsctl add-port br-int gre1 -- set interface gre1 type=gre options:remote_ip=172.16.2.1")
|
39
35
|
n.exec("ovs-vsctl add-port br-int eth0")
|
40
36
|
#n.exec("/root/monitor_ovs_ports.rb --oml-id adhoc --oml-server tcp:norbit.npc.nicta.com.au:5000")
|
41
37
|
end
|
42
|
-
defGroup('wireless', property.wireless) do |node|
|
43
38
|
# no OVS on this node
|
44
39
|
node.net.w0.mode = "managed"
|
45
40
|
node.net.w0.type = 'g'
|
46
41
|
node.net.w0.channel = "10"
|
47
42
|
node.net.w0.essid = "ap"
|
48
43
|
node.net.w0.ip = "172.16.1.4"
|
49
44
|
node.addApplication("test:app:otg2", :id => 'flow1') do |app|
|
50
45
|
app.setProperty('cbr:rate', 800000)
|
51
46
|
app.setProperty('udp:local_host', '172.16.1.4')
|
52
47
|
app.setProperty('udp:dst_host', '172.16.1.1')
|
53
48
|
app.setProperty('udp:dst_port', 3000)
|
54
49
|
app.measure('udp_out', :samples => 1)
|
55
50
|
end
|
56
51
|
|
57
52
|
node.addApplication("test:app:otg2", :id => 'flow2') do |app|
|
58
53
|
app.setProperty('cbr:rate', 800000)
|
59
54
|
app.setProperty('udp:local_host', '172.16.1.4')
|
60
55
|
app.setProperty('udp:dst_host', '172.16.1.1')
|
61
56
|
app.setProperty('udp:dst_port', 3000)
|
62
57
|
app.measure('udp_out', :samples => 1)
|
63
58
|
end
|
64
|
-
defGroup('wired', property.wired) do |node|
|
65
59
|
node.addApplication("test:app:otr2") do |app|
|
66
60
|
app.setProperty('udp:local_host', '172.16.1.1')
|
67
61
|
app.setProperty('udp:local_port', 3000)
|
68
62
|
app.measure('udp_in', :samples => 1)
|
69
63
|
end
|
70
|
-
# no OVS on this node
|
71
64
|
node.net.e0.ip = "172.16.1.1"
|
72
|
-
onEvent(:ALL_UP) do |event|
|
73
65
|
allGroups.exec("sysctl -w net.ipv6.conf.all.disable_ipv6=1")
|
74
|
-
group("wired").startApplications
|
75
66
|
info "Start your OpenFlow controller now!"
|
76
|
-
while true
|
77
67
|
info "Starting flow 1"
|
78
68
|
group("wireless").startApplication('flow1')
|
79
69
|
sleep 10
|
80
70
|
info "Starting flow 2"
|
81
71
|
group("wireless").startApplication('flow2')
|
82
72
|
sleep 10
|
83
73
|
info "Stopping flow 1. Flow 2 should now re-route over flow 1's path"
|
84
74
|
group("wireless").stopApplication('flow1')
|
85
75
|
sleep 20
|
86
76
|
info "Starting flow 1. Should use secondary path now."
|
87
77
|
group("wireless").startApplication('flow1')
|
88
78
|
sleep 20
|
89
79
|
info "Stopping flow 2"
|
90
80
|
group("wireless").stopApplication('flow2')
|
91
81
|
info "Stopping flow 1"
|
92
82
|
group("wireless").stopApplication('flow1')
|
93
83
|
sleep 10
|
94
84
|
info "Restarting experiment cycle"
|
95
85
|
end
|
96
|
-
|
97
|
-
|
86
|
+
defProperty('wired', 'omf.nicta.node2', "Wired node (endpoint)") # baseline.ndz
|
87
|
+
defProperty('ap', 'omf.nicta.node3', "Access Point") # ovs-5.4.2-precise.ndz
|
88
|
+
defProperty('adhoc', 'omf.nicta.node4', "Secondary path node with ad-hoc link to AP") # ovs-5.4.2-precise.ndz
|
89
|
+
defProperty('wireless', 'omf.nicta.node5', "Wireless node (endpoint)") # baseline.ndz
|
90
|
+
|
91
|
+
defGroup('ap', property.ap) do |node|
|
92
|
+
# wlan0 is not part of OVS
|
93
|
+
# the IP address is the GRE tunnel endpoint
|
94
|
+
node.net.w0.mode = "adhoc"
|
95
|
+
node.net.w0.type = 'g'
|
96
|
+
node.net.w0.channel = "6"
|
97
|
+
node.net.w0.essid = "adhoc"
|
98
|
+
node.net.w0.ip = "172.16.2.1"
|
99
|
+
|
100
|
+
# wlan1 is part of OVS
|
101
|
+
node.net.w1.mode = "master"
|
102
|
+
node.net.w1.type = 'g'
|
103
|
+
node.net.w1.channel = "10"
|
104
|
+
node.net.w1.essid = "ap"
|
105
|
+
end
|
106
|
+
|
107
|
+
defGroup('adhoc', property.adhoc) do |node|
|
108
|
+
# wlan0 is not part of OVS
|
109
|
+
# the IP address is the GRE tunnel endpoint
|
110
|
+
node.net.w0.mode = "adhoc"
|
111
|
+
node.net.w0.type = 'g'
|
112
|
+
node.net.w0.channel = "6"
|
113
|
+
node.net.w0.essid = "adhoc"
|
114
|
+
node.net.w0.ip = "172.16.2.2"
|
115
|
+
end
|
116
|
+
|
117
|
+
defGroup('wireless', property.wireless) do |node|
|
118
|
+
# no OVS on this node
|
119
|
+
node.net.w0.mode = "managed"
|
120
|
+
node.net.w0.type = 'g'
|
121
|
+
node.net.w0.channel = "10"
|
122
|
+
node.net.w0.essid = "ap"
|
123
|
+
node.net.w0.ip = "172.16.1.4"
|
124
|
+
|
125
|
+
node.addApplication("test:app:otg2", :id => 'flow1') do |app|
|
126
|
+
app.setProperty('cbr:rate', 800000)
|
127
|
+
app.setProperty('udp:local_host', '172.16.1.4')
|
128
|
+
app.setProperty('udp:dst_host', '172.16.1.1')
|
129
|
+
app.setProperty('udp:dst_port', 3000)
|
130
|
+
app.measure('udp_out', :samples => 1)
|
131
|
+
end
|
132
|
+
node.addApplication("test:app:otg2", :id => 'flow2') do |app|
|
133
|
+
app.setProperty('cbr:rate', 800000)
|
134
|
+
app.setProperty('udp:local_host', '172.16.1.4')
|
135
|
+
app.setProperty('udp:dst_host', '172.16.1.1')
|
136
|
+
app.setProperty('udp:dst_port', 3000)
|
137
|
+
app.measure('udp_out', :samples => 1)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
defGroup('wired', property.wired) do |node|
|
142
|
+
node.addApplication("test:app:otr2") do |app|
|
143
|
+
app.setProperty('udp:local_host', '172.16.1.1')
|
144
|
+
app.setProperty('udp:local_port', 3000)
|
145
|
+
app.measure('udp_in', :samples => 1)
|
146
|
+
end
|
147
|
+
|
148
|
+
# no OVS on this node
|
149
|
+
node.net.e0.ip = "172.16.1.1"
|
150
|
+
end
|
151
|
+
|
152
|
+
onEvent(:ALL_UP) do |event|
|
153
|
+
allGroups.exec("sysctl -w net.ipv6.conf.all.disable_ipv6=1")
|
154
|
+
|
155
|
+
ovs_init="ovs-vsctl del-br br-int; ovs-vsctl add-br br-int;
|
156
|
+
ovs-vsctl set-controller br-int tcp:10.0.0.200:6633;
|
157
|
+
ovs-vsctl set controller br-int connection-mode=out-of-band; ifconfig eth0 0"
|
158
|
+
|
159
|
+
group("ap").exec(ovs_init)
|
160
|
+
group("adhoc").exec(ovs_init)
|
161
|
+
|
162
|
+
group("ap").exec("ovs-vsctl add-port br-int gre1 -- set interface gre1 type=gre options:remote_ip=172.16.2.2")
|
163
|
+
group("adhoc").exec("ovs-vsctl add-port br-int gre1 -- set interface gre1 type=gre options:remote_ip=172.16.2.1")
|
164
|
+
|
165
|
+
group("ap").exec("ovs-vsctl add-port br-int eth0")
|
166
|
+
group("ap").exec("ovs-vsctl add-port br-int wlan1")
|
167
|
+
group("adhoc").exec("ovs-vsctl add-port br-int eth0")
|
168
|
+
|
169
|
+
group("ap").exec("echo \"<omlc id='AP' exp_id='openflow-demo'><collect url='tcp:10.0.0.200:3004'><stream mp='net_if' name='net_if' samples='1'/></collect><collect url='tcp:10.0.0.200:5000' encoding='text'><stream mp='net_if' name='net_if1' samples='1'/></collect></omlc>\" > /tmp/oml.xml")
|
170
|
+
group("ap").exec("nmetrics-oml2 -s 1 -i eth0 -i wlan0 -i wlan1 --oml-config /tmp/oml.xml")
|
171
|
+
|
172
|
+
#group("ap").exec("/root/monitor_ovs_ports.rb --oml-id ap --oml-server tcp:norbit.npc.nicta.com.au:5000")
|
173
|
+
#group("adhoc").exec("/root/monitor_ovs_ports.rb --oml-id adhoc --oml-server tcp:norbit.npc.nicta.com.au:5000")
|
174
|
+
|
175
|
+
group("wired").startApplications
|
176
|
+
|
177
|
+
info "Start your OpenFlow controller now!"
|
178
|
+
sleep 10
|
179
|
+
|
180
|
+
while true
|
181
|
+
info "Starting flow 1"
|
182
|
+
group("wireless").startApplication('flow1')
|
183
|
+
sleep 10
|
184
|
+
info "Starting flow 2"
|
185
|
+
group("wireless").startApplication('flow2')
|
186
|
+
sleep 10
|
187
|
+
info "Stopping flow 1. Flow 2 should now re-route over flow 1's path"
|
188
|
+
group("wireless").stopApplication('flow1')
|
189
|
+
sleep 20
|
190
|
+
info "Starting flow 1. Should use secondary path now."
|
191
|
+
group("wireless").startApplication('flow1')
|
192
|
+
sleep 20
|
193
|
+
info "Stopping flow 2"
|
194
|
+
group("wireless").stopApplication('flow2')
|
195
|
+
sleep 10
|
196
|
+
info "Stopping flow 1"
|
197
|
+
group("wireless").stopApplication('flow1')
|
198
|
+
sleep 10
|
199
|
+
info "Restarting experiment cycle"
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
data/example/simple/README.md
CHANGED
@@ -1,2 +1,30 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
# Example/Simple
|
3
|
+
|
4
|
+
Essentially the 'Hello World' example of a viz server. Taking data out of a database and putting it into a graph.
|
5
|
+
|
6
|
+
Start the server through:
|
7
|
+
|
8
|
+
ruby -I$OMF_WEB_HOME/lib $OMF_WEB_HOME/example/simple/simple_viz_server.rb start
|
9
|
+
|
10
|
+
where $OMF_WEB_HOME points to the directory containing the __omf_web__ code. You will also need to __omf_oml__ package.
|
11
|
+
You may either install the Gem, or download the source code from https://github.com/mytestbed/omf_oml. In the later case you
|
12
|
+
will need to add a '-I$OMF_OML_HOME/lib' falg to the above command.
|
13
|
+
|
14
|
+
After all that, the console putput should look like:
|
15
|
+
|
16
|
+
DEBUG OmlSqlSource: Opening DB (sqlite:///Users/max/src/omf_web/example/simple/data_sources/gimi31.sq3)
|
17
|
+
DEBUG OmlSqlSource: DB: #<Sequel::SQLite::Database: "sqlite:///Users/max/src/omf_web/example/simple/data_sources/gimi31.sq3">
|
18
|
+
DEBUG OmlSqlSource: Finding tables [:_senders, :_experiment_metadata, :pingmonitor_myping]
|
19
|
+
DEBUG OmlSqlSource: Found table: pingmonitor_myping
|
20
|
+
DEBUG OmlSchema: schema: '[{:name=>:oml_sender, :type=>:string, :title=>"Oml Sender"}, {:name=>:oml_sender_id, :type=>:integer, :title=>"Oml Sender Id"}, {:name=>:oml_seq, :type=>:integer, :title=>"Oml Seq"}, {:name=>:oml_ts_client, :type=>:float, :title=>"Oml Ts Client"}, {:name=>:oml_ts_server, :type=>:float, :title=>"Oml Ts Server"}, {:name=>:dest_addr, :type=>:string, :title=>"Dest Addr"}, {:name=>:ttl, :type=>:integer, :title=>"Ttl"}, {:name=>:rtt, :type=>:float, :title=>"Rtt"}, {:name=>:rtt_unit, :type=>:string, :title=>"Rtt Unit"}]'
|
21
|
+
INFO PingDB: Stream: pingmonitor_myping
|
22
|
+
DEBUG OmlSqlRow-pingmonitor_myping: Read 145/145 rows from 'pingmonitor_myping'
|
23
|
+
INFO Server: >> Thin web server (v1.3.1 codename Triple Espresso)
|
24
|
+
DEBUG Server: >> Debugging ON
|
25
|
+
DEBUG Server: >> Tracing ON
|
26
|
+
INFO Server: >> Maximum connections set to 1024
|
27
|
+
INFO Server: >> Listening on 0.0.0.0:3000, CTRL+C to stop
|
28
|
+
|
29
|
+
This starts a web server on the local machine listening on port 3000. Now point your browser there and you should see the
|
30
|
+
result of a 'ping' experiment.
|
@@ -27,7 +27,7 @@ class PingDB < OMF::Common::LObject
|
|
27
27
|
def setup_table(stream)
|
28
28
|
schema = stream.schema.clone
|
29
29
|
schema.insert_column_at(0, :link)
|
30
|
-
puts stream.schema.names.inspect
|
30
|
+
#puts stream.schema.names.inspect
|
31
31
|
|
32
32
|
t = OMF::OML::OmlTable.new(:ping, schema)
|
33
33
|
stream.on_new_tuple() do |v|
|
@@ -53,4 +53,4 @@ class PingDB < OMF::Common::LObject
|
|
53
53
|
end
|
54
54
|
|
55
55
|
end
|
56
|
-
wv = PingDB.new(
|
56
|
+
wv = PingDB.new("sqlite://#{File.dirname(__FILE__)}/gimi31.sq3").run()
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
require 'irods4r'
|
3
|
+
|
4
|
+
module IRODS4r
|
5
|
+
|
6
|
+
# This class proxies a directory in an iRODS environment
|
7
|
+
#
|
8
|
+
class Directory
|
9
|
+
|
10
|
+
def list()
|
11
|
+
FileEnumerator.new(@dir_name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def file?
|
15
|
+
return false
|
16
|
+
end
|
17
|
+
|
18
|
+
def directory?
|
19
|
+
return true
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(dir_name)
|
23
|
+
@dir_name = dir_name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class FileEnumerator
|
28
|
+
include Enumerable
|
29
|
+
|
30
|
+
def each()
|
31
|
+
while e = @entries.shift
|
32
|
+
e = e.strip
|
33
|
+
if e.start_with? 'C-'
|
34
|
+
# it's a directory
|
35
|
+
yield Directory.new(e[3 .. -1])
|
36
|
+
else
|
37
|
+
yield File.new(::File.join(@dir_name, e))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize(dir_name)
|
43
|
+
r = `ils #{dir_name}`
|
44
|
+
@dir_name = dir_name
|
45
|
+
@entries = r.lines.to_a
|
46
|
+
@entries.shift # the first line is the directory name again
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/irods4r/file.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
require 'irods4r/directory'
|
3
|
+
|
4
|
+
module IRODS4r
|
5
|
+
|
6
|
+
#class NotFoundException < Exception; end
|
7
|
+
class NoFileException < Exception; end
|
8
|
+
class FileExistsException < Exception; end
|
9
|
+
|
10
|
+
# This class proxies a file in an iRODS environment
|
11
|
+
#
|
12
|
+
class File
|
13
|
+
|
14
|
+
# Create a file resource 'path'. If 'must_not_exist' is true,
|
15
|
+
# throw exception if resource already exists.
|
16
|
+
#
|
17
|
+
def self.create(path, must_not_exist = true, opts = {})
|
18
|
+
if must_not_exist
|
19
|
+
raise FileExistsException.new(path) if ICommands.exist?(path)
|
20
|
+
end
|
21
|
+
self.new(path, opts)
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# Return the content of this file
|
26
|
+
def read()
|
27
|
+
ICommands.read(@path)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Write content to this file.
|
31
|
+
#
|
32
|
+
# WARN: This will overwrite any previous content
|
33
|
+
#
|
34
|
+
def write(content)
|
35
|
+
ICommands.write(@path, content)
|
36
|
+
end
|
37
|
+
|
38
|
+
def file?
|
39
|
+
return true
|
40
|
+
end
|
41
|
+
|
42
|
+
def directory?
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
|
46
|
+
attr_reader :path
|
47
|
+
|
48
|
+
private
|
49
|
+
def initialize(path, opts = {})
|
50
|
+
@path = path
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
require 'irods4r'
|
3
|
+
|
4
|
+
module IRODS4r
|
5
|
+
|
6
|
+
# This module interfaces directly with the IRODS system
|
7
|
+
#
|
8
|
+
module ICommands
|
9
|
+
class ICommandException < IRODS4rException; end
|
10
|
+
|
11
|
+
# Return the list of files found at 'path'.
|
12
|
+
def self.ls(path)
|
13
|
+
r = `ils #{path}`
|
14
|
+
#raise ICommandException.new($?) unless $?.exitstatus == 0
|
15
|
+
if r.empty?
|
16
|
+
raise NotFoundException.new("Can't find resource '#{path}'")
|
17
|
+
end
|
18
|
+
r.lines
|
19
|
+
end
|
20
|
+
|
21
|
+
# Return content of resource at 'path'
|
22
|
+
#
|
23
|
+
def self.read(path)
|
24
|
+
f = Tempfile.new('irods4r')
|
25
|
+
`iget -f #{path} #{f.path}`
|
26
|
+
raise ICommandException.new($?) unless $?.exitstatus == 0
|
27
|
+
content = f.read
|
28
|
+
f.close
|
29
|
+
f.unlink
|
30
|
+
content
|
31
|
+
end
|
32
|
+
|
33
|
+
# Return content of resource at 'path'
|
34
|
+
#
|
35
|
+
def self.write(path, content)
|
36
|
+
f = Tempfile.new('irods4r')
|
37
|
+
f.write(content)
|
38
|
+
f.close
|
39
|
+
`iput -f #{f.path} #{path}`
|
40
|
+
raise ICommandException.new($?) unless $?.exitstatus == 0
|
41
|
+
f.unlink
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.exist?(path)
|
45
|
+
`ils #{path}`
|
46
|
+
$?.exitstatus == 0
|
47
|
+
end
|
48
|
+
|
49
|
+
# Copy the resource at 'path' in iRODS to 'file_path'
|
50
|
+
# in the local file system.
|
51
|
+
#
|
52
|
+
def self.export(path, file_path, create_parent_path = true)
|
53
|
+
#puts ">>>> #{path} -> #{file_path}"
|
54
|
+
if create_parent_path
|
55
|
+
require 'fileutils'
|
56
|
+
FileUtils.mkpath ::File.dirname(file_path)
|
57
|
+
end
|
58
|
+
`iget -f #{path} #{file_path}`
|
59
|
+
raise ICommandException.new($?) unless $?.exitstatus == 0
|
60
|
+
end
|
61
|
+
end #module
|
62
|
+
end # module
|
63
|
+
|
data/lib/irods4r.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module IRODS4r
|
4
|
+
|
5
|
+
class IRODS4rException < Exception; end
|
6
|
+
class NotFoundException < IRODS4rException; end
|
7
|
+
class NoDirectoryException < IRODS4rException; end
|
8
|
+
|
9
|
+
# Return a IRODS4r object for 'irodsPath' if it exists.
|
10
|
+
#
|
11
|
+
# @param [String] irodsPath Absolute path into iRODS
|
12
|
+
# @param [Hash] opts Options to use for establishing context
|
13
|
+
# @return [Directory|File]
|
14
|
+
#
|
15
|
+
def self.find(irodsPath = ".", opts = {})
|
16
|
+
r = ICommands.ls(irodsPath)
|
17
|
+
name = r.to_a[0].strip
|
18
|
+
if name.end_with? ':'
|
19
|
+
Directory.new(name[0 ... -1])
|
20
|
+
else
|
21
|
+
File.new(name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return true if 'path' exists
|
26
|
+
def self.exists?(path)
|
27
|
+
ICommands.exist?(path)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
require 'irods4r/directory'
|
32
|
+
require 'irods4r/file'
|
33
|
+
require 'irods4r/icommands'
|
34
|
+
|
@@ -39,10 +39,6 @@ module OMF::Web
|
|
39
39
|
def on_post(req)
|
40
40
|
data = req.POST
|
41
41
|
write(data['content'], data['message'])
|
42
|
-
# if (content = data['content']) != @content
|
43
|
-
# @content = content
|
44
|
-
# @repository.add_and_commit(@content_handle, content, data['message'], req)
|
45
|
-
# end
|
46
42
|
[true.to_json, "text/json"]
|
47
43
|
end
|
48
44
|
|
@@ -62,6 +58,19 @@ module OMF::Web
|
|
62
58
|
end
|
63
59
|
alias :read :content
|
64
60
|
|
61
|
+
# Return a new proxy for a url relative to this one
|
62
|
+
def create_proxy_for_url(url)
|
63
|
+
unless url.match ':'
|
64
|
+
unless url.start_with? '/'
|
65
|
+
# relative
|
66
|
+
ap = @repository.path(@content_descriptor)
|
67
|
+
url = File.join(File.dirname(ap), url)
|
68
|
+
end
|
69
|
+
url = @repository.get_url_for_path(url)
|
70
|
+
end
|
71
|
+
@repository.create_content_proxy_for(url)
|
72
|
+
end
|
73
|
+
|
65
74
|
private
|
66
75
|
|
67
76
|
def initialize(content_descriptor, repository)
|
@@ -72,7 +81,7 @@ module OMF::Web
|
|
72
81
|
@content_id = content_descriptor[:url_key]
|
73
82
|
@content_url = "/_content/#{@content_id}" # That most likley should come from the content handler
|
74
83
|
|
75
|
-
@mime_type = @content_descriptor[:mime_type] ||= repository.mime_type_for_file(content_descriptor
|
84
|
+
@mime_type = @content_descriptor[:mime_type] ||= repository.mime_type_for_file(content_descriptor)
|
76
85
|
@name = content_descriptor[:name]
|
77
86
|
|
78
87
|
@@proxies[@content_id] = self
|
@@ -12,41 +12,39 @@ module OMF::Web
|
|
12
12
|
#
|
13
13
|
class FileContentRepository < ContentRepository
|
14
14
|
|
15
|
-
@@file_repositories = {}
|
16
|
-
|
17
|
-
# Return the repository which is referenced to by elements in 'opts'.
|
18
|
-
#
|
19
|
-
#
|
20
|
-
def self.[](name)
|
21
|
-
unless repo = @@file_repositories[name.to_sym]
|
22
|
-
raise "Unknown file repo '#{name}'"
|
23
|
-
end
|
24
|
-
repo
|
25
|
-
end
|
26
|
-
|
27
|
-
# Register an existing directory to the system. It will be
|
28
|
-
# consulted for all content url's strarting with
|
29
|
-
# 'file:_top_dir_:'. If 'is_primary' is set to true, it will
|
30
|
-
# become the default repo for all newly created content
|
31
|
-
# in this app.
|
32
|
-
#
|
33
|
-
def self.register_file_repo(name, top_dir, is_primary = false)
|
34
|
-
name = name.to_sym
|
35
|
-
if @@file_repositories[name]
|
36
|
-
warn "Ignoring repeated registration of file rep '#{name}'"
|
37
|
-
return
|
38
|
-
end
|
39
|
-
repo = @@file_repositories[name] = FileContentRepository.new(name, top_dir)
|
40
|
-
if is_primary
|
41
|
-
@@primary_repository = repo
|
42
|
-
end
|
43
|
-
end
|
15
|
+
# @@file_repositories = {}
|
16
|
+
#
|
17
|
+
# # Return the repository which is referenced to by elements in 'opts'.
|
18
|
+
# #
|
19
|
+
# #
|
20
|
+
# def self.[](name)
|
21
|
+
# unless repo = @@file_repositories[name.to_sym]
|
22
|
+
# raise "Unknown file repo '#{name}'"
|
23
|
+
# end
|
24
|
+
# repo
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# # Register an existing directory to the system. It will be
|
28
|
+
# # consulted for all content url's strarting with
|
29
|
+
# # 'file:_top_dir_:'. If 'is_primary' is set to true, it will
|
30
|
+
# # become the default repo for all newly created content
|
31
|
+
# # in this app.
|
32
|
+
# #
|
33
|
+
# def self.register_file_repo(name, top_dir, is_primary = false)
|
34
|
+
# name = name.to_sym
|
35
|
+
# if @@file_repositories[name]
|
36
|
+
# warn "Ignoring repeated registration of file rep '#{name}'"
|
37
|
+
# return
|
38
|
+
# end
|
39
|
+
# repo = @@file_repositories[name] = FileContentRepository.new(name, top_dir)
|
40
|
+
# if is_primary
|
41
|
+
# @@primary_repository = repo
|
42
|
+
# end
|
43
|
+
# end
|
44
44
|
|
45
|
-
attr_reader :name, :top_dir
|
46
45
|
|
47
|
-
def initialize(name,
|
48
|
-
|
49
|
-
@top_dir = top_dir
|
46
|
+
def initialize(name, opts)
|
47
|
+
super
|
50
48
|
@url_prefix = "file:#{name}:"
|
51
49
|
end
|
52
50
|
|
@@ -100,48 +98,11 @@ module OMF::Web
|
|
100
98
|
end
|
101
99
|
end
|
102
100
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
#
|
109
|
-
# def find_files(search_pattern, opts = {})
|
110
|
-
# search_pattern = Regexp.new(search_pattern)
|
111
|
-
# tree = @repo.tree
|
112
|
-
# res = []
|
113
|
-
# fs = _find_files(search_pattern, tree, nil, res)
|
114
|
-
#
|
115
|
-
# if (mt = opts[:mime_type])
|
116
|
-
# fs = fs.select { |f| f[:mime_type] == mt }
|
117
|
-
# end
|
118
|
-
# fs
|
119
|
-
# end
|
120
|
-
#
|
121
|
-
# def _find_files(search_pattern, tree, dir_path, res)
|
122
|
-
# tree.contents.each do |e|
|
123
|
-
# d = e.name
|
124
|
-
# long_name = dir_path ? "#{dir_path}/#{d}" : d
|
125
|
-
#
|
126
|
-
# if e.is_a? Grit::Tree
|
127
|
-
# _find_files(search_pattern, e, long_name, res)
|
128
|
-
# else
|
129
|
-
# if long_name.match(search_pattern)
|
130
|
-
# mt = mime_type_for_file(e.name)
|
131
|
-
# path = @url_prefix + long_name
|
132
|
-
# res << {:path => path, :name => e.name,
|
133
|
-
# :mime_type => mt,
|
134
|
-
# #:id => Base64.encode64(long_name).gsub("\n", ''),
|
135
|
-
# :size => e.size, :blob => e.id}
|
136
|
-
# end
|
137
|
-
# # name = e.name
|
138
|
-
# # if File.fnmatch(search_pattern, long_name)
|
139
|
-
# # res << long_name
|
140
|
-
# # end
|
141
|
-
# end
|
142
|
-
# end
|
143
|
-
# res
|
144
|
-
# end
|
101
|
+
# Return a URL for a path in this repo
|
102
|
+
#
|
103
|
+
def get_url_for_path(path)
|
104
|
+
"file:#{path}"
|
105
|
+
end
|
145
106
|
|
146
107
|
def _get_path(content_descr)
|
147
108
|
if content_descr.is_a? String
|