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