NSX|P: Make sure service router exists for vlan interface
When adding a vlan interface to a tier1 router, the edge cluster must also be set, so that a service router will exist. When removing a vlan interface, check if the service router is still needed. Change-Id: I73b3b02b876eea3d3247487fd12b542b637b6e0b
This commit is contained in:
parent
1472b8d077
commit
920d93def2
@ -2333,10 +2333,22 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
return self.nsxpolicy.tier0.get_edge_cluster_path(
|
||||
tier0_uuid)
|
||||
|
||||
def _get_router_vlan_interfaces(self, context, router_id):
|
||||
# return data about VLAN subnet connected to the router
|
||||
rtr_subnets = self._load_router_subnet_cidrs_from_db(
|
||||
context, router_id)
|
||||
vlan_subnets = []
|
||||
for sub in rtr_subnets:
|
||||
net_id = sub['network_id']
|
||||
if not self._is_overlay_network(context, net_id):
|
||||
vlan_subnets.append(sub)
|
||||
return vlan_subnets
|
||||
|
||||
def service_router_has_services(self, context, router_id, router=None):
|
||||
"""Check if the neutron router has any services
|
||||
which require a backend service router
|
||||
currently those are: SNAT, Loadbalancer, Edge firewall
|
||||
currently those are: SNAT, Loadbalancer, Edge firewall,
|
||||
VPNaaS & Vlan interfaces
|
||||
"""
|
||||
if not router:
|
||||
router = self._get_router(context, router_id)
|
||||
@ -2344,10 +2356,15 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
fw_exist = self._router_has_edge_fw_rules(context, router)
|
||||
vpn_exist = self.service_router_has_vpnaas(context, router_id)
|
||||
lb_exist = False
|
||||
vlan_interfaces = []
|
||||
if not (fw_exist or snat_exist or vpn_exist):
|
||||
lb_exist = self.service_router_has_loadbalancers(
|
||||
context, router_id)
|
||||
return snat_exist or lb_exist or fw_exist or vpn_exist
|
||||
vlan_interfaces = self._get_router_vlan_interfaces(
|
||||
context.elevated(), router_id)
|
||||
if not vlan_interfaces:
|
||||
lb_exist = self.service_router_has_loadbalancers(
|
||||
context, router_id)
|
||||
return (snat_exist or lb_exist or fw_exist or vpn_exist or
|
||||
vlan_interfaces)
|
||||
|
||||
def service_router_has_loadbalancers(self, context, router_id):
|
||||
tags_to_search = [{'scope': lb_const.LR_ROUTER_TYPE, 'tag': router_id}]
|
||||
@ -2940,6 +2957,12 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
ip_addresses=[rtr_subnet['gateway_ip']],
|
||||
prefix_len=prefix_len))
|
||||
|
||||
# Service router is mandatory for VLAN interfaces
|
||||
if not self.verify_sr_at_backend(router_id):
|
||||
self.create_service_router(
|
||||
context, router_id, router=router_db,
|
||||
update_firewall=False)
|
||||
|
||||
ndra_profile_id = self._get_subnet_ndra_profile(subnet)
|
||||
self.nsxpolicy.tier1.add_segment_interface(
|
||||
router_id, segment_id,
|
||||
@ -3048,6 +3071,10 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
self.nsxpolicy.tier1.remove_segment_interface(
|
||||
router_id, segment_id)
|
||||
|
||||
if not self._core_plugin.service_router_has_services(
|
||||
context.elevated(), router_id):
|
||||
self.delete_service_router(router_id)
|
||||
|
||||
# try to delete the SNAT/NO_DNAT rules of this subnet
|
||||
router_db = self._get_router(context, router_id)
|
||||
if (subnet and router_db.gw_port and router_db.enable_snat and
|
||||
|
@ -2615,6 +2615,78 @@ class NsxPTestL3NatTestCase(NsxPTestL3NatTest,
|
||||
nsx_plugin.STATELESS_DHCP_NDRA_PROFILE_ID,
|
||||
sub2_ipversion=4)
|
||||
|
||||
def _add_external_gateway_to_router(self, router_id, network_id,
|
||||
expected_code=exc.HTTPOk.code,
|
||||
neutron_context=None, ext_ips=None,
|
||||
**kwargs):
|
||||
# Copy the neutron api to add support for disabled SNAT
|
||||
ext_ips = ext_ips or []
|
||||
body = {'router':
|
||||
{'external_gateway_info': {'network_id': network_id}}}
|
||||
if ext_ips:
|
||||
body['router']['external_gateway_info'][
|
||||
'external_fixed_ips'] = ext_ips
|
||||
if 'policy_id' in kwargs:
|
||||
body['router']['external_gateway_info'][
|
||||
'qos_policy_id'] = kwargs.get('policy_id')
|
||||
if 'enable_snat' in kwargs:
|
||||
body['router']['external_gateway_info'][
|
||||
'enable_snat'] = kwargs.get('enable_snat')
|
||||
return self._update('routers', router_id, body,
|
||||
expected_code=expected_code,
|
||||
neutron_context=neutron_context)
|
||||
|
||||
def test_router_vlan_interface_sr(self):
|
||||
providernet_args = {pnet.NETWORK_TYPE: 'vlan',
|
||||
pnet.SEGMENTATION_ID: 11}
|
||||
|
||||
with mock.patch('vmware_nsxlib.v3.policy.core_resources.'
|
||||
'NsxPolicyTransportZoneApi.get_transport_type',
|
||||
return_value=nsx_constants.TRANSPORT_TYPE_VLAN), \
|
||||
self.network(name='vlan_net',
|
||||
providernet_args=providernet_args,
|
||||
arg_list=(pnet.NETWORK_TYPE,
|
||||
pnet.SEGMENTATION_ID)) as net,\
|
||||
self.router() as r,\
|
||||
self.subnet(cidr='2001::/64', network=net,
|
||||
ip_version=6, enable_dhcp=False,
|
||||
ipv6_address_mode=None,
|
||||
ipv6_ra_mode=None) as if_subnet,\
|
||||
self._create_l3_ext_network() as ext_net,\
|
||||
self.subnet(network=ext_net, cidr='10.0.0.0/16',
|
||||
enable_dhcp=False) as ext_sub,\
|
||||
mock.patch("vmware_nsxlib.v3.policy.core_resources."
|
||||
"NsxPolicyTier1Api.get_edge_cluster_path",
|
||||
return_value=None),\
|
||||
mock.patch("vmware_nsxlib.v3.policy.core_resources."
|
||||
"NsxPolicyTier1Api.get_realized_id"),\
|
||||
mock.patch("vmware_nsxlib.v3.policy.core_resources."
|
||||
"NsxPolicyTier1Api.set_edge_cluster_path"
|
||||
) as add_srv_router,\
|
||||
mock.patch("vmware_nsxlib.v3.policy.core_resources."
|
||||
"NsxPolicyTier1Api.remove_edge_cluster"
|
||||
) as del_srv_router:
|
||||
|
||||
# Add router GW
|
||||
self._add_external_gateway_to_router(
|
||||
r['router']['id'],
|
||||
ext_sub['subnet']['network_id'],
|
||||
enable_snat=False)
|
||||
|
||||
# Adding subnet interface
|
||||
self._router_interface_action(
|
||||
'add', r['router']['id'],
|
||||
if_subnet['subnet']['id'], None)
|
||||
# verify service router was created
|
||||
add_srv_router.assert_called_once_with(r['router']['id'], mock.ANY)
|
||||
|
||||
# Removing subnet interface
|
||||
self._router_interface_action(
|
||||
'remove', r['router']['id'],
|
||||
if_subnet['subnet']['id'], None)
|
||||
# verify service router was removed
|
||||
del_srv_router.assert_called_once_with(r['router']['id'])
|
||||
|
||||
def _test_router_vlan_interface_ndprofile(self, profile_with,
|
||||
enable_dhcp=True, mode='slaac'):
|
||||
providernet_args = {pnet.NETWORK_TYPE: 'vlan',
|
||||
|
Loading…
x
Reference in New Issue
Block a user