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