1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2025-02-06 20:45:18 +00:00

Additional changes

This commit is contained in:
Bandic007 2018-09-27 11:54:11 +03:00
parent e44e01cad4
commit 40738d7920
17 changed files with 289 additions and 19 deletions

View file

@ -11,6 +11,9 @@
<li class="active"> <li class="active">
<i class="fa fa-dashboard"></i> {% trans "Overview" %} <i class="fa fa-dashboard"></i> {% trans "Overview" %}
</li> </li>
<li>
<i class="fa fa-server"></i> <a href="{% url 'compute_instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li> <li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a> <i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li> </li>

View file

@ -1,9 +1,22 @@
from django.conf.urls import url from django.conf.urls import url
from . import views from storages.views import storages, storage
from networks.views import networks, network
from secrets.views import secrets
from create.views import create_instance
from interfaces.views import interfaces, interface
from computes.views import overview, compute_graph
from instances.views import instances
urlpatterns = [ urlpatterns = [
url(r'^$', views.computes, name='computes'), url(r'^(?P<compute_id>[0-9]+)/$', overview, name='overview'),
url(r'^overview/(?P<compute_id>[0-9]+)/$', views.overview, name='overview'), url(r'^(?P<compute_id>[0-9]+)/statistics$', compute_graph, name='compute_graph'),
url(r'^statistics/(?P<compute_id>[0-9]+)/$', url(r'^(?P<compute_id>[0-9]+)/instances/$', instances, name='compute_instances'),
views.compute_graph, name='compute_graph'), url(r'^(?P<compute_id>[0-9]+)/storages/$', storages, name='storages'),
url(r'^(?P<compute_id>[0-9]+)/storage/(?P<pool>[\w\-\.\/]+)/$', storage, name='storage'),
url(r'^(?P<compute_id>[0-9]+)/networks/$', networks, name='networks'),
url(r'^(?P<compute_id>[0-9]+)/network/(?P<pool>[\w\-\.]+)/$', network, name='network'),
url(r'^(?P<compute_id>[0-9]+)/interfaces/$', interfaces, name='interfaces'),
url(r'^(?P<compute_id>[0-9]+)/interface/(?P<iface>[\w\-\.\:]+)/$', interface, name='interface'),
url(r'^(?P<compute_id>[0-9]+)/secrets/$', secrets, name='secrets'),
url(r'^(?P<compute_id>[0-9]+)/create/$', create_instance, name='create_instance'),
] ]

View file

@ -134,6 +134,28 @@ def computes(request):
error_messages.append(msg_err.as_text()) error_messages.append(msg_err.as_text())
return render(request, 'computes.html', locals()) return render(request, 'computes.html', locals())
@login_required
def compute_instances(request, compute_id):
"""
:param request:
:return:
"""
if not request.user.is_superuser:
return HttpResponseRedirect(reverse('index'))
error_messages = []
compute = get_object_or_404(Compute, pk=compute_id)
try:
conn = wvmHostDetails(compute.hostname,
compute.login,
compute.password,
compute.type)
hostname, host_arch, host_memory, logical_cpu, model_cpu, uri_conn = conn.get_node_info()
hypervisor = conn.hypervisor_type()
mem_usage = conn.get_memory_usage()
conn.close()
except libvirtError as lib_err:
error_messages.append(lib_err)
return render(request, 'compute_instances.html', locals())
@login_required @login_required
def overview(request, compute_id): def overview(request, compute_id):

View file

@ -233,7 +233,7 @@
</li> </li>
<li> <li>
<label for="noVNC_setting_host">Host:</label> <label for="noVNC_setting_host">Host:</label>
<input id="noVNC_setting_host" value="{{ ws_host }}"/> <input id="noVNC_setting_host" value="{{ ws_host }}{{ ws_path }}"/>
</li> </li>
<li> <li>
<label for="noVNC_setting_port">Port:</label> <label for="noVNC_setting_port">Port:</label>
@ -332,4 +332,4 @@
<source src="{% static "js/novnc/app/sounds/bell.oga" %}" type="audio/ogg"> <source src="{% static "js/novnc/app/sounds/bell.oga" %}" type="audio/ogg">
<source src="{% static "js/novnc/app/sounds/bell.mp3" %}" type="audio/mpeg"> <source src="{% static "js/novnc/app/sounds/bell.mp3" %}" type="audio/mpeg">
</audio> </audio>
{% endblock %} {% endblock %}

