from neutron.common import exceptions as n_exc
from neutron.common import utils as n_utils
from neutron.db import agents_db
+from neutron.db import l3_attrs_db
+from neutron.db import l3_db
from neutron.db import l3_dvr_db
from neutron.db import model_base
from neutron.db import models_v2
return router_db
+ def _delete_ha_network(self, context, net):
+ admin_ctx = context.elevated()
+ self._core_plugin.delete_network(admin_ctx, net.network_id)
+
+ def _ha_routers_present(self, context, tenant_id):
+ ha = True
+ routers = context.session.query(l3_db.Router).filter(
+ l3_db.Router.tenant_id == tenant_id).subquery()
+ ha_routers = context.session.query(
+ l3_attrs_db.RouterExtraAttributes).join(
+ routers,
+ l3_attrs_db.RouterExtraAttributes.router_id == routers.c.id
+ ).filter(l3_attrs_db.RouterExtraAttributes.ha == ha).first()
+ return ha_routers is not None
+
def delete_router(self, context, id):
router_db = self._get_router(context, id)
super(L3_HA_NAT_db_mixin, self).delete_router(context, id)
self._delete_vr_id_allocation(
context, ha_network, router_db.extra_attributes.ha_vr_id)
self._delete_ha_interfaces(context, router_db.id)
+ try:
+ 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)
def _unbind_ha_router(self, context, router_id):
for agent in self.get_l3_agents_hosting_routers(context, [router_id]):
import mock
from oslo_config import cfg
from oslo_utils import uuidutils
+import sqlalchemy as sa
from neutron.api.rpc.handlers import l3_rpc
from neutron.api.v2 import attributes
self.plugin.get_number_of_agents_for_scheduling,
self.admin_ctx)
+ def test_ha_network_deleted_if_no_ha_router_present_two_tenants(self):
+ # Create two routers in different tenants.
+ router1 = self._create_router()
+ router2 = self._create_router(tenant_id='tenant2')
+ nets_before = [net['name'] for net in
+ self.core_plugin.get_networks(self.admin_ctx)]
+ # Check that HA networks created for each tenant
+ self.assertIn('HA network tenant %s' % router1['tenant_id'],
+ nets_before)
+ self.assertIn('HA network tenant %s' % router2['tenant_id'],
+ nets_before)
+ # Delete router1
+ self.plugin.delete_router(self.admin_ctx, router1['id'])
+ nets_after = [net['name'] for net in
+ self.core_plugin.get_networks(self.admin_ctx)]
+ # Check that HA network for tenant1 is deleted and for tenant2 is not.
+ self.assertNotIn('HA network tenant %s' % router1['tenant_id'],
+ nets_after)
+ self.assertIn('HA network tenant %s' % router2['tenant_id'],
+ nets_after)
+
+ def test_ha_network_is_not_delete_if_ha_router_is_present(self):
+ # Create 2 routers in one tenant and check if one is deleted, HA
+ # network still exists.
+ router1 = self._create_router()
+ router2 = 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)
+ self.plugin.delete_router(self.admin_ctx, router2['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_delete_ha_and_non_ha_router(self):
+ # Create HA and non-HA router. Check after deletion HA router HA
+ # network is deleted.
+ router1 = self._create_router(ha=False)
+ router2 = 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)
+ self.plugin.delete_router(self.admin_ctx, router2['id'])
+ nets_after = [net['name'] for net in
+ self.core_plugin.get_networks(self.admin_ctx)]
+ 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.
+ 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):
+ 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)
+
class L3HAModeDbTestCase(L3HATestFramework):