Refactor disk and quota info (#1)

* Add WIP

* Fix typo

* Add disk macros

* Close tags

* Remove cruft

* Don't hover

* WIP glances

* Don't fill empty space

* remove bind mounts

* remove fuse entires also

* Rename to quota

* Hide drives

* Fix

* Fix function called

* Fix js

* Attempt at expanding card

* Fix expandable logic

* Don't adjust behavior every 4th item

* Right align

* Add logic to prevent errors when exactly 3 mounts
This commit is contained in:
liaralabs 2020-03-30 16:47:42 -07:00 committed by GitHub
parent e8ccbc8a03
commit 4db8ccede1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 249 additions and 43 deletions

View file

@ -40,6 +40,23 @@ def get_default_interface():
continue
return fields[0]
def get_mounts():
mounts = []
with open("/proc/mounts") as mount:
for line in mount:
fields = line.strip().split()
if fields[0].startswith("/dev"):
if ("boot" in fields[1]) or ("fuse" in fields):
continue
else:
mounts.append(fields[1])
with open("/etc/fstab") as fstab:
for line in fstab:
fields = line.strip().split()
if "bind" in str(fields):
mounts.remove(fields[1])
return mounts
def generate_page_list(user):
admin_user = current_app.config['ADMIN_USER']
pages = []

View file

@ -2,6 +2,29 @@
margin-bottom: 0;
}
.progress {
margin-bottom: 5px;
}
#diskinfo a.collapsed:after {
content: '+ Show More';
}
#diskinfo a:not(.collapsed):after {
content: '- Show Less';
}
#diskglances a.collapsed:after {
content: '+ Show More';
display: inline-block;
width: 100%;
text-align: right;
}
#diskglances a:not(.collapsed):after {
content: '- Show Less';
}
a[post=true] {
cursor: pointer;
}

View file

@ -104,7 +104,12 @@ def index(user):
# thread = Thread(target=current_speed)
# thread.start()
pages = generate_page_list(user)
return flask.render_template('index.html', title='{user} - swizzin dashboard'.format(user=user), user=user, pages=pages, async_mode=socketio.async_mode)
mounts = get_mounts()
if os.path.isfile("/install/.quota.lock"):
quota = True
else:
quota = False
return flask.render_template('index.html', title='{user} - swizzin dashboard'.format(user=user), user=user, pages=pages, quota=quota, mounts=mounts, async_mode=socketio.async_mode)
@socketio.on('connect', namespace='/websocket')
def socket_connect():
@ -228,12 +233,21 @@ def vnstat(user):
@app.route('/stats/disk')
@htpasswd.required
def disk_free(user):
location = "/"
mounts = get_mounts()
data = {}
for mount in mounts:
total, used, free, usage = disk_usage(mount)
data[mount] = {"disktotal": total, "diskused": used, "diskfree": free, "perutil": usage}
return flask.jsonify(data)
@app.route('/stats/quota')
@htpasswd.required
def quota_free(user):
if os.path.isfile("/install/.quota.lock"):
total, used, free, usage = quota_usage(user)
return flask.jsonify({"quota": {"disktotal": total, "diskused": used, "diskfree": free, "perutil": usage}})
else:
total, used, free, usage = disk_usage(location)
return flask.jsonify({"disktotal": total, "diskused": used, "diskfree": free, "perutil": usage})
return """Quota not installed"""
@app.route('/stats/boot')
@htpasswd.required

View file

@ -1,23 +1,6 @@
<div class="card border-dark mt-3">
<div class="card-header">Disk Info</div>
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="text-center">Used</h5>
<p class="text-center"><span id="diskused"></span></p>
</div>
<div class="col">
<h5 class="text-center">Free</h5>
<p class="text-center"><span id="diskfree"></span></p>
</div>
<div class="col">
<h5 class="text-center">Total</h5>
<p class="text-center"><span id="disktotal"></span></p>
</div>
</div>
<div class="progress">
<div id="diskprogress" class="progress-bar bg-warning" role="progressbar" style="" aria-valuenow="" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="text-center">You have used <span id="diskpercent"></span>% of your disk</p>
<div id="diskinfo" class="card-body">
{{macros.build_disk_info(mounts=mounts)}}
</div>
</div>

View file

@ -6,10 +6,12 @@
<h5 class="text-center">Load</h5>
<p class="text-center"><span id="loadindicator" class="systemindicator"></span></p>
</div>
{% if quota == True %}
<div class="col">
<h5 class="text-center">Disk</h5>
<p class="text-center"><span id="diskindicator" class="systemindicator"></span></p>
<p class="text-center"><span id="quotaindicator" class="systemindicator"></span></p>
</div>
{% endif %}
<div class="col">
<h5 class="text-center">RAM</h5>
<p class="text-center"><span id="ramindicator" class="systemindicator"></span></p>
@ -19,6 +21,9 @@
<p class="text-center"><span id="iowait-glance">--</span></p>
</div>
</div>
{% if (quota == False or config.ADMIN_USER == user) %}
{{macros.build_disk_glances(mounts=mounts)}}
{% endif %}
<h5 class="text-center">Uptime</h5>
<div class="countup text-center" id="uptime">
<p>

