Set vif_details to reflect enable_security_group

While plugging vif, VIFDriver in Nova follows "ovs_hybrid_plug" and
"port_filter" in "binding:vif_detail" which is passed from Neutron, but
those are always true.  This patch make ML2 OVS mech driver set those
param depends on enable_security_group flag.  It enables users to avoid
ovs_hybrid plugging.

This patch also fixes the same issue in the following plugins/drivers:
  * NEC Plugin
  * BigSwitch Plugin
  * Ryu Plugin
  * ML2 Plugin - OFAgent Mech Driver

Closes-Bug: #1336624
Change-Id: I2b7fb526a6f1b730ad65289307b24fd28b996e1b
This commit is contained in:
Ryota MIBU 2014-07-03 00:10:32 +09:00
parent bed3769e25
commit a99a33d290
10 changed files with 102 additions and 38 deletions

View File

@ -365,11 +365,12 @@ class NeutronRestProxyV2Base(db_base_plugin_v2.NeutronDbPluginV2,
cfg_vif_type = override cfg_vif_type = override
port[portbindings.VIF_TYPE] = cfg_vif_type port[portbindings.VIF_TYPE] = cfg_vif_type
sg_enabled = sg_rpc.is_firewall_enabled()
port[portbindings.VIF_DETAILS] = { port[portbindings.VIF_DETAILS] = {
# TODO(rkukura): Replace with new VIF security details # TODO(rkukura): Replace with new VIF security details
portbindings.CAP_PORT_FILTER: portbindings.CAP_PORT_FILTER:
'security-group' in self.supported_extension_aliases, 'security-group' in self.supported_extension_aliases,
portbindings.OVS_HYBRID_PLUG: True portbindings.OVS_HYBRID_PLUG: sg_enabled
} }
return port return port

View File

@ -19,6 +19,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from neutron.agent import securitygroups_rpc
from neutron.common import constants from neutron.common import constants
from neutron.extensions import portbindings from neutron.extensions import portbindings
from neutron.openstack.common import log from neutron.openstack.common import log
@ -40,11 +41,13 @@ class OfagentMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
""" """
def __init__(self): def __init__(self):
sg_enabled = securitygroups_rpc.is_firewall_enabled()
vif_details = {portbindings.CAP_PORT_FILTER: sg_enabled,
portbindings.OVS_HYBRID_PLUG: sg_enabled}
super(OfagentMechanismDriver, self).__init__( super(OfagentMechanismDriver, self).__init__(
constants.AGENT_TYPE_OFA, constants.AGENT_TYPE_OFA,
portbindings.VIF_TYPE_OVS, portbindings.VIF_TYPE_OVS,
{portbindings.CAP_PORT_FILTER: True, vif_details)
portbindings.OVS_HYBRID_PLUG: True})
def check_segment_for_agent(self, segment, agent): def check_segment_for_agent(self, segment, agent):
bridge_mappings = agent['configurations'].get('bridge_mappings', {}) bridge_mappings = agent['configurations'].get('bridge_mappings', {})

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from neutron.agent import securitygroups_rpc
from neutron.common import constants from neutron.common import constants
from neutron.extensions import portbindings from neutron.extensions import portbindings
from neutron.openstack.common import log from neutron.openstack.common import log
@ -33,11 +34,13 @@ class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
""" """
def __init__(self): def __init__(self):
sg_enabled = securitygroups_rpc.is_firewall_enabled()
vif_details = {portbindings.CAP_PORT_FILTER: sg_enabled,
portbindings.OVS_HYBRID_PLUG: sg_enabled}
super(OpenvswitchMechanismDriver, self).__init__( super(OpenvswitchMechanismDriver, self).__init__(
constants.AGENT_TYPE_OVS, constants.AGENT_TYPE_OVS,
portbindings.VIF_TYPE_OVS, portbindings.VIF_TYPE_OVS,
{portbindings.CAP_PORT_FILTER: True, vif_details)
portbindings.OVS_HYBRID_PLUG: True})
def check_segment_for_agent(self, segment, agent): def check_segment_for_agent(self, segment, agent):
mappings = agent['configurations'].get('bridge_mappings', {}) mappings = agent['configurations'].get('bridge_mappings', {})

View File

@ -421,15 +421,11 @@ class NECPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
self._cleanup_ofc_tenant(context, tenant_id) self._cleanup_ofc_tenant(context, tenant_id)
def _get_base_binding_dict(self): def _get_base_binding_dict(self):
binding = { sg_enabled = sg_rpc.is_firewall_enabled()
portbindings.VIF_TYPE: portbindings.VIF_TYPE_OVS, vif_details = {portbindings.CAP_PORT_FILTER: sg_enabled,
portbindings.VIF_DETAILS: { portbindings.OVS_HYBRID_PLUG: sg_enabled}
# TODO(rkukura): Replace with new VIF security details binding = {portbindings.VIF_TYPE: portbindings.VIF_TYPE_OVS,
portbindings.CAP_PORT_FILTER: portbindings.VIF_DETAILS: vif_details}
'security-group' in self.supported_extension_aliases,
portbindings.OVS_HYBRID_PLUG: True
}
}
return binding return binding
def _extend_port_dict_binding_portinfo(self, port_res, portinfo): def _extend_port_dict_binding_portinfo(self, port_res, portinfo):