View file

@ -220,6 +220,7 @@
//var port = WebUtil.getConfigVar('port', window.location.port); //var port = WebUtil.getConfigVar('port', window.location.port);
var host = '{{ ws_host }}'; var host = '{{ ws_host }}';
var port = '{{ ws_port }}'; var port = '{{ ws_port }}';
var wspath = '{{ ws_path }}';
// if port == 80 (or 443) then it won't be present and should be // if port == 80 (or 443) then it won't be present and should be
// set manually // set manually
@ -263,7 +264,7 @@
url = 'ws'; url = 'ws';
} }
url += '://' + host; url += '://' + host + wspath;
if(port) { if(port) {
url += ':' + port; url += ':' + port;
} }

View file

@ -7,6 +7,8 @@ from instances.models import Instance
from vrtManager.instance import wvmInstance from vrtManager.instance import wvmInstance
from webvirtcloud.settings import WS_PORT from webvirtcloud.settings import WS_PORT
from webvirtcloud.settings import WS_PUBLIC_HOST from webvirtcloud.settings import WS_PUBLIC_HOST
from webvirtcloud.settings import WS_PUBLIC_PORT
from webvirtcloud.settings import WS_PUBLIC_PATH
from libvirt import libvirtError from libvirt import libvirtError
@ -40,8 +42,9 @@ def console(request):
console_websocket_port = None console_websocket_port = None
console_passwd = None console_passwd = None
ws_port = console_websocket_port if console_websocket_port else WS_PORT ws_port = console_websocket_port if console_websocket_port else WS_PUBLIC_PORT
ws_host = WS_PUBLIC_HOST if WS_PUBLIC_HOST else request.get_host() ws_host = WS_PUBLIC_HOST if WS_PUBLIC_HOST else request.get_host()
ws_path = WS_PUBLIC_PATH if WS_PUBLIC_PATH else '/'
if ':' in ws_host: if ':' in ws_host:
ws_host = re.sub(':[0-9]+', '', ws_host) ws_host = re.sub(':[0-9]+', '', ws_host)

View file

