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.
This commit is contained in:
Arvind Somya 2011-08-16 15:04:36 -04:00
parent f99cd076a3
commit ca51e21e9f
41 changed files with 1529 additions and 3 deletions

View File

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

View File

@ -26,6 +26,8 @@ KEYPAIRS = r'^(?P<tenant_id>[^/]+)/keypairs/%s$'
SNAPSHOTS = r'^(?P<tenant_id>[^/]+)/snapshots/(?P<instance_id>[^/]+)/%s$'
CONTAINERS = r'^(?P<tenant_id>[^/]+)/containers/%s$'
OBJECTS = r'^(?P<tenant_id>[^/]+)/containers/(?P<container_name>[^/]+)/%s$'
NETWORKS = r'^(?P<tenant_id>[^/]+)/networks/%s$'
PORTS = r'^(?P<tenant_id>[^/]+)/networks/(?P<network_id>[^/]+)/ports/%s$'
urlpatterns = patterns('django_openstack.dash.views.instances',
url(r'^(?P<tenant_id>[^/]+)/$', 'usage', name='dash_usage'),
@ -65,3 +67,13 @@ urlpatterns += patterns('django_openstack.dash.views.objects',
url(OBJECTS % '(?P<object_name>[^/]+)/download',
'download', name='dash_objects_download'),
)
urlpatterns += patterns('django_openstack.dash.views.networks',
url(r'^(?P<tenant_id>[^/]+)/networks/$', 'index', name='dash_networks'),
url(NETWORKS % 'create', 'create', name='dash_network_create'),
url(NETWORKS % '(?P<network_id>[^/]+)/detail', 'detail', name='dash_networks_detail'),
)
urlpatterns += patterns('django_openstack.dash.views.ports',
url(PORTS % 'create', 'create', name='dash_ports_create'),
)

View File

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

View File

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

View File

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

View File

@ -0,0 +1,33 @@
<form id="attach_port_form_{{port.id}}" class="form-attach" 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 name="vif" type="hidden" value="" class="vif_input"/>
<input title="Attach port to a virtual interface" id="attach_{{port.id}}" class="attach" type="submit" value="Attach" />
<div class="port-attach" id="port_attach_div_{{port.id}}">
<div class="vif_status">
Fetching virtual interfaces ... <br/>
<img src="/media/dashboard/images/spinner.gif" />
</div>
<div class="select_area">
<select class="vif-list" name="vif"></select>
</div>
<div class="error_block ui-state-error ui-corner-all"></div>
<div class="attachment_details">
<table class="attachment_table">
<tr>
<td class="row_head">Instance Name</td> <td class="row_val instance_name"></td>
<td class="row_head">Instance Id</td> <td class="row_val instance_id"> </td>
</tr>
<tr>
<td class="row_head">VIF id</td> <td class="row_val vif_id"></td>
<td class="row_head">Network</td> <td class="row_val network"></td>
</tr>
</table>
</div>
<button class="attach_port_button" id="{{port.id}}">Attach</button>
</div>
</form>

View File

@ -0,0 +1,11 @@
<form id="create_port_form" method="post">
{% csrf_token %}
{% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %}
{% for field in form.visible_fields %}
{{ field.label_tag }}
{{ field.errors }}
{{ field }}
{% endfor %}
<input name="network" type="hidden" value="{{network_id}}" />
<input type="submit" value="Create Ports" class="large-rounded" />
</form>

View File

@ -6,6 +6,7 @@
<li><a {% if current_sidebar == "images" %} class="active" {% endif %} href="{% url dash_images request.user.tenant %}">Images</a></li>
<li><a {% if current_sidebar == "snapshots" %} class="active" {% endif %} href="{% url dash_snapshots request.user.tenant %}">Snapshots</a></li>
<li><a {% if current_sidebar == "keypairs" %} class="active" {% endif %} href="{% url dash_keypairs request.user.tenant %}">Keypairs</a></li>
<li><a {% if current_sidebar == "networks" %} class="active" {% endif %} href="{% url dash_networks request.user.tenant %}">Networks</a></li>
</ul>
{% if swift_configured %}
<h3>Manage Object Store</h3>

View File

@ -0,0 +1,8 @@
<form id="delete_form" class="form-delete" method="post">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{hidden}}
{% endfor %}
<input name="network" type="hidden" value="{{network.id}}" />
<input title="Network" id="delete_{{network.id}}" class="delete" type="submit" value="Delete" />
</form>

