X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/6fc8952ed133607f5ce317d929d731657e405edf..8aeac20eed5c6eb2cc9f41ada60632265cbdd556:/services/api/app/models/container.rb?ds=sidebyside diff --git a/services/api/app/models/container.rb b/services/api/app/models/container.rb index f452b10a2d..d777c0c2fe 100644 --- a/services/api/app/models/container.rb +++ b/services/api/app/models/container.rb @@ -13,10 +13,10 @@ class Container < ArvadosModel before_validation :fill_field_defaults, :if => :new_record? before_validation :set_timestamps - validates :command, :container_image, :output_path, :cwd, :presence => true + validates :command, :container_image, :output_path, :cwd, :priority, :presence => true + validate :validate_state_change validate :validate_change - after_save :request_finalize - after_save :process_tree_priority + after_save :handle_completed has_many :container_requests, :foreign_key => :container_uuid, :class_name => 'ContainerRequest', :primary_key => :uuid @@ -46,30 +46,29 @@ class Container < ArvadosModel (Cancelled = 'Cancelled') ] - # Turn a container request into a container. - def self.resolve req - # In the future this will do things like resolve symbolic git and keep - # references to content addresses. - Container.create!({ :command => req.command, - :container_image => req.container_image, - :cwd => req.cwd, - :environment => req.environment, - :mounts => req.mounts, - :output_path => req.output_path, - :runtime_constraints => req.runtime_constraints }) + State_transitions = { + nil => [Queued], + Queued => [Running, Cancelled], + Running => [Complete, Cancelled] + } + + def state_transitions + State_transitions end def update_priority! - # Update the priority of this container to the maximum priority of any of - # its committed container requests and save the record. - max = 0 - ContainerRequest.where(container_uuid: uuid).each do |cr| - if cr.state == "Committed" and cr.priority > max - max = cr.priority + if [Queued, Running].include? self.state + # Update the priority of this container to the maximum priority of any of + # its committed container requests and save the record. + max = 0 + ContainerRequest.where(container_uuid: uuid).each do |cr| + if cr.state == ContainerRequest::Committed and cr.priority > max + max = cr.priority + end end + self.priority = max + self.save! end - self.priority = max - self.save! end protected @@ -114,32 +113,20 @@ class Container < ArvadosModel # permit priority change only. permitted.push :priority - if self.state_changed? and not self.state_was.nil? - errors.add :state, "Can only go to from nil to Queued" - end - when Running if self.state_changed? # At point of state change, can set state and started_at - if self.state_was == Queued - permitted.push :state, :started_at - else - errors.add :state, "Can only go from Queued to Running" - end - + permitted.push :state, :started_at + else # While running, can update priority and progress. permitted.push :priority, :progress end when Complete if self.state_changed? - if self.state_was == Running - permitted.push :state, :finished_at, :output, :log - else - errors.add :state, "Cannot go from #{self.state_was} to #{self.state}" - end + permitted.push :state, :finished_at, :output, :log else - errors.add :state, "Cannot update record in Complete state" + errors.add :state, "cannot update record" end when Cancelled @@ -148,41 +135,35 @@ class Container < ArvadosModel permitted.push :state, :finished_at, :output, :log elsif self.state_was == Queued permitted.push :state, :finished_at - else - errors.add :state, "Cannot go from #{self.state_was} to #{self.state}" end else - errors.add :state, "Cannot update record in Cancelled state" + errors.add :state, "cannot update record" end else - errors.add :state, "Invalid state #{self.state}" + errors.add :state, "invalid state" end check_update_whitelist permitted end - def request_finalize + def handle_completed + # This container is finished so finalize any associated container requests + # that are associated with this container. if self.state_changed? and [Complete, Cancelled].include? self.state act_as_system_user do - ContainerRequest.where(container_uuid: uuid).each do |cr| - cr.state = "Final" - cr.save! + # Try to close container requests associated with this container + ContainerRequest.where(container_uuid: uuid, + :state => ContainerRequest::Committed).each do |cr| + cr.state = ContainerRequest::Final + cr.save end - end - end - end - def process_tree_priority - if self.priority_changed? - # This could propagate any parent priority to the children (not just - # priority 0) - if self.priority == 0 - act_as_system_user do - ContainerRequest.where(requesting_container_uuid: uuid).each do |cr| - cr.priority = self.priority - cr.save! - end + # Try to cancel any outstanding container requests made by this container. + ContainerRequest.where(requesting_container_uuid: uuid, + :state => ContainerRequest::Committed).each do |cr| + cr.priority = 0 + cr.save end end end