t2-server 0.9.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- # Copyright (c) 2010-2012 The University of Manchester, UK.
2
+ # Copyright (c) 2010-2013 The University of Manchester, UK.
3
3
  #
4
4
  # All rights reserved.
5
5
  #
@@ -39,18 +39,18 @@ include T2Server::CLI
39
39
  # set up options
40
40
  inputs = {}
41
41
  files = {}
42
- options = {}
43
- conn_params, creds = register_options("Usage: t2-run-workflow [options] " +
42
+ options = {:screds => [], :interactions => :show}
43
+ conn_params, creds = register_options("Usage: t2-run-workflow [options] "\
44
44
  "server-address") do |opt|
45
45
  opt.separator " Where server-address is the full URI of the server to"
46
46
  opt.separator " connect to, e.g.: http://example.com:8080/taverna"
47
47
  opt.separator " and [options] can be:"
48
- opt.on("-w WORKFLOW", "--workflow=WORKFLOW", "The workflow to run. If " +
49
- "this is not specified then the workflow is read from standard " +
48
+ opt.on("-w WORKFLOW", "--workflow=WORKFLOW", "The workflow to run. If "\
49
+ "this is not specified then the workflow is read from standard "\
50
50
  "input") do |val|
51
51
  options[:wkf_file] = val.chomp
52
52
  end
53
- opt.on("-i INPUT:VALUE", "--input=INPUT:VALUE", "Set input port INPUT to " +
53
+ opt.on("-i INPUT:VALUE", "--input=INPUT:VALUE", "Set input port INPUT to "\
54
54
  "VALUE") do |val|
55
55
  input, value = val.chomp.split(':', 2)
56
56
  inputs[input] = value
@@ -60,35 +60,78 @@ conn_params, creds = register_options("Usage: t2-run-workflow [options] " +
60
60
  input, filename = val.chomp.split(':', 2)
61
61
  files[input] = filename
62
62
  end
63
- opt.on("-e EXPIRY", "--expiry=EXPIRY", "Set the expiry date/time of this " +
63
+ opt.on("-I LEVEL", "--interactions=LEVEL", "Show, open or ignore any "\
64
+ "workflow interactions. LEVEL can be 'show' (the default), which simply "\
65
+ "lists the interaction URI in the terminal; 'open', which will open the "\
66
+ "interaction in a Web browser; or 'none', which will not check for "\
67
+ "interactions from the workflow at all. This should only be set to "\
68
+ "'none' if you are sure the workflow has no interactions or if you will "\
69
+ "be handling them in some other way.") do |val|
70
+ levels = [:show, :open, :none]
71
+ level = val.downcase.to_sym
72
+ options[:interactions] = levels.include?(level) ? level : :show
73
+ end
74
+ opt.on("-e EXPIRY", "--expiry=EXPIRY", "Set the expiry date/time of this "\
64
75
  "run") do |val|
65
76
  options[:expiry] = Time.parse(val.chomp)
66
77
  end
67
- opt.on("-b BACLAVA", "--baclava-in=BACLAVA", "Set baclava file for input " +
78
+ opt.on("-N NAME", "--name=NAME", "Give this run a name. Supported in "\
79
+ "Taverna Server versions 2.5.0 and up") do |val|
80
+ options[:name] = val.chomp
81
+ end
82
+ opt.on("-c URI::USER:PASS", "--credential=URI::USER:PASS",
83
+ "Provide a credential for a secure remote service. NOTE :: between URI "\
84
+ "and credential") do |val|
85
+ uri, cred = val.chomp.split('::', 2)
86
+ user, pass = cred.chomp.split(':', 2)
87
+ options[:screds] << [uri, user, pass]
88
+ end
89
+ opt.on("-b BACLAVA", "--baclava-in=BACLAVA", "Set baclava file for input "\
68
90
  "port values") do |val|
69
91
  inputs[:baclava] = val
70
92
  end
71
- opt.on("-o", "--baclava-out=BACLAVA", "Return outputs in baclava format." +
93
+ opt.on("-o", "--baclava-out=BACLAVA", "Return outputs in baclava format."\
72
94
  " A filename may be specified or 'out.xml' is used") do |val|
73
95
  options[:baclava_out] = val.chomp
74
96
  end
75
- opt.on("-n", "--no-wait", "Do not wait for workflow to finish, return " +
97
+ opt.on("-n", "--no-wait", "Do not wait for workflow to finish, return "\
76
98
  "once it has started running") do |val|
77
99
  options[:no_wait] = true
78
100
  end
79
- opt.on("-r", "--output-refs", "Return URIs that point to the data items " +
101
+ opt.on("-r", "--output-refs", "Return URIs that point to the data items "\
80
102
  "of the output rather than the data items themselves.") do |val|
81
103
  options[:output_refs] = val
82
104
  end
83
- opt.on("-D", "--delete", "Delete the run from the server when it is " +
84
- "complete. By default the run and its results are preserved. Note that " +
105
+ opt.on("-D", "--delete", "Delete the run from the server when it is "\
106
+ "complete. By default the run and its results are preserved. Note that "\
85
107
  "the run will still be deleted when its expiry time is reached") do |val|
86
108
  options[:delete] = val
87
109
  end
88
- opt.on("-z", "--zip=FILE", "Get the entire working directory of the run " +
110
+ opt.on("-z", "--zip=FILE", "Get the entire working directory of the run "\
89
111
  "in zip format and save it to the provided filename.") do |val|
90
112
  options[:zip_out] = val.chomp
91
113
  end
114
+ opt.on("-x", "--exitcode", "Return the exitcode of the run.") do
115
+ options[:exitcode] = true
116
+ end
117
+ opt.on("--stderr", 'Return the "standard error" output of the run.') do
118
+ options[:stderr] = true
119
+ end
120
+ opt.on("--stdout", 'Return the "standard out" output of the run.') do
121
+ options[:stdout] = true
122
+ end
123
+ end
124
+
125
+ if options[:interactions] == :open
126
+ begin
127
+ require 'launchy'
128
+ rescue LoadError
129
+ puts "\n****\nTo support opening interactions in your Web browser the "\
130
+ "launchy gem must be installed:\n\n$ gem install launchy\n\n"\
131
+ "Interaction URIs will be listed here instead. Please copy and paste "\
132
+ "them into your Web browser to display them.\n****\n\n"
133
+ options[:interactions] = :show
134
+ end
92
135
  end
93
136
 
94
137
  # read and check server address
@@ -107,6 +150,12 @@ begin
107
150
  puts "Created run with identifier: #{run.identifier}"
108
151
  puts "Created at #{run.create_time}"
109
152
 
153
+ # set run name
154
+ if options[:name]
155
+ run.name = options[:name]
156
+ puts "Run name set to '#{run.name}'"
157
+ end
158
+
110
159
  # set run expiry
111
160
  if options[:expiry]
112
161
  run.expiry=(options[:expiry])
@@ -135,43 +184,56 @@ begin
135
184
  end
136
185
  end
137
186
 
187
+ # set remote service credentials
188
+ options[:screds].each do |list|
189
+ run.add_password_credential(list[0], list[1], list[2])
190
+ end
191
+
138
192
  # output baclava?
139
193
  run.request_baclava_output if options[:baclava_out]
140
194
 
141
- # start run and wait until it is finished
142
- run.start
195
+ # try to start run
196
+ unless run.start
197
+ puts "Run could not be started because the server is already running "\
198
+ "its configured maximum number of runs. Please try again later."
199
+ run.delete
200
+ exit 1
201
+ end
143
202
  puts "Started at #{run.start_time}"
144
203
 
145
204
  # bail out if user doesn't want to wait
146
205
  exit 0 if options[:no_wait]
147
206
 
148
- # otherwise wait
149
- print "Running"
207
+ # otherwise wait, but list or open notifications if there are any
208
+ print "Running."
150
209
  until run.finished?
151
210
  sleep(1)
211
+ unless options[:interactions] == :none
212
+ run.notifications(:new_requests).each do |note|
213
+ if options[:interactions] == :open
214
+ Launchy.open note.uri
215
+ else
216
+ puts "\n#{note.uri}\n"
217
+ end
218
+ end
219
+ end
152
220
  print "."
153
221
  $stdout.flush
154
222
  end
155
223
  puts "\nFinished at #{run.finish_time}"
156
224
 
157
225
  # get outputs
158
- stdout = run.stdout
159
- stderr = run.stderr
160
226
  exitcd = run.exitcode
161
- puts "Exitcode: #{exitcd}"
162
- if stdout != "" then puts "Stdout:\n#{stdout}" end
163
- if stderr != "" then puts "Stderr:\n#{stderr}" end
227
+ puts "Exitcode: #{exitcd}" if options[:exitcode] || exitcd != 0
228
+ puts "Stdout:\n#{run.stdout}" if options[:stdout]
229
+ puts "Stderr:\n#{run.stderr}" if options[:stderr]
164
230
 
165
231
  if exitcd == 0
166
232
  if options[:baclava_out]
167
- File.open(options[:baclava_out], "w") do |file|
168
- file.syswrite(run.baclava_output)
169
- end
233
+ run.baclava_output(options[:baclava_out])
170
234
  puts "Baclava file written to '#{options[:baclava_out]}'"
171
235
  elsif options[:zip_out]
172
- File.open(options[:zip_out],"w") do |file|
173
- file.syswrite(run.zip_output)
174
- end
236
+ run.zip_output(options[:zip_out])
175
237
  puts "Zip file written to '#{options[:zip_out]}'"
176
238
  else
177
239
  # go through the outputs and print them out
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- # Copyright (c) 2010-2012 The University of Manchester, UK.
2
+ # Copyright (c) 2010-2013 The University of Manchester, UK.
3
3
  #
4
4
  # All rights reserved.
5
5
  #
@@ -38,15 +38,16 @@ require 'hirb'
38
38
  include T2Server::CLI
39
39
 
40
40
  # set up options
41
- options = {}
41
+ options = { :list => 0 }
42
42
  conn_params, creds = register_options("Usage: t2-server-info [options] " +
43
43
  "server-address") do |opt|
44
44
  opt.separator " Where server-address is the full URI of the server to"
45
45
  opt.separator " connect to, e.g.: http://example.com:8080/taverna"
46
46
  opt.separator " and [options] can be:"
47
47
 
48
- opt.on("-l", "--list", "List details for the runs on this server.") do
49
- options[:list] = true
48
+ opt.on("-l", "--list", "List details for the runs on this server. Repeat "\
49
+ "(e.g. -ll or -lll) to increase the amount of detail shown.") do
50
+ options[:list] += 1
50
51
  end
51
52
  end
52
53
 
@@ -61,14 +62,30 @@ begin
61
62
  puts " Run limit: #{server.run_limit(creds)}"
62
63
  runs = server.runs(creds)
63
64
  puts "No. of runs: #{runs.length}"
64
- if options[:list] && runs.length > 0
65
- puts (Hirb::Helpers::ObjectTable.render runs,
66
- :fields=>[:identifier, :status, :expiry],
67
- :headers=>{:identifier=>'Run ID', :status=>'Status',
68
- :expiry=>'Expiry time (local)'},
69
- :filters=>{:expiry=>[:strftime, "%H:%M:%S %d/%m/%Y"]},
70
- :max_fields=>{:expiry=>19},
71
- :description=>false)
65
+ if options[:list] > 0 && runs.length > 0
66
+ if options[:list] == 1
67
+ fields = [:identifier]
68
+ headers = {:identifier => 'Run ID'}
69
+ lengths = {}
70
+ elsif options[:list] == 2
71
+ fields = [:identifier, :status, :expiry]
72
+ headers = {:identifier => 'Run ID', :status => 'Status',
73
+ :expiry => 'Expiry time (local)'}
74
+ lengths = {:status => 11, :expiry => 19}
75
+ else
76
+ fields = [:identifier, :name, :status, :expiry]
77
+ headers = {:identifier => 'Run ID', :name => "Name",
78
+ :status => 'Status', :expiry => 'Expiry time (local)'}
79
+ lengths = {:identifier => 11, :name => 25, :status => 11,
80
+ :expiry => 19}
81
+ end
82
+
83
+ puts Hirb::Helpers::ObjectTable.render(runs,
84
+ :fields => fields,
85
+ :headers => headers,
86
+ :filters => {:expiry => [:strftime, "%H:%M:%S %d/%m/%Y"]},
87
+ :max_fields => lengths,
88
+ :description => false)
72
89
  end
73
90
  end
74
91
  rescue RuntimeError => e
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (c) 2010-2013 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 'rubygems'
35
+ require 't2-server-cli'
36
+ require 'hirb'
37
+
38
+ include T2Server::CLI
39
+
40
+ # Set up options and workflow inputs.
41
+ inputs = {}
42
+ files = {}
43
+ options = {:number => 5, :backoff => 0, :screds => []}
44
+ conn_params, creds = register_options("Usage: t2-server-stress [options] "\
45
+ "server-address") do |opt|
46
+ opt.separator " Where server-address is the full URI of the server to"
47
+ opt.separator " connect to, e.g.: http://example.com:8080/taverna"
48
+ opt.separator " and [options] can be:"
49
+
50
+ opt.on("-n NUMBER", "--number=NUMBER", "Number of concurrent runs. "\
51
+ "Default 5") do |val|
52
+ options[:number] = val.chomp.to_i
53
+ end
54
+ opt.on("-b NUMBER", "--backoff=NUMBER", "Time (in seconds) to back off "\
55
+ "before starting next run. Default 0") do |val|
56
+ options[:backoff] = val.chomp.to_i
57
+ end
58
+ opt.on("-w WORKFLOW", "--workflow=WORKFLOW", "The workflow to run. If "\
59
+ "this is not specified then the workflow is read from standard "\
60
+ "input") do |val|
61
+ options[:wkf_file] = val.chomp
62
+ end
63
+ opt.on("-i INPUT:VALUE", "--input=INPUT:VALUE", "Set input port INPUT to "\
64
+ "VALUE") do |val|
65
+ input, value = val.chomp.split(':', 2)
66
+ inputs[input] = value
67
+ end
68
+ opt.on("-f INPUT:FILE", "--input-file=INPUT:FILE",
69
+ "Set input port INPUT to use the contents of FILE as its input") do |val|
70
+ input, filename = val.chomp.split(':', 2)
71
+ files[input] = filename
72
+ end
73
+ opt.on("-K", "--keep-runs",
74
+ "Do not delete the runs at the end of the test") do
75
+ options[:keep] = true
76
+ end
77
+ opt.on("-c URI::USER:PASS", "--credential=URI::USER:PASS",
78
+ "Provide a credential for a secure remote service. NOTE :: between URI "\
79
+ "and credential") do |val|
80
+ uri, cred = val.chomp.split('::', 2)
81
+ user, pass = cred.chomp.split(':', 2)
82
+ options[:screds] << [uri, user, pass]
83
+ end
84
+ end
85
+
86
+ # Read and check server address and credentials.
87
+ uri, creds = parse_address(ARGV.shift, creds)
88
+
89
+ # Read workflow and ensure that it is not empty.
90
+ if options[:wkf_file]
91
+ wkf = IO.read(options[:wkf_file])
92
+ else
93
+ wkf = ARGF.read
94
+ end
95
+ exit 1 if wkf == ""
96
+
97
+ # Connect to server and check it's in a good state.
98
+ server = T2Server::Server.new(uri, conn_params)
99
+ puts "\nConnected to server at #{server.uri}"
100
+
101
+ current_runs = server.runs(creds)
102
+ unless current_runs.length == 0
103
+ puts "\nServer already has runs on it. Please clear out all runs before "\
104
+ "running the stress tests."
105
+ exit 1
106
+ end
107
+
108
+ run_limit = server.run_limit(creds)
109
+ unless run_limit >= options[:number]
110
+ puts "\nYou have asked for more concurrent runs than this server has been "\
111
+ "configured to allow. Please set the number to #{run_limit} or less."
112
+ exit 1
113
+ end
114
+
115
+ puts "\nInitializing #{options[:number]} runs and setting inputs."
116
+ runs = []
117
+ options[:number].times do
118
+ server.create_run(wkf, creds) do |run|
119
+ # Set inputs.
120
+ run.input_ports.each_value do |port|
121
+ input = port.name
122
+ if inputs.include? input
123
+ port.value = inputs[input]
124
+ elsif files.include? input
125
+ port.file = files[input]
126
+ else
127
+ puts "Input '#{input}' has not been given, exiting."
128
+ run.delete
129
+ exit 1
130
+ end
131
+ end
132
+
133
+ options[:screds].each do |list|
134
+ run.add_password_credential(list[0], list[1], list[2])
135
+ end
136
+
137
+ runs << run
138
+ end
139
+ end
140
+
141
+ puts "\nStarting runs with #{options[:backoff]} seconds back-off time between."
142
+
143
+ w_start = Time.now
144
+ runs.each do |run|
145
+ r_start = Time.now
146
+ while !run.start
147
+ puts "Server has reached configured maximum of concurrently running "\
148
+ "runs. Backing off for 10 seconds before retrying..."
149
+ sleep(10)
150
+ end
151
+ r_started = Time.now
152
+ puts "Run started at #{r_started} and took #{r_started - r_start} seconds to start."
153
+ sleep options[:backoff] if options[:backoff] > 0
154
+ end
155
+
156
+ puts "\nWaiting for runs to finish."
157
+
158
+ while runs.count { |run| run.finished? } < options[:number] do
159
+ sleep(5)
160
+ end
161
+ w_end = Time.now
162
+
163
+ puts "\nRuns finished.\n\nRun times:"
164
+
165
+ total = 0
166
+ runs.each do |run|
167
+ time = run.finish_time - run.start_time
168
+ total += time
169
+ puts time
170
+ end
171
+
172
+ average = total / options[:number]
173
+ puts "\nAverage time: #{average}"
174
+ w_time = w_end - w_start
175
+ puts "Wallclock time: #{w_time}"
176
+
177
+ unless options[:keep]
178
+ puts "\nDeleting runs."
179
+ runs.each do |run|
180
+ run.delete
181
+ end
182
+ end
183
+
184
+ puts "\nDone."