t2-server 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +9 -2
- data/bin/delete_all_runs +6 -1
- data/bin/run_workflow +18 -9
- data/bin/server_info +14 -9
- data/lib/t2server.rb +31 -0
- data/lib/t2server/exceptions.rb +153 -0
- data/lib/t2server/run.rb +215 -31
- data/lib/t2server/server.rb +175 -95
- data/test/tc_paths.rb +60 -0
- data/test/tc_run.rb +72 -0
- data/test/tc_server.rb +71 -0
- data/test/ts_t2server.rb +52 -0
- data/test/workflows/hello.t2flow +21 -0
- metadata +27 -8
data/README.rdoc
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
= Taverna[http://www.taverna.org.uk/] 2 Server Interaction Gem
|
2
2
|
|
3
3
|
Authors:: Robert Haines
|
4
|
-
Gem Version:: 0.0
|
4
|
+
Gem Version:: 0.1.0
|
5
5
|
API Version:: 2.2a1
|
6
6
|
Contact:: mailto:rhaines@manchester.ac.uk
|
7
7
|
URL:: http://taverna.sourceforge.net/
|
@@ -29,7 +29,14 @@ http://github.com/myGrid/t2-server-gem
|
|
29
29
|
|
30
30
|
== Usage
|
31
31
|
|
32
|
-
|
32
|
+
There are two entry points for the T2Server API:
|
33
|
+
* T2Server::Run - Use this for running single jobs on a server.
|
34
|
+
* T2Server::Server - Use this if you are providing a web interface to one or
|
35
|
+
more Taverna 2 Server instances.
|
36
|
+
|
37
|
+
See the rdoc for more information.
|
38
|
+
|
39
|
+
As well as rdoc there are also a couple of example scripts which
|
33
40
|
demonstrate good use of the T2Server API. These are available in the
|
34
41
|
<tt>bin</tt> directory:
|
35
42
|
* run_workflow
|
data/bin/delete_all_runs
CHANGED
data/bin/run_workflow
CHANGED
@@ -47,8 +47,8 @@ def get_outputs(run, pout, dir="")
|
|
47
47
|
if pout
|
48
48
|
p data
|
49
49
|
else
|
50
|
-
# remove
|
51
|
-
filename = "#{dir
|
50
|
+
# strip path and convert remove /'s for file output
|
51
|
+
filename = "#{dir.strip_path}/#{out}".gsub('/', '-')
|
52
52
|
File.open(filename, "w") do |file|
|
53
53
|
file.syswrite(data)
|
54
54
|
end
|
@@ -106,11 +106,17 @@ else
|
|
106
106
|
wkf = IO.read(wkf_file)
|
107
107
|
end
|
108
108
|
|
109
|
-
# create run
|
110
|
-
|
109
|
+
# create run
|
110
|
+
begin
|
111
|
+
run = T2Server::Run.create(uri, wkf)
|
112
|
+
rescue T2Server::T2ServerError => e
|
113
|
+
puts e
|
114
|
+
exit 1
|
115
|
+
end
|
111
116
|
puts "Created run with uuid: #{run.uuid}"
|
112
117
|
puts "Created at #{run.create_time}"
|
113
118
|
|
119
|
+
# set inputs
|
114
120
|
inputs.each do |input, value|
|
115
121
|
puts "Set input '#{input}' to #{value}"
|
116
122
|
run.set_input(input, value)
|
@@ -126,12 +132,15 @@ puts "Finished at #{run.finish_time}"
|
|
126
132
|
# get outputs
|
127
133
|
stdout = run.stdout
|
128
134
|
stderr = run.stderr
|
129
|
-
|
130
|
-
|
131
|
-
if
|
135
|
+
exitcd = run.exitcode
|
136
|
+
puts "Exitcode: #{exitcd}"
|
137
|
+
if stdout != "" then puts "Stdout:\n#{stdout}" end
|
138
|
+
if stderr != "" then puts "Stderr:\n#{stderr}" end
|
132
139
|
|
133
|
-
|
134
|
-
|
140
|
+
if exitcd == 0
|
141
|
+
puts "Outputs:"
|
142
|
+
get_outputs(run, print_output)
|
143
|
+
end
|
135
144
|
|
136
145
|
# delete run
|
137
146
|
run.delete
|
data/bin/server_info
CHANGED
@@ -62,14 +62,19 @@ if uri == nil
|
|
62
62
|
end
|
63
63
|
|
64
64
|
# connect to server and output information
|
65
|
-
|
66
|
-
|
67
|
-
print "
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
65
|
+
begin
|
66
|
+
server = T2Server::Server.connect(uri)
|
67
|
+
print " Server: #{uri}\n"
|
68
|
+
print " Run limit: #{server.run_limit}\n"
|
69
|
+
runs = server.runs
|
70
|
+
print "No. of runs: #{runs.length}\n"
|
71
|
+
if runs.length > 0
|
72
|
+
print " Run list: #{runs[0].uuid} - #{runs[0].expiry}\n"
|
73
|
+
runs[1..-1].each do |run|
|
74
|
+
print " #{run.uuid} - #{run.expiry}\n"
|
75
|
+
end
|
74
76
|
end
|
77
|
+
rescue T2Server::T2ServerError => e
|
78
|
+
puts e
|
79
|
+
exit 1
|
75
80
|
end
|
data/lib/t2server.rb
CHANGED
@@ -31,10 +31,41 @@
|
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
33
|
require 't2server/xml'
|
34
|
+
require 't2server/exceptions'
|
34
35
|
require 't2server/server'
|
35
36
|
require 't2server/run'
|
36
37
|
|
38
|
+
# This is a Ruby library to interface with the Taverna 2 Server REST API.
|
39
|
+
#
|
40
|
+
# There are two API entry points:
|
41
|
+
# * T2Server::Run - Use this for running single jobs on a server.
|
42
|
+
# * T2Server::Server - Use this if you are providing a web interface to a
|
43
|
+
# Taverna 2 Server instance.
|
37
44
|
module T2Server
|
45
|
+
# The version of this library
|
38
46
|
GEM_VERSION = "0.0.4"
|
47
|
+
# The version of the Taverna 2 Server API that this library can interface with
|
39
48
|
API_VERSION = "2.2a1"
|
40
49
|
end
|
50
|
+
|
51
|
+
# Add methods to the String class to operate on file paths.
|
52
|
+
class String
|
53
|
+
# :call-seq:
|
54
|
+
# str.strip_path -> string
|
55
|
+
#
|
56
|
+
# Returns a new String with one leading and one trailing slash
|
57
|
+
# removed from the ends of _str_ (if present).
|
58
|
+
def strip_path
|
59
|
+
self.gsub(/^\//, "").chomp("/")
|
60
|
+
end
|
61
|
+
|
62
|
+
# :call-seq:
|
63
|
+
# str.strip_path! -> str or nil
|
64
|
+
#
|
65
|
+
# Modifies _str_ in place as described for String#strip_path,
|
66
|
+
# returning _str_, or returning +nil+ if no modifications were made.
|
67
|
+
def strip_path!
|
68
|
+
g = self.gsub!(/^\//, "")
|
69
|
+
self.chomp!("/") || g
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,153 @@
|
|
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 'net/http'
|
34
|
+
|
35
|
+
module T2Server
|
36
|
+
# An internal module to collect all the exceptions that we
|
37
|
+
# can't really do anything about ourselves, such as
|
38
|
+
# timeouts and lost connections. This is further wrapped
|
39
|
+
# and exposed in the API as T2Server::ConnectionError below.
|
40
|
+
module InternalHTTPError #:nodoc:
|
41
|
+
end
|
42
|
+
|
43
|
+
# These are the HTTP errors we want to catch.
|
44
|
+
# Add the above exception as an ancestor to them all.
|
45
|
+
[
|
46
|
+
EOFError,
|
47
|
+
SocketError,
|
48
|
+
Timeout::Error,
|
49
|
+
Errno::EINVAL,
|
50
|
+
Errno::ETIMEDOUT,
|
51
|
+
Errno::ECONNRESET,
|
52
|
+
Errno::ECONNREFUSED,
|
53
|
+
Net::HTTPBadResponse,
|
54
|
+
Net::HTTPHeaderSyntaxError,
|
55
|
+
Net::ProtocolError
|
56
|
+
].each {|err| err.send(:include, InternalHTTPError)}
|
57
|
+
|
58
|
+
# This is a superclass for all T2Server exceptions. It is provided as a
|
59
|
+
# useful catch-all for all the internally raised/thrown exceptions.
|
60
|
+
class T2ServerError < RuntimeError
|
61
|
+
end
|
62
|
+
|
63
|
+
# Raised when there is an error with the connection to the server in some
|
64
|
+
# way. This could be due to the server not accepting the connection, the
|
65
|
+
# connection being dropped unexpectedly or a timeout of some sort.
|
66
|
+
class ConnectionError < T2ServerError
|
67
|
+
attr_reader :cause
|
68
|
+
|
69
|
+
# Create a new ConnectionError with the specified cause. The cause to be
|
70
|
+
# passed in should be the exception object that caused the connection
|
71
|
+
# error.
|
72
|
+
def initialize(cause)
|
73
|
+
@cause = cause
|
74
|
+
super "Connection error (#{@cause.class.name}): #{@cause.message}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Raised when there is an unexpected response from the server. This does
|
79
|
+
# not necessarily indicate a problem with the server.
|
80
|
+
class UnexpectedServerResponse < T2ServerError
|
81
|
+
|
82
|
+
# Create a new UnexpectedServerResponse with the specified unexpected
|
83
|
+
# response. The response to be passed in is that which was returned by a
|
84
|
+
# call to Net::HTTP#request.
|
85
|
+
def initialize(response)
|
86
|
+
body = "\n#{response.body}" if response.body
|
87
|
+
super "Unexpected server response: #{response.code}\n#{response.error!}#{body}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Raised when the run that is being operated on cannot be found. If the
|
92
|
+
# expectation is that the run exists then it could have been destroyed by
|
93
|
+
# a timeout or another user.
|
94
|
+
class RunNotFoundError < T2ServerError
|
95
|
+
attr_reader :uuid
|
96
|
+
|
97
|
+
# Create a new RunNotFoundError with the specified UUID.
|
98
|
+
def initialize(uuid)
|
99
|
+
@uuid = uuid
|
100
|
+
super "Could not find run #{@uuid}"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Indicates that the attribute that the user is trying to read/change does
|
105
|
+
# not exist. The attribute could be a server or run attribute.
|
106
|
+
class AttributeNotFoundError < T2ServerError
|
107
|
+
attr_reader :path
|
108
|
+
|
109
|
+
# Create a new AttributeNotFoundError with the path to the erroneous
|
110
|
+
# attribute.
|
111
|
+
def initialize(path)
|
112
|
+
@path = path
|
113
|
+
super "Could not find attribute at #{@path}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# The server is at capacity and cannot accept anymore runs at this time.
|
118
|
+
class ServerAtCapacityError < T2ServerError
|
119
|
+
attr_reader :limit
|
120
|
+
|
121
|
+
# Create a new ServerAtCapacityError with the specified limit for
|
122
|
+
# information.
|
123
|
+
def initialize(limit)
|
124
|
+
@limit = limit
|
125
|
+
super "The server is already running its configured limit of concurrent workflows (#{@limit})"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Access to the entity (run or attribute) is denied. The credentials
|
130
|
+
# supplied are not sufficient or the server does not allow the operation.
|
131
|
+
class AccessForbiddenError < T2ServerError
|
132
|
+
attr_reader :path
|
133
|
+
|
134
|
+
# Create a new AccessForbiddenError with the path to the restricted
|
135
|
+
# attribute.
|
136
|
+
def initialize(path)
|
137
|
+
@path = path
|
138
|
+
super "Access to #{@path} is forbidden. Either you do not have the required credentials or the server does not allow the requested operation"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Raised if an operation is performed on a run when it is in the wrong
|
143
|
+
# state. Trying to start a run if it is the finished state would cause this
|
144
|
+
# exception to be raised.
|
145
|
+
class RunStateError < T2ServerError
|
146
|
+
|
147
|
+
# Create a new RunStateError specifying both the current state and that
|
148
|
+
# which is needed to run the operation.
|
149
|
+
def initialize(current, need)
|
150
|
+
super "The run is in the wrong state (#{current}); it should be '#{need}' to perform that action"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
data/lib/t2server/run.rb
CHANGED
@@ -34,19 +34,29 @@ require 'rexml/document'
|
|
34
34
|
include REXML
|
35
35
|
|
36
36
|
module T2Server
|
37
|
-
|
37
|
+
|
38
|
+
# An interface for easily running jobs on a Taverna 2 Server with minimal
|
39
|
+
# setup and configuration required.
|
40
|
+
#
|
41
|
+
# A run can be in one of three states:
|
42
|
+
# * Initialized: The run has been accepted by the server. It may not yet be
|
43
|
+
# ready to run though as its input port may not have been set.
|
44
|
+
# * Running: The run is being run by the server.
|
45
|
+
# * Finished: The run has finished running and its outputs are available for
|
46
|
+
# download.
|
38
47
|
class Run
|
39
|
-
|
48
|
+
private_class_method :new
|
49
|
+
attr_reader :uuid
|
50
|
+
|
51
|
+
# :stopdoc:
|
40
52
|
STATE = {
|
41
53
|
:initialized => "Initialized",
|
42
54
|
:running => "Operating",
|
43
55
|
:finished => "Finished",
|
44
56
|
:stopped => "Stopped"
|
45
57
|
}
|
46
|
-
|
47
|
-
|
48
|
-
attr_reader :uuid
|
49
|
-
|
58
|
+
|
59
|
+
# New is private but rdoc does not get it right! Hence :stopdoc: section.
|
50
60
|
def initialize(server, uuid)
|
51
61
|
@server = server
|
52
62
|
@uuid = uuid
|
@@ -56,7 +66,16 @@ module T2Server
|
|
56
66
|
@links = get_attributes(@server.get_run_attribute(uuid, ""))
|
57
67
|
#@links.each {|key, val| puts "#{key}: #{val}"}
|
58
68
|
end
|
69
|
+
# :startdoc:
|
59
70
|
|
71
|
+
# :call-seq:
|
72
|
+
# Run.create(server, workflow) -> run
|
73
|
+
#
|
74
|
+
# Create a new run in the +Initialized+ state. The run will be created on
|
75
|
+
# the server with address supplied by _server_. This can either be a
|
76
|
+
# String of the form <tt>http://example.com:8888/blah</tt> or an already
|
77
|
+
# created instance of T2Server::Server. The _workflow_ must also be
|
78
|
+
# supplied as a string in t2flow or scufl format.
|
60
79
|
def Run.create(server, workflow, uuid="")
|
61
80
|
if server.class == String
|
62
81
|
server = Server.connect(server)
|
@@ -67,55 +86,130 @@ module T2Server
|
|
67
86
|
new(server, uuid)
|
68
87
|
end
|
69
88
|
end
|
70
|
-
|
89
|
+
|
90
|
+
# :call-seq:
|
91
|
+
# run.delete
|
92
|
+
#
|
93
|
+
# Delete this run from the server.
|
71
94
|
def delete
|
72
95
|
@server.delete_run uuid
|
73
96
|
end
|
74
|
-
|
97
|
+
|
98
|
+
# :call-seq:
|
99
|
+
# run.inputs -> string
|
100
|
+
#
|
101
|
+
# Return the path to the input ports of this run on the server.
|
75
102
|
def inputs
|
76
103
|
@links[:inputs]
|
77
104
|
end
|
78
|
-
|
105
|
+
|
106
|
+
# :call-seq:
|
107
|
+
# run.set_input(input, value) -> bool
|
108
|
+
#
|
109
|
+
# Set the workflow input port _input_ to _value_.
|
110
|
+
#
|
111
|
+
# Raises RunStateError if the run is not in the +Initialized+ state.
|
79
112
|
def set_input(input, value)
|
113
|
+
state = status
|
114
|
+
raise RunStateError.new(state, STATE[:initialized]) if state != STATE[:initialized]
|
115
|
+
|
80
116
|
@server.set_run_input(self, input, value)
|
81
117
|
end
|
82
|
-
|
118
|
+
|
119
|
+
# :call-seq:
|
120
|
+
# run.set_input_file(input, filename) -> bool
|
121
|
+
#
|
122
|
+
# Set the workflow input port _input_ to use the file at _filename_ as its
|
123
|
+
# input data.
|
124
|
+
#
|
125
|
+
# Raises RunStateError if the run is not in the +Initialized+ state.
|
83
126
|
def set_input_file(input, filename)
|
127
|
+
state = status
|
128
|
+
raise RunStateError.new(state, STATE[:initialized]) if state != STATE[:initialized]
|
129
|
+
|
84
130
|
@server.set_run_input_file(self, input, filename)
|
85
131
|
end
|
86
|
-
|
132
|
+
|
133
|
+
# :call-seq:
|
134
|
+
# run.get_output(output) -> string
|
135
|
+
#
|
136
|
+
# Return the value of the workflow output port _output_.
|
137
|
+
#
|
138
|
+
# Raises RunStateError if the run is not in the +Finished+ state.
|
87
139
|
def get_output(output, type="text/plain")
|
88
|
-
|
140
|
+
state = status
|
141
|
+
raise RunStateError.new(state, STATE[:finished]) if state != STATE[:finished]
|
142
|
+
|
143
|
+
output.strip_path!
|
89
144
|
doc = @server.get_run_attribute(@uuid, "#{@links[:wdir]}/out/#{output}")
|
90
145
|
doc
|
91
146
|
end
|
92
|
-
|
147
|
+
|
148
|
+
# :call-seq:
|
149
|
+
# run.expiry -> string
|
150
|
+
#
|
151
|
+
# Return the expiry time of this run. It is formatted as an ISO-8601
|
152
|
+
# timestamp.
|
93
153
|
def expiry
|
94
154
|
@server.get_run_attribute(@uuid, @links[:expiry])
|
95
155
|
end
|
96
|
-
|
156
|
+
|
157
|
+
# :call-seq:
|
158
|
+
# run.expiry=(time) -> bool
|
159
|
+
#
|
160
|
+
# Set the expiry time of this run to _time_. The format of _time_ should
|
161
|
+
# be an ISO-8601 timestamp.
|
97
162
|
def expiry=(date)
|
98
163
|
@server.set_run_attribute(@uuid, @links[:expiry], date)
|
99
164
|
end
|
100
165
|
|
166
|
+
# :call-seq:
|
167
|
+
# run.workflow -> string
|
168
|
+
#
|
169
|
+
# Get the workflow that this run represents.
|
101
170
|
def workflow
|
102
171
|
if @workflow == ""
|
103
172
|
@workflow = @server.get_run_attribute(@uuid, @links[:workflow])
|
104
173
|
end
|
105
174
|
@workflow
|
106
175
|
end
|
107
|
-
|
176
|
+
|
177
|
+
# :call-seq:
|
178
|
+
# run.status -> string
|
179
|
+
#
|
180
|
+
# Get the status of this run.
|
108
181
|
def status
|
109
182
|
@server.get_run_attribute(@uuid, @links[:status])
|
110
183
|
end
|
111
|
-
|
184
|
+
|
185
|
+
# :call-seq:
|
186
|
+
# run.start
|
187
|
+
#
|
188
|
+
# Start this run on the server.
|
189
|
+
#
|
190
|
+
# Raises RunStateError if the run is not in the +Initialized+ state.
|
112
191
|
def start
|
192
|
+
state = status
|
193
|
+
raise RunStateError.new(state, STATE[:initialized]) if state != STATE[:initialized]
|
194
|
+
|
113
195
|
@server.set_run_attribute(@uuid, @links[:status], STATE[:running])
|
114
196
|
end
|
115
|
-
|
197
|
+
|
198
|
+
# :call-seq:
|
199
|
+
# run.wait(params={})
|
200
|
+
#
|
201
|
+
# Wait (block) for this run to finish. Possible values that can be passed
|
202
|
+
# in via _params_ are:
|
203
|
+
# * :interval - How often (in seconds) to test for run completion.
|
204
|
+
# Default +1+.
|
205
|
+
# * :progress - Print a dot (.) each interval to show that something is
|
206
|
+
# actually happening. Default +false+.
|
207
|
+
#
|
208
|
+
# Raises RunStateError if the run is not in the +Running+ state.
|
116
209
|
def wait(params={})
|
117
|
-
|
118
|
-
|
210
|
+
state = status
|
211
|
+
raise RunStateError.new(state, STATE[:running]) if state != STATE[:running]
|
212
|
+
|
119
213
|
interval = params[:interval] || 1
|
120
214
|
progress = params[:progress] || false
|
121
215
|
keepalive = params[:keepalive] || false ### TODO maybe move out of params
|
@@ -132,42 +226,108 @@ module T2Server
|
|
132
226
|
# tidy up output if there is any
|
133
227
|
puts if progress
|
134
228
|
end
|
135
|
-
|
229
|
+
|
230
|
+
# :call-seq:
|
231
|
+
# run.exitcode -> integer
|
232
|
+
#
|
233
|
+
# Get the return code of the run. Zero indicates success.
|
136
234
|
def exitcode
|
137
235
|
@server.get_run_attribute(@uuid, @links[:exitcode]).to_i
|
138
236
|
end
|
139
|
-
|
237
|
+
|
238
|
+
# :call-seq:
|
239
|
+
# run.stdout -> string
|
240
|
+
#
|
241
|
+
# Get anything that the run printed to the standard out stream.
|
140
242
|
def stdout
|
141
243
|
@server.get_run_attribute(@uuid, @links[:stdout])
|
142
244
|
end
|
143
|
-
|
245
|
+
|
246
|
+
# :call-seq:
|
247
|
+
# run.stderr -> string
|
248
|
+
#
|
249
|
+
# Get anything that the run printed to the standard error stream.
|
144
250
|
def stderr
|
145
251
|
@server.get_run_attribute(@uuid, @links[:stderr])
|
146
252
|
end
|
147
|
-
|
253
|
+
|
254
|
+
# :call-seq:
|
255
|
+
# run.mkdir(dir) -> bool
|
256
|
+
#
|
257
|
+
# Create a directory in the run's working directory on the server. This
|
258
|
+
# could be used to store input data.
|
148
259
|
def mkdir(dir)
|
149
|
-
|
260
|
+
dir.strip_path!
|
261
|
+
if dir.include? ?/
|
262
|
+
# if a path is given then separate the leaf from the
|
263
|
+
# end and add the rest of the path to the wdir link
|
264
|
+
leaf = dir.split("/")[-1]
|
265
|
+
path = dir[0...-(leaf.length + 1)]
|
266
|
+
@server.make_run_dir(@uuid, "#{@links[:wdir]}/#{path}", leaf)
|
267
|
+
else
|
268
|
+
@server.make_run_dir(@uuid, @links[:wdir], dir)
|
269
|
+
end
|
150
270
|
end
|
151
|
-
|
271
|
+
|
272
|
+
# :call-seq:
|
273
|
+
# run.upload_file(filename, params={}) -> string
|
274
|
+
#
|
275
|
+
# Upload a file, with name _filename_, to the server. Possible values that
|
276
|
+
# can be passed in via _params_ are:
|
277
|
+
# * :dir - The directory to upload to. If this is not left blank the
|
278
|
+
# corresponding directory will need to have been created by Run#mkdir.
|
279
|
+
# * :rename - Save the file on the server with a different name.
|
280
|
+
#
|
281
|
+
# The name of the file on the server is returned.
|
152
282
|
def upload_file(filename, params={})
|
153
283
|
location = params[:dir] || ""
|
154
284
|
location = "#{@links[:wdir]}/#{location}"
|
155
285
|
rename = params[:rename] || ""
|
156
286
|
@server.upload_run_file(@uuid, filename, location, rename)
|
157
287
|
end
|
158
|
-
|
288
|
+
|
289
|
+
# :call-seq:
|
290
|
+
# run.upload_input_file(input, filename, params={}) -> string
|
291
|
+
#
|
292
|
+
# Upload a file, with name _filename_, to the server and set it as the
|
293
|
+
# input data for input port _input_. Possible values that can be passed
|
294
|
+
# in via _params_ are:
|
295
|
+
# * :dir - The directory to upload to. If this is not left blank the
|
296
|
+
# corresponding directory will need to have been created by Run#mkdir.
|
297
|
+
# * :rename - Save the file on the server with a different name.
|
298
|
+
#
|
299
|
+
# The name of the file on the server is returned.
|
300
|
+
#
|
301
|
+
# Raises RunStateError if the run is not in the +Initialized+ state.
|
159
302
|
def upload_input_file(input, filename, params={})
|
303
|
+
state = status
|
304
|
+
raise RunStateError.new(state, STATE[:initialized]) if state != STATE[:initialized]
|
305
|
+
|
160
306
|
file = upload_file(filename, params)
|
161
307
|
set_input_file(input, file)
|
162
308
|
end
|
163
|
-
|
309
|
+
|
310
|
+
# :call-seq:
|
311
|
+
# run.upload_baclava_file(filename) -> bool
|
312
|
+
#
|
313
|
+
# Upload a baclava file to be used for the workflow inputs.
|
164
314
|
def upload_baclava_file(filename)
|
315
|
+
state = status
|
316
|
+
raise RunStateError.new(state, STATE[:initialized]) if state != STATE[:initialized]
|
317
|
+
|
165
318
|
@baclava = true
|
166
319
|
rename = upload_file(filename)
|
167
320
|
@server.set_run_attribute(@uuid, @links[:baclava], rename)
|
168
321
|
end
|
169
322
|
|
323
|
+
# :call-seq:
|
324
|
+
# run.ls(dir="") -> [[dirs], [objects]]
|
325
|
+
#
|
326
|
+
# List a directory in the run's workspace on the server. If _dir_ is left
|
327
|
+
# blank then / is listed. The contents of a directory are returned as a
|
328
|
+
# list of two lists, directories and "objects" respectively.
|
170
329
|
def ls(dir="")
|
330
|
+
dir.strip_path!
|
171
331
|
dir_list = @server.get_run_attribute(@uuid, "#{@links[:wdir]}/#{dir}")
|
172
332
|
doc = Document.new(dir_list)
|
173
333
|
|
@@ -180,26 +340,50 @@ module T2Server
|
|
180
340
|
[dirs, files]
|
181
341
|
end
|
182
342
|
|
343
|
+
# :call-seq:
|
344
|
+
# run.initialized? -> bool
|
345
|
+
#
|
346
|
+
# Is this run in the +Initialized+ state?
|
183
347
|
def initialized?
|
184
348
|
status == STATE[:initialized]
|
185
349
|
end
|
186
|
-
|
350
|
+
|
351
|
+
# :call-seq:
|
352
|
+
# run.running? -> bool
|
353
|
+
#
|
354
|
+
# Is this run in the +Running+ state?
|
187
355
|
def running?
|
188
356
|
status == STATE[:running]
|
189
357
|
end
|
190
|
-
|
358
|
+
|
359
|
+
# :call-seq:
|
360
|
+
# run.finished? -> bool
|
361
|
+
#
|
362
|
+
# Is this run in the +Finished+ state?
|
191
363
|
def finished?
|
192
364
|
status == STATE[:finished]
|
193
365
|
end
|
194
|
-
|
366
|
+
|
367
|
+
# :call-seq:
|
368
|
+
# run.create_time -> string
|
369
|
+
#
|
370
|
+
# Get the creation time of this run formatted as an ISO-8601 timestamp.
|
195
371
|
def create_time
|
196
372
|
@server.get_run_attribute(@uuid, @links[:createtime])
|
197
373
|
end
|
198
|
-
|
374
|
+
|
375
|
+
# :call-seq:
|
376
|
+
# run.start_time -> string
|
377
|
+
#
|
378
|
+
# Get the start time of this run formatted as an ISO-8601 timestamp.
|
199
379
|
def start_time
|
200
380
|
@server.get_run_attribute(@uuid, @links[:starttime])
|
201
381
|
end
|
202
382
|
|
383
|
+
# :call-seq:
|
384
|
+
# run.finish_time -> string
|
385
|
+
#
|
386
|
+
# Get the finish time of this run formatted as an ISO-8601 timestamp.
|
203
387
|
def finish_time
|
204
388
|
@server.get_run_attribute(@uuid, @links[:finishtime])
|
205
389
|
end
|