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: Idb39b75ff6d611a1dd413f26055622310cdf0df7
This commit is contained in:
Thomas Bachman 2023-02-26 12:33:24 +00:00
parent d7ceb5a57c
commit 7d722bae8e
8 changed files with 540 additions and 16 deletions

View File

@ -1 +1 @@
90e1d92a49b2 e29a84f6a15f

View File

@ -0,0 +1,42 @@
# 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.
#
"""add no nat cidrs network extension
Revision ID: e29a84f6a15f
Revises: 90e1d92a49b2
"""
# revision identifiers, used by Alembic.
revision = 'e29a84f6a15f'
down_revision = '90e1d92a49b2'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.create_table(
'apic_aim_network_no_nat_cidrs',
sa.Column('network_id', sa.String(36), nullable=False),
sa.Column('cidr', sa.String(64), nullable=False),
sa.ForeignKeyConstraint(['network_id'], ['networks.id'],
name='apic_aim_network_no_nat_cidrs_extn_fk_network',
ondelete='CASCADE'),
sa.PrimaryKeyConstraint('network_id', 'cidr')
)
def downgrade():
pass

View File

@ -53,6 +53,7 @@ ERSPAN_CONFIG = 'apic:erspan_config'
POLICY_ENFORCEMENT_PREF = 'apic:policy_enforcement_pref' POLICY_ENFORCEMENT_PREF = 'apic:policy_enforcement_pref'
SNAT_SUBNET_ONLY = 'apic:snat_subnet_only' SNAT_SUBNET_ONLY = 'apic:snat_subnet_only'
EPG_SUBNET = 'apic:epg_subnet' EPG_SUBNET = 'apic:epg_subnet'
NO_NAT_CIDRS = 'apic:no_nat_cidrs'
BD = 'BridgeDomain' BD = 'BridgeDomain'
EPG = 'EndpointGroup' EPG = 'EndpointGroup'
@ -354,6 +355,12 @@ NET_ATTRIBUTES = {
'is_visible': True, 'default': 'unenforced', 'is_visible': True, 'default': 'unenforced',
'validate': {'type:values': ['unenforced', 'enforced', '']}, 'validate': {'type:values': ['unenforced', 'enforced', '']},
}, },
NO_NAT_CIDRS: {
'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': None,
'convert_to': convert_apic_none_to_empty_list,
'validate': {'type:list_of_unique_strings': None},
},
} }
EXT_NET_ATTRIBUTES = { EXT_NET_ATTRIBUTES = {

View File

@ -140,6 +140,21 @@ class NetworkExtEpgContractMasterDb(model_base.BASEV2):
lazy='joined', cascade='delete')) lazy='joined', cascade='delete'))
class NetworkExtensionNoNatCidrsDb(model_base.BASEV2):
__tablename__ = 'apic_aim_network_no_nat_cidrs'
network_id = sa.Column(
sa.String(36), sa.ForeignKey('networks.id', ondelete="CASCADE"),
primary_key=True)
cidr = sa.Column(sa.String(64), primary_key=True)
network = orm.relationship(models_v2.Network,
backref=orm.backref(
'aim_extension_no_nat_cidrs_mapping',
lazy='joined', uselist=True,
cascade='delete'))
class SubnetExtensionDb(model_base.BASEV2): class SubnetExtensionDb(model_base.BASEV2):
__tablename__ = 'apic_aim_subnet_extensions' __tablename__ = 'apic_aim_subnet_extensions'
@ -275,10 +290,19 @@ class ExtensionDbMixin(object):
db_masters = query(session).params( db_masters = query(session).params(
network_ids=network_ids).all() network_ids=network_ids).all()
query = BAKERY(lambda s: s.query(
NetworkExtensionNoNatCidrsDb))
query += lambda q: q.filter(
NetworkExtensionNoNatCidrsDb.network_id.in_(
sa.bindparam('network_ids', expanding=True)))
db_no_nat_cidrs = query(session).params(
network_ids=network_ids).all()
cidrs_by_net_id = {} cidrs_by_net_id = {}
vlans_by_net_id = {} vlans_by_net_id = {}
contracts_by_net_id = {} contracts_by_net_id = {}
masters_by_net_id = {} masters_by_net_id = {}
no_nat_cidrs_by_net_id = {}
for db_cidr in db_cidrs: for db_cidr in db_cidrs:
cidrs_by_net_id.setdefault(db_cidr.network_id, []).append( cidrs_by_net_id.setdefault(db_cidr.network_id, []).append(
db_cidr) db_cidr)
@ -291,6 +315,9 @@ class ExtensionDbMixin(object):
for db_master in db_masters: for db_master in db_masters:
masters_by_net_id.setdefault(db_master.network_id, []).append( masters_by_net_id.setdefault(db_master.network_id, []).append(
db_master) db_master)
for db_no_nat_cidr in db_no_nat_cidrs:
no_nat_cidrs_by_net_id.setdefault(db_no_nat_cidr.network_id,
[]).append(db_no_nat_cidr)
result = {} result = {}
for db_obj in db_objs: for db_obj in db_objs:
@ -299,11 +326,13 @@ class ExtensionDbMixin(object):
db_obj, cidrs_by_net_id.get(net_id, []), db_obj, cidrs_by_net_id.get(net_id, []),
vlans_by_net_id.get(net_id, []), vlans_by_net_id.get(net_id, []),
contracts_by_net_id.get(net_id, []), contracts_by_net_id.get(net_id, []),
masters_by_net_id.get(net_id, []))) masters_by_net_id.get(net_id, []),
no_nat_cidrs_by_net_id.get(net_id, [])))
return result return result
def make_network_extn_db_conf_dict(self, ext_db, db_cidrs, db_vlans, def make_network_extn_db_conf_dict(self, ext_db, db_cidrs, db_vlans,
db_contracts, db_masters): db_contracts, db_masters,
db_no_nat_cidrs):
net_res = {} net_res = {}
db_obj = ext_db db_obj = ext_db
if db_obj: if db_obj:
@ -338,6 +367,8 @@ class ExtensionDbMixin(object):
'name': m.name} for m in db_masters] 'name': m.name} for m in db_masters]
net_res[cisco_apic.POLICY_ENFORCEMENT_PREF] = db_obj[ net_res[cisco_apic.POLICY_ENFORCEMENT_PREF] = db_obj[
'policy_enforcement_pref'] 'policy_enforcement_pref']
net_res[cisco_apic.NO_NAT_CIDRS] = [
c.cidr for c in db_no_nat_cidrs]
if net_res.get(cisco_apic.EXTERNAL_NETWORK): if net_res.get(cisco_apic.EXTERNAL_NETWORK):
net_res[cisco_apic.EXTERNAL_CIDRS] = [c.cidr for c in db_cidrs] net_res[cisco_apic.EXTERNAL_CIDRS] = [c.cidr for c in db_cidrs]
return net_res return net_res
@ -418,6 +449,12 @@ class ExtensionDbMixin(object):
res_dict[cisco_apic.EPG_CONTRACT_MASTERS], res_dict[cisco_apic.EPG_CONTRACT_MASTERS],
network_id=network_id) network_id=network_id)
if cisco_apic.NO_NAT_CIDRS in res_dict:
self._update_list_attr(session, NetworkExtensionNoNatCidrsDb,
'cidr',
res_dict[cisco_apic.NO_NAT_CIDRS],
network_id=network_id)
def get_network_ids_by_ext_net_dn(self, session, dn, lock_update=False): def get_network_ids_by_ext_net_dn(self, session, dn, lock_update=False):
query = BAKERY(lambda s: s.query( query = BAKERY(lambda s: s.query(
NetworkExtensionDb.network_id)) NetworkExtensionDb.network_id))