@ -0,0 +1,199 @@
{% extends "base.html" %}
{% load i18n %}
{% load staticfiles %}
{% block title %}{% trans "Instances" %} - {{ compute.name }}{% endblock %}
{% block style %}
<link rel="stylesheet" href="{% static "css/sortable-theme-bootstrap.css" %}" />
{% endblock %}
{% block content %}
<!-- Page Heading -->
<div class="row">
<div class="col-lg-12">
{% if request.user.is_superuser %}
{% include 'create_inst_block.html' %}
{% endif %}
{% if all_host_vms or all_user_vms %}
<div class="pull-right search">
<input id="filter" class="form-control" type="text" placeholder="Search">
</div>
{% endif %}
<h1 class="page-header">{{ compute.name }}</h1>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<ol class="breadcrumb">
<li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li>
<li>
<i class="fa fa-server"></i> {% trans "Instances" %}
</li>
<li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li>
<li>
<i class="fa fa-sitemap"></i> <a href="{% url 'networks' compute.id %}">{% trans "Networks" %}</a>
</li>
<li>
<i class="fa fa-wifi"></i> <a href="{% url 'interfaces' compute.id %}">{% trans "Interfaces" %}</a>
</li>
<li>
<i class="fa fa-filter"></i> <a href="{% url 'nwfilters' compute.id %}">{% trans "NWFilters" %}</a>
</li>
<li>
<i class="fa fa-key"></i> <a href="{% url 'secrets' compute.id %}">{% trans "Secrets" %}</a>
</li>
</ol>
</div>
</div>
<!-- /.row -->
{% include 'errors_block.html' %}
<div class="row">
{% if not all_host_vms %}
<div class="col-lg-12">
<div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<i class="fa fa-exclamation-triangle"></i> <strong>{% trans "Warning:" %}</strong> {% trans "Hypervisor doesn't have any instances" %}
</div>
</div>
{% else %}
<div class="col-lg-12">
<table class="table table-hover table-striped sortable-theme-bootstrap" data-sortable>
<thead>
<tr>
<th>Name<br>Description</th>
<th>Host<br>User</th>
<th>Status</th>
<th>VCPU</th>
<th>Memory</th>
<th data-sortable="false" style="width:205px;">Actions</th>
</tr>
</thead>
<tbody class="searchable">
{% for host, inst in all_host_vms.items %}
{% for vm, info in inst.items %}
<tr>
<td><a href="{% url 'instance' host.0 vm %}">{{ vm }}</a><br><small><em>{{ info.title }}</em></small></td>
<td><a href="{% url 'overview' host.0 %}">{{ host.1 }}</a><br><small><em>{% if info.userinstances.count > 0 %}{{ info.userinstances.first_user.user.username }}{% if info.userinstances.count > 1 %} (+{{ info.userinstances.count|add:"-1" }}){% endif %}{% endif %}</em></small></td>
<td>
{% ifequal info.status 1 %}<span class="text-success">{% trans "Active" %}</span>{% endifequal %}
{% ifequal info.status 5 %}<span class="text-danger">{% trans "Off" %}</span>{% endifequal %}
{% ifequal info.status 3 %}<span class="text-warning">{% trans "Suspend" %}</span>{% endifequal %}
</td>
<td>{{ info.vcpu }}</td>
<td>{{ info.memory|filesizeformat }}</td>
<td><form action="" method="post" role="form">{% csrf_token %}
<input type="hidden" name="name" value="{{ vm }}"/>
<input type="hidden" name="compute_id" value="{{ host.0 }}"/>
{% ifequal info.status 5 %}
{% if info.is_template %}
<button class="btn btn-sm btn-default" type="button" name="clone" title="{% trans "Clone" %}" onclick="goto_instance_clone({{ host.0 }}, '{{ vm }}');">
<span class="glyphicon glyphicon-duplicate"></span>
</button>
{% else %}
<button class="btn btn-sm btn-default" type="submit" name="poweron" title="{% trans "Power On" %}">
<span class="glyphicon glyphicon-play"></span>
</button>
{% endif %}
<button class="btn btn-sm btn-default disabled" title="{% trans "Suspend" %}">
<span class="glyphicon glyphicon-pause"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Off" %}">
<span class="glyphicon glyphicon-off"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Cycle" %}">
<span class="glyphicon glyphicon-refresh"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "VNC Console" %}">
<span class="glyphicon glyphicon-eye-open"></span>
</button>
{% endifequal %}
{% ifequal info.status 3 %}
<button class="btn btn-sm btn-default" type="submit" name="resume" title="{% trans "Resume" %}">
<span class="glyphicon glyphicon-play"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Suspend" %}">
<span class="glyphicon glyphicon-pause"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Off" %}">
<span class="glyphicon glyphicon-off"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Cycle" %}">
<span class="glyphicon glyphicon-refresh"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "VNC Console" %}">
<span class="glyphicon glyphicon-eye-open"></span>
</button>
{% endifequal %}
{% ifequal info.status 1 %}
<button class="btn btn-sm btn-default disabled" title="{% trans "Power On" %}">
<span class="glyphicon glyphicon-play"></span>
</button>
<button class="btn btn-sm btn-default" type="submit" name="suspend" title="{% trans "Suspend" %}">
<span class="glyphicon glyphicon-pause"></span>
</button>
<button class="btn btn-sm btn-default" type="submit" name="poweroff" title="{% trans "Power Off" %}" onclick="return confirm('Are you sure?')">
<span class="glyphicon glyphicon-off"></span>
</button>
<button class="btn btn-sm btn-default" type="submit" name="powercycle" title="{% trans "Power Cycle" %}" onclick="return confirm('Are you sure?')">
<span class="glyphicon glyphicon-refresh"></span>
</button>
<a href="#" class="btn btn-sm btn-default" onclick='open_console("{{ host.0 }}-{{ info.uuid }}")' title="{% trans "Console" %}">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
{% endifequal %}
</form>
</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
{% endblock %}
{% block script %}
<script src="{% static "js/sortable.min.js" %}"></script>
<script>
function open_console(uuid) {
window.open("{% url 'console' %}?token=" + uuid, "", "width=850,height=485");
}
</script>
<script>
function filter_table() {
var rex = new RegExp($(this).val(), 'i');
$('.searchable tr').hide();
$('.searchable tr').filter(function () {
return rex.test($(this).text());
}).show();
Cookies.set("instances_filter", $(this).val(), { expires: 1 });
}
$(document).ready(function () {
instances_filter_cookie = Cookies.get("instances_filter");
if (instances_filter_cookie) {
$('#filter').val(instances_filter_cookie);
$('#filter').each(filter_table);
}
(function ($) {
$('#filter').keyup(filter_table)
}(jQuery));
});
</script>
<script>
function goto_instance_clone(compute, instance) {
window.location = "/instance/" + compute + "/" + instance + "/#clone";
}
</script>
{% if request.user.is_superuser %}
<script>
function goto_compute() {
var compute = $("#compute_select").val();
window.location = "/compute/" + compute + "/create/";
}
</script>
{% endif %}
{% endblock %}

