diff --git a/doc/source/topics/settings.rst b/doc/source/topics/settings.rst index 796242f66a..1d3fb2dfec 100644 --- a/doc/source/topics/settings.rst +++ b/doc/source/topics/settings.rst @@ -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`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/openstack_dashboard/dashboards/admin/networks/forms.py b/openstack_dashboard/dashboards/admin/networks/forms.py index 265f7f2395..f5143283ea 100644 --- a/openstack_dashboard/dashboards/admin/networks/forms.py +++ b/openstack_dashboard/dashboards/admin/networks/forms.py @@ -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]) diff --git a/openstack_dashboard/local/local_settings.py.example b/openstack_dashboard/local/local_settings.py.example index 0569735a17..83bef29464 100644 --- a/openstack_dashboard/local/local_settings.py.example +++ b/openstack_dashboard/local/local_settings.py.example @@ -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 diff --git a/releasenotes/notes/provider-net-config-713f0672c8e49888.yaml b/releasenotes/notes/provider-net-config-713f0672c8e49888.yaml new file mode 100644 index 0000000000..82ff751d25 --- /dev/null +++ b/releasenotes/notes/provider-net-config-713f0672c8e49888.yaml @@ -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.