Adds test for deleting external network with floatingIPs
The attached neutron bug causes server to hang when deleting external network
that still has a floating IP in it.
This test should recreate the bug, and verify it is fixed
Closes-Bug: #1374573
Change-Id: Ib7d8dcbb4485e87a49cb008ace37c81f6b06a32c
diff --git a/tempest/api/network/admin/test_external_network_extension.py b/tempest/api/network/admin/test_external_network_extension.py
index 2e58dae..738e498 100644
--- a/tempest/api/network/admin/test_external_network_extension.py
+++ b/tempest/api/network/admin/test_external_network_extension.py
@@ -12,6 +12,7 @@
from tempest.api.network import base
from tempest.common.utils import data_utils
+from tempest import exceptions
class ExternalNetworksTestJSON(base.BaseAdminNetworkTest):
@@ -31,6 +32,26 @@
self.addCleanup(self.admin_client.delete_network, network['id'])
return network
+ def _try_delete_resource(self, delete_callable, *args, **kwargs):
+ """Cleanup resources in case of test-failure
+
+ Some resources should be explicitly deleted by the test. if the test
+ fails, these resources remain.
+ If the test failed to delete a resource, this method will execute
+ the appropriate delete methods. Otherwise, the method ignores NotFound
+ exceptions thrown for resources that were correctly deleted by the
+ test.
+
+ :param delete_callable: delete method
+ :param args: arguments for delete method
+ :param kwargs: keyword arguments for delete method
+ """
+ try:
+ delete_callable(*args, **kwargs)
+ # if resource is not found, this means it was deleted in the test
+ except exceptions.NotFound:
+ pass
+
def test_create_external_network(self):
# Create a network as an admin user specifying the
# external network extension attribute
@@ -84,6 +105,41 @@
self.assertEqual(self.network['id'], show_net['id'])
self.assertFalse(show_net['router:external'])
+ def test_delete_external_networks_with_floating_ip(self):
+ """Verifies external network can be deleted while still holding
+ (unassociated) floating IPs
+
+ """
+ # Set cls.client to admin to use base.create_subnet()
+ client = self.admin_client
+ _, body = client.create_network(**{'router:external': True})
+ external_network = body['network']
+ self.addCleanup(self._try_delete_resource,
+ client.delete_network,
+ external_network['id'])
+ subnet = self.create_subnet(external_network, client=client)
+ _, body = client.create_floatingip(
+ floating_network_id=external_network['id'])
+ created_floating_ip = body['floatingip']
+ self.addCleanup(self._try_delete_resource,
+ client.delete_floatingip,
+ created_floating_ip['id'])
+ _, floatingip_list = client.list_floatingips(
+ network=external_network['id'])
+ self.assertIn(created_floating_ip['id'],
+ (f['id'] for f in floatingip_list['floatingips']))
+ client.delete_network(external_network['id'])
+ # Verifies floating ip is deleted
+ _, floatingip_list = client.list_floatingips()
+ self.assertNotIn(created_floating_ip['id'],
+ (f['id'] for f in floatingip_list['floatingips']))
+ # Verifies subnet is deleted
+ _, subnet_list = client.list_subnets()
+ self.assertNotIn(subnet['id'],
+ (s['id'] for s in subnet_list))
+ # Removes subnet from the cleanup list
+ self.subnets.remove(subnet)
+
class ExternalNetworksTestXML(ExternalNetworksTestJSON):
_interface = 'xml'
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 7ba68f7..7cd18cd 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -156,8 +156,13 @@
@classmethod
def create_subnet(cls, network, gateway='', cidr=None, mask_bits=None,
- ip_version=None, **kwargs):
+ ip_version=None, client=None, **kwargs):
"""Wrapper utility that returns a test subnet."""
+
+ # allow tests to use admin client
+ if not client:
+ client = cls.client
+
# The cidr and mask_bits depend on the ip version.
ip_version = ip_version if ip_version is not None else cls._ip_version
gateway_not_set = gateway == ''
@@ -175,7 +180,7 @@
else:
gateway_ip = gateway
try:
- resp, body = cls.client.create_subnet(
+ resp, body = client.create_subnet(
network_id=network['id'],
cidr=str(subnet_cidr),
ip_version=ip_version,