Merge "ofagent: Desupport ancillary bridges"

This commit is contained in:
Jenkins 2014-08-04 21:22:46 +00:00 committed by Gerrit Code Review
commit 6b83612dab
3 changed files with 33 additions and 199 deletions

View File

@ -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

View File

@ -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:

View File

@ -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'])