View File

@ -107,15 +107,7 @@ class RyuNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
def __init__(self, configfile=None): def __init__(self, configfile=None):
super(RyuNeutronPluginV2, self).__init__() super(RyuNeutronPluginV2, self).__init__()
self.base_binding_dict = { self.base_binding_dict = self._get_base_binding_dict()
portbindings.VIF_TYPE: portbindings.VIF_TYPE_OVS,
portbindings.VIF_DETAILS: {
# TODO(rkukura): Replace with new VIF security details
portbindings.CAP_PORT_FILTER:
'security-group' in self.supported_extension_aliases,
portbindings.OVS_HYBRID_PLUG: True
}
}
portbindings_base.register_port_dict_function() portbindings_base.register_port_dict_function()
self.tunnel_key = db_api_v2.TunnelKey( self.tunnel_key = db_api_v2.TunnelKey(
cfg.CONF.OVS.tunnel_key_min, cfg.CONF.OVS.tunnel_key_max) cfg.CONF.OVS.tunnel_key_min, cfg.CONF.OVS.tunnel_key_max)
@ -134,6 +126,14 @@ class RyuNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
# register known all network list on startup # register known all network list on startup
self._create_all_tenant_network() self._create_all_tenant_network()
def _get_base_binding_dict(self):
sg_enabled = sg_rpc.is_firewall_enabled()
vif_details = {portbindings.CAP_PORT_FILTER: sg_enabled,
portbindings.OVS_HYBRID_PLUG: sg_enabled}
binding = {portbindings.VIF_TYPE: portbindings.VIF_TYPE_OVS,
portbindings.VIF_DETAILS: vif_details}
return binding
def _setup_rpc(self): def _setup_rpc(self):
self.service_topics = {svc_constants.CORE: topics.PLUGIN, self.service_topics = {svc_constants.CORE: topics.PLUGIN,
svc_constants.L3_ROUTER_NAT: topics.L3PLUGIN} svc_constants.L3_ROUTER_NAT: topics.L3PLUGIN}

View File

@ -29,19 +29,27 @@ class PortBindingsTestCase(test_db_plugin.NeutronDbPluginV2TestCase):
# VIF_TYPE must be overridden according to plugin vif_type # VIF_TYPE must be overridden according to plugin vif_type
VIF_TYPE = portbindings.VIF_TYPE_OTHER VIF_TYPE = portbindings.VIF_TYPE_OTHER
# The plugin supports the port security feature such as # VIF_DETAILS must be overridden according to plugin vif_details
# security groups and anti spoofing. VIF_DETAILS = None
HAS_PORT_FILTER = False
def _check_response_portbindings(self, port): def _check_response_portbindings(self, port):
self.assertEqual(port[portbindings.VIF_TYPE], self.VIF_TYPE) self.assertEqual(port[portbindings.VIF_TYPE], self.VIF_TYPE)
vif_details = port[portbindings.VIF_DETAILS]
# REVISIT(rkukura): Consider reworking tests to enable ML2 to bind # REVISIT(rkukura): Consider reworking tests to enable ML2 to bind
if self.VIF_TYPE not in [portbindings.VIF_TYPE_UNBOUND, if self.VIF_TYPE not in [portbindings.VIF_TYPE_UNBOUND,
portbindings.VIF_TYPE_BINDING_FAILED]: portbindings.VIF_TYPE_BINDING_FAILED]:
# TODO(rkukura): Replace with new VIF security details # NOTE(r-mibu): The following six lines are just for backward
self.assertEqual(vif_details[portbindings.CAP_PORT_FILTER], # compatibility. In this class, HAS_PORT_FILTER has been replaced
self.HAS_PORT_FILTER) # by VIF_DETAILS which can be set expected vif_details to check,
# but all replacement of HAS_PORT_FILTER in successor has not been
# completed.
if self.VIF_DETAILS is None:
expected = getattr(self, 'HAS_PORT_FILTER', False)
vif_details = port[portbindings.VIF_DETAILS]
port_filter = vif_details[portbindings.CAP_PORT_FILTER]
self.assertEqual(expected, port_filter)
return
self.assertEqual(self.VIF_DETAILS, port[portbindings.VIF_DETAILS])
def _check_response_no_portbindings(self, port): def _check_response_no_portbindings(self, port):
self.assertIn('status', port) self.assertIn('status', port)

