ofagent: Implement physical_interface_mappings
Mark bridge_mappings as deprecated for ofagent. Document that it will be removed in Kilo. Implements: blueprint ofagent-physical-interface-mappings Change-Id: I38e3b6aad2914dc5425435dd7775f66306375cd2
This commit is contained in:
parent
213ad578b3
commit
e56bfa467d
@ -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))
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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>")),
|
||||
]
|
||||
|
||||
|
||||
|
@ -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).")),
|
||||
|
@ -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
|
||||
|
@ -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"),
|
||||
|
Loading…
Reference in New Issue
Block a user