Refactor the current UpdatePort form to workflow version
This patch change UpdatePort form to workflow in order to be able to add extra tabs like the setting of security groups. Originally, this work is a part of the subsequent patch "Support security groups association per port", but the changes are big so it is divided into two patches. This patch focuses on refactoring the existing implementation from the form to the workflow. Change-Id: Id42b311242b66ee25e8870ed86e45b5464e19c01 Co-Authored-By: Akihiro Motoki <amotoki@gmail.com> Related-bug: #1637444
This commit is contained in:
parent
d66c96269d
commit
5aab8bf508
@ -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):
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -1,7 +0,0 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "You may update the editable properties of your port here." %}</p>
|
||||
{% endblock %}
|
@ -1,7 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Update Port" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'admin/networks/ports/_update.html' %}
|
||||
{% endblock %}
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -1,7 +0,0 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "You may update the editable properties of your port here." %}</p>
|
||||
{% endblock %}
|
@ -1,7 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Update Port" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/networks/ports/_update.html' %}
|
||||
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user