+ 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
+
+ # Return a container_image PDH suitable for a Container.
+ def container_image_for_container
+ coll = Collection.for_latest_docker_image(container_image)
+ if !coll
+ raise ActiveRecord::RecordNotFound.new "docker image #{container_image.inspect} not found"
+ end
+ return coll.portable_data_hash
+ end
+
+ def set_container
+ if (container_uuid_changed? and
+ not current_user.andand.is_admin and
+ not container_uuid.nil?)
+ errors.add :container_uuid, "can only be updated to nil."
+ return false
+ end
+ if state_changed? and state == Committed and container_uuid.nil?
+ resolve
+ end
+ end
+
+ def validate_runtime_constraints
+ case self.state
+ when Committed
+ ['vcpus', 'ram'].each do |k|
+ if not (runtime_constraints.include? k and
+ runtime_constraints[k].is_a? Integer and
+ runtime_constraints[k] > 0)
+ errors.add :runtime_constraints, "#{k} must be a positive integer"