Merge "Fetch router port subnets in bulk" into stable/mitaka

This commit is contained in:
Jenkins 2016-07-16 01:56:51 +00:00 committed by Gerrit Code Review
commit 6ca8ac762c
2 changed files with 65 additions and 55 deletions

View File

@ -430,10 +430,8 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
# raise the underlying exception # raise the underlying exception
raise e.errors[0].error raise e.errors[0].error
for subnet in subnets: self._check_for_dup_router_subnets(context, router,
self._check_for_dup_router_subnet(context, router, new_network_id, subnets)
new_network_id, subnet['id'],
subnet['cidr'])
self._create_router_gw_port(context, router, self._create_router_gw_port(context, router,
new_network_id, ext_ips) new_network_id, ext_ips)
registry.notify(resources.ROUTER_GATEWAY, registry.notify(resources.ROUTER_GATEWAY,
@ -532,38 +530,42 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
return self._get_collection_count(context, Router, return self._get_collection_count(context, Router,
filters=filters) filters=filters)
def _check_for_dup_router_subnet(self, context, router, def _check_for_dup_router_subnets(self, context, router,
network_id, subnet_id, subnet_cidr): network_id, new_subnets):
try: # It's possible these ports are on the same network, but
# It's possible these ports are on the same network, but # different subnets.
# different subnets. new_subnet_ids = {s['id'] for s in new_subnets}
new_ipnet = netaddr.IPNetwork(subnet_cidr) router_subnets = []
for p in (rp.port for rp in router.attached_ports): for p in (rp.port for rp in router.attached_ports):
for ip in p['fixed_ips']: for ip in p['fixed_ips']:
if ip['subnet_id'] == subnet_id: if ip['subnet_id'] in new_subnet_ids:
msg = (_("Router already has a port on subnet %s") msg = (_("Router already has a port on subnet %s")
% subnet_id) % ip['subnet_id'])
raise n_exc.BadRequest(resource='router', msg=msg) raise n_exc.BadRequest(resource='router', msg=msg)
# Ignore temporary Prefix Delegation CIDRs router_subnets.append(ip['subnet_id'])
if subnet_cidr == l3_constants.PROVISIONAL_IPV6_PD_PREFIX: # Ignore temporary Prefix Delegation CIDRs
continue new_subnets = [s for s in new_subnets
sub_id = ip['subnet_id'] if s['cidr'] != l3_constants.PROVISIONAL_IPV6_PD_PREFIX]
cidr = self._core_plugin.get_subnet(context.elevated(), id_filter = {'id': router_subnets}
sub_id)['cidr'] subnets = self._core_plugin.get_subnets(context.elevated(),
ipnet = netaddr.IPNetwork(cidr) filters=id_filter)
match1 = netaddr.all_matching_cidrs(new_ipnet, [cidr]) for sub in subnets:
match2 = netaddr.all_matching_cidrs(ipnet, [subnet_cidr]) cidr = sub['cidr']
if match1 or match2: ipnet = netaddr.IPNetwork(cidr)
data = {'subnet_cidr': subnet_cidr, for s in new_subnets:
'subnet_id': subnet_id, new_cidr = s['cidr']
'cidr': cidr, new_ipnet = netaddr.IPNetwork(new_cidr)
'sub_id': sub_id} match1 = netaddr.all_matching_cidrs(new_ipnet, [cidr])
msg = (_("Cidr %(subnet_cidr)s of subnet " match2 = netaddr.all_matching_cidrs(ipnet, [new_cidr])
"%(subnet_id)s overlaps with cidr %(cidr)s " if match1 or match2:
"of subnet %(sub_id)s") % data) data = {'subnet_cidr': new_cidr,
raise n_exc.BadRequest(resource='router', msg=msg) 'subnet_id': s['id'],
except exc.NoResultFound: 'cidr': cidr,
pass 'sub_id': sub['id']}
msg = (_("Cidr %(subnet_cidr)s of subnet "
"%(subnet_id)s overlaps with cidr %(cidr)s "
"of subnet %(sub_id)s") % data)
raise n_exc.BadRequest(resource='router', msg=msg)
def _get_device_owner(self, context, router=None): def _get_device_owner(self, context, router=None):
"""Get device_owner for the specified router.""" """Get device_owner for the specified router."""
@ -631,10 +633,11 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
subnet = self._core_plugin.get_subnet(context, subnet = self._core_plugin.get_subnet(context,
fixed_ip['subnet_id']) fixed_ip['subnet_id'])
subnets.append(subnet) subnets.append(subnet)
self._check_for_dup_router_subnet(context, router,
port['network_id'], if subnets:
subnet['id'], self._check_for_dup_router_subnets(context, router,
subnet['cidr']) port['network_id'],
subnets)
# Keep the restriction against multiple IPv4 subnets # Keep the restriction against multiple IPv4 subnets
if len([s for s in subnets if s['ip_version'] == 4]) > 1: if len([s for s in subnets if s['ip_version'] == 4]) > 1:
@ -665,10 +668,8 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
'external router cannot be added to Neutron Router.') % 'external router cannot be added to Neutron Router.') %
subnet['id']) subnet['id'])
raise n_exc.BadRequest(resource='router', msg=msg) raise n_exc.BadRequest(resource='router', msg=msg)
self._check_for_dup_router_subnet(context, router, self._check_for_dup_router_subnets(context, router,
subnet['network_id'], subnet['network_id'], [subnet])
subnet_id,
subnet['cidr'])
fixed_ip = {'ip_address': subnet['gateway_ip'], fixed_ip = {'ip_address': subnet['gateway_ip'],
'subnet_id': subnet['id']} 'subnet_id': subnet['id']}

