t2-server 0.0.1

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/LICENCE ADDED
@@ -0,0 +1,29 @@
1
+ Copyright (c) 2010, The University of Manchester, UK.
2
+
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ * Redistributions of source code must retain the above copyright notice,
9
+ this list of conditions and the following disclaimer.
10
+
11
+ * Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ * Neither the names of The University of Manchester nor the names of its
16
+ contributors may be used to endorse or promote products derived from this
17
+ software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+ POSSIBILITY OF SUCH DAMAGE.
data/README.rdoc ADDED
@@ -0,0 +1,21 @@
1
+ = Taverna[http://www.taverna.org.uk/] 2 Server Interaction Gem
2
+
3
+ Authors:: Robert Haines
4
+ Version:: 0.1
5
+ Contact:: mailto:rhaines@manchester.ac.uk
6
+ URL:: http://taverna.sourceforge.net/
7
+ Licence:: BSD (See LICENCE or http://www.opensource.org/licenses/bsd-license.php)
8
+ Copyright:: (c) 2010 The University of Manchester, UK
9
+
10
+
11
+ == Synopsis
12
+
13
+ This is a Ruby library to interface with the Taverna 2 Server REST interface.
14
+
15
+ == Installation
16
+
17
+ [sudo] gem install t2-server
18
+
19
+ == Usage
20
+
21
+ TBC
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (c) 2010, The University of Manchester, UK.
3
+ #
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # * Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # * Neither the names of The University of Manchester nor the names of its
17
+ # contributors may be used to endorse or promote products derived from this
18
+ # software without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ # POSSIBILITY OF SUCH DAMAGE.
31
+ #
32
+ # Author: Robert Haines
33
+
34
+ require 't2server'
35
+ require 'optparse'
36
+
37
+ # set up options
38
+ opts = OptionParser.new do |opt|
39
+ opt.banner = "Usage: delete_all_runs [options] server-address"
40
+ opt.separator ""
41
+ opt.separator " Where server-address is the full URI of the server to"
42
+ opt.separator " connect to, e.g.: http://example.com:8080/taverna"
43
+ opt.separator " and [options] can be:"
44
+ opt.on_tail("-h", "-?", "--help", "Show this message") do
45
+ puts opt
46
+ exit
47
+ end
48
+ opt.on_tail("-v", "--version", "Show the version") do
49
+ puts "Taverna 2 Server Ruby Gem version: #{T2Server::GEM_VERSION}"
50
+ puts "Taverna 2 Server REST API version: #{T2Server::API_VERSION}"
51
+ exit
52
+ end
53
+ end
54
+
55
+ # parse options
56
+ opts.parse!
57
+
58
+ # check for server address
59
+ if ARGV[0] == nil
60
+ puts opts
61
+ exit 1
62
+ end
63
+
64
+ # connect and delete them all!
65
+ T2Server::Server.connect(ARGV[0]).delete_all_runs
data/bin/run_workflow ADDED
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (c) 2010, The University of Manchester, UK.
3
+ #
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # * Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # * Neither the names of The University of Manchester nor the names of its
17
+ # contributors may be used to endorse or promote products derived from this
18
+ # software without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ # POSSIBILITY OF SUCH DAMAGE.
31
+ #
32
+ # Author: Robert Haines
33
+
34
+ require 't2server'
35
+ require 'optparse'
36
+
37
+ # go through the outputs and either print the contents
38
+ # out or save them to a file.
39
+ # if the output is a list, it appears as a directory so
40
+ # all the individual entries must be grabbed from there.
41
+ # server seems to be rather sensitive to slashes, hence
42
+ # all the [...] mucking about.
43
+ def get_outputs(run, pout, dir="")
44
+ outputs = run.ls("out#{dir}")
45
+ outputs.each do |out|
46
+ if out.include? "/"
47
+ get_outputs(run, pout, "#{dir}/#{out[0...-1]}")
48
+ else
49
+ print " #{dir}/#{out} -> "
50
+ data = run.get_output("#{dir[1..-1]}/#{out}")
51
+ if pout
52
+ p data
53
+ else
54
+ filename = "#{dir[1..-1]}/#{out}".gsub('/','-')
55
+ File.open(filename, "w") do |file|
56
+ file.syswrite(data)
57
+ end
58
+ puts "written to file: #{filename}"
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # set up options
65
+ inputs = {}
66
+ wkf_file = ""
67
+ print_output = true
68
+ opts = OptionParser.new do |opt|
69
+ opt.banner = "Usage: run_workflow [options] server-address"
70
+ opt.separator ""
71
+ opt.separator " Where server-address is the full URI of the server to"
72
+ opt.separator " connect to, e.g.: http://example.com:8080/taverna"
73
+ opt.separator " and [options] can be:"
74
+ opt.on("-w WORKFLOW", "--workflow=WORKFLOW", "The workflow to run. If this is not " +
75
+ "specified then the workflow is read from standard input") do |val|
76
+ wkf_file = val
77
+ end
78
+ opt.on("-i INPUT:VALUE", "--input=INPUT:VALUE", "Set input port INPUT to VALUE") do |val|
79
+ input, value = val.chomp.split(':')
80
+ inputs[input] = value
81
+ end
82
+ opt.on("-p", "--[no-]print", "Print outputs to the console. On by default") do |val|
83
+ print_output = val
84
+ end
85
+ opt.on_tail("-h", "-?", "--help", "Show this message") do
86
+ puts opt
87
+ exit
88
+ end
89
+ opt.on_tail("-v", "--version", "Show the version") do
90
+ puts "Taverna 2 Server Ruby Gem version: #{T2Server::GEM_VERSION}"
91
+ puts "Taverna 2 Server REST API version: #{T2Server::API_VERSION}"
92
+ exit
93
+ end
94
+ end
95
+
96
+ # parse options
97
+ opts.parse!
98
+
99
+ # read and check server address
100
+ uri = ARGV.shift
101
+ if uri == nil
102
+ puts opts
103
+ exit 1
104
+ end
105
+
106
+ # read workflow
107
+ if wkf_file == ""
108
+ wkf = ARGF.read
109
+ else
110
+ wkf = IO.read(wkf_file)
111
+ end
112
+
113
+ # create run and set inputs
114
+ run = T2Server::Run.create(uri, wkf)
115
+ puts "Created run with uuid: #{run.uuid}"
116
+
117
+ inputs.each do |input, value|
118
+ puts "Set input '#{input}' to #{value}"
119
+ run.set_input(input, value)
120
+ end
121
+
122
+ # start run and wait until it is finished
123
+ print "Running"
124
+ run.start_and_wait(:progress => true)
125
+
126
+ # get outputs
127
+ stdout = run.stdout
128
+ stderr = run.stderr
129
+ puts "Exitcode: #{run.exitcode}"
130
+ if stdout != "" then puts "Stdout:\n #{stdout}" end
131
+ if stderr != "" then puts "Stderr:\n #{stderr}" end
132
+
133
+ puts "Outputs:"
134
+ get_outputs(run, print_output)
135
+
136
+ # delete run
137
+ run.delete
138
+ puts "Finished and deleted run"
data/lib/t2server.rb ADDED
@@ -0,0 +1,40 @@
1
+ # Copyright (c) 2010, The University of Manchester, UK.
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # * Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # * Neither the names of The University of Manchester nor the names of its
16
+ # contributors may be used to endorse or promote products derived from this
17
+ # software without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+ # POSSIBILITY OF SUCH DAMAGE.
30
+ #
31
+ # Author: Robert Haines
32
+
33
+ require 't2server/xml'
34
+ require 't2server/server'
35
+ require 't2server/run'
36
+
37
+ module T2Server
38
+ GEM_VERSION = "0.0.1"
39
+ API_VERSION = "2.2.0a1"
40
+ end
@@ -0,0 +1,228 @@
1
+ # Copyright (c) 2010, The University of Manchester, UK.
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # * Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # * Neither the names of The University of Manchester nor the names of its
16
+ # contributors may be used to endorse or promote products derived from this
17
+ # software without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+ # POSSIBILITY OF SUCH DAMAGE.
30
+ #
31
+ # Author: Robert Haines
32
+
33
+ require 'rexml/document'
34
+ include REXML
35
+
36
+ module T2Server
37
+
38
+ class Run
39
+
40
+ STATE = {
41
+ :initialized => "Initialized",
42
+ :running => "Operating",
43
+ :finished => "Finished",
44
+ :stopped => "Stopped"
45
+ }
46
+
47
+ private_class_method :new
48
+ attr_reader :uuid
49
+
50
+ def initialize(server, uuid)
51
+ @server = server
52
+ @uuid = uuid
53
+ @workflow = ""
54
+ @baclava = false
55
+
56
+ @links = get_attributes(@server.get_run_attribute(uuid, ""))
57
+ #@links.each {|key, val| puts "#{key}: #{val}"}
58
+ end
59
+
60
+ def Run.create(server, workflow, uuid="")
61
+ if server.class == String
62
+ server = Server.connect(server)
63
+ end
64
+ if uuid == ""
65
+ new(server, server.initialize_run(workflow))
66
+ else
67
+ new(server, uuid)
68
+ end
69
+ end
70
+
71
+ def delete
72
+ @server.delete_run uuid
73
+ end
74
+
75
+ def inputs
76
+ @links[:inputs]
77
+ end
78
+
79
+ def set_input(input, value)
80
+ @server.set_run_input(self, input, value)
81
+ end
82
+
83
+ def set_input_file(input, filename)
84
+ @server.set_run_input_file(self, input, filename)
85
+ end
86
+
87
+ def get_output(output, type="text/plain")
88
+ return unless finished? ### raise exception?
89
+ doc = @server.get_run_attribute(@uuid, "#{@links[:wdir]}/out/#{output}")
90
+ doc
91
+ end
92
+
93
+ def expiry
94
+ @server.get_run_attribute(@uuid, @links[:expiry])
95
+ end
96
+
97
+ def expiry=(date)
98
+ @server.set_run_attribute(@uuid, @links[:expiry], date)
99
+ end
100
+
101
+ def workflow
102
+ if @workflow == ""
103
+ @workflow = @server.get_run_attribute(@uuid, @links[:workflow])
104
+ end
105
+ @workflow
106
+ end
107
+
108
+ def status
109
+ @server.get_run_attribute(@uuid, @links[:status])
110
+ end
111
+
112
+ def start
113
+ @server.set_run_attribute(@uuid, @links[:status], STATE[:running])
114
+ end
115
+
116
+ def start_and_wait(params={})
117
+ interval = params[:interval] || 1
118
+ progress = params[:progress] || false
119
+ keepalive = params[:keepalive] || false ### TODO maybe move out of params
120
+
121
+ # start run and wait
122
+ start
123
+ until finished?
124
+ sleep(interval)
125
+ if progress
126
+ print "."
127
+ STDOUT.flush
128
+ end
129
+ end
130
+
131
+ # tidy up output if there is any
132
+ puts if progress
133
+ end
134
+
135
+ def exitcode
136
+ @server.get_run_attribute(@uuid, @links[:exitcode]).to_i
137
+ end
138
+
139
+ def stdout
140
+ @server.get_run_attribute(@uuid, @links[:stdout])
141
+ end
142
+
143
+ def stderr
144
+ @server.get_run_attribute(@uuid, @links[:stderr])
145
+ end
146
+
147
+ def mkdir(dir)
148
+ @server.make_run_dir(@uuid, @links[:wdir], dir)
149
+ end
150
+
151
+ def upload_file(filename, params={})
152
+ location = params[:dir] || ""
153
+ location = "#{@links[:wdir]}/#{location}"
154
+ rename = params[:rename] || ""
155
+ @server.upload_run_file(@uuid, filename, location, rename)
156
+ end
157
+
158
+ def upload_input_file(input, filename, params={})
159
+ file = upload_file(filename, params)
160
+ set_input_file(input, file)
161
+ end
162
+
163
+ def upload_baclava_file(filename)
164
+ @baclava = true
165
+ rename = upload_file(filename)
166
+ @server.set_run_attribute(@uuid, @links[:baclava], rename)
167
+ end
168
+
169
+ def ls(dir="")
170
+ dir_list = @server.get_run_attribute(@uuid, "#{@links[:wdir]}/#{dir}")
171
+ doc = Document.new(dir_list)
172
+
173
+ # compile a list of directory entries stripping the
174
+ # directory name from the front of each filename
175
+ entries = []
176
+ XPath.each(doc, "//nss:dir", Namespaces::MAP) {|e| entries << "#{e.text.split('/')[-1]}/"}
177
+ XPath.each(doc, "//nss:file", Namespaces::MAP) {|e| entries << e.text.split('/')[-1]}
178
+ entries
179
+ end
180
+
181
+ def initialized?
182
+ status == STATE[:initialized]
183
+ end
184
+
185
+ def running?
186
+ status == STATE[:running]
187
+ end
188
+
189
+ def finished?
190
+ status == STATE[:finished]
191
+ end
192
+
193
+ private
194
+ def get_attributes(desc)
195
+ # first parse out the basic stuff
196
+ links = parse_description(desc)
197
+
198
+ # get inputs
199
+ inputs = @server.get_run_attribute(@uuid, links[:inputs])
200
+ doc = Document.new(inputs)
201
+ nsmap = Namespaces::MAP
202
+ links[:baclava] = "#{links[:inputs]}/" + XPath.first(doc, "//nsr:baclava", nsmap).attributes["href"].split('/')[-1]
203
+
204
+ # set io properties
205
+ links[:io] = "#{links[:listeners]}/io"
206
+ links[:stdout] = "#{links[:io]}/properties/stdout"
207
+ links[:stderr] = "#{links[:io]}/properties/stderr"
208
+ links[:exitcode] = "#{links[:io]}/properties/exitcode"
209
+
210
+ links
211
+ end
212
+
213
+ def parse_description(desc)
214
+ doc = Document.new(desc)
215
+ nsmap = Namespaces::MAP
216
+ {
217
+ :expiry => XPath.first(doc, "//nsr:expiry", nsmap).attributes["href"].split('/')[-1],
218
+ :workflow => XPath.first(doc, "//nsr:creationWorkflow", nsmap).attributes["href"].split('/')[-1],
219
+ :status => XPath.first(doc, "//nsr:status", nsmap).attributes["href"].split('/')[-1],
220
+ :wdir => XPath.first(doc, "//nsr:workingDirectory", nsmap).attributes["href"].split('/')[-1],
221
+ :inputs => XPath.first(doc, "//nsr:inputs", nsmap).attributes["href"].split('/')[-1],
222
+ :output => XPath.first(doc, "//nsr:output", nsmap).attributes["href"].split('/')[-1],
223
+ :securectx => XPath.first(doc, "//nsr:securityContext", nsmap).attributes["href"].split('/')[-1],
224
+ :listeners => XPath.first(doc, "//nsr:listeners", nsmap).attributes["href"].split('/')[-1]
225
+ }
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,324 @@
1
+ # Copyright (c) 2010, The University of Manchester, UK.
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # * Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # * Neither the names of The University of Manchester nor the names of its
16
+ # contributors may be used to endorse or promote products derived from this
17
+ # software without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+ # POSSIBILITY OF SUCH DAMAGE.
30
+ #
31
+ # Author: Robert Haines
32
+
33
+ require 'base64'
34
+ require 'uri'
35
+ require 'net/http'
36
+ require 'rexml/document'
37
+ include REXML
38
+
39
+ module T2Server
40
+ class Server
41
+ private_class_method :new
42
+ attr_reader :uri, :run_limit
43
+
44
+ # list of servers we know about
45
+ @@servers = []
46
+
47
+ def initialize(uri)
48
+ @uri = uri
49
+ uri = URI.parse(uri)
50
+ @host = uri.host
51
+ @port = uri.port
52
+ @base_path = uri.path
53
+ @rest_path = uri.path + "/rest"
54
+ @links = get_server_description
55
+ #@links.each {|key, val| puts "#{key}: #{val}"}
56
+
57
+ # get max runs
58
+ @run_limit = get_attribute(@links[:runlimit]).to_i
59
+
60
+ # initialise run list
61
+ @runs = {}
62
+ @runs = runs
63
+ end
64
+
65
+ def Server.connect(uri)
66
+ # see if we've already got this server
67
+ server = @@servers.find {|s| s.uri == uri}
68
+
69
+ if !server
70
+ # no, so create new one and return it
71
+ server = new(uri)
72
+ @@servers << server
73
+ end
74
+
75
+ server
76
+ end
77
+
78
+ def create_run(workflow)
79
+ uuid = initialize_run(workflow)
80
+ @runs[uuid] = Run.create(self, "", uuid)
81
+ end
82
+
83
+ def initialize_run(workflow)
84
+ request = Net::HTTP::Post.new("#{@links[:runs]}")
85
+ request.content_type = "application/xml"
86
+ response = Net::HTTP.new(@host, @port).start do |http|
87
+ http.request(request, Fragments::WORKFLOW % workflow)
88
+ end
89
+
90
+ case response
91
+ when Net::HTTPCreated
92
+ # return the uuid of the newly created run
93
+ epr = URI.parse(response['location'])
94
+ epr.path[-36..-1]
95
+ when Net::HTTPForbidden
96
+ puts "Sorry, but the server is already running its configured limit of concurrent workflows."
97
+ puts "Please try again later."
98
+ ""
99
+ else
100
+ response_error(response)
101
+ ""
102
+ end
103
+ end
104
+
105
+ def runs
106
+ request = Net::HTTP::Get.new("#{@links[:runs]}")
107
+ response = Net::HTTP.new(@host, @port).start {|http| http.request(request)}
108
+
109
+ case response
110
+ when Net::HTTPOK
111
+ doc = Document.new(response.body)
112
+
113
+ # get list of run uuids
114
+ uuids = []
115
+ XPath.each(doc, "//nsr:run", Namespaces::MAP) do |run|
116
+ uuids << run.attributes["href"].split('/')[-1]
117
+ end
118
+
119
+ # add new runs
120
+ uuids.each do |uuid|
121
+ if !@runs.has_key? uuid
122
+ description = get_run_description(uuid)
123
+ @runs[uuid] = Run.create(self, "", uuid)
124
+ end
125
+ end
126
+
127
+ # clear out the expired runs
128
+ if @runs.length > @run_limit
129
+ @runs.delete_if {|key, val| !uuids.member? key}
130
+ end
131
+
132
+ @runs
133
+ else
134
+ response_error(response)
135
+ end
136
+ end
137
+
138
+ def delete_run(uuid)
139
+ request = Net::HTTP::Delete.new("#{@links[:runs]}/#{uuid}")
140
+ response = Net::HTTP.new(@host, @port).start {|http| http.request(request)}
141
+
142
+ case response
143
+ when Net::HTTPNoContent
144
+ # Success, carry on...
145
+ @runs.delete(uuid)
146
+ true
147
+ when Net::HTTPNotFound
148
+ puts "Cannot find run #{run.uuid}."
149
+ false
150
+ else
151
+ response_error(response)
152
+ end
153
+ end
154
+
155
+ def delete_all_runs
156
+ # first refresh run list
157
+ runs.each_value {|run| run.delete}
158
+ end
159
+
160
+ def set_run_input(run, input, value)
161
+ request = Net::HTTP::Put.new("#{@links[:runs]}/#{run.uuid}/#{run.inputs}/input/#{input}")
162
+ request.content_type = "application/xml"
163
+ response = Net::HTTP.new(@host, @port).start do |http|
164
+ http.request(request, Fragments::RUNINPUTVALUE % value)
165
+ end
166
+
167
+ case response
168
+ when Net::HTTPOK
169
+ # Yay!
170
+ true
171
+ else
172
+ response_error(response)
173
+ end
174
+ end
175
+
176
+ def set_run_input_file(run, input, filename)
177
+ request = Net::HTTP::Put.new("#{@links[:runs]}/#{run.uuid}/#{run.inputs}/input/#{input}")
178
+ request.content_type = "application/xml"
179
+ response = Net::HTTP.new(@host, @port).start do |http|
180
+ http.request(request, Fragments::RUNINPUTFILE % filename)
181
+ end
182
+
183
+ case response
184
+ when Net::HTTPOK
185
+ # Yay!
186
+ true
187
+ else
188
+ response_error(response)
189
+ end
190
+ end
191
+
192
+ def make_run_dir(uuid, root, dir)
193
+ request = Net::HTTP::Post.new("#{@links[:runs]}/#{uuid}/#{root}")
194
+ request.content_type = "application/xml"
195
+ response = Net::HTTP.new(@host, @port).start do |http|
196
+ http.request(request, Fragments::MKDIR % dir)
197
+ end
198
+
199
+ case response
200
+ when Net::HTTPCreated
201
+ # OK, carry on...
202
+ true
203
+ when Net::HTTPForbidden
204
+ puts "Error!", response.body
205
+ false
206
+ when Net::HTTPNotFound
207
+ puts "Cannot find run #{uuid}."
208
+ false
209
+ else
210
+ response_error(response)
211
+ end
212
+ end
213
+
214
+ def upload_run_file(uuid, filename, location, rename)
215
+ contents = Base64.encode64(IO.read(filename))
216
+ rename = filename.split('/')[-1] if rename == ""
217
+ request = Net::HTTP::Post.new("#{@links[:runs]}/#{uuid}/#{location}")
218
+ request.content_type = "application/xml"
219
+ response = Net::HTTP.new(@host, @port).start do |http|
220
+ http.request(request, Fragments::UPLOAD % [rename, contents])
221
+ end
222
+
223
+ case response
224
+ when Net::HTTPCreated
225
+ # Success, return remote name of uploaded file
226
+ rename
227
+ when Net::HTTPForbidden
228
+ puts "Error!", response.body
229
+ else
230
+ response_error(response)
231
+ end
232
+ end
233
+
234
+ def get_run_attribute(uuid, path)
235
+ get_attribute("#{@links[:runs]}/#{uuid}/#{path}")
236
+ end
237
+
238
+ def set_run_attribute(uuid, path, value)
239
+ request = Net::HTTP::Put.new("#{@links[:runs]}/#{uuid}/#{path}")
240
+ request.content_type = "text/plain"
241
+ response = Net::HTTP.new(@host, @port).start {|http| http.request(request, value)}
242
+
243
+ case response
244
+ when Net::HTTPOK
245
+ # OK, so carry on
246
+ true
247
+ when Net::HTTPForbidden
248
+ puts "Error!"
249
+ puts response.body
250
+ false
251
+ when Net::HTTPNotFound
252
+ puts "Cannot find run #{uuid}."
253
+ false
254
+ else
255
+ response_error(response)
256
+ end
257
+ end
258
+
259
+ protected
260
+ def get_attribute(path)
261
+ request = Net::HTTP::Get.new(path)
262
+ response = Net::HTTP.new(@host, @port).start {|http| http.request(request)}
263
+
264
+ case response
265
+ when Net::HTTPOK
266
+ return response.body
267
+ when Net::HTTPNotFound
268
+ puts "Cannot find attribute #{path}."
269
+ else
270
+ response_error(response)
271
+ end
272
+ end
273
+
274
+ private
275
+ def get_server_description
276
+ request = Net::HTTP::Get.new(@rest_path)
277
+ response = Net::HTTP.new(@host, @port).start {|http| http.request(request)}
278
+
279
+ case response
280
+ when Net::HTTPOK
281
+ parse_description(response.body)
282
+ else
283
+ response_error(response)
284
+ end
285
+ end
286
+
287
+ def parse_description(desc)
288
+ doc = Document.new(desc)
289
+ nsmap = Namespaces::MAP
290
+ {
291
+ :runs => URI.parse(XPath.first(doc, "//nsr:runs", nsmap).attributes["href"]).path,
292
+ :runlimit => URI.parse(XPath.first(doc, "//nsr:runLimit", nsmap).attributes["href"]).path,
293
+ :permworkflows => URI.parse(XPath.first(doc, "//nsr:permittedWorkflows", nsmap).attributes["href"]).path,
294
+ :permlisteners => URI.parse(XPath.first(doc, "//nsr:permittedListeners", nsmap).attributes["href"]).path
295
+ }
296
+ end
297
+
298
+ def get_run_description(uuid)
299
+ request = Net::HTTP::Get.new("#{@links[:runs]}/#{uuid}")
300
+ response = Net::HTTP.new(@host, @port).start {|http| http.request(request)}
301
+
302
+ case response
303
+ when Net::HTTPOK
304
+ return response.body
305
+ when Net::HTTPNotFound
306
+ puts "Cannot find run #{uuid}."
307
+ else
308
+ response_error(response)
309
+ end
310
+ end
311
+
312
+ def response_error(response)
313
+ puts "Unnexpected response from Taverna Server!"
314
+ puts "Server is: #{@host}:#{@port}#{@base_path}"
315
+ puts "Response code is: #{response.code}"
316
+ if response.body
317
+ puts "Response body is: \n#{response.body}"
318
+ end
319
+ puts "\nRaw error is: \n#{response.error!}"
320
+ false
321
+ end
322
+
323
+ end
324
+ end
@@ -0,0 +1,51 @@
1
+ # Copyright (c) 2010, The University of Manchester, UK.
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # * Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # * Neither the names of The University of Manchester nor the names of its
16
+ # contributors may be used to endorse or promote products derived from this
17
+ # software without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+ # POSSIBILITY OF SUCH DAMAGE.
30
+ #
31
+ # Author: Robert Haines
32
+
33
+ module T2Server
34
+ module Namespaces
35
+ SERVER = "http://ns.taverna.org.uk/2010/xml/server/"
36
+ REST = SERVER + "rest/"
37
+ MAP = {
38
+ "nss" => Namespaces::SERVER,
39
+ "nsr" => Namespaces::REST
40
+ }
41
+ end
42
+
43
+ module Fragments
44
+ WORKFLOW = "<t2s:scufl xmlns:t2s=\"#{Namespaces::SERVER}\">\n %s\n</t2s:scufl>"
45
+ RUNINPUT = "<t2sr:runInput xmlns:t2sr=\"#{Namespaces::REST}\">\n %s\n</t2sr:runInput>"
46
+ RUNINPUTVALUE = RUNINPUT % "<t2sr:value>%s</t2sr:value>"
47
+ RUNINPUTFILE = RUNINPUT % "<t2sr:file>%s</t2sr:file>"
48
+ UPLOAD = "<t2sr:upload xmlns:t2sr=\"#{Namespaces::REST}\" t2sr:name=\"%s\">\n %s\n</t2sr:upload>"
49
+ MKDIR = "<t2sr:mkdir xmlns:t2sr=\"#{Namespaces::REST}\" t2sr:name=\"%s\" />"
50
+ end
51
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: t2-server
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Robert Haines
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-21 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: This gem provides access to the Taverna 2 Server REST interface from Ruby.
23
+ email: rhaines@manchester.ac.uk
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.rdoc
30
+ - LICENCE
31
+ files:
32
+ - bin/run_workflow
33
+ - bin/delete_all_runs
34
+ - lib/t2server.rb
35
+ - lib/t2server/server.rb
36
+ - lib/t2server/xml.rb
37
+ - lib/t2server/run.rb
38
+ - README.rdoc
39
+ - LICENCE
40
+ has_rdoc: true
41
+ homepage: http://www.taverna.org.uk/
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options: []
46
+
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ hash: 3
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ hash: 3
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ requirements: []
68
+
69
+ rubyforge_project:
70
+ rubygems_version: 1.3.7
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Support for interacting with Taverna 2 Server.
74
+ test_files: []
75
+