View file

@ -22,7 +22,12 @@
{% include 'glance.html' %}
{{ macros.build_app_table(apps=pages) }}
{% include 'systeminfo.html' %}
{% include 'diskinfo.html' %}
{% if quota == True %}
{% include 'quotainfo.html' %}
{% endif %}
{% if (quota == False or config.ADMIN_USER == user) %}
{% include 'diskinfo.html' %}
{% endif %}
{% include 'raminfo.html' %}
{% if (config.SHAREDSERVER == True or config.ADMIN_USER == user) %}
{% include 'netinfo.html' %}
@ -46,6 +51,29 @@
{{ macros.build_widget_js_shared() }}
{% endif %}
{% if quota == True %}
(function quotausage() {
$.get('{{ url_for('quota_free') }}', function(data) {
var percent = Math.trunc(data["quota"]['perutil']);
$("#quotafree").html(data["quota"]['diskfree']);
$("#quotaused").html(data["quota"]['diskused']);
$("#quotatotal").html(data["quota"]['disktotal']);
$("#quotapercent").html(data["quota"]['perutil']);
if (Number(data["quota"]['perutil']) > 90) {
$("#quotaindicator.systemindicator").addClass("bg-danger").removeClass("bg-success bg-warning");
$("#quotaprogress").css("width", percent + "%").attr("aria-valuenow", percent).addClass("bg-danger").removeClass("bg-success bg-warning");
} else if (Number(data["quota"]['perutil']) > 75) {
$("#quotaindicator.systemindicator").addClass("bg-warning").removeClass("bg-success bg-danger");
$("#quotaprogress").css("width", percent + "%").attr("aria-valuenow", percent).addClass("bg-warning").removeClass("bg-success bg-danger");
} else {
$("#quotaindicator.systemindicator").addClass("bg-success").removeClass("bg-warning bg-danger");
$("#quotaprogress").css("width", percent + "%").attr("aria-valuenow", percent).addClass("bg-success").removeClass("bg-danger bg-warning");
}
setTimeout(function(){quotausage()}, 60000);
});
})();
{% endif %}
</script>
</body>

View file

