Skip to content
This repository has been archived by the owner on Mar 19, 2021. It is now read-only.

Commit

Permalink
Dashboard: Running Jobs Widget
Browse files Browse the repository at this point in the history
Displays a list of all running jobs with some status and progress information
in a widget on our dashboard which is frequently updated.
  • Loading branch information
fbergkemper committed May 12, 2017
1 parent b615e66 commit f8d9e54
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 5 deletions.
1 change: 1 addition & 0 deletions module/Dashboard/config/module.config.php
Expand Up @@ -61,6 +61,7 @@
'JobsPast24h' => __DIR__ . '/../view/partial/JobsPast24h.phtml',
'JobsLastStatus' => __DIR__ . '/../view/partial/JobsLastStatus.phtml',
'LastDirectorMessages' => __DIR__ . '/../view/partial/LastDirectorMessages.phtml',
'RunningJobs' => __DIR__ . '/../view/partial/RunningJobs.phtml',
),
),
'translator' => array(
Expand Down
10 changes: 10 additions & 0 deletions module/Dashboard/src/Dashboard/Controller/DashboardController.php
Expand Up @@ -145,6 +145,16 @@ public function getDataAction()
echo $e->getMessage();
}
}
elseif($data == "runningjobs") {
try {
$this->bsock = $this->getServiceLocator()->get('director');
$result = $this->getJobModel()->getRunningJobsStatistics($this->bsock);
$this->bsock->disconnect();
}
catch(Exception $e) {
echo $e->getMessage();
}
}
elseif($data == "dirdmsg") {
try {
$this->bsock = $this->getServiceLocator()->get('director');
Expand Down
58 changes: 54 additions & 4 deletions module/Dashboard/view/dashboard/dashboard/index.phtml
Expand Up @@ -38,7 +38,7 @@ $this->headTitle($title);
</div>

<div class="col-md-4">
<?php echo $this->partial('LastDirectorMessages'); ?>
<?php echo $this->partial('RunningJobs'); ?>
</div>

</div>
Expand Down Expand Up @@ -177,8 +177,58 @@ $this->headTitle($title);
});
}

function getRunningJobs() {
$.ajax({
url: '<?php echo $this->url('dashboard', array('action' => 'getData'), null) . '?data=runningjobs'; ?>',
dataType: 'json',
timeout: 10000,
success: function(data) {
if(Object.keys(data).length >= 1) {
var i = 0;
$('.running-jobs-container').empty();
$(Object.keys(data)).each(function(key, id) {
$('.running-jobs-container').append('<div class="panel panel-default"><div class="panel-body rjc-panel-'+ i +'">');
$('.rjc-panel-'+i).append('<p>');
$('.rjc-panel-'+i).append('<strong>' + data[id].name + ' (' + data[id].client + ')' + '</strong>' + ' ');
$('.rjc-panel-'+i).append('<a href="<?php echo $this->basePath() . '/job/cancel/'; ?>' + data[id].jobid + '"><span class="pull-right text-danger glyphicon glyphicon-remove" aria-hidden="true" title="Cancel"></span></a>');
$('.rjc-panel-'+i).append('</p>');
$('.rjc-panel-'+i).append('<strong>Job ID: </strong><a href="<?php echo $this->basePath() . '/job/details/'; ?>' + data[id].jobid + '">' + data[id].jobid + '</a> ');
$('.rjc-panel-'+i).append('<strong>Files: </strong>' + data[id].jobfiles + ' ');
$('.rjc-panel-'+i).append('<strong>Bytes: </strong>' + formatBytes(data[id].jobbytes) + ' ');
$('.rjc-panel-'+i).append('<strong>Bytes/s: </strong>' + formatBytes(data[id].speed) + ' ');
if(data[id].lastbackupsize > 0) {
$('.rjc-panel-'+i).append('<div class="progress"><div class="progress-bar" role="progressbar" aria-valuenow="'+data[id].progress+'" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em; width: '+data[id].progress+'%">'+data[id].progress+'%</div></div>');
}
else {
$('.rjc-panel-'+i).append('<div class="progress" id="progress" data-toggle="tooltip" data-placement="top"><div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em; width: 100%"></div></div>');
$('.rjc-panel-'+i).append('<span class="text-muted"><i>(<?php echo $this->translate("Not enough data to estimate progress or statistics collection is disabled."); ?>)</i></span>');
}
$('.rjc-panel-'+i).append('</div></div>');
i++;
});
}
else {
$('.running-jobs-container').empty();
$('.running-jobs-container').append('<?php echo $this->translate('There are no jobs running.'); ?>');
}
},
error: function() {
$('.running-jobs-container').empty();
$('.running-jobs-container').append('Error fetching data.');
},
timeout: function() {
$('.running-jobs-container').empty();
$('.running-jobs-container').append('Timeout fetching data.');
},
parsererror: function() {
$('.running-jobs-container').empty();
$('.running-jobs-container').append('Parsererror');
}
});
}

function refreshPartials() {
getDirectorMessages();
getRunningJobs();
getJobsPast24h();
table_jobs_last_status.ajax.reload( null, false );
}
Expand All @@ -188,8 +238,8 @@ $this->headTitle($title);
setDtTextDomain('<?php echo $this->basePath() . '/js/locale'; ?>');
setDtLocale('<?php echo $_SESSION['bareos']['locale']; ?>');

getDirectorMessages();
setInterval('getDirectorMessages()', 60000);
getRunningJobs();
setInterval('getRunningJobs()', 60000);

