class T2Server::Run

An interface for easily running jobs on a Taverna 2 Server with minimal setup and configuration required.

A run can be in one of three states:

Attributes

id[R]

The identifier of this run on the server.

identifier[R]

The identifier of this run on the server.

server[R]

The server instance that this run is hosted on.

Public Class Methods

create(server, workflow) → run click to toggle source
create(server, workflow, connection_parameters) → run
create(server, workflow, user_credentials) → run
create(server, workflow, ...) {|run| ...}

Create a new run in the :initialized state. The run will be created on the server with address supplied by server. This can either be a String of the form http://example.com:8888/blah or an already created instance of T2Server::Server. The workflow may be supplied as a string in t2flow format, a filename or a File or IO object. User credentials and connection parameters can be supplied if required but are both optional. If server is an instance of T2Server::Server then connection_parameters will be ignored.

This method will yield the newly created Run if a block is given.

# File lib/t2-server/run.rb, line 155
def Run.create(server, workflow, *rest)
  credentials = nil
  uri = nil
  conn_params = nil

  rest.each do |param|
    case param
    when URI
      uri = param
    when ConnectionParameters
      conn_params = param
    when HttpCredentials
      credentials = param
    end
  end

  # If server is not a Server object, get one.
  server = Server.new(server, conn_params) if server.class != Server

  # If we are not given a URI to a run then we know we need to create one.
  uri ||= server.initialize_run(workflow, credentials)

  # Create the run object and yield it if necessary.
  run = new(server, uri, credentials)
  yield(run) if block_given?
  run
end

Public Instance Methods

add_keypair_credential(service_uri, filename, password, click to toggle source
alias = "Imported Certificate", type = :pkcs12) → URI

Provide a client certificate credential for the secure service at the specified URI. You will need to provide the password to unlock the private key. You will also need to provide the ‘alias’ or ‘friendlyName’ of the key you wish to use if it differs from the default. The URI of the credential on the server is returned. Only the owner of a run may supply credentials for it. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 833
def add_keypair_credential(uri, filename, password,
                           name = "Imported Certificate", type = :pkcs12)
  return unless owner?

  type = type.to_s.upcase
  contents = Base64.encode64(IO.read(filename))

  # basic uri checks
  uri = _check_cred_uri(uri)

  value = xml_keypair_cred_fragment(uri, name, contents, type, password)

  @server.create(links[:sec_creds], value, "application/xml", @credentials)
end
add_password_credential(service_uri, username, password) → URI click to toggle source

Provide a username and password credential for the secure service at the specified URI. The URI of the credential on the server is returned. Only the owner of a run may supply credentials for it. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 803
def add_password_credential(uri, username, password)
  return unless owner?

  # Is this a new credential, or an update?
  cred_uri = credential(uri)

  # basic uri checks
  uri = _check_cred_uri(uri)

  value = xml_password_cred_fragment(uri, username, password)

  if cred_uri.nil?
    @server.create(links[:sec_creds], value, "application/xml",
      @credentials)
  else
    @server.update(cred_uri, value, "application/xml", @credentials)
  end
end
add_trust(filename, type = :x509) → URI click to toggle source

Add a trusted identity (server public key) to verify peers when using https connections to Web Services. The URI of the trust on the server is returned. Only the owner of a run may add a trust. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 913
def add_trust(filename, type = :x509)
  return unless owner?

  type = type.to_s.upcase

  contents = Base64.encode64(IO.read(filename))

  value = xml_trust_fragment(contents, type)
  @server.create(links[:sec_trusts], value, "application/xml", @credentials)
end
baclava_input = filename → true or false click to toggle source

Use a baclava file for the workflow inputs.

# File lib/t2-server/run.rb, line 470
def baclava_input=(filename)
  state = status
  raise RunStateError.new(state, :initialized) if state != :initialized

  file = upload_file(filename)
  result = @server.update(links[:baclava], file, "text/plain", @credentials)

  @baclava_in = true if result

  result
end
baclava_input? → true or false click to toggle source

Have the inputs to this run been set by a baclava document?

# File lib/t2-server/run.rb, line 510
def baclava_input?
  @baclava_in
end
baclava_output → string click to toggle source
baclava_output(filename) → fixnum
baclava_output(stream) → fixnum
baclava_output {|chunk| ...}

Get the outputs of this run in baclava format. This can only be done if the output has been requested in baclava format by set_baclava_output before starting the run.

