Converted Quantum to Datatables.
This is known to be broken with current quantum APIs, but it is a proper refactor of the previous tables using the new DataTables, modals, and exception handling. It makes future updates for API compatibility much easier. Change-Id: I9690db8553773f40d8aad88ffde90b26815bfed2
This commit is contained in:
parent
64b81acc0a
commit
fd9d583c47
@ -25,6 +25,7 @@ from django.contrib import messages
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from horizon import api
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
|
||||
|
||||
@ -36,44 +37,14 @@ class CreateNetwork(forms.SelfHandlingForm):
|
||||
|
||||
def handle(self, request, data):
|
||||
network_name = data['name']
|
||||
|
||||
try:
|
||||
LOG.info('Creating network %s ' % network_name)
|
||||
send_data = {'network': {'name': '%s' % network_name}}
|
||||
api.quantum_create_network(request, send_data)
|
||||
except Exception, e:
|
||||
if not hasattr(e, 'message'):
|
||||
e.message = str(e)
|
||||
messages.error(request,
|
||||
_('Unable to create network %(network)s: %(msg)s') %
|
||||
{"network": network_name, "msg": e.message})
|
||||
return shortcuts.redirect(request.build_absolute_uri())
|
||||
else:
|
||||
msg = _('Network %s has been created.') % network_name
|
||||
LOG.info(msg)
|
||||
messages.success(request, msg)
|
||||
return shortcuts.redirect('horizon:nova:networks:index')
|
||||
|
||||
|
||||
class DeleteNetwork(forms.SelfHandlingForm):
|
||||
network = forms.CharField(widget=forms.HiddenInput())
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
LOG.info('Deleting network %s ' % data['network'])
|
||||
api.quantum_delete_network(request, data['network'])
|
||||
except Exception, e:
|
||||
if not hasattr(e, 'message'):
|
||||
e.message = str(e)
|
||||
messages.error(request,
|
||||
_('Unable to delete network %(network)s: %(msg)s') %
|
||||
{"network": data['network'], "msg": e.message})
|
||||
else:
|
||||
msg = _('Network %s has been deleted.') % data['network']
|
||||
LOG.info(msg)
|
||||
messages.success(request, msg)
|
||||
|
||||
return shortcuts.redirect(request.build_absolute_uri())
|
||||
data = {'network': {'name': network_name}}
|
||||
api.quantum.quantum_create_network(request, data)
|
||||
messages.success(request,
|
||||
_('Network %s has been created.') % network_name)
|
||||
except:
|
||||
exceptions.handle(request, _("Unable to create network."))
|
||||
return shortcuts.redirect('horizon:nova:networks:index')
|
||||
|
||||
|
||||
class RenameNetwork(forms.SelfHandlingForm):
|
||||
@ -98,7 +69,7 @@ class RenameNetwork(forms.SelfHandlingForm):
|
||||
LOG.info(msg)
|
||||
messages.success(request, msg)
|
||||
|
||||
return shortcuts.redirect(request.build_absolute_uri())
|
||||
return shortcuts.redirect('horizon:nova:networks:index')
|
||||
|
||||
|
||||
class CreatePort(forms.SelfHandlingForm):
|
||||
@ -123,30 +94,8 @@ class CreatePort(forms.SelfHandlingForm):
|
||||
LOG.info(msg)
|
||||
messages.success(request, msg)
|
||||
|
||||
return shortcuts.redirect(request.build_absolute_uri())
|
||||
|
||||
|
||||
class DeletePort(forms.SelfHandlingForm):
|
||||
network = forms.CharField(widget=forms.HiddenInput())
|
||||
port = forms.CharField(widget=forms.HiddenInput())
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
LOG.info('Deleting %s ports on network %s' %
|
||||
(data['port'], data['network']))
|
||||
api.quantum_delete_port(request, data['network'], data['port'])
|
||||
except Exception, e:
|
||||
if not hasattr(e, 'message'):
|
||||
e.message = str(e)
|
||||
messages.error(request,
|
||||
_('Unable to delete port %(port)s: %(msg)s') %
|
||||
{"port": data['port'], "msg": e.message})
|
||||
else:
|
||||
msg = _('Port %(port)s deleted from network %(network)s.') % {
|
||||
"port": data['port'], "network": data['network']}
|
||||
LOG.info(msg)
|
||||
messages.success(request, msg)
|
||||
return shortcuts.redirect(request.build_absolute_uri())
|
||||
return shortcuts.redirect('horizon:nova:networks:detail',
|
||||
network_id=data['network'])
|
||||
|
||||
|
||||
class AttachPort(forms.SelfHandlingForm):
|
||||
@ -170,68 +119,13 @@ class AttachPort(forms.SelfHandlingForm):
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
LOG.info('Attaching %s port to VIF %s' %
|
||||
(data['port'], data['vif_id']))
|
||||
body = {'attachment': {'id': '%s' % data['vif_id']}}
|
||||
api.quantum_attach_port(request,
|
||||
data['network'], data['port'], body)
|
||||
except Exception, e:
|
||||
if not hasattr(e, 'message'):
|
||||
e.message = str(e)
|
||||
messages.error(request,
|
||||
_('Unable to attach port %(port)s to VIF %(vif)s: %(msg)s') %
|
||||
{"port": data['port'],
|
||||
"vif": data['vif_id'],
|
||||
"msg": e.message})
|
||||
else:
|
||||
msg = _('Port %(port)s connected to VIF %(vif)s.') % \
|
||||
{"port": data['port'], "vif": data['vif_id']}
|
||||
LOG.info(msg)
|
||||
messages.success(request, msg)
|
||||
return shortcuts.redirect(request.build_absolute_uri())
|
||||
|
||||
|
||||
class DetachPort(forms.SelfHandlingForm):
|
||||
network = forms.CharField(widget=forms.HiddenInput())
|
||||
port = forms.CharField(widget=forms.HiddenInput())
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
LOG.info('Detaching port %s' % data['port'])
|
||||
api.quantum_detach_port(request, data['network'], data['port'])
|
||||
except Exception, e:
|
||||
if not hasattr(e, 'message'):
|
||||
e.message = str(e)
|
||||
messages.error(request,
|
||||
_('Unable to detach port %(port)s: %(message)s') %
|
||||
{"port": data['port'], "message": e.message})
|
||||
else:
|
||||
msg = _('Port %s detached.') % (data['port'])
|
||||
LOG.info(msg)
|
||||
messages.success(request, msg)
|
||||
return shortcuts.redirect(request.build_absolute_uri())
|
||||
|
||||
|
||||
class TogglePort(forms.SelfHandlingForm):
|
||||
network = forms.CharField(widget=forms.HiddenInput())
|
||||
port = forms.CharField(widget=forms.HiddenInput())
|
||||
state = forms.CharField(widget=forms.HiddenInput())
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
LOG.info('Toggling port state to %s' % data['state'])
|
||||
body = {'port': {'state': '%s' % data['state']}}
|
||||
api.quantum_set_port_state(request,
|
||||
data['network'], data['port'], body)
|
||||
except Exception, e:
|
||||
if not hasattr(e, 'message'):
|
||||
e.message = str(e)
|
||||
messages.error(request,
|
||||
_('Unable to set port state to %(state)s: %(message)s') %
|
||||
{"state": data['state'], "message": e.message})
|
||||
else:
|
||||
msg = _('Port %(port)s state set to %(state)s.') % {
|
||||
"port": data['port'], "state": data['state']}
|
||||
LOG.info(msg)
|
||||
messages.success(request, msg)
|
||||
return shortcuts.redirect(request.build_absolute_uri())
|
||||
data['network'],
|
||||
data['port'],
|
||||
body)
|
||||
messages.success(request, _("Port attached."))
|
||||
except:
|
||||
exceptions.handle(request, _('Unable to attach port.'))
|
||||
return shortcuts.redirect("horizon:nova:networks:detail",
|
||||
data['network'])
|
||||
|
118
horizon/horizon/dashboards/nova/networks/tables.py
Normal file
118
horizon/horizon/dashboards/nova/networks/tables.py
Normal file
@ -0,0 +1,118 @@
|
||||
import logging
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import api
|
||||
from horizon import tables
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RenameNetworkLink(tables.LinkAction):
|
||||
name = "rename_network"
|
||||
verbose_name = _("Rename Network")
|
||||
url = "horizon:nova:networks:rename"
|
||||
attrs = {"class": "ajax-modal"}
|
||||
|
||||
|
||||
class CreateNetworkLink(tables.LinkAction):
|
||||
name = "create_network"
|
||||
verbose_name = _("Create New Network")
|
||||
url = "horizon:nova:networks:create"
|
||||
attrs = {"class": "ajax-modal btn small"}
|
||||
|
||||
|
||||
class DeleteNetworkAction(tables.DeleteAction):
|
||||
data_type_singular = _("Network")
|
||||
data_type_plural = _("Networks")
|
||||
|
||||
def delete(self, request, obj_id):
|
||||
api.quantum_delete_network(request, obj_id)
|
||||
|
||||
|
||||
class NetworksTable(tables.DataTable):
|
||||
id = tables.Column('id', verbose_name=_('Network Id'),
|
||||
link="horizon:nova:networks:detail")
|
||||
name = tables.Column('name', verbose_name=_('Name'))
|
||||
used = tables.Column('used', verbose_name=_('Used'))
|
||||
available = tables.Column('available', verbose_name=_('Available'))
|
||||
total = tables.Column('total', verbose_name=_('Total'))
|
||||
#tenant = tables.Column('tenant', verbose_name=_('Tenant'))
|
||||
|
||||
def get_object_id(self, datum):
|
||||
return datum['id']
|
||||
|
||||
def get_object_display(self, obj):
|
||||
return obj['name']
|
||||
|
||||
class Meta:
|
||||
name = "networks"
|
||||
verbose_name = _("Networks")
|
||||
row_actions = (DeleteNetworkAction, RenameNetworkLink,)
|
||||
table_actions = (CreateNetworkLink, DeleteNetworkAction,)
|
||||
|
||||
|
||||
class CreatePortLink(tables.LinkAction):
|
||||
name = "create_port"
|
||||
verbose_name = _("Create Ports")
|
||||
url = "horizon:nova:networks:port_create"
|
||||
attrs = {"class": "ajax-modal btn small"}
|
||||
|
||||
def get_link_url(self, datum=None):
|
||||
network_id = self.table.kwargs['network_id']
|
||||
return reverse(self.url, args=(network_id,))
|
||||
|
||||
|
||||
class DeletePortAction(tables.DeleteAction):
|
||||
data_type_singular = _("Port")
|
||||
data_type_plural = _("Ports")
|
||||
|
||||
def delete(self, request, obj_id):
|
||||
api.quantum_delete_port(request,
|
||||
self.table.kwargs['network_id'],
|
||||
obj_id)
|
||||
|
||||
|
||||
class DetachPortAction(tables.BatchAction):
|
||||
name = "detach_port"
|
||||
action_present = _("Detach")
|
||||
action_past = _("Detached")
|
||||
data_type_singular = _("Port")
|
||||
data_type_plural = _("Ports")
|
||||
|
||||
def action(self, request, datum_id):
|
||||
body = {'port': {'state': 'DOWN'}}
|
||||
api.quantum_set_port_state(request,
|
||||
self.table.kwargs['network_id'],
|
||||
datum_id, body)
|
||||
|
||||
|
||||
class AttachPortAction(tables.LinkAction):
|
||||
name = "attach_port"
|
||||
verbose_name = _("Attach Port")
|
||||
url = "horizon:nova:networks:port_attach"
|
||||
attrs = {"class": "ajax-modal"}
|
||||
|
||||
def get_link_url(self, datum=None):
|
||||
network_id = self.table.kwargs['network_id']
|
||||
return reverse(self.url, args=(network_id, datum['id']))
|
||||
|
||||
|
||||
class NetworkDetailsTable(tables.DataTable):
|
||||
id = tables.Column('id', verbose_name=_('Port Id'))
|
||||
state = tables.Column('state', verbose_name=_('State'))
|
||||
attachment = tables.Column('attachment', verbose_name=_('Attachment'))
|
||||
|
||||
def get_object_id(self, datum):
|
||||
return datum['id']
|
||||
|
||||
def get_object_display(self, obj):
|
||||
return obj['id']
|
||||
|
||||
class Meta:
|
||||
name = "network_details"
|
||||
verbose_name = _("Network Port Details")
|
||||
row_actions = (DeletePortAction, AttachPortAction, DetachPortAction)
|
||||
table_actions = (CreatePortLink, DeletePortAction,)
|
@ -22,7 +22,6 @@ from django import http
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
from mox import IgnoreArg, IsA
|
||||
import quantum.client
|
||||
|
||||
from horizon import api
|
||||
from horizon import test
|
||||
@ -69,8 +68,7 @@ class NetworkViewTests(test.BaseViewTests):
|
||||
res = self.client.get(reverse('horizon:nova:networks:index'))
|
||||
|
||||
self.assertTemplateUsed(res, 'nova/networks/index.html')
|
||||
self.assertIn('networks', res.context)
|
||||
networks = res.context['networks']
|
||||
networks = res.context['table'].data
|
||||
|
||||
self.assertEqual(len(networks), 1)
|
||||
self.assertEqual(networks[0]['name'], 'test_network')
|
||||
@ -80,8 +78,9 @@ class NetworkViewTests(test.BaseViewTests):
|
||||
self.assertEqual(networks[0]['available'], 0)
|
||||
|
||||
def test_network_create(self):
|
||||
self.mox.StubOutWithMock(api, "quantum_create_network")
|
||||
api.quantum_create_network(IsA(http.HttpRequest), dict).AndReturn(True)
|
||||
self.mox.StubOutWithMock(api.quantum, "quantum_create_network")
|
||||
api.quantum.quantum_create_network(IsA(http.HttpRequest),
|
||||
IsA(dict)).AndReturn(True)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@ -116,11 +115,9 @@ class NetworkViewTests(test.BaseViewTests):
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
formData = {'network': 'n1',
|
||||
'method': 'DeleteNetwork'}
|
||||
formData = {'action': 'networks__delete__n1'}
|
||||
|
||||
res = self.client.post(reverse('horizon:nova:networks:index'),
|
||||
formData)
|
||||
self.client.post(reverse('horizon:nova:networks:index'), formData)
|
||||
|
||||
def test_network_rename(self):
|
||||
self.mox.StubOutWithMock(api, 'quantum_network_details')
|
||||
@ -177,13 +174,12 @@ class NetworkViewTests(test.BaseViewTests):
|
||||
self.assertEqual(network['name'], 'test_network')
|
||||
self.assertEqual(network['id'], 'n1')
|
||||
|
||||
|
||||
class PortViewTests(test.BaseViewTests):
|
||||
def setUp(self):
|
||||
super(PortViewTests, self).setUp()
|
||||
|
||||
def test_port_create(self):
|
||||
self.mox.StubOutWithMock(api, "quantum_network_details")
|
||||
self.mox.StubOutWithMock(api, "quantum_create_port")
|
||||
network_details = {'network': {'id': 'n1'}}
|
||||
api.quantum_network_details(IsA(http.HttpRequest),
|
||||
'n1').AndReturn(network_details)
|
||||
api.quantum_create_port(IsA(http.HttpRequest), 'n1').AndReturn(True)
|
||||
|
||||
formData = {'ports_num': 1,
|
||||
@ -204,28 +200,49 @@ class PortViewTests(test.BaseViewTests):
|
||||
args=["n1"]))
|
||||
|
||||
def test_port_delete(self):
|
||||
self.mox.StubOutWithMock(api, 'quantum_network_details')
|
||||
self.mox.StubOutWithMock(api, 'quantum_list_ports')
|
||||
self.mox.StubOutWithMock(api, 'quantum_port_attachment')
|
||||
self.mox.StubOutWithMock(api, 'quantum_port_details')
|
||||
self.mox.StubOutWithMock(api, 'get_vif_ids')
|
||||
self.mox.StubOutWithMock(api, "quantum_delete_port")
|
||||
network_details = {'network': {'id': 'n1', 'name': 'network1'}}
|
||||
api.quantum_network_details(IsA(http.HttpRequest),
|
||||
'n1').AndReturn(network_details)
|
||||
|
||||
api.quantum_list_ports(IsA(http.HttpRequest),
|
||||
'n1').AndReturn(self.ports)
|
||||
|
||||
api.quantum_port_attachment(IsA(http.HttpRequest),
|
||||
'n1', 'p1').AndReturn(self.port_attachment)
|
||||
|
||||
api.quantum_port_details(IsA(http.HttpRequest),
|
||||
'n1', 'p1').AndReturn(self.port_details)
|
||||
|
||||
api.get_vif_ids(IsA(http.HttpRequest)).AndReturn(self.vifs)
|
||||
|
||||
api.quantum_delete_port(IsA(http.HttpRequest),
|
||||
'n1', 'p1').AndReturn(True)
|
||||
|
||||
formData = {'port': 'p1',
|
||||
'network': 'n1',
|
||||
'method': 'DeletePort'}
|
||||
formData = {'action': 'network_details__delete__p1'}
|
||||
|
||||
self.mox.StubOutWithMock(messages, 'success')
|
||||
messages.success(IgnoreArg(), IsA(basestring))
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(reverse('horizon:nova:networks:detail',
|
||||
args=["n1"]),
|
||||
formData)
|
||||
detail_url = reverse('horizon:nova:networks:detail', args=["n1"])
|
||||
self.client.post(detail_url, formData)
|
||||
|
||||
def test_port_attach(self):
|
||||
self.mox.StubOutWithMock(api, "quantum_network_details")
|
||||
self.mox.StubOutWithMock(api, "quantum_attach_port")
|
||||
api.quantum_attach_port(IsA(http.HttpRequest),
|
||||
'n1', 'p1', dict).AndReturn(True)
|
||||
self.mox.StubOutWithMock(api, "get_vif_ids")
|
||||
network_details = {'network': {'id': 'n1'}}
|
||||
api.quantum_network_details(IsA(http.HttpRequest),
|
||||
'n1').AndReturn(network_details)
|
||||
api.quantum_attach_port(IsA(http.HttpRequest),
|
||||
'n1', 'p1', IsA(dict)).AndReturn(True)
|
||||
api.get_vif_ids(IsA(http.HttpRequest)).AndReturn([{
|
||||
'id': 'v1',
|
||||
'instance_name': 'instance1',
|
||||
@ -247,19 +264,40 @@ class PortViewTests(test.BaseViewTests):
|
||||
args=["n1"]))
|
||||
|
||||
def test_port_detach(self):
|
||||
self.mox.StubOutWithMock(api, "quantum_detach_port")
|
||||
api.quantum_detach_port(IsA(http.HttpRequest),
|
||||
'n1', 'p1').AndReturn(True)
|
||||
self.mox.StubOutWithMock(api, 'quantum_network_details')
|
||||
self.mox.StubOutWithMock(api, 'quantum_list_ports')
|
||||
self.mox.StubOutWithMock(api, 'quantum_port_attachment')
|
||||
self.mox.StubOutWithMock(api, 'quantum_port_details')
|
||||
self.mox.StubOutWithMock(api, 'get_vif_ids')
|
||||
self.mox.StubOutWithMock(api, "quantum_set_port_state")
|
||||
network_details = {'network': {'id': 'n1', 'name': 'network1'}}
|
||||
api.quantum_network_details(IsA(http.HttpRequest),
|
||||
'n1').AndReturn(network_details)
|
||||
|
||||
formData = {'port': 'p1',
|
||||
'network': 'n1',
|
||||
'method': 'DetachPort'}
|
||||
api.quantum_list_ports(IsA(http.HttpRequest),
|
||||
'n1').AndReturn(self.ports)
|
||||
|
||||
api.quantum_port_attachment(IsA(http.HttpRequest),
|
||||
'n1', 'p1').AndReturn(self.port_attachment)
|
||||
|
||||
api.quantum_port_details(IsA(http.HttpRequest),
|
||||
'n1', 'p1').AndReturn(self.port_details)
|
||||
|
||||
api.get_vif_ids(IsA(http.HttpRequest)).AndReturn(self.vifs)
|
||||
|
||||
api.quantum_set_port_state(IsA(http.HttpRequest),
|
||||
'n1',
|
||||
'p1',
|
||||
{'port': {'state': 'DOWN'}}).AndReturn(True)
|
||||
|
||||
formData = {'action': "network_details__detach_port__p1"}
|
||||
|
||||
self.mox.StubOutWithMock(messages, 'success')
|
||||
messages.success(IgnoreArg(), IsA(basestring))
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(reverse('horizon:nova:networks:detail',
|
||||
args=["n1"]),
|
||||
formData)
|
||||
detail_url = reverse('horizon:nova:networks:detail', args=["n1"])
|
||||
res = self.client.post(detail_url, formData)
|
||||
|
||||
self.assertRedirectsNoFollow(res, detail_url)
|
||||
|
@ -20,12 +20,17 @@
|
||||
|
||||
from django.conf.urls.defaults import patterns, url
|
||||
|
||||
from .views import (IndexView, CreateView, RenameView,
|
||||
DetailView, CreatePortView, AttachPortView)
|
||||
|
||||
urlpatterns = patterns('horizon.dashboards.nova.networks.views',
|
||||
url(r'^$', 'index', name='index'),
|
||||
url(r'^create/$', 'create', name='create'),
|
||||
url(r'^(?P<network_id>[^/]+)/detail/$', 'detail', name='detail'),
|
||||
url(r'^(?P<network_id>[^/]+)/rename/$', 'rename', name='rename'),
|
||||
url(r'^(?P<network_id>[^/]+)/ports/create/$', 'port_create',
|
||||
url(r'^$', IndexView.as_view(), name='index'),
|
||||
url(r'^create/$', CreateView.as_view(), name='create'),
|
||||
url(r'^(?P<network_id>[^/]+)/detail/$', DetailView.as_view(),
|
||||
name='detail'),
|
||||
url(r'^(?P<network_id>[^/]+)/rename/$', RenameView.as_view(),
|
||||
name='rename'),
|
||||
url(r'^(?P<network_id>[^/]+)/ports/create/$', CreatePortView.as_view(),
|
||||
name='port_create'),
|
||||
url(r'^(?P<network_id>[^/]+)/ports/(?P<port_id>[^/]+)/attach/$',
|
||||
'port_attach', name='port_attach'))
|
||||
AttachPortView.as_view(), name='port_attach'))
|
||||
|
@ -23,115 +23,98 @@ Views for managing Quantum networks.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import warnings
|
||||
|
||||
from django import shortcuts
|
||||
from django import template
|
||||
from django import http
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from horizon import api
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import tables
|
||||
from horizon.dashboards.nova.networks.forms import (CreateNetwork,
|
||||
DeleteNetwork, RenameNetwork, AttachPort, CreatePort, DeletePort,
|
||||
DetachPort, TogglePort)
|
||||
RenameNetwork, AttachPort, CreatePort)
|
||||
from .tables import NetworksTable, NetworkDetailsTable
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def index(request):
|
||||
tenant_id = request.user.tenant_id
|
||||
delete_form, delete_handled = DeleteNetwork.maybe_handle(request)
|
||||
class IndexView(tables.DataTableView):
|
||||
table_class = NetworksTable
|
||||
template_name = 'nova/networks/index.html'
|
||||
|
||||
networks = []
|
||||
instances = []
|
||||
def get_data(self):
|
||||
tenant_id = self.request.user.tenant_id
|
||||
networks = []
|
||||
|
||||
try:
|
||||
networks_list = api.quantum_list_networks(request)
|
||||
details = []
|
||||
for network in networks_list['networks']:
|
||||
net_stats = _calc_network_stats(request, network['id'])
|
||||
# Get network details like name and id
|
||||
details = api.quantum_network_details(request, network['id'])
|
||||
networks.append({
|
||||
'name': details['network']['name'],
|
||||
'id': network['id'],
|
||||
'total': net_stats['total'],
|
||||
'available': net_stats['available'],
|
||||
'used': net_stats['used'],
|
||||
'tenant': tenant_id})
|
||||
|
||||
except Exception, e:
|
||||
LOG.exception("Unable to get network list.")
|
||||
if not hasattr(e, 'message'):
|
||||
e.message = str(e)
|
||||
messages.error(request,
|
||||
_('Unable to get network list: %s') % e.message)
|
||||
|
||||
return shortcuts.render(request,
|
||||
'nova/networks/index.html', {
|
||||
'networks': networks,
|
||||
'delete_form': delete_form})
|
||||
try:
|
||||
networks_list = api.quantum_list_networks(self.request)
|
||||
details = []
|
||||
for network in networks_list['networks']:
|
||||
net_stats = _calc_network_stats(self.request, network['id'])
|
||||
# Get network details like name and id
|
||||
details = api.quantum_network_details(self.request,
|
||||
network['id'])
|
||||
networks.append({
|
||||
'name': details['network']['name'],
|
||||
'id': network['id'],
|
||||
'total': net_stats['total'],
|
||||
'available': net_stats['available'],
|
||||
'used': net_stats['used'],
|
||||
'tenant': tenant_id})
|
||||
except Exception, e:
|
||||
LOG.exception("Unable to get network list.")
|
||||
if not hasattr(e, 'message'):
|
||||
e.message = str(e)
|
||||
messages.error(self.request,
|
||||
_('Unable to get network list: %s') % e.message)
|
||||
return networks
|
||||
|
||||
|
||||
def create(request):
|
||||
network_form, handled = CreateNetwork.maybe_handle(request)
|
||||
if handled:
|
||||
return shortcuts.redirect('horizon:nova:networks:index')
|
||||
|
||||
return shortcuts.render(request,
|
||||
'nova/networks/create.html',
|
||||
{'network_form': network_form})
|
||||
class CreateView(forms.ModalFormView):
|
||||
form_class = CreateNetwork
|
||||
template_name = 'nova/networks/create.html'
|
||||
|
||||
|
||||
def detail(request, network_id):
|
||||
tenant_id = request.user.tenant_id
|
||||
delete_port_form, delete_handled = DeletePort.maybe_handle(request,
|
||||
initial={"network": network_id})
|
||||
detach_port_form, detach_handled = DetachPort.maybe_handle(request,
|
||||
initial={"network": network_id})
|
||||
toggle_port_form, port_toggle_handled = TogglePort.maybe_handle(request,
|
||||
initial={"network": network_id})
|
||||
class RenameView(forms.ModalFormView):
|
||||
form_class = RenameNetwork
|
||||
template_name = 'nova/networks/rename.html'
|
||||
context_object_name = 'network'
|
||||
|
||||
network = {}
|
||||
network['id'] = network_id
|
||||
def get_object(self, *args, **kwargs):
|
||||
network_id = kwargs['network_id']
|
||||
try:
|
||||
return api.quantum_network_details(self.request,
|
||||
network_id)['network']
|
||||
except:
|
||||
redirect = reverse("horizon:nova:networks:detail",
|
||||
args=(network_id,))
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve network information.'),
|
||||
redirect=redirect)
|
||||
|
||||
try:
|
||||
network_details = api.quantum_network_details(request, network_id)
|
||||
network['name'] = network_details['network']['name']
|
||||
network['ports'] = _get_port_states(request, network_id)
|
||||
except Exception, e:
|
||||
LOG.exception("Unable to get network details.")
|
||||
if not hasattr(e, 'message'):
|
||||
e.message = str(e)
|
||||
messages.error(request,
|
||||
_('Unable to get network details: %s') % e.message)
|
||||
return shortcuts.redirect("horizon:nova:networks:index")
|
||||
|
||||
return shortcuts.render(request,
|
||||
'nova/networks/detail.html',
|
||||
{'network': network,
|
||||
'tenant': tenant_id,
|
||||
'delete_port_form': delete_port_form,
|
||||
'detach_port_form': detach_port_form,
|
||||
'toggle_port_form': toggle_port_form})
|
||||
def get_initial(self):
|
||||
return {'network': self.object['id']}
|
||||
|
||||
|
||||
def rename(request, network_id):
|
||||
network_details = api.quantum_network_details(request, network_id)
|
||||
network = network_details['network']
|
||||
class DetailView(tables.DataTableView):
|
||||
table_class = NetworkDetailsTable
|
||||
template_name = 'nova/networks/detail.html'
|
||||
|
||||
rename_form, handled = RenameNetwork.maybe_handle(request, initial={
|
||||
'network': network['id'],
|
||||
'new_name': network['name']})
|
||||
def get_data(self):
|
||||
network_id = self.kwargs['network_id']
|
||||
network_details = api.quantum_network_details(self.request, network_id)
|
||||
self.network = {'id': network_id,
|
||||
'name': network_details['network']['name'],
|
||||
'ports': _get_port_states(self.request, network_id)}
|
||||
return self.network['ports']
|
||||
|
||||
if handled:
|
||||
return shortcuts.redirect('horizon:nova:networks:index')
|
||||
|
||||
return shortcuts.render(request,
|
||||
'nova/networks/rename.html', {
|
||||
'network': network,
|
||||
'rename_form': rename_form})
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
context['network'] = self.network
|
||||
return context
|
||||
|
||||
|
||||
def _get_port_states(request, network_id):
|
||||
@ -187,31 +170,43 @@ def _calc_network_stats(request, network_id):
|
||||
return {'total': total, 'used': used, 'available': available}
|
||||
|
||||
|
||||
def port_create(request, network_id):
|
||||
create_form, handled = CreatePort.maybe_handle(request, initial={
|
||||
"network": network_id})
|
||||
class CreatePortView(forms.ModalFormView):
|
||||
form_class = CreatePort
|
||||
template_name = 'nova/networks/ports/create.html'
|
||||
context_object_name = 'port'
|
||||
|
||||
if handled:
|
||||
return shortcuts.redirect('horizon:nova:networks:detail',
|
||||
network_id=network_id)
|
||||
def get_object(self, *args, **kwargs):
|
||||
network_id = kwargs['network_id']
|
||||
try:
|
||||
return api.quantum_network_details(self.request,
|
||||
network_id)['network']
|
||||
except:
|
||||
redirect = reverse("horizon:nova:networks:detail",
|
||||
args=(network_id,))
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve network information.'),
|
||||
redirect=redirect)
|
||||
|
||||
return shortcuts.render(request,
|
||||
'nova/ports/create.html', {
|
||||
'network_id': network_id,
|
||||
'create_form': create_form})
|
||||
def get_initial(self):
|
||||
return {'network': self.object['id']}
|
||||
|
||||
|
||||
def port_attach(request, network_id, port_id):
|
||||
attach_form, handled = AttachPort.maybe_handle(request, initial={
|
||||
"network": network_id,
|
||||
"port": port_id})
|
||||
class AttachPortView(forms.ModalFormView):
|
||||
form_class = AttachPort
|
||||
template_name = 'nova/networks/ports/attach.html'
|
||||
context_object_name = 'network'
|
||||
|
||||
if handled:
|
||||
return shortcuts.redirect('horizon:nova:networks:detail',
|
||||
network_id=network_id)
|
||||
def get_object(self, *args, **kwargs):
|
||||
network_id = kwargs['network_id']
|
||||
try:
|
||||
return api.quantum_network_details(self.request,
|
||||
network_id)['network']
|
||||
except:
|
||||
redirect = reverse("horizon:nova:networks:detail",
|
||||
args=(network_id,))
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to attach port.'),
|
||||
redirect=redirect)
|
||||
|
||||
return shortcuts.render(request,
|
||||
'nova/ports/attach.html', {
|
||||
'network': network_id,
|
||||
'port': port_id,
|
||||
'attach_form': attach_form})
|
||||
def get_initial(self):
|
||||
return {'network': self.object['id']}
|
||||
|
@ -1,9 +0,0 @@
|
||||
{% load i18n %}
|
||||
<form id="form_delete_{{ network.id }}" class="form-delete" method="post">
|
||||
{% csrf_token %}
|
||||
{% for hidden in form.hidden_fields %}
|
||||
{{ hidden }}
|
||||
{% endfor %}
|
||||
<input name="network" type="hidden" value="{{ network.id }}" />
|
||||
<input id="delete_{{ network.id }}" class="btn small danger delete" title="Network: {{ network.name }}" type="submit" value="{% trans "Delete" %}" />
|
||||
</form>
|
@ -1,10 +0,0 @@
|
||||
{% load i18n %}
|
||||
<form id="form_delete_{{ network.id }}" class="form-delete" method="post">
|
||||
{% csrf_token %}
|
||||
{% for hidden in form.hidden_fields %}
|
||||
{{ hidden }}
|
||||
{% endfor %}
|
||||
<input name="network" type="hidden" value="{{ network.id }}" />
|
||||
<input name="port" type="hidden" value="{{ port.id }}" />
|
||||
<input title="Delete this port" id="delete_{{ port.id }}" class="btn small danger delete" type="submit" value="{% trans "Delete" %}" />
|
||||
</form>
|
@ -1,10 +0,0 @@
|
||||
{% load i18n %}
|
||||
<form id="detach_port_form" class="form-detach" method="post">
|
||||
{% csrf_token %}
|
||||
{% for hidden in form.hidden_fields %}
|
||||
{{ hidden }}
|
||||
{% endfor %}
|
||||
<input name="network" type="hidden" value="{{ network.id }}" />
|
||||
<input name="port" type="hidden" value="{{ port.id }}" />
|
||||
<input title="Detach port from instance" id="detach_{{ port.id }}" class="btn pull-right small detach" type="submit" value="{% trans "Detach" %}" />
|
||||
</form>
|
@ -1,49 +0,0 @@
|
||||
{% load i18n %}
|
||||
<table id='Ports' class="zebra-striped">
|
||||
<tr id='headings'>
|
||||
<th>{% trans "ID" %}</th>
|
||||
<th>{% trans "State" %}</th>
|
||||
<th>{% trans "Attachment" %}</th>
|
||||
<th>{% trans "Actions" %}</th>
|
||||
<th>{% trans "Extensions" %}</th>
|
||||
</tr>
|
||||
<tbody class='main'>
|
||||
{% for port in network.ports %}
|
||||
<tr class="{% cycle 'odd' 'even' %}">
|
||||
<td>{{ port.id }}</td>
|
||||
<td class="{{port.state}}">{{port.state}}</td>
|
||||
<td>
|
||||
{% if port.attachment %}
|
||||
<table class="attachmend_details">
|
||||
<tr>
|
||||
<td>{% trans "Instance" %}</td>
|
||||
<td>{% trans "VIF Id" %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> {{port.instance}} </td>
|
||||
<td> {{port.attachment.id}} </td>
|
||||
</tr>
|
||||
</table>
|
||||
{% else %}
|
||||
--
|
||||
{% endif %}
|
||||
</td>
|
||||
<td id="actions">
|
||||
<ul>
|
||||
{% if port.attachment %}
|
||||
<li class="form">{% include "nova/networks/_detach_port.html" with form=detach_port_form %}</li>
|
||||
{% else %}
|
||||
<li><a class='btn small' href='{% url horizon:nova:networks:port_attach network.id port.id %}'>{% trans "Attach" %}</a></li>
|
||||
{% endif %}
|
||||
<li class="form">{% include "nova/networks/_toggle_port.html" with form=toggle_port_form %}</li>
|
||||
<li class="form">{% include "nova/networks/_delete_port.html" with form=delete_port_form %}</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td id="extensions">
|
||||
<ul>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
@ -1,28 +0,0 @@
|
||||
{% load i18n %}
|
||||
<table id='networks' class="zebra-striped">
|
||||
<tr id='headings'>
|
||||
<th>{% trans "ID" %}</th>
|
||||
<th>{% trans "Name" %}</th>
|
||||
<th>{% trans "Ports" %}</th>
|
||||
<th>{% trans "Available" %}</th>
|
||||
<th>{% trans "Used" %}</th>
|
||||
<th>{% trans "Action" %}</th>
|
||||
</tr>
|
||||
<tbody class='main'>
|
||||
{% for network in networks %}
|
||||
<tr class="{% cycle 'odd' 'even' %}" id="{{ network.id }}">
|
||||
<td><a href='{% url horizon:nova:networks:detail network.id %}'>{{ network.id }}</a></td>
|
||||
<td class="name">{{ network.name }}</td>
|
||||
<td>{{ network.total }}</td>
|
||||
<td>{{ network.available }}</td>
|
||||
<td>{{ network.used }}</td>
|
||||
<td id="actions" class="single">
|
||||
<ul>
|
||||
<li><a class='btn small' href='{% url horizon:nova:networks:rename network.id %}'>{% trans "Rename" %}</a></li>
|
||||
<li class="form">{% include "nova/networks/_delete.html" with form=delete_form %}</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
@ -1,16 +0,0 @@
|
||||
{% load i18n %}
|
||||
<form id="port_toggle_form" class="form-toggle" method="post">
|
||||
{% csrf_token %}
|
||||
{% for hidden in form.hidden_fields %}
|
||||
{{ hidden }}
|
||||
{% endfor %}
|
||||
<input name="network" type="hidden" value="{{ network.id }}" />
|
||||
<input name="port" type="hidden" value="{{ port.id }}" />
|
||||
{% if port.state == 'DOWN' %}
|
||||
<input name="state" type="hidden" value="ACTIVE" />
|
||||
<input title="Turn port UP" id="port_up_{{ port.id }}" class="btn small port_up" type="submit" value="{% trans "Port UP" %}" />
|
||||
{% else %}
|
||||
<input name="state" type="hidden" value="DOWN" />
|
||||
<input title="Turn port DOWN" id="port_up_{{ port.id }}" class="btn small port_down" type="submit" value="{% trans "Port DOWN" %}" />
|
||||
{% endif %}
|
||||
</form>
|
@ -1,21 +1,11 @@
|
||||
{% extends 'nova/base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}Network Detail{% endblock %}
|
||||
{% block title %}{% trans "Network Detail" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% url horizon:nova:networks:detail network.id as refresh_link %}
|
||||
{# to make searchable false, just remove it from the include statement #}
|
||||
{% include "horizon/common/_page_header.html" with title=network.name refresh_link=refresh_link searchable="true" %}
|
||||
{% include "horizon/common/_page_header.html" with title=network.name %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block dash_main %}
|
||||
{% if network.ports %}
|
||||
{% include 'nova/networks/_detail.html' %}
|
||||
<a id="network_create_link" class="btn small" href="{% url horizon:nova:networks:port_create network.id %}">{% trans "Create Ports" %}</a>
|
||||
{% else %}
|
||||
<div class="alert alert-block alert-info">
|
||||
<h2>{% trans "Info" %}</h2>
|
||||
<p>{% trans "There are currently no ports in this network." %} <a class='btn small' href="{% url horizon:nova:networks:port_create network.id %}">{% trans "Create Ports" %}</a></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{{ table.render }}
|
||||
{% endblock %}
|
||||
|
@ -9,17 +9,5 @@
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block dash_main %}
|
||||
{% if networks %}
|
||||
{% include 'nova/networks/_list.html' %}
|
||||
{% url horizon:nova:networks:create as dash_net_url %}
|
||||
<a id="network_create_link" class="btn small" href="{{ dash_net_url }}">{% trans "Create New Network" %}</a>
|
||||
{% else %}
|
||||
<div class="alert alert-block alert-info">
|
||||
<p><strong>{% trans "Info: " %}</strong>{% trans "There are currently no networks." %}</p>
|
||||
<div class="alert-actions">
|
||||
<a class="btn small primary" href='{% url horizon:nova:networks:create %}'>{% trans "Create A Network" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{{ table.render }}
|
||||
{% endblock %}
|
||||
|
@ -1,25 +0,0 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_id %}attach_port_form{% endblock %}
|
||||
{% block form_action %}{% url horizon:nova:networks:port_attach network port %}{% endblock %}
|
||||
|
||||
{% block modal-header %}Attach Port{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<p>{% blocktrans %}Select an interface from the list on the left to attach it to this port.{% endblocktrans %}</p>
|
||||
<p>{% blocktrans %}Only interfaces that are not connected to any existing port are shown.{% endblocktrans %}</p>
|
||||
<p>{% blocktrans %}If you want to reconnect a connected interface, please detach it first.{% endblocktrans %}</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<input type="submit" class='btn small primary create' value="{% trans "Attach Port" %}" />
|
||||
<a href="{% url horizon:nova:networks:detail network %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
@ -1,24 +0,0 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_id %}create_port_form{% endblock %}
|
||||
{% block form_action %}{% url horizon:nova:networks:port_create network_id %}{% endblock %}
|
||||
|
||||
{% block modal-header %}Create Port{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Networks provide layer 2 connectivity to your instances." %}</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<input type="submit" class='btn small primary create' value="{% trans "Create Port" %}" />
|
||||
<a href="{% url horizon:nova:networks:detail network_id %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
@ -1,12 +0,0 @@
|
||||
{% extends 'nova/base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}Attach Port{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{# to make searchable false, just remove it from the include statement #}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Attach Port") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block dash_main %}
|
||||
{% include 'nova/ports/_attach.html' with form=attach_form %}
|
||||
{% endblock %}
|
@ -1,13 +0,0 @@
|
||||
{% extends 'nova/base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}Create Port{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{# to make searchable false, just remove it from the include statement #}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Create Network") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block dash_main %}
|
||||
{% include 'nova/ports/_create.html' with form=create_form %}
|
||||
{% endblock %}
|
||||
|
Loading…
x
Reference in New Issue
Block a user