From af4de720545167b8ca29f1256ec577b5dc108237 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Mon, 26 Jan 2015 16:41:24 +0900 Subject: [PATCH] ofagent: Vendor code decomposition networking-ofagent is now available on StackForge. (http://git.openstack.org/cgit/stackforge/networking-ofagent) Partially-implements: blueprint core-vendor-decomposition Closes-Bug: #1412653 Change-Id: I8a5bd10a346df5ec726635c47f18bb5c472823ed --- doc/source/devref/contribute.rst | 2 +- etc/neutron/rootwrap.d/ofagent.filters | 16 - neutron/plugins/ml2/drivers/mech_ofagent.py | 57 -- neutron/plugins/ofagent/README | 100 --- neutron/plugins/ofagent/__init__.py | 0 neutron/plugins/ofagent/agent/__init__.py | 0 neutron/plugins/ofagent/agent/arp_lib.py | 187 ---- neutron/plugins/ofagent/agent/constants.py | 19 - neutron/plugins/ofagent/agent/flows.py | 407 --------- neutron/plugins/ofagent/agent/main.py | 38 - neutron/plugins/ofagent/agent/metadata.py | 26 - neutron/plugins/ofagent/agent/ofswitch.py | 78 -- neutron/plugins/ofagent/agent/ports.py | 90 -- neutron/plugins/ofagent/agent/tables.py | 62 -- neutron/plugins/ofagent/common/__init__.py | 0 neutron/plugins/ofagent/common/config.py | 36 - .../unit/ml2/drivers/test_ofagent_mech.py | 98 --- neutron/tests/unit/ofagent/__init__.py | 0 neutron/tests/unit/ofagent/fake_oflib.py | 150 ---- neutron/tests/unit/ofagent/ofa_test_base.py | 71 -- neutron/tests/unit/ofagent/test_arp_lib.py | 334 -------- neutron/tests/unit/ofagent/test_ofa_flows.py | 384 --------- .../unit/ofagent/test_ofa_neutron_agent.py | 798 ------------------ neutron/tests/unit/ofagent/test_ofa_ports.py | 54 -- neutron/tests/unit/ofagent/test_ofswitch.py | 82 -- setup.cfg | 4 +- 26 files changed, 2 insertions(+), 3091 deletions(-) delete mode 100644 etc/neutron/rootwrap.d/ofagent.filters delete mode 100644 neutron/plugins/ml2/drivers/mech_ofagent.py delete mode 100644 neutron/plugins/ofagent/README delete mode 100644 neutron/plugins/ofagent/__init__.py delete mode 100644 neutron/plugins/ofagent/agent/__init__.py delete mode 100644 neutron/plugins/ofagent/agent/arp_lib.py delete mode 100644 neutron/plugins/ofagent/agent/constants.py delete mode 100644 neutron/plugins/ofagent/agent/flows.py delete mode 100755 neutron/plugins/ofagent/agent/main.py delete mode 100644 neutron/plugins/ofagent/agent/metadata.py delete mode 100644 neutron/plugins/ofagent/agent/ofswitch.py delete mode 100644 neutron/plugins/ofagent/agent/ports.py delete mode 100644 neutron/plugins/ofagent/agent/tables.py delete mode 100644 neutron/plugins/ofagent/common/__init__.py delete mode 100644 neutron/plugins/ofagent/common/config.py delete mode 100644 neutron/tests/unit/ml2/drivers/test_ofagent_mech.py delete mode 100644 neutron/tests/unit/ofagent/__init__.py delete mode 100644 neutron/tests/unit/ofagent/fake_oflib.py delete mode 100644 neutron/tests/unit/ofagent/ofa_test_base.py delete mode 100644 neutron/tests/unit/ofagent/test_arp_lib.py delete mode 100644 neutron/tests/unit/ofagent/test_ofa_flows.py delete mode 100644 neutron/tests/unit/ofagent/test_ofa_neutron_agent.py delete mode 100644 neutron/tests/unit/ofagent/test_ofa_ports.py delete mode 100644 neutron/tests/unit/ofagent/test_ofswitch.py diff --git a/doc/source/devref/contribute.rst b/doc/source/devref/contribute.rst index b24aa7e8f..399afa3ba 100644 --- a/doc/source/devref/contribute.rst +++ b/doc/source/devref/contribute.rst @@ -411,7 +411,7 @@ The following chart captures the following aspects: +-------------------------------+-----------------------+-----------+------------------+---------+--------------+ | networking-odl_ | ml2,l3,lb,fw | yes | no | [C] | Kilo | +-------------------------------+-----------------------+-----------+------------------+---------+--------------+ -| networking-ofagent_ | ml2 | yes | no | [B] | | +| networking-ofagent_ | ml2 | yes | no | [C] | Kilo | +-------------------------------+-----------------------+-----------+------------------+---------+--------------+ | networking-ovs-dpdk_ | | | | | | +-------------------------------+-----------------------+-----------+------------------+---------+--------------+ diff --git a/etc/neutron/rootwrap.d/ofagent.filters b/etc/neutron/rootwrap.d/ofagent.filters deleted file mode 100644 index 11e425648..000000000 --- a/etc/neutron/rootwrap.d/ofagent.filters +++ /dev/null @@ -1,16 +0,0 @@ -# neutron-rootwrap command filters for nodes on which -# neutron-ofagent-agent is expected to control network -# -# This file should be owned by (and only-writeable by) the root user - -# format seems to be -# cmd-name: filter-name, raw-command, user, args - -[Filters] - -# ovs_lib -ovs-vsctl: CommandFilter, ovs-vsctl, root - -# ip_lib -ip: IpFilter, ip, root -ip_exec: IpNetnsExecFilter, ip, root diff --git a/neutron/plugins/ml2/drivers/mech_ofagent.py b/neutron/plugins/ml2/drivers/mech_ofagent.py deleted file mode 100644 index 04ed82519..000000000 --- a/neutron/plugins/ml2/drivers/mech_ofagent.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 Fumihiko Kakuma -# All Rights Reserved. -# -# Based on openvswitch mechanism driver. -# -# Copyright (c) 2013 OpenStack Foundation -# 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.agent import securitygroups_rpc -from neutron.common import constants -from neutron.extensions import portbindings -from neutron.openstack.common import log -from neutron.plugins.common import constants as p_constants -from neutron.plugins.ml2.drivers import mech_agent - -LOG = log.getLogger(__name__) - - -class OfagentMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase): - """Attach to networks using ofagent L2 agent. - - The OfagentMechanismDriver integrates the ml2 plugin with the - ofagent L2 agent. Port binding with this driver requires the - ofagent agent to be running on the port's host, and that agent - to have connectivity to at least one segment of the port's - network. - """ - - def __init__(self): - sg_enabled = securitygroups_rpc.is_firewall_enabled() - vif_details = {portbindings.CAP_PORT_FILTER: sg_enabled, - portbindings.OVS_HYBRID_PLUG: sg_enabled} - super(OfagentMechanismDriver, self).__init__( - constants.AGENT_TYPE_OFA, - portbindings.VIF_TYPE_OVS, - vif_details) - - def get_allowed_network_types(self, agent): - return (agent['configurations'].get('tunnel_types', []) + - [p_constants.TYPE_LOCAL, p_constants.TYPE_FLAT, - p_constants.TYPE_VLAN]) - - def get_mappings(self, agent): - return dict(agent['configurations'].get('interface_mappings', {})) diff --git a/neutron/plugins/ofagent/README b/neutron/plugins/ofagent/README deleted file mode 100644 index 37aca7cf4..000000000 --- a/neutron/plugins/ofagent/README +++ /dev/null @@ -1,100 +0,0 @@ -This directory includes agent for OpenFlow Agent mechanism driver. - -# -- Installation - -For how to install/set up ML2 mechanism driver for OpenFlow Agent, please refer to -https://github.com/osrg/ryu/wiki/OpenStack - -# -- Notes for updating from Icehouce - -OVS.bridge_mappings is deprecated for ofagent. It was removed in Kilo. -Please use AGENT.physical_interface_mappings instead. -To mimic an existing setup with bridge_mapping, you can create -a veth pair, link one side of it to the bridge, and then specify -the other side in physical_interface_mappings. -For example, if you have the following: - - [OVS] - bridge_mappings=public:br-ex - -You can do: - - # ip link add int-public type veth peer name phy-public - # ip link set int-public up - # ip link set phy-public up - # ovs-vsctl add-port br-ex phy-public - -and then replace the bridge_mappings with: - - [AGENT] - physical_interface_mappings=public:int-public - -After Icehouce, most of the functionality have been folded into -a single bridge, the integration bridge. (aka. br-int) -The integration bridge is the only bridge which would have an -OpenFlow connection to the embedded controller in ofagent now. - -- ofagent no longer uses a separate bridge for tunneling. - Please remove br-tun if you have one. - - # ovs-vsctl del-br br-tun - -- ofagent no longer acts as an OpenFlow controller for physical bridges. - Please remove set-controller configuration from your physical bridges. - - # ovs-vsctl del-controller ${PHYSICAL_BRIDGE} - -The support of ancillary bridges has been removed after Icehouce. -While you can still use these bridges to provide connectivity, -neutron-ofagent-agent no longer reports port state changes (up/down) -for these bridges. If it is a problem for you, please consider -tweaking your configuration to avoid using ancillary bridges. -We recommend to use a provider network instead as the following: - -- Make l3-agent external_network_bridge configuration empty. - eg. - [DEFAULT] - external_network_bridge= - -- (Re-)create a network (and subnet) for public connectivity with - a flat provider network. - eg. - neutron net-create $PUBLIC_NETWORK -- \ - --router:external=True \ - --provider:network_type:flat \ - --provider:physical_network=$PUBLIC_PHYSICAL_NETWORK - -- Associate your neutron router to the above network. - eg. - neutron router-gateway-clear $ROUTER_ID - neutron router-gateway-set $ROUTER_ID $PUBLIC_NETWORK - -- Add the corresponding entry to bridge_mappings. - eg. - [OVS] - bridge_mappings=$PUBLIC_PHYSICAL_NETWORK:$PUBLIC_BRIDGE - -The port naming scheme for ofagent has been changed after Icehouce. -If you are using security groups, you should switch firewall_driver -accordingly. - From: - [securitygroup] - firewall_driver=neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver - To: - [securitygroup] - firewall_driver=neutron.agent.linux.iptables_firewall.IptablesFirewallDriver - -# -- Ryu General - -For general Ryu stuff, please refer to -http://osrg.github.io/ryu/ - -Ryu is available at github -git://github.com/osrg/ryu.git -https://github.com/osrg/ryu - -The mailing is at -ryu-devel@lists.sourceforge.net -https://lists.sourceforge.net/lists/listinfo/ryu-devel - -Enjoy! diff --git a/neutron/plugins/ofagent/__init__.py b/neutron/plugins/ofagent/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron/plugins/ofagent/agent/__init__.py b/neutron/plugins/ofagent/agent/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron/plugins/ofagent/agent/arp_lib.py b/neutron/plugins/ofagent/agent/arp_lib.py deleted file mode 100644 index 7747477cb..000000000 --- a/neutron/plugins/ofagent/agent/arp_lib.py +++ /dev/null @@ -1,187 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 Fumihiko Kakuma -# Copyright (C) 2014 YAMAMOTO Takashi -# 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 ryu.app.ofctl import api as ryu_api -from ryu.lib import dpid as dpid_lib -from ryu.lib.packet import arp -from ryu.lib.packet import ethernet -from ryu.lib.packet import packet -from ryu.lib.packet import vlan - -from neutron.common import log -from neutron.i18n import _LI -from neutron.openstack.common import log as logging -import neutron.plugins.ofagent.agent.metadata as meta - - -LOG = logging.getLogger(__name__) - - -class ArpLib(object): - - def __init__(self, ryuapp): - """Constructor. - - Define the internal table mapped an ip and a mac in a network. - self._arp_tbl: - {network1: {ip_addr: mac, ...}, - network2: {ip_addr: mac, ...}, - ..., - } - - :param ryuapp: object of the ryu app. - """ - self.ryuapp = ryuapp - self._arp_tbl = {} - self.br = None - - def set_bridge(self, br): - self.br = br - - @log.log - def _send_arp_reply(self, datapath, port, pkt): - ofp = datapath.ofproto - ofpp = datapath.ofproto_parser - pkt.serialize() - data = pkt.data - actions = [ofpp.OFPActionOutput(port=port)] - out = ofpp.OFPPacketOut(datapath=datapath, - buffer_id=ofp.OFP_NO_BUFFER, - in_port=ofp.OFPP_CONTROLLER, - actions=actions, - data=data) - ryu_api.send_msg(self.ryuapp, out) - - @log.log - def _send_unknown_packet(self, msg, in_port, out_port): - datapath = msg.datapath - ofp = datapath.ofproto - ofpp = datapath.ofproto_parser - data = None - if msg.buffer_id == ofp.OFP_NO_BUFFER: - data = msg.data - actions = [ofpp.OFPActionOutput(port=out_port)] - out = ofpp.OFPPacketOut(datapath=datapath, - buffer_id=msg.buffer_id, - in_port=in_port, - actions=actions, - data=data) - ryu_api.send_msg(self.ryuapp, out) - - def _respond_arp(self, datapath, port, arptbl, - pkt_ethernet, pkt_vlan, pkt_arp): - if pkt_arp.opcode != arp.ARP_REQUEST: - LOG.debug("unknown arp op %s", pkt_arp.opcode) - return False - ip_addr = pkt_arp.dst_ip - hw_addr = arptbl.get(ip_addr) - if hw_addr is None: - LOG.debug("unknown arp request %s", ip_addr) - return False - LOG.debug("responding arp request %(ip_addr)s -> %(hw_addr)s", - {'ip_addr': ip_addr, 'hw_addr': hw_addr}) - pkt = packet.Packet() - pkt.add_protocol(ethernet.ethernet(ethertype=pkt_ethernet.ethertype, - dst=pkt_ethernet.src, - src=hw_addr)) - if pkt_vlan: - pkt.add_protocol(vlan.vlan(cfi=pkt_vlan.cfi, - ethertype=pkt_vlan.ethertype, - pcp=pkt_vlan.pcp, - vid=pkt_vlan.vid)) - pkt.add_protocol(arp.arp(opcode=arp.ARP_REPLY, - src_mac=hw_addr, - src_ip=ip_addr, - dst_mac=pkt_arp.src_mac, - dst_ip=pkt_arp.src_ip)) - self._send_arp_reply(datapath, port, pkt) - return True - - @log.log - def add_arp_table_entry(self, network, ip, mac): - if network in self._arp_tbl: - self._arp_tbl[network][ip] = mac - else: - self._arp_tbl[network] = {ip: mac} - - @log.log - def del_arp_table_entry(self, network, ip): - if network not in self._arp_tbl: - LOG.debug("removal of unknown network %s", network) - return - if self._arp_tbl[network].pop(ip, None) is None: - LOG.debug("removal of unknown ip %s", ip) - return - if not self._arp_tbl[network]: - del self._arp_tbl[network] - - def packet_in_handler(self, ev): - """Check a packet-in message. - - Build and output an arp reply if a packet-in message is - an arp packet. - """ - msg = ev.msg - LOG.debug("packet-in msg %s", msg) - datapath = msg.datapath - if self.br is None: - LOG.info(_LI("No bridge is set")) - return - if self.br.datapath.id != datapath.id: - LOG.info(_LI("Unknown bridge %(dpid)s ours %(ours)s"), - {"dpid": datapath.id, "ours": self.br.datapath.id}) - return - ofp = datapath.ofproto - port = msg.match['in_port'] - metadata = msg.match.get('metadata') - # NOTE(yamamoto): Ryu packet library can raise various exceptions - # on a corrupted packet. - try: - pkt = packet.Packet(msg.data) - except Exception as e: - LOG.debug("Unparsable packet: got exception %s", e) - return - LOG.debug("packet-in dpid %(dpid)s in_port %(port)s pkt %(pkt)s", - {'dpid': dpid_lib.dpid_to_str(datapath.id), - 'port': port, 'pkt': pkt}) - - if metadata is None: - LOG.info(_LI("drop non tenant packet")) - return - network = metadata & meta.NETWORK_MASK - pkt_ethernet = pkt.get_protocol(ethernet.ethernet) - if not pkt_ethernet: - LOG.debug("drop non-ethernet packet") - return - pkt_vlan = pkt.get_protocol(vlan.vlan) - pkt_arp = pkt.get_protocol(arp.arp) - if not pkt_arp: - LOG.debug("drop non-arp packet") - return - - arptbl = self._arp_tbl.get(network) - if arptbl: - if self._respond_arp(datapath, port, arptbl, - pkt_ethernet, pkt_vlan, pkt_arp): - return - else: - LOG.info(_LI("unknown network %s"), network) - - # add a flow to skip a packet-in to a controller. - self.br.arp_passthrough(network=network, tpa=pkt_arp.dst_ip) - # send an unknown arp packet to the table. - self._send_unknown_packet(msg, port, ofp.OFPP_TABLE) diff --git a/neutron/plugins/ofagent/agent/constants.py b/neutron/plugins/ofagent/agent/constants.py deleted file mode 100644 index 633979d8b..000000000 --- a/neutron/plugins/ofagent/agent/constants.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 YAMAMOTO Takashi -# 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. - -LOCAL_VLAN_MIN = 1 -LOCAL_VLAN_MAX = 0xfff -LOCAL_VLAN_MASK = 0xfff diff --git a/neutron/plugins/ofagent/agent/flows.py b/neutron/plugins/ofagent/agent/flows.py deleted file mode 100644 index b699a6842..000000000 --- a/neutron/plugins/ofagent/agent/flows.py +++ /dev/null @@ -1,407 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 YAMAMOTO Takashi -# 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. - -""" -OpenFlow1.3 flow table for OFAgent - -* requirements -** plain OpenFlow 1.3. no vendor extensions. - -* legends - xxx: network id (agent internal use) - yyy: segment id (vlan id, gre key, ...) - a,b,c: tunnel port (tun_ofports, map[net_id].tun_ofports) - i,j,k: vm port (map[net_id].vif_ports[vif_id].ofport) - x,y,z: physical port (int_ofports) - N: tunnel type (0 for TYPE_GRE, 1 for TYPE_xxx, ...) - iii: unknown ip address - uuu: unicast l2 address - -* tables (in order) - CHECK_IN_PORT - TUNNEL_IN+N - PHYS_IN - LOCAL_IN - ARP_PASSTHROUGH - ARP_RESPONDER - TUNNEL_OUT - LOCAL_OUT - PHYS_OUT - TUNNEL_FLOOD+N - PHYS_FLOOD - LOCAL_FLOOD - -* CHECK_IN_PORT - - for each vm ports: - // check_in_port_add_local_port, check_in_port_delete_port - in_port=i, write_metadata(LOCAL|xxx),goto(LOCAL_IN) - TYPE_GRE - for each tunnel ports: - // check_in_port_add_tunnel_port, check_in_port_delete_port - in_port=a, goto(TUNNEL_IN+N) - TYPE_VLAN - for each networks ports: - // provision_tenant_physnet, reclaim_tenant_physnet - in_port=x,vlan_vid=present|yyy, write_metadata(xxx),goto(PHYS_IN) - TYPE_FLAT - // provision_tenant_physnet, reclaim_tenant_physnet - in_port=x, write_metadata(xxx),goto(PHYS_IN) - default drop - -* TUNNEL_IN+N (per tunnel types) tunnel -> network - - for each networks: - // provision_tenant_tunnel, reclaim_tenant_tunnel - tun_id=yyy, write_metadata(xxx),goto(TUNNEL_OUT) - - default drop - -* PHYS_IN - default goto(TUNNEL_OUT) - -* LOCAL_IN - default goto(next_table) - -* ARP_PASSTHROUGH - for each unknown tpa: - // arp_passthrough - arp,arp_op=request,metadata=xxx,tpa=iii, idle_timeout=5, goto(TUNNEL_OUT) - default goto(next_table) - -* ARP_RESPONDER - arp,arp_op=request, output:controller - default goto(next_table) - -* TUNNEL_OUT - TYPE_GRE - // !FLOODING_ENTRY - // install_tunnel_output, delete_tunnel_output - metadata=LOCAL|xxx,eth_dst=uuu set_tunnel(yyy),output:a - - default goto(next table) - -* LOCAL_OUT - for each known destinations: - // local_out_add_port, local_out_delete_port - metadata=xxx,eth_dst=uuu output:i - default goto(next table) - -* PHYS_OUT - - NOTE(yamamoto): currently this table is always empty. - - default goto(next table) - -* TUNNEL_FLOOD+N. (per tunnel types) - - network -> tunnel/vlan - output to tunnel/physical ports - "next table" might be LOCAL_OUT - TYPE_GRE - for each networks: - // FLOODING_ENTRY - // install_tunnel_output, delete_tunnel_output - metadata=LOCAL|xxx, set_tunnel(yyy),output:a,b,c,goto(next table) - - default goto(next table) - -* PHYS_FLOOD - - TYPE_VLAN - for each networks: - // provision_tenant_physnet, reclaim_tenant_physnet - metadata=LOCAL|xxx, push_vlan:0x8100,set_field:present|yyy->vlan_vid, - output:x,pop_vlan,goto(next table) - TYPE_FLAT - for each networks: - // provision_tenant_physnet, reclaim_tenant_physnet - metadata=LOCAL|xxx, output:x,goto(next table) - - default goto(next table) - -* LOCAL_FLOOD - - for each networks: - // local_flood_update, local_flood_delete - metadata=xxx, output:i,j,k - or - metadata=xxx,eth_dst=broadcast, output:i,j,k - - default drop - -* references -** OVS agent https://wiki.openstack.org/wiki/Ovs-flow-logic -*** we use metadata instead of "internal" VLANs -*** we don't want to use NX learn action -""" - -from ryu.lib.packet import arp -from ryu.ofproto import ether - -from neutron.plugins.common import constants as p_const -import neutron.plugins.ofagent.agent.metadata as meta -from neutron.plugins.ofagent.agent import ofswitch -from neutron.plugins.ofagent.agent import tables - - -class OFAgentIntegrationBridge(ofswitch.OpenFlowSwitch): - """ofagent br-int specific logic.""" - - def setup_default_table(self): - self.delete_flows() - - self.install_default_drop(tables.CHECK_IN_PORT) - - for t in tables.TUNNEL_IN.values(): - self.install_default_drop(t) - self.install_default_goto(tables.PHYS_IN, tables.TUNNEL_OUT) - self.install_default_goto_next(tables.LOCAL_IN) - self.install_default_goto_next(tables.ARP_PASSTHROUGH) - self.install_arp_responder(tables.ARP_RESPONDER) - - self.install_default_goto_next(tables.TUNNEL_OUT) - self.install_default_goto_next(tables.LOCAL_OUT) - self.install_default_goto_next(tables.PHYS_OUT) - - for t in tables.TUNNEL_FLOOD.values(): - self.install_default_goto_next(t) - self.install_default_goto_next(tables.PHYS_FLOOD) - self.install_default_drop(tables.LOCAL_FLOOD) - - def install_arp_responder(self, table_id): - (dp, ofp, ofpp) = self._get_dp() - match = ofpp.OFPMatch(eth_type=ether.ETH_TYPE_ARP, - arp_op=arp.ARP_REQUEST) - actions = [ofpp.OFPActionOutput(ofp.OFPP_CONTROLLER)] - instructions = [ - ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions)] - msg = ofpp.OFPFlowMod(dp, - table_id=table_id, - priority=1, - match=match, - instructions=instructions) - self._send_msg(msg) - self.install_default_goto_next(table_id) - - def install_tunnel_output(self, table_id, - network, segmentation_id, - ports, goto_next, **additional_matches): - (dp, ofp, ofpp) = self._get_dp() - match = ofpp.OFPMatch(metadata=meta.mk_metadata(network, meta.LOCAL), - **additional_matches) - actions = [ofpp.OFPActionSetField(tunnel_id=segmentation_id)] - actions += [ofpp.OFPActionOutput(port=p) for p in ports] - instructions = [ - ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions), - ] - if goto_next: - instructions += [ - ofpp.OFPInstructionGotoTable(table_id=table_id + 1), - ] - msg = ofpp.OFPFlowMod(dp, - table_id=table_id, - priority=1, - match=match, - instructions=instructions) - self._send_msg(msg) - - def delete_tunnel_output(self, table_id, - network, **additional_matches): - (dp, _ofp, ofpp) = self._get_dp() - self.delete_flows(table_id=table_id, - metadata=meta.mk_metadata(network, meta.LOCAL), - **additional_matches) - - def provision_tenant_tunnel(self, network_type, network, segmentation_id): - (dp, _ofp, ofpp) = self._get_dp() - match = ofpp.OFPMatch(tunnel_id=segmentation_id) - metadata = meta.mk_metadata(network) - instructions = [ - ofpp.OFPInstructionWriteMetadata(metadata=metadata[0], - metadata_mask=metadata[1]), - ofpp.OFPInstructionGotoTable(table_id=tables.TUNNEL_OUT), - ] - msg = ofpp.OFPFlowMod(dp, - table_id=tables.TUNNEL_IN[network_type], - priority=1, - match=match, - instructions=instructions) - self._send_msg(msg) - - def reclaim_tenant_tunnel(self, network_type, network, segmentation_id): - table_id = tables.TUNNEL_IN[network_type] - self.delete_flows(table_id=table_id, tunnel_id=segmentation_id) - - def provision_tenant_physnet(self, network_type, network, - segmentation_id, phys_port): - """for vlan and flat.""" - assert(network_type in [p_const.TYPE_VLAN, p_const.TYPE_FLAT]) - (dp, ofp, ofpp) = self._get_dp() - - # inbound - metadata = meta.mk_metadata(network) - instructions = [ - ofpp.OFPInstructionWriteMetadata(metadata=metadata[0], - metadata_mask=metadata[1]) - ] - if network_type == p_const.TYPE_VLAN: - vlan_vid = segmentation_id | ofp.OFPVID_PRESENT - match = ofpp.OFPMatch(in_port=phys_port, vlan_vid=vlan_vid) - actions = [ofpp.OFPActionPopVlan()] - instructions += [ofpp.OFPInstructionActions( - ofp.OFPIT_APPLY_ACTIONS, actions)] - else: - match = ofpp.OFPMatch(in_port=phys_port) - instructions += [ofpp.OFPInstructionGotoTable(table_id=tables.PHYS_IN)] - msg = ofpp.OFPFlowMod(dp, - priority=1, - table_id=tables.CHECK_IN_PORT, - match=match, - instructions=instructions) - self._send_msg(msg) - - # outbound - match = ofpp.OFPMatch(metadata=meta.mk_metadata(network, meta.LOCAL)) - if network_type == p_const.TYPE_VLAN: - actions = [ - ofpp.OFPActionPushVlan(), - ofpp.OFPActionSetField(vlan_vid=vlan_vid), - ] - else: - actions = [] - actions += [ofpp.OFPActionOutput(port=phys_port)] - if network_type == p_const.TYPE_VLAN: - actions += [ofpp.OFPActionPopVlan()] - instructions = [ - ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions), - ofpp.OFPInstructionGotoTable(table_id=tables.PHYS_FLOOD + 1), - ] - msg = ofpp.OFPFlowMod(dp, - priority=1, - table_id=tables.PHYS_FLOOD, - match=match, - instructions=instructions) - self._send_msg(msg) - - def reclaim_tenant_physnet(self, network_type, network, - segmentation_id, phys_port): - (_dp, ofp, _ofpp) = self._get_dp() - vlan_vid = segmentation_id | ofp.OFPVID_PRESENT - if network_type == p_const.TYPE_VLAN: - self.delete_flows(table_id=tables.CHECK_IN_PORT, - in_port=phys_port, vlan_vid=vlan_vid) - else: - self.delete_flows(table_id=tables.CHECK_IN_PORT, - in_port=phys_port) - self.delete_flows(table_id=tables.PHYS_FLOOD, - metadata=meta.mk_metadata(network)) - - def check_in_port_add_tunnel_port(self, network_type, port): - (dp, _ofp, ofpp) = self._get_dp() - match = ofpp.OFPMatch(in_port=port) - instructions = [ - ofpp.OFPInstructionGotoTable( - table_id=tables.TUNNEL_IN[network_type]) - ] - msg = ofpp.OFPFlowMod(dp, - table_id=tables.CHECK_IN_PORT, - priority=1, - match=match, - instructions=instructions) - self._send_msg(msg) - - def check_in_port_add_local_port(self, network, port): - (dp, ofp, ofpp) = self._get_dp() - match = ofpp.OFPMatch(in_port=port) - metadata = meta.mk_metadata(network, meta.LOCAL) - instructions = [ - ofpp.OFPInstructionWriteMetadata(metadata=metadata[0], - metadata_mask=metadata[1]), - ofpp.OFPInstructionGotoTable(table_id=tables.LOCAL_IN), - ] - msg = ofpp.OFPFlowMod(dp, - table_id=tables.CHECK_IN_PORT, - priority=1, - match=match, - instructions=instructions) - self._send_msg(msg) - - def check_in_port_delete_port(self, port): - self.delete_flows(table_id=tables.CHECK_IN_PORT, in_port=port) - - def local_flood_update(self, network, ports, flood_unicast): - (dp, ofp, ofpp) = self._get_dp() - match_all = ofpp.OFPMatch(metadata=meta.mk_metadata(network)) - match_multicast = ofpp.OFPMatch(metadata=meta.mk_metadata(network), - eth_dst=('01:00:00:00:00:00', - '01:00:00:00:00:00')) - if flood_unicast: - match_add = match_all - match_del = match_multicast - else: - match_add = match_multicast - match_del = match_all - actions = [ofpp.OFPActionOutput(port=p) for p in ports] - instructions = [ - ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions), - ] - msg = ofpp.OFPFlowMod(dp, - table_id=tables.LOCAL_FLOOD, - priority=1, - match=match_add, - instructions=instructions) - self._send_msg(msg) - self.delete_flows(table_id=tables.LOCAL_FLOOD, strict=True, - priority=1, match=match_del) - - def local_flood_delete(self, network): - self.delete_flows(table_id=tables.LOCAL_FLOOD, - metadata=meta.mk_metadata(network)) - - def local_out_add_port(self, network, port, mac): - (dp, ofp, ofpp) = self._get_dp() - match = ofpp.OFPMatch(metadata=meta.mk_metadata(network), eth_dst=mac) - actions = [ofpp.OFPActionOutput(port=port)] - instructions = [ - ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions), - ] - msg = ofpp.OFPFlowMod(dp, - table_id=tables.LOCAL_OUT, - priority=1, - match=match, - instructions=instructions) - self._send_msg(msg) - - def local_out_delete_port(self, network, mac): - self.delete_flows(table_id=tables.LOCAL_OUT, - metadata=meta.mk_metadata(network), eth_dst=mac) - - def arp_passthrough(self, network, tpa): - (dp, ofp, ofpp) = self._get_dp() - match = ofpp.OFPMatch(metadata=meta.mk_metadata(network), - eth_type=ether.ETH_TYPE_ARP, - arp_op=arp.ARP_REQUEST, - arp_tpa=tpa) - instructions = [ - ofpp.OFPInstructionGotoTable(table_id=tables.TUNNEL_OUT)] - msg = ofpp.OFPFlowMod(dp, - table_id=tables.ARP_PASSTHROUGH, - priority=1, - idle_timeout=5, - match=match, - instructions=instructions) - self._send_msg(msg) diff --git a/neutron/plugins/ofagent/agent/main.py b/neutron/plugins/ofagent/agent/main.py deleted file mode 100755 index ea81a160d..000000000 --- a/neutron/plugins/ofagent/agent/main.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 Fumihiko Kakuma -# Copyright (C) 2014 YAMAMOTO Takashi -# 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 ryu.lib import hub -hub.patch() - -import sys - -from oslo_config import cfg -from ryu.base.app_manager import AppManager -from ryu import cfg as ryu_cfg - -from neutron.common import config as common_config - - -def main(): - common_config.init(sys.argv[1:]) - # the following check is a transitional workaround to make this work - # with different versions of ryu. - # TODO(yamamoto) remove this later - if ryu_cfg.CONF is not cfg.CONF: - ryu_cfg.CONF(project='ryu', args=[]) - common_config.setup_logging() - AppManager.run_apps(['neutron.plugins.ofagent.agent.ofa_neutron_agent']) diff --git a/neutron/plugins/ofagent/agent/metadata.py b/neutron/plugins/ofagent/agent/metadata.py deleted file mode 100644 index e9d56909d..000000000 --- a/neutron/plugins/ofagent/agent/metadata.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 YAMAMOTO Takashi -# 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.ofagent.agent import constants as const - - -# metadata mask -NETWORK_MASK = const.LOCAL_VLAN_MASK -LOCAL = 0x10000 # the packet came from local vm ports - - -def mk_metadata(network, flags=0): - return (flags | network, flags | NETWORK_MASK) diff --git a/neutron/plugins/ofagent/agent/ofswitch.py b/neutron/plugins/ofagent/agent/ofswitch.py deleted file mode 100644 index eafe33d55..000000000 --- a/neutron/plugins/ofagent/agent/ofswitch.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 YAMAMOTO Takashi -# 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 ryu.app.ofctl import api as ofctl_api - - -class OpenFlowSwitch(object): - def __init__(self, *args, **kwargs): - super(OpenFlowSwitch, self).__init__(*args, **kwargs) - self._dp = None - # logically app doesn't belong here. just for convenience. - self._app = None - - def set_dp(self, dp): - self._dp = dp - - def set_app(self, app): - self._app = app - - def _get_dp(self): - """a convenient method for openflow message composers""" - dp = self._dp - return (dp, dp.ofproto, dp.ofproto_parser) - - def _send_msg(self, msg): - return ofctl_api.send_msg(self._app, msg) - - def delete_flows(self, table_id=None, strict=False, priority=0, - match=None, **match_kwargs): - (dp, ofp, ofpp) = self._get_dp() - if table_id is None: - table_id = ofp.OFPTT_ALL - if match is None: - match = ofpp.OFPMatch(**match_kwargs) - if strict: - cmd = ofp.OFPFC_DELETE_STRICT - else: - cmd = ofp.OFPFC_DELETE - msg = ofpp.OFPFlowMod(dp, - command=cmd, - table_id=table_id, - match=match, - priority=priority, - out_group=ofp.OFPG_ANY, - out_port=ofp.OFPP_ANY) - self._send_msg(msg) - - def install_default_drop(self, table_id): - (dp, _ofp, ofpp) = self._get_dp() - msg = ofpp.OFPFlowMod(dp, - table_id=table_id, - priority=0) - self._send_msg(msg) - - def install_default_goto(self, table_id, dest_table_id): - (dp, _ofp, ofpp) = self._get_dp() - instructions = [ofpp.OFPInstructionGotoTable(table_id=dest_table_id)] - msg = ofpp.OFPFlowMod(dp, - table_id=table_id, - priority=0, - instructions=instructions) - self._send_msg(msg) - - def install_default_goto_next(self, table_id): - self.install_default_goto(table_id, table_id + 1) diff --git a/neutron/plugins/ofagent/agent/ports.py b/neutron/plugins/ofagent/agent/ports.py deleted file mode 100644 index 218dc5ece..000000000 --- a/neutron/plugins/ofagent/agent/ports.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 YAMAMOTO Takashi -# 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 constants as n_const - - -class OFPort(object): - def __init__(self, port_name, ofport): - self.port_name = port_name - self.ofport = ofport - - @classmethod - def from_ofp_port(cls, ofp_port): - """Convert from ryu OFPPort.""" - return cls(port_name=ofp_port.name, ofport=ofp_port.port_no) - - -PORT_NAME_LEN = 14 -PORT_NAME_PREFIXES = [ - n_const.TAP_DEVICE_PREFIX, # common cases, including ovs_use_veth=True - "qvo", # nova hybrid interface driver - "qr-", # l3-agent INTERNAL_DEV_PREFIX (ovs_use_veth=False) - "qg-", # l3-agent EXTERNAL_DEV_PREFIX (ovs_use_veth=False) -] - - -def _is_neutron_port(name): - """Return True if the port name looks like a neutron port.""" - if len(name) != PORT_NAME_LEN: - return False - for pref in PORT_NAME_PREFIXES: - if name.startswith(pref): - return True - return False - - -def get_normalized_port_name(interface_id): - """Convert from neutron device id (uuid) to "normalized" port name. - - This needs to be synced with ML2 plugin's _device_to_port_id(). - - An assumption: The switch uses an OS's interface name as the - corresponding OpenFlow port name. - NOTE(yamamoto): While it's true for Open vSwitch, it isn't - necessarily true everywhere. For example, LINC uses something - like "LogicalSwitch0-Port2". - - NOTE(yamamoto): The actual prefix might be different. For example, - with the hybrid interface driver, it's "qvo". However, we always - use "tap" prefix throughout the agent and plugin for simplicity. - Some care should be taken when talking to the switch. - """ - return (n_const.TAP_DEVICE_PREFIX + interface_id)[0:PORT_NAME_LEN] - - -def _normalize_port_name(name): - """Normalize port name. - - See comments in _get_ofport_name. - """ - for pref in PORT_NAME_PREFIXES: - if name.startswith(pref): - return n_const.TAP_DEVICE_PREFIX + name[len(pref):] - return name - - -class Port(OFPort): - def __init__(self, *args, **kwargs): - super(Port, self).__init__(*args, **kwargs) - self.vif_mac = None - - def is_neutron_port(self): - """Return True if the port looks like a neutron port.""" - return _is_neutron_port(self.port_name) - - def normalized_port_name(self): - return _normalize_port_name(self.port_name) diff --git a/neutron/plugins/ofagent/agent/tables.py b/neutron/plugins/ofagent/agent/tables.py deleted file mode 100644 index f78c68f94..000000000 --- a/neutron/plugins/ofagent/agent/tables.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 YAMAMOTO Takashi -# 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.common import constants as p_const - - -def _seq(): - """Yield sequential numbers starting from 0.""" - i = 0 - while True: - yield i - i += 1 - -_table_id_gen = _seq() - - -def _table_id(): - """A simple table id allocator.""" - return _table_id_gen.next() - -# Supported tunnel types. -TUNNEL_TYPES = [ - p_const.TYPE_GRE, - p_const.TYPE_VXLAN, -] - -# Reversed version of TUNNEL_TYPES. -TUNNEL_TYPE_IDX = dict((t, TUNNEL_TYPES.index(t)) for t in TUNNEL_TYPES) - -# We use sequential table ids starting from 0. -# We don't hardcode values here to avoid manual reassignments eg. when adding -# a new tunnel type. -# See a big comment in flows.py for how each tables are used. -CHECK_IN_PORT = _table_id() -TUNNEL_IN = {} -for t in TUNNEL_TYPES: - TUNNEL_IN[t] = _table_id() -PHYS_IN = _table_id() -LOCAL_IN = _table_id() -ARP_PASSTHROUGH = _table_id() -ARP_RESPONDER = _table_id() -TUNNEL_OUT = _table_id() -LOCAL_OUT = _table_id() -PHYS_OUT = _table_id() -TUNNEL_FLOOD = {} -for t in TUNNEL_TYPES: - TUNNEL_FLOOD[t] = _table_id() -PHYS_FLOOD = _table_id() -LOCAL_FLOOD = _table_id() diff --git a/neutron/plugins/ofagent/common/__init__.py b/neutron/plugins/ofagent/common/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron/plugins/ofagent/common/config.py b/neutron/plugins/ofagent/common/config.py deleted file mode 100644 index 2d6d49545..000000000 --- a/neutron/plugins/ofagent/common/config.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 Fumihiko Kakuma -# 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 neutron.agent.common import config -from neutron.plugins.openvswitch.common import config as ovs_config - - -agent_opts = [ - cfg.IntOpt('get_datapath_retry_times', default=60, - help=_("Number of seconds to retry acquiring " - "an Open vSwitch datapath")), - cfg.ListOpt('physical_interface_mappings', - default=[], - help=_("List of :")), -] - - -cfg.CONF.register_opts(ovs_config.ovs_opts, 'OVS') -cfg.CONF.register_opts(ovs_config.agent_opts, 'AGENT') -cfg.CONF.register_opts(agent_opts, 'AGENT') -config.register_agent_state_opts_helper(cfg.CONF) diff --git a/neutron/tests/unit/ml2/drivers/test_ofagent_mech.py b/neutron/tests/unit/ml2/drivers/test_ofagent_mech.py deleted file mode 100644 index a409f021c..000000000 --- a/neutron/tests/unit/ml2/drivers/test_ofagent_mech.py +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright (c) 2014 OpenStack Foundation -# 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 neutron.common import constants -from neutron.extensions import portbindings -from neutron.plugins.ml2.drivers import mech_ofagent -from neutron.tests.unit.ml2 import _test_mech_agent as base - - -class OfagentMechanismBaseTestCase(base.AgentMechanismBaseTestCase): - VIF_TYPE = portbindings.VIF_TYPE_OVS - VIF_DETAILS = {portbindings.CAP_PORT_FILTER: True, - portbindings.OVS_HYBRID_PLUG: True} - AGENT_TYPE = constants.AGENT_TYPE_OFA - - GOOD_MAPPINGS = {'fake_physical_network': 'fake_interface'} - GOOD_TUNNEL_TYPES = ['gre', 'vxlan'] - GOOD_CONFIGS = {'interface_mappings': GOOD_MAPPINGS, - 'tunnel_types': GOOD_TUNNEL_TYPES} - - BAD_MAPPINGS = {'wrong_physical_network': 'wrong_interface'} - BAD_TUNNEL_TYPES = ['bad_tunnel_type'] - BAD_CONFIGS = {'interface_mappings': BAD_MAPPINGS, - 'tunnel_types': BAD_TUNNEL_TYPES} - - AGENTS = [{'alive': True, - 'configurations': GOOD_CONFIGS, - 'host': 'host'}] - AGENTS_DEAD = [{'alive': False, - 'configurations': GOOD_CONFIGS, - 'host': 'dead_host'}] - AGENTS_BAD = [{'alive': False, - 'configurations': GOOD_CONFIGS, - 'host': 'bad_host_1'}, - {'alive': True, - 'configurations': BAD_CONFIGS, - 'host': 'bad_host_2'}] - - def setUp(self): - super(OfagentMechanismBaseTestCase, self).setUp() - self.driver = mech_ofagent.OfagentMechanismDriver() - self.driver.initialize() - - -class OfagentMechanismSGDisabledBaseTestCase(OfagentMechanismBaseTestCase): - VIF_DETAILS = {portbindings.CAP_PORT_FILTER: False, - portbindings.OVS_HYBRID_PLUG: False} - - def setUp(self): - cfg.CONF.set_override('enable_security_group', - False, - group='SECURITYGROUP') - super(OfagentMechanismSGDisabledBaseTestCase, self).setUp() - - -class OfagentMechanismGenericTestCase(OfagentMechanismBaseTestCase, - base.AgentMechanismGenericTestCase): - pass - - -class OfagentMechanismLocalTestCase(OfagentMechanismBaseTestCase, - base.AgentMechanismLocalTestCase): - pass - - -class OfagentMechanismFlatTestCase(OfagentMechanismBaseTestCase, - base.AgentMechanismFlatTestCase): - pass - - -class OfagentMechanismVlanTestCase(OfagentMechanismBaseTestCase, - base.AgentMechanismVlanTestCase): - pass - - -class OfagentMechanismGreTestCase(OfagentMechanismBaseTestCase, - base.AgentMechanismGreTestCase): - pass - - -class OfagentMechanismSGDisabledLocalTestCase( - OfagentMechanismSGDisabledBaseTestCase, - base.AgentMechanismLocalTestCase): - pass diff --git a/neutron/tests/unit/ofagent/__init__.py b/neutron/tests/unit/ofagent/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron/tests/unit/ofagent/fake_oflib.py b/neutron/tests/unit/ofagent/fake_oflib.py deleted file mode 100644 index 005d95866..000000000 --- a/neutron/tests/unit/ofagent/fake_oflib.py +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 Fumihiko Kakuma -# Copyright (C) 2014 YAMAMOTO Takashi -# 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 - - -class _Eq(object): - def __eq__(self, other): - return repr(self) == repr(other) - - def __ne__(self, other): - return not self.__eq__(other) - - -class _Value(_Eq): - def __or__(self, b): - return _Op('|', self, b) - - def __ror__(self, a): - return _Op('|', a, self) - - -class _SimpleValue(_Value): - def __init__(self, name): - self.name = name - - def __repr__(self): - return self.name - - -class _Op(_Value): - def __init__(self, op, a, b): - self.op = op - self.a = a - self.b = b - - def __repr__(self): - return '%s%s%s' % (self.a, self.op, self.b) - - -def _mkcls(name): - class Cls(_Eq): - _name = name - - def __init__(self, *args, **kwargs): - self._args = args - self._kwargs = kwargs - self._hist = [] - - def __getattr__(self, name): - return self._kwargs[name] - - def __repr__(self): - args = map(repr, self._args) - kwargs = sorted(['%s=%s' % (x, y) for x, y in - self._kwargs.items()]) - return '%s(%s)' % (self._name, ', '.join(args + kwargs)) - - return Cls - - -class _Mod(object): - _cls_cache = {} - - def __init__(self, name): - self._name = name - - def __getattr__(self, name): - fullname = '%s.%s' % (self._name, name) - if '_' in name: # constants are named like OFPxxx_yyy_zzz - return _SimpleValue(fullname) - try: - return self._cls_cache[fullname] - except KeyError: - pass - cls = _mkcls(fullname) - self._cls_cache[fullname] = cls - return cls - - def __repr__(self): - return 'Mod(%s)' % (self._name,) - - -def patch_fake_oflib_of(): - ryu_mod = mock.Mock() - ryu_base_mod = ryu_mod.base - ryu_ctrl_mod = ryu_mod.controller - handler = _Mod('ryu.controller.handler') - handler.set_ev_cls = mock.Mock() - ofp_event = _Mod('ryu.controller.ofp_event') - ryu_ctrl_mod.handler = handler - ryu_ctrl_mod.ofp_event = ofp_event - ryu_lib_mod = ryu_mod.lib - ryu_lib_hub = ryu_lib_mod.hub - ryu_packet_mod = ryu_lib_mod.packet - packet = _Mod('ryu.lib.packet.packet') - arp = _Mod('ryu.lib.packet.arp') - ethernet = _Mod('ryu.lib.packet.ethernet') - vlan = _Mod('ryu.lib.packet.vlan') - ryu_packet_mod.packet = packet - packet.Packet = mock.Mock() - ryu_packet_mod.arp = arp - ryu_packet_mod.ethernet = ethernet - ryu_packet_mod.vlan = vlan - ryu_ofproto_mod = ryu_mod.ofproto - ether = _Mod('ryu.ofproto.ether') - ofp = _Mod('ryu.ofproto.ofproto_v1_3') - ofpp = _Mod('ryu.ofproto.ofproto_v1_3_parser') - ryu_ofproto_mod.ether = ether - ryu_ofproto_mod.ofproto_v1_3 = ofp - ryu_ofproto_mod.ofproto_v1_3_parser = ofpp - ryu_app_mod = ryu_mod.app - ryu_app_ofctl_mod = ryu_app_mod.ofctl - ryu_ofctl_api = ryu_app_ofctl_mod.api - modules = {'ryu': ryu_mod, - 'ryu.base': ryu_base_mod, - 'ryu.controller': ryu_ctrl_mod, - 'ryu.controller.handler': handler, - 'ryu.controller.handler.set_ev_cls': handler.set_ev_cls, - 'ryu.controller.ofp_event': ofp_event, - 'ryu.lib': ryu_lib_mod, - 'ryu.lib.hub': ryu_lib_hub, - 'ryu.lib.packet': ryu_packet_mod, - 'ryu.lib.packet.packet': packet, - 'ryu.lib.packet.packet.Packet': packet.Packet, - 'ryu.lib.packet.arp': arp, - 'ryu.lib.packet.ethernet': ethernet, - 'ryu.lib.packet.vlan': vlan, - 'ryu.ofproto': ryu_ofproto_mod, - 'ryu.ofproto.ether': ether, - 'ryu.ofproto.ofproto_v1_3': ofp, - 'ryu.ofproto.ofproto_v1_3_parser': ofpp, - 'ryu.app': ryu_app_mod, - 'ryu.app.ofctl': ryu_app_ofctl_mod, - 'ryu.app.ofctl.api': ryu_ofctl_api} - return mock.patch.dict('sys.modules', modules) diff --git a/neutron/tests/unit/ofagent/ofa_test_base.py b/neutron/tests/unit/ofagent/ofa_test_base.py deleted file mode 100644 index 309122fa0..000000000 --- a/neutron/tests/unit/ofagent/ofa_test_base.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 Fumihiko Kakuma -# Copyright (C) 2014 YAMAMOTO Takashi -# 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_utils import importutils - -from neutron.tests import base -from neutron.tests.unit.ofagent import fake_oflib - - -class OFATestBase(base.BaseTestCase): - - def setUp(self): - self.fake_oflib_of = fake_oflib.patch_fake_oflib_of() - self.fake_oflib_of.start() - self.addCleanup(self.fake_oflib_of.stop) - super(OFATestBase, self).setUp() - - def _mk_test_dp(self, name): - ofp = importutils.import_module('ryu.ofproto.ofproto_v1_3') - ofpp = importutils.import_module('ryu.ofproto.ofproto_v1_3_parser') - dp = mock.Mock() - dp.ofproto = ofp - dp.ofproto_parser = ofpp - dp.__repr__ = mock.Mock(return_value=name) - return dp - - def _mk_test_br(self, name): - dp = self._mk_test_dp(name) - br = mock.Mock() - br.datapath = dp - br.ofproto = dp.ofproto - br.ofparser = dp.ofproto_parser - return br - - -class OFAAgentTestBase(OFATestBase): - - _AGENT_NAME = 'neutron.plugins.ofagent.agent.ofa_neutron_agent' - - def setUp(self): - super(OFAAgentTestBase, self).setUp() - self.mod_agent = importutils.import_module(self._AGENT_NAME) - self.ryuapp = mock.Mock() - - def setup_config(self): - cfg.CONF.set_default('firewall_driver', - 'neutron.agent.firewall.NoopFirewallDriver', - group='SECURITYGROUP') - cfg.CONF.register_cli_opts([ - cfg.StrOpt('ofp-listen-host', default='', - help='openflow listen host'), - cfg.IntOpt('ofp-tcp-listen-port', default=6633, - help='openflow tcp listen port') - ]) - super(OFATestBase, self).setup_config() diff --git a/neutron/tests/unit/ofagent/test_arp_lib.py b/neutron/tests/unit/ofagent/test_arp_lib.py deleted file mode 100644 index 490fe34da..000000000 --- a/neutron/tests/unit/ofagent/test_arp_lib.py +++ /dev/null @@ -1,334 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 Fumihiko Kakuma -# 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 collections -import contextlib -import copy - -import mock -from oslo_utils import importutils - -import neutron.plugins.ofagent.agent.metadata as meta -from neutron.tests.unit.ofagent import ofa_test_base - - -_OFALIB_NAME = 'neutron.plugins.ofagent.agent.arp_lib' - - -class OFAAgentTestCase(ofa_test_base.OFAAgentTestBase): - - def setUp(self): - super(OFAAgentTestCase, self).setUp() - - Net = collections.namedtuple('Net', 'net, mac, ip') - self.nets = [Net(net=10, mac='11:11:11:44:55:66', ip='10.1.2.20'), - Net(net=10, mac='11:11:11:44:55:67', ip='10.1.2.21'), - Net(net=20, mac='22:22:22:44:55:66', ip='10.2.2.20')] - - self.packet_mod = mock.Mock() - self.proto_ethernet_mod = mock.Mock() - self.proto_vlan_mod = mock.Mock() - self.proto_vlan_mod.vid = 999 - self.proto_arp_mod = mock.Mock() - self.fake_get_protocol = mock.Mock(return_value=self.proto_vlan_mod) - self.packet_mod.get_protocol = self.fake_get_protocol - self.fake_add_protocol = mock.Mock() - self.packet_mod.add_protocol = self.fake_add_protocol - self.arp = importutils.import_module('ryu.lib.packet.arp') - self.ethernet = importutils.import_module('ryu.lib.packet.ethernet') - self.vlan = importutils.import_module('ryu.lib.packet.vlan') - mock.patch('ryu.lib.packet.packet.Packet', - return_value=self.packet_mod).start() - - self.ryuapp = 'ryuapp' - self.inport = '1' - self.ev = mock.Mock() - self.datapath = self._mk_test_dp('tun_br') - self.ofproto = importutils.import_module('ryu.ofproto.ofproto_v1_3') - self.ofpp = mock.Mock() - self.datapath.ofproto = self.ofproto - self.datapath.ofproto_parser = self.ofpp - self.OFPActionOutput = mock.Mock() - self.OFPActionOutput.return_value = 'OFPActionOutput' - self.ofpp.OFPActionOutput = self.OFPActionOutput - self.msg = mock.Mock() - self.msg.datapath = self.datapath - self.msg.buffer_id = self.ofproto.OFP_NO_BUFFER - self.msg_data = 'test_message_data' - self.msg.data = self.msg_data - self.ev.msg = self.msg - self.msg.match = {'in_port': self.inport, - 'metadata': meta.LOCAL | self.nets[0].net} - - -class TestArpLib(OFAAgentTestCase): - - def setUp(self): - super(TestArpLib, self).setUp() - - self.mod_arplib = importutils.import_module(_OFALIB_NAME) - self.arplib = self.mod_arplib.ArpLib(self.ryuapp) - self.packet_mod.get_protocol = self._fake_get_protocol - self._fake_get_protocol_ethernet = True - self._fake_get_protocol_vlan = True - self._fake_get_protocol_arp = True - self.br = mock.Mock(datapath=self.datapath) - self.arplib.set_bridge(self.br) - - def test__send_unknown_packet_no_buffer(self): - in_port = 3 - out_port = self.ofproto.OFPP_TABLE - self.msg.buffer_id = self.ofproto.OFP_NO_BUFFER - self.arplib._send_unknown_packet(self.msg, in_port, out_port) - actions = [self.ofpp.OFPActionOutput(self.ofproto.OFPP_TABLE, 0)] - self.ofpp.OFPPacketOut.assert_called_once_with( - datapath=self.datapath, - buffer_id=self.msg.buffer_id, - in_port=in_port, - actions=actions, - data=self.msg_data) - - def test__send_unknown_packet_existence_buffer(self): - in_port = 3 - out_port = self.ofproto.OFPP_TABLE - self.msg.buffer_id = 256 - self.arplib._send_unknown_packet(self.msg, in_port, out_port) - actions = [self.ofpp.OFPActionOutput(self.ofproto.OFPP_TABLE, 0)] - self.ofpp.OFPPacketOut.assert_called_once_with( - datapath=self.datapath, - buffer_id=self.msg.buffer_id, - in_port=in_port, - actions=actions, - data=None) - - def test__respond_arp(self): - self.arplib._arp_tbl = { - self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}} - port = 3 - arptbl = self.arplib._arp_tbl[self.nets[0].net] - pkt_ethernet = self.ethernet - pkt_vlan = self.vlan - pkt_arp = self.arp - pkt_arp.opcode = self.arp.ARP_REQUEST - pkt_arp.dst_ip = self.nets[0].ip - with mock.patch.object( - self.arplib, '_send_arp_reply' - ) as send_arp_rep_fn: - self.assertTrue( - self.arplib._respond_arp(self.datapath, port, arptbl, - pkt_ethernet, pkt_vlan, pkt_arp)) - ethernet_ethernet = self.ethernet.ethernet( - ethertype=pkt_ethernet.ethertype, - dst=pkt_ethernet.src, - src=self.nets[0].mac) - vlan_vlan = self.vlan.vlan(cfi=pkt_vlan.cfi, - ethertype=pkt_vlan.ethertype, - pcp=pkt_vlan.pcp, - vid=pkt_vlan.vid) - arp_arp = self.arp.arp(opcode=self.arp.ARP_REPLY, - src_mac=self.nets[0].mac, - src_ip=pkt_arp.dst_ip, - dst_mac=pkt_arp.src_mac, - dst_ip=pkt_arp.src_ip) - self.fake_add_protocol.assert_has_calls([mock.call(ethernet_ethernet), - mock.call(vlan_vlan), - mock.call(arp_arp)]) - send_arp_rep_fn.assert_called_once_with( - self.datapath, port, self.packet_mod) - - def _test__respond_arp(self, pkt_arp): - self.arplib._arp_tbl = { - self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}} - port = 3 - arptbl = self.arplib._arp_tbl[self.nets[0].net] - pkt_ethernet = mock.Mock() - pkt_vlan = mock.Mock() - self.assertFalse( - self.arplib._respond_arp(self.datapath, port, arptbl, - pkt_ethernet, pkt_vlan, pkt_arp)) - - def test__respond_arp_non_arp_req(self): - pkt_arp = mock.Mock() - pkt_arp.opcode = self.arp.ARP_REPLY - self._test__respond_arp(pkt_arp) - - def test__respond_arp_ip_not_found_in_arptable(self): - pkt_arp = mock.Mock() - pkt_arp.opcode = self.arp.ARP_REQUEST - pkt_arp.dst_ip = self.nets[1].ip - self._test__respond_arp(pkt_arp) - - def test_add_arp_table_entry(self): - self.arplib.add_arp_table_entry(self.nets[0].net, - self.nets[0].ip, self.nets[0].mac) - self.assertEqual( - self.arplib._arp_tbl, - {self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}}) - - def test_add_arp_table_entry_multiple_net(self): - self.arplib.add_arp_table_entry(self.nets[0].net, - self.nets[0].ip, self.nets[0].mac) - self.arplib.add_arp_table_entry(self.nets[2].net, - self.nets[2].ip, self.nets[2].mac) - self.assertEqual( - self.arplib._arp_tbl, - {self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}, - self.nets[2].net: {self.nets[2].ip: self.nets[2].mac}}) - - def test_add_arp_table_entry_multiple_ip(self): - self.arplib.add_arp_table_entry(self.nets[0].net, - self.nets[0].ip, self.nets[0].mac) - self.arplib.add_arp_table_entry(self.nets[0].net, - self.nets[1].ip, self.nets[1].mac) - self.assertEqual( - self.arplib._arp_tbl, - {self.nets[0].net: {self.nets[0].ip: self.nets[0].mac, - self.nets[1].ip: self.nets[1].mac}}) - - def test_del_arp_table_entry(self): - self.arplib._arp_tbl = { - self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}} - self.arplib.del_arp_table_entry(self.nets[0].net, self.nets[0].ip) - self.assertEqual(self.arplib._arp_tbl, {}) - - def test_del_arp_table_entry_unknown_network(self): - self.arplib._arp_tbl = { - 100: {"192.0.2.1": "fa:16:3e:e2:37:37"}, - } - orig = copy.deepcopy(self.arplib._arp_tbl) - self.arplib.del_arp_table_entry(200, "192.0.2.1") - self.assertEqual(orig, self.arplib._arp_tbl) - - def test_del_arp_table_entry_unknown_ip(self): - self.arplib._arp_tbl = { - 100: {"192.0.2.1": "fa:16:3e:e2:37:37"}, - } - orig = copy.deepcopy(self.arplib._arp_tbl) - self.arplib.del_arp_table_entry(100, "192.0.2.9") - self.assertEqual(orig, self.arplib._arp_tbl) - - def test_del_arp_table_entry_multiple_net(self): - self.arplib._arp_tbl = { - self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}, - self.nets[2].net: {self.nets[2].ip: self.nets[2].mac}} - self.arplib.del_arp_table_entry(self.nets[0].net, self.nets[0].ip) - self.assertEqual( - self.arplib._arp_tbl, - {self.nets[2].net: {self.nets[2].ip: self.nets[2].mac}}) - - def test_del_arp_table_entry_multiple_ip(self): - self.arplib._arp_tbl = { - self.nets[0].net: {self.nets[0].ip: self.nets[0].mac, - self.nets[1].ip: self.nets[1].mac}} - self.arplib.del_arp_table_entry(self.nets[0].net, self.nets[1].ip) - self.assertEqual( - self.arplib._arp_tbl, - {self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}}) - - def _fake_get_protocol(self, net_type): - if net_type == self.ethernet.ethernet: - if self._fake_get_protocol_ethernet: - return self.proto_ethernet_mod - else: - return - if net_type == self.vlan.vlan: - if self._fake_get_protocol_vlan: - return self.proto_vlan_mod - else: - return - if net_type == self.arp.arp: - if self._fake_get_protocol_arp: - return self.proto_arp_mod - else: - return - - def _test_packet_in_handler(self): - self.arplib._arp_tbl = { - self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}} - with contextlib.nested( - mock.patch.object(self.arplib, '_respond_arp', - return_value=True), - mock.patch.object(self.br, - 'arp_passthrough'), - mock.patch.object(self.arplib, - '_send_unknown_packet'), - ) as (res_arp_fn, add_flow_fn, send_unknown_pk_fn): - self.arplib.packet_in_handler(self.ev) - self.assertFalse(add_flow_fn.call_count) - self.assertFalse(send_unknown_pk_fn.call_count) - res_arp_fn.assert_called_once_with( - self.datapath, self.inport, - self.arplib._arp_tbl[self.nets[0].net], - self.proto_ethernet_mod, - self.proto_vlan_mod if self._fake_get_protocol_vlan else None, - self.proto_arp_mod) - - def _test_packet_in_handler_drop(self): - self.arplib._arp_tbl = { - self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}} - with contextlib.nested( - mock.patch.object(self.arplib, '_respond_arp', - return_value=True), - mock.patch.object(self.br, 'arp_passthrough'), - mock.patch.object(self.arplib, - '_send_unknown_packet'), - ) as (res_arp_fn, add_flow_fn, send_unknown_pk_fn): - self.arplib.packet_in_handler(self.ev) - self.assertFalse(add_flow_fn.call_count) - self.assertFalse(send_unknown_pk_fn.call_count) - self.assertFalse(res_arp_fn.call_count) - - def test_packet_in_handler(self): - self._test_packet_in_handler() - - def test_packet_in_handler_non_ethernet(self): - self._fake_get_protocol_ethernet = False - self._test_packet_in_handler_drop() - - def test_packet_in_handler_non_vlan(self): - self._fake_get_protocol_vlan = False - self._test_packet_in_handler() - - def test_packet_in_handler_non_arp(self): - self._fake_get_protocol_arp = False - self._test_packet_in_handler_drop() - - def test_packet_in_handler_corrupted(self): - mock.patch('ryu.lib.packet.packet.Packet', - side_effect=ValueError).start() - self._test_packet_in_handler_drop() - - def test_packet_in_handler_unknown_network(self): - self.arplib._arp_tbl = { - self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}} - with contextlib.nested( - mock.patch.object(self.arplib, '_respond_arp', - return_value=False), - mock.patch.object(self.br, 'arp_passthrough'), - mock.patch.object(self.arplib, - '_send_unknown_packet'), - ) as (res_arp_fn, add_flow_fn, send_unknown_pk_fn): - self.arplib.packet_in_handler(self.ev) - add_flow_fn.assert_called_once_with( - network=self.nets[0].net, - tpa=self.proto_arp_mod.dst_ip) - send_unknown_pk_fn.assert_called_once_with( - self.ev.msg, self.msg.match['in_port'], - self.datapath.ofproto.OFPP_TABLE) - res_arp_fn.assert_called_once_with( - self.datapath, self.inport, - self.arplib._arp_tbl[self.nets[0].net], - self.proto_ethernet_mod, self.proto_vlan_mod, self.proto_arp_mod) diff --git a/neutron/tests/unit/ofagent/test_ofa_flows.py b/neutron/tests/unit/ofagent/test_ofa_flows.py deleted file mode 100644 index ab2ce7e3b..000000000 --- a/neutron/tests/unit/ofagent/test_ofa_flows.py +++ /dev/null @@ -1,384 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 YAMAMOTO Takashi -# 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_utils import importutils - -import neutron.plugins.ofagent.agent.metadata as meta -from neutron.tests.unit.ofagent import ofa_test_base - - -class TestOFAgentFlows(ofa_test_base.OFATestBase): - - _MOD = 'neutron.plugins.ofagent.agent.flows' - - def setUp(self): - super(TestOFAgentFlows, self).setUp() - self.mod = importutils.import_module(self._MOD) - self.br = self.mod.OFAgentIntegrationBridge() - self.br.set_dp(self._mk_test_dp("dp")) - - def test_setup_default_table(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.setup_default_table() - (dp, ofp, ofpp) = br._get_dp() - arp = importutils.import_module('ryu.lib.packet.arp') - ether = importutils.import_module('ryu.ofproto.ether') - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE, - match=ofpp.OFPMatch(), out_group=ofp.OFPG_ANY, - out_port=ofp.OFPP_ANY, priority=0, table_id=ofp.OFPTT_ALL)), - call(ofpp.OFPFlowMod(dp, priority=0, table_id=0)), - call(ofpp.OFPFlowMod(dp, priority=0, table_id=1)), - call(ofpp.OFPFlowMod(dp, priority=0, table_id=2)), - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=7)], - priority=0, table_id=3)), - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=5)], - priority=0, table_id=4)), - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=6)], - priority=0, table_id=5)), - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, - [ofpp.OFPActionOutput(ofp.OFPP_CONTROLLER)])], - match=ofpp.OFPMatch(arp_op=arp.ARP_REQUEST, - eth_type=ether.ETH_TYPE_ARP), priority=1, table_id=6)), - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=7)], - priority=0, table_id=6)), - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=8)], - priority=0, table_id=7)), - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=9)], - priority=0, table_id=8)), - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=10)], - priority=0, table_id=9)), - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=11)], - priority=0, table_id=10)), - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=12)], - priority=0, table_id=11)), - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=13)], - priority=0, table_id=12)), - call(ofpp.OFPFlowMod(dp, priority=0, table_id=13)), - ] - sendmsg.assert_has_calls(expected_calls, any_order=True) - - def test_install_arp_responder(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.install_arp_responder(table_id=99) - (dp, ofp, ofpp) = br._get_dp() - arp = importutils.import_module('ryu.lib.packet.arp') - ether = importutils.import_module('ryu.ofproto.ether') - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, - [ofpp.OFPActionOutput(ofp.OFPP_CONTROLLER)])], - match=ofpp.OFPMatch(arp_op=arp.ARP_REQUEST, - eth_type=ether.ETH_TYPE_ARP), priority=1, table_id=99)), - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=100)], - priority=0, table_id=99)), - ] - sendmsg.assert_has_calls(expected_calls) - - def test_install_tunnel_output(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.install_tunnel_output(table_id=110, network=111, - segmentation_id=112, ports=[113, 114], - goto_next=True) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call( - ofpp.OFPFlowMod( - dp, - instructions=[ - ofpp.OFPInstructionActions( - ofp.OFPIT_APPLY_ACTIONS, - [ - ofpp.OFPActionSetField(tunnel_id=112), - ofpp.OFPActionOutput(port=113), - ofpp.OFPActionOutput(port=114) - ] - ), - ofpp.OFPInstructionGotoTable(table_id=111) - ], - match=ofpp.OFPMatch( - metadata=meta.mk_metadata(111, meta.LOCAL) - ), - priority=1, - table_id=110 - ) - ) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_delete_tunnel_output(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.delete_tunnel_output(table_id=110, network=111) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call( - ofpp.OFPFlowMod( - dp, - command=ofp.OFPFC_DELETE, - match=ofpp.OFPMatch( - metadata=meta.mk_metadata(111, meta.LOCAL) - ), - out_group=ofp.OFPG_ANY, - out_port=ofp.OFPP_ANY, priority=0, table_id=110 - ) - ) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_provision_tenant_tunnel(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.provision_tenant_tunnel(network_type="gre", network=150, - segmentation_id=151) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionWriteMetadata(metadata=150, - metadata_mask=meta.NETWORK_MASK), - ofpp.OFPInstructionGotoTable(table_id=7)], - match=ofpp.OFPMatch(tunnel_id=151), priority=1, table_id=1)) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_reclaim_tenant_tunnel(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.reclaim_tenant_tunnel(network_type="gre", network=150, - segmentation_id=151) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE, - match=ofpp.OFPMatch(tunnel_id=151), out_group=ofp.OFPG_ANY, - out_port=ofp.OFPP_ANY, priority=0, table_id=1)) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_provision_tenant_physnet(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.provision_tenant_physnet(network_type="vlan", network=150, - segmentation_id=151, phys_port=99) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionWriteMetadata(metadata=150, - metadata_mask=meta.NETWORK_MASK), - ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [ - ofpp.OFPActionPopVlan()]), - ofpp.OFPInstructionGotoTable(table_id=3)], - match=ofpp.OFPMatch(in_port=99, - vlan_vid=151 | ofp.OFPVID_PRESENT), - priority=1, table_id=0)), - call( - ofpp.OFPFlowMod( - dp, - instructions=[ - ofpp.OFPInstructionActions( - ofp.OFPIT_APPLY_ACTIONS, - [ - ofpp.OFPActionPushVlan(), - ofpp.OFPActionSetField( - vlan_vid=151 | ofp.OFPVID_PRESENT - ), - ofpp.OFPActionOutput(port=99), - ofpp.OFPActionPopVlan() - ] - ), - ofpp.OFPInstructionGotoTable(table_id=13) - ], - match=ofpp.OFPMatch( - metadata=meta.mk_metadata(150, meta.LOCAL) - ), - priority=1, - table_id=12 - ) - ) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_reclaim_tenant_physnet(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.reclaim_tenant_physnet(network_type="vlan", network=150, - segmentation_id=151, phys_port=99) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE, - match=ofpp.OFPMatch(in_port=99, - vlan_vid=151 | ofp.OFPVID_PRESENT), - out_group=ofp.OFPG_ANY, out_port=ofp.OFPP_ANY, priority=0, - table_id=0)), - call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE, - match=ofpp.OFPMatch(metadata=meta.mk_metadata(150)), - out_group=ofp.OFPG_ANY, out_port=ofp.OFPP_ANY, priority=0, - table_id=12)) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_check_in_port_add_tunnel_port(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.check_in_port_add_tunnel_port(network_type="gre", port=99) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, - instructions=[ofpp.OFPInstructionGotoTable(table_id=1)], - match=ofpp.OFPMatch(in_port=99), priority=1, table_id=0)) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_check_in_port_add_local_port(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.check_in_port_add_local_port(network=123, port=99) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, - instructions=[ - ofpp.OFPInstructionWriteMetadata( - metadata=meta.LOCAL | 123, - metadata_mask=meta.LOCAL | meta.NETWORK_MASK), - ofpp.OFPInstructionGotoTable(table_id=4)], - match=ofpp.OFPMatch(in_port=99), priority=1, table_id=0)) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_check_in_port_delete_port(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.check_in_port_delete_port(port=99) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE, - match=ofpp.OFPMatch(in_port=99), out_group=ofp.OFPG_ANY, - out_port=ofp.OFPP_ANY, priority=0, table_id=0)) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_local_flood_update(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.local_flood_update(network=1234, ports=[1, 2, 3], - flood_unicast=True) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, - instructions=[ofpp.OFPInstructionActions( - ofp.OFPIT_APPLY_ACTIONS, [ - ofpp.OFPActionOutput(port=1), - ofpp.OFPActionOutput(port=2), - ofpp.OFPActionOutput(port=3)])], - match=ofpp.OFPMatch(metadata=meta.mk_metadata(1234)), - priority=1, table_id=13)), - call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE_STRICT, - match=ofpp.OFPMatch( - eth_dst=('01:00:00:00:00:00', '01:00:00:00:00:00'), - metadata=meta.mk_metadata(1234)), - out_group=ofp.OFPG_ANY, out_port=ofp.OFPP_ANY, priority=1, - table_id=13)) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_local_flood_delete(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.local_flood_delete(network=1234) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE, - match=ofpp.OFPMatch(metadata=meta.mk_metadata(1234)), - out_group=ofp.OFPG_ANY, out_port=ofp.OFPP_ANY, priority=0, - table_id=13)) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_local_out_add_port(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.local_out_add_port(network=1234, port=7, - mac='12:34:56:78:9a:bc') - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, - [ofpp.OFPActionOutput(port=7)])], - match=ofpp.OFPMatch(eth_dst="12:34:56:78:9a:bc", - metadata=meta.mk_metadata(1234)), priority=1, table_id=8)) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_local_out_delete_port(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.local_out_delete_port(network=1234, mac='12:34:56:78:9a:bc') - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE, - match=ofpp.OFPMatch(eth_dst="12:34:56:78:9a:bc", - metadata=meta.mk_metadata(1234)), out_group=ofp.OFPG_ANY, - out_port=ofp.OFPP_ANY, priority=0, table_id=8)) - ] - sendmsg.assert_has_calls(expected_calls) - - def test_arp_passthrough(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.arp_passthrough(network=1234, tpa='192.0.2.1') - (dp, ofp, ofpp) = br._get_dp() - arp = importutils.import_module('ryu.lib.packet.arp') - ether = importutils.import_module('ryu.ofproto.ether') - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, idle_timeout=5, - instructions=[ofpp.OFPInstructionGotoTable(table_id=7)], - match=ofpp.OFPMatch(arp_op=arp.ARP_REQUEST, - arp_tpa="192.0.2.1", eth_type=ether.ETH_TYPE_ARP, - metadata=meta.mk_metadata(1234)), priority=1, table_id=5)) - ] - sendmsg.assert_has_calls(expected_calls) diff --git a/neutron/tests/unit/ofagent/test_ofa_neutron_agent.py b/neutron/tests/unit/ofagent/test_ofa_neutron_agent.py deleted file mode 100644 index 9eb32d49b..000000000 --- a/neutron/tests/unit/ofagent/test_ofa_neutron_agent.py +++ /dev/null @@ -1,798 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 Fumihiko Kakuma -# Copyright (C) 2014 YAMAMOTO Takashi -# All Rights Reserved. -# -# Based on test for openvswitch agent(test_ovs_neutron_agent.py). -# -# 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 collections -import contextlib -import copy - -import mock -import netaddr -from oslo_config import cfg -from oslo_utils import importutils -import testtools - -from neutron.agent.linux import ovs_lib -from neutron.common import constants as n_const -from neutron.plugins.common import constants as p_const -from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc -from neutron.tests.unit.ofagent import ofa_test_base - - -NOTIFIER = ('neutron.plugins.ml2.rpc.AgentNotifierApi') -FLOODING_ENTRY = l2pop_rpc.PortInfo(*n_const.FLOODING_ENTRY) - - -def _mock_port(is_neutron=True, normalized_name=None): - p = mock.Mock() - p.is_neutron_port.return_value = is_neutron - if normalized_name: - p.normalized_port_name.return_value = normalized_name - return p - - -class CreateAgentConfigMap(ofa_test_base.OFAAgentTestBase): - - def test_create_agent_config_map_succeeds(self): - self.assertTrue(self.mod_agent.create_agent_config_map(cfg.CONF)) - - def test_create_agent_config_map_fails_for_invalid_tunnel_config(self): - # An ip address is required for tunneling but there is no default, - # verify this for both gre and vxlan tunnels. - cfg.CONF.set_override('tunnel_types', [p_const.TYPE_GRE], - group='AGENT') - with testtools.ExpectedException(ValueError): - self.mod_agent.create_agent_config_map(cfg.CONF) - cfg.CONF.set_override('tunnel_types', [p_const.TYPE_VXLAN], - group='AGENT') - with testtools.ExpectedException(ValueError): - self.mod_agent.create_agent_config_map(cfg.CONF) - - def test_create_agent_config_map_fails_no_local_ip(self): - # An ip address is required for tunneling but there is no default - cfg.CONF.set_override('tunnel_types', [p_const.TYPE_VXLAN], - group='AGENT') - with testtools.ExpectedException(ValueError): - self.mod_agent.create_agent_config_map(cfg.CONF) - - def test_create_agent_config_map_fails_for_invalid_tunnel_type(self): - cfg.CONF.set_override('tunnel_types', ['foobar'], group='AGENT') - with testtools.ExpectedException(ValueError): - self.mod_agent.create_agent_config_map(cfg.CONF) - - def test_create_agent_config_map_multiple_tunnel_types(self): - cfg.CONF.set_override('local_ip', '10.10.10.10', group='OVS') - cfg.CONF.set_override('tunnel_types', [p_const.TYPE_GRE, - p_const.TYPE_VXLAN], group='AGENT') - cfgmap = self.mod_agent.create_agent_config_map(cfg.CONF) - self.assertEqual(cfgmap['tunnel_types'], - [p_const.TYPE_GRE, p_const.TYPE_VXLAN]) - - -class TestOFANeutronAgentBridge(ofa_test_base.OFAAgentTestBase): - - def setUp(self): - super(TestOFANeutronAgentBridge, self).setUp() - self.br_name = 'bridge1' - self.ovs = self.mod_agent.Bridge( - self.br_name, self.ryuapp) - - def test_find_datapath_id(self): - with mock.patch.object(self.ovs, 'get_datapath_id', - return_value='12345'): - self.ovs.find_datapath_id() - self.assertEqual(self.ovs.datapath_id, '12345') - - def _fake_get_datapath(self, app, datapath_id): - if self.ovs.retry_count >= 2: - datapath = mock.Mock() - datapath.ofproto_parser = mock.Mock() - return datapath - self.ovs.retry_count += 1 - return None - - def test_get_datapath_normal(self): - self.ovs.retry_count = 0 - with mock.patch.object(self.mod_agent.ryu_api, 'get_datapath', - new=self._fake_get_datapath): - self.ovs.datapath_id = '0x64' - self.ovs.get_datapath(retry_max=4) - self.assertEqual(self.ovs.retry_count, 2) - - def test_get_datapath_retry_out_by_default_time(self): - cfg.CONF.set_override('get_datapath_retry_times', 3, group='AGENT') - with mock.patch.object(self.mod_agent.ryu_api, 'get_datapath', - return_value=None) as mock_get_datapath: - with testtools.ExpectedException(SystemExit): - self.ovs.datapath_id = '0x64' - self.ovs.get_datapath(retry_max=3) - self.assertEqual(mock_get_datapath.call_count, 3) - - def test_get_datapath_retry_out_by_specified_time(self): - with mock.patch.object(self.mod_agent.ryu_api, 'get_datapath', - return_value=None) as mock_get_datapath: - with testtools.ExpectedException(SystemExit): - self.ovs.datapath_id = '0x64' - self.ovs.get_datapath(retry_max=2) - self.assertEqual(mock_get_datapath.call_count, 2) - - def test_setup_ofp_default_par(self): - with contextlib.nested( - mock.patch.object(self.ovs, 'set_protocols'), - mock.patch.object(self.ovs, 'set_controller'), - mock.patch.object(self.ovs, 'find_datapath_id'), - mock.patch.object(self.ovs, 'get_datapath'), - ) as (mock_set_protocols, mock_set_controller, - mock_find_datapath_id, mock_get_datapath): - self.ovs.setup_ofp() - mock_set_protocols.assert_called_with('OpenFlow13') - mock_set_controller.assert_called_with(['tcp:127.0.0.1:6633']) - mock_get_datapath.assert_called_with( - cfg.CONF.AGENT.get_datapath_retry_times) - self.assertEqual(mock_find_datapath_id.call_count, 1) - - def test_setup_ofp_specify_par(self): - controller_names = ['tcp:192.168.10.10:1234', 'tcp:172.17.16.20:5555'] - with contextlib.nested( - mock.patch.object(self.ovs, 'set_protocols'), - mock.patch.object(self.ovs, 'set_controller'), - mock.patch.object(self.ovs, 'find_datapath_id'), - mock.patch.object(self.ovs, 'get_datapath'), - ) as (mock_set_protocols, mock_set_controller, - mock_find_datapath_id, mock_get_datapath): - self.ovs.setup_ofp(controller_names=controller_names, - protocols='OpenFlow133', - retry_max=11) - mock_set_protocols.assert_called_with('OpenFlow133') - mock_set_controller.assert_called_with(controller_names) - mock_get_datapath.assert_called_with(11) - self.assertEqual(mock_find_datapath_id.call_count, 1) - - def test_setup_ofp_with_except(self): - with contextlib.nested( - mock.patch.object(self.ovs, 'set_protocols', - side_effect=RuntimeError), - mock.patch.object(self.ovs, 'set_controller'), - mock.patch.object(self.ovs, 'find_datapath_id'), - mock.patch.object(self.ovs, 'get_datapath'), - ) as (mock_set_protocols, mock_set_controller, - mock_find_datapath_id, mock_get_datapath): - with testtools.ExpectedException(SystemExit): - self.ovs.setup_ofp() - - -class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase): - - def setUp(self): - super(TestOFANeutronAgent, self).setUp() - notifier_p = mock.patch(NOTIFIER) - notifier_cls = notifier_p.start() - self.notifier = mock.Mock() - notifier_cls.return_value = self.notifier - kwargs = self.mod_agent.create_agent_config_map(cfg.CONF) - - class MockFixedIntervalLoopingCall(object): - def __init__(self, f): - self.f = f - - def start(self, interval=0): - self.f() - - with contextlib.nested( - mock.patch.object(self.mod_agent.OFANeutronAgent, - 'setup_integration_br', - return_value=mock.Mock()), - mock.patch.object(self.mod_agent.Bridge, - 'get_local_port_mac', - return_value='00:00:00:00:00:01'), - mock.patch('neutron.agent.linux.utils.get_interface_mac', - return_value='00:00:00:00:00:01'), - mock.patch('neutron.openstack.common.loopingcall.' - 'FixedIntervalLoopingCall', - new=MockFixedIntervalLoopingCall)): - self.agent = self.mod_agent.OFANeutronAgent(self.ryuapp, **kwargs) - - self.agent.sg_agent = mock.Mock() - self.int_dp = self._mk_test_dp('int_br') - self.agent.int_br = self._mk_test_br('int_br') - self.agent.int_br.set_dp(self.int_dp) - self.agent.int_ofports['phys-net1'] = 666 - - def _create_tunnel_port_name(self, tunnel_ip, tunnel_type): - tunnel_ip_hex = '%08x' % netaddr.IPAddress(tunnel_ip, version=4) - return '%s-%s' % (tunnel_type, tunnel_ip_hex) - - def mock_scan_ports(self, port_set=None, registered_ports=None, - updated_ports=None, port_tags_dict=None): - port_tags_dict = port_tags_dict or {} - with contextlib.nested( - mock.patch.object(self.agent, '_get_ofport_names', - return_value=port_set), - mock.patch.object(self.agent.int_br, 'get_port_tag_dict', - return_value=port_tags_dict) - ): - return self.agent.scan_ports(registered_ports, updated_ports) - - def test_scan_ports_returns_current_only_for_unchanged_ports(self): - vif_port_set = set([1, 3]) - registered_ports = set([1, 3]) - expected = {'current': vif_port_set} - actual = self.mock_scan_ports(vif_port_set, registered_ports) - self.assertEqual(expected, actual) - - def test_scan_ports_returns_port_changes(self): - vif_port_set = set([1, 3]) - registered_ports = set([1, 2]) - expected = dict(current=vif_port_set, added=set([3]), removed=set([2])) - actual = self.mock_scan_ports(vif_port_set, registered_ports) - self.assertEqual(expected, actual) - - def _test_scan_ports_with_updated_ports(self, updated_ports): - vif_port_set = set([1, 3, 4]) - registered_ports = set([1, 2, 4]) - expected = dict(current=vif_port_set, added=set([3]), - removed=set([2]), updated=set([4])) - actual = self.mock_scan_ports(vif_port_set, registered_ports, - updated_ports) - self.assertEqual(expected, actual) - - def test_scan_ports_finds_known_updated_ports(self): - self._test_scan_ports_with_updated_ports(set([4])) - - def test_scan_ports_ignores_unknown_updated_ports(self): - # the port '5' was not seen on current ports. Hence it has either - # never been wired or already removed and should be ignored - self._test_scan_ports_with_updated_ports(set([4, 5])) - - def test_scan_ports_ignores_updated_port_if_removed(self): - vif_port_set = set([1, 3]) - registered_ports = set([1, 2]) - updated_ports = set([1, 2]) - expected = dict(current=vif_port_set, added=set([3]), - removed=set([2]), updated=set([1])) - actual = self.mock_scan_ports(vif_port_set, registered_ports, - updated_ports) - self.assertEqual(expected, actual) - - def test_scan_ports_no_vif_changes_returns_updated_port_only(self): - vif_port_set = set([1, 2, 3]) - registered_ports = set([1, 2, 3]) - updated_ports = set([2]) - expected = dict(current=vif_port_set, updated=set([2])) - actual = self.mock_scan_ports(vif_port_set, registered_ports, - updated_ports) - self.assertEqual(expected, actual) - - def test_treat_devices_added_returns_true_for_missing_device(self): - with contextlib.nested( - mock.patch.object(self.agent.plugin_rpc, 'get_device_details', - side_effect=Exception()), - mock.patch.object(self.agent, '_get_ports', - return_value=[_mock_port(True, 'xxx')])): - self.assertTrue(self.agent.treat_devices_added_or_updated(['xxx'])) - - def _mock_treat_devices_added_updated(self, details, port, all_ports, - func_name): - """Mock treat devices added or updated. - - :param details: the details to return for the device - :param port: port name to process - :param all_ports: the port that _get_ports return - :param func_name: the function that should be called - :returns: whether the named function was called - """ - with contextlib.nested( - mock.patch.object(self.agent.plugin_rpc, 'get_device_details', - return_value=details), - mock.patch.object(self.agent, '_get_ports', - return_value=all_ports), - mock.patch.object(self.agent.plugin_rpc, 'update_device_up'), - mock.patch.object(self.agent.plugin_rpc, 'update_device_down'), - mock.patch.object(self.agent, func_name) - ) as (get_dev_fn, _get_ports, upd_dev_up, upd_dev_down, func): - self.assertFalse(self.agent.treat_devices_added_or_updated([port])) - _get_ports.assert_called_once_with(self.agent.int_br) - return func.called - - def test_treat_devices_added_updated_ignores_invalid_ofport(self): - port_name = 'hoge' - p1 = _mock_port(True, port_name) - p1.ofport = -1 - self.assertFalse(self._mock_treat_devices_added_updated( - mock.MagicMock(), port_name, [p1], 'port_dead')) - - def test_treat_devices_added_updated_marks_unknown_port_as_dead(self): - port_name = 'hoge' - p1 = _mock_port(True, port_name) - p1.ofport = 1 - self.assertTrue(self._mock_treat_devices_added_updated( - mock.MagicMock(), port_name, [p1], 'port_dead')) - - def test_treat_devices_added_does_not_process_missing_port(self): - with contextlib.nested( - mock.patch.object(self.agent.plugin_rpc, 'get_device_details'), - mock.patch.object(self.agent.int_br, 'get_vif_port_by_id', - return_value=None) - ) as (get_dev_fn, get_vif_func): - self.assertFalse(get_dev_fn.called) - - def test_treat_devices_added_updated_updates_known_port(self): - port_name = 'tapd3315981-0b' - p1 = _mock_port(False) - p2 = _mock_port(True, port_name) - ports = [p1, p2] - details = mock.MagicMock() - details.__contains__.side_effect = lambda x: True - self.assertTrue(self._mock_treat_devices_added_updated( - details, port_name, ports, 'treat_vif_port')) - - def test_treat_devices_added_updated_put_port_down(self): - fake_details_dict = {'admin_state_up': False, - 'port_id': 'xxx', - 'device': 'xxx', - 'network_id': 'yyy', - 'physical_network': 'foo', - 'segmentation_id': 'bar', - 'network_type': 'baz'} - with contextlib.nested( - mock.patch.object(self.agent.plugin_rpc, 'get_device_details', - return_value=fake_details_dict), - mock.patch.object(self.agent, '_get_ports', - return_value=[_mock_port(True, 'xxx')]), - mock.patch.object(self.agent.plugin_rpc, 'update_device_up'), - mock.patch.object(self.agent.plugin_rpc, 'update_device_down'), - mock.patch.object(self.agent, 'treat_vif_port') - ) as (get_dev_fn, _get_ports, upd_dev_up, - upd_dev_down, treat_vif_port): - self.assertFalse(self.agent.treat_devices_added_or_updated( - ['xxx'])) - self.assertTrue(treat_vif_port.called) - self.assertTrue(upd_dev_down.called) - _get_ports.assert_called_once_with(self.agent.int_br) - - def test_treat_devices_removed_returns_true_for_missing_device(self): - with mock.patch.object(self.agent.plugin_rpc, 'update_device_down', - side_effect=Exception()): - self.assertTrue(self.agent.treat_devices_removed([{}])) - - def _mock_treat_devices_removed(self, port_exists): - details = dict(exists=port_exists) - with mock.patch.object(self.agent.plugin_rpc, 'update_device_down', - return_value=details): - with mock.patch.object(self.agent, 'port_unbound') as port_unbound: - self.assertFalse(self.agent.treat_devices_removed([{}])) - self.assertTrue(port_unbound.called) - - def test_treat_devices_removed_unbinds_port(self): - self._mock_treat_devices_removed(True) - - def test_treat_devices_removed_ignores_missing_port(self): - self._mock_treat_devices_removed(False) - - def _test_process_network_ports(self, port_info): - with contextlib.nested( - mock.patch.object(self.agent.sg_agent, "setup_port_filters"), - mock.patch.object(self.agent, "treat_devices_added_or_updated", - return_value=False), - mock.patch.object(self.agent, "treat_devices_removed", - return_value=False) - ) as (setup_port_filters, device_added_updated, device_removed): - self.assertFalse(self.agent.process_network_ports(port_info)) - setup_port_filters.assert_called_once_with( - port_info['added'], port_info.get('updated', set())) - device_added_updated.assert_called_once_with( - port_info['added'] | port_info.get('updated', set())) - device_removed.assert_called_once_with(port_info['removed']) - - def test_process_network_ports(self): - self._test_process_network_ports( - {'current': set(['tap0']), - 'removed': set(['eth0']), - 'added': set(['eth1'])}) - - def test_process_network_port_with_updated_ports(self): - self._test_process_network_ports( - {'current': set(['tap0', 'tap1']), - 'updated': set(['tap1', 'eth1']), - 'removed': set(['eth0']), - 'added': set(['eth1'])}) - - def test_report_state(self): - with mock.patch.object(self.agent.state_rpc, - "report_state") as report_st: - self.agent.int_br_device_count = 5 - self.agent._report_state() - report_st.assert_called_with(self.agent.context, - self.agent.agent_state) - self.assertNotIn("start_flag", self.agent.agent_state) - self.assertEqual( - self.agent.agent_state["configurations"]["devices"], - self.agent.int_br_device_count - ) - - def test_port_update(self): - port = {"id": "b1981919-f516-11e3-a8f4-08606e7f74e7", - "network_id": "124", - "admin_state_up": False} - self.agent.port_update("unused_context", - port=port, - network_type="vlan", - segmentation_id="1", - physical_network="physnet") - self.assertEqual(set(['tapb1981919-f5']), self.agent.updated_ports) - - def test_setup_physical_interfaces(self): - with mock.patch.object(self.agent.int_br, "add_port") as add_port_fn: - add_port_fn.return_value = "111" - self.agent.setup_physical_interfaces({"physnet1": "eth1"}) - add_port_fn.assert_called_once_with("eth1") - self.assertEqual(111, self.agent.int_ofports["physnet1"]) - - def test_port_unbound(self): - with contextlib.nested( - mock.patch.object(self.agent, "reclaim_local_vlan"), - mock.patch.object(self.agent, "get_net_uuid", - return_value="netuid12345"), - ) as (reclvl_fn, _): - self.agent.enable_tunneling = True - lvm = mock.Mock() - lvm.network_type = "gre" - lvm.vif_ports = {"vif1": mock.Mock()} - self.agent.local_vlan_map["netuid12345"] = lvm - self.agent.port_unbound("vif1") - self.assertTrue(reclvl_fn.called) - - def _prepare_l2_pop_ofports(self, network_type=None): - LVM = collections.namedtuple('LVM', 'net, vlan, segid, ip') - self.lvms = [LVM(net='net1', vlan=11, segid=21, ip='1.1.1.1'), - LVM(net='net2', vlan=12, segid=22, ip='2.2.2.2')] - self.tunnel_type = 'gre' - self.tun_name1 = self._create_tunnel_port_name(self.lvms[0].ip, - self.tunnel_type) - self.tun_name2 = self._create_tunnel_port_name(self.lvms[1].ip, - self.tunnel_type) - if network_type is None: - network_type = self.tunnel_type - lvm1 = mock.Mock() - lvm1.network_type = network_type - lvm1.vlan = self.lvms[0].vlan - lvm1.segmentation_id = self.lvms[0].segid - lvm1.tun_ofports = set([1]) - lvm2 = mock.Mock() - lvm2.network_type = network_type - lvm2.vlan = self.lvms[1].vlan - lvm2.segmentation_id = self.lvms[1].segid - lvm2.tun_ofports = set([1, 2]) - self.agent.tunnel_types = [self.tunnel_type] - self.agent.local_vlan_map = {self.lvms[0].net: lvm1, - self.lvms[1].net: lvm2} - self.agent.tun_ofports = {self.tunnel_type: - {self.lvms[0].ip: 1, - self.lvms[1].ip: 2}} - - def test_fdb_ignore_network(self): - self._prepare_l2_pop_ofports() - fdb_entry = {'net3': {}} - with contextlib.nested( - mock.patch.object(self.agent, '_setup_tunnel_port'), - mock.patch.object(self.agent, 'cleanup_tunnel_port') - ) as (add_tun_fn, clean_tun_fn): - self.agent.fdb_add(None, fdb_entry) - self.assertFalse(add_tun_fn.called) - self.agent.fdb_remove(None, fdb_entry) - self.assertFalse(clean_tun_fn.called) - - def test_fdb_ignore_self(self): - self._prepare_l2_pop_ofports() - self.agent.local_ip = 'agent_ip' - fdb_entry = {self.lvms[1].net: - {'network_type': self.tunnel_type, - 'segment_id': 'tun2', - 'ports': - {'agent_ip': - [l2pop_rpc.PortInfo('mac', 'ip'), - FLOODING_ENTRY]}}} - with contextlib.nested( - mock.patch.object(self.agent.ryuapp, "add_arp_table_entry"), - mock.patch.object(self.agent.ryuapp, "del_arp_table_entry"), - ) as (add_fn, del_fn): - self.agent.fdb_add(None, copy.deepcopy(fdb_entry)) - add_fn.assert_called_once_with(12, 'ip', 'mac') - self.assertFalse(del_fn.called) - self.agent.fdb_remove(None, fdb_entry) - add_fn.assert_called_once_with(12, 'ip', 'mac') - del_fn.assert_called_once_with(12, 'ip') - - def test_fdb_add_flows(self): - self._prepare_l2_pop_ofports() - fdb_entry = {self.lvms[0].net: - {'network_type': self.tunnel_type, - 'segment_id': 'tun1', - 'ports': - {self.lvms[1].ip: - [l2pop_rpc.PortInfo('mac', 'ip'), - FLOODING_ENTRY]}}} - with contextlib.nested( - mock.patch.object(self.agent, '_setup_tunnel_port'), - mock.patch.object(self.agent.int_br, 'install_tunnel_output'), - mock.patch.object(self.agent.int_br, 'delete_tunnel_output'), - ) as (add_tun_fn, install_fn, delete_fn): - add_tun_fn.return_value = 2 - self.agent.fdb_add(None, fdb_entry) - self.assertEqual(2, install_fn.call_count) - expected_calls = [ - mock.call(7, 11, 21, set([2]), eth_dst='mac', goto_next=False), - mock.call(10, 11, 21, set([1, 2]), goto_next=True) - ] - install_fn.assert_has_calls(expected_calls) - self.assertFalse(delete_fn.called) - - def test_fdb_del_flows(self): - self._prepare_l2_pop_ofports() - fdb_entry = {self.lvms[1].net: - {'network_type': self.tunnel_type, - 'segment_id': 'tun2', - 'ports': - {self.lvms[1].ip: - [l2pop_rpc.PortInfo('mac', 'ip'), - FLOODING_ENTRY]}}} - with contextlib.nested( - mock.patch.object(self.agent.int_br, 'install_tunnel_output'), - mock.patch.object(self.agent.int_br, 'delete_tunnel_output'), - ) as (install_fn, delete_fn): - self.agent.fdb_remove(None, fdb_entry) - install_fn.assert_called_once_with(10, 12, 22, set([1]), - goto_next=True) - delete_fn.assert_called_once_with(7, 12, eth_dst='mac') - - def test_fdb_add_port(self): - self._prepare_l2_pop_ofports() - tunnel_ip = '10.10.10.10' - tun_name = self._create_tunnel_port_name(tunnel_ip, - self.tunnel_type) - fdb_entry = {self.lvms[0].net: - {'network_type': self.tunnel_type, - 'segment_id': 'tun1', - 'ports': {self.lvms[0].ip: [l2pop_rpc.PortInfo('mac', - 'ip')]}}} - with mock.patch.object(self.agent, '_setup_tunnel_port') as add_tun_fn: - self.agent.fdb_add(None, fdb_entry) - self.assertFalse(add_tun_fn.called) - fdb_entry[self.lvms[0].net]['ports'][tunnel_ip] = [ - l2pop_rpc.PortInfo('mac', 'ip')] - self.agent.fdb_add(None, fdb_entry) - add_tun_fn.assert_called_with( - self.agent.int_br, tun_name, tunnel_ip, self.tunnel_type) - - def test_fdb_del_port(self): - self._prepare_l2_pop_ofports() - fdb_entry = {self.lvms[1].net: - {'network_type': self.tunnel_type, - 'segment_id': 'tun2', - 'ports': {self.lvms[1].ip: [FLOODING_ENTRY]}}} - with mock.patch.object(self.agent.int_br, - 'delete_port') as del_port_fn: - self.agent.fdb_remove(None, fdb_entry) - del_port_fn.assert_called_once_with(self.tun_name2) - - def test_add_arp_table_entry(self): - self._prepare_l2_pop_ofports() - fdb_entry = {self.lvms[0].net: - {'network_type': self.tunnel_type, - 'segment_id': 'tun1', - 'ports': {self.lvms[0].ip: [ - FLOODING_ENTRY, - l2pop_rpc.PortInfo('mac1', 'ip1')], - self.lvms[1].ip: [ - l2pop_rpc.PortInfo('mac2', 'ip2')], - '192.0.2.1': [ - FLOODING_ENTRY, - l2pop_rpc.PortInfo('mac3', 'ip3')]}}} - with mock.patch.object(self.agent, - 'setup_tunnel_port') as setup_tun_fn: - self.agent.fdb_add(None, fdb_entry) - calls = [ - mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan, - 'ip1', 'mac1'), - mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan, - 'ip2', 'mac2') - ] - self.ryuapp.add_arp_table_entry.assert_has_calls(calls, - any_order=True) - setup_tun_fn.assert_called_once_with(self.agent.int_br, - '192.0.2.1', 'gre') - - def _test_add_arp_table_entry_non_tunnel(self, network_type): - self._prepare_l2_pop_ofports(network_type=network_type) - fdb_entry = {self.lvms[0].net: - {'network_type': network_type, - 'segment_id': 'tun1', - 'ports': {self.lvms[0].ip: [ - FLOODING_ENTRY, - l2pop_rpc.PortInfo('mac1', 'ip1')], - self.lvms[1].ip: [ - l2pop_rpc.PortInfo('mac2', 'ip2')], - '192.0.2.1': [ - FLOODING_ENTRY, - l2pop_rpc.PortInfo('mac3', 'ip3')]}}} - with mock.patch.object(self.agent, - 'setup_tunnel_port') as setup_tun_fn: - self.agent.fdb_add(None, fdb_entry) - calls = [ - mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan, - 'ip1', 'mac1'), - mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan, - 'ip2', 'mac2') - ] - self.ryuapp.add_arp_table_entry.assert_has_calls(calls, - any_order=True) - self.assertFalse(setup_tun_fn.called) - - def test_add_arp_table_entry_vlan(self): - self._test_add_arp_table_entry_non_tunnel('vlan') - - def test_add_arp_table_entry_flat(self): - self._test_add_arp_table_entry_non_tunnel('flat') - - def test_add_arp_table_entry_local(self): - self._test_add_arp_table_entry_non_tunnel('local') - - def test_del_arp_table_entry(self): - self._prepare_l2_pop_ofports() - fdb_entry = {self.lvms[0].net: - {'network_type': self.tunnel_type, - 'segment_id': 'tun1', - 'ports': {self.lvms[0].ip: [ - FLOODING_ENTRY, - l2pop_rpc.PortInfo('mac1', 'ip1')], - self.lvms[1].ip: [ - l2pop_rpc.PortInfo('mac2', 'ip2')], - '192.0.2.1': [ - FLOODING_ENTRY, - l2pop_rpc.PortInfo('mac3', 'ip3')]}}} - with mock.patch.object(self.agent, - 'cleanup_tunnel_port') as cleanup_tun_fn: - self.agent.fdb_remove(None, fdb_entry) - calls = [ - mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan, - 'ip1'), - mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan, - 'ip2') - ] - self.ryuapp.del_arp_table_entry.assert_has_calls(calls, - any_order=True) - cleanup_tun_fn.assert_called_once_with(self.agent.int_br, 1, 'gre') - - def _test_del_arp_table_entry_non_tunnel(self, network_type): - self._prepare_l2_pop_ofports(network_type=network_type) - fdb_entry = {self.lvms[0].net: - {'network_type': network_type, - 'segment_id': 'tun1', - 'ports': {self.lvms[0].ip: [ - FLOODING_ENTRY, - l2pop_rpc.PortInfo('mac1', 'ip1')], - self.lvms[1].ip: [ - l2pop_rpc.PortInfo('mac2', 'ip2')], - '192.0.2.1': [ - FLOODING_ENTRY, - l2pop_rpc.PortInfo('mac3', 'ip3')]}}} - with mock.patch.object(self.agent, - 'cleanup_tunnel_port') as cleanup_tun_fn: - self.agent.fdb_remove(None, fdb_entry) - calls = [ - mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan, - 'ip1'), - mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan, - 'ip2') - ] - self.ryuapp.del_arp_table_entry.assert_has_calls(calls, - any_order=True) - self.assertFalse(cleanup_tun_fn.called) - - def test_del_arp_table_entry_vlan(self): - self._test_del_arp_table_entry_non_tunnel('vlan') - - def test_del_arp_table_entry_flat(self): - self._test_del_arp_table_entry_non_tunnel('flat') - - def test_del_arp_table_entry_local(self): - self._test_del_arp_table_entry_non_tunnel('local') - - def test_recl_lv_port_to_preserve(self): - self._prepare_l2_pop_ofports() - self.agent.enable_tunneling = True - with mock.patch.object( - self.agent.int_br, 'delete_port' - ) as del_port_fn: - self.agent.reclaim_local_vlan(self.lvms[0].net) - self.assertFalse(del_port_fn.called) - - def test_recl_lv_port_to_remove(self): - self._prepare_l2_pop_ofports() - self.agent.enable_tunneling = True - with mock.patch.object(self.agent.int_br, - 'delete_port') as del_port_fn: - self.agent.reclaim_local_vlan(self.lvms[1].net) - del_port_fn.assert_called_once_with(self.tun_name2) - - def test__setup_tunnel_port_error_negative(self): - with contextlib.nested( - mock.patch.object(self.agent.int_br, 'add_tunnel_port', - return_value=ovs_lib.INVALID_OFPORT), - mock.patch.object(self.mod_agent.LOG, 'error') - ) as (add_tunnel_port_fn, log_error_fn): - ofport = self.agent._setup_tunnel_port( - self.agent.int_br, 'gre-1', 'remote_ip', p_const.TYPE_GRE) - add_tunnel_port_fn.assert_called_once_with( - 'gre-1', 'remote_ip', self.agent.local_ip, p_const.TYPE_GRE, - self.agent.vxlan_udp_port, self.agent.dont_fragment) - log_error_fn.assert_called_once_with( - _("Failed to set-up %(type)s tunnel port to %(ip)s"), - {'type': p_const.TYPE_GRE, 'ip': 'remote_ip'}) - self.assertEqual(ofport, 0) - - def test_setup_tunnel_port_returns_zero_for_failed_port_add(self): - with mock.patch.object(self.agent.int_br, 'add_tunnel_port', - return_value=ovs_lib.INVALID_OFPORT): - result = self.agent._setup_tunnel_port(self.agent.int_br, 'gre-1', - 'remote_ip', - p_const.TYPE_GRE) - self.assertEqual(0, result) - - def test_tunnel_sync(self): - self.agent.local_ip = 'agent_ip' - self.agent.context = 'fake_context' - self.agent.tunnel_types = ['vxlan'] - self.agent.host = cfg.CONF.host - with mock.patch.object( - self.agent.plugin_rpc, 'tunnel_sync' - ) as tunnel_sync_rpc_fn: - self.agent.tunnel_sync() - tunnel_sync_rpc_fn.assert_called_once_with( - self.agent.context, - self.agent.local_ip, - self.agent.tunnel_types[0], - self.agent.host) - - def test__get_ports(self): - ofpp = importutils.import_module('ryu.ofproto.ofproto_v1_3_parser') - reply = [ofpp.OFPPortDescStatsReply(body=[ofpp.OFPPort(name='hoge', - port_no=8)])] - sendmsg = mock.Mock(return_value=reply) - self.mod_agent.ryu_api.send_msg = sendmsg - result = self.agent._get_ports(self.agent.int_br) - result = list(result) # convert generator to list. - self.assertEqual(1, len(result)) - self.assertEqual('hoge', result[0].port_name) - self.assertEqual(8, result[0].ofport) - expected_msg = ofpp.OFPPortDescStatsRequest( - datapath=self.agent.int_br.datapath) - sendmsg.assert_has_calls([mock.call(app=self.agent.ryuapp, - msg=expected_msg, reply_cls=ofpp.OFPPortDescStatsReply, - reply_multi=True)]) - - def test__get_ofport_names(self): - names = ['p111', 'p222', 'p333'] - ps = [_mock_port(True, x) for x in names] - with mock.patch.object(self.agent, '_get_ports', - return_value=ps) as _get_ports: - result = self.agent._get_ofport_names('hoge') - _get_ports.assert_called_once_with('hoge') - self.assertEqual(set(names), result) diff --git a/neutron/tests/unit/ofagent/test_ofa_ports.py b/neutron/tests/unit/ofagent/test_ofa_ports.py deleted file mode 100644 index 8a19d8a70..000000000 --- a/neutron/tests/unit/ofagent/test_ofa_ports.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 YAMAMOTO Takashi -# 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.common import constants as n_const -from neutron.plugins.ofagent.agent import ports -from neutron.tests import base - - -class TestOFAgentPorts(base.BaseTestCase): - def test_port(self): - name = 'foo03b9a237-0b' - p1 = ports.Port(port_name=name, ofport=999) - ryu_ofp_port = mock.Mock(port_no=999) - ryu_ofp_port.name = name - p2 = ports.Port.from_ofp_port(ofp_port=ryu_ofp_port) - self.assertEqual(p1.port_name, p2.port_name) - self.assertEqual(p1.ofport, p2.ofport) - self.assertFalse(p1.is_neutron_port()) - self.assertFalse(p2.is_neutron_port()) - - def test_neutron_port(self): - for pref in ['qvo', 'qr-', 'qg-', n_const.TAP_DEVICE_PREFIX]: - name = pref + '03b9a237-0b' - p1 = ports.Port(port_name=name, ofport=999) - ryu_ofp_port = mock.Mock(port_no=999) - ryu_ofp_port.name = name - p2 = ports.Port.from_ofp_port(ofp_port=ryu_ofp_port) - self.assertEqual(p1.port_name, p2.port_name) - self.assertEqual(p1.ofport, p2.ofport) - self.assertTrue(p1.is_neutron_port()) - self.assertTrue(p2.is_neutron_port()) - self.assertTrue('tap03b9a237-0b', p1.normalized_port_name()) - self.assertTrue('tap03b9a237-0b', p2.normalized_port_name()) - - def test_get_normalized_port_name(self): - self.assertEqual('tap03b9a237-0b', - ports.get_normalized_port_name( - '03b9a237-0b1b-11e4-b537-08606e7f74e7')) diff --git a/neutron/tests/unit/ofagent/test_ofswitch.py b/neutron/tests/unit/ofagent/test_ofswitch.py deleted file mode 100644 index 3ce31ea60..000000000 --- a/neutron/tests/unit/ofagent/test_ofswitch.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (C) 2014 VA Linux Systems Japan K.K. -# Copyright (C) 2014 YAMAMOTO Takashi -# 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_utils import importutils - -from neutron.tests.unit.ofagent import ofa_test_base - - -class TestOFAgentFlows(ofa_test_base.OFATestBase): - - _MOD = 'neutron.plugins.ofagent.agent.ofswitch' - - def setUp(self): - super(TestOFAgentFlows, self).setUp() - self.mod = importutils.import_module(self._MOD) - self.br = self.mod.OpenFlowSwitch() - self.br.set_dp(self._mk_test_dp("dp")) - - def test_delete_flows(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.delete_flows() - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE, - match=ofpp.OFPMatch(), out_group=ofp.OFPG_ANY, - out_port=ofp.OFPP_ANY, priority=0, table_id=ofp.OFPTT_ALL)), - ] - sendmsg.assert_has_calls(expected_calls) - - def test_install_default_drop(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.install_default_drop(table_id=98) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, priority=0, table_id=98)), - ] - sendmsg.assert_has_calls(expected_calls) - - def test_install_default_goto(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.install_default_goto(table_id=98, dest_table_id=150) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=150)], - priority=0, table_id=98)), - ] - sendmsg.assert_has_calls(expected_calls) - - def test_install_default_goto_next(self): - br = self.br - with mock.patch.object(br, '_send_msg') as sendmsg: - br.install_default_goto_next(table_id=100) - (dp, ofp, ofpp) = br._get_dp() - call = mock.call - expected_calls = [ - call(ofpp.OFPFlowMod(dp, instructions=[ - ofpp.OFPInstructionGotoTable(table_id=101)], - priority=0, table_id=100)), - ] - sendmsg.assert_has_calls(expected_calls) diff --git a/setup.cfg b/setup.cfg index 6a5a5e5d4..afa3c3c3b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -38,7 +38,6 @@ data_files = etc/neutron/rootwrap.d/l3.filters etc/neutron/rootwrap.d/linuxbridge-plugin.filters etc/neutron/rootwrap.d/nec-plugin.filters - etc/neutron/rootwrap.d/ofagent.filters etc/neutron/rootwrap.d/openvswitch-plugin.filters etc/init.d = etc/init.d/neutron-server etc/neutron/plugins/bigswitch = @@ -113,7 +112,6 @@ console_scripts = neutron-rootwrap = oslo_rootwrap.cmd:main neutron-usage-audit = neutron.cmd.usage_audit:main neutron-metering-agent = neutron.cmd.eventlet.services.metering_agent:main - neutron-ofagent-agent = neutron.plugins.ofagent.agent.main:main neutron-sriov-nic-agent = neutron.plugins.sriovnicagent.sriov_nic_agent:main neutron-sanity-check = neutron.cmd.sanity_check:main neutron.core_plugins = @@ -178,7 +176,7 @@ neutron.ml2.mechanism_drivers = cisco_apic = neutron.plugins.ml2.drivers.cisco.apic.mechanism_apic:APICMechanismDriver l2population = neutron.plugins.ml2.drivers.l2pop.mech_driver:L2populationMechanismDriver bigswitch = neutron.plugins.ml2.drivers.mech_bigswitch.driver:BigSwitchMechanismDriver - ofagent = neutron.plugins.ml2.drivers.mech_ofagent:OfagentMechanismDriver + ofagent = networking_ofagent.plugins.ml2.drivers.mech_ofagent:OfagentMechanismDriver mlnx = neutron.plugins.ml2.drivers.mlnx.mech_mlnx:MlnxMechanismDriver brocade = neutron.plugins.ml2.drivers.brocade.mechanism_brocade:BrocadeMechanism fslsdn = neutron.plugins.ml2.drivers.freescale.mechanism_fslsdn:FslsdnMechanismDriver -- 2.45.2