Calling this method with no parameters will simply return a blob of XML data. Providing a filename will stream the data directly to that file and return the number of bytes written. Passing in an object that has a write method (for example, an instance of File or IO) will stream the XML data directly to that object and return the number of bytes that were streamed. Passing in a block will allow access to the underlying data stream:

run.baclava_output do |chunk|
  print chunk
end

Raises RunStateError if the run has not finished running.

# File lib/t2-server/run.rb, line 554
def baclava_output(param = nil, &block)
  raise ArgumentError,
    'both a parameter and block given for baclava_output' if param && block

  state = status
  raise RunStateError.new(state, :finished) if state != :finished

  raise AccessForbiddenError.new("baclava output") if !@baclava_out

  baclava_uri = Util.append_to_uri_path(links[:wdir], BACLAVA_FILE)
  download_or_stream(param, baclava_uri, "*/*", &block)
end
create_time → string click to toggle source

Get the creation time of this run as an instance of class Time.

# File lib/t2-server/run.rb, line 703
def create_time
  Time.parse(@server.read(links[:createtime], "text/plain", @credentials))
end
credential(service_uri) → URI click to toggle source

Return the URI of the credential set for the supplied service, if any. Only the owner of a run may query its credentials. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 876
def credential(uri)
  return unless owner?

  credentials[uri]
end
credentials → hash click to toggle source

Return a hash (service_uri => credential_uri) of all the credentials provided for this run. Only the owner of a run may query its credentials. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 854
def credentials
  return unless owner?

  creds = {}
  doc = xml_document(@server.read(links[:sec_creds], "application/xml",
    @credentials))

  xpath_find(doc, @@xpaths[:sec_cred]).each do |c|
    uri = URI.parse(xml_node_content(xpath_first(c, @@xpaths[:sec_suri])))
    cred_uri = URI.parse(xml_node_attribute(c, "href"))
    creds[uri] = cred_uri
  end

  creds
end
delete click to toggle source

Delete this run from the server.

# File lib/t2-server/run.rb, line 230
def delete
  @server.delete(@uri, @credentials)
  @deleted = true
end
delete_all_credentials → true or false click to toggle source

Delete all credentials associated with this workflow run. Only the owner of a run may delete its credentials. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 900
def delete_all_credentials
  return unless owner?

  @server.delete(links[:sec_creds], @credentials)
end
delete_all_trusts → true or false click to toggle source

Delete all trusted identities associated with this workflow run. Only the owner of a run may delete its trusts. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 964
def delete_all_trusts
  return unless owner?

  @server.delete(links[:sec_trusts], @credentials)
end
delete_credential(service_uri) → true or false click to toggle source

Delete the credential that has been provided for the specified service. Only the owner of a run may delete its credentials. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 888
def delete_credential(uri)
  return unless owner?

  @server.delete(credentials[uri], @credentials)
end
delete_trust(URI) → true or false click to toggle source

Delete the trust with the provided URI. Only the owner of a run may delete its trusts. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 952
def delete_trust(uri)
  return unless owner?

  @server.delete(uri, @credentials)
end
deleted? → true or false click to toggle source

Has this run been deleted from the server?

# File lib/t2-server/run.rb, line 239
def deleted?
  @deleted
end
error? → true or false click to toggle source

Are there errors in this run’s outputs? Returns false if the run is not finished yet.

# File lib/t2-server/run.rb, line 689
def error?
  return false unless finished?

  output_ports.values.each do |output|
    return true if output.error?
  end

  false
end
exitcode → fixnum click to toggle source

Get the return code of the run. Zero indicates success.

# File lib/t2-server/run.rb, line 378
def exitcode
  @server.read(links[:exitcode], "text/plain", @credentials).to_i
end
expiry → string click to toggle source

Return the expiry time of this run as an instance of class Time.

# File lib/t2-server/run.rb, line 284
def expiry
  Time.parse(@server.read(links[:expiry], "text/plain", @credentials))
end
expiry = time → true or false click to toggle source

Set the expiry time of this run to time. time should either be a Time object or something that the Time class can parse. If the value given does not specify a date then today’s date will be assumed. If a time/date in the past is specified, the expiry time will not be changed.

# File lib/t2-server/run.rb, line 295
def expiry=(time)
  unless time.instance_of? Time
    time = Time.parse(time)
  end

  # need to massage the xmlschema format slightly as the server cannot
  # parse timezone offsets with a colon (eg +00:00)
  date_str = time.xmlschema(2)
  date_str = date_str[0..-4] + date_str[-2..-1]
  @server.update(links[:expiry], date_str, "text/plain", @credentials)
end
finish_time → string click to toggle source

