X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/dea40b3efdb8b6b948cda5a1601fcbabb831f2fc..0f14b3456d2d3bdf95b78b65a1a41280a7416928:/services/api/app/models/container.rb diff --git a/services/api/app/models/container.rb b/services/api/app/models/container.rb index 5d46ac29f8..3d1e649115 100644 --- a/services/api/app/models/container.rb +++ b/services/api/app/models/container.rb @@ -223,7 +223,11 @@ class Container < ArvadosModel if mount['kind'] != 'collection' next end - if (uuid = mount.delete 'uuid') + + uuid = mount.delete 'uuid' + + if mount['portable_data_hash'].nil? and !uuid.nil? + # PDH not supplied, try by UUID c = Collection. readable_by(current_user). where(uuid: uuid). @@ -232,13 +236,7 @@ class Container < ArvadosModel if !c raise ArvadosModel::UnresolvableContainerError.new "cannot mount collection #{uuid.inspect}: not found" end - if mount['portable_data_hash'].nil? - # PDH not supplied by client - mount['portable_data_hash'] = c.portable_data_hash - elsif mount['portable_data_hash'] != c.portable_data_hash - # UUID and PDH supplied by client, but they don't agree - raise ArgumentError.new "cannot mount collection #{uuid.inspect}: current portable_data_hash #{c.portable_data_hash.inspect} does not match #{c['portable_data_hash'].inspect} in request" - end + mount['portable_data_hash'] = c.portable_data_hash end end return c_mounts @@ -248,15 +246,6 @@ class Container < ArvadosModel def self.resolve_container_image(container_image) coll = Collection.for_latest_docker_image(container_image) if !coll - if loc = Keep::Locator.parse(container_image) - loc.strip_hints! - if !Collection.where(portable_data_hash: loc.to_s).any? - # Allow bare pdh that doesn't exist in the local database so - # that federated container requests which refer to remotely - # stored containers will validate. - return loc.to_s - end - end raise ArvadosModel::UnresolvableContainerError.new "docker image #{container_image.inspect} not found" end coll.portable_data_hash @@ -290,14 +279,6 @@ class Container < ArvadosModel candidates = candidates.where_serialized(:runtime_constraints, resolve_runtime_constraints(attrs[:runtime_constraints]), md5: true) log_reuse_info(candidates) { "after filtering on runtime_constraints #{attrs[:runtime_constraints].inspect}" } - candidates = candidates.where('runtime_user_uuid = ? or (runtime_user_uuid is NULL and runtime_auth_scopes is NULL)', - attrs[:runtime_user_uuid]) - log_reuse_info(candidates) { "after filtering on runtime_user_uuid #{attrs[:runtime_user_uuid].inspect}" } - - candidates = candidates.where('runtime_auth_scopes = ? or (runtime_user_uuid is NULL and runtime_auth_scopes is NULL)', - SafeJSON.dump(attrs[:runtime_auth_scopes].sort)) - log_reuse_info(candidates) { "after filtering on runtime_auth_scopes #{attrs[:runtime_auth_scopes].inspect}" } - log_reuse_info { "checking for state=Complete with readable output and log..." } select_readable_pdh = Collection. @@ -365,7 +346,7 @@ class Container < ArvadosModel transaction do reload check_lock_fail - update_attributes!(state: Locked) + update_attributes!(state: Locked, lock_count: self.lock_count+1) end end @@ -383,7 +364,14 @@ class Container < ArvadosModel transaction do reload(lock: 'FOR UPDATE') check_unlock_fail - update_attributes!(state: Queued) + if self.lock_count < Rails.configuration.max_container_dispatch_attempts + update_attributes!(state: Queued) + else + update_attributes!(state: Cancelled, + runtime_status: { + error: "Container exceeded 'max_container_dispatch_attempts' (lock_count=#{self.lock_count}." + }) + end end end @@ -473,7 +461,7 @@ class Container < ArvadosModel case self.state when Locked - permitted.push :priority, :runtime_status, :log + permitted.push :priority, :runtime_status, :log, :lock_count when Queued permitted.push :priority @@ -494,7 +482,7 @@ class Container < ArvadosModel when Running permitted.push :finished_at, *progress_attrs when Queued, Locked - permitted.push :finished_at, :log + permitted.push :finished_at, :log, :runtime_status end else @@ -502,10 +490,14 @@ class Container < ArvadosModel return false end - if current_api_client_authorization.andand.uuid.andand == self.auth_uuid - # The contained process itself can update progress indicators, - # but can't change priority etc. - permitted = permitted & (progress_attrs + final_attrs + [:state] - [:log]) + if self.state == Running && + !current_api_client_authorization.nil? && + (current_api_client_authorization.uuid == self.auth_uuid || + current_api_client_authorization.token == self.runtime_token) + # The contained process itself can write final attrs but can't + # change priority or log. + permitted.push *final_attrs + permitted = permitted - [:log, :priority] elsif self.locked_by_uuid && self.locked_by_uuid != current_api_client_authorization.andand.uuid # When locked, progress fields cannot be updated by the wrong # dispatcher, even though it has admin privileges.