From 55c8f9e165e5720b8f187251c1899525e4f5262e Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Wed, 10 Jul 2013 18:35:11 +0900 Subject: [PATCH] quantum_adapter: race between ovs port deletion and plugin port deletion The order between the notification of ovs port deletion via OVSDB protocol and the notification network id/port deletion via REST from quantum plugin isn't deterministic. So when ovs port is deleted, the corresponding network id may or may not exist. The code wrongly assumed the order, so resulted in the following exception. When ovs port is deleted and the corresponding network id isn't find, just ignore the exception. > (19257) accepted ('127.0.0.1', 36841) > 127.0.0.1 - - [19/Jun/2013 11:24:25] "DELETE /v1.0/tunnels/networks/8179bb70-a63f-4c74-a82e-a21f3c275c9a/key HTTP/1.1" 200 115 0.000383 > hub: uncaught exception: Traceback (most recent call last): > File "/opt/stack/ryu/ryu/lib/hub.py", line 50, in _launch > func(*args, **kwargs) > File "/opt/stack/ryu/ryu/base/app_manager.py", line 104, in _event_loop > handler(ev) > File "/opt/stack/ryu/ryu/app/quantum_adapter.py", line 368, in > port_del_handler > self._port_handler(ev.dp.id, port.port_no, name, False) > File "/opt/stack/ryu/ryu/app/quantum_adapter.py", line 336, in _port_handler > ovs_switch.update_port(port_no, port_name, add) > File "/opt/stack/ryu/ryu/app/quantum_adapter.py", line 279, in update_port > self._update_vif_port(old_port, add=False) > File "/opt/stack/ryu/ryu/app/quantum_adapter.py", line 194, in > _update_vif_port > self.network_api.remove_port(network_id, self.dpid, port.ofport) > File "/opt/stack/ryu/ryu/controller/network.py", line 368, in remove_port > self.networks.remove(network_id, dpid, port_no) > File "/opt/stack/ryu/ryu/controller/network.py", line 119, in remove > raise NetworkNotFound(network_id=network_id) > NetworkNotFound: no such network id 8179bb70-a63f-4c74-a82e-a21f3c275c9a Signed-off-by: Isaku Yamahata Signed-off-by: FUJITA Tomonori --- ryu/app/quantum_adapter.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/ryu/app/quantum_adapter.py b/ryu/app/quantum_adapter.py index 464937ea..b6ea8b80 100644 --- a/ryu/app/quantum_adapter.py +++ b/ryu/app/quantum_adapter.py @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import traceback from oslo.config import cfg try: @@ -36,6 +37,7 @@ from ryu.controller import (conf_switch, dpset, handler, network) +from ryu import exception as ryu_exc from ryu.lib import dpid as dpid_lib from ryu.lib import mac as mac_lib from ryu.lib import quantum_ifaces @@ -189,6 +191,11 @@ class OVSSwitch(object): self.dpid, port.ofport) def _update_vif_port(self, port, add=True): + # When ovs port is updated, the corresponding network id may or + # may not exist because the order between the notification of + # ovs port deletion via OVSDB protocol and the notification + # network id/port deletion via REST from quantum plugin + # isn't deterministic. self.logger.debug("_update_vif_port: %s %s", port, add) iface_id = port.ext_ids.get('iface-id') if iface_id is None: @@ -200,7 +207,11 @@ class OVSSwitch(object): return if not add: - self.network_api.remove_port(network_id, self.dpid, port.ofport) + try: + self.network_api.remove_port(network_id, + self.dpid, port.ofport) + except (network.NetworkNotFound, ryu_exc.PortNotFound) as e: + self.logger.debug('remove_port %s', traceback.format_exc()) ports = self.ifaces.get_key(iface_id, QuantumIfaces.KEY_PORTS) other_ovs_ports = None for p in ports: @@ -232,12 +243,16 @@ class OVSSwitch(object): return # update {network, port, mac} - self.network_api.update_network(network_id) - self.network_api.update_port(network_id, self.dpid, port.ofport) - mac = port.ext_ids.get('attached-mac') - if mac: - self.network_api.update_mac(network_id, self.dpid, port.ofport, - mac_lib.haddr_to_bin(mac)) + try: + self.network_api.update_network(network_id) + self.network_api.update_port(network_id, self.dpid, port.ofport) + mac = port.ext_ids.get('attached-mac') + if mac: + self.network_api.update_mac(network_id, self.dpid, port.ofport, + mac_lib.haddr_to_bin(mac)) + except (network.NetworkNotFound, ryu_exc.PortNotFound) as e: + self.logger.debug('update network/port/mac %s', + traceback.format_exc()) def update_port(self, port_no, port_name, add): self.logger.debug('update_port port_no %d %s %s', port_no, port_name,