]> git.sur5r.net Git - bacula/bacula/blob - gui/bacula-web/includes/bweb.inc.php
bacula-web: Removed useless GetStoredBytesByInterval() function
[bacula/bacula] / gui / bacula-web / includes / bweb.inc.php
1 <?php
2 /* 
3 +-------------------------------------------------------------------------+
4 | Copyright (C) 2004 Juan Luis Francés Jiménez                                                    |
5 | Copyright 2010-2011, Davide Franco                                              |
6 |                                                                         |
7 | This program is free software; you can redistribute it and/or           |
8 | modify it under the terms of the GNU General Public License             |
9 | as published by the Free Software Foundation; either version 2          |
10 | of the License, or (at your option) any later version.                  |
11 |                                                                         |
12 | This program is distributed in the hope that it will be useful,         |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of          |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           |
15 | GNU General Public License for more details.                            |
16 +-------------------------------------------------------------------------+ 
17 */
18 class Bweb extends DB 
19 {
20     var         $driver;
21         
22         public  $tpl;
23         public  $db_link;                                               // Database link
24         
25         private $config_file;                                   // Config filename
26         private $config;                                                // Loaded config from bacula.conf
27         private $catalogs = array();                    // Catalog array
28         public  $catalog_nb;
29         private $catalog_current_id;
30         private $bwcfg;
31
32     function __construct()
33         {             
34                 $this->bwcfg = new Config();
35                 $dsn = array();
36                 
37                 // Loading configuration from config file
38                 $this->bwcfg->Load_Config();
39                 $this->catalog_nb = $this->bwcfg->Count_Catalogs();
40                 
41                 // Initialize smarty template classe
42                 $this->init_tpl();
43                 // Initialize smarty gettext function
44                 $this->init_gettext();
45                 
46                 // Check catalog id
47                 if( isset($_POST['catalog_id']) ) {
48                         $this->catalog_current_id = $_POST['catalog_id'];
49                         $_SESSION['catalog_id'] = $this->catalog_current_id;
50                 }
51                 elseif( isset( $_SESSION['catalog_id'] ) )
52                         $this->catalog_current_id = $_SESSION['catalog_id'];
53                 else {
54                         $this->catalog_current_id = 0;
55                         $_SESSION['catalog_id'] = $this->catalog_current_id;
56                 }
57
58                 $this->tpl->assign( 'catalog_current_id', $this->catalog_current_id );
59                 
60                 // Get DSN
61                 $dsn = $this->bwcfg->Get_Dsn( $this->catalog_current_id );
62                 
63                 // Connect to the database
64                 $options = array( 'portability' => DB_PORTABILITY_ALL );
65                 $this->db_link = $this->connect( $dsn, $options );
66         
67                 if (DB::isError($this->db_link)) {
68                         $this->TriggerDBError('Unable to connect to catalog', $this->db_link);
69                 }else {
70                         $this->driver = $dsn['phptype'];                            
71                         register_shutdown_function(array(&$this,'close') );
72                         $this->db_link->setFetchMode(DB_FETCHMODE_ASSOC);
73                 }
74                 
75                 // Catalog selection            
76                 if( $this->catalog_nb > 1 ) {
77                         // Catalogs list
78                         $this->tpl->assign( 'catalogs', $this->bwcfg->Get_Catalogs() );                 
79                         // Catalogs count
80                         $this->tpl->assign( 'catalog_nb', $this->catalog_nb );
81                 }
82         }
83                 
84     // Initialize Smarty template classe
85         function init_tpl()
86         {
87                 $this->tpl = new Smarty();
88                 
89                 $this->tpl->compile_check       = true;
90                 $this->tpl->debugging           = false;
91                 $this->tpl->force_compile       = true;
92
93                 $this->tpl->template_dir        = "./templates";
94                 $this->tpl->compile_dir         = "./templates_c";
95         }
96         
97         function init_gettext()
98         {
99                 global $smarty_gettext_path;
100                 
101                 if ( function_exists("gettext") ) {
102                         require_once( BW_SMARTY_GETTEXT . "smarty_gettext.php" );     
103                         $this->tpl->register_block('t','smarty_translate');
104         
105                         $language = $this->bwcfg->Get_Config_Param("lang");
106                         $domain = "messages";   
107                         putenv("LANG=$language"); 
108                         setlocale(LC_ALL, $language);
109                         bindtextdomain($domain,"./locale");
110                         textdomain($domain);
111                 }
112                 else {
113                         function smarty_translate($params, $text, &$smarty) {
114                 return $text;
115                         }
116                         $smarty->register_block('t','smarty_translate');
117                 }
118         }
119         
120         function close() 
121         {
122                 $this->db_link->disconnect();
123     }      
124        
125         function GetDbSize() 
126         {
127                 $database_size  = 0;
128                 $query                  = "";
129                 
130                 switch( $this->driver )
131                 {
132                         case 'mysql':
133                                 $query  = "SELECT table_schema AS 'database', sum( data_length + index_length) AS 'dbsize' ";
134                                 $query .= "FROM information_schema.TABLES ";
135                                 $query .= "WHERE table_schema = 'bacula' ";
136                                 $query .= "GROUP BY table_schema";
137                         break;
138                         case 'pgsql':
139                                 $query  = "SELECT pg_database_size('bacula') AS dbsize";
140                         break;
141                         case 'sqlite':
142                                 // Not yet implemented
143                                 return "0 MB";
144                         break;
145                 }
146                 
147                 $result = $this->db_link->query( $query );
148                 
149                 if(! PEAR::isError( $result ) )
150                 {
151                         $db = $result->fetchRow();
152                         $database_size = $db['dbsize'];
153                 }else
154                         $this->TriggerDBError( 'Unable to get database size', $result);
155                 
156                 return CUtils::Get_Human_Size( $database_size );
157         } // end function GetDbSize()
158         
159         public function Get_Nb_Clients()
160         {
161                 $clients = $this->db_link->query("SELECT COUNT(*) AS nb_client FROM Client");
162                 if( PEAR::isError($clients) )
163                         $this->TriggerDBError("Unable to get client number", $clients );
164                 else
165                         return $clients->fetchRow( DB_FETCHMODE_ASSOC );
166         }
167   
168         // Return an array of volumes ordered by poolid and volume name
169         function GetVolumeList() {
170
171                         $volumes   = array();
172                         $query     = "";
173                         $debug     = false;
174                         
175                         // Get the list of pools id
176                         $query = "SELECT Pool.poolid, Pool.name FROM Pool ORDER BY Pool.poolid";
177                         
178                         //$this->db_link->setFetchMode(DB_FETCHMODE_ASSOC);
179                         $pools = $this->db_link->query( $query );
180                         
181                         if( PEAR::isError( $pools ) )
182                                 $this->TriggerDBError("Failed to get pool list", $pools );
183                         
184                         while( $pool = $pools->fetchRow( DB_FETCHMODE_ASSOC ) ) {
185                                 switch( $this->driver )
186                                 {
187                                         case 'mysql':
188                                                 $query  = "SELECT Media.volumename, Media.volbytes, Media.volstatus, Media.mediatype, Media.lastwritten, Media.volretention
189                                                                    FROM Media LEFT JOIN Pool ON Media.poolid = Pool.poolid
190                                                                    WHERE Media.poolid = '". $pool['poolid'] . "' ORDER BY Media.volumename";
191                                         break;
192                                         case 'pgsql':
193                                                 $query  = "SELECT media.volumename, media.volbytes, media.volstatus, media.mediatype, media.lastwritten, media.volretention
194                                                                    FROM media LEFT JOIN pool ON media.poolid = pool.poolid
195                                                                    WHERE media.poolid = '". $pool['poolid'] . "' ORDER BY media.volumename";
196                                         break;
197                                         case 'sqlite':
198                                                 $query  = "";           // not yet implemented
199                                         break;
200                                         default:
201                                         break;
202                                 } // end switch
203                                 
204                                 $medias = $this->db_link->query( $query );
205
206                                 if( PEAR::isError( $medias ) ) {
207                                         $this->TriggerDBError("Failed to get media list for pool", $medias);
208                                 }else {
209                                         if( $debug ) echo "Found " . $medias->numRows() . " medias for pool " . $pool['name'] . " <br />";
210                                 
211                                         // Create array key for each pool
212                                         if( !array_key_exists( $pool['name'], $volumes) )
213                                         {
214                                                 $volumes[ $pool['name'] ] = array();
215                                         }
216                                         while( $media = $medias->fetchRow( DB_FETCHMODE_ASSOC ) ) {
217                                                 if( $debug ) {
218                                                         var_dump( $media );
219                                                 }
220                                                 // If the pool is empty (no volumes in this pool)
221                                                 if( $medias->numRows() == 0 ) {
222                                                         if( $debug ) echo "No media in pool " . $pool['name'] . "<br />";
223                                                 } else {
224                                                                 if( $media['lastwritten'] != "0000-00-00 00:00:00" ) {
225                                                                         // Calculate expiration date if the volume is Full
226                                                                         if( $media['volstatus'] == 'Full' ) {
227                                                                                 $expire_date     = strtotime($media['lastwritten']) + $media['volretention'];
228                                                                                 $media['expire'] = strftime("%Y-%m-%d", $expire_date);
229                                                                         }else {
230                                                                                 $media['expire'] = 'N/A';
231                                                                         }
232                                                                         // Media used bytes in a human format
233                                                                         $media['volbytes'] = CUtils::Get_Human_Size( $media['volbytes'] );
234                                                                 } else {
235                                                                         $media['lastwritten'] = "N/A";
236                                                                         $media['expire']      = "N/A";
237                                                                         $media['volbytes']        = "0 KB";
238                                                                 }                                                               
239                                                         
240                                                         // Odd or even row
241                                                         if( count(  $volumes[ $pool['name'] ] ) % 2)
242                                                                         $media['class'] = 'odd';
243
244                                                         // Add the media in pool array
245                                                         array_push( $volumes[ $pool['name']], $media);
246                                                 }
247                                         } // end while
248                                 } // end if else
249                         } // end while
250                         return $volumes;
251         } // end function GetVolumeList()
252         
253         public function CountJobsbyLevel( $delay = LAST_DAY, $level = 'F' )
254         {
255                 $end_date    = mktime();
256                 $start_date  = $end_date - $delay;
257                 
258                 $start_date  = date( "Y-m-d H:i:s", $start_date );
259                 $end_date    = date( "Y-m-d H:i:s", $end_date );
260                 
261                 $query   = "SELECT COUNT(JobId) as jobs FROM Job ";
262                 $query  .= "WHERE (EndTime BETWEEN '$start_date' AND '$end_date') AND ";
263                 $query  .= "Level = '$level' ";
264                 
265                 $result  = $this->db_link->query( $query );
266                 
267                 if (PEAR::isError( $result ) ) {
268                         $this->TriggerDBError( 'Unable to get number of jobs with ' . $level . ' status from catalog', $result);
269                 }else {
270                         $jobs = $result->fetchRow();
271                         return $jobs['jobs'];
272                 }
273                 
274         }
275         
276         public function CountJobs( $delay = LAST_DAY, $status = 'any' )
277         {
278                 $query                  = "SELECT COUNT(JobId) AS job_nb FROM Job ";
279                 $where_delay    = "";
280                 $where_status   = "";
281                 
282                 // Interval condition for SQL query
283                 if( $delay != ALL ) {
284                         $end_date    = mktime();
285                         $start_date  = $end_date - $delay;
286                 
287                         $start_date  = date( "Y-m-d H:i:s", $start_date );
288                         $end_date    = date( "Y-m-d H:i:s", $end_date );
289                 
290                         $where_delay = "WHERE EndTime BETWEEN '$start_date' AND '$end_date' ";
291                 }
292                 
293                 if( $status != 'any' ) {
294                         switch( $status )
295                         {
296                                 case 'completed':
297                                         $where_status = "JobStatus = 'T' ";
298                                 break;
299                                 case 'failed':
300                                         $where_status = "JobStatus IN ('f','E') ";
301                                 break;
302                                 case 'canceled':
303                                         $where_status = "JobStatus = 'A' ";
304                                 break;
305                                 case 'waiting':
306                                         $where_status = "JobStatus IN ('F','S','M','m','s','j','c','d','t') ";
307                                 break;
308                         } // end switch
309                 }
310                 
311                 if( !empty($where_delay) )
312                         $query = $query . $where_delay . 'AND ' . $where_status;
313                 else {
314                         if( !empty($where_status) )
315                                 $query = $query . 'WHERE ' . $where_status;
316                 }
317                         
318                 $jobs = $this->db_link->query( $query );
319         
320                 if (PEAR::isError( $jobs ) ) {
321                         $this->TriggerDBError("Unable to get last $status jobs number from catalog", $jobs);
322                 }else {
323                         $jobs = $jobs->fetchRow( DB_FETCHMODE_ASSOC ); 
324                         return $jobs['job_nb'];
325                 }
326         }
327         
328         // Return the list of Pools in a array
329         public function Get_Pools_List()
330         {
331                 $result         = "";
332                 $query          = "SELECT Name, PoolId FROM Pool";
333                 $result         = $this->db_link->query ( $query );
334
335                 if( PEAR::isError( $result ) ) {
336                         $this->TriggerDBError( "Unable to get the pool list from catalog", $result );                           
337                 }else {
338                         return $result;
339                 }
340         }
341         
342         public function Get_BackupJob_Names()
343         {
344                 $query  = '';
345                 
346                 switch( $this->driver )
347                 {
348                         case 'sqlite':
349                         case 'mysql':
350                                 $query          = "SELECT name FROM Job GROUP BY name ORDER BY name";
351                         break;
352                         case 'pgsql':
353                                 $query          = "SELECT name FROM Job GROUP BY name ORDER BY name";
354                         break;
355                 }
356                 
357                 $backupjobs = array();
358                 
359                 $result = $this->db_link->query( $query );
360                 
361                 if (PEAR::isError( $result ) ) {
362                         $this->TriggerDBError("Unable to get BackupJobs list from catalog", $result );
363                 }else{
364                         while( $backupjob = $result->fetchRow() ) {
365                                 array_push( $backupjobs, $backupjob["name"] );
366                         }
367                         return $backupjobs;
368                 }
369         }
370         
371         // Return Jobs statistics for a specific interval such as
372         // - Completed jobs number
373         // - Failed jobs number
374         // - Waiting jobs number
375         // The returned values will be used by a Bgraph classe
376         public function GetJobsStatistics( $type = 'completed', $delay = LAST_DAY )
377         {
378                 $query  = "";
379                 $where  = "";
380                 $jobs   = "";
381                 $label  = "";
382                 $res    = "";
383                 
384                 // Interval calculation
385                 $end_date   = mktime();
386                 $start_date = $end_date - $delay;
387                 
388                 $start_date = date( "Y-m-d H:i:s", $start_date );
389                 $end_date   = date( "Y-m-d H:i:s", $end_date );
390                 
391                 $interval_where = "(EndTime BETWEEN '$start_date' AND '$end_date') AND ";
392                 
393                 // Job status
394                 switch( $type )
395                 {
396                         case 'completed':
397                                 $where = $interval_where . "JobStatus = 'T' ";
398                                 $label = "Completed";
399                         break;
400                         case 'terminated_errors':
401                                 $where = $interval_where . "JobStatus = 'E' ";
402                                 $label = "Terminated with errors";
403                         break;
404                         case 'failed':
405                                 $where = $interval_where . "JobStatus = 'f' ";
406                                 $label = "Failed";
407                         break;
408                         case 'waiting':
409                                 $where = "JobStatus IN ('F','S','M','m','s','j','c','d','t') ";
410                                 $label = "Waiting";
411                         break;
412                         case 'created':
413                                 $where = "JobStatus = 'C' ";
414                                 $label = "Created but not running";
415                         break;
416                         case 'running':
417                                 $where = "JobStatus = 'R' ";
418                                 $label = "Running";
419                         break;
420                         case 'error':
421                                 $where = $interval_where . "JobStatus IN ('e','f') ";
422                                 $label = "Errors";
423                         break;
424                 }
425                 
426                 $query  = 'SELECT COUNT(JobId) AS count ';
427                 $query .= 'FROM Job ';
428                 $query .= "WHERE $where ";
429                 
430                 $res = $this->db_link->query( $query );
431         
432                 if (PEAR::isError( $res ) ) {
433                         $this->TriggerDBError( 'Unable to get last' . $type . 'jobs status from catalog', $res);
434                 }else {
435                         $result = $res->fetchRow();
436                         return array( $label, $result['count'] );
437                 }
438         } // end function GetJobsStatistics()
439         
440         public function CountVolumesByPool( $pool_id )
441         {
442                 $res    = null;
443                 $nb_vol = null;
444                 $query  = '';
445
446                 switch( $this->driver )
447                 {
448                         case 'sqlite':
449                         case 'mysql':
450                                 $query  = 'SELECT COUNT(*) as vols,Pool.name as pool_name ';
451                                 $query .= 'FROM Media ';
452                                 $query .= 'RIGHT JOIN Pool ON (Media.PoolId = Pool.PoolId) ';
453                                 $query .= 'WHERE Media.poolid = ' . $pool_id;
454                         break;
455                         case 'pgsql':
456                                 $query  = 'SELECT COUNT(*) as vols,Pool.name as pool_name ';
457                                 $query .= 'FROM Media ';
458                                 $query .= 'RIGHT JOIN Pool ON (Media.PoolId = Pool.PoolId) ';
459                                 $query .= 'WHERE Media.poolid = ' . $pool_id;
460                                 $query .= 'GROUP BY pool.name';
461                         break;
462                 }
463                 
464                 $res = $this->db_link->query( $query );
465                 if( PEAR::isError( $res ) )
466                         $this->triggerDBError( 'Unable to get volume number from pool', $res );
467                 
468                 $vols = $res->fetchRow( );
469                 
470                 return array( $vols['pool_name'], $vols['vols'] );
471         }
472         
473         public function GetStoredFiles( $delay = LAST_DAY )
474         {
475                 $totalfiles = 0;
476
477                 $query = "SELECT SUM(JobFiles) AS stored_files FROM Job ";
478                 
479                 // Interval calculation
480                 $end_date   = mktime();
481                 $start_date = $end_date - $delay;
482                 
483                 $start_date = date( "Y-m-d H:i:s", $start_date );
484                 $end_date   = date( "Y-m-d H:i:s", $end_date );                 
485
486                 if( $delay != ALL )
487                         $query .= "WHERE EndTime BETWEEN '$start_date' AND '$end_date'";
488                         
489                 $result = $this->db_link->query( $query );
490                 
491                 if( !PEAR::isError($result) ) {
492                         $nbfiles        = $result->fetchRow(DB_FETCHMODE_ASSOC);
493                         $totalfiles = $totalfiles + $nbfiles['stored_files'];
494                 }else{
495                         $this->TriggerDBError("Unable to get protected files from catalog", $result);
496                 }
497                 
498                 return $totalfiles;
499         }
500         
501         public function GetStoredBytesByJob( $jobname, $start_date, $end_date )
502         {
503                 $query = '';
504                 
505                 switch( $this->driver )
506                 {
507                         case 'sqlite':
508                         case 'mysql':
509                                 $query  = "SELECT SUM(JobBytes),EndTime as stored_bytes FROM Job ";
510                                 $query .= "WHERE ( EndTime BETWEEN '$start_date' AND '$end_date' ) AND ";
511                                 $query .= "Name = '$jobname'";
512                                 $query .= "GROUP BY EndTime";
513                                 break;
514                         case 'pgsql':
515                                 $query  = "SELECT SUM(jobbytes),endtime as stored_bytes FROM job ";
516                                 $query .= "WHERE ( endtime BETWEEN timestamp '$start_date' AND timestamp '$end_date' ) AND ";
517                                 $query .= "name = '$jobname'";
518                                 $query .= "GROUP BY EndTime";
519                                 break;
520                 }
521
522                 $result = $this->db_link->query( $query );
523                 
524                 if( PEAR::isError( $result ) ) {
525                         $this->TriggerDBError("Unable to get Job Bytes from catalog", $result );
526                 }else{
527                         $stored_bytes = 0;
528                         $tmp = $result->fetchRow();
529                         
530                         $day = date( "D d", strtotime($end_date) );
531                         
532                         if( isset( $tmp['stored_bytes'] ) ) {
533                                 $hbytes = CUtils::Get_Human_Size( $tmp['stored_bytes'], 3, 'GB' );
534                                 $hbytes = explode( " ", $hbytes );
535                                 $stored_bytes = $hbytes[0];
536                         }
537                         
538                         return array( $day, $stored_bytes );
539                 }                       
540         }
541         
542         // Function: getStoredBytes
543         // Parameters:
544         //              $start_timestamp:       start date in unix timestamp format
545         //              $end_timestamp:         end date in unix timestamp format
546         //              $job_name:                      optional job name
547         
548         public function getStoredBytes( $start_timestamp, $end_timestamp, $job_name = 'ALL' )
549         {
550                 $query                  = '';
551                 $start_date             = date( "Y-m-d H:i:s", $start_timestamp);       
552                 $end_date               = date( "Y-m-d H:i:s", $end_timestamp); 
553                 
554                 switch( $this->driver )
555                 {
556                         case 'sqlite':
557                         case 'mysql':
558                                 $query  = "SELECT SUM(JobBytes) as stored_bytes FROM Job ";
559                                 $query .= "WHERE ( EndTime BETWEEN '$start_date' AND '$end_date' )";
560                         break;
561                         case 'pgsql':
562                                 $query  = "SELECT SUM(jobbytes) as stored_bytes FROM job ";
563                                 $query .= "WHERE ( endtime BETWEEN timestamp '$start_date' AND timestamp '$end_date' )";
564                         break;
565                 }
566
567                 if( $job_name != 'ALL' ) 
568                         $query .= " AND name = '$job_name'";
569                 
570                 // Execute the query
571                 $result = $this->db_link->query( $query );
572                 
573                 // Testing query result
574                 if( PEAR::isError( $result ) ) {
575                         $this->TriggerDBError("Unable to get Job Bytes from catalog", $result );
576                 }else{
577                         $result = $result->fetchRow();
578                         
579                         if( !PEAR::isError($result) ) {
580                                 if( isset($result['stored_bytes']) and !empty($result['stored_bytes']) )
581                                         return $result['stored_bytes'];
582                                 else
583                                         return 0;
584                         }else
585                                 $this->TriggerDBError( "Error fetching query result", $result);
586                 }
587                 
588         }
589         
590         public function GetStoredFilesByJob( $jobname, $start_timestamp, $end_timestamp )
591         {
592                 $query          = '';
593                 $start_date = date( "Y-m-d H:i:s", $start_timestamp);
594                 $end_date       = date( "Y-m-d H:i:s", $end_timestamp);
595                 
596                 switch( $this->driver )
597                 {
598                         case 'sqlite':
599                         case 'mysql':
600                                 $query  = "SELECT SUM(JobFiles),EndTime as stored_files FROM Job ";
601                                 $query .= "WHERE ( EndTime BETWEEN '$start_date' AND '$end_date' ) AND ";
602                                 $query .= "Name = '$jobname'";
603                                 $query .= "GROUP BY EndTime";
604                                 break;
605                         case 'pgsql':
606                                 $query  = "SELECT SUM(jobfiles),endtime as stored_files FROM job ";
607                                 $query .= "WHERE ( endtime BETWEEN timestamp '$start_date' AND timestamp '$end_date' ) AND ";
608                                 $query .= "name = '$jobname'";
609                                 $query .= "GROUP BY EndTime";
610                                 break;
611                 }
612                 
613                 $result = $this->db_link->query( $query );
614                 
615                 if( PEAR::isError( $result ) ) {
616                         $this->TriggerDBError("Unable to get Job Files from catalog", $result);
617                 }else{
618                         $stored_bytes = 0;
619                         $tmp = $result->fetchRow();
620                         
621                         $day                    = date( "D d", strtotime($end_date) );
622                         $stored_files   = $tmp['stored_files'];
623                         
624                         return array( $day, $stored_files );
625                 }                       
626         }
627         
628         private function TriggerDBError( $message, $db_error)
629         {
630                 echo 'Error: ' . $message . '<br />';
631                 echo 'Standard Message: ' . $db_error->getMessage() . '<br />';
632                 echo 'Standard Code: ' . $db_error->getCode() . '<br />';
633                 echo 'DBMS/User Message: ' . $db_error->getUserInfo() . '<br />';
634                 echo 'DBMS/Debug Message: ' . $db_error->getDebugInfo() . '<br />';
635                 exit;
636         }
637 } // end class Bweb
638 ?>