Add interface to add a constraint to context
This adds methods to the Context to add, remove, and get a constraint on an object to be checked before a change is made to that object. Related-Bug: #1493714 Change-Id: Id01c4dfb740f680e96349dc08b11b5bca6c59a74
This commit is contained in:
parent
335d30061a
commit
6a2040fcdb
|
@ -12,6 +12,7 @@
|
|||
|
||||
"""Context: context for security/db session."""
|
||||
|
||||
import collections
|
||||
import copy
|
||||
import datetime
|
||||
|
||||
|
@ -141,10 +142,15 @@ class ContextBaseWithSession(ContextBase):
|
|||
pass
|
||||
|
||||
|
||||
_TransactionConstraint = collections.namedtuple(
|
||||
'TransactionConstraint', ['if_revision_match', 'resource', 'resource_id'])
|
||||
|
||||
|
||||
class Context(ContextBaseWithSession):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Context, self).__init__(*args, **kwargs)
|
||||
self._session = None
|
||||
self._txn_constraint = None
|
||||
|
||||
@property
|
||||
def session(self):
|
||||
|
@ -157,6 +163,26 @@ class Context(ContextBaseWithSession):
|
|||
|
||||
return self._session
|
||||
|
||||
def set_transaction_constraint(self, resource, resource_id, rev_number):
|
||||
"""Set a revision constraint to enfore before resource_id is changed.
|
||||
|
||||
:param resource: collection name of resource (e.g. ports or networks)
|
||||
:param resource_id: the primary key ID of the individiual resource that
|
||||
should have its revision number matched before
|
||||
allowing the transaction to proceed.
|
||||
:param rev_number: the revision_number that the resource should be at.
|
||||
"""
|
||||
|
||||
self._txn_constraint = _TransactionConstraint(
|
||||
if_revision_match=rev_number, resource=resource,
|
||||
resource_id=resource_id)
|
||||
|
||||
def clear_transaction_constraint(self):
|
||||
self._txn_constraint = None
|
||||
|
||||
def get_transaction_constraint(self):
|
||||
return self._txn_constraint
|
||||
|
||||
|
||||
def get_admin_context():
|
||||
return Context(user_id=None,
|
||||
|
|
|
@ -213,3 +213,14 @@ class TestNeutronContext(_base.BaseTestCase):
|
|||
session1 = ctx.session
|
||||
session2 = ctx.session
|
||||
self.assertIs(session1, session2)
|
||||
|
||||
def test_add_get_remove_constraint(self):
|
||||
ctx = context.Context('user_id', 'tenant_id')
|
||||
self.assertIsNone(ctx.get_transaction_constraint())
|
||||
ctx.set_transaction_constraint('networks', 'net_id', 44)
|
||||
constraint = ctx.get_transaction_constraint()
|
||||
self.assertEqual(44, constraint.if_revision_match)
|
||||
self.assertEqual('networks', constraint.resource)
|
||||
self.assertEqual('net_id', constraint.resource_id)
|
||||
ctx.clear_transaction_constraint()
|
||||
self.assertIsNone(ctx.get_transaction_constraint())
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Contexts may now have transaction constraints set on them to be enforced
|
||||
by the revision plugin in Neutron for generalized compare-and-swap updates.
|
||||
Calling ``set_transaction_constraint`` on the context before performing a
|
||||
resource mutation will setup the constraint. This is also exposed to users
|
||||
via the HTTP API with ``if-match`` headers and the API layer sets the
|
||||
constraint on the context.
|
Loading…
Reference in New Issue