Merge "Integrate Security Groups OVO"

This commit is contained in:
Jenkins 2017-06-15 07:37:38 +00:00 committed by Gerrit Code Review
commit c507656044
5 changed files with 150 additions and 114 deletions

View File

@ -19,21 +19,25 @@ from neutron_lib.callbacks import exceptions
from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources
from neutron_lib import constants
from neutron_lib import exceptions as n_exc
from neutron_lib.utils import helpers
from neutron_lib.utils import net
from oslo_utils import uuidutils
from sqlalchemy.orm import exc
import six
from sqlalchemy.orm import scoped_session
from neutron._i18n import _
from neutron.api.v2 import attributes
from neutron.common import constants as n_const
from neutron.common import utils
from neutron.db import _model_query as model_query
from neutron.db import _resource_extend as resource_extend
from neutron.db import _utils as db_utils
from neutron.db import api as db_api
from neutron.db.models import securitygroup as sg_models
from neutron.extensions import securitygroup as ext_sg
from neutron.objects import base as base_obj
from neutron.objects import securitygroup as sg_obj
@resource_extend.has_resource_extenders
@ -87,40 +91,39 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
return self.get_security_group(context, existing_def_sg_id)
with db_api.context_manager.writer.using(context):
security_group_db = sg_models.SecurityGroup(id=s.get('id') or (
uuidutils.generate_uuid()),
description=s['description'],
tenant_id=tenant_id,
name=s['name'])
context.session.add(security_group_db)
if default_sg:
context.session.add(sg_models.DefaultSecurityGroup(
security_group=security_group_db,
tenant_id=security_group_db['tenant_id']))
sg = sg_obj.SecurityGroup(
context, id=s.get('id') or uuidutils.generate_uuid(),
description=s['description'], project_id=tenant_id,
name=s['name'], is_default=default_sg)
sg.create()
for ethertype in ext_sg.sg_supported_ethertypes:
if default_sg:
# Allow intercommunication
ingress_rule = sg_models.SecurityGroupRule(
id=uuidutils.generate_uuid(), tenant_id=tenant_id,
security_group=security_group_db,
direction='ingress',
ethertype=ethertype,
source_group=security_group_db)
context.session.add(ingress_rule)
ingress_rule = sg_obj.SecurityGroupRule(
context, id=uuidutils.generate_uuid(),
project_id=tenant_id, security_group_id=sg.id,
direction='ingress', ethertype=ethertype,
remote_group_id=sg.id)
ingress_rule.create()
sg.rules.append(ingress_rule)
egress_rule = sg_models.SecurityGroupRule(
id=uuidutils.generate_uuid(), tenant_id=tenant_id,
security_group=security_group_db,
direction='egress',
ethertype=ethertype)
context.session.add(egress_rule)
egress_rule = sg_obj.SecurityGroupRule(
context, id=uuidutils.generate_uuid(),
project_id=tenant_id, security_group_id=sg.id,
direction='egress', ethertype=ethertype)
egress_rule.create()
sg.rules.append(egress_rule)
sg.obj_reset_changes(['rules'])
self._registry_notify(resources.SECURITY_GROUP,
events.PRECOMMIT_CREATE,
exc_cls=ext_sg.SecurityGroupConflict,
**kwargs)
secgroup_dict = self._make_security_group_dict(security_group_db)
# fetch sg from db to load the sg rules with sg model.
sg = sg_obj.SecurityGroup.get_object(context, id=sg.id)
secgroup_dict = self._make_security_group_dict(sg.db_obj)
kwargs['security_group'] = secgroup_dict
registry.notify(resources.SECURITY_GROUP, events.AFTER_CREATE, self,
@ -136,6 +139,7 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
# so this can be done recursively. Context.tenant_id is checked
# because all the unit tests do not explicitly set the context on
# GETS. TODO(arosen) context handling can probably be improved here.
filters = filters or {}
if not default_sg and context.tenant_id:
tenant_id = filters.get('tenant_id')
if tenant_id:
@ -143,20 +147,20 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
else:
tenant_id = context.tenant_id
self._ensure_default_security_group(context, tenant_id)
marker_obj = db_utils.get_marker_obj(self, context, 'security_group',
limit, marker)
return model_query.get_collection(context,
sg_models.SecurityGroup,
self._make_security_group_dict,
filters=filters, fields=fields,
sorts=sorts,
limit=limit, marker_obj=marker_obj,
page_reverse=page_reverse)
pager = base_obj.Pager(
sorts=sorts, limit=limit, marker=marker, page_reverse=page_reverse)
sg_objs = sg_obj.SecurityGroup.get_objects(
context, _pager=pager, validate_filters=False, **filters)
return [self._make_security_group_dict(obj, fields) for obj in sg_objs]
@db_api.retry_if_session_inactive()
def get_security_groups_count(self, context, filters=None):
return model_query.get_collection_count(
context, sg_models.SecurityGroup, filters=filters)
filters = filters or {}
return sg_obj.SecurityGroup.count(
context, validate_filters=False, **filters)
@db_api.retry_if_session_inactive()
def get_security_group(self, context, id, fields=None, tenant_id=None):
@ -180,12 +184,8 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
return ret
def _get_security_group(self, context, id):
try:
query = model_query.query_with_hooks(
context, sg_models.SecurityGroup)
sg = query.filter(sg_models.SecurityGroup.id == id).one()
except exc.NoResultFound:
sg = sg_obj.SecurityGroup.get_object(context, id=id)
if sg is None:
raise ext_sg.SecurityGroupNotFound(id=id)
return sg
@ -224,7 +224,7 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
events.PRECOMMIT_DELETE,
exc_cls=ext_sg.SecurityGroupInUse, id=id,
**kwargs)
context.session.delete(sg)
sg.delete()
kwargs.pop('security_group')
registry.notify(resources.SECURITY_GROUP, events.AFTER_DELETE,
@ -244,13 +244,14 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
with db_api.context_manager.writer.using(context):
sg = self._get_security_group(context, id)
if sg['name'] == 'default' and 'name' in s:
if sg.name == 'default' and 'name' in s:
raise ext_sg.SecurityGroupCannotUpdateDefault()
self._registry_notify(
resources.SECURITY_GROUP,
events.PRECOMMIT_UPDATE,
exc_cls=ext_sg.SecurityGroupConflict, **kwargs)
sg.update(s)
sg.update_fields(s)
sg.update()
sg_dict = self._make_security_group_dict(sg)
kwargs['security_group'] = sg_dict
@ -349,28 +350,45 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
events.BEFORE_CREATE,
exc_cls=ext_sg.SecurityGroupConflict, **kwargs)
remote_ip_prefix = rule_dict.get('remote_ip_prefix')
if remote_ip_prefix:
remote_ip_prefix = utils.AuthenticIPNetwork(remote_ip_prefix)
protocol = rule_dict.get('protocol')
if protocol:
# object expects strings only
protocol = six.text_type(protocol)
args = {
'id': (rule_dict.get('id') or uuidutils.generate_uuid()),
'project_id': rule_dict['tenant_id'],
'security_group_id': rule_dict['security_group_id'],
'direction': rule_dict['direction'],
'remote_group_id': rule_dict.get('remote_group_id'),
'ethertype': rule_dict['ethertype'],
'protocol': protocol,
'remote_ip_prefix': remote_ip_prefix,
'description': rule_dict.get('description'),
}
port_range_min = self._safe_int(rule_dict['port_range_min'])
if port_range_min is not None:
args['port_range_min'] = port_range_min
port_range_max = self._safe_int(rule_dict['port_range_max'])
if port_range_max is not None:
args['port_range_max'] = port_range_max
with db_api.context_manager.writer.using(context):
if validate:
self._check_for_duplicate_rules_in_db(context,
security_group_rule)
db = sg_models.SecurityGroupRule(
id=(rule_dict.get('id') or uuidutils.generate_uuid()),
tenant_id=rule_dict['tenant_id'],
security_group_id=rule_dict['security_group_id'],
direction=rule_dict['direction'],
remote_group_id=rule_dict.get('remote_group_id'),
ethertype=rule_dict['ethertype'],
protocol=rule_dict['protocol'],
port_range_min=rule_dict['port_range_min'],
port_range_max=rule_dict['port_range_max'],
remote_ip_prefix=rule_dict.get('remote_ip_prefix'),
description=rule_dict.get('description')
)
context.session.add(db)
sg_rule = sg_obj.SecurityGroupRule(context, **args)
sg_rule.create()
self._registry_notify(resources.SECURITY_GROUP_RULE,
events.PRECOMMIT_CREATE,
exc_cls=ext_sg.SecurityGroupConflict, **kwargs)
return self._make_security_group_rule_dict(db)
return self._make_security_group_rule_dict(sg_rule.db_obj)
def _get_ip_proto_number(self, protocol):
if protocol is None:
@ -394,6 +412,15 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
protocol]
return [protocol, protocol]
def _safe_int(self, port_range):
if port_range is None:
return
try:
return int(port_range)
except (ValueError, TypeError):
msg = "port range must be an integer"
raise n_exc.InvalidInput(error_message=msg)
def _validate_port_range(self, rule):
"""Check that port_range is valid."""
if (rule['port_range_min'] is None and
@ -574,6 +601,8 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
raise ext_sg.SecurityGroupRuleExists(rule_id=rule_id)
def _validate_duplicate_ip_prefix(self, ip_prefix, other_ip_prefix):
if other_ip_prefix is not None:
other_ip_prefix = str(other_ip_prefix)
all_address = ['0.0.0.0/0', '::/0', None]
if ip_prefix == other_ip_prefix:
return True
@ -603,21 +632,23 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
def get_security_group_rules(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
marker_obj = db_utils.get_marker_obj(self, context,
'security_group_rule',
limit, marker)
return model_query.get_collection(context,
sg_models.SecurityGroupRule,
self._make_security_group_rule_dict,
filters=filters, fields=fields,
sorts=sorts,
limit=limit, marker_obj=marker_obj,
page_reverse=page_reverse)
filters = filters or {}
pager = base_obj.Pager(
sorts=sorts, marker=marker, limit=limit, page_reverse=page_reverse)
rule_objs = sg_obj.SecurityGroupRule.get_objects(
context, _pager=pager, validate_filters=False, **filters
)
return [
self._make_security_group_rule_dict(obj, fields)
for obj in rule_objs
]
@db_api.retry_if_session_inactive()
def get_security_group_rules_count(self, context, filters=None):
return model_query.get_collection_count(
context, sg_models.SecurityGroupRule, filters=filters)
filters = filters or {}
return sg_obj.SecurityGroupRule.count(
context, validate_filters=False, **filters)
@db_api.retry_if_session_inactive()
def get_security_group_rule(self, context, id, fields=None):
@ -625,11 +656,8 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
return self._make_security_group_rule_dict(security_group_rule, fields)
def _get_security_group_rule(self, context, id):
try:
query = model_query.query_with_hooks(
context, sg_models.SecurityGroupRule)
sgr = query.filter(sg_models.SecurityGroupRule.id == id).one()
except exc.NoResultFound:
sgr = sg_obj.SecurityGroupRule.get_object(context, id=id)
if sgr is None:
raise ext_sg.SecurityGroupRuleNotFound(id=id)
return sgr
@ -644,24 +672,15 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
exc_cls=ext_sg.SecurityGroupRuleInUse, **kwargs)
with db_api.context_manager.writer.using(context):
query = model_query.query_with_hooks(
context, sg_models.SecurityGroupRule).filter(
sg_models.SecurityGroupRule.id == id)
self._registry_notify(resources.SECURITY_GROUP_RULE,
events.PRECOMMIT_DELETE,
exc_cls=ext_sg.SecurityGroupRuleInUse, id=id,
**kwargs)
try:
sg_rule = query.one()
# As there is a filter on a primary key it is not possible for
# MultipleResultsFound to be raised
context.session.delete(sg_rule)
except exc.NoResultFound:
raise ext_sg.SecurityGroupRuleNotFound(id=id)
sgr = self._get_security_group_rule(context, id)
sgr.delete()
kwargs['security_group_id'] = sg_rule['security_group_id']
kwargs['security_group_id'] = sgr['security_group_id']
registry.notify(
resources.SECURITY_GROUP_RULE, events.AFTER_DELETE, self,
@ -690,13 +709,12 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
list(security_group_ids) or [])
def _get_default_sg_id(self, context, tenant_id):
try:
query = model_query.query_with_hooks(
context, sg_models.DefaultSecurityGroup)
default_group = query.filter_by(tenant_id=tenant_id).one()
return default_group['security_group_id']
except exc.NoResultFound:
pass
default_group = sg_obj.DefaultSecurityGroup.get_object(
context,
project_id=tenant_id,
)
if default_group:
return default_group.security_group_id
@registry.receives(resources.PORT, [events.BEFORE_CREATE])
@registry.receives(resources.NETWORK, [events.BEFORE_CREATE])
@ -710,9 +728,10 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
:returns: the default security group id for given tenant.
"""
existing = self._get_default_sg_id(context, tenant_id)
if existing is not None:
return existing
default_group_id = self._get_default_sg_id(context, tenant_id)
if default_group_id:
return default_group_id
security_group = {
'security_group':
{'name': 'default',

View File

@ -51,7 +51,7 @@ class SecurityGroup(base.NeutronDbObject):
with db_api.autonested_transaction(self.obj_context.session):
super(SecurityGroup, self).create()
if is_default:
default_group = _DefaultSecurityGroup(
default_group = DefaultSecurityGroup(
self.obj_context,
project_id=self.project_id,
security_group_id=self.id)
@ -66,7 +66,7 @@ class SecurityGroup(base.NeutronDbObject):
@obj_base.VersionedObjectRegistry.register
class _DefaultSecurityGroup(base.NeutronDbObject):
class DefaultSecurityGroup(base.NeutronDbObject):
# Version 1.0: Initial version
VERSION = '1.0'

View File

@ -27,15 +27,31 @@ from neutron.extensions import securitygroup
from neutron.tests.unit import testlib_api
FAKE_SECGROUP = {'security_group': {"tenant_id": 'fake', 'description':
'fake', 'name': 'fake'}}
FAKE_SECGROUP = {
'security_group': {
"tenant_id": 'fake',
'description': 'fake',
'name': 'fake'
}
}
FAKE_SECGROUP_RULE = {'security_group_rule': {"tenant_id": 'fake',
'description': 'fake', 'name': 'fake', 'port_range_min':
'21', 'protocol': 'tcp', 'port_range_max': '23',
'remote_ip_prefix': '10.0.0.1', 'ethertype': 'IPv4',
'remote_group_id': None, 'security_group_id': 'None',
'direction': 'ingress'}}
FAKE_SECGROUP_RULE = {
'security_group_rule': {
"tenant_id": 'fake',
'description': 'fake',
'name': 'fake',
'port_range_min': '21',
'protocol': 'tcp',
'port_range_max': '23',
'remote_ip_prefix': '10.0.0.1',
'ethertype': 'IPv4',
'remote_group_id': None,
'security_group_id': 'None',
'direction': 'ingress'
}
}
DB_PLUGIN_KLASS = 'neutron.db.db_base_plugin_v2.NeutronDbPluginV2'
def fake_callback(resource, event, *args, **kwargs):
@ -51,6 +67,7 @@ class SecurityGroupDbMixinTestCase(testlib_api.SqlTestCase):
def setUp(self):
super(SecurityGroupDbMixinTestCase, self).setUp()
self.setup_coreplugin(core_plugin=DB_PLUGIN_KLASS)
self.ctx = context.get_admin_context()
self.mixin = SecurityGroupDbMixinImpl()

View File

@ -26,11 +26,11 @@ from neutron.tests import base as test_base
# corresponding version bump in the affected objects. Please keep the list in
# alphabetic order.
object_data = {
'_DefaultSecurityGroup': '1.0-971520cb2e0ec06d747885a0cf78347f',
'AddressScope': '1.0-dd0dfdb67775892d3adc090e28e43bd8',
'Agent': '1.0-7106cb40117a8d1f042545796ed8787d',
'AllowedAddressPair': '1.0-9f9186b6f952fbf31d257b0458b852c0',
'AutoAllocatedTopology': '1.0-74642e58c53bf3610dc224c59f81b242',
'DefaultSecurityGroup': '1.0-971520cb2e0ec06d747885a0cf78347f',
'DistributedPortBinding': '1.0-39c0d17b281991dcb66716fee5a8bef2',
'DNSNameServer': '1.0-bf87a85327e2d812d1666ede99d9918b',
'ExternalNetwork': '1.0-53d885e033cb931f9bb3bdd6bbe3f0ce',

View File

@ -41,7 +41,7 @@ class SecurityGroupDbObjTestCase(test_base.BaseDbObjectTestCase,
sg_obj.is_default = True
sg_obj.create()
default_sg_obj = securitygroup._DefaultSecurityGroup.get_object(
default_sg_obj = securitygroup.DefaultSecurityGroup.get_object(
self.context,
project_id=sg_obj.project_id,
security_group_id=sg_obj.id)
@ -60,7 +60,7 @@ class SecurityGroupDbObjTestCase(test_base.BaseDbObjectTestCase,
sg_obj.is_default = False
sg_obj.create()
default_sg_obj = securitygroup._DefaultSecurityGroup.get_object(
default_sg_obj = securitygroup.DefaultSecurityGroup.get_object(
self.context,
project_id=sg_obj.project_id,
security_group_id=sg_obj.id)
@ -100,13 +100,13 @@ class SecurityGroupDbObjTestCase(test_base.BaseDbObjectTestCase,
class DefaultSecurityGroupIfaceObjTestCase(test_base.BaseObjectIfaceTestCase):
_test_class = securitygroup._DefaultSecurityGroup
_test_class = securitygroup.DefaultSecurityGroup
class DefaultSecurityGroupDbObjTestCase(test_base.BaseDbObjectTestCase,
testlib_api.SqlTestCase):
_test_class = securitygroup._DefaultSecurityGroup
_test_class = securitygroup.DefaultSecurityGroup
def setUp(self):
super(DefaultSecurityGroupDbObjTestCase, self).setUp()