getJobsPast24h();
setInterval('getJobsPast24h()', 60000);
Expand Down
40 changes: 40 additions & 0 deletions module/Dashboard/view/partial/RunningJobs.phtml
@@ -0,0 +1,40 @@
<?php

/**
*
* bareos-webui - Bareos Web-Frontend
*
* @link https://github.com/bareos/bareos-webui for the canonical source repository
* @copyright Copyright (c) 2013-2017 Bareos GmbH & Co. KG (http://www.bareos.org/)
* @license GNU Affero General Public License (http://www.gnu.org/licenses/)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

?>

<div class="panel panel-default">

<div class="panel-heading">
<h3 class="panel-title"><?php echo $this->translate('Running Jobs'); ?>
<a href="#" onClick="refreshPartials();return false;" title="Refresh"><span class="glyphicon glyphicon-refresh pull-right" aria-hidden="true"></span></a>
</h3>
</div>

<div class="panel-body" style="height: 450px; overflow-y: scroll;">
<div class="running-jobs-container"></div>
</div>

</div>
97 changes: 96 additions & 1 deletion module/Job/src/Job/Model/JobModel.php
Expand Up @@ -5,7 +5,7 @@
* bareos-webui - Bareos Web-Frontend
*
* @link https://github.com/bareos/bareos-webui for the canonical source repository
* @copyright Copyright (c) 2013-2016 Bareos GmbH & Co. KG (http://www.bareos.org/)
* @copyright Copyright (c) 2013-2017 Bareos GmbH & Co. KG (http://www.bareos.org/)
* @license GNU Affero General Public License (http://www.gnu.org/licenses/)
*
* This program is free software: you can redistribute it and/or modify
Expand Down Expand Up @@ -161,6 +161,101 @@ public function getJobsLastStatus(&$bsock=null)
}
}

public function getRunningJobsStatistics(&$bsock = null) {
if(isset($bsock)) {

$jobstats = [];
$i = 0;

// GET RUNNING JOBS
$runningJobs = $this->getJobsByStatus($bsock, null, 'R');

// COLLECT REQUIRED DATA FOR EACH RUNNING JOB
foreach($runningJobs as $job) {

// GET THE JOB STATS
$cmd = 'list jobstatistics jobid=' . $job['jobid'];
$result = $bsock->send_command($cmd, 2, null);
$tmp = \Zend\Json\Json::decode($result, \Zend\Json\Json::TYPE_ARRAY);

// JOBID, JOBNAME AND CLIENT
$jobstats[$i]['jobid'] = $job['jobid'];
$jobstats[$i]['name'] = $job['name'];
$jobstats[$i]['client'] = $job['client'];
$jobstats[$i]['level'] = $job['level'];

if(count($tmp['result']['jobstats']) > 2) {

// CALCULATE THE CURRENT TRANSFER SPEED OF THE INTERVAL
$a = strtotime( $tmp['result']['jobstats'][count($tmp['result']['jobstats']) - 1]['sampletime'] );
$b = strtotime( $tmp['result']['jobstats'][count($tmp['result']['jobstats']) - 2]['sampletime'] );
$interval = $a - $b;

if($interval > 0) {
$speed = ($tmp['result']['jobstats'][count($tmp['result']['jobstats']) - 1]['jobbytes'] - $tmp['result']['jobstats'][count($tmp['result']['jobstats']) - 2]['jobbytes']) / $interval;
$speed = round($speed, 2);
}
else {
$speed = 0;
}

$jobstats[$i]['speed'] = $speed;

// JOBFILES
$tmp = $tmp['result']['jobstats'][count($tmp['result']['jobstats']) - 1];
if($tmp['jobfiles'] == null) {
$jobstats[$i]['jobfiles'] = 0;
}
else {
$jobstats[$i]['jobfiles'] = $tmp['jobfiles'];
}

// JOBBYTES
$jobstats[$i]['jobbytes'] = $tmp['jobbytes'];

// SAMPLETIME
$jobstats[$i]['sampletime'] = $tmp['sampletime'];

// LAST BACKUP SIZE
$level = $jobstats[$i]['level'];
$cmd = 'list jobs client=' . $job['client'] . ' jobstatus=T joblevel=' . $level . ' limit=1';

$result = $bsock->send_command($cmd, 2, null);
$tmp = \Zend\Json\Json::decode($result, \Zend\Json\Json::TYPE_ARRAY);
$jobstats[$i]['lastbackupsize'] = $tmp['result']['jobs'][0]['jobbytes'];
if($jobstats[$i]['lastbackupsize'] > 0) {
if($jobstats[$i]['jobbytes'] > 0 && $tmp['result']['jobs'][0]['jobbytes'] > 0) {
$jobstats[$i]['progress'] = ceil( (($jobstats[$i]['jobbytes'] * 100) / $tmp['result']['jobs'][0]['jobbytes']));
if($jobstats[$i]['progress'] > 100) {
$jobstats[$i]['progress'] = 99;
}
}
else {
$jobstats[$i]['progress'] = 0;
}
}
else {
$jobstats[$i]['progress'] = 0;
}
}
else {
$jobstats[$i]['speed'] = 0;
$jobstats[$i]['jobfiles'] = 0;
$jobstats[$i]['jobbytes'] = 0;
$jobstats[$i]['sampletime'] = null;
$jobstats[$i]['progress'] = 0;
}

$i++;

}
return $jobstats;
}
else {
throw new \Exception('Missing argument.');
}
}

public function getRestoreJobs(&$bsock=null)
{
if(isset($bsock)) {
Expand Down

0 comments on commit f8d9e54

Please sign in to comment.