Merge "Revert "Drop `AddressScope.shared` field""
This commit is contained in:
commit
2947b28f1a
7 files changed
+63
-97
No files matched your search
@@ -22,6 +22,7 @@ from neutron_lib.exceptions import address_scope as api_err
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from neutron._i18n import _
|
||||
from neutron.extensions import address_scope as ext_address_scope
|
||||
from neutron.objects import address_scope as obj_addr_scope
|
||||
from neutron.objects import base as base_obj
|
||||
@@ -78,10 +79,10 @@ class AddressScopeDbMixin(ext_address_scope.AddressScopePluginBase):
|
||||
'dictionary, using tenant_id instead. This support '
|
||||
'has been deprecated and will be removed in a '
|
||||
'future release.')
|
||||
a_s.pop('shared', None)
|
||||
pool_args = {'project_id': a_s['project_id'],
|
||||
'id': address_scope_id,
|
||||
'name': a_s['name'],
|
||||
'shared': a_s['shared'],
|
||||
'ip_version': a_s['ip_version']}
|
||||
address_scope = obj_addr_scope.AddressScope(context, **pool_args)
|
||||
address_scope.create()
|
||||
@@ -89,8 +90,12 @@ class AddressScopeDbMixin(ext_address_scope.AddressScopePluginBase):
|
||||
|
||||
def update_address_scope(self, context, id, address_scope):
|
||||
a_s = address_scope['address_scope']
|
||||
a_s.pop('shared', None)
|
||||
address_scope = self._get_address_scope(context, id)
|
||||
if address_scope.shared and not a_s.get('shared', True):
|
||||
reason = _("Shared address scope can't be unshared")
|
||||
raise api_err.AddressScopeUpdateError(
|
||||
address_scope_id=id, reason=reason)
|
||||
|
||||
address_scope.update_fields(a_s)
|
||||
address_scope.update()
|
||||
return self._make_address_scope_dict(address_scope)
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
from neutron_lib.db import api as db_api
|
||||
from neutron_lib.objects import common_types
|
||||
from oslo_utils import versionutils
|
||||
from oslo_versionedobjects import fields as obj_fields
|
||||
|
||||
from neutron.db.models import address_scope as models
|
||||
@@ -39,12 +38,10 @@ class AddressScopeRBAC(rbac.RBACBaseObject):
|
||||
class AddressScope(rbac_db.NeutronRbacObject):
|
||||
# Version 1.0: Initial version
|
||||
# Version 1.1: Add RBAC support
|
||||
# Version 1.2: Remove "shared" field
|
||||
VERSION = '1.2'
|
||||
VERSION = '1.1'
|
||||
|
||||
# required by RbacNeutronMetaclass
|
||||
rbac_db_cls = AddressScopeRBAC
|
||||
_rbac_shared_field = False
|
||||
|
||||
db_model = models.AddressScope
|
||||
|
||||
@@ -52,6 +49,7 @@ class AddressScope(rbac_db.NeutronRbacObject):
|
||||
'id': common_types.UUIDField(),
|
||||
'project_id': obj_fields.StringField(nullable=True),
|
||||
'name': obj_fields.StringField(),
|
||||
'shared': obj_fields.BooleanField(),
|
||||
'ip_version': common_types.IPVersionEnumField(),
|
||||
}
|
||||
|
||||
@@ -78,16 +76,3 @@ class AddressScope(rbac_db.NeutronRbacObject):
|
||||
snp_objs = subnetpool.SubnetPool.get_objects(
|
||||
context, address_scope_id=obj_id, fields=['project_id'])
|
||||
return {snp['project_id'] for snp in snp_objs}
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
_target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
if _target_version >= (1, 2):
|
||||
primitive.pop('shared', None)
|
||||
elif 'shared' not in primitive:
|
||||
if self.obj_context and self.id:
|
||||
primitive['shared'] = self.get_shared_with_project(
|
||||
self.obj_context.elevated(), self.rbac_db_cls,
|
||||
self.id, self.project_id)
|
||||
else:
|
||||
primitive['shared'] = False
|
||||
return super().obj_make_compatible(primitive, target_version)
|
||||
+11
-30
@@ -248,13 +248,11 @@ class RbacNeutronDbObjectMixin(rbac_db_mixin.RbacPluginMixin,
|
||||
return self.obj_context.session.delete(shared_prev)
|
||||
|
||||
def from_db_object(self, db_obj):
|
||||
if getattr(self.__class__, '_rbac_shared_field', True):
|
||||
self._load_shared(db_obj)
|
||||
self._load_shared(db_obj)
|
||||
super().from_db_object(db_obj)
|
||||
|
||||
def obj_load_attr(self, attrname):
|
||||
if (attrname == 'shared' and
|
||||
getattr(self.__class__, '_rbac_shared_field', True)):
|
||||
if attrname == 'shared':
|
||||
return self._load_shared()
|
||||
super().obj_load_attr(attrname)
|
||||
|
||||
@@ -292,9 +290,8 @@ def _update_hook(self, update_orig):
|
||||
# _update_post method because update() will reset all those changes
|
||||
obj_changes = self.obj_get_changes()
|
||||
update_orig(self)
|
||||
if getattr(self.__class__, '_rbac_shared_field', True):
|
||||
_update_post(self, obj_changes)
|
||||
self._load_shared(db_obj=self.db_obj)
|
||||
_update_post(self, obj_changes)
|
||||
self._load_shared(db_obj=self.db_obj)
|
||||
|
||||
|
||||
def _create_post(self):
|
||||
@@ -305,9 +302,8 @@ def _create_post(self):
|
||||
def _create_hook(self, orig_create):
|
||||
with self.db_context_writer(self.obj_context):
|
||||
orig_create(self)
|
||||
if getattr(self.__class__, '_rbac_shared_field', True):
|
||||
_create_post(self)
|
||||
self._load_shared(db_obj=self.db_obj)
|
||||
_create_post(self)
|
||||
self._load_shared(db_obj=self.db_obj)
|
||||
|
||||
|
||||
def _to_dict_hook(self, to_dict_orig):
|
||||
@@ -351,12 +347,6 @@ class RbacNeutronMetaclass(type):
|
||||
reason=_('already a synthetic attribute'))
|
||||
dct['synthetic_fields'].append('shared')
|
||||
|
||||
@classmethod
|
||||
def init_synthetic_fields(cls, bases, dct):
|
||||
if not dct.get('synthetic_fields', None):
|
||||
synthetic_attr = cls.get_attribute('synthetic_fields', bases, dct)
|
||||
dct['synthetic_fields'] = synthetic_attr or []
|
||||
|
||||
@staticmethod
|
||||
def subscribe_to_rbac_events(class_instance):
|
||||
for e in (events.BEFORE_CREATE, events.BEFORE_UPDATE,
|
||||
@@ -365,8 +355,8 @@ class RbacNeutronMetaclass(type):
|
||||
resources.RBAC_POLICY, e)
|
||||
|
||||
@staticmethod
|
||||
def validate_existing_attrs(cls_name, dct, uses_shared_field=True):
|
||||
if uses_shared_field and 'shared' not in dct['fields']:
|
||||
def validate_existing_attrs(cls_name, dct):
|
||||
if 'shared' not in dct['fields']:
|
||||
raise KeyError(_('No shared key in %s fields') % cls_name)
|
||||
if 'rbac_db_cls' not in dct:
|
||||
raise AttributeError(_('rbac_db_cls not found in %s') % cls_name)
|
||||
@@ -389,20 +379,11 @@ class RbacNeutronMetaclass(type):
|
||||
dct[orig_method_name] = hook_method
|
||||
|
||||
def __new__(cls, name, bases, dct):
|
||||
uses_shared_field = dct.get('_rbac_shared_field')
|
||||
if uses_shared_field is None:
|
||||
uses_shared_field = cls._get_attribute('_rbac_shared_field', bases)
|
||||
if uses_shared_field is None:
|
||||
uses_shared_field = True
|
||||
cls.validate_existing_attrs(name, dct, uses_shared_field)
|
||||
if uses_shared_field:
|
||||
cls.update_synthetic_fields(bases, dct)
|
||||
else:
|
||||
cls.init_synthetic_fields(bases, dct)
|
||||
cls.validate_existing_attrs(name, dct)
|
||||
cls.update_synthetic_fields(bases, dct)
|
||||
cls.replace_class_methods_with_hooks(bases, dct)
|
||||
klass = type(name, (RbacNeutronDbObjectMixin,) + bases, dct)
|
||||
if uses_shared_field:
|
||||
klass.add_extra_filter_name('shared')
|
||||
klass.add_extra_filter_name('shared')
|
||||
cls.subscribe_to_rbac_events(klass)
|
||||
|
||||
return klass
|
||||
|
||||
@@ -27,9 +27,7 @@ import webob.exc
|
||||
|
||||
from neutron.db import address_scope_db
|
||||
from neutron.db import db_base_plugin_v2
|
||||
from neutron.db import rbac_db_models
|
||||
from neutron.extensions import address_scope as ext_address_scope
|
||||
from neutron.objects import address_scope as obj_addr_scope
|
||||
from neutron.tests.common import test_db_base_plugin_v2
|
||||
|
||||
DB_PLUGIN_KLASS = ('neutron.tests.unit.extensions.test_address_scope.'
|
||||
@@ -98,16 +96,6 @@ class AddressScopeTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||
self._compare_resource(addr_scope, expected, 'address_scope')
|
||||
return addr_scope
|
||||
|
||||
def _share_address_scope(self, addr_scope, target_project='*'):
|
||||
rbac = obj_addr_scope.AddressScopeRBAC(
|
||||
context.get_admin_context(),
|
||||
project_id=addr_scope['address_scope']['project_id'],
|
||||
object_id=addr_scope['address_scope']['id'],
|
||||
action=rbac_db_models.ACCESS_SHARED,
|
||||
target_project=target_project,
|
||||
)
|
||||
rbac.create()
|
||||
|
||||
def _test_update_address_scope(self, addr_scope_id, data, admin=False,
|
||||
expected=None, project_id=None):
|
||||
update_req = self.new_update_request(
|
||||
@@ -142,6 +130,7 @@ class TestAddressScope(AddressScopeTestCase):
|
||||
def test_create_address_scope_ipv4(self):
|
||||
expected_addr_scope = {'name': 'foo-address-scope',
|
||||
'project_id': self._project_id,
|
||||
'shared': False,
|
||||
'ip_version': constants.IP_VERSION_4}
|
||||
self._test_create_address_scope(name='foo-address-scope',
|
||||
expected=expected_addr_scope)
|
||||
@@ -149,6 +138,7 @@ class TestAddressScope(AddressScopeTestCase):
|
||||
def test_create_address_scope_ipv6(self):
|
||||
expected_addr_scope = {'name': 'foo-address-scope',
|
||||
'project_id': self._project_id,
|
||||
'shared': False,
|
||||
'ip_version': constants.IP_VERSION_6}
|
||||
self._test_create_address_scope(constants.IP_VERSION_6,
|
||||
name='foo-address-scope',
|
||||
@@ -156,12 +146,25 @@ class TestAddressScope(AddressScopeTestCase):
|
||||
|
||||
def test_create_address_scope_empty_name(self):
|
||||
expected_addr_scope = {'name': '',
|
||||
'project_id': self._project_id}
|
||||
'project_id': self._project_id,
|
||||
'shared': False}
|
||||
self._test_create_address_scope(name='', expected=expected_addr_scope)
|
||||
|
||||
# no name specified
|
||||
self._test_create_address_scope(expected=expected_addr_scope)
|
||||
|
||||
def test_create_address_scope_shared_admin(self):
|
||||
expected_addr_scope = {'name': 'foo-address-scope', 'shared': True}
|
||||
self._test_create_address_scope(name='foo-address-scope', admin=True,
|
||||
shared=True,
|
||||
expected=expected_addr_scope)
|
||||
|
||||
def test_created_address_scope_shared_non_admin(self):
|
||||
res = self._create_address_scope(self.fmt, name='foo-address-scope',
|
||||
project_id=self._project_id,
|
||||
admin=False, shared=True)
|
||||
self.assertEqual(webob.exc.HTTPForbidden.code, res.status_int)
|
||||
|
||||
def test_created_address_scope_specify_id(self):
|
||||
res = self._create_address_scope(self.fmt, name='foo-address-scope',
|
||||
id='foo-id')
|
||||
@@ -179,6 +182,28 @@ class TestAddressScope(AddressScopeTestCase):
|
||||
self._test_update_address_scope(addr_scope['address_scope']['id'],
|
||||
data, expected=data['address_scope'])
|
||||
|
||||
def test_update_address_scope_shared_true_admin(self):
|
||||
addr_scope = self._test_create_address_scope(name='foo-address-scope')
|
||||
data = {'address_scope': {'shared': True}}
|
||||
self._test_update_address_scope(addr_scope['address_scope']['id'],
|
||||
data, admin=True,
|
||||
expected=data['address_scope'])
|
||||
|
||||
def test_update_address_scope_shared_true_non_admin(self):
|
||||
addr_scope = self._test_create_address_scope(name='foo-address-scope')
|
||||
data = {'address_scope': {'shared': True}}
|
||||
res = self._test_update_address_scope(
|
||||
addr_scope['address_scope']['id'], data, admin=False)
|
||||
self.assertEqual(webob.exc.HTTPForbidden.code, res.status_int)
|
||||
|
||||
def test_update_address_scope_shared_false_admin(self):
|
||||
addr_scope = self._test_create_address_scope(name='foo-address-scope',
|
||||
admin=True, shared=True)
|
||||
data = {'address_scope': {'shared': False}}
|
||||
res = self._test_update_address_scope(
|
||||
addr_scope['address_scope']['id'], data, admin=True)
|
||||
self.assertEqual(webob.exc.HTTPClientError.code, res.status_int)
|
||||
|
||||
def test_get_address_scope(self):
|
||||
addr_scope = self._test_create_address_scope(name='foo-address-scope')
|
||||
req = self.new_show_request('address-scopes',
|
||||
@@ -197,8 +222,8 @@ class TestAddressScope(AddressScopeTestCase):
|
||||
self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int)
|
||||
|
||||
def test_get_address_scope_different_projects_shared(self):
|
||||
addr_scope = self._test_create_address_scope(name='foo-address-scope')
|
||||
self._share_address_scope(addr_scope)
|
||||
addr_scope = self._test_create_address_scope(name='foo-address-scope',
|
||||
shared=True, admin=True)
|
||||
req = self.new_show_request('address-scopes',
|
||||
addr_scope['address_scope']['id'])
|
||||
neutron_context = context.Context('', 'test-project-2')
|
||||
@@ -215,9 +240,8 @@ class TestAddressScope(AddressScopeTestCase):
|
||||
self.assertEqual(2, len(res['address_scopes']))
|
||||
|
||||
def test_list_address_scopes_different_projects_shared(self):
|
||||
addr_scope = self._test_create_address_scope(
|
||||
name='foo-address-scope')
|
||||
self._share_address_scope(addr_scope)
|
||||
self._test_create_address_scope(name='foo-address-scope', shared=True,
|
||||
admin=True)
|
||||
admin_res = self._list('address-scopes')
|
||||
mortal_res = self._list(
|
||||
'address-scopes', project_id='not-the-owner')
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
from neutron_lib import constants as lib_constants
|
||||
|
||||
from neutron.db import rbac_db_models
|
||||
from neutron.objects import address_scope
|
||||
from neutron.tests.unit.objects import test_base
|
||||
from neutron.tests.unit.objects import test_rbac
|
||||
@@ -31,28 +30,6 @@ class AddressScopeDbObjectTestCase(test_base.BaseDbObjectTestCase,
|
||||
|
||||
_test_class = address_scope.AddressScope
|
||||
|
||||
def test_object_version_degradation_1_2_to_1_1_drop_shared_field(self):
|
||||
as_obj = address_scope.AddressScope()
|
||||
as_obj_1_2 = as_obj.obj_to_primitive(target_version='1.2')
|
||||
self.assertNotIn('shared', as_obj_1_2['versioned_object.data'])
|
||||
|
||||
as_obj_1_1 = as_obj.obj_to_primitive(target_version='1.1')
|
||||
self.assertIn('shared', as_obj_1_1['versioned_object.data'])
|
||||
self.assertFalse(as_obj_1_1['versioned_object.data']['shared'])
|
||||
|
||||
def test_object_version_degradation_1_2_to_1_1_shared_from_rbac(self):
|
||||
as_obj = self._make_object(self.obj_fields[0])
|
||||
as_obj.create()
|
||||
rbac = address_scope.AddressScopeRBAC(
|
||||
self.context, project_id=as_obj.project_id,
|
||||
object_id=as_obj.id,
|
||||
action=rbac_db_models.ACCESS_SHARED,
|
||||
target_project='*')
|
||||
rbac.create()
|
||||
|
||||
as_obj_1_1 = as_obj.obj_to_primitive(target_version='1.1')
|
||||
self.assertTrue(as_obj_1_1['versioned_object.data']['shared'])
|
||||
|
||||
|
||||
class AddressScopeRBACDbObjectTestCase(test_rbac.TestRBACObjectMixin,
|
||||
test_base.BaseDbObjectTestCase,
|
||||
|
||||
@@ -29,7 +29,7 @@ object_data = {
|
||||
'AddressAssociation': '1.0-b92160a3dd2fb7b951adcd2e6ae1665a',
|
||||
'AddressGroup': '1.2-1ddbf0a9f61785033ce31818ac62687e',
|
||||
'AddressGroupRBAC': '1.1-be82ed54376b85ee4f963d479ac48c91',
|
||||
'AddressScope': '1.2-2019fecf9701570128fba5d8a9f2f9e3',
|
||||
'AddressScope': '1.1-dd0dfdb67775892d3adc090e28e43bd8',
|
||||
'AddressScopeRBAC': '1.1-be82ed54376b85ee4f963d479ac48c91',
|
||||
'Agent': '1.1-4feb0abf8732a17c16dee962091d9203',
|
||||
'AllowedAddressPair': '1.0-9f9186b6f952fbf31d257b0458b852c0',
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
The ``shared`` attribute is no longer accepted when creating or updating
|
||||
address scopes. Use RBAC policies to share address scopes across
|
||||
projects instead.
|
||||
Reference in new issue
Block a user