Merge "[aim] security group support"

This commit is contained in:
Jenkins
2016-12-22 21:34:56 +00:00
committed by Gerrit Code Review
5 changed files with 118 additions and 60 deletions

View File

@@ -25,6 +25,7 @@ from aim import context as aim_context
from aim import utils as aim_utils
from neutron._i18n import _LI
from neutron._i18n import _LW
from neutron.agent import securitygroups_rpc
from neutron.api.v2 import attributes
from neutron.common import constants as n_constants
from neutron.common import exceptions
@@ -128,6 +129,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver):
self.ap_name = 'OpenStack'
self.apic_system_id = cfg.CONF.apic_system_id
self.notifier = ofrpc.AgentNotifierApi(n_topics.AGENT)
self.sg_enabled = securitygroups_rpc.is_firewall_enabled()
# setup APIC topology RPC handler
self.topology_conn = n_rpc.create_connection(new=True)
self.topology_conn.create_consumer(apic_topo_rpc.TOPIC_APIC_SERVICE,
@@ -1097,10 +1099,10 @@ class ApicMechanismDriver(api_plus.MechanismDriver):
return True
def _complete_binding(self, context, segment):
context.set_binding(segment[api.ID],
portbindings.VIF_TYPE_OVS,
{portbindings.CAP_PORT_FILTER: False,
portbindings.OVS_HYBRID_PLUG: False})
context.set_binding(
segment[api.ID], portbindings.VIF_TYPE_OVS,
{portbindings.CAP_PORT_FILTER: self.sg_enabled,
portbindings.OVS_HYBRID_PLUG: self.sg_enabled})
@property
def plugin(self):

View File

@@ -73,6 +73,7 @@ FILTERS = 'filters'
FILTER_ENTRIES = 'filter_entries'
ENFORCED = aim_resource.EndpointGroup.POLICY_ENFORCED
UNENFORCED = aim_resource.EndpointGroup.POLICY_UNENFORCED
DEFAULT_SG_NAME = 'gbp_default'
# REVISIT: Auto-PTG is currently config driven to align with the
# config driven behavior of the older driver but is slated for
@@ -612,7 +613,6 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
subnets = self._get_subnets(
context._plugin_context, {'id': ptg['subnets']},
clean_session=False)
self._use_implicit_port(context, subnets=subnets,
clean_session=False)
@@ -1974,3 +1974,32 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
return default_epg_name
else:
return ptg_id
def _get_default_security_group(self, plugin_context, ptg_id,
tenant_id, clean_session=True):
filters = {'name': [DEFAULT_SG_NAME], 'tenant_id': [tenant_id]}
default_group = self._get_sgs(plugin_context, filters,
clean_session=clean_session)
return default_group[0]['id'] if default_group else None
def _create_default_security_group(self, plugin_context, tenant_id):
# Allow all
sg_id = self._get_default_security_group(plugin_context, '', tenant_id)
ip_v = [(n_constants.IPv4, '0.0.0.0/0'), (n_constants.IPv6, '::/0')]
if not sg_id:
sg_name = DEFAULT_SG_NAME
sg = self._create_gbp_sg(plugin_context, tenant_id, sg_name,
description='default GBP security group')
sg_id = sg['id']
for v, g in ip_v:
self._sg_rule(plugin_context, tenant_id, sg_id,
'ingress', cidr=g, ethertype=v)
self._sg_rule(plugin_context, tenant_id, sg_id,
'egress', cidr=g, ethertype=v)
def _use_implicit_port(self, context, subnets=None, clean_session=True):
self._create_default_security_group(context._plugin_context,
context.current['tenant_id'])
super(AIMMappingDriver, self)._use_implicit_port(
context, subnets=subnets, clean_session=clean_session)

View File

@@ -209,6 +209,51 @@ class OwnedResourcesOperations(object):
class ImplicitResourceOperations(local_api.LocalAPI):
def _sg_rule(self, plugin_context, tenant_id, sg_id, direction,
protocol=None, port_range=None, cidr=None,
ethertype=const.IPv4, unset=False):
if port_range:
port_min, port_max = (gpdb.GroupPolicyDbPlugin.
_get_min_max_ports_from_range(port_range))
else:
port_min, port_max = None, None
attrs = {'tenant_id': tenant_id,
'security_group_id': sg_id,
'direction': direction,
'ethertype': ethertype,
'protocol': protocol,
'port_range_min': port_min,
'port_range_max': port_max,
'remote_ip_prefix': cidr,
'remote_group_id': None}
if unset:
filters = {}
for key in attrs:
value = attrs[key]
if value:
filters[key] = [value]
rule = self._get_sg_rules(plugin_context, filters)
if rule:
self._delete_sg_rule(plugin_context, rule[0]['id'])
else:
return self._create_sg_rule(plugin_context, attrs)
def _create_gbp_sg(self, plugin_context, tenant_id, name, **kwargs):
# This method sets up the attributes of security group
attrs = {'tenant_id': tenant_id,
'name': name,
'description': '',
'security_group_rules': ''}
attrs.update(kwargs)
sg = self._create_sg(plugin_context, attrs)
# Cleanup default rules
for rule in self._get_sg_rules(plugin_context,
filters={'security_group_id':
[sg['id']]}):
self._delete_sg_rule(plugin_context, rule['id'])
return sg
def _create_implicit_address_scope(self, context, clean_session=True,
**kwargs):
attrs = {'tenant_id': context.current['tenant_id'],
@@ -2029,21 +2074,6 @@ class ResourceMappingDriver(api.PolicyDriver, ImplicitResourceOperations,
context._plugin_context, context.current['tenant_id'],
sg_name_prefix + '_' + context.current['name'])
def _create_gbp_sg(self, plugin_context, tenant_id, name, **kwargs):
# This method sets up the attributes of security group
attrs = {'tenant_id': tenant_id,
'name': name,
'description': '',
'security_group_rules': ''}
attrs.update(kwargs)
sg = self._create_sg(plugin_context, attrs)
# Cleanup default rules
for rule in self._get_sg_rules(plugin_context,
filters={'security_group_id':
[sg['id']]}):
self._delete_sg_rule(plugin_context, rule['id'])
return sg
def _handle_policy_rule_sets(self, context):
# This method handles policy_rule_set => SG mapping
# context is PTG context
@@ -2171,36 +2201,6 @@ class ResourceMappingDriver(api.PolicyDriver, ImplicitResourceOperations,
return (session.query(PolicyRuleSetSGsMapping).
filter_by(policy_rule_set_id=policy_rule_set_id).one())
def _sg_rule(self, plugin_context, tenant_id, sg_id, direction,
protocol=None, port_range=None, cidr=None,
ethertype=const.IPv4, unset=False):
if port_range:
port_min, port_max = (gpdb.GroupPolicyDbPlugin.
_get_min_max_ports_from_range(port_range))
else:
port_min, port_max = None, None
attrs = {'tenant_id': tenant_id,
'security_group_id': sg_id,
'direction': direction,
'ethertype': ethertype,
'protocol': protocol,
'port_range_min': port_min,
'port_range_max': port_max,
'remote_ip_prefix': cidr,
'remote_group_id': None}
if unset:
filters = {}
for key in attrs:
value = attrs[key]
if value:
filters[key] = [value]
rule = self._get_sg_rules(plugin_context, filters)
if rule:
self._delete_sg_rule(plugin_context, rule[0]['id'])
else:
return self._create_sg_rule(plugin_context, attrs)
def _sg_ingress_rule(self, context, sg_id, protocol, port_range, cidr,
tenant_id, unset=False):
return self._sg_rule(

View File

@@ -1303,7 +1303,7 @@ class TestPortBinding(ApicAimTestCase):
port_id = port['id']
port = self._bind_port_to_host(port_id, 'host1')['port']
self.assertEqual('ovs', port['binding:vif_type'])
self.assertEqual({'port_filter': False, 'ovs_hybrid_plug': False},
self.assertEqual({'port_filter': True, 'ovs_hybrid_plug': True},
port['binding:vif_details'])
# TODO(rkukura): Add tests for promiscuous_mode cases.

View File

@@ -1737,6 +1737,7 @@ class TestPolicyTarget(AIMBaseTestCase):
req = self.new_show_request('ports', pt['port_id'], fmt=self.fmt)
res = self.deserialize(self.fmt, req.get_response(self.api))
self.assertIsNotNone(res['port']['id'])
self.assertEqual(1, len(res['port']['security_groups']))
self.update_policy_target(pt_id, expected_res_status=200,
name="new name")
@@ -2506,12 +2507,24 @@ class NotificationTest(AIMBaseTestCase):
mock.call().notify(mock.ANY, mock.ANY, "subnet.create.end"),
mock.call().notify(mock.ANY, mock.ANY,
"policy_target_group.create.end"),
mock.call().notify(mock.ANY, mock.ANY,
"security_group.create.end"),
mock.call().notify(mock.ANY, mock.ANY,
"security_group_rule.delete.end"),
mock.call().notify(mock.ANY, mock.ANY,
"security_group_rule.delete.end"),
mock.call().notify(mock.ANY, mock.ANY,
"security_group_rule.create.end"),
mock.call().notify(mock.ANY, mock.ANY,
"security_group_rule.create.end"),
mock.call().notify(mock.ANY, mock.ANY,
"security_group_rule.create.end"),
mock.call().notify(mock.ANY, mock.ANY,
"security_group_rule.create.end"),
mock.call().notify(mock.ANY, mock.ANY, "port.create.end"),
mock.call().notify(mock.ANY, mock.ANY,
"policy_target.create.end"),
mock.call().notify(mock.ANY, mock.ANY, "policy_target.create.end"),
mock.call().notify(mock.ANY, mock.ANY, "port.delete.end"),
mock.call().notify(mock.ANY, mock.ANY,
"policy_target.delete.end"),
mock.call().notify(mock.ANY, mock.ANY, "policy_target.delete.end"),
mock.call().notify(mock.ANY, mock.ANY, "port.delete.end"),
mock.call().notify(mock.ANY, mock.ANY, "subnet.delete.end"),
mock.call().notify(mock.ANY, mock.ANY, "network.delete.end"),
@@ -2542,6 +2555,19 @@ class NotificationTest(AIMBaseTestCase):
mock.call().notify("create_subnet", mock.ANY, mock.ANY),
mock.call().notify("create_policy_target_group",
mock.ANY, mock.ANY),
mock.call().notify("create_security_group", mock.ANY, mock.ANY),
mock.call().notify("delete_security_group_rule", mock.ANY,
mock.ANY),
mock.call().notify("delete_security_group_rule", mock.ANY,
mock.ANY),
mock.call().notify("create_security_group_rule", mock.ANY,
mock.ANY),
mock.call().notify("create_security_group_rule", mock.ANY,
mock.ANY),
mock.call().notify("create_security_group_rule", mock.ANY,
mock.ANY),
mock.call().notify("create_security_group_rule", mock.ANY,
mock.ANY),
mock.call().notify("create_port", mock.ANY, mock.ANY),
mock.call().notify("create_policy_target", mock.ANY, mock.ANY),
mock.call().notify("delete_port", mock.ANY, mock.ANY),
@@ -2553,8 +2579,8 @@ class NotificationTest(AIMBaseTestCase):
mock.call().notify("delete_router", mock.ANY, mock.ANY),
mock.call().notify("delete_policy_target_group",
mock.ANY, mock.ANY),
mock.call().notify("delete_security_group",
mock.ANY, mock.ANY)]
mock.call().notify("delete_security_group", mock.ANY, mock.ANY),
mock.call().notify("delete_security_group", mock.ANY, mock.ANY)]
return calls
def _test_notifier(self, notifier, expected_calls,
@@ -2571,9 +2597,10 @@ class NotificationTest(AIMBaseTestCase):
'policy_target_groups', ptg_id).get_response(self.ext_api)
sg_rules = self._plugin.get_security_group_rules(
self._neutron_context)
sg_id = sg_rules[0]['security_group_id']
self.new_delete_request(
'security-groups', sg_id).get_response(self.ext_api)
sg_ids = set([x['security_group_id'] for x in sg_rules])
for sg_id in sg_ids:
self.new_delete_request(
'security-groups', sg_id).get_response(self.ext_api)
notifier.assert_has_calls(expected_calls(), any_order=False)
# test that no notifications have been left out
self.assertEqual({}, local_api.NOTIFICATION_QUEUE)