Get the finish time of this run as an instance of class Time.

# File lib/t2-server/run.rb, line 719
def finish_time
  Time.parse(@server.read(links[:finishtime], "text/plain", @credentials))
end
finished? → true or false click to toggle source

Is this run in the :finished state?

# File lib/t2-server/run.rb, line 680
def finished?
  status == :finished
end
generate_baclava_output → true or false click to toggle source

Set the server to save the outputs of this run in baclava format. This must be done before the run is started.

# File lib/t2-server/run.rb, line 487
def generate_baclava_output
  return if @baclava_out
  state = status
  raise RunStateError.new(state, :initialized) if state != :initialized

  @baclava_out = @server.update(links[:output], BACLAVA_FILE, "text/plain",
    @credentials)
end
generate_baclava_output? → true or false click to toggle source

Has this run been set to return results in baclava format?

# File lib/t2-server/run.rb, line 518
def generate_baclava_output?
  @baclava_out
end
generate_provenance(toggle = true) → true or false click to toggle source

Toggle the generation of provenance for this run on or off. This must be done before the run is started. Once the run has completed provenance can be retrieved with #provenance.

Requesting baclava output for a run will override this setting.

# File lib/t2-server/run.rb, line 575
def generate_provenance(toggle = true)
  return @provenance if @provenance == toggle || links[:gen_prov].nil?
  state = status
  raise RunStateError.new(state, :initialized) if state != :initialized

  result = @server.update(links[:gen_prov], toggle.to_s, "text/plain",
    @credentials)

  # If changing the setting worked then return the new setting, otherwise
  # return the old one.
  @provenance = result ? toggle : @provenance
end
generate_provenance? → true or false click to toggle source

Has this run been set to generate provenance output?

# File lib/t2-server/run.rb, line 592
def generate_provenance?
  @provenance
end
grant_permission(username, permission) → username click to toggle source

Grant the user the stated permission. A permission can be one of :none, :read, :update or :destroy. Only the owner of a run may grant permissions on it. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 742
def grant_permission(username, permission)
  return unless owner?

  value = xml_permissions_fragment(username, permission.to_s)
  @server.create(links[:sec_perms], value, "application/xml", @credentials)
end
initialized? → true or false click to toggle source

Is this run in the :initialized state?

# File lib/t2-server/run.rb, line 664
def initialized?
  status == :initialized
end
input_port(port) → port click to toggle source

Get port.

# File lib/t2-server/run.rb, line 255
def input_port(port)
  input_ports[port]
end
input_ports → hash click to toggle source

Return a hash (name, port) of all the input ports this run expects.

# File lib/t2-server/run.rb, line 247
def input_ports
  @input_ports ||= _get_input_port_info
end
log → string click to toggle source
log(filename) → fixnum
log(stream) → fixnum
log {|chunk| ...}

Get the internal Taverna Server log from this run.

Calling this method with no parameters will simply return a text string. Providing a filename will stream the data directly to that file and return the number of bytes written. Passing in an object that has a write method (for example, an instance of File or IO) will stream the text directly to that object and return the number of bytes that were streamed. Passing in a block will allow access to the underlying data stream:

run.log do |chunk|
  print chunk
end
# File lib/t2-server/run.rb, line 416
def log(param = nil, &block)
  raise ArgumentError,
    'both a parameter and block given for baclava_output' if param && block

  download_or_stream(param, links[:logfile], "text/plain", &block)
end
mkdir(dir) → true or false click to toggle source

Create a directory in the run’s working directory on the server. This could be used to store input data.

# File lib/t2-server/run.rb, line 428
def mkdir(dir)
  dir = Util.strip_path_slashes(dir)

  @server.mkdir(links[:wdir], dir, @credentials)
end
name → String click to toggle source

Get the name of this run.

Initially this name is derived by Taverna Server from the name annotation in the workflow file and the time at which the run was initialized. It can be set with the name= method.

For Taverna Server versions prior to version 2.5.0 this is a no-op and the empty string is returned for consistency.

# File lib/t2-server/run.rb, line 203
def name
  return "" if links[:name].nil?
  @server.read(links[:name], "text/plain", @credentials)
end
name = new_name → bool click to toggle source

Set the name of this run. true is returned upon success. The maximum length of names supported by the server is 48 characters. Anything longer than 48 characters will be truncated before upload.

Initially this name is derived by Taverna Server from the name annotation in the workflow file and the time at which the run was initialized.

For Taverna Server versions prior to version 2.5.0 this is a no-op but true is still returned for consistency.