View File

@ -120,7 +120,7 @@ class AgentMechanismBaseTestCase(base.BaseTestCase):
# The following must be overridden for the specific mechanism # The following must be overridden for the specific mechanism
# driver being tested: # driver being tested:
VIF_TYPE = None VIF_TYPE = None
CAP_PORT_FILTER = None VIF_DETAILS = None
AGENT_TYPE = None AGENT_TYPE = None
AGENTS = None AGENTS = None
AGENTS_DEAD = None AGENTS_DEAD = None
@ -136,8 +136,17 @@ class AgentMechanismBaseTestCase(base.BaseTestCase):
self.assertEqual(context._bound_vif_type, self.VIF_TYPE) self.assertEqual(context._bound_vif_type, self.VIF_TYPE)
vif_details = context._bound_vif_details vif_details = context._bound_vif_details
self.assertIsNotNone(vif_details) self.assertIsNotNone(vif_details)
self.assertEqual(vif_details[portbindings.CAP_PORT_FILTER], # NOTE(r-mibu): The following five lines are just for backward
self.CAP_PORT_FILTER) # compatibility. In this class, HAS_PORT_FILTER has been replaced
# by VIF_DETAILS which can be set expected vif_details to check,
# but all replacement of HAS_PORT_FILTER in successor has not been
# completed.
if self.VIF_DETAILS is None:
expected = getattr(self, 'CAP_PORT_FILTER', None)
port_filter = vif_details[portbindings.CAP_PORT_FILTER]
self.assertEqual(expected, port_filter)
return
self.assertEqual(self.VIF_DETAILS, vif_details)
class AgentMechanismGenericTestCase(AgentMechanismBaseTestCase): class AgentMechanismGenericTestCase(AgentMechanismBaseTestCase):

View File