View File

@ -1365,40 +1365,49 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
def test_router_add_interface_dup_subnet2_returns_400(self): def test_router_add_interface_dup_subnet2_returns_400(self):
with self.router() as r: with self.router() as r:
with self.subnet() as s: with self.subnet() as s1, self.subnet(cidr='1.0.0.0/24') as s2:
with self.port(subnet=s) as p1: with self.port(subnet=s1) as p1, self.port(subnet=s2) as p2:
with self.port(subnet=s) as p2: with self.port(subnet=s1) as p3:
for p in [p1, p2]:
self._router_interface_action('add',
r['router']['id'],
None,
p['port']['id'])
self._router_interface_action('add', self._router_interface_action('add',
r['router']['id'], r['router']['id'],
None, None,
p1['port']['id']) p3['port']['id'],
self._router_interface_action('add',
r['router']['id'],
None,
p2['port']['id'],
expected_code=exc. expected_code=exc.
HTTPBadRequest.code) HTTPBadRequest.code)
def test_router_add_interface_overlapped_cidr_returns_400(self): def test_router_add_interface_overlapped_cidr_returns_400(self):
with self.router() as r: with self.router() as r:
with self.subnet(cidr='10.0.1.0/24') as s1: with self.subnet(cidr='10.0.1.0/24') as s1, self.subnet(
cidr='10.0.2.0/24') as s2:
self._router_interface_action('add', self._router_interface_action('add',
r['router']['id'], r['router']['id'],
s1['subnet']['id'], s1['subnet']['id'],
None) None)
self._router_interface_action('add',
r['router']['id'],
s2['subnet']['id'],
None)
def try_overlapped_cidr(cidr): def try_overlapped_cidr(cidr):
with self.subnet(cidr=cidr) as s2: with self.subnet(cidr=cidr) as s3:
self._router_interface_action('add', self._router_interface_action('add',
r['router']['id'], r['router']['id'],
s2['subnet']['id'], s3['subnet']['id'],
None, None,
expected_code=exc. expected_code=exc.
HTTPBadRequest.code) HTTPBadRequest.code)
# another subnet with same cidr # another subnet with same cidr
try_overlapped_cidr('10.0.1.0/24') try_overlapped_cidr('10.0.1.0/24')
try_overlapped_cidr('10.0.2.0/24')
# another subnet with overlapped cidr including s1 # another subnet with overlapped cidr including s1
try_overlapped_cidr('10.0.0.0/16') try_overlapped_cidr('10.0.0.0/16')
# another subnet with overlapped cidr including s2
try_overlapped_cidr('10.0.2.128/28')
def test_router_add_interface_no_data_returns_400(self): def test_router_add_interface_no_data_returns_400(self):
with self.router() as r: with self.router() as r: