From 76f196d1ed5208b75d6019a0f9311e174c3d5b76 Mon Sep 17 00:00:00 2001 From: Tatiana Ovchinnikova Date: Thu, 14 Jan 2021 15:56:28 -0600 Subject: [PATCH] Add option to set MTU on network creation Setting MTU is now available for network creation on project and admin panels. Closes-Bug: #1549636 Change-Id: I384a6b78eaf75d9c0373cdfa51c3ea5f53f63e6b --- .../dashboards/admin/networks/forms.py | 7 +++ .../dashboards/admin/networks/tests.py | 46 +++++++++++++++++++ .../dashboards/admin/networks/workflows.py | 2 +- .../dashboards/project/networks/tests.py | 32 +++++++++++++ .../dashboards/project/networks/workflows.py | 9 +++- 5 files changed, 94 insertions(+), 2 deletions(-) diff --git a/openstack_dashboard/dashboards/admin/networks/forms.py b/openstack_dashboard/dashboards/admin/networks/forms.py index 00d5c1faeb..1ea5941f08 100644 --- a/openstack_dashboard/dashboards/admin/networks/forms.py +++ b/openstack_dashboard/dashboards/admin/networks/forms.py @@ -147,6 +147,11 @@ class CreateNetwork(forms.SelfHandlingForm): help_text=_("Availability zones where the DHCP agents may be " "scheduled. Leaving this unset is equivalent to " "selecting all availability zones")) + mtu = forms.IntegerField( + label=_("MTU"), required=False, min_value=68, + help_text=_("Maximum Transmission Unit. " + "Minimum is 68 bytes for the IPv4 subnet " + "and 1280 bytes for the IPv6 subnet.")) @classmethod def _instantiate(cls, request, *args, **kwargs): @@ -284,6 +289,8 @@ class CreateNetwork(forms.SelfHandlingForm): data['segmentation_id']) if 'az_hints' in data and data['az_hints']: params['availability_zone_hints'] = data['az_hints'] + if data['mtu']: + params['mtu'] = data['mtu'] network = api.neutron.network_create(request, **params) LOG.debug('Network %s was successfully created.', data['name']) return network diff --git a/openstack_dashboard/dashboards/admin/networks/tests.py b/openstack_dashboard/dashboards/admin/networks/tests.py index de9be31cdf..3c34ad8fa7 100644 --- a/openstack_dashboard/dashboards/admin/networks/tests.py +++ b/openstack_dashboard/dashboards/admin/networks/tests.py @@ -539,6 +539,52 @@ class NetworkTests(test.BaseAdminViewTests): self.mock_network_create.assert_called_once_with(test.IsHttpRequest(), **params) + @test.create_mocks({api.neutron: ('network_create', + 'is_extension_supported', + 'subnetpool_list'), + api.keystone: ('tenant_list',)}) + def test_network_create_post_with_mtu(self): + tenants = self.tenants.list() + tenant_id = self.tenants.first().id + network = self.networks.first() + + self.mock_tenant_list.return_value = [tenants, False] + self._stub_is_extension_supported( + {'provider': True, + 'network_availability_zone': False, + 'subnet_allocation': True}) + self.mock_subnetpool_list.return_value = self.subnetpools.list() + self.mock_network_create.return_value = network + + form_data = {'tenant_id': tenant_id, + 'name': network.name, + 'admin_state': network.admin_state_up, + 'external': True, + 'shared': True, + 'mtu': 1450, + 'network_type': 'local'} + url = reverse('horizon:admin:networks:create') + res = self.client.post(url, form_data) + + self.assertNoFormErrors(res) + self.assertRedirectsNoFollow(res, INDEX_URL) + + self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest()) + self.mock_subnetpool_list.assert_called_once_with(test.IsHttpRequest()) + params = {'name': network.name, + 'tenant_id': tenant_id, + 'admin_state_up': network.admin_state_up, + 'router:external': True, + 'shared': True, + 'mtu': 1450, + 'provider:network_type': 'local'} + self.mock_network_create.assert_called_once_with(test.IsHttpRequest(), + **params) + self._check_is_extension_supported( + {'provider': 3, + 'network_availability_zone': 2, + 'subnet_allocation': 1}) + @test.create_mocks({api.neutron: ('network_create', 'subnet_create', 'is_extension_supported', diff --git a/openstack_dashboard/dashboards/admin/networks/workflows.py b/openstack_dashboard/dashboards/admin/networks/workflows.py index 1fa0a97b9f..e4bf6f01d8 100644 --- a/openstack_dashboard/dashboards/admin/networks/workflows.py +++ b/openstack_dashboard/dashboards/admin/networks/workflows.py @@ -42,7 +42,7 @@ class CreateNetworkInfoAction(network_workflows.CreateNetworkInfoAction): class CreateNetworkInfo(network_workflows.CreateNetworkInfo): action_class = CreateNetworkInfoAction - contributes = ("net_name", "admin_state", "with_subnet", "az_hints") + contributes = ("net_name", "admin_state", "with_subnet", "az_hints", "mtu") def __init__(self, workflow): self.contributes = tuple(workflow.create_network_form.fields.keys()) diff --git a/openstack_dashboard/dashboards/project/networks/tests.py b/openstack_dashboard/dashboards/project/networks/tests.py index 227611792d..dc53c9b990 100644 --- a/openstack_dashboard/dashboards/project/networks/tests.py +++ b/openstack_dashboard/dashboards/project/networks/tests.py @@ -451,6 +451,38 @@ class NetworkTests(test.TestCase, NetworkStubMixin): self._check_is_extension_supported({'network_availability_zone': 1, 'subnet_allocation': 1}) + @test.create_mocks({api.neutron: ('network_create', + 'is_extension_supported', + 'subnetpool_list')}) + def test_network_create_post_with_mtu(self): + network = self.networks.first() + params = {'name': network.name, + 'admin_state_up': network.admin_state_up, + 'shared': False, + 'mtu': 1450} + self._stub_is_extension_supported({'network_availability_zone': False, + 'subnet_allocation': True}) + self.mock_subnetpool_list.return_value = self.subnetpools.list() + self.mock_network_create.return_value = network + + form_data = {'net_name': network.name, + 'admin_state': network.admin_state_up, + 'shared': False, + 'with_subnet': False, + 'mtu': 1450} + form_data.update(form_data_no_subnet()) + url = reverse('horizon:project:networks:create') + res = self.client.post(url, form_data) + + self.assertNoFormErrors(res) + self.assertRedirectsNoFollow(res, INDEX_URL) + + self.mock_subnetpool_list.assert_called_once_with(test.IsHttpRequest()) + self.mock_network_create.assert_called_once_with( + test.IsHttpRequest(), **params) + self._check_is_extension_supported({'network_availability_zone': 1, + 'subnet_allocation': 1}) + @test.create_mocks({api.neutron: ('network_create', 'is_extension_supported', 'subnetpool_list')}) diff --git a/openstack_dashboard/dashboards/project/networks/workflows.py b/openstack_dashboard/dashboards/project/networks/workflows.py index f3554495d4..5d0e7ad2ee 100644 --- a/openstack_dashboard/dashboards/project/networks/workflows.py +++ b/openstack_dashboard/dashboards/project/networks/workflows.py @@ -65,6 +65,11 @@ class CreateNetworkInfoAction(workflows.Action): help_text=_("Availability zones where the DHCP agents may be " "scheduled. Leaving this unset is equivalent to " "selecting all availability zones")) + mtu = forms.IntegerField( + label=_("MTU"), required=False, min_value=68, + help_text=_("Maximum Transmission Unit. " + "Minimum is 68 bytes for the IPv4 subnet " + "and 1280 bytes for the IPv6 subnet.")) def __init__(self, request, *args, **kwargs): super().__init__(request, *args, **kwargs) @@ -94,7 +99,7 @@ class CreateNetworkInfoAction(workflows.Action): class CreateNetworkInfo(workflows.Step): action_class = CreateNetworkInfoAction contributes = ("net_name", "admin_state", "with_subnet", "shared", - "az_hints") + "az_hints", "mtu") class CreateSubnetInfoAction(workflows.Action): @@ -485,6 +490,8 @@ class CreateNetwork(workflows.Workflow): 'shared': data['shared']} if 'az_hints' in data and data['az_hints']: params['availability_zone_hints'] = data['az_hints'] + if data['mtu']: + params['mtu'] = data['mtu'] network = api.neutron.network_create(request, **params) self.context['net_id'] = network.id LOG.debug('Network "%s" was successfully created.',