Only restrict gateway_ip change for router ports
The subnet update code was restricting gateway_ip changes if the existing gateway IP belonged to a Neutron port. This was implemented because changing the gateway will break all floating IP addresses if the gateway is a Neutron router. However, this restriction makes it possible to get a subnet stuck to an IP address that belongs to another port (e.g. a compute port) so the user has to either delete the port or change it's IP, both of which are disruptive. This patch just changes the restriction so it only prevents gateway IP changes if the current gateway IP belongs to a router. This preserves the intent of the original change while allowing the subnet to be updated off of IP addresses that belong to normal ports. Change-Id: I4691505ef2fad6019e0d2fd80ff1b9e157662a29 Closes-bug: #1532004
This commit is contained in:
parent
df4966081a
commit
30dab936e6
|
@ -466,10 +466,12 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
|
|||
# a subnet-update and a router-interface-add operation are
|
||||
# executed concurrently
|
||||
if cur_subnet and not ipv6_utils.is_ipv6_pd_enabled(s):
|
||||
alloc_qry = context.session.query(models_v2.IPAllocation)
|
||||
allocated = alloc_qry.filter_by(
|
||||
ip_address=cur_subnet['gateway_ip'],
|
||||
subnet_id=cur_subnet['id']).first()
|
||||
ipal = models_v2.IPAllocation
|
||||
alloc_qry = context.session.query(ipal)
|
||||
alloc_qry = alloc_qry.join("port", "routerport")
|
||||
allocated = alloc_qry.filter(
|
||||
ipal.ip_address == cur_subnet['gateway_ip'],
|
||||
ipal.subnet_id == cur_subnet['id']).first()
|
||||
if allocated and allocated['port_id']:
|
||||
raise n_exc.GatewayIpInUse(
|
||||
ip_address=cur_subnet['gateway_ip'],
|
||||
|
|
|
@ -4177,22 +4177,37 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
|
|||
self.assertEqual(webob.exc.HTTPClientError.code,
|
||||
res.status_int)
|
||||
|
||||
def test_update_subnet_gw_ip_in_use_returns_409(self):
|
||||
def test_update_subnet_gw_ip_in_use_by_router_returns_409(self):
|
||||
with self.network() as network:
|
||||
with self.subnet(
|
||||
network=network,
|
||||
allocation_pools=[{'start': '10.0.0.100',
|
||||
'end': '10.0.0.253'}]) as subnet:
|
||||
subnet_data = subnet['subnet']
|
||||
with self.subnet(network=network,
|
||||
allocation_pools=[{'start': '10.0.0.2',
|
||||
'end': '10.0.0.8'}]) as subnet:
|
||||
s = subnet['subnet']
|
||||
with self.port(
|
||||
subnet=subnet,
|
||||
fixed_ips=[{'subnet_id': subnet_data['id'],
|
||||
'ip_address': subnet_data['gateway_ip']}]):
|
||||
subnet=subnet, fixed_ips=[{'subnet_id': s['id'],
|
||||
'ip_address': s['gateway_ip']}]
|
||||
) as port:
|
||||
# this protection only applies to router ports so we need
|
||||
# to make this port belong to a router
|
||||
ctx = context.get_admin_context()
|
||||
with ctx.session.begin():
|
||||
router = l3_db.Router()
|
||||
ctx.session.add(router)
|
||||
with ctx.session.begin():
|
||||
rp = l3_db.RouterPort(router_id=router.id,
|
||||
port_id=port['port']['id'])
|
||||
ctx.session.add(rp)
|
||||
data = {'subnet': {'gateway_ip': '10.0.0.99'}}
|
||||
req = self.new_update_request('subnets', data,
|
||||
subnet_data['id'])
|
||||
s['id'])
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(409, res.status_int)
|
||||
# should work fine if it's not a router port
|
||||
with ctx.session.begin():
|
||||
ctx.session.delete(rp)
|
||||
ctx.session.delete(router)
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(res.status_int, 200)
|
||||
|
||||
def test_update_subnet_inconsistent_ipv4_gatewayv6(self):
|
||||
with self.network() as network:
|
||||
|
|
Loading…
Reference in New Issue