NSXv3: Adding support for 'secgroup-rule-local-ip-prefix' extension
Supporting this extension will allow users to define rules with the notation of local-prefix-ip, which matches on the destination address of packets going into the port. One may use this extended API in order to specify a specific set of multicast groups addresses in which a port (or group of ports) should be allowed to accept packets from. Change-Id: I2bd6b3381c715c1286dfa10bf3b143c73fecf49d
This commit is contained in:
parent
1ac25e8896
commit
82660993e7
@ -12,15 +12,18 @@
|
||||
# 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 sqlalchemy.orm import exc
|
||||
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import orm
|
||||
|
||||
from neutron.api.v2 import attributes as attr
|
||||
from neutron.db import db_base_plugin_v2
|
||||
from neutron.db import model_base
|
||||
from neutron.db import securitygroups_db
|
||||
from neutron.extensions import securitygroup as ext_sg
|
||||
from neutron_lib import exceptions as nexception
|
||||
from vmware_nsx._i18n import _
|
||||
from vmware_nsx.db import nsxv_models
|
||||
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix as ext_loip
|
||||
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix as ext_local_ip
|
||||
|
||||
|
||||
class NotIngressRule(nexception.BadRequest):
|
||||
@ -28,41 +31,55 @@ class NotIngressRule(nexception.BadRequest):
|
||||
"with ingress rules only.")
|
||||
|
||||
|
||||
class NsxExtendedSecurityGroupRuleProperties(model_base.BASEV2):
|
||||
"""Persist security group rule properties for the
|
||||
extended-security-group-rule extension.
|
||||
"""
|
||||
|
||||
__tablename__ = 'nsx_extended_security_group_rule_properties'
|
||||
|
||||
rule_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('securitygrouprules.id',
|
||||
ondelete='CASCADE'),
|
||||
primary_key=True,
|
||||
nullable=False)
|
||||
local_ip_prefix = sa.Column(sa.String(255), nullable=False)
|
||||
|
||||
rule = orm.relationship(
|
||||
securitygroups_db.SecurityGroupRule,
|
||||
backref=orm.backref('ext_properties', lazy='joined',
|
||||
uselist=False, cascade='delete'))
|
||||
|
||||
|
||||
class ExtendedSecurityGroupRuleMixin(object):
|
||||
|
||||
def _check_local_ip_prefix(self, context, rule):
|
||||
rule_specify_local_ip_prefix = attr.is_attr_set(
|
||||
rule.get(ext_loip.LOCAL_IP_PREFIX))
|
||||
rule.get(ext_local_ip.LOCAL_IP_PREFIX))
|
||||
if rule_specify_local_ip_prefix and rule['direction'] != 'ingress':
|
||||
raise NotIngressRule()
|
||||
return rule_specify_local_ip_prefix
|
||||
|
||||
def _save_extended_rule_properties(self, context, rule):
|
||||
if not attr.is_attr_set(rule.get(ext_loip.LOCAL_IP_PREFIX)):
|
||||
def _process_security_group_rule_properties(self, context,
|
||||
rule_res, rule_req):
|
||||
rule_res[ext_local_ip.LOCAL_IP_PREFIX] = None
|
||||
if not attr.is_attr_set(rule_req.get(ext_local_ip.LOCAL_IP_PREFIX)):
|
||||
return
|
||||
with context.session.begin(subtransactions=True):
|
||||
properties = nsxv_models.NsxvExtendedSecurityGroupRuleProperties(
|
||||
rule_id=rule['id'],
|
||||
local_ip_prefix=rule[ext_loip.LOCAL_IP_PREFIX])
|
||||
context.session.add(properties)
|
||||
|
||||
def _get_security_group_rule_properties(self, context, sgr):
|
||||
try:
|
||||
properties = (context.session.query(
|
||||
nsxv_models.NsxvExtendedSecurityGroupRuleProperties).filter_by(
|
||||
rule_id=sgr['id']).one())
|
||||
except exc.NoResultFound:
|
||||
sgr[ext_loip.LOCAL_IP_PREFIX] = None
|
||||
else:
|
||||
sgr[ext_loip.LOCAL_IP_PREFIX] = properties.local_ip_prefix
|
||||
return sgr
|
||||
with context.session.begin(subtransactions=True):
|
||||
properties = NsxExtendedSecurityGroupRuleProperties(
|
||||
rule_id=rule_res['id'],
|
||||
local_ip_prefix=rule_req[ext_local_ip.LOCAL_IP_PREFIX])
|
||||
context.session.add(properties)
|
||||
rule_res[ext_local_ip.LOCAL_IP_PREFIX] = (
|
||||
rule_req[ext_local_ip.LOCAL_IP_PREFIX])
|
||||
|
||||
db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs(
|
||||
ext_sg.SECURITYGROUPRULES, ['_extend_security_group_rule_with_params'])
|
||||
|
||||
def _extend_security_group_rule_with_params(self, sg_rule_res, sg_rule_db):
|
||||
if sg_rule_db.ext_properties:
|
||||
sg_rule_res[ext_loip.LOCAL_IP_PREFIX] = (
|
||||
sg_rule_res[ext_local_ip.LOCAL_IP_PREFIX] = (
|
||||
sg_rule_db.ext_properties.local_ip_prefix)
|
||||
else:
|
||||
sg_rule_res[ext_loip.LOCAL_IP_PREFIX] = None
|
||||
sg_rule_res[ext_local_ip.LOCAL_IP_PREFIX] = None
|
||||
|
@ -1 +1 @@
|
||||
5ed1ffbc0d2a
|
||||
081af0e396d7
|
||||
|
@ -0,0 +1,32 @@
|
||||
# Copyright 2016 VMware, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""nsxv3_secgroup_local_ip_prefix
|
||||
|
||||
Revision ID: 081af0e396d7
|
||||
Revises: 5ed1ffbc0d2a
|
||||
Create Date: 2016-03-24 07:11:30.300482
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '081af0e396d7'
|
||||
down_revision = '5ed1ffbc0d2a'
|
||||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.rename_table('nsxv_extended_security_group_rule_properties',
|
||||
'nsx_extended_security_group_rule_properties')
|
@ -21,7 +21,6 @@ from sqlalchemy import orm
|
||||
from neutron.db import l3_db
|
||||
from neutron.db import model_base
|
||||
from neutron.db import models_v2
|
||||
from neutron.db import securitygroups_db
|
||||
|
||||
from vmware_nsx.common import nsxv_constants
|
||||
|
||||
@ -328,23 +327,3 @@ class NsxvSubnetExtAttributes(model_base.BASEV2):
|
||||
models_v2.Subnet,
|
||||
backref=orm.backref("nsxv_subnet_attributes", lazy='joined',
|
||||
uselist=False, cascade='delete'))
|
||||
|
||||
|
||||
class NsxvExtendedSecurityGroupRuleProperties(model_base.BASEV2):
|
||||
"""Persist security group rule properties for the
|
||||
extended-security-group-rule extension.
|
||||
"""
|
||||
|
||||
__tablename__ = 'nsxv_extended_security_group_rule_properties'
|
||||
|
||||
rule_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('securitygrouprules.id',
|
||||
ondelete='CASCADE'),
|
||||
primary_key=True,
|
||||
nullable=False)
|
||||
local_ip_prefix = sa.Column(sa.String(255), nullable=False)
|
||||
|
||||
rule = orm.relationship(
|
||||
securitygroups_db.SecurityGroupRule,
|
||||
backref=orm.backref('ext_properties', lazy='joined',
|
||||
uselist=False, cascade='delete'))
|
||||
|
@ -28,6 +28,7 @@ from vmware_nsx._i18n import _, _LW
|
||||
from vmware_nsx.common import exceptions as nsx_exc
|
||||
from vmware_nsx.common import utils
|
||||
from vmware_nsx.db import nsx_models
|
||||
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix
|
||||
from vmware_nsx.extensions import securitygrouplogging as sg_logging
|
||||
from vmware_nsx.nsxlib.v3 import dfw_api as firewall
|
||||
|
||||
@ -97,16 +98,23 @@ def _get_fw_rule_from_sg_rule(sg_rule, nsgroup_id, rmt_nsgroup_id, logged):
|
||||
ip_protocol = sg_rule['ethertype'].upper()
|
||||
direction = _get_direction(sg_rule)
|
||||
|
||||
if sg_rule.get(secgroup_rule_local_ip_prefix.LOCAL_IP_PREFIX):
|
||||
local_ip_prefix = firewall.get_ip_cidr_reference(
|
||||
sg_rule[secgroup_rule_local_ip_prefix.LOCAL_IP_PREFIX],
|
||||
ip_protocol)
|
||||
else:
|
||||
local_ip_prefix = None
|
||||
|
||||
source = None
|
||||
local_group = firewall.get_nsgroup_reference(nsgroup_id)
|
||||
if sg_rule['remote_ip_prefix'] is not None:
|
||||
source = firewall.get_ip_cidr_reference(sg_rule['remote_ip_prefix'],
|
||||
ip_protocol)
|
||||
destination = local_group
|
||||
destination = local_ip_prefix or local_group
|
||||
else:
|
||||
if rmt_nsgroup_id:
|
||||
source = firewall.get_nsgroup_reference(rmt_nsgroup_id)
|
||||
destination = local_group
|
||||
destination = local_ip_prefix or local_group
|
||||
if direction == firewall.OUT:
|
||||
source, destination = destination, source
|
||||
|
||||
|
@ -80,7 +80,7 @@ from vmware_nsx.extensions import (
|
||||
vnicindex as ext_vnic_idx)
|
||||
from vmware_nsx.extensions import dns_search_domain as ext_dns_search_domain
|
||||
from vmware_nsx.extensions import routersize
|
||||
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix as ext_loip
|
||||
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix
|
||||
from vmware_nsx.extensions import securitygrouplogging as sg_logging
|
||||
from vmware_nsx.plugins.nsx_v import managers
|
||||
from vmware_nsx.plugins.nsx_v import md_proxy as nsx_v_md_proxy
|
||||
@ -2111,9 +2111,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
|
||||
# Get source and destination containers from rule
|
||||
if rule['direction'] == 'ingress':
|
||||
if rule.get(ext_loip.LOCAL_IP_PREFIX):
|
||||
if rule.get(secgroup_rule_local_ip_prefix.LOCAL_IP_PREFIX):
|
||||
dest = self.nsx_sg_utils.get_remote_container(
|
||||
None, rule[ext_loip.LOCAL_IP_PREFIX])
|
||||
None, rule[secgroup_rule_local_ip_prefix.LOCAL_IP_PREFIX])
|
||||
src = self.nsx_sg_utils.get_remote_container(
|
||||
remote_nsx_sg_id, rule['remote_ip_prefix'])
|
||||
dest = dest or self.nsx_sg_utils.get_container(nsx_sg_id)
|
||||
@ -2177,7 +2177,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
for r in sg_rules:
|
||||
rule = r['security_group_rule']
|
||||
if not self._check_local_ip_prefix(context, rule):
|
||||
rule[ext_loip.LOCAL_IP_PREFIX] = None
|
||||
rule[secgroup_rule_local_ip_prefix.LOCAL_IP_PREFIX] = None
|
||||
rule['id'] = uuidutils.generate_uuid()
|
||||
ruleids.add(rule['id'])
|
||||
nsx_rules.append(self._create_nsx_rule(
|
||||
@ -2204,10 +2204,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
nsxv_db.add_neutron_nsx_rule_mapping(
|
||||
context.session, neutron_rule_id, nsx_rule_id)
|
||||
for i, r in enumerate(sg_rules):
|
||||
rule = r['security_group_rule']
|
||||
self._save_extended_rule_properties(context, rule)
|
||||
self._get_security_group_rule_properties(context,
|
||||
new_rule_list[i])
|
||||
self._process_security_group_rule_properties(
|
||||
context, new_rule_list[i], r['security_group_rule'])
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
for nsx_rule_id in [p['nsx_id'] for p in rule_pairs
|
||||
|
@ -69,6 +69,7 @@ from vmware_nsx.common import nsx_constants
|
||||
from vmware_nsx.common import utils
|
||||
from vmware_nsx.db import db as nsx_db
|
||||
from vmware_nsx.db import extended_security_group
|
||||
from vmware_nsx.db import extended_security_group_rule as extend_sg_rule
|
||||
from vmware_nsx.dhcp_meta import rpc as nsx_rpc
|
||||
from vmware_nsx.extensions import securitygrouplogging as sg_logging
|
||||
from vmware_nsx.nsxlib import v3 as nsxlib
|
||||
@ -88,6 +89,7 @@ NSX_V3_DHCP_PROFILE_NAME = 'neutron_port_dhcp_profile'
|
||||
|
||||
class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
|
||||
db_base_plugin_v2.NeutronDbPluginV2,
|
||||
extend_sg_rule.ExtendedSecurityGroupRuleMixin,
|
||||
securitygroups_db.SecurityGroupDbMixin,
|
||||
extended_security_group.ExtendedSecurityGroupPropertiesMixin,
|
||||
external_net_db.External_net_db_mixin,
|
||||
@ -111,6 +113,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
|
||||
"dhcp_agent_scheduler",
|
||||
"ext-gw-mode",
|
||||
"security-group",
|
||||
"secgroup-rule-local-ip-prefix",
|
||||
"port-security",
|
||||
"provider",
|
||||
"external-net",
|
||||
@ -1827,25 +1830,32 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
|
||||
return self.create_security_group_rule_bulk(context, bulk_rule)[0]
|
||||
|
||||
def create_security_group_rule_bulk(self, context, security_group_rules):
|
||||
security_group_rules_db = (
|
||||
super(NsxV3Plugin, self).create_security_group_rule_bulk_native(
|
||||
sg_rules = security_group_rules['security_group_rules']
|
||||
for r in sg_rules:
|
||||
self._check_local_ip_prefix(context, r['security_group_rule'])
|
||||
|
||||
with context.session.begin(subtransactions=True):
|
||||
rules_db = (super(NsxV3Plugin,
|
||||
self).create_security_group_rule_bulk_native(
|
||||
context, security_group_rules))
|
||||
sg_id = security_group_rules_db[0]['security_group_id']
|
||||
for i, r in enumerate(sg_rules):
|
||||
self._process_security_group_rule_properties(
|
||||
context, rules_db[i], r['security_group_rule'])
|
||||
sg_id = rules_db[0]['security_group_id']
|
||||
nsgroup_id, section_id = security.get_sg_mappings(context.session,
|
||||
sg_id)
|
||||
logging_enabled = (cfg.CONF.nsx_v3.log_security_groups_allowed_traffic
|
||||
or self._is_security_group_logged(context, sg_id))
|
||||
try:
|
||||
rules = security.create_firewall_rules(context, section_id,
|
||||
nsgroup_id, logging_enabled,
|
||||
security_group_rules_db)
|
||||
rules = security.create_firewall_rules(
|
||||
context, section_id, nsgroup_id, logging_enabled, rules_db)
|
||||
except nsx_exc.ManagerError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
for rule in security_group_rules_db:
|
||||
for rule in rules_db:
|
||||
super(NsxV3Plugin, self).delete_security_group_rule(
|
||||
context, rule['id'])
|
||||
security.save_sg_rule_mappings(context.session, rules['rules'])
|
||||
return security_group_rules_db
|
||||
return rules_db
|
||||
|
||||
def delete_security_group_rule(self, context, id):
|
||||
rule_db = self._get_security_group_rule(context, id)
|
||||
|
@ -27,8 +27,10 @@ from neutron_lib import constants as const
|
||||
|
||||
from vmware_nsx.db import extended_security_group_rule as ext_rule_db
|
||||
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix as ext_loip
|
||||
from vmware_nsx.nsxlib.v3 import dfw_api as v3_fw
|
||||
from vmware_nsx.plugins.nsx_v.vshield import securitygroup_utils
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin as test_nsxv_plugin
|
||||
from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_nsxv3_plugin
|
||||
|
||||
|
||||
PLUGIN_NAME = ('vmware_nsx.tests.unit.extensions.'
|
||||
@ -46,14 +48,12 @@ class ExtendedRuleTestPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
|
||||
def create_security_group_rule(self, context, security_group_rule):
|
||||
rule = security_group_rule['security_group_rule']
|
||||
rule['id'] = _uuid()
|
||||
self._check_local_ip_prefix(context, rule)
|
||||
with context.session.begin(subtransactions=True):
|
||||
res = super(ExtendedRuleTestPlugin,
|
||||
self).create_security_group_rule(
|
||||
context, security_group_rule)
|
||||
self._save_extended_rule_properties(context, rule)
|
||||
self._get_security_group_rule_properties(context, res)
|
||||
self._process_security_group_rule_properties(context, res, rule)
|
||||
return res
|
||||
|
||||
|
||||
@ -111,10 +111,6 @@ class TestNsxVExtendedSGRule(test_nsxv_plugin.NsxVSecurityGroupsTestCase,
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
dest = {'type': 'Ipv4Address', 'value': local_ip_prefix}
|
||||
|
||||
def _assert_destination_as_expected(*args, **kwargs):
|
||||
self.assertEqual(dest, kwargs['destination'])
|
||||
return sg_utils.get_rule_config(*args, **kwargs)
|
||||
|
||||
plugin.nsx_sg_utils.get_rule_config = mock.Mock(
|
||||
side_effect=sg_utils.get_rule_config)
|
||||
super(TestNsxVExtendedSGRule,
|
||||
@ -123,3 +119,20 @@ class TestNsxVExtendedSGRule(test_nsxv_plugin.NsxVSecurityGroupsTestCase,
|
||||
source=mock.ANY, destination=dest, services=mock.ANY,
|
||||
name=mock.ANY, applied_to_ids=mock.ANY, flags=mock.ANY,
|
||||
logged=mock.ANY)
|
||||
|
||||
|
||||
class TestNSXv3ExtendedSGRule(test_nsxv3_plugin.NsxV3PluginTestCaseMixin,
|
||||
LocalIPPrefixExtTestCase):
|
||||
def test_create_rule_with_local_ip_prefix(self):
|
||||
local_ip_prefix = '239.255.0.0/16'
|
||||
dest = v3_fw.get_ip_cidr_reference(local_ip_prefix, v3_fw.IPV4)
|
||||
|
||||
with mock.patch.object(v3_fw, 'get_firewall_rule_dict',
|
||||
side_effect=v3_fw.get_firewall_rule_dict) as mock_rule:
|
||||
|
||||
super(TestNSXv3ExtendedSGRule,
|
||||
self).test_create_rule_with_local_ip_prefix()
|
||||
|
||||
mock_rule.assert_called_with(mock.ANY, mock.ANY, dest, mock.ANY,
|
||||
v3_fw.IPV4, mock.ANY, v3_fw.ALLOW,
|
||||
mock.ANY)
|
||||
|
Loading…
Reference in New Issue
Block a user