Change tenant network type usage for IB Fabric
This patch changes tenant network type usage for InfiniBand Fabric to vlan type. Add the indication of Fabric Type (Ethernet/InfiniBand) to the provider_network via the plugin configuration file. If physical network type is not specified for some provider network listed in the network_vlan_ranges, use default physical network type. Co-authored-by: Roey Chen <roeyc@mellanox.com> Change-Id: Id45acfb8234359a43303c2eee2205a44998c039a Closes-Bug: 1263638
This commit is contained in:
parent
4f6c33439b
commit
989246779d
@ -18,6 +18,21 @@
|
||||
# network_vlan_ranges =
|
||||
# Example: network_vlan_ranges = default:1:100
|
||||
|
||||
# (ListOpt) Comma-separated list of
|
||||
# <physical_network>:<physical_network_type> tuples mapping physical
|
||||
# network names to physical network types. All physical
|
||||
# networks listed in network_vlan_ranges should have
|
||||
# mappings to appropriate physical network type.
|
||||
# Type of the physical network can be either eth (Ethernet) or
|
||||
# ib (InfiniBand). If empty, physical network eth type is assumed.
|
||||
#
|
||||
# physical_network_type_mappings =
|
||||
# Example: physical_network_type_mappings = default:eth
|
||||
|
||||
# (StrOpt) Type of the physical network, can be either 'eth' or 'ib'
|
||||
# The default value is 'eth'
|
||||
# physical_network_type = eth
|
||||
|
||||
[eswitch]
|
||||
# (ListOpt) Comma-separated list of
|
||||
# <physical_network>:<physical_interface> tuples mapping physical
|
||||
|
@ -37,7 +37,6 @@ from neutron.openstack.common.rpc import dispatcher
|
||||
from neutron.plugins.common import constants as p_const
|
||||
from neutron.plugins.mlnx.agent import utils
|
||||
from neutron.plugins.mlnx.common import config # noqa
|
||||
from neutron.plugins.mlnx.common import constants
|
||||
from neutron.plugins.mlnx.common import exceptions
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -103,8 +102,7 @@ class EswitchManager(object):
|
||||
net_map = self.network_map[network_id]
|
||||
net_map['ports'].append({'port_id': port_id, 'port_mac': port_mac})
|
||||
|
||||
if network_type in (p_const.TYPE_VLAN,
|
||||
constants.TYPE_IB):
|
||||
if network_type == p_const.TYPE_VLAN:
|
||||
LOG.info(_('Binding Segmentation ID %(seg_id)s'
|
||||
'to eSwitch for vNIC mac_address %(mac)s'),
|
||||
{'seg_id': seg_id,
|
||||
@ -132,8 +130,6 @@ class EswitchManager(object):
|
||||
LOG.info(_("Provisioning network %s"), network_id)
|
||||
if network_type == p_const.TYPE_VLAN:
|
||||
LOG.debug(_("Creating VLAN Network"))
|
||||
elif network_type == constants.TYPE_IB:
|
||||
LOG.debug(_("Creating IB Network"))
|
||||
else:
|
||||
LOG.error(_("Unknown network type %(network_type)s "
|
||||
"for network %(network_id)s"),
|
||||
|
@ -26,11 +26,18 @@ DEFAULT_INTERFACE_MAPPINGS = []
|
||||
vlan_opts = [
|
||||
cfg.StrOpt('tenant_network_type', default='vlan',
|
||||
help=_("Network type for tenant networks "
|
||||
"(local, ib, vlan, or none)")),
|
||||
"(local, vlan, or none)")),
|
||||
cfg.ListOpt('network_vlan_ranges',
|
||||
default=DEFAULT_VLAN_RANGES,
|
||||
help=_("List of <physical_network>:<vlan_min>:<vlan_max> "
|
||||
"or <physical_network>")),
|
||||
cfg.ListOpt('physical_network_type_mappings',
|
||||
default=[],
|
||||
help=_("List of <physical_network>:<physical_network_type> "
|
||||
" with physical_network_type is either eth or ib")),
|
||||
cfg.StrOpt('physical_network_type', default='eth',
|
||||
help=_("Physical network type for provider network "
|
||||
"(eth or ib)"))
|
||||
]
|
||||
|
||||
|
||||
|
@ -18,8 +18,9 @@
|
||||
LOCAL_VLAN_ID = -2
|
||||
FLAT_VLAN_ID = -1
|
||||
|
||||
# Values for network_type
|
||||
# Values for physical network_type
|
||||
TYPE_IB = 'ib'
|
||||
TYPE_ETH = 'eth'
|
||||
|
||||
VIF_TYPE_DIRECT = 'mlnx_direct'
|
||||
VIF_TYPE_HOSTDEV = 'hostdev'
|
||||
|
@ -96,7 +96,7 @@ class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
def __init__(self):
|
||||
"""Start Mellanox Neutron Plugin."""
|
||||
super(MellanoxEswitchPlugin, self).__init__()
|
||||
self._parse_network_vlan_ranges()
|
||||
self._parse_network_config()
|
||||
db.sync_network_states(self.network_vlan_ranges)
|
||||
self._set_tenant_network_type()
|
||||
self.vnic_type = cfg.CONF.ESWITCH.vnic_type
|
||||
@ -133,6 +133,41 @@ class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
l3_rpc_agent_api.L3AgentNotify
|
||||
)
|
||||
|
||||
def _parse_network_config(self):
|
||||
self._parse_physical_network_types()
|
||||
self._parse_network_vlan_ranges()
|
||||
for network in self.network_vlan_ranges.keys():
|
||||
if not self.phys_network_type_maps.get(network):
|
||||
self.phys_network_type_maps[network] = self.physical_net_type
|
||||
|
||||
def _parse_physical_network_types(self):
|
||||
"""Parse physical network types configuration.
|
||||
|
||||
Verify default physical network type is valid.
|
||||
Parse physical network mappings.
|
||||
"""
|
||||
self.physical_net_type = cfg.CONF.MLNX.physical_network_type
|
||||
if self.physical_net_type not in (constants.TYPE_ETH,
|
||||
constants.TYPE_IB):
|
||||
LOG.error(_("Invalid physical network type %(type)s."
|
||||
"Server terminated!"), {'type': self.physical_net_type})
|
||||
raise SystemExit(1)
|
||||
try:
|
||||
self.phys_network_type_maps = utils.parse_mappings(
|
||||
cfg.CONF.MLNX.physical_network_type_mappings)
|
||||
except ValueError as e:
|
||||
LOG.error(_("Parsing physical_network_type failed: %s."
|
||||
" Server terminated!"), e)
|
||||
raise SystemExit(1)
|
||||
for network, type in self.phys_network_type_maps.iteritems():
|
||||
if type not in (constants.TYPE_ETH, constants.TYPE_IB):
|
||||
LOG.error(_("Invalid physical network type %(type)s "
|
||||
" for network %(net)s. Server terminated!"),
|
||||
{'net': network, 'type': type})
|
||||
raise SystemExit(1)
|
||||
LOG.info(_("Physical Network type mappings: %s"),
|
||||
self.phys_network_type_maps)
|
||||
|
||||
def _parse_network_vlan_ranges(self):
|
||||
try:
|
||||
self.network_vlan_ranges = plugin_utils.parse_network_vlan_ranges(
|
||||
@ -142,14 +177,6 @@ class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
sys.exit(1)
|
||||
LOG.info(_("Network VLAN ranges: %s"), self.network_vlan_ranges)
|
||||
|
||||
def _add_network_vlan_range(self, physical_network, vlan_min, vlan_max):
|
||||
self._add_network(physical_network)
|
||||
self.network_vlan_ranges[physical_network].append((vlan_min, vlan_max))
|
||||
|
||||
def _add_network(self, physical_network):
|
||||
if physical_network not in self.network_vlan_ranges:
|
||||
self.network_vlan_ranges[physical_network] = []
|
||||
|
||||
def _extend_network_dict_provider(self, context, network):
|
||||
binding = db.get_network_binding(context.session, network['id'])
|
||||
network[provider.NETWORK_TYPE] = binding.network_type
|
||||
@ -166,7 +193,6 @@ class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
def _set_tenant_network_type(self):
|
||||
self.tenant_network_type = cfg.CONF.MLNX.tenant_network_type
|
||||
if self.tenant_network_type not in [svc_constants.TYPE_VLAN,
|
||||
constants.TYPE_IB,
|
||||
svc_constants.TYPE_LOCAL,
|
||||
svc_constants.TYPE_NONE]:
|
||||
LOG.error(_("Invalid tenant_network_type: %s. "
|
||||
@ -194,7 +220,7 @@ class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
self._process_flat_net(segmentation_id_set)
|
||||
segmentation_id = constants.FLAT_VLAN_ID
|
||||
|
||||
elif network_type in [svc_constants.TYPE_VLAN, constants.TYPE_IB]:
|
||||
elif network_type == svc_constants.TYPE_VLAN:
|
||||
self._process_vlan_net(segmentation_id, segmentation_id_set)
|
||||
|
||||
elif network_type == svc_constants.TYPE_LOCAL:
|
||||
@ -241,7 +267,6 @@ class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
physical_network,
|
||||
physical_network_set):
|
||||
if network_type in [svc_constants.TYPE_VLAN,
|
||||
constants.TYPE_IB,
|
||||
svc_constants.TYPE_FLAT]:
|
||||
if physical_network_set:
|
||||
if physical_network not in self.network_vlan_ranges:
|
||||
@ -256,7 +281,10 @@ class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
return physical_network
|
||||
|
||||
def _check_port_binding_for_net_type(self, vnic_type, net_type):
|
||||
if net_type == svc_constants.TYPE_VLAN:
|
||||
"""
|
||||
VIF_TYPE_DIRECT is valid only for Ethernet fabric
|
||||
"""
|
||||
if net_type == constants.TYPE_ETH:
|
||||
return vnic_type in (constants.VIF_TYPE_DIRECT,
|
||||
constants.VIF_TYPE_HOSTDEV)
|
||||
elif net_type == constants.TYPE_IB:
|
||||
@ -269,22 +297,23 @@ class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
|
||||
net_binding = db.get_network_binding(context.session,
|
||||
attrs.get('network_id'))
|
||||
net_type = net_binding.network_type
|
||||
phy_net = net_binding.physical_network
|
||||
|
||||
if not binding_profile_set:
|
||||
return self.vnic_type
|
||||
if constants.VNIC_TYPE in binding_profile:
|
||||
vnic_type = binding_profile[constants.VNIC_TYPE]
|
||||
phy_net_type = self.phys_network_type_maps[phy_net]
|
||||
if vnic_type in (constants.VIF_TYPE_DIRECT,
|
||||
constants.VIF_TYPE_HOSTDEV):
|
||||
if self._check_port_binding_for_net_type(vnic_type,
|
||||
net_type):
|
||||
phy_net_type):
|
||||
self.base_binding_dict[portbindings.VIF_TYPE] = vnic_type
|
||||
return vnic_type
|
||||
else:
|
||||
msg = (_("Unsupported vnic type %(vnic_type)s "
|
||||
"for network type %(net_type)s") %
|
||||
{'vnic_type': vnic_type, 'net_type': net_type})
|
||||
"for physical network type %(net_type)s") %
|
||||
{'vnic_type': vnic_type, 'net_type': phy_net_type})
|
||||
else:
|
||||
msg = _("Invalid vnic_type on port_create")
|
||||
else:
|
||||
@ -307,15 +336,13 @@ class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
network_type = self.tenant_network_type
|
||||
if network_type == svc_constants.TYPE_NONE:
|
||||
raise q_exc.TenantNetworksDisabled()
|
||||
elif network_type in [svc_constants.TYPE_VLAN,
|
||||
constants.TYPE_IB]:
|
||||
elif network_type == svc_constants.TYPE_VLAN:
|
||||
physical_network, vlan_id = db.reserve_network(session)
|
||||
else: # TYPE_LOCAL
|
||||
vlan_id = constants.LOCAL_VLAN_ID
|
||||
else:
|
||||
# provider network
|
||||
if network_type in [svc_constants.TYPE_VLAN,
|
||||
constants.TYPE_IB,
|
||||
svc_constants.TYPE_FLAT]:
|
||||
db.reserve_specific_network(session,
|
||||
physical_network,
|
||||
|
@ -29,6 +29,9 @@ class ConfigurationTest(base.BaseTestCase):
|
||||
cfg.CONF.MLNX.tenant_network_type)
|
||||
self.assertEqual(1,
|
||||
len(cfg.CONF.MLNX.network_vlan_ranges))
|
||||
self.assertEqual('eth',
|
||||
cfg.CONF.MLNX.physical_network_type)
|
||||
self.assertFalse(cfg.CONF.MLNX.physical_network_type_mappings)
|
||||
self.assertEqual(0,
|
||||
len(cfg.CONF.ESWITCH.
|
||||
physical_interface_mappings))
|
||||
|
89
neutron/tests/unit/mlnx/test_mlnx_plugin_config.py
Normal file
89
neutron/tests/unit/mlnx/test_mlnx_plugin_config.py
Normal file
@ -0,0 +1,89 @@
|
||||
# Copyright (c) 2014 OpenStack Foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import mock
|
||||
from oslo.config import cfg
|
||||
|
||||
#NOTE this import loads tests required options
|
||||
from neutron.plugins.mlnx.common import config # noqa
|
||||
from neutron.plugins.mlnx.common import constants
|
||||
from neutron.plugins.mlnx.mlnx_plugin import MellanoxEswitchPlugin
|
||||
from neutron.tests import base
|
||||
|
||||
|
||||
class TestMlnxPluginConfig(base.BaseTestCase):
|
||||
expected_vlan_mappings = {'physnet1': [(1, 1000)],
|
||||
'physnet2': [(1, 1000)]}
|
||||
expected_network_types = {'physnet1': constants.TYPE_ETH,
|
||||
'physnet2': constants.TYPE_IB}
|
||||
config_vlan_ranges = ['physnet1:1:1000', 'physnet2:1:1000']
|
||||
config_network_types = ['physnet1:eth', 'physnet2:ib']
|
||||
|
||||
def setUp(self):
|
||||
super(TestMlnxPluginConfig, self).setUp()
|
||||
cfg.CONF.set_override('rpc_backend',
|
||||
'neutron.openstack.common.rpc.impl_fake')
|
||||
cfg.CONF.set_override(group='MLNX',
|
||||
name='network_vlan_ranges',
|
||||
override=self.config_vlan_ranges)
|
||||
|
||||
def _create_mlnx_plugin(self):
|
||||
with mock.patch('neutron.plugins.mlnx.db.mlnx_db_v2'):
|
||||
return MellanoxEswitchPlugin()
|
||||
|
||||
def _assert_expected_config(self):
|
||||
plugin = self._create_mlnx_plugin()
|
||||
self.assertEqual(plugin.network_vlan_ranges,
|
||||
self.expected_vlan_mappings)
|
||||
self.assertEqual(plugin.phys_network_type_maps,
|
||||
self.expected_network_types)
|
||||
|
||||
def test_vlan_ranges_with_network_type(self):
|
||||
cfg.CONF.set_override(group='MLNX',
|
||||
name='physical_network_type_mappings',
|
||||
override=self.config_network_types)
|
||||
self._assert_expected_config()
|
||||
|
||||
def test_vlan_ranges_partial_network_type(self):
|
||||
cfg.CONF.set_override(group='MLNX',
|
||||
name='physical_network_type_mappings',
|
||||
override=self.config_network_types[:1])
|
||||
cfg.CONF.set_override(group='MLNX',
|
||||
name='physical_network_type',
|
||||
override=constants.TYPE_IB)
|
||||
self._assert_expected_config()
|
||||
|
||||
def test_vlan_ranges_no_network_type(self):
|
||||
cfg.CONF.set_override(group='MLNX',
|
||||
name='physical_network_type',
|
||||
override=constants.TYPE_IB)
|
||||
cfg.CONF.set_override(group='MLNX',
|
||||
name='physical_network_type_mappings',
|
||||
override=[])
|
||||
self.expected_network_types.update({'physnet1': constants.TYPE_IB})
|
||||
self._assert_expected_config()
|
||||
self.expected_network_types.update({'physnet1': constants.TYPE_ETH})
|
||||
|
||||
def test_parse_physical_network_mappings_invalid_type(self):
|
||||
cfg.CONF.set_override(group='MLNX',
|
||||
name='physical_network_type_mappings',
|
||||
override=['physnet:invalid-type'])
|
||||
self.assertRaises(SystemExit, self._create_mlnx_plugin)
|
||||
|
||||
def test_invalid_network_type(self):
|
||||
cfg.CONF.set_override(group='MLNX',
|
||||
name='physical_network_type',
|
||||
override='invalid-type')
|
||||
self.assertRaises(SystemExit, self._create_mlnx_plugin)
|
Loading…
Reference in New Issue
Block a user