summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--inc/property.inc.php13
-rw-r--r--inc/taskmanager.inc.php40
-rw-r--r--modules/systemstatus.inc.php75
-rw-r--r--script/circles.min.js16
-rw-r--r--script/custom.js37
-rw-r--r--style/default.css8
-rw-r--r--templates/main-menu.html1
-rw-r--r--templates/systemstatus/_page.html13
-rw-r--r--templates/systemstatus/diskstat.html50
9 files changed, 218 insertions, 35 deletions
diff --git a/inc/property.inc.php b/inc/property.inc.php
index d62bbcb9..00c8018f 100644
--- a/inc/property.inc.php
+++ b/inc/property.inc.php
@@ -133,6 +133,19 @@ class Property
{
return json_decode(self::get('vmstore-config'), true);
}
+ public static function getVmStoreUrl()
+ {
+ $store = self::getVmStoreConfig();
+ if (!isset($store['storetype']))
+ return false;
+ if ($store['storetype'] === 'nfs')
+ return $store['nfsaddr'];
+ if ($store['storetype'] === 'cifs')
+ return $store['cifsaddr'];
+ if ($store['storetype'] === 'internal')
+ return '<local>';
+ return '<unknown>';
+ }
public static function setVmStoreConfig($value)
{
diff --git a/inc/taskmanager.inc.php b/inc/taskmanager.inc.php
index 99e35e94..dfacc5a7 100644
--- a/inc/taskmanager.inc.php
+++ b/inc/taskmanager.inc.php
@@ -18,7 +18,7 @@ class Taskmanager
socket_connect(self::$sock, '127.0.0.1', 9215);
}
- public static function submit($task, $data, $async = false)
+ public static function submit($task, $data = false, $async = false)
{
self::init();
$seq = (string) mt_rand();
@@ -67,21 +67,30 @@ class Taskmanager
return $reply;
}
- public static function waitComplete($taskId)
+ public static function waitComplete($task)
{
+ if (isset($task['id'])) {
+ if ($task['statusCode'] !== TASK_PROCESSING && $task['statusCode'] !== TASK_WAITING) {
+ self::release($task['id']);
+ return $task;
+ }
+ $task = $task['id'];
+ }
+ if (!is_string($task))
+ return false;
$done = false;
for ($i = 0; $i < 10; ++$i) {
- $status = self::status($taskId);
+ $status = self::status($task);
if (!isset($status['statusCode']))
break;
- if ($status['statusCode'] != TASK_PROCESSING && $status['statusCode'] != TASK_WAITING) {
+ if ($status['statusCode'] !== TASK_PROCESSING && $status['statusCode'] !== TASK_WAITING) {
$done = true;
break;
}
usleep(150000);
}
if ($done)
- self::release($taskId);
+ self::release($task);
return $status;
}
@@ -93,6 +102,27 @@ class Taskmanager
return true;
return false;
}
+
+ public static function addErrorMessage($task)
+ {
+ static $failure = false;
+ if ($task === false) {
+ if (!$failure) {
+ Message::addError('taskmanager-error');
+ $failure = true;
+ }
+ return;
+ }
+ if (!isset($task['statusCode'])) {
+ Message::addError('taskmanager-format');
+ return;
+ }
+ if (isset($task['data']['error'])) {
+ Message::addError('task-error', $task['statusCode'] . ' (' . $task['data']['error'] . ')');
+ return;
+ }
+ Message::addError('task-error', $task['statusCode']);
+ }
public static function release($taskId)
{
diff --git a/modules/systemstatus.inc.php b/modules/systemstatus.inc.php
new file mode 100644
index 00000000..c6d45812
--- /dev/null
+++ b/modules/systemstatus.inc.php
@@ -0,0 +1,75 @@
+<?php
+
+class Page_SystemStatus extends Page
+{
+
+ protected function doPreprocess()
+ {
+ User::load();
+
+ if (!User::isLoggedIn()) {
+ Util::redirect('?do=Main');
+ }
+ }
+
+ protected function doRender()
+ {
+ Render::addScriptTop('custom');
+ Render::addScriptBottom('circles.min');
+ Render::addTemplate('systemstatus/_page');
+ }
+
+ protected function doAjax()
+ {
+ User::load();
+
+ if (!User::isLoggedIn())
+ return;
+
+ $action = 'ajax' . Request::any('action');
+ if (method_exists($this, $action))
+ $this->$action();
+ else
+ echo "Action $action not known in " . get_class();
+ }
+
+ protected function ajaxDiskStat()
+ {
+ $task = Taskmanager::submit('DiskStat');
+ $task = Taskmanager::waitComplete($task);
+
+ if (!isset($task['data']['list']) || empty($task['data']['list'])) {
+ Taskmanager::addErrorMessage($task);
+ Message::renderList();
+ return;
+ }
+ $store = Property::getVmStoreUrl();
+ $storeUsage = false;
+ $systemUsage = false;
+ if ($store !== false) {
+ if ($store === '<local>')
+ $storePoint = '/';
+ else
+ $storePoint = '/srv/openslx/nfs';
+ foreach ($task['data']['list'] as $entry) {
+ if ($entry['mountPoint'] === $storePoint)
+ $storeUsage = array(
+ 'percent' => $entry['usedPercent'],
+ 'size' => Util::readableFileSize ($entry['sizeKb'] * 1024),
+ 'color' => dechex(round(($entry['usedPercent'] / 100) * 15)) . dechex(round(((100 - $entry['usedPercent']) / 100) * 15)) . '4'
+ );
+ if ($entry['mountPoint'] === '/')
+ $systemUsage = array(
+ 'percent' => $entry['usedPercent'],
+ 'size' => Util::readableFileSize ($entry['sizeKb'] * 1024),
+ 'color' => dechex(round(($entry['usedPercent'] / 100) * 15)) . dechex(round(((100 - $entry['usedPercent']) / 100) * 15)) . '4'
+ );
+ }
+ }
+ echo Render::parse('systemstatus/diskstat', array(
+ 'store' => $storeUsage,
+ 'system' => $systemUsage
+ ));
+ }
+
+}
diff --git a/script/circles.min.js b/script/circles.min.js
new file mode 100644
index 00000000..7349a408
--- /dev/null
+++ b/script/circles.min.js
@@ -0,0 +1,16 @@
+/**
+ * circles - v0.0.5 - 2014-05-30
+ *
+ * Copyright (c) 2014 lugolabs
+ * Licensed
+ */
+(function(){var l=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){setTimeout(a,1E3/60)},f=window.Circles=function(a){this._el=document.getElementById(a.id);if(null!==this._el){this._radius=a.radius||10;this._duration=void 0===a.duration?500:a.duration;this._value=0;this._maxValue=a.maxValue||100;this._text=void 0===a.text?function(a){return this.htmlifyNumber(a)}:a.text;this._strokeWidth=
+a.width||10;this._colors=a.colors||["#EEE","#F00"];this._textContainer=this._wrapContainer=this._movingPath=this._svg=null;this._wrpClass=a.wrpClass||"circles-wrp";this._textClass=a.textClass||"circles-text";var b=Math.PI/180*270;this._start=-Math.PI/180*90;this._startPrecise=this._precise(this._start);this._circ=b-this._start;this._generate().update(a.value||0)}};f.prototype={VERSION:"0.0.5",_generate:function(){this._svgSize=2*this._radius;this._radiusAdjusted=this._radius-this._strokeWidth/2;this._generateSvg()._generateText()._generateWrapper();
+this._el.innerHTML="";this._el.appendChild(this._wrapContainer);return this},_setPercentage:function(a){this._movingPath.setAttribute("d",this._calculatePath(a,!0));this._textContainer.innerHTML=this._getText(this.getValueFromPercent(a))},_generateWrapper:function(){this._wrapContainer=document.createElement("div");this._wrapContainer.className=this._wrpClass;this._wrapContainer.style.position="relative";this._wrapContainer.style.display="inline-block";this._wrapContainer.appendChild(this._svg);this._wrapContainer.appendChild(this._textContainer);
+return this},_generateText:function(){this._textContainer=document.createElement("div");this._textContainer.className=this._textClass;var a={position:"absolute",top:0,left:0,textAlign:"center",width:"100%",fontSize:.7*this._radius+"px",height:this._svgSize+"px",lineHeight:this._svgSize+"px"},b;for(b in a)this._textContainer.style[b]=a[b];this._textContainer.innerHTML=this._getText(0);return this},_getText:function(a){if(!this._text)return"";void 0===a&&(a=this._value);a=parseFloat(a.toFixed(2));return"function"===
+typeof this._text?this._text.call(this,a):this._text},_generateSvg:function(){this._svg=document.createElementNS("http://www.w3.org/2000/svg","svg");this._svg.setAttribute("xmlns","http://www.w3.org/2000/svg");this._svg.setAttribute("width",this._svgSize);this._svg.setAttribute("height",this._svgSize);this._generatePath(100,!1,this._colors[0])._generatePath(1,!0,this._colors[1]);this._movingPath=this._svg.getElementsByTagName("path")[1];return this},_generatePath:function(a,b,d){var c=document.createElementNS("http://www.w3.org/2000/svg",
+"path");c.setAttribute("fill","transparent");c.setAttribute("stroke",d);c.setAttribute("stroke-width",this._strokeWidth);c.setAttribute("d",this._calculatePath(a,b));this._svg.appendChild(c);return this},_calculatePath:function(a,b){var d=this._precise(this._start+a/100*this._circ);return this._arc(d,b)},_arc:function(a,b){var d=a-.001,c=a-this._startPrecise<Math.PI?0:1;return["M",this._radius+this._radiusAdjusted*Math.cos(this._startPrecise),this._radius+this._radiusAdjusted*Math.sin(this._startPrecise),
+"A",this._radiusAdjusted,this._radiusAdjusted,0,c,1,this._radius+this._radiusAdjusted*Math.cos(d),this._radius+this._radiusAdjusted*Math.sin(d),b?"":"Z"].join(" ")},_precise:function(a){return Math.round(1E3*a)/1E3},htmlifyNumber:function(a,b,d){b=b||"circles-integer";d=d||"circles-decimals";a=(a+"").split(".");b='<span class="'+b+'">'+a[0]+"</span>";1<a.length&&(b+='.<span class="'+d+'">'+a[1].substring(0,2)+"</span>");return b},updateRadius:function(a){this._radius=a;return this._generate().update(!0)},
+updateWidth:function(a){this._strokeWidth=a;return this._generate().update(!0)},updateColors:function(a){this._colors=a;var b=this._svg.getElementsByTagName("path");b[0].setAttribute("stroke",a[0]);b[1].setAttribute("stroke",a[1]);return this},getPercent:function(){return 100*this._value/this._maxValue},getValueFromPercent:function(a){return this._maxValue*a/100},getValue:function(){return this._value},getMaxValue:function(){return this._maxValue},update:function(a,b){if(!0===a)return this._setPercentage(this.getPercent()),
+this;if(this._value==a||isNaN(a))return this;void 0===b&&(b=this._duration);var d=this,c=d.getPercent(),g=1,e,h,f,k;this._value=Math.min(this._maxValue,Math.max(0,a));if(!b)return this._setPercentage(this.getPercent()),this;e=d.getPercent();h=e>c;g+=e%1;f=Math.floor(Math.abs(e-c)/g);k=b/f;(function m(a){c=h?c+g:c-g;if(h&&c>=e||!h&&c<=e)l(function(){d._setPercentage(e)});else{l(function(){d._setPercentage(c)});var b=Date.now();a=b-a;a>=k?m(b):setTimeout(function(){m(Date.now())},k-a)}})(Date.now());
+return this}};f.create=function(a){return new f(a)}})(); \ No newline at end of file
diff --git a/script/custom.js b/script/custom.js
index 12e760af..12fe817e 100644
--- a/script/custom.js
+++ b/script/custom.js
@@ -1,34 +1,11 @@
-/*
function loadContent(elem, source)
{
- $(elem).html('<div class="progress progress-striped active"><div class="progress-bar" style="width:100%"><span class="sr-only">In Progress....</span></div></div>');
- $(elem).load(source);
-}
-
-function selectDir(obj)
-{
- dirname = $(obj).parent().parent().find('td.isdir').text() + '/';
- console.log("CALLED! Dirname: " + dirname);
- $('td.fileEntry').each(function() {
- var text = $(this).text();
- if (text.length < dirname.length) return;
- if (text.substr(0, dirname.length) !== dirname) return;
- $(this).parent().find('.fileBox')[0].checked = obj.checked;
- });
-}
-*/
-
-function updater(url, postdata, callback)
-{
- var updateTimer = setInterval(function () {
- if (typeof $ === 'undefined')
+ var waitForIt = function() {
+ if (typeof $ === 'undefined') {
+ setTimeout(waitForIt, 50);
return;
- $.post(url, postdata, function (data, status) {
- if (!callback(data, status))
- clearInterval(updateTimer);
- }, 'json').fail(function (jqXHR, textStatus, errorThrown) {
- if (!callback(errorThrown, textStatus))
- clearInterval(updateTimer);
- });
- }, 1000);
+ }
+ $(elem).load(source);
+ }
+ waitForIt();
}
diff --git a/style/default.css b/style/default.css
index 813e54c2..1cac5ee7 100644
--- a/style/default.css
+++ b/style/default.css
@@ -103,3 +103,11 @@ body {
.slx-md-width {
max-width: 600px;
}
+
+.slx-storechart {
+ max-width: 140px;
+ margin: 5px;
+ padding: 3px;
+ float: left;
+ background-color: #eee;
+}
diff --git a/templates/main-menu.html b/templates/main-menu.html
index 50fdd211..06c3ed6b 100644
--- a/templates/main-menu.html
+++ b/templates/main-menu.html
@@ -27,6 +27,7 @@
</ul>
</li>
<li><a href="?do=News">News</a></li>
+ <li><a href="?do=SystemStatus">Status</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
{{{loginPanel}}}
diff --git a/templates/systemstatus/_page.html b/templates/systemstatus/_page.html
new file mode 100644
index 00000000..5b1ab375
--- /dev/null
+++ b/templates/systemstatus/_page.html
@@ -0,0 +1,13 @@
+<div class="container">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ Speicherplatz
+ </div>
+ <div class="panel-body" id="diskstat">
+ *dreh dreh dreh dreh*
+ </div>
+ </div>
+</div>
+<script type="text/javascript">
+ loadContent('#diskstat', '?do=SystemStatus&action=DiskStat');
+</script>
diff --git a/templates/systemstatus/diskstat.html b/templates/systemstatus/diskstat.html
new file mode 100644
index 00000000..e1d4a57e
--- /dev/null
+++ b/templates/systemstatus/diskstat.html
@@ -0,0 +1,50 @@
+<div class="slx-storechart">
+ {{#system}}
+ <b>Systempartition</b>
+ <div id="circles-system"></div>
+ Kapazität: {{size}}
+ {{/system}}
+ {{^system}}
+ <b>Fehler beim Ermitteln des verfügbaren Speichers auf der Systempartition!</b>
+ {{/system}}
+</div>
+<div class="slx-storechart">
+ {{#store}}
+ <b>VM-Speicher</b>
+ <div id="circles-store"></div>
+ Kapazität: {{size}}
+ {{/store}}
+ {{^store}}
+ <b>Fehler beim Ermitteln des verfügbaren Speicherplatzes am VM-Speicherort. Bitte überprüfen Sie die Konfiguration.</b>
+ {{/store}}
+</div>
+<script type="text/javascript">
+ {{#store}}
+ Circles.create({
+ id: 'circles-store',
+ radius: 60,
+ value: {{{percent}}},
+ maxValue: 100,
+ width: 10,
+ text: function(value){return value + '%'; },
+ colors: ['#D3B6C6', '#{{color}}'],
+ duration: 400,
+ wrpClass: 'circles-wrp',
+ textClass: 'circles-text'
+ });
+ {{/store}}
+ {{#system}}
+ Circles.create({
+ id: 'circles-system',
+ radius: 60,
+ value: {{{percent}}},
+ maxValue: 100,
+ width: 10,
+ text: function(value){return value + '%'; },
+ colors: ['#D3B6C6', '#{{color}}'],
+ duration: 400,
+ wrpClass: 'circles-wrp',
+ textClass: 'circles-text'
+ });
+ {{/system}}
+</script> \ No newline at end of file