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
35 t.add :runtime_constraints
40 # Supported states for a container
44 (Running = 'Running'),
45 (Complete = 'Complete'),
46 (Cancelled = 'Cancelled')
51 Queued => [Running, Cancelled],
52 Running => [Complete, Cancelled]
60 if [Queued, Running].include? self.state
61 # Update the priority of this container to the maximum priority of any of
62 # its committed container requests and save the record.
64 ContainerRequest.where(container_uuid: uuid).each do |cr|
65 if cr.state == ContainerRequest::Committed and cr.priority > max
76 def fill_field_defaults
78 self.environment ||= {}
79 self.runtime_constraints ||= {}
85 def permission_to_create
86 current_user.andand.is_admin
89 def permission_to_update
90 current_user.andand.is_admin
94 if self.state_changed? and self.state == Running
95 self.started_at ||= db_current_time
98 if self.state_changed? and [Complete, Cancelled].include? self.state
99 self.finished_at ||= db_current_time
107 permitted.push :owner_uuid, :command, :container_image, :cwd, :environment,
108 :mounts, :output_path, :priority, :runtime_constraints, :state
113 # permit priority change only.
114 permitted.push :priority
117 if self.state_changed?
118 # At point of state change, can set state and started_at
119 permitted.push :state, :started_at
121 # While running, can update priority and progress.
122 permitted.push :priority, :progress
126 if self.state_changed?
127 permitted.push :state, :finished_at, :output, :log
129 errors.add :state, "cannot update record"
133 if self.state_changed?
134 if self.state_was == Running
135 permitted.push :state, :finished_at, :output, :log
136 elsif self.state_was == Queued
137 permitted.push :state, :finished_at
140 errors.add :state, "cannot update record"
144 errors.add :state, "invalid state"
147 check_update_whitelist permitted
151 # This container is finished so finalize any associated container requests
152 # that are associated with this container.
153 if self.state_changed? and [Complete, Cancelled].include? self.state
154 act_as_system_user do
155 # Try to close container requests associated with this container
156 ContainerRequest.where(container_uuid: uuid,
157 :state => ContainerRequest::Committed).each do |cr|
158 cr.state = ContainerRequest::Final
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|