X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/e7d49ab46462902a98d812b69d7257d837f85e90..5bcb3cee7d38123480cccc84a22a451ea17f2ae9:/services/api/app/models/container_request.rb diff --git a/services/api/app/models/container_request.rb b/services/api/app/models/container_request.rb index 496a6b141d..15418f237f 100644 --- a/services/api/app/models/container_request.rb +++ b/services/api/app/models/container_request.rb @@ -82,20 +82,73 @@ class ContainerRequest < ArvadosModel # Create a new container (or find an existing one) to satisfy this # request. def resolve - # TODO: resolve symbolic git and keep references to content - # addresses. + # TODO: resolve container_image to a content address. + c_mounts = mounts_for_container + c_runtime_constraints = runtime_constraints_for_container c = act_as_system_user do Container.create!(command: self.command, container_image: self.container_image, cwd: self.cwd, environment: self.environment, - mounts: self.mounts, + mounts: c_mounts, output_path: self.output_path, - runtime_constraints: self.runtime_constraints) + runtime_constraints: c_runtime_constraints) end self.container_uuid = c.uuid end + # Return a runtime_constraints hash that complies with + # self.runtime_constraints but is suitable for saving in a container + # record, i.e., has specific values instead of ranges. + # + # Doing this as a step separate from other resolutions, like "git + # revision range to commit hash", makes sense only when there is no + # opportunity to reuse an existing container (e.g., container reuse + # is not implemented yet, or we have already found that no existing + # containers are suitable). + def runtime_constraints_for_container + rc = {} + runtime_constraints.each do |k, v| + if v.is_a? Array + rc[k] = v[0] + else + rc[k] = v + end + end + rc + end + + # Return a mounts hash suitable for a Container, i.e., with every + # readonly collection UUID resolved to a PDH. + def mounts_for_container + c_mounts = {} + mounts.each do |k, mount| + mount = mount.dup + c_mounts[k] = mount + if mount['kind'] != 'collection' + next + end + if (uuid = mount.delete 'uuid') + c = Collection. + readable_by(current_user). + where(uuid: uuid). + select(:portable_data_hash). + first + if !c + raise ActiveRecord::RecordNotFound.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 + end + end + return c_mounts + end + def set_container if (container_uuid_changed? and not current_user.andand.is_admin and