summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEd Bak <ed.bak2@hp.com>2014-09-29 14:15:52 -0600
committerCarl Baldwin <carl.baldwin@hp.com>2014-10-07 14:19:16 +0000
commit75f34fbbd930a143ed2c4b868f33c117e467e98e (patch)
tree2b9092efa8e6182e75b3b45caf5c5a56d1eac974
parent205162f58050fcb94db53cd51b674d2093dfe700 (diff)
downloadneutron-75f34fbbd930a143ed2c4b868f33c117e467e98e.tar.gz
Don't fail when trying to unbind a router
If a router is already unbound from an l3 agent, don't fail. Log the condition and go on. This is harmless since it can happen due to a delete race condition between multiple neutron-server processes. One delete request can determine that it needs to unbind the router. A second process may also determine that it needs to unbind the router. The exception thrown will result in a port delete failure and cause nova to mark a deleted instance as ERROR. Change-Id: Ia667ea77a0a483deff8acfdcf90ca84cd3adf44f Closes-Bug: 1367892
-rw-r--r--neutron/plugins/ml2/plugin.py12
-rw-r--r--neutron/tests/unit/ml2/test_ml2_plugin.py25
2 files changed, 34 insertions, 3 deletions
diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py
index 422cbff86e..d744f19fe1 100644
--- a/neutron/plugins/ml2/plugin.py
+++ b/neutron/plugins/ml2/plugin.py
@@ -45,6 +45,7 @@ from neutron.db import quota_db # noqa
from neutron.db import securitygroups_rpc_base as sg_db_rpc
from neutron.extensions import allowedaddresspairs as addr_pair
from neutron.extensions import extra_dhcp_opt as edo_ext
+from neutron.extensions import l3agentscheduler
from neutron.extensions import portbindings
from neutron.extensions import providernet as provider
from neutron import manager
@@ -1019,9 +1020,14 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
if l3plugin:
l3plugin.notify_routers_updated(context, router_ids)
for router in removed_routers:
- l3plugin.remove_router_from_l3_agent(
- context, router['agent_id'], router['router_id'])
-
+ try:
+ l3plugin.remove_router_from_l3_agent(
+ context, router['agent_id'], router['router_id'])
+ except l3agentscheduler.RouterNotHostedByL3Agent:
+ # router may have been removed by another process
+ LOG.debug("Router %(id)s not hosted by L3 agent %(agent)s",
+ {'id': router['router_id'],
+ 'agent': router['agent_id']})
try:
# for both normal and DVR Interface ports, only one invocation of
# delete_port_postcommit. We use gather/scatter technique for DVR
diff --git a/neutron/tests/unit/ml2/test_ml2_plugin.py b/neutron/tests/unit/ml2/test_ml2_plugin.py
index 5cb6df44bc..0d43145d2c 100644
--- a/neutron/tests/unit/ml2/test_ml2_plugin.py
+++ b/neutron/tests/unit/ml2/test_ml2_plugin.py
@@ -25,6 +25,7 @@ from neutron.common import utils
from neutron import context
from neutron.db import db_base_plugin_v2 as base_plugin
from neutron.extensions import external_net as external_net
+from neutron.extensions import l3agentscheduler
from neutron.extensions import multiprovidernet as mpnet
from neutron.extensions import portbindings
from neutron.extensions import providernet as pnet
@@ -267,6 +268,30 @@ class TestMl2DvrPortsV2(TestMl2PortsV2):
self._test_delete_dvr_serviced_port(device_owner='compute:None',
floating_ip=True)
+ def test_delete_vm_port_namespace_already_deleted(self):
+ ns_to_delete = {'host': 'myhost',
+ 'agent_id': 'vm_l3_agent',
+ 'router_id': 'my_router'}
+
+ with contextlib.nested(
+ mock.patch.object(manager.NeutronManager,
+ 'get_service_plugins',
+ return_value=self.service_plugins),
+ self.port(do_delete=False,
+ device_owner='compute:None'),
+ mock.patch.object(self.l3plugin, 'dvr_deletens_if_no_port',
+ return_value=[ns_to_delete]),
+ mock.patch.object(self.l3plugin, 'remove_router_from_l3_agent',
+ side_effect=l3agentscheduler.RouterNotHostedByL3Agent(
+ router_id=ns_to_delete['router_id'],
+ agent_id=ns_to_delete['agent_id']))
+ ) as (get_service_plugin, port, dvr_delns_ifno_port,
+ remove_router_from_l3_agent):
+
+ self.plugin.delete_port(self.context, port['port']['id'])
+ remove_router_from_l3_agent.assert_called_once_with(self.context,
+ ns_to_delete['agent_id'], ns_to_delete['router_id'])
+
def test_delete_lbaas_vip_port(self):
self._test_delete_dvr_serviced_port(
device_owner=constants.DEVICE_OWNER_LOADBALANCER)