Add no nat cidrs network extension

The no-NAT CIDRs extension is applied to the network resource
in neutron. When applied, it affects the list of subnets that
should be reachable without NAT that are delivered in the RPC
calls to agents. The agents can then use this information to
ensure that specific destination CIDRs will never use NAT.

The extension can be applied to both tenant and external/public
networks. The extension should be used judiciously, as placing
it on a network will cause those CIDRs to be added to all RPC
calls requesting subnets within that VRF (e.g. the extension
could be added to a shared network or to a network that uses
a subnetpool relating to a shared address scope, which would
be seen by all other networks that report to that same address
scope or shared network).

Change-Id: Ic2cdd501933cc21c286ca36218361aadef1878b8
This commit is contained in:
mdsufair
2022-05-25 04:45:23 -04:00
committed by Thomas Bachman
parent cb3efe4afa
commit d1ff11cb8e
8 changed files with 544 additions and 16 deletions

View File

@@ -7133,6 +7133,49 @@ class TestExtensionAttributes(ApicAimTestCase):
network_id=net_id).all())
self.assertEqual([], db_masters)
def test_network_with_no_nat_cidrs_lifecycle(self):
session = db_api.get_reader_session()
extn = extn_db.ExtensionDbMixin()
# Create network with default no nat cidrs extension
net = self._make_network(
self.fmt, 'net1', True)['network']
net_id = net['id']
self.assertItemsEqual([],
net['apic:no_nat_cidrs'])
# Test show.
net = self._show('networks', net_id)['network']
self.assertItemsEqual([],
net['apic:no_nat_cidrs'])
# Test list.
net = self._list(
'networks', query_params=('id=%s' % net_id))['networks'][0]
self.assertItemsEqual([],
net['apic:no_nat_cidrs'])
# Test update with no nat cidrs extension
net = self._update(
'networks', net_id,
{'network':
{'apic:no_nat_cidrs': ['10.10.10.0/24']}})['network']
self.assertItemsEqual(['10.10.10.0/24'],
net['apic:no_nat_cidrs'])
# Test show after update.
net = self._show('networks', net_id)['network']
self.assertItemsEqual(['10.10.10.0/24'],
net['apic:no_nat_cidrs'])
# Test delete.
self._delete('networks', net_id)
self.assertFalse(extn.get_network_extn_db(session, net_id))
db_masters = (session.query(
extn_db.NetworkExtensionNoNatCidrsDb).filter_by(
network_id=net_id).all())
self.assertEqual([], db_masters)
def test_external_network_lifecycle(self):
session = db_api.get_reader_session()
extn = extn_db.ExtensionDbMixin()
@@ -12776,3 +12819,340 @@ class TestUpdateRouterSubnet(ApicAimTestCase):
self._check_ip_in_cidr(router
['external_gateway_info']['external_fixed_ips'][0]['ip_address'],
fip_sub['cidr'])
class TestExtensionNoNatCidrsScenarios(TestOpflexRpc, ApicAimTestCase):
def _get_vrfid_from_net(self, net):
kwargs = {}
vrf_dn = net['network']['apic:distinguished_names']['VRF']
_, tenant_rn, vrf_rn = vrf_dn.split('/')
tenant = tenant_rn.split('tn-')[1]
vrf = vrf_rn.split('ctx-')[1]
kwargs['vrf_id'] = '%s %s' % (tenant, vrf)
return kwargs
def test_no_nat_cidrs_isolated_private_net(self):
# test no nat cidrs extension for isolated private network
host = 'host1'
kwargs = {'apic:no_nat_cidrs': ['10.10.10.0/24']}
net = self._make_network(
self.fmt, 'net10', True,
arg_list=tuple(list(kwargs.keys())), **kwargs)
net_id = net['network']['id']
self._make_subnet(self.fmt, net, '10.0.1.1', '10.0.1.0/24')
port = self._make_port(self.fmt, net_id)['port']
port_id = port['id']
port = self._bind_port_to_host(port_id, host)['port']
self.assertEqual('ovs', port['binding:vif_type'])
# Call the RPC handler.
request = {
'device': 'tap' + port_id,
'timestamp': 12345,
'request_id': 'a_request'
}
response = self.driver.request_endpoint_details(
n_context.get_admin_context(), request=request, host=host)
self.assertEqual(set(['10.0.1.0/24', '10.10.10.0/24']),
set(response['gbp_details']['vrf_subnets']))
kwargs = self._get_vrfid_from_net(net)
response = self.driver.get_vrf_details(
n_context.get_admin_context(), **kwargs)
self.assertEqual(set(['10.0.1.0/24', '10.10.10.0/24']),
set(response['vrf_subnets']))
def test_no_nat_cidrs_external_network(self):
# test no nat cidrs extension for external network
ext_net = self._make_ext_network('ext-net1',
dn=self.dn_t1_l1_n1)
ext_net = self._update(
'networks', ext_net['id'],
{'network':
{'apic:no_nat_cidrs': ['50.50.50.0/24']}})
self._make_subnet(
self.fmt, {'network': ext_net['network']}, '100.100.100.1',
'100.100.100.0/24')
host = 'host1'
port = self._make_port(self.fmt, ext_net['network']['id'])['port']
port_id = port['id']
port = self._bind_port_to_host(port_id, host)['port']
self.assertEqual('ovs', port['binding:vif_type'])
# Call the RPC handler.
request = {
'device': 'tap' + port_id,
'timestamp': 12345,
'request_id': 'a_request'
}
response = self.driver.request_endpoint_details(
n_context.get_admin_context(), request=request, host=host)
self.assertEqual(['100.100.100.0/24', '50.50.50.0/24'],
response['gbp_details']['vrf_subnets'])
net = self._show('networks', ext_net['network']['id'])
kwargs = self._get_vrfid_from_net(net)
response = self.driver.get_vrf_details(
n_context.get_admin_context(), **kwargs)
self.assertEqual(['100.100.100.0/24', '50.50.50.0/24'],
response['vrf_subnets'])
def test_no_nat_cidrs_private_net_router(self):
# test no nat cidrs extension for private network connected to a
# router with out external gateway
host = 'host1'
kwargs = {'apic:no_nat_cidrs': ['10.10.10.0/24']}
net = self._make_network(
self.fmt, 'net10', True,
arg_list=tuple(list(kwargs.keys())), **kwargs)
net_id = net['network']['id']
subnet_id = self._make_subnet(
self.fmt, net, '10.0.1.1', '10.0.1.0/24')['subnet']['id']
rtr = self._make_router(
self.fmt, net['network']['tenant_id'], 'router1')['router']
self._router_interface_action('add', rtr['id'], subnet_id, None)
port = self._make_port(self.fmt, net_id)['port']
port_id = port['id']
port = self._bind_port_to_host(port_id, host)['port']
self.assertEqual('ovs', port['binding:vif_type'])
# Call the RPC handler.
request = {
'device': 'tap' + port_id,
'timestamp': 12345,
'request_id': 'a_request'
}
response = self.driver.request_endpoint_details(
n_context.get_admin_context(), request=request, host=host)
self.assertEqual(set(['10.0.1.0/24', '10.10.10.0/24']),
set(response['gbp_details']['vrf_subnets']))
net = self._show('networks', net['network']['id'])
kwargs = self._get_vrfid_from_net(net)
response = self.driver.get_vrf_details(
n_context.get_admin_context(), **kwargs)
self.assertEqual(set(['10.0.1.0/24', '10.10.10.0/24']),
set(response['vrf_subnets']))
def test_no_nat_cidrs_private_net_router_with_gw_case1(self):
# test no nat cidrs extension for private network connected to a
# router with an external gateway.
# extension available in private network, but not in external network
ext_net = self._make_ext_network('ext-net1',
dn=self.dn_t1_l1_n1)
self._make_subnet(
self.fmt, {'network': ext_net}, '100.100.100.1',
'100.100.100.0/24')
host = 'host1'
kwargs = {'apic:no_nat_cidrs': ['10.10.10.0/24']}
net = self._make_network(
self.fmt, 'net10', True,
arg_list=tuple(list(kwargs.keys())), **kwargs)
net_id = net['network']['id']
subnet_id = self._make_subnet(
self.fmt, net, '10.0.1.1', '10.0.1.0/24')['subnet']['id']
rtr = self._make_router(
self.fmt, net['network']['tenant_id'], 'router1',
external_gateway_info={'network_id': ext_net['id']})['router']
self._router_interface_action('add', rtr['id'], subnet_id, None)
port = self._make_port(self.fmt, net_id)['port']
port_id = port['id']
port = self._bind_port_to_host(port_id, host)['port']
self.assertEqual('ovs', port['binding:vif_type'])
# Call the RPC handler.
request = {
'device': 'tap' + port_id,
'timestamp': 12345,
'request_id': 'a_request'
}
response = self.driver.request_endpoint_details(
n_context.get_admin_context(), request=request, host=host)
self.assertEqual(['10.0.1.0/24', '10.10.10.0/24'],
response['gbp_details']['vrf_subnets'])
net = self._show('networks', net['network']['id'])
kwargs = self._get_vrfid_from_net(net)
response = self.driver.get_vrf_details(
n_context.get_admin_context(), **kwargs)
self.assertEqual(['10.0.1.0/24', '10.10.10.0/24'],
response['vrf_subnets'])
def test_no_nat_cidrs_private_net_router_with_gw_case2(self):
# test no nat cidrs extension for private network connected to a
# router with an external gateway.
# extension available in external network, but not in private network
ext_net = self._make_ext_network('ext-net1',
dn=self.dn_t1_l1_n1)
ext_net = self._update(
'networks', ext_net['id'],
{'network':
{'apic:no_nat_cidrs': ['50.50.50.0/24']}})
self._make_subnet(
self.fmt, {'network': ext_net['network']}, '100.100.100.1',
'100.100.100.0/24')
host = 'host1'
net = self._make_network(
self.fmt, 'net10', True)
net_id = net['network']['id']
subnet_id = self._make_subnet(
self.fmt, net, '10.0.1.1', '10.0.1.0/24')['subnet']['id']
rtr = self._make_router(
self.fmt, net['network']['tenant_id'], 'router1',
external_gateway_info={'network_id': ext_net['network']['id']})
self._router_interface_action('add', rtr['router']['id'],
subnet_id, None)
port = self._make_port(self.fmt, net_id)['port']
port_id = port['id']
port = self._bind_port_to_host(port_id, host)['port']
self.assertEqual('ovs', port['binding:vif_type'])
# Call the RPC handler.
request = {
'device': 'tap' + port_id,
'timestamp': 12345,
'request_id': 'a_request'
}
response = self.driver.request_endpoint_details(
n_context.get_admin_context(), request=request, host=host)
self.assertEqual(['10.0.1.0/24', '50.50.50.0/24'],
response['gbp_details']['vrf_subnets'])
net = self._show('networks', net['network']['id'])
kwargs = self._get_vrfid_from_net(net)
response = self.driver.get_vrf_details(
n_context.get_admin_context(), **kwargs)
self.assertEqual(['10.0.1.0/24', '50.50.50.0/24'],
response['vrf_subnets'])
def test_no_nat_cidrs_private_net_router_with_gw_case3(self):
# test no nat cidrs extension for private network connected to a
# router with an external gateway.
# extension available in both external network and private network
ext_net = self._make_ext_network('ext-net1',
dn=self.dn_t1_l1_n1)
ext_net = self._update(
'networks', ext_net['id'],
{'network':
{'apic:no_nat_cidrs': ['50.50.50.0/24']}})
self._make_subnet(
self.fmt, {'network': ext_net['network']}, '100.100.100.1',
'100.100.100.0/24')
host = 'host1'
kwargs = {'apic:no_nat_cidrs': ['10.10.10.0/24']}
net = self._make_network(
self.fmt, 'net10', True,
arg_list=tuple(list(kwargs.keys())), **kwargs)
net_id = net['network']['id']
subnet_id = self._make_subnet(
self.fmt, net, '10.0.1.1', '10.0.1.0/24')['subnet']['id']
rtr = self._make_router(
self.fmt, net['network']['tenant_id'], 'router1',
external_gateway_info={'network_id': ext_net['network']['id']})
self._router_interface_action('add', rtr['router']['id'],
subnet_id, None)
port = self._make_port(self.fmt, net_id)['port']
port_id = port['id']
port = self._bind_port_to_host(port_id, host)['port']
self.assertEqual('ovs', port['binding:vif_type'])
# Call the RPC handler.
request = {
'device': 'tap' + port_id,
'timestamp': 12345,
'request_id': 'a_request'
}
response = self.driver.request_endpoint_details(
n_context.get_admin_context(), request=request, host=host)
self.assertEqual(
set(['10.0.1.0/24', '50.50.50.0/24', '10.10.10.0/24']),
set(response['gbp_details']['vrf_subnets']))
net = self._show('networks', net['network']['id'])
kwargs = self._get_vrfid_from_net(net)
response = self.driver.get_vrf_details(
n_context.get_admin_context(), **kwargs)
self.assertEqual(
set(['10.0.1.0/24', '50.50.50.0/24', '10.10.10.0/24']),
set(response['vrf_subnets']))
def test_no_nat_cidrs_with_address_scope(self):
# test no nat cidrs extension when address scope available
# Create address scope.
scope = self._make_address_scope(
self.fmt, 4, name='as1')['address_scope']
scope_id = scope['id']
# Create subnet pool.
pool = self._make_subnetpool(self.fmt, ['10.0.0.0/8'], name='sp1',
tenant_id=self._tenant_id,
address_scope_id=scope_id,
default_prefixlen=24)['subnetpool']
pool_id = pool['id']
# Create network.
kwargs = {'apic:no_nat_cidrs': ['10.10.10.0/24']}
net = self._make_network(
self.fmt, 'net10', True,
arg_list=tuple(list(kwargs.keys())), **kwargs)
net_id = net['network']['id']
# Create subnet1.
subnet = self._make_subnet(
self.fmt, net, '10.0.1.1', '10.0.1.0/24',
subnetpool_id=pool_id)['subnet']
subnet_id = subnet['id']
# Create an external network and make it as a gateway to router
ext_net = self._make_ext_network('ext-net1',
dn=self.dn_t1_l1_n1)
ext_net = self._update(
'networks', ext_net['id'],
{'network':
{'apic:no_nat_cidrs': ['50.50.50.0/24']}})
self._make_subnet(
self.fmt, {'network': ext_net['network']}, '100.100.100.1',
'100.100.100.0/24')
rtr = self._make_router(
self.fmt, self._tenant_id, 'router1',
external_gateway_info={'network_id': ext_net['network']['id']})
self._router_interface_action('add', rtr['router']['id'],
subnet_id, None)
host = 'host1'
port = self._make_port(self.fmt, net_id)['port']
port_id = port['id']
port = self._bind_port_to_host(port_id, host)['port']
self.assertEqual('ovs', port['binding:vif_type'])
# Call the RPC handler.
request = {
'device': 'tap' + port_id,
'timestamp': 12345,
'request_id': 'a_request'
}
response = self.driver.request_endpoint_details(
n_context.get_admin_context(), request=request, host=host)
self.assertEqual(
set(['10.0.0.0/8', '50.50.50.0/24', '10.10.10.0/24']),
set(response['gbp_details']['vrf_subnets']))
net = self._show('networks', net['network']['id'])
kwargs = self._get_vrfid_from_net(net)
response = self.driver.get_vrf_details(
n_context.get_admin_context(), **kwargs)
self.assertEqual(
set(['10.0.0.0/8', '50.50.50.0/24', '10.10.10.0/24']),
set(response['vrf_subnets']))