Merge "Fetch router port subnets in bulk" into stable/mitaka
This commit is contained in:
commit
6ca8ac762c
|
@ -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']}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue