Use stevedore to load apps
We used to load apps by listing module and class names in a configuration entry. This patch defines entry points for all present apps, so we don't have to import them by module path, additionally, other packages can register new apps, allowing further extensibility. Closes-Bug: #1702462 Change-Id: Iffa0fea3db36df2f59ef19a621b41838d66cb8d7
This commit is contained in:
parent
cd10f47219
commit
7367754398
|
@ -138,7 +138,7 @@ function configure_ovs {
|
|||
|
||||
if is_service_enabled df-controller ; then
|
||||
# setup external bridge if necessary
|
||||
check_dnat=$(echo $DF_APPS_LIST | grep "DNATApp")
|
||||
check_dnat=$(echo $DF_APPS_LIST | grep "dnat")
|
||||
if [[ "$check_dnat" != "" ]]; then
|
||||
echo "Setup external bridge for DNAT"
|
||||
sudo ovs-vsctl add-br $PUBLIC_BRIDGE || true
|
||||
|
|
|
@ -158,7 +158,7 @@ function start_ovs {
|
|||
function configure_ovs {
|
||||
if is_service_enabled df-controller ; then
|
||||
# setup external bridge if necessary
|
||||
check_dnat=$(echo $DF_APPS_LIST | grep "DNATApp")
|
||||
check_dnat=$(echo $DF_APPS_LIST | grep "dnat")
|
||||
if [[ "$check_dnat" != "" ]]; then
|
||||
echo "Setup external bridge for DNAT"
|
||||
sudo ovs-vsctl add-br $PUBLIC_BRIDGE || true
|
||||
|
|
|
@ -17,36 +17,33 @@ OVS_BRANCH=${OVS_BRANCH:-branch-2.6}
|
|||
EXTERNAL_HOST_IP=${EXTERNAL_HOST_IP:-}
|
||||
|
||||
DEFAULT_TUNNEL_TYPES="vxlan,geneve,gre"
|
||||
DEFAULT_APPS_LIST="l2_app.L2App,l3_proactive_app.L3ProactiveApp,"\
|
||||
"dhcp_app.DHCPApp,dnat_app.DNATApp,sg_app.SGApp,portsec_app.PortSecApp,"\
|
||||
"portqos_app.PortQosApp,classifier_app.ClassifierApp,tunneling_app.TunnelingApp,"\
|
||||
"provider_networks_app.ProviderNetworksApp"
|
||||
DEFAULT_APPS_LIST="l2,l3_proactive,dhcp,dnat,sg,portsec,portqos,classifier,tunneling,provider"
|
||||
|
||||
if is_service_enabled df-metadata ; then
|
||||
DEFAULT_APPS_LIST="$DEFAULT_APPS_LIST,metadata_service_app.MetadataServiceApp"
|
||||
DEFAULT_APPS_LIST="$DEFAULT_APPS_LIST,metadata_service"
|
||||
fi
|
||||
|
||||
if is_service_enabled q-trunk ; then
|
||||
DEFAULT_APPS_LIST="$DEFAULT_APPS_LIST,trunk_app.TrunkApp"
|
||||
DEFAULT_APPS_LIST="$DEFAULT_APPS_LIST,trunk"
|
||||
fi
|
||||
|
||||
ENABLE_ACTIVE_DETECTION=${ENABLE_ACTIVE_DETECTION:-True}
|
||||
if [[ "$ENABLE_ACTIVE_DETECTION" == "True" ]]; then
|
||||
DEFAULT_APPS_LIST="$DEFAULT_APPS_LIST,active_port_detection_app.ActivePortDetectionApp"
|
||||
DEFAULT_APPS_LIST="$DEFAULT_APPS_LIST,active_port_detection"
|
||||
fi
|
||||
|
||||
ENABLE_LIVE_MIGRATION=${ENABLE_LIVE_MIGRATION:-True}
|
||||
if [[ "$ENABLE_LIVE_MIGRATION" == "True" ]]; then
|
||||
DEFAULT_APPS_LIST="$DEFAULT_APPS_LIST,migration_app.MigrationApp"
|
||||
DEFAULT_APPS_LIST="$DEFAULT_APPS_LIST,migration"
|
||||
fi
|
||||
|
||||
if [[ ! -z ${EXTERNAL_HOST_IP} ]]; then
|
||||
DEFAULT_APPS_LIST="$DEFAULT_APPS_LIST,chassis_snat_app.ChassisSNATApp"
|
||||
DEFAULT_APPS_LIST="$DEFAULT_APPS_LIST,chassis_snat"
|
||||
fi
|
||||
|
||||
ENABLED_AGING_APP=${ENABLE_AGING_APP:-True}
|
||||
if [[ "$ENABLE_AGING_APP" == "True" ]]; then
|
||||
DEFAULT_APPS_LIST="aging_app.Aging,$DEFAULT_APPS_LIST"
|
||||
DEFAULT_APPS_LIST="aging,$DEFAULT_APPS_LIST"
|
||||
fi
|
||||
|
||||
DF_APPS_LIST=${DF_APPS_LIST:-$DEFAULT_APPS_LIST}
|
||||
|
|
|
@ -95,7 +95,7 @@ Basic Configurations
|
|||
[df]
|
||||
metadata_interface = tap-metadata
|
||||
enable_selective_topology_distribution = True
|
||||
apps_list = l2_app.L2App,l3_proactive_app.L3ProactiveApp,dhcp_app.DHCPApp,dnat_app.DNATApp,sg_app.SGApp,portsec_app.PortSecApp,portqos_app.PortQosApp
|
||||
apps_list = l2,l3_proactive,dhcp,dnat,sg,portsec,portqos
|
||||
integration_bridge = br-int
|
||||
tunnel_type = geneve
|
||||
|
||||
|
|
|
@ -41,9 +41,7 @@ df_opts = [
|
|||
default=False,
|
||||
help=_("Enable dpdk")),
|
||||
cfg.StrOpt('apps_list',
|
||||
default='l2_app.L2App,'
|
||||
'l3_proactive_app.L3ProactiveApp,'
|
||||
'dhcp_app.DHCPApp',
|
||||
default='l2,l3_proactive,dhcp',
|
||||
help=_('List of openflow applications classes to load')),
|
||||
cfg.StrOpt('integration_bridge', default='br-int',
|
||||
help=_("Integration bridge to use. "
|
||||
|
|
|
@ -11,9 +11,8 @@
|
|||
# under the License.
|
||||
|
||||
from oslo_log import log
|
||||
from oslo_utils import importutils
|
||||
import stevedore
|
||||
|
||||
from dragonflow._i18n import _
|
||||
from dragonflow.common import exceptions
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
@ -21,21 +20,21 @@ LOG = log.getLogger(__name__)
|
|||
|
||||
class AppDispatcher(object):
|
||||
|
||||
def __init__(self, apps_location_prefix, app_list):
|
||||
self.apps_location_prefix = apps_location_prefix
|
||||
def __init__(self, app_list):
|
||||
self.apps_list = app_list.split(',')
|
||||
self.apps = []
|
||||
|
||||
def load(self, *args, **kwargs):
|
||||
for app in self.apps_list:
|
||||
app_class_name = self.apps_location_prefix + "." + app
|
||||
try:
|
||||
app_class = importutils.import_class(app_class_name)
|
||||
app = app_class(*args, **kwargs)
|
||||
self.apps.append(app)
|
||||
except ImportError as e:
|
||||
LOG.exception("Error loading application by class, %s", e)
|
||||
raise ImportError(_("Application class not found."))
|
||||
mgr = stevedore.NamedExtensionManager(
|
||||
'dragonflow.controller.apps',
|
||||
self.apps_list,
|
||||
invoke_on_load=True,
|
||||
invoke_args=args,
|
||||
invoke_kwds=kwargs,
|
||||
)
|
||||
|
||||
for ext in mgr:
|
||||
self.apps.append(ext.obj)
|
||||
|
||||
def dispatch(self, method, *args, **kwargs):
|
||||
errors = []
|
||||
|
|
|
@ -39,8 +39,7 @@ class RyuDFAdapter(ofp_handler.OFPHandler):
|
|||
def __init__(self, vswitch_api=None, nb_api=None,
|
||||
neutron_server_notifier=None):
|
||||
super(RyuDFAdapter, self).__init__()
|
||||
self.dispatcher = dispatcher.AppDispatcher('dragonflow.controller',
|
||||
cfg.CONF.df.apps_list)
|
||||
self.dispatcher = dispatcher.AppDispatcher(cfg.CONF.df.apps_list)
|
||||
self.vswitch_api = vswitch_api
|
||||
self.nb_api = nb_api
|
||||
self.neutron_server_notifier = neutron_server_notifier
|
||||
|
|
|
@ -91,7 +91,7 @@ class NbApi(object):
|
|||
# FIXME(nick-ma-z): if active-detection is enabled,
|
||||
# we initialize the publisher here. Make sure it
|
||||
# only supports redis-based pub/sub driver.
|
||||
if "ActivePortDetectionApp" in cfg.CONF.df.apps_list:
|
||||
if "active_port_detection" in cfg.CONF.df.apps_list:
|
||||
self.publisher.initialize()
|
||||
|
||||
# NOTE(gampel) we want to start queuing event as soon
|
||||
|
|
|
@ -16,7 +16,7 @@ from dragonflow.tests.common import utils
|
|||
from dragonflow.tests.fullstack import test_base
|
||||
from dragonflow.tests.fullstack import test_objects as objects
|
||||
|
||||
SNAT_APP_NAME = 'chassis_snat_app.ChassisSNATApp'
|
||||
SNAT_APP_NAME = 'chassis_snat'
|
||||
|
||||
|
||||
class TestSnatFlows(test_base.DFTestBase):
|
||||
|
|
|
@ -21,7 +21,7 @@ from dragonflow.tests.unit import test_app_base
|
|||
|
||||
|
||||
class TestChassisSNATApp(test_app_base.DFAppTestBase):
|
||||
apps_list = "chassis_snat_app.ChassisSNATApp"
|
||||
apps_list = "chassis_snat"
|
||||
external_host_ip = '172.24.4.100'
|
||||
|
||||
def setUp(self):
|
||||
|
|
|
@ -22,7 +22,7 @@ make_fake_local_port = test_app_base.make_fake_local_port
|
|||
|
||||
|
||||
class TestClassifierApp(test_app_base.DFAppTestBase):
|
||||
apps_list = "classifier_app.ClassifierApp"
|
||||
apps_list = "classifier"
|
||||
|
||||
def setUp(self):
|
||||
super(TestClassifierApp, self).setUp()
|
||||
|
|
|
@ -36,7 +36,7 @@ class _ModelNoEvents(model_framework.ModelBase, mixins.Version):
|
|||
|
||||
class DfLocalControllerTestCase(test_app_base.DFAppTestBase):
|
||||
|
||||
apps_list = "l2_app.L2App"
|
||||
apps_list = "l2"
|
||||
|
||||
@mock.patch.object(ryu_base_app.RyuDFAdapter, 'notify_ovs_sync_finished')
|
||||
def test_ovs_sync_finished(self, mock_notify):
|
||||
|
|
|
@ -32,7 +32,7 @@ class Option(object):
|
|||
|
||||
|
||||
class TestDHCPApp(test_app_base.DFAppTestBase):
|
||||
apps_list = "dhcp_app.DHCPApp"
|
||||
apps_list = "dhcp"
|
||||
|
||||
def setUp(self):
|
||||
super(TestDHCPApp, self).setUp()
|
||||
|
|
|
@ -30,7 +30,7 @@ class TestAppDispatcher(tests_base.BaseTestCase):
|
|||
|
||||
def setUp(self):
|
||||
super(TestAppDispatcher, self).setUp()
|
||||
self.dispatcher = dispatcher.AppDispatcher("", "")
|
||||
self.dispatcher = dispatcher.AppDispatcher("")
|
||||
|
||||
def test_dispatch_with_exception(self):
|
||||
fake_app = mock.MagicMock()
|
||||
|
|
|
@ -46,7 +46,7 @@ remote_lport.is_local = False
|
|||
|
||||
|
||||
class TestDNATApp(test_app_base.DFAppTestBase):
|
||||
apps_list = "dnat_app.DNATApp"
|
||||
apps_list = "dnat"
|
||||
|
||||
def setUp(self):
|
||||
super(TestDNATApp, self).setUp(enable_selective_topo_dist=True)
|
||||
|
|
|
@ -21,7 +21,7 @@ from dragonflow.tests.unit import test_app_base
|
|||
|
||||
|
||||
class TestL2App(test_app_base.DFAppTestBase):
|
||||
apps_list = "l2_app.L2App"
|
||||
apps_list = "l2"
|
||||
|
||||
def setUp(self):
|
||||
super(TestL2App, self).setUp()
|
||||
|
|
|
@ -23,7 +23,7 @@ from dragonflow.tests.unit import test_app_base
|
|||
|
||||
class TestL3App(test_app_base.DFAppTestBase,
|
||||
_test_l3.L3AppTestCaseMixin):
|
||||
apps_list = "l3_app.L3App"
|
||||
apps_list = "l3_reactive"
|
||||
|
||||
def setUp(self):
|
||||
super(TestL3App, self).setUp()
|
||||
|
|
|
@ -24,7 +24,7 @@ from dragonflow.tests.unit import test_app_base
|
|||
|
||||
class TestL3ProactiveApp(test_app_base.DFAppTestBase,
|
||||
_test_l3.L3AppTestCaseMixin):
|
||||
apps_list = "l3_proactive_app.L3ProactiveApp"
|
||||
apps_list = "l3_proactive"
|
||||
|
||||
def setUp(self):
|
||||
super(TestL3ProactiveApp, self).setUp()
|
||||
|
|
|
@ -20,7 +20,7 @@ from dragonflow.tests.unit import test_app_base
|
|||
|
||||
|
||||
class TestLegacySNatApp(test_app_base.DFAppTestBase):
|
||||
apps_list = "legacy_snat_app.LegacySNatApp"
|
||||
apps_list = "legacy_snat"
|
||||
|
||||
def setUp(self):
|
||||
super(TestLegacySNatApp, self).setUp()
|
||||
|
|
|
@ -25,7 +25,7 @@ from dragonflow.tests.unit import test_app_base
|
|||
|
||||
|
||||
class TestMetadataServiceApp(test_app_base.DFAppTestBase):
|
||||
apps_list = "metadata_service_app.MetadataServiceApp"
|
||||
apps_list = "metadata_service"
|
||||
|
||||
def setUp(self):
|
||||
super(TestMetadataServiceApp, self).setUp()
|
||||
|
|
|
@ -18,7 +18,7 @@ from dragonflow.tests.unit import test_app_base
|
|||
|
||||
|
||||
class TestMigrationApp(test_app_base.DFAppTestBase):
|
||||
apps_list = "migration_app.MigrationApp"
|
||||
apps_list = "migration"
|
||||
|
||||
def test_update_migration_flows(self):
|
||||
cfg.CONF.set_override('host', 'fake-local-host')
|
||||
|
|
|
@ -23,7 +23,7 @@ make_fake_remote_port = test_app_base.make_fake_remote_port
|
|||
|
||||
|
||||
class TestProviderNetsApp(test_app_base.DFAppTestBase):
|
||||
apps_list = "provider_networks_app.ProviderNetworksApp"
|
||||
apps_list = "provider"
|
||||
|
||||
def setUp(self):
|
||||
super(TestProviderNetsApp, self).setUp()
|
||||
|
|
|
@ -27,7 +27,7 @@ COMMAND_DELETE = 2
|
|||
|
||||
|
||||
class TestSGApp(test_app_base.DFAppTestBase):
|
||||
apps_list = "sg_app.SGApp"
|
||||
apps_list = "sg"
|
||||
|
||||
def setUp(self):
|
||||
super(TestSGApp, self).setUp()
|
||||
|
|
|
@ -50,7 +50,7 @@ def nb_api_get_all_func(*instances):
|
|||
class TestTopology(test_app_base.DFAppTestBase):
|
||||
# This is to comply the current code, as the app_list can't be empty.
|
||||
# But we don't need any app in this test, acutally.
|
||||
apps_list = "l2_app.L2App"
|
||||
apps_list = "l2"
|
||||
|
||||
def setUp(self):
|
||||
cfg.CONF.set_override('enable_selective_topology_distribution',
|
||||
|
|
|
@ -41,7 +41,7 @@ class SettingMock(object):
|
|||
|
||||
|
||||
class TestTrunkApp(test_app_base.DFAppTestBase):
|
||||
apps_list = "trunk_app.TrunkApp"
|
||||
apps_list = "trunk"
|
||||
|
||||
def setUp(self):
|
||||
super(TestTrunkApp, self).setUp()
|
||||
|
|
|
@ -23,7 +23,7 @@ make_fake_remote_port = test_app_base.make_fake_remote_port
|
|||
|
||||
|
||||
class TestTunnelingApp(test_app_base.DFAppTestBase):
|
||||
apps_list = "tunneling_app.TunnelingApp"
|
||||
apps_list = "tunneling"
|
||||
|
||||
def setUp(self):
|
||||
super(TestTunnelingApp, self).setUp()
|
||||
|
|
19
setup.cfg
19
setup.cfg
|
@ -75,3 +75,22 @@ neutron.service_plugins =
|
|||
df-bgp = dragonflow.neutron.services.bgp.bgp_plugin:DFBgpPlugin
|
||||
oslo.config.opts =
|
||||
dragonflow.conf = dragonflow.conf.opts:list_opts
|
||||
dragonflow.controller.apps =
|
||||
active_port_detection = dragonflow.controller.active_port_detection_app:ActivePortDetectionApp
|
||||
aging = dragonflow.controller.aging_app:Aging
|
||||
chassis_snat = dragonflow.controller.chassis_snat_app:ChassisSNATApp
|
||||
classifier = dragonflow.controller.classifier_app:ClassifierApp
|
||||
dhcp = dragonflow.controller.dhcp_app:DHCPApp
|
||||
dnat = dragonflow.controller.dnat_app:DNATApp
|
||||
l2 = dragonflow.controller.l2_app:L2App
|
||||
legacy_snat = dragonflow.controller.legacy_snat_app:LegacySNatApp
|
||||
l3_proactive = dragonflow.controller.l3_proactive_app:L3ProactiveApp
|
||||
l3_reactive = dragonflow.controller.l3_app:L3App
|
||||
metadata_service = dragonflow.controller.metadata_service_app:MetadataServiceApp
|
||||
migration = dragonflow.controller.migration_app:MigrationApp
|
||||
portqos = dragonflow.controller.portqos_app:PortQosApp
|
||||
portsec = dragonflow.controller.portsec_app:PortSecApp
|
||||
provider = dragonflow.controller.provider_networks_app:ProviderNetworksApp
|
||||
sg = dragonflow.controller.sg_app:SGApp
|
||||
trunk = dragonflow.controller.trunk_app:TrunkApp
|
||||
tunneling = dragonflow.controller.tunneling_app:TunnelingApp
|
||||
|
|
Loading…
Reference in New Issue