# File lib/t2-server/run.rb, line 221
def name=(name)
  return true if links[:name].nil?
  @server.update(links[:name], name[0...48], "text/plain", @credentials)
end
notifications(type = :new_requests) → array click to toggle source

Poll the server for notifications and return them in a list. Returns the empty list if there are none, or if the server does not support the Interaction Service.

The type parameter is used to select which types of notifications are returned as follows:

  • :requests - Interaction requests.

  • :replies - Interaction replies.

  • :new_requests - Interaction requests that are new since the last time they were polled (default).

  • :all - All interaction requests and replies.

# File lib/t2-server/run.rb, line 1028
def notifications(type = :new_requests)
  return [] if links[:feed].nil?

  @interaction_reader ||= Interaction::Feed.new(self)

  if type == :new_requests
    @interaction_reader.new_requests
  else
    @interaction_reader.notifications(type)
  end
end
output_port(port) → port click to toggle source

Get output port port.

# File lib/t2-server/run.rb, line 276
def output_port(port)
  output_ports[port] if finished?
end
output_ports → hash click to toggle source

Return a hash (name, port) of all the output ports this run has. Until the run is finished this method will return nil.

# File lib/t2-server/run.rb, line 264
def output_ports
  if finished? && @output_ports.nil?
    @output_ports = _get_output_port_info
  end

  @output_ports
end
owner → string click to toggle source

Get the username of the owner of this run. The owner is the user who created the run on the server.

# File lib/t2-server/run.rb, line 188
def owner
  @owner ||= _get_run_owner
end
owner? → true or false click to toggle source

Are the credentials being used to access this run those of the owner? The owner of the run can give other users certain access rights to their runs but only the owner can change these rights - or even see what they are. Sometimes it is useful to know if the user accessing the run is actually the owner of it or not.

# File lib/t2-server/run.rb, line 731
def owner?
  @credentials.username == owner
end
permission(username) → permission click to toggle source

Return the permission granted to the supplied username, if any. Only the owner of a run may query its permissions. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 777
def permission(username)
  return unless owner?

  permissions[username] || :none
end
permissions → hash click to toggle source

Return a hash (username => permission) of all the permissions set for this run. Only the owner of a run may query its permissions. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 755
def permissions
  return unless owner?

  perms = {}
  doc = xml_document(@server.read(links[:sec_perms], "application/xml",
    @credentials))

  xpath_find(doc, @@xpaths[:sec_perm]).each do |p|
    user = xml_node_content(xpath_first(p, @@xpaths[:sec_uname]))
    perm = xml_node_content(xpath_first(p, @@xpaths[:sec_uperm])).to_sym
    perms[user] = perm
  end

  perms
end
provenance → binary blob click to toggle source
provenance(filename) → fixnum
provenance(stream) → fixnum
provenance {|chunk| ...}

Get the provenance of this run from the server in zip format.

Calling this method with no parameters will simply return a blob of zipped data. Providing a filename will stream the data directly to that file and return the number of bytes written. Passing in an object that has a write method (for example, an instance of File or IO) will stream the data directly to that object and return the number of bytes that were streamed. Passing in a block will allow access to the underlying data stream:

run.provenance do |chunk|
  print chunk
end

Raises RunStateError if the run has not finished running.

# File lib/t2-server/run.rb, line 616
def provenance(param = nil, &block)
  raise ArgumentError,
    'both a parameter and block given for provenance' if param && block

  state = status
  raise RunStateError.new(state, :finished) if state != :finished

  raise AccessForbiddenError.new("provenance") unless @provenance
  download_or_stream(param, links[:run_bundle], "*/*", &block)
end
revoke_permission(username) → true or false click to toggle source

Revoke whatever permissions that have been granted to the user. Only the owner of a run may revoke permissions on it. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 789
def revoke_permission(username)
  return unless owner?

  uri = Util.append_to_uri_path(links[:sec_perms], username)
  @server.delete(uri, @credentials)
end
running? → true or false click to toggle source

Is this run in the :running state?

# File lib/t2-server/run.rb, line 672
def running?
  status == :running
end
start → true or false click to toggle source

Start this run on the server. Returns true if the run was started, false otherwise.

Raises RunStateError if the run is not in the :initialized state.

# File lib/t2-server/run.rb, line 342
def start
  state = status
  raise RunStateError.new(state, :initialized) if state != :initialized

  # set all the inputs
  _check_and_set_inputs unless baclava_input?

  begin
    @server.update(links[:status], Status.to_text(:running), "text/plain",
      @credentials)
  rescue ServerAtCapacityError => sace
    false
  end
