]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
ofagent: Implement physical_interface_mappings
authorYAMAMOTO Takashi <yamamoto@valinux.co.jp>
Mon, 11 Aug 2014 04:41:13 +0000 (13:41 +0900)
committerYAMAMOTO Takashi <yamamoto@valinux.co.jp>
Tue, 2 Sep 2014 05:13:31 +0000 (14:13 +0900)
Mark bridge_mappings as deprecated for ofagent.
Document that it will be removed in Kilo.

Implements: blueprint ofagent-physical-interface-mappings
Change-Id: I38e3b6aad2914dc5425435dd7775f66306375cd2

neutron/plugins/ml2/drivers/mech_ofagent.py
neutron/plugins/ofagent/README
neutron/plugins/ofagent/agent/ofa_neutron_agent.py
neutron/plugins/ofagent/common/config.py
neutron/plugins/openvswitch/common/config.py
neutron/tests/unit/ml2/drivers/test_ofagent_mech.py
neutron/tests/unit/ofagent/test_ofa_neutron_agent.py

index b593e61d6bb82c25948f5ec1de394228b722ec10..6a25c98c9efcd3733883301efbee12fe0a595707 100644 (file)
@@ -45,17 +45,23 @@ class OfagentMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
              portbindings.OVS_HYBRID_PLUG: True})
 
     def check_segment_for_agent(self, segment, agent):
-        mappings = agent['configurations'].get('bridge_mappings', {})
+        bridge_mappings = agent['configurations'].get('bridge_mappings', {})
+        interface_mappings = agent['configurations'].get('interface_mappings',
+                                                         {})
         tunnel_types = agent['configurations'].get('tunnel_types', [])
