From ca51e21e9f31b7ef804a46c8af82468fb26a3fba Mon Sep 17 00:00:00 2001 From: Arvind Somya Date: Tue, 16 Aug 2011 15:04:36 -0400 Subject: [PATCH 01/10] Merged quantum code into django-openstack module - Merged django-quantum code into django-openstack. - Added quantum connector to django_openstack's api. - Moved creating networks to a separate page. - Moved creating ports to a separate page. - Aligned styles to the updated dashboard style. - Checking in 1.8.xx jquery ui libs for dialog boxes. - Moved port specific code to a separate port view. --- django-openstack/django_openstack/api.py | 8 +- .../django_openstack/dash/urls.py | 12 + .../django_openstack/dash/views/networks.py | 265 ++++++++ .../django_openstack/dash/views/ports.py | 156 +++++ django-openstack/django_openstack/urls.py | 4 + .../dashboard/templates/_attach_port.html | 33 + .../dashboard/templates/_create_port.html | 11 + .../dashboard/templates/_dash_sidebar.html | 1 + .../dashboard/templates/_delete_network.html | 8 + .../dashboard/templates/_delete_port.html | 9 + .../dashboard/templates/_detach_port.html | 9 + .../dashboard/templates/_network_detail.html | 49 ++ .../dashboard/templates/_network_form.html | 10 + .../dashboard/templates/_network_list.html | 27 + .../dashboard/templates/_page_header.html | 2 + .../dashboard/templates/_rename_network.html | 17 + .../dashboard/templates/_toggle_port.html | 15 + .../templates/dash_network_create.html | 28 + .../dashboard/templates/dash_networks.html | 34 ++ .../templates/dash_networks_detail.html | 38 ++ .../templates/dash_ports_create.html | 28 + .../ui-bg_diagonals-thick_90_eeeeee_40x40.png | Bin 0 -> 251 bytes .../images/ui-bg_flat_15_cd0a0a_40x100.png | Bin 0 -> 181 bytes .../images/ui-bg_glass_100_e4f1fb_1x400.png | Bin 0 -> 119 bytes .../images/ui-bg_glass_50_3baae3_1x400.png | Bin 0 -> 176 bytes .../images/ui-bg_glass_80_d7ebf9_1x400.png | Bin 0 -> 124 bytes .../ui-bg_highlight-hard_100_f2f5f7_1x100.png | Bin 0 -> 103 bytes .../ui-bg_highlight-hard_70_000000_1x100.png | Bin 0 -> 118 bytes .../ui-bg_highlight-soft_100_deedf7_1x100.png | Bin 0 -> 143 bytes .../ui-bg_highlight-soft_25_ffef8f_1x100.png | Bin 0 -> 119 bytes .../images/ui-icons_2694e8_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_3d80b3_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_72a7cf_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 4369 bytes .../jquery-ui-1.8.15.custom.css | 568 ++++++++++++++++++ .../media/dashboard/css/style.css | 45 ++ .../media/dashboard/js/application.js | 8 +- .../media/dashboard/js/network_detail.js | 114 ++++ .../media/dashboard/js/network_list.js | 32 + openstack-dashboard/tools/pip-requires | 1 + 41 files changed, 1529 insertions(+), 3 deletions(-) create mode 100644 django-openstack/django_openstack/dash/views/networks.py create mode 100644 django-openstack/django_openstack/dash/views/ports.py create mode 100644 openstack-dashboard/dashboard/templates/_attach_port.html create mode 100644 openstack-dashboard/dashboard/templates/_create_port.html create mode 100644 openstack-dashboard/dashboard/templates/_delete_network.html create mode 100644 openstack-dashboard/dashboard/templates/_delete_port.html create mode 100644 openstack-dashboard/dashboard/templates/_detach_port.html create mode 100644 openstack-dashboard/dashboard/templates/_network_detail.html create mode 100644 openstack-dashboard/dashboard/templates/_network_form.html create mode 100644 openstack-dashboard/dashboard/templates/_network_list.html create mode 100644 openstack-dashboard/dashboard/templates/_rename_network.html create mode 100644 openstack-dashboard/dashboard/templates/_toggle_port.html create mode 100644 openstack-dashboard/dashboard/templates/dash_network_create.html create mode 100644 openstack-dashboard/dashboard/templates/dash_networks.html create mode 100644 openstack-dashboard/dashboard/templates/dash_networks_detail.html create mode 100644 openstack-dashboard/dashboard/templates/dash_ports_create.html create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-bg_flat_15_cd0a0a_40x100.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-bg_glass_100_e4f1fb_1x400.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-bg_glass_50_3baae3_1x400.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-bg_glass_80_d7ebf9_1x400.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-bg_highlight-hard_70_000000_1x100.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-bg_highlight-soft_100_deedf7_1x100.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-bg_highlight-soft_25_ffef8f_1x100.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-icons_2694e8_256x240.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-icons_2e83ff_256x240.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-icons_3d80b3_256x240.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-icons_72a7cf_256x240.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/images/ui-icons_ffffff_256x240.png create mode 100644 openstack-dashboard/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/jquery-ui-1.8.15.custom.css create mode 100644 openstack-dashboard/media/dashboard/js/network_detail.js create mode 100644 openstack-dashboard/media/dashboard/js/network_list.js diff --git a/django-openstack/django_openstack/api.py b/django-openstack/django_openstack/api.py index e4bb3cd49..e47d40ab5 100644 --- a/django-openstack/django_openstack/api.py +++ b/django-openstack/django_openstack/api.py @@ -47,6 +47,7 @@ import openstackx.admin import openstackx.api.exceptions as api_exceptions import openstackx.extras import openstackx.auth +from quantum.client import Client from urlparse import urlparse @@ -162,7 +163,7 @@ class Server(APIResourceWrapper): """ _attrs = ['addresses', 'attrs', 'hostId', 'id', 'image', 'links', 'metadata', 'name', 'private_ip', 'public_ip', 'status', 'uuid', - 'image_name'] + 'image_name', 'virtual_interfaces'] def __init__(self, apiresource, request): super(Server, self).__init__(apiresource) @@ -345,6 +346,11 @@ def swift_api(request): return cloudfiles.get_connection(auth=auth) +def quantum_api(request): + return Client(settings.QUANTUM_URL, settings.QUANTUM_PORT, + False, request.user.tenant, 'json') + + def console_create(request, instance_id, kind='text'): return Console(extras_api(request).consoles.create(instance_id, kind)) diff --git a/django-openstack/django_openstack/dash/urls.py b/django-openstack/django_openstack/dash/urls.py index f58bcaf3e..2251427cb 100644 --- a/django-openstack/django_openstack/dash/urls.py +++ b/django-openstack/django_openstack/dash/urls.py @@ -26,6 +26,8 @@ KEYPAIRS = r'^(?P[^/]+)/keypairs/%s$' SNAPSHOTS = r'^(?P[^/]+)/snapshots/(?P[^/]+)/%s$' CONTAINERS = r'^(?P[^/]+)/containers/%s$' OBJECTS = r'^(?P[^/]+)/containers/(?P[^/]+)/%s$' +NETWORKS = r'^(?P[^/]+)/networks/%s$' +PORTS = r'^(?P[^/]+)/networks/(?P[^/]+)/ports/%s$' urlpatterns = patterns('django_openstack.dash.views.instances', url(r'^(?P[^/]+)/$', 'usage', name='dash_usage'), @@ -65,3 +67,13 @@ urlpatterns += patterns('django_openstack.dash.views.objects', url(OBJECTS % '(?P[^/]+)/download', 'download', name='dash_objects_download'), ) + +urlpatterns += patterns('django_openstack.dash.views.networks', + url(r'^(?P[^/]+)/networks/$', 'index', name='dash_networks'), + url(NETWORKS % 'create', 'create', name='dash_network_create'), + url(NETWORKS % '(?P[^/]+)/detail', 'detail', name='dash_networks_detail'), +) + +urlpatterns += patterns('django_openstack.dash.views.ports', + url(PORTS % 'create', 'create', name='dash_ports_create'), +) diff --git a/django-openstack/django_openstack/dash/views/networks.py b/django-openstack/django_openstack/dash/views/networks.py new file mode 100644 index 000000000..93db9d8a8 --- /dev/null +++ b/django-openstack/django_openstack/dash/views/networks.py @@ -0,0 +1,265 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# Copyright 2011 Fourth Paradigm Development, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Views for managing api.quantum_api(request) networks. +""" +import logging + +from django import http +from django import shortcuts +from django import template +from django.conf import settings +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.utils import simplejson +from django.utils.translation import ugettext as _ + +from django_openstack import forms +from django_openstack import api + +from django_openstack.dash.views.ports import DeletePort +from django_openstack.dash.views.ports import AttachPort +from django_openstack.dash.views.ports import DetachPort +from django_openstack.dash.views.ports import TogglePort + +import warnings + + +LOG = logging.getLogger('django_openstack.dash') + +class CreateNetwork(forms.SelfHandlingForm): + name = forms.CharField(required=True, label="Network Name") + + def handle(self, request, data): + network_name = data['name'] + + try: + LOG.info('Creating network %s ' % network_name) + send_data = {'network': {'net-name': '%s' % network_name}} + api.quantum_api(request).create_network(send_data) + except Exception, e: + messages.error(request, + 'Unable to create network %s: %s' % + (network_name, 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('dash_networks', tenant_id=request.user.tenant) + + +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_api(request).delete_network(data['network']) + except Exception, e: + messages.error(request, + 'Unable to delete network %s: %s' % + (data['network'], 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): + network = forms.CharField(widget=forms.HiddenInput()) + new_name = forms.CharField(required=True) + + def handle(self, request, data): + try: + LOG.info('Renaming network %s to %s' % (data['network'], data['new_name'])) + send_data = {'network': {'net-name': '%s' % data['new_name']}} + api.quantum_api(request).update_network(data['network'], send_data) + except Exception, e: + messages.error(request, + 'Unable to rename network %s: %s' % + (data['network'], e.message,)) + else: + msg = 'Network %s has been renamed to %s.' % (data['network'], data['new_name']) + LOG.info(msg) + messages.success(request, msg) + + return shortcuts.redirect(request.build_absolute_uri()) + + +@login_required +def index(request, tenant_id): + delete_form, delete_handled = DeleteNetwork.maybe_handle(request) + rename_form, rename_handled = RenameNetwork.maybe_handle(request) + + networks = [] + instances = [] + + try: + networks_list = api.quantum_api(request).list_networks() + details = [] + for network in networks_list['networks']: + + # Get all ports statistics for the network + total = 0 + available = 0 + used = 0 + ports = api.quantum_api(request).list_ports(network['id']) + for port in ports['ports']: + total += 1 + # Get port details + port_details = api.quantum_api(request).list_port_details(network['id'], port['id']) + # Get port attachment + port_attachment = api.quantum_api(request).list_port_attachments(network['id'], port['id']) + if port_attachment['attachment'] == None: + available += 1 + else: + used += 1 + # Get network details like name and id + details = api.quantum_api(request).list_network_details(network['id']) + networks.append({ + 'name' : details['network']['name'], + 'id' : network['id'], + 'total' : total, + 'available' : available, + 'used' : used, + 'tenant' : tenant_id + }) + + except Exception, e: + messages.error(request, 'Unable to get network list: %s' % e.message) + + return shortcuts.render_to_response('dash_networks.html', { + 'networks': networks, + 'delete_form' : delete_form, + 'rename_form' : rename_form, + }, context_instance=template.RequestContext(request)) + + +@login_required +def create(request, tenant_id): + network_form, handled = CreateNetwork.maybe_handle(request) + if handled: + return shortcuts.redirect('dash_networks', request.user.tenant) + + return shortcuts.render_to_response('dash_network_create.html', { + 'network_form' : network_form + }, context_instance=template.RequestContext(request)) + + +@login_required +def detail(request, tenant_id, network_id): + delete_port_form, delete_handled = DeletePort.maybe_handle(request) + attach_port_form, attach_handled = AttachPort.maybe_handle(request) + detach_port_form, detach_handled = DetachPort.maybe_handle(request) + toggle_port_form, port_toggle_handled = TogglePort.maybe_handle(request) + + network = {} + network_ports = [] + + try: + network_details = api.quantum_api(request).list_network_details(network_id) + network['name'] = network_details['network']['name'] + network['id'] = network_id + # Get all ports on this network + ports = api.quantum_api(request).list_ports(network_id) + for port in ports['ports']: + port_details = api.quantum_api(request).list_port_details(network_id, port['id']) + # Get port attachments + port_attachment = api.quantum_api(request).list_port_attachments(network_id, port['id']) + # Find instance the attachment belongs to + # Get all instances + instances = api.server_list(request) + connected_instance = None + # Get virtual interface ids by instance + for instance in instances: + for vif in instance.virtual_interfaces: + + if str(vif['id']) == str(port_attachment['attachment']): + connected_instance = instance.name + break + network_ports.append({ + 'id' : port_details['port']['id'], + 'state' : port_details['port']['state'], + 'attachment' : port_attachment['attachment'], + 'instance' : connected_instance + }) + network['ports'] = network_ports + + except Exception, e: + messages.error(request, 'Unable to get network details: %s' % e.message) + + return shortcuts.render_to_response('dash_networks_detail.html', { + 'network': network, + 'tenant' : tenant_id, + 'delete_port_form' : delete_port_form, + 'attach_port_form' : attach_port_form, + 'detach_port_form' : detach_port_form, + 'toggle_port_form' : toggle_port_form + }, context_instance=template.RequestContext(request)) + + +@login_required +def vif_ids(request): + vifs = [] + attached_vifs = [] + + try: + # Get a list of all networks + networks_list = api.quantum_api(request).list_networks() + for network in networks_list['networks']: + ports = api.quantum_api(request).list_ports(network['id']) + # Get port attachments + for port in ports['ports']: + port_attachment = api.quantum_api(request).list_port_attachments(network['id'], port['id']) + if port_attachment['attachment']: + attached_vifs.append(port_attachment['attachment'].encode('ascii')) + # Get all instances + instances = api.server_list(request) + # Get virtual interface ids by instance + for instance in instances: + instance_vifs = instance.virtual_interfaces + for vif in instance_vifs: + # Check if this VIF is already connected to any port + if str(vif['id']) in attached_vifs: + vifs.append({ + 'id' : vif['id'], + 'instance' : instance.id, + 'instance_name' : instance.name, + 'available' : False, + 'network_id' : vif['network']['id'], + 'network_name' : vif['network']['label'] + }) + else: + vifs.append({ + 'id' : vif['id'], + 'instance' : instance.id, + 'instance_name' : instance.name, + 'available' : True, + 'network_id' : vif['network']['id'], + 'network_name' : vif['network']['label'] + }) + return http.HttpResponse(simplejson.dumps(vifs), mimetype='application/json') + except Exception, e: + messages.error(request, 'Unable to get virtual interfaces: %s' % e.message) + return http.HttpResponse('Unable to get virtual interfaces: %s' % e.message, mimetype='application/json') diff --git a/django-openstack/django_openstack/dash/views/ports.py b/django-openstack/django_openstack/dash/views/ports.py new file mode 100644 index 000000000..068d30398 --- /dev/null +++ b/django-openstack/django_openstack/dash/views/ports.py @@ -0,0 +1,156 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# Copyright 2011 Fourth Paradigm Development, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Views for managing api.quantum_api(request) network ports. +""" +import logging + +from django import http +from django import shortcuts +from django import template +from django.conf import settings +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.utils.translation import ugettext as _ + +from django_openstack import forms +from django_openstack import api + + +LOG = logging.getLogger('django_api.quantum_api(request).dash') + + +class CreatePort(forms.SelfHandlingForm): + network = forms.CharField(widget=forms.HiddenInput()) + ports_num = forms.IntegerField(required=True, label="Number of Ports") + + def handle(self, request, data): + try: + LOG.info('Creating %s ports on network %s' % (data['ports_num'], data['network'])) + for i in range(0, data['ports_num']): + api.quantum_api(request).create_port(data['network']) + except Exception, e: + messages.error(request, + 'Unable to create ports on network %s: %s' % + (data['network'], e.message,)) + else: + msg = '%s ports created on network %s.' % (data['ports_num'], data['network']) + 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_api(request).delete_port(data['network'], data['port']) + except Exception, e: + messages.error(request, + 'Unable to delete port %s: %s' % + (data['port'], e.message,)) + else: + msg = 'Port %s deleted from network %s.' % (data['port'], data['network']) + LOG.info(msg) + messages.success(request, msg) + return shortcuts.redirect(request.build_absolute_uri()) + + +class AttachPort(forms.SelfHandlingForm): + network = forms.CharField(widget=forms.HiddenInput()) + port = forms.CharField(widget=forms.HiddenInput()) + vif = forms.CharField(required=True, label="Select VIF to connect") + + def handle(self, request, data): + try: + LOG.info('Attaching %s port to VIF %s' % (data['port'], data['vif'])) + body = {'port': {'attachment-id': '%s' % data['vif']}} + api.quantum_api(request).attach_resource(data['network'], data['port'], body) + except Exception, e: + messages.error(request, + 'Unable to attach port %s to VIF %s: %s' % + (data['port'], data['vif'], e.message,)) + else: + msg = 'Port %s connect to VIF %s.' % (data['port'], data['vif']) + 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_api(request).detach_resource(data['network'], data['port']) + except Exception, e: + messages.error(request, + 'Unable to detach port %s: %s' % + (data['port'], 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': {'port-state': '%s' % data['state']}} + api.quantum_api(request).set_port_state(data['network'], data['port'], body) + except Exception, e: + messages.error(request, + 'Unable to set port state to %s: %s' % + (data['state'], e.message,)) + else: + msg = 'Port %s state set to %s.' % (data['port'],data['state']) + LOG.info(msg) + messages.success(request, msg) + return shortcuts.redirect(request.build_absolute_uri()) + + +@login_required +def create(request, tenant_id, network_id): + create_form, handled = CreatePort.maybe_handle(request) + + if (handled): + return shortcuts.redirect( + 'dash_networks_detail', + tenant_id=request.user.tenant, + network_id=network_id + ) + + return shortcuts.render_to_response('dash_ports_create.html', { + 'network_id' : network_id, + 'create_form' : create_form + }, context_instance=template.RequestContext(request)) diff --git a/django-openstack/django_openstack/urls.py b/django-openstack/django_openstack/urls.py index bd4491cff..c1e1782e7 100644 --- a/django-openstack/django_openstack/urls.py +++ b/django-openstack/django_openstack/urls.py @@ -26,3 +26,7 @@ urlpatterns = patterns('', url(r'^dash/', include('django_openstack.dash.urls')), url(r'^syspanel/', include('django_openstack.syspanel.urls')), ) + +urlpatterns += patterns('', + url(r'^ajax/virtual_interfaces/$', 'django_openstack.dash.views.networks.vif_ids') +) diff --git a/openstack-dashboard/dashboard/templates/_attach_port.html b/openstack-dashboard/dashboard/templates/_attach_port.html new file mode 100644 index 000000000..0f1efa205 --- /dev/null +++ b/openstack-dashboard/dashboard/templates/_attach_port.html @@ -0,0 +1,33 @@ +
+ {% csrf_token %} + {% for hidden in form.hidden_fields %} + {{hidden}} + {% endfor %} + + + + +
+
+ Fetching virtual interfaces ...
+ +
+
+ +
+
+
+ + + + + + + + + +
Instance Name Instance Id
VIF id Network
+
+ +
+
diff --git a/openstack-dashboard/dashboard/templates/_create_port.html b/openstack-dashboard/dashboard/templates/_create_port.html new file mode 100644 index 000000000..c8f3fc3d3 --- /dev/null +++ b/openstack-dashboard/dashboard/templates/_create_port.html @@ -0,0 +1,11 @@ +
+ {% csrf_token %} + {% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %} + {% for field in form.visible_fields %} + {{ field.label_tag }} + {{ field.errors }} + {{ field }} + {% endfor %} + + +
diff --git a/openstack-dashboard/dashboard/templates/_dash_sidebar.html b/openstack-dashboard/dashboard/templates/_dash_sidebar.html index fe54cf675..b666015f2 100644 --- a/openstack-dashboard/dashboard/templates/_dash_sidebar.html +++ b/openstack-dashboard/dashboard/templates/_dash_sidebar.html @@ -6,6 +6,7 @@
  • Images
  • Snapshots
  • Keypairs
  • +
  • Networks
  • {% if swift_configured %}

    Manage Object Store

    diff --git a/openstack-dashboard/dashboard/templates/_delete_network.html b/openstack-dashboard/dashboard/templates/_delete_network.html new file mode 100644 index 000000000..e90283d8e --- /dev/null +++ b/openstack-dashboard/dashboard/templates/_delete_network.html @@ -0,0 +1,8 @@ +
    + {% csrf_token %} + {% for hidden in form.hidden_fields %} + {{hidden}} + {% endfor %} + + +
    diff --git a/openstack-dashboard/dashboard/templates/_delete_port.html b/openstack-dashboard/dashboard/templates/_delete_port.html new file mode 100644 index 000000000..8869cf2a8 --- /dev/null +++ b/openstack-dashboard/dashboard/templates/_delete_port.html @@ -0,0 +1,9 @@ +
    + {% csrf_token %} + {% for hidden in form.hidden_fields %} + {{hidden}} + {% endfor %} + + + +
    diff --git a/openstack-dashboard/dashboard/templates/_detach_port.html b/openstack-dashboard/dashboard/templates/_detach_port.html new file mode 100644 index 000000000..defb5978c --- /dev/null +++ b/openstack-dashboard/dashboard/templates/_detach_port.html @@ -0,0 +1,9 @@ +
    + {% csrf_token %} + {% for hidden in form.hidden_fields %} + {{hidden}} + {% endfor %} + + + +
    diff --git a/openstack-dashboard/dashboard/templates/_network_detail.html b/openstack-dashboard/dashboard/templates/_network_detail.html new file mode 100644 index 000000000..32c62e4a1 --- /dev/null +++ b/openstack-dashboard/dashboard/templates/_network_detail.html @@ -0,0 +1,49 @@ + + + + + + + + + + {% for port in network.ports %} + + + + + + + + {% endfor %} + +
    IDStateAttachmentActionsExtensions
    {{port.id}}{{port.state}} + {% if port.attachment == None %} + -- + {% else %} + + + + + + + + + +
    Instance VIF Id
    {{port.instance}} {{port.attachment}}
    + {% endif %} +
    +
      + {% if port.attachment == None %} +
    • {% include "_attach_port.html" with form=attach_port_form %}
    • + {% else %} +
    • {% include "_detach_port.html" with form=detach_port_form %}
    • + {% endif %} +
    • {% include "_delete_port.html" with form=delete_port_form %}
    • +
    • {% include "_toggle_port.html" with form=toggle_port_form %}
    • +
    +
    +
      +
    +
    + diff --git a/openstack-dashboard/dashboard/templates/_network_form.html b/openstack-dashboard/dashboard/templates/_network_form.html new file mode 100644 index 000000000..4e90d5094 --- /dev/null +++ b/openstack-dashboard/dashboard/templates/_network_form.html @@ -0,0 +1,10 @@ +
    + {% csrf_token %} + {% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %} + {% for field in form.visible_fields %} + {{ field.label_tag }} + {{ field.errors }} + {{ field }} + {% endfor %} + +
    diff --git a/openstack-dashboard/dashboard/templates/_network_list.html b/openstack-dashboard/dashboard/templates/_network_list.html new file mode 100644 index 000000000..36754f645 --- /dev/null +++ b/openstack-dashboard/dashboard/templates/_network_list.html @@ -0,0 +1,27 @@ + + + + + + + + + + + {% for network in networks %} + + + + + + + + + {% endfor %} + +
    IDNamePortsAvailableUsedAction
    {{network.id}}{{network.name}}{{network.total}}{{network.available}}{{network.used}} +
      +
    • {% include "_delete_network.html" with form=delete_form %}
    • +
    • {% include "_rename_network.html" with form=rename_form %}
    • +
    +
    diff --git a/openstack-dashboard/dashboard/templates/_page_header.html b/openstack-dashboard/dashboard/templates/_page_header.html index bba230053..78a38520f 100644 --- a/openstack-dashboard/dashboard/templates/_page_header.html +++ b/openstack-dashboard/dashboard/templates/_page_header.html @@ -1,6 +1,8 @@ {% block page_header %}