diff --git a/openstack_dashboard/dashboards/router/nexus1000v/forms.py b/openstack_dashboard/dashboards/router/nexus1000v/forms.py index 212edf7c56..7f60087d1e 100644 --- a/openstack_dashboard/dashboards/router/nexus1000v/forms.py +++ b/openstack_dashboard/dashboards/router/nexus1000v/forms.py @@ -53,14 +53,16 @@ class CreateNetworkProfile(forms.SelfHandlingForm): required=True) segment_type = forms.ChoiceField(label=_('Segment Type'), choices=[('vlan', _('VLAN')), - ('overlay', _('OVERLAY'))], + ('overlay', _('Overlay')), + ('trunk', _('Trunk'))], widget=forms.Select (attrs={'class': 'switchable', 'data-slug': 'segtype'})) + # Sub type options available for Overlay segment type sub_type = forms.ChoiceField(label=_('Sub Type'), - choices=[('native_vxlan', _('NATIVE VXLAN')), - ('enhanced', _('ENHANCED')), - ('other', _('OTHER'))], + choices=[('native_vxlan', _('Native VXLAN')), + ('enhanced', _('Enhanced VXLAN')), + ('other', _('Other'))], required=False, widget=forms.Select (attrs={'class': 'switchable switched', @@ -68,9 +70,24 @@ class CreateNetworkProfile(forms.SelfHandlingForm): 'data-switch-on': 'segtype', 'data-segtype-overlay': _("Sub Type")})) + # Sub type options available for Trunk segment type + sub_type_trunk = forms.ChoiceField(label=_('Sub Type'), + choices=[('vlan', _('VLAN'))], + required=False, + widget=forms.Select + (attrs={'class': 'switched', + 'data-switch-on': 'segtype', + 'data-segtype-trunk': _("Sub Type")})) segment_range = forms.CharField(max_length=255, label=_("Segment Range"), - required=True, + required=False, + widget=forms.TextInput + (attrs={'class': 'switched', + 'data-switch-on': 'segtype', + 'data-segtype-vlan': + _("Segment Range"), + 'data-segtype-overlay': + _("Segment Range")}), help_text=_("1-4093 for VLAN; " "5000-10000 for Overlay")) multicast_ip_range = forms.CharField(max_length=30, @@ -83,8 +100,8 @@ class CreateNetworkProfile(forms.SelfHandlingForm): 'data-subtype-native_vxlan': _("Multicast IP Range")}), help_text=_("Multicast IPv4 range" - "(e.g. 132.0.0.0-" - "132.0.0.100)")) + "(e.g. 224.0.0.0-" + "224.0.0.100)")) other_subtype = forms.CharField(max_length=255, label=_("Sub Type Value (Manual Input)"), required=False, @@ -112,7 +129,8 @@ class CreateNetworkProfile(forms.SelfHandlingForm): self.fields['project'].choices = get_tenant_choices(request) def clean(self): - # If sub_type is 'other' then assign this new value for sub_type + # If sub_type is 'other' or 'trunk' then + # assign this new value for sub_type cleaned_data = super(CreateNetworkProfile, self).clean() segment_type = cleaned_data.get('segment_type') @@ -123,6 +141,11 @@ class CreateNetworkProfile(forms.SelfHandlingForm): cleaned_data['sub_type'] = other_subtype LOG.debug('subtype is now %(params)s', {'params': other_subtype}) + elif segment_type == 'trunk': + sub_type_trunk = cleaned_data.get('sub_type_trunk') + cleaned_data['sub_type'] = sub_type_trunk + LOG.debug('subtype is now %(params)s', + {'params': sub_type_trunk}) return cleaned_data diff --git a/openstack_dashboard/dashboards/router/nexus1000v/templates/nexus1000v/_create_network_profile.html b/openstack_dashboard/dashboards/router/nexus1000v/templates/nexus1000v/_create_network_profile.html index 6a14cd566a..3af06ce110 100644 --- a/openstack_dashboard/dashboards/router/nexus1000v/templates/nexus1000v/_create_network_profile.html +++ b/openstack_dashboard/dashboards/router/nexus1000v/templates/nexus1000v/_create_network_profile.html @@ -17,9 +17,9 @@

{% trans "Description" %}:

{% trans "Name" %}: {% blocktrans %} Select a name for your network profile.{% endblocktrans %}

-

{% trans "Segment Type" %}: {% blocktrans %} Segment types available are VLAN and OVERLAY.{% endblocktrans %}

-

{% trans "Segment Sub Type" %}: {% blocktrans %} Sub types available are for the Overlay segment. Available sub-types for overlay are: native_vxlan, enhanced or 'other' (eg. GRE) which can be manually inputed as a text parameter for subtype.{% endblocktrans %}

-

{% trans "Segment Range" %}: {% blocktrans %} Segment Ranges are 1-4093 for VLAN and above 5000 for enhanced overlay.{% endblocktrans %}

+

{% trans "Segment Type" %}: {% blocktrans %} Segment types available are VLAN, Overlay and Trunk.{% endblocktrans %}

+

{% trans "Segment Sub Type" %}: {% blocktrans %} Sub types available are for the Overlay and Trunk segments. Available sub-types for Overlay are: Native-VXLAN, Enhanced-VXLAN or 'Other' (eg. GRE) which can be manually inputed as a text parameter for subtype. Available sub-type for Trunk is: VLAN.{% endblocktrans %}

+

