# 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
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__)
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,
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"),
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)"))
]
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'
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
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(
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
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. "
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:
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:
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:
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:
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,
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))
--- /dev/null
+# 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)