diff --git a/openstack_dashboard/api/neutron.py b/openstack_dashboard/api/neutron.py index 3266eb396a..5f075a4c4f 100644 --- a/openstack_dashboard/api/neutron.py +++ b/openstack_dashboard/api/neutron.py @@ -53,6 +53,15 @@ ROUTER_INTERFACE_OWNERS = ( 'network:ha_router_replicated_interface' ) +VNIC_TYPES = [ + ('normal', _('Normal')), + ('direct', _('Direct')), + ('direct-physical', _('Direct Physical')), + ('macvtap', _('MacVTap')), + ('baremetal', _('Bare Metal')), + ('virtio-forwarder', _('Virtio Forwarder')), +] + class NeutronAPIDictWrapper(base.APIDictWrapper): diff --git a/openstack_dashboard/dashboards/admin/networks/ports/forms.py b/openstack_dashboard/dashboards/admin/networks/ports/forms.py index f852cc625b..3ead0fd5dc 100644 --- a/openstack_dashboard/dashboards/admin/networks/ports/forms.py +++ b/openstack_dashboard/dashboards/admin/networks/ports/forms.py @@ -28,12 +28,6 @@ from openstack_dashboard.dashboards.project.networks.ports \ LOG = logging.getLogger(__name__) -VNIC_TYPES = [('normal', _('Normal')), - ('direct', _('Direct')), - ('direct-physical', _('Direct Physical')), - ('macvtap', _('MacVTap')), - ('baremetal', _('Bare Metal')), - ('virtio-forwarder', _('Virtio Forwarder'))] class CreatePort(project_forms.CreatePort): @@ -56,10 +50,10 @@ class CreatePort(project_forms.CreatePort): 'supported_vnic_types', ['*']) if supported_vnic_types: if supported_vnic_types == ['*']: - vnic_type_choices = VNIC_TYPES + vnic_type_choices = api.neutron.VNIC_TYPES else: vnic_type_choices = [ - vnic_type for vnic_type in VNIC_TYPES + vnic_type for vnic_type in api.neutron.VNIC_TYPES if vnic_type[0] in supported_vnic_types ] @@ -137,63 +131,3 @@ class CreatePort(project_forms.CreatePort): msg = _('Failed to create a port for network %s') % network_id redirect = reverse(self.failure_url, args=(network_id,)) exceptions.handle(request, msg, redirect=redirect) - - -class UpdatePort(project_forms.UpdatePort): - # tenant_id = forms.CharField(widget=forms.HiddenInput()) - device_id = forms.CharField(max_length=100, label=_("Device ID"), - help_text=_("Device ID attached to the port"), - required=False) - device_owner = forms.CharField(max_length=100, label=_("Device Owner"), - help_text=_("Device owner attached to the " - "port"), - required=False) - binding__host_id = forms.CharField( - label=_("Binding: Host"), - help_text=_("The ID of the host where the port is allocated. In some " - "cases, different implementations can run on different " - "hosts."), - required=False) - mac_address = forms.MACAddressField( - label=_("MAC Address"), - required=False, - help_text=_("Specify a new MAC address for the port")) - - failure_url = 'horizon:admin:networks:detail' - - def handle(self, request, data): - port_id = self.initial['port_id'] - try: - LOG.debug('params = %s', data) - extension_kwargs = {} - if 'binding__vnic_type' in data: - extension_kwargs['binding__vnic_type'] = \ - data['binding__vnic_type'] - - if 'mac_state' in data: - extension_kwargs['mac_learning_enabled'] = data['mac_state'] - - if 'port_security_enabled' in data: - extension_kwargs['port_security_enabled'] = \ - data['port_security_enabled'] - - port = api.neutron.port_update(request, - port_id, - name=data['name'], - admin_state_up=data['admin_state'], - device_id=data['device_id'], - device_owner=data['device_owner'], - binding__host_id=data - ['binding__host_id'], - mac_address=data['mac_address'], - **extension_kwargs) - msg = _('Port %s was successfully updated.') % port_id - messages.success(request, msg) - return port - except Exception as e: - LOG.info('Failed to update port %(id)s: %(exc)s', - {'id': port_id, 'exc': e}) - msg = _('Failed to update port %s') % port_id - redirect = reverse(self.failure_url, - args=[self.initial['network_id']]) - exceptions.handle(request, msg, redirect=redirect) diff --git a/openstack_dashboard/dashboards/admin/networks/ports/tests.py b/openstack_dashboard/dashboards/admin/networks/ports/tests.py index 5ed322fa4a..248e2aba88 100644 --- a/openstack_dashboard/dashboards/admin/networks/ports/tests.py +++ b/openstack_dashboard/dashboards/admin/networks/ports/tests.py @@ -18,6 +18,8 @@ from django import http from mox3.mox import IsA +from horizon.workflows import views + from openstack_dashboard import api from openstack_dashboard.test import helpers as test @@ -375,7 +377,7 @@ class NetworkPortTests(test.BaseAdminViewTests): args=[port.network_id, port.id]) res = self.client.get(url) - self.assertTemplateUsed(res, 'admin/networks/ports/update.html') + self.assertTemplateUsed(res, views.WorkflowView.template_name) @test.create_stubs({api.neutron: ('port_get', 'is_extension_supported', @@ -402,13 +404,13 @@ class NetworkPortTests(test.BaseAdminViewTests): .AndReturn(port) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'binding')\ - .AndReturn(binding) + .MultipleTimes().AndReturn(binding) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'mac-learning')\ - .AndReturn(mac_learning) + .MultipleTimes().AndReturn(mac_learning) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'port-security')\ - .AndReturn(port_security) + .MultipleTimes().AndReturn(port_security) extension_kwargs = {} if binding: extension_kwargs['binding__vnic_type'] = port.binding__vnic_type @@ -475,13 +477,13 @@ class NetworkPortTests(test.BaseAdminViewTests): .AndReturn(port) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'binding')\ - .AndReturn(binding) + .MultipleTimes().AndReturn(binding) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'mac-learning')\ - .AndReturn(mac_learning) + .MultipleTimes().AndReturn(mac_learning) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'port-security')\ - .AndReturn(port_security) + .MultipleTimes().AndReturn(port_security) extension_kwargs = {} if binding: extension_kwargs['binding__vnic_type'] = port.binding__vnic_type diff --git a/openstack_dashboard/dashboards/admin/networks/ports/views.py b/openstack_dashboard/dashboards/admin/networks/ports/views.py index ed0bcda8f4..9a827ce50d 100644 --- a/openstack_dashboard/dashboards/admin/networks/ports/views.py +++ b/openstack_dashboard/dashboards/admin/networks/ports/views.py @@ -27,6 +27,8 @@ from openstack_dashboard.dashboards.admin.networks.ports \ import tables as ports_tables from openstack_dashboard.dashboards.admin.networks.ports \ import tabs as ports_tabs +from openstack_dashboard.dashboards.admin.networks.ports \ + import workflows as admin_workflows from openstack_dashboard.dashboards.project.networks.ports \ import views as project_views @@ -99,11 +101,8 @@ class DetailView(project_views.DetailView): class UpdateView(project_views.UpdateView): - form_class = ports_forms.UpdatePort - template_name = 'admin/networks/ports/update.html' - context_object_name = 'port' - submit_url = "horizon:admin:networks:editport" - success_url = 'horizon:admin:networks:detail' + workflow_class = admin_workflows.UpdatePort + failure_url = 'horizon:admin:networks:detail' def get_initial(self): initial = super(UpdateView, self).get_initial() @@ -111,4 +110,5 @@ class UpdateView(project_views.UpdateView): initial['binding__host_id'] = port['binding__host_id'] initial['device_id'] = port['device_id'] initial['device_owner'] = port['device_owner'] + return initial diff --git a/openstack_dashboard/dashboards/admin/networks/ports/workflows.py b/openstack_dashboard/dashboards/admin/networks/ports/workflows.py new file mode 100644 index 0000000000..c86b13aedf --- /dev/null +++ b/openstack_dashboard/dashboards/admin/networks/ports/workflows.py @@ -0,0 +1,75 @@ +# Copyright 2016 NEC Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +import logging + +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext_lazy as _ + +from horizon import forms + +from openstack_dashboard.dashboards.project.networks.ports \ + import workflows as project_workflow + + +LOG = logging.getLogger(__name__) + + +class UpdatePortInfoAction(project_workflow.UpdatePortInfoAction): + device_id = forms.CharField( + max_length=100, label=_("Device ID"), + help_text=_("Device ID attached to the port"), + required=False) + device_owner = forms.CharField( + max_length=100, label=_("Device Owner"), + help_text=_("Device owner attached to the port"), + required=False) + binding__host_id = forms.CharField( + label=_("Binding: Host"), + help_text=_("The ID of the host where the port is allocated. In some " + "cases, different implementations can run on different " + "hosts."), + required=False) + mac_address = forms.MACAddressField( + label=_("MAC Address"), + required=False, + help_text=_("MAC address for the port")) + + class Meta(object): + name = _("Info") + + +class UpdatePortInfo(project_workflow.UpdatePortInfo): + action_class = UpdatePortInfoAction + contributes = ["name", "admin_state", + "binding__vnic_type", "mac_state", "port_security_enabled", + "device_id", "device_owner", "binding__host_id", + "mac_address"] + + +class UpdatePort(project_workflow.UpdatePort): + default_steps = (UpdatePortInfo, ) + + def get_success_url(self): + return reverse("horizon:admin:networks:detail", + args=(self.context['network_id'],)) + + def _construct_parameters(self, data): + params = super(UpdatePort, self)._construct_parameters(data) + params.update({'device_id': data['device_id'], + 'device_owner': data['device_owner'], + 'binding__host_id': data['binding__host_id'], + 'mac_address': data['mac_address']}) + return params diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/_update.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/_update.html deleted file mode 100644 index e356d8f604..0000000000 --- a/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/_update.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends "horizon/common/_modal_form.html" %} -{% load i18n %} - -{% block modal-body-right %} -
{% trans "You may update the editable properties of your port here." %}
-{% endblock %} diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/update.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/update.html deleted file mode 100644 index cb90bb2e88..0000000000 --- a/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/update.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends 'base.html' %} -{% load i18n %} -{% block title %}{% trans "Update Port" %}{% endblock %} - -{% block main %} - {% include 'admin/networks/ports/_update.html' %} -{% endblock %} diff --git a/openstack_dashboard/dashboards/project/networks/ports/forms.py b/openstack_dashboard/dashboards/project/networks/ports/forms.py index e0ab20fde3..e43fb4fd16 100644 --- a/openstack_dashboard/dashboards/project/networks/ports/forms.py +++ b/openstack_dashboard/dashboards/project/networks/ports/forms.py @@ -14,7 +14,6 @@ import logging -from django.conf import settings from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ @@ -26,12 +25,6 @@ from openstack_dashboard import api LOG = logging.getLogger(__name__) -VNIC_TYPES = [('normal', _('Normal')), - ('direct', _('Direct')), - ('direct-physical', _('Direct Physical')), - ('macvtap', _('MacVTap')), - ('baremetal', _('Bare Metal')), - ('virtio-forwarder', _('Virtio Forwarder'))] class CreatePort(forms.SelfHandlingForm): @@ -163,88 +156,3 @@ class CreatePort(forms.SelfHandlingForm): redirect = reverse(self.failure_url, args=(self.initial['network_id'],)) exceptions.handle(request, msg, redirect=redirect) - - -class UpdatePort(forms.SelfHandlingForm): - name = forms.CharField(max_length=255, - label=_("Name"), - required=False) - admin_state = forms.BooleanField(label=_("Enable Admin State"), - required=False) - failure_url = 'horizon:project:networks:detail' - - def __init__(self, request, *args, **kwargs): - super(UpdatePort, self).__init__(request, *args, **kwargs) - try: - if api.neutron.is_extension_supported(request, 'binding'): - neutron_settings = getattr(settings, - 'OPENSTACK_NEUTRON_NETWORK', {}) - supported_vnic_types = neutron_settings.get( - 'supported_vnic_types', ['*']) - if supported_vnic_types: - if supported_vnic_types == ['*']: - vnic_type_choices = VNIC_TYPES - else: - vnic_type_choices = [ - vnic_type for vnic_type in VNIC_TYPES - if vnic_type[0] in supported_vnic_types - ] - - self.fields['binding__vnic_type'] = forms.ChoiceField( - choices=vnic_type_choices, - label=_("Binding: VNIC Type"), - help_text=_( - "The VNIC type that is bound to the neutron port"), - required=False) - except Exception: - msg = _("Unable to verify the VNIC types extension in Neutron") - exceptions.handle(self.request, msg) - - try: - if api.neutron.is_extension_supported(request, 'mac-learning'): - self.fields['mac_state'] = forms.BooleanField( - label=_("MAC Learning State"), initial=False, - required=False) - except Exception: - msg = _("Unable to retrieve MAC learning state") - exceptions.handle(self.request, msg) - - try: - if api.neutron.is_extension_supported(request, 'port-security'): - self.fields['port_security_enabled'] = forms.BooleanField( - label=_("Port Security"), - help_text=_("Enable anti-spoofing rules for the port"), - required=False) - except Exception: - msg = _("Unable to retrieve port security state") - exceptions.handle(self.request, msg) - - def handle(self, request, data): - port_id = self.initial['port_id'] - try: - LOG.debug('params = %s', data) - extension_kwargs = {} - if 'binding__vnic_type' in data: - extension_kwargs['binding__vnic_type'] = \ - data['binding__vnic_type'] - if 'mac_state' in data: - extension_kwargs['mac_learning_enabled'] = data['mac_state'] - if 'port_security_enabled' in data: - extension_kwargs['port_security_enabled'] = \ - data['port_security_enabled'] - - port = api.neutron.port_update(request, - port_id, - name=data['name'], - admin_state_up=data['admin_state'], - **extension_kwargs) - msg = _('Port %s was successfully updated.') % port_id - messages.success(request, msg) - return port - except Exception as e: - LOG.info('Failed to update port %(id)s: %(exc)s', - {'id': port_id, 'exc': e}) - msg = _('Failed to update port %s') % port_id - redirect = reverse(self.failure_url, - args=[self.initial['network_id']]) - exceptions.handle(request, msg, redirect=redirect) diff --git a/openstack_dashboard/dashboards/project/networks/ports/tests.py b/openstack_dashboard/dashboards/project/networks/ports/tests.py index 237450bf8c..4aa96cc122 100644 --- a/openstack_dashboard/dashboards/project/networks/ports/tests.py +++ b/openstack_dashboard/dashboards/project/networks/ports/tests.py @@ -20,6 +20,8 @@ from django import http from mox3.mox import IsA +from horizon.workflows import views + from openstack_dashboard import api from openstack_dashboard.test import helpers as test @@ -91,22 +93,21 @@ class NetworkPortTests(test.TestCase): def _test_port_update_get(self, mac_learning=False, binding=False): port = self.ports.first() - api.neutron.port_get(IsA(http.HttpRequest), - port.id)\ - .AndReturn(port) + api.neutron.port_get(IsA(http.HttpRequest), port.id) \ + .MultipleTimes().AndReturn(port) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'binding')\ - .AndReturn(binding) + .MultipleTimes().AndReturn(binding) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'mac-learning')\ - .AndReturn(mac_learning) + .MultipleTimes().AndReturn(mac_learning) self.mox.ReplayAll() url = reverse('horizon:project:networks:editport', args=[port.network_id, port.id]) res = self.client.get(url) - self.assertTemplateUsed(res, 'project/networks/ports/update.html') + self.assertTemplateUsed(res, views.WorkflowView.template_name) @test.create_stubs({api.neutron: ('port_get', 'is_extension_supported', @@ -133,13 +134,13 @@ class NetworkPortTests(test.TestCase): .AndReturn(port) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'binding')\ - .AndReturn(binding) + .MultipleTimes().AndReturn(binding) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'mac-learning')\ - .AndReturn(mac_learning) + .MultipleTimes().AndReturn(mac_learning) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'port-security')\ - .AndReturn(port_security) + .MultipleTimes().AndReturn(port_security) extension_kwargs = {} if binding: extension_kwargs['binding__vnic_type'] = port.binding__vnic_type @@ -198,13 +199,13 @@ class NetworkPortTests(test.TestCase): .AndReturn(port) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'binding')\ - .AndReturn(binding) + .MultipleTimes().AndReturn(binding) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'mac-learning')\ - .AndReturn(mac_learning) + .MultipleTimes().AndReturn(mac_learning) api.neutron.is_extension_supported(IsA(http.HttpRequest), 'port-security')\ - .AndReturn(port_security) + .MultipleTimes().AndReturn(port_security) extension_kwargs = {} if binding: extension_kwargs['binding__vnic_type'] = port.binding__vnic_type diff --git a/openstack_dashboard/dashboards/project/networks/ports/views.py b/openstack_dashboard/dashboards/project/networks/ports/views.py index 2ed4559853..603290f285 100644 --- a/openstack_dashboard/dashboards/project/networks/ports/views.py +++ b/openstack_dashboard/dashboards/project/networks/ports/views.py @@ -19,6 +19,7 @@ from horizon import exceptions from horizon import forms from horizon import tabs from horizon.utils import memoized +from horizon import workflows from openstack_dashboard import api @@ -28,10 +29,13 @@ from openstack_dashboard.dashboards.project.networks.ports \ import tables as project_tables from openstack_dashboard.dashboards.project.networks.ports \ import tabs as project_tabs +from openstack_dashboard.dashboards.project.networks.ports \ + import workflows as project_workflows + STATE_DICT = dict(project_tables.DISPLAY_CHOICES) STATUS_DICT = dict(project_tables.STATUS_DISPLAY_CHOICES) -VNIC_TYPES = dict(project_forms.VNIC_TYPES) +VNIC_TYPE_DICT = dict(api.neutron.VNIC_TYPES) class CreateView(forms.ModalFormView): @@ -89,7 +93,7 @@ class DetailView(tabs.TabbedTableView): port.status_label = STATUS_DICT.get(port.status, port.status) if port.get('binding__vnic_type'): - port.binding__vnic_type = VNIC_TYPES.get( + port.binding__vnic_type = VNIC_TYPE_DICT.get( port.binding__vnic_type, port.binding__vnic_type) except Exception: port = [] @@ -161,19 +165,9 @@ class DetailView(tabs.TabbedTableView): return reverse('horizon:project:networks:index') -class UpdateView(forms.ModalFormView): - form_class = project_forms.UpdatePort - form_id = "update_port_form" - template_name = 'project/networks/ports/update.html' - context_object_name = 'port' - submit_label = _("Save Changes") - submit_url = "horizon:project:networks:editport" - success_url = 'horizon:project:networks:detail' - page_title = _("Edit Port") - - def get_success_url(self): - return reverse(self.success_url, - args=(self.kwargs['network_id'],)) +class UpdateView(workflows.WorkflowView): + workflow_class = project_workflows.UpdatePort + failure_url = "horizon:project:networks:detail" @memoized.memoized_method def _get_object(self, *args, **kwargs): @@ -181,21 +175,11 @@ class UpdateView(forms.ModalFormView): try: return api.neutron.port_get(self.request, port_id) except Exception: - redirect = self.get_success_url() + redirect = reverse(self.failure_url, + args=(self.kwargs['network_id'],)) msg = _('Unable to retrieve port details') exceptions.handle(self.request, msg, redirect=redirect) - def get_context_data(self, **kwargs): - context = super(UpdateView, self).get_context_data(**kwargs) - port = self._get_object() - context['port_id'] = port['id'] - context['network_id'] = port['network_id'] - args = (self.kwargs['network_id'], self.kwargs['port_id'],) - context['submit_url'] = reverse(self.submit_url, args=args) - context['cancel_url'] = reverse(self.success_url, - args=(self.kwargs['network_id'],)) - return context - def get_initial(self): port = self._get_object() initial = {'port_id': port['id'], @@ -213,4 +197,5 @@ class UpdateView(forms.ModalFormView): pass if 'port_security_enabled' in port: initial['port_security_enabled'] = port['port_security_enabled'] + return initial diff --git a/openstack_dashboard/dashboards/project/networks/ports/workflows.py b/openstack_dashboard/dashboards/project/networks/ports/workflows.py new file mode 100644 index 0000000000..133939a8a2 --- /dev/null +++ b/openstack_dashboard/dashboards/project/networks/ports/workflows.py @@ -0,0 +1,139 @@ +# Copyright 2016 NEC Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +import logging + +from django.conf import settings +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext_lazy as _ + +from horizon import exceptions +from horizon import forms +from horizon import workflows + +from openstack_dashboard import api + + +LOG = logging.getLogger(__name__) + + +class UpdatePortInfoAction(workflows.Action): + name = forms.CharField(max_length=255, + label=_("Name"), + required=False) + admin_state = forms.BooleanField(label=_("Enable Admin State"), + required=False) + + def __init__(self, request, *args, **kwargs): + super(UpdatePortInfoAction, self).__init__(request, *args, **kwargs) + try: + if api.neutron.is_extension_supported(request, 'binding'): + neutron_settings = getattr(settings, + 'OPENSTACK_NEUTRON_NETWORK', {}) + supported_vnic_types = neutron_settings.get( + 'supported_vnic_types', ['*']) + if supported_vnic_types: + if supported_vnic_types == ['*']: + vnic_type_choices = api.neutron.VNIC_TYPES + else: + vnic_type_choices = [ + vnic_type for vnic_type in api.neutron.VNIC_TYPES + if vnic_type[0] in supported_vnic_types + ] + self.fields['binding__vnic_type'] = forms.ChoiceField( + choices=vnic_type_choices, + label=_("Binding: VNIC Type"), + help_text=_( + "The VNIC type that is bound to the neutron port"), + required=False) + except Exception: + msg = _("Unable to verify the VNIC types extension in Neutron") + exceptions.handle(self.request, msg) + + try: + if api.neutron.is_extension_supported(request, 'mac-learning'): + self.fields['mac_state'] = forms.BooleanField( + label=_("MAC Learning State"), initial=False, + required=False) + except Exception: + msg = _("Unable to retrieve MAC learning state") + exceptions.handle(self.request, msg) + + try: + if api.neutron.is_extension_supported(request, 'port-security'): + self.fields['port_security_enabled'] = forms.BooleanField( + label=_("Port Security"), + help_text=_("Enable anti-spoofing rules for the port"), + required=False + ) + except Exception: + msg = _("Unable to retrieve port security state") + exceptions.handle(self.request, msg) + + class Meta(object): + name = _("Info") + + +class UpdatePortInfo(workflows.Step): + action_class = UpdatePortInfoAction + depends_on = ("network_id", "port_id") + contributes = ["name", "admin_state", + "binding__vnic_type", "mac_state", "port_security_enabled"] + help_text = _("You can update the editable properties of your port here.") + + +class UpdatePort(workflows.Workflow): + slug = "update_port" + name = _("Edit Port") + finalize_button_name = _("Update") + success_message = _('Port %s was successfully updated.') + failure_message = _('Failed to update port "%s".') + default_steps = (UpdatePortInfo,) + + def get_success_url(self): + return reverse("horizon:project:networks:detail", + args=(self.context['network_id'],)) + + def format_status_message(self, message): + name = self.context['name'] or self.context['port_id'] + return message % name + + def handle(self, request, data): + port_id = self.context['port_id'] + LOG.debug('params = %s', data) + params = self._construct_parameters(data) + try: + api.neutron.port_update(request, port_id, **params) + return True + except Exception as e: + LOG.info('Failed to update port %(port_id)s: %(exc)s', + {'port_id': port_id, 'exc': e}) + return False + + def _construct_parameters(self, data): + params = { + 'name': data['name'], + 'admin_state_up': data['admin_state'], + } + # If a field value is None, it means the field is not supported, + # If so, we skip sending such field. + if data['binding__vnic_type'] is not None: + params['binding__vnic_type'] = data['binding__vnic_type'] + if data['mac_state'] is not None: + params['mac_learning_enabled'] = data['mac_state'] + if data['port_security_enabled'] is not None: + params['port_security_enabled'] = data['port_security_enabled'] + + return params diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/ports/_update.html b/openstack_dashboard/dashboards/project/networks/templates/networks/ports/_update.html deleted file mode 100644 index e356d8f604..0000000000 --- a/openstack_dashboard/dashboards/project/networks/templates/networks/ports/_update.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends "horizon/common/_modal_form.html" %} -{% load i18n %} - -{% block modal-body-right %} -{% trans "You may update the editable properties of your port here." %}
-{% endblock %} diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/ports/update.html b/openstack_dashboard/dashboards/project/networks/templates/networks/ports/update.html deleted file mode 100644 index 22ae2bc03b..0000000000 --- a/openstack_dashboard/dashboards/project/networks/templates/networks/ports/update.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends 'base.html' %} -{% load i18n %} -{% block title %}{% trans "Update Port" %}{% endblock %} - -{% block main %} - {% include 'project/networks/ports/_update.html' %} -{% endblock %}