end
start_time → string click to toggle source

Get the start time of this run as an instance of class Time.

# File lib/t2-server/run.rb, line 711
def start_time
  Time.parse(@server.read(links[:starttime], "text/plain", @credentials))
end
status → string click to toggle source

Get the status of this run. Status can be one of :initialized, :running or :finished.

# File lib/t2-server/run.rb, line 324
def status
  return :deleted if @deleted
  return :finished if @finished

  state = Status.to_sym(@server.read(links[:status], "text/plain",
    @credentials))

  @finished = (state == :finished)
  state
end
stderr → string click to toggle source

Get anything that the run printed to the standard error stream.

# File lib/t2-server/run.rb, line 394
def stderr
  @server.read(links[:stderr], "text/plain", @credentials)
end
stdout → string click to toggle source

Get anything that the run printed to the standard out stream.

# File lib/t2-server/run.rb, line 386
def stdout
  @server.read(links[:stdout], "text/plain", @credentials)
end
trusts → array click to toggle source

Return a list of all the URIs of trusts that have been registered for this run. At present there is no way to differentiate between trusts without noting the URI returned when originally uploaded. Only the owner of a run may query its trusts. nil is returned if a user other than the owner uses this method.

# File lib/t2-server/run.rb, line 932
def trusts
  return unless owner?

  t_uris = []
  doc = xml_document(@server.read(links[:sec_trusts], "application/xml",
    @credentials))

  xpath_find(doc, @@xpaths[:sec_trust]). each do |t|
    t_uris << URI.parse(xml_node_attribute(t, "href"))
  end

  t_uris
end
upload_data(data, remote_name, remote_directory = "") → URI click to toggle source

Upload data to the server and store it in remote_file. The remote directory to put this file in can also be specified, but if it is it must first have been created by a call to #mkdir.

Returns the URI of the file on the server in which the data has been stored.

# File lib/t2-server/run.rb, line 461
def upload_data(data, remote_name, remote_directory = "")
  location_uri = Util.append_to_uri_path(links[:wdir], remote_directory)
  @server.upload_data(data, remote_name, location_uri, @credentials)
end
upload_file(filename, params={}) → string click to toggle source

Upload a file, with name filename, to the server. Possible values that can be passed in via params are:

  • :dir - The directory to upload to. If this is not left blank the corresponding directory will need to have been created by #mkdir.

  • :rename - Save the file on the server with a different name.

The name of the file on the server is returned.

# File lib/t2-server/run.rb, line 444
def upload_file(filename, params={})
  location = params[:dir] || ""
  uri = Util.append_to_uri_path(links[:wdir], location)
  rename = params[:rename] || ""
  file_uri = @server.upload_file(filename, uri, rename, @credentials)
  Util.get_path_leaf_from_uri(file_uri)
end
wait(check_interval = 1) click to toggle source

Wait (block) for this run to finish. How often (in seconds) the run is tested for completion can be specified with check_interval.

Raises RunStateError if the run is still in the :initialized state.

# File lib/t2-server/run.rb, line 364
def wait(interval = 1)
  state = status
  raise RunStateError.new(state, :running) if state == :initialized

  # wait
  until finished?
    sleep(interval)
  end
end
workflow → string click to toggle source

Get the workflow that this run represents.

# File lib/t2-server/run.rb, line 311
def workflow
  if @workflow == ""
    @workflow = @server.read(links[:workflow], "application/xml",
      @credentials)
  end
  @workflow
end
zip_output → binary blob click to toggle source
zip_output(filename) → fixnum
zip_output(stream) → fixnum
zip_output {|chunk| ...}

Get the working directory of this run directly from the server in zip format.

Calling this method with no parameters will simply return a blob of zipped data. Providing a filename will stream the data directly to that file and return the number of bytes written. Passing in an object that has a write method (for example, an instance of File or IO) will stream the zip data directly to that object and return the number of bytes that were streamed. Passing in a block will allow access to the underlying data stream:

run.zip_output do |chunk|
  print chunk
end

Raises RunStateError if the run has not finished running.

# File lib/t2-server/run.rb, line 648
def zip_output(param = nil, port = "", &block)
  raise ArgumentError,
    "both a parameter and block given for zip_output" if param && block

  state = status
  raise RunStateError.new(state, :finished) if state != :finished

  path = port.empty? ? "out" : "out/#{port}"
  output_uri = Util.append_to_uri_path(links[:wdir], path)
  download_or_stream(param, output_uri, "application/zip", &block)
end