Merge "OVS Mech: Set hybrid plug based on agent config"

This commit is contained in:
Jenkins 2016-05-16 10:18:13 +00:00 committed by Gerrit Code Review
commit d9a282b32c
6 changed files with 132 additions and 33 deletions

View File

@ -912,6 +912,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
class OVSHybridIptablesFirewallDriver(IptablesFirewallDriver):
OVS_HYBRID_TAP_PREFIX = constants.TAP_DEVICE_PREFIX
OVS_HYBRID_PLUG_REQUIRED = True
def _port_chain_name(self, port, direction):
return iptables_manager.get_chain_name(

View File

@ -47,6 +47,7 @@ from neutron.common import ipv6_utils as ipv6
from neutron.common import topics
from neutron.common import utils as n_utils
from neutron import context
from neutron.extensions import portbindings
from neutron.plugins.common import constants as p_const
from neutron.plugins.common import utils as p_utils
from neutron.plugins.ml2.drivers.l2pop.rpc_manager import l2population_rpc
@ -231,6 +232,34 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
self.enable_tunneling,
self.enable_distributed_routing)
if self.enable_tunneling:
self.setup_tunnel_br_flows()
self.dvr_agent.setup_dvr_flows()
# Collect additional bridges to monitor
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
self._restore_local_vlan_map()
# Security group agent support
self.sg_agent = sg_rpc.SecurityGroupAgentRpc(self.context,
self.sg_plugin_rpc, self.local_vlan_map,
defer_refresh_firewall=True, integration_bridge=self.int_br)
# we default to False to provide backward compat with out of tree
# firewall drivers that expect the logic that existed on the Neutron
# server which only enabled hybrid plugging based on the use of the
# hybrid driver.
hybrid_plug = getattr(self.sg_agent.firewall,
'OVS_HYBRID_PLUG_REQUIRED', False)
self.prevent_arp_spoofing = (
agent_conf.prevent_arp_spoofing and
not self.sg_agent.firewall.provides_arp_spoofing_protection)
#TODO(mangelajo): optimize resource_versions to only report
# versions about resources which are common,
# or which are used by specific extensions.
@ -252,7 +281,8 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
'datapath_type': ovs_conf.datapath_type,
'ovs_capabilities': self.ovs.capabilities,
'vhostuser_socket_dir':
ovs_conf.vhostuser_socket_dir},
ovs_conf.vhostuser_socket_dir,
portbindings.OVS_HYBRID_PLUG: hybrid_plug},
'resource_versions': resources.LOCAL_RESOURCE_VERSIONS,
'agent_type': agent_conf.agent_type,
'start_flag': True}
@ -262,29 +292,6 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
heartbeat = loopingcall.FixedIntervalLoopingCall(
self._report_state)
heartbeat.start(interval=report_interval)
if self.enable_tunneling:
self.setup_tunnel_br_flows()
self.dvr_agent.setup_dvr_flows()
# Collect additional bridges to monitor
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
self._restore_local_vlan_map()
# Security group agent support
self.sg_agent = sg_rpc.SecurityGroupAgentRpc(self.context,
self.sg_plugin_rpc, self.local_vlan_map,
defer_refresh_firewall=True, integration_bridge=self.int_br)
self.prevent_arp_spoofing = (
agent_conf.prevent_arp_spoofing and
not self.sg_agent.firewall.provides_arp_spoofing_protection)
# Initialize iteration counter
self.iter_num = 0
self.run_daemon_loop = True

View File

