diff --git a/neutron/db/l3_hamode_db.py b/neutron/db/l3_hamode_db.py index 076ccc1f0e1..85a4f93e73b 100644 --- a/neutron/db/l3_hamode_db.py +++ b/neutron/db/l3_hamode_db.py @@ -468,21 +468,31 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin): self._delete_vr_id_allocation( context, ha_network, router_db.extra_attributes.ha_vr_id) self._delete_ha_interfaces(context, router_db.id) - try: + + # In case that create HA router failed because of the failure + # in HA network creation. So here put this deleting HA network + # procedure under 'if ha_network' block. if not self._ha_routers_present(context, router_db.tenant_id): - self._delete_ha_network(context, ha_network) - LOG.info(_LI("HA network %(network)s was deleted as " - "no HA routers are present in tenant " - "%(tenant)s."), - {'network': ha_network.network_id, - 'tenant': router_db.tenant_id}) - except n_exc.NetworkNotFound: - LOG.debug("HA network %s was already deleted.", - ha_network.network_id) - except sa.exc.InvalidRequestError: - LOG.info(_LI("HA network %s can not be deleted."), - ha_network.network_id) + try: + self._delete_ha_network(context, ha_network) + except (n_exc.NetworkNotFound, + orm.exc.ObjectDeletedError): + LOG.debug( + "HA network for tenant %s was already deleted.", + router_db.tenant_id) + except sa.exc.InvalidRequestError: + LOG.info(_LI("HA network %s can not be deleted."), + ha_network.network_id) + except n_exc.NetworkInUse: + LOG.debug("HA network %s is still in use.", + ha_network.network_id) + else: + LOG.info(_LI("HA network %(network)s was deleted as " + "no HA routers are present in tenant " + "%(tenant)s."), + {'network': ha_network.network_id, + 'tenant': router_db.tenant_id}) def get_ha_router_port_bindings(self, context, router_ids, host=None): if not router_ids: diff --git a/neutron/tests/unit/db/test_l3_hamode_db.py b/neutron/tests/unit/db/test_l3_hamode_db.py index af05a0c8e11..659dbcc3314 100644 --- a/neutron/tests/unit/db/test_l3_hamode_db.py +++ b/neutron/tests/unit/db/test_l3_hamode_db.py @@ -18,10 +18,12 @@ from oslo_config import cfg from oslo_utils import timeutils from oslo_utils import uuidutils import sqlalchemy as sa +from sqlalchemy import orm from neutron.api.rpc.handlers import l3_rpc from neutron.api.v2 import attributes from neutron.common import constants +from neutron.common import exceptions as n_exc from neutron import context from neutron.db import agents_db from neutron.db import common_db_mixin @@ -574,23 +576,53 @@ class L3HATestCase(L3HATestFramework): self.assertNotIn('HA network tenant %s' % router1['tenant_id'], nets_after) - def test_ha_network_is_not_deleted_if_another_ha_router_is_created(self): - # If another router was created during deletion of current router, - # _delete_ha_network will fail with InvalidRequestError. Check that HA - # network won't be deleted. + def _test_ha_network_is_not_deleted_raise_exception(self, exception): router1 = self._create_router() nets_before = [net['name'] for net in self.core_plugin.get_networks(self.admin_ctx)] self.assertIn('HA network tenant %s' % router1['tenant_id'], nets_before) with mock.patch.object(self.plugin, '_delete_ha_network', - side_effect=sa.exc.InvalidRequestError): + side_effect=exception): self.plugin.delete_router(self.admin_ctx, router1['id']) nets_after = [net['name'] for net in self.core_plugin.get_networks(self.admin_ctx)] self.assertIn('HA network tenant %s' % router1['tenant_id'], nets_after) + def test_ha_network_is_not_deleted_if_another_ha_router_is_created(self): + # If another router was created during deletion of current router, + # _delete_ha_network will fail with InvalidRequestError. Check that HA + # network won't be deleted. + self._test_ha_network_is_not_deleted_raise_exception( + sa.exc.InvalidRequestError) + + def test_ha_network_is_not_deleted_if_network_in_use(self): + self._test_ha_network_is_not_deleted_raise_exception( + n_exc.NetworkInUse(net_id="foo_net_id")) + + def test_ha_network_is_not_deleted_if_db_deleted_error(self): + self._test_ha_network_is_not_deleted_raise_exception( + orm.exc.ObjectDeletedError(None)) + + def test_ha_router_create_failed_no_ha_network_delete(self): + tenant_id = "foo_tenant_id" + nets_before = self.core_plugin.get_networks(self.admin_ctx) + self.assertNotIn('HA network tenant %s' % tenant_id, + nets_before) + + # Unable to create HA network + with mock.patch.object(self.core_plugin, 'create_network', + side_effect=n_exc.NoNetworkAvailable): + self.assertRaises(n_exc.NoNetworkAvailable, + self._create_router, + True, + tenant_id) + nets_after = self.core_plugin.get_networks(self.admin_ctx) + self.assertEqual(nets_before, nets_after) + self.assertNotIn('HA network tenant %s' % tenant_id, + nets_after) + class L3HAModeDbTestCase(L3HATestFramework):