View File

@ -0,0 +1,9 @@
<form id="delete_port_form" 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="delete" type="submit" value="Delete" />
</form>

View File

@ -0,0 +1,9 @@
<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="detach" type="submit" value="Detach" />
</form>

View File

@ -0,0 +1,49 @@
<table id='Ports' class="wide">
<tr id='headings'>
<th>ID</th>
<th>State</th>
<th>Attachment</th>
<th>Actions</th>
<th>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 == None %}
--
{% else %}
<table class="attachmend_details">
<tr>
<td> Instance </td>
<td> VIF Id </td>
</tr>
<tr>
<td> {{port.instance}} </td>
<td> {{port.attachment}} </td>
</tr>
</table>
{% endif %}
</td>
<td id="actions">
<ul>
{% if port.attachment == None %}
<li class="form">{% include "_attach_port.html" with form=attach_port_form %}</li>
{% else %}
<li class="form">{% include "_detach_port.html" with form=detach_port_form %}</li>
{% endif %}
<li class="form">{% include "_delete_port.html" with form=delete_port_form %}</li>
<li class="form">{% include "_toggle_port.html" with form=toggle_port_form %}</li>
</ul>
</td>
<td id="extensions">
<ul>
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -0,0 +1,10 @@
<form id="network_form" method="post">
{% csrf_token %}
{% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %}
{% for field in form.visible_fields %}
{{ field.label_tag }}
{{ field.errors }}
{{ field }}
{% endfor %}
<input type="submit" value="Create Network" class="large-rounded" />
</form>

View File

@ -0,0 +1,27 @@
<table id='networks' class="wide">
<tr id='headings'>
<th>ID</th>
<th>Name</th>
<th>Ports</th>
<th>Available</th>
<th>Used</th>
<th>Action</th>
</tr>
<tbody class='main'>
{% for network in networks %}
<tr class="{% cycle 'odd' 'even' %}" id="{{network.id}}">
<td><a href='{% url dash_networks_detail request.user.tenant 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">
<ul>
<li class="form">{% include "_delete_network.html" with form=delete_form %}</li>
<li class="form">{% include "_rename_network.html" with form=rename_form %}</li>
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -1,6 +1,8 @@
{% block page_header %}
<div id='page_header'>
<h2>{{title}}</h2>
{% block breadcrumbs %}
{% endblock %}
{% if searchable %}
<div class="right">
<div class='search'>

View File

@ -0,0 +1,17 @@
<form id="form_rename_{{network.id}}" class="form-rename" method="post">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{hidden}}
{% endfor %}
<input name="network" type="hidden" value="{{network.id}}" />
<input id="new_name_{{network.id}}" name="new_name" type="hidden" value="{{network.name}}" />
<input id="rename_{{network.id}}" class="rename" type="submit" value="Rename" />
<div class="network_rename_div" id="rename_div_{{network.id}}">
<input id="change_to_{{network.id}}" name="change_to" class="change_to ui-corner-all ui-state-highlight" size="20" value="{{network.name}}"/><br/><br/>
<button id="{{network.id}}" class="dialog_rename">Rename</button>
</div>
</form>

View File

@ -0,0 +1,15 @@
<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="port_up" type="submit" value="Port UP" />
{% else %}
<input name="state" type="hidden" value="DOWN" />
<input title="Turn port DOWN" id="port_up_{{port.id}}" class="port_down" type="submit" value="Port DOWN" />
{% endif %}
</form>

View File