View file

@ -15,6 +15,7 @@
{% for host, inst in all_host_vms.items %} {% for host, inst in all_host_vms.items %}
<tr class="active" style="font-weight: bold;border-bottom: 2px solid darkgray;border-top: 2px solid darkgray;"> <tr class="active" style="font-weight: bold;border-bottom: 2px solid darkgray;border-top: 2px solid darkgray;">
<td> <td>
<span style="text-align:center;">{{ inst.items|length }}</span>
<span id="collapse_host_instances_{{ host.1 }}" class="glyphicon glyphicon-chevron-up" onclick="hide_host_instances('{{ host.1 }}');"></span> <span id="collapse_host_instances_{{ host.1 }}" class="glyphicon glyphicon-chevron-up" onclick="hide_host_instances('{{ host.1 }}');"></span>
</td> </td>
<td><a href="{% url 'overview' host.0 %}">{{ host.1 }}</a></td> <td><a href="{% url 'overview' host.0 %}">{{ host.1 }}</a></td>

View file

@ -38,7 +38,7 @@ def index(request):
@login_required @login_required
def instances(request): def instances(request, compute_id=None):
""" """
:param request: :param request:
:return: :return:
@ -47,7 +47,11 @@ def instances(request):
error_messages = [] error_messages = []
all_host_vms = {} all_host_vms = {}
all_user_vms = {} all_user_vms = {}
computes = Compute.objects.all().order_by("name")
if not compute_id:
computes = Compute.objects.all().order_by("name")
else:
computes = [Compute.objects.get(id=compute_id),]
def get_userinstances_info(instance): def get_userinstances_info(instance):
info = {} info = {}
@ -195,8 +199,11 @@ def instances(request):
view_style = settings.VIEW_INSTANCES_LIST_STYLE view_style = settings.VIEW_INSTANCES_LIST_STYLE
return render(request, 'instances.html', locals()) if compute_id:
compute = computes[0]
return render(request, 'compute_instances.html', locals())
return render(request, 'instances.html', locals())
@login_required @login_required
def instance(request, compute_id, vname): def instance(request, compute_id, vname):

View file

@ -12,6 +12,9 @@
<li class="active"> <li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a> <i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li> </li>
<li class="active">
<i class="fa fa-server"></i> <a href="{% url 'compute_instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li> <li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a> <i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li> </li>
@ -94,4 +97,4 @@
}).change(); }).change();
}); });
</script> </script>
{% endblock %} {% endblock %}

View file

@ -11,6 +11,9 @@
<li class="active"> <li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a> <i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li> </li>
<li class="active">
<i class="fa fa-server"></i> <a href="{% url 'compute_instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li> <li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a> <i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li> </li>
@ -80,4 +83,4 @@
}).change(); }).change();
}); });
</script> </script>
{% endblock %} {% endblock %}

View file

