diff --git a/LICENSE.md b/LICENSE.md
index 42e9839..06763cd 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2014 Florian Neagu
+Copyright (c) 2014 Florian Neagu - michaelneagu@gmail.com - https://github.com/k3oni/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/main/views.py b/main/views.py
index 90f7cb0..9e79bea 100755
--- a/main/views.py
+++ b/main/views.py
@@ -1,3 +1,25 @@
+#The MIT License (MIT)
+#
+#Copyright (c) 2014 Florian Neagu - michaelneagu@gmail.com - https://github.com/k3oni/
+#
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+#
+#The above copyright notice and this permission notice shall be included in all
+#copies or substantial portions of the Software.
+#
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+#SOFTWARE.
+
import socket, platform, os, multiprocessing, json
from datetime import timedelta
@@ -179,6 +201,29 @@ def get_disk():
return data
+def get_disk_rw():
+ """
+ Get the disk reads and writes
+ """
+ try:
+ pipe = os.popen("cat /proc/partitions | grep -v 'major' | awk '{print $4}'")
+ data = pipe.read().strip().split('\n')
+ pipe.close()
+
+ for i in data:
+ if i.isalpha():
+ data = []
+ pipe = os.popen("cat /proc/diskstats | grep -w '" + i + "'|awk '{print $4, $8}'")
+ rw = pipe.read().strip().split()
+ pipe.close()
+
+ data.append([i, rw[0], rw[1]])
+
+ except Exception,err:
+ data = str(err)
+
+ return data
+
def get_mem():
"""
Get memory usage
@@ -251,6 +296,7 @@ def getall(request):
return render_to_response('main.html', {'gethostname': get_hostname(),
'getplatform': get_platform(),
'getcpus': get_cpus(),
+ 'getdiskrw': get_disk_rw(),
'time_refresh': time_refresh,
'time_refresh_long': time_refresh_long,
'time_refresh_net': time_refresh_net,
diff --git a/pydash/settings.py b/pydash/settings.py
index 4b564c6..4e56a0a 100644
--- a/pydash/settings.py
+++ b/pydash/settings.py
@@ -36,7 +36,7 @@ TIME_JS_REFRESH = 30000
TIME_JS_REFRESH_LONG = 120000
TIME_JS_REFRESH_NET = 2000
-VERSION = 1.1
+VERSION = 1.2
ALLOWED_HOSTS = ['*']
diff --git a/pydash/urls.py b/pydash/urls.py
index f08a0be..4ef5663 100644
--- a/pydash/urls.py
+++ b/pydash/urls.py
@@ -16,13 +16,13 @@ urlpatterns = patterns('',
url(r'^main/$', 'main.views.getall', name='main'),
url(r'^info/uptime/$', 'usage.views.uptime', name='uptime'),
url(r'^info/memory/$', 'usage.views.memusage', name='memusage'),
- url(r'^info/users/$', 'usage.views.getusers', name='getusers'),
url(r'^info/cpuusage/$', 'usage.views.cpuusage', name='cpuusage'),
url(r'^info/getdisk/$', 'usage.views.getdisk', name='getdisk'),
url(r'^info/getusers/$', 'usage.views.getusers', name='getusers'),
url(r'^info/getips/$', 'usage.views.getips', name='getips'),
url(r'^info/gettraffic/$', 'usage.views.gettraffic', name='gettraffic'),
url(r'^info/proc/$', 'usage.views.getproc', name='getproc'),
+ url(r'^info/getdiskio/$', 'usage.views.getdiskio', name='getdiskio'),
url(r'^info/loadaverage/$', 'usage.views.loadaverage', name='loadaverage')
)
diff --git a/static/css/dashboard.css b/static/css/dashboard.css
index 337845c..b0b44ab 100644
--- a/static/css/dashboard.css
+++ b/static/css/dashboard.css
@@ -388,4 +388,19 @@ h6.bigstats {
padding: 0 0.3em;
border-style: solid;
}
-
+.diskr {
+ border-color: rgb(245,134,15);
+ margin: 0.5em;
+ border-style: solid;
+ border-width: 0 0 0 1em;
+ padding: 0 0.3em;
+ border-style: solid;
+}
+.diskw {
+ border-color: rgb(15,103,245);
+ margin: 0.5em;
+ border-style: solid;
+ border-width: 0 0 0 1em;
+ padding: 0 0.3em;
+ border-style: solid;
+}
diff --git a/templates/main.html b/templates/main.html
index 8323d15..9be9b94 100644
--- a/templates/main.html
+++ b/templates/main.html
@@ -200,58 +200,83 @@
+
+
-
+
+
+
@@ -412,6 +437,19 @@ var trf_ctx = $("#trfChart").get(0).getContext("2d");
trfChart.Line(data, options);
});
}
+
+var dsk_ctx = $("#dskChart").get(0).getContext("2d");
+ var dskChart = new Chart(dsk_ctx);
+ function disk_io(){
+ $.getJSON('/info/getdiskio/', function(data) {
+ var options = {
+ animation : false,
+ pointDotRadius : 2,
+ scaleLabel : "<%=value%>"
+ }
+ dskChart.Line(data, options);
+ });
+ }
var load_ctx = $("#loadChart").get(0).getContext("2d");
var loadChart = new Chart(load_ctx);
@@ -432,6 +470,7 @@ $(function() {
window.setInterval('load_average()', {{ time_refresh }});
window.setInterval('cpuu_usage()', {{ time_refresh }});
window.setInterval('traffic_usage()', {{ time_refresh_net }});
+ window.setInterval('disk_io()', {{ time_refresh_net }});
window.setInterval('dashboard.getUptime()', {{ time_refresh_long }});
window.setInterval('dashboard.getDisk()', {{ time_refresh_long }});
window.setInterval('dashboard.getUsers()', {{ time_refresh_long }});
@@ -443,6 +482,7 @@ $(function pageLoad() {
load_average();
cpuu_usage();
traffic_usage();
+ disk_io();
dashboard.getUptime();
dashboard.getDisk();
dashboard.getUsers();
diff --git a/usage/views.py b/usage/views.py
index 150be81..92a528a 100755
--- a/usage/views.py
+++ b/usage/views.py
@@ -1,3 +1,25 @@
+#The MIT License (MIT)
+#
+#Copyright (c) 2014 Florian Neagu - michaelneagu@gmail.com - https://github.com/k3oni/
+#
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+#
+#The above copyright notice and this permission notice shall be included in all
+#copies or substantial portions of the Software.
+#
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+#SOFTWARE.
+
import json
from django.shortcuts import render_to_response
from django.http import HttpResponse, HttpResponseRedirect
@@ -365,3 +387,120 @@ def gettraffic(request):
response.write(data)
return response
+
+@login_required(login_url='/login/')
+def getdiskio(request):
+ """
+ Return the reads and writes for the drive
+ """
+ datasets_in = []
+ datasets_in_i = []
+ datasets_out = []
+ datasets_out_o = []
+ json_diskrw = []
+ cookie_diskrw = {}
+
+ try:
+ diskrw = get_disk_rw()
+ diskrw = diskrw[0]
+
+ except Exception:
+ diskrw = 0
+
+ try:
+ cookies = request._cookies['diskrw']
+ except Exception:
+ cookies = None
+
+ if not cookies:
+ datasets_in.append(0)
+ datasets_in_i.append(0)
+ datasets_out.append(0)
+ datasets_out_o.append(0)
+ else:
+ datasets = eval(cookies)
+ datasets_in = datasets[0]
+ datasets_out = datasets[1]
+ datasets_in_i = datasets[2]
+ datasets_out_o = datasets[3]
+
+ if len(datasets_in) > 10:
+ while datasets_in:
+ del datasets_in[0]
+ if len(datasets_in) == 10:
+ break
+ if len(datasets_in_i) > 2:
+ while datasets_in_i:
+ del datasets_in_i[0]
+ if len(datasets_in_i) == 2:
+ break
+ if len(datasets_out) > 10:
+ while datasets_out:
+ del datasets_out[0]
+ if len(datasets_out) == 10:
+ break
+ if len(datasets_out_o) > 2:
+ while datasets_out_o:
+ del datasets_out_o[0]
+ if len(datasets_out_o) == 2:
+ break
+
+ if len(datasets_in_i) <= 1:
+ datasets_in_i.append(int(diskrw[1]))
+ if len(datasets_in_i) == 2:
+ datasets_in_i.append(int(diskrw[1]))
+ del datasets_in_i[0]
+ if len(datasets_out_o) <= 1:
+ datasets_out_o.append(int(diskrw[2]))
+ if len(datasets_out_o) == 2:
+ datasets_out_o.append(int(diskrw[2]))
+ del datasets_out_o[0]
+
+ dataset_in = (int((datasets_in_i[1] - datasets_in_i[0]) / ( time_refresh_net / 1000 )))
+ dataset_out = (int((datasets_out_o[1] - datasets_out_o[0]) / ( time_refresh_net / 1000 )))
+
+ if len(datasets_in) <= 9:
+ datasets_in.append(dataset_in)
+ if len(datasets_in) == 10:
+ datasets_in.append(dataset_in)
+ del datasets_in[0]
+ if len(datasets_out) <= 9:
+ datasets_out.append(dataset_out)
+ if len(datasets_out) == 10:
+ datasets_out.append(dataset_out)
+ del datasets_out[0]
+
+ # Some fix division by 0 Chart.js
+ if len(datasets_in) == 10:
+ if sum(datasets_in) == 0:
+ datasets_in[9] += 0.1
+ if sum(datasets_in) / 10 == datasets_in[0]:
+ datasets_in[9] += 0.1
+
+ disk_rw = {
+ 'labels': [""] * 10,
+ 'datasets': [
+ {
+ "fillColor": "rgba(245,134,15,0.5)",
+ "strokeColor": "rgba(245,134,15,1)",
+ "pointColor": "rgba(245,134,15,1)",
+ "pointStrokeColor": "#fff",
+ "data": datasets_in
+ },
+ {
+ "fillColor": "rgba(15,103,245,0.5)",
+ "strokeColor": "rgba(15,103,245,1)",
+ "pointColor": "rgba(15,103,245,1)",
+ "pointStrokeColor": "#fff",
+ "data": datasets_out
+ }
+ ]
+ }
+
+ cookie_diskrw = [datasets_in, datasets_out, datasets_in_i, datasets_out_o]
+ data = json.dumps(disk_rw)
+ response = HttpResponse()
+ response['Content-Type'] = "text/javascript"
+ response.cookies['diskrw'] = cookie_diskrw
+ response.write(data)
+ return response