@ -0,0 +1,28 @@
{% extends 'dash_base.html' %}
{% block sidebar %}
{% with current_sidebar="networks" %}
{{block.super}}
{% endwith %}
{% endblock %}
{% block page_header %}
{# to make searchable false, just remove it from the include statement #}
{% include "_page_header.html" with title="Create Network" %}
{% endblock page_header %}
{% block dash_main %}
<div class="dash_block">
<div class="left">
{% include '_network_form.html' with form=network_form %}
<h3><a href="{% url dash_networks request.user.tenant %}"><< Return to networks list</a></h3>
</div>
<div class="right">
<h3>Description:</h3>
<p>Networks provide layer 2 connectivity to your instances.</p>
</div>
<div class="clear">&nbsp;</div>
</div>
{% endblock %}

View File

@ -0,0 +1,34 @@
{% extends 'dash_base.html' %}
{% block sidebar %}
{% with current_sidebar="networks" %}
{{block.super}}
{% endwith %}
{% endblock %}
{% block page_header %}
{% url dash_networks request.user.tenant as refresh_link %}
{# to make searchable false, just remove it from the include statement #}
{% include "_page_header.html" with title="Networks" refresh_link=refresh_link searchable="true" %}
{% endblock page_header %}
{% block headerjs %}
<script src="/media/dashboard/js/network_list.js"></script>
{% endblock %}
{% block headercss %}
<link href='/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/jquery-ui-1.8.15.custom.css' media='screen' rel='stylesheet' />
{% endblock %}
{% block dash_main %}
{% if networks %}
{% include '_network_list.html' %}
<a id="network_create_link" class="action_link large-rounded" href="{% url dash_network_create request.user.tenant %}">Create New Network</a>
{% else %}
<div class="message_box info">
<h2>Info</h2>
<p>There are currently no networks. <a href='{% url dash_network_create request.user.tenant %}'>Create A Network &gt;&gt;</a></p>
</div>
{% endif %}
</div>
{% endblock %}

View File

@ -0,0 +1,38 @@
{% extends 'dash_base.html' %}
{% block sidebar %}
{% with current_sidebar="networks" %}
{{block.super}}
{% endwith %}
{% endblock %}
{% block page_header %}
{% url dash_networks_detail request.user.tenant network.id as refresh_link %}
{# to make searchable false, just remove it from the include statement #}
{% include "_page_header.html" with title=network.name refresh_link=refresh_link searchable="true" %}
{% endblock page_header %}
{% block headerjs %}
<script src="/media/dashboard/js/network_detail.js"></script>
{% endblock %}
{% block headercss %}
<link href='/media/dashboard/css/cupertino/jquery-ui-1.8.15.custom/jquery-ui-1.8.15.custom.css' media='screen' rel='stylesheet' />
{% endblock %}
{% block breadcrumbs %}
<a href="{% url dash_networks tenant %}">Networks</a>&nbsp;&raquo;&nbsp;
<a href="{% url dash_networks_detail tenant network.id %}">{{network.name}}</a>
{% endblock %}
{% block dash_main %}
{% if network.ports %}
{% include '_network_detail.html' %}
<a id="network_create_link" class="action_link large-rounded" href="{% url dash_ports_create request.user.tenant network.id %}">Create Ports</a>
{% else %}
<div class="message_box info">
<h2>Info</h2>
<p>There are currently no ports in this network. <a href="{% url dash_ports_create request.user.tenant network.id %}">Create Ports &gt;&gt;</a></p>
</div>
{% endif %}
{% endblock %}

View File

@ -0,0 +1,28 @@
{% extends 'dash_base.html' %}
{% block sidebar %}
{% with current_sidebar="networks" %}
{{block.super}}
{% endwith %}
{% endblock %}
{% block page_header %}
{# to make searchable false, just remove it from the include statement #}
{% include "_page_header.html" with title="Create Network" %}
{% endblock page_header %}
{% block dash_main %}
<div class="dash_block">
<div class="left">
{% include '_create_port.html' with form=create_form %}
<h3><a href="{% url dash_networks_detail request.user.tenant network_id %}"><< Return to network detail</a></h3>
</div>
<div class="right">
<h3>Description:</h3>
<p>You can plug virtual interfaces from your instances to ports created in the network</p>
</div>
<div class="clear">&nbsp;</div>
</div>
{% endblock %}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,568 @@
/*
* jQuery UI CSS Framework 1.8.15
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming/API
*/
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; }
/* required comment for clearfix to work in Opera \*/
* html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; }
/* end clearfix */
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/*
* jQuery UI CSS Framework 1.8.15
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming/API
*
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=deedf7&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=100&borderColorHeader=aed0ea&fcHeader=222222&iconColorHeader=72a7cf&bgColorContent=f2f5f7&bgTextureContent=04_highlight_hard.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=362b36&iconColorContent=72a7cf&bgColorDefault=d7ebf9&bgTextureDefault=02_glass.png&bgImgOpacityDefault=80&borderColorDefault=aed0ea&fcDefault=2779aa&iconColorDefault=3d80b3&bgColorHover=e4f1fb&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=74b2e2&fcHover=0070a3&iconColorHover=2694e8&bgColorActive=3baae3&bgTextureActive=02_glass.png&bgImgOpacityActive=50&borderColorActive=2694e8&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=ffef8f&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=25&borderColorHighlight=f9dd34&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=cd0a0a&bgTextureError=01_flat.png&bgImgOpacityError=15&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffffff&bgColorOverlay=eeeeee&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=90&opacityOverlay=80&bgColorShadow=000000&bgTextureShadow=04_highlight_hard.png&bgImgOpacityShadow=70&opacityShadow=30&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px
*/
/* Component containers
----------------------------------*/
.ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #dddddd; background: #f2f5f7 url(images/ui-bg_highlight-hard_100_f2f5f7_1x100.png) 50% top repeat-x; color: #362b36; }
.ui-widget-content a { color: #362b36; }
.ui-widget-header { border: 1px solid #aed0ea; background: #deedf7 url(images/ui-bg_highlight-soft_100_deedf7_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
.ui-widget-header a { color: #222222; }
/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #aed0ea; background: #d7ebf9 url(images/ui-bg_glass_80_d7ebf9_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2779aa; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2779aa; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #74b2e2; background: #e4f1fb url(images/ui-bg_glass_100_e4f1fb_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #0070a3; }
.ui-state-hover a, .ui-state-hover a:hover { color: #0070a3; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #2694e8; background: #3baae3 url(images/ui-bg_glass_50_3baae3_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #ffffff; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #ffffff; text-decoration: none; }
.ui-widget :active { outline: none; }
/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #f9dd34; background: #ffef8f url(images/ui-bg_highlight-soft_25_ffef8f_1x100.png) 50% top repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #cd0a0a url(images/ui-bg_flat_15_cd0a0a_40x100.png) 50% 50% repeat-x; color: #ffffff; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_72a7cf_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_72a7cf_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_72a7cf_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_3d80b3_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_2694e8_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -khtml-border-top-left-radius: 6px; border-top-left-radius: 6px; }
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; -khtml-border-top-right-radius: 6px; border-top-right-radius: 6px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; -khtml-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; -khtml-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
/* Overlays */
.ui-widget-overlay { background: #eeeeee url(images/ui-bg_diagonals-thick_90_eeeeee_40x40.png) 50% 50% repeat; opacity: .80;filter:Alpha(Opacity=80); }
.ui-widget-shadow { margin: -7px 0 0 -7px; padding: 7px; background: #000000 url(images/ui-bg_highlight-hard_70_000000_1x100.png) 50% top repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
* jQuery UI Resizable 1.8.15
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Resizable#theming
*/
.ui-resizable { position: relative;}
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
* jQuery UI Selectable 1.8.15
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Selectable#theming
*/
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
/*
* jQuery UI Accordion 1.8.15
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Accordion#theming
*/
/* IE/Win - Fix animation bug - #4615 */
.ui-accordion { width: 100%; }
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
.ui-accordion .ui-accordion-li-fix { display: inline; }
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
.ui-accordion .ui-accordion-content-active { display: block; }
/*
* jQuery UI Autocomplete 1.8.15
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Autocomplete#theming
*/
.ui-autocomplete { position: absolute; cursor: default; }
/* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
/*
* jQuery UI Menu 1.8.15
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Menu#theming
*/
.ui-menu {
list-style:none;
padding: 2px;
margin: 0;
display:block;
float: left;
}
.ui-menu .ui-menu {
margin-top: -3px;
}
.ui-menu .ui-menu-item {
margin:0;
padding: 0;
zoom: 1;
float: left;
clear: left;
width: 100%;
}
.ui-menu .ui-menu-item a {
text-decoration:none;
display:block;
padding:.2em .4em;
line-height:1.5;
zoom:1;
}
.ui-menu .ui-menu-item a.ui-state-hover,
.ui-menu .ui-menu-item a.ui-state-active {
font-weight: normal;
margin: -1px;
}
/*
* jQuery UI Button 1.8.15
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Button#theming
*/
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
.ui-button-icons-only { width: 3.4em; }
button.ui-button-icons-only { width: 3.7em; }
/*button text element */
.ui-button .ui-button-text { display: block; line-height: 1.4; }
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
/* no icon support for input elements, provide padding by default */
input.ui-button { padding: .4em 1em; }
/*button icon element(s) */
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
/*button sets*/
.ui-buttonset { margin-right: 7px; }
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
/* workarounds */
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
/*
* jQuery UI Dialog 1.8.15
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Dialog#theming
*/
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
.ui-draggable .ui-dialog-titlebar { cursor: move; }
/*
* jQuery UI Slider 1.8.15
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Slider#theming
*/
.ui-slider { position: relative; text-align: left; }
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
.ui-slider-horizontal { height: .8em; }
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
.ui-slider-vertical { width: .8em; height: 100px; }
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
* jQuery UI Tabs 1.8.15
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Tabs#theming
*/
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
.ui-tabs .ui-tabs-hide { display: none !important; }
/*
* jQuery UI Datepicker 1.8.15
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Datepicker#theming
*/
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
display: none; /*sorry for IE5*/
display/**/: block; /*sorry for IE5*/
position: absolute; /*must have*/
z-index: -1; /*must have*/
filter: mask(); /*must have*/
top: -4px; /*must have*/
left: -4px; /*must have*/
width: 200px; /*must have*/
height: 200px; /*must have*/
}/*
* jQuery UI Progressbar 1.8.15
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Progressbar#theming
*/
.ui-progressbar { height:2em; text-align: left; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }

View File

@ -894,3 +894,48 @@ h3 span, .left h3 { color: #6a6a6a; }
margin: 25px 0 0 0;
float: left;
}
/* Network details page */
td.ACTIVE {
color:#6EAF6E;
}
td.DOWN {
color:#CC3333;
}
.vif-list {
font: 12px/21px arial,sans-serif;
font-style: italic;
}
table.attachment_table {
margin-top: 10px;
border: none;
display: none;
}
table.attachment_table td {
padding: 5px;
font-size: 8pt;
}
table.attachment_table td.row_head {
font-weight: bold;
}
table.attachment_table td.row_val {
font-style: italic;
}
div.error_block {
padding: 5px;
font-size: 8pt;
}
span.attachment_value {
font-weight:bold;
display:inline-block;
font-style:italic;
color:#6EAF6E;
}

View File

@ -45,5 +45,9 @@ $(function(){
});
return true;
});
})
$(".detach").click(function(e){
var response = confirm('Are you sure you want to detach the '+$(this).attr('title')+" ?");
return response;
})
})

View File

@ -0,0 +1,114 @@
$(document).ready(function() {
$(".form-attach button").button();
// Convert attach port into a dialog
$(".form-attach div.port-attach").dialog({
autoOpen : false,
modal : true,
draggable : true,
resizable: false,
position: 'center',
title : 'Select virtual interface'
});
// Port attach
$(".form-attach .attach").click(function() {
var id = $(this).attr('id');
id = id.replace(/^attach_/,'');
// Hide error
$("div#port_attach_div_"+id+" div.error_block").hide();
// Remove select
$("div#port_attach_div_"+id+" select").remove();
// Show status
$("div#port_attach_div_"+id+" div.vif_status").show();
// Clear out the values table
$("div#port_attach_div_"+id+" td.row_val").html('-');
// Hide the submit button
$("div#port_attach_div_"+id+" .attach_port_button").hide();
// Fetch interfaces from the server
$.ajax({
url : '/ajax/virtual_interfaces',
type : 'GET',
success : function(msg) {
// Hide status
$("div#port_attach_div_"+id+" div.vif_status").hide(100);
if ( $.isArray(msg) ) {
if (msg.length == 0) {
// No interfaces found, show message
$("div#port_attach_div_"+id+" div.error_block")
.html('No virtual interfaces found.')
.show(100);
return false;
}
$("div#port_attach_div_"+id+" .attach_port_button").show();
// Create a select box
$("div#port_attach_div_"+id+" div.select_area")
.append($('<select></select>')
.addClass('vif-list'));
// Add an empty option on top
$("div#port_attach_div_"+id+" select")
.append($('<option></option>')
.attr('value','')
.text('')
.attr('selected','selected')
.addClass('attach_option'));
// Update select values
for (i=0; i < msg.length; i++) {
if (msg[i].available) {
// Append option to select box
text = msg[i].instance_name + ' VIF ' + msg[i].id;
$("div#port_attach_div_"+id+" select")
.append($('<option></option>')
.attr('value',msg[i].id)
.text(text)
.addClass('attach_option'));
}
}
// Show details table
$("div#port_attach_div_"+id+" table").show();
// Install click handlers for select options
$("div#port_attach_div_"+id+" select").change(function() {
var selected = $("div#port_attach_div_"+id+" select.vif-list option:selected").val();
for (i=0; i < msg.length; i++) {
if (msg[i].id == selected) {
$("div#port_attach_div_"+id+" td.instance_name").html(msg[i].instance_name);
$("div#port_attach_div_"+id+" td.instance_id").html(msg[i].instance);
$("div#port_attach_div_"+id+" td.vif_id").html(msg[i].id);
$("div#port_attach_div_"+id+" td.network").html(msg[i].network_name);
}
}
});
} else {
// Show error message
$("div#port_attach_div_"+id+" div.error_block")
.html('Error fetching virtual interface ids: ' + msg)
.show(100);
}
},
failure : function(request, msg) {
$("div#port_attach_div_"+id+" div.vif_status").hide();
// Show error message
$("div#port_attach_div_"+id+" div.error_block")
.html('Error fetching virtual interface ids: ' + msg)
.show(100);
}
});
// Show the dialog
$("div#port_attach_div_"+id).dialog('open');
// Return false here to prevent submitting the form
return false;
});
$("button.attach_port_button").click(function() {
var id = $(this).attr('id');
// Check if we have a vif
var val = $("div#port_attach_div_"+id+" select.vif-list option:selected").val();
if (val) {
// Append value to form
$('form#attach_port_form_' + id+ ' input.vif_input').val(val);
$('form#attach_port_form_' + id).submit();
} else {
$("div#port_attach_div_"+id+" div.error_block")
.html('Please select a virtual interface')
.show(100);
}
});
});

View File

@ -0,0 +1,32 @@
$(document).ready(function() {
$(".form-rename button").button();
// Convert the rename input into a dialog
$(".form-rename div.network_rename_div").dialog({
autoOpen : false,
modal : true,
draggable : true,
resizable: false,
position: 'center',
title : 'Enter new network name'
});
// Network rename
$(".form-rename .rename").click(function() {
var id = $(this).attr('id');
id = id.replace(/^rename_/,'');
// Show the dialog
$("div#rename_div_"+id).dialog('open');
// Return false here to prevent submitting the form
return false;
});
$("div.network_rename_div .dialog_rename").click(function() {
var id = $(this).attr('id');
// Update name
$('#new_name_'+id).val($('#change_to_'+id).val());
// Close dialog
$("div#rename_div_"+id).dialog('close');
// Submit original form
$("form#form_rename_"+id).submit();
});
});

View File

@ -16,6 +16,7 @@ eventlet
xattr
bzr+https://launchpad.net/glance#egg=glance
bzr+https://launchpad.net/~asomya/+junk/quantum-dev
-e git://github.com/jacobian/openstack.compute.git#egg=openstack
-e git://github.com/cloudbuilders/openstackx.git#egg=openstackx