Add missing trunk segment type option for profile create

The Cisco N1K plugin allows for 'trunk' type network profiles to
be created in addition to existing 'vlan' and 'overlay' types.
This fix is to add to the segment_type choices in forms.py to
include the missing 'trunk' choice. Additionally the description
message has been updated to make sure strings are uniform in all
locations. The help string for the multicast range has also been
updated to reflect a valid mcast IP and finally new unit tests
have been added.

Closes-bug: #1285298

Change-Id: Ifc6d2952f2e37d6757fe7a432cffdb8fe36ffc61
This commit is contained in:
Abishek Subramanian 2014-03-21 03:08:46 -04:00
parent 537dbacdcc
commit 72b2d8685c
4 changed files with 148 additions and 11 deletions

View File

@ -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

View File

@ -17,9 +17,9 @@
<div class="right">
<h3>{% trans "Description" %}:</h3>
<p><strong>{% trans "Name" %}</strong>: {% blocktrans %} Select a name for your network profile.{% endblocktrans %}</p>
<p><strong>{% trans "Segment Type" %}</strong>: {% blocktrans %} Segment types available are VLAN and OVERLAY.{% endblocktrans %}</p>
<p><strong>{% trans "Segment Sub Type" %}</strong>: {% 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 %}</p>
<p><strong>{% trans "Segment Range" %}</strong>: {% blocktrans %} Segment Ranges are 1-4093 for VLAN and above 5000 for enhanced overlay.{% endblocktrans %}</p>
<p><strong>{% trans "Segment Type" %}</strong>: {% blocktrans %} Segment types available are VLAN, Overlay and Trunk.{% endblocktrans %}</p>
<p><strong>{% trans "Segment Sub Type" %}</strong>: {% 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 %}</p>
<p><strong>{% trans "Segment Range" %}</strong>: {% blocktrans %} Segment Ranges are 1-4093 for VLAN and above 5000 for Enhanced-VXLAN Overlay.{% endblocktrans %}</p>
</div>
{% endblock %}

View File

@ -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'))

View File

@ -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))