diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index 33506df01..5cbe5a8c3 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -657,13 +657,14 @@ class ApiController extends Zend_Controller_Action "platform"=>Application_Model_Systemstatus::GetPlatformInfo(), "airtime_version"=>Application_Model_Systemstatus::GetAirtimeVersion(), "services"=>array( - Application_Model_Systemstatus::GetIcecastStatus(), - Application_Model_Systemstatus::GetRabbitMqStatus(), - Application_Model_Systemstatus::GetPypoStatus(), - Application_Model_Systemstatus::GetLiquidsoapStatus(), - Application_Model_Systemstatus::GetShowRecorderStatus(), - Application_Model_Systemstatus::GetMediaMonitorStatus() - ) + "icecast2"=>Application_Model_Systemstatus::GetIcecastStatus(), + "rabbitmq"=>Application_Model_Systemstatus::GetRabbitMqStatus(), + "pypo"=>Application_Model_Systemstatus::GetPypoStatus(), + "liquidsoap"=>Application_Model_Systemstatus::GetLiquidsoapStatus(), + "show_recorder"=>Application_Model_Systemstatus::GetShowRecorderStatus(), + "media_monitor"=>Application_Model_Systemstatus::GetMediaMonitorStatus() + ), + "partitions"=>Application_Model_Systemstatus::GetDiskInfo() ); $this->view->status = $status; diff --git a/airtime_mvc/application/controllers/SystemstatusController.php b/airtime_mvc/application/controllers/SystemstatusController.php index 58dcc1597..d78c8e6bb 100644 --- a/airtime_mvc/application/controllers/SystemstatusController.php +++ b/airtime_mvc/application/controllers/SystemstatusController.php @@ -8,11 +8,12 @@ class SystemstatusController extends Zend_Controller_Action $baseUrl = $request->getBaseUrl(); $this->view->headScript()->appendFile($baseUrl.'/js/airtime/status/status.js','text/javascript'); + $this->view->headScript()->appendFile($baseUrl.'/js/sprintf/sprintf-0.7-beta1.js','text/javascript'); } public function indexAction() { - $status = array( + $services = array( "pypo"=>Application_Model_Systemstatus::GetPypoStatus(), "liquidsoap"=>Application_Model_Systemstatus::GetLiquidsoapStatus(), "show-recorder"=>Application_Model_Systemstatus::GetShowRecorderStatus(), @@ -20,8 +21,13 @@ class SystemstatusController extends Zend_Controller_Action "rabbitmq-server"=>Application_Model_Systemstatus::GetRabbitMqStatus(), "icecast2"=>Application_Model_Systemstatus::GetIcecastStatus() ); + + $partitions = Application_Model_Systemstatus::GetDiskInfo(); - $this->view->status = $status; + $this->view->status = new StdClass; + $this->view->status->services = $services; + $this->view->status->partitions = $partitions; + } public function getLogFileAction() diff --git a/airtime_mvc/application/models/MusicDir.php b/airtime_mvc/application/models/MusicDir.php index d104ac268..2b65eaded 100644 --- a/airtime_mvc/application/models/MusicDir.php +++ b/airtime_mvc/application/models/MusicDir.php @@ -222,8 +222,7 @@ class MusicDir { ->find(); foreach($dirs as $dir) { - $tmp = new MusicDir($dir); - $result[] = $tmp; + $result[] = new MusicDir($dir); } return $result; diff --git a/airtime_mvc/application/models/Systemstatus.php b/airtime_mvc/application/models/Systemstatus.php index f1df35476..db41991f5 100644 --- a/airtime_mvc/application/models/Systemstatus.php +++ b/airtime_mvc/application/models/Systemstatus.php @@ -14,10 +14,14 @@ class Application_Model_Systemstatus $result = curl_exec($ch); curl_close($ch); - $xmlDoc = new DOMDocument(); - $xmlDoc->loadXML($result); + $docRoot = null; + if ($result != ""){ + $xmlDoc = new DOMDocument(); + $xmlDoc->loadXML($result); + $docRoot = $xmlDoc->documentElement; + } - return $xmlDoc->documentElement; + return $docRoot; } public static function ExtractServiceInformation($p_docRoot, $p_serviceName){ @@ -25,20 +29,20 @@ class Application_Model_Systemstatus $starting = array( "name"=>"", "process_id"=>"STARTING...", - "uptime_seconds"=>"STARTING...", + "uptime_seconds"=>"-1", "status"=>true, - "memory_perc"=>"UNKNOWN", - "memory_kb"=>"UNKNOWN", - "cpu_perc"=>"UNKNOWN"); + "memory_perc"=>"0%", + "memory_kb"=>"0", + "cpu_perc"=>"0%"); $notRunning = array( - "name"=>"", + "name"=>$p_serviceName, "process_id"=>"FAILED", - "uptime_seconds"=>"FAILED", + "uptime_seconds"=>"-1", "status"=>false, - "memory_perc"=>"UNKNOWN", - "memory_kb"=>"UNKNOWN", - "cpu_perc"=>"UNKNOWN" + "memory_perc"=>"0%", + "memory_kb"=>"0", + "cpu_perc"=>"0%" ); $data = $notRunning; @@ -174,6 +178,32 @@ class Application_Model_Systemstatus public static function GetAirtimeVersion(){ return AIRTIME_VERSION; } + + public static function GetDiskInfo(){ + /* First lets get all the watched directories. Then we can group them + * into the same paritions by comparing the partition sizes. */ + $musicDirs = MusicDir::getWatchedDirs(); + $musicDirs[] = MusicDir::getStorDir(); + + + $partions = array(); + + foreach($musicDirs as $md){ + $totalSpace = disk_total_space($md->getDirectory()); + + if (!isset($partitions[$totalSpace])){ + $partitions[$totalSpace] = new StdClass; + $partitions[$totalSpace]->totalSpace = $totalSpace; + $partitions[$totalSpace]->totalFreeSpace = disk_free_space($md->getDirectory()); + } + + $partitions[$totalSpace]->dirs[] = $md->getDirectory(); + } + + return array_values($partitions); + } + + /* diff --git a/airtime_mvc/application/views/scripts/systemstatus/index.phtml b/airtime_mvc/application/views/scripts/systemstatus/index.phtml index 7aa567549..d8fe2b940 100644 --- a/airtime_mvc/application/views/scripts/systemstatus/index.phtml +++ b/airtime_mvc/application/views/scripts/systemstatus/index.phtml @@ -1,23 +1,11 @@ - - + + @@ -29,46 +17,17 @@ --> - status as $key=>$value): ?> + status->services as $key=>$value): ?> " id=""> - - + + + + - - - - - - - - - - - - + +
Service Status UptimeCPUMemory
"> 
Disk Space
Disk #1 (/dev/sda) -
    -
  • /home/bob
  • -
  • /srv/airtime/stor
  • -
-
12GB of 128GB -
-
-
-
-
10% in use
-
Disk #2 (/dev/sdb) -
    -
  • /home/external/audio
  • -
-
90GB of 450GB -
-
-
-
-
20% in use
-
Disk Space
diff --git a/airtime_mvc/public/js/airtime/dashboard/helperfunctions.js b/airtime_mvc/public/js/airtime/dashboard/helperfunctions.js index 85fbbb18c..e1abb3f2d 100644 --- a/airtime_mvc/public/js/airtime/dashboard/helperfunctions.js +++ b/airtime_mvc/public/js/airtime/dashboard/helperfunctions.js @@ -11,6 +11,23 @@ function popup(mylink){ return false; } +function convertSecondsToDaysHoursMinutesSeconds(seconds){ + if (seconds < 0) + seconds = 0; + + seconds = parseInt(seconds, 10); + + var days = parseInt(seconds / 86400); + seconds -= days*86400; + + var hours = parseInt(seconds / 3600); + seconds -= hours*3600; + + var minutes = parseInt(seconds / 60); + seconds -= minutes*60; + + return {days:days, hours:hours, minutes:minutes, seconds:seconds}; +} /* Takes an input parameter of milliseconds and converts these into * the format HH:MM:SS */ diff --git a/airtime_mvc/public/js/airtime/status/status.js b/airtime_mvc/public/js/airtime/status/status.js index f8c4a871e..779594476 100644 --- a/airtime_mvc/public/js/airtime/status/status.js +++ b/airtime_mvc/public/js/airtime/status/status.js @@ -1,12 +1,60 @@ +function generatePartitions(partitions){ + + var rowTemplate = + ''+ + 'Disk #%s'+ + ''+ + ''+ + '%sGB of %sGB'+ + ''+ + '
'+ + '
'+ + '
'+ + '
'+ + '
%s%% in use
'+ + ''+ + ''; + + $(".partition-info").remove(); + var lastElement = $('#partitions'); + for (var i=0; i'+partitions[i].dirs[j]+''); + } + lastElement = tr; + } + +} + function success(data, textStatus, jqXHR){ var services = data.status.services; - for (var i=0; i +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of sprintf() for JavaScript nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Changelog: +2010.09.06 - 0.7-beta1 + - features: vsprintf, support for named placeholders + - enhancements: format cache, reduced global namespace pollution + +2010.05.22 - 0.6: + - reverted to 0.4 and fixed the bug regarding the sign of the number 0 + Note: + Thanks to Raphael Pigulla (http://www.n3rd.org/) + who warned me about a bug in 0.5, I discovered that the last update was + a regress. I appologize for that. + +2010.05.09 - 0.5: + - bug fix: 0 is now preceeded with a + sign + - bug fix: the sign was not at the right position on padded results (Kamal Abdali) + - switched from GPL to BSD license + +2007.10.21 - 0.4: + - unit test and patch (David Baird) + +2007.09.17 - 0.3: + - bug fix: no longer throws exception on empty paramenters (Hans Pufal) + +2007.09.11 - 0.2: + - feature: added argument swapping + +2007.04.03 - 0.1: + - initial release +**/ + +var sprintf = (function() { + function get_type(variable) { + return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); + } + function str_repeat(input, multiplier) { + for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */} + return output.join(''); + } + + var str_format = function() { + if (!str_format.cache.hasOwnProperty(arguments[0])) { + str_format.cache[arguments[0]] = str_format.parse(arguments[0]); + } + return str_format.format.call(null, str_format.cache[arguments[0]], arguments); + }; + + str_format.format = function(parse_tree, argv) { + var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; + for (i = 0; i < tree_length; i++) { + node_type = get_type(parse_tree[i]); + if (node_type === 'string') { + output.push(parse_tree[i]); + } + else if (node_type === 'array') { + match = parse_tree[i]; // convenience purposes only + if (match[2]) { // keyword argument + arg = argv[cursor]; + for (k = 0; k < match[2].length; k++) { + if (!arg.hasOwnProperty(match[2][k])) { + throw(sprintf('[sprintf] property "%s" does not exist', match[2][k])); + } + arg = arg[match[2][k]]; + } + } + else if (match[1]) { // positional argument (explicit) + arg = argv[match[1]]; + } + else { // positional argument (implicit) + arg = argv[cursor++]; + } + + if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { + throw(sprintf('[sprintf] expecting number but found %s', get_type(arg))); + } + switch (match[8]) { + case 'b': arg = arg.toString(2); break; + case 'c': arg = String.fromCharCode(arg); break; + case 'd': arg = parseInt(arg, 10); break; + case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; + case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; + case 'o': arg = arg.toString(8); break; + case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; + case 'u': arg = Math.abs(arg); break; + case 'x': arg = arg.toString(16); break; + case 'X': arg = arg.toString(16).toUpperCase(); break; + } + arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); + pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; + pad_length = match[6] - String(arg).length; + pad = match[6] ? str_repeat(pad_character, pad_length) : ''; + output.push(match[5] ? arg + pad : pad + arg); + } + } + return output.join(''); + }; + + str_format.cache = {}; + + str_format.parse = function(fmt) { + var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; + while (_fmt) { + if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { + parse_tree.push(match[0]); + } + else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { + parse_tree.push('%'); + } + else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { + if (match[2]) { + arg_names |= 1; + var field_list = [], replacement_field = match[2], field_match = []; + if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { + if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else { + throw('[sprintf] huh?'); + } + } + } + else { + throw('[sprintf] huh?'); + } + match[2] = field_list; + } + else { + arg_names |= 2; + } + if (arg_names === 3) { + throw('[sprintf] mixing positional and named placeholders is not (yet) supported'); + } + parse_tree.push(match); + } + else { + throw('[sprintf] huh?'); + } + _fmt = _fmt.substring(match[0].length); + } + return parse_tree; + }; + + return str_format; +})(); + +var vsprintf = function(fmt, argv) { + argv.unshift(fmt); + return sprintf.apply(null, argv); +}; diff --git a/utils/airtime-check-system.php b/utils/airtime-check-system.php index b9bc21afc..6fc13060f 100644 --- a/utils/airtime-check-system.php +++ b/utils/airtime-check-system.php @@ -69,30 +69,30 @@ class AirtimeCheck { self::output_status("TOTAL_MEMORY_MBYTES", $p_status->platform->memory); self::output_status("TOTAL_SWAP_MBYTES", $p_status->platform->swap); self::output_status("AIRTIME_VERSION", $p_status->airtime_version); - self::output_status("PLAYOUT_ENGINE_PROCESS_ID", $p_status->pypo->process_id); - self::output_status("PLAYOUT_ENGINE_RUNNING_SECONDS", $p_status->pypo->uptime_seconds); - self::output_status("PLAYOUT_ENGINE_MEM_PERC", $p_status->pypo->memory_perc); - self::output_status("PLAYOUT_ENGINE_CPU_PERC", $p_status->pypo->cpu_perc); - self::output_status("LIQUIDSOAP_PROCESS_ID", $p_status->liquidsoap->process_id); - self::output_status("LIQUIDSOAP_RUNNING_SECONDS", $p_status->liquidsoap->uptime_seconds); - self::output_status("LIQUIDSOAP_MEM_PERC", $p_status->liquidsoap->memory_perc); - self::output_status("LIQUIDSOAP_CPU_PERC", $p_status->liquidsoap->cpu_perc); - self::output_status("MEDIA_MONITOR_PROCESS_ID", $p_status->media_monitor->process_id); - self::output_status("MEDIA_MONITOR_RUNNING_SECONDS", $p_status->media_monitor->uptime_seconds); - self::output_status("MEDIA_MONITOR_MEM_PERC", $p_status->media_monitor->memory_perc); - self::output_status("MEDIA_MONITOR_CPU_PERC", $p_status->media_monitor->cpu_perc); - self::output_status("SHOW_RECORDER_PROCESS_ID", $p_status->show_recorder->process_id); - self::output_status("SHOW_RECORDER_RUNNING_SECONDS", $p_status->show_recorder->uptime_seconds); - self::output_status("SHOW_RECORDER_MEM_PERC", $p_status->show_recorder->memory_perc); - self::output_status("SHOW_RECORDER_CPU_PERC", $p_status->show_recorder->cpu_perc); - self::output_status("ICECAST_PROCESS_ID", $p_status->icecast2->process_id); - self::output_status("ICECAST_RUNNING_SECONDS", $p_status->icecast2->uptime_seconds); - self::output_status("ICECAST_MEM_PERC", $p_status->icecast2->memory_perc); - self::output_status("ICECAST_CPU_PERC", $p_status->icecast2->cpu_perc); - self::output_status("RABBITMQ_PROCESS_ID", $p_status->rabbitmq->process_id); - self::output_status("RABBITMQ_RUNNING_SECONDS", $p_status->rabbitmq->uptime_seconds); - self::output_status("RABBITMQ_MEM_PERC", $p_status->rabbitmq->memory_perc); - self::output_status("RABBITMQ_CPU_PERC", $p_status->rabbitmq->cpu_perc); + self::output_status("PLAYOUT_ENGINE_PROCESS_ID", $p_status->services->pypo->process_id); + self::output_status("PLAYOUT_ENGINE_RUNNING_SECONDS", $p_status->services->pypo->uptime_seconds); + self::output_status("PLAYOUT_ENGINE_MEM_PERC", $p_status->services->pypo->memory_perc); + self::output_status("PLAYOUT_ENGINE_CPU_PERC", $p_status->services->pypo->cpu_perc); + self::output_status("LIQUIDSOAP_PROCESS_ID", $p_status->services->liquidsoap->process_id); + self::output_status("LIQUIDSOAP_RUNNING_SECONDS", $p_status->services->liquidsoap->uptime_seconds); + self::output_status("LIQUIDSOAP_MEM_PERC", $p_status->services->liquidsoap->memory_perc); + self::output_status("LIQUIDSOAP_CPU_PERC", $p_status->services->liquidsoap->cpu_perc); + self::output_status("MEDIA_MONITOR_PROCESS_ID", $p_status->services->media_monitor->process_id); + self::output_status("MEDIA_MONITOR_RUNNING_SECONDS", $p_status->services->media_monitor->uptime_seconds); + self::output_status("MEDIA_MONITOR_MEM_PERC", $p_status->services->media_monitor->memory_perc); + self::output_status("MEDIA_MONITOR_CPU_PERC", $p_status->services->media_monitor->cpu_perc); + self::output_status("SHOW_RECORDER_PROCESS_ID", $p_status->services->show_recorder->process_id); + self::output_status("SHOW_RECORDER_RUNNING_SECONDS", $p_status->services->show_recorder->uptime_seconds); + self::output_status("SHOW_RECORDER_MEM_PERC", $p_status->services->show_recorder->memory_perc); + self::output_status("SHOW_RECORDER_CPU_PERC", $p_status->services->show_recorder->cpu_perc); + self::output_status("ICECAST_PROCESS_ID", $p_status->services->icecast2->process_id); + self::output_status("ICECAST_RUNNING_SECONDS", $p_status->services->icecast2->uptime_seconds); + self::output_status("ICECAST_MEM_PERC", $p_status->services->icecast2->memory_perc); + self::output_status("ICECAST_CPU_PERC", $p_status->services->icecast2->cpu_perc); + self::output_status("RABBITMQ_PROCESS_ID", $p_status->services->rabbitmq->process_id); + self::output_status("RABBITMQ_RUNNING_SECONDS", $p_status->services->rabbitmq->uptime_seconds); + self::output_status("RABBITMQ_MEM_PERC", $p_status->services->rabbitmq->memory_perc); + self::output_status("RABBITMQ_CPU_PERC", $p_status->services->rabbitmq->cpu_perc); }