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 django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from horizon import api
|
from horizon import api
|
||||||
|
from horizon import exceptions
|
||||||
from horizon import forms
|
from horizon import forms
|
||||||
|
|
||||||
|
|
||||||
@ -36,46 +37,16 @@ class CreateNetwork(forms.SelfHandlingForm):
|
|||||||
|
|
||||||
def handle(self, request, data):
|
def handle(self, request, data):
|
||||||
network_name = data['name']
|
network_name = data['name']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
LOG.info('Creating network %s ' % network_name)
|
data = {'network': {'name': network_name}}
|
||||||
send_data = {'network': {'name': '%s' % network_name}}
|
api.quantum.quantum_create_network(request, data)
|
||||||
api.quantum_create_network(request, send_data)
|
messages.success(request,
|
||||||
except Exception, e:
|
_('Network %s has been created.') % network_name)
|
||||||
if not hasattr(e, 'message'):
|
except:
|
||||||
e.message = str(e)
|
exceptions.handle(request, _("Unable to create network."))
|
||||||
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')
|
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())
|
|
||||||
|
|
||||||
|
|
||||||
class RenameNetwork(forms.SelfHandlingForm):
|
class RenameNetwork(forms.SelfHandlingForm):
|
||||||
network = forms.CharField(widget=forms.HiddenInput())
|
network = forms.CharField(widget=forms.HiddenInput())
|
||||||
new_name = forms.CharField(required=True)
|
new_name = forms.CharField(required=True)
|
||||||
@ -98,7 +69,7 @@ class RenameNetwork(forms.SelfHandlingForm):
|
|||||||
LOG.info(msg)
|
LOG.info(msg)
|
||||||
messages.success(request, msg)
|
messages.success(request, msg)
|
||||||
|
|
||||||
return shortcuts.redirect(request.build_absolute_uri())
|
return shortcuts.redirect('horizon:nova:networks:index')
|
||||||
|
|
||||||
|
|
||||||
class CreatePort(forms.SelfHandlingForm):
|
class CreatePort(forms.SelfHandlingForm):
|
||||||
@ -123,30 +94,8 @@ class CreatePort(forms.SelfHandlingForm):
|
|||||||
LOG.info(msg)
|
LOG.info(msg)
|
||||||
messages.success(request, msg)
|
messages.success(request, msg)
|
||||||
|
|
||||||
return shortcuts.redirect(request.build_absolute_uri())
|
return shortcuts.redirect('horizon:nova:networks:detail',
|
||||||
|
network_id=data['network'])
|
||||||
|
|
||||||
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())
|
|
||||||
|
|
||||||
|
|
||||||
class AttachPort(forms.SelfHandlingForm):
|
class AttachPort(forms.SelfHandlingForm):
|
||||||
@ -170,68 +119,13 @@ class AttachPort(forms.SelfHandlingForm):
|
|||||||
|
|
||||||
def handle(self, request, data):
|
def handle(self, request, data):
|
||||||
try:
|
try:
|
||||||
LOG.info('Attaching %s port to VIF %s' %
|
|
||||||
(data['port'], data['vif_id']))
|
|
||||||
body = {'attachment': {'id': '%s' % data['vif_id']}}
|
body = {'attachment': {'id': '%s' % data['vif_id']}}
|
||||||
api.quantum_attach_port(request,
|
api.quantum_attach_port(request,
|
||||||
data['network'], data['port'], body)
|
data['network'],
|
||||||
except Exception, e:
|
data['port'],
|
||||||
if not hasattr(e, 'message'):
|
body)
|
||||||
e.message = str(e)
|
messages.success(request, _("Port attached."))
|
||||||
messages.error(request,
|
except:
|
||||||
_('Unable to attach port %(port)s to VIF %(vif)s: %(msg)s') %
|
exceptions.handle(request, _('Unable to attach port.'))
|
||||||
{"port": data['port'],
|
return shortcuts.redirect("horizon:nova:networks:detail",
|
||||||
"vif": data['vif_id'],
|
data['network'])
|
||||||
"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())
|
|
||||||
|
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.contrib import messages
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from mox import IgnoreArg, IsA
|
from mox import IgnoreArg, IsA
|
||||||
import quantum.client
|
|
||||||
|
|
||||||
from horizon import api
|
from horizon import api
|
||||||
from horizon import test
|
from horizon import test
|
||||||
@ -69,8 +68,7 @@ class NetworkViewTests(test.BaseViewTests):
|
|||||||
res = self.client.get(reverse('horizon:nova:networks:index'))
|
res = self.client.get(reverse('horizon:nova:networks:index'))
|
||||||
|
|
||||||
self.assertTemplateUsed(res, 'nova/networks/index.html')
|
self.assertTemplateUsed(res, 'nova/networks/index.html')
|
||||||
self.assertIn('networks', res.context)
|
networks = res.context['table'].data
|
||||||
networks = res.context['networks']
|
|
||||||
|
|
||||||
self.assertEqual(len(networks), 1)
|
self.assertEqual(len(networks), 1)
|
||||||
self.assertEqual(networks[0]['name'], 'test_network')
|
self.assertEqual(networks[0]['name'], 'test_network')
|
||||||
@ -80,8 +78,9 @@ class NetworkViewTests(test.BaseViewTests):
|
|||||||
self.assertEqual(networks[0]['available'], 0)
|
self.assertEqual(networks[0]['available'], 0)
|
||||||
|
|
||||||
def test_network_create(self):
|
def test_network_create(self):
|
||||||
self.mox.StubOutWithMock(api, "quantum_create_network")
|
self.mox.StubOutWithMock(api.quantum, "quantum_create_network")
|
||||||
api.quantum_create_network(IsA(http.HttpRequest), dict).AndReturn(True)
|
api.quantum.quantum_create_network(IsA(http.HttpRequest),
|
||||||
|
IsA(dict)).AndReturn(True)
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
@ -116,11 +115,9 @@ class NetworkViewTests(test.BaseViewTests):
|
|||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
formData = {'network': 'n1',
|
formData = {'action': 'networks__delete__n1'}
|
||||||
'method': 'DeleteNetwork'}
|
|
||||||
|
|
||||||
res = self.client.post(reverse('horizon:nova:networks:index'),
|
self.client.post(reverse('horizon:nova:networks:index'), formData)
|
||||||
formData)
|
|
||||||
|
|
||||||
def test_network_rename(self):
|
def test_network_rename(self):
|
||||||
self.mox.StubOutWithMock(api, 'quantum_network_details')
|
self.mox.StubOutWithMock(api, 'quantum_network_details')
|
||||||
@ -177,13 +174,12 @@ class NetworkViewTests(test.BaseViewTests):
|
|||||||
self.assertEqual(network['name'], 'test_network')
|
self.assertEqual(network['name'], 'test_network')
|
||||||
self.assertEqual(network['id'], 'n1')
|
self.assertEqual(network['id'], 'n1')
|
||||||
|
|
||||||
|
|
||||||
class PortViewTests(test.BaseViewTests):
|
|
||||||
def setUp(self):
|
|
||||||
super(PortViewTests, self).setUp()
|
|
||||||
|
|
||||||
def test_port_create(self):
|
def test_port_create(self):
|
||||||
|
self.mox.StubOutWithMock(api, "quantum_network_details")
|
||||||
self.mox.StubOutWithMock(api, "quantum_create_port")
|
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)
|
api.quantum_create_port(IsA(http.HttpRequest), 'n1').AndReturn(True)
|
||||||
|
|
||||||
formData = {'ports_num': 1,
|
formData = {'ports_num': 1,
|
||||||
@ -204,28 +200,49 @@ class PortViewTests(test.BaseViewTests):
|
|||||||
args=["n1"]))
|
args=["n1"]))
|
||||||
|
|
||||||
def test_port_delete(self):
|
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")
|
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),
|
api.quantum_delete_port(IsA(http.HttpRequest),
|
||||||
'n1', 'p1').AndReturn(True)
|
'n1', 'p1').AndReturn(True)
|
||||||
|
|
||||||
formData = {'port': 'p1',
|
formData = {'action': 'network_details__delete__p1'}
|
||||||
'network': 'n1',
|
|
||||||
'method': 'DeletePort'}
|
|
||||||
|
|
||||||
self.mox.StubOutWithMock(messages, 'success')
|
self.mox.StubOutWithMock(messages, 'success')
|
||||||
messages.success(IgnoreArg(), IsA(basestring))
|
messages.success(IgnoreArg(), IsA(basestring))
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
res = self.client.post(reverse('horizon:nova:networks:detail',
|
detail_url = reverse('horizon:nova:networks:detail', args=["n1"])
|
||||||
args=["n1"]),
|
self.client.post(detail_url, formData)
|
||||||
formData)
|
|
||||||
|
|
||||||
def test_port_attach(self):
|
def test_port_attach(self):
|
||||||
|
self.mox.StubOutWithMock(api, "quantum_network_details")
|
||||||
self.mox.StubOutWithMock(api, "quantum_attach_port")
|
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")
|
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([{
|
api.get_vif_ids(IsA(http.HttpRequest)).AndReturn([{
|
||||||
'id': 'v1',
|
'id': 'v1',
|
||||||
'instance_name': 'instance1',
|
'instance_name': 'instance1',
|
||||||
@ -247,19 +264,40 @@ class PortViewTests(test.BaseViewTests):
|
|||||||
args=["n1"]))
|
args=["n1"]))
|
||||||
|
|
||||||
def test_port_detach(self):
|
def test_port_detach(self):
|
||||||
self.mox.StubOutWithMock(api, "quantum_detach_port")
|
self.mox.StubOutWithMock(api, 'quantum_network_details')
|
||||||
api.quantum_detach_port(IsA(http.HttpRequest),
|
self.mox.StubOutWithMock(api, 'quantum_list_ports')
|
||||||
'n1', 'p1').AndReturn(True)
|
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',
|
api.quantum_list_ports(IsA(http.HttpRequest),
|
||||||
'network': 'n1',
|
'n1').AndReturn(self.ports)
|
||||||
'method': 'DetachPort'}
|
|
||||||
|
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')
|
self.mox.StubOutWithMock(messages, 'success')
|
||||||
messages.success(IgnoreArg(), IsA(basestring))
|
messages.success(IgnoreArg(), IsA(basestring))
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
res = self.client.post(reverse('horizon:nova:networks:detail',
|
detail_url = reverse('horizon:nova:networks:detail', args=["n1"])
|
||||||
args=["n1"]),
|
res = self.client.post(detail_url, formData)
|
||||||
formData)
|
|
||||||
|
self.assertRedirectsNoFollow(res, detail_url)
|
||||||
|
@ -20,12 +20,17 @@
|
|||||||
|
|
||||||
from django.conf.urls.defaults import patterns, url
|
from django.conf.urls.defaults import patterns, url
|
||||||
|
|
||||||
|
from .views import (IndexView, CreateView, RenameView,
|
||||||
|
DetailView, CreatePortView, AttachPortView)
|
||||||
|
|
||||||
urlpatterns = patterns('horizon.dashboards.nova.networks.views',
|
urlpatterns = patterns('horizon.dashboards.nova.networks.views',
|
||||||
url(r'^$', 'index', name='index'),
|
url(r'^$', IndexView.as_view(), name='index'),
|
||||||
url(r'^create/$', 'create', name='create'),
|
url(r'^create/$', CreateView.as_view(), name='create'),
|
||||||
url(r'^(?P<network_id>[^/]+)/detail/$', 'detail', name='detail'),
|
url(r'^(?P<network_id>[^/]+)/detail/$', DetailView.as_view(),
|
||||||
url(r'^(?P<network_id>[^/]+)/rename/$', 'rename', name='rename'),
|
name='detail'),
|
||||||
url(r'^(?P<network_id>[^/]+)/ports/create/$', 'port_create',
|
url(r'^(?P<network_id>[^/]+)/rename/$', RenameView.as_view(),
|
||||||
|
name='rename'),
|
||||||
|
url(r'^(?P<network_id>[^/]+)/ports/create/$', CreatePortView.as_view(),
|
||||||
name='port_create'),
|
name='port_create'),
|
||||||
url(r'^(?P<network_id>[^/]+)/ports/(?P<port_id>[^/]+)/attach/$',
|
url(r'^(?P<network_id>[^/]+)/ports/(?P<port_id>[^/]+)/attach/$',
|
||||||
'port_attach', name='port_attach'))
|
AttachPortView.as_view(), name='port_attach'))
|
||||||
|
@ -23,36 +23,40 @@ Views for managing Quantum networks.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import warnings
|
|
||||||
|
|
||||||
from django import shortcuts
|
from django import http
|
||||||
from django import template
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from horizon import api
|
from horizon import api
|
||||||
|
from horizon import exceptions
|
||||||
|
from horizon import forms
|
||||||
|
from horizon import tables
|
||||||
from horizon.dashboards.nova.networks.forms import (CreateNetwork,
|
from horizon.dashboards.nova.networks.forms import (CreateNetwork,
|
||||||
DeleteNetwork, RenameNetwork, AttachPort, CreatePort, DeletePort,
|
RenameNetwork, AttachPort, CreatePort)
|
||||||
DetachPort, TogglePort)
|
from .tables import NetworksTable, NetworkDetailsTable
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
class IndexView(tables.DataTableView):
|
||||||
tenant_id = request.user.tenant_id
|
table_class = NetworksTable
|
||||||
delete_form, delete_handled = DeleteNetwork.maybe_handle(request)
|
template_name = 'nova/networks/index.html'
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
tenant_id = self.request.user.tenant_id
|
||||||
networks = []
|
networks = []
|
||||||
instances = []
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
networks_list = api.quantum_list_networks(request)
|
networks_list = api.quantum_list_networks(self.request)
|
||||||
details = []
|
details = []
|
||||||
for network in networks_list['networks']:
|
for network in networks_list['networks']:
|
||||||
net_stats = _calc_network_stats(request, network['id'])
|
net_stats = _calc_network_stats(self.request, network['id'])
|
||||||
# Get network details like name and id
|
# Get network details like name and id
|
||||||
details = api.quantum_network_details(request, network['id'])
|
details = api.quantum_network_details(self.request,
|
||||||
|
network['id'])
|
||||||
networks.append({
|
networks.append({
|
||||||
'name': details['network']['name'],
|
'name': details['network']['name'],
|
||||||
'id': network['id'],
|
'id': network['id'],
|
||||||
@ -60,78 +64,57 @@ def index(request):
|
|||||||
'available': net_stats['available'],
|
'available': net_stats['available'],
|
||||||
'used': net_stats['used'],
|
'used': net_stats['used'],
|
||||||
'tenant': tenant_id})
|
'tenant': tenant_id})
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
LOG.exception("Unable to get network list.")
|
LOG.exception("Unable to get network list.")
|
||||||
if not hasattr(e, 'message'):
|
if not hasattr(e, 'message'):
|
||||||
e.message = str(e)
|
e.message = str(e)
|
||||||
messages.error(request,
|
messages.error(self.request,
|
||||||
_('Unable to get network list: %s') % e.message)
|
_('Unable to get network list: %s') % e.message)
|
||||||
|
return networks
|
||||||
return shortcuts.render(request,
|
|
||||||
'nova/networks/index.html', {
|
|
||||||
'networks': networks,
|
|
||||||
'delete_form': delete_form})
|
|
||||||
|
|
||||||
|
|
||||||
def create(request):
|
class CreateView(forms.ModalFormView):
|
||||||
network_form, handled = CreateNetwork.maybe_handle(request)
|
form_class = CreateNetwork
|
||||||
if handled:
|
template_name = 'nova/networks/create.html'
|
||||||
return shortcuts.redirect('horizon:nova:networks:index')
|
|
||||||
|
|
||||||
return shortcuts.render(request,
|
|
||||||
'nova/networks/create.html',
|
|
||||||
{'network_form': network_form})
|
|
||||||
|
|
||||||
|
|
||||||
def detail(request, network_id):
|
class RenameView(forms.ModalFormView):
|
||||||
tenant_id = request.user.tenant_id
|
form_class = RenameNetwork
|
||||||
delete_port_form, delete_handled = DeletePort.maybe_handle(request,
|
template_name = 'nova/networks/rename.html'
|
||||||
initial={"network": network_id})
|
context_object_name = 'network'
|
||||||
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})
|
|
||||||
|
|
||||||
network = {}
|
|
||||||
network['id'] = network_id
|
|
||||||
|
|
||||||
|
def get_object(self, *args, **kwargs):
|
||||||
|
network_id = kwargs['network_id']
|
||||||
try:
|
try:
|
||||||
network_details = api.quantum_network_details(request, network_id)
|
return api.quantum_network_details(self.request,
|
||||||
network['name'] = network_details['network']['name']
|
network_id)['network']
|
||||||
network['ports'] = _get_port_states(request, network_id)
|
except:
|
||||||
except Exception, e:
|
redirect = reverse("horizon:nova:networks:detail",
|
||||||
LOG.exception("Unable to get network details.")
|
args=(network_id,))
|
||||||
if not hasattr(e, 'message'):
|
exceptions.handle(self.request,
|
||||||
e.message = str(e)
|
_('Unable to retrieve network information.'),
|
||||||
messages.error(request,
|
redirect=redirect)
|
||||||
_('Unable to get network details: %s') % e.message)
|
|
||||||
return shortcuts.redirect("horizon:nova:networks:index")
|
|
||||||
|
|
||||||
return shortcuts.render(request,
|
def get_initial(self):
|
||||||
'nova/networks/detail.html',
|
return {'network': self.object['id']}
|
||||||
{'network': network,
|
|
||||||
'tenant': tenant_id,
|
|
||||||
'delete_port_form': delete_port_form,
|
|
||||||
'detach_port_form': detach_port_form,
|
|
||||||
'toggle_port_form': toggle_port_form})
|
|
||||||
|
|
||||||
|
|
||||||
def rename(request, network_id):
|
class DetailView(tables.DataTableView):
|
||||||
network_details = api.quantum_network_details(request, network_id)
|
table_class = NetworkDetailsTable
|
||||||
network = network_details['network']
|
template_name = 'nova/networks/detail.html'
|
||||||
|
|
||||||
rename_form, handled = RenameNetwork.maybe_handle(request, initial={
|
def get_data(self):
|
||||||
'network': network['id'],
|
network_id = self.kwargs['network_id']
|
||||||
'new_name': network['name']})
|
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:
|
def get_context_data(self, **kwargs):
|
||||||
return shortcuts.redirect('horizon:nova:networks:index')
|
context = super(DetailView, self).get_context_data(**kwargs)
|
||||||
|
context['network'] = self.network
|
||||||
return shortcuts.render(request,
|
return context
|
||||||
'nova/networks/rename.html', {
|
|
||||||
'network': network,
|
|
||||||
'rename_form': rename_form})
|
|
||||||
|
|
||||||
|
|
||||||
def _get_port_states(request, network_id):
|
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}
|
return {'total': total, 'used': used, 'available': available}
|
||||||
|
|
||||||
|
|
||||||
def port_create(request, network_id):
|
class CreatePortView(forms.ModalFormView):
|
||||||
create_form, handled = CreatePort.maybe_handle(request, initial={
|
form_class = CreatePort
|
||||||
"network": network_id})
|
template_name = 'nova/networks/ports/create.html'
|
||||||
|
context_object_name = 'port'
|
||||||
|
|
||||||
if handled:
|
def get_object(self, *args, **kwargs):
|
||||||
return shortcuts.redirect('horizon:nova:networks:detail',
|
network_id = kwargs['network_id']
|
||||||
network_id=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,
|
def get_initial(self):
|
||||||
'nova/ports/create.html', {
|
return {'network': self.object['id']}
|
||||||
'network_id': network_id,
|
|
||||||
'create_form': create_form})
|
|
||||||
|
|
||||||
|
|
||||||
def port_attach(request, network_id, port_id):
|
class AttachPortView(forms.ModalFormView):
|
||||||
attach_form, handled = AttachPort.maybe_handle(request, initial={
|
form_class = AttachPort
|
||||||
"network": network_id,
|
template_name = 'nova/networks/ports/attach.html'
|
||||||
"port": port_id})
|
context_object_name = 'network'
|
||||||
|
|
||||||
if handled:
|
def get_object(self, *args, **kwargs):
|
||||||
return shortcuts.redirect('horizon:nova:networks:detail',
|
network_id = kwargs['network_id']
|
||||||
network_id=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,
|
def get_initial(self):
|
||||||
'nova/ports/attach.html', {
|
return {'network': self.object['id']}
|
||||||
'network': network_id,
|
|
||||||
'port': port_id,
|
|
||||||
'attach_form': attach_form})
|
|
||||||
|
@ -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' %}
|
{% extends 'nova/base.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block title %}Network Detail{% endblock %}
|
{% block title %}{% trans "Network Detail" %}{% endblock %}
|
||||||
|
|
||||||
{% block page_header %}
|
{% block page_header %}
|
||||||
{% url horizon:nova:networks:detail network.id as refresh_link %}
|
{% include "horizon/common/_page_header.html" with title=network.name %}
|
||||||
{# 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" %}
|
|
||||||
{% endblock page_header %}
|
{% endblock page_header %}
|
||||||
|
|
||||||
{% block dash_main %}
|
{% block dash_main %}
|
||||||
{% if network.ports %}
|
{{ table.render }}
|
||||||
{% 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 %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -9,17 +9,5 @@
|
|||||||
{% endblock page_header %}
|
{% endblock page_header %}
|
||||||
|
|
||||||
{% block dash_main %}
|
{% block dash_main %}
|
||||||
{% if networks %}
|
{{ table.render }}
|
||||||
{% 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>
|
|
||||||
{% endblock %}
|
{% 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