{% trans "Segment Range" %}: {% blocktrans %} Segment Ranges are 1-4093 for VLAN and above 5000 for Enhanced-VXLAN Overlay.{% endblocktrans %}

{% endblock %} diff --git a/openstack_dashboard/dashboards/router/nexus1000v/tests.py b/openstack_dashboard/dashboards/router/nexus1000v/tests.py index 00de01b4bd..d957ae335c 100644 --- a/openstack_dashboard/dashboards/router/nexus1000v/tests.py +++ b/openstack_dashboard/dashboards/router/nexus1000v/tests.py @@ -133,3 +133,73 @@ if api.neutron.is_port_profiles_supported(): self.assertRedirectsNoFollow(res, reverse ('horizon:router:nexus1000v:index')) + + @test.create_stubs({api.neutron: ('profile_create',), + api.keystone: ('tenant_list',)}) + def test_create_overlay_other_net_profile(self): + tenants = self.tenants.list() + net_profile = self.net_profiles.list()[2] + params = {'name': net_profile.name, + 'segment_type': net_profile.segment_type, + 'segment_range': net_profile.segment_range, + 'sub_type': net_profile.other_subtype, + 'tenant_id': net_profile.project, + # overlay 'other' profiles have no multicast_ip_range + # or physical_network type + 'multicast_ip_range': '', + 'physical_network': ''} + + api.neutron.profile_create(IsA(http.HttpRequest), + **params).AndReturn(net_profile) + api.keystone.tenant_list( + IsA(http.HttpRequest)).AndReturn([tenants, False]) + self.mox.ReplayAll() + + form_data = {'name': net_profile.name, + 'segment_type': net_profile.segment_type, + 'segment_range': net_profile.segment_range, + 'sub_type': net_profile.sub_type, + 'other_subtype': net_profile.other_subtype, + 'project': net_profile.project} + form_data.update(form_data_overlay()) + url = reverse('horizon:router:nexus1000v:create_network_profile') + res = self.client.post(url, form_data) + + self.assertNoFormErrors(res) + self.assertRedirectsNoFollow(res, + reverse + ('horizon:router:nexus1000v:index')) + + @test.create_stubs({api.neutron: ('profile_create',), + api.keystone: ('tenant_list',)}) + def test_create_trunk_net_profile(self): + tenants = self.tenants.list() + net_profile = self.net_profiles.list()[3] + params = {'name': net_profile.name, + 'segment_type': net_profile.segment_type, + 'sub_type': net_profile.sub_type_trunk, + 'tenant_id': net_profile.project, + # trunk profiles have no multicast_ip_range, + # no segment_range or no physical_network type + 'multicast_ip_range': '', + 'segment_range': '', + 'physical_network': ''} + + api.neutron.profile_create(IsA(http.HttpRequest), + **params).AndReturn(net_profile) + api.keystone.tenant_list( + IsA(http.HttpRequest)).AndReturn([tenants, False]) + self.mox.ReplayAll() + + form_data = {'name': net_profile.name, + 'segment_type': net_profile.segment_type, + 'sub_type_trunk': net_profile.sub_type_trunk, + 'project': net_profile.project} + form_data.update(form_data_no_overlay()) + url = reverse('horizon:router:nexus1000v:create_network_profile') + res = self.client.post(url, form_data) + + self.assertNoFormErrors(res) + self.assertRedirectsNoFollow(res, + reverse + ('horizon:router:nexus1000v:index')) diff --git a/openstack_dashboard/test/test_data/neutron_data.py b/openstack_dashboard/test/test_data/neutron_data.py index 6445833f73..e64af7862f 100644 --- a/openstack_dashboard/test/test_data/neutron_data.py +++ b/openstack_dashboard/test/test_data/neutron_data.py @@ -911,3 +911,47 @@ def data(TEST): TEST.api_network_profile_binding.add(network_profile_binding_dict) TEST.network_profile_binding.add(neutron.Profile( network_profile_binding_dict)) + + # 3rd network profile for network when using the cisco n1k plugin + # Profile applied on 1st network + net_profile_dict = {'name': 'net_profile_test3', + 'segment_type': 'overlay', + 'sub_type': 'other', + 'other_subtype': 'GRE', + 'segment_range': '11000-11100', + 'id': + '00000000-3333-3333-3333-000000000000', + 'project': '1'} + + TEST.api_net_profiles.add(net_profile_dict) + TEST.net_profiles.add(neutron.Profile(net_profile_dict)) + + # 3rd network profile binding + network_profile_binding_dict = {'profile_id': + '00000000-3333-3333-3333-000000000000', + 'tenant_id': '1'} + + TEST.api_network_profile_binding.add(network_profile_binding_dict) + TEST.network_profile_binding.add(neutron.Profile( + network_profile_binding_dict)) + + # 4th network profile for network when using the cisco n1k plugin + # Profile applied on 1st network + net_profile_dict = {'name': 'net_profile_test4', + 'segment_type': 'trunk', + 'sub_type_trunk': 'vlan', + 'id': + '00000000-4444-4444-4444-000000000000', + 'project': '1'} + + TEST.api_net_profiles.add(net_profile_dict) + TEST.net_profiles.add(neutron.Profile(net_profile_dict)) + + # 4th network profile binding + network_profile_binding_dict = {'profile_id': + '00000000-4444-4444-4444-000000000000', + 'tenant_id': '1'} + + TEST.api_network_profile_binding.add(network_profile_binding_dict) + TEST.network_profile_binding.add(neutron.Profile( + network_profile_binding_dict))