+-------------------------------+-----------------------+-----------+------------------+---------+--------------+
| networking-mlnx_ | | | | | |
+-------------------------------+-----------------------+-----------+------------------+---------+--------------+
+| networking-nec_ | core | yes | no | [C] | Kilo |
++-------------------------------+-----------------------+-----------+------------------+---------+--------------+
| nuage-openstack-neutron_ | | | | | |
+-------------------------------+-----------------------+-----------+------------------+---------+--------------+
| networking-odl_ | ml2,l3,lb,fw | yes | no | [C] | Kilo |
.. _networking-mlnx:
+.. _networking-nec:
+
+NEC
+---
+
+* Git: https://github.com/stackforge/networking-nec
+* Launchpad: https://launchpad.net/networking-nec
+
.. _nuage-openstack-neutron:
.. _networking-odl:
-# 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
# 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()
-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
+++ /dev/null
-#!/usr/bin/env python
-# Copyright 2012 NEC Corporation.
-# Based on ryu/openvswitch agents.
-#
-# Copyright 2012 Isaku Yamahata <yamahata at private email ne jp>
-# 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()
+++ /dev/null
-# 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'
+++ /dev/null
-# 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.")
+++ /dev/null
-# 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)
from oslo_config import cfg
from neutron.agent.common import config
-from neutron.plugins.nec.common import constants as nconst
ovs_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)
+++ /dev/null
-# 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
+++ /dev/null
-# 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
+++ /dev/null
-# 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
+++ /dev/null
-# 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)
+++ /dev/null
-# 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<tenant_id>[^/]+)/networks/(?P<network_id>[^/]+)$")
- match_ofc_port_id = re.compile(
- "^/tenants/(?P<tenant_id>[^/]+)/networks/(?P<network_id>[^/]+)"
- "/ports/(?P<port_id>[^/]+)$")
-
- 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<filter_id>[^/]+)$")
-
- @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<tenant_id>[^/]+)/routers/(?P<router_id>[^/]+)"
- "/interfaces/(?P<router_inf_id>[^/]+)$")
-
- 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 : <ip_address>/<netmask> (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 : <ip_address>/<netmask> (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
+++ /dev/null
-# 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/<network-id>
- return ofc_network_id.split('/')[2]
-
- def _get_tenant_id(self, tenant_id):
- # Trema does not use tenant_id, but it returns
- # /tenants/<tenant_id> 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)
# 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",
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.' + <hostname>,
- 'datapath_id': <datapath_id of br-int on remote host>,
- 'port_added': [<new PortInfo>,...],
- 'port_removed': [<removed Port ID>,...]}
- """
- 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
+++ /dev/null
-# 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]
+++ /dev/null
-# 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
+++ /dev/null
-# 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'])
+++ /dev/null
-# 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)
--- /dev/null
+networking-nec>=2015.1,<2015.2
+++ /dev/null
-# 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)
+++ /dev/null
-# 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]
+++ /dev/null
-# 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
+++ /dev/null
-# 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)
+++ /dev/null
-# 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)
+++ /dev/null
-# 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)
+++ /dev/null
-# 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()
- ])
+++ /dev/null
-# Copyright (c) 2012 OpenStack Foundation.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-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
+++ /dev/null
-# 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)
+++ /dev/null
-# 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)
+++ /dev/null
-# 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)
+++ /dev/null
-# 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)
+++ /dev/null
-# 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)
+++ /dev/null
-# 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()
+++ /dev/null
-# 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)
+++ /dev/null
-# 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)
+++ /dev/null
-# 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))
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