Eliminate lookup of "resource extend" funcs by name
By registering functions directly we cut off the dependency of the "resource extend" functions on the plugin. This is a step towards the goal of removing the CommonDbMixin mixin class. Also, we register all "resource extend" functions at plugin create (in __new__) instead of in the class definition (which caused the hooks to be registered on import). This ensures the "resource extend" functions are only registered for the plugins/mixins that are actually used. Note that decorators are used to register "resource extend" methods, similar to the callback receiver decorators. Related-Blueprint: neutron-lib Change-Id: I128cfda773d5f9597df9cd61261fdc05f2a174aa
This commit is contained in:
parent
0479f0f9d2
commit
b3c0d5f239
@ -15,6 +15,9 @@ NOTE: This module shall not be used by external projects. It will be moved
|
||||
to neutron-lib in due course, and then it can be used from there.
|
||||
"""
|
||||
|
||||
import collections
|
||||
import inspect
|
||||
|
||||
from neutron.common import utils
|
||||
|
||||
# This dictionary will store methods for extending API resources.
|
||||
@ -25,6 +28,10 @@ _resource_extend_functions = {
|
||||
# ...
|
||||
}
|
||||
|
||||
# This dictionary will store @extends decorated methods with a list of
|
||||
# resources that each method will extend on class initialization.
|
||||
_DECORATED_EXTEND_METHODS = collections.defaultdict(list)
|
||||
|
||||
|
||||
def register_funcs(resource, funcs):
|
||||
"""Add functions to extend a resource.
|
||||
@ -59,3 +66,65 @@ def get_funcs(resource):
|
||||
|
||||
"""
|
||||
return _resource_extend_functions.get(resource, [])
|
||||
|
||||
|
||||
def extends(resources):
|
||||
"""Use to decorate methods on classes before initialization.
|
||||
|
||||
Any classes that use this must themselves be decorated with the
|
||||
@has_resource_extenders decorator to setup the __new__ method to
|
||||
actually register the instance methods after initialization.
|
||||
|
||||
:param resources: Resource collection names. The decorated method will
|
||||
be registered with each resource as an extend function.
|
||||
:type resources: list of str
|
||||
|
||||
"""
|
||||
def decorator(method):
|
||||
_DECORATED_EXTEND_METHODS[method].extend(resources)
|
||||
return method
|
||||
return decorator
|
||||
|
||||
|
||||
def has_resource_extenders(klass):
|
||||
"""Decorator to setup __new__ method in classes to extend resources.
|
||||
|
||||
Any method decorated with @extends above is an unbound method on a class.
|
||||
This decorator sets up the class __new__ method to add the bound
|
||||
method to _resource_extend_functions after object instantiation.
|
||||
"""
|
||||
orig_new = klass.__new__
|
||||
new_inherited = '__new__' not in klass.__dict__
|
||||
|
||||
@staticmethod
|
||||
def replacement_new(cls, *args, **kwargs):
|
||||
if new_inherited:
|
||||
# class didn't define __new__ so we need to call inherited __new__
|
||||
super_new = super(klass, cls).__new__
|
||||
if super_new is object.__new__:
|
||||
# object.__new__ doesn't accept args nor kwargs
|
||||
instance = super_new(cls)
|
||||
else:
|
||||
instance = super_new(cls, *args, **kwargs)
|
||||
else:
|
||||
instance = orig_new(cls, *args, **kwargs)
|
||||
if getattr(instance, '_DECORATED_METHODS_REGISTERED', False):
|
||||
# Avoid running this logic twice for classes inheriting other
|
||||
# classes with this same decorator. Only one needs to execute
|
||||
# to subscribe all decorated methods.
|
||||
return instance
|
||||
for name, unbound_method in inspect.getmembers(cls):
|
||||
if (not inspect.ismethod(unbound_method) and
|
||||
not inspect.isfunction(unbound_method)):
|
||||
continue
|
||||
# Handle py27/py34 difference
|
||||
method = getattr(unbound_method, 'im_func', unbound_method)
|
||||
if method not in _DECORATED_EXTEND_METHODS:
|
||||
continue
|
||||
for resource in _DECORATED_EXTEND_METHODS[method]:
|
||||
# Register the bound method for the resourse
|
||||
register_funcs(resource, [method])
|
||||
setattr(instance, '_DECORATED_METHODS_REGISTERED', True)
|
||||
return instance
|
||||
klass.__new__ = replacement_new
|
||||
return klass
|
||||
|
@ -26,6 +26,7 @@ from neutron.objects import base as base_obj
|
||||
from neutron.objects import subnetpool as subnetpool_obj
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class AddressScopeDbMixin(ext_address_scope.AddressScopePluginBase):
|
||||
"""Mixin class to add address scope to db_base_plugin_v2."""
|
||||
|
||||
@ -117,7 +118,9 @@ class AddressScopeDbMixin(ext_address_scope.AddressScopePluginBase):
|
||||
address_scope = self._get_address_scope(context, id)
|
||||
address_scope.delete()
|
||||
|
||||
def _extend_network_dict_address_scope(self, network_res, network_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends([attr.NETWORKS])
|
||||
def _extend_network_dict_address_scope(network_res, network_db):
|
||||
network_res[ext_address_scope.IPV4_ADDRESS_SCOPE] = None
|
||||
network_res[ext_address_scope.IPV6_ADDRESS_SCOPE] = None
|
||||
subnetpools = {subnet.subnetpool for subnet in network_db.subnets
|
||||
@ -132,6 +135,3 @@ class AddressScopeDbMixin(ext_address_scope.AddressScopePluginBase):
|
||||
if subnetpool['ip_version'] == constants.IP_VERSION_6:
|
||||
network_res[ext_address_scope.IPV6_ADDRESS_SCOPE] = as_id
|
||||
return network_res
|
||||
|
||||
resource_extend.register_funcs(
|
||||
attr.NETWORKS, ['_extend_network_dict_address_scope'])
|
||||
|
@ -26,6 +26,7 @@ from neutron.objects.port.extensions import (allowedaddresspairs
|
||||
as obj_addr_pair)
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class AllowedAddressPairsMixin(object):
|
||||
"""Mixin class for allowed address pairs."""
|
||||
|
||||
@ -63,19 +64,19 @@ class AllowedAddressPairsMixin(object):
|
||||
return [self._make_allowed_address_pairs_dict(pair.db_obj)
|
||||
for pair in pairs]
|
||||
|
||||
def _extend_port_dict_allowed_address_pairs(self, port_res, port_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends([attr.PORTS])
|
||||
def _extend_port_dict_allowed_address_pairs(port_res, port_db):
|
||||
# If port_db is provided, allowed address pairs will be accessed via
|
||||
# sqlalchemy models. As they're loaded together with ports this
|
||||
# will not cause an extra query.
|
||||
allowed_address_pairs = [
|
||||
self._make_allowed_address_pairs_dict(address_pair) for
|
||||
AllowedAddressPairsMixin._make_allowed_address_pairs_dict(
|
||||
address_pair) for
|
||||
address_pair in port_db.allowed_address_pairs]
|
||||
port_res[addr_pair.ADDRESS_PAIRS] = allowed_address_pairs
|
||||
return port_res
|
||||
|
||||
resource_extend.register_funcs(
|
||||
attr.PORTS, ['_extend_port_dict_allowed_address_pairs'])
|
||||
|
||||
def _delete_allowed_address_pairs(self, context, id):
|
||||
obj_addr_pair.AllowedAddressPair.delete_objects(
|
||||
context, port_id=id)
|
||||
|
@ -11,20 +11,23 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.db import _resource_extend as resource_extend
|
||||
from neutron.extensions import availability_zone as az_ext
|
||||
from neutron.extensions import network_availability_zone as net_az
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class NetworkAvailabilityZoneMixin(net_az.NetworkAvailabilityZonePluginBase):
|
||||
"""Mixin class to enable network's availability zone attributes."""
|
||||
|
||||
def _extend_availability_zone(self, net_res, net_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.NETWORKS])
|
||||
def _extend_availability_zone(net_res, net_db):
|
||||
net_res[az_ext.AZ_HINTS] = az_ext.convert_az_string_to_list(
|
||||
net_db[az_ext.AZ_HINTS])
|
||||
plugin = directory.get_plugin()
|
||||
net_res[az_ext.AVAILABILITY_ZONES] = (
|
||||
self.get_network_availability_zones(net_db))
|
||||
|
||||
resource_extend.register_funcs(
|
||||
attributes.NETWORKS, ['_extend_availability_zone'])
|
||||
plugin.get_network_availability_zones(net_db))
|
||||
|
@ -11,32 +11,33 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib import constants
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from neutron.callbacks import events
|
||||
from neutron.callbacks import registry
|
||||
from neutron.callbacks import resources
|
||||
from neutron.common import utils
|
||||
from neutron.db import db_base_plugin_v2
|
||||
from neutron.db import _resource_extend as resource_extend
|
||||
from neutron.db import l3_attrs_db
|
||||
from neutron.extensions import availability_zone as az_ext
|
||||
from neutron.extensions import l3
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
@registry.has_registry_receivers
|
||||
class RouterAvailabilityZoneMixin(l3_attrs_db.ExtraAttributesMixin):
|
||||
"""Mixin class to enable router's availability zone attributes."""
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
inst = super(RouterAvailabilityZoneMixin, cls).__new__(
|
||||
cls, *args, **kwargs)
|
||||
db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs(
|
||||
l3.ROUTERS, [inst._add_az_to_response])
|
||||
return inst
|
||||
|
||||
def _add_az_to_response(self, plugin, router_res, router_db):
|
||||
if not utils.is_extension_supported(self, 'router_availability_zone'):
|
||||
@staticmethod
|
||||
@resource_extend.extends([l3.ROUTERS])
|
||||
def _add_az_to_response(router_res, router_db):
|
||||
l3_plugin = directory.get_plugin(constants.L3)
|
||||
if not utils.is_extension_supported(l3_plugin,
|
||||
'router_availability_zone'):
|
||||
return
|
||||
router_res['availability_zones'] = (
|
||||
self.get_router_availability_zones(router_db))
|
||||
l3_plugin.get_router_availability_zones(router_db))
|
||||
|
||||
@registry.receives(resources.ROUTER, [events.PRECOMMIT_CREATE])
|
||||
def _process_az_request(self, resource, event, trigger, context,
|
||||
|
@ -17,7 +17,6 @@ import weakref
|
||||
|
||||
from neutron_lib.db import utils as db_utils
|
||||
from oslo_db.sqlalchemy import utils as sa_utils
|
||||
import six
|
||||
from sqlalchemy import and_
|
||||
from sqlalchemy.ext import associationproxy
|
||||
from sqlalchemy import or_
|
||||
@ -36,6 +35,13 @@ model_query = ndb_utils.model_query
|
||||
resource_fields = ndb_utils.resource_fields
|
||||
|
||||
|
||||
def _resolve_ref(ref):
|
||||
"""Handles dereference of weakref."""
|
||||
if isinstance(ref, weakref.ref):
|
||||
ref = ref()
|
||||
return ref
|
||||
|
||||
|
||||
class CommonDbMixin(object):
|
||||
"""Common methods used in core and service plugins."""
|
||||
|
||||
@ -85,11 +91,11 @@ class CommonDbMixin(object):
|
||||
query_filter = (model.tenant_id == context.tenant_id)
|
||||
# Execute query hooks registered from mixins and plugins
|
||||
for hook in _model_query.get_hooks(model):
|
||||
query_hook = self._resolve_ref(hook.get('query'))
|
||||
query_hook = _resolve_ref(hook.get('query'))
|
||||
if query_hook:
|
||||
query = query_hook(context, model, query)
|
||||
|
||||
filter_hook = self._resolve_ref(hook.get('filter'))
|
||||
filter_hook = _resolve_ref(hook.get('filter'))
|
||||
if filter_hook:
|
||||
query_filter = filter_hook(context, model, query_filter)
|
||||
|
||||
@ -164,31 +170,19 @@ class CommonDbMixin(object):
|
||||
query = query.outerjoin(model.rbac_entries)
|
||||
query = query.filter(is_shared)
|
||||
for hook in _model_query.get_hooks(model):
|
||||
result_filter = self._resolve_ref(
|
||||
hook.get('result_filters', None))
|
||||
result_filter = _resolve_ref(hook.get('result_filters', None))
|
||||
|
||||
if result_filter:
|
||||
query = result_filter(query, filters)
|
||||
return query
|
||||
|
||||
def _resolve_ref(self, ref):
|
||||
"""Finds string ref functions, handles dereference of weakref."""
|
||||
if isinstance(ref, six.string_types):
|
||||
ref = getattr(self, ref, None)
|
||||
if isinstance(ref, weakref.ref):
|
||||
ref = ref()
|
||||
return ref
|
||||
|
||||
def _apply_dict_extend_functions(self, resource_type,
|
||||
@staticmethod
|
||||
def _apply_dict_extend_functions(resource_type,
|
||||
response, db_object):
|
||||
for func in _resource_extend.get_funcs(resource_type):
|
||||
args = (response, db_object)
|
||||
if not isinstance(func, six.string_types):
|
||||
# must call unbound method - use self as 1st argument
|
||||
args = (self,) + args
|
||||
func = self._resolve_ref(func)
|
||||
if func:
|
||||
func(*args)
|
||||
resolved_func = _resolve_ref(func)
|
||||
if resolved_func:
|
||||
resolved_func(response, db_object)
|
||||
|
||||
def _get_collection_query(self, context, model, filters=None,
|
||||
sorts=None, limit=None, marker_obj=None,
|
||||
|
@ -40,7 +40,8 @@ class DataPlaneStatusMixin(object):
|
||||
else:
|
||||
self._process_create_port_data_plane_status(context, data, res)
|
||||
|
||||
def _extend_port_data_plane_status(self, port_res, port_db):
|
||||
@staticmethod
|
||||
def _extend_port_data_plane_status(port_res, port_db):
|
||||
port_res[dps_lib.DATA_PLANE_STATUS] = None
|
||||
|
||||
if port_db.get(dps_lib.DATA_PLANE_STATUS):
|
||||
|
@ -41,6 +41,7 @@ class DNSActionsData(object):
|
||||
self.previous_dns_domain = previous_dns_domain
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class DNSDbMixin(object):
|
||||
"""Mixin class to add DNS methods to db_base_plugin_v2."""
|
||||
|
||||
@ -63,7 +64,9 @@ class DNSDbMixin(object):
|
||||
raise dns.ExternalDNSDriverNotFound(
|
||||
driver=cfg.CONF.external_dns_driver)
|
||||
|
||||
def _extend_floatingip_dict_dns(self, floatingip_res, floatingip_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends([l3.FLOATINGIPS])
|
||||
def _extend_floatingip_dict_dns(floatingip_res, floatingip_db):
|
||||
floatingip_res['dns_domain'] = ''
|
||||
floatingip_res['dns_name'] = ''
|
||||
if floatingip_db.dns:
|
||||
@ -71,9 +74,6 @@ class DNSDbMixin(object):
|
||||
floatingip_res['dns_name'] = floatingip_db.dns['dns_name']
|
||||
return floatingip_res
|
||||
|
||||
resource_extend.register_funcs(
|
||||
l3.FLOATINGIPS, ['_extend_floatingip_dict_dns'])
|
||||
|
||||
def _process_dns_floatingip_create_precommit(self, context,
|
||||
floatingip_data, req_data):
|
||||
# expects to be called within a plugin's session
|
||||
|
@ -64,6 +64,7 @@ def _network_result_filter_hook(query, filters):
|
||||
return query.filter(~models_v2.Network.external.has())
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
@registry.has_registry_receivers
|
||||
class External_net_db_mixin(object):
|
||||
"""Mixin class to add external network methods to db_base_plugin_v2."""
|
||||
@ -81,14 +82,13 @@ class External_net_db_mixin(object):
|
||||
return net_obj.ExternalNetwork.objects_exist(
|
||||
context, network_id=net_id)
|
||||
|
||||
def _extend_network_dict_l3(self, network_res, network_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.NETWORKS])
|
||||
def _extend_network_dict_l3(network_res, network_db):
|
||||
# Comparing with None for converting uuid into bool
|
||||
network_res[external_net.EXTERNAL] = network_db.external is not None
|
||||
return network_res
|
||||
|
||||
resource_extend.register_funcs(
|
||||
attributes.NETWORKS, ['_extend_network_dict_l3'])
|
||||
|
||||
def _process_l3_create(self, context, net_data, req_data):
|
||||
external = req_data.get(external_net.EXTERNAL)
|
||||
external_set = validators.is_attr_set(external)
|
||||
|
@ -20,6 +20,7 @@ from neutron.extensions import extra_dhcp_opt as edo_ext
|
||||
from neutron.objects.port.extensions import extra_dhcp_opt as obj_extra_dhcp
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class ExtraDhcpOptMixin(object):
|
||||
"""Mixin class to add extra options to the DHCP opts file
|
||||
and associate them to a port.
|
||||
@ -114,12 +115,11 @@ class ExtraDhcpOptMixin(object):
|
||||
|
||||
return bool(dopts)
|
||||
|
||||
def _extend_port_dict_extra_dhcp_opt(self, res, port):
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.PORTS])
|
||||
def _extend_port_dict_extra_dhcp_opt(res, port):
|
||||
res[edo_ext.EXTRADHCPOPTS] = [{'opt_name': dho.opt_name,
|
||||
'opt_value': dho.opt_value,
|
||||
'ip_version': dho.ip_version}
|
||||
for dho in port.dhcp_opts]
|
||||
return res
|
||||
|
||||
resource_extend.register_funcs(
|
||||
attributes.PORTS, ['_extend_port_dict_extra_dhcp_opt'])
|
||||
|
@ -39,18 +39,18 @@ extra_route_opts = [
|
||||
cfg.CONF.register_opts(extra_route_opts)
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class ExtraRoute_dbonly_mixin(l3_db.L3_NAT_dbonly_mixin):
|
||||
"""Mixin class to support extra route configuration on router."""
|
||||
|
||||
def _extend_router_dict_extraroute(self, router_res, router_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends([l3.ROUTERS])
|
||||
def _extend_router_dict_extraroute(router_res, router_db):
|
||||
router_res['routes'] = (ExtraRoute_dbonly_mixin.
|
||||
_make_extra_route_list(
|
||||
router_db['route_list']
|
||||
))
|
||||
|
||||
resource_extend.register_funcs(
|
||||
l3.ROUTERS, ['_extend_router_dict_extraroute'])
|
||||
|
||||
def update_router(self, context, id, router):
|
||||
r = router['router']
|
||||
if 'routes' in r:
|
||||
|
@ -33,10 +33,13 @@ def get_attr_info():
|
||||
}
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class ExtraAttributesMixin(object):
|
||||
"""Mixin class to enable router's extra attributes."""
|
||||
|
||||
def _extend_extra_router_dict(self, router_res, router_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends([l3.ROUTERS])
|
||||
def _extend_extra_router_dict(router_res, router_db):
|
||||
extra_attrs = router_db['extra_attributes'] or {}
|
||||
for name, info in get_attr_info().items():
|
||||
from_db = info.get('transform_from_db', lambda x: x)
|
||||
@ -61,6 +64,3 @@ class ExtraAttributesMixin(object):
|
||||
return
|
||||
raise RuntimeError(_("Tried to set a key '%s' that doesn't exist "
|
||||
"in the extra attributes table.") % key)
|
||||
|
||||
resource_extend.register_funcs(
|
||||
l3.ROUTERS, ['_extend_extra_router_dict'])
|
||||
|
@ -38,13 +38,13 @@ setattr(l3_models.Router, 'enable_snat',
|
||||
nullable=False))
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class L3_NAT_dbonly_mixin(l3_db.L3_NAT_dbonly_mixin):
|
||||
"""Mixin class to add configurable gateway modes."""
|
||||
|
||||
resource_extend.register_funcs(
|
||||
l3.ROUTERS, ['_extend_router_dict_gw_mode'])
|
||||
|
||||
def _extend_router_dict_gw_mode(self, router_res, router_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends([l3.ROUTERS])
|
||||
def _extend_router_dict_gw_mode(router_res, router_db):
|
||||
if router_db.gw_port_id:
|
||||
nw_id = router_db.gw_port['network_id']
|
||||
router_res[EXTERNAL_GW_INFO] = {
|
||||
|
@ -13,11 +13,16 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.db import _resource_extend as resource_extend
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class PortBindingBaseMixin(object):
|
||||
|
||||
# Initialized by core plugin or ml2 mechanism driver(s)
|
||||
base_binding_dict = None
|
||||
|
||||
def _process_portbindings_create_and_update(self, context, port_data,
|
||||
@ -28,13 +33,10 @@ class PortBindingBaseMixin(object):
|
||||
if self.base_binding_dict:
|
||||
port_res.update(self.base_binding_dict)
|
||||
|
||||
|
||||
def _extend_port_dict_binding(plugin, port_res, port_db):
|
||||
if not isinstance(plugin, PortBindingBaseMixin):
|
||||
return
|
||||
plugin.extend_port_dict_binding(port_res, port_db)
|
||||
|
||||
|
||||
def register_port_dict_function():
|
||||
resource_extend.register_funcs(
|
||||
attributes.PORTS, [_extend_port_dict_binding])
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.PORTS])
|
||||
def _extend_port_dict_binding(port_res, port_db):
|
||||
plugin = directory.get_plugin()
|
||||
if not isinstance(plugin, PortBindingBaseMixin):
|
||||
return
|
||||
plugin.extend_port_dict_binding(port_res, port_db)
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
from neutron_lib.api.definitions import portbindings
|
||||
from neutron_lib.api import validators
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.db import _model_query as model_query
|
||||
@ -40,8 +41,8 @@ def _port_result_filter_hook(query, filters):
|
||||
return query
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class PortBindingMixin(portbindings_base.PortBindingBaseMixin):
|
||||
extra_binding_dict = None
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
model_query.register_hook(
|
||||
@ -101,11 +102,10 @@ class PortBindingMixin(portbindings_base.PortBindingBaseMixin):
|
||||
host = port_db.portbinding.host if port_db.portbinding else None
|
||||
self._extend_port_dict_binding_host(port_res, host)
|
||||
|
||||
|
||||
def _extend_port_dict_binding(plugin, port_res, port_db):
|
||||
if not isinstance(plugin, PortBindingMixin):
|
||||
return
|
||||
plugin.extend_port_dict_binding(port_res, port_db)
|
||||
|
||||
|
||||
resource_extend.register_funcs(attributes.PORTS, [_extend_port_dict_binding])
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.PORTS])
|
||||
def _extend_port_dict_binding(port_res, port_db):
|
||||
plugin = directory.get_plugin()
|
||||
if not isinstance(plugin, PortBindingMixin):
|
||||
return
|
||||
plugin.extend_port_dict_binding(port_res, port_db)
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.api import validators
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from neutron.api.v2 import attributes as attrs
|
||||
from neutron.common import utils
|
||||
@ -21,16 +22,16 @@ from neutron.db import portsecurity_db_common
|
||||
from neutron.extensions import portsecurity as psec
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class PortSecurityDbMixin(portsecurity_db_common.PortSecurityDbCommon):
|
||||
resource_extend.register_funcs(
|
||||
attrs.NETWORKS, ['_extend_port_security_dict'])
|
||||
resource_extend.register_funcs(
|
||||
attrs.PORTS, ['_extend_port_security_dict'])
|
||||
|
||||
def _extend_port_security_dict(self, response_data, db_data):
|
||||
@staticmethod
|
||||
@resource_extend.extends([attrs.NETWORKS, attrs.PORTS])
|
||||
def _extend_port_security_dict(response_data, db_data):
|
||||
plugin = directory.get_plugin()
|
||||
if ('port-security' in
|
||||
getattr(self, 'supported_extension_aliases', [])):
|
||||
super(PortSecurityDbMixin, self)._extend_port_security_dict(
|
||||
getattr(plugin, 'supported_extension_aliases', [])):
|
||||
super(PortSecurityDbMixin, plugin)._extend_port_security_dict(
|
||||
response_data, db_data)
|
||||
|
||||
def _determine_port_security_and_has_ip(self, context, port):
|
||||
|
@ -21,7 +21,8 @@ from neutron.objects.port.extensions import port_security as p_ps
|
||||
class PortSecurityDbCommon(object):
|
||||
"""Mixin class to add port security."""
|
||||
|
||||
def _extend_port_security_dict(self, response_data, db_data):
|
||||
@staticmethod
|
||||
def _extend_port_security_dict(response_data, db_data):
|
||||
if db_data.get('port_security') is None:
|
||||
response_data[psec.PORTSECURITY] = psec.DEFAULT_PORT_SECURITY
|
||||
else:
|
||||
|
@ -35,6 +35,7 @@ from neutron.db.models import securitygroup as sg_models
|
||||
from neutron.extensions import securitygroup as ext_sg
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
@registry.has_registry_receivers
|
||||
class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
|
||||
"""Mixin class to add security group to db_base_plugin_v2."""
|
||||
@ -662,7 +663,9 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
|
||||
resources.SECURITY_GROUP_RULE, events.AFTER_DELETE, self,
|
||||
**kwargs)
|
||||
|
||||
def _extend_port_dict_security_group(self, port_res, port_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.PORTS])
|
||||
def _extend_port_dict_security_group(port_res, port_db):
|
||||
# Security group bindings will be retrieved from the SQLAlchemy
|
||||
# model. As they're loaded eagerly with ports because of the
|
||||
# joined load they will not cause an extra query.
|
||||
@ -671,9 +674,6 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
|
||||
port_res[ext_sg.SECURITYGROUPS] = security_group_ids
|
||||
return port_res
|
||||
|
||||
resource_extend.register_funcs(
|
||||
attributes.PORTS, ['_extend_port_dict_security_group'])
|
||||
|
||||
def _process_port_create_security_group(self, context, port,
|
||||
security_group_ids):
|
||||
if validators.is_attr_set(security_group_ids):
|
||||
|
@ -16,17 +16,14 @@ from neutron.db import _resource_extend as resource_extend
|
||||
from neutron.db import standard_attr
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class StandardAttrDescriptionMixin(object):
|
||||
supported_extension_aliases = ['standard-attr-description']
|
||||
|
||||
def _extend_standard_attr_description(self, res, db_object):
|
||||
@staticmethod
|
||||
@resource_extend.extends(
|
||||
list(standard_attr.get_standard_attr_resource_model_map()))
|
||||
def _extend_standard_attr_description(res, db_object):
|
||||
if not hasattr(db_object, 'description'):
|
||||
return
|
||||
res['description'] = db_object.description
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
for resource in standard_attr.get_standard_attr_resource_model_map():
|
||||
resource_extend.register_funcs(
|
||||
resource, ['_extend_standard_attr_description'])
|
||||
return super(StandardAttrDescriptionMixin, cls).__new__(cls, *args,
|
||||
**kwargs)
|
||||
|
@ -20,13 +20,13 @@ from neutron.api.v2 import attributes
|
||||
from neutron.db import _resource_extend as resource_extend
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class SubnetServiceTypeMixin(object):
|
||||
"""Mixin class to extend subnet with service type attribute"""
|
||||
|
||||
def _extend_subnet_service_types(self, subnet_res, subnet_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.SUBNETS])
|
||||
def _extend_subnet_service_types(subnet_res, subnet_db):
|
||||
subnet_res['service_types'] = [service_type['service_type'] for
|
||||
service_type in
|
||||
subnet_db.service_types]
|
||||
|
||||
resource_extend.register_funcs(
|
||||
attributes.SUBNETS, [_extend_subnet_service_types])
|
||||
|
@ -17,13 +17,13 @@ from neutron.db import _resource_extend as resource_extend
|
||||
from neutron.extensions import vlantransparent
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class Vlantransparent_db_mixin(object):
|
||||
"""Mixin class to add vlan transparent methods to db_base_plugin_v2."""
|
||||
|
||||
def _extend_network_dict_vlan_transparent(self, network_res, network_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.NETWORKS])
|
||||
def _extend_network_dict_vlan_transparent(network_res, network_db):
|
||||
network_res[vlantransparent.VLANTRANSPARENT] = (
|
||||
network_db.vlan_transparent)
|
||||
return network_res
|
||||
|
||||
resource_extend.register_funcs(
|
||||
attributes.NETWORKS, ['_extend_network_dict_vlan_transparent'])
|
||||
|
@ -109,6 +109,7 @@ def _ml2_port_result_filter_hook(query, filters):
|
||||
return query.filter(models_v2.Port.port_binding.has(bind_criteria))
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
@registry.has_registry_receivers
|
||||
class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
dvr_mac_db.DVRDbMixin,
|
||||
@ -602,34 +603,37 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
'port': binding.port_id})
|
||||
return {}
|
||||
|
||||
def _ml2_extend_port_dict_binding(self, port_res, port_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.PORTS])
|
||||
def _ml2_extend_port_dict_binding(port_res, port_db):
|
||||
plugin = directory.get_plugin()
|
||||
# None when called during unit tests for other plugins.
|
||||
if port_db.port_binding:
|
||||
self._update_port_dict_binding(port_res, port_db.port_binding)
|
||||
|
||||
resource_extend.register_funcs(
|
||||
attributes.PORTS, ['_ml2_extend_port_dict_binding'])
|
||||
plugin._update_port_dict_binding(port_res, port_db.port_binding)
|
||||
|
||||
# ML2's resource extend functions allow extension drivers that extend
|
||||
# attributes for the resources to add those attributes to the result.
|
||||
resource_extend.register_funcs(
|
||||
attributes.NETWORKS, ['_ml2_md_extend_network_dict'])
|
||||
resource_extend.register_funcs(
|
||||
attributes.PORTS, ['_ml2_md_extend_port_dict'])
|
||||
resource_extend.register_funcs(
|
||||
attributes.SUBNETS, ['_ml2_md_extend_subnet_dict'])
|
||||
|
||||
def _ml2_md_extend_network_dict(self, result, netdb):
|
||||
session = self._object_session_or_new_session(netdb)
|
||||
self.extension_manager.extend_network_dict(session, netdb, result)
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.NETWORKS])
|
||||
def _ml2_md_extend_network_dict(result, netdb):
|
||||
plugin = directory.get_plugin()
|
||||
session = plugin._object_session_or_new_session(netdb)
|
||||
plugin.extension_manager.extend_network_dict(session, netdb, result)
|
||||
|
||||
def _ml2_md_extend_port_dict(self, result, portdb):
|
||||
session = self._object_session_or_new_session(portdb)
|
||||
self.extension_manager.extend_port_dict(session, portdb, result)
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.PORTS])
|
||||
def _ml2_md_extend_port_dict(result, portdb):
|
||||
plugin = directory.get_plugin()
|
||||
session = plugin._object_session_or_new_session(portdb)
|
||||
plugin.extension_manager.extend_port_dict(session, portdb, result)
|
||||
|
||||
def _ml2_md_extend_subnet_dict(self, result, subnetdb):
|
||||
session = self._object_session_or_new_session(subnetdb)
|
||||
self.extension_manager.extend_subnet_dict(session, subnetdb, result)
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.SUBNETS])
|
||||
def _ml2_md_extend_subnet_dict(result, subnetdb):
|
||||
plugin = directory.get_plugin()
|
||||
session = plugin._object_session_or_new_session(subnetdb)
|
||||
plugin.extension_manager.extend_subnet_dict(session, subnetdb, result)
|
||||
|
||||
@staticmethod
|
||||
def _object_session_or_new_session(sql_obj):
|
||||
|
@ -42,13 +42,6 @@ IS_DEFAULT = 'is_default'
|
||||
CHECK_REQUIREMENTS = 'dry-run'
|
||||
|
||||
|
||||
def _extend_external_network_default(core_plugin, net_res, net_db):
|
||||
"""Add is_default field to 'show' response."""
|
||||
if net_db.external is not None:
|
||||
net_res[IS_DEFAULT] = net_db.external.is_default
|
||||
return net_res
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
def _ensure_external_network_default_value_callback(
|
||||
resource, event, trigger, context, request, network, **kwargs):
|
||||
@ -78,11 +71,9 @@ def _ensure_external_network_default_value_callback(
|
||||
obj.update()
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class AutoAllocatedTopologyMixin(common_db_mixin.CommonDbMixin):
|
||||
|
||||
resource_extend.register_funcs(
|
||||
attributes.NETWORKS, [_extend_external_network_default])
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
# NOTE(kevinbenton): we subscribe on object construction because
|
||||
# the tests blow away the callback manager for each run
|
||||
@ -116,6 +107,14 @@ class AutoAllocatedTopologyMixin(common_db_mixin.CommonDbMixin):
|
||||
self._l3_plugin = directory.get_plugin(constants.L3)
|
||||
return self._l3_plugin
|
||||
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.NETWORKS])
|
||||
def _extend_external_network_default(net_res, net_db):
|
||||
"""Add is_default field to 'show' response."""
|
||||
if net_db.external is not None:
|
||||
net_res[IS_DEFAULT] = net_db.external.is_default
|
||||
return net_res
|
||||
|
||||
def get_auto_allocated_topology(self, context, tenant_id, fields=None):
|
||||
"""Return tenant's network associated to auto-allocated topology.
|
||||
|
||||
|
@ -51,6 +51,7 @@ def disable_dvr_extension_by_config(aliases):
|
||||
aliases.remove('dvr')
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class L3RouterPlugin(service_base.ServicePluginBase,
|
||||
common_db_mixin.CommonDbMixin,
|
||||
extraroute_db.ExtraRoute_db_mixin,
|
||||
@ -141,10 +142,7 @@ class L3RouterPlugin(service_base.ServicePluginBase,
|
||||
context, floatingip,
|
||||
initial_status=n_const.FLOATINGIP_STATUS_DOWN)
|
||||
|
||||
|
||||
def add_flavor_id(plugin, router_res, router_db):
|
||||
router_res['flavor_id'] = router_db['flavor_id']
|
||||
|
||||
|
||||
resource_extend.register_funcs(
|
||||
l3.ROUTERS, [add_flavor_id])
|
||||
@staticmethod
|
||||
@resource_extend.extends([l3.ROUTERS])
|
||||
def add_flavor_id(router_res, router_db):
|
||||
router_res['flavor_id'] = router_db['flavor_id']
|
||||
|
@ -25,6 +25,7 @@ from neutron.db import standard_attr
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class RevisionPlugin(service_base.ServicePluginBase):
|
||||
"""Plugin to populate revision numbers into standard attr resources."""
|
||||
|
||||
@ -32,9 +33,6 @@ class RevisionPlugin(service_base.ServicePluginBase):
|
||||
|
||||
def __init__(self):
|
||||
super(RevisionPlugin, self).__init__()
|
||||
for resource in standard_attr.get_standard_attr_resource_model_map():
|
||||
resource_extend.register_funcs(
|
||||
resource, [self.extend_resource_dict_revision])
|
||||
db_api.sqla_listen(se.Session, 'before_flush', self.bump_revisions)
|
||||
|
||||
def bump_revisions(self, session, context, instances):
|
||||
@ -76,7 +74,10 @@ class RevisionPlugin(service_base.ServicePluginBase):
|
||||
def get_plugin_description(self):
|
||||
return "Adds revision numbers to resources."
|
||||
|
||||
def extend_resource_dict_revision(self, plugin, resource_res, resource_db):
|
||||
@staticmethod
|
||||
@resource_extend.extends(
|
||||
list(standard_attr.get_standard_attr_resource_model_map()))
|
||||
def extend_resource_dict_revision(resource_res, resource_db):
|
||||
resource_res['revision_number'] = resource_db.revision_number
|
||||
|
||||
def _find_related_obj(self, session, obj, relationship_col):
|
||||
|
@ -49,30 +49,7 @@ SEGMENT_NAME_STUB = 'Neutron segment id %s'
|
||||
MAX_INVENTORY_UPDATE_RETRIES = 10
|
||||
|
||||
|
||||
def _extend_network_dict_binding(plugin, network_res, network_db):
|
||||
if not directory.get_plugin('segments'):
|
||||
return
|
||||
|
||||
# TODO(carl_baldwin) Make this work with service subnets when it's a thing.
|
||||
is_adjacent = (not network_db.subnets
|
||||
or not network_db.subnets[0].segment_id)
|
||||
network_res[l2_adjacency.L2_ADJACENCY] = is_adjacent
|
||||
|
||||
|
||||
def _extend_subnet_dict_binding(plugin, subnet_res, subnet_db):
|
||||
subnet_res['segment_id'] = subnet_db.get('segment_id')
|
||||
|
||||
|
||||
def _extend_port_dict_binding(plugin, port_res, port_db):
|
||||
if not directory.get_plugin('segments'):
|
||||
return
|
||||
|
||||
value = ip_allocation.IP_ALLOCATION_IMMEDIATE
|
||||
if port_db.get('ip_allocation'):
|
||||
value = port_db.get('ip_allocation')
|
||||
port_res[ip_allocation.IP_ALLOCATION] = value
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
@registry.has_registry_receivers
|
||||
class Plugin(db.SegmentDbMixin, segment.SegmentPluginBase):
|
||||
|
||||
@ -81,14 +58,36 @@ class Plugin(db.SegmentDbMixin, segment.SegmentPluginBase):
|
||||
supported_extension_aliases = ["segment", "ip_allocation", "l2_adjacency"]
|
||||
|
||||
def __init__(self):
|
||||
resource_extend.register_funcs(
|
||||
attributes.NETWORKS, [_extend_network_dict_binding])
|
||||
resource_extend.register_funcs(
|
||||
attributes.SUBNETS, [_extend_subnet_dict_binding])
|
||||
resource_extend.register_funcs(
|
||||
attributes.PORTS, [_extend_port_dict_binding])
|
||||
self.nova_updater = NovaSegmentNotifier()
|
||||
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.NETWORKS])
|
||||
def _extend_network_dict_binding(network_res, network_db):
|
||||
if not directory.get_plugin('segments'):
|
||||
return
|
||||
|
||||
# TODO(carl_baldwin) Make this work with service subnets when
|
||||
# it's a thing.
|
||||
is_adjacent = (not network_db.subnets
|
||||
or not network_db.subnets[0].segment_id)
|
||||
network_res[l2_adjacency.L2_ADJACENCY] = is_adjacent
|
||||
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.SUBNETS])
|
||||
def _extend_subnet_dict_binding(subnet_res, subnet_db):
|
||||
subnet_res['segment_id'] = subnet_db.get('segment_id')
|
||||
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.PORTS])
|
||||
def _extend_port_dict_binding(port_res, port_db):
|
||||
if not directory.get_plugin('segments'):
|
||||
return
|
||||
|
||||
value = ip_allocation.IP_ALLOCATION_IMMEDIATE
|
||||
if port_db.get('ip_allocation'):
|
||||
value = port_db.get('ip_allocation')
|
||||
port_res[ip_allocation.IP_ALLOCATION] = value
|
||||
|
||||
@classmethod
|
||||
def get_instance(cls):
|
||||
if cls._instance is None:
|
||||
|
@ -44,13 +44,7 @@ resource_model_map = {
|
||||
}
|
||||
|
||||
|
||||
def _extend_tags_dict(plugin, response_data, db_data):
|
||||
if not directory.get_plugin(tag_ext.TAG_PLUGIN_TYPE):
|
||||
return
|
||||
tags = [tag_db.tag for tag_db in db_data.standard_attr.tags]
|
||||
response_data['tags'] = tags
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class TagPlugin(common_db_mixin.CommonDbMixin, tag_ext.TagPluginBase):
|
||||
"""Implementation of the Neutron Tag Service Plugin."""
|
||||
|
||||
@ -59,8 +53,7 @@ class TagPlugin(common_db_mixin.CommonDbMixin, tag_ext.TagPluginBase):
|
||||
def __new__(cls, *args, **kwargs):
|
||||
inst = super(TagPlugin, cls).__new__(cls, *args, **kwargs)
|
||||
inst._filter_methods = [] # prevent GC of our partial functions
|
||||
for resource, model in resource_model_map.items():
|
||||
resource_extend.register_funcs(resource, [_extend_tags_dict])
|
||||
for model in resource_model_map.values():
|
||||
method = functools.partial(tag_methods.apply_tag_filters, model)
|
||||
inst._filter_methods.append(method)
|
||||
model_query.register_hook(model, "tag",
|
||||
@ -69,6 +62,14 @@ class TagPlugin(common_db_mixin.CommonDbMixin, tag_ext.TagPluginBase):
|
||||
result_filters=method)
|
||||
return inst
|
||||
|
||||
@staticmethod
|
||||
@resource_extend.extends(list(resource_model_map))
|
||||
def _extend_tags_dict(response_data, db_data):
|
||||
if not directory.get_plugin(tag_ext.TAG_PLUGIN_TYPE):
|
||||
return
|
||||
tags = [tag_db.tag for tag_db in db_data.standard_attr.tags]
|
||||
response_data['tags'] = tags
|
||||
|
||||
def _get_resource(self, context, resource, resource_id):
|
||||
model = resource_model_map[resource]
|
||||
try:
|
||||
|
@ -70,12 +70,6 @@ def _format_timestamp(resource_db, result):
|
||||
strftime(TIME_FORMAT_WHOLE_SECONDS)) + 'Z'
|
||||
|
||||
|
||||
def _extend_resource_dict_timestamp(plugin_obj, resource_res, resource_db):
|
||||
if (resource_db and resource_db.created_at and
|
||||
resource_db.updated_at):
|
||||
_format_timestamp(resource_db, resource_res)
|
||||
|
||||
|
||||
def _add_timestamp(mapper, _conn, target):
|
||||
if not target.created_at and not target.updated_at:
|
||||
time = timeutils.utcnow()
|
||||
@ -84,14 +78,13 @@ def _add_timestamp(mapper, _conn, target):
|
||||
return target
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class TimeStamp_db_mixin(object):
|
||||
"""Mixin class to add Time Stamp methods."""
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
rs_model_maps = standard_attr.get_standard_attr_resource_model_map()
|
||||
for rsmap, model in rs_model_maps.items():
|
||||
resource_extend.register_funcs(
|
||||
rsmap, [_extend_resource_dict_timestamp])
|
||||
for model in rs_model_maps.values():
|
||||
model_query.register_hook(
|
||||
model,
|
||||
"change_since_query",
|
||||
@ -105,3 +98,11 @@ class TimeStamp_db_mixin(object):
|
||||
listen(standard_attr.StandardAttribute, 'before_insert',
|
||||
_add_timestamp)
|
||||
listen(se.Session, 'before_flush', _update_timestamp)
|
||||
|
||||
@staticmethod
|
||||
@resource_extend.extends(
|
||||
list(standard_attr.get_standard_attr_resource_model_map()))
|
||||
def _extend_resource_dict_timestamp(resource_res, resource_db):
|
||||
if (resource_db and resource_db.created_at and
|
||||
resource_db.updated_at):
|
||||
_format_timestamp(resource_db, resource_res)
|
||||
|
@ -16,6 +16,7 @@ import copy
|
||||
|
||||
from neutron_lib.api.definitions import portbindings
|
||||
from neutron_lib import context
|
||||
from neutron_lib.plugins import directory
|
||||
from neutron_lib.services import base as service_base
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import uuidutils
|
||||
@ -40,26 +41,7 @@ from neutron.services.trunk.seg_types import validators
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _extend_port_trunk_details(core_plugin, port_res, port_db):
|
||||
"""Add trunk details to a port."""
|
||||
if port_db.trunk_port:
|
||||
subports = {
|
||||
x.port_id: {'segmentation_id': x.segmentation_id,
|
||||
'segmentation_type': x.segmentation_type,
|
||||
'port_id': x.port_id}
|
||||
for x in port_db.trunk_port.sub_ports
|
||||
}
|
||||
ports = core_plugin.get_ports(
|
||||
context.get_admin_context(), filters={'id': subports})
|
||||
for port in ports:
|
||||
subports[port['id']]['mac_address'] = port['mac_address']
|
||||
trunk_details = {'trunk_id': port_db.trunk_port.id,
|
||||
'sub_ports': [x for x in subports.values()]}
|
||||
port_res['trunk_details'] = trunk_details
|
||||
|
||||
return port_res
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
@registry.has_registry_receivers
|
||||
class TrunkPlugin(service_base.ServicePluginBase,
|
||||
common_db_mixin.CommonDbMixin):
|
||||
@ -70,8 +52,6 @@ class TrunkPlugin(service_base.ServicePluginBase,
|
||||
__native_sorting_support = True
|
||||
|
||||
def __init__(self):
|
||||
resource_extend.register_funcs(
|
||||
attributes.PORTS, [_extend_port_trunk_details])
|
||||
self._rpc_backend = None
|
||||
self._drivers = []
|
||||
self._segmentation_types = {}
|
||||
@ -85,6 +65,28 @@ class TrunkPlugin(service_base.ServicePluginBase,
|
||||
LOG.debug('Trunk plugin loaded with driver %s', driver.name)
|
||||
self.check_compatibility()
|
||||
|
||||
@staticmethod
|
||||
@resource_extend.extends([attributes.PORTS])
|
||||
def _extend_port_trunk_details(port_res, port_db):
|
||||
"""Add trunk details to a port."""
|
||||
if port_db.trunk_port:
|
||||
subports = {
|
||||
x.port_id: {'segmentation_id': x.segmentation_id,
|
||||
'segmentation_type': x.segmentation_type,
|
||||
'port_id': x.port_id}
|
||||
for x in port_db.trunk_port.sub_ports
|
||||
}
|
||||
core_plugin = directory.get_plugin()
|
||||
ports = core_plugin.get_ports(
|
||||
context.get_admin_context(), filters={'id': subports})
|
||||
for port in ports:
|
||||
subports[port['id']]['mac_address'] = port['mac_address']
|
||||
trunk_details = {'trunk_id': port_db.trunk_port.id,
|
||||
'sub_ports': [x for x in subports.values()]}
|
||||
port_res['trunk_details'] = trunk_details
|
||||
|
||||
return port_res
|
||||
|
||||
def check_compatibility(self):
|
||||
"""Verify the plugin can load correctly and fail otherwise."""
|
||||
self.check_driver_compatibility()
|
||||
|
@ -47,6 +47,7 @@ from neutron.callbacks import registry
|
||||
from neutron.common import config
|
||||
from neutron.common import rpc as n_rpc
|
||||
from neutron.db import _model_query as model_query
|
||||
from neutron.db import _resource_extend as resource_extend
|
||||
from neutron.db import agentschedulers_db
|
||||
from neutron.db import api as db_api
|
||||
from neutron import manager
|
||||
@ -168,6 +169,7 @@ class DietTestCase(base.BaseTestCase):
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
|
||||
self.addCleanup(self.reset_model_query_hooks)
|
||||
self.addCleanup(self.reset_resource_extend_functions)
|
||||
|
||||
self.addOnException(self.check_for_systemexit)
|
||||
self.orig_pid = os.getpid()
|
||||
@ -178,6 +180,10 @@ class DietTestCase(base.BaseTestCase):
|
||||
def reset_model_query_hooks():
|
||||
model_query._model_query_hooks = {}
|
||||
|
||||
@staticmethod
|
||||
def reset_resource_extend_functions():
|
||||
resource_extend._resource_extend_functions = {}
|
||||
|
||||
def addOnException(self, handler):
|
||||
|
||||
def safe_handler(*args, **kwargs):
|
||||
|
@ -18,6 +18,7 @@ import random
|
||||
|
||||
from neutron_lib import constants
|
||||
from neutron_lib import context
|
||||
from neutron_lib.plugins import directory
|
||||
from oslo_utils import uuidutils
|
||||
import testscenarios
|
||||
|
||||
@ -45,6 +46,7 @@ class L3SchedulerBaseTest(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||
super(L3SchedulerBaseTest, self).setUp(PLUGIN_NAME)
|
||||
|
||||
self.l3_plugin = l3_router_plugin.L3RouterPlugin()
|
||||
directory.add_plugin(constants.L3, self.l3_plugin)
|
||||
self.adminContext = context.get_admin_context()
|
||||
self.adminContext.tenant_id = _uuid()
|
||||
|
||||
@ -296,6 +298,7 @@ class L3AZSchedulerBaseTest(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||
super(L3AZSchedulerBaseTest, self).setUp(plugin='ml2')
|
||||
|
||||
self.l3_plugin = l3_router_plugin.L3RouterPlugin()
|
||||
directory.add_plugin(constants.L3, self.l3_plugin)
|
||||
self.l3_plugin.router_scheduler = None
|
||||
self.adminContext = context.get_admin_context()
|
||||
self.adminContext.tenant_id = '_func_test_tenant_'
|
||||
|
@ -48,6 +48,7 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||
self.core_plugin = directory.get_plugin()
|
||||
self.ctx = context.get_admin_context()
|
||||
self.mixin = FakeL3Plugin()
|
||||
directory.add_plugin(const.L3, self.mixin)
|
||||
|
||||
def _create_router(self, router):
|
||||
with self.ctx.session.begin(subtransactions=True):
|
||||
|
@ -11,6 +11,8 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from neutron_lib import constants
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from neutron.db import portsecurity_db as pd
|
||||
from neutron.db import portsecurity_db_common as pdc
|
||||
@ -29,6 +31,7 @@ class PortSecurityDbMixinTestCase(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(PortSecurityDbMixinTestCase, self).setUp()
|
||||
self.plugin = FakePlugin()
|
||||
directory.add_plugin(constants.CORE, self.plugin)
|
||||
|
||||
@mock.patch.object(common, '_extend_port_security_dict')
|
||||
def test__extend_port_security_dict_relies_on_common(self, extend):
|
||||
|
@ -41,11 +41,18 @@ class DataPlaneStatusTestExtensionManager(object):
|
||||
return dps_ext.Data_plane_status.get_extended_resources(version)
|
||||
|
||||
|
||||
@resource_extend.has_resource_extenders
|
||||
class DataPlaneStatusExtensionTestPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
dps_db.DataPlaneStatusMixin):
|
||||
|
||||
supported_extension_aliases = ["data-plane-status"]
|
||||
|
||||
@staticmethod
|
||||
@resource_extend.extends([attrs.PORTS])
|
||||
def _extend_port_data_plane_status(port_res, port_db):
|
||||
return dps_db.DataPlaneStatusMixin._extend_port_data_plane_status(
|
||||
port_res, port_db)
|
||||
|
||||
def update_port(self, context, id, port):
|
||||
with context.session.begin(subtransactions=True):
|
||||
ret_port = super(DataPlaneStatusExtensionTestPlugin,
|
||||
@ -56,9 +63,6 @@ class DataPlaneStatusExtensionTestPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
ret_port)
|
||||
return ret_port
|
||||
|
||||
resource_extend.register_funcs(attrs.PORTS,
|
||||
['_extend_port_data_plane_status'])
|
||||
|
||||
|
||||
class DataPlaneStatusExtensionTestCase(
|
||||
test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||
|
@ -571,6 +571,7 @@ class ExtraAttributesMixinTestCase(testlib_api.SqlTestCase):
|
||||
def setUp(self):
|
||||
super(ExtraAttributesMixinTestCase, self).setUp()
|
||||
self.mixin = l3_attrs_db.ExtraAttributesMixin()
|
||||
directory.add_plugin(lib_constants.L3, self.mixin)
|
||||
self.ctx = context.get_admin_context()
|
||||
self.router = l3_models.Router()
|
||||
with self.ctx.session.begin():
|
||||
|
@ -13,6 +13,7 @@
|
||||
import webob.exc
|
||||
|
||||
from neutron.db import db_base_plugin_v2
|
||||
from neutron.db import subnet_service_type_db_models
|
||||
from neutron.extensions import subnet_service_types
|
||||
from neutron.tests.unit.db import test_db_base_plugin_v2
|
||||
|
||||
@ -34,7 +35,8 @@ class SubnetServiceTypesExtensionManager(object):
|
||||
|
||||
|
||||
class SubnetServiceTypesExtensionTestPlugin(
|
||||
db_base_plugin_v2.NeutronDbPluginV2):
|
||||
db_base_plugin_v2.NeutronDbPluginV2,
|
||||
subnet_service_type_db_models.SubnetServiceTypeMixin):
|
||||
"""Test plugin to mixin the subnet service_types extension.
|
||||
"""
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user