diff --git a/neutron/api/rpc/handlers/securitygroups_rpc.py b/neutron/api/rpc/handlers/securitygroups_rpc.py new file mode 100644 index 0000000000..bbba92a16e --- /dev/null +++ b/neutron/api/rpc/handlers/securitygroups_rpc.py @@ -0,0 +1,59 @@ +# 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 neutron.common import rpc as n_rpc +from neutron import manager + + +# TODO(amotoki): Move security group RPC API and agent callback +# from securitygroups_rpc.py. + + +class SecurityGroupServerRpcCallback(n_rpc.RpcCallback): + """Callback for SecurityGroup agent RPC in plugin implementations. + + Subclass which inherits this class must implement get_port_from_device(). + """ + + # API version history: + # 1.1 - Initial version + + # NOTE: RPC_API_VERSION must not be overridden in subclasses + # to keep RPC API version consistent across plugins. + RPC_API_VERSION = '1.1' + + @property + def plugin(self): + return manager.NeutronManager.get_plugin() + + def security_group_rules_for_devices(self, context, **kwargs): + """Callback method to return security group rules for each port. + + also convert remote_group_id rule + to source_ip_prefix and dest_ip_prefix rule + + :params devices: list of devices + :returns: port correspond to the devices with security group rules + """ + devices = kwargs.get('devices') + + ports = {} + for device in devices: + port = self.plugin.get_port_from_device(device) + if not port: + continue + if port['device_owner'].startswith('network:'): + continue + ports[port['id']] = port + return self.plugin.security_group_rules_for_ports(context, ports) diff --git a/neutron/db/securitygroups_rpc_base.py b/neutron/db/securitygroups_rpc_base.py index 4a659bd188..81d3457f67 100644 --- a/neutron/db/securitygroups_rpc_base.py +++ b/neutron/db/securitygroups_rpc_base.py @@ -36,6 +36,27 @@ DIRECTION_IP_PREFIX = {'ingress': 'source_ip_prefix', class SecurityGroupServerRpcMixin(sg_db.SecurityGroupDbMixin): + """Mixin class to add agent-based security group implementation.""" + + def get_port_from_device(self, device): + """Get port dict from device name on an agent. + + Subclass must provide this method. + + :param device: device name which identifies a port on the agent side. + What is specified in "device" depends on a plugin agent implementation. + For example, it is a port ID in OVS agent and netdev name in Linux + Bridge agent. + :return: port dict returned by DB plugin get_port(). In addition, + it must contain the following fields in the port dict returned. + - device + - security_groups + - security_group_rules, + - security_group_source_groups + - fixed_ips + """ + raise NotImplementedError(_("%s must implement get_port_from_device.") + % self.__class__.__name__) def create_security_group_rule(self, context, security_group_rule): bulk_rule = {'security_group_rules': [security_group_rule]} @@ -128,33 +149,6 @@ class SecurityGroupServerRpcMixin(sg_db.SecurityGroupDbMixin): self.notifier.security_groups_member_updated( context, port.get(ext_sg.SECURITYGROUPS)) - -class SecurityGroupServerRpcCallbackMixin(object): - """A mix-in that enable SecurityGroup agent support in plugin - implementations. - """ - - def security_group_rules_for_devices(self, context, **kwargs): - """Return security group rules for each port. - - also convert remote_group_id rule - to source_ip_prefix and dest_ip_prefix rule - - :params devices: list of devices - :returns: port correspond to the devices with security group rules - """ - devices = kwargs.get('devices') - - ports = {} - for device in devices: - port = self.get_port_from_device(device) - if not port: - continue - if port['device_owner'].startswith('network:'): - continue - ports[port['id']] = port - return self._security_group_rules_for_ports(context, ports) - def _select_rules_for_ports(self, context, ports): if not ports: return [] @@ -354,7 +348,7 @@ class SecurityGroupServerRpcCallbackMixin(object): self._add_ingress_ra_rule(port, ips_ra) self._add_ingress_dhcp_rule(port, ips_dhcp) - def _security_group_rules_for_ports(self, context, ports): + def security_group_rules_for_ports(self, context, ports): rules_in_db = self._select_rules_for_ports(context, ports) for (binding, rule_in_db) in rules_in_db: port_id = binding['port_id'] diff --git a/neutron/plugins/bigswitch/plugin.py b/neutron/plugins/bigswitch/plugin.py index 1ac8a78e31..78ed005c7b 100644 --- a/neutron/plugins/bigswitch/plugin.py +++ b/neutron/plugins/bigswitch/plugin.py @@ -56,6 +56,7 @@ from neutron.agent import securitygroups_rpc as sg_rpc from neutron.api import extensions as neutron_extensions from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api from neutron.api.rpc.handlers import dhcp_rpc +from neutron.api.rpc.handlers import securitygroups_rpc from neutron.common import constants as const from neutron.common import exceptions from neutron.common import rpc as n_rpc @@ -72,7 +73,7 @@ from neutron.db import extradhcpopt_db from neutron.db import l3_db from neutron.db import models_v2 from neutron.db import securitygroups_db as sg_db -from neutron.db import securitygroups_rpc_base as sg_rpc_base +from neutron.db import securitygroups_rpc_base as sg_db_rpc from neutron.extensions import allowedaddresspairs as addr_pair from neutron.extensions import external_net from neutron.extensions import extra_dhcp_opt as edo_ext @@ -113,10 +114,7 @@ class AgentNotifierApi(n_rpc.RpcProxy, topic=self.topic_port_update) -class RestProxyCallbacks(n_rpc.RpcCallback, - sg_rpc_base.SecurityGroupServerRpcCallbackMixin): - - RPC_API_VERSION = '1.1' +class SecurityGroupServerRpcMixin(sg_db_rpc.SecurityGroupServerRpcMixin): def get_port_from_device(self, device): port_id = re.sub(r"^tap", "", device) @@ -454,7 +452,7 @@ class NeutronRestProxyV2(NeutronRestProxyV2Base, addr_pair_db.AllowedAddressPairsMixin, extradhcpopt_db.ExtraDhcpOptMixin, agentschedulers_db.DhcpAgentSchedulerDbMixin, - sg_rpc_base.SecurityGroupServerRpcMixin): + SecurityGroupServerRpcMixin): _supported_extension_aliases = ["external-net", "router", "binding", "router_rules", "extra_dhcp_opt", "quotas", @@ -509,7 +507,7 @@ class NeutronRestProxyV2(NeutronRestProxyV2Base, self.agent_notifiers[const.AGENT_TYPE_DHCP] = ( self._dhcp_agent_notifier ) - self.endpoints = [RestProxyCallbacks(), + self.endpoints = [securitygroups_rpc.SecurityGroupServerRpcCallback(), dhcp_rpc.DhcpRpcCallback(), agents_db.AgentExtRpcCallback()] self.conn.create_consumer(self.topic, self.endpoints, diff --git a/neutron/plugins/brocade/NeutronPlugin.py b/neutron/plugins/brocade/NeutronPlugin.py index e1408c44db..7b46e04bce 100644 --- a/neutron/plugins/brocade/NeutronPlugin.py +++ b/neutron/plugins/brocade/NeutronPlugin.py @@ -30,6 +30,7 @@ from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api from neutron.api.rpc.handlers import dhcp_rpc from neutron.api.rpc.handlers import l3_rpc +from neutron.api.rpc.handlers import securitygroups_rpc from neutron.common import constants as q_const from neutron.common import rpc as n_rpc from neutron.common import topics @@ -57,6 +58,7 @@ LOG = logging.getLogger(__name__) PLUGIN_VERSION = 0.88 AGENT_OWNER_PREFIX = "network:" NOS_DRIVER = 'neutron.plugins.brocade.nos.nosdriver.NOSdriver' +TAP_PREFIX_LEN = 3 SWITCH_OPTS = [cfg.StrOpt('address', default='', help=_('The address of the host to SSH to')), @@ -77,8 +79,7 @@ cfg.CONF.register_opts(SWITCH_OPTS, "SWITCH") cfg.CONF.register_opts(PHYSICAL_INTERFACE_OPTS, "PHYSICAL_INTERFACE") -class BridgeRpcCallbacks(n_rpc.RpcCallback, - sg_db_rpc.SecurityGroupServerRpcCallbackMixin): +class BridgeRpcCallbacks(n_rpc.RpcCallback): """Agent callback.""" RPC_API_VERSION = '1.2' @@ -86,32 +87,6 @@ class BridgeRpcCallbacks(n_rpc.RpcCallback, # history # 1.1 Support Security Group RPC # 1.2 Support get_devices_details_list - TAP_PREFIX_LEN = 3 - - @classmethod - def get_port_from_device(cls, device): - """Get port from the brocade specific db.""" - - # TODO(shh) context is not being passed as - # an argument to this function; - # - # need to be fixed in: - # file: neutron/db/securtygroups_rpc_base.py - # function: securitygroup_rules_for_devices() - # which needs to pass context to us - - # Doing what other plugins are doing - session = db.get_session() - port = brocade_db.get_port_from_device( - session, device[cls.TAP_PREFIX_LEN:]) - - # TODO(shiv): need to extend the db model to include device owners - # make it appears that the device owner is of type network - if port: - port['device'] = device - port['device_owner'] = AGENT_OWNER_PREFIX - port['binding:vif_type'] = 'bridge' - return port def get_device_details(self, rpc_context, **kwargs): """Agent requests device details.""" @@ -120,7 +95,7 @@ class BridgeRpcCallbacks(n_rpc.RpcCallback, device = kwargs.get('device') LOG.debug(_("Device %(device)s details requested from %(agent_id)s"), {'device': device, 'agent_id': agent_id}) - port = brocade_db.get_port(rpc_context, device[self.TAP_PREFIX_LEN:]) + port = brocade_db.get_port(rpc_context, device[TAP_PREFIX_LEN:]) if port: entry = {'device': device, 'vlan_id': port.vlan_id, @@ -163,6 +138,34 @@ class BridgeRpcCallbacks(n_rpc.RpcCallback, return entry +class SecurityGroupServerRpcMixin(sg_db_rpc.SecurityGroupServerRpcMixin): + + @classmethod + def get_port_from_device(cls, device): + """Get port from the brocade specific db.""" + + # TODO(shh) context is not being passed as + # an argument to this function; + # + # need to be fixed in: + # file: neutron/db/securtygroups_rpc_base.py + # function: securitygroup_rules_for_devices() + # which needs to pass context to us + + # Doing what other plugins are doing + session = db.get_session() + port = brocade_db.get_port_from_device( + session, device[TAP_PREFIX_LEN:]) + + # TODO(shiv): need to extend the db model to include device owners + # make it appears that the device owner is of type network + if port: + port['device'] = device + port['device_owner'] = AGENT_OWNER_PREFIX + port['binding:vif_type'] = 'bridge' + return port + + class AgentNotifierApi(n_rpc.RpcProxy, sg_rpc.SecurityGroupAgentRpcApiMixin): """Agent side of the linux bridge rpc API. @@ -205,7 +208,7 @@ class AgentNotifierApi(n_rpc.RpcProxy, class BrocadePluginV2(db_base_plugin_v2.NeutronDbPluginV2, external_net_db.External_net_db_mixin, extraroute_db.ExtraRoute_db_mixin, - sg_db_rpc.SecurityGroupServerRpcMixin, + SecurityGroupServerRpcMixin, l3_agentschedulers_db.L3AgentSchedulerDbMixin, agentschedulers_db.DhcpAgentSchedulerDbMixin, portbindings_base.PortBindingBaseMixin): @@ -262,6 +265,7 @@ class BrocadePluginV2(db_base_plugin_v2.NeutronDbPluginV2, is_admin=False) self.conn = n_rpc.create_connection(new=True) self.endpoints = [BridgeRpcCallbacks(), + securitygroups_rpc.SecurityGroupServerRpcCallback(), dhcp_rpc.DhcpRpcCallback(), l3_rpc.L3RpcCallback(), agents_db.AgentExtRpcCallback()] diff --git a/neutron/plugins/linuxbridge/lb_neutron_plugin.py b/neutron/plugins/linuxbridge/lb_neutron_plugin.py index b8ff5710de..2319f8da96 100644 --- a/neutron/plugins/linuxbridge/lb_neutron_plugin.py +++ b/neutron/plugins/linuxbridge/lb_neutron_plugin.py @@ -22,6 +22,7 @@ from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api from neutron.api.rpc.handlers import dhcp_rpc from neutron.api.rpc.handlers import l3_rpc +from neutron.api.rpc.handlers import securitygroups_rpc from neutron.api.v2 import attributes from neutron.common import constants as q_const from neutron.common import exceptions as n_exc @@ -52,24 +53,16 @@ from neutron.plugins.linuxbridge.db import l2network_db_v2 as db LOG = logging.getLogger(__name__) +# Device names start with "tap" +TAP_PREFIX_LEN = 3 -class LinuxBridgeRpcCallbacks(n_rpc.RpcCallback, - sg_db_rpc.SecurityGroupServerRpcCallbackMixin - ): + +class LinuxBridgeRpcCallbacks(n_rpc.RpcCallback): # history # 1.1 Support Security Group RPC # 1.2 Support get_devices_details_list RPC_API_VERSION = '1.2' - # Device names start with "tap" - TAP_PREFIX_LEN = 3 - - @classmethod - def get_port_from_device(cls, device): - port = db.get_port_from_device(device[cls.TAP_PREFIX_LEN:]) - if port: - port['device'] = device - return port def get_device_details(self, rpc_context, **kwargs): """Agent requests device details.""" @@ -77,7 +70,8 @@ class LinuxBridgeRpcCallbacks(n_rpc.RpcCallback, device = kwargs.get('device') LOG.debug(_("Device %(device)s details requested from %(agent_id)s"), {'device': device, 'agent_id': agent_id}) - port = self.get_port_from_device(device) + plugin = manager.NeutronManager.get_plugin() + port = plugin.get_port_from_device(device) if port: binding = db.get_network_binding(db_api.get_session(), port['network_id']) @@ -117,10 +111,10 @@ class LinuxBridgeRpcCallbacks(n_rpc.RpcCallback, agent_id = kwargs.get('agent_id') device = kwargs.get('device') host = kwargs.get('host') - port = self.get_port_from_device(device) LOG.debug(_("Device %(device)s no longer exists on %(agent_id)s"), {'device': device, 'agent_id': agent_id}) plugin = manager.NeutronManager.get_plugin() + port = plugin.get_port_from_device(device) if port: entry = {'device': device, 'exists': True} @@ -143,10 +137,10 @@ class LinuxBridgeRpcCallbacks(n_rpc.RpcCallback, agent_id = kwargs.get('agent_id') device = kwargs.get('device') host = kwargs.get('host') - port = self.get_port_from_device(device) LOG.debug(_("Device %(device)s up on %(agent_id)s"), {'device': device, 'agent_id': agent_id}) plugin = manager.NeutronManager.get_plugin() + port = plugin.get_port_from_device(device) if port: if (host and not plugin.get_port_host(rpc_context, port['id']) == host): @@ -283,6 +277,7 @@ class LinuxBridgePluginV2(db_base_plugin_v2.NeutronDbPluginV2, svc_constants.L3_ROUTER_NAT: topics.L3PLUGIN} self.conn = n_rpc.create_connection(new=True) self.endpoints = [LinuxBridgeRpcCallbacks(), + securitygroups_rpc.SecurityGroupServerRpcCallback(), dhcp_rpc.DhcpRpcCallback(), l3_rpc.L3RpcCallback(), agents_db.AgentExtRpcCallback()] @@ -542,3 +537,10 @@ class LinuxBridgePluginV2(db_base_plugin_v2.NeutronDbPluginV2, self.notifier.port_update(context, port, binding.physical_network, binding.vlan_id) + + @classmethod + def get_port_from_device(cls, device): + port = db.get_port_from_device(device[TAP_PREFIX_LEN:]) + if port: + port['device'] = device + return port diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index cb57323544..7f60ba5ce6 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -25,6 +25,7 @@ from neutron.agent import securitygroups_rpc as sg_rpc from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api from neutron.api.rpc.handlers import dhcp_rpc from neutron.api.rpc.handlers import dvr_rpc +from neutron.api.rpc.handlers import securitygroups_rpc from neutron.api.v2 import attributes from neutron.common import constants as const from neutron.common import exceptions as exc @@ -51,6 +52,7 @@ from neutron.openstack.common import importutils from neutron.openstack.common import jsonutils from neutron.openstack.common import lockutils from neutron.openstack.common import log +from neutron.openstack.common import uuidutils from neutron.plugins.common import constants as service_constants from neutron.plugins.ml2.common import exceptions as ml2_exc from neutron.plugins.ml2 import config # noqa @@ -69,6 +71,9 @@ MAX_BIND_TRIES = 10 # providernet.py? TYPE_MULTI_SEGMENT = 'multi-segment' +TAP_DEVICE_PREFIX = 'tap' +TAP_DEVICE_PREFIX_LENGTH = 3 + class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, dvr_mac_db.DVRDbMixin, @@ -136,6 +141,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, def start_rpc_listeners(self): self.endpoints = [rpc.RpcCallbacks(self.notifier, self.type_manager), + securitygroups_rpc.SecurityGroupServerRpcCallback(), dvr_rpc.DVRServerRpcCallback(), dhcp_rpc.DhcpRpcCallback(), agents_db.AgentExtRpcCallback()] @@ -1083,3 +1089,25 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, else: port_host = db.get_port_binding_host(port_id) return (port_host == host) + + def get_port_from_device(self, device): + port_id = self._device_to_port_id(device) + port = db.get_port_and_sgs(port_id) + if port: + port['device'] = device + return port + + def _device_to_port_id(self, device): + # REVISIT(rkukura): Consider calling into MechanismDrivers to + # process device names, or having MechanismDrivers supply list + # of device prefixes to strip. + if device.startswith(TAP_DEVICE_PREFIX): + return device[TAP_DEVICE_PREFIX_LENGTH:] + else: + # REVISIT(irenab): Consider calling into bound MD to + # handle the get_device_details RPC, then remove the 'else' clause + if not uuidutils.is_uuid_like(device): + port = db.get_port_from_device_mac(device) + if port: + return port.id + return device diff --git a/neutron/plugins/ml2/rpc.py b/neutron/plugins/ml2/rpc.py index 6a1c647cde..52d3980d92 100644 --- a/neutron/plugins/ml2/rpc.py +++ b/neutron/plugins/ml2/rpc.py @@ -20,13 +20,10 @@ from neutron.common import exceptions from neutron.common import rpc as n_rpc from neutron.common import topics from neutron.common import utils -from neutron.db import securitygroups_rpc_base as sg_db_rpc from neutron.extensions import portbindings from neutron import manager from neutron.openstack.common import log -from neutron.openstack.common import uuidutils from neutron.plugins.common import constants as service_constants -from neutron.plugins.ml2 import db from neutron.plugins.ml2 import driver_api as api from neutron.plugins.ml2.drivers import type_tunnel # REVISIT(kmestery): Allow the type and mechanism drivers to supply the @@ -34,12 +31,8 @@ from neutron.plugins.ml2.drivers import type_tunnel LOG = log.getLogger(__name__) -TAP_DEVICE_PREFIX = 'tap' -TAP_DEVICE_PREFIX_LENGTH = 3 - class RpcCallbacks(n_rpc.RpcCallback, - sg_db_rpc.SecurityGroupServerRpcCallbackMixin, type_tunnel.TunnelRpcCallbackMixin): RPC_API_VERSION = '1.3' @@ -53,30 +46,6 @@ class RpcCallbacks(n_rpc.RpcCallback, self.setup_tunnel_callback_mixin(notifier, type_manager) super(RpcCallbacks, self).__init__() - @classmethod - def _device_to_port_id(cls, device): - # REVISIT(rkukura): Consider calling into MechanismDrivers to - # process device names, or having MechanismDrivers supply list - # of device prefixes to strip. - if device.startswith(TAP_DEVICE_PREFIX): - return device[TAP_DEVICE_PREFIX_LENGTH:] - else: - # REVISIT(irenab): Consider calling into bound MD to - # handle the get_device_details RPC, then remove the 'else' clause - if not uuidutils.is_uuid_like(device): - port = db.get_port_from_device_mac(device) - if port: - return port.id - return device - - @classmethod - def get_port_from_device(cls, device): - port_id = cls._device_to_port_id(device) - port = db.get_port_and_sgs(port_id) - if port: - port['device'] = device - return port - def get_device_details(self, rpc_context, **kwargs): """Agent requests device details.""" agent_id = kwargs.get('agent_id') @@ -85,9 +54,9 @@ class RpcCallbacks(n_rpc.RpcCallback, LOG.debug("Device %(device)s details requested by agent " "%(agent_id)s with host %(host)s", {'device': device, 'agent_id': agent_id, 'host': host}) - port_id = self._device_to_port_id(device) plugin = manager.NeutronManager.get_plugin() + port_id = plugin._device_to_port_id(device) port_context = plugin.get_bound_port_context(rpc_context, port_id, host) @@ -152,7 +121,7 @@ class RpcCallbacks(n_rpc.RpcCallback, "%(agent_id)s"), {'device': device, 'agent_id': agent_id}) plugin = manager.NeutronManager.get_plugin() - port_id = self._device_to_port_id(device) + port_id = plugin._device_to_port_id(device) port_exists = True if (host and not plugin.port_bound_to_host(rpc_context, port_id, host)): @@ -177,7 +146,7 @@ class RpcCallbacks(n_rpc.RpcCallback, LOG.debug(_("Device %(device)s up at agent %(agent_id)s"), {'device': device, 'agent_id': agent_id}) plugin = manager.NeutronManager.get_plugin() - port_id = self._device_to_port_id(device) + port_id = plugin._device_to_port_id(device) if (host and not plugin.port_bound_to_host(rpc_context, port_id, host)): LOG.debug(_("Device %(device)s not bound to the" diff --git a/neutron/plugins/mlnx/mlnx_plugin.py b/neutron/plugins/mlnx/mlnx_plugin.py index ea5a4bc92f..0a8ed5b761 100644 --- a/neutron/plugins/mlnx/mlnx_plugin.py +++ b/neutron/plugins/mlnx/mlnx_plugin.py @@ -22,6 +22,7 @@ from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api from neutron.api.rpc.handlers import dhcp_rpc from neutron.api.rpc.handlers import l3_rpc +from neutron.api.rpc.handlers import securitygroups_rpc from neutron.api.v2 import attributes from neutron.common import constants as q_const from neutron.common import exceptions as n_exc @@ -51,6 +52,9 @@ from neutron.plugins.mlnx import rpc_callbacks LOG = logging.getLogger(__name__) +#to be compatible with Linux Bridge Agent on Network Node +TAP_PREFIX_LEN = 3 + class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2, external_net_db.External_net_db_mixin, @@ -122,6 +126,7 @@ class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2, svc_constants.L3_ROUTER_NAT: topics.L3PLUGIN} self.conn = n_rpc.create_connection(new=True) self.endpoints = [rpc_callbacks.MlnxRpcCallbacks(), + securitygroups_rpc.SecurityGroupServerRpcCallback(), dhcp_rpc.DhcpRpcCallback(), l3_rpc.L3RpcCallback(), agents_db.AgentExtRpcCallback()] @@ -515,3 +520,20 @@ class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2, # now that we've left db transaction, we are safe to notify self.notify_routers_updated(context, router_ids) self.notify_security_groups_member_updated(context, port) + + @classmethod + def get_port_from_device(cls, device): + """Get port according to device. + + To maintain compatibility with Linux Bridge L2 Agent for DHCP/L3 + services get device either by linux bridge plugin + device name convention or by mac address + """ + port = db.get_port_from_device(device[TAP_PREFIX_LEN:]) + if port: + port['device'] = device + else: + port = db.get_port_from_device_mac(device) + if port: + port['device'] = device + return port diff --git a/neutron/plugins/mlnx/rpc_callbacks.py b/neutron/plugins/mlnx/rpc_callbacks.py index 9337290fa6..d2252d3505 100644 --- a/neutron/plugins/mlnx/rpc_callbacks.py +++ b/neutron/plugins/mlnx/rpc_callbacks.py @@ -17,40 +17,18 @@ from oslo.config import cfg from neutron.common import constants as q_const from neutron.common import rpc as n_rpc from neutron.db import api as db_api -from neutron.db import securitygroups_rpc_base as sg_db_rpc from neutron.openstack.common import log as logging from neutron.plugins.mlnx.db import mlnx_db_v2 as db LOG = logging.getLogger(__name__) -class MlnxRpcCallbacks(n_rpc.RpcCallback, - sg_db_rpc.SecurityGroupServerRpcCallbackMixin): +class MlnxRpcCallbacks(n_rpc.RpcCallback): # History # 1.1 Support Security Group RPC # 1.2 Support get_devices_details_list RPC_API_VERSION = '1.2' - #to be compatible with Linux Bridge Agent on Network Node - TAP_PREFIX_LEN = 3 - - @classmethod - def get_port_from_device(cls, device): - """Get port according to device. - - To maintain compatibility with Linux Bridge L2 Agent for DHCP/L3 - services get device either by linux bridge plugin - device name convention or by mac address - """ - port = db.get_port_from_device(device[cls.TAP_PREFIX_LEN:]) - if port: - port['device'] = device - else: - port = db.get_port_from_device_mac(device) - if port: - port['device'] = device - return port - def get_device_details(self, rpc_context, **kwargs): """Agent requests device details.""" agent_id = kwargs.get('agent_id') diff --git a/neutron/plugins/nec/nec_plugin.py b/neutron/plugins/nec/nec_plugin.py index 936057ba1b..f88ce8d3d3 100644 --- a/neutron/plugins/nec/nec_plugin.py +++ b/neutron/plugins/nec/nec_plugin.py @@ -19,6 +19,7 @@ from neutron.api import extensions as neutron_extensions from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api from neutron.api.rpc.handlers import dhcp_rpc from neutron.api.rpc.handlers import l3_rpc +from neutron.api.rpc.handlers import securitygroups_rpc from neutron.api.v2 import attributes as attrs from neutron.common import constants as const from neutron.common import exceptions as n_exc @@ -53,10 +54,23 @@ from neutron.plugins.nec import packet_filter LOG = logging.getLogger(__name__) +class SecurityGroupServerRpcMixin(sg_db_rpc.SecurityGroupServerRpcMixin): + + @staticmethod + def get_port_from_device(device): + port = ndb.get_port_from_device(device) + if port: + port['device'] = device + LOG.debug("NECPluginV2.get_port_from_device() called, " + "device=%(device)s => %(ret)s.", + {'device': device, 'ret': port}) + return port + + class NECPluginV2(db_base_plugin_v2.NeutronDbPluginV2, external_net_db.External_net_db_mixin, nec_router.RouterMixin, - sg_db_rpc.SecurityGroupServerRpcMixin, + SecurityGroupServerRpcMixin, agentschedulers_db.DhcpAgentSchedulerDbMixin, nec_router.L3AgentSchedulerDbMixin, packet_filter.PacketFilterMixin, @@ -143,7 +157,7 @@ class NECPluginV2(db_base_plugin_v2.NeutronDbPluginV2, ) # NOTE: callback_sg is referred to from the sg unit test. - self.callback_sg = SecurityGroupServerRpcCallback() + self.callback_sg = securitygroups_rpc.SecurityGroupServerRpcCallback() self.endpoints = [ NECPluginV2RPCCallbacks(self.safe_reference), dhcp_rpc.DhcpRpcCallback(), @@ -680,23 +694,6 @@ class NECPluginV2AgentNotifierApi(n_rpc.RpcProxy, topic=self.topic_port_update) -class SecurityGroupServerRpcCallback( - n_rpc.RpcCallback, - sg_db_rpc.SecurityGroupServerRpcCallbackMixin): - - RPC_API_VERSION = sg_rpc.SG_RPC_VERSION - - @staticmethod - def get_port_from_device(device): - port = ndb.get_port_from_device(device) - if port: - port['device'] = device - LOG.debug(_("NECPluginV2RPCCallbacks.get_port_from_device() called, " - "device=%(device)s => %(ret)s."), - {'device': device, 'ret': port}) - return port - - class NECPluginV2RPCCallbacks(n_rpc.RpcCallback): RPC_API_VERSION = '1.0' diff --git a/neutron/plugins/oneconvergence/plugin.py b/neutron/plugins/oneconvergence/plugin.py index b0c0f3e17f..580a66d3d8 100644 --- a/neutron/plugins/oneconvergence/plugin.py +++ b/neutron/plugins/oneconvergence/plugin.py @@ -23,6 +23,7 @@ from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api from neutron.api.rpc.handlers import dhcp_rpc from neutron.api.rpc.handlers import l3_rpc +from neutron.api.rpc.handlers import securitygroups_rpc from neutron.common import constants as q_const from neutron.common import exceptions as nexception from neutron.common import rpc as n_rpc @@ -51,10 +52,7 @@ LOG = logging.getLogger(__name__) IPv6 = 6 -class NVSDPluginRpcCallbacks(n_rpc.RpcCallback, - sg_db_rpc.SecurityGroupServerRpcCallbackMixin): - - RPC_API_VERSION = '1.1' +class SecurityGroupServerRpcMixin(sg_db_rpc.SecurityGroupServerRpcMixin): @staticmethod def get_port_from_device(device): @@ -88,7 +86,7 @@ class OneConvergencePluginV2(db_base_plugin_v2.NeutronDbPluginV2, external_net_db.External_net_db_mixin, l3_gwmode_db.L3_NAT_db_mixin, portbindings_base.PortBindingBaseMixin, - sg_db_rpc.SecurityGroupServerRpcMixin): + SecurityGroupServerRpcMixin): """L2 Virtual Network Plugin. @@ -159,7 +157,7 @@ class OneConvergencePluginV2(db_base_plugin_v2.NeutronDbPluginV2, self.agent_notifiers[q_const.AGENT_TYPE_L3] = ( l3_rpc_agent_api.L3AgentNotifyAPI() ) - self.endpoints = [NVSDPluginRpcCallbacks(), + self.endpoints = [securitygroups_rpc.SecurityGroupServerRpcCallback(), dhcp_rpc.DhcpRpcCallback(), l3_rpc.L3RpcCallback(), agents_db.AgentExtRpcCallback()] diff --git a/neutron/plugins/openvswitch/ovs_neutron_plugin.py b/neutron/plugins/openvswitch/ovs_neutron_plugin.py index f72a82e365..7dad9b66d9 100644 --- a/neutron/plugins/openvswitch/ovs_neutron_plugin.py +++ b/neutron/plugins/openvswitch/ovs_neutron_plugin.py @@ -22,6 +22,7 @@ from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api from neutron.api.rpc.handlers import dhcp_rpc from neutron.api.rpc.handlers import l3_rpc +from neutron.api.rpc.handlers import securitygroups_rpc from neutron.api.v2 import attributes from neutron.common import constants as q_const from neutron.common import exceptions as n_exc @@ -58,8 +59,7 @@ from neutron.plugins.openvswitch import ovs_db_v2 LOG = logging.getLogger(__name__) -class OVSRpcCallbacks(n_rpc.RpcCallback, - sg_db_rpc.SecurityGroupServerRpcCallbackMixin): +class OVSRpcCallbacks(n_rpc.RpcCallback): # history # 1.0 Initial version @@ -73,13 +73,6 @@ class OVSRpcCallbacks(n_rpc.RpcCallback, self.notifier = notifier self.tunnel_type = tunnel_type - @classmethod - def get_port_from_device(cls, device): - port = ovs_db_v2.get_port_from_device(device) - if port: - port['device'] = device - return port - def get_device_details(self, rpc_context, **kwargs): """Agent requests device details.""" agent_id = kwargs.get('agent_id') @@ -183,6 +176,16 @@ class OVSRpcCallbacks(n_rpc.RpcCallback, return entry +class SecurityGroupServerRpcMixin(sg_db_rpc.SecurityGroupServerRpcMixin): + + @classmethod + def get_port_from_device(cls, device): + port = ovs_db_v2.get_port_from_device(device) + if port: + port['device'] = device + return port + + class AgentNotifierApi(n_rpc.RpcProxy, sg_rpc.SecurityGroupAgentRpcApiMixin): '''Agent side of the openvswitch rpc API. @@ -236,7 +239,7 @@ class OVSNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2, external_net_db.External_net_db_mixin, extraroute_db.ExtraRoute_db_mixin, l3_gwmode_db.L3_NAT_db_mixin, - sg_db_rpc.SecurityGroupServerRpcMixin, + SecurityGroupServerRpcMixin, l3_agentschedulers_db.L3AgentSchedulerDbMixin, agentschedulers_db.DhcpAgentSchedulerDbMixin, portbindings_db.PortBindingMixin, @@ -344,6 +347,7 @@ class OVSNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2, l3_rpc_agent_api.L3AgentNotifyAPI() ) self.endpoints = [OVSRpcCallbacks(self.notifier, self.tunnel_type), + securitygroups_rpc.SecurityGroupServerRpcCallback(), dhcp_rpc.DhcpRpcCallback(), l3_rpc.L3RpcCallback(), agents_db.AgentExtRpcCallback()] diff --git a/neutron/plugins/ryu/ryu_neutron_plugin.py b/neutron/plugins/ryu/ryu_neutron_plugin.py index cb6ee87804..a6da5df3d5 100644 --- a/neutron/plugins/ryu/ryu_neutron_plugin.py +++ b/neutron/plugins/ryu/ryu_neutron_plugin.py @@ -22,6 +22,7 @@ from ryu.app import rest_nw_id from neutron.agent import securitygroups_rpc as sg_rpc from neutron.api.rpc.handlers import dhcp_rpc from neutron.api.rpc.handlers import l3_rpc +from neutron.api.rpc.handlers import securitygroups_rpc from neutron.common import constants as q_const from neutron.common import exceptions as n_exc from neutron.common import rpc as n_rpc @@ -45,8 +46,17 @@ from neutron.plugins.ryu.db import api_v2 as db_api_v2 LOG = logging.getLogger(__name__) -class RyuRpcCallbacks(n_rpc.RpcCallback, - sg_db_rpc.SecurityGroupServerRpcCallbackMixin): +class SecurityGroupServerRpcMixin(sg_db_rpc.SecurityGroupServerRpcMixin): + + @classmethod + def get_port_from_device(cls, device): + port = db_api_v2.get_port_from_device(device) + if port: + port['device'] = device + return port + + +class RyuRpcCallbacks(n_rpc.RpcCallback): RPC_API_VERSION = '1.1' @@ -58,13 +68,6 @@ class RyuRpcCallbacks(n_rpc.RpcCallback, LOG.debug(_("get_ofp_rest_api: %s"), self.ofp_rest_api_addr) return self.ofp_rest_api_addr - @classmethod - def get_port_from_device(cls, device): - port = db_api_v2.get_port_from_device(device) - if port: - port['device'] = device - return port - class AgentNotifierApi(n_rpc.RpcProxy, sg_rpc.SecurityGroupAgentRpcApiMixin): @@ -88,7 +91,7 @@ class RyuNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2, external_net_db.External_net_db_mixin, extraroute_db.ExtraRoute_db_mixin, l3_gwmode_db.L3_NAT_db_mixin, - sg_db_rpc.SecurityGroupServerRpcMixin, + SecurityGroupServerRpcMixin, portbindings_base.PortBindingBaseMixin): _supported_extension_aliases = ["external-net", "router", "ext-gw-mode", @@ -138,6 +141,7 @@ class RyuNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2, self.conn = n_rpc.create_connection(new=True) self.notifier = AgentNotifierApi(topics.AGENT) self.endpoints = [RyuRpcCallbacks(self.ofp_api_host), + securitygroups_rpc.SecurityGroupServerRpcCallback(), dhcp_rpc.DhcpRpcCallback(), l3_rpc.L3RpcCallback()] for svc_topic in self.service_topics.values(): diff --git a/neutron/tests/unit/bigswitch/test_security_groups.py b/neutron/tests/unit/bigswitch/test_security_groups.py index 1e3a7aa56f..409e9ce4f4 100644 --- a/neutron/tests/unit/bigswitch/test_security_groups.py +++ b/neutron/tests/unit/bigswitch/test_security_groups.py @@ -36,7 +36,7 @@ class RestProxySecurityGroupsTestCase(test_sg.SecurityGroupDBTestCase, self.startHttpPatch() -class TestSecServerRpcCallBack(test_sg_rpc.SGServerRpcCallBackMixinTestCase, +class TestSecServerRpcCallBack(test_sg_rpc.SGServerRpcCallBackTestCase, RestProxySecurityGroupsTestCase): pass diff --git a/neutron/tests/unit/linuxbridge/test_linuxbridge_plugin.py b/neutron/tests/unit/linuxbridge/test_linuxbridge_plugin.py index 3ff0f7592a..0572336af5 100644 --- a/neutron/tests/unit/linuxbridge/test_linuxbridge_plugin.py +++ b/neutron/tests/unit/linuxbridge/test_linuxbridge_plugin.py @@ -13,8 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import contextlib - import mock from oslo.config import cfg @@ -95,11 +93,9 @@ class TestLinuxBridgePluginRpcCallbacks(test_plugin.NeutronDbPluginV2TestCase): self.callbacks = lb_neutron_plugin.LinuxBridgeRpcCallbacks() def test_update_device_down(self): - with contextlib.nested( - mock.patch.object(self.callbacks, "get_port_from_device", - return_value=None), - mock.patch.object(manager.NeutronManager, "get_plugin") - ) as (gpfd, gp): + with mock.patch.object(manager.NeutronManager, "get_plugin") as gp: + plugin = gp.return_value + plugin.get_port_from_device.return_value = None self.assertEqual( self.callbacks.update_device_down("fake_context", agent_id="123", @@ -107,8 +103,9 @@ class TestLinuxBridgePluginRpcCallbacks(test_plugin.NeutronDbPluginV2TestCase): host="host"), {'device': 'device', 'exists': False} ) - gpfd.return_value = {'id': 'fakeid', - 'status': q_const.PORT_STATUS_ACTIVE} + plugin.get_port_from_device.return_value = { + 'id': 'fakeid', + 'status': q_const.PORT_STATUS_ACTIVE} self.assertEqual( self.callbacks.update_device_down("fake_context", agent_id="123", @@ -118,15 +115,13 @@ class TestLinuxBridgePluginRpcCallbacks(test_plugin.NeutronDbPluginV2TestCase): ) def test_update_device_up(self): - with contextlib.nested( - mock.patch.object(self.callbacks, "get_port_from_device", - return_value=None), - mock.patch.object(manager.NeutronManager, "get_plugin") - ) as (gpfd, gp): - gpfd.return_value = {'id': 'fakeid', - 'status': q_const.PORT_STATUS_ACTIVE} + with mock.patch.object(manager.NeutronManager, "get_plugin") as gp: + plugin = gp.return_value + plugin.get_port_from_device.return_value = { + 'id': 'fakeid', + 'status': q_const.PORT_STATUS_ACTIVE} self.callbacks.update_device_up("fake_context", agent_id="123", device="device", host="host") - gpfd.assert_called_once_with('device') + plugin.get_port_from_device.assert_called_once_with('device') diff --git a/neutron/tests/unit/ml2/test_rpcapi.py b/neutron/tests/unit/ml2/test_rpcapi.py index 71d80d040d..272dcb2f36 100644 --- a/neutron/tests/unit/ml2/test_rpcapi.py +++ b/neutron/tests/unit/ml2/test_rpcapi.py @@ -42,7 +42,8 @@ class RpcCallbacksTestCase(base.BaseTestCase): } def _test_update_device_up(self, extensions, kwargs): - with mock.patch.object(self.callbacks, '_device_to_port_id'): + with mock.patch('neutron.plugins.ml2.plugin.Ml2Plugin' + '._device_to_port_id'): type(self.l3plugin).supported_extension_aliases = ( mock.PropertyMock(return_value=extensions)) self.callbacks.update_device_up(mock.ANY, **kwargs) diff --git a/neutron/tests/unit/ml2/test_security_group.py b/neutron/tests/unit/ml2/test_security_group.py index 3e82c91e4f..39c3cc2bae 100644 --- a/neutron/tests/unit/ml2/test_security_group.py +++ b/neutron/tests/unit/ml2/test_security_group.py @@ -74,8 +74,7 @@ class TestMl2SecurityGroups(Ml2SecurityGroupsTestCase, req.get_response(self.api)) port_id = res['port']['id'] plugin = manager.NeutronManager.get_plugin() - callbacks = plugin.endpoints[0] - port_dict = callbacks.get_port_from_device(port_id) + port_dict = plugin.get_port_from_device(port_id) self.assertEqual(port_id, port_dict['id']) self.assertEqual([security_group_id], port_dict[ext_sg.SECURITYGROUPS]) @@ -86,7 +85,7 @@ class TestMl2SecurityGroups(Ml2SecurityGroupsTestCase, def test_security_group_get_port_from_device_with_no_port(self): plugin = manager.NeutronManager.get_plugin() - port_dict = plugin.endpoints[0].get_port_from_device('bad_device_id') + port_dict = plugin.get_port_from_device('bad_device_id') self.assertIsNone(port_dict) @@ -96,11 +95,11 @@ class TestMl2SecurityGroupsXML(TestMl2SecurityGroups): class TestMl2SGServerRpcCallBack( Ml2SecurityGroupsTestCase, - test_sg_rpc.SGServerRpcCallBackMixinTestCase): + test_sg_rpc.SGServerRpcCallBackTestCase): pass class TestMl2SGServerRpcCallBackXML( Ml2SecurityGroupsTestCase, - test_sg_rpc.SGServerRpcCallBackMixinTestCaseXML): + test_sg_rpc.SGServerRpcCallBackTestCaseXML): pass diff --git a/neutron/tests/unit/nec/test_security_group.py b/neutron/tests/unit/nec/test_security_group.py index fd442c3b24..1d961fa650 100644 --- a/neutron/tests/unit/nec/test_security_group.py +++ b/neutron/tests/unit/nec/test_security_group.py @@ -51,13 +51,13 @@ class NecSecurityGroupsTestCase(test_sg.SecurityGroupDBTestCase): class TestNecSGServerRpcCallBack( - test_sg_rpc.SGServerRpcCallBackMixinTestCase, + test_sg_rpc.SGServerRpcCallBackTestCase, NecSecurityGroupsTestCase): pass class TestNecSGServerRpcCallBackXML( - test_sg_rpc.SGServerRpcCallBackMixinTestCaseXML, + test_sg_rpc.SGServerRpcCallBackTestCaseXML, NecSecurityGroupsTestCase): pass @@ -84,7 +84,7 @@ class TestNecSecurityGroups(NecSecurityGroupsTestCase, req.get_response(self.api)) plugin = manager.NeutronManager.get_plugin() - port_dict = plugin.callback_sg.get_port_from_device(port_id) + port_dict = plugin.get_port_from_device(port_id) self.assertEqual(port_id, port_dict['id']) self.assertEqual([sg_id], port_dict[ext_sg.SECURITYGROUPS]) diff --git a/neutron/tests/unit/oneconvergence/test_security_group.py b/neutron/tests/unit/oneconvergence/test_security_group.py index 93dc0ab4dc..495a30b99d 100644 --- a/neutron/tests/unit/oneconvergence/test_security_group.py +++ b/neutron/tests/unit/oneconvergence/test_security_group.py @@ -68,15 +68,13 @@ class OneConvergenceSecurityGroupsTestCase(test_sg.SecurityGroupDBTestCase): class TestOneConvergenceSGServerRpcCallBack( OneConvergenceSecurityGroupsTestCase, - test_sg_rpc.SGServerRpcCallBackMixinTestCase): - + test_sg_rpc.SGServerRpcCallBackTestCase): pass class TestOneConvergenceSGServerRpcCallBackXML( OneConvergenceSecurityGroupsTestCase, - test_sg_rpc.SGServerRpcCallBackMixinTestCaseXML): - + test_sg_rpc.SGServerRpcCallBackTestCaseXML): pass @@ -103,8 +101,7 @@ class TestOneConvergenceSecurityGroups(OneConvergenceSecurityGroupsTestCase, req.get_response(self.api)) port_id = res['port']['id'] plugin = manager.NeutronManager.get_plugin() - callbacks = plugin.endpoints[0] - port_dict = callbacks.get_port_from_device(port_id) + port_dict = plugin.get_port_from_device(port_id) self.assertEqual(port_id, port_dict['id']) self.assertEqual([security_group_id], port_dict[ext_sg.SECURITYGROUPS]) @@ -116,7 +113,7 @@ class TestOneConvergenceSecurityGroups(OneConvergenceSecurityGroupsTestCase, def test_security_group_get_port_from_device_with_no_port(self): plugin = manager.NeutronManager.get_plugin() - port_dict = plugin.endpoints[0].get_port_from_device('bad_device_id') + port_dict = plugin.get_port_from_device('bad_device_id') self.assertIsNone(port_dict) diff --git a/neutron/tests/unit/openvswitch/test_ovs_security_group.py b/neutron/tests/unit/openvswitch/test_ovs_security_group.py index 05acdc5dec..83f91cb7b9 100644 --- a/neutron/tests/unit/openvswitch/test_ovs_security_group.py +++ b/neutron/tests/unit/openvswitch/test_ovs_security_group.py @@ -50,13 +50,13 @@ class OpenvswitchSecurityGroupsTestCase(test_sg.SecurityGroupDBTestCase): class TestOpenvswitchSGServerRpcCallBack( OpenvswitchSecurityGroupsTestCase, - test_sg_rpc.SGServerRpcCallBackMixinTestCase): + test_sg_rpc.SGServerRpcCallBackTestCase): pass class TestOpenvswitchSGServerRpcCallBackXML( OpenvswitchSecurityGroupsTestCase, - test_sg_rpc.SGServerRpcCallBackMixinTestCaseXML): + test_sg_rpc.SGServerRpcCallBackTestCaseXML): pass @@ -82,8 +82,7 @@ class TestOpenvswitchSecurityGroups(OpenvswitchSecurityGroupsTestCase, req.get_response(self.api)) port_id = res['port']['id'] plugin = manager.NeutronManager.get_plugin() - callbacks = plugin.endpoints[0] - port_dict = callbacks.get_port_from_device(port_id) + port_dict = plugin.get_port_from_device(port_id) self.assertEqual(port_id, port_dict['id']) self.assertEqual([security_group_id], port_dict[ext_sg.SECURITYGROUPS]) @@ -94,7 +93,7 @@ class TestOpenvswitchSecurityGroups(OpenvswitchSecurityGroupsTestCase, def test_security_group_get_port_from_device_with_no_port(self): plugin = manager.NeutronManager.get_plugin() - port_dict = plugin.endpoints[0].get_port_from_device('bad_device_id') + port_dict = plugin.get_port_from_device('bad_device_id') self.assertIsNone(port_dict) diff --git a/neutron/tests/unit/ryu/test_ryu_security_group.py b/neutron/tests/unit/ryu/test_ryu_security_group.py index 5e1c1ecd6c..8939c79b06 100644 --- a/neutron/tests/unit/ryu/test_ryu_security_group.py +++ b/neutron/tests/unit/ryu/test_ryu_security_group.py @@ -71,7 +71,7 @@ class TestRyuSecurityGroups(RyuSecurityGroupsTestCase, req.get_response(self.api)) port_id = res['port']['id'] plugin = manager.NeutronManager.get_plugin() - port_dict = plugin.endpoints[0].get_port_from_device(port_id) + port_dict = plugin.get_port_from_device(port_id) self.assertEqual(port_id, port_dict['id']) self.assertEqual([security_group_id], port_dict[ext_sg.SECURITYGROUPS]) @@ -82,7 +82,7 @@ class TestRyuSecurityGroups(RyuSecurityGroupsTestCase, def test_security_group_get_port_from_device_with_no_port(self): plugin = manager.NeutronManager.get_plugin() - port_dict = plugin.endpoints[0].get_port_from_device('bad_device_id') + port_dict = plugin.get_port_from_device('bad_device_id') self.assertIsNone(port_dict) diff --git a/neutron/tests/unit/test_security_groups_rpc.py b/neutron/tests/unit/test_security_groups_rpc.py index 81a43ea5bf..695a744871 100644 --- a/neutron/tests/unit/test_security_groups_rpc.py +++ b/neutron/tests/unit/test_security_groups_rpc.py @@ -25,6 +25,7 @@ from neutron.agent import firewall as firewall_base from neutron.agent.linux import iptables_manager from neutron.agent import rpc as agent_rpc from neutron.agent import securitygroups_rpc as sg_rpc +from neutron.api.rpc.handlers import securitygroups_rpc from neutron.common import constants as const from neutron.common import ipv6_utils as ipv6 from neutron.common import rpc as n_rpc @@ -45,7 +46,38 @@ FAKE_IP = {const.IPv4: '10.0.0.1', 'IPv6_LLA': 'fe80::123'} -class FakeSGCallback(sg_db_rpc.SecurityGroupServerRpcCallbackMixin): +TEST_PLUGIN_CLASS = ('neutron.tests.unit.test_security_groups_rpc.' + 'SecurityGroupRpcTestPlugin') + + +class SecurityGroupRpcTestPlugin(test_sg.SecurityGroupTestPlugin, + sg_db_rpc.SecurityGroupServerRpcMixin): + def __init__(self): + super(SecurityGroupRpcTestPlugin, self).__init__() + self.notifier = mock.Mock() + self.devices = {} + + def create_port(self, context, port): + result = super(SecurityGroupRpcTestPlugin, + self).create_port(context, port) + self.devices[result['id']] = result + self.notify_security_groups_member_updated(context, result) + return result + + def update_port(self, context, id, port): + original_port = self.get_port(context, id) + updated_port = super(SecurityGroupRpcTestPlugin, + self).update_port(context, id, port) + self.devices[id] = updated_port + self.update_security_group_on_port( + context, id, port, original_port, updated_port) + + def delete_port(self, context, id): + port = self.get_port(context, id) + super(SecurityGroupRpcTestPlugin, self).delete_port(context, id) + self.notify_security_groups_member_updated(context, port) + del self.devices[id] + def get_port_from_device(self, device): device = self.devices.get(device) if device: @@ -56,13 +88,15 @@ class FakeSGCallback(sg_db_rpc.SecurityGroupServerRpcCallbackMixin): return device -class SGServerRpcCallBackMixinTestCase(test_sg.SecurityGroupDBTestCase): +class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase): def setUp(self, plugin=None): + plugin = plugin or TEST_PLUGIN_CLASS cfg.CONF.set_default('firewall_driver', 'neutron.agent.firewall.NoopFirewallDriver', group='SECURITYGROUP') - super(SGServerRpcCallBackMixinTestCase, self).setUp(plugin) - self.rpc = FakeSGCallback() + super(SGServerRpcCallBackTestCase, self).setUp(plugin) + self.notifier = manager.NeutronManager.get_plugin().notifier + self.rpc = securitygroups_rpc.SecurityGroupServerRpcCallback() def _test_security_group_port(self, device_owner, gw_ip, cidr, ip_version, ip_address): @@ -71,93 +105,73 @@ class SGServerRpcCallBackMixinTestCase(test_sg.SecurityGroupDBTestCase): gateway_ip=gw_ip, cidr=cidr, ip_version=ip_version) as subnet: - with mock.patch.object( - self.notifier, - 'security_groups_provider_updated') as mock_notifier: - kwargs = { - 'fixed_ips': [{'subnet_id': subnet['subnet']['id'], - 'ip_address': ip_address}]} - if device_owner: - kwargs['device_owner'] = device_owner - res = self._create_port( - self.fmt, net['network']['id'], **kwargs) - res = self.deserialize(self.fmt, res) - port_id = res['port']['id'] - if device_owner == const.DEVICE_OWNER_ROUTER_INTF: - data = {'port': {'fixed_ips': []}} - req = self.new_update_request('ports', data, port_id) - res = self.deserialize(self.fmt, - req.get_response(self.api)) - self._delete('ports', port_id) - return mock_notifier + kwargs = { + 'fixed_ips': [{'subnet_id': subnet['subnet']['id'], + 'ip_address': ip_address}]} + if device_owner: + kwargs['device_owner'] = device_owner + res = self._create_port( + self.fmt, net['network']['id'], **kwargs) + res = self.deserialize(self.fmt, res) + port_id = res['port']['id'] + if device_owner == const.DEVICE_OWNER_ROUTER_INTF: + data = {'port': {'fixed_ips': []}} + req = self.new_update_request('ports', data, port_id) + res = self.deserialize(self.fmt, + req.get_response(self.api)) + self._delete('ports', port_id) def test_notify_security_group_ipv6_gateway_port_added(self): - if getattr(self, "notifier", None) is None: - self.skipTest("Notifier mock is not set so security group " - "RPC calls can't be tested") - - mock_notifier = self._test_security_group_port( + self._test_security_group_port( const.DEVICE_OWNER_ROUTER_INTF, '2001:0db8::1', '2001:0db8::/64', 6, '2001:0db8::1') - self.assertTrue(mock_notifier.called) + self.assertTrue(self.notifier.security_groups_provider_updated.called) def test_notify_security_group_ipv6_normal_port_added(self): - if getattr(self, "notifier", None) is None: - self.skipTest("Notifier mock is not set so security group " - "RPC calls can't be tested") - mock_notifier = self._test_security_group_port( + self._test_security_group_port( None, '2001:0db8::1', '2001:0db8::/64', 6, '2001:0db8::3') - self.assertFalse(mock_notifier.called) + self.assertFalse(self.notifier.security_groups_provider_updated.called) def test_notify_security_group_ipv4_dhcp_port_added(self): - if getattr(self, "notifier", None) is None: - self.skipTest("Notifier mock is not set so security group " - "RPC calls can't be tested") - mock_notifier = self._test_security_group_port( + self._test_security_group_port( const.DEVICE_OWNER_DHCP, '192.168.1.1', '192.168.1.0/24', 4, '192.168.1.2') - self.assertTrue(mock_notifier.called) + self.assertTrue(self.notifier.security_groups_provider_updated.called) def test_notify_security_group_ipv4_gateway_port_added(self): - if getattr(self, "notifier", None) is None: - self.skipTest("Notifier mock is not set so security group " - "RPC calls can't be tested") - mock_notifier = self._test_security_group_port( + self._test_security_group_port( const.DEVICE_OWNER_ROUTER_INTF, '192.168.1.1', '192.168.1.0/24', 4, '192.168.1.1') - self.assertFalse(mock_notifier.called) + self.assertFalse(self.notifier.security_groups_provider_updated.called) def test_notify_security_group_ipv4_normal_port_added(self): - if getattr(self, "notifier", None) is None: - self.skipTest("Notifier mock is not set so security group " - "RPC calls can't be tested") - mock_notifier = self._test_security_group_port( + self._test_security_group_port( None, '192.168.1.1', '192.168.1.0/24', 4, '192.168.1.3') - self.assertFalse(mock_notifier.called) + self.assertFalse(self.notifier.security_groups_provider_updated.called) def test_security_group_rules_for_devices_ipv4_ingress(self): fake_prefix = FAKE_PREFIX[const.IPv4] with self.network() as n: - with contextlib.nested(self.subnet(n), - self.security_group()) as (subnet_v4, - sg1): + with contextlib.nested( + self.subnet(n), + self.security_group()) as (subnet_v4, sg1): sg1_id = sg1['security_group']['id'] rule1 = self._build_security_group_rule( sg1_id, @@ -829,7 +843,7 @@ class SGServerRpcCallBackMixinTestCase(test_sg.SecurityGroupDBTestCase): self._delete('ports', port_id2) -class SGServerRpcCallBackMixinTestCaseXML(SGServerRpcCallBackMixinTestCase): +class SGServerRpcCallBackTestCaseXML(SGServerRpcCallBackTestCase): fmt = 'xml'