Merge "OVS Mech: Set hybrid plug based on agent config"
This commit is contained in:
commit
d9a282b32c
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
Loading…
Reference in New Issue