Merge "ofagent: Desupport ancillary bridges"
This commit is contained in:
commit
6b83612dab
@ -5,6 +5,38 @@ This directory includes agent for OpenFlow Agent mechanism driver.
|
|||||||
For how to install/set up ML2 mechanism driver for OpenFlow Agent, please refer to
|
For how to install/set up ML2 mechanism driver for OpenFlow Agent, please refer to
|
||||||
https://github.com/osrg/ryu/wiki/OpenStack
|
https://github.com/osrg/ryu/wiki/OpenStack
|
||||||
|
|
||||||
|
# -- Notes for updating from Icehouce
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
# -- Ryu General
|
# -- Ryu General
|
||||||
|
|
||||||
For general Ryu stuff, please refer to
|
For general Ryu stuff, please refer to
|
||||||
|
@ -264,8 +264,6 @@ class OFANeutronAgent(n_rpc.RpcCallback,
|
|||||||
self.dont_fragment = cfg.CONF.AGENT.dont_fragment
|
self.dont_fragment = cfg.CONF.AGENT.dont_fragment
|
||||||
if self.enable_tunneling:
|
if self.enable_tunneling:
|
||||||
self.setup_tunnel_br(tun_br)
|
self.setup_tunnel_br(tun_br)
|
||||||
# Collect additional bridges to monitor
|
|
||||||
self.ancillary_brs = self.setup_ancillary_bridges(integ_br, tun_br)
|
|
||||||
|
|
||||||
# Security group agent support
|
# Security group agent support
|
||||||
self.sg_agent = OFASecurityGroupAgent(self.context,
|
self.sg_agent = OFASecurityGroupAgent(self.context,
|
||||||
@ -787,31 +785,6 @@ class OFANeutronAgent(n_rpc.RpcCallback,
|
|||||||
instructions=instructions)
|
instructions=instructions)
|
||||||
self.ryu_send_msg(msg)
|
self.ryu_send_msg(msg)
|
||||||
|
|
||||||
def setup_ancillary_bridges(self, integ_br, tun_br):
|
|
||||||
"""Setup ancillary bridges - for example br-ex."""
|
|
||||||
ovs_bridges = set(ovs_lib.get_bridges(self.root_helper))
|
|
||||||
# Remove all known bridges
|
|
||||||
ovs_bridges.remove(integ_br)
|
|
||||||
if self.enable_tunneling:
|
|
||||||
ovs_bridges.remove(tun_br)
|
|
||||||
br_names = [self.phys_brs[physical_network].br_name for
|
|
||||||
physical_network in self.phys_brs]
|
|
||||||
ovs_bridges.difference_update(br_names)
|
|
||||||
# Filter list of bridges to those that have external
|
|
||||||
# bridge-id's configured
|
|
||||||
br_names = [
|
|
||||||
bridge for bridge in ovs_bridges
|
|
||||||
if bridge != ovs_lib.get_bridge_external_bridge_id(
|
|
||||||
self.root_helper, bridge)
|
|
||||||
]
|
|
||||||
ovs_bridges.difference_update(br_names)
|
|
||||||
ancillary_bridges = []
|
|
||||||
for bridge in ovs_bridges:
|
|
||||||
br = OVSBridge(bridge, self.root_helper, self.ryuapp)
|
|
||||||
ancillary_bridges.append(br)
|
|
||||||
LOG.info(_('ancillary bridge list: %s.'), ancillary_bridges)
|
|
||||||
return ancillary_bridges
|
|
||||||
|
|
||||||
def _tun_br_sort_incoming_traffic_depend_in_port(self, br):
|
def _tun_br_sort_incoming_traffic_depend_in_port(self, br):
|
||||||
match = br.ofparser.OFPMatch(
|
match = br.ofparser.OFPMatch(
|
||||||
in_port=int(self.patch_int_ofport))
|
in_port=int(self.patch_int_ofport))
|
||||||
@ -1087,23 +1060,6 @@ class OFANeutronAgent(n_rpc.RpcCallback,
|
|||||||
changed_ports.add(port)
|
changed_ports.add(port)
|
||||||
return changed_ports
|
return changed_ports
|
||||||
|
|
||||||
def update_ancillary_ports(self, registered_ports):
|
|
||||||
# TODO(yamamoto): stop using ovsdb
|
|
||||||
# - do the same as scan_ports
|
|
||||||
# - or, find a way to update status of ancillary ports differently
|
|
||||||
# eg. let interface drivers mark ports up
|
|
||||||
ports = set()
|
|
||||||
for bridge in self.ancillary_brs:
|
|
||||||
ports |= bridge.get_vif_port_set()
|
|
||||||
|
|
||||||
if ports == registered_ports:
|
|
||||||
return
|
|
||||||
added = ports - registered_ports
|
|
||||||
removed = registered_ports - ports
|
|
||||||
return {'current': ports,
|
|
||||||
'added': added,
|
|
||||||
'removed': removed}
|
|
||||||
|
|
||||||
def treat_vif_port(self, vif_port, port_id, network_id, network_type,
|
def treat_vif_port(self, vif_port, port_id, network_id, network_type,
|
||||||
physical_network, segmentation_id, admin_state_up):
|
physical_network, segmentation_id, admin_state_up):
|
||||||
if vif_port:
|
if vif_port:
|
||||||
@ -1240,27 +1196,6 @@ class OFANeutronAgent(n_rpc.RpcCallback,
|
|||||||
self.port_dead(port)
|
self.port_dead(port)
|
||||||
return resync
|
return resync
|
||||||
|
|
||||||
def treat_ancillary_devices_added(self, devices):
|
|
||||||
resync = False
|
|
||||||
for device in devices:
|
|
||||||
LOG.info(_("Ancillary Port %s added"), device)
|
|
||||||
try:
|
|
||||||
self.plugin_rpc.get_device_details(self.context, device,
|
|
||||||
self.agent_id)
|
|
||||||
except Exception as e:
|
|
||||||
LOG.debug(_("Unable to get port details for "
|
|
||||||
"%(device)s: %(e)s"),
|
|
||||||
{'device': device, 'e': e})
|
|
||||||
resync = True
|
|
||||||
continue
|
|
||||||
|
|
||||||
# update plugin about port status
|
|
||||||
self.plugin_rpc.update_device_up(self.context,
|
|
||||||
device,
|
|
||||||
self.agent_id,
|
|
||||||
cfg.CONF.host)
|
|
||||||
return resync
|
|
||||||
|
|
||||||
def treat_devices_removed(self, devices):
|
def treat_devices_removed(self, devices):
|
||||||
resync = False
|
resync = False
|
||||||
self.sg_agent.remove_devices_filter(devices)
|
self.sg_agent.remove_devices_filter(devices)
|
||||||
@ -1279,27 +1214,6 @@ class OFANeutronAgent(n_rpc.RpcCallback,
|
|||||||
self.port_unbound(device)
|
self.port_unbound(device)
|
||||||
return resync
|
return resync
|
||||||
|
|
||||||
def treat_ancillary_devices_removed(self, devices):
|
|
||||||
resync = False
|
|
||||||
for device in devices:
|
|
||||||
LOG.info(_("Attachment %s removed"), device)
|
|
||||||
try:
|
|
||||||
details = self.plugin_rpc.update_device_down(self.context,
|
|
||||||
device,
|
|
||||||
self.agent_id,
|
|
||||||
cfg.CONF.host)
|
|
||||||
except Exception as e:
|
|
||||||
LOG.debug(_("port_removed failed for %(device)s: %(e)s"),
|
|
||||||
{'device': device, 'e': e})
|
|
||||||
resync = True
|
|
||||||
continue
|
|
||||||
if details['exists']:
|
|
||||||
LOG.info(_("Port %s updated."), device)
|
|
||||||
# Nothing to do regarding local networking
|
|
||||||
else:
|
|
||||||
LOG.debug(_("Device %s not defined on plugin"), device)
|
|
||||||
return resync
|
|
||||||
|
|
||||||
def process_network_ports(self, port_info):
|
def process_network_ports(self, port_info):
|
||||||
resync_add = False
|
resync_add = False
|
||||||
resync_removed = False
|
resync_removed = False
|
||||||
@ -1333,30 +1247,6 @@ class OFANeutronAgent(n_rpc.RpcCallback,
|
|||||||
# If one of the above opertaions fails => resync with plugin
|
# If one of the above opertaions fails => resync with plugin
|
||||||
return (resync_add | resync_removed)
|
return (resync_add | resync_removed)
|
||||||
|
|
||||||
def process_ancillary_network_ports(self, port_info):
|
|
||||||
resync_add = False
|
|
||||||
resync_removed = False
|
|
||||||
if 'added' in port_info:
|
|
||||||
start = time.time()
|
|
||||||
resync_add = self.treat_ancillary_devices_added(port_info['added'])
|
|
||||||
LOG.debug(_("process_ancillary_network_ports - iteration: "
|
|
||||||
"%(iter_num)d - treat_ancillary_devices_added "
|
|
||||||
"completed in %(elapsed).3f"),
|
|
||||||
{'iter_num': self.iter_num,
|
|
||||||
'elapsed': time.time() - start})
|
|
||||||
if 'removed' in port_info:
|
|
||||||
start = time.time()
|
|
||||||
resync_removed = self.treat_ancillary_devices_removed(
|
|
||||||
port_info['removed'])
|
|
||||||
LOG.debug(_("process_ancillary_network_ports - iteration: "
|
|
||||||
"%(iter_num)d - treat_ancillary_devices_removed "
|
|
||||||
"completed in %(elapsed).3f"),
|
|
||||||
{'iter_num': self.iter_num,
|
|
||||||
'elapsed': time.time() - start})
|
|
||||||
|
|
||||||
# If one of the above opertaions fails => resync with plugin
|
|
||||||
return (resync_add | resync_removed)
|
|
||||||
|
|
||||||
def tunnel_sync(self):
|
def tunnel_sync(self):
|
||||||
resync = False
|
resync = False
|
||||||
try:
|
try:
|
||||||
@ -1387,19 +1277,16 @@ class OFANeutronAgent(n_rpc.RpcCallback,
|
|||||||
sync = True
|
sync = True
|
||||||
ports = set()
|
ports = set()
|
||||||
updated_ports_copy = set()
|
updated_ports_copy = set()
|
||||||
ancillary_ports = set()
|
|
||||||
tunnel_sync = True
|
tunnel_sync = True
|
||||||
while True:
|
while True:
|
||||||
start = time.time()
|
start = time.time()
|
||||||
port_stats = {'regular': {'added': 0, 'updated': 0, 'removed': 0},
|
port_stats = {'regular': {'added': 0, 'updated': 0, 'removed': 0}}
|
||||||
'ancillary': {'added': 0, 'removed': 0}}
|
|
||||||
LOG.debug(_("Agent ovsdb_monitor_loop - "
|
LOG.debug(_("Agent ovsdb_monitor_loop - "
|
||||||
"iteration:%d started"),
|
"iteration:%d started"),
|
||||||
self.iter_num)
|
self.iter_num)
|
||||||
if sync:
|
if sync:
|
||||||
LOG.info(_("Agent out of sync with plugin!"))
|
LOG.info(_("Agent out of sync with plugin!"))
|
||||||
ports.clear()
|
ports.clear()
|
||||||
ancillary_ports.clear()
|
|
||||||
sync = False
|
sync = False
|
||||||
polling_manager.force_polling()
|
polling_manager.force_polling()
|
||||||
# Notify the plugin of tunnel IP
|
# Notify the plugin of tunnel IP
|
||||||
@ -1450,32 +1337,6 @@ class OFANeutronAgent(n_rpc.RpcCallback,
|
|||||||
len(port_info.get('updated', [])))
|
len(port_info.get('updated', [])))
|
||||||
port_stats['regular']['removed'] = (
|
port_stats['regular']['removed'] = (
|
||||||
len(port_info.get('removed', [])))
|
len(port_info.get('removed', [])))
|
||||||
# Treat ancillary devices if they exist
|
|
||||||
if self.ancillary_brs:
|
|
||||||
port_info = self.update_ancillary_ports(
|
|
||||||
ancillary_ports)
|
|
||||||
LOG.debug(_("Agent ovsdb_monitor_loop - "
|
|
||||||
"iteration:%(iter_num)d - "
|
|
||||||
"ancillary port info retrieved. "
|
|
||||||
"Elapsed:%(elapsed).3f"),
|
|
||||||
{'iter_num': self.iter_num,
|
|
||||||
'elapsed': time.time() - start})
|
|
||||||
|
|
||||||
if port_info:
|
|
||||||
rc = self.process_ancillary_network_ports(
|
|
||||||
port_info)
|
|
||||||
LOG.debug(_("Agent ovsdb_monitor_loop - "
|
|
||||||
"iteration:"
|
|
||||||
"%(iter_num)d - ancillary ports "
|
|
||||||
"processed. Elapsed:%(elapsed).3f"),
|
|
||||||
{'iter_num': self.iter_num,
|
|
||||||
'elapsed': time.time() - start})
|
|
||||||
ancillary_ports = port_info['current']
|
|
||||||
port_stats['ancillary']['added'] = (
|
|
||||||
len(port_info.get('added', [])))
|
|
||||||
port_stats['ancillary']['removed'] = (
|
|
||||||
len(port_info.get('removed', [])))
|
|
||||||
sync = sync | rc
|
|
||||||
|
|
||||||
polling_manager.polling_completed()
|
polling_manager.polling_completed()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -208,9 +208,6 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
|
|||||||
mock.patch.object(self.mod_agent.OFANeutronAgent,
|
mock.patch.object(self.mod_agent.OFANeutronAgent,
|
||||||
'setup_integration_br',
|
'setup_integration_br',
|
||||||
return_value=mock.Mock()),
|
return_value=mock.Mock()),
|
||||||
mock.patch.object(self.mod_agent.OFANeutronAgent,
|
|
||||||
'setup_ancillary_bridges',
|
|
||||||
return_value=[]),
|
|
||||||
mock.patch.object(self.mod_agent.OVSBridge,
|
mock.patch.object(self.mod_agent.OVSBridge,
|
||||||
'get_local_port_mac',
|
'get_local_port_mac',
|
||||||
return_value='00:00:00:00:00:01'),
|
return_value='00:00:00:00:00:01'),
|
||||||
@ -1129,59 +1126,3 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
|
|||||||
ovs_br_class, tun_output_ctrl):
|
ovs_br_class, tun_output_ctrl):
|
||||||
self.agent.setup_tunnel_br(cfg.CONF.OVS.tunnel_bridge)
|
self.agent.setup_tunnel_br(cfg.CONF.OVS.tunnel_bridge)
|
||||||
tun_output_ctrl.assert_called_once_with(self.agent.tun_br)
|
tun_output_ctrl.assert_called_once_with(self.agent.tun_br)
|
||||||
|
|
||||||
|
|
||||||
class AncillaryBridgesTest(ofa_test_base.OFAAgentTestBase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(AncillaryBridgesTest, self).setUp()
|
|
||||||
notifier_p = mock.patch(NOTIFIER)
|
|
||||||
notifier_cls = notifier_p.start()
|
|
||||||
self.notifier = mock.Mock()
|
|
||||||
notifier_cls.return_value = self.notifier
|
|
||||||
# Avoid rpc initialization for unit tests
|
|
||||||
cfg.CONF.set_override('rpc_backend',
|
|
||||||
'neutron.openstack.common.rpc.impl_fake')
|
|
||||||
cfg.CONF.set_override('report_interval', 0, 'AGENT')
|
|
||||||
self.kwargs = self.mod_agent.create_agent_config_map(cfg.CONF)
|
|
||||||
|
|
||||||
def _test_ancillary_bridges(self, bridges, ancillary):
|
|
||||||
device_ids = ancillary[:]
|
|
||||||
|
|
||||||
def pullup_side_effect(self, *args):
|
|
||||||
result = device_ids.pop(0)
|
|
||||||
return result
|
|
||||||
|
|
||||||
with contextlib.nested(
|
|
||||||
mock.patch.object(self.mod_agent.OFANeutronAgent,
|
|
||||||
'setup_integration_br',
|
|
||||||
return_value=mock.Mock()),
|
|
||||||
mock.patch('neutron.agent.linux.utils.get_interface_mac',
|
|
||||||
return_value='00:00:00:00:00:01'),
|
|
||||||
mock.patch.object(self.mod_agent.OVSBridge,
|
|
||||||
'get_local_port_mac',
|
|
||||||
return_value='00:00:00:00:00:01'),
|
|
||||||
mock.patch('neutron.agent.linux.ovs_lib.get_bridges',
|
|
||||||
return_value=bridges),
|
|
||||||
mock.patch(
|
|
||||||
'neutron.agent.linux.ovs_lib.get_bridge_external_bridge_id',
|
|
||||||
side_effect=pullup_side_effect)):
|
|
||||||
self.agent = self.mod_agent.OFANeutronAgent(
|
|
||||||
self.ryuapp, **self.kwargs)
|
|
||||||
self.assertEqual(len(ancillary), len(self.agent.ancillary_brs))
|
|
||||||
if ancillary:
|
|
||||||
bridges = [br.br_name for br in self.agent.ancillary_brs]
|
|
||||||
for br in ancillary:
|
|
||||||
self.assertIn(br, bridges)
|
|
||||||
|
|
||||||
def test_ancillary_bridges_single(self):
|
|
||||||
bridges = ['br-int', 'br-ex']
|
|
||||||
self._test_ancillary_bridges(bridges, ['br-ex'])
|
|
||||||
|
|
||||||
def test_ancillary_bridges_none(self):
|
|
||||||
bridges = ['br-int']
|
|
||||||
self._test_ancillary_bridges(bridges, [])
|
|
||||||
|
|
||||||
def test_ancillary_bridges_multiple(self):
|
|
||||||
bridges = ['br-int', 'br-ex1', 'br-ex2']
|
|
||||||
self._test_ancillary_bridges(bridges, ['br-ex1', 'br-ex2'])
|
|
||||||
|
Loading…
Reference in New Issue
Block a user