Make neutron provider network configuration more flexible

Previously only the predefined provider network types
can be used in supported_provider_types.
Neutron support various network back-ends and some of
them use different provider network types.
Operators who use such back-ends cannot specify extra
provider network types not defined in Horizon.

This commit reorganizes the logic around neutron provider
network and allows to specify extra provider network types.

Co-Authored-By: YAMAMOTO Takashi <yamamoto@midokura.com>
Related-Bug: #1504466
Change-Id: Ia5e3f91b7c5964a5253a67a42c7d63e35619d1c2
This commit is contained in:
Akihiro Motoki 2015-11-09 05:02:57 +09:00 committed by Akihiro Motoki
parent fbfc638de6
commit 5fc69c9764
4 changed files with 183 additions and 62 deletions

View File

@ -1059,9 +1059,10 @@ Default::
'enable_firewall': True,
'enable_vpn': True,
'profile_support': None,
'supported_provider_types': ["*"],
'supported_vnic_types': ["*"],
'supported_provider_types': ["*"],
'segmentation_id_range': {},
'extra_provider_types': {},
'enable_fip_topology_check': True,
}
@ -1190,9 +1191,14 @@ Default: ``["*"]``
For use with the provider network extension. Use this to explicitly set which
provider network types are supported. Only the network types in this list will
be available to choose from when creating a network. Network types include
local, flat, vlan, gre, and vxlan. By default all provider network types will
be available to choose from.
be available to choose from when creating a network.
Network types defined in Horizon or defined in ``extra_provider_types``
settings can be specified in this list.
As of the Liberty release, the network types defined in Horizon include
network types supported by Neutron ML2 plugin with Open vSwitch driver
(``local``, ``flat``, ``vlan``, ``gre``, and ``vxlan``).
``["*"]`` means that all provider network types supported by Neutron
ML2 plugin will be available to choose from.
Example: ``['local', 'flat', 'gre']``
@ -1226,7 +1232,48 @@ number is the maximum segmentation ID. Pertains only to the vlan, gre, and
vxlan network types. By default this option is not provided and each minimum
and maximum value will be the default for the provider network type.
Example: ``{'vlan': [1024, 2048], 'gre': [4094, 65536]}``
Example::
{
'vlan': [1024, 2048],
'gre': [4094, 65536]
}
``extra_provider_types``
~~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 10.0.0(Newton)
Default: ``{}``
For use with the provider network extension.
This is a dictionary to define extra provider network definitions.
Network types supported by Neutron depend on the configured plugin.
Horizon has predefined provider network types but horizon cannot cover
all of them. If you are using a provider network type not defined
in advance, you can add a definition through this setting.
The **key** name of each item in this must be a network type used
in the Neutron API. * **value** should be a dictionary which contains
the following items:
* ``display_name``: string displayed in the network creation form.
* ``require_physical_network``: a boolean parameter which indicates
this network type requires a physical network.
* ``require_segmentation_id``: a boolean parameter which indicates
this network type requires a segmentation ID.
If True, a valid segmentation ID range must be configureed
in ``segmentation_id_range`` settings above.
Example::
{
'awesome': {
'display_name': 'Awesome',
'require_physical_network': False,
'require_segmentation_id': True,
},
}
``enable_fip_topology_check``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -26,11 +26,51 @@ from openstack_dashboard import api
LOG = logging.getLogger(__name__)
PROVIDER_TYPES = [('local', _('Local')), ('flat', _('Flat')),
('vlan', _('VLAN')), ('gre', _('GRE')),
('vxlan', _('VXLAN'))]
SEGMENTATION_ID_RANGE = {'vlan': [1, 4094], 'gre': [0, (2 ** 32) - 1],
'vxlan': [0, (2 ** 24) - 1]}
# Predefined provider network types.
# You can add or override these entries by extra_provider_types
# in the settings.
PROVIDER_TYPES = {
'local': {
'display_name': _('Local'),
'require_physical_network': False,
'require_segmentation_id': False,
},
'flat': {
'display_name': _('Flat'),
'require_physical_network': True,
'require_segmentation_id': False,
},
'vlan': {
'display_name': _('VLAN'),
'require_physical_network': True,
'require_segmentation_id': True,
},
'gre': {
'display_name': _('GRE'),
'require_physical_network': False,
'require_segmentation_id': True,
},
'vxlan': {
'display_name': _('VXLAN'),
'require_physical_network': False,
'require_segmentation_id': True,
},
}
# Predefined valid segmentation ID range per network type.
# You can add or override these entries by segmentation_id_range
# in the settings.
SEGMENTATION_ID_RANGE = {
'vlan': (1, 4094),
'gre': (0, (2 ** 32) - 1),
'vxlan': (0, (2 ** 24) - 1),
}
# DEFAULT_PROVIDER_TYPES is used when ['*'] is specified
# in supported_provider_types. This list contains network types
# supported by Neutron ML2 plugin reference implementation.
# You can control enabled network types by
# supported_provider_types setting.
DEFAULT_PROVIDER_TYPES = ['local', 'flat', 'vlan', 'gre', 'vxlan']
class CreateNetwork(forms.SelfHandlingForm):
@ -62,17 +102,12 @@ class CreateNetwork(forms.SelfHandlingForm):
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'network_type',
'data-network_type-flat': _('Physical Network'),
'data-network_type-vlan': _('Physical Network')
}))
segmentation_id = forms.IntegerField(
label=_("Segmentation ID"),
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'network_type',
'data-network_type-vlan': _('Segmentation ID'),
'data-network_type-gre': _('Segmentation ID'),
'data-network_type-vxlan': _('Segmentation ID')
}))
admin_state = forms.ChoiceField(choices=[(True, _('UP')),
(False, _('DOWN'))],
@ -102,38 +137,58 @@ class CreateNetwork(forms.SelfHandlingForm):
if api.neutron.is_extension_supported(request, 'provider'):
neutron_settings = getattr(settings,
'OPENSTACK_NEUTRON_NETWORK', {})
seg_id_range = neutron_settings.get('segmentation_id_range', {})
self.seg_id_range = {
'vlan': seg_id_range.get('vlan',
SEGMENTATION_ID_RANGE.get('vlan')),
'gre': seg_id_range.get('gre',
SEGMENTATION_ID_RANGE.get('gre')),
'vxlan': seg_id_range.get('vxlan',
SEGMENTATION_ID_RANGE.get('vxlan'))
}
seg_id_help = (
_("For VLAN networks, the VLAN VID on the physical "
"network that realizes the virtual network. Valid VLAN VIDs "
"are %(vlan_min)s through %(vlan_max)s. For GRE or VXLAN "
"networks, the tunnel ID. Valid tunnel IDs for GRE networks "
"are %(gre_min)s through %(gre_max)s. For VXLAN networks, "
"%(vxlan_min)s through %(vxlan_max)s.")
% {'vlan_min': self.seg_id_range['vlan'][0],
'vlan_max': self.seg_id_range['vlan'][1],
'gre_min': self.seg_id_range['gre'][0],
'gre_max': self.seg_id_range['gre'][1],
'vxlan_min': self.seg_id_range['vxlan'][0],
'vxlan_max': self.seg_id_range['vxlan'][1]})
self.fields['segmentation_id'].help_text = seg_id_help
self.seg_id_range = SEGMENTATION_ID_RANGE.copy()
seg_id_range = neutron_settings.get('segmentation_id_range')
if seg_id_range:
self.seg_id_range.update(seg_id_range)
self.provider_types = PROVIDER_TYPES.copy()
extra_provider_types = neutron_settings.get('extra_provider_types')
if extra_provider_types:
self.provider_types.update(extra_provider_types)
self.nettypes_with_seg_id = [
net_type for net_type in self.provider_types
if self.provider_types[net_type]['require_segmentation_id']]
self.nettypes_with_physnet = [
net_type for net_type in self.provider_types
if self.provider_types[net_type]['require_physical_network']]
supported_provider_types = neutron_settings.get(
'supported_provider_types', ['*'])
'supported_provider_types', DEFAULT_PROVIDER_TYPES)
if supported_provider_types == ['*']:
network_type_choices = PROVIDER_TYPES
else:
network_type_choices = [
net_type for net_type in PROVIDER_TYPES
if net_type[0] in supported_provider_types]
supported_provider_types = DEFAULT_PROVIDER_TYPES
undefined_provider_types = [
net_type for net_type in supported_provider_types
if net_type not in self.provider_types]
if undefined_provider_types:
LOG.error('Undefined provider network types are found: %s',
undefined_provider_types)
seg_id_help = [
_("For %(type)s networks, valid IDs are %(min)s to %(max)s.")
% {'type': net_type,
'min': self.seg_id_range[net_type][0],
'max': self.seg_id_range[net_type][1]}
for net_type in self.nettypes_with_seg_id]
self.fields['segmentation_id'].help_text = ' '.join(seg_id_help)
# Register network types which require segmentation ID
attrs = dict(('data-network_type-%s' % network_type,
_('Segmentation ID'))
for network_type in self.nettypes_with_seg_id)
self.fields['segmentation_id'].widget.attrs.update(attrs)
# Register network types which require physical network
attrs = dict(('data-network_type-%s' % network_type,
_('Physical Network'))
for network_type in self.nettypes_with_physnet)
self.fields['physical_network'].widget.attrs.update(attrs)
network_type_choices = [
(net_type, self.provider_types[net_type]['display_name'])
for net_type in supported_provider_types]
if len(network_type_choices) == 0:
self._hide_provider_network_type()
else:
@ -176,10 +231,10 @@ class CreateNetwork(forms.SelfHandlingForm):
if api.neutron.is_extension_supported(request, 'provider'):
network_type = data['network_type']
params['provider:network_type'] = network_type
if network_type in ['flat', 'vlan']:
if network_type in self.nettypes_with_physnet:
params['provider:physical_network'] = (
data['physical_network'])
if network_type in ['vlan', 'gre', 'vxlan']:
if network_type in self.nettypes_with_seg_id:
params['provider:segmentation_id'] = (
data['segmentation_id'])
network = api.neutron.network_create(request, **params)
@ -194,14 +249,15 @@ class CreateNetwork(forms.SelfHandlingForm):
def clean(self):
cleaned_data = super(CreateNetwork, self).clean()
self._clean_physical_network(cleaned_data)
self._clean_segmentation_id(cleaned_data)
if api.neutron.is_extension_supported(self.request, 'provider'):
self._clean_physical_network(cleaned_data)
self._clean_segmentation_id(cleaned_data)
return cleaned_data
def _clean_physical_network(self, data):
network_type = data.get('network_type')
if 'physical_network' in self._errors and (
network_type in ['local', 'gre']):
if ('physical_network' in self._errors and
network_type not in self.nettypes_with_physnet):
# In this case the physical network is not required, so we can
# ignore any errors.
del self._errors['physical_network']
@ -209,24 +265,20 @@ class CreateNetwork(forms.SelfHandlingForm):
def _clean_segmentation_id(self, data):
network_type = data.get('network_type')
if 'segmentation_id' in self._errors:
if network_type in ['local', 'flat']:
if network_type not in self.nettypes_with_seg_id:
# In this case the segmentation ID is not required, so we can
# ignore any errors.
del self._errors['segmentation_id']
elif network_type in ['vlan', 'gre', 'vxlan']:
elif network_type in self.nettypes_with_seg_id:
seg_id = data.get('segmentation_id')
seg_id_range = {'min': self.seg_id_range[network_type][0],
'max': self.seg_id_range[network_type][1]}
if seg_id < seg_id_range['min'] or seg_id > seg_id_range['max']:
if network_type == 'vlan':
msg = _('For VLAN networks, valid VLAN IDs are %(min)s '
'through %(max)s.') % seg_id_range
elif network_type == 'gre':
msg = _('For GRE networks, valid tunnel IDs are %(min)s '
'through %(max)s.') % seg_id_range
elif network_type == 'vxlan':
msg = _('For VXLAN networks, valid tunnel IDs are %(min)s '
'through %(max)s.') % seg_id_range
msg = (_('For a %(network_type)s network, valid segmentation '
'IDs are %(min)s through %(max)s.')
% {'network_type': network_type,
'min': seg_id_range['min'],
'max': seg_id_range['max']})
self._errors['segmentation_id'] = self.error_class([msg])

View File

@ -291,7 +291,23 @@ OPENSTACK_NEUTRON_NETWORK = {
# Set which provider network types are supported. Only the network types
# in this list will be available to choose from when creating a network.
# Network types include local, flat, vlan, gre, and vxlan.
'supported_provider_types': ['*'],
# 'supported_provider_types': ['*'],
# You can configure available segmentation ID range per network type
# in your deployment.
# 'segmentation_id_range': {
# 'vlan': [1024, 2048],
# 'vxlan': [4094, 65536],
# },
# You can define additional provider network types here.
# 'extra_provider_types': {
# 'awesome_type': {
# 'display_name': 'Awesome New Type',
# 'require_physical_network': False,
# 'require_segmentation_id': True,
# }
# },
# Set which VNIC types are supported for port binding. Only the VNIC
# types in this list will be available to choose from when creating a

View File

@ -0,0 +1,6 @@
---
features:
- Neutron provider network configuration now becomes more flexible
so that operators can configure various provider network parameters
including new network type, segmenatiton ID ranges and so on
based on neutron network back-ends they use.