From f557b19d3a235709acee417121d167101db3d7ff Mon Sep 17 00:00:00 2001 From: Omer Anson Date: Mon, 3 Jul 2017 11:59:33 +0300 Subject: [PATCH] OvsPort to reference lport, not just hold its id OvsPort holds its lport ID in iface_id. This change turns that field into a reference to lport, using the ID as key. The field (iface_id) is also renamed to iface to reflect the change in semantics. Related-Bug: #1690775 Change-Id: I80ac2f4bac5f43b9f3a16afab5e36b3b1e299bcf --- dragonflow/controller/apps/classifier.py | 7 ++- dragonflow/controller/topology.py | 54 +++++++++---------- dragonflow/db/models/ovs.py | 9 ++-- .../pubsub_drivers/nb_api_neutron_notifier.py | 4 +- dragonflow/tests/common/utils.py | 7 ++- .../tests/fullstack/test_ovsdb_monitor.py | 4 +- dragonflow/tests/unit/test_app_base.py | 4 +- dragonflow/tests/unit/test_classifier_app.py | 2 +- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/dragonflow/controller/apps/classifier.py b/dragonflow/controller/apps/classifier.py index 28496af81..9f45ca725 100644 --- a/dragonflow/controller/apps/classifier.py +++ b/dragonflow/controller/apps/classifier.py @@ -18,7 +18,6 @@ from ryu.ofproto import nicira_ext from dragonflow.controller.common import constants as const from dragonflow.controller import df_base_app from dragonflow.db.models import constants as model_constants -from dragonflow.db.models import l2 from dragonflow.db.models import ovs @@ -43,14 +42,14 @@ class ClassifierApp(df_base_app.DFlowApp): @df_base_app.register_event(ovs.OvsPort, model_constants.EVENT_UPDATED) def _ovs_port_created(self, ovs_port, orig_ovs_port=None): ofport = ovs_port.ofport - lport_id = ovs_port.iface_id - if not lport_id: + lport_ref = ovs_port.lport + if not lport_ref: return # Not relevant if orig_ovs_port and orig_ovs_port.ofport != ofport: self._ovs_port_deleted(ovs_port) if not ofport or ofport == -1: return # Not ready yet, or error - lport = self.nb_api.get(l2.LogicalPort(id=lport_id)) + lport = self.nb_api.get(lport_ref) self._ofport_unique_key_map[ovs_port.id] = (ofport, lport.unique_key) LOG.info("Add local ovs port %(ovs_port)s, logical port " "%(lport)s for classification", diff --git a/dragonflow/controller/topology.py b/dragonflow/controller/topology.py index 4f5fc3a9c..64d9e4be2 100644 --- a/dragonflow/controller/topology.py +++ b/dragonflow/controller/topology.py @@ -139,7 +139,7 @@ class Topology(object): return False if (port_type == constants.OVS_VM_INTERFACE and - ovs_port.iface_id is None): + ovs_port.lport is None): return False return True @@ -187,8 +187,7 @@ class Topology(object): ovs_port, n_const.PORT_STATUS_ACTIVE) def _vm_port_updated(self, ovs_port): - lport_id = ovs_port.iface_id - lport = self._get_lport(lport_id) + lport = self._get_lport(ovs_port) if lport is None: LOG.warning("No logical port found for ovs port: %s", ovs_port) @@ -196,10 +195,10 @@ class Topology(object): topic = lport.topic if not topic: return - self._add_to_topic_subscribed(topic, lport_id) + self._add_to_topic_subscribed(topic, lport.id) self.ovs_to_lport_mapping[ovs_port.id] = OvsLportMapping( - lport_id=lport_id, topic=topic) + lport_id=lport.id, topic=topic) chassis = lport.binding.chassis # check if migration occurs @@ -207,13 +206,13 @@ class Topology(object): device_owner = lport.device_owner if n_const.DEVICE_OWNER_COMPUTE_PREFIX in device_owner: LOG.info("Prepare migrate lport %(lport)s to %(chassis)s", - {"lport": lport_id, "chassis": chassis}) + {"lport": lport.id, "chassis": chassis}) self.nb_api.create(migration.Migration( - id=lport_id, dest_chassis=self.chassis_name, + id=lport.id, dest_chassis=self.chassis_name, status=migration.MIGRATION_STATUS_DEST_PLUG)) return - cached_lport = self.db_store.get_one(l2.LogicalPort(id=lport_id)) + cached_lport = ovs_port.lport.get_object() if not cached_lport: # If the logical port is not in db store it has not been applied # to dragonflow apps. We need to update it in dragonflow controller @@ -226,15 +225,15 @@ class Topology(object): def _vm_port_deleted(self, ovs_port): ovs_port_id = ovs_port.id - lport_id = ovs_port.iface_id - lport = self.db_store.get_one(l2.LogicalPort(id=lport_id)) + lport_ref = ovs_port.lport + lport = lport_ref.get_object() if lport is None: lport = self.ovs_to_lport_mapping.get(ovs_port_id) if lport is None: return topic = lport.topic del self.ovs_to_lport_mapping[ovs_port_id] - self._del_from_topic_subscribed(topic, lport_id) + self._del_from_topic_subscribed(topic, lport.id) return topic = lport.topic @@ -243,21 +242,22 @@ class Topology(object): try: self.controller.delete(lport) except Exception: - LOG.exception( - 'Failed to process logical port offline event %s', lport_id) + LOG.exception('Failed to process logical port offline event %s', + lport_ref.id) finally: self.controller.notify_port_status( ovs_port, n_const.PORT_STATUS_DOWN) - migration_obj = self.nb_api.get(migration.Migration(id=lport_id)) + migration_obj = self.nb_api.get( + migration.Migration(id=lport_ref.id)) if migration_obj and migration_obj.chassis: - LOG.info("Sending migrating event for %s", lport_id) - migration_obj.lport = lport_id + LOG.info("Sending migrating event for %s", lport_ref.id) + migration_obj.lport = lport_ref migration_obj.status = migration.MIGRATION_STATUS_SRC_UNPLUG self.nb_api.update(migration_obj) del self.ovs_to_lport_mapping[ovs_port_id] - self._del_from_topic_subscribed(topic, lport_id) + self._del_from_topic_subscribed(topic, lport_ref.id) def _add_to_topic_subscribed(self, topic, lport_id): if not self.enable_selective_topo_dist or not topic: @@ -291,15 +291,12 @@ class Topology(object): # set, which represents no topic is subscribed now. return set(self.topic_subscribed) - def _get_lport(self, port_id, topic=None): - if topic is None: - lean_lport = l2.LogicalPort(id=port_id) - else: - lean_lport = l2.LogicalPort(id=port_id, topic=topic) - lport = self.db_store.get_one(lean_lport) + def _get_lport(self, ovs_port): + if not ovs_port.lport: + return None + lport = ovs_port.lport.get_object() if lport is None: - lport = self.nb_api.get(lean_lport) - + lport = self.nb_api.get(ovs_port.lport) return lport def check_topology_info(self): @@ -314,8 +311,7 @@ class Topology(object): delete_ovs_to_lport_mapping = self.ovs_to_lport_mapping for key, ovs_port in self.ovs_ports.items(): if ovs_port.type == constants.OVS_VM_INTERFACE: - lport_id = ovs_port.iface_id - lport = self._get_lport(lport_id) + lport = self._get_lport(ovs_port) if lport is None: LOG.warning("No logical port found for ovs port: %s", ovs_port) @@ -324,10 +320,10 @@ class Topology(object): if not topic: continue new_ovs_to_lport_mapping[key] = OvsLportMapping( - lport_id=lport_id, topic=topic) + lport_id=lport.id, topic=topic) if not delete_ovs_to_lport_mapping.pop(key, None): add_ovs_to_lport_mapping[key] = OvsLportMapping( - lport_id=lport_id, topic=topic) + lport_id=lport.id, topic=topic) self.ovs_to_lport_mapping = new_ovs_to_lport_mapping for value in add_ovs_to_lport_mapping.values(): lport_id = value.lport_id diff --git a/dragonflow/db/models/ovs.py b/dragonflow/db/models/ovs.py index 66ad2f075..6b06bc74a 100644 --- a/dragonflow/db/models/ovs.py +++ b/dragonflow/db/models/ovs.py @@ -14,6 +14,7 @@ from jsonmodels import fields from dragonflow.common import constants import dragonflow.db.field_types as df_fields import dragonflow.db.model_framework as mf +from dragonflow.db.models import l2 from dragonflow.db.models import mixins @@ -44,7 +45,7 @@ class OvsPort(mf.ModelBase, mixins.BasicEvents, mixins.Name): ofport = fields.IntField() admin_state = df_fields.EnumField(('up', 'down')) - iface_id = fields.StringField() + lport = df_fields.ReferenceField(l2.LogicalPort) type = df_fields.EnumField( ( constants.OVS_BRIDGE_INTERFACE, @@ -82,9 +83,9 @@ class OvsPort(mf.ModelBase, mixins.BasicEvents, mixins.Name): res.tunnel_types = row.type external_ids = row.external_ids - iface_id = external_ids.get('iface-id') - if iface_id is not None: - res.iface_id = iface_id + lport_id = external_ids.get('iface-id') + if lport_id is not None: + res.lport = lport_id attached_mac = external_ids.get('attached-mac') if attached_mac is not None: diff --git a/dragonflow/db/pubsub_drivers/nb_api_neutron_notifier.py b/dragonflow/db/pubsub_drivers/nb_api_neutron_notifier.py index fcd3853cb..5dd005c5c 100644 --- a/dragonflow/db/pubsub_drivers/nb_api_neutron_notifier.py +++ b/dragonflow/db/pubsub_drivers/nb_api_neutron_notifier.py @@ -82,8 +82,8 @@ class NbApiNeutronNotifier(neutron_notifier_api.NeutronNotifierDriver): self.heart_beat_reporter.daemonize() def notify_port_status(self, ovs_port, status): - port_id = ovs_port.iface_id - self._send_event(l2.LogicalPort.table_name, port_id, 'update', status) + port = ovs_port.lport + self._send_event(l2.LogicalPort.table_name, port.id, 'update', status) def notify_fip_status(self, fip, status): self._send_event(models.Floatingip.table_name, diff --git a/dragonflow/tests/common/utils.py b/dragonflow/tests/common/utils.py index e6d4fd2a8..a71582cfd 100644 --- a/dragonflow/tests/common/utils.py +++ b/dragonflow/tests/common/utils.py @@ -23,6 +23,7 @@ import six from dragonflow.common import exceptions from dragonflow.controller.common import constants as df_const from dragonflow.db import db_store +from dragonflow.db import model_proxy from dragonflow.db.models import l2 from dragonflow.ovsdb import vswitch_impl from dragonflow.tests.common import constants as const @@ -246,7 +247,11 @@ def with_nb_objects(*objs): return res def _get(obj): - objs = _get_all(type(obj)) + if model_proxy.is_model_proxy(obj): + model = obj.get_proxied_model() + else: + model = type(obj) + objs = _get_all(model) for o in objs: if obj.id == o.id: return o diff --git a/dragonflow/tests/fullstack/test_ovsdb_monitor.py b/dragonflow/tests/fullstack/test_ovsdb_monitor.py index 3c6b07ce6..b3447413b 100644 --- a/dragonflow/tests/fullstack/test_ovsdb_monitor.py +++ b/dragonflow/tests/fullstack/test_ovsdb_monitor.py @@ -37,7 +37,7 @@ class TestOvsdbMonitor(test_base.DFTestBase): return False elif _interface.type != constants.OVS_VM_INTERFACE: return False - elif _interface.iface_id is None: + elif _interface.lport is None: return False elif _interface.ofport <= 0: return False @@ -58,7 +58,7 @@ class TestOvsdbMonitor(test_base.DFTestBase): return False elif _interface.type != constants.OVS_VM_INTERFACE: return False - elif _interface.iface_id is None: + elif _interface.lport is None: return False else: return True diff --git a/dragonflow/tests/unit/test_app_base.py b/dragonflow/tests/unit/test_app_base.py index 007478464..fe35e7f53 100644 --- a/dragonflow/tests/unit/test_app_base.py +++ b/dragonflow/tests/unit/test_app_base.py @@ -250,7 +250,7 @@ fake_ovs_port1 = ovs.OvsPort( name='tap-fake_port1', admin_state='up', type=constants.OVS_VM_INTERFACE, - iface_id='fake_port1', + lport='fake_port1', attached_mac='fa:16:3e:8c:2e:b3', ) @@ -268,7 +268,7 @@ fake_ovs_port2 = ovs.OvsPort( name='tap-fake_port2', admin_state='up', type=constants.OVS_VM_INTERFACE, - iface_id='fake_port2', + lport='fake_port2', attached_mac='fa:16:3e:8c:2e:b4', ) diff --git a/dragonflow/tests/unit/test_classifier_app.py b/dragonflow/tests/unit/test_classifier_app.py index b29cd5580..975af2412 100644 --- a/dragonflow/tests/unit/test_classifier_app.py +++ b/dragonflow/tests/unit/test_classifier_app.py @@ -55,7 +55,7 @@ class TestClassifierAppForVlan(testscenarios.WithScenarios, self.controller.update(fake_local_vlan_port) self.app.mod_flow.assert_not_called() ovs_port = ovs.OvsPort(id='fake_ovs_port', - iface_id=fake_local_vlan_port.id, + lport=fake_local_vlan_port.id, ofport=1, admin_state='up', type=constants.OVS_VM_INTERFACE) self.controller.update(ovs_port)