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(
|
return self.nsxpolicy.tier0.get_edge_cluster_path(
|
||||||
tier0_uuid)
|
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):
|
def service_router_has_services(self, context, router_id, router=None):
|
||||||
"""Check if the neutron router has any services
|
"""Check if the neutron router has any services
|
||||||
which require a backend service router
|
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:
|
if not router:
|
||||||
router = self._get_router(context, router_id)
|
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)
|
fw_exist = self._router_has_edge_fw_rules(context, router)
|
||||||
vpn_exist = self.service_router_has_vpnaas(context, router_id)
|
vpn_exist = self.service_router_has_vpnaas(context, router_id)
|
||||||
lb_exist = False
|
lb_exist = False
|
||||||
|
vlan_interfaces = []
|
||||||
if not (fw_exist or snat_exist or vpn_exist):
|
if not (fw_exist or snat_exist or vpn_exist):
|
||||||
lb_exist = self.service_router_has_loadbalancers(
|
vlan_interfaces = self._get_router_vlan_interfaces(
|
||||||
context, router_id)
|
context.elevated(), router_id)
|
||||||
return snat_exist or lb_exist or fw_exist or vpn_exist
|
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):
|
def service_router_has_loadbalancers(self, context, router_id):
|
||||||
tags_to_search = [{'scope': lb_const.LR_ROUTER_TYPE, 'tag': 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']],
|
ip_addresses=[rtr_subnet['gateway_ip']],
|
||||||
prefix_len=prefix_len))
|
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)
|
ndra_profile_id = self._get_subnet_ndra_profile(subnet)
|
||||||
self.nsxpolicy.tier1.add_segment_interface(
|
self.nsxpolicy.tier1.add_segment_interface(
|
||||||
router_id, segment_id,
|
router_id, segment_id,
|
||||||
@ -3048,6 +3071,10 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||||||
self.nsxpolicy.tier1.remove_segment_interface(
|
self.nsxpolicy.tier1.remove_segment_interface(
|
||||||
router_id, segment_id)
|
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
|
# try to delete the SNAT/NO_DNAT rules of this subnet
|
||||||
router_db = self._get_router(context, router_id)
|
router_db = self._get_router(context, router_id)
|
||||||
if (subnet and router_db.gw_port and router_db.enable_snat and
|
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,
|
nsx_plugin.STATELESS_DHCP_NDRA_PROFILE_ID,
|
||||||
sub2_ipversion=4)
|
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,
|
def _test_router_vlan_interface_ndprofile(self, profile_with,
|
||||||
enable_dhcp=True, mode='slaac'):
|
enable_dhcp=True, mode='slaac'):
|
||||||
providernet_args = {pnet.NETWORK_TYPE: 'vlan',
|
providernet_args = {pnet.NETWORK_TYPE: 'vlan',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user