Merge remote branch 'origin/master'
This commit is contained in:
commit
fb60f932c4
@ -191,6 +191,8 @@ def tenant_update(request, tenant_id, description, enabled):
|
|||||||
def token_create(request, tenant, username, password):
|
def token_create(request, tenant, username, password):
|
||||||
return auth_api().tokens.create(tenant, username, password)
|
return auth_api().tokens.create(tenant, username, password)
|
||||||
|
|
||||||
|
def tenant_quota_get(request, tenant):
|
||||||
|
return admin_api(request).quota_sets.get(tenant)
|
||||||
|
|
||||||
def token_info(request, token):
|
def token_info(request, token):
|
||||||
hdrs = {"Content-type": "application/json",
|
hdrs = {"Content-type": "application/json",
|
||||||
|
@ -10,6 +10,7 @@ KEYPAIRS = r'^(?P<tenant_id>[^/]+)/keypairs/%s$'
|
|||||||
urlpatterns = patterns('django_openstack.dash.views.instances',
|
urlpatterns = patterns('django_openstack.dash.views.instances',
|
||||||
url(r'^(?P<tenant_id>[^/]+)/$', 'usage', name='dash_usage'),
|
url(r'^(?P<tenant_id>[^/]+)/$', 'usage', name='dash_usage'),
|
||||||
url(r'^(?P<tenant_id>[^/]+)/instances/$', 'index', name='dash_instances'),
|
url(r'^(?P<tenant_id>[^/]+)/instances/$', 'index', name='dash_instances'),
|
||||||
|
url(r'^(?P<tenant_id>[^/]+)/instances/refresh$', 'refresh', name='dash_instances_refresh'),
|
||||||
url(INSTANCES % 'console', 'console', name='dash_instances_console'),
|
url(INSTANCES % 'console', 'console', name='dash_instances_console'),
|
||||||
url(INSTANCES % 'vnc', 'vnc', name='dash_instances_vnc'),
|
url(INSTANCES % 'vnc', 'vnc', name='dash_instances_vnc'),
|
||||||
url(INSTANCES % 'update', 'update', name='dash_instances_update'),
|
url(INSTANCES % 'update', 'update', name='dash_instances_update'),
|
||||||
|
@ -175,6 +175,10 @@ def launch(request, tenant_id, image_id):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
image = api.image_get(request, image_id)
|
image = api.image_get(request, image_id)
|
||||||
|
tenant = api.token_get_tenant(request, request.user.tenant)
|
||||||
|
quotas = api.tenant_quota_get(request, request.user.tenant)
|
||||||
|
quotas.ram = int(quotas.ram)/100
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
messages.error(request, 'Unable to retrieve image %s: %s' %
|
messages.error(request, 'Unable to retrieve image %s: %s' %
|
||||||
(image_id, e.message))
|
(image_id, e.message))
|
||||||
@ -199,4 +203,5 @@ def launch(request, tenant_id, image_id):
|
|||||||
'tenant': tenant,
|
'tenant': tenant,
|
||||||
'image': image,
|
'image': image,
|
||||||
'form': form,
|
'form': form,
|
||||||
|
'quotas': quotas,
|
||||||
}, context_instance=template.RequestContext(request))
|
}, context_instance=template.RequestContext(request))
|
||||||
|
@ -109,7 +109,34 @@ def index(request, tenant_id):
|
|||||||
'reboot_form': reboot_form,
|
'reboot_form': reboot_form,
|
||||||
}, context_instance=template.RequestContext(request))
|
}, context_instance=template.RequestContext(request))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def refresh(request, tenant_id):
|
||||||
|
for f in (TerminateInstance, RebootInstance):
|
||||||
|
_, handled = f.maybe_handle(request)
|
||||||
|
if handled:
|
||||||
|
return handled
|
||||||
|
instances = []
|
||||||
|
try:
|
||||||
|
image_dict = api.image_all_metadata(request)
|
||||||
|
instances = api.server_list(request)
|
||||||
|
for instance in instances:
|
||||||
|
# FIXME - ported this over, but it is hacky
|
||||||
|
instance.attrs['image_name'] =\
|
||||||
|
image_dict.get(int(instance.attrs['image_ref']),{}).get('name')
|
||||||
|
except Exception as e:
|
||||||
|
messages.error(request, 'Unable to get instance list: %s' % e.message)
|
||||||
|
|
||||||
|
# We don't have any way of showing errors for these, so don't bother
|
||||||
|
# trying to reuse the forms from above
|
||||||
|
terminate_form = TerminateInstance()
|
||||||
|
reboot_form = RebootInstance()
|
||||||
|
|
||||||
|
return render_to_response('_instance_list.html', {
|
||||||
|
'instances': instances,
|
||||||
|
'terminate_form': terminate_form,
|
||||||
|
'reboot_form': reboot_form,
|
||||||
|
}, context_instance=template.RequestContext(request))
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def usage(request, tenant_id=None):
|
def usage(request, tenant_id=None):
|
||||||
today = datetime.date.today()
|
today = datetime.date.today()
|
||||||
|
@ -12,6 +12,7 @@ urlpatterns = patterns('django_openstack.syspanel.views.instances',
|
|||||||
url(r'^usage/(?P<tenant_id>[^/]+)$', 'tenant_usage',
|
url(r'^usage/(?P<tenant_id>[^/]+)$', 'tenant_usage',
|
||||||
name='syspanel_tenant_usage'),
|
name='syspanel_tenant_usage'),
|
||||||
url(r'^instances/$', 'index', name='syspanel_instances'),
|
url(r'^instances/$', 'index', name='syspanel_instances'),
|
||||||
|
url(r'^instances/refresh$', 'refresh', name='syspanel_instances_refresh'),
|
||||||
# NOTE(termie): currently just using the 'dash' versions
|
# NOTE(termie): currently just using the 'dash' versions
|
||||||
#url(INSTANCES % 'console', 'console', name='syspanel_instances_console'),
|
#url(INSTANCES % 'console', 'console', name='syspanel_instances_console'),
|
||||||
#url(INSTANCES % 'vnc', 'vnc', name='syspanel_instances_vnc'),
|
#url(INSTANCES % 'vnc', 'vnc', name='syspanel_instances_vnc'),
|
||||||
@ -25,6 +26,10 @@ urlpatterns += patterns('django_openstack.syspanel.views.images',
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns += patterns('django_openstack.syspanel.views.quotas',
|
||||||
|
url(r'^quotas/$', 'index', name='syspanel_quotas'),
|
||||||
|
)
|
||||||
|
|
||||||
urlpatterns += patterns('django_openstack.syspanel.views.flavors',
|
urlpatterns += patterns('django_openstack.syspanel.views.flavors',
|
||||||
url(r'^flavors/$', 'index', name='syspanel_flavors'),
|
url(r'^flavors/$', 'index', name='syspanel_flavors'),
|
||||||
url(r'^flavors/create/$', 'create', name='syspanel_flavors_create'),
|
url(r'^flavors/create/$', 'create', name='syspanel_flavors_create'),
|
||||||
@ -45,7 +50,8 @@ urlpatterns += patterns('django_openstack.syspanel.views.services',
|
|||||||
|
|
||||||
urlpatterns += patterns('django_openstack.syspanel.views.tenants',
|
urlpatterns += patterns('django_openstack.syspanel.views.tenants',
|
||||||
url(r'^tenants/$', 'index', name='syspanel_tenants'),
|
url(r'^tenants/$', 'index', name='syspanel_tenants'),
|
||||||
|
url(r'^tenants/create$', 'create', name='syspanel_tenants_create'),
|
||||||
url(TENANTS % 'update', 'update', name='syspanel_tenant_update'),
|
url(TENANTS % 'update', 'update', name='syspanel_tenant_update'),
|
||||||
url(TENANTS % 'users', 'users', name='syspanel_tenant_users'),
|
url(TENANTS % 'users', 'users', name='syspanel_tenant_users'),
|
||||||
url(r'^tenants/create$', 'create', name='syspanel_tenants_create'),
|
url(TENANTS % 'quotas', 'quotas', name='syspanel_tenant_quotas'),
|
||||||
)
|
)
|
||||||
|
@ -196,3 +196,32 @@ def index(request):
|
|||||||
'terminate_form': terminate_form,
|
'terminate_form': terminate_form,
|
||||||
'reboot_form': reboot_form,
|
'reboot_form': reboot_form,
|
||||||
}, context_instance=template.RequestContext(request))
|
}, context_instance=template.RequestContext(request))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def refresh(request):
|
||||||
|
for f in (TerminateInstance, RebootInstance):
|
||||||
|
_, handled = f.maybe_handle(request)
|
||||||
|
if handled:
|
||||||
|
return handled
|
||||||
|
|
||||||
|
instances = []
|
||||||
|
try:
|
||||||
|
image_dict = api.image_all_metadata(request)
|
||||||
|
instances = api.server_list(request)
|
||||||
|
for instance in instances:
|
||||||
|
# FIXME - ported this over, but it is hacky
|
||||||
|
instance._info['attrs']['image_name'] =\
|
||||||
|
image_dict.get(int(instance.attrs['image_ref']),{}).get('name')
|
||||||
|
except Exception as e:
|
||||||
|
messages.error(request, 'Unable to get instance list: %s' % e.message)
|
||||||
|
|
||||||
|
# We don't have any way of showing errors for these, so don't bother
|
||||||
|
# trying to reuse the forms from above
|
||||||
|
terminate_form = TerminateInstance()
|
||||||
|
reboot_form = RebootInstance()
|
||||||
|
|
||||||
|
return render_to_response('_syspanel_instance_list.html', {
|
||||||
|
'instances': instances,
|
||||||
|
'terminate_form': terminate_form,
|
||||||
|
'reboot_form': reboot_form,
|
||||||
|
}, context_instance=template.RequestContext(request))
|
||||||
|
28
django-openstack/django_openstack/syspanel/views/quotas.py
Normal file
28
django-openstack/django_openstack/syspanel/views/quotas.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
from operator import itemgetter
|
||||||
|
|
||||||
|
from django import template
|
||||||
|
from django import http
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.shortcuts import render_to_response
|
||||||
|
from openstackx.api import exceptions as api_exceptions
|
||||||
|
|
||||||
|
|
||||||
|
from django_openstack import api
|
||||||
|
from django_openstack import forms
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def index(request):
|
||||||
|
quotas = api.admin_api(request).quota_sets.get(True)._info
|
||||||
|
quotas['ram'] = int(quotas['ram']) / 100
|
||||||
|
quotas.pop('id')
|
||||||
|
|
||||||
|
return render_to_response('syspanel_quotas.html',{
|
||||||
|
'quotas': quotas,
|
||||||
|
}, context_instance = template.RequestContext(request))
|
||||||
|
|
@ -92,6 +92,38 @@ class UpdateTenant(forms.SelfHandlingForm):
|
|||||||
messages.error(request, 'Unable to update tenant: %s' % e.message)
|
messages.error(request, 'Unable to update tenant: %s' % e.message)
|
||||||
return redirect('syspanel_tenants')
|
return redirect('syspanel_tenants')
|
||||||
|
|
||||||
|
class UpdateQuotas(forms.SelfHandlingForm):
|
||||||
|
tenant_id = forms.CharField(label="ID (name)", widget=forms.TextInput(attrs={'readonly':'readonly'}))
|
||||||
|
metadata_items = forms.CharField(label="Metadata Items")
|
||||||
|
injected_files = forms.CharField(label="Injected Files")
|
||||||
|
injected_file_content_bytes = forms.CharField(label="Injected File Content Bytes")
|
||||||
|
cores = forms.CharField(label="VCPUs")
|
||||||
|
instances = forms.CharField(label="Instances")
|
||||||
|
volumes = forms.CharField(label="Volumes")
|
||||||
|
gigabytes = forms.CharField(label="Gigabytes")
|
||||||
|
ram = forms.CharField(label="RAM (in MB)")
|
||||||
|
floating_ips = forms.CharField(label="Floating IPs")
|
||||||
|
|
||||||
|
def handle(self, request, data):
|
||||||
|
try:
|
||||||
|
api.admin_api(request).quota_sets.update(data['tenant_id'],
|
||||||
|
metadata_items=data['metadata_items'],
|
||||||
|
injected_file_content_bytes=
|
||||||
|
data['injected_file_content_bytes'],
|
||||||
|
volumes=data['volumes'],
|
||||||
|
gigabytes=data['gigabytes'],
|
||||||
|
ram=int(data['ram']) * 100,
|
||||||
|
floating_ips=data['floating_ips'],
|
||||||
|
instances=data['instances'],
|
||||||
|
injected_files=data['injected_files'],
|
||||||
|
cores=data['cores'],
|
||||||
|
)
|
||||||
|
messages.success(request,
|
||||||
|
'Quotas for %s were successfully updated.'
|
||||||
|
% data['tenant_id'])
|
||||||
|
except api_exceptions.ApiException, e:
|
||||||
|
messages.error(request, 'Unable to update quotas: %s' % e.message)
|
||||||
|
return redirect('syspanel_tenants')
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def index(request):
|
def index(request):
|
||||||
@ -171,3 +203,32 @@ def users(request, tenant_id):
|
|||||||
'users': users,
|
'users': users,
|
||||||
'new_users': new_user_ids,
|
'new_users': new_user_ids,
|
||||||
}, context_instance = template.RequestContext(request))
|
}, context_instance = template.RequestContext(request))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def quotas(request, tenant_id):
|
||||||
|
for f in (UpdateQuotas,):
|
||||||
|
_, handled = f.maybe_handle(request)
|
||||||
|
if handled:
|
||||||
|
return handled
|
||||||
|
|
||||||
|
quotas = api.admin_api(request).quota_sets.get(tenant_id)
|
||||||
|
quota_set = {
|
||||||
|
'tenant_id': quotas.id,
|
||||||
|
'metadata_items': quotas.metadata_items,
|
||||||
|
'injected_file_content_bytes': quotas.injected_file_content_bytes,
|
||||||
|
'volumes': quotas.volumes,
|
||||||
|
'gigabytes': quotas.gigabytes,
|
||||||
|
'ram': int(quotas.ram) / 100,
|
||||||
|
'floating_ips': quotas.floating_ips,
|
||||||
|
'instances': quotas.instances,
|
||||||
|
'injected_files': quotas.injected_files,
|
||||||
|
'cores': quotas.cores,
|
||||||
|
}
|
||||||
|
form = UpdateQuotas(initial=quota_set)
|
||||||
|
|
||||||
|
return render_to_response(
|
||||||
|
'syspanel_tenant_quotas.html',{
|
||||||
|
'form': form,
|
||||||
|
'tenant_id': tenant_id,
|
||||||
|
'quotas': quotas,
|
||||||
|
}, context_instance = template.RequestContext(request))
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
{% extends "_quotas_form.html" %}
|
||||||
|
|
||||||
|
{% block submit %}
|
||||||
|
<input type="submit" value="Update Quotas" class="large-rounded" />
|
||||||
|
{% endblock %}
|
||||||
|
|
12
openstack-dashboard/dashboard/templates/_quotas_form.html
Normal file
12
openstack-dashboard/dashboard/templates/_quotas_form.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<form id="quotas_form" action="" 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 %}
|
||||||
|
{% block submit %}
|
||||||
|
{% endblock %}
|
||||||
|
</form>
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
{% load parse_date %}
|
{% load parse_date %}
|
||||||
<table class="wide">
|
<table id="instances" class="wide">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Id</th>
|
<th>Id</th>
|
||||||
<th>User</th>
|
<th>User</th>
|
||||||
|
@ -8,5 +8,6 @@
|
|||||||
<li><a {% if current_sidebar == "images" %} class="active" {% endif %} href="{% url syspanel_images %}">Images</a></li>
|
<li><a {% if current_sidebar == "images" %} class="active" {% endif %} href="{% url syspanel_images %}">Images</a></li>
|
||||||
<li><a {% if current_sidebar == "tenants" %} class="active" {% endif %} href="{% url syspanel_tenants %}">Tenants</a></li>
|
<li><a {% if current_sidebar == "tenants" %} class="active" {% endif %} href="{% url syspanel_tenants %}">Tenants</a></li>
|
||||||
<li><a {% if current_sidebar == "users" %} class="active" {% endif %} href="{% url syspanel_users %}">Users</a></li>
|
<li><a {% if current_sidebar == "users" %} class="active" {% endif %} href="{% url syspanel_users %}">Users</a></li>
|
||||||
|
<li><a {% if current_sidebar == "quotas" %} class="active" {% endif %} href="{% url syspanel_quotas %}">Quotas</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
<li>{% include "_tenant_delete.html" with form=tenant_delete_form %}</li>
|
<li>{% include "_tenant_delete.html" with form=tenant_delete_form %}</li>
|
||||||
<li><a href="{% url syspanel_tenant_update tenant.id %}">Edit</a></li>
|
<li><a href="{% url syspanel_tenant_update tenant.id %}">Edit</a></li>
|
||||||
<li><a href="{% url syspanel_tenant_users tenant.id %}">View Members</a></li>
|
<li><a href="{% url syspanel_tenant_users tenant.id %}">View Members</a></li>
|
||||||
|
<li><a href="{% url syspanel_tenant_quotas tenant.id %}">Modify Quotas</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
<div id='page_header'>
|
<div id='page_header'>
|
||||||
<h2><span>Compute:</span> Instances</h2>
|
<h2><span>Compute:</span> Instances</h2>
|
||||||
<p class='desc'><span>—</span> Instances are virtual servers launched from images.</p>
|
<p class='desc'><span>—</span> Instances are virtual servers launched from images.</p>
|
||||||
|
<div id="spinner" class="dash">Loading...</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% include "_messages.html" %}
|
{% include "_messages.html" %}
|
||||||
@ -41,3 +42,26 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block footer_js %}
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
$(function(){
|
||||||
|
$("#spinner").hide()
|
||||||
|
function loadInstances(){
|
||||||
|
$('#spinner').show();
|
||||||
|
$('#instances').load('{% url dash_instances_refresh request.user.tenant %}', function(){
|
||||||
|
$("#spinner").hide()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setInterval(function(){
|
||||||
|
loadInstances();
|
||||||
|
}, 15000);
|
||||||
|
|
||||||
|
$("a.refresh").click(function(e){
|
||||||
|
e.preventDefault()
|
||||||
|
loadInstances();
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
{% endblock footer_js %}
|
@ -24,11 +24,36 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% include '_launch.html' %}
|
{% include '_launch.html' %}
|
||||||
|
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<h3>Description:</h3>
|
<h3>Description:</h3>
|
||||||
<p>Specify the details for launching an instance.</p>
|
<p>Specify the details for launching an instance. Also please make note of the table below; all tenants have quotas which define the limit of resources you are allowed to provision.</p>
|
||||||
</div>
|
<table border="0">
|
||||||
|
<tr>
|
||||||
|
<th>Quota Name</th>
|
||||||
|
<th>Limit</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>RAM (MB)</td>
|
||||||
|
<td>{{quotas.ram}}MB</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Floating IPs</td>
|
||||||
|
<td>{{quotas.floating_ips}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Instances</td>
|
||||||
|
<td>{{quotas.instances}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Volumes</td>
|
||||||
|
<td>{{quotas.volumes}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Gigabytes</td>
|
||||||
|
<td>{{quotas.gigabytes}}GB</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
<div id='page_header'>
|
<div id='page_header'>
|
||||||
<h2><span>System Panel:</span> Instances</h2>
|
<h2><span>System Panel:</span> Instances</h2>
|
||||||
<p class='desc'><span>—</span> View all running instances other than VPNs.</p>
|
<p class='desc'><span>—</span> View all running instances other than VPNs.</p>
|
||||||
|
<div id="spinner" class="syspanel">Loading...</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% include "_messages.html" %}
|
{% include "_messages.html" %}
|
||||||
@ -43,3 +44,25 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block footer_js %}
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
$(function(){
|
||||||
|
$("#spinner").hide()
|
||||||
|
function loadInstances(){
|
||||||
|
$('#spinner').show();
|
||||||
|
$('#instances').load('{% url syspanel_instances_refresh %}', function(){
|
||||||
|
$("#spinner").hide()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setInterval(function(){
|
||||||
|
loadInstances();
|
||||||
|
}, 15000);
|
||||||
|
|
||||||
|
$("a.refresh").click(function(e){
|
||||||
|
e.preventDefault()
|
||||||
|
loadInstances();
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
{% endblock footer_js %}
|
48
openstack-dashboard/dashboard/templates/syspanel_quotas.html
Normal file
48
openstack-dashboard/dashboard/templates/syspanel_quotas.html
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{% extends 'syspanel_base.html' %}
|
||||||
|
{# list of tenants #}
|
||||||
|
{# standard nav, sidebar, list of instances in main #}
|
||||||
|
|
||||||
|
{% block sidebar %}
|
||||||
|
{% with current_sidebar="quotas" %}
|
||||||
|
{{block.super}}
|
||||||
|
{% endwith %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<div id='page_header'>
|
||||||
|
<h2><span>System Panel:</span> Quotas</h2>
|
||||||
|
<p class='desc'><span>—</span>Default Quotas</p>
|
||||||
|
</div>
|
||||||
|
{% include "_messages.html" %}
|
||||||
|
<div class="main_content">
|
||||||
|
<div class='table_title wide'>
|
||||||
|
<h3>Default Quotas</h3>
|
||||||
|
<a class="refresh" title="Refresh" href="{% url syspanel_quotas %}">Refresh List</a>
|
||||||
|
<div class='search'>
|
||||||
|
<form action='' method='post'>
|
||||||
|
<fieldset>
|
||||||
|
<label for='table_search'>Search</label>
|
||||||
|
<input id='table_search' name='search' type='text' value='' />
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="wide">
|
||||||
|
<tr>
|
||||||
|
<th>Quota Name</th>
|
||||||
|
<th>Limit</th>
|
||||||
|
</tr>
|
||||||
|
{% for name,value in quotas.items %}
|
||||||
|
<tr>
|
||||||
|
<td>{{name}}</td>
|
||||||
|
<td>{{value}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<a id="tenant_create_link" class="action_link large-rounded" href="{% url syspanel_tenants_create %}">Create New Tenant </a>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
{% extends 'syspanel_base.html' %}
|
||||||
|
{# list of tenants #}
|
||||||
|
{# standard nav, sidebar, list of instances in main #}
|
||||||
|
|
||||||
|
{% block sidebar %}
|
||||||
|
{% with current_sidebar="tenants" %}
|
||||||
|
{{block.super}}
|
||||||
|
{% endwith %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<div id='page_header'>
|
||||||
|
<h2><span>System Panel:</span> Tenants</h2>
|
||||||
|
<p class='desc'><span>—</span>Manage Tenants Quotas</p>
|
||||||
|
</div>
|
||||||
|
{% include "_messages.html" %}
|
||||||
|
|
||||||
|
<div class="main_content">
|
||||||
|
<div class="dash_block wide form">
|
||||||
|
<div class='title_block'>
|
||||||
|
<h3>Update Tenant Quotas</h3>
|
||||||
|
</div>
|
||||||
|
{% include 'django_openstack/syspanel/_update_quotas_form.html' with form=form %}
|
||||||
|
|
||||||
|
<div class="right">
|
||||||
|
<h3>Description:</h3>
|
||||||
|
<p>From here you can edit quotas (max limits) for the tenant {{tenant_id}}.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
@ -1692,3 +1692,26 @@ li.title h4{
|
|||||||
margin-left: 25px;
|
margin-left: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#spinner {
|
||||||
|
background: url(../images/spinner.gif) top left no-repeat;
|
||||||
|
float: right;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
text-indent: -9999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spinner.dash {
|
||||||
|
position: relative;
|
||||||
|
right: 10px;
|
||||||
|
bottom: 0;
|
||||||
|
margin-bottom: -24px;
|
||||||
|
top: -10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spinner.syspanel {
|
||||||
|
position: relative;
|
||||||
|
right: 20px;
|
||||||
|
top: -24px;
|
||||||
|
bottom: 0;
|
||||||
|
margin-bottom: -24px;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user