-        LOG.debug(_("Checking segment: %(segment)s "
-                    "for mappings: %(mappings)s "
-                    "with tunnel_types: %(tunnel_types)s"),
-                  {'segment': segment, 'mappings': mappings,
+        LOG.debug("Checking segment: %(segment)s "
+                  "for bridge_mappings: %(bridge_mappings)s "
+                  "and interface_mappings: %(interface_mappings)s "
+                  "with tunnel_types: %(tunnel_types)s",
+                  {'segment': segment,
+                   'bridge_mappings': bridge_mappings,
+                   'interface_mappings': interface_mappings,
                    'tunnel_types': tunnel_types})
         network_type = segment[api.NETWORK_TYPE]
         return (
             network_type == p_const.TYPE_LOCAL or
             network_type in tunnel_types or
             (network_type in [p_const.TYPE_FLAT, p_const.TYPE_VLAN] and
-                segment[api.PHYSICAL_NETWORK] in mappings)
+                (segment[api.PHYSICAL_NETWORK] in bridge_mappings
+                or segment[api.PHYSICAL_NETWORK] in interface_mappings))
         )
index 51164a1efc24b777c4791d4007c775bec215d773..b18172c1983c0dcb89b64b78b3d9d2bb7c2426a6 100644 (file)
@@ -7,6 +7,28 @@ https://github.com/osrg/ryu/wiki/OpenStack
 
 # -- Notes for updating from Icehouce
 
+OVS.bridge_mappings is deprecated for ofagent.  It's planned to be
+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
index 8be7fa5cb4fc424bb3a4c82be5dc6d200c7fc9c5..be7c0bbff542f534f400001a5601ec6d5fb5ab47 100644 (file)
@@ -199,7 +199,7 @@ class OFANeutronAgent(n_rpc.RpcCallback,
     RPC_API_VERSION = '1.1'
 
     def __init__(self, ryuapp, integ_br, local_ip,
-                 bridge_mappings, root_helper,
+                 bridge_mappings, interface_mappings, root_helper,
                  polling_interval, tunnel_types=None,
                  veth_mtu=None):
         """Constructor.
@@ -208,6 +208,9 @@ class OFANeutronAgent(n_rpc.RpcCallback,
         :param integ_br: name of the integration bridge.
         :param local_ip: local IP address of this hypervisor.
         :param bridge_mappings: mappings from physical network name to bridge.
+               (deprecated)
+        :param interface_mappings: mappings from physical network name to
+               interface.
         :param root_helper: utility to use when running shell cmds.
         :param polling_interval: interval (secs) to poll DB.
         :param tunnel_types: A list of tunnel types to enable support for in
@@ -229,11 +232,13 @@ class OFANeutronAgent(n_rpc.RpcCallback,
             'binary': 'neutron-ofa-agent',
             'host': cfg.CONF.host,
             'topic': n_const.L2_AGENT_TOPIC,
-            'configurations': {'bridge_mappings': bridge_mappings,
-                               'tunnel_types': self.tunnel_types,
-                               'tunneling_ip': local_ip,
-                               'l2_population': True,
-                               'l2pop_network_types': l2pop_network_types},
+            'configurations': {
+                'bridge_mappings': bridge_mappings,
+                'interface_mappings': interface_mappings,
+                'tunnel_types': self.tunnel_types,
+                'tunneling_ip': local_ip,
+                'l2_population': True,
+                'l2pop_network_types': l2pop_network_types},
             'agent_type': n_const.AGENT_TYPE_OFA,
             'start_flag': True}
 
@@ -245,6 +250,9 @@ class OFANeutronAgent(n_rpc.RpcCallback,
         self.updated_ports = set()
         self.setup_rpc()
         self.setup_integration_br()
+        self.int_ofports = {}
+        self.setup_physical_interfaces(interface_mappings)
+        # TODO(yamamoto): Remove physical bridge support
         self.setup_physical_bridges(bridge_mappings)
         self.local_vlan_map = {}
         self.tun_ofports = {}
@@ -638,7 +646,6 @@ class OFANeutronAgent(n_rpc.RpcCallback,
         :param bridge_mappings: map physical network names to bridge names.
         """
         self.phys_brs = {}
-        self.int_ofports = {}
         self.phys_ofports = {}
         ip_wrapper = ip_lib.IPWrapper(self.root_helper)
         for physical_network, bridge in bridge_mappings.iteritems():
@@ -660,6 +667,18 @@ class OFANeutronAgent(n_rpc.RpcCallback,
             self._phys_br_patch_physical_bridge_with_integration_bridge(
                 br, physical_network, bridge, ip_wrapper)
 
+    def setup_physical_interfaces(self, interface_mappings):
+        """Setup the physical network interfaces.
+
+        Link physical network interfaces to the integration bridge.
+
+        :param interface_mappings: map physical network names to
+                                   interface names.
+        """
+        for physical_network, interface_name in interface_mappings.iteritems():
+            ofport = int(self.int_br.add_port(interface_name))
+            self.int_ofports[physical_network] = ofport
+
     def scan_ports(self, registered_ports, updated_ports=None):
         cur_ports = self._get_ofport_names(self.int_br)
         self.int_br_device_count = len(cur_ports)
@@ -968,10 +987,17 @@ def create_agent_config_map(config):
         bridge_mappings = n_utils.parse_mappings(config.OVS.bridge_mappings)
     except ValueError as e:
         raise ValueError(_("Parsing bridge_mappings failed: %s.") % e)
+    try:
+        interface_mappings = n_utils.parse_mappings(
+            config.AGENT.physical_interface_mappings)
+    except ValueError as e:
+        raise ValueError(_("Parsing physical_interface_mappings failed: %s.")
+                         % e)
 
     kwargs = dict(
         integ_br=config.OVS.integration_bridge,
         local_ip=config.OVS.local_ip,
+        interface_mappings=interface_mappings,
         bridge_mappings=bridge_mappings,
         root_helper=config.AGENT.root_helper,
         polling_interval=config.AGENT.polling_interval,
index 759d3df1dbdb28672bb2271d47710a97cbdf9c3b..0b2b44890bd40246bd543f7d2cd29a63db9fc3d6 100644 (file)
@@ -23,6 +23,9 @@ 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 <physical_network>:<physical_interface>")),
 ]
 
 
index 07ab6564a6893979fc5078af8c1ae18e38d49866..d9e0454839c7934a77713967de81ed7d7404450b 100644 (file)
@@ -41,7 +41,8 @@ ovs_opts = [
                help=_("Local IP address of GRE tunnel endpoints.")),
     cfg.ListOpt('bridge_mappings',
                 default=DEFAULT_BRIDGE_MAPPINGS,
-                help=_("List of <physical_network>:<bridge>")),
+                help=_("List of <physical_network>:<bridge>. "
+                       "Deprecated for ofagent.")),
     cfg.StrOpt('tenant_network_type', default='local',
                help=_("Network type for tenant networks "
                       "(local, vlan, gre, vxlan, or none).")),
index 63daf9ec05c039a221a7163dcebc7f6b0487b79b..3187f296b4e64eccd37ec985511d108df0d09d0b 100644 (file)
@@ -24,14 +24,14 @@ class OfagentMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
     CAP_PORT_FILTER = True
     AGENT_TYPE = constants.AGENT_TYPE_OFA
 
-    GOOD_MAPPINGS = {'fake_physical_network': 'fake_bridge'}
+    GOOD_MAPPINGS = {'fake_physical_network': 'fake_interface'}
     GOOD_TUNNEL_TYPES = ['gre', 'vxlan']
-    GOOD_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS,
+    GOOD_CONFIGS = {'interface_mappings': GOOD_MAPPINGS,
                     'tunnel_types': GOOD_TUNNEL_TYPES}
 
-    BAD_MAPPINGS = {'wrong_physical_network': 'wrong_bridge'}
+    BAD_MAPPINGS = {'wrong_physical_network': 'wrong_interface'}
     BAD_TUNNEL_TYPES = ['bad_tunnel_type']
-    BAD_CONFIGS = {'bridge_mappings': BAD_MAPPINGS,
+    BAD_CONFIGS = {'interface_mappings': BAD_MAPPINGS,
                    'tunnel_types': BAD_TUNNEL_TYPES}
 
     AGENTS = [{'alive': True,
@@ -72,3 +72,66 @@ class OfagentMechanismVlanTestCase(OfagentMechanismBaseTestCase,
 class OfagentMechanismGreTestCase(OfagentMechanismBaseTestCase,
                                   base.AgentMechanismGreTestCase):
     pass
+
+
+# The following tests are for deprecated "bridge_mappings".
+# TODO(yamamoto): Remove them.
+
+class OfagentMechanismPhysBridgeTestCase(base.AgentMechanismBaseTestCase):
+    VIF_TYPE = portbindings.VIF_TYPE_OVS
+    CAP_PORT_FILTER = True
+    AGENT_TYPE = constants.AGENT_TYPE_OFA
+
+    GOOD_MAPPINGS = {'fake_physical_network': 'fake_bridge'}
+    GOOD_TUNNEL_TYPES = ['gre', 'vxlan']
+    GOOD_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS,
+                    'tunnel_types': GOOD_TUNNEL_TYPES}
+
+    BAD_MAPPINGS = {'wrong_physical_network': 'wrong_bridge'}
+    BAD_TUNNEL_TYPES = ['bad_tunnel_type']
+    BAD_CONFIGS = {'bridge_mappings': BAD_MAPPINGS,
+                   'tunnel_types': BAD_TUNNEL_TYPES}
+
+    AGENTS = [{'alive': True,
+               'configurations': GOOD_CONFIGS}]
+    AGENTS_DEAD = [{'alive': False,
+                    'configurations': GOOD_CONFIGS}]
+    AGENTS_BAD = [{'alive': False,
+                   'configurations': GOOD_CONFIGS},
+                  {'alive': True,
+                   'configurations': BAD_CONFIGS}]
+
+    def setUp(self):
+        super(OfagentMechanismPhysBridgeTestCase, self).setUp()
+        self.driver = mech_ofagent.OfagentMechanismDriver()
+        self.driver.initialize()
+
+
+class OfagentMechanismPhysBridgeGenericTestCase(
+        OfagentMechanismPhysBridgeTestCase,
+        base.AgentMechanismGenericTestCase):
+    pass
+
+
+class OfagentMechanismPhysBridgeLocalTestCase(
+        OfagentMechanismPhysBridgeTestCase,
+        base.AgentMechanismLocalTestCase):
+    pass
+
+
+class OfagentMechanismPhysBridgeFlatTestCase(
+        OfagentMechanismPhysBridgeTestCase,
+        base.AgentMechanismFlatTestCase):
+    pass
+
+
+class OfagentMechanismPhysBridgeVlanTestCase(
+        OfagentMechanismPhysBridgeTestCase,
+        base.AgentMechanismVlanTestCase):
+    pass
+
+
+class OfagentMechanismPhysBridgeGreTestCase(
+        OfagentMechanismPhysBridgeTestCase,
+        base.AgentMechanismGreTestCase):
+    pass
index b9b83655dc52da5defcfef80b43afba74448e182..5b5f62980511b9b64e5895da44ddba210d7e5057 100644 (file)
@@ -490,6 +490,13 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
             self.assertEqual(11, self.agent.int_ofports["physnet1"])
             self.assertEqual(25, self.agent.phys_ofports["physnet1"])
 
+    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"),