@ -86,10 +86,16 @@ class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
return self.vif_type
def get_vif_details(self, agent, context):
if (agent['configurations'].get('datapath_type') !=
a_const.OVS_DATAPATH_NETDEV):
return self.vif_details
caps = agent['configurations'].get('ovs_capabilities', {})
a_config = agent['configurations']
if a_config.get('datapath_type') != a_const.OVS_DATAPATH_NETDEV:
details = dict(self.vif_details)
hybrid = portbindings.OVS_HYBRID_PLUG
if hybrid in a_config:
# we only override the vif_details for hybrid pluggin set
# in the constuctor if the agent specifically requests it
details[hybrid] = a_config[hybrid]
return details
caps = a_config.get('ovs_capabilities', {})
if a_const.OVS_DPDK_VHOST_USER in caps.get('iface_types', []):
sock_path = self.agent_vhu_sockpath(agent, context.current['id'])
return {

View File

@ -117,6 +117,10 @@ class TestOvsNeutronAgent(object):
mock.patch('neutron.agent.common.ovs_lib.BaseOVS.config',
new_callable=mock.PropertyMock,
return_value={}).start()
self.agent = self._make_agent()
self.agent.sg_agent = mock.Mock()
def _make_agent(self):
with mock.patch.object(self.mod_agent.OVSNeutronAgent,
'setup_integration_br'),\
mock.patch.object(self.mod_agent.OVSNeutronAgent,
@ -131,10 +135,10 @@ class TestOvsNeutronAgent(object):
mock.patch(
'neutron.agent.common.ovs_lib.OVSBridge.' 'get_vif_ports',
return_value=[]):
self.agent = self.mod_agent.OVSNeutronAgent(self._bridge_classes(),
cfg.CONF)
self.agent.tun_br = self.br_tun_cls(br_name='br-tun')
self.agent.sg_agent = mock.Mock()
agent = self.mod_agent.OVSNeutronAgent(self._bridge_classes(),
cfg.CONF)
agent.tun_br = self.br_tun_cls(br_name='br-tun')
return agent
def _mock_port_bound(self, ofport=None, new_local_vlan=None,
old_local_vlan=None, db_get_val=None):
@ -935,6 +939,31 @@ class TestOvsNeutronAgent(object):
setup_port_filters.assert_called_once_with(
set(), port_info.get('updated', set()))
def test_hybrid_plug_flag_based_on_firewall(self):
cfg.CONF.set_default(
'firewall_driver',
'neutron.agent.firewall.NoopFirewallDriver',
group='SECURITYGROUP')
agt = self._make_agent()
self.assertFalse(agt.agent_state['configurations']['ovs_hybrid_plug'])
cfg.CONF.set_default(
'firewall_driver',
'neutron.agent.linux.openvswitch_firewall.OVSFirewallDriver',
group='SECURITYGROUP')
with mock.patch('neutron.agent.linux.openvswitch_firewall.'
'OVSFirewallDriver.initialize_bridge'):
agt = self._make_agent()
self.assertFalse(agt.agent_state['configurations']['ovs_hybrid_plug'])
cfg.CONF.set_default(
'firewall_driver',
'neutron.agent.linux.iptables_firewall.'
'OVSHybridIptablesFirewallDriver',
group='SECURITYGROUP')
with mock.patch('neutron.agent.linux.iptables_firewall.'
'IptablesFirewallDriver._populate_initial_zone_map'):
agt = self._make_agent()
self.assertTrue(agt.agent_state['configurations']['ovs_hybrid_plug'])
def test_report_state(self):
with mock.patch.object(self.agent.state_rpc,
"report_state") as report_st:
@ -2112,7 +2141,7 @@ class TestOvsDvrNeutronAgent(object):
'neutron.agent.common.ovs_lib.OVSBridge.' 'get_vif_ports',
return_value=[]):
self.agent = self.mod_agent.OVSNeutronAgent(self._bridge_classes(),
cfg.CONF)
cfg.CONF)
self.agent.tun_br = self.br_tun_cls(br_name='br-tun')
self.agent.sg_agent = mock.Mock()

View File

@ -17,6 +17,7 @@ from neutron_lib import constants
from oslo_config import cfg
from neutron.extensions import portbindings
from neutron.plugins.ml2 import driver_api as api
from neutron.plugins.ml2.drivers.openvswitch.mech_driver \
import mech_openvswitch
from neutron.tests.unit.plugins.ml2 import _test_mech_agent as base
@ -71,6 +72,49 @@ class OpenvswitchMechanismSGDisabledBaseTestCase(
super(OpenvswitchMechanismSGDisabledBaseTestCase, self).setUp()
class OpenvswitchMechanismHybridPlugTestCase(OpenvswitchMechanismBaseTestCase):
def _make_port_ctx(self, agents):
segments = [{api.ID: 'local_segment_id', api.NETWORK_TYPE: 'local'}]
return base.FakePortContext(self.AGENT_TYPE, agents, segments,
vnic_type=self.VNIC_TYPE)
def test_backward_compat_with_unreporting_agent(self):
hybrid = portbindings.OVS_HYBRID_PLUG
# agent didn't report so it should be hybrid based on server config
context = self._make_port_ctx(self.AGENTS)
self.driver.bind_port(context)
self.assertTrue(context._bound_vif_details[hybrid])
self.driver.vif_details[hybrid] = False
context = self._make_port_ctx(self.AGENTS)
self.driver.bind_port(context)
self.assertFalse(context._bound_vif_details[hybrid])
def test_hybrid_plug_true_if_agent_requests(self):
hybrid = portbindings.OVS_HYBRID_PLUG
# set server side default to false and ensure that hybrid becomes
# true if requested by the agent
self.driver.vif_details[hybrid] = False
agents = [{'alive': True,
'configurations': {hybrid: True},
'host': 'host'}]
context = self._make_port_ctx(agents)
self.driver.bind_port(context)
self.assertTrue(context._bound_vif_details[hybrid])
def test_hybrid_plug_false_if_agent_requests(self):
hybrid = portbindings.OVS_HYBRID_PLUG
# set server side default to true and ensure that hybrid becomes
# false if requested by the agent
self.driver.vif_details[hybrid] = True
agents = [{'alive': True,
'configurations': {hybrid: False},
'host': 'host'}]
context = self._make_port_ctx(agents)
self.driver.bind_port(context)
self.assertFalse(context._bound_vif_details[hybrid])
class OpenvswitchMechanismGenericTestCase(OpenvswitchMechanismBaseTestCase,
base.AgentMechanismGenericTestCase):
pass

View File

@ -0,0 +1,12 @@
---
prelude: >
The Neutron server no longer needs to be configured
with a firewall driver and it can support mixed
environments of hybrid iptables firewalls and the
pure OVS firewall.
features:
- The Neutron server now learns the appropriate firewall
wiring behavior from each OVS agent so it no longer needs
to be configured with the firewall_driver. This means
it also supports multiple agents with different types
of firewalls.