X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/adfc2c563d47c0eb70985245a1a7c4df004d7aa0..28b6afc1e8ccf652c7a8fd43e22a8ac788febd85:/apps/workbench/app/models/container_work_unit.rb diff --git a/apps/workbench/app/models/container_work_unit.rb b/apps/workbench/app/models/container_work_unit.rb index 036f8a481e..292bc3679b 100644 --- a/apps/workbench/app/models/container_work_unit.rb +++ b/apps/workbench/app/models/container_work_unit.rb @@ -1,31 +1,44 @@ +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + class ContainerWorkUnit < ProxyWorkUnit attr_accessor :container + attr_accessor :child_proxies - def initialize proxied, label - super + def initialize proxied, label, parent, child_objects=nil + super proxied, label, parent if @proxied.is_a?(ContainerRequest) container_uuid = get(:container_uuid) if container_uuid - @container = Container.where(uuid: container_uuid).first + @container = Container.find(container_uuid) end end + @container = nil if !defined?(@container) + @child_proxies = child_objects end def children - return self.my_children if self.my_children - - container_uuid = nil - container_uuid = if @proxied.is_a?(Container) then uuid else get(:container_uuid) end + return @my_children if @my_children items = [] + container_uuid = if @proxied.is_a?(Container) then uuid else get(:container_uuid) end if container_uuid - reqs = ContainerRequest.where(requesting_container_uuid: container_uuid).results - reqs.each do |cr| - items << cr.work_unit(cr.name || 'this container') + cols = ContainerRequest.columns.map(&:name) - %w(id updated_at mounts secret_mounts runtime_token) + my_children = @child_proxies || ContainerRequest.select(cols).where(requesting_container_uuid: container_uuid).with_count("none").results if !my_children + my_child_containers = my_children.map(&:container_uuid).compact.uniq + grandchildren = {} + my_child_containers.each { |c| grandchildren[c] = []} if my_child_containers.any? + reqs = ContainerRequest.select(cols).where(requesting_container_uuid: my_child_containers).order(["requesting_container_uuid", "uuid"]).with_count("none").results if my_child_containers.any? + reqs.each {|cr| grandchildren[cr.requesting_container_uuid] << cr} if reqs + + my_children.each do |cr| + items << cr.work_unit(cr.name || 'this container', child_objects=grandchildren[cr.container_uuid]) end end - self.my_children = items + @child_proxies = nil #no need of this any longer + @my_children = items end def title @@ -34,18 +47,36 @@ class ContainerWorkUnit < ProxyWorkUnit def uri uuid = get(:uuid) - "/#{@proxied.class.table_name}/#{uuid}" rescue nil - end + return nil unless uuid + + if @proxied.class.respond_to? :table_name + "/#{@proxied.class.table_name}/#{uuid}" + else + resource_class = ArvadosBase.resource_class_for_uuid(uuid) + "#{resource_class.table_name}/#{uuid}" if resource_class + end + end def can_cancel? - @proxied.is_a?(ContainerRequest) && state_label.in?(["Queued", "Locked", "Running"]) && priority > 0 + @proxied.is_a?(ContainerRequest) && + @proxied.state == "Committed" && + (@proxied.priority > 0 || get(:state, @container) != 'Running') && + @proxied.editable? end def container_uuid get(:container_uuid) end + def requesting_container_uuid + get(:requesting_container_uuid) + end + + def priority + @proxied.priority + end + # For the following properties, use value from the @container if exists # This applies to a ContainerRequest with container_uuid @@ -68,7 +99,56 @@ class ContainerWorkUnit < ProxyWorkUnit end def state_label - get_combined(:state) + if get(:state) == 'Final' && get(:state, @container) != 'Complete' + # Request was finalized before its container started (or the + # container was cancelled) + return 'Cancelled' + end + state = get(:state, @container) || get(:state, @proxied) + case state + when 'Locked', 'Queued' + if priority == 0 + 'On hold' + else + 'Queued' + end + when 'Complete' + if exit_code == 0 + state + else + 'Failed' + end + when 'Running' + if runtime_status[:error] + 'Failing' + elsif runtime_status[:warning] + 'Warning' + else + state + end + else + # Cancelled, or Uncommitted (no container assigned) + state + end + end + + def runtime_status + return get(:runtime_status, @container) || get(:runtime_status, @proxied) + end + + def state_bootstrap_class + case state_label + when 'Failing' + 'danger' + when 'Warning' + 'warning' + else + super + end + end + + def exit_code + get_combined(:exit_code) end def docker_image @@ -79,17 +159,22 @@ class ContainerWorkUnit < ProxyWorkUnit get_combined(:runtime_constraints) end - def priority - get_combined(:priority) - end - def log_collection - get_combined(:log) + if @proxied.is_a?(ContainerRequest) + get(:log_uuid) + else + get(:log) + end end def outputs items = [] - items << get_combined(:output) if get_combined(:output) + if @proxied.is_a?(ContainerRequest) + out = get(:output_uuid) + else + out = get(:output) + end + items << out if out items end @@ -117,10 +202,35 @@ class ContainerWorkUnit < ProxyWorkUnit get_combined(:output_path) end - # End combined propeties + def log_object_uuids + [get(:uuid, @container), get(:uuid, @proxied)].compact + end + + def render_log + collection = Collection.find(log_collection) rescue nil + if collection + return {log: collection, partial: 'collections/show_files', locals: {object: collection, no_checkboxes: true}} + end + end + + def template_uuid + properties = get(:properties) + if properties + properties[:template_uuid] + end + end + + # End combined properties protected def get_combined key - get(key, @container) || get(key, @proxied) + from_container = get(key, @container) + from_proxied = get(key, @proxied) + + if from_container.is_a? Hash or from_container.is_a? Array + if from_container.any? then from_container else from_proxied end + else + from_container || from_proxied + end end end