From: Akihiro Motoki Date: Sat, 7 Feb 2015 13:22:14 +0000 (+0900) Subject: NEC plugin code split X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=1fdbcb13432c9d31e42d28912f5575a9a623c627;p=openstack-build%2Fneutron-build.git NEC plugin code split - Removes main codes and unit tests of NEC plugin - Add plugin-specific requirements.txt to the plugin dir. - Move config to the plugin top dir - Remove references of networking_nec from config module because it may prevent config guide generator. - agent command can be moved to neutron/cmd/eventlet if some consensus has been made. Closes-Bug: #1419396 Related to blueprint core-vendor-decomposition Change-Id: I946e0f829e8f6251a63572331c783d7a7b5f6c01 --- diff --git a/doc/source/devref/contribute.rst b/doc/source/devref/contribute.rst index 454c7d134..90b56d1bd 100644 --- a/doc/source/devref/contribute.rst +++ b/doc/source/devref/contribute.rst @@ -412,6 +412,8 @@ The following chart captures the following aspects: +-------------------------------+-----------------------+-----------+------------------+---------+--------------+ | networking-mlnx_ | | | | | | +-------------------------------+-----------------------+-----------+------------------+---------+--------------+ +| networking-nec_ | core | yes | no | [C] | Kilo | ++-------------------------------+-----------------------+-----------+------------------+---------+--------------+ | nuage-openstack-neutron_ | | | | | | +-------------------------------+-----------------------+-----------+------------------+---------+--------------+ | networking-odl_ | ml2,l3,lb,fw | yes | no | [C] | Kilo | @@ -468,6 +470,14 @@ MidoNet .. _networking-mlnx: +.. _networking-nec: + +NEC +--- + +* Git: https://github.com/stackforge/networking-nec +* Launchpad: https://launchpad.net/networking-nec + .. _nuage-openstack-neutron: .. _networking-odl: diff --git a/neutron/plugins/nec/agent/__init__.py b/neutron/cmd/eventlet/plugins/__init__.py similarity index 100% rename from neutron/plugins/nec/agent/__init__.py rename to neutron/cmd/eventlet/plugins/__init__.py diff --git a/neutron/plugins/nec/common/utils.py b/neutron/cmd/eventlet/plugins/nec_neutron_agent.py similarity index 60% rename from neutron/plugins/nec/common/utils.py rename to neutron/cmd/eventlet/plugins/nec_neutron_agent.py index a628d8ef0..7cd7503a9 100644 --- a/neutron/plugins/nec/common/utils.py +++ b/neutron/cmd/eventlet/plugins/nec_neutron_agent.py @@ -1,4 +1,5 @@ -# Copyright 2014 NEC Corporation. All rights reserved. +# Copyright 2012 NEC Corporation. +# 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 @@ -12,13 +13,16 @@ # License for the specific language governing permissions and limitations # under the License. +import sys -def cmp_dpid(dpid_a, dpid_b): - """Compare two datapath IDs as hexadecimal int. +from networking_nec.plugins.openflow.agent import l2_agent - It returns True if equal, otherwise False. - """ - try: - return (int(dpid_a, 16) == int(dpid_b, 16)) - except Exception: - return False +from neutron.common import config as common_config +from neutron.plugins.nec import config as nec_config + + +def main(): + nec_config.register_agent_opts() + common_config.init(sys.argv[1:]) + common_config.setup_logging() + l2_agent.run() diff --git a/neutron/plugins/nec/README b/neutron/plugins/nec/README index 694b80e99..337c2a03c 100644 --- a/neutron/plugins/nec/README +++ b/neutron/plugins/nec/README @@ -1,13 +1,11 @@ -Quantum NEC OpenFlow Plugin +Neutron NEC OpenFlow Plugin +=========================== +Neutron plugins for NEC OpenFlow networking products and +Trema Sliceable Switch (reference implementation). -# -- What's this? +* Main Page: https://wiki.openstack.org/wiki/Neutron/NEC_OpenFlow_Plugin -https://wiki.openstack.org/wiki/Neutron/NEC_OpenFlow_Plugin - - -# -- Installation - -Use QuickStart Script for this plugin. This provides you auto installation and -configuration of Nova, Neutron and Trema. -https://github.com/nec-openstack/quantum-openflow-plugin/tree/folsom +* Repository: + * http://git.openstack.org/cgit/stackforge/networking-nec/ + * https://github.com/stackforge/networking-nec diff --git a/neutron/plugins/nec/agent/nec_neutron_agent.py b/neutron/plugins/nec/agent/nec_neutron_agent.py deleted file mode 100755 index 23b7d543f..000000000 --- a/neutron/plugins/nec/agent/nec_neutron_agent.py +++ /dev/null @@ -1,232 +0,0 @@ -#!/usr/bin/env python -# Copyright 2012 NEC Corporation. -# Based on ryu/openvswitch agents. -# -# Copyright 2012 Isaku Yamahata -# Copyright 2011 VMware, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import socket -import sys -import time - -import eventlet -eventlet.monkey_patch() - -import oslo_messaging - -from neutron.agent.linux import ovs_lib -from neutron.agent import rpc as agent_rpc -from neutron.agent import securitygroups_rpc as sg_rpc -from neutron.common import config as common_config -from neutron.common import constants as q_const -from neutron.common import topics -from neutron import context as q_context -from neutron.extensions import securitygroup as ext_sg -from neutron.i18n import _LE, _LI -from neutron.openstack.common import log as logging -from neutron.openstack.common import loopingcall -from neutron.plugins.nec.common import config - - -LOG = logging.getLogger(__name__) - - -class NECPluginApi(agent_rpc.PluginApi): - - def update_ports(self, context, agent_id, datapath_id, - port_added, port_removed): - """RPC to update information of ports on Neutron Server.""" - LOG.info(_LI("Update ports: added=%(added)s, " - "removed=%(removed)s"), - {'added': port_added, 'removed': port_removed}) - cctxt = self.client.prepare() - return cctxt.call(context, 'update_ports', - agent_id=agent_id, - datapath_id=datapath_id, - port_added=port_added, - port_removed=port_removed) - - -class NECAgentRpcCallback(object): - - target = oslo_messaging.Target(version='1.0') - - def __init__(self, context, agent, sg_agent): - super(NECAgentRpcCallback, self).__init__() - self.context = context - self.agent = agent - self.sg_agent = sg_agent - - def port_update(self, context, **kwargs): - LOG.debug("port_update received: %s", kwargs) - port = kwargs.get('port') - # Validate that port is on OVS - vif_port = self.agent.int_br.get_vif_port_by_id(port['id']) - if not vif_port: - return - - if ext_sg.SECURITYGROUPS in port: - self.sg_agent.refresh_firewall() - - -class SecurityGroupAgentRpcCallback(sg_rpc.SecurityGroupAgentRpcCallbackMixin): - - target = oslo_messaging.Target(version=sg_rpc.SG_RPC_VERSION) - - def __init__(self, context, sg_agent): - super(SecurityGroupAgentRpcCallback, self).__init__() - self.context = context - self.sg_agent = sg_agent - - -class NECNeutronAgent(object): - - def __init__(self, integ_br, polling_interval): - '''Constructor. - - :param integ_br: name of the integration bridge. - :param polling_interval: interval (secs) to check the bridge. - ''' - self.int_br = ovs_lib.OVSBridge(integ_br) - self.polling_interval = polling_interval - self.cur_ports = [] - self.need_sync = True - - self.datapath_id = "0x%s" % self.int_br.get_datapath_id() - - self.agent_state = { - 'binary': 'neutron-nec-agent', - 'host': config.CONF.host, - 'topic': q_const.L2_AGENT_TOPIC, - 'configurations': {}, - 'agent_type': q_const.AGENT_TYPE_NEC, - 'start_flag': True} - - self.setup_rpc() - - def setup_rpc(self): - self.host = socket.gethostname() - self.agent_id = 'nec-q-agent.%s' % self.host - LOG.info(_LI("RPC agent_id: %s"), self.agent_id) - - self.topic = topics.AGENT - self.context = q_context.get_admin_context_without_session() - - self.plugin_rpc = NECPluginApi(topics.PLUGIN) - self.state_rpc = agent_rpc.PluginReportStateAPI(topics.PLUGIN) - self.sg_plugin_rpc = sg_rpc.SecurityGroupServerRpcApi(topics.PLUGIN) - self.sg_agent = sg_rpc.SecurityGroupAgentRpc(self.context, - self.sg_plugin_rpc) - - # RPC network init - # Handle updates from service - self.callback_nec = NECAgentRpcCallback(self.context, - self, self.sg_agent) - self.callback_sg = SecurityGroupAgentRpcCallback(self.context, - self.sg_agent) - self.endpoints = [self.callback_nec, self.callback_sg] - # Define the listening consumer for the agent - consumers = [[topics.PORT, topics.UPDATE], - [topics.SECURITY_GROUP, topics.UPDATE]] - self.connection = agent_rpc.create_consumers(self.endpoints, - self.topic, - consumers) - - report_interval = config.CONF.AGENT.report_interval - if report_interval: - heartbeat = loopingcall.FixedIntervalLoopingCall( - self._report_state) - heartbeat.start(interval=report_interval) - - def _report_state(self): - try: - # How many devices are likely used by a VM - num_devices = len(self.cur_ports) - self.agent_state['configurations']['devices'] = num_devices - self.state_rpc.report_state(self.context, - self.agent_state) - self.agent_state.pop('start_flag', None) - except Exception: - LOG.exception(_LE("Failed reporting state!")) - - def _vif_port_to_port_info(self, vif_port): - return dict(id=vif_port.vif_id, port_no=vif_port.ofport, - mac=vif_port.vif_mac) - - def _process_security_group(self, port_added, port_removed): - if port_added: - devices_added = [p['id'] for p in port_added] - self.sg_agent.prepare_devices_filter(devices_added) - if port_removed: - self.sg_agent.remove_devices_filter(port_removed) - - def loop_handler(self): - try: - # self.cur_ports will be kept until loop_handler succeeds. - cur_ports = [] if self.need_sync else self.cur_ports - new_ports = [] - - port_added = [] - for vif_port in self.int_br.get_vif_ports(): - port_id = vif_port.vif_id - new_ports.append(port_id) - if port_id not in cur_ports: - port_info = self._vif_port_to_port_info(vif_port) - port_added.append(port_info) - - port_removed = [] - for port_id in cur_ports: - if port_id not in new_ports: - port_removed.append(port_id) - - if port_added or port_removed: - self.plugin_rpc.update_ports(self.context, - self.agent_id, self.datapath_id, - port_added, port_removed) - self._process_security_group(port_added, port_removed) - else: - LOG.debug("No port changed.") - - self.cur_ports = new_ports - self.need_sync = False - except Exception: - LOG.exception(_LE("Error in agent event loop")) - self.need_sync = True - - def daemon_loop(self): - """Main processing loop for NEC Plugin Agent.""" - while True: - self.loop_handler() - time.sleep(self.polling_interval) - - -def main(): - common_config.init(sys.argv[1:]) - - common_config.setup_logging() - - # Determine which agent type to use. - integ_br = config.OVS.integration_bridge - polling_interval = config.AGENT.polling_interval - - agent = NECNeutronAgent(integ_br, polling_interval) - - # Start everything. - agent.daemon_loop() - - -if __name__ == "__main__": - main() diff --git a/neutron/plugins/nec/common/__init__.py b/neutron/plugins/nec/common/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron/plugins/nec/common/constants.py b/neutron/plugins/nec/common/constants.py deleted file mode 100644 index cb7d43a36..000000000 --- a/neutron/plugins/nec/common/constants.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2013 NEC Corporation. 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. - -ROUTER_PROVIDER_L3AGENT = 'l3-agent' -ROUTER_PROVIDER_OPENFLOW = 'openflow' - -DEFAULT_ROUTER_PROVIDERS = [ROUTER_PROVIDER_L3AGENT, ROUTER_PROVIDER_OPENFLOW] -DEFAULT_ROUTER_PROVIDER = ROUTER_PROVIDER_L3AGENT - -ROUTER_STATUS_ACTIVE = 'ACTIVE' -ROUTER_STATUS_ERROR = 'ERROR' diff --git a/neutron/plugins/nec/common/exceptions.py b/neutron/plugins/nec/common/exceptions.py deleted file mode 100644 index 3fd5d7494..000000000 --- a/neutron/plugins/nec/common/exceptions.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2012 NEC Corporation. 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 exceptions as qexc - - -class OFCException(qexc.NeutronException): - message = _("An OFC exception has occurred: %(reason)s") - - def __init__(self, **kwargs): - super(OFCException, self).__init__(**kwargs) - self.status = kwargs.get('status') - self.err_msg = kwargs.get('err_msg') - self.err_code = kwargs.get('err_code') - - -class OFCResourceNotFound(qexc.NotFound): - message = _("The specified OFC resource (%(resource)s) is not found.") - - -class NECDBException(qexc.NeutronException): - message = _("An exception occurred in NECPluginV2 DB: %(reason)s") - - -class OFCMappingNotFound(qexc.NotFound): - message = _("Neutron-OFC resource mapping for " - "%(resource)s %(neutron_id)s is not found. " - "It may be deleted during processing.") - - -class OFCServiceUnavailable(OFCException): - message = _("OFC returns Server Unavailable (503) " - "(Retry-After=%(retry_after)s)") - - def __init__(self, **kwargs): - super(OFCServiceUnavailable, self).__init__(**kwargs) - self.retry_after = kwargs.get('retry_after') - - -class PortInfoNotFound(qexc.NotFound): - message = _("PortInfo %(id)s could not be found") - - -class ProfilePortInfoInvalidDataPathId(qexc.InvalidInput): - message = _('Invalid input for operation: ' - 'datapath_id should be a hex string ' - 'with at most 8 bytes') - - -class ProfilePortInfoInvalidPortNo(qexc.InvalidInput): - message = _('Invalid input for operation: ' - 'port_no should be [0:65535]') - - -class RouterExternalGatewayNotSupported(qexc.BadRequest): - message = _("Router (provider=%(provider)s) does not support " - "an external network") - - -class ProviderNotFound(qexc.NotFound): - message = _("Provider %(provider)s could not be found") - - -class RouterOverLimit(qexc.Conflict): - message = _("Cannot create more routers with provider=%(provider)s") - - -class RouterProviderMismatch(qexc.Conflict): - message = _("Provider of Router %(router_id)s is %(provider)s. " - "This operation is supported only for router provider " - "%(expected_provider)s.") diff --git a/neutron/plugins/nec/common/ofc_client.py b/neutron/plugins/nec/common/ofc_client.py deleted file mode 100644 index a738019f7..000000000 --- a/neutron/plugins/nec/common/ofc_client.py +++ /dev/null @@ -1,156 +0,0 @@ -# Copyright 2012 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time - -from oslo_serialization import jsonutils -from oslo_utils import excutils -import requests - -from neutron.i18n import _LI, _LW -from neutron.openstack.common import log as logging -from neutron.plugins.nec.common import config -from neutron.plugins.nec.common import exceptions as nexc - - -LOG = logging.getLogger(__name__) - - -class OFCClient(object): - """A HTTP/HTTPS client for OFC Drivers.""" - - def __init__(self, host="127.0.0.1", port=8888, use_ssl=False, - key_file=None, cert_file=None, insecure_ssl=False): - """Creates a new client to some OFC. - - :param host: The host where service resides - :param port: The port where service resides - :param use_ssl: True to use SSL, False to use HTTP - :param key_file: The SSL key file to use if use_ssl is true - :param cert_file: The SSL cert file to use if use_ssl is true - :param insecure_ssl: Don't verify SSL certificate - """ - self.host = host - self.port = port - self.use_ssl = use_ssl - self.key_file = key_file - self.cert_file = cert_file - self.insecure_ssl = insecure_ssl - self.connection = None - - def _format_error_message(self, status, detail): - detail = ' ' + detail if detail else '' - return (_("Operation on OFC failed: %(status)s%(msg)s") % - {'status': status, 'msg': detail}) - - def _get_response(self, method, action, body=None): - headers = {"Content-Type": "application/json"} - protocol = "http" - certs = {'key_file': self.key_file, 'cert_file': self.cert_file} - certs = dict((x, certs[x]) for x in certs if certs[x] is not None) - verify = True - - if self.use_ssl: - protocol = "https" - if self.insecure_ssl: - verify = False - - url = "%s://%s:%d%s" % (protocol, self.host, int(self.port), - action) - - res = requests.request(method, url, data=body, headers=headers, - cert=certs, verify=verify) - return res - - def do_single_request(self, method, action, body=None): - action = config.OFC.path_prefix + action - LOG.debug("Client request: %(host)s:%(port)s " - "%(method)s %(action)s [%(body)s]", - {'host': self.host, 'port': self.port, - 'method': method, 'action': action, 'body': body}) - if type(body) is dict: - body = jsonutils.dumps(body) - try: - res = self._get_response(method, action, body) - data = res.text - LOG.debug("OFC returns [%(status)s:%(data)s]", - {'status': res.status_code, - 'data': data}) - - # Try to decode JSON data if possible. - try: - data = jsonutils.loads(data) - except (ValueError, TypeError): - pass - - if res.status_code in (requests.codes.OK, - requests.codes.CREATED, - requests.codes.ACCEPTED, - requests.codes.NO_CONTENT): - return data - elif res.status_code == requests.codes.SERVICE_UNAVAILABLE: - retry_after = res.headers.get('retry-after') - LOG.warning(_LW("OFC returns ServiceUnavailable " - "(retry-after=%s)"), retry_after) - raise nexc.OFCServiceUnavailable(retry_after=retry_after) - elif res.status_code == requests.codes.NOT_FOUND: - LOG.info(_LI("Specified resource %s does not exist on OFC "), - action) - raise nexc.OFCResourceNotFound(resource=action) - else: - LOG.warning(_LW("Operation on OFC failed: " - "status=%(status)s, detail=%(detail)s"), - {'status': res.status_code, 'detail': data}) - params = {'reason': _("Operation on OFC failed"), - 'status': res.status_code} - if isinstance(data, dict): - params['err_code'] = data.get('err_code') - params['err_msg'] = data.get('err_msg') - else: - params['err_msg'] = data - raise nexc.OFCException(**params) - except requests.exceptions.RequestException as e: - reason = _("Failed to connect OFC : %s") % e - LOG.error(reason) - raise nexc.OFCException(reason=reason) - - def do_request(self, method, action, body=None): - max_attempts = config.OFC.api_max_attempts - for i in range(max_attempts, 0, -1): - try: - return self.do_single_request(method, action, body) - except nexc.OFCServiceUnavailable as e: - with excutils.save_and_reraise_exception() as ctxt: - try: - wait_time = int(e.retry_after) - except (ValueError, TypeError): - wait_time = None - if i > 1 and wait_time: - LOG.info(_LI("Waiting for %s seconds due to " - "OFC Service_Unavailable."), wait_time) - time.sleep(wait_time) - ctxt.reraise = False - continue - - def get(self, action): - return self.do_request("GET", action) - - def post(self, action, body=None): - return self.do_request("POST", action, body=body) - - def put(self, action, body=None): - return self.do_request("PUT", action, body=body) - - def delete(self, action): - return self.do_request("DELETE", action) diff --git a/neutron/plugins/nec/common/config.py b/neutron/plugins/nec/config.py similarity index 83% rename from neutron/plugins/nec/common/config.py rename to neutron/plugins/nec/config.py index 429dc3783..be1021a1f 100644 --- a/neutron/plugins/nec/common/config.py +++ b/neutron/plugins/nec/config.py @@ -15,7 +15,6 @@ from oslo_config import cfg from neutron.agent.common import config -from neutron.plugins.nec.common import constants as nconst ovs_opts = [ @@ -60,23 +59,20 @@ ofc_opts = [ provider_opts = [ cfg.StrOpt('default_router_provider', - default=nconst.DEFAULT_ROUTER_PROVIDER, + default='l3-agent', help=_('Default router provider to use.')), cfg.ListOpt('router_providers', - default=nconst.DEFAULT_ROUTER_PROVIDERS, + default=['l3-agent', 'openflow'], help=_('List of enabled router providers.')) ] -cfg.CONF.register_opts(ovs_opts, "OVS") -cfg.CONF.register_opts(agent_opts, "AGENT") -cfg.CONF.register_opts(ofc_opts, "OFC") -cfg.CONF.register_opts(provider_opts, "PROVIDER") -config.register_agent_state_opts_helper(cfg.CONF) +def register_plugin_opts(): + cfg.CONF.register_opts(ofc_opts, "OFC") + cfg.CONF.register_opts(provider_opts, "PROVIDER") -# shortcuts -CONF = cfg.CONF -OVS = cfg.CONF.OVS -AGENT = cfg.CONF.AGENT -OFC = cfg.CONF.OFC -PROVIDER = cfg.CONF.PROVIDER + +def register_agent_opts(): + cfg.CONF.register_opts(agent_opts, "AGENT") + cfg.CONF.register_opts(ovs_opts, "OVS") + config.register_agent_state_opts_helper(cfg.CONF) diff --git a/neutron/plugins/nec/db/api.py b/neutron/plugins/nec/db/api.py deleted file mode 100644 index 37ab776c2..000000000 --- a/neutron/plugins/nec/db/api.py +++ /dev/null @@ -1,179 +0,0 @@ -# Copyright 2012 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sqlalchemy as sa - -from neutron.db import api as db -from neutron.db import models_v2 -from neutron.db import securitygroups_db as sg_db -from neutron.extensions import securitygroup as ext_sg -from neutron.i18n import _LW -from neutron import manager -from neutron.openstack.common import log as logging -from neutron.plugins.nec.common import config # noqa -from neutron.plugins.nec.common import exceptions as nexc -from neutron.plugins.nec.db import models as nmodels - - -LOG = logging.getLogger(__name__) -OFP_VLAN_NONE = 0xffff - - -resource_map = {'ofc_tenant': nmodels.OFCTenantMapping, - 'ofc_network': nmodels.OFCNetworkMapping, - 'ofc_port': nmodels.OFCPortMapping, - 'ofc_router': nmodels.OFCRouterMapping, - 'ofc_packet_filter': nmodels.OFCFilterMapping} - - -# utitlity methods - -def _get_resource_model(resource): - return resource_map[resource] - - -def get_ofc_item(session, resource, neutron_id): - model = _get_resource_model(resource) - if not model: - return - try: - return session.query(model).filter_by(neutron_id=neutron_id).one() - except sa.orm.exc.NoResultFound: - return - - -def get_ofc_id(session, resource, neutron_id): - ofc_item = get_ofc_item(session, resource, neutron_id) - if ofc_item: - return ofc_item.ofc_id - else: - raise nexc.OFCMappingNotFound(resource=resource, - neutron_id=neutron_id) - - -def exists_ofc_item(session, resource, neutron_id): - if get_ofc_item(session, resource, neutron_id): - return True - else: - return False - - -def find_ofc_item(session, resource, ofc_id): - try: - model = _get_resource_model(resource) - params = dict(ofc_id=ofc_id) - return (session.query(model).filter_by(**params).one()) - except sa.orm.exc.NoResultFound: - return None - - -def add_ofc_item(session, resource, neutron_id, ofc_id): - try: - model = _get_resource_model(resource) - params = dict(neutron_id=neutron_id, ofc_id=ofc_id) - item = model(**params) - with session.begin(subtransactions=True): - session.add(item) - session.flush() - except Exception as exc: - LOG.exception(exc) - raise nexc.NECDBException(reason=exc.message) - return item - - -def del_ofc_item(session, resource, neutron_id): - try: - model = _get_resource_model(resource) - with session.begin(subtransactions=True): - item = session.query(model).filter_by(neutron_id=neutron_id).one() - session.delete(item) - return True - except sa.orm.exc.NoResultFound: - LOG.warning(_LW("del_ofc_item(): NotFound item " - "(resource=%(resource)s, id=%(id)s) "), - {'resource': resource, 'id': neutron_id}) - return False - - -def get_portinfo(session, id): - try: - return (session.query(nmodels.PortInfo). - filter_by(id=id). - one()) - except sa.orm.exc.NoResultFound: - return None - - -def add_portinfo(session, id, datapath_id='', port_no=0, - vlan_id=OFP_VLAN_NONE, mac=''): - try: - portinfo = nmodels.PortInfo(id=id, datapath_id=datapath_id, - port_no=port_no, vlan_id=vlan_id, mac=mac) - with session.begin(subtransactions=True): - session.add(portinfo) - except Exception as exc: - LOG.exception(exc) - raise nexc.NECDBException(reason=exc.message) - return portinfo - - -def del_portinfo(session, id): - try: - with session.begin(subtransactions=True): - portinfo = session.query(nmodels.PortInfo).filter_by(id=id).one() - session.delete(portinfo) - except sa.orm.exc.NoResultFound: - LOG.warning(_LW("del_portinfo(): NotFound portinfo for " - "port_id: %s"), id) - - -def get_active_ports_on_ofc(context, network_id, port_id=None): - """Retrieve ports on OFC on a given network. - - It returns a list of tuple (neutron port_id, OFC id). - """ - query = context.session.query(nmodels.OFCPortMapping) - query = query.join(models_v2.Port, - nmodels.OFCPortMapping.neutron_id == models_v2.Port.id) - query = query.filter(models_v2.Port.network_id == network_id) - if port_id: - query = query.filter(nmodels.OFCPortMapping.neutron_id == port_id) - - return [(p['neutron_id'], p['ofc_id']) for p in query] - - -def get_port_from_device(port_id): - """Get port from database.""" - LOG.debug("get_port_with_securitygroups() called:port_id=%s", port_id) - session = db.get_session() - sg_binding_port = sg_db.SecurityGroupPortBinding.port_id - - query = session.query(models_v2.Port, - sg_db.SecurityGroupPortBinding.security_group_id) - query = query.outerjoin(sg_db.SecurityGroupPortBinding, - models_v2.Port.id == sg_binding_port) - query = query.filter(models_v2.Port.id == port_id) - port_and_sgs = query.all() - if not port_and_sgs: - return None - port = port_and_sgs[0][0] - plugin = manager.NeutronManager.get_plugin() - port_dict = plugin._make_port_dict(port) - port_dict[ext_sg.SECURITYGROUPS] = [ - sg_id for port_, sg_id in port_and_sgs if sg_id] - port_dict['security_group_rules'] = [] - port_dict['security_group_source_groups'] = [] - port_dict['fixed_ips'] = [ip['ip_address'] - for ip in port['fixed_ips']] - return port_dict diff --git a/neutron/plugins/nec/db/packetfilter.py b/neutron/plugins/nec/db/packetfilter.py deleted file mode 100644 index 45aea5f4f..000000000 --- a/neutron/plugins/nec/db/packetfilter.py +++ /dev/null @@ -1,181 +0,0 @@ -# Copyright 2012-2013 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from sqlalchemy.orm import exc as sa_exc -from sqlalchemy import sql - -from neutron.api.v2 import attributes -from neutron.openstack.common import uuidutils -from neutron.plugins.nec.db import models as nmodels -from neutron.plugins.nec.extensions import packetfilter as ext_pf - - -PF_STATUS_ACTIVE = 'ACTIVE' -PF_STATUS_DOWN = 'DOWN' -PF_STATUS_ERROR = 'ERROR' - -INT_FIELDS = ('eth_type', 'src_port', 'dst_port') - - -class PacketFilterDbMixin(object): - - def _make_packet_filter_dict(self, pf_entry, fields=None): - res = {'id': pf_entry['id'], - 'name': pf_entry['name'], - 'tenant_id': pf_entry['tenant_id'], - 'network_id': pf_entry['network_id'], - 'action': pf_entry['action'], - 'priority': pf_entry['priority'], - 'in_port': pf_entry['in_port'], - # "or None" ensure the filed is None if empty - 'src_mac': pf_entry['src_mac'] or None, - 'dst_mac': pf_entry['dst_mac'] or None, - 'eth_type': pf_entry['eth_type'] or None, - 'src_cidr': pf_entry['src_cidr'] or None, - 'dst_cidr': pf_entry['dst_cidr'] or None, - 'protocol': pf_entry['protocol'] or None, - 'src_port': pf_entry['src_port'] or None, - 'dst_port': pf_entry['dst_port'] or None, - 'admin_state_up': pf_entry['admin_state_up'], - 'status': pf_entry['status']} - return self._fields(res, fields) - - def _get_packet_filter(self, context, id): - try: - pf_entry = self._get_by_id(context, nmodels.PacketFilter, id) - except sa_exc.NoResultFound: - raise ext_pf.PacketFilterNotFound(id=id) - return pf_entry - - def get_packet_filter(self, context, id, fields=None): - pf_entry = self._get_packet_filter(context, id) - return self._make_packet_filter_dict(pf_entry, fields) - - def get_packet_filters(self, context, filters=None, fields=None): - return self._get_collection(context, - nmodels.PacketFilter, - self._make_packet_filter_dict, - filters=filters, - fields=fields) - - def _replace_unspecified_field(self, params, key): - if not attributes.is_attr_set(params[key]): - if key == 'in_port': - params[key] = None - elif key in INT_FIELDS: - # Integer field - params[key] = 0 - else: - params[key] = '' - - def _get_eth_type_for_protocol(self, protocol): - if protocol.upper() in ("ICMP", "TCP", "UDP"): - return 0x800 - elif protocol.upper() == "ARP": - return 0x806 - - def _set_eth_type_from_protocol(self, filter_dict): - if filter_dict.get('protocol'): - eth_type = self._get_eth_type_for_protocol(filter_dict['protocol']) - if eth_type: - filter_dict['eth_type'] = eth_type - - def _check_eth_type_and_protocol(self, new_filter, current_filter): - if 'protocol' in new_filter or 'eth_type' not in new_filter: - return - eth_type = self._get_eth_type_for_protocol(current_filter['protocol']) - if not eth_type: - return - if eth_type != new_filter['eth_type']: - raise ext_pf.PacketFilterEtherTypeProtocolMismatch( - eth_type=hex(new_filter['eth_type']), - protocol=current_filter['protocol']) - - def create_packet_filter(self, context, packet_filter): - pf_dict = packet_filter['packet_filter'] - tenant_id = self._get_tenant_id_for_create(context, pf_dict) - - if pf_dict['in_port'] == attributes.ATTR_NOT_SPECIFIED: - # validate network ownership - self.get_network(context, pf_dict['network_id']) - else: - # validate port ownership - self.get_port(context, pf_dict['in_port']) - - params = {'tenant_id': tenant_id, - 'id': pf_dict.get('id') or uuidutils.generate_uuid(), - 'name': pf_dict['name'], - 'network_id': pf_dict['network_id'], - 'priority': pf_dict['priority'], - 'action': pf_dict['action'], - 'admin_state_up': pf_dict.get('admin_state_up', True), - 'status': PF_STATUS_DOWN, - 'in_port': pf_dict['in_port'], - 'src_mac': pf_dict['src_mac'], - 'dst_mac': pf_dict['dst_mac'], - 'eth_type': pf_dict['eth_type'], - 'src_cidr': pf_dict['src_cidr'], - 'dst_cidr': pf_dict['dst_cidr'], - 'src_port': pf_dict['src_port'], - 'dst_port': pf_dict['dst_port'], - 'protocol': pf_dict['protocol']} - for key in params: - self._replace_unspecified_field(params, key) - self._set_eth_type_from_protocol(params) - - with context.session.begin(subtransactions=True): - pf_entry = nmodels.PacketFilter(**params) - context.session.add(pf_entry) - - return self._make_packet_filter_dict(pf_entry) - - def update_packet_filter(self, context, id, packet_filter): - params = packet_filter['packet_filter'] - for key in params: - self._replace_unspecified_field(params, key) - self._set_eth_type_from_protocol(params) - with context.session.begin(subtransactions=True): - pf_entry = self._get_packet_filter(context, id) - self._check_eth_type_and_protocol(params, pf_entry) - pf_entry.update(params) - return self._make_packet_filter_dict(pf_entry) - - def delete_packet_filter(self, context, id): - with context.session.begin(subtransactions=True): - pf_entry = self._get_packet_filter(context, id) - context.session.delete(pf_entry) - - def get_packet_filters_for_port(self, context, port): - """Retrieve packet filters on OFC on a given port. - - It returns a list of tuple (neutron filter_id, OFC id). - """ - query = (context.session.query(nmodels.OFCFilterMapping) - .join(nmodels.PacketFilter, - nmodels.OFCFilterMapping.neutron_id - == nmodels.PacketFilter.id) - .filter(nmodels.PacketFilter.admin_state_up == sql.true())) - - network_id = port['network_id'] - net_pf_query = (query.filter(nmodels.PacketFilter.network_id - == network_id) - .filter(nmodels.PacketFilter.in_port == sql.null())) - net_filters = [(pf['neutron_id'], pf['ofc_id']) for pf in net_pf_query] - - port_pf_query = query.filter(nmodels.PacketFilter.in_port - == port['id']) - port_filters = [(pf['neutron_id'], pf['ofc_id']) - for pf in port_pf_query] - - return net_filters + port_filters diff --git a/neutron/plugins/nec/db/router.py b/neutron/plugins/nec/db/router.py deleted file mode 100644 index d6d42f24c..000000000 --- a/neutron/plugins/nec/db/router.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright 2013 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from sqlalchemy.orm import exc as sa_exc - -from neutron.db import l3_db -from neutron.openstack.common import log as logging -from neutron.plugins.nec.db import models as nmodels - -LOG = logging.getLogger(__name__) - - -def _get_router_providers_query(query, provider=None, router_ids=None): - if provider: - query = query.filter_by(provider=provider) - if router_ids: - column = nmodels.RouterProvider.router_id - query = query.filter(column.in_(router_ids)) - return query - - -def get_router_providers(session, provider=None, router_ids=None): - """Retrieve a list of a pair of router ID and its provider.""" - query = session.query(nmodels.RouterProvider) - query = _get_router_providers_query(query, provider, router_ids) - return [{'provider': router.provider, 'router_id': router.router_id} - for router in query] - - -def get_routers_by_provider(session, provider, router_ids=None): - """Retrieve a list of router IDs with the given provider.""" - query = session.query(nmodels.RouterProvider.router_id) - query = _get_router_providers_query(query, provider, router_ids) - return [router[0] for router in query] - - -def get_router_count_by_provider(session, provider, tenant_id=None): - """Return the number of routers with the given provider.""" - query = session.query(nmodels.RouterProvider).filter_by(provider=provider) - if tenant_id: - query = (query.join('router'). - filter(l3_db.Router.tenant_id == tenant_id)) - return query.count() - - -def get_provider_by_router(session, router_id): - """Retrieve a provider of the given router.""" - try: - binding = (session.query(nmodels.RouterProvider). - filter_by(router_id=router_id). - one()) - except sa_exc.NoResultFound: - return None - return binding.provider - - -def add_router_provider_binding(session, provider, router_id): - """Add a router provider association.""" - LOG.debug("Add provider binding " - "(router=%(router_id)s, provider=%(provider)s)", - {'router_id': router_id, 'provider': provider}) - binding = nmodels.RouterProvider(provider=provider, router_id=router_id) - session.add(binding) - return binding diff --git a/neutron/plugins/nec/drivers/__init__.py b/neutron/plugins/nec/drivers/__init__.py deleted file mode 100644 index 7ed4b9b7a..000000000 --- a/neutron/plugins/nec/drivers/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2012 NEC Corporation. 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 oslo_utils import importutils - -from neutron.i18n import _LI -from neutron.openstack.common import log as logging - - -LOG = logging.getLogger(__name__) -DRIVER_PATH = "neutron.plugins.nec.drivers.%s" -DRIVER_LIST = { - 'trema': DRIVER_PATH % "trema.TremaPortBaseDriver", - 'trema_port': DRIVER_PATH % "trema.TremaPortBaseDriver", - 'trema_portmac': DRIVER_PATH % "trema.TremaPortMACBaseDriver", - 'trema_mac': DRIVER_PATH % "trema.TremaMACBaseDriver", - 'pfc': DRIVER_PATH % "pfc.PFCV51Driver", - 'pfc_v3': DRIVER_PATH % "pfc.PFCV3Driver", - 'pfc_v4': DRIVER_PATH % "pfc.PFCV4Driver", - 'pfc_v5': DRIVER_PATH % "pfc.PFCV5Driver", - 'pfc_v51': DRIVER_PATH % "pfc.PFCV51Driver", -} - - -def get_driver(driver_name): - LOG.info(_LI("Loading OFC driver: %s"), driver_name) - driver_klass = DRIVER_LIST.get(driver_name) or driver_name - return importutils.import_class(driver_klass) diff --git a/neutron/plugins/nec/drivers/pfc.py b/neutron/plugins/nec/drivers/pfc.py deleted file mode 100644 index 12f15fb0d..000000000 --- a/neutron/plugins/nec/drivers/pfc.py +++ /dev/null @@ -1,399 +0,0 @@ -# Copyright 2012 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re -import uuid - -import netaddr - -from neutron.api.v2 import attributes -from neutron.common import constants -from neutron.common import exceptions as qexc -from neutron.common import log as call_log -from neutron import manager -from neutron.plugins.nec.common import config -from neutron.plugins.nec.common import ofc_client -from neutron.plugins.nec.db import api as ndb -from neutron.plugins.nec.extensions import packetfilter as ext_pf -from neutron.plugins.nec import ofc_driver_base - - -class InvalidOFCIdFormat(qexc.NeutronException): - message = _("OFC %(resource)s ID has an invalid format: %(ofc_id)s") - - -class PFCDriverBase(ofc_driver_base.OFCDriverBase): - """Base Class for PDC Drivers. - - PFCDriverBase provides methods to handle PFC resources through REST API. - This uses ofc resource path instead of ofc resource ID. - - The class implements the API for PFC V4.0 or later. - """ - - router_supported = False - - match_ofc_network_id = re.compile( - "^/tenants/(?P[^/]+)/networks/(?P[^/]+)$") - match_ofc_port_id = re.compile( - "^/tenants/(?P[^/]+)/networks/(?P[^/]+)" - "/ports/(?P[^/]+)$") - - def __init__(self, conf_ofc): - self.client = ofc_client.OFCClient(host=conf_ofc.host, - port=conf_ofc.port, - use_ssl=conf_ofc.use_ssl, - key_file=conf_ofc.key_file, - cert_file=conf_ofc.cert_file, - insecure_ssl=conf_ofc.insecure_ssl) - - @classmethod - def filter_supported(cls): - return False - - def _generate_pfc_str(self, raw_str): - """Generate PFC acceptable String.""" - return re.sub(r'[^0-9a-zA-Z]', '_', raw_str) - - def _generate_pfc_id(self, id_str): - """Generate ID on PFC. - - Currently, PFC ID must be less than 32. - Shorten UUID string length from 36 to 31 by follows: - * delete UUID Version and hyphen (see RFC4122) - * ensure str length - """ - try: - # openstack.common.uuidutils.is_uuid_like() returns - # False for KeyStone tenant_id, so uuid.UUID is used - # directly here to accept tenant_id as UUID string - uuid_str = str(uuid.UUID(id_str)).replace('-', '') - uuid_no_version = uuid_str[:12] + uuid_str[13:] - return uuid_no_version[:31] - except Exception: - return self._generate_pfc_str(id_str)[:31] - - def _generate_pfc_description(self, desc): - """Generate Description on PFC. - - Currently, PFC Description must be less than 128. - """ - return self._generate_pfc_str(desc)[:127] - - def _extract_ofc_network_id(self, ofc_network_id): - match = self.match_ofc_network_id.match(ofc_network_id) - if match: - return match.group('network_id') - raise InvalidOFCIdFormat(resource='network', ofc_id=ofc_network_id) - - def _extract_ofc_port_id(self, ofc_port_id): - match = self.match_ofc_port_id.match(ofc_port_id) - if match: - return {'tenant': match.group('tenant_id'), - 'network': match.group('network_id'), - 'port': match.group('port_id')} - raise InvalidOFCIdFormat(resource='port', ofc_id=ofc_port_id) - - def create_tenant(self, description, tenant_id=None): - ofc_tenant_id = self._generate_pfc_id(tenant_id) - body = {'id': ofc_tenant_id} - self.client.post('/tenants', body=body) - return '/tenants/' + ofc_tenant_id - - def delete_tenant(self, ofc_tenant_id): - return self.client.delete(ofc_tenant_id) - - def create_network(self, ofc_tenant_id, description, network_id=None): - path = "%s/networks" % ofc_tenant_id - pfc_desc = self._generate_pfc_description(description) - body = {'description': pfc_desc} - res = self.client.post(path, body=body) - ofc_network_id = res['id'] - return path + '/' + ofc_network_id - - def delete_network(self, ofc_network_id): - return self.client.delete(ofc_network_id) - - def create_port(self, ofc_network_id, portinfo, - port_id=None, filters=None): - path = "%s/ports" % ofc_network_id - body = {'datapath_id': portinfo.datapath_id, - 'port': str(portinfo.port_no), - 'vid': str(portinfo.vlan_id)} - if self.filter_supported() and filters: - body['filters'] = [self._extract_ofc_filter_id(pf[1]) - for pf in filters] - res = self.client.post(path, body=body) - ofc_port_id = res['id'] - return path + '/' + ofc_port_id - - def delete_port(self, ofc_port_id): - return self.client.delete(ofc_port_id) - - -class PFCFilterDriverMixin(object): - """PFC PacketFilter Driver Mixin.""" - filters_path = "/filters" - filter_path = "/filters/%s" - - # PFC specific constants - MIN_PRIORITY = 1 - MAX_PRIORITY = 32766 - CREATE_ONLY_FIELDS = ['action', 'priority'] - PFC_ALLOW_ACTION = "pass" - PFC_DROP_ACTION = "drop" - - match_ofc_filter_id = re.compile("^/filters/(?P[^/]+)$") - - @classmethod - def filter_supported(cls): - return True - - def _set_param(self, filter_dict, body, key, create, convert_to=None): - if key in filter_dict: - if filter_dict[key]: - if convert_to: - body[key] = convert_to(filter_dict[key]) - else: - body[key] = filter_dict[key] - elif not create: - body[key] = "" - - def _extract_ofc_filter_port_id(self, ofc_port_id): - """Return ofc port id description for packet filter. - - It returns either of the following format: - {'tenant': xxxx, 'network': xxxx, 'port': xxxx} or - {'tenant': xxxx, 'router': xxxx, 'interface': xxxx} - If no matching ofc id is found, InvalidOFCIdFormat is raised. - """ - if config.OFC.support_packet_filter_on_ofc_router: - try: - return self._extract_ofc_router_inf_id(ofc_port_id) - except InvalidOFCIdFormat: - pass - return self._extract_ofc_port_id(ofc_port_id) - - def _generate_body(self, filter_dict, apply_ports=None, create=True): - body = {} - - if create: - # action : pass, drop (mandatory) - if filter_dict['action'].lower() in ext_pf.ALLOW_ACTIONS: - body['action'] = self.PFC_ALLOW_ACTION - else: - body['action'] = self.PFC_DROP_ACTION - # priority : mandatory - body['priority'] = filter_dict['priority'] - - for key in ['src_mac', 'dst_mac', 'src_port', 'dst_port']: - self._set_param(filter_dict, body, key, create) - - for key in ['src_cidr', 'dst_cidr']: - # CIDR must contain netmask even if it is an address. - convert_to = lambda x: str(netaddr.IPNetwork(x)) - self._set_param(filter_dict, body, key, create, convert_to) - - # protocol : decimal (0-255) - if 'protocol' in filter_dict: - if (not filter_dict['protocol'] or - # In the case of ARP, ip_proto should be set to wildcard. - # eth_type is set during adding an entry to DB layer. - filter_dict['protocol'].lower() == ext_pf.PROTO_NAME_ARP): - if not create: - body['protocol'] = "" - elif filter_dict['protocol'].lower() == constants.PROTO_NAME_ICMP: - body['protocol'] = constants.PROTO_NUM_ICMP - elif filter_dict['protocol'].lower() == constants.PROTO_NAME_TCP: - body['protocol'] = constants.PROTO_NUM_TCP - elif filter_dict['protocol'].lower() == constants.PROTO_NAME_UDP: - body['protocol'] = constants.PROTO_NUM_UDP - else: - body['protocol'] = int(filter_dict['protocol'], 0) - - # eth_type : hex (0x0-0xFFFF) - self._set_param(filter_dict, body, 'eth_type', create, hex) - - # apply_ports - if apply_ports: - # each element of apply_ports is a tuple of (neutron_id, ofc_id), - body['apply_ports'] = [] - for p in apply_ports: - try: - _ofc_id = self._extract_ofc_filter_port_id(p[1]) - body['apply_ports'].append(_ofc_id) - except InvalidOFCIdFormat: - pass - - return body - - def _validate_filter_common(self, filter_dict): - # Currently PFC support only IPv4 CIDR. - for field in ['src_cidr', 'dst_cidr']: - if (not filter_dict.get(field) or - filter_dict[field] == attributes.ATTR_NOT_SPECIFIED): - continue - net = netaddr.IPNetwork(filter_dict[field]) - if net.version != 4: - raise ext_pf.PacketFilterIpVersionNonSupported( - version=net.version, field=field, value=filter_dict[field]) - if ('priority' in filter_dict and - not (self.MIN_PRIORITY <= filter_dict['priority'] - <= self.MAX_PRIORITY)): - raise ext_pf.PacketFilterInvalidPriority( - min=self.MIN_PRIORITY, max=self.MAX_PRIORITY) - - def _validate_duplicate_priority(self, context, filter_dict): - plugin = manager.NeutronManager.get_plugin() - filters = {'network_id': [filter_dict['network_id']], - 'priority': [filter_dict['priority']]} - ret = plugin.get_packet_filters(context, filters=filters, - fields=['id']) - if ret: - raise ext_pf.PacketFilterDuplicatedPriority( - priority=filter_dict['priority']) - - def validate_filter_create(self, context, filter_dict): - self._validate_filter_common(filter_dict) - self._validate_duplicate_priority(context, filter_dict) - - def validate_filter_update(self, context, filter_dict): - for field in self.CREATE_ONLY_FIELDS: - if field in filter_dict: - raise ext_pf.PacketFilterUpdateNotSupported(field=field) - self._validate_filter_common(filter_dict) - - @call_log.log - def create_filter(self, context, filter_dict, filter_id=None): - in_port_id = filter_dict.get('in_port') - apply_ports = ndb.get_active_ports_on_ofc( - context, filter_dict['network_id'], in_port_id) - - body = self._generate_body(filter_dict, apply_ports, create=True) - res = self.client.post(self.filters_path, body=body) - # filter_id passed from a caller is not used. - # ofc_filter_id is generated by PFC because the prefix of - # filter_id has special meaning and it is internally used. - ofc_filter_id = res['id'] - return self.filter_path % ofc_filter_id - - @call_log.log - def update_filter(self, ofc_filter_id, filter_dict): - body = self._generate_body(filter_dict, create=False) - self.client.put(ofc_filter_id, body) - - @call_log.log - def delete_filter(self, ofc_filter_id): - return self.client.delete(ofc_filter_id) - - def _extract_ofc_filter_id(self, ofc_filter_id): - match = self.match_ofc_filter_id.match(ofc_filter_id) - if match: - return match.group('filter_id') - raise InvalidOFCIdFormat(resource='filter', ofc_id=ofc_filter_id) - - -class PFCRouterDriverMixin(object): - - router_supported = True - router_nat_supported = False - - match_ofc_router_inf_id = re.compile( - "^/tenants/(?P[^/]+)/routers/(?P[^/]+)" - "/interfaces/(?P[^/]+)$") - - def _extract_ofc_router_inf_id(self, ofc_router_inf_id): - match = self.match_ofc_router_inf_id.match(ofc_router_inf_id) - if match: - return {'tenant': match.group('tenant_id'), - 'router': match.group('router_id'), - 'interface': match.group('router_inf_id')} - raise InvalidOFCIdFormat(resource='router-interface', - ofc_id=ofc_router_inf_id) - - def create_router(self, ofc_tenant_id, router_id, description): - path = '%s/routers' % ofc_tenant_id - res = self.client.post(path, body=None) - ofc_router_id = res['id'] - return path + '/' + ofc_router_id - - def delete_router(self, ofc_router_id): - return self.client.delete(ofc_router_id) - - def add_router_interface(self, ofc_router_id, ofc_net_id, - ip_address=None, mac_address=None): - # ip_address : / (e.g., 10.0.0.0/24) - path = '%s/interfaces' % ofc_router_id - body = {'net_id': self._extract_ofc_network_id(ofc_net_id)} - if ip_address: - body['ip_address'] = ip_address - if mac_address: - body['mac_address'] = mac_address - res = self.client.post(path, body=body) - return path + '/' + res['id'] - - def update_router_interface(self, ofc_router_inf_id, - ip_address=None, mac_address=None): - # ip_address : / (e.g., 10.0.0.0/24) - if not ip_address and not mac_address: - return - body = {} - if ip_address: - body['ip_address'] = ip_address - if mac_address: - body['mac_address'] = mac_address - return self.client.put(ofc_router_inf_id, body=body) - - def delete_router_interface(self, ofc_router_inf_id): - return self.client.delete(ofc_router_inf_id) - - def list_router_routes(self, ofc_router_id): - path = '%s/routes' % ofc_router_id - ret = self.client.get(path) - # Prepend ofc_router_id to route_id - for r in ret['routes']: - r['id'] = ofc_router_id + '/routes/' + r['id'] - return ret['routes'] - - def add_router_route(self, ofc_router_id, destination, nexthop): - path = '%s/routes' % ofc_router_id - body = {'destination': destination, - 'nexthop': nexthop} - ret = self.client.post(path, body=body) - return path + '/' + ret['id'] - - def delete_router_route(self, ofc_router_route_id): - return self.client.delete(ofc_router_route_id) - - -class PFCV3Driver(PFCDriverBase): - - def create_tenant(self, description, tenant_id): - ofc_tenant_id = self._generate_pfc_id(tenant_id) - return "/tenants/" + ofc_tenant_id - - def delete_tenant(self, ofc_tenant_id): - pass - - -class PFCV4Driver(PFCDriverBase): - pass - - -class PFCV5Driver(PFCRouterDriverMixin, PFCDriverBase): - pass - - -class PFCV51Driver(PFCFilterDriverMixin, PFCV5Driver): - pass diff --git a/neutron/plugins/nec/drivers/trema.py b/neutron/plugins/nec/drivers/trema.py deleted file mode 100644 index a13028d96..000000000 --- a/neutron/plugins/nec/drivers/trema.py +++ /dev/null @@ -1,259 +0,0 @@ -# Copyright 2012 NEC Corporation. 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.openstack.common import uuidutils -from neutron.plugins.nec.common import exceptions as nexc -from neutron.plugins.nec.common import ofc_client -from neutron.plugins.nec.db import api as ndb -from neutron.plugins.nec import ofc_driver_base - - -class TremaDriverBase(ofc_driver_base.OFCDriverBase): - """Common class for Trema (Sliceable Switch) Drivers.""" - networks_path = "/networks" - network_path = "/networks/%s" - - router_supported = False - - def __init__(self, conf_ofc): - # Trema sliceable REST API does not support HTTPS - self.client = ofc_client.OFCClient(host=conf_ofc.host, - port=conf_ofc.port) - - def _get_network_id(self, ofc_network_id): - # ofc_network_id : /networks/ - return ofc_network_id.split('/')[2] - - def _get_tenant_id(self, tenant_id): - # Trema does not use tenant_id, but it returns - # /tenants/ format to keep consistency with PFC driver. - return '/tenants/' + tenant_id - - def create_tenant(self, description, tenant_id=None): - return self._get_tenant_id(tenant_id or uuidutils.generate_uuid()) - - def update_tenant(self, ofc_tenant_id, description): - pass - - def delete_tenant(self, ofc_tenant_id): - pass - - def create_network(self, ofc_tenant_id, description, network_id=None): - ofc_network_id = network_id or uuidutils.generate_uuid() - body = {'id': ofc_network_id, 'description': description} - self.client.post(self.networks_path, body=body) - return self.network_path % ofc_network_id - - def delete_network(self, ofc_network_id): - return self.client.delete(ofc_network_id) - - -class TremaFilterDriverMixin(object): - """Trema (Sliceable Switch) PacketFilter Driver Mixin.""" - filters_path = "/filters" - filter_path = "/filters/%s" - - @classmethod - def filter_supported(cls): - return True - - def create_filter(self, context, filter_dict, filter_id=None): - ofc_network_id = ndb.get_ofc_id(context.session, "ofc_network", - filter_dict['network_id']) - # Prepare portinfo - in_port_id = filter_dict.get('in_port') - if in_port_id: - portinfo = ndb.get_portinfo(context.session, in_port_id) - if not portinfo: - raise nexc.PortInfoNotFound(id=in_port_id) - else: - portinfo = None - - # Prepare filter body - if filter_dict['action'].upper() in ["ACCEPT", "ALLOW"]: - ofc_action = "ALLOW" - elif filter_dict['action'].upper() in ["DROP", "DENY"]: - ofc_action = "DENY" - - body = {'priority': filter_dict['priority'], - 'slice': self._get_network_id(ofc_network_id), - 'action': ofc_action} - ofp_wildcards = ["dl_vlan", "dl_vlan_pcp", "nw_tos"] - - if portinfo: - body['in_datapath_id'] = portinfo.datapath_id - body['in_port'] = portinfo.port_no - else: - body['wildcards'] = "in_datapath_id" - ofp_wildcards.append("in_port") - - if filter_dict['src_mac']: - body['dl_src'] = filter_dict['src_mac'] - else: - ofp_wildcards.append("dl_src") - - if filter_dict['dst_mac']: - body['dl_dst'] = filter_dict['dst_mac'] - else: - ofp_wildcards.append("dl_dst") - - if filter_dict['src_cidr']: - body['nw_src'] = filter_dict['src_cidr'] - else: - ofp_wildcards.append("nw_src:32") - - if filter_dict['dst_cidr']: - body['nw_dst'] = filter_dict['dst_cidr'] - else: - ofp_wildcards.append("nw_dst:32") - - if filter_dict['protocol']: - if filter_dict['protocol'].upper() == "ICMP": - body['dl_type'] = "0x800" - body['nw_proto'] = hex(1) - elif filter_dict['protocol'].upper() == "TCP": - body['dl_type'] = "0x800" - body['nw_proto'] = hex(6) - elif filter_dict['protocol'].upper() == "UDP": - body['dl_type'] = "0x800" - body['nw_proto'] = hex(17) - elif filter_dict['protocol'].upper() == "ARP": - body['dl_type'] = "0x806" - ofp_wildcards.append("nw_proto") - else: - body['nw_proto'] = filter_dict['protocol'] - else: - ofp_wildcards.append("nw_proto") - - if 'dl_type' in body: - pass - elif filter_dict['eth_type']: - body['dl_type'] = filter_dict['eth_type'] - else: - ofp_wildcards.append("dl_type") - - if filter_dict['src_port']: - body['tp_src'] = hex(filter_dict['src_port']) - else: - ofp_wildcards.append("tp_src") - - if filter_dict['dst_port']: - body['tp_dst'] = hex(filter_dict['dst_port']) - else: - ofp_wildcards.append("tp_dst") - - ofc_filter_id = filter_id or uuidutils.generate_uuid() - body['id'] = ofc_filter_id - - body['ofp_wildcards'] = ','.join(ofp_wildcards) - - self.client.post(self.filters_path, body=body) - return self.filter_path % ofc_filter_id - - def delete_filter(self, ofc_filter_id): - return self.client.delete(ofc_filter_id) - - -class TremaPortBaseDriver(TremaDriverBase, TremaFilterDriverMixin): - """Trema (Sliceable Switch) Driver for port base binding. - - TremaPortBaseDriver uses port base binding. - Ports are identified by datapath_id, port_no and vlan_id. - """ - ports_path = "%(network)s/ports" - port_path = "%(network)s/ports/%(port)s" - - def create_port(self, ofc_network_id, portinfo, - port_id=None, filters=None): - ofc_port_id = port_id or uuidutils.generate_uuid() - path = self.ports_path % {'network': ofc_network_id} - body = {'id': ofc_port_id, - 'datapath_id': portinfo.datapath_id, - 'port': str(portinfo.port_no), - 'vid': str(portinfo.vlan_id)} - self.client.post(path, body=body) - return self.port_path % {'network': ofc_network_id, - 'port': ofc_port_id} - - def delete_port(self, ofc_port_id): - return self.client.delete(ofc_port_id) - - -class TremaPortMACBaseDriver(TremaDriverBase, TremaFilterDriverMixin): - """Trema (Sliceable Switch) Driver for port-mac base binding. - - TremaPortBaseDriver uses port-mac base binding. - Ports are identified by datapath_id, port_no, vlan_id and mac. - """ - ports_path = "%(network)s/ports" - port_path = "%(network)s/ports/%(port)s" - attachments_path = "%(network)s/ports/%(port)s/attachments" - attachment_path = "%(network)s/ports/%(port)s/attachments/%(attachment)s" - - def create_port(self, ofc_network_id, portinfo, port_id=None, - filters=None): - #NOTE: This Driver create slices with Port-MAC Based bindings on Trema - # Sliceable. It's REST API requires Port Based binding before you - # define Port-MAC Based binding. - ofc_port_id = port_id or uuidutils.generate_uuid() - dummy_port_id = "dummy-%s" % ofc_port_id - - path = self.ports_path % {'network': ofc_network_id} - body = {'id': dummy_port_id, - 'datapath_id': portinfo.datapath_id, - 'port': str(portinfo.port_no), - 'vid': str(portinfo.vlan_id)} - self.client.post(path, body=body) - - path = self.attachments_path % {'network': ofc_network_id, - 'port': dummy_port_id} - body = {'id': ofc_port_id, 'mac': portinfo.mac} - self.client.post(path, body=body) - - path = self.port_path % {'network': ofc_network_id, - 'port': dummy_port_id} - self.client.delete(path) - - return self.attachment_path % {'network': ofc_network_id, - 'port': dummy_port_id, - 'attachment': ofc_port_id} - - def delete_port(self, ofc_port_id): - return self.client.delete(ofc_port_id) - - -class TremaMACBaseDriver(TremaDriverBase): - """Trema (Sliceable Switch) Driver for mac base binding. - - TremaPortBaseDriver uses mac base binding. - Ports are identified by mac. - """ - attachments_path = "%(network)s/attachments" - attachment_path = "%(network)s/attachments/%(attachment)s" - - @classmethod - def filter_supported(cls): - return False - - def create_port(self, ofc_network_id, portinfo, port_id=None, - filters=None): - ofc_port_id = port_id or uuidutils.generate_uuid() - path = self.attachments_path % {'network': ofc_network_id} - body = {'id': ofc_port_id, 'mac': portinfo.mac} - self.client.post(path, body=body) - return self.attachment_path % {'network': ofc_network_id, - 'attachment': ofc_port_id} - - def delete_port(self, ofc_port_id): - return self.client.delete(ofc_port_id) diff --git a/neutron/plugins/nec/nec_plugin.py b/neutron/plugins/nec/nec_plugin.py index f37670f45..449bb9b0c 100644 --- a/neutron/plugins/nec/nec_plugin.py +++ b/neutron/plugins/nec/nec_plugin.py @@ -12,84 +12,14 @@ # License for the specific language governing permissions and limitations # under the License. -import oslo_messaging -from oslo_utils import excutils -from oslo_utils import importutils -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 l3_rpc -from neutron.api.rpc.handlers import metadata_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 -from neutron.common import rpc as n_rpc -from neutron.common import topics -from neutron.db import agents_db -from neutron.db import agentschedulers_db -from neutron.db import allowedaddresspairs_db as addr_pair_db -from neutron.db import db_base_plugin_v2 -from neutron.db import external_net_db -from neutron.db import portbindings_base -from neutron.db import portbindings_db -from neutron.db import quota_db # noqa -from neutron.db import securitygroups_rpc_base as sg_db_rpc -from neutron.extensions import allowedaddresspairs as addr_pair -from neutron.extensions import portbindings -from neutron.i18n import _LE, _LI, _LW -from neutron.openstack.common import log as logging -from neutron.openstack.common import uuidutils -from neutron.plugins.common import constants as svc_constants -from neutron.plugins.nec.common import config -from neutron.plugins.nec.common import exceptions as nexc -from neutron.plugins.nec.common import utils as necutils -from neutron.plugins.nec.db import api as ndb -from neutron.plugins.nec.db import router as rdb -from neutron.plugins.nec import extensions -from neutron.plugins.nec import nec_router -from neutron.plugins.nec import ofc_manager -from neutron.plugins.nec import packet_filter +from networking_nec.plugins.openflow import plugin -LOG = logging.getLogger(__name__) +from neutron.plugins.nec import config as nec_config -class SecurityGroupServerRpcMixin(sg_db_rpc.SecurityGroupServerRpcMixin): +class NECPluginV2(plugin.NECPluginV2Impl): - @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, - SecurityGroupServerRpcMixin, - agentschedulers_db.DhcpAgentSchedulerDbMixin, - nec_router.L3AgentSchedulerDbMixin, - packet_filter.PacketFilterMixin, - portbindings_db.PortBindingMixin, - addr_pair_db.AllowedAddressPairsMixin): - """NECPluginV2 controls an OpenFlow Controller. - - The Neutron NECPluginV2 maps L2 logical networks to L2 virtualized networks - on an OpenFlow enabled network. An OpenFlow Controller (OFC) provides - L2 network isolation without VLAN and this plugin controls the OFC. - - NOTE: This is for Neutron API V2. Codes for V1.0 and V1.1 are available - at https://github.com/nec-openstack/neutron-openflow-plugin . - - The port binding extension enables an external application relay - information to and from the plugin. - """ _supported_extension_aliases = ["agent", "allowed-address-pairs", "binding", @@ -109,653 +39,10 @@ class NECPluginV2(db_base_plugin_v2.NeutronDbPluginV2, def supported_extension_aliases(self): if not hasattr(self, '_aliases'): aliases = self._supported_extension_aliases[:] - sg_rpc.disable_security_group_extension_by_config(aliases) - self.remove_packet_filter_extension_if_disabled(aliases) + self.setup_extension_aliases(aliases) self._aliases = aliases return self._aliases def __init__(self): + nec_config.register_plugin_opts() super(NECPluginV2, self).__init__() - self.ofc = ofc_manager.OFCManager(self.safe_reference) - self.base_binding_dict = self._get_base_binding_dict() - portbindings_base.register_port_dict_function() - - neutron_extensions.append_api_extensions_path(extensions.__path__) - - self.setup_rpc() - self.l3_rpc_notifier = nec_router.L3AgentNotifyAPI() - - self.network_scheduler = importutils.import_object( - config.CONF.network_scheduler_driver - ) - self.router_scheduler = importutils.import_object( - config.CONF.router_scheduler_driver - ) - - nec_router.load_driver(self.safe_reference, self.ofc) - self.port_handlers = { - 'create': { - const.DEVICE_OWNER_ROUTER_GW: self.create_router_port, - const.DEVICE_OWNER_ROUTER_INTF: self.create_router_port, - 'default': self.activate_port_if_ready, - }, - 'delete': { - const.DEVICE_OWNER_ROUTER_GW: self.delete_router_port, - const.DEVICE_OWNER_ROUTER_INTF: self.delete_router_port, - 'default': self.deactivate_port, - } - } - self.start_periodic_dhcp_agent_status_check() - - def setup_rpc(self): - self.service_topics = {svc_constants.CORE: topics.PLUGIN, - svc_constants.L3_ROUTER_NAT: topics.L3PLUGIN} - self.conn = n_rpc.create_connection(new=True) - self.notifier = NECPluginV2AgentNotifierApi(topics.AGENT) - self.agent_notifiers[const.AGENT_TYPE_DHCP] = ( - dhcp_rpc_agent_api.DhcpAgentNotifyAPI() - ) - self.agent_notifiers[const.AGENT_TYPE_L3] = ( - nec_router.L3AgentNotifyAPI() - ) - - # NOTE: callback_sg is referred to from the sg unit test. - self.callback_sg = securitygroups_rpc.SecurityGroupServerRpcCallback() - self.endpoints = [ - NECPluginV2RPCCallbacks(self.safe_reference), - dhcp_rpc.DhcpRpcCallback(), - l3_rpc.L3RpcCallback(), - self.callback_sg, - agents_db.AgentExtRpcCallback(), - metadata_rpc.MetadataRpcCallback()] - for svc_topic in self.service_topics.values(): - self.conn.create_consumer(svc_topic, self.endpoints, fanout=False) - # Consume from all consumers in threads - self.conn.consume_in_threads() - - def _update_resource_status(self, context, resource, id, status): - """Update status of specified resource.""" - request = {'status': status} - obj_getter = getattr(self, '_get_%s' % resource) - with context.session.begin(subtransactions=True): - obj_db = obj_getter(context, id) - obj_db.update(request) - - def _update_resource_status_if_changed(self, context, resource_type, - resource_dict, new_status): - if resource_dict['status'] != new_status: - self._update_resource_status(context, resource_type, - resource_dict['id'], - new_status) - resource_dict['status'] = new_status - - def _check_ofc_tenant_in_use(self, context, tenant_id): - """Check if the specified tenant is used.""" - # All networks are created on OFC - filters = {'tenant_id': [tenant_id]} - if self.get_networks_count(context, filters=filters): - return True - if rdb.get_router_count_by_provider(context.session, - nec_router.PROVIDER_OPENFLOW, - tenant_id): - return True - return False - - def _cleanup_ofc_tenant(self, context, tenant_id): - if not self._check_ofc_tenant_in_use(context, tenant_id): - try: - if self.ofc.exists_ofc_tenant(context, tenant_id): - self.ofc.delete_ofc_tenant(context, tenant_id) - else: - LOG.debug('_cleanup_ofc_tenant: No OFC tenant for %s', - tenant_id) - except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: - LOG.warn(_LW("delete_ofc_tenant() failed due to %s"), exc) - - def activate_port_if_ready(self, context, port, network=None): - """Activate port by creating port on OFC if ready. - - Conditions to activate port on OFC are: - * port admin_state is UP - * network admin_state is UP - * portinfo are available (to identify port on OFC) - """ - if not network: - network = super(NECPluginV2, self).get_network(context, - port['network_id']) - - if not port['admin_state_up']: - LOG.debug("activate_port_if_ready(): skip, " - "port.admin_state_up is False.") - return port - elif not network['admin_state_up']: - LOG.debug("activate_port_if_ready(): skip, " - "network.admin_state_up is False.") - return port - elif not ndb.get_portinfo(context.session, port['id']): - LOG.debug("activate_port_if_ready(): skip, " - "no portinfo for this port.") - return port - elif self.ofc.exists_ofc_port(context, port['id']): - LOG.debug("activate_port_if_ready(): skip, " - "ofc_port already exists.") - return port - - try: - self.ofc.create_ofc_port(context, port['id'], port) - port_status = const.PORT_STATUS_ACTIVE - except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: - LOG.error(_LE("create_ofc_port() failed due to %s"), exc) - port_status = const.PORT_STATUS_ERROR - - if port_status != port['status']: - self._update_resource_status(context, "port", port['id'], - port_status) - port['status'] = port_status - - return port - - def deactivate_port(self, context, port, raise_exc=True): - """Deactivate port by deleting port from OFC if exists.""" - if not self.ofc.exists_ofc_port(context, port['id']): - LOG.debug("deactivate_port(): skip, ofc_port for port=%s " - "does not exist.", port['id']) - return port - - try: - self.ofc.delete_ofc_port(context, port['id'], port) - self._update_resource_status_if_changed( - context, "port", port, const.PORT_STATUS_DOWN) - return port - except (nexc.OFCResourceNotFound, nexc.OFCMappingNotFound): - # There is a case where multiple delete_port operation are - # running concurrently. For example, delete_port from - # release_dhcp_port and deletion of network owned ports in - # delete_network. In such cases delete_ofc_port may receive - # 404 error from OFC. - # Also there is a case where neutron port is deleted - # between exists_ofc_port and get_ofc_id in delete_ofc_port. - # In this case OFCMappingNotFound is raised. - # These two cases are valid situations. - LOG.info(_LI("deactivate_port(): OFC port for port=%s is " - "already removed."), port['id']) - # The port is already removed, so there is no need - # to update status in the database. - port['status'] = const.PORT_STATUS_DOWN - return port - except nexc.OFCException as exc: - with excutils.save_and_reraise_exception() as ctxt: - LOG.error(_LE("Failed to delete port=%(port)s from OFC: " - "%(exc)s"), {'port': port['id'], 'exc': exc}) - self._update_resource_status_if_changed( - context, "port", port, const.PORT_STATUS_ERROR) - if not raise_exc: - ctxt.reraise = False - return port - - def _net_status(self, network): - # NOTE: NEC Plugin accept admin_state_up. When it's False, this plugin - # deactivate all ports on the network to drop all packet and show - # status='DOWN' to users. But the network is kept defined on OFC. - if network['network']['admin_state_up']: - return const.NET_STATUS_ACTIVE - else: - return const.NET_STATUS_DOWN - - def create_network(self, context, network): - """Create a new network entry on DB, and create it on OFC.""" - LOG.debug("NECPluginV2.create_network() called, " - "network=%s .", network) - tenant_id = self._get_tenant_id_for_create(context, network['network']) - net_name = network['network']['name'] - net_id = uuidutils.generate_uuid() - - #set up default security groups - self._ensure_default_security_group(context, tenant_id) - - network['network']['id'] = net_id - network['network']['status'] = self._net_status(network) - - try: - if not self.ofc.exists_ofc_tenant(context, tenant_id): - self.ofc.create_ofc_tenant(context, tenant_id) - self.ofc.create_ofc_network(context, tenant_id, net_id, net_name) - except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: - LOG.error(_LE("Failed to create network id=%(id)s on " - "OFC: %(exc)s"), {'id': net_id, 'exc': exc}) - network['network']['status'] = const.NET_STATUS_ERROR - - with context.session.begin(subtransactions=True): - new_net = super(NECPluginV2, self).create_network(context, network) - self._process_l3_create(context, new_net, network['network']) - - return new_net - - def update_network(self, context, id, network): - """Update network and handle resources associated with the network. - - Update network entry on DB. If 'admin_state_up' was changed, activate - or deactivate ports and packetfilters associated with the network. - """ - LOG.debug("NECPluginV2.update_network() called, " - "id=%(id)s network=%(network)s .", - {'id': id, 'network': network}) - - if 'admin_state_up' in network['network']: - network['network']['status'] = self._net_status(network) - - session = context.session - with session.begin(subtransactions=True): - old_net = super(NECPluginV2, self).get_network(context, id) - new_net = super(NECPluginV2, self).update_network(context, id, - network) - self._process_l3_update(context, new_net, network['network']) - - changed = (old_net['admin_state_up'] != new_net['admin_state_up']) - if changed and not new_net['admin_state_up']: - # disable all active ports of the network - filters = dict(network_id=[id], status=[const.PORT_STATUS_ACTIVE]) - ports = super(NECPluginV2, self).get_ports(context, - filters=filters) - for port in ports: - # If some error occurs, status of errored port is set to ERROR. - # This is avoids too many rollback. - # TODO(amotoki): Raise an exception after all port operations - # are finished to inform the caller of API of the failure. - self.deactivate_port(context, port, raise_exc=False) - elif changed and new_net['admin_state_up']: - # enable ports of the network - filters = dict(network_id=[id], status=[const.PORT_STATUS_DOWN], - admin_state_up=[True]) - ports = super(NECPluginV2, self).get_ports(context, - filters=filters) - for port in ports: - self.activate_port_if_ready(context, port, new_net) - - return new_net - - def delete_network(self, context, id): - """Delete network and packet_filters associated with the network. - - Delete network entry from DB and OFC. Then delete packet_filters - associated with the network. If the network is the last resource - of the tenant, delete unnessary ofc_tenant. - """ - LOG.debug("NECPluginV2.delete_network() called, id=%s .", id) - net_db = self._get_network(context, id) - tenant_id = net_db['tenant_id'] - ports = self.get_ports(context, filters={'network_id': [id]}) - - # check if there are any tenant owned ports in-use; - # consider ports owned by floating ips as auto_delete as if there are - # no other tenant owned ports, those floating ips are disassociated - # and will be auto deleted with self._process_l3_delete() - only_auto_del = all(p['device_owner'] in - db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS or - p['device_owner'] == const.DEVICE_OWNER_FLOATINGIP - for p in ports) - if not only_auto_del: - raise n_exc.NetworkInUse(net_id=id) - - self._process_l3_delete(context, id) - - # Make sure auto-delete ports on OFC are deleted. - # If an error occurs during port deletion, - # delete_network will be aborted. - for port in [p for p in ports if p['device_owner'] - in db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS]: - port = self.deactivate_port(context, port) - - # delete all packet_filters of the network from the controller - for pf in net_db.packetfilters: - self.delete_packet_filter(context, pf['id']) - - if self.ofc.exists_ofc_network(context, id): - try: - self.ofc.delete_ofc_network(context, id, net_db) - except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("delete_network() failed due to %s"), exc) - self._update_resource_status( - context, "network", net_db['id'], - const.NET_STATUS_ERROR) - - super(NECPluginV2, self).delete_network(context, id) - - self._cleanup_ofc_tenant(context, tenant_id) - - def _get_base_binding_dict(self): - sg_enabled = sg_rpc.is_firewall_enabled() - vif_details = {portbindings.CAP_PORT_FILTER: sg_enabled, - portbindings.OVS_HYBRID_PLUG: sg_enabled} - binding = {portbindings.VIF_TYPE: portbindings.VIF_TYPE_OVS, - portbindings.VIF_DETAILS: vif_details} - return binding - - def _extend_port_dict_binding_portinfo(self, port_res, portinfo): - if portinfo: - port_res[portbindings.PROFILE] = { - 'datapath_id': portinfo['datapath_id'], - 'port_no': portinfo['port_no'], - } - elif portbindings.PROFILE in port_res: - del port_res[portbindings.PROFILE] - - def _validate_portinfo(self, profile): - key_specs = { - 'datapath_id': {'type:string': None, 'required': True}, - 'port_no': {'type:non_negative': None, 'required': True, - 'convert_to': attrs.convert_to_int} - } - msg = attrs._validate_dict_or_empty(profile, key_specs=key_specs) - if msg: - raise n_exc.InvalidInput(error_message=msg) - - datapath_id = profile.get('datapath_id') - port_no = profile.get('port_no') - try: - dpid = int(datapath_id, 16) - except ValueError: - raise nexc.ProfilePortInfoInvalidDataPathId() - if dpid > 0xffffffffffffffffL: - raise nexc.ProfilePortInfoInvalidDataPathId() - # Make sure dpid is a hex string beginning with 0x. - dpid = hex(dpid) - - if int(port_no) > 65535: - raise nexc.ProfilePortInfoInvalidPortNo() - - return {'datapath_id': dpid, 'port_no': port_no} - - def _process_portbindings_portinfo_create(self, context, port_data, port): - """Add portinfo according to bindings:profile in create_port(). - - :param context: neutron api request context - :param port_data: port attributes passed in PUT request - :param port: port attributes to be returned - """ - profile = port_data.get(portbindings.PROFILE) - # If portbindings.PROFILE is None, unspecified or an empty dict - # it is regarded that portbinding.PROFILE is not set. - profile_set = attrs.is_attr_set(profile) and profile - if profile_set: - portinfo = self._validate_portinfo(profile) - portinfo['mac'] = port['mac_address'] - ndb.add_portinfo(context.session, port['id'], **portinfo) - else: - portinfo = None - self._extend_port_dict_binding_portinfo(port, portinfo) - - def _process_portbindings_portinfo_update(self, context, port_data, port): - """Update portinfo according to bindings:profile in update_port(). - - :param context: neutron api request context - :param port_data: port attributes passed in PUT request - :param port: port attributes to be returned - :returns: 'ADD', 'MOD', 'DEL' or None - """ - if portbindings.PROFILE not in port_data: - return - profile = port_data.get(portbindings.PROFILE) - # If binding:profile is None or an empty dict, - # it means binding:.profile needs to be cleared. - # TODO(amotoki): Allow Make None in binding:profile in - # the API layer. See LP bug #1220011. - profile_set = attrs.is_attr_set(profile) and profile - cur_portinfo = ndb.get_portinfo(context.session, port['id']) - if profile_set: - portinfo = self._validate_portinfo(profile) - portinfo_changed = 'ADD' - if cur_portinfo: - if (necutils.cmp_dpid(portinfo['datapath_id'], - cur_portinfo.datapath_id) and - portinfo['port_no'] == cur_portinfo.port_no): - return - ndb.del_portinfo(context.session, port['id']) - portinfo_changed = 'MOD' - portinfo['mac'] = port['mac_address'] - ndb.add_portinfo(context.session, port['id'], **portinfo) - elif cur_portinfo: - portinfo_changed = 'DEL' - portinfo = None - ndb.del_portinfo(context.session, port['id']) - else: - portinfo = None - portinfo_changed = None - self._extend_port_dict_binding_portinfo(port, portinfo) - return portinfo_changed - - def extend_port_dict_binding(self, port_res, port_db): - super(NECPluginV2, self).extend_port_dict_binding(port_res, port_db) - self._extend_port_dict_binding_portinfo(port_res, port_db.portinfo) - - def _process_portbindings_create(self, context, port_data, port): - super(NECPluginV2, self)._process_portbindings_create_and_update( - context, port_data, port) - self._process_portbindings_portinfo_create(context, port_data, port) - - def _process_portbindings_update(self, context, port_data, port): - super(NECPluginV2, self)._process_portbindings_create_and_update( - context, port_data, port) - portinfo_changed = self._process_portbindings_portinfo_update( - context, port_data, port) - return portinfo_changed - - def _get_port_handler(self, operation, device_owner): - handlers = self.port_handlers[operation] - handler = handlers.get(device_owner) - if handler: - return handler - else: - return handlers['default'] - - def create_port(self, context, port): - """Create a new port entry on DB, then try to activate it.""" - LOG.debug("NECPluginV2.create_port() called, port=%s .", port) - - port['port']['status'] = const.PORT_STATUS_DOWN - - port_data = port['port'] - with context.session.begin(subtransactions=True): - self._ensure_default_security_group_on_port(context, port) - sgids = self._get_security_groups_on_port(context, port) - port = super(NECPluginV2, self).create_port(context, port) - self._process_portbindings_create(context, port_data, port) - self._process_port_create_security_group( - context, port, sgids) - port[addr_pair.ADDRESS_PAIRS] = ( - self._process_create_allowed_address_pairs( - context, port, - port_data.get(addr_pair.ADDRESS_PAIRS))) - self.notify_security_groups_member_updated(context, port) - - handler = self._get_port_handler('create', port['device_owner']) - return handler(context, port) - - def _update_ofc_port_if_required(self, context, old_port, new_port, - portinfo_changed): - def get_ofport_exist(port): - return (port['admin_state_up'] and - bool(port.get(portbindings.PROFILE))) - - # Determine it is required to update OFC port - need_add = False - need_del = False - need_packet_filter_update = False - - old_ofport_exist = get_ofport_exist(old_port) - new_ofport_exist = get_ofport_exist(new_port) - - if old_port['admin_state_up'] != new_port['admin_state_up']: - if new_port['admin_state_up']: - need_add |= new_ofport_exist - else: - need_del |= old_ofport_exist - - if portinfo_changed: - if portinfo_changed in ['DEL', 'MOD']: - need_del |= old_ofport_exist - if portinfo_changed in ['ADD', 'MOD']: - need_add |= new_ofport_exist - need_packet_filter_update |= True - - # Update OFC port if required - if need_del: - self.deactivate_port(context, new_port) - if need_packet_filter_update: - self.deactivate_packet_filters_by_port(context, id) - if need_add: - if need_packet_filter_update: - self.activate_packet_filters_by_port(context, id) - self.activate_port_if_ready(context, new_port) - - def update_port(self, context, id, port): - """Update port, and handle packetfilters associated with the port. - - Update network entry on DB. If admin_state_up was changed, activate - or deactivate the port and packetfilters associated with it. - """ - LOG.debug("NECPluginV2.update_port() called, " - "id=%(id)s port=%(port)s .", - {'id': id, 'port': port}) - need_port_update_notify = False - with context.session.begin(subtransactions=True): - old_port = super(NECPluginV2, self).get_port(context, id) - new_port = super(NECPluginV2, self).update_port(context, id, port) - portinfo_changed = self._process_portbindings_update( - context, port['port'], new_port) - if addr_pair.ADDRESS_PAIRS in port['port']: - need_port_update_notify |= ( - self.update_address_pairs_on_port(context, id, port, - old_port, - new_port)) - need_port_update_notify |= self.update_security_group_on_port( - context, id, port, old_port, new_port) - - need_port_update_notify |= self.is_security_group_member_updated( - context, old_port, new_port) - if need_port_update_notify: - self.notifier.port_update(context, new_port) - - self._update_ofc_port_if_required(context, old_port, new_port, - portinfo_changed) - return new_port - - def delete_port(self, context, id, l3_port_check=True): - """Delete port and packet_filters associated with the port.""" - LOG.debug("NECPluginV2.delete_port() called, id=%s .", id) - # ext_sg.SECURITYGROUPS attribute for the port is required - # since notifier.security_groups_member_updated() need the attribute. - # Thus we need to call self.get_port() instead of super().get_port() - port_db = self._get_port(context, id) - port = self._make_port_dict(port_db) - - handler = self._get_port_handler('delete', port['device_owner']) - # handler() raises an exception if an error occurs during processing. - port = handler(context, port) - - # delete all packet_filters of the port from the controller - for pf in port_db.packetfilters: - self.delete_packet_filter(context, pf['id']) - - # if needed, check to see if this is a port owned by - # and l3-router. If so, we should prevent deletion. - if l3_port_check: - self.prevent_l3_port_deletion(context, id) - with context.session.begin(subtransactions=True): - router_ids = self.disassociate_floatingips( - context, id, do_notify=False) - super(NECPluginV2, self).delete_port(context, id) - - # 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) - - -class NECPluginV2AgentNotifierApi(sg_rpc.SecurityGroupAgentRpcApiMixin): - '''RPC API for NEC plugin agent.''' - - def __init__(self, topic): - self.topic = topic - self.topic_port_update = topics.get_topic_name( - topic, topics.PORT, topics.UPDATE) - target = oslo_messaging.Target(topic=topic, version='1.0') - self.client = n_rpc.get_client(target) - - def port_update(self, context, port): - cctxt = self.client.prepare(topic=self.topic_port_update, fanout=True) - cctxt.cast(context, 'port_update', port=port) - - -class NECPluginV2RPCCallbacks(object): - - target = oslo_messaging.Target(version='1.0') - - def __init__(self, plugin): - super(NECPluginV2RPCCallbacks, self).__init__() - self.plugin = plugin - - def update_ports(self, rpc_context, **kwargs): - """Update ports' information and activate/deavtivate them. - - Expected input format is: - {'topic': 'q-agent-notifier', - 'agent_id': 'nec-q-agent.' + , - 'datapath_id': , - 'port_added': [,...], - 'port_removed': [,...]} - """ - LOG.debug("NECPluginV2RPCCallbacks.update_ports() called, " - "kwargs=%s .", kwargs) - datapath_id = kwargs['datapath_id'] - session = rpc_context.session - for p in kwargs.get('port_added', []): - id = p['id'] - portinfo = ndb.get_portinfo(session, id) - if portinfo: - if (necutils.cmp_dpid(portinfo.datapath_id, datapath_id) and - portinfo.port_no == p['port_no']): - LOG.debug("update_ports(): ignore unchanged portinfo in " - "port_added message (port_id=%s).", id) - continue - ndb.del_portinfo(session, id) - port = self._get_port(rpc_context, id) - if port: - ndb.add_portinfo(session, id, datapath_id, p['port_no'], - mac=p.get('mac', '')) - # NOTE: Make sure that packet filters on this port exist while - # the port is active to avoid unexpected packet transfer. - if portinfo: - self.plugin.deactivate_port(rpc_context, port, - raise_exc=False) - self.plugin.deactivate_packet_filters_by_port( - rpc_context, id, raise_exc=False) - self.plugin.activate_packet_filters_by_port(rpc_context, id) - self.plugin.activate_port_if_ready(rpc_context, port) - for id in kwargs.get('port_removed', []): - portinfo = ndb.get_portinfo(session, id) - if not portinfo: - LOG.debug("update_ports(): ignore port_removed message " - "due to portinfo for port_id=%s was not " - "registered", id) - continue - if not necutils.cmp_dpid(portinfo.datapath_id, datapath_id): - LOG.debug("update_ports(): ignore port_removed message " - "received from different host " - "(registered_datapath_id=%(registered)s, " - "received_datapath_id=%(received)s).", - {'registered': portinfo.datapath_id, - 'received': datapath_id}) - continue - ndb.del_portinfo(session, id) - port = self._get_port(rpc_context, id) - if port: - self.plugin.deactivate_port(rpc_context, port, raise_exc=False) - self.plugin.deactivate_packet_filters_by_port( - rpc_context, id, raise_exc=False) - - def _get_port(self, context, port_id): - try: - return self.plugin.get_port(context, port_id) - except n_exc.PortNotFound: - return None diff --git a/neutron/plugins/nec/nec_router.py b/neutron/plugins/nec/nec_router.py deleted file mode 100644 index 1eec439b2..000000000 --- a/neutron/plugins/nec/nec_router.py +++ /dev/null @@ -1,358 +0,0 @@ -# Copyright 2013 NEC Corporation. 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 oslo_utils import excutils -from oslo_utils import importutils - -from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api -from neutron.api.v2 import attributes as attr -from neutron.common import exceptions as n_exc -from neutron.db import db_base_plugin_v2 -from neutron.db import extraroute_db -from neutron.db import l3_agentschedulers_db -from neutron.db import l3_db -from neutron.db import l3_gwmode_db -from neutron.db import models_v2 -from neutron.extensions import l3 -from neutron.i18n import _LE, _LI, _LW -from neutron.openstack.common import log as logging -from neutron.plugins.nec.common import config -from neutron.plugins.nec.common import constants as nconst -from neutron.plugins.nec.common import exceptions as nexc -from neutron.plugins.nec.db import router as rdb -from neutron.plugins.nec.extensions import router_provider as ext_provider - -LOG = logging.getLogger(__name__) - -PROVIDER_L3AGENT = nconst.ROUTER_PROVIDER_L3AGENT -PROVIDER_OPENFLOW = nconst.ROUTER_PROVIDER_OPENFLOW - -ROUTER_DRIVER_PATH = 'neutron.plugins.nec.router_drivers.' -ROUTER_DRIVER_MAP = { - PROVIDER_L3AGENT: ROUTER_DRIVER_PATH + 'RouterL3AgentDriver', - PROVIDER_OPENFLOW: ROUTER_DRIVER_PATH + 'RouterOpenFlowDriver' -} - -ROUTER_DRIVERS = {} - -STATUS_ACTIVE = nconst.ROUTER_STATUS_ACTIVE -STATUS_ERROR = nconst.ROUTER_STATUS_ERROR - - -class RouterMixin(extraroute_db.ExtraRoute_db_mixin, - l3_gwmode_db.L3_NAT_db_mixin): - - def create_router(self, context, router): - """Create a new router entry on DB, and create it on OFC.""" - LOG.debug("RouterMixin.create_router() called, " - "router=%s .", router) - tenant_id = self._get_tenant_id_for_create(context, router['router']) - - provider = get_provider_with_default( - router['router'].get(ext_provider.ROUTER_PROVIDER)) - driver = get_driver_by_provider(provider) - - with context.session.begin(subtransactions=True): - new_router = super(RouterMixin, self).create_router(context, - router) - new_router['gw_port'] = self._get_gw_port_detail( - context, driver, new_router['gw_port_id']) - rdb.add_router_provider_binding(context.session, - provider, str(new_router['id'])) - self._extend_router_dict_provider(new_router, provider) - - # create router on the network controller - try: - return driver.create_router(context, tenant_id, new_router) - except nexc.RouterOverLimit: - with excutils.save_and_reraise_exception(): - super(RouterMixin, self).delete_router(context, - new_router['id']) - - def update_router(self, context, router_id, router): - LOG.debug("RouterMixin.update_router() called, " - "id=%(id)s, router=%(router)s .", - {'id': router_id, 'router': router}) - - with context.session.begin(subtransactions=True): - old_rtr = super(RouterMixin, self).get_router(context, router_id) - provider = old_rtr[ext_provider.ROUTER_PROVIDER] - driver = get_driver_by_provider(provider) - old_rtr['gw_port'] = self._get_gw_port_detail( - context, driver, old_rtr['gw_port_id']) - new_rtr = super(RouterMixin, self).update_router( - context, router_id, router) - new_rtr['gw_port'] = self._get_gw_port_detail( - context, driver, new_rtr['gw_port_id']) - driver.update_router(context, router_id, old_rtr, new_rtr) - return new_rtr - - def delete_router(self, context, router_id): - LOG.debug("RouterMixin.delete_router() called, id=%s.", router_id) - - router = super(RouterMixin, self).get_router(context, router_id) - tenant_id = router['tenant_id'] - # Since l3_db.delete_router() has no interaction with the plugin layer, - # we need to check if the router can be deleted first. - self._check_router_in_use(context, router_id) - driver = self._get_router_driver_by_id(context, router_id) - # If gw_port exists, remove it. - gw_port = self._get_gw_port(context, router_id) - if gw_port: - driver.delete_interface(context, router_id, gw_port) - driver.delete_router(context, router_id, router) - - super(RouterMixin, self).delete_router(context, router_id) - - self._cleanup_ofc_tenant(context, tenant_id) - - def add_router_interface(self, context, router_id, interface_info): - LOG.debug("RouterMixin.add_router_interface() called, " - "id=%(id)s, interface=%(interface)s.", - {'id': router_id, 'interface': interface_info}) - return super(RouterMixin, self).add_router_interface( - context, router_id, interface_info) - - def remove_router_interface(self, context, router_id, interface_info): - LOG.debug("RouterMixin.remove_router_interface() called, " - "id=%(id)s, interface=%(interface)s.", - {'id': router_id, 'interface': interface_info}) - return super(RouterMixin, self).remove_router_interface( - context, router_id, interface_info) - - def create_router_port(self, context, port): - # This method is called from plugin.create_port() - router_id = port['device_id'] - driver = self._get_router_driver_by_id(context, router_id) - port = driver.add_interface(context, router_id, port) - return port - - def delete_router_port(self, context, port): - # This method is called from plugin.delete_port() - router_id = port['device_id'] - driver = self._get_router_driver_by_id(context, router_id) - return driver.delete_interface(context, router_id, port) - - def _get_gw_port_detail(self, context, driver, gw_port_id): - if not gw_port_id or not driver.need_gw_info: - return - ctx_elevated = context.elevated() - gw_port = self._get_port(ctx_elevated, gw_port_id) - # At this moment gw_port has been created, so it is guaranteed - # that fixed_ip is assigned for the gw_port. - ext_subnet_id = gw_port['fixed_ips'][0]['subnet_id'] - ext_subnet = self._get_subnet(ctx_elevated, ext_subnet_id) - gw_info = {'network_id': gw_port['network_id'], - 'ip_address': gw_port['fixed_ips'][0]['ip_address'], - 'mac_address': gw_port['mac_address'], - 'cidr': ext_subnet['cidr'], - 'gateway_ip': ext_subnet['gateway_ip']} - return gw_info - - def _get_gw_port(self, context, router_id): - device_filter = {'device_id': [router_id], - 'device_owner': [l3_db.DEVICE_OWNER_ROUTER_GW]} - ports = self.get_ports(context.elevated(), filters=device_filter) - if ports: - return ports[0] - - def _check_router_in_use(self, context, router_id): - with context.session.begin(subtransactions=True): - # Ensure that the router is not used - router_filter = {'router_id': [router_id]} - fips = self.get_floatingips_count(context.elevated(), - filters=router_filter) - if fips: - raise l3.RouterInUse(router_id=router_id) - - device_filter = {'device_id': [router_id], - 'device_owner': [l3_db.DEVICE_OWNER_ROUTER_INTF]} - ports = self.get_ports_count(context.elevated(), - filters=device_filter) - if ports: - raise l3.RouterInUse(router_id=router_id) - - def _get_router_for_floatingip(self, context, internal_port, - internal_subnet_id, - external_network_id): - """Get a router for a requested floating IP. - - OpenFlow vrouter does not support NAT, so we need to exclude them - from candidate routers for floating IP association. - This method is called in l3_db.get_assoc_data(). - """ - subnet_db = self._get_subnet(context, internal_subnet_id) - if not subnet_db['gateway_ip']: - msg = (_('Cannot add floating IP to port on subnet %s ' - 'which has no gateway_ip') % internal_subnet_id) - raise n_exc.BadRequest(resource='floatingip', msg=msg) - - # find router interface ports on this network - router_intf_qry = context.session.query(models_v2.Port) - router_intf_ports = router_intf_qry.filter_by( - network_id=internal_port['network_id'], - device_owner=l3_db.DEVICE_OWNER_ROUTER_INTF) - - for intf_p in router_intf_ports: - if intf_p['fixed_ips'][0]['subnet_id'] == internal_subnet_id: - router_id = intf_p['device_id'] - router_gw_qry = context.session.query(models_v2.Port) - has_gw_port = router_gw_qry.filter_by( - network_id=external_network_id, - device_id=router_id, - device_owner=l3_db.DEVICE_OWNER_ROUTER_GW).count() - driver = self._get_router_driver_by_id(context, router_id) - if (has_gw_port and driver.floating_ip_support()): - return router_id - - raise l3.ExternalGatewayForFloatingIPNotFound( - subnet_id=internal_subnet_id, - external_network_id=external_network_id, - port_id=internal_port['id']) - - def _get_sync_routers(self, context, router_ids=None, active=None): - """Query routers and their gw ports for l3 agent. - - The difference from the superclass in l3_db is that this method - only lists routers hosted on l3-agents. - """ - router_list = super(RouterMixin, self)._get_sync_routers( - context, router_ids, active) - if router_list: - _router_ids = [r['id'] for r in router_list] - agent_routers = rdb.get_routers_by_provider( - context.session, 'l3-agent', - router_ids=_router_ids) - router_list = [r for r in router_list - if r['id'] in agent_routers] - return router_list - - def _get_router_driver_by_id(self, context, router_id): - provider = self._get_provider_by_router_id(context, router_id) - return get_driver_by_provider(provider) - - def _get_provider_by_router_id(self, context, router_id): - return rdb.get_provider_by_router(context.session, router_id) - - def _extend_router_dict_provider(self, router_res, provider): - router_res[ext_provider.ROUTER_PROVIDER] = provider - - def extend_router_dict_provider(self, router_res, router_db): - # NOTE: router_db.provider is None just after creating a router, - # so we need to skip setting router_provider here. - if not router_db.provider: - return - self._extend_router_dict_provider(router_res, - router_db.provider['provider']) - - db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs( - l3.ROUTERS, [extend_router_dict_provider]) - - -class L3AgentSchedulerDbMixin(l3_agentschedulers_db.L3AgentSchedulerDbMixin): - - def auto_schedule_routers(self, context, host, router_ids): - router_ids = rdb.get_routers_by_provider( - context.session, nconst.ROUTER_PROVIDER_L3AGENT, router_ids) - # If no l3-agent hosted router, there is no need to schedule. - if not router_ids: - return - return super(L3AgentSchedulerDbMixin, self).auto_schedule_routers( - context, host, router_ids) - - def schedule_router(self, context, router, candidates=None): - if (self._get_provider_by_router_id(context, router) == - nconst.ROUTER_PROVIDER_L3AGENT): - return super(L3AgentSchedulerDbMixin, self).schedule_router( - context, router, candidates=candidates) - - def add_router_to_l3_agent(self, context, id, router_id): - provider = self._get_provider_by_router_id(context, router_id) - if provider != nconst.ROUTER_PROVIDER_L3AGENT: - raise nexc.RouterProviderMismatch( - router_id=router_id, provider=provider, - expected_provider=nconst.ROUTER_PROVIDER_L3AGENT) - return super(L3AgentSchedulerDbMixin, self).add_router_to_l3_agent( - context, id, router_id) - - -class L3AgentNotifyAPI(l3_rpc_agent_api.L3AgentNotifyAPI): - - def _notification(self, context, method, router_ids, operation, - shuffle_agents): - """Notify all the agents that are hosting the routers. - - _notification() is called in L3 db plugin for all routers regardless - the routers are hosted on l3 agents or not. When the routers are - not hosted on l3 agents, there is no need to notify. - This method filters routers not hosted by l3 agents. - """ - router_ids = rdb.get_routers_by_provider( - context.session, nconst.ROUTER_PROVIDER_L3AGENT, router_ids) - super(L3AgentNotifyAPI, self)._notification( - context, method, router_ids, operation, shuffle_agents) - - -def load_driver(plugin, ofc_manager): - - if (PROVIDER_OPENFLOW in ROUTER_DRIVER_MAP and - not ofc_manager.driver.router_supported): - LOG.warning( - _LW('OFC does not support router with provider=%(provider)s, ' - 'so removed it from supported provider ' - '(new router driver map=%(driver_map)s)'), - {'provider': PROVIDER_OPENFLOW, - 'driver_map': ROUTER_DRIVER_MAP}) - del ROUTER_DRIVER_MAP[PROVIDER_OPENFLOW] - - if config.PROVIDER.default_router_provider not in ROUTER_DRIVER_MAP: - LOG.error(_LE('default_router_provider %(default)s is supported! ' - 'Please specify one of %(supported)s'), - {'default': config.PROVIDER.default_router_provider, - 'supported': ROUTER_DRIVER_MAP.keys()}) - raise SystemExit(1) - - enabled_providers = (set(config.PROVIDER.router_providers + - [config.PROVIDER.default_router_provider]) & - set(ROUTER_DRIVER_MAP.keys())) - - for driver in enabled_providers: - driver_klass = importutils.import_class(ROUTER_DRIVER_MAP[driver]) - ROUTER_DRIVERS[driver] = driver_klass(plugin, ofc_manager) - - LOG.info(_LI('Enabled router drivers: %s'), ROUTER_DRIVERS.keys()) - - if not ROUTER_DRIVERS: - LOG.error(_LE('No router provider is enabled. neutron-server ' - 'terminated! (supported=%(supported)s, ' - 'configured=%(config)s)'), - {'supported': ROUTER_DRIVER_MAP.keys(), - 'config': config.PROVIDER.router_providers}) - raise SystemExit(1) - - -def get_provider_with_default(provider): - if not attr.is_attr_set(provider): - provider = config.PROVIDER.default_router_provider - elif provider not in ROUTER_DRIVERS: - raise nexc.ProviderNotFound(provider=provider) - return provider - - -def get_driver_by_provider(provider): - if provider is None: - provider = config.PROVIDER.default_router_provider - elif provider not in ROUTER_DRIVERS: - raise nexc.ProviderNotFound(provider=provider) - return ROUTER_DRIVERS[provider] diff --git a/neutron/plugins/nec/ofc_driver_base.py b/neutron/plugins/nec/ofc_driver_base.py deleted file mode 100644 index b1c6e0163..000000000 --- a/neutron/plugins/nec/ofc_driver_base.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright 2012 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import abc -import six - - -@six.add_metaclass(abc.ABCMeta) -class OFCDriverBase(object): - """OpenFlow Controller (OFC) Driver Specification. - - OFCDriverBase defines the minimum set of methods required by this plugin. - It would be better that other methods like update_* are implemented. - """ - - @abc.abstractmethod - def create_tenant(self, description, tenant_id=None): - """Create a new tenant at OpenFlow Controller. - - :param description: A description of this tenant. - :param tenant_id: A hint of OFC tenant ID. - A driver could use this id as a OFC id or ignore it. - :returns: ID of the tenant created at OpenFlow Controller. - :raises: neutron.plugin.nec.common.exceptions.OFCException - """ - pass - - @abc.abstractmethod - def delete_tenant(self, ofc_tenant_id): - """Delete a tenant at OpenFlow Controller. - - :raises: neutron.plugin.nec.common.exceptions.OFCException - """ - pass - - @abc.abstractmethod - def create_network(self, ofc_tenant_id, description, network_id=None): - """Create a new network on specified OFC tenant at OpenFlow Controller. - - :param ofc_tenant_id: a OFC tenant ID in which a new network belongs. - :param description: A description of this network. - :param network_id: A hint of an ID of OFC network. - :returns: ID of the network created at OpenFlow Controller. - ID returned must be unique in the OpenFlow Controller. - If a network is identified in conjunction with other information - such as a tenant ID, such information should be included in the ID. - :raises: neutron.plugin.nec.common.exceptions.OFCException - """ - pass - - @abc.abstractmethod - def delete_network(self, ofc_network_id): - """Delete a netwrok at OpenFlow Controller. - - :raises: neutron.plugin.nec.common.exceptions.OFCException - """ - pass - - @abc.abstractmethod - def create_port(self, ofc_network_id, portinfo, - port_id=None, filters=None): - """Create a new port on specified network at OFC. - - :param ofc_network_id: a OFC tenant ID in which a new port belongs. - :param portinfo: An OpenFlow information of this port. - {'datapath_id': Switch ID that a port connected. - 'port_no': Port Number that a port connected on a Swtich. - 'vlan_id': VLAN ID that a port tagging. - 'mac': Mac address. - } - :param port_id: A hint of an ID of OFC port. - ID returned must be unique in the OpenFlow Controller. - - If a port is identified in combination with a network or - a tenant, such information should be included in the ID. - :param filters: A list of packet filter associated with the port. - Each element is a tuple (neutron ID, OFC ID) - - :returns: ID of the port created at OpenFlow Controller. - :raises: neutron.plugin.nec.common.exceptions.OFCException - """ - pass - - @abc.abstractmethod - def delete_port(self, ofc_port_id): - """Delete a port at OpenFlow Controller. - - :raises: neutron.plugin.nec.common.exceptions.OFCException - """ - pass diff --git a/neutron/plugins/nec/ofc_manager.py b/neutron/plugins/nec/ofc_manager.py deleted file mode 100644 index 68d605de6..000000000 --- a/neutron/plugins/nec/ofc_manager.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright 2012 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import netaddr - -from neutron.common import utils -from neutron.openstack.common import log as logging -from neutron.plugins.nec.common import config -from neutron.plugins.nec.common import exceptions as nexc -from neutron.plugins.nec.db import api as ndb -from neutron.plugins.nec import drivers - - -LOG = logging.getLogger(__name__) - - -class OFCManager(object): - """This class manages an OpenFlow Controller and map resources. - - This class manage an OpenFlow Controller (OFC) with a driver specified in - a configuration of this plugin. This keeps mappings between IDs on Neutron - and OFC for various entities such as Tenant, Network and Filter. A Port on - OFC is identified by a switch ID 'datapath_id' and a port number 'port_no' - of the switch. An ID named as 'ofc_*' is used to identify resource on OFC. - """ - - def __init__(self, plugin): - self.driver = drivers.get_driver(config.OFC.driver)(config.OFC) - self.plugin = plugin - - def _get_ofc_id(self, context, resource, neutron_id): - return ndb.get_ofc_id(context.session, resource, neutron_id) - - def _exists_ofc_item(self, context, resource, neutron_id): - return ndb.exists_ofc_item(context.session, resource, neutron_id) - - def _add_ofc_item(self, context, resource, neutron_id, ofc_id): - # Ensure a new item is added to the new mapping table - ndb.add_ofc_item(context.session, resource, neutron_id, ofc_id) - - def _del_ofc_item(self, context, resource, neutron_id): - ndb.del_ofc_item(context.session, resource, neutron_id) - - def ensure_ofc_tenant(self, context, tenant_id): - if not self.exists_ofc_tenant(context, tenant_id): - self.create_ofc_tenant(context, tenant_id) - - def create_ofc_tenant(self, context, tenant_id): - desc = "ID=%s at OpenStack." % tenant_id - ofc_tenant_id = self.driver.create_tenant(desc, tenant_id) - self._add_ofc_item(context, "ofc_tenant", tenant_id, ofc_tenant_id) - - def exists_ofc_tenant(self, context, tenant_id): - return self._exists_ofc_item(context, "ofc_tenant", tenant_id) - - def delete_ofc_tenant(self, context, tenant_id): - ofc_tenant_id = self._get_ofc_id(context, "ofc_tenant", tenant_id) - self.driver.delete_tenant(ofc_tenant_id) - self._del_ofc_item(context, "ofc_tenant", tenant_id) - - def create_ofc_network(self, context, tenant_id, network_id, - network_name=None): - ofc_tenant_id = self._get_ofc_id(context, "ofc_tenant", tenant_id) - desc = "ID=%s Name=%s at Neutron." % (network_id, network_name) - ofc_net_id = self.driver.create_network(ofc_tenant_id, desc, - network_id) - self._add_ofc_item(context, "ofc_network", network_id, ofc_net_id) - - def exists_ofc_network(self, context, network_id): - return self._exists_ofc_item(context, "ofc_network", network_id) - - def delete_ofc_network(self, context, network_id, network): - ofc_net_id = self._get_ofc_id(context, "ofc_network", network_id) - self.driver.delete_network(ofc_net_id) - self._del_ofc_item(context, "ofc_network", network_id) - - def create_ofc_port(self, context, port_id, port): - ofc_net_id = self._get_ofc_id(context, "ofc_network", - port['network_id']) - portinfo = ndb.get_portinfo(context.session, port_id) - if not portinfo: - raise nexc.PortInfoNotFound(id=port_id) - - # Associate packet filters - filters = self.plugin.get_packet_filters_for_port(context, port) - if filters is not None: - params = {'filters': filters} - else: - params = {} - - ofc_port_id = self.driver.create_port(ofc_net_id, portinfo, port_id, - **params) - self._add_ofc_item(context, "ofc_port", port_id, ofc_port_id) - - def exists_ofc_port(self, context, port_id): - return self._exists_ofc_item(context, "ofc_port", port_id) - - def delete_ofc_port(self, context, port_id, port): - ofc_port_id = self._get_ofc_id(context, "ofc_port", port_id) - self.driver.delete_port(ofc_port_id) - self._del_ofc_item(context, "ofc_port", port_id) - - def create_ofc_packet_filter(self, context, filter_id, filter_dict): - ofc_pf_id = self.driver.create_filter(context, filter_dict, filter_id) - self._add_ofc_item(context, "ofc_packet_filter", filter_id, ofc_pf_id) - - def update_ofc_packet_filter(self, context, filter_id, filter_dict): - ofc_pf_id = self._get_ofc_id(context, "ofc_packet_filter", filter_id) - self.driver.update_filter(ofc_pf_id, filter_dict) - - def exists_ofc_packet_filter(self, context, filter_id): - return self._exists_ofc_item(context, "ofc_packet_filter", filter_id) - - def delete_ofc_packet_filter(self, context, filter_id): - ofc_pf_id = self._get_ofc_id(context, "ofc_packet_filter", filter_id) - self.driver.delete_filter(ofc_pf_id) - self._del_ofc_item(context, "ofc_packet_filter", filter_id) - - def create_ofc_router(self, context, tenant_id, router_id, name=None): - ofc_tenant_id = self._get_ofc_id(context, "ofc_tenant", tenant_id) - desc = "ID=%s Name=%s at Neutron." % (router_id, name) - ofc_router_id = self.driver.create_router(ofc_tenant_id, router_id, - desc) - self._add_ofc_item(context, "ofc_router", router_id, ofc_router_id) - - def exists_ofc_router(self, context, router_id): - return self._exists_ofc_item(context, "ofc_router", router_id) - - def delete_ofc_router(self, context, router_id, router): - ofc_router_id = self._get_ofc_id(context, "ofc_router", router_id) - self.driver.delete_router(ofc_router_id) - self._del_ofc_item(context, "ofc_router", router_id) - - def add_ofc_router_interface(self, context, router_id, port_id, port): - # port must have the following fields: - # network_id, cidr, ip_address, mac_address - ofc_router_id = self._get_ofc_id(context, "ofc_router", router_id) - ofc_net_id = self._get_ofc_id(context, "ofc_network", - port['network_id']) - ip_address = '%s/%s' % (port['ip_address'], - netaddr.IPNetwork(port['cidr']).prefixlen) - mac_address = port['mac_address'] - ofc_inf_id = self.driver.add_router_interface( - ofc_router_id, ofc_net_id, ip_address, mac_address) - # Use port mapping table to maintain an interface of OFC router - self._add_ofc_item(context, "ofc_port", port_id, ofc_inf_id) - - def delete_ofc_router_interface(self, context, router_id, port_id): - # Use port mapping table to maintain an interface of OFC router - ofc_inf_id = self._get_ofc_id(context, "ofc_port", port_id) - self.driver.delete_router_interface(ofc_inf_id) - self._del_ofc_item(context, "ofc_port", port_id) - - def update_ofc_router_route(self, context, router_id, new_routes): - ofc_router_id = self._get_ofc_id(context, "ofc_router", router_id) - ofc_routes = self.driver.list_router_routes(ofc_router_id) - route_dict = {} - cur_routes = [] - for r in ofc_routes: - key = ','.join((r['destination'], r['nexthop'])) - route_dict[key] = r['id'] - del r['id'] - cur_routes.append(r) - added, removed = utils.diff_list_of_dict(cur_routes, new_routes) - for r in removed: - key = ','.join((r['destination'], r['nexthop'])) - route_id = route_dict[key] - self.driver.delete_router_route(route_id) - for r in added: - self.driver.add_router_route(ofc_router_id, r['destination'], - r['nexthop']) diff --git a/neutron/plugins/nec/packet_filter.py b/neutron/plugins/nec/packet_filter.py deleted file mode 100644 index 87a94a5b9..000000000 --- a/neutron/plugins/nec/packet_filter.py +++ /dev/null @@ -1,255 +0,0 @@ -# Copyright 2012-2013 NEC Corporation. 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 oslo_utils import excutils - -from neutron.i18n import _LE -from neutron.openstack.common import log as logging -from neutron.plugins.nec.common import config -from neutron.plugins.nec.common import exceptions as nexc -from neutron.plugins.nec.db import packetfilter as pf_db - - -LOG = logging.getLogger(__name__) - - -class PacketFilterMixin(pf_db.PacketFilterDbMixin): - """Mixin class to add packet filter to NECPluginV2.""" - - @property - def packet_filter_enabled(self): - if not hasattr(self, '_packet_filter_enabled'): - self._packet_filter_enabled = ( - config.OFC.enable_packet_filter and - self.ofc.driver.filter_supported()) - return self._packet_filter_enabled - - def remove_packet_filter_extension_if_disabled(self, aliases): - if not self.packet_filter_enabled: - LOG.debug('Disabled packet-filter extension.') - aliases.remove('packet-filter') - - def create_packet_filter(self, context, packet_filter): - """Create a new packet_filter entry on DB, then try to activate it.""" - LOG.debug("create_packet_filter() called, packet_filter=%s .", - packet_filter) - - if hasattr(self.ofc.driver, 'validate_filter_create'): - pf = packet_filter['packet_filter'] - self.ofc.driver.validate_filter_create(context, pf) - pf = super(PacketFilterMixin, self).create_packet_filter( - context, packet_filter) - - return self.activate_packet_filter_if_ready(context, pf) - - def update_packet_filter(self, context, id, packet_filter): - """Update packet_filter entry on DB, and recreate it if changed. - - If any rule of the packet_filter was changed, recreate it on OFC. - """ - LOG.debug("update_packet_filter() called, " - "id=%(id)s packet_filter=%(packet_filter)s .", - {'id': id, 'packet_filter': packet_filter}) - - pf_data = packet_filter['packet_filter'] - if hasattr(self.ofc.driver, 'validate_filter_update'): - self.ofc.driver.validate_filter_update(context, pf_data) - - # validate ownership - pf_old = self.get_packet_filter(context, id) - - pf = super(PacketFilterMixin, self).update_packet_filter( - context, id, packet_filter) - - def _packet_filter_changed(old_pf, new_pf): - LOG.debug('old_pf=%(old_pf)s, new_pf=%(new_pf)s', - {'old_pf': old_pf, 'new_pf': new_pf}) - # When the status is ERROR, force sync to OFC. - if old_pf['status'] == pf_db.PF_STATUS_ERROR: - LOG.debug('update_packet_filter: Force filter update ' - 'because the previous status is ERROR.') - return True - for key in new_pf: - if key in ('id', 'name', 'tenant_id', 'network_id', - 'in_port', 'status'): - continue - if old_pf[key] != new_pf[key]: - return True - return False - - if _packet_filter_changed(pf_old, pf): - if hasattr(self.ofc.driver, 'update_filter'): - # admin_state is changed - if pf_old['admin_state_up'] != pf['admin_state_up']: - LOG.debug('update_packet_filter: admin_state ' - 'is changed to %s', pf['admin_state_up']) - if pf['admin_state_up']: - self.activate_packet_filter_if_ready(context, pf) - else: - self.deactivate_packet_filter(context, pf) - elif pf['admin_state_up']: - LOG.debug('update_packet_filter: admin_state is ' - 'unchanged (True)') - if self.ofc.exists_ofc_packet_filter(context, id): - pf = self._update_packet_filter(context, pf, pf_data) - else: - pf = self.activate_packet_filter_if_ready(context, pf) - else: - LOG.debug('update_packet_filter: admin_state is unchanged ' - '(False). No need to update OFC filter.') - else: - pf = self.deactivate_packet_filter(context, pf) - pf = self.activate_packet_filter_if_ready(context, pf) - - return pf - - def _update_packet_filter(self, context, new_pf, pf_data): - pf_id = new_pf['id'] - prev_status = new_pf['status'] - try: - # If previous status is ERROR, try to sync all attributes. - pf = new_pf if prev_status == pf_db.PF_STATUS_ERROR else pf_data - self.ofc.update_ofc_packet_filter(context, pf_id, pf) - new_status = pf_db.PF_STATUS_ACTIVE - if new_status != prev_status: - self._update_resource_status(context, "packet_filter", - pf_id, new_status) - new_pf['status'] = new_status - return new_pf - except Exception as exc: - with excutils.save_and_reraise_exception(): - if (isinstance(exc, nexc.OFCException) or - isinstance(exc, nexc.OFCConsistencyBroken)): - LOG.error(_LE("Failed to create packet_filter id=%(id)s " - "on OFC: %(exc)s"), - {'id': pf_id, 'exc': exc}) - new_status = pf_db.PF_STATUS_ERROR - if new_status != prev_status: - self._update_resource_status(context, "packet_filter", - pf_id, new_status) - - def delete_packet_filter(self, context, id): - """Deactivate and delete packet_filter.""" - LOG.debug("delete_packet_filter() called, id=%s .", id) - - # validate ownership - pf = self.get_packet_filter(context, id) - - # deactivate_packet_filter() raises an exception - # if an error occurs during processing. - pf = self.deactivate_packet_filter(context, pf) - - super(PacketFilterMixin, self).delete_packet_filter(context, id) - - def activate_packet_filter_if_ready(self, context, packet_filter): - """Activate packet_filter by creating filter on OFC if ready. - - Conditions to create packet_filter on OFC are: - * packet_filter admin_state is UP - * (if 'in_port' is specified) portinfo is available - """ - LOG.debug("activate_packet_filter_if_ready() called, " - "packet_filter=%s.", packet_filter) - - pf_id = packet_filter['id'] - current = packet_filter['status'] - - pf_status = current - if not packet_filter['admin_state_up']: - LOG.debug("activate_packet_filter_if_ready(): skip pf_id=%s, " - "packet_filter.admin_state_up is False.", pf_id) - elif self.ofc.exists_ofc_packet_filter(context, packet_filter['id']): - LOG.debug("_activate_packet_filter_if_ready(): skip, " - "ofc_packet_filter already exists.") - else: - LOG.debug("activate_packet_filter_if_ready(): create " - "packet_filter id=%s on OFC.", pf_id) - try: - self.ofc.create_ofc_packet_filter(context, pf_id, - packet_filter) - pf_status = pf_db.PF_STATUS_ACTIVE - except nexc.PortInfoNotFound: - LOG.debug("Skipped to create a packet filter pf_id=%s " - "on OFC, no portinfo for the in_port.", pf_id) - except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: - LOG.error(_LE("Failed to create packet_filter id=%(id)s on " - "OFC: %(exc)s"), {'id': pf_id, 'exc': exc}) - pf_status = pf_db.PF_STATUS_ERROR - - if pf_status != current: - self._update_resource_status(context, "packet_filter", pf_id, - pf_status) - packet_filter.update({'status': pf_status}) - - return packet_filter - - def deactivate_packet_filter(self, context, packet_filter): - """Deactivate packet_filter by deleting filter from OFC if exixts.""" - LOG.debug("deactivate_packet_filter_if_ready() called, " - "packet_filter=%s.", packet_filter) - pf_id = packet_filter['id'] - - if not self.ofc.exists_ofc_packet_filter(context, pf_id): - LOG.debug("deactivate_packet_filter(): skip, " - "Not found OFC Mapping for packet_filter id=%s.", - pf_id) - return packet_filter - - LOG.debug("deactivate_packet_filter(): " - "deleting packet_filter id=%s from OFC.", pf_id) - try: - self.ofc.delete_ofc_packet_filter(context, pf_id) - self._update_resource_status_if_changed( - context, "packet_filter", packet_filter, pf_db.PF_STATUS_DOWN) - return packet_filter - except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("Failed to delete packet_filter id=%(id)s " - "from OFC: %(exc)s"), - {'id': pf_id, 'exc': exc}) - self._update_resource_status_if_changed( - context, "packet_filter", packet_filter, - pf_db.PF_STATUS_ERROR) - - def activate_packet_filters_by_port(self, context, port_id): - if not self.packet_filter_enabled: - return - - filters = {'in_port': [port_id], 'admin_state_up': [True], - 'status': [pf_db.PF_STATUS_DOWN]} - pfs = self.get_packet_filters(context, filters=filters) - for pf in pfs: - self.activate_packet_filter_if_ready(context, pf) - - def deactivate_packet_filters_by_port(self, context, port_id, - raise_exc=True): - if not self.packet_filter_enabled: - return - - filters = {'in_port': [port_id], 'status': [pf_db.PF_STATUS_ACTIVE]} - pfs = self.get_packet_filters(context, filters=filters) - error = False - for pf in pfs: - try: - self.deactivate_packet_filter(context, pf) - except (nexc.OFCException, nexc.OFCMappingNotFound): - error = True - if raise_exc and error: - raise nexc.OFCException(_('Error occurred while disabling packet ' - 'filter(s) for port %s'), port_id) - - def get_packet_filters_for_port(self, context, port): - if self.packet_filter_enabled: - return super(PacketFilterMixin, - self).get_packet_filters_for_port(context, port) diff --git a/neutron/plugins/nec/requirements.txt b/neutron/plugins/nec/requirements.txt new file mode 100644 index 000000000..fafd1a9c4 --- /dev/null +++ b/neutron/plugins/nec/requirements.txt @@ -0,0 +1 @@ +networking-nec>=2015.1,<2015.2 diff --git a/neutron/plugins/nec/router_drivers.py b/neutron/plugins/nec/router_drivers.py deleted file mode 100644 index 70458c888..000000000 --- a/neutron/plugins/nec/router_drivers.py +++ /dev/null @@ -1,221 +0,0 @@ -# Copyright 2013 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import abc -import httplib - -from oslo_utils import excutils -import six - -from neutron.common import constants -from neutron.common import log as call_log -from neutron.common import utils -from neutron.i18n import _LE, _LW -from neutron.openstack.common import log as logging -from neutron.plugins.nec.common import constants as nconst -from neutron.plugins.nec.common import exceptions as nexc - -LOG = logging.getLogger(__name__) - -PROVIDER_OPENFLOW = nconst.ROUTER_PROVIDER_OPENFLOW - - -@six.add_metaclass(abc.ABCMeta) -class RouterDriverBase(object): - - def __init__(self, plugin, ofc_manager): - self.plugin = plugin - self.ofc = ofc_manager - - def floating_ip_support(self): - return True - - @abc.abstractmethod - def create_router(self, context, tenant_id, router): - pass - - @abc.abstractmethod - def update_router(self, context, router_id, old_router, new_router): - pass - - @abc.abstractmethod - def delete_router(self, context, router_id, router): - pass - - @abc.abstractmethod - def add_interface(self, context, router_id, port): - pass - - @abc.abstractmethod - def delete_interface(self, context, router_id, port): - pass - - -class RouterL3AgentDriver(RouterDriverBase): - - need_gw_info = False - - @call_log.log - def create_router(self, context, tenant_id, router): - return router - - @call_log.log - def update_router(self, context, router_id, old_router, new_router): - return new_router - - @call_log.log - def delete_router(self, context, router_id, router): - pass - - @call_log.log - def add_interface(self, context, router_id, port): - return self.plugin.activate_port_if_ready(context, port) - - @call_log.log - def delete_interface(self, context, router_id, port): - return self.plugin.deactivate_port(context, port) - - -class RouterOpenFlowDriver(RouterDriverBase): - - need_gw_info = True - - def floating_ip_support(self): - return self.ofc.driver.router_nat_supported - - def _process_gw_port(self, gw_info, routes): - if gw_info and gw_info['gateway_ip']: - routes.append({'destination': constants.IPv4_ANY, - 'nexthop': gw_info['gateway_ip']}) - - @call_log.log - def create_router(self, context, tenant_id, router): - try: - router_id = router['id'] - added_routes = [] - self.ofc.ensure_ofc_tenant(context, tenant_id) - self.ofc.create_ofc_router(context, tenant_id, router_id, - router['name']) - self._process_gw_port(router['gw_port'], added_routes) - if added_routes: - self.ofc.update_ofc_router_route(context, router_id, - added_routes, []) - new_status = nconst.ROUTER_STATUS_ACTIVE - self.plugin._update_resource_status(context, "router", - router['id'], - new_status) - router['status'] = new_status - return router - except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: - with excutils.save_and_reraise_exception(): - if (isinstance(exc, nexc.OFCException) and - exc.status == httplib.CONFLICT): - raise nexc.RouterOverLimit(provider=PROVIDER_OPENFLOW) - LOG.error(_LE("create_router() failed due to %s"), exc) - new_status = nconst.ROUTER_STATUS_ERROR - self._update_resource_status(context, "router", - router['id'], - new_status) - - @call_log.log - def update_router(self, context, router_id, old_router, new_router): - old_routes = old_router['routes'][:] - new_routes = new_router['routes'][:] - self._process_gw_port(old_router['gw_port'], old_routes) - self._process_gw_port(new_router['gw_port'], new_routes) - added, removed = utils.diff_list_of_dict(old_routes, new_routes) - if added or removed: - try: - # NOTE(amotoki): PFC supports one-by-one route update at now. - # It means there may be a case where some route is updated but - # some not. To allow the next call of failures to sync routes - # with Neutron side, we pass the whole new routes here. - # PFC should support atomic route update in the future. - self.ofc.update_ofc_router_route(context, router_id, - new_routes) - new_status = nconst.ROUTER_STATUS_ACTIVE - self.plugin._update_resource_status( - context, "router", router_id, new_status) - new_router['status'] = new_status - except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("_update_ofc_routes() failed due to %s"), - exc) - new_status = nconst.ROUTER_STATUS_ERROR - self.plugin._update_resource_status( - context, "router", router_id, new_status) - return new_router - - @call_log.log - def delete_router(self, context, router_id, router): - if not self.ofc.exists_ofc_router(context, router_id): - return - try: - self.ofc.delete_ofc_router(context, router_id, router) - except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("delete_router() failed due to %s"), exc) - self.plugin._update_resource_status( - context, "router", router_id, nconst.ROUTER_STATUS_ERROR) - - @call_log.log - def add_interface(self, context, router_id, port): - port_id = port['id'] - # port['fixed_ips'] may be empty if ext_net has no subnet. - # Such port is invalid for a router port and we don't create a port - # on OFC. The port is removed in l3_db._create_router_gw_port. - if not port['fixed_ips']: - LOG.warning(_LW('RouterOpenFlowDriver.add_interface(): the ' - 'requested port ' - 'has no subnet. add_interface() is skipped. ' - 'router_id=%(id)s, port=%(port)s)'), - {'id': router_id, 'port': port}) - return port - fixed_ip = port['fixed_ips'][0] - subnet = self.plugin._get_subnet(context, fixed_ip['subnet_id']) - port_info = {'network_id': port['network_id'], - 'ip_address': fixed_ip['ip_address'], - 'cidr': subnet['cidr'], - 'mac_address': port['mac_address']} - try: - self.ofc.add_ofc_router_interface(context, router_id, - port_id, port_info) - new_status = nconst.ROUTER_STATUS_ACTIVE - self.plugin._update_resource_status( - context, "port", port_id, new_status) - return port - except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("add_router_interface() failed due to %s"), exc) - new_status = nconst.ROUTER_STATUS_ERROR - self.plugin._update_resource_status( - context, "port", port_id, new_status) - - @call_log.log - def delete_interface(self, context, router_id, port): - port_id = port['id'] - try: - self.ofc.delete_ofc_router_interface(context, router_id, port_id) - new_status = nconst.ROUTER_STATUS_ACTIVE - self.plugin._update_resource_status(context, "port", port_id, - new_status) - port['status'] = new_status - return port - except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("delete_router_interface() failed due to %s"), - exc) - new_status = nconst.ROUTER_STATUS_ERROR - self.plugin._update_resource_status(context, "port", port_id, - new_status) diff --git a/neutron/tests/unit/nec/__init__.py b/neutron/tests/unit/nec/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron/tests/unit/nec/fake_ofc_manager.py b/neutron/tests/unit/nec/fake_ofc_manager.py deleted file mode 100644 index d64b11d03..000000000 --- a/neutron/tests/unit/nec/fake_ofc_manager.py +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import mock - - -OFC_MANAGER = 'neutron.plugins.nec.nec_plugin.ofc_manager.OFCManager' - - -def patch_ofc_manager(): - m = mock.patch(OFC_MANAGER).start() - f = FakeOFCManager() - - m.create_ofc_tenant.side_effect = f.create_ofc_tenant - m.delete_ofc_tenant.side_effect = f.delete_ofc_tenant - m.exists_ofc_tenant.side_effect = f.exists_ofc_tenant - m.create_ofc_network.side_effect = f.create_ofc_net - m.delete_ofc_network.side_effect = f.delete_ofc_net - m.exists_ofc_network.side_effect = f.exists_ofc_net - m.create_ofc_port.side_effect = f.create_ofc_port - m.delete_ofc_port.side_effect = f.delete_ofc_port - m.exists_ofc_port.side_effect = f.exists_ofc_port - m.create_ofc_packet_filter.side_effect = f.create_ofc_pf - m.delete_ofc_packet_filter.side_effect = f.delete_ofc_pf - m.exists_ofc_packet_filter.side_effect = f.exists_ofc_pf - m.set_raise_exc = f.set_raise_exc - - return m - - -class FakeOFCManager(object): - - def __init__(self): - self.ofc_tenants = {} - self.ofc_nets = {} - self.ofc_ports = {} - self.ofc_pfs = {} - self.raise_exc_map = {} - - def set_raise_exc(self, func, raise_exc): - self.raise_exc_map.update({func: raise_exc}) - - def _raise_exc(self, func): - exc = self.raise_exc_map.get(func) - if exc: - raise exc - - def create_ofc_tenant(self, context, tenant_id): - self._raise_exc('create_ofc_tenant') - self.ofc_tenants.update({tenant_id: True}) - - def exists_ofc_tenant(self, context, tenant_id): - self._raise_exc('exists_ofc_tenant') - return self.ofc_tenants.get(tenant_id, False) - - def delete_ofc_tenant(self, context, tenant_id): - self._raise_exc('delete_ofc_tenant') - del self.ofc_tenants[tenant_id] - - def create_ofc_net(self, context, tenant_id, net_id, net_name=None): - self._raise_exc('create_ofc_network') - self.ofc_nets.update({net_id: True}) - - def exists_ofc_net(self, context, net_id): - self._raise_exc('exists_ofc_network') - return self.ofc_nets.get(net_id, False) - - def delete_ofc_net(self, context, net_id, net): - self._raise_exc('delete_ofc_network') - del self.ofc_nets[net_id] - - def create_ofc_port(self, context, port_id, port): - self._raise_exc('create_ofc_port') - self.ofc_ports.update({port_id: True}) - - def exists_ofc_port(self, context, port_id): - self._raise_exc('exists_ofc_port') - return self.ofc_ports.get(port_id, False) - - def delete_ofc_port(self, context, port_id, port): - self._raise_exc('delete_ofc_port') - del self.ofc_ports[port_id] - - def create_ofc_pf(self, context, pf_id, pf_dict): - self._raise_exc('create_ofc_packet_filter') - self.ofc_pfs.update({pf_id: True}) - - def exists_ofc_pf(self, context, pf_id): - self._raise_exc('exists_ofc_packet_filter') - return self.ofc_pfs.get(pf_id, False) - - def delete_ofc_pf(self, context, pf_id): - self._raise_exc('delete_ofc_packet_filter') - del self.ofc_pfs[pf_id] diff --git a/neutron/tests/unit/nec/stub_ofc_driver.py b/neutron/tests/unit/nec/stub_ofc_driver.py deleted file mode 100644 index fc611bd89..000000000 --- a/neutron/tests/unit/nec/stub_ofc_driver.py +++ /dev/null @@ -1,289 +0,0 @@ -# Copyright 2012 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import netaddr - -from neutron.common import log as call_log -from neutron.openstack.common import log as logging -from neutron.openstack.common import uuidutils -from neutron.plugins.nec.common import exceptions as nexc -from neutron.plugins.nec import ofc_driver_base - - -LOG = logging.getLogger(__name__) - -MAX_NUM_OPENFLOW_ROUTER = 2 - - -class StubOFCDriver(ofc_driver_base.OFCDriverBase): - """Stub OFC driver for testing. - - This driver can be used not only for unit tests but also for real testing - as a logging driver. It stores the created resources on OFC and returns - them in get methods(). - - If autocheck is enabled, it checks whether the specified resource exists - in OFC and raises an exception if it is different from expected status. - """ - - def __init__(self, conf): - self.autocheck = False - self.reset_all() - - def reset_all(self): - self.ofc_tenant_dict = {} - self.ofc_network_dict = {} - self.ofc_port_dict = {} - self.ofc_filter_dict = {} - self.ofc_router_dict = {} - self.ofc_router_inf_dict = {} - self.ofc_router_route_dict = {} - - def enable_autocheck(self): - self.autocheck = True - - def disable_autocheck(self): - self.autocheck = False - - @call_log.log - def create_tenant(self, description, tenant_id=None): - ofc_id = "ofc-" + tenant_id[:-4] - if self.autocheck: - if ofc_id in self.ofc_tenant_dict: - raise Exception(_('(create_tenant) OFC tenant %s ' - 'already exists') % ofc_id) - self.ofc_tenant_dict[ofc_id] = {'tenant_id': tenant_id, - 'description': description} - return ofc_id - - @call_log.log - def delete_tenant(self, ofc_tenant_id): - if ofc_tenant_id in self.ofc_tenant_dict: - del self.ofc_tenant_dict[ofc_tenant_id] - else: - if self.autocheck: - raise Exception(_('(delete_tenant) OFC tenant %s not found') - % ofc_tenant_id) - LOG.debug('delete_tenant: SUCCEED') - - @call_log.log - def create_network(self, ofc_tenant_id, description, network_id=None): - ofc_id = "ofc-" + network_id[:-4] - if self.autocheck: - if ofc_tenant_id not in self.ofc_tenant_dict: - raise Exception(_('(create_network) OFC tenant %s not found') - % ofc_tenant_id) - if ofc_id in self.ofc_network_dict: - raise Exception(_('(create_network) OFC network %s ' - 'already exists') % ofc_id) - self.ofc_network_dict[ofc_id] = {'tenant_id': ofc_tenant_id, - 'network_id': network_id, - 'description': description} - return ofc_id - - @call_log.log - def update_network(self, ofc_network_id, description): - if self.autocheck: - if ofc_network_id not in self.ofc_network_dict: - raise Exception(_('(update_network) OFC network %s not found') - % ofc_network_id) - data = {'description': description} - self.ofc_network_dict[ofc_network_id].update(data) - LOG.debug('update_network: SUCCEED') - - @call_log.log - def delete_network(self, ofc_network_id): - if ofc_network_id in self.ofc_network_dict: - del self.ofc_network_dict[ofc_network_id] - else: - if self.autocheck: - raise Exception(_('(delete_network) OFC network %s not found') - % ofc_network_id) - LOG.debug('delete_network: SUCCEED') - - @call_log.log - def create_port(self, ofc_network_id, info, port_id=None, filters=None): - ofc_id = "ofc-" + port_id[:-4] - if self.autocheck: - if ofc_network_id not in self.ofc_network_dict: - raise Exception(_('(create_port) OFC network %s not found') - % ofc_network_id) - if ofc_id in self.ofc_port_dict: - raise Exception(_('(create_port) OFC port %s already exists') - % ofc_id) - self.ofc_port_dict[ofc_id] = {'network_id': ofc_network_id, - 'port_id': port_id} - if filters: - self.ofc_port_dict[ofc_id]['filters'] = filters - return ofc_id - - @call_log.log - def delete_port(self, ofc_port_id): - if ofc_port_id in self.ofc_port_dict: - del self.ofc_port_dict[ofc_port_id] - else: - if self.autocheck: - raise Exception(_('(delete_port) OFC port %s not found') - % ofc_port_id) - LOG.debug('delete_port: SUCCEED') - - @classmethod - def filter_supported(cls): - return True - - def create_filter(self, context, filter_dict, filter_id=None): - return "ofc-" + filter_id[:-4] - - def delete_filter(self, ofc_filter_id): - pass - - def convert_ofc_tenant_id(self, context, ofc_tenant_id): - return ofc_tenant_id - - def convert_ofc_network_id(self, context, ofc_network_id, tenant_id): - return ofc_network_id - - def convert_ofc_port_id(self, context, ofc_port_id, tenant_id, network_id): - return ofc_port_id - - def convert_ofc_filter_id(self, context, ofc_filter_id): - return ofc_filter_id - - router_supported = True - router_nat_supported = True - - @call_log.log - def create_router(self, ofc_tenant_id, router_id, description): - ofc_id = "ofc-" + router_id[:-4] - if self.autocheck: - if ofc_tenant_id not in self.ofc_tenant_dict: - raise Exception(_('(create_router) OFC tenant %s not found') - % ofc_tenant_id) - if ofc_id in self.ofc_router_dict: - raise Exception(_('(create_router) OFC router %s ' - 'already exists') % ofc_id) - if len(self.ofc_router_dict) >= MAX_NUM_OPENFLOW_ROUTER: - params = {'reason': _("Operation on OFC is failed"), - 'status': 409} - raise nexc.OFCException(**params) - self.ofc_router_dict[ofc_id] = {'tenant_id': ofc_tenant_id, - 'router_id': router_id, - 'description': description} - return ofc_id - - @call_log.log - def delete_router(self, ofc_router_id): - if ofc_router_id in self.ofc_router_dict: - del self.ofc_router_dict[ofc_router_id] - else: - if self.autocheck: - raise Exception(_('(delete_router) OFC router %s not found') - % ofc_router_id) - LOG.debug('delete_router: SUCCEED') - - @call_log.log - def add_router_interface(self, ofc_router_id, ofc_net_id, - ip_address=None, mac_address=None): - if_id = "ofc-" + uuidutils.generate_uuid()[:-4] - # IP address should have a format of a.b.c.d/N - if ip_address != str(netaddr.IPNetwork(ip_address)): - raise Exception(_('(add_router_interface) ' - 'ip_address %s is not a valid format (a.b.c.d/N).') - % ip_address) - if self.autocheck: - if ofc_router_id not in self.ofc_router_dict: - raise Exception(_('(add_router_interface) ' - 'OFC router %s not found') % ofc_router_id) - if ofc_net_id not in self.ofc_network_dict: - raise Exception(_('(add_router_interface) ' - 'OFC network %s not found') % ofc_net_id) - # Check duplicate destination - self.ofc_router_inf_dict[if_id] = {'router_id': ofc_router_id, - 'network_id': ofc_net_id, - 'ip_address': ip_address, - 'mac_address': mac_address} - LOG.debug('add_router_interface: SUCCEED (if_id=%s)', if_id) - return if_id - - @call_log.log - def update_router_interface(self, ofc_router_inf_id, - ip_address=None, mac_address=None): - if ofc_router_inf_id not in self.ofc_router_inf_dict: - if self.autocheck: - raise Exception(_('(delete_router_interface) ' - 'OFC router interface %s not found') - % ofc_router_inf_id) - self.ofc_router_inf_dict[ofc_router_inf_id] = {} - inf = self.ofc_router_inf_dict[ofc_router_inf_id] - if ip_address: - inf.update({'ip_address': ip_address}) - if mac_address: - inf.update({'mac_address': mac_address}) - LOG.debug('update_router_route: SUCCEED') - - @call_log.log - def delete_router_interface(self, ofc_router_inf_id): - if ofc_router_inf_id in self.ofc_router_inf_dict: - del self.ofc_router_inf_dict[ofc_router_inf_id] - else: - if self.autocheck: - raise Exception(_('(delete_router_interface) ' - 'OFC router interface %s not found') - % ofc_router_inf_id) - LOG.debug('delete_router_interface: SUCCEED') - - @call_log.log - def add_router_route(self, ofc_router_id, destination, nexthop): - route_id = "ofc-" + uuidutils.generate_uuid()[:-4] - # IP address format check - netaddr.IPNetwork(destination) - netaddr.IPAddress(nexthop) - if self.autocheck: - if ofc_router_id not in self.ofc_router_dict: - raise Exception(_('(add_router_route) OFC router %s not found') - % ofc_router_id) - # Check duplicate destination - if destination in [route['destination'] for route in - self.ofc_router_route_dict.values()]: - raise Exception(_('(add_router_route) ' - 'route to "%s" already exists') % destination) - self.ofc_router_route_dict[route_id] = {'router_id': ofc_router_id, - 'destination': destination, - 'nexthop': nexthop} - LOG.debug('add_router_route: SUCCEED (route_id=%s)', route_id) - return route_id - - @call_log.log - def delete_router_route(self, ofc_router_route_id): - if ofc_router_route_id in self.ofc_router_route_dict: - del self.ofc_router_route_dict[ofc_router_route_id] - else: - if self.autocheck: - raise Exception(_('(delete_router_route) OFC router route %s ' - 'not found') % ofc_router_route_id) - LOG.debug('delete_router_route: SUCCEED') - - @call_log.log - def list_router_routes(self, ofc_router_id): - if self.autocheck: - if ofc_router_id not in self.ofc_router_dict: - raise Exception(_('(delete_router) OFC router %s not found') - % ofc_router_id) - routes = [{'id': k, - 'destination': v['destination'], - 'nexthop': v['nexthop']} - for k, v in self.ofc_router_route_dict.items() - if v['router_id'] == ofc_router_id] - LOG.debug('list_router_routes: routes=%s', routes) - return routes diff --git a/neutron/tests/unit/nec/test_agent_scheduler.py b/neutron/tests/unit/nec/test_agent_scheduler.py deleted file mode 100644 index 70f4f1e7c..000000000 --- a/neutron/tests/unit/nec/test_agent_scheduler.py +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright 2013 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import contextlib - -from neutron.api.rpc.handlers import l3_rpc -from neutron.common import constants -from neutron.tests.unit.nec import test_nec_plugin -from neutron.tests.unit.openvswitch import test_agent_scheduler - -L3_HOSTA = test_agent_scheduler.L3_HOSTA -L3_HOSTB = test_agent_scheduler.L3_HOSTB - - -class NecAgentSchedulerTestCase( - test_agent_scheduler.OvsAgentSchedulerTestCase, - test_nec_plugin.NecPluginV2TestCaseBase): - - plugin_str = test_nec_plugin.PLUGIN_NAME - l3_plugin = None - - def setUp(self): - self.setup_nec_plugin_base() - super(NecAgentSchedulerTestCase, self).setUp() - - -class NecDhcpAgentNotifierTestCase( - test_agent_scheduler.OvsDhcpAgentNotifierTestCase, - test_nec_plugin.NecPluginV2TestCaseBase): - - plugin_str = test_nec_plugin.PLUGIN_NAME - l3_plugin = None - - def setUp(self): - self.setup_nec_plugin_base() - super(NecDhcpAgentNotifierTestCase, self).setUp() - - -class NecL3AgentNotifierTestCase( - test_agent_scheduler.OvsL3AgentNotifierTestCase, - test_nec_plugin.NecPluginV2TestCaseBase): - - plugin_str = test_nec_plugin.PLUGIN_NAME - l3_plugin = None - - def setUp(self): - self.setup_nec_plugin_base() - super(NecL3AgentNotifierTestCase, self).setUp() - - -class NecL3AgentSchedulerWithOpenFlowRouter( - test_agent_scheduler.OvsAgentSchedulerTestCaseBase, - test_nec_plugin.NecPluginV2TestCaseBase): - - plugin_str = test_nec_plugin.PLUGIN_NAME - l3_plugin = None - - def setUp(self): - self.setup_nec_plugin_base() - super(NecL3AgentSchedulerWithOpenFlowRouter, self).setUp() - - def test_router_auto_schedule_with_l3agent_and_openflow(self): - with contextlib.nested( - self.router(), - self.router(arg_list=('provider',), - provider='openflow' - )) as (r1, r2): - l3_rpc_cb = l3_rpc.L3RpcCallback() - self._register_agent_states() - ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA) - ret_b = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTB) - l3_agents = self._list_l3_agents_hosting_router( - r1['router']['id']) - self.assertEqual(1, len(ret_a)) - self.assertFalse(len(ret_b)) - self.assertIn(r1['router']['id'], [r['id'] for r in ret_a]) - self.assertNotIn(r2['router']['id'], [r['id'] for r in ret_a]) - self.assertEqual(1, len(l3_agents['agents'])) - self.assertEqual(L3_HOSTA, l3_agents['agents'][0]['host']) - - def test_router_auto_schedule_only_with_openflow_router(self): - with contextlib.nested( - self.router(arg_list=('provider',), provider='openflow'), - self.router(arg_list=('provider',), provider='openflow') - ) as (r1, r2): - l3_rpc_cb = l3_rpc.L3RpcCallback() - self._register_agent_states() - ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA) - l3_agents_1 = self._list_l3_agents_hosting_router( - r1['router']['id']) - l3_agents_2 = self._list_l3_agents_hosting_router( - r2['router']['id']) - self.assertFalse(len(ret_a)) - self.assertNotIn(r1['router']['id'], [r['id'] for r in ret_a]) - self.assertNotIn(r2['router']['id'], [r['id'] for r in ret_a]) - self.assertFalse(len(l3_agents_1['agents'])) - self.assertFalse(len(l3_agents_2['agents'])) - - def test_add_router_to_l3_agent_for_openflow_router(self): - with self.router(arg_list=('provider',), provider='openflow') as r1: - self._register_agent_states() - hosta_id = self._get_agent_id(constants.AGENT_TYPE_L3, - L3_HOSTA) - self._add_router_to_l3_agent(hosta_id, - r1['router']['id'], - expected_code=409) diff --git a/neutron/tests/unit/nec/test_config.py b/neutron/tests/unit/nec/test_config.py deleted file mode 100644 index 17a672978..000000000 --- a/neutron/tests/unit/nec/test_config.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2012 NEC Corporation. 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.plugins.nec.common import config -from neutron.tests import base - - -class ConfigurationTest(base.BaseTestCase): - - def test_defaults(self): - self.assertEqual('br-int', config.CONF.OVS.integration_bridge) - self.assertEqual(2, config.CONF.AGENT.polling_interval) - - self.assertEqual('127.0.0.1', config.CONF.OFC.host) - self.assertEqual('8888', config.CONF.OFC.port) - # Check path_prefix is an empty string explicitly. - self.assertEqual('', config.CONF.OFC.path_prefix) - self.assertEqual('trema', config.CONF.OFC.driver) - self.assertTrue(config.CONF.OFC.enable_packet_filter) - self.assertTrue(config.CONF.OFC.support_packet_filter_on_ofc_router) - self.assertFalse(config.CONF.OFC.use_ssl) - self.assertIsNone(config.CONF.OFC.key_file) - self.assertIsNone(config.CONF.OFC.cert_file) - - def test_shortcuts(self): - self.assertEqual(config.CONF.OVS.integration_bridge, - config.OVS.integration_bridge) - self.assertEqual(config.CONF.AGENT.polling_interval, - config.AGENT.polling_interval) - self.assertEqual(config.CONF.OFC.host, config.OFC.host) diff --git a/neutron/tests/unit/nec/test_db.py b/neutron/tests/unit/nec/test_db.py deleted file mode 100644 index 8f6414212..000000000 --- a/neutron/tests/unit/nec/test_db.py +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright 2012 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import contextlib -import random - -from neutron.common import constants as q_const -from neutron.openstack.common import uuidutils -from neutron.plugins.nec.common import exceptions as nexc -from neutron.plugins.nec.db import api as ndb -from neutron.tests.unit.nec import test_nec_plugin - - -class NECPluginV2DBTestBase(test_nec_plugin.NecPluginV2TestCase): - """Class conisting of NECPluginV2 DB unit tests.""" - - def setUp(self): - """Setup for tests.""" - super(NECPluginV2DBTestBase, self).setUp() - self.session = self.context.session - - def get_ofc_item_random_params(self): - """create random parameters for ofc_item test.""" - ofc_id = uuidutils.generate_uuid() - neutron_id = uuidutils.generate_uuid() - none = uuidutils.generate_uuid() - return ofc_id, neutron_id, none - - @contextlib.contextmanager - def portinfo_random_params(self): - with self.port() as port: - params = {'port_id': port['port']['id'], - 'datapath_id': hex(random.randint(0, 0xffffffff)), - 'port_no': random.randint(1, 100), - 'vlan_id': random.randint(q_const.MIN_VLAN_TAG, - q_const.MAX_VLAN_TAG), - 'mac': ':'.join(["%02x" % random.randint(0, 0xff) - for x in range(6)]) - } - yield params - - -class NECPluginV2DBOfcMappingTest(NECPluginV2DBTestBase): - - def test_add_ofc_item(self): - """test add OFC item.""" - o, q, n = self.get_ofc_item_random_params() - tenant = ndb.add_ofc_item(self.session, 'ofc_tenant', q, o) - self.assertEqual(tenant.ofc_id, o) - self.assertEqual(tenant.neutron_id, q) - - def test_add_ofc_item_duplicate_entry(self): - o, q, n = self.get_ofc_item_random_params() - ndb.add_ofc_item(self.session, 'ofc_tenant', q, o) - self.assertRaises(nexc.NECDBException, - ndb.add_ofc_item, - self.session, 'ofc_tenant', q, o) - - def test_get_ofc_item(self): - o, q, n = self.get_ofc_item_random_params() - ndb.add_ofc_item(self.session, 'ofc_tenant', q, o) - tenant = ndb.get_ofc_item(self.session, 'ofc_tenant', q) - self.assertEqual(tenant.ofc_id, o) - self.assertEqual(tenant.neutron_id, q) - - def test_get_ofc_item_for_nonexisting_entry(self): - self.assertIsNone( - ndb.get_ofc_item(self.session, 'ofc_tenant', 'non-exist-id')) - - def test_get_ofc_id(self): - o, q, n = self.get_ofc_item_random_params() - ndb.add_ofc_item(self.session, 'ofc_tenant', q, o) - tenant_id = ndb.get_ofc_id(self.session, 'ofc_tenant', q) - self.assertEqual(tenant_id, o) - - def test_get_ofc_id_for_nonexisting_entry(self): - self.assertRaises(nexc.OFCMappingNotFound, - ndb.get_ofc_id, - self.session, 'ofc_tenant', 'non-exist-id') - - def test_exists_ofc_item(self): - o, q, n = self.get_ofc_item_random_params() - self.assertFalse(ndb.exists_ofc_item(self.session, 'ofc_tenant', q)) - - ndb.add_ofc_item(self.session, 'ofc_tenant', q, o) - self.assertTrue(ndb.exists_ofc_item(self.session, 'ofc_tenant', q)) - - ndb.del_ofc_item(self.session, 'ofc_tenant', q) - self.assertFalse(ndb.exists_ofc_item(self.session, 'ofc_tenant', q)) - - def test_find_ofc_item(self): - o, q, n = self.get_ofc_item_random_params() - ndb.add_ofc_item(self.session, 'ofc_tenant', q, o) - tenant = ndb.find_ofc_item(self.session, 'ofc_tenant', o) - self.assertEqual(tenant.ofc_id, o) - self.assertEqual(tenant.neutron_id, q) - - def test_find_ofc_item_for_nonexisting_entry(self): - self.assertIsNone( - ndb.find_ofc_item(self.session, 'ofc_tenant', 'non-existi-id')) - - def test_del_ofc_item(self): - o, q, n = self.get_ofc_item_random_params() - ndb.add_ofc_item(self.session, 'ofc_tenant', q, o) - self.assertTrue(ndb.del_ofc_item(self.session, 'ofc_tenant', q)) - - self.assertIsNone(ndb.get_ofc_item(self.session, 'ofc_tenant', q)) - self.assertIsNone(ndb.find_ofc_item(self.session, 'ofc_tenant', o)) - - def test_del_ofc_item_for_nonexisting_entry(self): - self.assertFalse( - ndb.del_ofc_item(self.session, 'ofc_tenant', 'non-existi-id')) - - -class NECPluginV2DBPortInfoTest(NECPluginV2DBTestBase): - - def _compare_portinfo(self, portinfo, expected): - self.assertEqual(portinfo.id, expected['port_id']) - self.assertEqual(portinfo.datapath_id, expected['datapath_id']) - self.assertEqual(portinfo.port_no, expected['port_no']) - self.assertEqual(portinfo.vlan_id, expected['vlan_id']) - self.assertEqual(portinfo.mac, expected['mac']) - - def _add_portinfo(self, session, params): - return ndb.add_portinfo(session, params['port_id'], - params['datapath_id'], params['port_no'], - params['vlan_id'], params['mac']) - - def testd_add_portinfo(self): - """test add portinfo.""" - with self.portinfo_random_params() as params: - portinfo = self._add_portinfo(self.session, params) - self._compare_portinfo(portinfo, params) - - exception_raised = False - try: - self._add_portinfo(self.session, params) - except nexc.NECDBException: - exception_raised = True - self.assertTrue(exception_raised) - - def teste_get_portinfo(self): - """test get portinfo.""" - with self.portinfo_random_params() as params: - self._add_portinfo(self.session, params) - portinfo = ndb.get_portinfo(self.session, params['port_id']) - self._compare_portinfo(portinfo, params) - - nonexist_id = uuidutils.generate_uuid() - portinfo_none = ndb.get_portinfo(self.session, nonexist_id) - self.assertIsNone(portinfo_none) - - def testf_del_portinfo(self): - """test delete portinfo.""" - with self.portinfo_random_params() as params: - self._add_portinfo(self.session, params) - portinfo = ndb.get_portinfo(self.session, params['port_id']) - self.assertEqual(portinfo.id, params['port_id']) - ndb.del_portinfo(self.session, params['port_id']) - portinfo_none = ndb.get_portinfo(self.session, params['port_id']) - self.assertIsNone(portinfo_none) diff --git a/neutron/tests/unit/nec/test_nec_agent.py b/neutron/tests/unit/nec/test_nec_agent.py deleted file mode 100644 index 2b7559cfa..000000000 --- a/neutron/tests/unit/nec/test_nec_agent.py +++ /dev/null @@ -1,345 +0,0 @@ -# Copyright 2013 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import contextlib -import copy -import itertools -import time - -import mock -from oslo_config import cfg -from six import moves -import testtools - -from neutron.agent.linux import ovs_lib -from neutron.extensions import securitygroup as ext_sg -from neutron.plugins.nec.agent import nec_neutron_agent -from neutron.tests import base - -DAEMON_LOOP_COUNT = 10 -OVS_DPID = '00000629355b6943' -OVS_DPID_0X = '0x' + OVS_DPID - - -class TestNecAgentBase(base.BaseTestCase): - - def setUp(self): - super(TestNecAgentBase, self).setUp() - cfg.CONF.set_default('firewall_driver', - 'neutron.agent.firewall.NoopFirewallDriver', - group='SECURITYGROUP') - cfg.CONF.set_override('host', 'dummy-host') - with contextlib.nested( - mock.patch.object(ovs_lib.OVSBridge, 'get_datapath_id', - return_value=OVS_DPID), - mock.patch('socket.gethostname', return_value='dummy-host'), - mock.patch('neutron.openstack.common.loopingcall.' - 'FixedIntervalLoopingCall'), - mock.patch('neutron.agent.rpc.PluginReportStateAPI') - ) as (get_datapath_id, gethostname, - loopingcall, state_rpc_api): - kwargs = {'integ_br': 'integ_br', 'polling_interval': 1} - self.agent = nec_neutron_agent.NECNeutronAgent(**kwargs) - self.loopingcall = loopingcall - self.state_rpc_api = state_rpc_api - - -class TestNecAgent(TestNecAgentBase): - - def _setup_mock(self): - vif_ports = [ovs_lib.VifPort('port1', '1', 'id-1', 'mac-1', - self.agent.int_br), - ovs_lib.VifPort('port2', '2', 'id-2', 'mac-2', - self.agent.int_br)] - self.get_vif_ports = mock.patch.object( - ovs_lib.OVSBridge, 'get_vif_ports', - return_value=vif_ports).start() - self.update_ports = mock.patch.object( - nec_neutron_agent.NECPluginApi, 'update_ports').start() - self.prepare_devices_filter = mock.patch.object( - self.agent.sg_agent, 'prepare_devices_filter').start() - self.remove_devices_filter = mock.patch.object( - self.agent.sg_agent, 'remove_devices_filter').start() - - def _test_single_loop(self, with_exc=False, need_sync=False): - self.agent.cur_ports = ['id-0', 'id-1'] - self.agent.need_sync = need_sync - - self.agent.loop_handler() - if with_exc: - self.assertEqual(self.agent.cur_ports, ['id-0', 'id-1']) - self.assertTrue(self.agent.need_sync) - else: - self.assertEqual(self.agent.cur_ports, ['id-1', 'id-2']) - self.assertFalse(self.agent.need_sync) - - def test_single_loop_normal(self): - self._setup_mock() - self._test_single_loop() - agent_id = 'nec-q-agent.dummy-host' - self.update_ports.assert_called_once_with( - mock.ANY, agent_id, OVS_DPID_0X, - [{'id': 'id-2', 'mac': 'mac-2', 'port_no': '2'}], - ['id-0']) - self.prepare_devices_filter.assert_called_once_with(['id-2']) - self.remove_devices_filter.assert_called_once_with(['id-0']) - - def test_single_loop_need_sync(self): - self._setup_mock() - self._test_single_loop(need_sync=True) - agent_id = 'nec-q-agent.dummy-host' - self.update_ports.assert_called_once_with( - mock.ANY, agent_id, OVS_DPID_0X, - [{'id': 'id-1', 'mac': 'mac-1', 'port_no': '1'}, - {'id': 'id-2', 'mac': 'mac-2', 'port_no': '2'}], - []) - self.prepare_devices_filter.assert_called_once_with(['id-1', 'id-2']) - self.assertFalse(self.remove_devices_filter.call_count) - - def test_single_loop_with_sg_exception_remove(self): - self._setup_mock() - self.update_ports.side_effect = Exception() - self._test_single_loop(with_exc=True) - - def test_single_loop_with_sg_exception_prepare(self): - self._setup_mock() - self.prepare_devices_filter.side_effect = Exception() - self._test_single_loop(with_exc=True) - - def test_single_loop_with_update_ports_exception(self): - self._setup_mock() - self.remove_devices_filter.side_effect = Exception() - self._test_single_loop(with_exc=True) - - def test_daemon_loop(self): - - def state_check(index): - self.assertEqual(len(self.vif_ports_scenario[index]), - len(self.agent.cur_ports)) - - # Fake time.sleep to stop the infinite loop in daemon_loop() - self.sleep_count = 0 - - def sleep_mock(*args, **kwargs): - state_check(self.sleep_count) - self.sleep_count += 1 - if self.sleep_count >= DAEMON_LOOP_COUNT: - raise RuntimeError() - - vif_ports = [ovs_lib.VifPort('port1', '1', 'id-1', 'mac-1', - self.agent.int_br), - ovs_lib.VifPort('port2', '2', 'id-2', 'mac-2', - self.agent.int_br)] - - self.vif_ports_scenario = [[], [], vif_ports[0:1], vif_ports[0:2], - vif_ports[1:2], []] - - # Ensure vif_ports_scenario is longer than DAEMON_LOOP_COUNT - if len(self.vif_ports_scenario) < DAEMON_LOOP_COUNT: - self.vif_ports_scenario.extend( - [] for _i in moves.xrange(DAEMON_LOOP_COUNT - - len(self.vif_ports_scenario))) - - with contextlib.nested( - mock.patch.object(time, 'sleep', side_effect=sleep_mock), - mock.patch.object(ovs_lib.OVSBridge, 'get_vif_ports'), - mock.patch.object(nec_neutron_agent.NECPluginApi, 'update_ports'), - mock.patch.object(self.agent.sg_agent, 'prepare_devices_filter'), - mock.patch.object(self.agent.sg_agent, 'remove_devices_filter') - ) as (sleep, get_vif_potrs, update_ports, - prepare_devices_filter, remove_devices_filter): - get_vif_potrs.side_effect = self.vif_ports_scenario - - with testtools.ExpectedException(RuntimeError): - self.agent.daemon_loop() - self.assertEqual(update_ports.call_count, 4) - self.assertEqual(sleep.call_count, DAEMON_LOOP_COUNT) - - agent_id = 'nec-q-agent.dummy-host' - expected = [ - mock.call(mock.ANY, agent_id, OVS_DPID_0X, - [{'id': 'id-1', 'mac': 'mac-1', 'port_no': '1'}], - []), - mock.call(mock.ANY, agent_id, OVS_DPID_0X, - [{'id': 'id-2', 'mac': 'mac-2', 'port_no': '2'}], - []), - mock.call(mock.ANY, agent_id, OVS_DPID_0X, - [], ['id-1']), - mock.call(mock.ANY, agent_id, OVS_DPID_0X, - [], ['id-2']) - ] - update_ports.assert_has_calls(expected) - - expected = [mock.call(['id-1']), - mock.call(['id-2'])] - self.assertEqual(prepare_devices_filter.call_count, 2) - prepare_devices_filter.assert_has_calls(expected) - self.assertEqual(remove_devices_filter.call_count, 2) - remove_devices_filter.assert_has_calls(expected) - - sleep.assert_called_with(self.agent.polling_interval) - - def test_report_state_installed(self): - self.loopingcall.assert_called_once_with(self.agent._report_state) - instance = self.loopingcall.return_value - self.assertTrue(instance.start.called) - - def _check_report_state(self, cur_ports, num_ports, fail_mode, - first=False): - self.assertEqual(first or fail_mode, - 'start_flag' in self.agent.agent_state) - self.agent.cur_ports = cur_ports - - self.agent._report_state() - - self.assertEqual(fail_mode, - 'start_flag' in self.agent.agent_state) - self.assertEqual(self.agent. - agent_state['configurations']['devices'], - num_ports) - self.num_ports_hist.append(num_ports) - - def _test_report_state(self, fail_mode): - log_mocked = mock.patch.object(nec_neutron_agent, 'LOG') - log_patched = log_mocked.start() - - def record_state(*args, **kwargs): - self.record_calls.append(copy.deepcopy(args)) - if fail_mode: - raise Exception() - - self.record_calls = [] - self.num_ports_hist = [] - state_rpc = self.state_rpc_api.return_value - state_rpc.report_state.side_effect = record_state - dummy_vif = ovs_lib.VifPort('port1', '1', 'id-1', 'mac-1', None) - - self.state_rpc_api.assert_called_once_with('q-plugin') - self.assertIn('start_flag', self.agent.agent_state) - - self._check_report_state([], 0, fail_mode, first=True) - self._check_report_state([dummy_vif] * 2, 2, fail_mode) - self._check_report_state([dummy_vif] * 5, 5, fail_mode) - self._check_report_state([], 0, fail_mode) - - # Since loopingcall start is mocked, call_count is same as - # the call count of check_report_state. - self.assertEqual(state_rpc.report_state.call_count, 4) - self.assertEqual(len(self.record_calls), 4) - - for i, x in enumerate(itertools.izip(self.record_calls, - self.num_ports_hist)): - rec, num_ports = x - expected_state = { - 'binary': 'neutron-nec-agent', - 'host': 'dummy-host', - 'topic': 'N/A', - 'configurations': {'devices': 0}, - 'agent_type': 'NEC plugin agent'} - expected_state['configurations']['devices'] = num_ports - if i == 0 or fail_mode: - expected_state['start_flag'] = True - self.assertEqual(expected_state, rec[1]) - - self.assertEqual(fail_mode, log_patched.exception.called) - - def test_report_state(self): - self._test_report_state(fail_mode=False) - - def test_report_state_fail(self): - self._test_report_state(fail_mode=True) - - -class TestNecAgentCallback(TestNecAgentBase): - - def test_port_update(self): - with contextlib.nested( - mock.patch.object(ovs_lib.OVSBridge, 'get_vif_port_by_id'), - mock.patch.object(self.agent.sg_agent, 'refresh_firewall') - ) as (get_vif_port_by_id, refresh_firewall): - context = mock.Mock() - vifport = ovs_lib.VifPort('port1', '1', 'id-1', 'mac-1', - self.agent.int_br) - - # The OVS port does not exist. - get_vif_port_by_id.return_value = None - port = {'id': 'update-port-1'} - self.agent.callback_nec.port_update(context, port=port) - self.assertEqual(get_vif_port_by_id.call_count, 1) - self.assertFalse(refresh_firewall.call_count) - - # The OVS port exists but no security group is associated. - get_vif_port_by_id.return_value = vifport - port = {'id': 'update-port-1'} - self.agent.callback_nec.port_update(context, port=port) - self.assertEqual(get_vif_port_by_id.call_count, 2) - self.assertFalse(refresh_firewall.call_count) - - # The OVS port exists but a security group is associated. - get_vif_port_by_id.return_value = vifport - port = {'id': 'update-port-1', - ext_sg.SECURITYGROUPS: ['default']} - self.agent.callback_nec.port_update(context, port=port) - self.assertEqual(get_vif_port_by_id.call_count, 3) - self.assertEqual(refresh_firewall.call_count, 1) - - get_vif_port_by_id.return_value = None - port = {'id': 'update-port-1', - ext_sg.SECURITYGROUPS: ['default']} - self.agent.callback_nec.port_update(context, port=port) - self.assertEqual(get_vif_port_by_id.call_count, 4) - self.assertEqual(refresh_firewall.call_count, 1) - - -class TestNecAgentPluginApi(TestNecAgentBase): - - def test_plugin_api(self): - with contextlib.nested( - mock.patch.object(self.agent.plugin_rpc.client, 'prepare'), - mock.patch.object(self.agent.plugin_rpc.client, 'call'), - ) as (mock_prepare, mock_call): - mock_prepare.return_value = self.agent.plugin_rpc.client - - agent_id = 'nec-q-agent.dummy-host' - port_added = [{'id': 'id-1', 'mac': 'mac-1', 'port_no': '1'}, - {'id': 'id-2', 'mac': 'mac-2', 'port_no': '2'}] - port_removed = ['id-3', 'id-4', 'id-5'] - - self.agent.plugin_rpc.update_ports( - mock.sentinel.ctx, agent_id, OVS_DPID_0X, - port_added, port_removed) - - mock_call.assert_called_once_with( - mock.sentinel.ctx, 'update_ports', - agent_id=agent_id, datapath_id=OVS_DPID_0X, - port_added=port_added, port_removed=port_removed) - - -class TestNecAgentMain(base.BaseTestCase): - def test_main(self): - with contextlib.nested( - mock.patch.object(nec_neutron_agent, 'NECNeutronAgent'), - mock.patch.object(nec_neutron_agent, 'common_config'), - mock.patch.object(nec_neutron_agent, 'config') - ) as (agent, common_config, cfg): - cfg.OVS.integration_bridge = 'br-int-x' - cfg.AGENT.polling_interval = 10 - - nec_neutron_agent.main() - - self.assertTrue(common_config.setup_logging.called) - agent.assert_has_calls([ - mock.call('br-int-x', 10), - mock.call().daemon_loop() - ]) diff --git a/neutron/tests/unit/nec/test_nec_plugin.py b/neutron/tests/unit/nec/test_nec_plugin.py deleted file mode 100644 index 907af0485..000000000 --- a/neutron/tests/unit/nec/test_nec_plugin.py +++ /dev/null @@ -1,941 +0,0 @@ -# Copyright (c) 2012 OpenStack Foundation. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import mock -import webob.exc - -from neutron.common import constants -from neutron.common import test_lib -from neutron.common import topics -from neutron import context -from neutron.db import db_base_plugin_v2 -from neutron import manager -from neutron.plugins.nec.common import exceptions as nexc -from neutron.plugins.nec.db import api as ndb -from neutron.plugins.nec import nec_plugin -from neutron.tests.unit.nec import fake_ofc_manager -from neutron.tests.unit import test_db_plugin as test_plugin -from neutron.tests.unit import test_extension_allowedaddresspairs as test_pair - - -PLUGIN_NAME = 'neutron.plugins.nec.nec_plugin.NECPluginV2' -OFC_MANAGER = 'neutron.plugins.nec.nec_plugin.ofc_manager.OFCManager' -NOTIFIER = 'neutron.plugins.nec.nec_plugin.NECPluginV2AgentNotifierApi' -NEC_PLUGIN_INI = """ -[DEFAULT] -api_extensions_path = neutron/plugins/nec/extensions -[OFC] -driver = neutron.tests.unit.nec.stub_ofc_driver.StubOFCDriver -enable_packet_filter = False -""" - - -class NecPluginV2TestCaseBase(object): - _nec_ini = NEC_PLUGIN_INI - - def _set_nec_ini(self): - self.nec_ini_file = self.get_temp_file_path('nec.ini') - with open(self.nec_ini_file, 'w') as f: - f.write(self._nec_ini) - if 'config_files' in test_lib.test_config.keys(): - for c in test_lib.test_config['config_files']: - if c.rfind("/nec.ini") > -1: - test_lib.test_config['config_files'].remove(c) - test_lib.test_config['config_files'].append(self.nec_ini_file) - else: - test_lib.test_config['config_files'] = [self.nec_ini_file] - self.addCleanup(self._clean_nec_ini) - - def _clean_nec_ini(self): - test_lib.test_config['config_files'].remove(self.nec_ini_file) - self.nec_ini_file = None - - def patch_remote_calls(self): - self.plugin_notifier_p = mock.patch(NOTIFIER) - self.ofc_manager_p = mock.patch(OFC_MANAGER) - self.plugin_notifier_p.start() - self.ofc_manager_p.start() - - def setup_nec_plugin_base(self): - self._set_nec_ini() - self.patch_remote_calls() - - -class NecPluginV2TestCase(NecPluginV2TestCaseBase, - test_plugin.NeutronDbPluginV2TestCase): - - _plugin_name = PLUGIN_NAME - - def rpcapi_update_ports(self, agent_id='nec-q-agent.fake', - datapath_id="0xabc", added=[], removed=[]): - kwargs = {'topic': topics.AGENT, - 'agent_id': agent_id, - 'datapath_id': datapath_id, - 'port_added': added, 'port_removed': removed} - self.callback_nec.update_ports(self.context, **kwargs) - - def setUp(self, plugin=None, ext_mgr=None): - - self._set_nec_ini() - plugin = plugin or self._plugin_name - super(NecPluginV2TestCase, self).setUp(plugin, ext_mgr=ext_mgr) - - self.plugin = manager.NeutronManager.get_plugin() - self.plugin.ofc = fake_ofc_manager.patch_ofc_manager() - self.ofc = self.plugin.ofc - self.callback_nec = nec_plugin.NECPluginV2RPCCallbacks(self.plugin) - self.context = context.get_admin_context() - self.net_create_status = 'ACTIVE' - self.port_create_status = 'DOWN' - - -class TestNecBasicGet(test_plugin.TestBasicGet, NecPluginV2TestCase): - pass - - -class TestNecV2HTTPResponse(test_plugin.TestV2HTTPResponse, - NecPluginV2TestCase): - pass - - -class TestNecNetworksV2(test_plugin.TestNetworksV2, NecPluginV2TestCase): - pass - - -class TestNecPortsV2Callback(NecPluginV2TestCase): - - def _get_portinfo(self, port_id): - return ndb.get_portinfo(self.context.session, port_id) - - def test_portinfo_create(self): - with self.port() as port: - port_id = port['port']['id'] - sport = self.plugin.get_port(self.context, port_id) - self.assertEqual(sport['status'], 'DOWN') - self.assertEqual(self.ofc.create_ofc_port.call_count, 0) - self.assertIsNone(self._get_portinfo(port_id)) - - portinfo = {'id': port_id, 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - - sport = self.plugin.get_port(self.context, port_id) - self.assertEqual(sport['status'], 'ACTIVE') - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertIsNotNone(self._get_portinfo(port_id)) - - expected = [ - mock.call.exists_ofc_port(mock.ANY, port_id), - mock.call.create_ofc_port(mock.ANY, port_id, mock.ANY), - ] - self.ofc.assert_has_calls(expected) - - def test_portinfo_delete_before_port_deletion(self): - self._test_portinfo_delete() - - def test_portinfo_delete_after_port_deletion(self): - self._test_portinfo_delete(portinfo_delete_first=False) - - def _test_portinfo_delete(self, portinfo_delete_first=True): - with self.port() as port: - port_id = port['port']['id'] - portinfo = {'id': port_id, 'port_no': 456} - self.assertEqual(self.ofc.create_ofc_port.call_count, 0) - self.assertIsNone(self._get_portinfo(port_id)) - - self.rpcapi_update_ports(added=[portinfo]) - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 0) - self.assertIsNotNone(self._get_portinfo(port_id)) - - # Before port-deletion, switch port removed message is sent. - if portinfo_delete_first: - self.rpcapi_update_ports(removed=[port_id]) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 1) - self.assertIsNone(self._get_portinfo(port_id)) - self._delete('ports', port['port']['id']) - - # The port and portinfo is expected to delete when exiting with-clause. - self.assertEqual(self.ofc.delete_ofc_port.call_count, 1) - self.assertIsNone(self._get_portinfo(port_id)) - if not portinfo_delete_first: - self.rpcapi_update_ports(removed=[port_id]) - - # Ensure port deletion is called once. - self.assertEqual(self.ofc.delete_ofc_port.call_count, 1) - self.assertIsNone(self._get_portinfo(port_id)) - - expected = [ - mock.call.exists_ofc_port(mock.ANY, port_id), - mock.call.create_ofc_port(mock.ANY, port_id, mock.ANY), - mock.call.exists_ofc_port(mock.ANY, port_id), - mock.call.delete_ofc_port(mock.ANY, port_id, mock.ANY), - ] - self.ofc.assert_has_calls(expected) - - def test_portinfo_added_unknown_port(self): - portinfo = {'id': 'dummy-p1', 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - self.assertIsNone(ndb.get_portinfo(self.context.session, - 'dummy-p1')) - self.assertEqual(self.ofc.exists_ofc_port.call_count, 0) - self.assertEqual(self.ofc.create_ofc_port.call_count, 0) - - def _test_portinfo_change(self, portinfo_change_first=True): - with self.port() as port: - port_id = port['port']['id'] - self.assertEqual(self.ofc.create_ofc_port.call_count, 0) - - portinfo = {'id': port_id, 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 0) - self.assertEqual(ndb.get_portinfo(self.context.session, - port_id).port_no, 123) - - if portinfo_change_first: - portinfo = {'id': port_id, 'port_no': 456} - self.rpcapi_update_ports(added=[portinfo]) - # OFC port is recreated. - self.assertEqual(self.ofc.create_ofc_port.call_count, 2) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 1) - self.assertEqual(ndb.get_portinfo(self.context.session, - port_id).port_no, 456) - self._delete('ports', port['port']['id']) - - if not portinfo_change_first: - # The port is expected to delete when exiting with-clause. - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 1) - - portinfo = {'id': port_id, 'port_no': 456} - self.rpcapi_update_ports(added=[portinfo]) - # No OFC operations are expected. - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 1) - self.assertIsNone(ndb.get_portinfo(self.context.session, port_id)) - - def test_portinfo_change(self): - self._test_portinfo_change() - - def test_portinfo_change_for_nonexisting_port(self): - self._test_portinfo_change(portinfo_change_first=False) - - def test_port_migration(self): - agent_id_a, datapath_id_a, port_no_a = 'nec-q-agent.aa', '0xaaa', 10 - agent_id_b, datapath_id_b, port_no_b = 'nec-q-agent.bb', '0xbbb', 11 - - with self.port() as port: - port_id = port['port']['id'] - sport = self.plugin.get_port(self.context, port_id) - self.assertEqual(sport['status'], 'DOWN') - - portinfo_a = {'id': port_id, 'port_no': port_no_a} - self.rpcapi_update_ports(agent_id=agent_id_a, - datapath_id=datapath_id_a, - added=[portinfo_a]) - - portinfo_b = {'id': port_id, 'port_no': port_no_b} - self.rpcapi_update_ports(agent_id=agent_id_b, - datapath_id=datapath_id_b, - added=[portinfo_b]) - - self.rpcapi_update_ports(agent_id=agent_id_a, - datapath_id=datapath_id_a, - removed=[port_id]) - - sport = self.plugin.get_port(self.context, port_id) - self.assertEqual(sport['status'], 'ACTIVE') - self.assertTrue(self.ofc.ofc_ports[port_id]) - - expected = [ - mock.call.exists_ofc_port(mock.ANY, port_id), - mock.call.create_ofc_port(mock.ANY, port_id, mock.ANY), - mock.call.exists_ofc_port(mock.ANY, port_id), - mock.call.delete_ofc_port(mock.ANY, port_id, mock.ANY), - mock.call.exists_ofc_port(mock.ANY, port_id), - mock.call.create_ofc_port(mock.ANY, port_id, mock.ANY), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(2, self.ofc.create_ofc_port.call_count) - self.assertEqual(1, self.ofc.delete_ofc_port.call_count) - - def test_portinfo_readd(self): - with self.port() as port: - port_id = port['port']['id'] - self.plugin.get_port(self.context, port_id) - - portinfo = {'id': port_id, 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - - sport = self.plugin.get_port(self.context, port_id) - self.assertEqual(sport['status'], 'ACTIVE') - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 0) - self.assertIsNotNone(self._get_portinfo(port_id)) - - portinfo = {'id': port_id, 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - - sport = self.plugin.get_port(self.context, port_id) - self.assertEqual(sport['status'], 'ACTIVE') - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 0) - self.assertIsNotNone(self._get_portinfo(port_id)) - - -class TestNecPluginDbTest(NecPluginV2TestCase): - - def test_update_resource(self): - with self.network() as network: - self.assertEqual("ACTIVE", network['network']['status']) - net_id = network['network']['id'] - for status in ["DOWN", "BUILD", "ERROR", "ACTIVE"]: - self.plugin._update_resource_status( - self.context, 'network', net_id, - getattr(constants, 'NET_STATUS_%s' % status)) - n = self.plugin._get_network(self.context, net_id) - self.assertEqual(status, n.status) - - -class TestNecPluginOfcManager(NecPluginV2TestCase): - def setUp(self): - super(TestNecPluginOfcManager, self).setUp() - self.ofc = self.plugin.ofc - - def _create_resource(self, resource, data): - collection = resource + 's' - data = {resource: data} - req = self.new_create_request(collection, data) - res = self.deserialize(self.fmt, req.get_response(self.api)) - return res[resource] - - def _update_resource(self, resource, id, data): - collection = resource + 's' - data = {resource: data} - req = self.new_update_request(collection, data, id) - res = self.deserialize(self.fmt, req.get_response(self.api)) - return res[resource] - - def _show_resource(self, resource, id): - collection = resource + 's' - req = self.new_show_request(collection, id) - res = self.deserialize(self.fmt, req.get_response(self.api)) - return res[resource] - - def _list_resource(self, resource): - collection = resource + 's' - req = self.new_list_request(collection) - res = req.get_response(self.api) - return res[collection] - - def _delete_resource(self, resource, id): - collection = resource + 's' - req = self.new_delete_request(collection, id) - res = req.get_response(self.api) - return res.status_int - - def test_create_network(self): - net = None - ctx = mock.ANY - with self.network() as network: - net = network['network'] - self.assertEqual(network['network']['status'], 'ACTIVE') - self._delete('networks', network['network']['id']) - - expected = [ - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_network(ctx, self._tenant_id, net['id'], - net['name']), - mock.call.exists_ofc_network(ctx, net['id']), - mock.call.delete_ofc_network(ctx, net['id'], mock.ANY), - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.delete_ofc_tenant(ctx, self._tenant_id) - ] - self.ofc.assert_has_calls(expected) - - def test_create_network_with_admin_state_down(self): - net = None - ctx = mock.ANY - with self.network(admin_state_up=False) as network: - net = network['network'] - self.assertEqual(network['network']['status'], 'DOWN') - self._delete('networks', network['network']['id']) - - expected = [ - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_network(ctx, self._tenant_id, net['id'], - net['name']), - mock.call.exists_ofc_network(ctx, net['id']), - mock.call.delete_ofc_network(ctx, net['id'], mock.ANY), - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.delete_ofc_tenant(ctx, self._tenant_id) - ] - self.ofc.assert_has_calls(expected) - - def test_create_two_network(self): - nets = [] - ctx = mock.ANY - with self.network() as net1: - nets.append(net1['network']) - self.assertEqual(net1['network']['status'], 'ACTIVE') - with self.network() as net2: - nets.append(net2['network']) - self.assertEqual(net2['network']['status'], 'ACTIVE') - self._delete('networks', net2['network']['id']) - self._delete('networks', net1['network']['id']) - expected = [ - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_network(ctx, self._tenant_id, nets[0]['id'], - nets[0]['name']), - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_network(ctx, self._tenant_id, nets[1]['id'], - nets[1]['name']), - mock.call.exists_ofc_network(ctx, nets[1]['id']), - mock.call.delete_ofc_network(ctx, nets[1]['id'], mock.ANY), - mock.call.exists_ofc_network(ctx, nets[0]['id']), - mock.call.delete_ofc_network(ctx, nets[0]['id'], mock.ANY), - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.delete_ofc_tenant(ctx, self._tenant_id) - ] - self.ofc.assert_has_calls(expected) - - def test_create_network_fail(self): - self.ofc.create_ofc_network.side_effect = nexc.OFCException( - reason='hoge') - - net = None - ctx = mock.ANY - # NOTE: We don't delete network through api, but db will be cleaned in - # tearDown(). When OFCManager has failed to create a network on OFC, - # it does not keeps ofc_network entry and will fail to delete this - # network from OFC. Deletion of network is not the scope of this test. - with self.network() as network: - net = network['network'] - self.assertEqual(net['status'], 'ERROR') - net_ref = self._show('networks', net['id']) - self.assertEqual(net_ref['network']['status'], 'ERROR') - - expected = [ - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_network(ctx, self._tenant_id, net['id'], - net['name']) - ] - self.ofc.assert_has_calls(expected) - - def test_update_network(self): - net = None - ctx = mock.ANY - with self.network() as network: - net = network['network'] - self.assertEqual(network['network']['status'], 'ACTIVE') - - net_ref = self._show('networks', net['id']) - self.assertEqual(net_ref['network']['status'], 'ACTIVE') - - # Set admin_state_up to False - res = self._update_resource('network', net['id'], - {'admin_state_up': False}) - self.assertFalse(res['admin_state_up']) - self.assertEqual(res['status'], 'DOWN') - - net_ref = self._show('networks', net['id']) - self.assertEqual(net_ref['network']['status'], 'DOWN') - - # Set admin_state_up to True - res = self._update_resource('network', net['id'], - {'admin_state_up': True}) - self.assertTrue(res['admin_state_up']) - self.assertEqual(res['status'], 'ACTIVE') - - net_ref = self._show('networks', net['id']) - self.assertEqual(net_ref['network']['status'], 'ACTIVE') - self._delete('networks', network['network']['id']) - - expected = [ - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_network(ctx, self._tenant_id, net['id'], - net['name']), - mock.call.exists_ofc_network(ctx, net['id']), - mock.call.delete_ofc_network(ctx, net['id'], mock.ANY), - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.delete_ofc_tenant(ctx, self._tenant_id) - ] - self.ofc.assert_has_calls(expected) - - def test_create_port_no_ofc_creation(self): - net = None - p1 = None - ctx = mock.ANY - with self.subnet() as subnet: - with self.port(subnet=subnet) as port: - p1 = port['port'] - net_id = port['port']['network_id'] - net = self._show_resource('network', net_id) - self.assertEqual(net['status'], 'ACTIVE') - self.assertEqual(p1['status'], 'DOWN') - - p1_ref = self._show('ports', p1['id']) - self.assertEqual(p1_ref['port']['status'], 'DOWN') - self._delete('ports', port['port']['id']) - self._delete('networks', port['port']['network_id']) - expected = [ - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_network(ctx, self._tenant_id, net['id'], - net['name']), - - mock.call.exists_ofc_port(ctx, p1['id']), - mock.call.exists_ofc_network(ctx, net['id']), - mock.call.delete_ofc_network(ctx, net['id'], mock.ANY), - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.delete_ofc_tenant(ctx, self._tenant_id) - ] - self.ofc.assert_has_calls(expected) - - def test_create_port_with_ofc_creation(self): - net = None - p1 = None - ctx = mock.ANY - with self.subnet() as subnet: - with self.port(subnet=subnet) as port: - p1 = port['port'] - net_id = port['port']['network_id'] - net = self._show_resource('network', net_id) - self.assertEqual(net['status'], 'ACTIVE') - self.assertEqual(p1['status'], 'DOWN') - - p1_ref = self._show('ports', p1['id']) - self.assertEqual(p1_ref['port']['status'], 'DOWN') - - # Check the port is not created on OFC - self.assertFalse(self.ofc.create_ofc_port.call_count) - - # Register portinfo, then the port is created on OFC - portinfo = {'id': p1['id'], 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - - p1_ref = self._show('ports', p1['id']) - self.assertEqual(p1_ref['port']['status'], 'ACTIVE') - self._delete('ports', port['port']['id']) - self._delete('networks', port['port']['network_id']) - - expected = [ - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_network(ctx, self._tenant_id, net['id'], - net['name']), - - mock.call.exists_ofc_port(ctx, p1['id']), - mock.call.create_ofc_port(ctx, p1['id'], mock.ANY), - - mock.call.exists_ofc_port(ctx, p1['id']), - mock.call.delete_ofc_port(ctx, p1['id'], mock.ANY), - mock.call.exists_ofc_network(ctx, net['id']), - mock.call.delete_ofc_network(ctx, net['id'], mock.ANY), - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.delete_ofc_tenant(ctx, self._tenant_id) - ] - self.ofc.assert_has_calls(expected) - - def test_delete_network_with_dhcp_port(self): - ctx = mock.ANY - with self.network() as network: - with self.subnet(network=network): - net = network['network'] - p = self._create_resource( - 'port', - {'network_id': net['id'], - 'tenant_id': net['tenant_id'], - 'device_owner': constants.DEVICE_OWNER_DHCP, - 'device_id': 'dhcp-port1'}) - # Make sure that the port is created on OFC. - portinfo = {'id': p['id'], 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - # In a case of dhcp port, the port is deleted automatically - # when delete_network. - self._delete('networks', network['network']['id']) - - expected = [ - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_network(ctx, self._tenant_id, - net['id'], net['name']), - mock.call.exists_ofc_port(ctx, p['id']), - mock.call.create_ofc_port(ctx, p['id'], mock.ANY), - mock.call.exists_ofc_port(ctx, p['id']), - mock.call.delete_ofc_port(ctx, p['id'], mock.ANY), - mock.call.exists_ofc_network(ctx, net['id']), - mock.call.delete_ofc_network(ctx, net['id'], mock.ANY), - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.delete_ofc_tenant(ctx, self._tenant_id) - ] - self.ofc.assert_has_calls(expected) - - def test_delete_network_with_error_status(self): - self.ofc.set_raise_exc('create_ofc_network', - nexc.OFCException(reason='fake error')) - - with self.network() as net: - net_id = net['network']['id'] - net_ref = self._show('networks', net_id) - self.assertEqual(net_ref['network']['status'], 'ERROR') - self._delete('networks', net['network']['id']) - ctx = mock.ANY - tenant_id = self._tenant_id - net_name = mock.ANY - net = mock.ANY - expected = [ - mock.call.exists_ofc_tenant(ctx, tenant_id), - mock.call.create_ofc_tenant(ctx, tenant_id), - mock.call.create_ofc_network(ctx, tenant_id, net_id, net_name), - mock.call.exists_ofc_network(ctx, net_id), - mock.call.exists_ofc_tenant(ctx, tenant_id), - mock.call.delete_ofc_tenant(ctx, tenant_id), - ] - self.ofc.assert_has_calls(expected) - self.assertFalse(self.ofc.delete_ofc_network.call_count) - - def test_delete_network_with_ofc_deletion_failure(self): - self.ofc.set_raise_exc('delete_ofc_network', - nexc.OFCException(reason='hoge')) - - with self.network() as net: - net_id = net['network']['id'] - - self._delete('networks', net_id, - expected_code=webob.exc.HTTPInternalServerError.code) - - net_ref = self._show('networks', net_id) - self.assertEqual(net_ref['network']['status'], 'ERROR') - - self.ofc.set_raise_exc('delete_ofc_network', None) - self._delete('networks', net['network']['id']) - - ctx = mock.ANY - tenant = mock.ANY - net_name = mock.ANY - net = mock.ANY - expected = [ - mock.call.create_ofc_network(ctx, tenant, net_id, net_name), - mock.call.exists_ofc_network(ctx, net_id), - mock.call.delete_ofc_network(ctx, net_id, net), - mock.call.exists_ofc_network(ctx, net_id), - mock.call.delete_ofc_network(ctx, net_id, net), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.delete_ofc_network.call_count, 2) - - def test_delete_network_with_deactivating_auto_delete_port_failure(self): - self.ofc.set_raise_exc('delete_ofc_port', - nexc.OFCException(reason='hoge')) - - with self.network() as net: - net_id = net['network']['id'] - - device_owner = db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS[0] - port = self._make_port(self.fmt, net_id, device_owner=device_owner) - port_id = port['port']['id'] - - portinfo = {'id': port_id, 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - - self._delete('networks', net_id, - expected_code=webob.exc.HTTPInternalServerError.code) - - net_ref = self._show('networks', net_id) - self.assertEqual(net_ref['network']['status'], 'ACTIVE') - port_ref = self._show('ports', port_id) - self.assertEqual(port_ref['port']['status'], 'ERROR') - - self.ofc.set_raise_exc('delete_ofc_port', None) - self._delete('networks', net_id) - - ctx = mock.ANY - tenant = mock.ANY - net_name = mock.ANY - net = mock.ANY - port = mock.ANY - expected = [ - mock.call.create_ofc_network(ctx, tenant, net_id, net_name), - mock.call.exists_ofc_port(ctx, port_id), - mock.call.create_ofc_port(ctx, port_id, port), - mock.call.exists_ofc_port(ctx, port_id), - mock.call.delete_ofc_port(ctx, port_id, port), - mock.call.exists_ofc_port(ctx, port_id), - mock.call.delete_ofc_port(ctx, port_id, port), - mock.call.exists_ofc_network(ctx, net_id), - mock.call.delete_ofc_network(ctx, net_id, net) - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.delete_ofc_network.call_count, 1) - - def test_update_port(self): - self._test_update_port_with_admin_state(resource='port') - - def test_update_network_with_ofc_port(self): - self._test_update_port_with_admin_state(resource='network') - - def _test_update_port_with_admin_state(self, resource='port'): - net = None - p1 = None - ctx = mock.ANY - - if resource == 'network': - net_ini_admin_state = False - port_ini_admin_state = True - else: - net_ini_admin_state = True - port_ini_admin_state = False - - with self.network(admin_state_up=net_ini_admin_state) as network: - with self.subnet(network=network) as subnet: - with self.port(subnet=subnet, - admin_state_up=port_ini_admin_state) as port: - p1 = port['port'] - net_id = port['port']['network_id'] - res_id = net_id if resource == 'network' else p1['id'] - self.assertEqual(p1['status'], 'DOWN') - - net = self._show_resource('network', net_id) - - # Check the port is not created on OFC - self.assertFalse(self.ofc.create_ofc_port.call_count) - - # Register portinfo, then the port is created on OFC - portinfo = {'id': p1['id'], 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - self.assertFalse(self.ofc.create_ofc_port.call_count) - - res = self._update_resource(resource, res_id, - {'admin_state_up': True}) - self.assertEqual(res['status'], 'ACTIVE') - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertFalse(self.ofc.delete_ofc_port.call_count) - - res = self._update_resource(resource, res_id, - {'admin_state_up': False}) - self.assertEqual(res['status'], 'DOWN') - self.assertEqual(self.ofc.delete_ofc_port.call_count, 1) - self._delete('ports', port['port']['id']) - self._delete('networks', port['port']['network_id']) - - expected = [ - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_tenant(ctx, self._tenant_id), - mock.call.create_ofc_network(ctx, self._tenant_id, net['id'], - net['name']), - - mock.call.exists_ofc_port(ctx, p1['id']), - mock.call.create_ofc_port(ctx, p1['id'], mock.ANY), - - mock.call.exists_ofc_port(ctx, p1['id']), - mock.call.delete_ofc_port(ctx, p1['id'], mock.ANY), - - mock.call.exists_ofc_port(ctx, p1['id']), - mock.call.exists_ofc_network(ctx, net['id']), - mock.call.delete_ofc_network(ctx, net['id'], mock.ANY), - mock.call.exists_ofc_tenant(ctx, self._tenant_id), - mock.call.delete_ofc_tenant(ctx, self._tenant_id) - ] - self.ofc.assert_has_calls(expected) - - def test_update_port_with_ofc_creation_failure(self): - with self.port(admin_state_up=False) as port: - port_id = port['port']['id'] - portinfo = {'id': port_id, 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - - self.ofc.set_raise_exc('create_ofc_port', - nexc.OFCException(reason='hoge')) - - body = {'port': {'admin_state_up': True}} - res = self._update('ports', port_id, body) - self.assertEqual(res['port']['status'], 'ERROR') - port_ref = self._show('ports', port_id) - self.assertEqual(port_ref['port']['status'], 'ERROR') - - body = {'port': {'admin_state_up': False}} - res = self._update('ports', port_id, body) - self.assertEqual(res['port']['status'], 'ERROR') - port_ref = self._show('ports', port_id) - self.assertEqual(port_ref['port']['status'], 'ERROR') - - self.ofc.set_raise_exc('create_ofc_port', None) - - body = {'port': {'admin_state_up': True}} - res = self._update('ports', port_id, body) - self.assertEqual(res['port']['status'], 'ACTIVE') - port_ref = self._show('ports', port_id) - self.assertEqual(port_ref['port']['status'], 'ACTIVE') - self._delete('ports', port['port']['id']) - ctx = mock.ANY - port = mock.ANY - expected = [ - mock.call.exists_ofc_port(ctx, port_id), - mock.call.create_ofc_port(ctx, port_id, port), - mock.call.exists_ofc_port(ctx, port_id), - mock.call.exists_ofc_port(ctx, port_id), - mock.call.create_ofc_port(ctx, port_id, port), - mock.call.exists_ofc_port(ctx, port_id), - mock.call.delete_ofc_port(ctx, port_id, port), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.create_ofc_port.call_count, 2) - - def test_update_port_with_ofc_deletion_failure(self): - with self.port() as port: - port_id = port['port']['id'] - portinfo = {'id': port_id, 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - - self.ofc.set_raise_exc('delete_ofc_port', - nexc.OFCException(reason='hoge')) - - body = {'port': {'admin_state_up': False}} - self._update('ports', port_id, body, - expected_code=webob.exc.HTTPInternalServerError.code) - port_ref = self._show('ports', port_id) - self.assertEqual(port_ref['port']['status'], 'ERROR') - - body = {'port': {'admin_state_up': True}} - res = self._update('ports', port_id, body) - self.assertEqual(res['port']['status'], 'ERROR') - port_ref = self._show('ports', port_id) - self.assertEqual(port_ref['port']['status'], 'ERROR') - - self.ofc.set_raise_exc('delete_ofc_port', None) - - body = {'port': {'admin_state_up': False}} - res = self._update('ports', port_id, body) - self.assertEqual(res['port']['status'], 'DOWN') - port_ref = self._show('ports', port_id) - self.assertEqual(port_ref['port']['status'], 'DOWN') - self._delete('ports', port['port']['id']) - - ctx = mock.ANY - port = mock.ANY - expected = [ - mock.call.exists_ofc_port(ctx, port_id), - mock.call.create_ofc_port(ctx, port_id, port), - mock.call.exists_ofc_port(ctx, port_id), - mock.call.delete_ofc_port(ctx, port_id, port), - mock.call.exists_ofc_port(ctx, port_id), - mock.call.exists_ofc_port(ctx, port_id), - mock.call.delete_ofc_port(ctx, port_id, port), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 2) - - def test_delete_port_with_error_status(self): - self.ofc.set_raise_exc('create_ofc_port', - nexc.OFCException(reason='fake')) - - with self.port() as port: - port_id = port['port']['id'] - portinfo = {'id': port_id, 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - port_ref = self._show('ports', port_id) - self.assertEqual(port_ref['port']['status'], 'ERROR') - self._delete('ports', port['port']['id']) - - ctx = mock.ANY - port = mock.ANY - expected = [ - mock.call.exists_ofc_port(ctx, port_id), - mock.call.create_ofc_port(ctx, port_id, port), - mock.call.exists_ofc_port(ctx, port_id), - ] - self.ofc.assert_has_calls(expected) - self.assertFalse(self.ofc.delete_ofc_port.call_count) - - def test_delete_port_with_ofc_deletion_failure(self): - self.ofc.set_raise_exc('delete_ofc_port', - nexc.OFCException(reason='hoge')) - - with self.port() as port: - port_id = port['port']['id'] - - portinfo = {'id': port_id, 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - - self._delete('ports', port_id, - expected_code=webob.exc.HTTPInternalServerError.code) - - port_ref = self._show('ports', port_id) - self.assertEqual(port_ref['port']['status'], 'ERROR') - - self.ofc.set_raise_exc('delete_ofc_port', None) - self._delete('ports', port['port']['id']) - - ctx = mock.ANY - port = mock.ANY - expected = [ - mock.call.exists_ofc_port(ctx, port_id), - mock.call.create_ofc_port(ctx, port_id, port), - mock.call.exists_ofc_port(ctx, port_id), - mock.call.delete_ofc_port(ctx, port_id, port), - mock.call.exists_ofc_port(ctx, port_id), - mock.call.delete_ofc_port(ctx, port_id, port) - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 2) - - def _test_delete_port_for_disappeared_ofc_port(self, raised_exc): - self.ofc.set_raise_exc('delete_ofc_port', raised_exc) - - with self.port() as port: - port_id = port['port']['id'] - - portinfo = {'id': port_id, 'port_no': 123} - self.rpcapi_update_ports(added=[portinfo]) - - self._delete('ports', port_id) - - # Check the port on neutron db is deleted. NotFound for - # neutron port itself should be handled by called. It is - # consistent with ML2 behavior, but it may need to be - # revisit. - self._show('ports', port_id, - expected_code=webob.exc.HTTPNotFound.code) - - ctx = mock.ANY - port = mock.ANY - expected = [ - mock.call.exists_ofc_port(ctx, port_id), - mock.call.create_ofc_port(ctx, port_id, port), - mock.call.exists_ofc_port(ctx, port_id), - mock.call.delete_ofc_port(ctx, port_id, port), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 1) - - def test_delete_port_for_nonexist_ofc_port(self): - self._test_delete_port_for_disappeared_ofc_port( - nexc.OFCResourceNotFound(resource='ofc_port')) - - def test_delete_port_for_noofcmap_ofc_port(self): - self._test_delete_port_for_disappeared_ofc_port( - nexc.OFCMappingNotFound(resource='port', neutron_id='port1')) - - -class TestNecAllowedAddressPairs(NecPluginV2TestCase, - test_pair.TestAllowedAddressPairs): - pass diff --git a/neutron/tests/unit/nec/test_ofc_client.py b/neutron/tests/unit/nec/test_ofc_client.py deleted file mode 100644 index 416ba2c2d..000000000 --- a/neutron/tests/unit/nec/test_ofc_client.py +++ /dev/null @@ -1,175 +0,0 @@ -# Copyright 2013 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -from oslo_config import cfg -from oslo_serialization import jsonutils -import requests - -from neutron.plugins.nec.common import config -from neutron.plugins.nec.common import exceptions as nexc -from neutron.plugins.nec.common import ofc_client -from neutron.tests import base - - -class FakeResponse(requests.Response): - def __init__(self, status_code=None, text=None, headers=None): - self._text = text - self.status_code = status_code - if headers is not None: - self.headers = headers - - @property - def text(self): - return self._text - - -class OFCClientTest(base.BaseTestCase): - - def _test_do_request(self, status, resbody, expected_data, exctype=None, - exc_checks=None, path_prefix=None): - req = mock.Mock(return_value=(FakeResponse(status, resbody))) - - with mock.patch.object(requests, 'request', req): - client = ofc_client.OFCClient() - path = '/somewhere' - realpath = path_prefix + path if path_prefix else path - if exctype: - e = self.assertRaises(exctype, client.do_request, - 'GET', path, body={}) - self.assertEqual(expected_data, str(e)) - if exc_checks: - for k, v in exc_checks.items(): - self.assertEqual(v, getattr(e, k)) - else: - response = client.do_request('GET', path, body={}) - self.assertEqual(response, expected_data) - - headers = {"Content-Type": "application/json"} - req.assert_called_with('GET', 'http://127.0.0.1:8888' + realpath, - verify=True, cert={}, data='{}', - headers=headers) - - def test_do_request_200_json_value(self): - self._test_do_request(200, jsonutils.dumps([1, 2, 3]), [1, 2, 3]) - - def test_do_request_200_string(self): - self._test_do_request(200, 'abcdef', 'abcdef') - - def test_do_request_200_no_body(self): - self._test_do_request(200, None, None) - - def test_do_request_other_success_codes(self): - for status in [201, 202, 204]: - self._test_do_request(status, None, None) - - def test_do_request_with_path_prefix(self): - config.CONF.set_override('path_prefix', '/dummy', group='OFC') - self._test_do_request(200, jsonutils.dumps([1, 2, 3]), [1, 2, 3], - path_prefix='/dummy') - - def test_do_request_returns_404(self): - resbody = '' - errmsg = _("The specified OFC resource (/somewhere) is not found.") - self._test_do_request(404, resbody, errmsg, nexc.OFCResourceNotFound) - - def test_do_request_error_no_body(self): - errmsg = _("An OFC exception has occurred: Operation on OFC failed") - exc_checks = {'status': 400, 'err_code': None, 'err_msg': None} - self._test_do_request(400, None, errmsg, nexc.OFCException, exc_checks) - - def test_do_request_error_string_body(self): - resbody = 'This is an error.' - errmsg = _("An OFC exception has occurred: Operation on OFC failed") - exc_checks = {'status': 400, 'err_code': None, - 'err_msg': 'This is an error.'} - self._test_do_request(400, resbody, errmsg, nexc.OFCException, - exc_checks) - - def test_do_request_error_json_body(self): - resbody = jsonutils.dumps({'err_code': 40022, - 'err_msg': 'This is an error.'}) - errmsg = _("An OFC exception has occurred: Operation on OFC failed") - exc_checks = {'status': 400, 'err_code': 40022, - 'err_msg': 'This is an error.'} - self._test_do_request(400, resbody, errmsg, nexc.OFCException, - exc_checks) - - def test_do_request_socket_error(self): - data = _("An OFC exception has occurred: Failed to connect OFC : ") - - req = mock.Mock() - req.side_effect = requests.exceptions.RequestException - - with mock.patch.object(requests, 'request', req): - client = ofc_client.OFCClient() - - e = self.assertRaises(nexc.OFCException, client.do_request, - 'GET', '/somewhere', body={}) - self.assertEqual(data, str(e)) - for k in ['status', 'err_code', 'err_msg']: - self.assertIsNone(getattr(e, k)) - - headers = {"Content-Type": "application/json"} - req.assert_called_with('GET', 'http://127.0.0.1:8888/somewhere', - verify=True, cert={}, data='{}', - headers=headers) - - def test_do_request_retry_fail_after_one_attempts(self): - self._test_do_request_retry_after(1, api_max_attempts=1) - - def test_do_request_retry_fail_with_max_attempts(self): - self._test_do_request_retry_after(3) - - def test_do_request_retry_succeed_with_2nd_attempt(self): - self._test_do_request_retry_after(2, succeed_final=True) - - def test_do_request_retry_succeed_with_1st_attempt(self): - self._test_do_request_retry_after(1, succeed_final=True) - - def _test_do_request_retry_after(self, exp_request_count, - api_max_attempts=None, - succeed_final=False): - if api_max_attempts is not None: - cfg.CONF.set_override('api_max_attempts', api_max_attempts, - group='OFC') - - res_unavail = FakeResponse(503, headers={'retry-after': '10'}) - res_ok = FakeResponse(200) - - req = mock.Mock() - if succeed_final: - req.side_effect = ([res_unavail] * (exp_request_count - 1) - + [res_ok]) - else: - req.side_effect = [res_unavail] * exp_request_count - - with mock.patch.object(requests, 'request', req): - with mock.patch('time.sleep') as sleep: - client = ofc_client.OFCClient() - if succeed_final: - ret = client.do_request('GET', '/somewhere') - self.assertIsNone(ret) - else: - e = self.assertRaises(nexc.OFCServiceUnavailable, - client.do_request, - 'GET', '/somewhere') - self.assertEqual('10', e.retry_after) - - headers = {"Content-Type": "application/json"} - req.assert_called_with('GET', 'http://127.0.0.1:8888/somewhere', - verify=True, cert={}, data=None, - headers=headers) - self.assertEqual(exp_request_count, req.call_count) - self.assertEqual(exp_request_count - 1, sleep.call_count) diff --git a/neutron/tests/unit/nec/test_ofc_manager.py b/neutron/tests/unit/nec/test_ofc_manager.py deleted file mode 100644 index 24fa8de77..000000000 --- a/neutron/tests/unit/nec/test_ofc_manager.py +++ /dev/null @@ -1,290 +0,0 @@ -# Copyright 2012 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from neutron import context -from neutron.openstack.common import uuidutils -from neutron.plugins.nec.common import config -from neutron.plugins.nec.db import api as ndb -from neutron.plugins.nec import ofc_manager -from neutron.tests.unit import testlib_api - - -class FakePortInfo(object): - def __init__(self, id, datapath_id, port_no=0, - vlan_id=65535, mac='00:11:22:33:44:55'): - self.data = {'id': id, 'datapath_id': datapath_id, - 'port_no': port_no, 'vlan_id': vlan_id, 'mac': mac} - - def __getattr__(self, name): - if name in self.fields: - return self[name] - else: - raise AttributeError(name) - - -class OFCManagerTestBase(testlib_api.SqlTestCase): - """Class conisting of OFCManager unit tests.""" - - def setUp(self): - super(OFCManagerTestBase, self).setUp() - driver = "neutron.tests.unit.nec.stub_ofc_driver.StubOFCDriver" - config.CONF.set_override('driver', driver, 'OFC') - self.plugin = mock.Mock() - self.plugin.get_packet_filters_for_port.return_value = None - self.ofc = ofc_manager.OFCManager(self.plugin) - # NOTE: enable_autocheck() is a feature of StubOFCDriver - self.ofc.driver.enable_autocheck() - self.ctx = context.get_admin_context() - - def get_random_params(self): - """create random parameters for portinfo test.""" - tenant = uuidutils.generate_uuid() - network = uuidutils.generate_uuid() - port = uuidutils.generate_uuid() - _filter = uuidutils.generate_uuid() - none = uuidutils.generate_uuid() - return tenant, network, port, _filter, none - - -class OFCManagerTest(OFCManagerTestBase): - def testa_create_ofc_tenant(self): - """test create ofc_tenant.""" - t, n, p, f, none = self.get_random_params() - self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_tenant', t)) - self.ofc.create_ofc_tenant(self.ctx, t) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_tenant', t)) - tenant = ndb.get_ofc_item(self.ctx.session, 'ofc_tenant', t) - self.assertEqual(tenant.ofc_id, "ofc-" + t[:-4]) - - def testb_exists_ofc_tenant(self): - """test exists_ofc_tenant.""" - t, n, p, f, none = self.get_random_params() - self.assertFalse(self.ofc.exists_ofc_tenant(self.ctx, t)) - self.ofc.create_ofc_tenant(self.ctx, t) - self.assertTrue(self.ofc.exists_ofc_tenant(self.ctx, t)) - - def testc_delete_ofc_tenant(self): - """test delete ofc_tenant.""" - t, n, p, f, none = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_tenant', t)) - self.ofc.delete_ofc_tenant(self.ctx, t) - self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_tenant', t)) - - def testd_create_ofc_network(self): - """test create ofc_network.""" - t, n, p, f, none = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_network', n)) - self.ofc.create_ofc_network(self.ctx, t, n) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_network', n)) - network = ndb.get_ofc_item(self.ctx.session, 'ofc_network', n) - self.assertEqual(network.ofc_id, "ofc-" + n[:-4]) - - def teste_exists_ofc_network(self): - """test exists_ofc_network.""" - t, n, p, f, none = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.assertFalse(self.ofc.exists_ofc_network(self.ctx, n)) - self.ofc.create_ofc_network(self.ctx, t, n) - self.assertTrue(self.ofc.exists_ofc_network(self.ctx, n)) - - def testf_delete_ofc_network(self): - """test delete ofc_network.""" - t, n, p, f, none = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.ofc.create_ofc_network(self.ctx, t, n) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_network', n)) - self.ofc.delete_ofc_network(self.ctx, n, {'tenant_id': t}) - self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_network', n)) - - def _mock_get_portinfo(self, port_id, datapath_id='0xabc', port_no=1): - get_portinfo = mock.patch.object(ndb, 'get_portinfo').start() - fake_portinfo = FakePortInfo(id=port_id, datapath_id=datapath_id, - port_no=port_no) - get_portinfo.return_value = fake_portinfo - return get_portinfo - - def _test_create_ofc_port(self, with_filter=False): - t, n, p, f, none = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.ofc.create_ofc_network(self.ctx, t, n) - self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_port', p)) - get_portinfo = self._mock_get_portinfo(p) - port = {'tenant_id': t, 'network_id': n} - if with_filter: - _filters = ['filter1', 'filter2'] - self.plugin.get_packet_filters_for_port.return_value = _filters - self.ofc.create_ofc_port(self.ctx, p, port) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_port', p)) - port = ndb.get_ofc_item(self.ctx.session, 'ofc_port', p) - self.assertEqual(port.ofc_id, "ofc-" + p[:-4]) - get_portinfo.assert_called_once_with(mock.ANY, p) - portval = self.ofc.driver.ofc_port_dict[port.ofc_id] - if with_filter: - self.assertEqual(_filters, portval['filters']) - else: - self.assertFalse('filters' in portval) - - def testg_create_ofc_port(self): - """test create ofc_port.""" - self._test_create_ofc_port(with_filter=False) - - def testg_create_ofc_port_with_filters(self): - """test create ofc_port.""" - self._test_create_ofc_port(with_filter=True) - - def testh_exists_ofc_port(self): - """test exists_ofc_port.""" - t, n, p, f, none = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.ofc.create_ofc_network(self.ctx, t, n) - self.assertFalse(self.ofc.exists_ofc_port(self.ctx, p)) - get_portinfo = self._mock_get_portinfo(p) - port = {'tenant_id': t, 'network_id': n} - self.ofc.create_ofc_port(self.ctx, p, port) - self.assertTrue(self.ofc.exists_ofc_port(self.ctx, p)) - get_portinfo.assert_called_once_with(mock.ANY, p) - - def testi_delete_ofc_port(self): - """test delete ofc_port.""" - t, n, p, f, none = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.ofc.create_ofc_network(self.ctx, t, n) - get_portinfo = self._mock_get_portinfo(p) - port = {'tenant_id': t, 'network_id': n} - self.ofc.create_ofc_port(self.ctx, p, port) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_port', p)) - self.ofc.delete_ofc_port(self.ctx, p, port) - self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_port', p)) - get_portinfo.assert_called_once_with(mock.ANY, p) - - -class OFCManagerFilterTest(OFCManagerTestBase): - def testj_create_ofc_packet_filter(self): - """test create ofc_filter.""" - t, n, p, f, none = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.ofc.create_ofc_network(self.ctx, t, n) - self.assertFalse(ndb.get_ofc_item(self.ctx.session, - 'ofc_packet_filter', f)) - pf = {'tenant_id': t, 'network_id': n} - self.ofc.create_ofc_packet_filter(self.ctx, f, pf) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, - 'ofc_packet_filter', f)) - _filter = ndb.get_ofc_item(self.ctx.session, 'ofc_packet_filter', f) - self.assertEqual(_filter.ofc_id, "ofc-" + f[:-4]) - - def testk_exists_ofc_packet_filter(self): - """test exists_ofc_packet_filter.""" - t, n, p, f, none = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.ofc.create_ofc_network(self.ctx, t, n) - self.assertFalse(self.ofc.exists_ofc_packet_filter(self.ctx, f)) - pf = {'tenant_id': t, 'network_id': n} - self.ofc.create_ofc_packet_filter(self.ctx, f, pf) - self.assertTrue(self.ofc.exists_ofc_packet_filter(self.ctx, f)) - - def testl_delete_ofc_packet_filter(self): - """test delete ofc_filter.""" - t, n, p, f, none = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.ofc.create_ofc_network(self.ctx, t, n) - pf = {'tenant_id': t, 'network_id': n} - self.ofc.create_ofc_packet_filter(self.ctx, f, pf) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, - 'ofc_packet_filter', f)) - self.ofc.delete_ofc_packet_filter(self.ctx, f) - self.assertFalse(ndb.get_ofc_item(self.ctx.session, - 'ofc_packet_filter', f)) - - -class OFCManagerRouterTest(OFCManagerTestBase): - def get_random_params(self): - tenant = uuidutils.generate_uuid() - router = uuidutils.generate_uuid() - network = uuidutils.generate_uuid() - return (tenant, router, network) - - def test_create_ofc_router(self): - """test create ofc_router""" - t, r, _n = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_router', r)) - self.ofc.create_ofc_router(self.ctx, t, r, 'test router') - self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_router', r)) - router = ndb.get_ofc_item(self.ctx.session, 'ofc_router', r) - self.assertEqual(router.ofc_id, "ofc-" + r[:-4]) - - def test_exists_ofc_router(self): - """test exists_ofc_router""" - t, r, _n = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.assertFalse(self.ofc.exists_ofc_router(self.ctx, r)) - self.ofc.create_ofc_router(self.ctx, t, r) - self.assertTrue(self.ofc.exists_ofc_router(self.ctx, r)) - - def test_delete_ofc_router(self): - """test delete ofc_router""" - t, r, _n = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.ofc.create_ofc_router(self.ctx, t, r) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_router', r)) - self.ofc.delete_ofc_router(self.ctx, r, {'tenant_id': t}) - self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_network', r)) - - def test_router_interface(self): - t, r, n = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.ofc.create_ofc_router(self.ctx, t, r) - self.ofc.create_ofc_network(self.ctx, t, n) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_router', r)) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_network', n)) - - p = {'id': uuidutils.generate_uuid(), - 'network_id': n, 'ip_address': '10.1.1.1', 'cidr': '10.1.0.0/20', - 'mac_address': '11:22:33:44:55:66'} - self.ofc.add_ofc_router_interface(self.ctx, r, p['id'], p) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, - 'ofc_port', p['id'])) - self.ofc.delete_ofc_router_interface(self.ctx, r, p['id']) - self.assertFalse(ndb.get_ofc_item(self.ctx.session, - 'ofc_port', p['id'])) - self.ofc.delete_ofc_router(self.ctx, r, {'tenant_id': t}) - self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_network', r)) - - def test_router_route(self): - t, r, _n = self.get_random_params() - self.ofc.create_ofc_tenant(self.ctx, t) - self.ofc.create_ofc_router(self.ctx, t, r) - self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_router', r)) - - routes = [{'destination': '2.2.2.0/24', 'nexthop': '1.1.1.10'}] - self.ofc.update_ofc_router_route(self.ctx, r, routes) - self.assertEqual(len(self.ofc.driver.ofc_router_route_dict), 1) - - routes = [{'destination': '3.3.3.0/24', 'nexthop': '1.1.1.11'}, - {'destination': '4.4.4.0/24', 'nexthop': '1.1.1.11'}] - self.ofc.update_ofc_router_route(self.ctx, r, routes) - self.assertEqual(len(self.ofc.driver.ofc_router_route_dict), 2) - - routes = [{'destination': '2.2.2.0/24', 'nexthop': '1.1.1.10'}] - self.ofc.update_ofc_router_route(self.ctx, r, routes) - self.assertEqual(len(self.ofc.driver.ofc_router_route_dict), 1) - - routes = [] - self.ofc.update_ofc_router_route(self.ctx, r, routes) - self.assertEqual(len(self.ofc.driver.ofc_router_route_dict), 0) diff --git a/neutron/tests/unit/nec/test_packet_filter.py b/neutron/tests/unit/nec/test_packet_filter.py deleted file mode 100644 index a96f65cfa..000000000 --- a/neutron/tests/unit/nec/test_packet_filter.py +++ /dev/null @@ -1,719 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import contextlib - -import mock -import webob.exc - -from neutron.api.v2 import attributes -from neutron import context -from neutron.plugins.nec.common import exceptions as nexc -from neutron.plugins.nec.extensions import packetfilter as ext_pf -from neutron.tests.unit.nec import test_nec_plugin -from neutron.tests.unit import test_db_plugin as test_plugin - - -NEC_PLUGIN_PF_INI = """ -[DEFAULT] -api_extensions_path = neutron/plugins/nec/extensions -[OFC] -driver = neutron.tests.unit.nec.stub_ofc_driver.StubOFCDriver -enable_packet_filter = True -""" - - -class PacketfilterExtensionManager(ext_pf.Packetfilter): - - @classmethod - def get_resources(cls): - # Add the resources to the global attribute map - # This is done here as the setup process won't - # initialize the main API router which extends - # the global attribute map - attributes.RESOURCE_ATTRIBUTE_MAP.update( - {'packet_filters': ext_pf.PACKET_FILTER_ATTR_MAP}) - return super(PacketfilterExtensionManager, cls).get_resources() - - -class TestNecPluginPacketFilterBase(test_nec_plugin.NecPluginV2TestCase): - - _nec_ini = NEC_PLUGIN_PF_INI - - def setUp(self): - ext_mgr = PacketfilterExtensionManager() - super(TestNecPluginPacketFilterBase, self).setUp(ext_mgr=ext_mgr) - - def _create_packet_filter(self, fmt, net_id, expected_res_status=None, - arg_list=None, **kwargs): - data = {'packet_filter': {'network_id': net_id, - 'tenant_id': self._tenant_id, - 'priority': '1', - 'action': 'ALLOW'}} - - for arg in (('name', 'admin_state_up', 'action', 'priority', 'in_port', - 'src_mac', 'dst_mac', 'eth_type', 'src_cidr', 'dst_cidr', - 'protocol', 'src_port', 'dst_port') + - (arg_list or ())): - # Arg must be present - if arg in kwargs: - data['packet_filter'][arg] = kwargs[arg] - pf_req = self.new_create_request('packet_filters', data, fmt) - if (kwargs.get('set_context') and 'tenant_id' in kwargs): - # create a specific auth context for this request - pf_req.environ['neutron.context'] = context.Context( - '', kwargs['tenant_id']) - - pf_res = pf_req.get_response(self.ext_api) - if expected_res_status: - self.assertEqual(pf_res.status_int, expected_res_status) - return pf_res - - def _make_packet_filter(self, fmt, net_id, expected_res_status=None, - **kwargs): - res = self._create_packet_filter(fmt, net_id, expected_res_status, - **kwargs) - # Things can go wrong - raise HTTP exc with res code only - # so it can be caught by unit tests - if res.status_int >= 400: - raise webob.exc.HTTPClientError(code=res.status_int) - return self.deserialize(fmt, res) - - @contextlib.contextmanager - def packet_filter_on_network(self, network=None, fmt=None, **kwargs): - with test_plugin.optional_ctx(network, self.network) as network_to_use: - net_id = network_to_use['network']['id'] - pf = self._make_packet_filter(fmt or self.fmt, net_id, **kwargs) - yield pf - if not network: - self._delete('networks', network_to_use['network']['id']) - - @contextlib.contextmanager - def packet_filter_on_port(self, port=None, fmt=None, set_portinfo=True, - **kwargs): - with test_plugin.optional_ctx(port, self.port) as port_to_use: - net_id = port_to_use['port']['network_id'] - port_id = port_to_use['port']['id'] - - if set_portinfo: - portinfo = {'id': port_id, - 'port_no': kwargs.get('port_no', 123)} - kw = {'added': [portinfo]} - if 'datapath_id' in kwargs: - kw['datapath_id'] = kwargs['datapath_id'] - self.rpcapi_update_ports(**kw) - - kwargs['in_port'] = port_id - pf = self._make_packet_filter(fmt or self.fmt, net_id, **kwargs) - self.assertEqual(port_id, pf['packet_filter']['in_port']) - yield pf - - -class TestNecPluginPacketFilter(TestNecPluginPacketFilterBase): - - def setUp(self): - super(TestNecPluginPacketFilter, self).setUp() - # Remove attributes explicitly from mock object to check - # a case where there are no update_filter and validate_*. - del self.ofc.driver.update_filter - del self.ofc.driver.validate_filter_create - del self.ofc.driver.validate_filter_update - - def test_list_packet_filters(self): - self._list('packet_filters') - - def test_create_pf_on_network_no_ofc_creation(self): - with self.packet_filter_on_network(admin_state_up=False) as pf: - self.assertEqual(pf['packet_filter']['status'], 'DOWN') - - self.assertFalse(self.ofc.create_ofc_packet_filter.called) - self.assertFalse(self.ofc.delete_ofc_packet_filter.called) - - def test_create_pf_on_port_no_ofc_creation(self): - with self.packet_filter_on_port(admin_state_up=False, - set_portinfo=False) as pf: - self.assertEqual(pf['packet_filter']['status'], 'DOWN') - - self.assertFalse(self.ofc.create_ofc_packet_filter.called) - self.assertFalse(self.ofc.delete_ofc_packet_filter.called) - - def test_create_pf_on_network_with_ofc_creation(self): - with self.packet_filter_on_network() as pf: - pf_id = pf['packet_filter']['id'] - self.assertEqual(pf['packet_filter']['status'], 'ACTIVE') - - ctx = mock.ANY - pf_dict = mock.ANY - expected = [ - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict), - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.delete_ofc_packet_filter(ctx, pf_id), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.create_ofc_packet_filter.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 1) - - def test_create_pf_on_port_with_ofc_creation(self): - with self.packet_filter_on_port() as pf: - pf_id = pf['packet_filter']['id'] - self.assertEqual(pf['packet_filter']['status'], 'ACTIVE') - self._delete('packet_filters', pf_id) - - ctx = mock.ANY - pf_dict = mock.ANY - expected = [ - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict), - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.delete_ofc_packet_filter(ctx, pf_id), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.create_ofc_packet_filter.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 1) - - def _test_create_pf_with_protocol(self, protocol, expected_eth_type): - with self.packet_filter_on_network(protocol=protocol) as pf: - pf_data = pf['packet_filter'] - self.assertEqual(protocol, pf_data['protocol']) - self.assertEqual(expected_eth_type, pf_data['eth_type']) - - def test_create_pf_with_protocol_tcp(self): - self._test_create_pf_with_protocol('TCP', 0x800) - - def test_create_pf_with_protocol_udp(self): - self._test_create_pf_with_protocol('UDP', 0x800) - - def test_create_pf_with_protocol_icmp(self): - self._test_create_pf_with_protocol('ICMP', 0x800) - - def test_create_pf_with_protocol_arp(self): - self._test_create_pf_with_protocol('ARP', 0x806) - - def test_create_pf_with_inconsistent_protocol_and_eth_type(self): - with self.packet_filter_on_network(protocol='TCP') as pf: - pf_data = pf['packet_filter'] - pf_id = pf_data['id'] - self.assertEqual('TCP', pf_data['protocol']) - self.assertEqual(0x800, pf_data['eth_type']) - data = {'packet_filter': {'eth_type': 0x806}} - self._update('packet_filters', pf_id, data, - expected_code=409) - - def test_create_pf_with_invalid_priority(self): - with self.network() as net: - net_id = net['network']['id'] - kwargs = {'priority': 'high'} - self._create_packet_filter(self.fmt, net_id, - webob.exc.HTTPBadRequest.code, - **kwargs) - self.assertFalse(self.ofc.create_ofc_packet_filter.called) - - def test_create_pf_with_ofc_creation_failure(self): - self.ofc.set_raise_exc('create_ofc_packet_filter', - nexc.OFCException(reason='hoge')) - - with self.packet_filter_on_network() as pf: - pf_id = pf['packet_filter']['id'] - pf_ref = self._show('packet_filters', pf_id) - self.assertEqual(pf_ref['packet_filter']['status'], 'ERROR') - - self.ofc.set_raise_exc('create_ofc_packet_filter', None) - - # Retry activate packet_filter (even if there is no change). - data = {'packet_filter': {}} - self._update('packet_filters', pf_id, data) - - pf_ref = self._show('packet_filters', pf_id) - self.assertEqual(pf_ref['packet_filter']['status'], 'ACTIVE') - - ctx = mock.ANY - pf_dict = mock.ANY - expected = [ - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict), - - mock.call.exists_ofc_packet_filter(ctx, pf_id), - - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.create_ofc_packet_filter.call_count, 2) - - def test_show_pf_on_network(self): - kwargs = { - 'name': 'test-pf-net', - 'admin_state_up': False, - 'action': 'DENY', - 'priority': '102', - 'src_mac': '00:11:22:33:44:55', - 'dst_mac': '66:77:88:99:aa:bb', - 'eth_type': '2048', - 'src_cidr': '192.168.1.0/24', - 'dst_cidr': '192.168.2.0/24', - 'protocol': 'TCP', - 'src_port': '35001', - 'dst_port': '22' - } - - with self.packet_filter_on_network(**kwargs) as pf: - pf_id = pf['packet_filter']['id'] - pf_ref = self._show('packet_filters', pf_id) - - # convert string to int. - kwargs.update({'priority': 102, 'eth_type': 2048, - 'src_port': 35001, 'dst_port': 22, - 'in_port': None}) - - self.assertEqual(pf_id, pf_ref['packet_filter']['id']) - for key in kwargs: - self.assertEqual(kwargs[key], pf_ref['packet_filter'][key]) - - def test_show_pf_on_network_with_wildcards(self): - kwargs = { - 'name': 'test-pf-net', - 'admin_state_up': False, - 'action': 'DENY', - 'priority': '102', - } - - with self.packet_filter_on_network(**kwargs) as pf: - pf_id = pf['packet_filter']['id'] - pf_ref = self._show('packet_filters', pf_id) - - # convert string to int. - kwargs.update({'priority': 102, - 'in_port': None, - 'src_mac': None, - 'dst_mac': None, - 'eth_type': None, - 'src_cidr': None, - 'dst_cidr': None, - 'protocol': None, - 'src_port': None, - 'dst_port': None}) - - self.assertEqual(pf_id, pf_ref['packet_filter']['id']) - for key in kwargs: - self.assertEqual(kwargs[key], pf_ref['packet_filter'][key]) - - def test_show_pf_on_port(self): - kwargs = { - 'name': 'test-pf-port', - 'admin_state_up': False, - 'action': 'DENY', - 'priority': '0o147', - 'src_mac': '00:11:22:33:44:55', - 'dst_mac': '66:77:88:99:aa:bb', - 'eth_type': 2048, - 'src_cidr': '192.168.1.0/24', - 'dst_cidr': '192.168.2.0/24', - 'protocol': 'TCP', - 'dst_port': '0x50' - } - - with self.packet_filter_on_port(**kwargs) as pf: - pf_id = pf['packet_filter']['id'] - pf_ref = self._show('packet_filters', pf_id) - - # convert string to int. - kwargs.update({'priority': 103, 'eth_type': 2048, - 'dst_port': 80, - # wildcard field is None in a response. - 'src_port': None}) - - self.assertEqual(pf_id, pf_ref['packet_filter']['id']) - self.assertTrue(pf_ref['packet_filter']['in_port']) - for key in kwargs: - self.assertEqual(kwargs[key], pf_ref['packet_filter'][key]) - - def test_show_pf_not_found(self): - pf_id = '00000000-ffff-ffff-ffff-000000000000' - - self._show('packet_filters', pf_id, - expected_code=webob.exc.HTTPNotFound.code) - - def test_update_pf_on_network(self): - ctx = mock.ANY - pf_dict = mock.ANY - with self.packet_filter_on_network(admin_state_up=False) as pf: - pf_id = pf['packet_filter']['id'] - - self.assertFalse(self.ofc.create_ofc_packet_filter.called) - data = {'packet_filter': {'admin_state_up': True}} - self._update('packet_filters', pf_id, data) - self.ofc.create_ofc_packet_filter.assert_called_once_with( - ctx, pf_id, pf_dict) - - self.assertFalse(self.ofc.delete_ofc_packet_filter.called) - data = {'packet_filter': {'admin_state_up': False}} - self._update('packet_filters', pf_id, data) - self.ofc.delete_ofc_packet_filter.assert_called_once_with( - ctx, pf_id) - - def test_update_pf_on_port(self): - ctx = mock.ANY - pf_dict = mock.ANY - with self.packet_filter_on_port(admin_state_up=False) as pf: - pf_id = pf['packet_filter']['id'] - - self.assertFalse(self.ofc.create_ofc_packet_filter.called) - data = {'packet_filter': {'admin_state_up': True}} - self._update('packet_filters', pf_id, data) - self.ofc.create_ofc_packet_filter.assert_called_once_with( - ctx, pf_id, pf_dict) - - self.assertFalse(self.ofc.delete_ofc_packet_filter.called) - data = {'packet_filter': {'admin_state_up': False}} - self._update('packet_filters', pf_id, data) - self.ofc.delete_ofc_packet_filter.assert_called_once_with( - ctx, pf_id) - - def test_delete_pf_with_error_status(self): - self.ofc.set_raise_exc('create_ofc_packet_filter', - nexc.OFCException(reason='fake')) - with self.packet_filter_on_network() as pf: - pf_id = pf['packet_filter']['id'] - pf_ref = self._show('packet_filters', pf_id) - self.assertEqual(pf_ref['packet_filter']['status'], 'ERROR') - - ctx = mock.ANY - pf_dict = mock.ANY - expected = [ - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict), - mock.call.exists_ofc_packet_filter(ctx, pf_id), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(1, self.ofc.create_ofc_packet_filter.call_count) - self.assertEqual(0, self.ofc.delete_ofc_packet_filter.call_count) - - def test_activate_pf_on_port_triggered_by_update_port(self): - ctx = mock.ANY - pf_dict = mock.ANY - self.ofc.set_raise_exc('create_ofc_packet_filter', - nexc.PortInfoNotFound(id='fake_id')) - with self.packet_filter_on_port(set_portinfo=False) as pf: - pf_id = pf['packet_filter']['id'] - in_port_id = pf['packet_filter']['in_port'] - - # create_ofc_packet_filter is now called even when - # in_port does not exists yet. In this case - # PortInfoNotFound exception is raised. - self.assertEqual(1, self.ofc.create_ofc_packet_filter.call_count) - portinfo = {'id': in_port_id, 'port_no': 123} - kw = {'added': [portinfo]} - self.ofc.set_raise_exc('create_ofc_packet_filter', None) - self.rpcapi_update_ports(**kw) - self.assertEqual(2, self.ofc.create_ofc_packet_filter.call_count) - self.ofc.assert_has_calls([ - mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict), - ]) - - self.assertFalse(self.ofc.delete_ofc_packet_filter.called) - kw = {'removed': [in_port_id]} - self.rpcapi_update_ports(**kw) - self.ofc.delete_ofc_packet_filter.assert_called_once_with( - ctx, pf_id) - - # Ensure pf was created before in_port has activated. - ctx = mock.ANY - pf_dict = mock.ANY - port_dict = mock.ANY - expected = [ - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict), - mock.call.exists_ofc_port(ctx, in_port_id), - mock.call.create_ofc_port(ctx, in_port_id, port_dict), - - mock.call.exists_ofc_port(ctx, in_port_id), - mock.call.delete_ofc_port(ctx, in_port_id, port_dict), - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.delete_ofc_packet_filter(ctx, pf_id), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(2, self.ofc.create_ofc_packet_filter.call_count) - self.assertEqual(1, self.ofc.delete_ofc_packet_filter.call_count) - - def test_activate_pf_while_exists_on_ofc(self): - ctx = mock.ANY - with self.packet_filter_on_network() as pf: - pf_id = pf['packet_filter']['id'] - - self.ofc.set_raise_exc('delete_ofc_packet_filter', - nexc.OFCException(reason='hoge')) - - # This update request will make plugin reactivate pf. - data = {'packet_filter': {'priority': 1000}} - self._update('packet_filters', pf_id, data, - expected_code=webob.exc.HTTPInternalServerError.code) - - self.ofc.set_raise_exc('delete_ofc_packet_filter', None) - - ctx = mock.ANY - pf_dict = mock.ANY - expected = [ - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict), - - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.delete_ofc_packet_filter(ctx, pf_id), - - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.delete_ofc_packet_filter(ctx, pf_id), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 2) - - def test_deactivate_pf_with_ofc_deletion_failure(self): - ctx = mock.ANY - with self.packet_filter_on_network() as pf: - pf_id = pf['packet_filter']['id'] - - self.ofc.set_raise_exc('delete_ofc_packet_filter', - nexc.OFCException(reason='hoge')) - - data = {'packet_filter': {'admin_state_up': False}} - self._update('packet_filters', pf_id, data, - expected_code=webob.exc.HTTPInternalServerError.code) - - pf_ref = self._show('packet_filters', pf_id) - self.assertEqual(pf_ref['packet_filter']['status'], 'ERROR') - - self.ofc.set_raise_exc('delete_ofc_packet_filter', None) - - data = {'packet_filter': {'priority': 1000}} - self._update('packet_filters', pf_id, data) - - pf_ref = self._show('packet_filters', pf_id) - self.assertEqual(pf_ref['packet_filter']['status'], 'DOWN') - - ctx = mock.ANY - pf_dict = mock.ANY - expected = [ - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict), - - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.delete_ofc_packet_filter(ctx, pf_id), - - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.delete_ofc_packet_filter(ctx, pf_id), - - mock.call.exists_ofc_packet_filter(ctx, pf_id), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 2) - - def test_delete_pf_with_ofc_deletion_failure(self): - self.ofc.set_raise_exc('delete_ofc_packet_filter', - nexc.OFCException(reason='hoge')) - - with self.packet_filter_on_network() as pf: - pf_id = pf['packet_filter']['id'] - - self._delete('packet_filters', pf_id, - expected_code=webob.exc.HTTPInternalServerError.code) - - pf_ref = self._show('packet_filters', pf_id) - self.assertEqual(pf_ref['packet_filter']['status'], 'ERROR') - - self.ofc.set_raise_exc('delete_ofc_packet_filter', None) - # Then, self._delete('packet_filters', pf_id) will success. - - ctx = mock.ANY - pf_dict = mock.ANY - expected = [ - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict), - - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.delete_ofc_packet_filter(ctx, pf_id), - - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.delete_ofc_packet_filter(ctx, pf_id), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 2) - - def test_auto_delete_pf_in_network_deletion(self): - with self.packet_filter_on_network(admin_state_up=False) as pf: - pf_id = pf['packet_filter']['id'] - - self._show('packet_filters', pf_id, - expected_code=webob.exc.HTTPNotFound.code) - - def test_auto_delete_pf_in_port_deletion(self): - with self.port() as port: - network = self._show('networks', port['port']['network_id']) - - with self.packet_filter_on_network(network=network) as pfn: - with self.packet_filter_on_port(port=port, - set_portinfo=False) as pf: - pf_id = pf['packet_filter']['id'] - in_port_id = pf['packet_filter']['in_port'] - - self._delete('ports', in_port_id) - # Check the packet filter on the port is deleted. - self._show('packet_filters', pf_id, - expected_code=webob.exc.HTTPNotFound.code) - # Check the packet filter on the network is not deleted. - self._show('packet_filters', pfn['packet_filter']['id']) - - def test_no_pf_activation_while_port_operations(self): - with self.packet_filter_on_port() as pf: - in_port_id = pf['packet_filter']['in_port'] - self.assertEqual(self.ofc.create_ofc_packet_filter.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 0) - - data = {'port': {'admin_state_up': False}} - self._update('ports', in_port_id, data) - self.assertEqual(self.ofc.create_ofc_packet_filter.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 0) - - data = {'port': {'admin_state_up': True}} - self._update('ports', in_port_id, data) - self.assertEqual(self.ofc.create_ofc_packet_filter.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 0) - - -class TestNecPluginPacketFilterWithValidate(TestNecPluginPacketFilterBase): - - def setUp(self): - super(TestNecPluginPacketFilterWithValidate, self).setUp() - # Remove attributes explicitly from mock object to check - # a case where there are no update_filter. - del self.ofc.driver.update_filter - self.validate_create = self.ofc.driver.validate_filter_create - self.validate_update = self.ofc.driver.validate_filter_update - - def test_create_pf_on_network(self): - with self.packet_filter_on_network() as pf: - pf_id = pf['packet_filter']['id'] - self.assertEqual(pf['packet_filter']['status'], 'ACTIVE') - - ctx = mock.ANY - pf_dict = mock.ANY - expected = [ - mock.call.driver.validate_filter_create(ctx, pf_dict), - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict), - mock.call.exists_ofc_packet_filter(ctx, pf_id), - mock.call.delete_ofc_packet_filter(ctx, pf_id), - ] - self.ofc.assert_has_calls(expected) - self.assertEqual(self.ofc.create_ofc_packet_filter.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 1) - - def test_update_pf_on_network(self): - ctx = mock.ANY - pf_dict = mock.ANY - with self.packet_filter_on_network(admin_state_up=False) as pf: - pf_id = pf['packet_filter']['id'] - - self.assertFalse(self.ofc.create_ofc_packet_filter.called) - data = {'packet_filter': {'admin_state_up': True}} - self._update('packet_filters', pf_id, data) - self.ofc.create_ofc_packet_filter.assert_called_once_with( - ctx, pf_id, pf_dict) - self.ofc.driver.validate_filter_update.assert_called_once_with( - ctx, data['packet_filter']) - - self.assertFalse(self.ofc.delete_ofc_packet_filter.called) - data = {'packet_filter': {'admin_state_up': False}} - self._update('packet_filters', pf_id, data) - self.ofc.delete_ofc_packet_filter.assert_called_once_with( - ctx, pf_id) - self.assertEqual( - 2, self.ofc.driver.validate_filter_update.call_count) - - def test_create_pf_on_network_with_validation_error(self): - self.validate_create.side_effect = ext_pf.PacketFilterInvalidPriority( - min=1, max=65535) - with self.network() as net: - net_id = net['network']['id'] - e = self.assertRaises(webob.exc.HTTPClientError, - self._make_packet_filter, - self.fmt, net_id, expected_res_status=400) - self.assertEqual(400, e.status_int) - - def test_update_pf_on_network_with_validation_error(self): - self.validate_update.side_effect = ( - ext_pf.PacketFilterUpdateNotSupported(field='priority')) - with self.packet_filter_on_network() as pf: - pf_id = pf['packet_filter']['id'] - pf_ref = self._show('packet_filters', pf_id) - self.assertEqual(pf_ref['packet_filter']['status'], 'ACTIVE') - data = {'packet_filter': {'priority': 1000}} - self._update('packet_filters', pf_id, data, - expected_code=400) - - -class TestNecPluginPacketFilterWithFilterUpdate(TestNecPluginPacketFilterBase): - - def setUp(self): - super(TestNecPluginPacketFilterWithFilterUpdate, self).setUp() - # Remove attributes explicitly from mock object to check - # a case where there are no update_filter and validate_*. - del self.ofc.driver.validate_filter_create - del self.ofc.driver.validate_filter_update - - def test_update_pf_toggle_admin_state(self): - ctx = mock.ANY - pf_dict = mock.ANY - with self.packet_filter_on_network(admin_state_up=False) as pf: - pf_id = pf['packet_filter']['id'] - - self.assertFalse(self.ofc.create_ofc_packet_filter.called) - data = {'packet_filter': {'admin_state_up': True}} - self._update('packet_filters', pf_id, data) - self.ofc.create_ofc_packet_filter.assert_called_once_with( - ctx, pf_id, pf_dict) - - self.assertFalse(self.ofc.delete_ofc_packet_filter.called) - data = {'packet_filter': {'admin_state_up': False}} - self._update('packet_filters', pf_id, data) - self.ofc.delete_ofc_packet_filter.assert_called_once_with( - ctx, pf_id) - - def test_update_pf_change_field(self): - ctx = mock.ANY - with self.packet_filter_on_network(admin_state_up=True) as pf: - pf_id = pf['packet_filter']['id'] - self.assertTrue(self.ofc.create_ofc_packet_filter.called) - - data = {'packet_filter': {'src_mac': '12:34:56:78:9a:bc'}} - self._update('packet_filters', pf_id, data) - self.ofc.update_ofc_packet_filter.assert_called_once_with( - ctx, pf_id, data['packet_filter']) - self.assertEqual(1, self.ofc.update_ofc_packet_filter.call_count) - - self.assertFalse(self.ofc.delete_ofc_packet_filter.called) - data = {'packet_filter': {'admin_state_up': False}} - self._update('packet_filters', pf_id, data) - self.ofc.delete_ofc_packet_filter.assert_called_once_with( - ctx, pf_id) - - data = {'packet_filter': {'src_mac': '11:22:33:44:55:66'}} - self._update('packet_filters', pf_id, data) - self.assertEqual(1, self.ofc.update_ofc_packet_filter.call_count) - - data = {'packet_filter': {'admin_state_up': True}} - self._update('packet_filters', pf_id, data) - - data = {'packet_filter': {'src_mac': '66:55:44:33:22:11'}} - self._update('packet_filters', pf_id, data) - self.assertEqual(2, self.ofc.update_ofc_packet_filter.call_count) diff --git a/neutron/tests/unit/nec/test_pfc_driver.py b/neutron/tests/unit/nec/test_pfc_driver.py deleted file mode 100644 index d18b44999..000000000 --- a/neutron/tests/unit/nec/test_pfc_driver.py +++ /dev/null @@ -1,726 +0,0 @@ -# Copyright 2012 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import random -import string -import uuid - -import mock -import netaddr -from oslo_config import cfg - -from neutron.common import constants -from neutron.openstack.common import uuidutils -from neutron.plugins.nec.common import ofc_client as ofc -from neutron.plugins.nec.db import models as nmodels -from neutron.plugins.nec import drivers -from neutron.plugins.nec.drivers import pfc -from neutron.plugins.nec.extensions import packetfilter as ext_pf -from neutron.tests import base - - -class TestConfig(object): - """Configuration for this test.""" - host = '127.0.0.1' - port = 8888 - use_ssl = False - key_file = None - cert_file = None - insecure_ssl = False - - -def _ofc(id): - """OFC ID converter.""" - return "ofc-%s" % id - - -class PFCDriverTestBase(base.BaseTestCase): - - driver = 'neutron.plugins.nec.drivers.pfc.PFCDriverBase' - filter_supported = False - - def setUp(self): - super(PFCDriverTestBase, self).setUp() - self.driver = drivers.get_driver(self.driver)(TestConfig) - self.do_request = mock.patch.object(ofc.OFCClient, - 'do_request').start() - - def get_ofc_item_random_params(self): - """create random parameters for ofc_item test.""" - tenant_id = uuidutils.generate_uuid() - network_id = uuidutils.generate_uuid() - port_id = uuidutils.generate_uuid() - portinfo = nmodels.PortInfo(id=port_id, datapath_id="0x123456789", - port_no=1234, vlan_id=321, - mac="11:22:33:44:55:66") - return tenant_id, network_id, portinfo - - def _generate_ofc_tenant_id(self, tenant_id): - fields = tenant_id.split('-') - # Strip 1st character (UUID version) of 3rd field - fields[2] = fields[2][1:] - return ''.join(fields) - - def get_ofc_description(self, desc): - """OFC description consists of [A-Za-z0-9_].""" - return desc.replace('-', '_').replace(' ', '_') - - def _create_tenant(self, t, ofc_t, post_id=False, post_desc=False): - tenant_path = '/tenants/%s' % ofc_t - path = "/tenants" - description = "desc of %s" % t - body = {} - if post_desc: - ofc_description = self.get_ofc_description(description) - body['description'] = ofc_description - if post_id: - body['id'] = ofc_t - self.do_request.return_value = None - else: - self.do_request.return_value = {'id': ofc_t} - - ret = self.driver.create_tenant(description, t) - self.do_request.assert_called_once_with("POST", path, body=body) - self.assertEqual(ret, tenant_path) - - def testa_create_tenant(self): - t, n, p = self.get_ofc_item_random_params() - ofc_t = self._generate_ofc_tenant_id(t) - self._create_tenant(t, ofc_t, post_id=True) - - def testc_delete_tenant(self): - t, n, p = self.get_ofc_item_random_params() - - path = "/tenants/%s" % _ofc(t) - - self.driver.delete_tenant(path) - self.do_request.assert_called_once_with("DELETE", path) - - def testd_create_network(self): - t, n, p = self.get_ofc_item_random_params() - description = "desc of %s" % n - ofc_description = self.get_ofc_description(description) - - tenant_path = "/tenants/%s" % _ofc(t) - post_path = "%s/networks" % tenant_path - body = {'description': ofc_description} - network = {'id': _ofc(n)} - self.do_request.return_value = network - - ret = self.driver.create_network(tenant_path, description, n) - self.do_request.assert_called_once_with("POST", post_path, body=body) - net_path = "/tenants/%s/networks/%s" % (_ofc(t), _ofc(n)) - self.assertEqual(ret, net_path) - - def testf_delete_network(self): - t, n, p = self.get_ofc_item_random_params() - - net_path = "/tenants/%s/networks/%s" % (_ofc(t), _ofc(n)) - - self.driver.delete_network(net_path) - self.do_request.assert_called_once_with("DELETE", net_path) - - def _test_create_port(self, call_filters_arg=None, send_filters_arg=None): - t, n, p = self.get_ofc_item_random_params() - - net_path = "/tenants/%s/networks/%s" % (_ofc(t), _ofc(n)) - post_path = "%s/ports" % net_path - port_path = "/tenants/%s/networks/%s/ports/%s" % (_ofc(t), _ofc(n), - _ofc(p.id)) - body = {'datapath_id': p.datapath_id, - 'port': str(p.port_no), - 'vid': str(p.vlan_id)} - if send_filters_arg is not None: - body['filters'] = send_filters_arg - port = {'id': _ofc(p.id)} - self.do_request.return_value = port - - if call_filters_arg is not None: - ret = self.driver.create_port(net_path, p, p.id, call_filters_arg) - else: - ret = self.driver.create_port(net_path, p, p.id) - self.do_request.assert_called_once_with("POST", post_path, body=body) - self.assertEqual(ret, port_path) - - def testg_create_port(self): - self._test_create_port() - - def test_create_port_with_filters_argument(self): - # If no filter support, 'filters' argument is passed to OFC. - # Note that it will be overridden in a test class with filter support. - self._test_create_port(call_filters_arg=['dummy'], - send_filters_arg=None) - - def testh_delete_port(self): - t, n, p = self.get_ofc_item_random_params() - - port_path = "/tenants/%s/networks/%s/ports/%s" % (_ofc(t), _ofc(n), - _ofc(p.id)) - - self.driver.delete_port(port_path) - self.do_request.assert_called_once_with("DELETE", port_path) - - def test_filter_supported(self): - self.assertEqual(self.filter_supported, self.driver.filter_supported()) - - -class PFCDriverBaseTest(PFCDriverTestBase): - - def test_extract_ofc_network_id(self): - network_id = '/tenants/tenant-a/networks/network-a' - self.assertEqual('network-a', - self.driver._extract_ofc_network_id(network_id)) - - def test_extract_ofc_network_id_failure(self): - network_id = '/tenants/tenant-a/networks/network-a/dummy' - self.assertRaises(pfc.InvalidOFCIdFormat, - self.driver._extract_ofc_network_id, network_id) - - def test_extract_ofc_port_id(self): - port_id = '/tenants/tenant-a/networks/network-a/ports/port-a' - self.assertEqual({'tenant': 'tenant-a', - 'network': 'network-a', - 'port': 'port-a'}, - self.driver._extract_ofc_port_id(port_id)) - - def test_extract_ofc_port_id_failure(self): - port_id = '/tenants/tenant-a/dummy/network-a/ports/port-a' - self.assertRaises(pfc.InvalidOFCIdFormat, - self.driver._extract_ofc_port_id, port_id) - - -class PFCV3DriverTest(PFCDriverTestBase): - driver = 'pfc_v3' - - def testa_create_tenant(self): - t, n, p = self.get_ofc_item_random_params() - ret = self.driver.create_tenant('dummy_desc', t) - self.assertEqual(0, self.do_request.call_count) - ofc_t_path = "/tenants/" + self._generate_ofc_tenant_id(t) - self.assertEqual(ofc_t_path, ret) - - def testc_delete_tenant(self): - t, n, p = self.get_ofc_item_random_params() - path = "/tenants/%s" % _ofc(t) - self.driver.delete_tenant(path) - self.assertEqual(0, self.do_request.call_count) - - -class PFCV4DriverTest(PFCDriverTestBase): - driver = 'pfc_v4' - - -class PFCV5DriverTest(PFCDriverTestBase): - driver = 'pfc_v5' - - def test_create_router(self): - t = uuidutils.generate_uuid() - r = uuidutils.generate_uuid() - description = 'dummy_router_desc' - - tenant_path = "/tenants/%s" % _ofc(t) - post_path = "%s/routers" % tenant_path - router = {'id': _ofc(r)} - self.do_request.return_value = router - - ret = self.driver.create_router(tenant_path, description, r) - self.do_request.assert_called_once_with("POST", post_path, body=None) - router_path = "/tenants/%s/routers/%s" % (_ofc(t), _ofc(r)) - self.assertEqual(ret, router_path) - - def test_delete_router(self): - t = uuidutils.generate_uuid() - r = uuidutils.generate_uuid() - - router_path = "/tenants/%s/routers/%s" % (_ofc(t), _ofc(r)) - - self.driver.delete_router(router_path) - self.do_request.assert_called_once_with("DELETE", router_path) - - def test_add_router_interface(self): - t = uuidutils.generate_uuid() - r = uuidutils.generate_uuid() - n = uuidutils.generate_uuid() - p = uuidutils.generate_uuid() - - router_path = "/tenants/%s/routers/%s" % (_ofc(t), _ofc(r)) - infs_path = router_path + "/interfaces" - net_path = "/tenants/%s/networks/%s" % (_ofc(t), _ofc(n)) - ip_address = '10.1.1.1/24' - mac_address = '11:22:33:44:55:66' - body = {'net_id': _ofc(n), - 'ip_address': ip_address, - 'mac_address': mac_address} - inf = {'id': _ofc(p)} - self.do_request.return_value = inf - - ret = self.driver.add_router_interface(router_path, net_path, - ip_address, mac_address) - self.do_request.assert_called_once_with("POST", infs_path, body=body) - - inf_path = "%s/interfaces/%s" % (router_path, _ofc(p)) - self.assertEqual(ret, inf_path) - - def test_update_router_interface(self): - t = uuidutils.generate_uuid() - r = uuidutils.generate_uuid() - p = uuidutils.generate_uuid() - - router_path = "/tenants/%s/routers/%s" % (_ofc(t), _ofc(r)) - inf_path = "%s/interfaces/%s" % (router_path, _ofc(p)) - ip_address = '10.1.1.1/24' - mac_address = '11:22:33:44:55:66' - - self.driver.update_router_interface(inf_path, ip_address, mac_address) - self.driver.update_router_interface(inf_path, ip_address=ip_address) - self.driver.update_router_interface(inf_path, mac_address=mac_address) - - self.do_request.assert_has_calls([ - mock.call("PUT", inf_path, body={'ip_address': ip_address, - 'mac_address': mac_address}), - mock.call("PUT", inf_path, body={'ip_address': ip_address}), - mock.call("PUT", inf_path, body={'mac_address': mac_address}), - ]) - - def test_delete_router_interface(self): - t = uuidutils.generate_uuid() - r = uuidutils.generate_uuid() - p = uuidutils.generate_uuid() - - router_path = "/tenants/%s/routers/%s" % (_ofc(t), _ofc(r)) - inf_path = "%s/interfaces/%s" % (router_path, _ofc(p)) - - self.driver.delete_router_interface(inf_path) - self.do_request.assert_called_once_with("DELETE", inf_path) - - def _get_route_id(self, dest, nexthop): - dest = netaddr.IPNetwork(dest) - return '-'.join([str(dest.network), nexthop, str(dest.netmask)]) - - def test_add_router_route(self): - t = uuidutils.generate_uuid() - r = uuidutils.generate_uuid() - - router_path = "/tenants/%s/routers/%s" % (_ofc(t), _ofc(r)) - routes_path = router_path + "/routes" - dest = '10.1.1.0/24' - nexthop = '192.168.100.10' - body = {'destination': dest, 'nexthop': nexthop} - route_id = self._get_route_id(dest, nexthop) - self.do_request.return_value = {'id': route_id} - - ret = self.driver.add_router_route(router_path, '10.1.1.0/24', - '192.168.100.10') - self.do_request.assert_called_once_with("POST", routes_path, body=body) - route_path = routes_path + '/' + route_id - self.assertEqual(ret, route_path) - - def test_delete_router_route(self): - t = uuidutils.generate_uuid() - r = uuidutils.generate_uuid() - - router_path = "/tenants/%s/routers/%s" % (_ofc(t), _ofc(r)) - routes_path = router_path + "/routes" - - route_id = self._get_route_id('10.1.1.0/24', '192.168.100.10') - route_path = routes_path + '/' + route_id - - self.driver.delete_router_route(route_path) - self.do_request.assert_called_once_with("DELETE", route_path) - - def test_list_router_routes(self): - t = uuidutils.generate_uuid() - r = uuidutils.generate_uuid() - - router_path = "/tenants/%s/routers/%s" % (_ofc(t), _ofc(r)) - routes_path = router_path + "/routes" - - routes = [('10.1.1.0/24', '192.168.100.10'), - ('10.2.2.0/20', '192.168.100.20')] - data = {'routes': [{'id': self._get_route_id(route[0], route[1]), - 'destination': route[0], 'nexthop': route[1]} - for route in routes]} - self.do_request.return_value = data - - ret = self.driver.list_router_routes(router_path) - self.do_request.assert_called_once_with("GET", routes_path) - - expected = [{'id': (routes_path + "/" + - self._get_route_id(route[0], route[1])), - 'destination': route[0], 'nexthop': route[1]} - for route in routes] - self.assertEqual(len(routes), len(ret)) - self.assertEqual(data['routes'], expected) - - -class PFCFilterDriverTestMixin(object): - def _test_create_filter(self, filter_dict=None, filter_post=None, - apply_ports=None): - t, n, p = self.get_ofc_item_random_params() - - filter_id = uuidutils.generate_uuid() - f = {'priority': 123, 'action': "ACCEPT", - 'network_id': n} - if filter_dict: - f.update(filter_dict) - - body = {'action': 'pass', 'priority': 123} - if filter_post: - body.update(filter_post) - - self.do_request.return_value = {'id': filter_id} - with mock.patch('neutron.plugins.nec.db.api.get_active_ports_on_ofc', - return_value=apply_ports) as active_ports: - ret = self.driver.create_filter(mock.sentinel.ctx, f) - self.do_request.assert_called_once_with("POST", "/filters", - body=body) - self.assertEqual(ret, '/filters/%s' % filter_id) - active_ports.assert_called_once_with(mock.sentinel.ctx, n, - filter_dict.get('in_port')) - - def test_create_filter_accept(self): - self._test_create_filter(filter_dict={'action': 'ACCEPT'}) - - def test_create_filter_allow(self): - self._test_create_filter(filter_dict={'action': 'ALLOW'}) - - def test_create_filter_deny(self): - self._test_create_filter(filter_dict={'action': 'DENY'}, - filter_post={'action': 'drop'}) - - def test_create_filter_drop(self): - self._test_create_filter(filter_dict={'action': 'DROP'}, - filter_post={'action': 'drop'}) - - def test_create_filter_empty_field_not_post(self): - filter_dict = {'src_mac': '', 'src_cidr': '', 'src_port': 0, - 'dst_mac': '', 'dst_cidr': '', 'dst_port': 0, - 'protocol': '', 'eth_type': 0} - filter_post = {} - self._test_create_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_create_filter_none_field_not_post(self): - filter_dict = {'src_mac': None, 'src_cidr': None, 'src_port': None, - 'dst_mac': None, 'dst_cidr': None, 'dst_port': None, - 'protocol': None, 'eth_type': None} - filter_post = {} - self._test_create_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_create_filter_all_fields(self): - filter_dict = {'src_mac': '11:22:33:44:55:66', - 'dst_mac': '77:88:99:aa:bb:cc', - 'src_cidr': '192.168.3.0/24', - 'dst_cidr': '10.11.240.0/20', - 'src_port': 12345, - 'dst_port': 23456, - 'protocol': '0x10', - 'eth_type': 0x800} - filter_post = filter_dict.copy() - filter_post['protocol'] = 16 - filter_post['eth_type'] = '0x800' - self._test_create_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_create_filter_cidr_ip_addr_32(self): - filter_dict = {'src_cidr': '192.168.3.1', - 'dst_cidr': '10.11.240.2'} - filter_post = {'src_cidr': '192.168.3.1/32', - 'dst_cidr': '10.11.240.2/32'} - self._test_create_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_create_filter_proto_tcp(self): - filter_dict = {'protocol': 'TCP'} - filter_post = {'protocol': constants.PROTO_NUM_TCP} - self._test_create_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_create_filter_proto_udp(self): - filter_dict = {'protocol': 'UDP'} - filter_post = {'protocol': constants.PROTO_NUM_UDP} - self._test_create_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_create_filter_proto_icmp(self): - filter_dict = {'protocol': 'ICMP'} - filter_post = {'protocol': constants.PROTO_NUM_ICMP} - self._test_create_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_create_filter_proto_arp_not_proto_post(self): - filter_dict = {'protocol': 'ARP'} - filter_post = {} - self._test_create_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_create_filter_apply_ports(self): - apply_ports = [ - ('p1', '/tenants/tenant-1/networks/network-1/ports/port-1'), - ('p2', '/tenants/tenant-2/networks/network-2/ports/port-2')] - filter_post = {'apply_ports': [ - {'tenant': 'tenant-1', 'network': 'network-1', 'port': 'port-1'}, - {'tenant': 'tenant-2', 'network': 'network-2', 'port': 'port-2'} - ]} - self._test_create_filter(filter_dict={}, apply_ports=apply_ports, - filter_post=filter_post) - - def test_create_filter_apply_ports_with_router_interface(self): - apply_ports = [ - ('p1', '/tenants/tenant-1/networks/network-1/ports/port-1'), - ('p2', '/tenants/tenant-2/routers/router-3/interfaces/if-4')] - filter_post = {'apply_ports': [ - {'tenant': 'tenant-1', 'network': 'network-1', 'port': 'port-1'}, - {'tenant': 'tenant-2', 'router': 'router-3', 'interface': 'if-4'} - ]} - self._test_create_filter(filter_dict={}, apply_ports=apply_ports, - filter_post=filter_post) - - def test_create_filter_apply_ports_no_router_interface_support(self): - cfg.CONF.set_override('support_packet_filter_on_ofc_router', - False, 'OFC') - apply_ports = [ - ('p1', '/tenants/tenant-1/networks/network-1/ports/port-1'), - ('p2', '/tenants/tenant-2/routers/router-3/interfaces/if-4')] - filter_post = {'apply_ports': [ - {'tenant': 'tenant-1', 'network': 'network-1', 'port': 'port-1'}, - ]} - self._test_create_filter(filter_dict={}, apply_ports=apply_ports, - filter_post=filter_post) - - def _test_update_filter(self, filter_dict=None, filter_post=None): - filter_id = uuidutils.generate_uuid() - ofc_filter_id = '/filters/%s' % filter_id - self.driver.update_filter(ofc_filter_id, filter_dict) - self.do_request.assert_called_once_with("PUT", ofc_filter_id, - body=filter_post) - - def test_update_filter_empty_fields(self): - filter_dict = {'src_mac': '', 'src_cidr': '', 'src_port': 0, - 'dst_mac': '', 'dst_cidr': '', 'dst_port': 0, - 'protocol': '', 'eth_type': 0} - filter_post = {'src_mac': '', 'src_cidr': '', 'src_port': '', - 'dst_mac': '', 'dst_cidr': '', 'dst_port': '', - 'protocol': '', 'eth_type': ''} - self._test_update_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_update_filter_none_fields(self): - filter_dict = {'src_mac': None, 'src_cidr': None, 'src_port': None, - 'dst_mac': None, 'dst_cidr': None, 'dst_port': None, - 'protocol': None, 'eth_type': None} - filter_post = {'src_mac': '', 'src_cidr': '', 'src_port': '', - 'dst_mac': '', 'dst_cidr': '', 'dst_port': '', - 'protocol': '', 'eth_type': ''} - self._test_update_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_update_filter_all_fields(self): - filter_dict = {'src_mac': '11:22:33:44:55:66', - 'dst_mac': '77:88:99:aa:bb:cc', - 'src_cidr': '192.168.3.0/24', - 'dst_cidr': '10.11.240.0/20', - 'src_port': 12345, - 'dst_port': 23456, - 'protocol': '0x10', - 'eth_type': 0x800} - filter_post = filter_dict.copy() - filter_post['protocol'] = 16 - filter_post['eth_type'] = '0x800' - self._test_update_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_update_filter_cidr_ip_addr_32(self): - filter_dict = {'src_cidr': '192.168.3.1', - 'dst_cidr': '10.11.240.2'} - filter_post = {'src_cidr': '192.168.3.1/32', - 'dst_cidr': '10.11.240.2/32'} - self._test_update_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_update_filter_proto_tcp(self): - filter_dict = {'protocol': 'TCP'} - filter_post = {'protocol': constants.PROTO_NUM_TCP} - self._test_update_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_update_filter_proto_udp(self): - filter_dict = {'protocol': 'UDP'} - filter_post = {'protocol': constants.PROTO_NUM_UDP} - self._test_update_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_update_filter_proto_icmp(self): - filter_dict = {'protocol': 'ICMP'} - filter_post = {'protocol': constants.PROTO_NUM_ICMP} - self._test_update_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_update_filter_proto_arp_post_empty(self): - filter_dict = {'protocol': 'ARP'} - filter_post = {'protocol': ''} - self._test_update_filter(filter_dict=filter_dict, - filter_post=filter_post) - - def test_delete_filter(self): - t, n, p = self.get_ofc_item_random_params() - f_path = "/filters/%s" % uuidutils.generate_uuid() - self.driver.delete_filter(f_path) - self.do_request.assert_called_once_with("DELETE", f_path) - - def _test_validate_filter_duplicate_priority(self, method, found_dup): - with mock.patch('neutron.manager.NeutronManager' - '.get_plugin') as get_plugin: - plugin = get_plugin.return_value - if found_dup: - plugin.get_packet_filters.return_value = ['found'] - else: - plugin.get_packet_filters.return_value = [] - network_id = str(uuid.uuid4()) - filter_dict = {'network_id': network_id, - 'priority': 12} - if found_dup: - self.assertRaises(ext_pf.PacketFilterDuplicatedPriority, - method, 'context', filter_dict) - else: - self.assertIsNone(method('context', filter_dict)) - plugin.get_packet_filters.assert_called_once_with( - 'context', - filters={'network_id': [network_id], - 'priority': [12]}, - fields=['id']) - - def test_validate_filter_create_no_duplicate_priority(self): - self._test_validate_filter_duplicate_priority( - self.driver.validate_filter_create, - found_dup=False) - - def test_validate_filter_create_duplicate_priority(self): - self._test_validate_filter_duplicate_priority( - self.driver.validate_filter_create, - found_dup=True) - - def test_validate_filter_update_action_raises_error(self): - filter_dict = {'action': 'ALLOW'} - self.assertRaises(ext_pf.PacketFilterUpdateNotSupported, - self.driver.validate_filter_update, - 'context', filter_dict) - - def test_validate_filter_update_priority_raises_error(self): - filter_dict = {'priority': '13'} - self.assertRaises(ext_pf.PacketFilterUpdateNotSupported, - self.driver.validate_filter_update, - 'context', filter_dict) - - def _test_validate_filter_ipv6_not_supported(self, field, create=True): - if create: - filter_dict = {'network_id': 'net1', 'priority': 12} - method = self.driver.validate_filter_create - else: - filter_dict = {} - method = self.driver.validate_filter_update - filter_dict[field] = 'fe80::1' - self.assertRaises(ext_pf.PacketFilterIpVersionNonSupported, - method, 'context', filter_dict) - filter_dict[field] = '10.56.3.3' - self.assertIsNone(method('context', filter_dict)) - - def test_validate_filter_create_ipv6_not_supported(self): - with mock.patch('neutron.manager.NeutronManager' - '.get_plugin') as get_plugin: - plugin = get_plugin.return_value - plugin.get_packet_filters.return_value = [] - self._test_validate_filter_ipv6_not_supported( - 'src_cidr', create=True) - self._test_validate_filter_ipv6_not_supported( - 'dst_cidr', create=True) - - def test_validate_filter_update_ipv6_not_supported(self): - self._test_validate_filter_ipv6_not_supported('src_cidr', create=False) - self._test_validate_filter_ipv6_not_supported('dst_cidr', create=False) - - def _test_validate_filter_priority_range_one(self, method, priority, ok): - filter_dict = {'priority': priority, 'network_id': 'net1'} - if ok: - self.assertIsNone(method('context', filter_dict)) - else: - self.assertRaises(ext_pf.PacketFilterInvalidPriority, - method, 'context', filter_dict) - - def test_validate_filter_create_priority_range(self): - with mock.patch('neutron.manager.NeutronManager' - '.get_plugin') as get_plugin: - plugin = get_plugin.return_value - plugin.get_packet_filters.return_value = [] - - method = self.driver.validate_filter_create - self._test_validate_filter_priority_range_one(method, 0, False) - self._test_validate_filter_priority_range_one(method, 1, True) - self._test_validate_filter_priority_range_one(method, 32766, True) - self._test_validate_filter_priority_range_one(method, 32767, False) - - -class PFCV51DriverTest(PFCFilterDriverTestMixin, PFCV5DriverTest): - driver = 'pfc_v51' - filter_supported = True - - def test_create_port_with_filters_argument(self): - self._test_create_port( - call_filters_arg=[('neutron-id-1', '/filters/filter-1'), - ('neutron-id-2', '/filters/filter-2')], - send_filters_arg=['filter-1', 'filter-2']) - - -class PFCDriverStringTest(base.BaseTestCase): - - driver = 'neutron.plugins.nec.drivers.pfc.PFCDriverBase' - - def setUp(self): - super(PFCDriverStringTest, self).setUp() - self.driver = drivers.get_driver(self.driver)(TestConfig) - - def test_generate_pfc_id_uuid(self): - id_str = uuidutils.generate_uuid() - exp_str = (id_str[:14] + id_str[15:]).replace('-', '')[:31] - - ret_str = self.driver._generate_pfc_id(id_str) - self.assertEqual(exp_str, ret_str) - - def test_generate_pfc_id_uuid_no_hyphen(self): - # Keystone tenant_id style uuid - id_str = uuidutils.generate_uuid() - id_no_hyphen = id_str.replace('-', '') - exp_str = (id_str[:14] + id_str[15:]).replace('-', '')[:31] - - ret_str = self.driver._generate_pfc_id(id_no_hyphen) - self.assertEqual(exp_str, ret_str) - - def test_generate_pfc_id_string(self): - id_str = uuidutils.generate_uuid() + 'x' - exp_str = id_str[:31].replace('-', '_') - - ret_str = self.driver._generate_pfc_id(id_str) - self.assertEqual(exp_str, ret_str) - - def test_generate_pfc_desc(self): - random_list = [random.choice(string.printable) for x in range(128)] - random_str = ''.join(random_list) - - accept_letters = string.letters + string.digits - exp_list = [x if x in accept_letters else '_' for x in random_list] - exp_str = ''.join(exp_list)[:127] - - ret_str = self.driver._generate_pfc_description(random_str) - self.assertEqual(exp_str, ret_str) diff --git a/neutron/tests/unit/nec/test_portbindings.py b/neutron/tests/unit/nec/test_portbindings.py deleted file mode 100644 index c2975ca21..000000000 --- a/neutron/tests/unit/nec/test_portbindings.py +++ /dev/null @@ -1,345 +0,0 @@ -# Copyright 2013 NEC Corporation -# 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 oslo_config import cfg -from testtools import matchers -from webob import exc - -from neutron.common import exceptions as n_exc -from neutron import context -from neutron.extensions import portbindings -from neutron.tests.unit import _test_extension_portbindings as test_bindings -from neutron.tests.unit.nec import test_nec_plugin -from neutron.tests.unit import test_security_groups_rpc as test_sg_rpc - - -class TestNecPortBinding(test_bindings.PortBindingsTestCase, - test_nec_plugin.NecPluginV2TestCase): - VIF_TYPE = portbindings.VIF_TYPE_OVS - VIF_DETAILS = {portbindings.CAP_PORT_FILTER: True, - portbindings.OVS_HYBRID_PLUG: True} - ENABLE_SG = True - FIREWALL_DRIVER = test_sg_rpc.FIREWALL_HYBRID_DRIVER - - def setUp(self): - test_sg_rpc.set_firewall_driver(self.FIREWALL_DRIVER) - cfg.CONF.set_override( - 'enable_security_group', self.ENABLE_SG, - group='SECURITYGROUP') - super(TestNecPortBinding, self).setUp() - - -class TestNecPortBindingNoSG(TestNecPortBinding): - VIF_DETAILS = {portbindings.CAP_PORT_FILTER: False, - portbindings.OVS_HYBRID_PLUG: False} - ENABLE_SG = False - FIREWALL_DRIVER = test_sg_rpc.FIREWALL_NOOP_DRIVER - - -class TestNecPortBindingHost( - test_bindings.PortBindingsHostTestCaseMixin, - test_nec_plugin.NecPluginV2TestCase): - pass - - -class TestNecPortBindingPortInfo(test_nec_plugin.NecPluginV2TestCase): - def _get_portinfo(self, datapath_id=None, port_no=None): - if datapath_id is None: - datapath_id = '0xabc' - if port_no is None: - port_no = 1 - return {'datapath_id': datapath_id, - 'port_no': port_no} - - def _check_response_portbinding_profile(self, port, datapath_id=None, - port_no=None): - expected = self._get_portinfo(datapath_id, port_no) - profile = port[portbindings.PROFILE] - self.assertEqual(len(profile), 2) - self.assertEqual(profile['datapath_id'], - expected['datapath_id']) - self.assertEqual(profile['port_no'], - expected['port_no']) - - def _check_response_portbinding_no_profile(self, port): - self.assertIn('status', port) - self.assertNotIn(portbindings.PROFILE, port) - - def _get_non_admin_context(self): - return context.Context(user_id=None, - tenant_id=self._tenant_id, - is_admin=False, - read_deleted="no") - - def test_port_create_portinfo(self): - profile_arg = {portbindings.PROFILE: self._get_portinfo()} - with self.port(arg_list=(portbindings.PROFILE,), - **profile_arg) as port: - port_id = port['port']['id'] - # Check a response of create_port - self._check_response_portbinding_profile(port['port']) - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - # Check a response of get_port - ctx = context.get_admin_context() - port = self._show('ports', port_id, neutron_context=ctx)['port'] - self._check_response_portbinding_profile(port) - # By default user is admin - now test non admin user - ctx = self._get_non_admin_context() - non_admin_port = self._show( - 'ports', port_id, neutron_context=ctx)['port'] - self._check_response_portbinding_no_profile(non_admin_port) - # port-update with non admin user should fail - self._update('ports', port_id, - {'port': profile_arg}, - expected_code=exc.HTTPForbidden.code, - neutron_context=ctx) - - def test_port_update_portinfo(self): - profile_arg = {portbindings.PROFILE: self._get_portinfo()} - with self.port() as port: - self.assertEqual(self.ofc.create_ofc_port.call_count, 0) - port_id = port['port']['id'] - # Check a response of create_port - self._check_response_portbinding_no_profile(port['port']) - # Check a response of update_port - ctx = context.get_admin_context() - port = self._update('ports', port_id, {'port': profile_arg}, - neutron_context=ctx)['port'] - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self._check_response_portbinding_profile(port) - port = self._show('ports', port_id, neutron_context=ctx)['port'] - self._check_response_portbinding_profile(port) - - def test_port_update_portinfo_detail(self): - with self.port() as port: - self.assertEqual(self.ofc.create_ofc_port.call_count, 0) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 0) - port_id = port['port']['id'] - ctx = context.get_admin_context() - - # add portinfo - profile_arg = {portbindings.PROFILE: self._get_portinfo()} - port = self._update('ports', port_id, {'port': profile_arg}, - neutron_context=ctx)['port'] - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 0) - - # portinfo unchanged - port = self._update('ports', port_id, {'port': profile_arg}, - neutron_context=ctx)['port'] - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 0) - - # modify portinfo - profile_arg = {portbindings.PROFILE: - self._get_portinfo(datapath_id='0x1234567890', - port_no=99)} - port = self._update('ports', port_id, {'port': profile_arg}, - neutron_context=ctx)['port'] - self.assertEqual(self.ofc.create_ofc_port.call_count, 2) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 1) - - # delete portinfo with an empty dict - profile_arg = {portbindings.PROFILE: {}} - port = self._update('ports', port_id, {'port': profile_arg}, - neutron_context=ctx)['port'] - self.assertEqual(self.ofc.create_ofc_port.call_count, 2) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 2) - - def test_port_update_portinfo_detail_clear_with_none(self): - with self.port() as port: - self.assertEqual(self.ofc.create_ofc_port.call_count, 0) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 0) - port_id = port['port']['id'] - ctx = context.get_admin_context() - - # add portinfo - profile_arg = {portbindings.PROFILE: self._get_portinfo()} - port = self._update('ports', port_id, {'port': profile_arg}, - neutron_context=ctx)['port'] - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 0) - - # delete portinfo with None - profile_arg = {portbindings.PROFILE: None} - port = self._update('ports', port_id, {'port': profile_arg}, - neutron_context=ctx)['port'] - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 1) - - def test_port_create_portinfo_with_empty_dict(self): - profile_arg = {portbindings.PROFILE: {}} - with self.port(arg_list=(portbindings.PROFILE,), - **profile_arg) as port: - port_id = port['port']['id'] - - # Check a response of create_port - self._check_response_portbinding_no_profile(port['port']) - self.assertEqual(self.ofc.create_ofc_port.call_count, 0) - # add portinfo - ctx = context.get_admin_context() - profile_arg = {portbindings.PROFILE: self._get_portinfo()} - port = self._update('ports', port_id, {'port': profile_arg}, - neutron_context=ctx)['port'] - self._check_response_portbinding_profile(port) - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 0) - - def test_port_create_portinfo_with_none(self): - profile_arg = {portbindings.PROFILE: None} - with self.port(arg_list=(portbindings.PROFILE,), - **profile_arg) as port: - port_id = port['port']['id'] - - # Check a response of create_port - self._check_response_portbinding_no_profile(port['port']) - self.assertEqual(self.ofc.create_ofc_port.call_count, 0) - # add portinfo - ctx = context.get_admin_context() - profile_arg = {portbindings.PROFILE: self._get_portinfo()} - port = self._update('ports', port_id, {'port': profile_arg}, - neutron_context=ctx)['port'] - self._check_response_portbinding_profile(port) - self.assertEqual(self.ofc.create_ofc_port.call_count, 1) - self.assertEqual(self.ofc.delete_ofc_port.call_count, 0) - - def test_port_update_for_existing_port_with_different_padding_dpid(self): - ctx = context.get_admin_context() - with self.port() as port: - port_id = port['port']['id'] - portinfo = {'id': port_id, 'port_no': 123} - self.rpcapi_update_ports(datapath_id='0x000000000000abcd', - added=[portinfo]) - self.assertEqual(1, self.ofc.create_ofc_port.call_count) - self.assertEqual(0, self.ofc.delete_ofc_port.call_count) - - profile_arg = {portbindings.PROFILE: - self._get_portinfo(datapath_id='0xabcd', - port_no=123)} - self._update('ports', port_id, {'port': profile_arg}, - neutron_context=ctx) - # Check create_ofc_port/delete_ofc_port are not called. - self.assertEqual(1, self.ofc.create_ofc_port.call_count) - self.assertEqual(0, self.ofc.delete_ofc_port.call_count) - - def test_port_create_portinfo_non_admin(self): - with self.network(set_context=True, tenant_id='test') as net1: - with self.subnet(network=net1) as subnet1: - profile_arg = {portbindings.PROFILE: self._get_portinfo()} - try: - with self.port(subnet=subnet1, - expected_res_status=403, - arg_list=(portbindings.PROFILE,), - set_context=True, tenant_id='test', - **profile_arg): - pass - except exc.HTTPClientError: - pass - self.assertEqual(self.ofc.create_ofc_port.call_count, 0) - - def test_port_update_portinfo_non_admin(self): - profile_arg = {portbindings.PROFILE: self._get_portinfo()} - with self.network() as net1: - with self.subnet(network=net1) as subnet1: - with self.port(subnet=subnet1) as port: - # By default user is admin - now test non admin user - port_id = port['port']['id'] - ctx = self._get_non_admin_context() - port = self._update('ports', port_id, - {'port': profile_arg}, - expected_code=exc.HTTPForbidden.code, - neutron_context=ctx) - self.assertEqual(self.ofc.create_ofc_port.call_count, 0) - - def test_port_create_portinfo_validation_called(self): - # Check validate_portinfo is called. - profile_arg = {portbindings.PROFILE: - {'datapath_id': '0xabc', - 'port_no': 0xffff + 1}} - try: - with self.port(arg_list=(portbindings.PROFILE,), - expected_res_status=400, - **profile_arg): - pass - except exc.HTTPClientError: - pass - - -class TestNecPortBindingValidatePortInfo(test_nec_plugin.NecPluginV2TestCase): - - def test_validate_portinfo_ok(self): - profile = {'datapath_id': '0x1234567890abcdef', - 'port_no': 123} - portinfo = self.plugin._validate_portinfo(profile) - # NOTE(mriedem): Handle long integer conversion universally. - self.assertEqual( - 0x1234567890abcdef, - int(portinfo['datapath_id'].replace('L', ''), 16) - ) - self.assertEqual(portinfo['port_no'], 123) - - def test_validate_portinfo_ok_without_0x(self): - profile = {'datapath_id': '1234567890abcdef', - 'port_no': 123} - portinfo = self.plugin._validate_portinfo(profile) - # NOTE(mriedem): Handle long integer conversion universally. - self.assertEqual( - 0x1234567890abcdef, - int(portinfo['datapath_id'].replace('L', ''), 16) - ) - self.assertEqual(portinfo['port_no'], 123) - - def _test_validate_exception(self, profile, expected_msg): - e = self.assertRaises(n_exc.InvalidInput, - self.plugin._validate_portinfo, profile) - self.assertThat(str(e), matchers.StartsWith(expected_msg)) - - def test_validate_portinfo_dict_validation(self): - expected_msg = ("Invalid input for operation: " - "Validation of dictionary's keys failed.") - - profile = {'port_no': 123} - self._test_validate_exception(profile, expected_msg) - - profile = {'datapath_id': '0xabcdef'} - self._test_validate_exception(profile, expected_msg) - - def test_validate_portinfo_negative_port_number(self): - profile = {'datapath_id': '0x1234567890abcdef', - 'port_no': -1} - expected_msg = ("Invalid input for operation: " - "'-1' should be non-negative.") - self._test_validate_exception(profile, expected_msg) - - def test_validate_portinfo_invalid_datapath_id(self): - expected_msg = ("Invalid input for operation: " - "datapath_id should be a hex string") - - # non hexidecimal datapath_id - profile = {'datapath_id': 'INVALID', - 'port_no': 123} - self._test_validate_exception(profile, expected_msg) - - # Too big datapath_id - profile = {'datapath_id': '0x10000000000000000', - 'port_no': 123} - self._test_validate_exception(profile, expected_msg) - - def test_validate_portinfo_too_big_port_number(self): - profile = {'datapath_id': '0x1234567890abcdef', - 'port_no': 65536} - expected_msg = ("Invalid input for operation: " - "port_no should be [0:65535]") - self._test_validate_exception(profile, expected_msg) diff --git a/neutron/tests/unit/nec/test_router.py b/neutron/tests/unit/nec/test_router.py deleted file mode 100644 index 5f3fc0035..000000000 --- a/neutron/tests/unit/nec/test_router.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import mock - -from neutron import manager -from neutron.plugins.nec.common import config -from neutron.tests.unit.nec import test_nec_plugin -from neutron.tests.unit import test_extension_extraroute as test_ext_route - - -class NecRouterL3AgentTestCase(test_ext_route.ExtraRouteDBIntTestCase): - - _plugin_name = test_nec_plugin.PLUGIN_NAME - - def setUp(self): - mock.patch(test_nec_plugin.OFC_MANAGER).start() - super(NecRouterL3AgentTestCase, self).setUp(self._plugin_name) - - plugin = manager.NeutronManager.get_plugin() - plugin.network_scheduler = None - plugin.router_scheduler = None - - def test_floatingip_with_invalid_create_port(self): - self._test_floatingip_with_invalid_create_port(self._plugin_name) - - -class NecRouterOpenFlowTestCase(NecRouterL3AgentTestCase): - - def setUp(self): - config.CONF.set_override('default_router_provider', - 'openflow', 'PROVIDER') - super(NecRouterOpenFlowTestCase, self).setUp() diff --git a/neutron/tests/unit/nec/test_security_group.py b/neutron/tests/unit/nec/test_security_group.py deleted file mode 100644 index 2b29b59da..000000000 --- a/neutron/tests/unit/nec/test_security_group.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright 2013, NEC Corporation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import contextlib - -import mock - -from neutron.api.v2 import attributes -from neutron.extensions import securitygroup as ext_sg -from neutron import manager -from neutron.tests.unit.nec import test_nec_plugin -from neutron.tests.unit import test_extension_security_group as test_sg -from neutron.tests.unit import test_security_groups_rpc as test_sg_rpc - -PLUGIN_NAME = test_nec_plugin.PLUGIN_NAME -OFC_MANAGER = 'neutron.plugins.nec.nec_plugin.ofc_manager.OFCManager' -NOTIFIER = 'neutron.plugins.nec.nec_plugin.NECPluginV2AgentNotifierApi' - - -class NecSecurityGroupsTestCase(test_sg.SecurityGroupDBTestCase): - - def setUp(self, plugin=None): - test_sg_rpc.set_firewall_driver(test_sg_rpc.FIREWALL_HYBRID_DRIVER) - mock.patch(NOTIFIER).start() - mock.patch(OFC_MANAGER).start() - self._attribute_map_bk_ = {} - for item in attributes.RESOURCE_ATTRIBUTE_MAP: - self._attribute_map_bk_[item] = (attributes. - RESOURCE_ATTRIBUTE_MAP[item]. - copy()) - super(NecSecurityGroupsTestCase, self).setUp(PLUGIN_NAME) - plugin = manager.NeutronManager.get_plugin() - self.notifier = plugin.notifier - self.rpc = plugin.callback_sg - - def tearDown(self): - super(NecSecurityGroupsTestCase, self).tearDown() - attributes.RESOURCE_ATTRIBUTE_MAP = self._attribute_map_bk_ - - -class TestNecSGServerRpcCallBack( - test_sg_rpc.SGServerRpcCallBackTestCase, - NecSecurityGroupsTestCase): - pass - - -class TestNecSecurityGroups(NecSecurityGroupsTestCase, - test_sg.TestSecurityGroups, - test_sg_rpc.SGNotificationTestMixin): - - def test_security_group_get_port_from_device(self): - with contextlib.nested(self.network(), - self.security_group()) as (n, sg): - with self.subnet(n): - res = self._create_port(self.fmt, n['network']['id']) - port = self.deserialize(self.fmt, res) - port_id = port['port']['id'] - sg_id = sg['security_group']['id'] - fixed_ips = port['port']['fixed_ips'] - - data = {'port': {'fixed_ips': fixed_ips, - 'name': port['port']['name'], - ext_sg.SECURITYGROUPS: [sg_id]}} - req = self.new_update_request('ports', data, port_id) - res = self.deserialize(self.fmt, - req.get_response(self.api)) - - plugin = manager.NeutronManager.get_plugin() - 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]) - self.assertEqual([], port_dict['security_group_rules']) - self.assertEqual([fixed_ips[0]['ip_address']], - port_dict['fixed_ips']) - self._delete('ports', port_id) diff --git a/neutron/tests/unit/nec/test_trema_driver.py b/neutron/tests/unit/nec/test_trema_driver.py deleted file mode 100644 index 766f3b233..000000000 --- a/neutron/tests/unit/nec/test_trema_driver.py +++ /dev/null @@ -1,363 +0,0 @@ -# Copyright 2012 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import random - -import mock -from six import moves - -from neutron.openstack.common import uuidutils -from neutron.plugins.nec.common import exceptions as nexc -from neutron.plugins.nec.common import ofc_client -from neutron.plugins.nec.db import models as nmodels -from neutron.plugins.nec import drivers -from neutron.tests import base - - -class TestConfig(object): - """Configuration for this test.""" - host = '127.0.0.1' - port = 8888 - - -class TremaDriverTestBase(base.BaseTestCase): - - driver_name = "trema" - - def setUp(self): - super(TremaDriverTestBase, self).setUp() - self.driver = drivers.get_driver(self.driver_name)(TestConfig) - self.do_request = mock.patch.object(ofc_client.OFCClient, - 'do_request').start() - - def get_ofc_item_random_params(self): - """create random parameters for ofc_item test.""" - tenant_id = uuidutils.generate_uuid() - network_id = uuidutils.generate_uuid() - port_id = uuidutils.generate_uuid() - mac = ':'.join(['%x' % random.randint(0, 255) - for i in moves.xrange(6)]) - portinfo = nmodels.PortInfo(id=port_id, datapath_id="0x123456789", - port_no=1234, vlan_id=321, - mac=mac) - return tenant_id, network_id, portinfo - - -class TremaDriverNetworkTestBase(TremaDriverTestBase): - - def test_create_tenant(self): - t, n, p = self.get_ofc_item_random_params() - ret = self.driver.create_tenant('dummy_desc', t) - ofc_t_path = "/tenants/%s" % t - self.assertEqual(ofc_t_path, ret) - # There is no API call. - self.assertEqual(0, self.do_request.call_count) - - def test_update_tenant(self): - t, n, p = self.get_ofc_item_random_params() - path = "/tenants/%s" % t - self.driver.update_tenant(path, 'dummy_desc') - # There is no API call. - self.assertEqual(0, self.do_request.call_count) - - def testc_delete_tenant(self): - t, n, p = self.get_ofc_item_random_params() - path = "/tenants/%s" % t - self.driver.delete_tenant(path) - # There is no API call. - self.assertEqual(0, self.do_request.call_count) - - def testa_create_network(self): - t, n, p = self.get_ofc_item_random_params() - description = "desc of %s" % n - body = {'id': n, 'description': description} - ret = self.driver.create_network(t, description, n) - self.do_request.assert_called_once_with("POST", "/networks", body=body) - self.assertEqual(ret, '/networks/%s' % n) - - def testc_delete_network(self): - t, n, p = self.get_ofc_item_random_params() - net_path = "/networks/%s" % n - self.driver.delete_network(net_path) - self.do_request.assert_called_once_with("DELETE", net_path) - - -class TremaPortBaseDriverTest(TremaDriverNetworkTestBase): - - driver_name = "trema_port" - - def test_filter_supported(self): - self.assertTrue(self.driver.filter_supported()) - - def testd_create_port(self): - _t, n, p = self.get_ofc_item_random_params() - net_path = "/networks/%s" % n - body = {'id': p.id, - 'datapath_id': p.datapath_id, - 'port': str(p.port_no), - 'vid': str(p.vlan_id)} - ret = self.driver.create_port(net_path, p, p.id) - self.do_request.assert_called_once_with( - "POST", "/networks/%s/ports" % n, body=body) - self.assertEqual(ret, '/networks/%s/ports/%s' % (n, p.id)) - - def testd_delete_port(self): - t, n, p = self.get_ofc_item_random_params() - p_path = "/networks/%s/ports/%s" % (n, p.id) - self.driver.delete_port(p_path) - self.do_request.assert_called_once_with("DELETE", p_path) - - -class TremaPortMACBaseDriverTest(TremaDriverNetworkTestBase): - - driver_name = "trema_portmac" - - def test_filter_supported(self): - self.assertTrue(self.driver.filter_supported()) - - def testd_create_port(self): - t, n, p = self.get_ofc_item_random_params() - dummy_port = "dummy-%s" % p.id - - net_path = "/networks/%s" % n - path_1 = "/networks/%s/ports" % n - body_1 = {'id': dummy_port, - 'datapath_id': p.datapath_id, - 'port': str(p.port_no), - 'vid': str(p.vlan_id)} - path_2 = "/networks/%s/ports/%s/attachments" % (n, dummy_port) - body_2 = {'id': p.id, 'mac': p.mac} - path_3 = "/networks/%s/ports/%s" % (n, dummy_port) - ret = self.driver.create_port(net_path, p, p.id) - - self.do_request.assert_has_calls([ - mock.call("POST", path_1, body=body_1), - mock.call("POST", path_2, body=body_2), - mock.call("DELETE", path_3) - ]) - port_path = "/networks/%s/ports/%s/attachments/%s" % (n, dummy_port, - p.id) - self.assertEqual(ret, port_path) - - def testd_delete_port(self): - t, n, p = self.get_ofc_item_random_params() - dummy_port = "dummy-%s" % p.id - path = "/networks/%s/ports/%s/attachments/%s" % (n, dummy_port, p.id) - self.driver.delete_port(path) - self.do_request.assert_called_once_with("DELETE", path) - - -class TremaMACBaseDriverTest(TremaDriverNetworkTestBase): - - driver_name = "trema_mac" - - def test_filter_supported(self): - self.assertFalse(self.driver.filter_supported()) - - def testd_create_port(self): - t, n, p = self.get_ofc_item_random_params() - net_path = "/networks/%s" % n - path = "/networks/%s/attachments" % n - body = {'id': p.id, 'mac': p.mac} - ret = self.driver.create_port(net_path, p, p.id) - self.do_request.assert_called_once_with("POST", path, body=body) - self.assertEqual(ret, '/networks/%s/attachments/%s' % (n, p.id)) - - def testd_delete_port(self): - t, n, p = self.get_ofc_item_random_params() - path = "/networks/%s/attachments/%s" % (n, p.id) - self.driver.delete_port(path) - self.do_request.assert_called_once_with("DELETE", path) - - -class TremaFilterDriverTest(TremaDriverTestBase): - def _test_create_filter(self, filter_dict=None, filter_post=None, - filter_wildcards=None, no_portinfo=False): - t, n, p = self.get_ofc_item_random_params() - src_mac = ':'.join(['%x' % random.randint(0, 255) - for i in moves.xrange(6)]) - if filter_wildcards is None: - filter_wildcards = [] - - f = {'tenant_id': t, - 'id': uuidutils.generate_uuid(), - 'network_id': n, - 'priority': 123, - 'action': "ACCEPT", - 'in_port': p.id, - 'src_mac': src_mac, - 'dst_mac': "", - 'eth_type': 0, - 'src_cidr': "", - 'dst_cidr': "", - 'src_port': 0, - 'dst_port': 0, - 'protocol': "TCP", - 'admin_state_up': True, - 'status': "ACTIVE"} - if filter_dict: - f.update(filter_dict) - - net_path = "/networks/%s" % n - - all_wildcards_ofp = ['dl_vlan', 'dl_vlan_pcp', 'nw_tos', - 'in_port', 'dl_src', 'dl_dst', - 'nw_src', 'nw_dst', - 'dl_type', 'nw_proto', - 'tp_src', 'tp_dst'] - all_wildcards_non_ofp = ['in_datapath_id', 'slice'] - - body = {'id': f['id'], - 'action': 'ALLOW', - 'priority': 123, - 'slice': n, - 'in_datapath_id': '0x123456789', - 'in_port': 1234, - 'nw_proto': '0x6', - 'dl_type': '0x800', - 'dl_src': src_mac} - if filter_post: - body.update(filter_post) - - if no_portinfo: - filter_wildcards += ['in_datapath_id', 'in_port'] - p = None - - for field in filter_wildcards: - if field in body: - del body[field] - - ofp_wildcards = ["%s:32" % _f if _f in ['nw_src', 'nw_dst'] else _f - for _f in all_wildcards_ofp if _f not in body] - body['ofp_wildcards'] = set(ofp_wildcards) - - non_ofp_wildcards = [_f for _f in all_wildcards_non_ofp - if _f not in body] - if non_ofp_wildcards: - body['wildcards'] = set(non_ofp_wildcards) - - ctx = mock.Mock() - ctx.session = mock.sentinel.session - with mock.patch('neutron.plugins.nec.db.api.get_portinfo', - return_value=p) as get_portinfo: - with mock.patch('neutron.plugins.nec.db.api.get_ofc_id', - return_value=net_path) as get_ofc_id: - ret = self.driver.create_filter(ctx, f, f['id']) - - # The content of 'body' is checked below. - self.do_request.assert_called_once_with("POST", "/filters", - body=mock.ANY) - self.assertEqual(ret, '/filters/%s' % f['id']) - - # ofp_wildcards and wildcards in body are comma-separated - # string but the order of elements are not considered, - # so we check these fields as set. - actual_body = self.do_request.call_args[1]['body'] - if 'ofp_wildcards' in actual_body: - ofp_wildcards = actual_body['ofp_wildcards'].split(',') - actual_body['ofp_wildcards'] = set(ofp_wildcards) - if 'wildcards' in actual_body: - actual_body['wildcards'] = set(actual_body['wildcards'].split(',')) - self.assertEqual(body, actual_body) - - get_ofc_id.assert_called_once_with(mock.sentinel.session, - 'ofc_network', n) - get_portinfo.assert_called_once_with(mock.sentinel.session, p.id) - - def test_create_filter_accept(self): - self._test_create_filter(filter_dict={'action': 'ACCEPT'}) - - def test_create_filter_allow(self): - self._test_create_filter(filter_dict={'action': 'ALLOW'}) - - def test_create_filter_deny(self): - self._test_create_filter(filter_dict={'action': 'DENY'}, - filter_post={'action': 'DENY'}) - - def test_create_filter_drop(self): - self._test_create_filter(filter_dict={'action': 'DROP'}, - filter_post={'action': 'DENY'}) - - def test_create_filter_no_port(self): - self.assertRaises(nexc.PortInfoNotFound, - self._test_create_filter, no_portinfo=True) - - def test_create_filter_src_mac_wildcard(self): - self._test_create_filter(filter_dict={'src_mac': ''}, - filter_wildcards=['dl_src']) - - def test_create_filter_dst_mac(self): - dst_mac = ':'.join(['%x' % random.randint(0, 255) - for i in moves.xrange(6)]) - self._test_create_filter(filter_dict={'dst_mac': dst_mac}, - filter_post={'dl_dst': dst_mac}) - - def test_create_filter_src_cidr(self): - src_cidr = '10.2.0.0/24' - self._test_create_filter(filter_dict={'src_cidr': src_cidr}, - filter_post={'nw_src': src_cidr}) - - def test_create_filter_dst_cidr(self): - dst_cidr = '192.168.10.0/24' - self._test_create_filter(filter_dict={'dst_cidr': dst_cidr}, - filter_post={'nw_dst': dst_cidr}) - - def test_create_filter_proto_icmp(self): - self._test_create_filter( - filter_dict={'protocol': 'icmp'}, - filter_post={'dl_type': '0x800', 'nw_proto': '0x1'}) - - def test_create_filter_proto_tcp(self): - self._test_create_filter( - filter_dict={'protocol': 'tcp'}, - filter_post={'dl_type': '0x800', 'nw_proto': '0x6'}) - - def test_create_filter_proto_udp(self): - self._test_create_filter( - filter_dict={'protocol': 'udp'}, - filter_post={'dl_type': '0x800', 'nw_proto': '0x11'}) - - def test_create_filter_proto_arp(self): - self._test_create_filter( - filter_dict={'protocol': 'arp'}, - filter_post={'dl_type': '0x806'}, - filter_wildcards=['nw_proto']) - - def test_create_filter_proto_misc(self): - self._test_create_filter( - filter_dict={'protocol': '0x33', 'eth_type': '0x900'}, - filter_post={'dl_type': '0x900', 'nw_proto': '0x33'}) - - def test_create_filter_proto_misc_dl_type_wildcard(self): - self._test_create_filter( - filter_dict={'protocol': '0x33', 'ether_type': ''}, - filter_post={'nw_proto': '0x33'}, - filter_wildcards=['dl_type']) - - def test_create_filter_proto_wildcard(self): - self._test_create_filter( - filter_dict={'protocol': ''}, - filter_wildcards=['dl_type', 'nw_proto']) - - def test_create_filter_src_dst_port(self): - self._test_create_filter(filter_dict={'src_port': 8192, - 'dst_port': 4096}, - filter_post={'tp_src': '0x2000', - 'tp_dst': '0x1000'}) - - def testb_delete_filter(self): - t, n, p = self.get_ofc_item_random_params() - f_path = "/filters/%s" % uuidutils.generate_uuid() - self.driver.delete_filter(f_path) - self.do_request.assert_called_once_with("DELETE", f_path) diff --git a/neutron/tests/unit/nec/test_utils.py b/neutron/tests/unit/nec/test_utils.py deleted file mode 100644 index c8a8ac7bc..000000000 --- a/neutron/tests/unit/nec/test_utils.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2014 NEC Corporation. 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.plugins.nec.common import utils -from neutron.tests import base - - -class NecUtilsTest(base.BaseTestCase): - - def test_cmp_dpid(self): - self.assertTrue(utils.cmp_dpid('0xabcd', '0xabcd')) - self.assertTrue(utils.cmp_dpid('abcd', '0xabcd')) - self.assertTrue(utils.cmp_dpid('0x000000000000abcd', '0xabcd')) - self.assertTrue(utils.cmp_dpid('0x000000000000abcd', '0x00abcd')) - self.assertFalse(utils.cmp_dpid('0x000000000000abcd', '0xabc0')) - self.assertFalse(utils.cmp_dpid('0x000000000000abcd', '0x00abc0')) - - def test_cmp_dpid_with_exception(self): - self.assertFalse(utils.cmp_dpid('0xabcx', '0xabcx')) - self.assertFalse(utils.cmp_dpid(None, None)) diff --git a/setup.cfg b/setup.cfg index 102756c3a..7af3c80eb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -98,7 +98,7 @@ console_scripts = neutron-linuxbridge-agent = neutron.plugins.linuxbridge.agent.linuxbridge_neutron_agent:main neutron-metadata-agent = neutron.cmd.eventlet.agents.metadata:main neutron-mlnx-agent = neutron.plugins.mlnx.agent.eswitch_neutron_agent:main - neutron-nec-agent = neutron.plugins.nec.agent.nec_neutron_agent:main + neutron-nec-agent = neutron.cmd.eventlet.plugins.nec_neutron_agent:main neutron-netns-cleanup = neutron.cmd.netns_cleanup:main neutron-ns-metadata-proxy = neutron.cmd.eventlet.agents.metadata_proxy:main neutron-nvsd-agent = neutron.plugins.oneconvergence.agent.nvsd_neutron_agent:main