Merge "[aim] security group support"
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user