View File

@ -160,6 +160,8 @@ class ApicExtensionDriver(api_plus.ExtensionDriver,
data.get(cisco_apic.EPG_CONTRACT_MASTERS), data.get(cisco_apic.EPG_CONTRACT_MASTERS),
cisco_apic.POLICY_ENFORCEMENT_PREF: cisco_apic.POLICY_ENFORCEMENT_PREF:
data.get(cisco_apic.POLICY_ENFORCEMENT_PREF, "unenforced"), data.get(cisco_apic.POLICY_ENFORCEMENT_PREF, "unenforced"),
cisco_apic.NO_NAT_CIDRS:
data.get(cisco_apic.NO_NAT_CIDRS),
} }
if cisco_apic.VLANS_LIST in (data.get( if cisco_apic.VLANS_LIST in (data.get(
cisco_apic.NESTED_DOMAIN_ALLOWED_VLANS) or {}): cisco_apic.NESTED_DOMAIN_ALLOWED_VLANS) or {}):
@ -222,7 +224,8 @@ class ApicExtensionDriver(api_plus.ExtensionDriver,
cisco_apic.EXTRA_PROVIDED_CONTRACTS, cisco_apic.EXTRA_PROVIDED_CONTRACTS,
cisco_apic.EXTRA_CONSUMED_CONTRACTS, cisco_apic.EXTRA_CONSUMED_CONTRACTS,
cisco_apic.EPG_CONTRACT_MASTERS, cisco_apic.EPG_CONTRACT_MASTERS,
cisco_apic.POLICY_ENFORCEMENT_PREF] cisco_apic.POLICY_ENFORCEMENT_PREF,
cisco_apic.NO_NAT_CIDRS]
if not(set(update_attrs) & set(data.keys())): if not(set(update_attrs) & set(data.keys())):
return return
@ -242,7 +245,8 @@ class ApicExtensionDriver(api_plus.ExtensionDriver,
cisco_apic.EXTRA_PROVIDED_CONTRACTS, cisco_apic.EXTRA_PROVIDED_CONTRACTS,
cisco_apic.EXTRA_CONSUMED_CONTRACTS, cisco_apic.EXTRA_CONSUMED_CONTRACTS,
cisco_apic.EPG_CONTRACT_MASTERS, cisco_apic.EPG_CONTRACT_MASTERS,
cisco_apic.POLICY_ENFORCEMENT_PREF] cisco_apic.POLICY_ENFORCEMENT_PREF,
cisco_apic.NO_NAT_CIDRS]
for e_k in ext_keys: for e_k in ext_keys:
if e_k in data: if e_k in data:
res_dict.update({e_k: data[e_k]}) res_dict.update({e_k: data[e_k]})

