From 7f973380b639d6222677be8ba7d4c02b9cc2aab5 Mon Sep 17 00:00:00 2001 From: Shachar Snapiri Date: Sun, 5 Aug 2018 17:49:12 +0300 Subject: [PATCH] Separate vswitch_api and ryu from the main logic The vswitch_api and ryu are specific to ovs and should be removed from the main code logic. They are now encapsulated within the df_ovs_driver. Currently the vswitch is still referenced directly from the driver in all the tests. This behavior should be removed in a later patch. Change-Id: Id919faaebece90c1410226d38f28c52af7693c08 Partial-Bug: #1781376 --- dragonflow/controller/apps/trunk.py | 4 ++-- dragonflow/controller/df_base_app.py | 10 +++++++--- dragonflow/switch/drivers/df_switch_driver.py | 13 +++++++++++++ dragonflow/switch/drivers/ovs/__init__.py | 0 .../drivers/ovs}/datapath.py | 6 +++--- .../switch/drivers/{ => ovs}/df_ovs_driver.py | 16 ++++++++++++++-- .../drivers/ovs}/ryu_base_app.py | 14 +++++--------- dragonflow/tests/fullstack/test_base.py | 2 +- dragonflow/tests/fullstack/test_ryu_base_app.py | 4 ++-- dragonflow/tests/unit/test_app_base.py | 6 +++--- dragonflow/tests/unit/test_datapath.py | 2 +- .../tests/unit/test_df_local_controller.py | 2 +- dragonflow/tests/unit/test_model_framework.py | 2 +- dragonflow/tests/unit/test_ryu_base_app.py | 4 ++-- setup.cfg | 2 +- 15 files changed, 56 insertions(+), 31 deletions(-) create mode 100644 dragonflow/switch/drivers/ovs/__init__.py rename dragonflow/{controller => switch/drivers/ovs}/datapath.py (98%) rename dragonflow/switch/drivers/{ => ovs}/df_ovs_driver.py (88%) rename dragonflow/{controller => switch/drivers/ovs}/ryu_base_app.py (94%) diff --git a/dragonflow/controller/apps/trunk.py b/dragonflow/controller/apps/trunk.py index 843db814a..2cadd531f 100644 --- a/dragonflow/controller/apps/trunk.py +++ b/dragonflow/controller/apps/trunk.py @@ -379,10 +379,10 @@ class IPVlanNestedPortArpImpl(IPv4NestedPortMixin, BaseNestedPortImpl): class TrunkApp(df_base_app.DFlowApp): - def __init__(self, api, vswitch_api=None, nb_api=None, + def __init__(self, api, switch_backend=None, nb_api=None, neutron_server_notifier=None): super(TrunkApp, self).__init__( - api, vswitch_api=vswitch_api, + api, switch_backend=switch_backend, nb_api=nb_api, neutron_server_notifier=neutron_server_notifier) # A dispatch table, to add the relevant openflow rules according to diff --git a/dragonflow/controller/df_base_app.py b/dragonflow/controller/df_base_app.py index 4f4562896..d762611c1 100644 --- a/dragonflow/controller/df_base_app.py +++ b/dragonflow/controller/df_base_app.py @@ -33,11 +33,11 @@ LOG = log.getLogger(__name__) class DFlowApp(object): - def __init__(self, api, vswitch_api=None, nb_api=None, + def __init__(self, api, switch_backend=None, nb_api=None, neutron_server_notifier=None): self.api = api self.db_store = db_store.get_instance() - self.vswitch_api = vswitch_api + self.switch_backend = switch_backend self.nb_api = nb_api self.neutron_server_notifier = neutron_server_notifier # Though there is nothing to initialize in super class, call it @@ -45,6 +45,10 @@ class DFlowApp(object): super(DFlowApp, self).__init__() self._register_events() + @property + def vswitch_api(self): + return self.switch_backend.vswitch_api + def _register_events(self): '''Iterate all methods we decorated with @register_event and register them to the requested models. @@ -75,7 +79,7 @@ class DFlowApp(object): @property def dfdp(self): - return self.api._new_dp + return self.switch_backend.datapath @property def parser(self): diff --git a/dragonflow/switch/drivers/df_switch_driver.py b/dragonflow/switch/drivers/df_switch_driver.py index 328dd6093..a6883a205 100644 --- a/dragonflow/switch/drivers/df_switch_driver.py +++ b/dragonflow/switch/drivers/df_switch_driver.py @@ -29,6 +29,19 @@ class DfSwitchDriver(object): self.db_change_callback = db_change_callback self.neutron_notifier = neutron_notifier + # TODO(snapiri): remove the need for the df_app argument + @abc.abstractmethod + def setup_datapath(self, df_app): + """Setup the datapath flow + This method needs to be called for every dragonflow application in the + packet flow to initialize its datapath + """ + + @property + @abc.abstractmethod + def datapath(self): + """Returns a datapath object""" + @abc.abstractmethod def start(self): """Start running the switch backend""" diff --git a/dragonflow/switch/drivers/ovs/__init__.py b/dragonflow/switch/drivers/ovs/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/dragonflow/controller/datapath.py b/dragonflow/switch/drivers/ovs/datapath.py similarity index 98% rename from dragonflow/controller/datapath.py rename to dragonflow/switch/drivers/ovs/datapath.py index 0d47944b6..f413f7eb2 100644 --- a/dragonflow/controller/datapath.py +++ b/dragonflow/switch/drivers/ovs/datapath.py @@ -72,7 +72,7 @@ class Datapath(object): } ) - def set_up(self, ryu_base, vswitch_api, nb_api, notifier): + def set_up(self, ryu_base, switch_backend, nb_api, neutron_notifier): """ Instantiate the application classes. Instantiate the applications (Including table and register allocation) @@ -102,9 +102,9 @@ class Datapath(object): self.log_datapath_allocation(vertex.name, dp_alloc) self._dp_allocs[vertex.name] = dp_alloc app = app_class(api=ryu_base, - vswitch_api=vswitch_api, + switch_backend=switch_backend, nb_api=nb_api, - neutron_server_notifier=notifier, + neutron_server_notifier=neutron_notifier, dp_alloc=dp_alloc, **(vertex.params or {}) ) diff --git a/dragonflow/switch/drivers/df_ovs_driver.py b/dragonflow/switch/drivers/ovs/df_ovs_driver.py similarity index 88% rename from dragonflow/switch/drivers/df_ovs_driver.py rename to dragonflow/switch/drivers/ovs/df_ovs_driver.py index 1d8b3477d..f0cea5e83 100644 --- a/dragonflow/switch/drivers/df_ovs_driver.py +++ b/dragonflow/switch/drivers/ovs/df_ovs_driver.py @@ -18,11 +18,13 @@ from ryu.base import app_manager from ryu import cfg as ryu_cfg from dragonflow import conf as cfg -from dragonflow.controller import ryu_base_app +from dragonflow.controller import datapath_layout from dragonflow.db.models import l2 from dragonflow.db.models import switch from dragonflow.ovsdb import vswitch_impl from dragonflow.switch.drivers import df_switch_driver +from dragonflow.switch.drivers.ovs import datapath +from dragonflow.switch.drivers.ovs import ryu_base_app class DfOvsDriver(df_switch_driver.DfSwitchDriver): @@ -34,6 +36,8 @@ class DfOvsDriver(df_switch_driver.DfSwitchDriver): self.open_flow_app = None self.open_flow_service = None self.neutron_notifier = None + self._datapath = datapath.Datapath( + datapath_layout.get_datapath_layout()) def initialize(self, db_change_callback, neutron_notifier): super(DfOvsDriver, self).initialize(db_change_callback, @@ -41,7 +45,7 @@ class DfOvsDriver(df_switch_driver.DfSwitchDriver): self.open_flow_app = self.app_mgr.instantiate( ryu_base_app.RyuDFAdapter, nb_api=self.nb_api, - vswitch_api=self.vswitch_api, + switch_backend=self, neutron_server_notifier=self.neutron_notifier, db_change_callback=self.db_change_callback ) @@ -49,6 +53,14 @@ class DfOvsDriver(df_switch_driver.DfSwitchDriver): self.open_flow_service = self.app_mgr.instantiate( of_service.OfctlService) + def setup_datapath(self, df_app): + self._datapath.set_up(df_app, self, + self.nb_api, self.neutron_notifier) + + @property + def datapath(self): + return self._datapath + def start(self): self.vswitch_api.initialize(self.db_change_callback) # both set_controller and del_controller will delete flows. diff --git a/dragonflow/controller/ryu_base_app.py b/dragonflow/switch/drivers/ovs/ryu_base_app.py similarity index 94% rename from dragonflow/controller/ryu_base_app.py rename to dragonflow/switch/drivers/ovs/ryu_base_app.py index 138ba9f0f..746bf281b 100644 --- a/dragonflow/controller/ryu_base_app.py +++ b/dragonflow/switch/drivers/ovs/ryu_base_app.py @@ -27,8 +27,6 @@ from ryu import utils from dragonflow.common import profiler as df_profiler from dragonflow.controller.common import constants -from dragonflow.controller import datapath as new_dp -from dragonflow.controller import datapath_layout as new_dp_layout from dragonflow.controller import dispatcher @@ -39,19 +37,19 @@ class RyuDFAdapter(ofp_handler.OFPHandler): OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] OF_AUTO_PORT_DESC_STATS_REQ_VER = 0x04 - def __init__(self, vswitch_api, nb_api, + def __init__(self, switch_backend, nb_api, db_change_callback, neutron_server_notifier=None): super(RyuDFAdapter, self).__init__() self.dispatcher = dispatcher.AppDispatcher(cfg.CONF.df.apps_list) - self.vswitch_api = vswitch_api + self.vswitch_api = switch_backend.vswitch_api self.nb_api = nb_api + self.switch_backend = switch_backend self.neutron_server_notifier = neutron_server_notifier self._datapath = None self.table_handlers = {} self.first_connect = True self.db_change_callback = db_change_callback - self._new_dp = new_dp.Datapath(new_dp_layout.get_datapath_layout()) @property def datapath(self): @@ -60,7 +58,7 @@ class RyuDFAdapter(ofp_handler.OFPHandler): def start(self): super(RyuDFAdapter, self).start() self.load(self, - vswitch_api=self.vswitch_api, + switch_backend=self.switch_backend, nb_api=self.nb_api, neutron_server_notifier=self.neutron_server_notifier) self.wait_until_ready() @@ -111,9 +109,7 @@ class RyuDFAdapter(ofp_handler.OFPHandler): self.get_sw_async_msg_config() - self._new_dp.set_up( - self, self.vswitch_api, self.nb_api, self.neutron_server_notifier) - + self.switch_backend.setup_datapath(self) self.dispatcher.dispatch('switch_features_handler', ev) if not self.first_connect: diff --git a/dragonflow/tests/fullstack/test_base.py b/dragonflow/tests/fullstack/test_base.py index 1b6b92f9a..abdd8cec7 100644 --- a/dragonflow/tests/fullstack/test_base.py +++ b/dragonflow/tests/fullstack/test_base.py @@ -21,9 +21,9 @@ from oslo_log import log from dragonflow.common import utils as df_utils from dragonflow import conf as cfg from dragonflow.controller.common import constants as ctrl_const -from dragonflow.controller import datapath from dragonflow.db import api_nb from dragonflow.db import db_common +from dragonflow.switch.drivers.ovs import datapath from dragonflow.tests import base from dragonflow.tests.common import app_testing_objects as test_objects from dragonflow.tests.common import clients diff --git a/dragonflow/tests/fullstack/test_ryu_base_app.py b/dragonflow/tests/fullstack/test_ryu_base_app.py index 3f887ce9a..8704031bd 100644 --- a/dragonflow/tests/fullstack/test_ryu_base_app.py +++ b/dragonflow/tests/fullstack/test_ryu_base_app.py @@ -20,8 +20,8 @@ from ryu.base import app_manager from ryu import cfg as ryu_cfg from dragonflow import conf as cfg -from dragonflow.controller import ryu_base_app from dragonflow.ovsdb import vswitch_impl +from dragonflow.switch.drivers.ovs import ryu_base_app from dragonflow.tests.common import constants as const from dragonflow.tests.fullstack import test_base @@ -35,7 +35,7 @@ class TestRyuBaseApp(test_base.DFTestBase): app_mgr = app_manager.AppManager.get_instance() self.open_flow_app = app_mgr.instantiate( ryu_base_app.RyuDFAdapter, - vswitch_api=mock.Mock(), + switch_backend=mock.Mock(), nb_api=mock.Mock(), db_change_callback=self._db_change_callback) self.open_flow_app.load = mock.Mock() diff --git a/dragonflow/tests/unit/test_app_base.py b/dragonflow/tests/unit/test_app_base.py index c7802b713..33c0c7e4a 100644 --- a/dragonflow/tests/unit/test_app_base.py +++ b/dragonflow/tests/unit/test_app_base.py @@ -21,10 +21,8 @@ from oslo_config import cfg from oslo_log import fixture as log_fixture from dragonflow.common import constants -from dragonflow.controller import datapath from dragonflow.controller import datapath_layout from dragonflow.controller import df_local_controller -from dragonflow.controller import ryu_base_app from dragonflow.controller import topology from dragonflow.db import api_nb from dragonflow.db import db_store @@ -34,6 +32,8 @@ from dragonflow.db.models import l2 from dragonflow.db.models import l3 from dragonflow.db.models import secgroups from dragonflow.db.models import switch +from dragonflow.switch.drivers.ovs import datapath +from dragonflow.switch.drivers.ovs import ryu_base_app from dragonflow.tests import base as tests_base @@ -87,7 +87,7 @@ class DFAppTestBase(tests_base.BaseTestCase): self.vswitch_api = switch_backend.vswitch_api = mock.MagicMock() kwargs = dict( nb_api=self.controller.nb_api, - vswitch_api=self.vswitch_api + switch_backend=switch_backend ) switch_backend.open_flow_app = ryu_base_app.RyuDFAdapter( db_change_callback=self.controller.db_change_callback, diff --git a/dragonflow/tests/unit/test_datapath.py b/dragonflow/tests/unit/test_datapath.py index c8cf9e5ee..d0b9ac6ff 100644 --- a/dragonflow/tests/unit/test_datapath.py +++ b/dragonflow/tests/unit/test_datapath.py @@ -15,8 +15,8 @@ import mock import testscenarios from dragonflow.controller import app_base -from dragonflow.controller import datapath from dragonflow.controller import datapath_layout +from dragonflow.switch.drivers.ovs import datapath from dragonflow.tests import base as tests_base load_tests = testscenarios.load_tests_apply_scenarios diff --git a/dragonflow/tests/unit/test_df_local_controller.py b/dragonflow/tests/unit/test_df_local_controller.py index 17d0d01cf..16d9f1753 100644 --- a/dragonflow/tests/unit/test_df_local_controller.py +++ b/dragonflow/tests/unit/test_df_local_controller.py @@ -14,12 +14,12 @@ import mock from oslo_config import cfg from dragonflow.controller import df_local_controller -from dragonflow.controller import ryu_base_app from dragonflow.db import db_store from dragonflow.db import field_types as df_fields from dragonflow.db import model_framework from dragonflow.db.models import core from dragonflow.db.models import mixins +from dragonflow.switch.drivers.ovs import ryu_base_app from dragonflow.tests.common import utils from dragonflow.tests.unit import test_app_base diff --git a/dragonflow/tests/unit/test_model_framework.py b/dragonflow/tests/unit/test_model_framework.py index 6c8e04a85..64bbd55a9 100644 --- a/dragonflow/tests/unit/test_model_framework.py +++ b/dragonflow/tests/unit/test_model_framework.py @@ -326,7 +326,7 @@ class TestModelFramework(tests_base.BaseTestCase): TestApp( api=mock.MagicMock(), - vswitch_api=mock.MagicMock(), + switch_backend=mock.MagicMock(), nb_api=mock.MagicMock(), ) diff --git a/dragonflow/tests/unit/test_ryu_base_app.py b/dragonflow/tests/unit/test_ryu_base_app.py index 2c7faaefe..885c1d066 100644 --- a/dragonflow/tests/unit/test_ryu_base_app.py +++ b/dragonflow/tests/unit/test_ryu_base_app.py @@ -17,7 +17,7 @@ import mock import testtools from dragonflow import conf as cfg -from dragonflow.controller import ryu_base_app +from dragonflow.switch.drivers.ovs import ryu_base_app from dragonflow.tests import base as tests_base @@ -36,7 +36,7 @@ class TestRyuDFAdapter(tests_base.BaseTestCase): group='df', ) self.ryu_df_adapter = ryu_base_app.RyuDFAdapter( - vswitch_api=mock.Mock(), + switch_backend=mock.Mock(), nb_api=mock.Mock(), db_change_callback=mock.Mock()) self.mock_app = mock.Mock(spec=[ diff --git a/setup.cfg b/setup.cfg index 801750942..9ad22c214 100644 --- a/setup.cfg +++ b/setup.cfg @@ -75,7 +75,7 @@ dragonflow.nb_db_driver = dragonflow.neutron_notifier_driver = nb_api_neutron_notifier_driver = dragonflow.db.pubsub_drivers.nb_api_neutron_notifier:NbApiNeutronNotifier dragonflow.switch_backend_driver = - vswitch_backend_driver = dragonflow.switch.drivers.df_ovs_driver:DfOvsDriver + vswitch_backend_driver = dragonflow.switch.drivers.ovs.df_ovs_driver:DfOvsDriver neutron.service_plugins = df-l3-agentless = dragonflow.neutron.services.l3_router_plugin:DFL3AgentlessRouterPlugin df-l3 = dragonflow.neutron.services.l3_router_plugin:DFL3RouterPlugin