# 1.4 Added support for network_update
target = oslo_messaging.Target(version='1.4')
- def __init__(self, bridge_classes, integ_br, tun_br, local_ip,
- bridge_mappings, polling_interval, tunnel_types=None,
- veth_mtu=None, l2_population=False,
- enable_distributed_routing=False,
- minimize_polling=False,
- ovsdb_monitor_respawn_interval=(
- constants.DEFAULT_OVSDBMON_RESPAWN),
- arp_responder=False,
- prevent_arp_spoofing=True,
- use_veth_interconnection=False,
- quitting_rpc_timeout=None,
- conf=None):
+ def __init__(self, bridge_classes, conf=None):
'''Constructor.
:param bridge_classes: a dict for bridge classes.
- :param integ_br: name of the integration bridge.
- :param tun_br: name of the tunnel bridge.
- :param local_ip: local IP address of this hypervisor.
- :param bridge_mappings: mappings from physical network name to bridge.
- :param polling_interval: interval (secs) to poll DB.
- :param tunnel_types: A list of tunnel types to enable support for in
- the agent. If set, will automatically set enable_tunneling to
- True.
- :param veth_mtu: MTU size for veth interfaces.
- :param l2_population: Optional, whether L2 population is turned on
- :param minimize_polling: Optional, whether to minimize polling by
- monitoring ovsdb for interface changes.
- :param ovsdb_monitor_respawn_interval: Optional, when using polling
- minimization, the number of seconds to wait before respawning
- the ovsdb monitor.
- :param arp_responder: Optional, enable local ARP responder if it is
- supported.
- :param prevent_arp_spoofing: Optional, enable suppression of any ARP
- responses from ports that don't match an IP address that belongs
- to the ports. Spoofing rules will not be added to ports that
- have port security disabled.
- :param use_veth_interconnection: use veths instead of patch ports to
- interconnect the integration bridge to physical bridges.
- :param quitting_rpc_timeout: timeout in seconds for rpc calls after
- SIGTERM is received
:param conf: an instance of ConfigOpts
'''
super(OVSNeutronAgent, self).__init__()
self.conf = conf or cfg.CONF
self.ovs = ovs_lib.BaseOVS()
+ agent_conf = self.conf.AGENT
+ ovs_conf = self.conf.OVS
self.fullsync = True
# init bridge classes with configured datapath type.
self.br_int_cls, self.br_phys_cls, self.br_tun_cls = (
functools.partial(bridge_classes[b],
- datapath_type=self.conf.OVS.datapath_type)
+ datapath_type=ovs_conf.datapath_type)
for b in ('br_int', 'br_phys', 'br_tun'))
- self.use_veth_interconnection = use_veth_interconnection
- self.veth_mtu = veth_mtu
+ self.use_veth_interconnection = ovs_conf.use_veth_interconnection
+ self.veth_mtu = agent_conf.veth_mtu
self.available_local_vlans = set(moves.range(p_const.MIN_VLAN_TAG,
p_const.MAX_VLAN_TAG))
- self.tunnel_types = tunnel_types or []
- self.l2_pop = l2_population
+ self.tunnel_types = agent_conf.tunnel_types or []
+ self.l2_pop = agent_conf.l2_population
# TODO(ethuleau): Change ARP responder so it's not dependent on the
# ML2 l2 population mechanism driver.
- self.enable_distributed_routing = enable_distributed_routing
- self.arp_responder_enabled = arp_responder and self.l2_pop
- self.prevent_arp_spoofing = prevent_arp_spoofing
+ self.enable_distributed_routing = agent_conf.enable_distributed_routing
+ self.arp_responder_enabled = agent_conf.arp_responder and self.l2_pop
+ self.prevent_arp_spoofing = agent_conf.prevent_arp_spoofing
host = self.conf.host
self.agent_id = 'ovs-agent-%s' % host
- if tunnel_types:
+ if self.tunnel_types:
self.enable_tunneling = True
else:
self.enable_tunneling = False
self.agent_uuid_stamp = uuid.uuid4().int & UINT64_BITMASK
- self.int_br = self.br_int_cls(integ_br)
+ self.int_br = self.br_int_cls(ovs_conf.integration_bridge)
self.setup_integration_br()
# Stores port update notifications for processing in main rpc loop
self.updated_ports = set()
self.vifname_to_ofport_map = {}
self.setup_rpc()
self.init_extension_manager(self.connection)
- self.bridge_mappings = bridge_mappings
+ self.bridge_mappings = self._parse_bridge_mappings(
+ ovs_conf.bridge_mappings)
self.setup_physical_bridges(self.bridge_mappings)
self.local_vlan_map = {}
p_const.TYPE_GRE: {},
p_const.TYPE_VXLAN: {}}
- self.polling_interval = polling_interval
- self.minimize_polling = minimize_polling
- self.ovsdb_monitor_respawn_interval = ovsdb_monitor_respawn_interval
- self.local_ip = local_ip
+ self.polling_interval = agent_conf.polling_interval
+ self.minimize_polling = agent_conf.minimize_polling
+ self.ovsdb_monitor_respawn_interval = (
+ agent_conf.ovsdb_monitor_respawn_interval or
+ constants.DEFAULT_OVSDBMON_RESPAWN)
+ self.local_ip = ovs_conf.local_ip
self.tunnel_count = 0
- self.vxlan_udp_port = self.conf.AGENT.vxlan_udp_port
- self.dont_fragment = self.conf.AGENT.dont_fragment
- self.tunnel_csum = cfg.CONF.AGENT.tunnel_csum
+ self.vxlan_udp_port = agent_conf.vxlan_udp_port
+ self.dont_fragment = agent_conf.dont_fragment
+ self.tunnel_csum = agent_conf.tunnel_csum
self.tun_br = None
self.patch_int_ofport = constants.OFPORT_INVALID
self.patch_tun_ofport = constants.OFPORT_INVALID
if self.enable_tunneling:
# The patch_int_ofport and patch_tun_ofport are updated
# here inside the call to setup_tunnel_br()
- self.setup_tunnel_br(tun_br)
+ self.setup_tunnel_br(ovs_conf.tunnel_bridge)
self.dvr_agent = ovs_dvr_neutron_agent.OVSDVRNeutronAgent(
self.context,
'binary': 'neutron-openvswitch-agent',
'host': host,
'topic': n_const.L2_AGENT_TOPIC,
- 'configurations': {'bridge_mappings': bridge_mappings,
+ 'configurations': {'bridge_mappings': self.bridge_mappings,
'tunnel_types': self.tunnel_types,
- 'tunneling_ip': local_ip,
+ 'tunneling_ip': self.local_ip,
'l2_population': self.l2_pop,
'arp_responder_enabled':
self.arp_responder_enabled,
'enable_distributed_routing':
self.enable_distributed_routing,
'log_agent_heartbeats':
- self.conf.AGENT.log_agent_heartbeats,
+ agent_conf.log_agent_heartbeats,
'extensions': self.ext_manager.names(),
- 'datapath_type': self.conf.OVS.datapath_type,
+ 'datapath_type': ovs_conf.datapath_type,
'ovs_capabilities': self.ovs.capabilities,
'vhostuser_socket_dir':
- self.conf.OVS.vhostuser_socket_dir},
- 'agent_type': self.conf.AGENT.agent_type,
+ ovs_conf.vhostuser_socket_dir},
+ 'agent_type': agent_conf.agent_type,
'start_flag': True}
- report_interval = self.conf.AGENT.report_interval
+ report_interval = agent_conf.report_interval
if report_interval:
heartbeat = loopingcall.FixedIntervalLoopingCall(
self._report_state)
self.dvr_agent.setup_dvr_flows()
# Collect additional bridges to monitor
- self.ancillary_brs = self.setup_ancillary_bridges(integ_br, tun_br)
+ self.ancillary_brs = self.setup_ancillary_bridges(
+ ovs_conf.integration_bridge, ovs_conf.tunnel_bridge)
# In order to keep existed device's local vlan unchanged,
# restore local vlan mapping at start
# The initialization is complete; we can start receiving messages
self.connection.consume_in_threads()
- self.quitting_rpc_timeout = quitting_rpc_timeout
+ self.quitting_rpc_timeout = agent_conf.quitting_rpc_timeout
+
+ def _parse_bridge_mappings(self, bridge_mappings):
+ try:
+ return n_utils.parse_mappings(bridge_mappings)
+ except ValueError as e:
+ raise ValueError(_("Parsing bridge_mappings failed: %s.") % e)
def _report_state(self):
# How many devices are likely used by a VM
"in both the Agent and Server side."))
-def create_agent_config_map(config):
- """Create a map of agent config parameters.
-
- :param config: an instance of cfg.CONF
- :returns: a map of agent configuration parameters
- """
- try:
- bridge_mappings = n_utils.parse_mappings(config.OVS.bridge_mappings)
- except ValueError as e:
- raise ValueError(_("Parsing bridge_mappings failed: %s.") % e)
-
- kwargs = dict(
- integ_br=config.OVS.integration_bridge,
- tun_br=config.OVS.tunnel_bridge,
- local_ip=config.OVS.local_ip,
- bridge_mappings=bridge_mappings,
- polling_interval=config.AGENT.polling_interval,
- minimize_polling=config.AGENT.minimize_polling,
- tunnel_types=config.AGENT.tunnel_types,
- veth_mtu=config.AGENT.veth_mtu,
- enable_distributed_routing=config.AGENT.enable_distributed_routing,
- l2_population=config.AGENT.l2_population,
- arp_responder=config.AGENT.arp_responder,
- prevent_arp_spoofing=config.AGENT.prevent_arp_spoofing,
- use_veth_interconnection=config.OVS.use_veth_interconnection,
- quitting_rpc_timeout=config.AGENT.quitting_rpc_timeout
- )
-
- # Verify the tunnel_types specified are valid
- for tun in kwargs['tunnel_types']:
- if tun not in constants.TUNNEL_NETWORK_TYPES:
- msg = _('Invalid tunnel type specified: %s'), tun
- raise ValueError(msg)
- if not kwargs['local_ip']:
- msg = _('Tunneling cannot be enabled without a valid local_ip.')
- raise ValueError(msg)
-
- return kwargs
-
-
def validate_local_ip(local_ip):
"""If tunneling is enabled, verify if the ip exists on the agent's host."""
if not cfg.CONF.AGENT.tunnel_types:
raise SystemExit(1)
+def validate_tunnel_types(tunnel_types, local_ip):
+ if tunnel_types and not local_ip:
+ msg = _('Tunneling cannot be enabled without a valid local_ip.')
+ raise ValueError(msg)
+
+ for tun in tunnel_types:
+ if tun not in constants.TUNNEL_NETWORK_TYPES:
+ msg = _('Invalid tunnel type specified: %s') % tun
+ raise ValueError(msg)
+
+
def prepare_xen_compute():
is_xen_compute_host = 'rootwrap-xen-dom0' in cfg.CONF.AGENT.root_helper
if is_xen_compute_host:
def main(bridge_classes):
+ prepare_xen_compute()
+ validate_local_ip(cfg.CONF.OVS.local_ip)
try:
- agent_config = create_agent_config_map(cfg.CONF)
- except ValueError:
- LOG.exception(_LE("Agent failed to create agent config map"))
+ validate_tunnel_types(cfg.CONF.AGENT.tunnel_types,
+ cfg.CONF.OVS.local_ip)
+ except ValueError as e:
+ LOG.error(_LE("Validation of tunnel types failed. %s"), e)
raise SystemExit(1)
- prepare_xen_compute()
- validate_local_ip(agent_config['local_ip'])
+
try:
- agent = OVSNeutronAgent(bridge_classes, **agent_config)
+ agent = OVSNeutronAgent(bridge_classes, cfg.CONF)
except (RuntimeError, ValueError) as e:
LOG.error(_LE("%s Agent terminated!"), e)
sys.exit(1)
self.f()
-class CreateAgentConfigMap(ovs_test_base.OVSAgentConfigTestBase):
+class ValidateTunnelTypes(ovs_test_base.OVSAgentConfigTestBase):
- def test_create_agent_config_map_succeeds(self):
- self.assertTrue(self.mod_agent.create_agent_config_map(cfg.CONF))
+ def test_validate_tunnel_types_succeeds(self):
+ cfg.CONF.set_override('local_ip', '10.10.10.10', group='OVS')
+ cfg.CONF.set_override('tunnel_types', [p_const.TYPE_GRE],
+ group='AGENT')
+ # ValueError will not raise
+ self.mod_agent.validate_tunnel_types(cfg.CONF.AGENT.tunnel_types,
+ cfg.CONF.OVS.local_ip)
- def test_create_agent_config_map_fails_for_invalid_tunnel_config(self):
+ def test_validate_tunnel_types_fails_for_invalid_tunnel_config(self):
# An ip address is required for tunneling but there is no default,
# verify this for both gre and vxlan tunnels.
+ cfg.CONF.set_override('local_ip', None, group='OVS')
cfg.CONF.set_override('tunnel_types', [p_const.TYPE_GRE],
group='AGENT')
with testtools.ExpectedException(ValueError):
- self.mod_agent.create_agent_config_map(cfg.CONF)
+ self.mod_agent.validate_tunnel_types(cfg.CONF.AGENT.tunnel_types,
+ cfg.CONF.OVS.local_ip)
cfg.CONF.set_override('tunnel_types', [p_const.TYPE_VXLAN],
group='AGENT')
with testtools.ExpectedException(ValueError):
- self.mod_agent.create_agent_config_map(cfg.CONF)
+ self.mod_agent.validate_tunnel_types(cfg.CONF.AGENT.tunnel_types,
+ cfg.CONF.OVS.local_ip)
- def test_create_agent_config_map_fails_no_local_ip(self):
- # An ip address is required for tunneling but there is no default
- cfg.CONF.set_override('tunnel_types', [p_const.TYPE_VXLAN],
- group='AGENT')
- with testtools.ExpectedException(ValueError):
- self.mod_agent.create_agent_config_map(cfg.CONF)
-
- def test_create_agent_config_map_fails_for_invalid_tunnel_type(self):
+ def test_validate_tunnel_types_fails_for_invalid_tunnel_type(self):
+ cfg.CONF.set_override('local_ip', '10.10.10.10', group='OVS')
cfg.CONF.set_override('tunnel_types', ['foobar'], group='AGENT')
with testtools.ExpectedException(ValueError):
- self.mod_agent.create_agent_config_map(cfg.CONF)
-
- def test_create_agent_config_map_multiple_tunnel_types(self):
- cfg.CONF.set_override('local_ip', '10.10.10.10', group='OVS')
- cfg.CONF.set_override('tunnel_types', [p_const.TYPE_GRE,
- p_const.TYPE_VXLAN], group='AGENT')
- cfgmap = self.mod_agent.create_agent_config_map(cfg.CONF)
- self.assertEqual(cfgmap['tunnel_types'],
- [p_const.TYPE_GRE, p_const.TYPE_VXLAN])
-
- def test_create_agent_config_map_enable_distributed_routing(self):
- self.addCleanup(cfg.CONF.reset)
- # Verify setting only enable_tunneling will default tunnel_type to GRE
- cfg.CONF.set_override('enable_distributed_routing', True,
- group='AGENT')
- cfgmap = self.mod_agent.create_agent_config_map(cfg.CONF)
- self.assertTrue(cfgmap['enable_distributed_routing'])
+ self.mod_agent.validate_tunnel_types(cfg.CONF.AGENT.tunnel_types,
+ cfg.CONF.OVS.local_ip)
class TestOvsNeutronAgent(object):
group='SECURITYGROUP')
cfg.CONF.set_default('quitting_rpc_timeout', 10, 'AGENT')
cfg.CONF.set_default('prevent_arp_spoofing', False, 'AGENT')
- kwargs = self.mod_agent.create_agent_config_map(cfg.CONF)
mock.patch(
'neutron.agent.common.ovs_lib.OVSBridge.get_ports_attributes',
return_value=[]).start()
'neutron.agent.common.ovs_lib.OVSBridge.' 'get_vif_ports',
return_value=[]):
self.agent = self.mod_agent.OVSNeutronAgent(self._bridge_classes(),
- **kwargs)
+ cfg.CONF)
self.agent.tun_br = self.br_tun_cls(br_name='br-tun')
self.agent.sg_agent = mock.Mock()
cfg.CONF.set_override('datapath_type',
expected,
group='OVS')
- kwargs = self.mod_agent.create_agent_config_map(cfg.CONF)
self.agent = self.mod_agent.OVSNeutronAgent(self._bridge_classes(),
- **kwargs)
+ cfg.CONF)
self.assertEqual(expected, self.agent.int_br.datapath_type)
def test_agent_type_ovs(self):
cfg.CONF.set_override('agent_type',
expected,
group='AGENT')
- kwargs = self.mod_agent.create_agent_config_map(cfg.CONF)
self.agent = self.mod_agent.OVSNeutronAgent(self._bridge_classes(),
- **kwargs)
+ cfg.CONF)
self.assertEqual(expected,
self.agent.agent_state['agent_type'])
'neutron.agent.firewall.NoopFirewallDriver',
group='SECURITYGROUP')
cfg.CONF.set_override('report_interval', 0, 'AGENT')
- self.kwargs = self.mod_agent.create_agent_config_map(cfg.CONF)
mock.patch('neutron.agent.common.ovs_lib.BaseOVS.config',
new_callable=mock.PropertyMock,
return_value={}).start()
'neutron.agent.common.ovs_lib.OVSBridge.' 'get_vif_ports',
return_value=[]):
self.agent = self.mod_agent.OVSNeutronAgent(self._bridge_classes(),
- **self.kwargs)
+ cfg.CONF)
self.assertEqual(len(ancillary), len(self.agent.ancillary_brs))
if ancillary:
bridges = [br.br_name for br in self.agent.ancillary_brs]
'get_vif_port_set',
return_value=vif_port_set):
self.agent = self.mod_agent.OVSNeutronAgent(self._bridge_classes(),
- **self.kwargs)
+ cfg.CONF)
return self.agent.scan_ancillary_ports(registered_ports, sync)
def test_scan_ancillary_ports_returns_cur_only_for_unchanged_ports(self):
cfg.CONF.set_default('firewall_driver',
'neutron.agent.firewall.NoopFirewallDriver',
group='SECURITYGROUP')
- kwargs = self.mod_agent.create_agent_config_map(cfg.CONF)
mock.patch('neutron.agent.common.ovs_lib.BaseOVS.config',
new_callable=mock.PropertyMock,
'neutron.agent.common.ovs_lib.OVSBridge.' 'get_vif_ports',
return_value=[]):
self.agent = self.mod_agent.OVSNeutronAgent(self._bridge_classes(),
- **kwargs)
+ cfg.CONF)
self.agent.tun_br = self.br_tun_cls(br_name='br-tun')
self.agent.sg_agent = mock.Mock()
self.INT_BRIDGE = 'integration_bridge'
self.TUN_BRIDGE = 'tunnel_bridge'
self.MAP_TUN_BRIDGE = 'tun_br_map'
- self.NET_MAPPING = {'net1': self.MAP_TUN_BRIDGE}
+ self.NET_MAPPING = ['net1:%s' % self.MAP_TUN_BRIDGE]
self.INT_OFPORT = 11111
self.TUN_OFPORT = 22222
self.MAP_TUN_INT_OFPORT = 33333
self.intb_expected = []
self.execute_expected = []
- def _build_agent(self, **kwargs):
+ def _build_agent(self, **config_opts_agent):
+ """Configure and initialize OVS agent.
+
+ :param config_opts_agent: a dict with options to override the
+ default values for the AGENT group.
+ """
bridge_classes = {
'br_int': self.mock_int_bridge_cls,
'br_phys': self.mock_phys_bridge_cls,
'br_tun': self.mock_tun_bridge_cls,
}
- kwargs.setdefault('bridge_classes', bridge_classes)
- kwargs.setdefault('integ_br', self.INT_BRIDGE)
- kwargs.setdefault('tun_br', self.TUN_BRIDGE)
- kwargs.setdefault('local_ip', '10.0.0.1')
- kwargs.setdefault('bridge_mappings', self.NET_MAPPING)
- kwargs.setdefault('polling_interval', 2)
- kwargs.setdefault('tunnel_types', ['gre'])
- kwargs.setdefault('veth_mtu', self.VETH_MTU)
- kwargs.setdefault('use_veth_interconnection',
- self.USE_VETH_INTERCONNECTION)
- return self.mod_agent.OVSNeutronAgent(**kwargs)
+ cfg.CONF.set_override('integration_bridge', self.INT_BRIDGE, 'OVS')
+ cfg.CONF.set_override('tunnel_bridge', self.TUN_BRIDGE, 'OVS')
+ cfg.CONF.set_override('local_ip', '10.0.0.1', 'OVS')
+ cfg.CONF.set_override('bridge_mappings', self.NET_MAPPING, 'OVS')
+ cfg.CONF.set_override('polling_interval', 2, 'AGENT')
+ cfg.CONF.set_override('tunnel_types', ['gre'], 'AGENT')
+ cfg.CONF.set_override('veth_mtu', self.VETH_MTU, 'AGENT')
+ cfg.CONF.set_override('minimize_polling', False, 'AGENT')
+ cfg.CONF.set_override('use_veth_interconnection',
+ self.USE_VETH_INTERCONNECTION, 'OVS')
+
+ for k, v in config_opts_agent.items():
+ cfg.CONF.set_override(k, v, 'AGENT')
+
+ return self.mod_agent.OVSNeutronAgent(bridge_classes, cfg.CONF)
def _verify_mock_call(self, mock_obj, expected):
mock_obj.assert_has_calls(expected)