From 8370483edcac525d88cc97855f0f72901c49034f Mon Sep 17 00:00:00 2001 From: Jakub Libosvar Date: Wed, 6 Dec 2017 16:02:28 +0000 Subject: [PATCH] api: Add HA router delete test The test makes sure deleting router does not influence any HA network segmentation details being wiped out. Change-Id: Ib12986c25eda25970445169310c7c0334d6da49c Related-bug: #1732543 --- .../api/admin/test_routers_ha.py | 29 +++++++++++++++++++ neutron_tempest_plugin/api/base.py | 9 +++--- neutron_tempest_plugin/api/base_routers.py | 17 +++++++++-- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/neutron_tempest_plugin/api/admin/test_routers_ha.py b/neutron_tempest_plugin/api/admin/test_routers_ha.py index fafe2097..da3b9af9 100644 --- a/neutron_tempest_plugin/api/admin/test_routers_ha.py +++ b/neutron_tempest_plugin/api/admin/test_routers_ha.py @@ -10,6 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. +from tempest.common import utils as tutils from tempest.lib.common.utils import data_utils from tempest.lib import decorators @@ -19,6 +20,7 @@ from neutron_tempest_plugin.api import base_routers as base class RoutersTestHA(base.BaseRouterTest): required_extensions = ['router', 'l3-ha'] + HA_NETWORK_NAME_TEMPL = "HA network tenant %s" @classmethod def resource_setup(cls): @@ -90,3 +92,30 @@ class RoutersTestHA(base.BaseRouterTest): router = self.admin_client.update_router(router['router']['id'], ha=True) self.assertTrue(router['router']['ha']) + + @decorators.idempotent_id('0d8c0c8f-3809-4acc-a2c8-e0941333ff6c') + @tutils.requires_ext(extension="provider", service="network") + def test_delete_ha_router_keeps_ha_network_segment_data(self): + """Test deleting an HA router keeps correct segment data for network. + + Each tenant with HA router has an HA network. The HA network is a + normal tenant network with segmentation data like type (vxlan) and + segmenation id. This test makes sure that after an HA router is + deleted, those segmentation data are kept in HA network. This tests + regression of https://bugs.launchpad.net/neutron/+bug/1732543. + """ + for i in range(2): + router = self._create_admin_router( + data_utils.rand_name('router%d' % i), + ha=True) + ha_net_name = self.HA_NETWORK_NAME_TEMPL % router['tenant_id'] + ha_network_pre_delete = self.admin_client.list_networks( + name=ha_net_name)['networks'][0] + segmentation_id = ha_network_pre_delete['provider:segmentation_id'] + self._delete_router(router['id'], self.admin_client) + + ha_network_post_delete = self.admin_client.show_network( + ha_network_pre_delete['id'])['network'] + self.assertEqual( + ha_network_post_delete['provider:segmentation_id'], + segmentation_id) diff --git a/neutron_tempest_plugin/api/base.py b/neutron_tempest_plugin/api/base.py index 8db5108c..ec66818a 100644 --- a/neutron_tempest_plugin/api/base.py +++ b/neutron_tempest_plugin/api/base.py @@ -412,17 +412,18 @@ class BaseNetworkTest(test.BaseTestCase): return qos_rule @classmethod - def delete_router(cls, router): - body = cls.client.list_router_interfaces(router['id']) + def delete_router(cls, router, client=None): + client = client or cls.client + body = client.list_router_interfaces(router['id']) interfaces = [port for port in body['ports'] if port['device_owner'] in const.ROUTER_INTERFACE_OWNERS] for i in interfaces: try: - cls.client.remove_router_interface_with_subnet_id( + client.remove_router_interface_with_subnet_id( router['id'], i['fixed_ips'][0]['subnet_id']) except lib_exc.NotFound: pass - cls.client.delete_router(router['id']) + client.delete_router(router['id']) @classmethod def create_address_scope(cls, name, is_admin=False, **kwargs): diff --git a/neutron_tempest_plugin/api/base_routers.py b/neutron_tempest_plugin/api/base_routers.py index c8d37835..52db742d 100644 --- a/neutron_tempest_plugin/api/base_routers.py +++ b/neutron_tempest_plugin/api/base_routers.py @@ -13,6 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. +from tempest.lib import exceptions + from neutron_tempest_plugin.api import base @@ -21,9 +23,12 @@ class BaseRouterTest(base.BaseAdminNetworkTest): # as some router operations, such as enabling or disabling SNAT # require admin credentials by default - def _cleanup_router(self, router): - self.delete_router(router) - self.routers.remove(router) + def _cleanup_router(self, router, client=None): + try: + self.delete_router(router, client) + self.routers.remove(router) + except exceptions.NotFound: + pass def _create_router(self, name, admin_state_up=False, external_network_id=None, enable_snat=None): @@ -33,6 +38,12 @@ class BaseRouterTest(base.BaseAdminNetworkTest): self.addCleanup(self._cleanup_router, router) return router + def _create_admin_router(self, *args, **kwargs): + router = self.create_admin_router(*args, **kwargs) + self.addCleanup( + self._cleanup_router, router, self.os_admin.network_client) + return router + def _delete_router(self, router_id, network_client=None): client = network_client or self.client client.delete_router(router_id)