Support remote address group in SG rules
- Add api extension and db model changes to support remote_address_group_id in SG rules. - RPC and firewall agent changes will be in the follow-up patches. Change-Id: I99681736d05eefd82bdba72b3866eab9468ef5dd Implements: blueprint address-groups-in-sg-rules
This commit is contained in:
parent
e59a7c9aca
commit
85c089eef2
|
@ -17,6 +17,8 @@
|
||||||
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_remote_address_group \
|
||||||
|
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
|
||||||
from oslo_concurrency import lockutils
|
from oslo_concurrency import lockutils
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
@ -49,6 +51,7 @@ def disable_security_group_extension_by_config(aliases):
|
||||||
_disable_extension('security-group', aliases)
|
_disable_extension('security-group', 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)
|
||||||
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.')
|
||||||
|
|
|
@ -16,12 +16,21 @@ from neutron_lib.callbacks import registry
|
||||||
from neutron_lib import constants
|
from neutron_lib import constants
|
||||||
from neutron_lib.db import resource_extend
|
from neutron_lib.db import resource_extend
|
||||||
from neutron_lib.db import utils as db_utils
|
from neutron_lib.db import utils as db_utils
|
||||||
|
from neutron_lib import exceptions
|
||||||
from neutron_lib.exceptions import address_group as ag_exc
|
from neutron_lib.exceptions import address_group as ag_exc
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
|
from neutron._i18n import _
|
||||||
from neutron.extensions import address_group as ag_ext
|
from neutron.extensions import address_group as ag_ext
|
||||||
from neutron.objects import address_group as ag_obj
|
from neutron.objects import address_group as ag_obj
|
||||||
from neutron.objects import base as base_obj
|
from neutron.objects import base as base_obj
|
||||||
|
from neutron.objects import securitygroup as sg_obj
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(hangyang): Remove this exception once neutron_lib > 2.6.1 is released.
|
||||||
|
class AddressGroupInUse(exceptions.InUse):
|
||||||
|
message = _("Address group %(address_group_id)s is in use on one or more "
|
||||||
|
"security group rules.")
|
||||||
|
|
||||||
|
|
||||||
# TODO(mlavalle) Following line should be deleted when
|
# TODO(mlavalle) Following line should be deleted when
|
||||||
|
@ -44,6 +53,19 @@ class AddressGroupDbMixin(ag_ext.AddressGroupPluginBase):
|
||||||
for addr_assoc in address_group['addresses']]
|
for addr_assoc in address_group['addresses']]
|
||||||
return db_utils.resource_fields(res, fields)
|
return db_utils.resource_fields(res, fields)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_address_group(context, ag_id, project_id=None):
|
||||||
|
"""Check if address group id exists for the given project"""
|
||||||
|
if project_id:
|
||||||
|
tmp_context_project_id = context.project_id
|
||||||
|
context.project_id = project_id
|
||||||
|
try:
|
||||||
|
if not ag_obj.AddressGroup.objects_exist(context, id=ag_id):
|
||||||
|
raise ag_exc.AddressGroupNotFound(address_group_id=ag_id)
|
||||||
|
finally:
|
||||||
|
if project_id:
|
||||||
|
context.project_id = tmp_context_project_id
|
||||||
|
|
||||||
def _get_address_group(self, context, id):
|
def _get_address_group(self, context, id):
|
||||||
obj = ag_obj.AddressGroup.get_object(context, id=id)
|
obj = ag_obj.AddressGroup.get_object(context, id=id)
|
||||||
if obj is None:
|
if obj is None:
|
||||||
|
@ -150,6 +172,10 @@ class AddressGroupDbMixin(ag_ext.AddressGroupPluginBase):
|
||||||
]
|
]
|
||||||
|
|
||||||
def delete_address_group(self, context, id):
|
def delete_address_group(self, context, id):
|
||||||
|
if sg_obj.SecurityGroupRule.get_objects(context.elevated(),
|
||||||
|
remote_address_group_id=id):
|
||||||
|
# TODO(hangyang): use exception from neutron_lib
|
||||||
|
raise AddressGroupInUse(address_group_id=id)
|
||||||
address_group = self._get_address_group(context, id)
|
address_group = self._get_address_group(context, id)
|
||||||
address_group.delete()
|
address_group.delete()
|
||||||
# TODO(mlavalle) this notification should be updated to publish when
|
# TODO(mlavalle) this notification should be updated to publish when
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
f010820fc498
|
a964d94b4677
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
# Copyright 2020 OpenStack Foundation
|
||||||
|
#
|
||||||
|
# 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 alembic import op
|
||||||
|
from neutron_lib.db import constants as db_const
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
"""support remote address group in SG rules
|
||||||
|
|
||||||
|
Revision ID: a964d94b4677
|
||||||
|
Revises: f010820fc498
|
||||||
|
Create Date: 2020-09-10 18:57:21.063935
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'a964d94b4677'
|
||||||
|
down_revision = 'f010820fc498'
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.add_column('securitygrouprules',
|
||||||
|
sa.Column('remote_address_group_id',
|
||||||
|
sa.String(length=db_const.UUID_FIELD_SIZE),
|
||||||
|
nullable=True))
|
||||||
|
op.create_foreign_key(None, 'securitygrouprules', 'address_groups',
|
||||||
|
['remote_address_group_id'],
|
||||||
|
['id'], ondelete='CASCADE')
|
|
@ -87,6 +87,11 @@ class SecurityGroupRule(standard_attr.HasStandardAttributes, model_base.BASEV2,
|
||||||
sa.ForeignKey("securitygroups.id",
|
sa.ForeignKey("securitygroups.id",
|
||||||
ondelete="CASCADE"),
|
ondelete="CASCADE"),
|
||||||
nullable=True)
|
nullable=True)
|
||||||
|
|
||||||
|
remote_address_group_id = sa.Column(sa.String(db_const.UUID_FIELD_SIZE),
|
||||||
|
sa.ForeignKey("address_groups.id",
|
||||||
|
ondelete="CASCADE"),
|
||||||
|
nullable=True)
|
||||||
revises_on_change = ('security_group', )
|
revises_on_change = ('security_group', )
|
||||||
direction = sa.Column(sa.Enum('ingress', 'egress',
|
direction = sa.Column(sa.Enum('ingress', 'egress',
|
||||||
name='securitygrouprules_direction'))
|
name='securitygrouprules_direction'))
|
||||||
|
|
|
@ -35,6 +35,7 @@ from sqlalchemy.orm import scoped_session
|
||||||
|
|
||||||
from neutron._i18n import _
|
from neutron._i18n import _
|
||||||
from neutron.common import _constants as const
|
from neutron.common import _constants as const
|
||||||
|
from neutron.db import address_group_db as ag_db
|
||||||
from neutron.db.models import securitygroup as sg_models
|
from neutron.db.models import securitygroup as sg_models
|
||||||
from neutron.db import rbac_db_mixin as rbac_mixin
|
from neutron.db import rbac_db_mixin as rbac_mixin
|
||||||
from neutron.extensions import securitygroup as ext_sg
|
from neutron.extensions import securitygroup as ext_sg
|
||||||
|
@ -426,6 +427,8 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase,
|
||||||
'security_group_id': rule_dict['security_group_id'],
|
'security_group_id': rule_dict['security_group_id'],
|
||||||
'direction': rule_dict['direction'],
|
'direction': rule_dict['direction'],
|
||||||
'remote_group_id': rule_dict.get('remote_group_id'),
|
'remote_group_id': rule_dict.get('remote_group_id'),
|
||||||
|
'remote_address_group_id': rule_dict.get(
|
||||||
|
'remote_address_group_id'),
|
||||||
'ethertype': rule_dict['ethertype'],
|
'ethertype': rule_dict['ethertype'],
|
||||||
'protocol': protocol,
|
'protocol': protocol,
|
||||||
'remote_ip_prefix': remote_ip_prefix,
|
'remote_ip_prefix': remote_ip_prefix,
|
||||||
|
@ -621,8 +624,12 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase,
|
||||||
self._validate_ip_prefix(rule)
|
self._validate_ip_prefix(rule)
|
||||||
self._validate_ethertype_and_protocol(rule)
|
self._validate_ethertype_and_protocol(rule)
|
||||||
|
|
||||||
if rule['remote_ip_prefix'] and rule['remote_group_id']:
|
remote = None
|
||||||
raise ext_sg.SecurityGroupRemoteGroupAndRemoteIpPrefix()
|
for key in ['remote_ip_prefix', 'remote_group_id',
|
||||||
|
'remote_address_group_id']:
|
||||||
|
if remote and rule.get(key):
|
||||||
|
raise ext_sg.SecurityGroupMultipleRemoteEntites()
|
||||||
|
remote = rule.get(key) or remote
|
||||||
|
|
||||||
remote_group_id = rule['remote_group_id']
|
remote_group_id = rule['remote_group_id']
|
||||||
# Check that remote_group_id exists for tenant
|
# Check that remote_group_id exists for tenant
|
||||||
|
@ -630,8 +637,14 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase,
|
||||||
self._check_security_group(context, remote_group_id,
|
self._check_security_group(context, remote_group_id,
|
||||||
tenant_id=rule['tenant_id'])
|
tenant_id=rule['tenant_id'])
|
||||||
|
|
||||||
security_group_id = rule['security_group_id']
|
remote_address_group_id = rule['remote_address_group_id']
|
||||||
|
# Check that remote_address_group_id exists for project
|
||||||
|
if remote_address_group_id:
|
||||||
|
ag_db.AddressGroupDbMixin.check_address_group(
|
||||||
|
context, remote_address_group_id,
|
||||||
|
project_id=rule['project_id'])
|
||||||
|
|
||||||
|
security_group_id = rule['security_group_id']
|
||||||
# Confirm that the tenant has permission
|
# Confirm that the tenant has permission
|
||||||
# to add rules to this security group.
|
# to add rules to this security group.
|
||||||
self._check_security_group(context, security_group_id,
|
self._check_security_group(context, security_group_id,
|
||||||
|
@ -663,6 +676,8 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase,
|
||||||
'port_range_min': security_group_rule['port_range_min'],
|
'port_range_min': security_group_rule['port_range_min'],
|
||||||
'port_range_max': security_group_rule['port_range_max'],
|
'port_range_max': security_group_rule['port_range_max'],
|
||||||
'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'],
|
||||||
'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,
|
||||||
}
|
}
|
||||||
|
@ -694,6 +709,7 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase,
|
||||||
'port_range_min',
|
'port_range_min',
|
||||||
'protocol',
|
'protocol',
|
||||||
'remote_group_id',
|
'remote_group_id',
|
||||||
|
'remote_address_group_id',
|
||||||
'remote_ip_prefix',
|
'remote_ip_prefix',
|
||||||
'security_group_id'
|
'security_group_id'
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# 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_remote_address_group
|
||||||
|
from neutron_lib.api import extensions
|
||||||
|
|
||||||
|
|
||||||
|
class Security_groups_remote_address_group(extensions.APIExtensionDescriptor):
|
||||||
|
"""Extension class supporting remote address group in security
|
||||||
|
group rules.
|
||||||
|
"""
|
||||||
|
api_definition = security_groups_remote_address_group
|
|
@ -95,9 +95,9 @@ class SecurityGroupRulesNotSingleTenant(exceptions.InvalidInput):
|
||||||
" not allowed")
|
" not allowed")
|
||||||
|
|
||||||
|
|
||||||
class SecurityGroupRemoteGroupAndRemoteIpPrefix(exceptions.InvalidInput):
|
class SecurityGroupMultipleRemoteEntites(exceptions.InvalidInput):
|
||||||
message = _("Only remote_ip_prefix or remote_group_id may "
|
message = _("Only one of remote_ip_prefix or remote_group_id or "
|
||||||
"be provided.")
|
"remote_address_group_id may be provided.")
|
||||||
|
|
||||||
|
|
||||||
class SecurityGroupProtocolRequiredWithPorts(exceptions.InvalidInput):
|
class SecurityGroupProtocolRequiredWithPorts(exceptions.InvalidInput):
|
||||||
|
|
|
@ -38,7 +38,8 @@ class SecurityGroup(rbac_db.NeutronRbacObject):
|
||||||
# Version 1.0: Initial version
|
# Version 1.0: Initial version
|
||||||
# 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.2'
|
# Version 1.3: Added support for remote_address_group_id in rules
|
||||||
|
VERSION = '1.3'
|
||||||
|
|
||||||
# required by RbacNeutronMetaclass
|
# required by RbacNeutronMetaclass
|
||||||
rbac_db_cls = SecurityGroupRBAC
|
rbac_db_cls = SecurityGroupRBAC
|
||||||
|
@ -93,10 +94,21 @@ class SecurityGroup(rbac_db.NeutronRbacObject):
|
||||||
|
|
||||||
def obj_make_compatible(self, primitive, target_version):
|
def obj_make_compatible(self, primitive, target_version):
|
||||||
_target_version = versionutils.convert_version_to_tuple(target_version)
|
_target_version = versionutils.convert_version_to_tuple(target_version)
|
||||||
|
|
||||||
|
def filter_remote_address_group_id_from_rules(rules):
|
||||||
|
sg_rule = SecurityGroupRule()
|
||||||
|
for rule in rules:
|
||||||
|
sg_rule.obj_make_compatible(
|
||||||
|
rule['versioned_object.data'], '1.0')
|
||||||
|
rule['versioned_object.version'] = '1.0'
|
||||||
|
|
||||||
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):
|
||||||
primitive.pop('stateful')
|
primitive.pop('stateful')
|
||||||
|
if _target_version < (1, 3):
|
||||||
|
if 'rules' in primitive:
|
||||||
|
filter_remote_address_group_id_from_rules(primitive['rules'])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_bound_tenant_ids(cls, context, obj_id):
|
def get_bound_tenant_ids(cls, context, obj_id):
|
||||||
|
@ -125,7 +137,8 @@ class DefaultSecurityGroup(base.NeutronDbObject):
|
||||||
@base.NeutronObjectRegistry.register
|
@base.NeutronObjectRegistry.register
|
||||||
class SecurityGroupRule(base.NeutronDbObject):
|
class SecurityGroupRule(base.NeutronDbObject):
|
||||||
# Version 1.0: Initial version
|
# Version 1.0: Initial version
|
||||||
VERSION = '1.0'
|
# Version 1.1: Add remote address group support
|
||||||
|
VERSION = '1.1'
|
||||||
|
|
||||||
db_model = sg_models.SecurityGroupRule
|
db_model = sg_models.SecurityGroupRule
|
||||||
|
|
||||||
|
@ -140,11 +153,18 @@ class SecurityGroupRule(base.NeutronDbObject):
|
||||||
'port_range_min': common_types.PortRangeWith0Field(nullable=True),
|
'port_range_min': common_types.PortRangeWith0Field(nullable=True),
|
||||||
'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),
|
||||||
}
|
}
|
||||||
|
|
||||||
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',
|
||||||
|
'remote_address_group_id']
|
||||||
|
|
||||||
|
def obj_make_compatible(self, primitive, target_version):
|
||||||
|
_target_version = versionutils.convert_version_to_tuple(target_version)
|
||||||
|
if _target_version < (1, 1):
|
||||||
|
primitive.pop('remote_address_group_id', 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.
|
||||||
|
|
|
@ -49,6 +49,7 @@ 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_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 stateful_security_group
|
from neutron_lib.api.definitions import stateful_security_group
|
||||||
from neutron_lib.api.definitions import subnet as subnet_def
|
from neutron_lib.api.definitions import subnet as subnet_def
|
||||||
from neutron_lib.api.definitions import subnet_onboard as subnet_onboard_def
|
from neutron_lib.api.definitions import subnet_onboard as subnet_onboard_def
|
||||||
|
@ -206,6 +207,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
"subnet-service-types",
|
"subnet-service-types",
|
||||||
ip_substring_port_filtering.ALIAS,
|
ip_substring_port_filtering.ALIAS,
|
||||||
security_groups_port_filtering.ALIAS,
|
security_groups_port_filtering.ALIAS,
|
||||||
|
security_groups_remote_address_group.ALIAS,
|
||||||
empty_string_filtering.ALIAS,
|
empty_string_filtering.ALIAS,
|
||||||
filter_apidef.ALIAS,
|
filter_apidef.ALIAS,
|
||||||
port_mac_address_regenerate.ALIAS,
|
port_mac_address_regenerate.ALIAS,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Keep entries alphabetically
|
# Keep entries alphabetically
|
||||||
# NOTE: The first entry should not use '+=' and a comma.
|
# NOTE: The first entry should not use '+=' and a comma.
|
||||||
NETWORK_API_EXTENSIONS="address-scope"
|
NETWORK_API_EXTENSIONS="address-group"
|
||||||
|
NETWORK_API_EXTENSIONS+=",address-scope"
|
||||||
NETWORK_API_EXTENSIONS+=",agent"
|
NETWORK_API_EXTENSIONS+=",agent"
|
||||||
NETWORK_API_EXTENSIONS+=",allowed-address-pairs"
|
NETWORK_API_EXTENSIONS+=",allowed-address-pairs"
|
||||||
NETWORK_API_EXTENSIONS+=",auto-allocated-topology"
|
NETWORK_API_EXTENSIONS+=",auto-allocated-topology"
|
||||||
|
@ -52,6 +53,7 @@ NETWORK_API_EXTENSIONS+=",router"
|
||||||
NETWORK_API_EXTENSIONS+=",router-admin-state-down-before-update"
|
NETWORK_API_EXTENSIONS+=",router-admin-state-down-before-update"
|
||||||
NETWORK_API_EXTENSIONS+=",router_availability_zone"
|
NETWORK_API_EXTENSIONS+=",router_availability_zone"
|
||||||
NETWORK_API_EXTENSIONS+=",security-group"
|
NETWORK_API_EXTENSIONS+=",security-group"
|
||||||
|
NETWORK_API_EXTENSIONS+=",security-groups-remote-address-group"
|
||||||
NETWORK_API_EXTENSIONS+=",port-mac-address-regenerate"
|
NETWORK_API_EXTENSIONS+=",port-mac-address-regenerate"
|
||||||
NETWORK_API_EXTENSIONS+=",port-numa-affinity-policy"
|
NETWORK_API_EXTENSIONS+=",port-numa-affinity-policy"
|
||||||
NETWORK_API_EXTENSIONS+=",port-security-groups-filtering"
|
NETWORK_API_EXTENSIONS+=",port-security-groups-filtering"
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
|
from neutron_lib.api.definitions import security_groups_remote_address_group \
|
||||||
|
as sgag_def
|
||||||
from neutron_lib import constants as n_const
|
from neutron_lib import constants as n_const
|
||||||
from neutron_lib import context
|
from neutron_lib import context
|
||||||
from neutron_lib.db import api as db_api
|
from neutron_lib.db import api as db_api
|
||||||
|
@ -113,7 +115,8 @@ class TestMaintenancePlugin(test_securitygroup.SecurityGroupTestPlugin,
|
||||||
__native_pagination_support = True
|
__native_pagination_support = True
|
||||||
__native_sorting_support = True
|
__native_sorting_support = True
|
||||||
|
|
||||||
supported_extension_aliases = ['external-net', 'security-group']
|
supported_extension_aliases = ['external-net', 'security-group',
|
||||||
|
sgag_def.ALIAS]
|
||||||
|
|
||||||
|
|
||||||
class TestRevisionNumberMaintenance(test_securitygroup.SecurityGroupsTestCase,
|
class TestRevisionNumberMaintenance(test_securitygroup.SecurityGroupsTestCase,
|
||||||
|
|
|
@ -50,6 +50,7 @@ FAKE_SECGROUP_RULE = {
|
||||||
'remote_ip_prefix': '10.0.0.1',
|
'remote_ip_prefix': '10.0.0.1',
|
||||||
'ethertype': 'IPv4',
|
'ethertype': 'IPv4',
|
||||||
'remote_group_id': None,
|
'remote_group_id': None,
|
||||||
|
'remote_address_group_id': None,
|
||||||
'security_group_id': 'None',
|
'security_group_id': 'None',
|
||||||
'direction': 'ingress'
|
'direction': 'ingress'
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ import contextlib
|
||||||
import copy
|
import copy
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
|
from neutron_lib.api.definitions import security_groups_remote_address_group \
|
||||||
|
as sgag_def
|
||||||
from neutron_lib.api import validators
|
from neutron_lib.api import validators
|
||||||
from neutron_lib import constants as const
|
from neutron_lib import constants as const
|
||||||
from neutron_lib import context
|
from neutron_lib import context
|
||||||
|
@ -29,12 +31,15 @@ import oslo_db.exception as exc
|
||||||
import testtools
|
import testtools
|
||||||
import webob.exc
|
import webob.exc
|
||||||
|
|
||||||
|
from neutron.db import address_group_db
|
||||||
from neutron.db import db_base_plugin_v2
|
from neutron.db import db_base_plugin_v2
|
||||||
from neutron.db import securitygroups_db
|
from neutron.db import securitygroups_db
|
||||||
|
from neutron.extensions import address_group as ext_ag
|
||||||
from neutron.extensions import securitygroup as ext_sg
|
from neutron.extensions import securitygroup as ext_sg
|
||||||
from neutron.extensions import standardattrdescription
|
from neutron.extensions import standardattrdescription
|
||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
from neutron.tests.unit.db import test_db_base_plugin_v2
|
from neutron.tests.unit.db import test_db_base_plugin_v2
|
||||||
|
from neutron.tests.unit.extensions import test_address_group
|
||||||
|
|
||||||
DB_PLUGIN_KLASS = ('neutron.tests.unit.extensions.test_securitygroup.'
|
DB_PLUGIN_KLASS = ('neutron.tests.unit.extensions.test_securitygroup.'
|
||||||
'SecurityGroupTestPlugin')
|
'SecurityGroupTestPlugin')
|
||||||
|
@ -60,7 +65,11 @@ class SecurityGroupTestExtensionManager(object):
|
||||||
ext_sg.RESOURCE_ATTRIBUTE_MAP[ext_sg.SECURITYGROUPS])
|
ext_sg.RESOURCE_ATTRIBUTE_MAP[ext_sg.SECURITYGROUPS])
|
||||||
sg_attr_desc = ext_res[ext_sg.SECURITYGROUPS]
|
sg_attr_desc = ext_res[ext_sg.SECURITYGROUPS]
|
||||||
existing_sg_attr_map.update(sg_attr_desc)
|
existing_sg_attr_map.update(sg_attr_desc)
|
||||||
return ext_sg.Securitygroup.get_resources()
|
# update with the remote address group api definition
|
||||||
|
ext_sg.Securitygroup().update_attributes_map(
|
||||||
|
sgag_def.RESOURCE_ATTRIBUTE_MAP)
|
||||||
|
return (ext_sg.Securitygroup.get_resources() +
|
||||||
|
ext_ag.Address_group().get_resources())
|
||||||
|
|
||||||
def get_actions(self):
|
def get_actions(self):
|
||||||
return []
|
return []
|
||||||
|
@ -97,6 +106,7 @@ class SecurityGroupsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||||
self, security_group_id, direction, proto,
|
self, security_group_id, direction, proto,
|
||||||
port_range_min=None, port_range_max=None,
|
port_range_min=None, port_range_max=None,
|
||||||
remote_ip_prefix=None, remote_group_id=None,
|
remote_ip_prefix=None, remote_group_id=None,
|
||||||
|
remote_address_group_id=None,
|
||||||
tenant_id=test_db_base_plugin_v2.TEST_TENANT_ID,
|
tenant_id=test_db_base_plugin_v2.TEST_TENANT_ID,
|
||||||
ethertype=const.IPv4):
|
ethertype=const.IPv4):
|
||||||
|
|
||||||
|
@ -117,6 +127,10 @@ class SecurityGroupsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||||
if remote_group_id:
|
if remote_group_id:
|
||||||
data['security_group_rule']['remote_group_id'] = remote_group_id
|
data['security_group_rule']['remote_group_id'] = remote_group_id
|
||||||
|
|
||||||
|
if remote_address_group_id:
|
||||||
|
data['security_group_rule']['remote_address_group_id'] = \
|
||||||
|
remote_address_group_id
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def _create_security_group_rule(self, fmt, rules, **kwargs):
|
def _create_security_group_rule(self, fmt, rules, **kwargs):
|
||||||
|
@ -160,6 +174,7 @@ class SecurityGroupsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||||
direction='ingress', protocol=const.PROTO_NAME_TCP,
|
direction='ingress', protocol=const.PROTO_NAME_TCP,
|
||||||
port_range_min='22', port_range_max='22',
|
port_range_min='22', port_range_max='22',
|
||||||
remote_ip_prefix=None, remote_group_id=None,
|
remote_ip_prefix=None, remote_group_id=None,
|
||||||
|
remote_address_group_id=None,
|
||||||
fmt=None, ethertype=const.IPv4):
|
fmt=None, ethertype=const.IPv4):
|
||||||
if not fmt:
|
if not fmt:
|
||||||
fmt = self.fmt
|
fmt = self.fmt
|
||||||
|
@ -169,6 +184,7 @@ class SecurityGroupsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||||
port_range_max,
|
port_range_max,
|
||||||
remote_ip_prefix,
|
remote_ip_prefix,
|
||||||
remote_group_id,
|
remote_group_id,
|
||||||
|
remote_address_group_id,
|
||||||
ethertype=ethertype)
|
ethertype=ethertype)
|
||||||
security_group_rule = self._make_security_group_rule(self.fmt, rule)
|
security_group_rule = self._make_security_group_rule(self.fmt, rule)
|
||||||
yield security_group_rule
|
yield security_group_rule
|
||||||
|
@ -194,7 +210,8 @@ class SecurityGroupsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||||
|
|
||||||
|
|
||||||
class SecurityGroupTestPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
class SecurityGroupTestPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
securitygroups_db.SecurityGroupDbMixin):
|
securitygroups_db.SecurityGroupDbMixin,
|
||||||
|
address_group_db.AddressGroupDbMixin):
|
||||||
"""Test plugin that implements necessary calls on create/delete port for
|
"""Test plugin that implements necessary calls on create/delete port for
|
||||||
associating ports with security groups.
|
associating ports with security groups.
|
||||||
"""
|
"""
|
||||||
|
@ -248,7 +265,8 @@ class SecurityGroupTestPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
return neutron_lports
|
return neutron_lports
|
||||||
|
|
||||||
|
|
||||||
class SecurityGroupDBTestCase(SecurityGroupsTestCase):
|
class SecurityGroupDBTestCase(SecurityGroupsTestCase,
|
||||||
|
test_address_group.AddressGroupTestCase):
|
||||||
def setUp(self, plugin=None, ext_mgr=None):
|
def setUp(self, plugin=None, ext_mgr=None):
|
||||||
self._backup = copy.deepcopy(ext_sg.RESOURCE_ATTRIBUTE_MAP)
|
self._backup = copy.deepcopy(ext_sg.RESOURCE_ATTRIBUTE_MAP)
|
||||||
self.addCleanup(self._restore)
|
self.addCleanup(self._restore)
|
||||||
|
@ -659,10 +677,12 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||||
port_range_min = 22
|
port_range_min = 22
|
||||||
port_range_max = 22
|
port_range_max = 22
|
||||||
ethertype = 'ipV4'
|
ethertype = 'ipV4'
|
||||||
with self.security_group_rule(security_group_id, direction,
|
with self.security_group_rule(security_group_id,
|
||||||
protocol, port_range_min,
|
direction=direction,
|
||||||
port_range_max,
|
protocol=protocol,
|
||||||
remote_ip_prefix,
|
port_range_min=port_range_min,
|
||||||
|
port_range_max=port_range_max,
|
||||||
|
remote_ip_prefix=remote_ip_prefix,
|
||||||
ethertype=ethertype) as rule:
|
ethertype=ethertype) as rule:
|
||||||
|
|
||||||
# the lower case value will be return
|
# the lower case value will be return
|
||||||
|
@ -689,10 +709,12 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||||
('protocol', protocol),
|
('protocol', protocol),
|
||||||
('port_range_min', port_range_min),
|
('port_range_min', port_range_min),
|
||||||
('port_range_max', port_range_max)]
|
('port_range_max', port_range_max)]
|
||||||
with self.security_group_rule(security_group_id, direction,
|
with self.security_group_rule(security_group_id,
|
||||||
protocol, port_range_min,
|
direction=direction,
|
||||||
port_range_max,
|
protocol=protocol,
|
||||||
remote_ip_prefix):
|
port_range_min=port_range_min,
|
||||||
|
port_range_max=port_range_max,
|
||||||
|
remote_ip_prefix=remote_ip_prefix):
|
||||||
|
|
||||||
group = self.deserialize(
|
group = self.deserialize(
|
||||||
self.fmt, res.get_response(self.ext_api))
|
self.fmt, res.get_response(self.ext_api))
|
||||||
|
@ -951,10 +973,13 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||||
('protocol', protocol),
|
('protocol', protocol),
|
||||||
('port_range_min', port_range_min),
|
('port_range_min', port_range_min),
|
||||||
('port_range_max', port_range_max)]
|
('port_range_max', port_range_max)]
|
||||||
with self.security_group_rule(security_group_id, direction,
|
with self.security_group_rule(security_group_id,
|
||||||
protocol, port_range_min,
|
direction=direction,
|
||||||
port_range_max,
|
protocol=protocol,
|
||||||
remote_ip_prefix) as rule:
|
port_range_min=port_range_min,
|
||||||
|
port_range_max=port_range_max,
|
||||||
|
remote_ip_prefix=remote_ip_prefix
|
||||||
|
) as rule:
|
||||||
for k, v, in keys:
|
for k, v, in keys:
|
||||||
self.assertEqual(v, rule['security_group_rule'][k])
|
self.assertEqual(v, rule['security_group_rule'][k])
|
||||||
|
|
||||||
|
@ -975,14 +1000,76 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||||
('protocol', protocol),
|
('protocol', protocol),
|
||||||
('port_range_min', port_range_min),
|
('port_range_min', port_range_min),
|
||||||
('port_range_max', port_range_max)]
|
('port_range_max', port_range_max)]
|
||||||
with self.security_group_rule(security_group_id, direction,
|
with self.security_group_rule(security_group_id,
|
||||||
protocol, port_range_min,
|
direction=direction,
|
||||||
port_range_max,
|
protocol=protocol,
|
||||||
|
port_range_min=port_range_min,
|
||||||
|
port_range_max=port_range_max,
|
||||||
remote_group_id=remote_group_id
|
remote_group_id=remote_group_id
|
||||||
) as rule:
|
) as rule:
|
||||||
for k, v, in keys:
|
for k, v, in keys:
|
||||||
self.assertEqual(v, rule['security_group_rule'][k])
|
self.assertEqual(v, rule['security_group_rule'][k])
|
||||||
|
|
||||||
|
def test_create_security_group_rule_remote_address_group_id(self):
|
||||||
|
name = 'webservers'
|
||||||
|
description = 'my webservers'
|
||||||
|
ag = self._test_create_address_group(name='foo')
|
||||||
|
ag_id = ag['address_group']['id']
|
||||||
|
with self.security_group(name, description) as sg:
|
||||||
|
security_group_id = sg['security_group']['id']
|
||||||
|
direction = "ingress"
|
||||||
|
remote_address_group_id = ag_id
|
||||||
|
protocol = const.PROTO_NAME_TCP
|
||||||
|
port_range_min = 22
|
||||||
|
port_range_max = 22
|
||||||
|
keys = [('remote_address_group_id', remote_address_group_id),
|
||||||
|
('security_group_id', security_group_id),
|
||||||
|
('direction', direction),
|
||||||
|
('protocol', protocol),
|
||||||
|
('port_range_min', port_range_min),
|
||||||
|
('port_range_max', port_range_max)]
|
||||||
|
with self.security_group_rule(security_group_id,
|
||||||
|
direction=direction,
|
||||||
|
protocol=protocol,
|
||||||
|
port_range_min=port_range_min,
|
||||||
|
port_range_max=port_range_max,
|
||||||
|
remote_address_group_id=(
|
||||||
|
remote_address_group_id)
|
||||||
|
) as rule:
|
||||||
|
for k, v, in keys:
|
||||||
|
self.assertEqual(v, rule['security_group_rule'][k])
|
||||||
|
|
||||||
|
def test_delete_address_group_in_use(self):
|
||||||
|
ag = self._test_create_address_group(name='foo')
|
||||||
|
ag_id = ag['address_group']['id']
|
||||||
|
with self.security_group() as sg:
|
||||||
|
security_group_id = sg['security_group']['id']
|
||||||
|
with self.security_group_rule(security_group_id,
|
||||||
|
remote_address_group_id=ag_id):
|
||||||
|
self._delete('address-groups', ag['address_group']['id'],
|
||||||
|
expected_code=webob.exc.HTTPConflict.code)
|
||||||
|
|
||||||
|
def test_create_security_group_rule_multiple_remotes(self):
|
||||||
|
name = 'webservers'
|
||||||
|
description = 'my webservers'
|
||||||
|
ag = self._test_create_address_group(name='foo')
|
||||||
|
ag_id = ag['address_group']['id']
|
||||||
|
with self.security_group(name, description) as sg:
|
||||||
|
sg_id = sg['security_group']['id']
|
||||||
|
for remote in [
|
||||||
|
{'remote_ip_prefix': '10.0.0.0/8', 'remote_group_id': sg_id},
|
||||||
|
{'remote_group_id': sg_id, 'remote_address_group_id': ag_id},
|
||||||
|
{'remote_ip_prefix': '10.0.0.0/8',
|
||||||
|
'remote_address_group_id': ag_id},
|
||||||
|
{'remote_ip_prefix': '10.0.0.0/8', 'remote_group_id': sg_id,
|
||||||
|
'remote_address_group_id': ag_id}
|
||||||
|
]:
|
||||||
|
rule = self._build_security_group_rule(sg_id, "ingress",
|
||||||
|
const.PROTO_NAME_TCP,
|
||||||
|
**remote)
|
||||||
|
res = self._create_security_group_rule(self.fmt, rule)
|
||||||
|
self.assertEqual(webob.exc.HTTPBadRequest.code, res.status_int)
|
||||||
|
|
||||||
def test_create_security_group_rule_port_range_min_max_limits(self):
|
def test_create_security_group_rule_port_range_min_max_limits(self):
|
||||||
name = 'webservers'
|
name = 'webservers'
|
||||||
description = 'my webservers'
|
description = 'my webservers'
|
||||||
|
@ -998,9 +1085,12 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||||
('protocol', protocol),
|
('protocol', protocol),
|
||||||
('port_range_min', None),
|
('port_range_min', None),
|
||||||
('port_range_max', None)]
|
('port_range_max', None)]
|
||||||
with self.security_group_rule(security_group_id, direction,
|
with self.security_group_rule(security_group_id,
|
||||||
protocol, port_range_min,
|
direction=direction,
|
||||||
port_range_max) as rule:
|
protocol=protocol,
|
||||||
|
port_range_min=port_range_min,
|
||||||
|
port_range_max=port_range_max
|
||||||
|
) as rule:
|
||||||
for k, v, in keys:
|
for k, v, in keys:
|
||||||
self.assertEqual(v, rule['security_group_rule'][k])
|
self.assertEqual(v, rule['security_group_rule'][k])
|
||||||
|
|
||||||
|
@ -1023,10 +1113,13 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||||
('protocol', protocol),
|
('protocol', protocol),
|
||||||
('port_range_min', port_range_min),
|
('port_range_min', port_range_min),
|
||||||
('port_range_max', port_range_max)]
|
('port_range_max', port_range_max)]
|
||||||
with self.security_group_rule(security_group_id, direction,
|
with self.security_group_rule(security_group_id,
|
||||||
protocol, port_range_min,
|
direction=direction,
|
||||||
port_range_max,
|
protocol=protocol,
|
||||||
remote_ip_prefix) as rule:
|
port_range_min=port_range_min,
|
||||||
|
port_range_max=port_range_max,
|
||||||
|
remote_ip_prefix=remote_ip_prefix
|
||||||
|
) as rule:
|
||||||
for k, v, in keys:
|
for k, v, in keys:
|
||||||
self.assertEqual(v, rule['security_group_rule'][k])
|
self.assertEqual(v, rule['security_group_rule'][k])
|
||||||
|
|
||||||
|
@ -1048,10 +1141,13 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||||
('protocol', protocol),
|
('protocol', protocol),
|
||||||
('port_range_min', port_range_min),
|
('port_range_min', port_range_min),
|
||||||
('port_range_max', port_range_max)]
|
('port_range_max', port_range_max)]
|
||||||
with self.security_group_rule(security_group_id, direction,
|
with self.security_group_rule(security_group_id,
|
||||||
protocol, port_range_min,
|
direction=direction,
|
||||||
port_range_max,
|
protocol=protocol,
|
||||||
remote_ip_prefix) as rule:
|
port_range_min=port_range_min,
|
||||||
|
port_range_max=port_range_max,
|
||||||
|
remote_ip_prefix=remote_ip_prefix
|
||||||
|
) as rule:
|
||||||
for k, v, in keys:
|
for k, v, in keys:
|
||||||
self.assertEqual(v, rule['security_group_rule'][k])
|
self.assertEqual(v, rule['security_group_rule'][k])
|
||||||
|
|
||||||
|
@ -1075,12 +1171,13 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||||
('protocol', protocol),
|
('protocol', protocol),
|
||||||
('port_range_min', port_range_min),
|
('port_range_min', port_range_min),
|
||||||
('port_range_max', port_range_max)]
|
('port_range_max', port_range_max)]
|
||||||
with self.security_group_rule(security_group_id, direction,
|
with self.security_group_rule(security_group_id,
|
||||||
protocol, port_range_min,
|
direction=direction,
|
||||||
port_range_max,
|
protocol=protocol,
|
||||||
remote_ip_prefix,
|
port_range_min=port_range_min,
|
||||||
None, None,
|
port_range_max=port_range_max,
|
||||||
ethertype) as rule:
|
remote_ip_prefix=remote_ip_prefix,
|
||||||
|
ethertype=ethertype) as rule:
|
||||||
for k, v, in keys:
|
for k, v, in keys:
|
||||||
self.assertEqual(v, rule['security_group_rule'][k])
|
self.assertEqual(v, rule['security_group_rule'][k])
|
||||||
|
|
||||||
|
@ -1097,11 +1194,11 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||||
('direction', direction),
|
('direction', direction),
|
||||||
('ethertype', ethertype),
|
('ethertype', ethertype),
|
||||||
('protocol', protocol)]
|
('protocol', protocol)]
|
||||||
with self.security_group_rule(security_group_id, direction,
|
with self.security_group_rule(security_group_id,
|
||||||
protocol, None, None,
|
direction=direction,
|
||||||
remote_ip_prefix,
|
protocol=protocol,
|
||||||
None, None,
|
remote_ip_prefix=remote_ip_prefix,
|
||||||
ethertype) as rule:
|
ethertype=ethertype) as rule:
|
||||||
for k, v, in keys:
|
for k, v, in keys:
|
||||||
# IPv6 ICMP protocol will always be 'ipv6-icmp'
|
# IPv6 ICMP protocol will always be 'ipv6-icmp'
|
||||||
if k == 'protocol':
|
if k == 'protocol':
|
||||||
|
@ -1129,11 +1226,11 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||||
('direction', direction),
|
('direction', direction),
|
||||||
('ethertype', ethertype),
|
('ethertype', ethertype),
|
||||||
('protocol', protocol)]
|
('protocol', protocol)]
|
||||||
with self.security_group_rule(security_group_id, direction,
|
with self.security_group_rule(security_group_id,
|
||||||
protocol, None, None,
|
direction=direction,
|
||||||
remote_ip_prefix,
|
protocol=protocol,
|
||||||
None, None,
|
remote_ip_prefix=remote_ip_prefix,
|
||||||
ethertype) as rule:
|
ethertype=ethertype) as rule:
|
||||||
for k, v, in keys:
|
for k, v, in keys:
|
||||||
# IPv6 ICMP protocol will always be '58'
|
# IPv6 ICMP protocol will always be '58'
|
||||||
if k == 'protocol':
|
if k == 'protocol':
|
||||||
|
@ -1255,6 +1352,26 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||||
self.deserialize(self.fmt, res)
|
self.deserialize(self.fmt, res)
|
||||||
self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int)
|
self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int)
|
||||||
|
|
||||||
|
def test_create_security_group_rule_bad_remote_address_group_id(self):
|
||||||
|
name = 'webservers'
|
||||||
|
description = 'my webservers'
|
||||||
|
with self.security_group(name, description) as sg:
|
||||||
|
security_group_id = sg['security_group']['id']
|
||||||
|
remote_address_group_id = "4cd70774-cc67-4a87-9b39-7d1db38eb087"
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = const.PROTO_NAME_TCP
|
||||||
|
port_range_min = 22
|
||||||
|
port_range_max = 22
|
||||||
|
rule = self._build_security_group_rule(security_group_id, direction,
|
||||||
|
protocol, port_range_min,
|
||||||
|
port_range_max,
|
||||||
|
remote_address_group_id=(
|
||||||
|
remote_address_group_id
|
||||||
|
))
|
||||||
|
res = self._create_security_group_rule(self.fmt, rule)
|
||||||
|
self.deserialize(self.fmt, res)
|
||||||
|
self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int)
|
||||||
|
|
||||||
def test_create_security_group_rule_duplicate_rules(self):
|
def test_create_security_group_rule_duplicate_rules(self):
|
||||||
name = 'webservers'
|
name = 'webservers'
|
||||||
description = 'my webservers'
|
description = 'my webservers'
|
||||||
|
@ -1961,7 +2078,9 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
||||||
'port_range_min': None,
|
'port_range_min': None,
|
||||||
'port_range_max': None,
|
'port_range_max': None,
|
||||||
'remote_ip_prefix': None,
|
'remote_ip_prefix': None,
|
||||||
'remote_group_id': None})
|
'remote_group_id': None,
|
||||||
|
'remote_address_group_id':
|
||||||
|
None})
|
||||||
result = self.plugin.create_security_group_rule(
|
result = self.plugin.create_security_group_rule(
|
||||||
neutron_context, rule)
|
neutron_context, rule)
|
||||||
self.assertEqual(specified_id, result['id'])
|
self.assertEqual(specified_id, result['id'])
|
||||||
|
|
|
@ -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.2-7b63b834e511856f54a09282d6843ecc',
|
'SecurityGroup': '1.3-7b63b834e511856f54a09282d6843ecc',
|
||||||
'SecurityGroupPortBinding': '1.0-6879d5c0af80396ef5a72934b6a6ef20',
|
'SecurityGroupPortBinding': '1.0-6879d5c0af80396ef5a72934b6a6ef20',
|
||||||
'SecurityGroupRBAC': '1.0-192845c5ed0718e1c54fac36936fcd7d',
|
'SecurityGroupRBAC': '1.0-192845c5ed0718e1c54fac36936fcd7d',
|
||||||
'SecurityGroupRule': '1.0-e9b8dace9d48b936c62ad40fe1f339d5',
|
'SecurityGroupRule': '1.1-0a8614633901e353dd32948dc2f8708f',
|
||||||
'SegmentHostMapping': '1.0-521597cf82ead26217c3bd10738f00f0',
|
'SegmentHostMapping': '1.0-521597cf82ead26217c3bd10738f00f0',
|
||||||
'ServiceProfile': '1.0-9beafc9e7d081b8258f3c5cb66ac5eed',
|
'ServiceProfile': '1.0-9beafc9e7d081b8258f3c5cb66ac5eed',
|
||||||
'StandardAttribute': '1.0-617d4f46524c4ce734a6fc1cc0ac6a0b',
|
'StandardAttribute': '1.0-617d4f46524c4ce734a6fc1cc0ac6a0b',
|
||||||
|
|
|
@ -76,6 +76,25 @@ class SecurityGroupDbObjTestCase(test_base.BaseDbObjectTestCase,
|
||||||
self.objs[0].create()
|
self.objs[0].create()
|
||||||
return self.objs[0]
|
return self.objs[0]
|
||||||
|
|
||||||
|
def _create_test_security_group_with_rule(self):
|
||||||
|
sg_obj = self._create_test_security_group()
|
||||||
|
rule_params = {
|
||||||
|
'project_id': sg_obj.project_id,
|
||||||
|
'security_group_id': sg_obj.id,
|
||||||
|
'remote_address_group_id': None}
|
||||||
|
sg_rule = securitygroup.SecurityGroupRule(
|
||||||
|
self.context, **rule_params)
|
||||||
|
sg_obj.rules = [sg_rule]
|
||||||
|
return sg_obj
|
||||||
|
|
||||||
|
def test_object_version_degradation_1_3_to_1_2_no_remote_ag(self):
|
||||||
|
sg_obj = self._create_test_security_group_with_rule()
|
||||||
|
sg_obj_1_2 = sg_obj.obj_to_primitive('1.2')
|
||||||
|
for rule in sg_obj_1_2['versioned_object.data']['rules']:
|
||||||
|
self.assertEqual('1.0', rule['versioned_object.version'])
|
||||||
|
self.assertNotIn('remote_address_group_id',
|
||||||
|
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')
|
||||||
|
@ -213,9 +232,15 @@ class SecurityGroupRuleDbObjTestCase(test_base.BaseDbObjectTestCase,
|
||||||
'security_group_id':
|
'security_group_id':
|
||||||
lambda: self._create_test_security_group_id(),
|
lambda: self._create_test_security_group_id(),
|
||||||
'remote_group_id':
|
'remote_group_id':
|
||||||
lambda: self._create_test_security_group_id()
|
lambda: self._create_test_security_group_id(),
|
||||||
|
'remote_address_group_id':
|
||||||
|
lambda: self._create_test_address_group_id()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def _create_test_security_group_rule(self):
|
||||||
|
self.objs[0].create()
|
||||||
|
return self.objs[0]
|
||||||
|
|
||||||
def test_get_security_group_rule_ids(self):
|
def test_get_security_group_rule_ids(self):
|
||||||
"""Retrieve the SG rules associated to a project (see method desc.)
|
"""Retrieve the SG rules associated to a project (see method desc.)
|
||||||
|
|
||||||
|
@ -250,3 +275,9 @@ class SecurityGroupRuleDbObjTestCase(test_base.BaseDbObjectTestCase,
|
||||||
rule_ids_ref = set(rules_per_project[projects[idx]])
|
rule_ids_ref = set(rules_per_project[projects[idx]])
|
||||||
rule_ids_ref.update(set(rules_per_sg[sgs[idx]]))
|
rule_ids_ref.update(set(rules_per_sg[sgs[idx]]))
|
||||||
self.assertEqual(rule_ids_ref, set(rule_ids))
|
self.assertEqual(rule_ids_ref, set(rule_ids))
|
||||||
|
|
||||||
|
def test_object_version_degradation_1_1_to_1_0_no_remote_ag(self):
|
||||||
|
rule_remote_ag_obj = self._create_test_security_group_rule()
|
||||||
|
rule_no_remote_ag_obj = rule_remote_ag_obj.obj_to_primitive('1.0')
|
||||||
|
self.assertNotIn('remote_address_group_id',
|
||||||
|
rule_no_remote_ag_obj['versioned_object.data'])
|
||||||
|
|
|
@ -81,6 +81,7 @@ class OVOServerRpcInterfaceTestCase(test_plugin.Ml2PluginV2TestCase):
|
||||||
'port_range_max': None,
|
'port_range_max': None,
|
||||||
'remote_ip_prefix': None,
|
'remote_ip_prefix': None,
|
||||||
'remote_group_id': None,
|
'remote_group_id': None,
|
||||||
|
'remote_address_group_id': None,
|
||||||
'protocol': None,
|
'protocol': None,
|
||||||
'direction': None,
|
'direction': None,
|
||||||
'ethertype': 'IPv4'}})
|
'ethertype': 'IPv4'}})
|
||||||
|
|
|
@ -192,6 +192,7 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase):
|
||||||
'remote_ip_prefix': '0.0.0.0/0',
|
'remote_ip_prefix': '0.0.0.0/0',
|
||||||
'ethertype': 'IPv4',
|
'ethertype': 'IPv4',
|
||||||
'remote_group_id': None,
|
'remote_group_id': None,
|
||||||
|
'remote_address_group_id': None,
|
||||||
'direction': 'ingress',
|
'direction': 'ingress',
|
||||||
'security_group_id': sg['id']}}
|
'security_group_id': sg['id']}}
|
||||||
rule = self.cp.create_security_group_rule(self.ctx, r)
|
rule = self.cp.create_security_group_rule(self.ctx, r)
|
||||||
|
|
Loading…
Reference in New Issue