@ -12,6 +12,9 @@
<li class="active"> <li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a> <i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li> </li>
<li>
<i class="fa fa-server"></i> <a href="{% url 'compute_instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li> <li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a> <i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li> </li>

View file

@ -10,11 +10,14 @@
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">
{% include 'create_secret_block.html' %} {% include 'create_secret_block.html' %}
<h1 class="page-header">{% trans "Secrets" %}</h1> <h1 class="page-header">{{ compute.name }}</h1>
<ol class="breadcrumb"> <ol class="breadcrumb">
<li class="active"> <li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a> <i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li> </li>
<li class="active">
<i class="fa fa-server"></i> <a href="{% url 'compute_instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li> <li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a> <i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li> </li>
@ -122,4 +125,4 @@
{% endblock %} {% endblock %}
{% block script %} {% block script %}
<script src="{% static "js/sortable.min.js" %}"></script> <script src="{% static "js/sortable.min.js" %}"></script>
{% endblock %} {% endblock %}

View file

@ -1,2 +1,2 @@
/*! sortable.js 0.8.0 */ /*! sortable.js 0.8.0 */
(function(){var a,b,c,d,e,f,g;a="table[data-sortable]",d=/^-?[£$¤]?[\d,.]+%?$/,g=/^\s+|\s+$/g,c=["click"],f="ontouchstart"in document.documentElement,f&&c.push("touchstart"),b=function(a,b,c){return null!=a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent("on"+b,c)},e={init:function(b){var c,d,f,g,h;for(null==b&&(b={}),null==b.selector&&(b.selector=a),d=document.querySelectorAll(b.selector),h=[],f=0,g=d.length;g>f;f++)c=d[f],h.push(e.initTable(c));return h},initTable:function(a){var b,c,d,f,g,h;if(1===(null!=(h=a.tHead)?h.rows.length:void 0)&&"true"!==a.getAttribute("data-sortable-initialized")){for(a.setAttribute("data-sortable-initialized","true"),d=a.querySelectorAll("th"),b=f=0,g=d.length;g>f;b=++f)c=d[b],"false"!==c.getAttribute("data-sortable")&&e.setupClickableTH(a,c,b);return a}},setupClickableTH:function(a,d,f){var g,h,i,j,k,l;for(i=e.getColumnType(a,f),h=function(b){var c,g,h,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D;if(b.handled===!0)return!1;for(b.handled=!0,m="true"===this.getAttribute("data-sorted"),n=this.getAttribute("data-sorted-direction"),h=m?"ascending"===n?"descending":"ascending":i.defaultSortDirection,p=this.parentNode.querySelectorAll("th"),s=0,w=p.length;w>s;s++)d=p[s],d.setAttribute("data-sorted","false"),d.removeAttribute("data-sorted-direction");if(this.setAttribute("data-sorted","true"),this.setAttribute("data-sorted-direction",h),o=a.tBodies[0],l=[],m){for(D=o.rows,v=0,z=D.length;z>v;v++)g=D[v],l.push(g);for(l.reverse(),B=0,A=l.length;A>B;B++)k=l[B],o.appendChild(k)}else{for(r=null!=i.compare?i.compare:function(a,b){return b-a},c=function(a,b){return a[0]===b[0]?a[2]-b[2]:i.reverse?r(b[0],a[0]):r(a[0],b[0])},C=o.rows,j=t=0,x=C.length;x>t;j=++t)k=C[j],q=e.getNodeValue(k.cells[f]),null!=i.comparator&&(q=i.comparator(q)),l.push([q,k,j]);for(l.sort(c),u=0,y=l.length;y>u;u++)k=l[u],o.appendChild(k[1])}return"function"==typeof window.CustomEvent&&"function"==typeof a.dispatchEvent?a.dispatchEvent(new CustomEvent("Sortable.sorted",{bubbles:!0})):void 0},l=[],j=0,k=c.length;k>j;j++)g=c[j],l.push(b(d,g,h));return l},getColumnType:function(a,b){var c,d,f,g,h,i,j,k,l,m,n;if(d=null!=(l=a.querySelectorAll("th")[b])?l.getAttribute("data-sortable-type"):void 0,null!=d)return e.typesObject[d];for(m=a.tBodies[0].rows,h=0,j=m.length;j>h;h++)for(c=m[h],f=e.getNodeValue(c.cells[b]),n=e.types,i=0,k=n.length;k>i;i++)if(g=n[i],g.match(f))return g;return e.typesObject.alpha},getNodeValue:function(a){var b;return a?(b=a.getAttribute("data-value"),null!==b?b:"undefined"!=typeof a.innerText?a.innerText.replace(g,""):a.textContent.replace(g,"")):""},setupTypes:function(a){var b,c,d,f;for(e.types=a,e.typesObject={},f=[],c=0,d=a.length;d>c;c++)b=a[c],f.push(e.typesObject[b.name]=b);return f}},e.setupTypes([{name:"numeric",defaultSortDirection:"descending",match:function(a){return a.match(d)},comparator:function(a){return parseFloat(a.replace(/[^0-9.-]/g,""),10)||0}},{name:"date",defaultSortDirection:"ascending",reverse:!0,match:function(a){return!isNaN(Date.parse(a))},comparator:function(a){return Date.parse(a)||0}},{name:"alpha",defaultSortDirection:"ascending",match:function(){return!0},compare:function(a,b){return a.localeCompare(b)}}]),setTimeout(e.init,0),"function"==typeof define&&define.amd?define(function(){return e}):"undefined"!=typeof exports?module.exports=e:window.Sortable=e}).call(this); (function(){var a,b,c,d,e,f,g;a="table[data-sortable]",d=/^-?[£$¤]?[\d,.]+%?$/,g=/^\s+|\s+$/g,c=["click"],f="ontouchstart"in document.documentElement,f&&c.push("touchstart"),b=function(a,b,c){return null!=a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent("on"+b,c)},e={init:function(b){var c,d,f,g,h;for(null==b&&(b={}),null==b.selector&&(b.selector=a),d=document.querySelectorAll(b.selector),h=[],f=0,g=d.length;g>f;f++)c=d[f],h.push(e.initTable(c));return h},initTable:function(a){var b,c,d,f,g,h;if(1===(null!=(h=a.tHead)?h.rows.length:void 0)&&"true"!==a.getAttribute("data-sortable-initialized")){for(a.setAttribute("data-sortable-initialized","true"),d=a.querySelectorAll("th"),b=f=0,g=d.length;g>f;b=++f)c=d[b],"false"!==c.getAttribute("data-sortable")&&e.setupClickableTH(a,c,b);return a}},setupClickableTH:function(a,d,f){var g,h,i,j,k,l;for(i=e.getColumnType(a,f),h=function(b){var c,g,h,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D;if(b.handled===!0)return!1;for(b.handled=!0,m="true"===this.getAttribute("data-sorted"),n=this.getAttribute("data-sorted-direction"),h=m?"ascending"===n?"descending":"ascending":i.defaultSortDirection,p=this.parentNode.querySelectorAll("th"),s=0,w=p.length;w>s;s++)d=p[s],d.setAttribute("data-sorted","false"),d.removeAttribute("data-sorted-direction");if(this.setAttribute("data-sorted","true"),this.setAttribute("data-sorted-direction",h),o=a.tBodies[0],l=[],m){for(D=o.rows,v=0,z=D.length;z>v;v++)g=D[v],l.push(g);for(l.reverse(),B=0,A=l.length;A>B;B++)k=l[B],o.appendChild(k)}else{for(r=null!=i.compare?i.compare:function(a,b){return b-a},c=function(a,b){return a[0]===b[0]?a[2]-b[2]:i.reverse?r(b[0],a[0]):r(a[0],b[0])},C=o.rows,j=t=0,x=C.length;x>t;j=++t)k=C[j],q=e.getNodeValue(k.cells[f]),null!=i.comparator&&(q=i.comparator(q)),l.push([q,k,j]);for(l.sort(c),u=0,y=l.length;y>u;u++)k=l[u],o.appendChild(k[1])}return"function"==typeof window.CustomEvent&&"function"==typeof a.dispatchEvent?a.dispatchEvent(new CustomEvent("Sortable.sorted",{bubbles:!0})):void 0},l=[],j=0,k=c.length;k>j;j++)g=c[j],l.push(b(d,g,h));return l},getColumnType:function(a,b){var c,d,f,g,h,i,j,k,l,m,n;if(d=null!=(l=a.querySelectorAll("th")[b])?l.getAttribute("data-sortable-type"):void 0,null!=d)return e.typesObject[d];for(m=a.tBodies[0].rows,h=0,j=m.length;j>h;h++)for(c=m[h],f=e.getNodeValue(c.cells[b]),n=e.types,i=0,k=n.length;k>i;i++)if(g=n[i],g.match(f))return g;return e.typesObject.alpha},getNodeValue:function(a){var b;return a?(b=a.getAttribute("data-value"),null!==b?b:"undefined"!=typeof a.innerText?a.innerText.replace(g,""):a.textContent.replace(g,"")):""},setupTypes:function(a){var b,c,d,f;for(e.types=a,e.typesObject={},f=[],c=0,d=a.length;d>c;c++)b=a[c],f.push(e.typesObject[b.name]=b);return f}},e.setupTypes([{name:"numeric",defaultSortDirection:"descending",match:function(a){return a.match(d)},comparator:function(a){return parseFloat(a.replace(/[^0-9.-]/g,""),10)||0}},{name:"date",defaultSortDirection:"ascending",reverse:!0,match:function(a){return!isNaN(Date.parse(a))},comparator:function(a){return Date.parse(a)||0}},{name:"alpha",defaultSortDirection:"ascending",match:function(){return!0},compare:function(a,b){return a.localeCompare(b)}}]),setTimeout(e.init,0),"function"==typeof define&&define.amd?define(function(){return e}):"undefined"!=typeof exports?module.exports=e:window.Sortable=e}).call(this);

