1 require 'whitelist_update'
3 class Container < ArvadosModel
6 include CommonApiTemplate
7 include WhitelistUpdate
9 serialize :environment, Hash
10 serialize :mounts, Hash
11 serialize :runtime_constraints, Hash
12 serialize :command, Array
14 before_validation :fill_field_defaults, :if => :new_record?
15 before_validation :set_timestamps
16 validates :command, :container_image, :output_path, :cwd, :priority, :presence => true
17 validate :validate_state_change
18 validate :validate_change
19 after_save :handle_completed
21 has_many :container_requests, :foreign_key => :container_uuid, :class_name => 'ContainerRequest', :primary_key => :uuid
23 api_accessible :user, extend: :common do |t|
25 t.add :container_image
36 t.add :runtime_constraints
41 # Supported states for a container
45 (Running = 'Running'),
46 (Complete = 'Complete'),
47 (Cancelled = 'Cancelled')
52 Queued => [Running, Cancelled],
53 Running => [Complete, Cancelled]
61 if [Queued, Running].include? self.state
62 # Update the priority of this container to the maximum priority of any of
63 # its committed container requests and save the record.
65 ContainerRequest.where(container_uuid: uuid).each do |cr|
66 if cr.state == ContainerRequest::Committed and cr.priority > max
77 def fill_field_defaults
79 self.environment ||= {}
80 self.runtime_constraints ||= {}
86 def permission_to_create
87 current_user.andand.is_admin
90 def permission_to_update
91 current_user.andand.is_admin
95 if self.state_changed? and self.state == Running
96 self.started_at ||= db_current_time
99 if self.state_changed? and [Complete, Cancelled].include? self.state
100 self.finished_at ||= db_current_time
108 permitted.push :owner_uuid, :command, :container_image, :cwd, :environment,
109 :mounts, :output_path, :priority, :runtime_constraints, :state
114 # permit priority change only.
115 permitted.push :priority
118 if self.state_changed?
119 # At point of state change, can set state and started_at
120 permitted.push :state, :started_at
122 # While running, can update priority and progress.
123 permitted.push :priority, :progress
127 if self.state_changed?
128 permitted.push :state, :finished_at, :output, :log, :exit_code
130 errors.add :state, "cannot update record"
134 if self.state_changed?
135 if self.state_was == Running
136 permitted.push :state, :finished_at, :output, :log
137 elsif self.state_was == Queued
138 permitted.push :state, :finished_at
141 errors.add :state, "cannot update record"
145 errors.add :state, "invalid state"
148 check_update_whitelist permitted
152 # This container is finished so finalize any associated container requests
153 # that are associated with this container.
154 if self.state_changed? and [Complete, Cancelled].include? self.state
155 act_as_system_user do
156 # Notify container requests associated with this container
157 ContainerRequest.where(container_uuid: uuid,
158 :state => ContainerRequest::Committed).each do |cr|
159 cr.container_completed!
162 # Try to cancel any outstanding container requests made by this container.
163 ContainerRequest.where(requesting_container_uuid: uuid,
164 :state => ContainerRequest::Committed).each do |cr|