@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from oslo.config import cfg
from neutron.common import constants from neutron.common import constants
from neutron.extensions import portbindings from neutron.extensions import portbindings
from neutron.plugins.ml2.drivers import mech_ofagent from neutron.plugins.ml2.drivers import mech_ofagent
@ -21,7 +23,8 @@ from neutron.tests.unit.ml2 import _test_mech_agent as base
class OfagentMechanismBaseTestCase(base.AgentMechanismBaseTestCase): class OfagentMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
VIF_TYPE = portbindings.VIF_TYPE_OVS VIF_TYPE = portbindings.VIF_TYPE_OVS
CAP_PORT_FILTER = True VIF_DETAILS = {portbindings.CAP_PORT_FILTER: True,
portbindings.OVS_HYBRID_PLUG: True}
AGENT_TYPE = constants.AGENT_TYPE_OFA AGENT_TYPE = constants.AGENT_TYPE_OFA
GOOD_MAPPINGS = {'fake_physical_network': 'fake_interface'} GOOD_MAPPINGS = {'fake_physical_network': 'fake_interface'}
@ -49,6 +52,17 @@ class OfagentMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
self.driver.initialize() self.driver.initialize()
class OfagentMechanismSGDisabledBaseTestCase(OfagentMechanismBaseTestCase):
VIF_DETAILS = {portbindings.CAP_PORT_FILTER: False,
portbindings.OVS_HYBRID_PLUG: False}
def setUp(self):
cfg.CONF.set_override('enable_security_group',
False,
group='SECURITYGROUP')
super(OfagentMechanismSGDisabledBaseTestCase, self).setUp()
class OfagentMechanismGenericTestCase(OfagentMechanismBaseTestCase, class OfagentMechanismGenericTestCase(OfagentMechanismBaseTestCase,
base.AgentMechanismGenericTestCase): base.AgentMechanismGenericTestCase):
pass pass
@ -74,12 +88,19 @@ class OfagentMechanismGreTestCase(OfagentMechanismBaseTestCase,
pass pass
class OfagentMechanismSGDisabledLocalTestCase(
OfagentMechanismSGDisabledBaseTestCase,
base.AgentMechanismLocalTestCase):
pass
# The following tests are for deprecated "bridge_mappings". # The following tests are for deprecated "bridge_mappings".
# TODO(yamamoto): Remove them. # TODO(yamamoto): Remove them.
class OfagentMechanismPhysBridgeTestCase(base.AgentMechanismBaseTestCase): class OfagentMechanismPhysBridgeTestCase(base.AgentMechanismBaseTestCase):
VIF_TYPE = portbindings.VIF_TYPE_OVS VIF_TYPE = portbindings.VIF_TYPE_OVS
CAP_PORT_FILTER = True VIF_DETAILS = {portbindings.CAP_PORT_FILTER: True,
portbindings.OVS_HYBRID_PLUG: True}
AGENT_TYPE = constants.AGENT_TYPE_OFA AGENT_TYPE = constants.AGENT_TYPE_OFA
GOOD_MAPPINGS = {'fake_physical_network': 'fake_bridge'} GOOD_MAPPINGS = {'fake_physical_network': 'fake_bridge'}

View File

@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from oslo.config import cfg
from neutron.common import constants from neutron.common import constants
from neutron.extensions import portbindings from neutron.extensions import portbindings
from neutron.plugins.ml2.drivers import mech_openvswitch from neutron.plugins.ml2.drivers import mech_openvswitch
@ -21,7 +23,8 @@ from neutron.tests.unit.ml2 import _test_mech_agent as base
class OpenvswitchMechanismBaseTestCase(base.AgentMechanismBaseTestCase): class OpenvswitchMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
VIF_TYPE = portbindings.VIF_TYPE_OVS VIF_TYPE = portbindings.VIF_TYPE_OVS
CAP_PORT_FILTER = True VIF_DETAILS = {portbindings.CAP_PORT_FILTER: True,
portbindings.OVS_HYBRID_PLUG: True}
AGENT_TYPE = constants.AGENT_TYPE_OVS AGENT_TYPE = constants.AGENT_TYPE_OVS
GOOD_MAPPINGS = {'fake_physical_network': 'fake_bridge'} GOOD_MAPPINGS = {'fake_physical_network': 'fake_bridge'}
@ -49,6 +52,18 @@ class OpenvswitchMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
self.driver.initialize() self.driver.initialize()
class OpenvswitchMechanismSGDisabledBaseTestCase(
OpenvswitchMechanismBaseTestCase):
VIF_DETAILS = {portbindings.CAP_PORT_FILTER: False,
portbindings.OVS_HYBRID_PLUG: False}
def setUp(self):
cfg.CONF.set_override('enable_security_group',
False,
group='SECURITYGROUP')
super(OpenvswitchMechanismSGDisabledBaseTestCase, self).setUp()
class OpenvswitchMechanismGenericTestCase(OpenvswitchMechanismBaseTestCase, class OpenvswitchMechanismGenericTestCase(OpenvswitchMechanismBaseTestCase,
base.AgentMechanismGenericTestCase): base.AgentMechanismGenericTestCase):
pass pass
@ -72,3 +87,9 @@ class OpenvswitchMechanismVlanTestCase(OpenvswitchMechanismBaseTestCase,
class OpenvswitchMechanismGreTestCase(OpenvswitchMechanismBaseTestCase, class OpenvswitchMechanismGreTestCase(OpenvswitchMechanismBaseTestCase,
base.AgentMechanismGreTestCase): base.AgentMechanismGreTestCase):
pass pass
class OpenvswitchMechanismSGDisabledLocalTestCase(
OpenvswitchMechanismSGDisabledBaseTestCase,
base.AgentMechanismLocalTestCase):
pass

View File

@ -28,7 +28,8 @@ from neutron.tests.unit import test_security_groups_rpc as test_sg_rpc
class TestNecPortBinding(test_bindings.PortBindingsTestCase, class TestNecPortBinding(test_bindings.PortBindingsTestCase,
test_nec_plugin.NecPluginV2TestCase): test_nec_plugin.NecPluginV2TestCase):
VIF_TYPE = portbindings.VIF_TYPE_OVS VIF_TYPE = portbindings.VIF_TYPE_OVS
HAS_PORT_FILTER = True VIF_DETAILS = {portbindings.CAP_PORT_FILTER: True,
portbindings.OVS_HYBRID_PLUG: True}
ENABLE_SG = True ENABLE_SG = True
FIREWALL_DRIVER = test_sg_rpc.FIREWALL_HYBRID_DRIVER FIREWALL_DRIVER = test_sg_rpc.FIREWALL_HYBRID_DRIVER
@ -41,7 +42,8 @@ class TestNecPortBinding(test_bindings.PortBindingsTestCase,
class TestNecPortBindingNoSG(TestNecPortBinding): class TestNecPortBindingNoSG(TestNecPortBinding):
HAS_PORT_FILTER = False VIF_DETAILS = {portbindings.CAP_PORT_FILTER: False,
portbindings.OVS_HYBRID_PLUG: False}
ENABLE_SG = False ENABLE_SG = False
FIREWALL_DRIVER = test_sg_rpc.FIREWALL_NOOP_DRIVER FIREWALL_DRIVER = test_sg_rpc.FIREWALL_NOOP_DRIVER