@ -133,7 +133,119 @@
</div>
{% endmacro %}
{% macro build_disk_info(mounts) %}
<table class="table table-sm table-dark table-borderless">
<thead class="table-active">
<tr>
<th scope="col" class="text-center">Mount</th>
<th scope="col" class="text-center">Used</th>
<th scope="col" class="text-center">Free</th>
<th scope="col" class="text-center">Total</th>
</tr>
</thead>
{% for mount in mounts %}
<tbody class="diskwidget">
<tr style="height: 15px;"></tr>
<tr>
<td>{{ mount }}</td>
<td id='{{ mount }}diskused' class="text-center"></td>
<td id='{{ mount }}diskfree'class="text-center"></td>
<td id='{{ mount }}disktotal' class="text-center"></td>
</tr>
<tr>
<td colspan="4" class="align-middle"><span class="progress"><div id='{{ mount }}diskprogress' class='progress-bar' role='progressbar' style='' aria-valuenow='' aria-valuemin='0' aria-valuemax='100'></div></span></td>
</tr>
<tr>
<td colspan="4" class="text-center"><span id='{{ mount }}diskpercent'></span>%</td>
</tr>
</tbody>
{% if (loop.index == 3 and not loop.last) %}
</table>
<table class="collapse" id="collapsediskinfo" aria-expanded="false">
{% endif %}
{% if loop.last %}
</table>
{% if loop.index > 3 %}
<a role="button" class="collapsed" data-toggle="collapse" href="#collapsediskinfo" aria-expanded="false" aria-controls="collapsediskinfo"></a>
{% endif %}
{% endif %}
{% endfor %}
{% endmacro %}
{% macro build_disk_glances(mounts) %}
<div id="diskglances">
<div class="row">
{% for mount in mounts %}
<div class="col">
<h5 class="text-center">{{ mount }}</h5>
<p class="text-center"><span id="{{ mount }}indicator" class="systemindicator"></span></p>
</div>
{% if (loop.index == 3 and not loop.last) %}
</div>
<div id="collapsediskglances" class="collapse row" aria-expanded="false">
{% endif %}
{% if loop.last %}
</div>
{% if loop.index > 3%}
<a role="button" class="collapsed" data-toggle="collapse" href="#collapsediskglances" aria-expanded="false" aria-controls="collapsediskinfo"></a>
{% endif %}
{% endif %}
{% endfor %}
</div>
{% endmacro %}
{% macro build_widget_js() %}
function getdisks() {
$('#diskinfo').html('')
var html =`
<table class="table table-sm table-hover table-dark table-borderless">
<thead class="table-active">
<tr>
<th scope="col" class="text-center">Mount</th>
<th scope="col" class="text-center">Used</th>
<th scope="col" class="text-center">Free</th>
<th scope="col" class="text-center">Total</th>
</tr>
</thead>
`
$.get('{{ url_for('disk_free') }}', function(data) {
var datalength = $(data).length
var i = 0
for (var mount in data) {
html += `
<tbody class="diskwidget">
<tr style="height: 15px;"></tr>
<tr>
<td>`+mount+`</td>
<td id='`+mount+`diskused' class="text-center"></td>
<td id='`+mount+`diskfree'class="text-center"></td>
<td id='`+mount+`disktotal' class="text-center"></td>
</tr>
<tr>
<td colspan="4" class="align-middle"><span class="progress"><div id='`+mount+`diskprogress' class='progress-bar bg-warning' role='progressbar' style='' aria-valuenow='' aria-valuemin='0' aria-valuemax='100'></div></span></td>
</tr>
<tr>
<td colspan="4" class="text-center"><span id='`+mount+`diskpercent'></span>%</td>
</tr>
</tbody>
`
if (i < $(data).length) {
html += ``
}
i++
}
html += `
</table>
`
$('#diskinfo').append(html)
}
);
}
//getdisks()
function appstatus(){
$.get("{{ url_for('app_status') }}", function(data){
for (var apps in data) {
@ -177,24 +289,25 @@ appstatus();
(function diskusage() {
$.get('{{ url_for('disk_free') }}', function(data) {
var percent = Math.trunc(data['perutil']);
$("#diskfree").html(data['diskfree']);
$("#diskused").html(data['diskused']);
$("#disktotal").html(data['disktotal']);
$("#diskpercent").html(data['perutil']);
if (Number(data['perutil']) > 90) {
$("#diskindicator.systemindicator").addClass("bg-danger").removeClass("bg-success bg-warning");
$("#diskprogress").css("width", percent + "%").attr("aria-valuenow", percent).addClass("bg-danger").removeClass("bg-success bg-warning");
} else if (Number(data['perutil']) > 75) {
$("#diskindicator.systemindicator").addClass("bg-warning").removeClass("bg-success bg-danger");
$("#diskprogress").css("width", percent + "%").attr("aria-valuenow", percent).addClass("bg-warning").removeClass("bg-success bg-danger");
} else {
$("#diskindicator.systemindicator").addClass("bg-success").removeClass("bg-warning bg-danger");
$("#diskprogress").css("width", percent + "%").attr("aria-valuenow", percent).addClass("bg-success").removeClass("bg-danger bg-warning");
}
setTimeout(function(){diskusage()}, 60000);
}
);
for (var mount in data) {
var percent = Math.trunc(data[mount]['perutil']);
$("#"+$.escapeSelector(mount)+"diskfree").html(data[mount]['diskfree']);
$("#"+$.escapeSelector(mount)+"diskused").html(data[mount]['diskused']);
$("#"+$.escapeSelector(mount)+"disktotal").html(data[mount]['disktotal']);
$("#"+$.escapeSelector(mount)+"diskpercent").html(data[mount]['perutil']);
if (Number(data[mount]['perutil']) > 90) {
$("#"+$.escapeSelector(mount)+"indicator.systemindicator").addClass("bg-danger").removeClass("bg-success bg-warning");
$("#"+$.escapeSelector(mount)+"diskprogress").css("width", percent + "%").attr("aria-valuenow", percent).addClass("bg-danger").removeClass("bg-success bg-warning");
} else if (Number(data[mount]['perutil']) > 75) {
$("#"+$.escapeSelector(mount)+"indicator.systemindicator").addClass("bg-warning").removeClass("bg-success bg-danger");
$("#"+$.escapeSelector(mount)+"diskprogress").css("width", percent + "%").attr("aria-valuenow", percent).addClass("bg-warning").removeClass("bg-success bg-danger");
} else {
$("#"+$.escapeSelector(mount)+"indicator.systemindicator").addClass("bg-success").removeClass("bg-warning bg-danger");
$("#"+$.escapeSelector(mount)+"diskprogress").css("width", percent + "%").attr("aria-valuenow", percent).addClass("bg-success").removeClass("bg-danger bg-warning");
}
}
setTimeout(function(){diskusage()}, 60000);
});
})();
(function ramusage() {

23
templates/quotainfo.html Normal file
View file

@ -0,0 +1,23 @@
<div class="card border-dark mt-3">
<div class="card-header">Disk Quota Info</div>
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="text-center">Used</h5>
<p class="text-center"><span id="quotaused"></span></p>
</div>
<div class="col">
<h5 class="text-center">Free</h5>
<p class="text-center"><span id="quotafree"></span></p>
</div>
<div class="col">
<h5 class="text-center">Total</h5>
<p class="text-center"><span id="quotatotal"></span></p>
</div>
</div>
<div class="progress">
<div id="quotaprogress" class="progress-bar bg-warning" role="progressbar" style="" aria-valuenow="" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="text-center">You have used <span id="quotapercent"></span>% of your disk quota</p>
</div>
</div>