func (s *FederationSuite) TestUpdateRemoteContainerRequest(c *check.C) {
defer s.localServiceReturns404(c).Close()
- req := httptest.NewRequest("PATCH", "/arvados/v1/container_requests/"+arvadostest.QueuedContainerRequestUUID,
- strings.NewReader(`{"container_request": {"priority": 696}}`))
- req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
- req.Header.Set("Content-type", "application/json")
- resp := s.testRequest(req)
- c.Check(resp.StatusCode, check.Equals, http.StatusOK)
- var cr arvados.ContainerRequest
- c.Check(json.NewDecoder(resp.Body).Decode(&cr), check.IsNil)
- c.Check(cr.UUID, check.Equals, arvadostest.QueuedContainerRequestUUID)
- c.Check(cr.Priority, check.Equals, 696)
+ setPri := func(pri int) {
+ req := httptest.NewRequest("PATCH", "/arvados/v1/container_requests/"+arvadostest.QueuedContainerRequestUUID,
+ strings.NewReader(fmt.Sprintf(`{"container_request": {"priority": %d}}`, pri)))
+ req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
+ req.Header.Set("Content-type", "application/json")
+ resp := s.testRequest(req)
+ c.Check(resp.StatusCode, check.Equals, http.StatusOK)
+ var cr arvados.ContainerRequest
+ c.Check(json.NewDecoder(resp.Body).Decode(&cr), check.IsNil)
+ c.Check(cr.UUID, check.Equals, arvadostest.QueuedContainerRequestUUID)
+ c.Check(cr.Priority, check.Equals, pri)
+ }
+ setPri(696)
+ setPri(1) // Reset fixture so side effect doesn't break other tests.
}
func (s *FederationSuite) TestCreateRemoteContainerRequest(c *check.C) {
h.handlerStack = mux
sc := *arvados.DefaultSecureClient
- sc.Timeout = time.Duration(h.Cluster.HTTPRequestTimeout)
sc.CheckRedirect = neverRedirect
h.secureClient = &sc
ic := *arvados.InsecureHTTPClient
- ic.Timeout = time.Duration(h.Cluster.HTTPRequestTimeout)
ic.CheckRedirect = neverRedirect
h.insecureClient = &ic
sync_past_versions if syncable_updates.any?
if snapshot
snapshot.attributes = self.syncable_updates
+ snapshot.manifest_text = snapshot.signed_manifest_text
snapshot.save
end
end
transaction do
reload
check_lock_fail
- update_attributes!(state: Locked)
+ update_attributes!(state: Locked, lock_count: self.lock_count+1)
end
end
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
case self.state
when Locked
- permitted.push :priority, :runtime_status, :log
+ permitted.push :priority, :runtime_status, :log, :lock_count
when Queued
permitted.push :priority
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
# > 0 = auto-create a new version when older than the specified number of seconds.
preserve_version_if_idle: -1
+ # Number of times a container can be unlocked before being
+ # automatically cancelled.
+ max_container_dispatch_attempts: 5
+
development:
force_ssl: false
cache_classes: false
--- /dev/null
+class AddContainerLockCount < ActiveRecord::Migration
+ def change
+ add_column :containers, :lock_count, :int, :null => false, :default => 0
+ end
+end
runtime_status jsonb DEFAULT '{}'::jsonb,
runtime_user_uuid text,
runtime_auth_scopes jsonb,
- runtime_token text
+ runtime_token text,
+ lock_count integer DEFAULT 0 NOT NULL
);
INSERT INTO schema_migrations (version) VALUES ('20181213183234');
+INSERT INTO schema_migrations (version) VALUES ('20190214214814');
+
version: 42,
current_version_uuid: collections(:collection_owned_by_active).uuid,
manifest_text: manifest_text,
- # portable_data_hash: "d30fe8ae534397864cb96c544f4cf102+47"
}
}
assert_response :success
assert_equal 1, resp['version']
assert_equal resp['uuid'], resp['current_version_uuid']
end
+
+ test "update collection with versioning enabled" do
+ Rails.configuration.collection_versioning = true
+ Rails.configuration.preserve_version_if_idle = 1 # 1 second
+
+ col = collections(:collection_owned_by_active)
+ assert_equal 2, col.version
+ assert col.modified_at < Time.now - 1.second
+
+ token = api_client_authorizations(:active).v2token
+ signed = Blob.sign_locator(
+ 'acbd18db4cc2f85cedef654fccc4a4d8+3',
+ key: Rails.configuration.blob_signing_key,
+ api_token: token)
+ authorize_with_token token
+ put :update, {
+ id: col.uuid,
+ collection: {
+ manifest_text: ". #{signed} 0:3:foo.txt\n",
+ },
+ }
+ assert_response :success
+ assert_equal 3, json_response['version']
+ end
end
assert_operator auth_exp, :<, db_current_time
end
+ test "Exceed maximum lock-unlock cycles" do
+ Rails.configuration.max_container_dispatch_attempts = 3
+
+ set_user_from_auth :active
+ c, cr = minimal_new
+
+ set_user_from_auth :dispatch1
+ assert_equal Container::Queued, c.state
+ assert_equal 0, c.lock_count
+
+ c.lock
+ c.reload
+ assert_equal 1, c.lock_count
+ assert_equal Container::Locked, c.state
+
+ c.unlock
+ c.reload
+ assert_equal 1, c.lock_count
+ assert_equal Container::Queued, c.state
+
+ c.lock
+ c.reload
+ assert_equal 2, c.lock_count
+ assert_equal Container::Locked, c.state
+
+ c.unlock
+ c.reload
+ assert_equal 2, c.lock_count
+ assert_equal Container::Queued, c.state
+
+ c.lock
+ c.reload
+ assert_equal 3, c.lock_count
+ assert_equal Container::Locked, c.state
+
+ c.unlock
+ c.reload
+ assert_equal 3, c.lock_count
+ assert_equal Container::Cancelled, c.state
+
+ assert_raise(ArvadosModel::LockFailedError) do
+ # Cancelled to Locked is not allowed
+ c.lock
+ end
+ end
+
test "Container queued cancel" do
set_user_from_auth :active
c, cr = minimal_new({container_count_max: 1})