+-------------------------------+-----------------------+-----------+------------------+---------+--------------+
| networking-hyperv_ | | | | | |
+-------------------------------+-----------------------+-----------+------------------+---------+--------------+
-| networking-metaplugin_ | | | | | |
+| networking-metaplugin_ | core | no | no | [C] | Kilo |
+-------------------------------+-----------------------+-----------+------------------+---------+--------------+
| networking-midonet_ | | | | | |
+-------------------------------+-----------------------+-----------+------------------+---------+--------------+
.. _networking-metaplugin:
+Metaplugin
+----------
+
+* Git: https://github.com/ntt-sic/networking-metaplugin
+
.. _networking-midonet:
.. _networking-mlnx:
-# -- Background
-
-This plugin supports multiple plugin at same time. This plugin is for L3 connectivility
-between networks which are realized by different plugins.This plugin adds new attributes 'flavor:network' and 'flavor:router".
-flavor:network corresponds to specific l2 plugin ( flavor-plugin mapping could be configurable by plugin_list config.
-flavor:router corresponds to specific l3 plugin ( flavor-plugin mapping could be configurable by l3_plugin_list config. Note that Metaplugin can provide l3 functionaliteis for l2 plugin which didn't support l3 extension yet.
-This plugin also support extensions. We can map extension to plugin by using extension_map config.
-
-[database]
-# This line MUST be changed to actually run the plugin.
-# Example:
-# connection = mysql://root:nova@127.0.0.1:3306/ovs_neutron
-# Replace 127.0.0.1 above with the IP address of the database used by the
-# main neutron server. (Leave it as is if the database runs on this host.)
-connection = mysql://root:password@localhost/neutron_metaplugin?charset=utf8
-
-# Database reconnection retry times - in event connectivity is lost
-# set to -1 implgies an infinite retry count
-# max_retries = 10
-# Database reconnection interval in seconds - in event connectivity is lost
-retry_interval = 2
-
-[meta]
-## This is list of flavor:neutron_plugins
-# extension method is used in the order of this list
-plugin_list= 'openvswitch:neutron.plugins.openvswitch.ovs_neutron_plugin.OVSneutronPluginV2,linuxbridge:neutron.plugins.linuxbridge.lb_neutron_plugin.LinuxBridgePluginV2'
-# plugin for l3
-l3_plugin_list= 'openvswitch:neutron.plugins.openvswitch.ovs_neutron_plugin.OVSneutronPluginV2,linuxbridge:neutron.plugins.linuxbridge.lb_neutron_plugin.LinuxBridgePluginV2'
-
-# Default value of flavor
-default_flavor = 'openvswitch'
-# Default value for l3
-default_l3_flavor = 'openvswitch'
-
-# supported extensions
-supported_extension_aliases = 'providernet'
-# specific method map for each flavor to extensions
-extension_map = 'get_port_stats:nvp'
-
-# -- BridgeDriver Configration
-# In order to use metaplugin, you should use MetaDriver. Following configation is needed.
-
-[DEFAULT]
-# Meta Plugin
-# Mapping between flavor and driver
-meta_flavor_driver_mappings = openvswitch:neutron.agent.linux.interface.OVSInterfaceDriver, linuxbridge:neutron.agent.linux.interface.BridgeInterfaceDriver
-# interface driver for MetaPlugin
-interface_driver = neutron.agent.linux.interface.MetaInterfaceDriver
-
-[proxy]
-auth_url = http://10.0.0.1:35357/v2.0
-auth_region = RegionOne
-admin_tenant_name = service
-admin_user = neutron
-admin_password = password
-
-
-# -- Agent
-Agents for Metaplugin are in neutron/plugins/metaplugin/agent
-linuxbridge_neutron_agent and ovs_neutron_agent is available.
-
-# -- Extensions
-
-- flavor
-MetaPlugin supports flavor and provider net extension.
-Metaplugin select plugin_list using flavor.
-One plugin may use multiple flavor value. If the plugin support flavor, it may provide
-multiple flavor of network.
-
-- Attribute extension
-Each plugin can use attribute extension such as provider_net, if you specify that in supported_extension_aliases.
-
-- providernet
-Vlan ID range of each plugin should be different, since Metaplugin dose not manage that.
-
-#- limitations
-
-Basically, All plugin should inherit NeutronDbPluginV2.
-Metaplugin assumes all plugin share same Database especially for IPAM part in NeutronV2 API.
-You can use another plugin if you use ProxyPluginV2, which proxies request to the another neutron server.
-
-Example flavor configration for ProxyPluginV2
-
-meta_flavor_driver_mappings = "openvswitch:neutron.agent.linux.interface.OVSInterfaceDriver,proxy:neutron.plugins.metaplugin.proxy_neutron_plugin.ProxyPluginV2"
-
-- Limited L3 support
-In folsom version, l3 is an extension. There is no way to extend exntension attributes.
-so you can set flavor:router value but you can't get flavor:router value in API output.
-L3 agent dont's support flavor:router.
-
-
+# NOTE
+The main source codes of Metaplugin is now in https://github.com/ntt-sic/networking-metaplugin.
+They were moved from Neutron tree to there according to core-vendor-decomposition.
+Defining config and DB are still here according to the decomposition policy.
+Codes of 'flavor' extension and interface driver used by *-agent remain in Neutron tree too.
+++ /dev/null
-# Copyright 2012, Nachi Ueno, NTT MCL, Inc.
-# All Rights Reserved.
-#
-# 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 sqlalchemy.orm import exc
-
-from neutron.plugins.metaplugin import meta_models_v2
-
-
-def get_flavor_by_network(session, net_id):
- try:
- binding = (session.query(meta_models_v2.NetworkFlavor).
- filter_by(network_id=net_id).
- one())
- except exc.NoResultFound:
- return None
- return binding.flavor
-
-
-def add_network_flavor_binding(session, flavor, net_id):
- binding = meta_models_v2.NetworkFlavor(flavor=flavor, network_id=net_id)
- session.add(binding)
- return binding
-
-
-def get_flavor_by_router(session, router_id):
- try:
- binding = (session.query(meta_models_v2.RouterFlavor).
- filter_by(router_id=router_id).
- one())
- except exc.NoResultFound:
- return None
- return binding.flavor
-
-
-def add_router_flavor_binding(session, flavor, router_id):
- binding = meta_models_v2.RouterFlavor(flavor=flavor, router_id=router_id)
- session.add(binding)
- return binding
# License for the specific language governing permissions and limitations
# under the License.
-from oslo_config import cfg
-from oslo_utils import importutils
+from metaplugin.plugin import meta_neutron_plugin
-from neutron.common import exceptions as exc
-from neutron.common import topics
-from neutron import context as neutron_context
-from neutron.db import db_base_plugin_v2
-from neutron.db import external_net_db
-from neutron.db import extraroute_db
-from neutron.db import l3_db
-from neutron.db import models_v2
-from neutron.extensions import flavor as ext_flavor
-from neutron.i18n import _LE
-from neutron.openstack.common import log as logging
-from neutron.plugins.metaplugin.common import config # noqa
-from neutron.plugins.metaplugin import meta_db_v2
-from neutron.plugins.metaplugin import meta_models_v2
-
-LOG = logging.getLogger(__name__)
-
-
-# Hooks used to select records which belong a target plugin.
-def _meta_network_model_hook(context, original_model, query):
- return query.outerjoin(meta_models_v2.NetworkFlavor,
- meta_models_v2.NetworkFlavor.network_id ==
- models_v2.Network.id)
-
-
-def _meta_port_model_hook(context, original_model, query):
- return query.join(meta_models_v2.NetworkFlavor,
- meta_models_v2.NetworkFlavor.network_id ==
- models_v2.Port.network_id)
-
-
-def _meta_flavor_filter_hook(query, filters):
- if ext_flavor.FLAVOR_NETWORK in filters:
- return query.filter(meta_models_v2.NetworkFlavor.flavor ==
- filters[ext_flavor.FLAVOR_NETWORK][0])
- return query
-
-
-# Metaplugin Exceptions
-class FlavorNotFound(exc.NotFound):
- message = _("Flavor %(flavor)s could not be found")
-
-
-class FaildToAddFlavorBinding(exc.NeutronException):
- message = _("Failed to add flavor binding")
-
-
-class MetaPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
- external_net_db.External_net_db_mixin,
- extraroute_db.ExtraRoute_db_mixin):
-
- def __init__(self, configfile=None):
- super(MetaPluginV2, self).__init__()
- LOG.debug("Start initializing metaplugin")
- self.supported_extension_aliases = ['flavor', 'external-net']
- if cfg.CONF.META.supported_extension_aliases:
- cfg_aliases = cfg.CONF.META.supported_extension_aliases.split(',')
- self.supported_extension_aliases += cfg_aliases
-
- # Ignore config option overapping
- def _is_opt_registered(opts, opt):
- if opt.dest in opts:
- return True
- else:
- return False
-
- cfg._is_opt_registered = _is_opt_registered
-
- self.plugins = {}
-
- plugin_list = [plugin_set.split(':')
- for plugin_set
- in cfg.CONF.META.plugin_list.split(',')]
- self.rpc_flavor = cfg.CONF.META.rpc_flavor
- topic_save = topics.PLUGIN
- topic_fake = topic_save + '-metaplugin'
- for flavor, plugin_provider in plugin_list:
- # Rename topic used by a plugin other than rpc_flavor during
- # loading the plugin instance if rpc_flavor is specified.
- # This enforces the plugin specified by rpc_flavor is only
- # consumer of 'q-plugin'. It is a bit tricky but there is no
- # bad effect.
- if self.rpc_flavor and self.rpc_flavor != flavor:
- topics.PLUGIN = topic_fake
- self.plugins[flavor] = self._load_plugin(plugin_provider)
- topics.PLUGIN = topic_save
-
- self.l3_plugins = {}
- if cfg.CONF.META.l3_plugin_list:
- l3_plugin_list = [plugin_set.split(':')
- for plugin_set
- in cfg.CONF.META.l3_plugin_list.split(',')]
- for flavor, plugin_provider in l3_plugin_list:
- if flavor in self.plugins:
- self.l3_plugins[flavor] = self.plugins[flavor]
- else:
- # For l3 only plugin
- self.l3_plugins[flavor] = self._load_plugin(
- plugin_provider)
-
- self.default_flavor = cfg.CONF.META.default_flavor
- if self.default_flavor not in self.plugins:
- raise exc.Invalid(_('default_flavor %s is not plugin list') %
- self.default_flavor)
-
- if self.l3_plugins:
- self.default_l3_flavor = cfg.CONF.META.default_l3_flavor
- if self.default_l3_flavor not in self.l3_plugins:
- raise exc.Invalid(_('default_l3_flavor %s is not plugin list')
- % self.default_l3_flavor)
- self.supported_extension_aliases += ['router', 'ext-gw-mode',
- 'extraroute']
-
- if self.rpc_flavor and self.rpc_flavor not in self.plugins:
- raise exc.Invalid(_('rpc_flavor %s is not plugin list') %
- self.rpc_flavor)
-
- self.extension_map = {}
- if not cfg.CONF.META.extension_map == '':
- extension_list = [method_set.split(':')
- for method_set
- in cfg.CONF.META.extension_map.split(',')]
- for method_name, flavor in extension_list:
- self.extension_map[method_name] = flavor
-
- # Register hooks.
- # The hooks are applied for each target plugin instance when
- # calling the base class to get networks/ports so that only records
- # which belong to the plugin are selected.
- #NOTE: Doing registration here (within __init__()) is to avoid
- # registration when merely importing this file. This is only
- # for running whole unit tests.
- db_base_plugin_v2.NeutronDbPluginV2.register_model_query_hook(
- models_v2.Network,
- 'metaplugin_net',
- _meta_network_model_hook,
- None,
- _meta_flavor_filter_hook)
- db_base_plugin_v2.NeutronDbPluginV2.register_model_query_hook(
- models_v2.Port,
- 'metaplugin_port',
- _meta_port_model_hook,
- None,
- _meta_flavor_filter_hook)
-
- def _load_plugin(self, plugin_provider):
- LOG.debug("Plugin location: %s", plugin_provider)
- plugin_klass = importutils.import_class(plugin_provider)
- return plugin_klass()
-
- def _get_plugin(self, flavor):
- if flavor not in self.plugins:
- raise FlavorNotFound(flavor=flavor)
- return self.plugins[flavor]
-
- def _get_l3_plugin(self, flavor):
- if flavor not in self.l3_plugins:
- raise FlavorNotFound(flavor=flavor)
- return self.l3_plugins[flavor]
-
- def __getattr__(self, key):
- # At first, try to pickup extension command from extension_map
-
- if key in self.extension_map:
- flavor = self.extension_map[key]
- plugin = self._get_plugin(flavor)
- if plugin and hasattr(plugin, key):
- return getattr(plugin, key)
-
- # Second, try to match extension method in order of plugin list
- for flavor, plugin in self.plugins.items():
- if hasattr(plugin, key):
- return getattr(plugin, key)
-
- # if no plugin support the method, then raise
- raise AttributeError()
-
- def _extend_network_dict(self, context, network):
- flavor = self._get_flavor_by_network_id(context, network['id'])
- network[ext_flavor.FLAVOR_NETWORK] = flavor
-
- def start_rpc_listeners(self):
- return self.plugins[self.rpc_flavor].start_rpc_listeners()
-
- def rpc_workers_supported(self):
- #NOTE: If a plugin which supports multiple RPC workers is desired
- # to handle RPC, rpc_flavor must be specified.
- return (self.rpc_flavor and
- self.plugins[self.rpc_flavor].rpc_workers_supported())
-
- def create_network(self, context, network):
- n = network['network']
- flavor = n.get(ext_flavor.FLAVOR_NETWORK)
- if str(flavor) not in self.plugins:
- flavor = self.default_flavor
- plugin = self._get_plugin(flavor)
- net = plugin.create_network(context, network)
- LOG.debug("Created network: %(net_id)s with flavor "
- "%(flavor)s", {'net_id': net['id'], 'flavor': flavor})
- try:
- meta_db_v2.add_network_flavor_binding(context.session,
- flavor, str(net['id']))
- except Exception:
- LOG.exception(_LE('Failed to add flavor bindings'))
- plugin.delete_network(context, net['id'])
- raise FaildToAddFlavorBinding()
-
- LOG.debug("Created network: %s", net['id'])
- self._extend_network_dict(context, net)
- return net
-
- def update_network(self, context, id, network):
- flavor = meta_db_v2.get_flavor_by_network(context.session, id)
- plugin = self._get_plugin(flavor)
- return plugin.update_network(context, id, network)
-
- def delete_network(self, context, id):
- flavor = meta_db_v2.get_flavor_by_network(context.session, id)
- plugin = self._get_plugin(flavor)
- return plugin.delete_network(context, id)
-
- def get_network(self, context, id, fields=None):
- flavor = meta_db_v2.get_flavor_by_network(context.session, id)
- plugin = self._get_plugin(flavor)
- net = plugin.get_network(context, id, fields)
- net['id'] = id
- if not fields or ext_flavor.FLAVOR_NETWORK in fields:
- self._extend_network_dict(context, net)
- if fields and 'id' not in fields:
- del net['id']
- return net
-
- def get_networks(self, context, filters=None, fields=None):
- nets = []
- for flavor, plugin in self.plugins.items():
- if (filters and ext_flavor.FLAVOR_NETWORK in filters and
- flavor not in filters[ext_flavor.FLAVOR_NETWORK]):
- continue
- if filters:
- #NOTE: copy each time since a target plugin may modify
- # plugin_filters.
- plugin_filters = filters.copy()
- else:
- plugin_filters = {}
- plugin_filters[ext_flavor.FLAVOR_NETWORK] = [flavor]
- plugin_nets = plugin.get_networks(context, plugin_filters, fields)
- for net in plugin_nets:
- if not fields or ext_flavor.FLAVOR_NETWORK in fields:
- net[ext_flavor.FLAVOR_NETWORK] = flavor
- nets.append(net)
- return nets
-
- def _get_flavor_by_network_id(self, context, network_id):
- return meta_db_v2.get_flavor_by_network(context.session, network_id)
-
- def _get_flavor_by_router_id(self, context, router_id):
- return meta_db_v2.get_flavor_by_router(context.session, router_id)
-
- def _get_plugin_by_network_id(self, context, network_id):
- flavor = self._get_flavor_by_network_id(context, network_id)
- return self._get_plugin(flavor)
-
- def create_port(self, context, port):
- p = port['port']
- if 'network_id' not in p:
- raise exc.NotFound()
- plugin = self._get_plugin_by_network_id(context, p['network_id'])
- return plugin.create_port(context, port)
-
- def update_port(self, context, id, port):
- port_in_db = self._get_port(context, id)
- plugin = self._get_plugin_by_network_id(context,
- port_in_db['network_id'])
- return plugin.update_port(context, id, port)
-
- def delete_port(self, context, id, l3_port_check=True):
- port_in_db = self._get_port(context, id)
- plugin = self._get_plugin_by_network_id(context,
- port_in_db['network_id'])
- return plugin.delete_port(context, id, l3_port_check)
-
- # This is necessary since there is a case that
- # NeutronManager.get_plugin()._make_port_dict is called.
- def _make_port_dict(self, port):
- context = neutron_context.get_admin_context()
- plugin = self._get_plugin_by_network_id(context,
- port['network_id'])
- return plugin._make_port_dict(port)
-
- def get_port(self, context, id, fields=None):
- port_in_db = self._get_port(context, id)
- plugin = self._get_plugin_by_network_id(context,
- port_in_db['network_id'])
- return plugin.get_port(context, id, fields)
-
- def get_ports(self, context, filters=None, fields=None):
- all_ports = []
- for flavor, plugin in self.plugins.items():
- if filters:
- #NOTE: copy each time since a target plugin may modify
- # plugin_filters.
- plugin_filters = filters.copy()
- else:
- plugin_filters = {}
- plugin_filters[ext_flavor.FLAVOR_NETWORK] = [flavor]
- ports = plugin.get_ports(context, plugin_filters, fields)
- all_ports += ports
- return all_ports
-
- def create_subnet(self, context, subnet):
- s = subnet['subnet']
- if 'network_id' not in s:
- raise exc.NotFound()
- plugin = self._get_plugin_by_network_id(context,
- s['network_id'])
- return plugin.create_subnet(context, subnet)
-
- def update_subnet(self, context, id, subnet):
- s = self.get_subnet(context, id)
- plugin = self._get_plugin_by_network_id(context,
- s['network_id'])
- return plugin.update_subnet(context, id, subnet)
-
- def delete_subnet(self, context, id):
- s = self.get_subnet(context, id)
- plugin = self._get_plugin_by_network_id(context,
- s['network_id'])
- return plugin.delete_subnet(context, id)
-
- def _extend_router_dict(self, context, router):
- flavor = self._get_flavor_by_router_id(context, router['id'])
- router[ext_flavor.FLAVOR_ROUTER] = flavor
-
- def create_router(self, context, router):
- r = router['router']
- flavor = r.get(ext_flavor.FLAVOR_ROUTER)
- if str(flavor) not in self.l3_plugins:
- flavor = self.default_l3_flavor
- plugin = self._get_l3_plugin(flavor)
- r_in_db = plugin.create_router(context, router)
- LOG.debug("Created router: %(router_id)s with flavor "
- "%(flavor)s",
- {'router_id': r_in_db['id'], 'flavor': flavor})
- try:
- meta_db_v2.add_router_flavor_binding(context.session,
- flavor, str(r_in_db['id']))
- except Exception:
- LOG.exception(_LE('Failed to add flavor bindings'))
- plugin.delete_router(context, r_in_db['id'])
- raise FaildToAddFlavorBinding()
-
- LOG.debug("Created router: %s", r_in_db['id'])
- self._extend_router_dict(context, r_in_db)
- return r_in_db
-
- def update_router(self, context, id, router):
- flavor = meta_db_v2.get_flavor_by_router(context.session, id)
- plugin = self._get_l3_plugin(flavor)
- return plugin.update_router(context, id, router)
-
- def delete_router(self, context, id):
- flavor = meta_db_v2.get_flavor_by_router(context.session, id)
- plugin = self._get_l3_plugin(flavor)
- return plugin.delete_router(context, id)
-
- def get_router(self, context, id, fields=None):
- flavor = meta_db_v2.get_flavor_by_router(context.session, id)
- plugin = self._get_l3_plugin(flavor)
- router = plugin.get_router(context, id, fields)
- if not fields or ext_flavor.FLAVOR_ROUTER in fields:
- self._extend_router_dict(context, router)
- return router
-
- def get_routers_with_flavor(self, context, filters=None,
- fields=None):
- collection = self._model_query(context, l3_db.Router)
- r_model = meta_models_v2.RouterFlavor
- collection = collection.join(r_model,
- l3_db.Router.id == r_model.router_id)
- if filters:
- for key, value in filters.iteritems():
- if key == ext_flavor.FLAVOR_ROUTER:
- column = meta_models_v2.RouterFlavor.flavor
- else:
- column = getattr(l3_db.Router, key, None)
- if column:
- collection = collection.filter(column.in_(value))
- return [self._make_router_dict(c, fields) for c in collection]
-
- def get_routers(self, context, filters=None, fields=None):
- routers = self.get_routers_with_flavor(context, filters,
- None)
- return [self.get_router(context, router['id'],
- fields)
- for router in routers]
+MetaPluginV2 = meta_neutron_plugin.MetaPluginV2
# License for the specific language governing permissions and limitations
# under the License.
-from oslo_config import cfg
+from metaplugin.plugin import proxy_neutron_plugin
-from neutron.db import db_base_plugin_v2
-from neutron.db import external_net_db
-from neutron.db import l3_db
-from neutron.i18n import _LE, _LW
-from neutron.openstack.common import log as logging
-from neutronclient.common import exceptions
-from neutronclient.v2_0 import client
-
-LOG = logging.getLogger(__name__)
-
-
-class ProxyPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
- external_net_db.External_net_db_mixin,
- l3_db.L3_NAT_db_mixin):
- supported_extension_aliases = ["external-net", "router"]
-
- def __init__(self, configfile=None):
- super(ProxyPluginV2, self).__init__()
- self.neutron = client.Client(
- username=cfg.CONF.PROXY.admin_user,
- password=cfg.CONF.PROXY.admin_password,
- tenant_name=cfg.CONF.PROXY.admin_tenant_name,
- auth_url=cfg.CONF.PROXY.auth_url,
- auth_strategy=cfg.CONF.PROXY.auth_strategy,
- region_name=cfg.CONF.PROXY.auth_region
- )
-
- def _get_client(self):
- return self.neutron
-
- def create_subnet(self, context, subnet):
- subnet_remote = self._get_client().create_subnet(subnet)
- subnet['subnet']['id'] = subnet_remote['id']
- tenant_id = self._get_tenant_id_for_create(context, subnet['subnet'])
- subnet['subnet']['tenant_id'] = tenant_id
- try:
- subnet_in_db = super(ProxyPluginV2, self).create_subnet(
- context, subnet)
- except Exception:
- self._get_client().delete_subnet(subnet_remote['id'])
- return subnet_in_db
-
- def update_subnet(self, context, id, subnet):
- subnet_in_db = super(ProxyPluginV2, self).update_subnet(
- context, id, subnet)
- try:
- self._get_client().update_subnet(id, subnet)
- except Exception as e:
- LOG.error(_LE("Update subnet failed: %s"), e)
- return subnet_in_db
-
- def delete_subnet(self, context, id):
- try:
- self._get_client().delete_subnet(id)
- except exceptions.NotFound:
- LOG.warn(_LW("Subnet in remote have already deleted"))
- return super(ProxyPluginV2, self).delete_subnet(context, id)
-
- def create_network(self, context, network):
- network_remote = self._get_client().create_network(network)
- network['network']['id'] = network_remote['id']
- tenant_id = self._get_tenant_id_for_create(context, network['network'])
- network['network']['tenant_id'] = tenant_id
- try:
- network_in_db = super(ProxyPluginV2, self).create_network(
- context, network)
- except Exception:
- self._get_client().delete_network(network_remote['id'])
- return network_in_db
-
- def update_network(self, context, id, network):
- network_in_db = super(ProxyPluginV2, self).update_network(
- context, id, network)
- try:
- self._get_client().update_network(id, network)
- except Exception as e:
- LOG.error(_LE("Update network failed: %s"), e)
- return network_in_db
-
- def delete_network(self, context, id):
- try:
- self._get_client().delete_network(id)
- except exceptions.NetworkNotFoundClient:
- LOG.warn(_LW("Network in remote have already deleted"))
- return super(ProxyPluginV2, self).delete_network(context, id)
-
- def create_port(self, context, port):
- port_remote = self._get_client().create_port(port)
- port['port']['id'] = port_remote['id']
- tenant_id = self._get_tenant_id_for_create(context, port['port'])
- port['port']['tenant_id'] = tenant_id
- try:
- port_in_db = super(ProxyPluginV2, self).create_port(
- context, port)
- except Exception:
- self._get_client().delete_port(port_remote['id'])
- return port_in_db
-
- def update_port(self, context, id, port):
- port_in_db = super(ProxyPluginV2, self).update_port(
- context, id, port)
- try:
- self._get_client().update_port(id, port)
- except Exception as e:
- LOG.error(_LE("Update port failed: %s"), e)
- return port_in_db
-
- def delete_port(self, context, id, l3_port_check=True):
- if l3_port_check:
- self.prevent_l3_port_deletion(context, id)
- self.disassociate_floatingips(context, id)
-
- try:
- self._get_client().delete_port(id)
- except exceptions.PortNotFoundClient:
- LOG.warn(_LW("Port in remote have already deleted"))
- return super(ProxyPluginV2, self).delete_port(context, id)
+ProxyPluginV2 = proxy_neutron_plugin.ProxyPluginV2
+++ /dev/null
-# Copyright 2012, Nachi Ueno, NTT MCL, Inc.
-#
-# 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 neutron.db import db_base_plugin_v2
-from neutron.db import external_net_db
-from neutron.db import l3_gwmode_db
-
-
-class Fake1(db_base_plugin_v2.NeutronDbPluginV2,
- external_net_db.External_net_db_mixin,
- l3_gwmode_db.L3_NAT_db_mixin):
- supported_extension_aliases = ['external-net', 'router']
-
- def fake_func(self):
- return 'fake1'
-
- def create_network(self, context, network):
- session = context.session
- with session.begin(subtransactions=True):
- net = super(Fake1, self).create_network(context, network)
- self._process_l3_create(context, net, network['network'])
- return net
-
- def update_network(self, context, id, network):
- session = context.session
- with session.begin(subtransactions=True):
- net = super(Fake1, self).update_network(context, id,
- network)
- self._process_l3_update(context, net, network['network'])
- return net
-
- def delete_network(self, context, id):
- session = context.session
- with session.begin(subtransactions=True):
- self._process_l3_delete(context, id)
- return super(Fake1, self).delete_network(context, id)
-
- def create_port(self, context, port):
- port = super(Fake1, self).create_port(context, port)
- return port
-
- def create_subnet(self, context, subnet):
- subnet = super(Fake1, self).create_subnet(context, subnet)
- return subnet
-
- def update_port(self, context, id, port):
- port = super(Fake1, self).update_port(context, id, port)
- return port
-
- def delete_port(self, context, id, l3_port_check=True):
- if l3_port_check:
- self.prevent_l3_port_deletion(context, id)
- self.disassociate_floatingips(context, id)
- return super(Fake1, self).delete_port(context, id)
-
-
-class Fake2(Fake1):
- def fake_func(self):
- return 'fake2'
-
- def fake_func2(self):
- return 'fake2'
-
- def start_rpc_listeners(self):
- # return value is only used to confirm this method was called.
- return 'OK'
+++ /dev/null
-# Copyright (c) 2012 OpenStack Foundation.
-#
-# 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 neutron.tests.unit.metaplugin import test_metaplugin
-from neutron.tests.unit import test_db_plugin as test_plugin
-from neutron.tests.unit import test_l3_plugin
-
-
-class MetaPluginV2DBTestCase(test_plugin.NeutronDbPluginV2TestCase):
-
- _plugin_name = ('neutron.plugins.metaplugin.'
- 'meta_neutron_plugin.MetaPluginV2')
-
- def setUp(self, plugin=None, ext_mgr=None,
- service_plugins=None):
- # NOTE(salv-orlando): The plugin keyword argument is ignored,
- # as this class will always invoke super with self._plugin_name.
- # These keyword parameters ensure setUp methods always have the
- # same signature.
- test_metaplugin.setup_metaplugin_conf()
- ext_mgr = ext_mgr or test_l3_plugin.L3TestExtensionManager()
- self.addCleanup(test_metaplugin.unregister_meta_hooks)
- super(MetaPluginV2DBTestCase, self).setUp(
- plugin=self._plugin_name, ext_mgr=ext_mgr,
- service_plugins=service_plugins)
-
-
-class TestMetaBasicGet(test_plugin.TestBasicGet,
- MetaPluginV2DBTestCase):
- pass
-
-
-class TestMetaV2HTTPResponse(test_plugin.TestV2HTTPResponse,
- MetaPluginV2DBTestCase):
- pass
-
-
-class TestMetaPortsV2(test_plugin.TestPortsV2,
- MetaPluginV2DBTestCase):
- pass
-
-
-class TestMetaNetworksV2(test_plugin.TestNetworksV2,
- MetaPluginV2DBTestCase):
- pass
-
-
-class TestMetaSubnetsV2(test_plugin.TestSubnetsV2,
- MetaPluginV2DBTestCase):
- #TODO(nati) This test fails if we run all test, but It success just one
- def test_update_subnet_route(self):
- pass
-
- def test_update_subnet_dns_to_None(self):
- pass
-
- def test_update_subnet_route_to_None(self):
- pass
-
- def test_update_subnet_dns(self):
- pass
-
-
-class TestMetaL3NatDBTestCase(test_l3_plugin.L3NatDBIntTestCase,
- MetaPluginV2DBTestCase):
- pass
+++ /dev/null
-# Copyright 2012, Nachi Ueno, NTT MCL, Inc.
-# All Rights Reserved.
-#
-# 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.
-
-import mock
-from oslo_config import cfg
-import testtools
-
-from neutron.common import exceptions as exc
-from neutron.common import topics
-from neutron import context
-from neutron.db import db_base_plugin_v2
-from neutron.db import models_v2
-from neutron.extensions import flavor as ext_flavor
-from neutron.openstack.common import uuidutils
-from neutron.plugins.metaplugin import meta_neutron_plugin
-from neutron.tests.unit import testlib_api
-from neutron.tests.unit import testlib_plugin
-
-CONF_FILE = ""
-META_PATH = "neutron.plugins.metaplugin"
-FAKE_PATH = "neutron.tests.unit.metaplugin"
-PROXY_PATH = "%s.proxy_neutron_plugin.ProxyPluginV2" % META_PATH
-PLUGIN_LIST = """
-fake1:%s.fake_plugin.Fake1,fake2:%s.fake_plugin.Fake2,proxy:%s
-""".strip() % (FAKE_PATH, FAKE_PATH, PROXY_PATH)
-L3_PLUGIN_LIST = """
-fake1:%s.fake_plugin.Fake1,fake2:%s.fake_plugin.Fake2
-""".strip() % (FAKE_PATH, FAKE_PATH)
-
-
-def setup_metaplugin_conf(has_l3=True):
- cfg.CONF.set_override('auth_url', 'http://localhost:35357/v2.0',
- 'PROXY')
- cfg.CONF.set_override('auth_region', 'RegionOne', 'PROXY')
- cfg.CONF.set_override('admin_user', 'neutron', 'PROXY')
- cfg.CONF.set_override('admin_password', 'password', 'PROXY')
- cfg.CONF.set_override('admin_tenant_name', 'service', 'PROXY')
- cfg.CONF.set_override('plugin_list', PLUGIN_LIST, 'META')
- if has_l3:
- cfg.CONF.set_override('l3_plugin_list', L3_PLUGIN_LIST, 'META')
- else:
- cfg.CONF.set_override('l3_plugin_list', "", 'META')
- cfg.CONF.set_override('default_flavor', 'fake2', 'META')
- cfg.CONF.set_override('default_l3_flavor', 'fake1', 'META')
- cfg.CONF.set_override('base_mac', "12:34:56:78:90:ab")
- #TODO(nati) remove this after subnet quota change is merged
- cfg.CONF.set_override('max_dns_nameservers', 10)
-
-
-# Hooks registered by metaplugin must not exist for other plugins UT.
-# So hooks must be unregistered (overwrite to None in fact).
-def unregister_meta_hooks():
- db_base_plugin_v2.NeutronDbPluginV2.register_model_query_hook(
- models_v2.Network, 'metaplugin_net', None, None, None)
- db_base_plugin_v2.NeutronDbPluginV2.register_model_query_hook(
- models_v2.Port, 'metaplugin_port', None, None, None)
-
-
-class MetaNeutronPluginV2Test(testlib_api.SqlTestCase,
- testlib_plugin.PluginSetupHelper):
- """Class conisting of MetaNeutronPluginV2 unit tests."""
-
- has_l3 = True
-
- def setUp(self):
- super(MetaNeutronPluginV2Test, self).setUp()
- self.fake_tenant_id = uuidutils.generate_uuid()
- self.context = context.get_admin_context()
-
- self.addCleanup(unregister_meta_hooks)
-
- setup_metaplugin_conf(self.has_l3)
-
- self.client_cls_p = mock.patch('neutronclient.v2_0.client.Client')
- client_cls = self.client_cls_p.start()
- self.client_inst = mock.Mock()
- client_cls.return_value = self.client_inst
- self.client_inst.create_network.return_value = \
- {'id': 'fake_id'}
- self.client_inst.create_port.return_value = \
- {'id': 'fake_id'}
- self.client_inst.create_subnet.return_value = \
- {'id': 'fake_id'}
- self.client_inst.update_network.return_value = \
- {'id': 'fake_id'}
- self.client_inst.update_port.return_value = \
- {'id': 'fake_id'}
- self.client_inst.update_subnet.return_value = \
- {'id': 'fake_id'}
- self.client_inst.delete_network.return_value = True
- self.client_inst.delete_port.return_value = True
- self.client_inst.delete_subnet.return_value = True
- plugin = (meta_neutron_plugin.MetaPluginV2.__module__ + '.'
- + meta_neutron_plugin.MetaPluginV2.__name__)
- self.setup_coreplugin(plugin)
- self.plugin = meta_neutron_plugin.MetaPluginV2(configfile=None)
-
- def _fake_network(self, flavor):
- data = {'network': {'name': flavor,
- 'admin_state_up': True,
- 'shared': False,
- 'router:external': [],
- 'tenant_id': self.fake_tenant_id,
- ext_flavor.FLAVOR_NETWORK: flavor}}
- return data
-
- def _fake_port(self, net_id):
- return {'port': {'name': net_id,
- 'network_id': net_id,
- 'admin_state_up': True,
- 'device_id': 'bad_device_id',
- 'device_owner': 'bad_device_owner',
- 'admin_state_up': True,
- 'host_routes': [],
- 'fixed_ips': [],
- 'mac_address': self.plugin._generate_mac(),
- 'tenant_id': self.fake_tenant_id}}
-
- def _fake_subnet(self, net_id):
- allocation_pools = [{'start': '10.0.0.2',
- 'end': '10.0.0.254'}]
- return {'subnet': {'name': net_id,
- 'network_id': net_id,
- 'gateway_ip': '10.0.0.1',
- 'dns_nameservers': ['10.0.0.2'],
- 'host_routes': [],
- 'cidr': '10.0.0.0/24',
- 'allocation_pools': allocation_pools,
- 'enable_dhcp': True,
- 'ip_version': 4}}
-
- def _fake_router(self, flavor):
- data = {'router': {'name': flavor, 'admin_state_up': True,
- 'tenant_id': self.fake_tenant_id,
- ext_flavor.FLAVOR_ROUTER: flavor,
- 'external_gateway_info': None}}
- return data
-
- def test_create_delete_network(self):
- network1 = self._fake_network('fake1')
- ret1 = self.plugin.create_network(self.context, network1)
- self.assertEqual('fake1', ret1[ext_flavor.FLAVOR_NETWORK])
-
- network2 = self._fake_network('fake2')
- ret2 = self.plugin.create_network(self.context, network2)
- self.assertEqual('fake2', ret2[ext_flavor.FLAVOR_NETWORK])
-
- network3 = self._fake_network('proxy')
- ret3 = self.plugin.create_network(self.context, network3)
- self.assertEqual('proxy', ret3[ext_flavor.FLAVOR_NETWORK])
-
- db_ret1 = self.plugin.get_network(self.context, ret1['id'])
- self.assertEqual('fake1', db_ret1['name'])
-
- db_ret2 = self.plugin.get_network(self.context, ret2['id'])
- self.assertEqual('fake2', db_ret2['name'])
-
- db_ret3 = self.plugin.get_network(self.context, ret3['id'])
- self.assertEqual('proxy', db_ret3['name'])
-
- db_ret4 = self.plugin.get_networks(self.context)
- self.assertEqual(3, len(db_ret4))
-
- db_ret5 = self.plugin.get_networks(
- self.context,
- {ext_flavor.FLAVOR_NETWORK: ['fake1']})
- self.assertEqual(1, len(db_ret5))
- self.assertEqual('fake1', db_ret5[0]['name'])
- self.plugin.delete_network(self.context, ret1['id'])
- self.plugin.delete_network(self.context, ret2['id'])
- self.plugin.delete_network(self.context, ret3['id'])
-
- def test_create_delete_port(self):
- network1 = self._fake_network('fake1')
- network_ret1 = self.plugin.create_network(self.context, network1)
- network2 = self._fake_network('fake2')
- network_ret2 = self.plugin.create_network(self.context, network2)
- network3 = self._fake_network('proxy')
- network_ret3 = self.plugin.create_network(self.context, network3)
-
- port1 = self._fake_port(network_ret1['id'])
- port2 = self._fake_port(network_ret2['id'])
- port3 = self._fake_port(network_ret3['id'])
-
- port1_ret = self.plugin.create_port(self.context, port1)
- port2_ret = self.plugin.create_port(self.context, port2)
- port3_ret = self.plugin.create_port(self.context, port3)
- ports_all = self.plugin.get_ports(self.context)
-
- self.assertEqual(network_ret1['id'], port1_ret['network_id'])
- self.assertEqual(network_ret2['id'], port2_ret['network_id'])
- self.assertEqual(network_ret3['id'], port3_ret['network_id'])
- self.assertEqual(3, len(ports_all))
-
- port1_dict = self.plugin._make_port_dict(port1_ret)
- port2_dict = self.plugin._make_port_dict(port2_ret)
- port3_dict = self.plugin._make_port_dict(port3_ret)
-
- self.assertEqual(port1_dict, port1_ret)
- self.assertEqual(port2_dict, port2_ret)
- self.assertEqual(port3_dict, port3_ret)
-
- port1['port']['admin_state_up'] = False
- port2['port']['admin_state_up'] = False
- port3['port']['admin_state_up'] = False
- self.plugin.update_port(self.context, port1_ret['id'], port1)
- self.plugin.update_port(self.context, port2_ret['id'], port2)
- self.plugin.update_port(self.context, port3_ret['id'], port3)
- port_in_db1 = self.plugin.get_port(self.context, port1_ret['id'])
- port_in_db2 = self.plugin.get_port(self.context, port2_ret['id'])
- port_in_db3 = self.plugin.get_port(self.context, port3_ret['id'])
- self.assertEqual(False, port_in_db1['admin_state_up'])
- self.assertEqual(False, port_in_db2['admin_state_up'])
- self.assertEqual(False, port_in_db3['admin_state_up'])
-
- self.plugin.delete_port(self.context, port1_ret['id'])
- self.plugin.delete_port(self.context, port2_ret['id'])
- self.plugin.delete_port(self.context, port3_ret['id'])
-
- self.plugin.delete_network(self.context, network_ret1['id'])
- self.plugin.delete_network(self.context, network_ret2['id'])
- self.plugin.delete_network(self.context, network_ret3['id'])
-
- def test_create_delete_subnet(self):
- # for this test we need to enable overlapping ips
- cfg.CONF.set_default('allow_overlapping_ips', True)
- network1 = self._fake_network('fake1')
- network_ret1 = self.plugin.create_network(self.context, network1)
- network2 = self._fake_network('fake2')
- network_ret2 = self.plugin.create_network(self.context, network2)
- network3 = self._fake_network('proxy')
- network_ret3 = self.plugin.create_network(self.context, network3)
-
- subnet1 = self._fake_subnet(network_ret1['id'])
- subnet2 = self._fake_subnet(network_ret2['id'])
- subnet3 = self._fake_subnet(network_ret3['id'])
-
- subnet1_ret = self.plugin.create_subnet(self.context, subnet1)
- subnet2_ret = self.plugin.create_subnet(self.context, subnet2)
- subnet3_ret = self.plugin.create_subnet(self.context, subnet3)
- self.assertEqual(network_ret1['id'], subnet1_ret['network_id'])
- self.assertEqual(network_ret2['id'], subnet2_ret['network_id'])
- self.assertEqual(network_ret3['id'], subnet3_ret['network_id'])
-
- subnet_in_db1 = self.plugin.get_subnet(self.context, subnet1_ret['id'])
- subnet_in_db2 = self.plugin.get_subnet(self.context, subnet2_ret['id'])
- subnet_in_db3 = self.plugin.get_subnet(self.context, subnet3_ret['id'])
-
- subnet1['subnet']['allocation_pools'].pop()
- subnet2['subnet']['allocation_pools'].pop()
- subnet3['subnet']['allocation_pools'].pop()
-
- self.plugin.update_subnet(self.context,
- subnet1_ret['id'], subnet1)
- self.plugin.update_subnet(self.context,
- subnet2_ret['id'], subnet2)
- self.plugin.update_subnet(self.context,
- subnet3_ret['id'], subnet3)
- subnet_in_db1 = self.plugin.get_subnet(self.context, subnet1_ret['id'])
- subnet_in_db2 = self.plugin.get_subnet(self.context, subnet2_ret['id'])
- subnet_in_db3 = self.plugin.get_subnet(self.context, subnet3_ret['id'])
-
- self.assertEqual(4, subnet_in_db1['ip_version'])
- self.assertEqual(4, subnet_in_db2['ip_version'])
- self.assertEqual(4, subnet_in_db3['ip_version'])
-
- self.plugin.delete_subnet(self.context, subnet1_ret['id'])
- self.plugin.delete_subnet(self.context, subnet2_ret['id'])
- self.plugin.delete_subnet(self.context, subnet3_ret['id'])
-
- self.plugin.delete_network(self.context, network_ret1['id'])
- self.plugin.delete_network(self.context, network_ret2['id'])
- self.plugin.delete_network(self.context, network_ret3['id'])
-
- def test_create_delete_router(self):
- router1 = self._fake_router('fake1')
- router_ret1 = self.plugin.create_router(self.context, router1)
- router2 = self._fake_router('fake2')
- router_ret2 = self.plugin.create_router(self.context, router2)
-
- self.assertEqual('fake1', router_ret1[ext_flavor.FLAVOR_ROUTER])
- self.assertEqual('fake2', router_ret2[ext_flavor.FLAVOR_ROUTER])
-
- router_in_db1 = self.plugin.get_router(self.context, router_ret1['id'])
- router_in_db2 = self.plugin.get_router(self.context, router_ret2['id'])
-
- self.assertEqual('fake1', router_in_db1[ext_flavor.FLAVOR_ROUTER])
- self.assertEqual('fake2', router_in_db2[ext_flavor.FLAVOR_ROUTER])
-
- self.plugin.delete_router(self.context, router_ret1['id'])
- self.plugin.delete_router(self.context, router_ret2['id'])
- with testtools.ExpectedException(meta_neutron_plugin.FlavorNotFound):
- self.plugin.get_router(self.context, router_ret1['id'])
-
- def test_extension_method(self):
- """Test if plugin methods are accessible from self.plugin
-
- This test compensates for the nondeterministic ordering of
- self.plugin's plugins dictionary. Fake Plugin 1 and Fake Plugin 2
- both have a function called fake_func and the order of
- self.plugin.plugins will determine which fake_func is called.
- """
- fake1 = self.plugin.plugins.keys().index('fake1')
- fake2 = self.plugin.plugins.keys().index('fake2')
- fake1_before_fake2 = fake1 < fake2
-
- fake_func_return = 'fake1' if fake1_before_fake2 else 'fake2'
-
- self.assertEqual(fake_func_return, self.plugin.fake_func())
- self.assertEqual('fake2', self.plugin.fake_func2())
-
- def test_extension_not_implemented_method(self):
- try:
- self.plugin.not_implemented()
- except AttributeError:
- return
- except Exception:
- self.fail("AttributeError Error is not raised")
-
- self.fail("No Error is not raised")
-
- def test_create_network_flavor_fail(self):
- with mock.patch('neutron.plugins.metaplugin.meta_db_v2.'
- 'add_network_flavor_binding',
- side_effect=Exception):
- network = self._fake_network('fake1')
- self.assertRaises(meta_neutron_plugin.FaildToAddFlavorBinding,
- self.plugin.create_network,
- self.context,
- network)
- count = self.plugin.get_networks_count(self.context)
- self.assertEqual(count, 0)
-
- def test_create_router_flavor_fail(self):
- with mock.patch('neutron.plugins.metaplugin.meta_db_v2.'
- 'add_router_flavor_binding',
- side_effect=Exception):
- router = self._fake_router('fake1')
- self.assertRaises(meta_neutron_plugin.FaildToAddFlavorBinding,
- self.plugin.create_router,
- self.context,
- router)
- count = self.plugin.get_routers_count(self.context)
- self.assertEqual(count, 0)
-
-
-class MetaNeutronPluginV2TestWithoutL3(MetaNeutronPluginV2Test):
- """Tests without l3_plugin_list configration."""
-
- has_l3 = False
-
- def test_supported_extension_aliases(self):
- self.assertEqual(self.plugin.supported_extension_aliases,
- ['flavor', 'external-net'])
-
- def test_create_delete_router(self):
- self.skipTest("Test case without router")
-
- def test_create_router_flavor_fail(self):
- self.skipTest("Test case without router")
-
-
-class MetaNeutronPluginV2TestRpcFlavor(testlib_api.SqlTestCase):
- """Tests for rpc_flavor."""
-
- def setUp(self):
- super(MetaNeutronPluginV2TestRpcFlavor, self).setUp()
- self.addCleanup(unregister_meta_hooks)
-
- def test_rpc_flavor(self):
- setup_metaplugin_conf()
- cfg.CONF.set_override('rpc_flavor', 'fake1', 'META')
- self.plugin = meta_neutron_plugin.MetaPluginV2()
- self.assertEqual(topics.PLUGIN, 'q-plugin')
- ret = self.plugin.rpc_workers_supported()
- self.assertFalse(ret)
-
- def test_invalid_rpc_flavor(self):
- setup_metaplugin_conf()
- cfg.CONF.set_override('rpc_flavor', 'fake-fake', 'META')
- self.assertRaises(exc.Invalid,
- meta_neutron_plugin.MetaPluginV2)
- self.assertEqual(topics.PLUGIN, 'q-plugin')
-
- def test_rpc_flavor_multiple_rpc_workers(self):
- setup_metaplugin_conf()
- cfg.CONF.set_override('rpc_flavor', 'fake2', 'META')
- self.plugin = meta_neutron_plugin.MetaPluginV2()
- self.assertEqual(topics.PLUGIN, 'q-plugin')
- ret = self.plugin.rpc_workers_supported()
- self.assertTrue(ret)
- ret = self.plugin.start_rpc_listeners()
- self.assertEqual('OK', ret)