View file

@ -45,7 +45,7 @@
<p>{% trans "Pool type:" %}</p> <p>{% trans "Pool type:" %}</p>
<p>{% trans "Pool path:" %}</p> <p>{% trans "Pool path:" %}</p>
<p>{% trans "Pool status:" %}</p> <p>{% trans "Pool status:" %}</p>
<p>{% trans "Size:" %} ({{ size|filesizeformat }} / {{ used|filesizeformat }})</p> <p>{% trans "Size:" %} (Used: {{ used|filesizeformat }} / From total: {{ size|filesizeformat }})</p>
<p>{% trans "State:" %}</p> <p>{% trans "State:" %}</p>
<p>{% trans "Autostart:" %}</p> <p>{% trans "Autostart:" %}</p>
</div> </div>

View file

@ -11,6 +11,9 @@
<li class="active"> <li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a> <i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li> </li>
<li class="active">
<i class="fa fa-server"></i> <a href="{% url 'compute_instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li> <li>
<i class="fa fa-hdd-o"></i> {% trans "Storages" %} <i class="fa fa-hdd-o"></i> {% trans "Storages" %}
</li> </li>
@ -67,4 +70,4 @@
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</div> </div>
{% endblock %} {% endblock %}

View file

@ -8,6 +8,7 @@ from create.views import create_instance
from interfaces.views import interfaces, interface from interfaces.views import interfaces, interface
from console.views import console from console.views import console
from nwfilters.views import nwfilters, nwfilter from nwfilters.views import nwfilters, nwfilter
from computes.views import computes
# from django.contrib import admin # from django.contrib import admin
urlpatterns = [ urlpatterns = [
@ -15,8 +16,13 @@ urlpatterns = [
url(r'^instances/$', instances, name='instances'), url(r'^instances/$', instances, name='instances'),
url(r'^instance/', include('instances.urls')), url(r'^instance/', include('instances.urls')),
url(r'^instances/$', instances, name='instances'),
url(r'^accounts/', include('accounts.urls')), url(r'^accounts/', include('accounts.urls')),
url(r'^computes/', include('computes.urls')), url(r'^computes/', include('computes.urls')),
url(r'^computes/', computes, name='computes'),
url(r'^logs/', include('logs.urls')), url(r'^logs/', include('logs.urls')),
url(r'^datasource/', include('datasource.urls')), url(r'^datasource/', include('datasource.urls')),