Merge "NSX-V3 Add NO NAT rules for router interfaces"
This commit is contained in:
commit
49e30433ac
@ -191,7 +191,8 @@ class NsxPluginBase(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
subnet = subnet_qry.filter_by(id=ip.subnet_id).one()
|
subnet = subnet_qry.filter_by(id=ip.subnet_id).one()
|
||||||
subnets.append({'id': subnet.id, 'cidr': subnet.cidr,
|
subnets.append({'id': subnet.id, 'cidr': subnet.cidr,
|
||||||
'subnetpool_id': subnet.subnetpool_id,
|
'subnetpool_id': subnet.subnetpool_id,
|
||||||
'ip_version': subnet.ip_version})
|
'ip_version': subnet.ip_version,
|
||||||
|
'network_id': subnet.network_id})
|
||||||
return subnets
|
return subnets
|
||||||
|
|
||||||
def _find_router_gw_subnets(self, context, router):
|
def _find_router_gw_subnets(self, context, router):
|
||||||
|
@ -118,6 +118,7 @@ from vmware_nsx.services.trunk.nsx_v3 import driver as trunk_driver
|
|||||||
from vmware_nsxlib.v3 import core_resources as nsx_resources
|
from vmware_nsxlib.v3 import core_resources as nsx_resources
|
||||||
from vmware_nsxlib.v3 import exceptions as nsx_lib_exc
|
from vmware_nsxlib.v3 import exceptions as nsx_lib_exc
|
||||||
from vmware_nsxlib.v3 import nsx_constants as nsxlib_consts
|
from vmware_nsxlib.v3 import nsx_constants as nsxlib_consts
|
||||||
|
from vmware_nsxlib.v3 import router as nsxlib_router
|
||||||
from vmware_nsxlib.v3 import security
|
from vmware_nsxlib.v3 import security
|
||||||
from vmware_nsxlib.v3 import utils as nsxlib_utils
|
from vmware_nsxlib.v3 import utils as nsxlib_utils
|
||||||
|
|
||||||
@ -3230,6 +3231,9 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
(newaddr != orgaddr or
|
(newaddr != orgaddr or
|
||||||
not new_enable_snat))
|
not new_enable_snat))
|
||||||
|
|
||||||
|
# Remove No-DNAT rules if GW was removed
|
||||||
|
remove_no_dnat_rules = (orgaddr and not newaddr)
|
||||||
|
|
||||||
# Revocate bgp announce for nonat subnets if tier0 router link is
|
# Revocate bgp announce for nonat subnets if tier0 router link is
|
||||||
# changed or enable_snat is updated from False to True
|
# changed or enable_snat is updated from False to True
|
||||||
revocate_bgp_announce = (not org_enable_snat and org_tier0_uuid and
|
revocate_bgp_announce = (not org_enable_snat and org_tier0_uuid and
|
||||||
@ -3248,6 +3252,9 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
(newaddr != orgaddr or
|
(newaddr != orgaddr or
|
||||||
not org_enable_snat))
|
not org_enable_snat))
|
||||||
|
|
||||||
|
# Add No-DNAT rules if GW was added
|
||||||
|
add_no_dnat_rules = (newaddr and not orgaddr)
|
||||||
|
|
||||||
# Bgp announce for nonat subnets if tier0 router link is changed or
|
# Bgp announce for nonat subnets if tier0 router link is changed or
|
||||||
# enable_snat is updated from True to False
|
# enable_snat is updated from True to False
|
||||||
bgp_announce = (not new_enable_snat and new_tier0_uuid and
|
bgp_announce = (not new_enable_snat and new_tier0_uuid and
|
||||||
@ -3259,11 +3266,18 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
advertise_route_nat_flag = True if new_enable_snat else False
|
advertise_route_nat_flag = True if new_enable_snat else False
|
||||||
advertise_route_connected_flag = True if not new_enable_snat else False
|
advertise_route_connected_flag = True if not new_enable_snat else False
|
||||||
|
|
||||||
|
if add_no_dnat_rules or remove_no_dnat_rules or add_snat_rules:
|
||||||
|
subnets = self._find_router_subnets(context.elevated(),
|
||||||
|
router_id)
|
||||||
|
|
||||||
if revocate_bgp_announce:
|
if revocate_bgp_announce:
|
||||||
# TODO(berlin): revocate bgp announce on org tier0 router
|
# TODO(berlin): revocate bgp announce on org tier0 router
|
||||||
pass
|
pass
|
||||||
if remove_snat_rules:
|
if remove_snat_rules:
|
||||||
self.nsxlib.router.delete_gw_snat_rules(nsx_router_id, orgaddr)
|
self.nsxlib.router.delete_gw_snat_rules(nsx_router_id, orgaddr)
|
||||||
|
if remove_no_dnat_rules:
|
||||||
|
for subnet in subnets:
|
||||||
|
self._del_subnet_no_dnat_rule(context, nsx_router_id, subnet)
|
||||||
if remove_router_link_port:
|
if remove_router_link_port:
|
||||||
self.nsxlib.router.remove_router_link_port(
|
self.nsxlib.router.remove_router_link_port(
|
||||||
nsx_router_id, org_tier0_uuid)
|
nsx_router_id, org_tier0_uuid)
|
||||||
@ -3283,11 +3297,13 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
# than the gw
|
# than the gw
|
||||||
gw_address_scope = self._get_network_address_scope(
|
gw_address_scope = self._get_network_address_scope(
|
||||||
context, router.gw_port.network_id)
|
context, router.gw_port.network_id)
|
||||||
subnets = self._find_router_subnets(context.elevated(),
|
|
||||||
router_id)
|
|
||||||
for subnet in subnets:
|
for subnet in subnets:
|
||||||
self._add_subnet_snat_rule(context, router_id, nsx_router_id,
|
self._add_subnet_snat_rule(context, router_id, nsx_router_id,
|
||||||
subnet, gw_address_scope, newaddr)
|
subnet, gw_address_scope, newaddr)
|
||||||
|
if add_no_dnat_rules:
|
||||||
|
for subnet in subnets:
|
||||||
|
self._add_subnet_no_dnat_rule(context, nsx_router_id, subnet)
|
||||||
|
|
||||||
if bgp_announce:
|
if bgp_announce:
|
||||||
# TODO(berlin): bgp announce on new tier0 router
|
# TODO(berlin): bgp announce on new tier0 router
|
||||||
pass
|
pass
|
||||||
@ -3316,6 +3332,21 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
source_net=subnet['cidr'],
|
source_net=subnet['cidr'],
|
||||||
bypass_firewall=False)
|
bypass_firewall=False)
|
||||||
|
|
||||||
|
def _add_subnet_no_dnat_rule(self, context, nsx_router_id, subnet):
|
||||||
|
# Add NO-DNAT rule to allow internal traffic between VMs, even if
|
||||||
|
# they have floating ips
|
||||||
|
self.nsxlib.logical_router.add_nat_rule(
|
||||||
|
nsx_router_id, "NO_DNAT", None,
|
||||||
|
dest_net=subnet['cidr'],
|
||||||
|
rule_priority=nsxlib_router.GW_NAT_PRI)
|
||||||
|
|
||||||
|
def _del_subnet_no_dnat_rule(self, context, nsx_router_id, subnet):
|
||||||
|
# Delete the previously created NO-DNAT rules
|
||||||
|
self.nsxlib.logical_router.delete_nat_rule_by_values(
|
||||||
|
nsx_router_id,
|
||||||
|
action="NO_DNAT",
|
||||||
|
match_destination_network=subnet['cidr'])
|
||||||
|
|
||||||
def _process_extra_attr_router_create(self, context, router_db, r):
|
def _process_extra_attr_router_create(self, context, router_db, r):
|
||||||
for extra_attr in l3_attrs_db.get_attr_info().keys():
|
for extra_attr in l3_attrs_db.get_attr_info().keys():
|
||||||
if (extra_attr in r and
|
if (extra_attr in r and
|
||||||
@ -3881,7 +3912,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
nsx_rpc.handle_router_metadata_access(self, context, router_id,
|
nsx_rpc.handle_router_metadata_access(self, context, router_id,
|
||||||
interface=info)
|
interface=info)
|
||||||
|
|
||||||
# add the SNAT rule for this interface
|
# add the SNAT/NO_DNAT rules for this interface
|
||||||
if (router_db.enable_snat and gw_network_id and
|
if (router_db.enable_snat and gw_network_id and
|
||||||
router_db.gw_port.get('fixed_ips')):
|
router_db.gw_port.get('fixed_ips')):
|
||||||
gw_ip = router_db.gw_port['fixed_ips'][0]['ip_address']
|
gw_ip = router_db.gw_port['fixed_ips'][0]['ip_address']
|
||||||
@ -3889,6 +3920,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
context, gw_network_id)
|
context, gw_network_id)
|
||||||
self._add_subnet_snat_rule(context, router_id, nsx_router_id,
|
self._add_subnet_snat_rule(context, router_id, nsx_router_id,
|
||||||
subnet, gw_address_scope, gw_ip)
|
subnet, gw_address_scope, gw_ip)
|
||||||
|
if gw_network_id:
|
||||||
|
self._add_subnet_no_dnat_rule(context, nsx_router_id, subnet)
|
||||||
# update firewall rules
|
# update firewall rules
|
||||||
self.update_router_firewall(context, router_id)
|
self.update_router_firewall(context, router_id)
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -3961,13 +3994,15 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
else:
|
else:
|
||||||
self.nsxlib.logical_router_port.delete_by_lswitch_id(
|
self.nsxlib.logical_router_port.delete_by_lswitch_id(
|
||||||
nsx_net_id)
|
nsx_net_id)
|
||||||
# try to delete the SNAT rule of this subnet
|
# try to delete the SNAT/NO_DNAT rules of this subnet
|
||||||
if (router_db.gw_port and router_db.enable_snat and
|
if (router_db.gw_port and router_db.enable_snat and
|
||||||
router_db.gw_port.get('fixed_ips')):
|
router_db.gw_port.get('fixed_ips')):
|
||||||
gw_ip = router_db.gw_port['fixed_ips'][0]['ip_address']
|
gw_ip = router_db.gw_port['fixed_ips'][0]['ip_address']
|
||||||
self.nsxlib.router.delete_gw_snat_rule_by_source(
|
self.nsxlib.router.delete_gw_snat_rule_by_source(
|
||||||
nsx_router_id, gw_ip, subnet['cidr'],
|
nsx_router_id, gw_ip, subnet['cidr'],
|
||||||
skip_not_found=True)
|
skip_not_found=True)
|
||||||
|
if router_db.gw_port:
|
||||||
|
self._del_subnet_no_dnat_rule(context, nsx_router_id, subnet)
|
||||||
|
|
||||||
except nsx_lib_exc.ResourceNotFound:
|
except nsx_lib_exc.ResourceNotFound:
|
||||||
LOG.error("router port on router %(router_id)s for net "
|
LOG.error("router port on router %(router_id)s for net "
|
||||||
|
@ -1319,6 +1319,47 @@ class TestL3NatTestCase(L3NatTest,
|
|||||||
gw_info = body['router']['external_gateway_info']
|
gw_info = body['router']['external_gateway_info']
|
||||||
self.assertIsNone(gw_info)
|
self.assertIsNone(gw_info)
|
||||||
|
|
||||||
|
def test_router_on_vlan_net(self):
|
||||||
|
providernet_args = {pnet.NETWORK_TYPE: 'vlan',
|
||||||
|
pnet.SEGMENTATION_ID: 10}
|
||||||
|
with mock.patch('vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
|
||||||
|
'get_transport_type', return_value='VLAN'):
|
||||||
|
result = self._create_network(fmt='json', name='badvlan_net',
|
||||||
|
admin_state_up=True,
|
||||||
|
providernet_args=providernet_args,
|
||||||
|
arg_list=(
|
||||||
|
pnet.NETWORK_TYPE,
|
||||||
|
pnet.SEGMENTATION_ID))
|
||||||
|
vlan_network = self.deserialize('json', result)
|
||||||
|
with self.router() as r1,\
|
||||||
|
self.subnet() as ext_subnet,\
|
||||||
|
self.subnet(cidr='11.0.0.0/24', network=vlan_network) as s1:
|
||||||
|
self._set_net_external(ext_subnet['subnet']['network_id'])
|
||||||
|
# adding a vlan interface with no GW should fail
|
||||||
|
self._router_interface_action(
|
||||||
|
'add', r1['router']['id'],
|
||||||
|
s1['subnet']['id'], None,
|
||||||
|
expected_code=400)
|
||||||
|
# adding GW
|
||||||
|
self._add_external_gateway_to_router(
|
||||||
|
r1['router']['id'],
|
||||||
|
ext_subnet['subnet']['network_id'])
|
||||||
|
# adding the vlan interface
|
||||||
|
self._router_interface_action(
|
||||||
|
'add', r1['router']['id'],
|
||||||
|
s1['subnet']['id'], None)
|
||||||
|
|
||||||
|
# adding a floating ip
|
||||||
|
with self.port(subnet=s1) as p:
|
||||||
|
fip_res = self._create_floatingip(
|
||||||
|
self.fmt,
|
||||||
|
ext_subnet['subnet']['network_id'],
|
||||||
|
subnet_id=ext_subnet['subnet']['id'],
|
||||||
|
port_id=p['port']['id'])
|
||||||
|
fip = self.deserialize(self.fmt, fip_res)
|
||||||
|
self.assertEqual(p['port']['id'],
|
||||||
|
fip['floatingip']['port_id'])
|
||||||
|
|
||||||
def test_create_router_gateway_fails(self):
|
def test_create_router_gateway_fails(self):
|
||||||
self.skipTest('not supported')
|
self.skipTest('not supported')
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user