From: Carl Baldwin Date: Wed, 6 Aug 2014 01:02:09 +0000 (+0000) Subject: Refactor l2_pop code to pass mac/ip info more readably X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=8f50bc29edf0788dbc6220d56b45334eab9ecdc9;p=openstack-build%2Fneutron-build.git Refactor l2_pop code to pass mac/ip info more readably Previous code used a 2 element array to represent a mac/ip address pair. Code assumed that element 0 was mac and 1 was ip. This made the code difficult to read and difficult to maintain. An attempt was made to insert a third value that failed miserably because of the position dependence and other code that assumed not only positions but also the number of elements. Using a namedtuple seems to be the best way to get better maintainability. Named tuples can be compared with regular tuples. The json serializer still uses an array to represent it so the on-wire representation of the object has not changed. A short snip of code was required to restore the namedtuple from the RPC message. Change-Id: I7f8c93b0e12ee0179bb23dfbb3a3d814615b1c2e Closes-Bug: #1352801 --- diff --git a/neutron/agent/l2population_rpc.py b/neutron/agent/l2population_rpc.py index 2798eee5e..6cc64fc68 100644 --- a/neutron/agent/l2population_rpc.py +++ b/neutron/agent/l2population_rpc.py @@ -21,6 +21,7 @@ import six from neutron.common import constants as n_const from neutron.common import log from neutron.openstack.common import log as logging +from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc LOG = logging.getLogger(__name__) @@ -38,17 +39,43 @@ class L2populationRpcCallBackMixin(object): @log.log def add_fdb_entries(self, context, fdb_entries, host=None): if not host or host == cfg.CONF.host: - self.fdb_add(context, fdb_entries) + self.fdb_add(context, self._unmarshall_fdb_entries(fdb_entries)) @log.log def remove_fdb_entries(self, context, fdb_entries, host=None): if not host or host == cfg.CONF.host: - self.fdb_remove(context, fdb_entries) + self.fdb_remove(context, self._unmarshall_fdb_entries(fdb_entries)) @log.log def update_fdb_entries(self, context, fdb_entries, host=None): if not host or host == cfg.CONF.host: - self.fdb_update(context, fdb_entries) + self.fdb_update(context, self._unmarshall_fdb_entries(fdb_entries)) + + @staticmethod + def _unmarshall_fdb_entries(fdb_entries): + """Prepares fdb_entries from JSON. + + All methods in this class that receive messages should call this to + unmarshall fdb_entries from the wire. + + :param fdb_entries: Original fdb_entries data-structure. Looks like: + { + : { + ..., + 'ports': { + : [ [, ], ... ], + ... + + :returns: Deep copy with [, ] converted to PortInfo + """ + unmarshalled = dict(fdb_entries) + for value in unmarshalled.values(): + if 'ports' in value: + value['ports'] = dict( + (address, [l2pop_rpc.PortInfo(*pi) for pi in port_infos]) + for address, port_infos in value['ports'].items() + ) + return unmarshalled @abc.abstractmethod def fdb_add(self, context, fdb_entries): @@ -80,9 +107,10 @@ class L2populationRpcCallBackTunnelMixin(L2populationRpcCallBackMixin): :param br: represent the bridge on which add_fdb_flow should be applied. - :param port_info: list to include mac and ip. + :param port_info: PortInfo instance to include mac and ip. + .mac_address + .ip_address - [mac, ip] :remote_ip: remote ip address. :param lvm: a local VLAN map of network. :param ofport: a port to add. @@ -100,8 +128,10 @@ class L2populationRpcCallBackTunnelMixin(L2populationRpcCallBackMixin): :param br: represent the bridge on which del_fdb_flow should be applied. - :param port_info: a list to contain mac and ip. - [mac, ip] + :param port_info: PortInfo instance to include mac and ip. + .mac_address + .ip_address + :remote_ip: remote ip address. :param lvm: local VLAN map of network. :param ofport: a port to delete. @@ -222,13 +252,16 @@ class L2populationRpcCallBackTunnelMixin(L2populationRpcCallBackMixin): agent and network. {'net1': {'agent_ip': - {'before': [[mac, ip]], - 'after': [[mac, ip]] + {'before': PortInfo, + 'after': PortInfo } } 'net2': ... } + + PortInfo has .mac_address and .ip_address attrs. + :param local_ip: local IP address of this agent. :local_vlan_map: local VLAN map of network. ''' @@ -243,11 +276,13 @@ class L2populationRpcCallBackTunnelMixin(L2populationRpcCallBackMixin): continue after = state.get('after', []) - for mac, ip in after: - self.setup_entry_for_arp_reply(br, 'add', lvm.vlan, mac, - ip) + for mac_ip in after: + self.setup_entry_for_arp_reply(br, 'add', lvm.vlan, + mac_ip.mac_address, + mac_ip.ip_address) before = state.get('before', []) - for mac, ip in before: - self.setup_entry_for_arp_reply(br, 'remove', lvm.vlan, mac, - ip) + for mac_ip in before: + self.setup_entry_for_arp_reply(br, 'remove', lvm.vlan, + mac_ip.mac_address, + mac_ip.ip_address) diff --git a/neutron/common/constants.py b/neutron/common/constants.py index 59066903b..2935760c6 100644 --- a/neutron/common/constants.py +++ b/neutron/common/constants.py @@ -70,7 +70,7 @@ MAX_GRE_ID = 2 ** 32 - 1 MIN_VXLAN_VNI = 1 MAX_VXLAN_VNI = 2 ** 24 - 1 -FLOODING_ENTRY = ['00:00:00:00:00:00', '0.0.0.0'] +FLOODING_ENTRY = ('00:00:00:00:00:00', '0.0.0.0') EXT_NS_COMP = '_backward_comp_e_ns' EXT_NS = '_extension_ns' diff --git a/neutron/plugins/ml2/drivers/l2pop/mech_driver.py b/neutron/plugins/ml2/drivers/l2pop/mech_driver.py index c85acb1c7..75c8f0d06 100644 --- a/neutron/plugins/ml2/drivers/l2pop/mech_driver.py +++ b/neutron/plugins/ml2/drivers/l2pop/mech_driver.py @@ -40,8 +40,9 @@ class L2populationMechanismDriver(api.MechanismDriver, self.migrated_ports = {} def _get_port_fdb_entries(self, port): - return [[port['mac_address'], - ip['ip_address']] for ip in port['fixed_ips']] + return [l2pop_rpc.PortInfo(mac_address=port['mac_address'], + ip_address=ip['ip_address']) + for ip in port['fixed_ips']] def delete_port_postcommit(self, context): port = context.current @@ -75,8 +76,12 @@ class L2populationMechanismDriver(api.MechanismDriver, return agent, agent_host, agent_ip, segment, port_fdb_entries = port_infos - orig_mac_ip = [[port['mac_address'], ip] for ip in orig_ips] - port_mac_ip = [[port['mac_address'], ip] for ip in port_ips] + orig_mac_ip = [l2pop_rpc.PortInfo(mac_address=port['mac_address'], + ip_address=ip) + for ip in orig_ips] + port_mac_ip = [l2pop_rpc.PortInfo(mac_address=port['mac_address'], + ip_address=ip) + for ip in port_ips] upd_fdb_entries = {port['network_id']: {agent_ip: {}}} diff --git a/neutron/plugins/ml2/drivers/l2pop/rpc.py b/neutron/plugins/ml2/drivers/l2pop/rpc.py index 8b5efacf2..95341cca5 100644 --- a/neutron/plugins/ml2/drivers/l2pop/rpc.py +++ b/neutron/plugins/ml2/drivers/l2pop/rpc.py @@ -13,6 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. +import collections +import copy + from neutron.common import rpc as n_rpc from neutron.common import topics from neutron.openstack.common import log as logging @@ -21,6 +24,9 @@ from neutron.openstack.common import log as logging LOG = logging.getLogger(__name__) +PortInfo = collections.namedtuple("PortInfo", "mac_address ip_address") + + class L2populationAgentNotifyAPI(n_rpc.RpcProxy): BASE_RPC_API_VERSION = '1.0' @@ -39,8 +45,10 @@ class L2populationAgentNotifyAPI(n_rpc.RpcProxy): 'method': method, 'fdb_entries': fdb_entries}) + marshalled_fdb_entries = self._marshall_fdb_entries(fdb_entries) self.fanout_cast(context, - self.make_msg(method, fdb_entries=fdb_entries), + self.make_msg(method, + fdb_entries=marshalled_fdb_entries), topic=self.topic_l2pop_update) def _notification_host(self, context, method, fdb_entries, host): @@ -50,8 +58,10 @@ class L2populationAgentNotifyAPI(n_rpc.RpcProxy): 'topic': self.topic, 'method': method, 'fdb_entries': fdb_entries}) + marshalled_fdb_entries = self._marshall_fdb_entries(fdb_entries) self.cast(context, - self.make_msg(method, fdb_entries=fdb_entries), + self.make_msg(method, + fdb_entries=marshalled_fdb_entries), topic='%s.%s' % (self.topic_l2pop_update, host)) def add_fdb_entries(self, context, fdb_entries, host=None): @@ -80,3 +90,28 @@ class L2populationAgentNotifyAPI(n_rpc.RpcProxy): else: self._notification_fanout(context, 'update_fdb_entries', fdb_entries) + + @staticmethod + def _marshall_fdb_entries(fdb_entries): + """Prepares fdb_entries for serialization to JSON for RPC. + + All methods in this class that send messages should call this to + marshall fdb_entries for the wire. + + :param fdb_entries: Original fdb_entries data-structure. Looks like: + { + : { + ..., + 'ports': { + : [ PortInfo, ... ], + ... + + :returns: Deep copy with PortInfo converted to [mac, ip] + """ + marshalled = copy.deepcopy(fdb_entries) + for value in marshalled.values(): + if 'ports' in value: + for address, port_infos in value['ports'].items(): + value['ports'][address] = [[mac, ip] + for mac, ip in port_infos] + return marshalled diff --git a/neutron/plugins/ofagent/agent/ofa_neutron_agent.py b/neutron/plugins/ofagent/agent/ofa_neutron_agent.py index 8c4b98a3e..76f692891 100644 --- a/neutron/plugins/ofagent/agent/ofa_neutron_agent.py +++ b/neutron/plugins/ofagent/agent/ofa_neutron_agent.py @@ -379,8 +379,9 @@ class OFANeutronAgent(n_rpc.RpcCallback, for port_info in port_infos: if port_info == n_const.FLOODING_ENTRY: continue - self.ryuapp.add_arp_table_entry( - lvm.vlan, port_info[1], port_info[0]) + self.ryuapp.add_arp_table_entry(lvm.vlan, + port_info.ip_address, + port_info.mac_address) @log.log def _fdb_remove_arp(self, lvm, agent_ports): @@ -388,7 +389,7 @@ class OFANeutronAgent(n_rpc.RpcCallback, for port_info in port_infos: if port_info == n_const.FLOODING_ENTRY: continue - self.ryuapp.del_arp_table_entry(lvm.vlan, port_info[1]) + self.ryuapp.del_arp_table_entry(lvm.vlan, port_info.ip_address) def add_fdb_flow(self, br, port_info, remote_ip, lvm, ofport): if port_info == n_const.FLOODING_ENTRY: @@ -399,11 +400,13 @@ class OFANeutronAgent(n_rpc.RpcCallback, lvm.tun_ofports, goto_next=True) else: self.ryuapp.add_arp_table_entry( - lvm.vlan, port_info[1], port_info[0]) + lvm.vlan, + port_info.ip_address, + port_info.mac_address) br.install_tunnel_output( tables.TUNNEL_OUT, lvm.vlan, lvm.segmentation_id, - set([ofport]), goto_next=False, eth_dst=port_info[0]) + set([ofport]), goto_next=False, eth_dst=port_info.mac_address) def del_fdb_flow(self, br, port_info, remote_ip, lvm, ofport): if port_info == n_const.FLOODING_ENTRY: @@ -418,9 +421,9 @@ class OFANeutronAgent(n_rpc.RpcCallback, tables.TUNNEL_FLOOD[lvm.network_type], lvm.vlan) else: - self.ryuapp.del_arp_table_entry(lvm.vlan, port_info[1]) + self.ryuapp.del_arp_table_entry(lvm.vlan, port_info.ip_address) br.delete_tunnel_output(tables.TUNNEL_OUT, - lvm.vlan, eth_dst=port_info[0]) + lvm.vlan, eth_dst=port_info.mac_address) def setup_entry_for_arp_reply(self, br, action, local_vid, mac_address, ip_address): diff --git a/neutron/plugins/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/openvswitch/agent/ovs_neutron_agent.py index 8901cdeb9..173ba01bd 100644 --- a/neutron/plugins/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/openvswitch/agent/ovs_neutron_agent.py @@ -375,12 +375,13 @@ class OVSNeutronAgent(n_rpc.RpcCallback, actions="strip_vlan,set_tunnel:%s,output:%s" % (lvm.segmentation_id, ofports)) else: - self.setup_entry_for_arp_reply(br, 'add', lvm.vlan, port_info[0], - port_info[1]) + self.setup_entry_for_arp_reply(br, 'add', lvm.vlan, + port_info.mac_address, + port_info.ip_address) br.add_flow(table=constants.UCAST_TO_TUN, priority=2, dl_vlan=lvm.vlan, - dl_dst=port_info[0], + dl_dst=port_info.mac_address, actions="strip_vlan,set_tunnel:%s,output:%s" % (lvm.segmentation_id, ofport)) @@ -398,10 +399,11 @@ class OVSNeutronAgent(n_rpc.RpcCallback, br.delete_flows(table=constants.FLOOD_TO_TUN, dl_vlan=lvm.vlan) else: self.setup_entry_for_arp_reply(br, 'remove', lvm.vlan, - port_info[0], port_info[1]) + port_info.mac_address, + port_info.ip_address) br.delete_flows(table=constants.UCAST_TO_TUN, dl_vlan=lvm.vlan, - dl_dst=port_info[0]) + dl_dst=port_info.mac_address) def _fdb_chg_ip(self, context, fdb_entries): LOG.debug("update chg_ip received") diff --git a/neutron/tests/unit/agent/l2population_rpc_base.py b/neutron/tests/unit/agent/l2population_rpc_base.py index c9c22de0f..8ce648213 100644 --- a/neutron/tests/unit/agent/l2population_rpc_base.py +++ b/neutron/tests/unit/agent/l2population_rpc_base.py @@ -18,6 +18,7 @@ import collections import mock from neutron.agent import l2population_rpc +from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc from neutron.plugins.openvswitch.agent import ovs_neutron_agent from neutron.tests import base @@ -81,9 +82,9 @@ class TestL2populationRpcCallBackTunnelMixinBase(base.BaseTestCase): port='port3')] self.agent_ports = { - self.ports[0].ip: [[self.lvms[0].mac, self.lvms[0].ip]], - self.ports[1].ip: [[self.lvms[1].mac, self.lvms[1].ip]], - self.ports[2].ip: [[self.lvms[2].mac, self.lvms[2].ip]], + self.ports[0].ip: [(self.lvms[0].mac, self.lvms[0].ip)], + self.ports[1].ip: [(self.lvms[1].mac, self.lvms[1].ip)], + self.ports[2].ip: [(self.lvms[2].mac, self.lvms[2].ip)], } self.fdb_entries1 = { @@ -92,21 +93,21 @@ class TestL2populationRpcCallBackTunnelMixinBase(base.BaseTestCase): 'segment_id': self.lvms[0].segid, 'ports': { self.local_ip: [], - self.ports[0].ip: [[self.lvms[0].mac, self.lvms[0].ip]]}, + self.ports[0].ip: [(self.lvms[0].mac, self.lvms[0].ip)]}, }, self.lvms[1].net: { 'network_type': self.type_gre, 'segment_id': self.lvms[1].segid, 'ports': { self.local_ip: [], - self.ports[1].ip: [[self.lvms[1].mac, self.lvms[1].ip]]}, + self.ports[1].ip: [(self.lvms[1].mac, self.lvms[1].ip)]}, }, self.lvms[2].net: { 'network_type': self.type_gre, 'segment_id': self.lvms[2].segid, 'ports': { self.local_ip: [], - self.ports[2].ip: [[self.lvms[2].mac, self.lvms[2].ip]]}, + self.ports[2].ip: [(self.lvms[2].mac, self.lvms[2].ip)]}, }, } @@ -129,18 +130,24 @@ class TestL2populationRpcCallBackTunnelMixinBase(base.BaseTestCase): self.upd_fdb_entry1_val = { self.lvms[0].net: { self.ports[0].ip: { - 'before': [[self.lvms[0].mac, self.lvms[0].ip]], - 'after': [[self.lvms[1].mac, self.lvms[1].ip]], + 'before': [l2pop_rpc.PortInfo(self.lvms[0].mac, + self.lvms[0].ip)], + 'after': [l2pop_rpc.PortInfo(self.lvms[1].mac, + self.lvms[1].ip)], }, self.ports[1].ip: { - 'before': [[self.lvms[0].mac, self.lvms[0].ip]], - 'after': [[self.lvms[1].mac, self.lvms[1].ip]], + 'before': [l2pop_rpc.PortInfo(self.lvms[0].mac, + self.lvms[0].ip)], + 'after': [l2pop_rpc.PortInfo(self.lvms[1].mac, + self.lvms[1].ip)], }, }, self.lvms[1].net: { self.ports[2].ip: { - 'before': [[self.lvms[0].mac, self.lvms[0].ip]], - 'after': [[self.lvms[2].mac, self.lvms[2].ip]], + 'before': [l2pop_rpc.PortInfo(self.lvms[0].mac, + self.lvms[0].ip)], + 'after': [l2pop_rpc.PortInfo(self.lvms[2].mac, + self.lvms[2].ip)], }, }, } diff --git a/neutron/tests/unit/agent/test_l2population_rpc.py b/neutron/tests/unit/agent/test_l2population_rpc.py index 563c53b19..b0b8f7e49 100644 --- a/neutron/tests/unit/agent/test_l2population_rpc.py +++ b/neutron/tests/unit/agent/test_l2population_rpc.py @@ -39,10 +39,10 @@ class TestL2populationRpcCallBackTunnelMixin( results[lvm] = agent_ports expected = { self.lvm1: { - self.ports[0].ip: [[self.lvms[0].mac, self.lvms[0].ip]], + self.ports[0].ip: [(self.lvms[0].mac, self.lvms[0].ip)], self.local_ip: []}, self.lvm3: { - self.ports[2].ip: [[self.lvms[2].mac, self.lvms[2].ip]], + self.ports[2].ip: [(self.lvms[2].mac, self.lvms[2].ip)], self.local_ip: []}, } self.assertEqual(expected, results) @@ -55,11 +55,11 @@ class TestL2populationRpcCallBackTunnelMixin( results[lvm] = agent_ports expected = { self.lvm1: { - self.ports[0].ip: [[self.lvms[0].mac, self.lvms[0].ip]], + self.ports[0].ip: [(self.lvms[0].mac, self.lvms[0].ip)], self.local_ip: []}, self.lvm2: {}, self.lvm3: { - self.ports[2].ip: [[self.lvms[2].mac, self.lvms[2].ip]], + self.ports[2].ip: [(self.lvms[2].mac, self.lvms[2].ip)], self.local_ip: []}, } self.assertEqual(expected, results) @@ -72,11 +72,11 @@ class TestL2populationRpcCallBackTunnelMixin( self.fakeagent.fdb_add_tun('context', self.fakebr, self.lvm1, self.agent_ports, self.ofports) expected = [ - mock.call(self.fakebr, [self.lvms[0].mac, self.lvms[0].ip], + mock.call(self.fakebr, (self.lvms[0].mac, self.lvms[0].ip), self.ports[0].ip, self.lvm1, self.ports[0].ofport), - mock.call(self.fakebr, [self.lvms[1].mac, self.lvms[1].ip], + mock.call(self.fakebr, (self.lvms[1].mac, self.lvms[1].ip), self.ports[1].ip, self.lvm1, self.ports[1].ofport), - mock.call(self.fakebr, [self.lvms[2].mac, self.lvms[2].ip], + mock.call(self.fakebr, (self.lvms[2].mac, self.lvms[2].ip), self.ports[2].ip, self.lvm1, self.ports[2].ofport), ] self.assertEqual(sorted(expected), @@ -95,11 +95,11 @@ class TestL2populationRpcCallBackTunnelMixin( mock_setup_tunnel_port.assert_called_once_with( self.fakebr, self.ports[1].ip, self.lvm1.network_type) expected = [ - mock.call(self.fakebr, [self.lvms[0].mac, self.lvms[0].ip], + mock.call(self.fakebr, (self.lvms[0].mac, self.lvms[0].ip), self.ports[0].ip, self.lvm1, self.ports[0].ofport), - mock.call(self.fakebr, [self.lvms[1].mac, self.lvms[1].ip], + mock.call(self.fakebr, (self.lvms[1].mac, self.lvms[1].ip), self.ports[1].ip, self.lvm1, ofport), - mock.call(self.fakebr, [self.lvms[2].mac, self.lvms[2].ip], + mock.call(self.fakebr, (self.lvms[2].mac, self.lvms[2].ip), self.ports[2].ip, self.lvm1, self.ports[2].ofport), ] self.assertEqual(sorted(expected), @@ -117,9 +117,9 @@ class TestL2populationRpcCallBackTunnelMixin( mock_setup_tunnel_port.assert_called_once_with( self.fakebr, self.ports[1].ip, self.lvm1.network_type) expected = [ - mock.call(self.fakebr, [self.lvms[0].mac, self.lvms[0].ip], + mock.call(self.fakebr, (self.lvms[0].mac, self.lvms[0].ip), self.ports[0].ip, self.lvm1, self.ports[0].ofport), - mock.call(self.fakebr, [self.lvms[2].mac, self.lvms[2].ip], + mock.call(self.fakebr, (self.lvms[2].mac, self.lvms[2].ip), self.ports[2].ip, self.lvm1, self.ports[2].ofport), ] self.assertEqual(sorted(expected), @@ -131,11 +131,11 @@ class TestL2populationRpcCallBackTunnelMixin( self.fakeagent.fdb_remove_tun('context', self.fakebr, self.lvm1, self.agent_ports, self.ofports) expected = [ - mock.call(self.fakebr, [self.lvms[0].mac, self.lvms[0].ip], + mock.call(self.fakebr, (self.lvms[0].mac, self.lvms[0].ip), self.ports[0].ip, self.lvm1, self.ports[0].ofport), - mock.call(self.fakebr, [self.lvms[1].mac, self.lvms[1].ip], + mock.call(self.fakebr, (self.lvms[1].mac, self.lvms[1].ip), self.ports[1].ip, self.lvm1, self.ports[1].ofport), - mock.call(self.fakebr, [self.lvms[2].mac, self.lvms[2].ip], + mock.call(self.fakebr, (self.lvms[2].mac, self.lvms[2].ip), self.ports[2].ip, self.lvm1, self.ports[2].ofport), ] self.assertEqual(sorted(expected), @@ -150,12 +150,12 @@ class TestL2populationRpcCallBackTunnelMixin( self.fakeagent.fdb_remove_tun('context', self.fakebr, self.lvm1, self.agent_ports, self.ofports) expected = [ - mock.call(self.fakebr, [self.lvms[0].mac, self.lvms[0].ip], + mock.call(self.fakebr, (self.lvms[0].mac, self.lvms[0].ip), self.ports[0].ip, self.lvm1, self.ports[0].ofport), mock.call(self.fakebr, - [n_const.FLOODING_ENTRY[0], n_const.FLOODING_ENTRY[1]], + (n_const.FLOODING_ENTRY[0], n_const.FLOODING_ENTRY[1]), self.ports[1].ip, self.lvm1, self.ports[1].ofport), - mock.call(self.fakebr, [self.lvms[2].mac, self.lvms[2].ip], + mock.call(self.fakebr, (self.lvms[2].mac, self.lvms[2].ip), self.ports[2].ip, self.lvm1, self.ports[2].ofport), ] self.assertEqual(sorted(expected), @@ -170,9 +170,9 @@ class TestL2populationRpcCallBackTunnelMixin( self.fakeagent.fdb_remove_tun('context', self.fakebr, self.lvm1, self.agent_ports, self.ofports) expected = [ - mock.call(self.fakebr, [self.lvms[0].mac, self.lvms[0].ip], + mock.call(self.fakebr, (self.lvms[0].mac, self.lvms[0].ip), self.ports[0].ip, self.lvm1, self.ports[0].ofport), - mock.call(self.fakebr, [self.lvms[2].mac, self.lvms[2].ip], + mock.call(self.fakebr, (self.lvms[2].mac, self.lvms[2].ip), self.ports[2].ip, self.lvm1, self.ports[2].ofport), ] self.assertEqual(sorted(expected), @@ -223,8 +223,8 @@ class TestL2populationRpcCallBackTunnelMixin( upd_fdb_entry_val = { self.lvms[0].net: { self.local_ip: { - 'before': [[self.lvms[0].mac, self.lvms[0].ip]], - 'after': [[self.lvms[1].mac, self.lvms[1].ip]], + 'before': [(self.lvms[0].mac, self.lvms[0].ip)], + 'after': [(self.lvms[1].mac, self.lvms[1].ip)], }, }, } diff --git a/neutron/tests/unit/ml2/drivers/test_l2population.py b/neutron/tests/unit/ml2/drivers/test_l2population.py index 85d8b37a7..1073a0e48 100644 --- a/neutron/tests/unit/ml2/drivers/test_l2population.py +++ b/neutron/tests/unit/ml2/drivers/test_l2population.py @@ -16,6 +16,7 @@ import contextlib import mock +from neutron.agent import l2population_rpc from neutron.common import constants from neutron.common import topics from neutron import context @@ -26,6 +27,7 @@ from neutron import manager from neutron.openstack.common import timeutils from neutron.plugins.ml2 import config as config from neutron.plugins.ml2.drivers.l2pop import mech_driver as l2pop_mech_driver +from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc from neutron.plugins.ml2 import managers from neutron.plugins.ml2 import rpc from neutron.tests.unit import test_db_plugin as test_plugin @@ -92,6 +94,8 @@ PLUGIN_NAME = 'neutron.plugins.ml2.plugin.Ml2Plugin' NOTIFIER = 'neutron.plugins.ml2.rpc.AgentNotifierApi' DEVICE_OWNER_COMPUTE = 'compute:None' +FLOODING_ENTRY_AS_LIST = list(constants.FLOODING_ENTRY) + class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): @@ -167,6 +171,48 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): agent_state={'agent_state': L2_AGENT_5}, time=timeutils.strtime()) + def test_port_info_compare(self): + # An assumption the code makes is that PortInfo compares equal to + # equivalent regular tuples. + self.assertEqual(("mac", "ip"), l2pop_rpc.PortInfo("mac", "ip")) + + flooding_entry = l2pop_rpc.PortInfo(*constants.FLOODING_ENTRY) + self.assertEqual(constants.FLOODING_ENTRY, flooding_entry) + + def test__unmarshall_fdb_entries(self): + entries = {'foouuid': { + 'segment_id': 1001, + 'ports': {'192.168.0.10': [['00:00:00:00:00:00', '0.0.0.0'], + ['fa:16:3e:ff:8c:0f', '10.0.0.6']]}, + 'network_type': 'vxlan'}} + + mixin = l2population_rpc.L2populationRpcCallBackMixin + entries = mixin._unmarshall_fdb_entries(entries) + + port_info_list = entries['foouuid']['ports']['192.168.0.10'] + # Check that the lists have been properly converted to PortInfo + self.assertIsInstance(port_info_list[0], l2pop_rpc.PortInfo) + self.assertIsInstance(port_info_list[1], l2pop_rpc.PortInfo) + self.assertEqual(('00:00:00:00:00:00', '0.0.0.0'), port_info_list[0]) + self.assertEqual(('fa:16:3e:ff:8c:0f', '10.0.0.6'), port_info_list[1]) + + def test__marshall_fdb_entries(self): + entries = {'foouuid': { + 'segment_id': 1001, + 'ports': {'192.168.0.10': [('00:00:00:00:00:00', '0.0.0.0'), + ('fa:16:3e:ff:8c:0f', '10.0.0.6')]}, + 'network_type': 'vxlan'}} + + entries = l2pop_rpc.L2populationAgentNotifyAPI._marshall_fdb_entries( + entries) + + port_info_list = entries['foouuid']['ports']['192.168.0.10'] + # Check that the PortInfo tuples have been converted to list + self.assertIsInstance(port_info_list[0], list) + self.assertIsInstance(port_info_list[1], list) + self.assertEqual(['00:00:00:00:00:00', '0.0.0.0'], port_info_list[0]) + self.assertEqual(['fa:16:3e:ff:8c:0f', '10.0.0.6'], port_info_list[1]) + def test_fdb_add_called(self): self._register_ml2_agents() @@ -193,7 +239,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {'fdb_entries': {p1['network_id']: {'ports': - {'20.0.0.1': [constants.FLOODING_ENTRY, + {'20.0.0.1': [FLOODING_ENTRY_AS_LIST, [p1['mac_address'], p1_ips[0]]]}, 'network_type': 'vxlan', @@ -253,7 +299,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {'fdb_entries': {p1['network_id']: {'ports': - {'20.0.0.5': [constants.FLOODING_ENTRY, + {'20.0.0.5': [FLOODING_ENTRY_AS_LIST, [p1['mac_address'], p1_ips[0]]]}, 'network_type': 'vlan', @@ -299,7 +345,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {'fdb_entries': {p1['network_id']: {'ports': - {'20.0.0.2': [constants.FLOODING_ENTRY, + {'20.0.0.2': [FLOODING_ENTRY_AS_LIST, [p2['mac_address'], p2_ips[0]]]}, 'network_type': 'vxlan', @@ -320,7 +366,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {'fdb_entries': {p1['network_id']: {'ports': - {'20.0.0.1': [constants.FLOODING_ENTRY, + {'20.0.0.1': [FLOODING_ENTRY_AS_LIST, [p1['mac_address'], p1_ips[0]]]}, 'network_type': 'vxlan', @@ -368,7 +414,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {p1['network_id']: {'ports': {'20.0.0.2': - [constants.FLOODING_ENTRY, + [FLOODING_ENTRY_AS_LIST, [p1['mac_address'], p1_ips[0]]]}, 'network_type': 'vxlan', @@ -392,7 +438,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {p1['network_id']: {'ports': {'20.0.0.1': - [constants.FLOODING_ENTRY, + [FLOODING_ENTRY_AS_LIST, [p3['mac_address'], p3_ips[0]]]}, 'network_type': 'vxlan', @@ -481,7 +527,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {'fdb_entries': {p2['network_id']: {'ports': - {'20.0.0.1': [constants.FLOODING_ENTRY, + {'20.0.0.1': [FLOODING_ENTRY_AS_LIST, [p2['mac_address'], p2_ips[0]]]}, 'network_type': 'vxlan', @@ -562,7 +608,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {'fdb_entries': {p1['network_id']: {'ports': - {'20.0.0.1': [constants.FLOODING_ENTRY, + {'20.0.0.1': [FLOODING_ENTRY_AS_LIST, [p1['mac_address'], p1_ips[0]]]}, 'network_type': 'vxlan', @@ -604,8 +650,8 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {'chg_ip': {p1['network_id']: {'20.0.0.1': - {'after': [[p1['mac_address'], - '10.0.0.10']]}}}}}, + {'after': [(p1['mac_address'], + '10.0.0.10')]}}}}}, 'namespace': None, 'method': 'update_fdb_entries'} @@ -626,10 +672,10 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {'chg_ip': {p1['network_id']: {'20.0.0.1': - {'before': [[p1['mac_address'], - '10.0.0.10']], - 'after': [[p1['mac_address'], - '10.0.0.16']]}}}}}, + {'before': [(p1['mac_address'], + '10.0.0.10')], + 'after': [(p1['mac_address'], + '10.0.0.16')]}}}}}, 'namespace': None, 'method': 'update_fdb_entries'} @@ -649,8 +695,8 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {'chg_ip': {p1['network_id']: {'20.0.0.1': - {'before': [[p1['mac_address'], - '10.0.0.2']]}}}}}, + {'before': [(p1['mac_address'], + '10.0.0.2')]}}}}}, 'namespace': None, 'method': 'update_fdb_entries'} @@ -728,7 +774,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {'fdb_entries': {p1['network_id']: {'ports': - {'20.0.0.1': [constants.FLOODING_ENTRY, + {'20.0.0.1': [FLOODING_ENTRY_AS_LIST, [p1['mac_address'], p1_ips[0]]]}, 'network_type': 'vxlan', @@ -786,7 +832,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): {'fdb_entries': {p1['network_id']: {'ports': - {'20.0.0.1': [constants.FLOODING_ENTRY, + {'20.0.0.1': [FLOODING_ENTRY_AS_LIST, [p1['mac_address'], p1_ips[0]]]}, 'network_type': 'vxlan', @@ -809,4 +855,4 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase): 'remove_fdb_entries')) as (upd_port_down, rem_fdb_entries): l2pop_mech.delete_port_postcommit(mock.Mock()) - self.assertTrue(upd_port_down.called) \ No newline at end of file + self.assertTrue(upd_port_down.called) diff --git a/neutron/tests/unit/ofagent/test_ofa_neutron_agent.py b/neutron/tests/unit/ofagent/test_ofa_neutron_agent.py index 638b40120..d1a79aa2f 100644 --- a/neutron/tests/unit/ofagent/test_ofa_neutron_agent.py +++ b/neutron/tests/unit/ofagent/test_ofa_neutron_agent.py @@ -33,10 +33,12 @@ from neutron.agent.linux import utils from neutron.common import constants as n_const from neutron.openstack.common import importutils 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): @@ -560,8 +562,8 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase): 'segment_id': 'tun2', 'ports': {'agent_ip': - [['mac', 'ip'], - n_const.FLOODING_ENTRY]}}} + [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"), @@ -580,8 +582,8 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase): 'segment_id': 'tun1', 'ports': {self.lvms[1].ip: - [['mac', 'ip'], - n_const.FLOODING_ENTRY]}}} + [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'), @@ -604,8 +606,8 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase): 'segment_id': 'tun2', 'ports': {self.lvms[1].ip: - [['mac', 'ip'], - n_const.FLOODING_ENTRY]}}} + [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'), @@ -623,11 +625,13 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase): fdb_entry = {self.lvms[0].net: {'network_type': self.tunnel_type, 'segment_id': 'tun1', - 'ports': {self.lvms[0].ip: [['mac', 'ip']]}}} + '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] = [['mac', 'ip']] + 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) @@ -637,7 +641,7 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase): fdb_entry = {self.lvms[1].net: {'network_type': self.tunnel_type, 'segment_id': 'tun2', - 'ports': {self.lvms[1].ip: [n_const.FLOODING_ENTRY]}}} + '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) @@ -648,11 +652,14 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase): fdb_entry = {self.lvms[0].net: {'network_type': self.tunnel_type, 'segment_id': 'tun1', - 'ports': {self.lvms[0].ip: [n_const.FLOODING_ENTRY, - ['mac1', 'ip1']], - self.lvms[1].ip: [['mac2', 'ip2']], - '192.0.2.1': [n_const.FLOODING_ENTRY, - ['mac3', 'ip3']]}}} + '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) @@ -671,11 +678,14 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase): fdb_entry = {self.lvms[0].net: {'network_type': network_type, 'segment_id': 'tun1', - 'ports': {self.lvms[0].ip: [n_const.FLOODING_ENTRY, - ['mac1', 'ip1']], - self.lvms[1].ip: [['mac2', 'ip2']], - '192.0.2.1': [n_const.FLOODING_ENTRY, - ['mac3', 'ip3']]}}} + '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) @@ -702,11 +712,14 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase): fdb_entry = {self.lvms[0].net: {'network_type': self.tunnel_type, 'segment_id': 'tun1', - 'ports': {self.lvms[0].ip: [n_const.FLOODING_ENTRY, - ['mac1', 'ip1']], - self.lvms[1].ip: [['mac2', 'ip2']], - '192.0.2.1': [n_const.FLOODING_ENTRY, - ['mac3', 'ip3']]}}} + '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) @@ -724,11 +737,14 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase): fdb_entry = {self.lvms[0].net: {'network_type': network_type, 'segment_id': 'tun1', - 'ports': {self.lvms[0].ip: [n_const.FLOODING_ENTRY, - ['mac1', 'ip1']], - self.lvms[1].ip: [['mac2', 'ip2']], - '192.0.2.1': [n_const.FLOODING_ENTRY, - ['mac3', 'ip3']]}}} + '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) diff --git a/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py b/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py index 73d62b3df..376b1c03c 100644 --- a/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py @@ -27,6 +27,7 @@ from neutron.agent.linux import utils from neutron.common import constants as n_const from neutron.openstack.common import log from neutron.plugins.common import constants as p_const +from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc from neutron.plugins.openvswitch.agent import ovs_neutron_agent from neutron.plugins.openvswitch.common import constants from neutron.tests import base @@ -1030,7 +1031,7 @@ class TestOvsNeutronAgent(base.BaseTestCase): 'segment_id': 'tun2', 'ports': {'agent_ip': - [[FAKE_MAC, FAKE_IP1], + [l2pop_rpc.PortInfo(FAKE_MAC, FAKE_IP1), n_const.FLOODING_ENTRY]}}} with mock.patch.object(self.agent.tun_br, "deferred") as defer_fn: @@ -1047,7 +1048,7 @@ class TestOvsNeutronAgent(base.BaseTestCase): 'segment_id': 'tun1', 'ports': {'2.2.2.2': - [[FAKE_MAC, FAKE_IP1], + [l2pop_rpc.PortInfo(FAKE_MAC, FAKE_IP1), n_const.FLOODING_ENTRY]}}} class ActionMatcher(object): @@ -1102,7 +1103,7 @@ class TestOvsNeutronAgent(base.BaseTestCase): 'segment_id': 'tun2', 'ports': {'2.2.2.2': - [[FAKE_MAC, FAKE_IP1], + [l2pop_rpc.PortInfo(FAKE_MAC, FAKE_IP1), n_const.FLOODING_ENTRY]}}} with contextlib.nested( mock.patch.object(self.agent.tun_br, 'deferred'), @@ -1132,7 +1133,8 @@ class TestOvsNeutronAgent(base.BaseTestCase): fdb_entry = {'net1': {'network_type': 'gre', 'segment_id': 'tun1', - 'ports': {'1.1.1.1': [[FAKE_MAC, FAKE_IP1]]}}} + 'ports': {'1.1.1.1': [l2pop_rpc.PortInfo(FAKE_MAC, + FAKE_IP1)]}}} with contextlib.nested( mock.patch.object(self.agent.tun_br, 'deferred'), mock.patch.object(self.agent.tun_br, 'do_action_flows'), @@ -1142,7 +1144,8 @@ class TestOvsNeutronAgent(base.BaseTestCase): deferred_fn.return_value = deferred_br self.agent.fdb_add(None, fdb_entry) self.assertFalse(add_tun_fn.called) - fdb_entry['net1']['ports']['10.10.10.10'] = [[FAKE_MAC, FAKE_IP1]] + fdb_entry['net1']['ports']['10.10.10.10'] = [ + l2pop_rpc.PortInfo(FAKE_MAC, FAKE_IP1)] self.agent.fdb_add(None, fdb_entry) add_tun_fn.assert_called_with( deferred_br, 'gre-0a0a0a0a', '10.10.10.10', 'gre') @@ -1168,8 +1171,8 @@ class TestOvsNeutronAgent(base.BaseTestCase): fdb_entries = {'chg_ip': {'net1': {'agent_ip': - {'before': [[FAKE_MAC, FAKE_IP1]], - 'after': [[FAKE_MAC, FAKE_IP2]]}}}} + {'before': [l2pop_rpc.PortInfo(FAKE_MAC, FAKE_IP1)], + 'after': [l2pop_rpc.PortInfo(FAKE_MAC, FAKE_IP2)]}}}} with contextlib.nested( mock.patch.object(self.agent.tun_br, 'deferred'), mock.patch.object(self.agent.tun_br, 'do_action_flows'),