Topology: move filtering to ovsdb monitor

Topology app keeps a local ovs port cache because it does not want all
port updates to take effect. In particular, events with missing data
(ofport, type). Moving this logic to vswitch_impl because it makes a lot
of sense to hold off those events even for apps that consume OvsPorts.

Partial-Bug: #1737339
Change-Id: I0bc8053d6fb3ed277028cf6bce9c6a0269e601af
This commit is contained in:
Dima Kuznetsov 2017-11-13 10:05:04 +02:00
parent a77ba0de6a
commit adadf17948
4 changed files with 88 additions and 28 deletions

View File

@ -64,9 +64,6 @@ class Topology(object):
@return : None
"""
LOG.info("Ovs port updated: %s", ovs_port)
# ignore port that misses some parameters
if not self._check_ovs_port_integrity(ovs_port):
return
port_id = ovs_port.id
old_port = self.ovs_ports.get(port_id)
if old_port is None:
@ -122,24 +119,6 @@ class Topology(object):
finally:
del self.ovs_ports[ovs_port.id]
def _check_ovs_port_integrity(self, ovs_port):
"""
There are some cases that some para of ovs port is missing
then the event will be discarded
"""
ofport = ovs_port.ofport
port_type = ovs_port.type
if (ofport is None) or (ofport < 0) or (port_type is None):
return False
if (port_type == constants.OVS_VM_INTERFACE and
ovs_port.lport is None):
return False
return True
def _tunnel_port_added(self, ovs_port):
self._tunnel_port_updated(ovs_port)

View File

@ -72,7 +72,7 @@ _HANDLED_INTERFACE_TYPES = (
)
def _is_ovsport_update_valid(ovsport):
def _is_ovsport_update_valid(action, ovsport):
if ovsport.name == cfg.CONF.df_metadata.metadata_interface:
return True
@ -82,6 +82,16 @@ def _is_ovsport_update_valid(ovsport):
if ovsport.name.startswith('qg'):
return False
if (ovsport.type == constants.OVS_VM_INTERFACE and
ovsport.lport is None):
return False
if action == 'set':
# No need for 'updated' event if the ofport is being deleted
ofport = ovsport.ofport
if (ofport is None) or (ofport < 0):
return False
return True
@ -98,7 +108,7 @@ class DFIdl(idl.Idl):
local_interface = ovs.OvsPort.from_idl_row(row)
action = event if event != 'update' else 'set'
if _is_ovsport_update_valid(local_interface):
if _is_ovsport_update_valid(action, local_interface):
self.nb_api.db_change_callback(
local_interface.table_name,
local_interface.id,

View File

@ -0,0 +1,76 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from dragonflow.common import constants
from dragonflow.db.models import ovs
from dragonflow.ovsdb import impl_idl
from dragonflow.tests import base as tests_base
class TestDFIdl(tests_base.BaseTestCase):
def setUp(self):
super(TestDFIdl, self).setUp()
def test_port_update_qg(self):
self.assertFalse(
impl_idl._is_ovsport_update_valid(
'set',
ovs.OvsPort(
ofport=1,
name='qg-some-uuid',
),
),
)
def test_port_update_no_ofport(self):
self.assertFalse(
impl_idl._is_ovsport_update_valid(
'set',
ovs.OvsPort(
name='tap-uuid',
),
),
)
def test_port_update_neg_ofport(self):
self.assertFalse(
impl_idl._is_ovsport_update_valid(
'set',
ovs.OvsPort(
ofport=-1,
name='tap-uuid',
),
),
)
def test_port_update_bad_type(self):
self.assertFalse(
impl_idl._is_ovsport_update_valid(
'set',
ovs.OvsPort(
ofport=1,
type=constants.OVS_PATCH_INTERFACE,
name='tap-uuid',
),
),
)
def test_port_update_missing_lport(self):
self.assertFalse(
impl_idl._is_ovsport_update_valid(
'set',
ovs.OvsPort(
ofport=1,
type=constants.OVS_VM_INTERFACE,
name='tap-uuid',
),
),
)

View File

@ -106,11 +106,6 @@ class TestTopology(test_app_base.DFAppTestBase):
self.nb_api.subscriber.unregister_topic.assert_called_once_with(
test_app_base.fake_local_port1.topic)
self.fake_invalid_ovs_port.ofport = -1
self.controller.update.reset_mock()
self.topology.ovs_port_updated(self.fake_invalid_ovs_port)
self.controller.update.assert_not_called()
def test_vm_online_after_topology_pulled(self):
self.nb_api.get_all.side_effect = nb_api_get_all_func(
test_app_base.fake_logic_switch1,