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