Fix bug in ipam_release_address

When user deallocates an ip address with the given PoolID,
if we have another cidrs with the same subnetpool prefix, at
the same time the give PoolID subnet had already deleted
before(for example: run fullstack test remove_network,
we firstly call DeleteNetwork, and then ReleaseAddress),
we will hit the exception described in LaunchPad.

This patch always check the subnetpool id if we get subnets.

Change-Id: Ia097c3613841619ed2beae2f9d56ec26bc530f69
Closes-Bug: #1644404
This commit is contained in:
Dongcan Ye 2016-11-24 14:25:55 +08:00 committed by Dongcan Ye
parent b5f25cd41e
commit ea1ba68a5f
2 changed files with 56 additions and 11 deletions

View File

@ -1462,17 +1462,15 @@ def ipam_release_address():
if not len(subnets):
app.logger.info(_LI("Subnet already deleted."))
return flask.jsonify(const.SCHEMA['SUCCESS'])
if len(subnets) > 1:
subnet = {}
for tmp_subnet in subnets:
if tmp_subnet['subnetpool_id'] == pool_id:
subnet = tmp_subnet
if not subnet:
raise exceptions.KuryrException(
("Subnet with cidr({0}) and pool {1}, does not "
"exist.").format(subnet_cidr, pool_id))
else:
subnet = subnets[0]
subnet = {}
for tmp_subnet in subnets:
if tmp_subnet['subnetpool_id'] == pool_id:
subnet = tmp_subnet
break
if not subnet:
app.logger.info(_LI("Subnet already deleted."))
return flask.jsonify(const.SCHEMA['SUCCESS'])
iface = ipaddress.ip_interface(six.text_type(rel_address))
rcvd_fixed_ips = []

View File

@ -627,3 +627,50 @@ class TestKuryrIpam(base.TestKuryrBase):
self.assertTrue(mock_list_ports.called)
mock_delete_port.assert_called_with(
fake_port['port']['id'])
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnets')
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnetpools')
def test_ipam_driver_release_address_with_one_subnet_deleted(
self, mock_list_subnetpools, mock_list_subnets):
"""Another unittest for release address.
For those two subnets have same cidrs, one of them had already deleted.
"""
# Faking list_subnetpools
fake_kuryr_subnetpool_id = uuidutils.generate_uuid()
fake_name = str('-'.join(['kuryrPool', FAKE_IP4_CIDR]))
kuryr_subnetpools = self._get_fake_v4_subnetpools(
fake_kuryr_subnetpool_id, prefixes=[FAKE_IP4_CIDR], name=fake_name)
mock_list_subnetpools.return_value = kuryr_subnetpools
# Faking list_subnets
docker_network_id = uuidutils.generate_uuid()
docker_endpoint_id = uuidutils.generate_uuid()
docker_network_id = uuidutils.generate_uuid()
subnet_v4_id = uuidutils.generate_uuid()
# Make two subnets have different subnetpool id
another_fake_kuryr_subnetpool_id = uuidutils.generate_uuid()
fake_v4_subnet = self._get_fake_v4_subnet(
docker_network_id, docker_endpoint_id, subnet_v4_id,
subnetpool_id=another_fake_kuryr_subnetpool_id,
cidr=FAKE_IP4_CIDR)
fake_subnet_response = {
'subnets': [
fake_v4_subnet['subnet']
]
}
mock_list_subnets.return_value = fake_subnet_response
fake_ip4 = '10.0.0.5'
fake_request = {
'PoolID': fake_kuryr_subnetpool_id,
'Address': fake_ip4
}
response = self.app.post('/IpamDriver.ReleaseAddress',
content_type='application/json',
data=jsonutils.dumps(fake_request))
self.assertEqual(200, response.status_code)
mock_list_subnetpools.assert_called_with(id=fake_kuryr_subnetpool_id)
mock_list_subnets.assert_called_with(cidr=FAKE_IP4_CIDR)