Add normalized_cidr column to SG rules
New API extension was added in [1] to extend security group rules with "normalized_cidr" read only attribute. This patch implements this API extension in Neutron ML2 plugin and extends security group rules with "normalized_cidr" value. [1] https://review.opendev.org/#/c/743630/ Related-Bug: #1869129 Change-Id: I65584817a22f952da8da979ab68cd6cfaa2143be
This commit is contained in:
parent
5d4923d11d
commit
0e0c7fa07e
@ -17,6 +17,7 @@
|
|||||||
import functools
|
import functools
|
||||||
|
|
||||||
from neutron_lib.api.definitions import rbac_security_groups as rbac_sg_apidef
|
from neutron_lib.api.definitions import rbac_security_groups as rbac_sg_apidef
|
||||||
|
from neutron_lib.api.definitions import security_groups_normalized_cidr
|
||||||
from neutron_lib.api.definitions import security_groups_remote_address_group \
|
from neutron_lib.api.definitions import security_groups_remote_address_group \
|
||||||
as sgag_def
|
as sgag_def
|
||||||
from neutron_lib.api.definitions import stateful_security_group as stateful_sg
|
from neutron_lib.api.definitions import stateful_security_group as stateful_sg
|
||||||
@ -52,6 +53,7 @@ def disable_security_group_extension_by_config(aliases):
|
|||||||
_disable_extension(rbac_sg_apidef.ALIAS, aliases)
|
_disable_extension(rbac_sg_apidef.ALIAS, aliases)
|
||||||
_disable_extension(stateful_sg.ALIAS, aliases)
|
_disable_extension(stateful_sg.ALIAS, aliases)
|
||||||
_disable_extension(sgag_def.ALIAS, aliases)
|
_disable_extension(sgag_def.ALIAS, aliases)
|
||||||
|
_disable_extension(security_groups_normalized_cidr.ALIAS, aliases)
|
||||||
LOG.info('Disabled allowed-address-pairs extension.')
|
LOG.info('Disabled allowed-address-pairs extension.')
|
||||||
_disable_extension('allowed-address-pairs', aliases)
|
_disable_extension('allowed-address-pairs', aliases)
|
||||||
LOG.info('Disabled address-group extension.')
|
LOG.info('Disabled address-group extension.')
|
||||||
|
@ -667,6 +667,8 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase,
|
|||||||
return sg_id
|
return sg_id
|
||||||
|
|
||||||
def _make_security_group_rule_dict(self, security_group_rule, fields=None):
|
def _make_security_group_rule_dict(self, security_group_rule, fields=None):
|
||||||
|
|
||||||
|
# TODO(slaweq): switch this to use OVO instead of db object
|
||||||
res = {'id': security_group_rule['id'],
|
res = {'id': security_group_rule['id'],
|
||||||
'tenant_id': security_group_rule['tenant_id'],
|
'tenant_id': security_group_rule['tenant_id'],
|
||||||
'security_group_id': security_group_rule['security_group_id'],
|
'security_group_id': security_group_rule['security_group_id'],
|
||||||
@ -678,6 +680,8 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase,
|
|||||||
'remote_ip_prefix': security_group_rule['remote_ip_prefix'],
|
'remote_ip_prefix': security_group_rule['remote_ip_prefix'],
|
||||||
'remote_address_group_id': security_group_rule[
|
'remote_address_group_id': security_group_rule[
|
||||||
'remote_address_group_id'],
|
'remote_address_group_id'],
|
||||||
|
'normalized_cidr': self._get_normalized_cidr_from_rule(
|
||||||
|
security_group_rule),
|
||||||
'remote_group_id': security_group_rule['remote_group_id'],
|
'remote_group_id': security_group_rule['remote_group_id'],
|
||||||
'standard_attr_id': security_group_rule.standard_attr.id,
|
'standard_attr_id': security_group_rule.standard_attr.id,
|
||||||
}
|
}
|
||||||
@ -686,6 +690,15 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase,
|
|||||||
security_group_rule)
|
security_group_rule)
|
||||||
return db_utils.resource_fields(res, fields)
|
return db_utils.resource_fields(res, fields)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_normalized_cidr_from_rule(rule):
|
||||||
|
normalized_cidr = None
|
||||||
|
remote_ip_prefix = rule.get('remote_ip_prefix')
|
||||||
|
if remote_ip_prefix:
|
||||||
|
normalized_cidr = str(
|
||||||
|
net.AuthenticIPNetwork(remote_ip_prefix).cidr)
|
||||||
|
return normalized_cidr
|
||||||
|
|
||||||
def _rule_to_key(self, rule):
|
def _rule_to_key(self, rule):
|
||||||
def _normalize_rule_value(key, value):
|
def _normalize_rule_value(key, value):
|
||||||
# This string is used as a placeholder for str(None), but shorter.
|
# This string is used as a placeholder for str(None), but shorter.
|
||||||
|
20
neutron/extensions/security_groups_normalized_cidr.py
Normal file
20
neutron/extensions/security_groups_normalized_cidr.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from neutron_lib.api.definitions import security_groups_normalized_cidr
|
||||||
|
from neutron_lib.api import extensions
|
||||||
|
|
||||||
|
|
||||||
|
class Security_groups_normalized_cidr(extensions.APIExtensionDescriptor):
|
||||||
|
"""Extension class supporting normalized cidr in the SG rules."""
|
||||||
|
|
||||||
|
api_definition = security_groups_normalized_cidr
|
@ -39,7 +39,8 @@ class SecurityGroup(rbac_db.NeutronRbacObject):
|
|||||||
# Version 1.1: Add RBAC support
|
# Version 1.1: Add RBAC support
|
||||||
# Version 1.2: Added stateful support
|
# Version 1.2: Added stateful support
|
||||||
# Version 1.3: Added support for remote_address_group_id in rules
|
# Version 1.3: Added support for remote_address_group_id in rules
|
||||||
VERSION = '1.3'
|
# Version 1.4: Added support for normalized_cidr in rules
|
||||||
|
VERSION = '1.4'
|
||||||
|
|
||||||
# required by RbacNeutronMetaclass
|
# required by RbacNeutronMetaclass
|
||||||
rbac_db_cls = SecurityGroupRBAC
|
rbac_db_cls = SecurityGroupRBAC
|
||||||
@ -102,6 +103,16 @@ class SecurityGroup(rbac_db.NeutronRbacObject):
|
|||||||
rule['versioned_object.data'], '1.0')
|
rule['versioned_object.data'], '1.0')
|
||||||
rule['versioned_object.version'] = '1.0'
|
rule['versioned_object.version'] = '1.0'
|
||||||
|
|
||||||
|
def filter_normalized_cidr_from_rules(rules):
|
||||||
|
sg_rule = SecurityGroupRule()
|
||||||
|
for rule in rules:
|
||||||
|
rule_version = versionutils.convert_version_to_tuple(
|
||||||
|
rule['versioned_object.version'])
|
||||||
|
if rule_version > (1, 1):
|
||||||
|
sg_rule.obj_make_compatible(
|
||||||
|
rule['versioned_object.data'], '1.1')
|
||||||
|
rule['versioned_object.version'] = '1.1'
|
||||||
|
|
||||||
if _target_version < (1, 1):
|
if _target_version < (1, 1):
|
||||||
primitive.pop('shared')
|
primitive.pop('shared')
|
||||||
if _target_version < (1, 2):
|
if _target_version < (1, 2):
|
||||||
@ -109,6 +120,9 @@ class SecurityGroup(rbac_db.NeutronRbacObject):
|
|||||||
if _target_version < (1, 3):
|
if _target_version < (1, 3):
|
||||||
if 'rules' in primitive:
|
if 'rules' in primitive:
|
||||||
filter_remote_address_group_id_from_rules(primitive['rules'])
|
filter_remote_address_group_id_from_rules(primitive['rules'])
|
||||||
|
if _target_version < (1, 4):
|
||||||
|
if 'rules' in primitive:
|
||||||
|
filter_normalized_cidr_from_rules(primitive['rules'])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_bound_tenant_ids(cls, context, obj_id):
|
def get_bound_tenant_ids(cls, context, obj_id):
|
||||||
@ -138,7 +152,8 @@ class DefaultSecurityGroup(base.NeutronDbObject):
|
|||||||
class SecurityGroupRule(base.NeutronDbObject):
|
class SecurityGroupRule(base.NeutronDbObject):
|
||||||
# Version 1.0: Initial version
|
# Version 1.0: Initial version
|
||||||
# Version 1.1: Add remote address group support
|
# Version 1.1: Add remote address group support
|
||||||
VERSION = '1.1'
|
# Version 1.2: Added normalized cidr column
|
||||||
|
VERSION = '1.2'
|
||||||
|
|
||||||
db_model = sg_models.SecurityGroupRule
|
db_model = sg_models.SecurityGroupRule
|
||||||
|
|
||||||
@ -154,8 +169,11 @@ class SecurityGroupRule(base.NeutronDbObject):
|
|||||||
'port_range_max': common_types.PortRangeWith0Field(nullable=True),
|
'port_range_max': common_types.PortRangeWith0Field(nullable=True),
|
||||||
'remote_ip_prefix': common_types.IPNetworkField(nullable=True),
|
'remote_ip_prefix': common_types.IPNetworkField(nullable=True),
|
||||||
'remote_address_group_id': common_types.UUIDField(nullable=True),
|
'remote_address_group_id': common_types.UUIDField(nullable=True),
|
||||||
|
'normalized_cidr': common_types.IPNetworkField(nullable=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synthetic_fields = ['normalized_cidr']
|
||||||
|
|
||||||
foreign_keys = {'SecurityGroup': {'security_group_id': 'id'}}
|
foreign_keys = {'SecurityGroup': {'security_group_id': 'id'}}
|
||||||
|
|
||||||
fields_no_update = ['project_id', 'security_group_id', 'remote_group_id',
|
fields_no_update = ['project_id', 'security_group_id', 'remote_group_id',
|
||||||
@ -165,6 +183,8 @@ class SecurityGroupRule(base.NeutronDbObject):
|
|||||||
_target_version = versionutils.convert_version_to_tuple(target_version)
|
_target_version = versionutils.convert_version_to_tuple(target_version)
|
||||||
if _target_version < (1, 1):
|
if _target_version < (1, 1):
|
||||||
primitive.pop('remote_address_group_id', None)
|
primitive.pop('remote_address_group_id', None)
|
||||||
|
if _target_version < (1, 2):
|
||||||
|
primitive.pop('normalized_cidr', None)
|
||||||
|
|
||||||
# TODO(sayalilunkad): get rid of it once we switch the db model to using
|
# TODO(sayalilunkad): get rid of it once we switch the db model to using
|
||||||
# custom types.
|
# custom types.
|
||||||
@ -176,6 +196,28 @@ class SecurityGroupRule(base.NeutronDbObject):
|
|||||||
result['remote_ip_prefix'] = cls.filter_to_str(remote_ip_prefix)
|
result['remote_ip_prefix'] = cls.filter_to_str(remote_ip_prefix)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def _load_normalized_cidr(self, db_obj=None):
|
||||||
|
db_obj = db_obj or SecurityGroupRule.get_object(self.obj_context,
|
||||||
|
id=self.id)
|
||||||
|
if not db_obj:
|
||||||
|
return
|
||||||
|
|
||||||
|
cidr = None
|
||||||
|
if db_obj.remote_ip_prefix:
|
||||||
|
cidr = net_utils.AuthenticIPNetwork(db_obj.remote_ip_prefix).cidr
|
||||||
|
|
||||||
|
setattr(self, 'normalized_cidr', cidr)
|
||||||
|
self.obj_reset_changes(['normalized_cidr'])
|
||||||
|
|
||||||
|
def from_db_object(self, db_obj):
|
||||||
|
super(SecurityGroupRule, self).from_db_object(db_obj)
|
||||||
|
self._load_normalized_cidr(db_obj)
|
||||||
|
|
||||||
|
def obj_load_attr(self, attrname):
|
||||||
|
if attrname == 'normalized_cidr':
|
||||||
|
return self._load_normalized_cidr()
|
||||||
|
super(SecurityGroupRule, self).obj_load_attr(attrname)
|
||||||
|
|
||||||
# TODO(sayalilunkad): get rid of it once we switch the db model to using
|
# TODO(sayalilunkad): get rid of it once we switch the db model to using
|
||||||
# custom types.
|
# custom types.
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -48,6 +48,7 @@ from neutron_lib.api.definitions import provider_net
|
|||||||
from neutron_lib.api.definitions import rbac_address_scope
|
from neutron_lib.api.definitions import rbac_address_scope
|
||||||
from neutron_lib.api.definitions import rbac_security_groups as rbac_sg_apidef
|
from neutron_lib.api.definitions import rbac_security_groups as rbac_sg_apidef
|
||||||
from neutron_lib.api.definitions import rbac_subnetpool
|
from neutron_lib.api.definitions import rbac_subnetpool
|
||||||
|
from neutron_lib.api.definitions import security_groups_normalized_cidr
|
||||||
from neutron_lib.api.definitions import security_groups_port_filtering
|
from neutron_lib.api.definitions import security_groups_port_filtering
|
||||||
from neutron_lib.api.definitions import security_groups_remote_address_group
|
from neutron_lib.api.definitions import security_groups_remote_address_group
|
||||||
from neutron_lib.api.definitions import stateful_security_group
|
from neutron_lib.api.definitions import stateful_security_group
|
||||||
@ -206,6 +207,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
default_subnetpools.ALIAS,
|
default_subnetpools.ALIAS,
|
||||||
"subnet-service-types",
|
"subnet-service-types",
|
||||||
ip_substring_port_filtering.ALIAS,
|
ip_substring_port_filtering.ALIAS,
|
||||||
|
security_groups_normalized_cidr.ALIAS,
|
||||||
security_groups_port_filtering.ALIAS,
|
security_groups_port_filtering.ALIAS,
|
||||||
security_groups_remote_address_group.ALIAS,
|
security_groups_remote_address_group.ALIAS,
|
||||||
empty_string_filtering.ALIAS,
|
empty_string_filtering.ALIAS,
|
||||||
|
@ -691,3 +691,18 @@ class SecurityGroupRulesTest(base.BaseFullStackTestCase):
|
|||||||
|
|
||||||
self.assertRaises(nc_exc.OverQuotaClient,
|
self.assertRaises(nc_exc.OverQuotaClient,
|
||||||
self.safe_client.create_security_group, project_id)
|
self.safe_client.create_security_group, project_id)
|
||||||
|
|
||||||
|
def test_normalized_cidr_in_rule(self):
|
||||||
|
project_id = uuidutils.generate_uuid()
|
||||||
|
sg = self.safe_client.create_security_group(project_id)
|
||||||
|
|
||||||
|
rule = self.safe_client.create_security_group_rule(
|
||||||
|
project_id, sg['id'], direction='ingress',
|
||||||
|
remote_ip_prefix='10.0.0.34/24')
|
||||||
|
self.assertEqual('10.0.0.0/24', rule['normalized_cidr'])
|
||||||
|
self.assertEqual('10.0.0.34/24', rule['remote_ip_prefix'])
|
||||||
|
|
||||||
|
rule = self.safe_client.create_security_group_rule(
|
||||||
|
project_id, sg['id'], direction='ingress')
|
||||||
|
self.assertIsNone(rule['normalized_cidr'])
|
||||||
|
self.assertIsNone(rule['remote_ip_prefix'])
|
||||||
|
@ -125,7 +125,7 @@ class SecurityGroupDbMixinTestCase(testlib_api.SqlTestCase):
|
|||||||
with testtools.ExpectedException(
|
with testtools.ExpectedException(
|
||||||
securitygroup.SecurityGroupConflict):
|
securitygroup.SecurityGroupConflict):
|
||||||
self.mixin.create_security_group_rule(
|
self.mixin.create_security_group_rule(
|
||||||
self.ctx, mock.MagicMock())
|
self.ctx, FAKE_SECGROUP_RULE)
|
||||||
|
|
||||||
def test__check_for_duplicate_rules_does_not_drop_protocol(self):
|
def test__check_for_duplicate_rules_does_not_drop_protocol(self):
|
||||||
with mock.patch.object(self.mixin, 'get_security_group',
|
with mock.patch.object(self.mixin, 'get_security_group',
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from neutron_lib.api.definitions import security_groups_normalized_cidr
|
||||||
|
import webob.exc
|
||||||
|
|
||||||
|
from neutron.tests.unit.extensions import test_securitygroup
|
||||||
|
|
||||||
|
|
||||||
|
DB_PLUGIN_KLASS = (
|
||||||
|
'neutron.tests.unit.extensions.test_security_groups_normalized_cidr.'
|
||||||
|
'TestPlugin')
|
||||||
|
|
||||||
|
|
||||||
|
class SecurityGroupNormalizedCidrTestExtManager(
|
||||||
|
test_securitygroup.SecurityGroupTestExtensionManager):
|
||||||
|
|
||||||
|
def get_resources(self):
|
||||||
|
self.update_attributes_map(
|
||||||
|
security_groups_normalized_cidr.RESOURCE_ATTRIBUTE_MAP)
|
||||||
|
return super(
|
||||||
|
SecurityGroupNormalizedCidrTestExtManager, self).get_resources()
|
||||||
|
|
||||||
|
|
||||||
|
class TestPlugin(test_securitygroup.SecurityGroupTestPlugin):
|
||||||
|
|
||||||
|
supported_extension_aliases = ['security-group',
|
||||||
|
security_groups_normalized_cidr.ALIAS]
|
||||||
|
|
||||||
|
|
||||||
|
class TestSecurityGroupsNormalizedCidr(
|
||||||
|
test_securitygroup.SecurityGroupDBTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestSecurityGroupsNormalizedCidr, self).setUp(
|
||||||
|
plugin=DB_PLUGIN_KLASS,
|
||||||
|
ext_mgr=SecurityGroupNormalizedCidrTestExtManager())
|
||||||
|
|
||||||
|
def test_create_security_group_rule_with_not_normalized_cidr(self):
|
||||||
|
name = 'webservers'
|
||||||
|
description = 'my webservers'
|
||||||
|
remote_prefixes = ['10.0.0.120/24', '10.0.0.200/24']
|
||||||
|
with self.security_group(name, description) as sg:
|
||||||
|
sg_id = sg['security_group']['id']
|
||||||
|
for remote_ip_prefix in remote_prefixes:
|
||||||
|
rule = self._build_security_group_rule(
|
||||||
|
sg_id,
|
||||||
|
'ingress', 'tcp',
|
||||||
|
remote_ip_prefix=remote_ip_prefix)
|
||||||
|
res = self._create_security_group_rule(self.fmt, rule)
|
||||||
|
self.assertEqual(webob.exc.HTTPCreated.code, res.status_int)
|
||||||
|
res_sg = self.deserialize(self.fmt, res)
|
||||||
|
self.assertEqual(
|
||||||
|
'10.0.0.0/24',
|
||||||
|
res_sg['security_group_rule']['normalized_cidr']
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
remote_ip_prefix,
|
||||||
|
res_sg['security_group_rule']['remote_ip_prefix']
|
||||||
|
)
|
@ -77,6 +77,12 @@ class SecurityGroupTestExtensionManager(object):
|
|||||||
def get_request_extensions(self):
|
def get_request_extensions(self):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def update_attributes_map(self, attributes):
|
||||||
|
for resource, attrs in ext_sg.RESOURCE_ATTRIBUTE_MAP.items():
|
||||||
|
extended_attrs = attributes.get(resource)
|
||||||
|
if extended_attrs:
|
||||||
|
attrs.update(extended_attrs)
|
||||||
|
|
||||||
|
|
||||||
class SecurityGroupsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
class SecurityGroupsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||||
|
|
||||||
|
@ -102,10 +102,10 @@ object_data = {
|
|||||||
'RouterL3AgentBinding': '1.0-c5ba6c95e3a4c1236a55f490cd67da82',
|
'RouterL3AgentBinding': '1.0-c5ba6c95e3a4c1236a55f490cd67da82',
|
||||||
'RouterPort': '1.0-c8c8f499bcdd59186fcd83f323106908',
|
'RouterPort': '1.0-c8c8f499bcdd59186fcd83f323106908',
|
||||||
'RouterRoute': '1.0-07fc5337c801fb8c6ccfbcc5afb45907',
|
'RouterRoute': '1.0-07fc5337c801fb8c6ccfbcc5afb45907',
|
||||||
'SecurityGroup': '1.3-7b63b834e511856f54a09282d6843ecc',
|
'SecurityGroup': '1.4-7b63b834e511856f54a09282d6843ecc',
|
||||||
'SecurityGroupPortBinding': '1.0-6879d5c0af80396ef5a72934b6a6ef20',
|
'SecurityGroupPortBinding': '1.0-6879d5c0af80396ef5a72934b6a6ef20',
|
||||||
'SecurityGroupRBAC': '1.0-192845c5ed0718e1c54fac36936fcd7d',
|
'SecurityGroupRBAC': '1.0-192845c5ed0718e1c54fac36936fcd7d',
|
||||||
'SecurityGroupRule': '1.1-0a8614633901e353dd32948dc2f8708f',
|
'SecurityGroupRule': '1.2-27793368d4ac35f2ed6e0bb653c6aaad',
|
||||||
'SegmentHostMapping': '1.0-521597cf82ead26217c3bd10738f00f0',
|
'SegmentHostMapping': '1.0-521597cf82ead26217c3bd10738f00f0',
|
||||||
'ServiceProfile': '1.0-9beafc9e7d081b8258f3c5cb66ac5eed',
|
'ServiceProfile': '1.0-9beafc9e7d081b8258f3c5cb66ac5eed',
|
||||||
'StandardAttribute': '1.0-617d4f46524c4ce734a6fc1cc0ac6a0b',
|
'StandardAttribute': '1.0-617d4f46524c4ce734a6fc1cc0ac6a0b',
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
import collections
|
import collections
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
import netaddr
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
from neutron.objects import securitygroup
|
from neutron.objects import securitygroup
|
||||||
@ -72,6 +73,11 @@ class SecurityGroupDbObjTestCase(test_base.BaseDbObjectTestCase,
|
|||||||
# generated; we picked the former here
|
# generated; we picked the former here
|
||||||
rule['remote_group_id'] = None
|
rule['remote_group_id'] = None
|
||||||
|
|
||||||
|
sg_rule = self.get_random_db_fields(securitygroup.SecurityGroupRule)
|
||||||
|
self.model_map.update({
|
||||||
|
self._test_class.db_model: self.db_objs,
|
||||||
|
securitygroup.SecurityGroupRule.db_model: sg_rule})
|
||||||
|
|
||||||
def _create_test_security_group(self):
|
def _create_test_security_group(self):
|
||||||
self.objs[0].create()
|
self.objs[0].create()
|
||||||
return self.objs[0]
|
return self.objs[0]
|
||||||
@ -81,7 +87,8 @@ class SecurityGroupDbObjTestCase(test_base.BaseDbObjectTestCase,
|
|||||||
rule_params = {
|
rule_params = {
|
||||||
'project_id': sg_obj.project_id,
|
'project_id': sg_obj.project_id,
|
||||||
'security_group_id': sg_obj.id,
|
'security_group_id': sg_obj.id,
|
||||||
'remote_address_group_id': None}
|
'remote_address_group_id': None,
|
||||||
|
'remote_ip_prefix': netaddr.IPNetwork('10.0.0.120/24')}
|
||||||
sg_rule = securitygroup.SecurityGroupRule(
|
sg_rule = securitygroup.SecurityGroupRule(
|
||||||
self.context, **rule_params)
|
self.context, **rule_params)
|
||||||
sg_obj.rules = [sg_rule]
|
sg_obj.rules = [sg_rule]
|
||||||
@ -95,6 +102,13 @@ class SecurityGroupDbObjTestCase(test_base.BaseDbObjectTestCase,
|
|||||||
self.assertNotIn('remote_address_group_id',
|
self.assertNotIn('remote_address_group_id',
|
||||||
rule['versioned_object.data'])
|
rule['versioned_object.data'])
|
||||||
|
|
||||||
|
def test_object_version_degradation_1_4_to_1_3_no_normalized_cidr(self):
|
||||||
|
sg_obj = self._create_test_security_group_with_rule()
|
||||||
|
sg_obj_1_3 = sg_obj.obj_to_primitive('1.3')
|
||||||
|
for rule in sg_obj_1_3['versioned_object.data']['rules']:
|
||||||
|
self.assertEqual('1.1', rule['versioned_object.version'])
|
||||||
|
self.assertNotIn('normalized_cidr', rule['versioned_object.data'])
|
||||||
|
|
||||||
def test_object_version_degradation_1_2_to_1_1_no_stateful(self):
|
def test_object_version_degradation_1_2_to_1_1_no_stateful(self):
|
||||||
sg_stateful_obj = self._create_test_security_group()
|
sg_stateful_obj = self._create_test_security_group()
|
||||||
sg_no_stateful_obj = sg_stateful_obj.obj_to_primitive('1.1')
|
sg_no_stateful_obj = sg_stateful_obj.obj_to_primitive('1.1')
|
||||||
@ -281,3 +295,9 @@ class SecurityGroupRuleDbObjTestCase(test_base.BaseDbObjectTestCase,
|
|||||||
rule_no_remote_ag_obj = rule_remote_ag_obj.obj_to_primitive('1.0')
|
rule_no_remote_ag_obj = rule_remote_ag_obj.obj_to_primitive('1.0')
|
||||||
self.assertNotIn('remote_address_group_id',
|
self.assertNotIn('remote_address_group_id',
|
||||||
rule_no_remote_ag_obj['versioned_object.data'])
|
rule_no_remote_ag_obj['versioned_object.data'])
|
||||||
|
|
||||||
|
def test_object_version_degradation_1_2_to_1_1_no_normalized_cidr(self):
|
||||||
|
sg_rule_obj = self._create_test_security_group_rule()
|
||||||
|
sg_rule_10_obj = sg_rule_obj.obj_to_primitive('1.0')
|
||||||
|
self.assertNotIn('normalized_cidr',
|
||||||
|
sg_rule_10_obj['versioned_object.data'])
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Security group rule has now new, read only attribute ``normalized_cidr``
|
||||||
|
which contains network address from the CIDR provided in the
|
||||||
|
``remote_ip_prefix`` attribute.
|
||||||
|
This new attribute shows actual CIDR used by backend firewall drivers.
|
Loading…
x
Reference in New Issue
Block a user