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:
Paul McMillan 2012-01-23 19:13:52 -08:00 committed by Gabriel Hurley
parent 64b81acc0a
commit fd9d583c47
17 changed files with 324 additions and 492 deletions

View File

@ -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'])

View 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,)

View File

@ -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)

View File

@ -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'))

View File

@ -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']}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}