View File

@ -1422,7 +1422,8 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
net_db.aim_extension_cidr_mapping, net_db.aim_extension_cidr_mapping,
net_db.aim_extension_domain_mapping, net_db.aim_extension_domain_mapping,
net_db.aim_extension_extra_contract_mapping, net_db.aim_extension_extra_contract_mapping,
net_db.aim_extension_epg_contract_masters) net_db.aim_extension_epg_contract_masters,
net_db.aim_extension_no_nat_cidrs_mapping)
if cisco_apic.EXTERNAL_NETWORK in ext_dict: if cisco_apic.EXTERNAL_NETWORK in ext_dict:
dn = ext_dict.pop(cisco_apic.EXTERNAL_NETWORK) dn = ext_dict.pop(cisco_apic.EXTERNAL_NETWORK)
a_ext_net = aim_resource.ExternalNetwork.from_dn(dn) a_ext_net = aim_resource.ExternalNetwork.from_dn(dn)

View File

@ -455,7 +455,8 @@ class ApicRpcHandlerMixin(object):
# Query for VRF subnets. # Query for VRF subnets.
info['vrf_subnets'] = self._query_vrf_subnets( info['vrf_subnets'] = self._query_vrf_subnets(
session, port_info.vrf_tenant_name, port_info.vrf_name) session, port_info.vrf_tenant_name, port_info.vrf_name,
ext_net_info=info['ext_net_info'])
# Let the GBP policy driver do its queries and add # Let the GBP policy driver do its queries and add
# its info. # its info.
@ -849,14 +850,20 @@ class ApicRpcHandlerMixin(object):
return [x for x, in query(session).params( return [x for x, in query(session).params(
network_id=network_id)] network_id=network_id)]
def _query_vrf_subnets(self, session, vrf_tenant_name, vrf_name): def _query_vrf_subnets(self, session, vrf_tenant_name, vrf_name,
ext_net_info=None):
# A VRF mapped from one or two (IPv4 and/or IPv6) # A VRF mapped from one or two (IPv4 and/or IPv6)
# address_scopes cannot be associated with unscoped # address_scopes cannot be associated with unscoped
# subnets. So first see if the VRF is mapped from # subnets. So first see if the VRF is mapped from
# address_scopes, and if so, return the subnetpool CIDRs # address_scopes, and if so, return the subnetpool CIDRs
# associated with those address_scopes. # associated with those address_scopes.
result = []
sub_ids = []
net_ids = []
query = BAKERY(lambda s: s.query( query = BAKERY(lambda s: s.query(
models_v2.SubnetPoolPrefix.cidr)) models_v2.SubnetPoolPrefix.cidr,
models_v2.Subnet.id,
models_v2.Network.id))
query += lambda q: q.join( query += lambda q: q.join(
models_v2.SubnetPool, models_v2.SubnetPool,
models_v2.SubnetPool.id == models_v2.SubnetPool.id ==
@ -865,15 +872,33 @@ class ApicRpcHandlerMixin(object):
db.AddressScopeMapping, db.AddressScopeMapping,
db.AddressScopeMapping.scope_id == db.AddressScopeMapping.scope_id ==
models_v2.SubnetPool.address_scope_id) models_v2.SubnetPool.address_scope_id)
query += lambda q: q.join(
db.NetworkMapping,
db.NetworkMapping.network_id ==
models_v2.Network.id)
query += lambda q: q.filter( query += lambda q: q.filter(
db.AddressScopeMapping.vrf_name == db.AddressScopeMapping.vrf_name ==
sa.bindparam('vrf_name'), sa.bindparam('vrf_name'),
db.AddressScopeMapping.vrf_tenant_name == db.AddressScopeMapping.vrf_tenant_name ==
sa.bindparam('vrf_tenant_name'),
db.NetworkMapping.vrf_name ==
sa.bindparam('vrf_name'),
db.NetworkMapping.vrf_tenant_name ==
sa.bindparam('vrf_tenant_name')) sa.bindparam('vrf_tenant_name'))
result = [x for x, in query(session).params( for cidr, sub_id, net_id in query(session).params(vrf_name=vrf_name,
vrf_name=vrf_name, vrf_tenant_name=vrf_tenant_name).all():
vrf_tenant_name=vrf_tenant_name)] result.append(cidr)
sub_ids.append(sub_id)
net_ids.append(net_id)
if result: if result:
# query to fetch no nat cidrs extension from the networks
if not ext_net_info:
ext_net_info = self._query_endpoint_ext_net_info(
session, sub_ids)
net_ids.extend(list(ext_net_info.keys()))
cidrs = self._query_no_nat_cidrs_extension(session, net_ids)
if cidrs:
result.extend(cidrs)
return result return result
# If the VRF is not mapped from address_scopes, return the # If the VRF is not mapped from address_scopes, return the
@ -886,7 +911,9 @@ class ApicRpcHandlerMixin(object):
# subnets' CIDRs being returned, even for the scoped case # subnets' CIDRs being returned, even for the scoped case
# where they are not needed, so it may not be a win. # where they are not needed, so it may not be a win.
query = BAKERY(lambda s: s.query( query = BAKERY(lambda s: s.query(
models_v2.Subnet.cidr)) models_v2.Subnet.cidr,
models_v2.Subnet.id,
models_v2.Subnet.network_id))
query += lambda q: q.join( query += lambda q: q.join(
db.NetworkMapping, db.NetworkMapping,
db.NetworkMapping.network_id == db.NetworkMapping.network_id ==
@ -896,9 +923,35 @@ class ApicRpcHandlerMixin(object):
sa.bindparam('vrf_name'), sa.bindparam('vrf_name'),
db.NetworkMapping.vrf_tenant_name == db.NetworkMapping.vrf_tenant_name ==
sa.bindparam('vrf_tenant_name')) sa.bindparam('vrf_tenant_name'))
return [x for x, in query(session).params( for cidr, sub_id, net_id in query(session).params(vrf_name=vrf_name,
vrf_name=vrf_name, vrf_tenant_name=vrf_tenant_name).all():
vrf_tenant_name=vrf_tenant_name)] result.append(cidr)
sub_ids.append(sub_id)
net_ids.append(net_id)
if not ext_net_info:
ext_net_info = self._query_endpoint_ext_net_info(
session, sub_ids)
net_ids.extend(list(ext_net_info.keys()))
# query to fetch no nat cidrs extension from the networks
cidrs = self._query_no_nat_cidrs_extension(session, net_ids)
if cidrs:
result.extend(cidrs)
return result
def _query_no_nat_cidrs_extension(self, session, net_ids):
query = BAKERY(lambda s: s.query(
extension_db.NetworkExtensionNoNatCidrsDb.cidr))
query += lambda q: q.join(
models_v2.Network,
models_v2.Network.id ==
extension_db.NetworkExtensionNoNatCidrsDb.network_id)
query += lambda q: q.filter(
extension_db.NetworkExtensionNoNatCidrsDb.network_id.in_(
sa.bindparam('network_ids', expanding=True)))
query += lambda q: q.distinct()
cidrs = [x for x, in query(session).params(
network_ids=net_ids)]
return cidrs
def _build_endpoint_neutron_details(self, info): def _build_endpoint_neutron_details(self, info):
port_info = info['port_info'] port_info = info['port_info']

View File

@ -7133,6 +7133,49 @@ class TestExtensionAttributes(ApicAimTestCase):
network_id=net_id).all()) network_id=net_id).all())
self.assertEqual([], db_masters) 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): def test_external_network_lifecycle(self):
session = db_api.get_reader_session() session = db_api.get_reader_session()
extn = extn_db.ExtensionDbMixin() extn = extn_db.ExtensionDbMixin()
@ -12776,3 +12819,340 @@ class TestUpdateRouterSubnet(ApicAimTestCase):
self._check_ip_in_cidr(router self._check_ip_in_cidr(router
['external_gateway_info']['external_fixed_ips'][0]['ip_address'], ['external_gateway_info']['external_fixed_ips'][0]['ip_address'],
fip_sub['cidr']) 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']))