Subversion Repositories computer_asset_manager_v1

Rev

Rev 94 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
23 rodolico 1
<?php
2
 
3
/*
4
 * Requires php-pear and libyaml under Debian Wheezy
5
 *
6
 * apt-get install php-pear php5-dev libyaml-dev libyaml-0-2 libyaml-0-2-dbg
7
 * pecl install yaml
8
 * echo 'extension=yaml.so' >> /etc/php5/cli/php.ini
9
 * echo 'extension=yaml.so' >> /etc/apache2/cli/php.ini
10
 * 
25 rodolico 11
 * truncate table backups_run
24 rodolico 12
 * alter table backups_run add skipped bigint(20),add file_name varchar(60),add notes text;
13
 * alter table backups_run modify end_time  datetime null, modify start_time datetime null;
25 rodolico 14
 * alter table backups_run add added_date datetime not null;
23 rodolico 15
 * 
28 rodolico 16
 * Version 0.1.1 20160713 RWR
17
 * Fixed issue where report had no transfers. In that case, header lines
18
 * are terminated by two blank lines, not the constant 'sending incremental file
19
 * list'. Simply modified to terminate on an empty line OR the constant
20
 * 
21
 * Also set it up to only report on one file at a time, ie accept
22
 * only one parameter, and that is assumed to be a file name
35 rodolico 23
 * 
24
 * Version 0.2.0 20160826 RWR
25
 * Fixed problem where file name has YYYYMMDD_HHMMSS_servername_backup.log instead of
26
 *    YYYYMMDD_servername_backup.log (it now checks for both)
27
 * Start and end time now accepted as YYYYMMDD_HHMMSS or YYYYMMDDHHMMSS
95 rodolico 28
 *
29
 * Version 0.2.1 20191208 RWR
30
 * When numeric strings are looked for, allow comma's in them and remove them before recording in the database
31
 * Fixes modifications made to rsync where reports now contain comma's.
23 rodolico 32
*/
33
 
25 rodolico 34
   /*
35
    * This will return error codes
36
    * 1 - Invalid Data File Name
37
    * 2 - Could not open the file
38
    * 3 - Duplicate Report
39
    * 4 - Server Not Found
40
    */
41
 
42
 
23 rodolico 43
require 'library.php';
95 rodolico 44
$VERSION='0.2.1';
23 rodolico 45
 
24 rodolico 46
$results = array();
23 rodolico 47
 
24 rodolico 48
function parseFile( $filename, $path, $maxLineLength = 4096 ) {
49
   $data = array ( 
50
                     'server_name' => '',
51
                     'report_date' => '',
52
                     'start_time' => '',
53
                     'version' => '',
54
                     'end_time' => '',
28 rodolico 55
                     'files_count' => 0,
56
                     'files_size' => 0,
24 rodolico 57
                     'transferred_count' => 0,
28 rodolico 58
                     'transferred_size' => 0,
24 rodolico 59
                     'files_deleted' => 0,
60
                     'skipped' => 0,
28 rodolico 61
                     'data_sent' => 0,
62
                     'data_received' => 0,
24 rodolico 63
                     'disk_used' => '',
64
                     'notes' => '',
65
   );
94 rodolico 66
 
67
   function cleanNumber( $number ) {
68
      return preg_replace("/[^0-9.]/", "", $number );
69
   }
23 rodolico 70
 
71
 
24 rodolico 72
   $matches = array();
23 rodolico 73
 
24 rodolico 74
   $line;
23 rodolico 75
 
24 rodolico 76
   $data['file_name'] = $filename;
77
   # get server name from the file name, which should be
35 rodolico 78
   # date_time_servername.backup.log
79
   if ( preg_match( '/(\d+)_(\d+)_([a-z0-9_.-]+)\.backup\.log/', $filename, $matches ) ) {
80
      $data['report_date'] = $matches[1] . $matches[2];
81
      $data['server_name'] = $matches[3];
82
   } elseif ( preg_match( '/(\d+)_([a-z0-9_.-]+)\.backup\.log/', $filename, $matches ) ) {
24 rodolico 83
   # datetime_servername.backup.log
84
      $data['report_date'] = $matches[1];
85
      $data['server_name'] = $matches[2];
86
   } else {
87
      # ensure only three parts returned
88
      $data['error'] = "1\tInvalid Data File Name";
89
      return $data;
23 rodolico 90
   }
91
 
24 rodolico 92
   $log = fopen ( $path . '/' . $filename , 'rb' );
93
   if ( $log ) {
28 rodolico 94
      // get through the header lines, ended by either a blank line
95
      // or the constant 'sending incremental file list'
24 rodolico 96
      while (( $line = fgets( $log, $maxLineLength )) !== false ) {
28 rodolico 97
         $line = rtrim( $line );
98
         if ( $line ) {
99
            if ( preg_match( '/^backup\s+v?([\d.]+)$/', $line, $matches ) ) {
100
               $data['version'] = $matches[1];
101
            }
102
            // this line is the end of the header lines
103
            if ( preg_match( '/sending incremental file list/', $line, $matches ) ) {
104
               break;
105
            }
106
         } else {
24 rodolico 107
            break;
108
         }
23 rodolico 109
      }
110
 
24 rodolico 111
      // count line by line processing information. These are the actual lines
112
      // indicating files checked and how they were processed
113
      while (( $line = fgets( $log, $maxLineLength )) !== false ) {
114
         $line = rtrim($line);
115
         if ( $line ) {
116
            if ( ! preg_match( '~/$~', $line ) ) // count lines not ending in /, ie not directories
117
               $data['transferred_count']++;
118
            if ( preg_match( '/^deleting /', $line ) ) // count number deleted
119
               $data['files_deleted']++;
120
            if ( preg_match( '/^skipping /', $line ) )  // count number skipped
121
               $data['skipped']++ ;
122
         } else {
123
            break;
124
         }
23 rodolico 125
      }
24 rodolico 126
      $data['transferred_count'] -= $data['files_deleted'] + $data['skipped'];
23 rodolico 127
 
24 rodolico 128
      // we should have a stats summary at the end
129
      while (( $line = fgets( $log, $maxLineLength )) !== false ) {
130
         $data['notes'] .= $line; // everything here goes into notes
94 rodolico 131
         if ( preg_match( '/Number of files:\s+([0-9,]+)/', $line, $matches ) ) {
132
            $data['files_count'] = cleanNumber($matches[1]);
133
         } elseif ( preg_match( '/Number of files transferred:\s+([0-9,]+)/', $line, $matches ) ) {
134
            $data['transferred_count'] = cleanNumber($matches[1]);
135
         } elseif ( preg_match( '/Total file size:\s+([0-9,]+) bytes/', $line, $matches )  ) {
136
            $data['files_size'] = cleanNumber($matches[1]);
137
         } elseif ( preg_match( '/Total transferred file size:\s+([0-9,]+) bytes/', $line, $matches )  ) {
138
            $data['transferred_size'] = cleanNumber($matches[1]);
139
         } elseif ( preg_match( '/Total bytes sent:\s+([0-9,]+)/', $line, $matches )  ) {
140
            $data['data_sent'] = cleanNumber($matches[1]);
141
         } elseif ( preg_match( '/Total bytes received:\s+([0-9,]+)/', $line, $matches )  ) {
142
            $data['data_received'] = cleanNumber($matches[1]);
24 rodolico 143
         } elseif ( preg_match( '/Backup Version\s+v?([\d.]+)/', $line, $matches )  ) {
94 rodolico 144
         // this is the end of the rsync stats summary, and the
24 rodolico 145
            // beginning of the rsbackup summary
146
            $data['version'] = $matches[1];
147
            break;
148
         }
23 rodolico 149
      }
150
 
24 rodolico 151
      // process rsbackup summary
152
      while (( $line = fgets( $log, $maxLineLength )) !== false ) {
153
         $data['notes'] .= $line;
35 rodolico 154
         if ( preg_match( '/^Begin\s+([\d_]+)/', $line, $matches )   ) {
155
            $data['start_time'] = str_replace( '_', '', $matches[1] );
156
         } elseif ( preg_match( '/Complete\s+([\d_]+)/', $line, $matches )   ) {
157
            $data['end_time'] = str_replace( '_', '', $matches[1] );
24 rodolico 158
         } elseif ( preg_match( '/^Status:/', $line, $matches )   ) {
159
            break;
23 rodolico 160
         }
161
      }
24 rodolico 162
      // the rest of it just goes into notes
163
      while (( $line = fgets( $log, $maxLineLength )) !== false ) {
164
         $data['notes'] .= $line;
23 rodolico 165
      }
24 rodolico 166
      fclose ( $log );
167
   } else {
168
      $data['error'] = "2\tCould not open file name $filename for read";
23 rodolico 169
   }
24 rodolico 170
   return $data;
23 rodolico 171
 
24 rodolico 172
}
23 rodolico 173
 
174
 
24 rodolico 175
function recordMessage( $message ) {
176
   global $results;
177
   $results[] = $message;
178
}
23 rodolico 179
 
180
 
24 rodolico 181
/* 
35 rodolico 182
 * checks for a duplicate report, ie one that has already been run.q
24 rodolico 183
 * if this computer has a report already for this date/time
184
 */ 
185
function checkDuplicate( $backups_id, $report_date) {
186
   $sql = "select count(*) from backups_run where backups_id = $backups_id and report_date = $report_date";
187
   $count = getOneDBValue( $sql );
188
   return $count ? "3\tDuplicate Report for $backups_id on $report_date" : null;
189
} // recordReport
23 rodolico 190
 
191
 
24 rodolico 192
function findServer( $name ) {
193
   $sql = "select distinct( device_id ) from (select device_id from device where name = '$name' union select device_id from device_alias where alias = '$name') a";
194
   $device_id = getOneDBValue( $sql );
195
   if ( ! isset( $device_id ) ) {
196
      recordMessage( "Could not locate device $name, not processing record" );
197
      return null;
23 rodolico 198
   }
24 rodolico 199
   $sql = "select backups_id from backups where device_id = $device_id";
200
   $backups_id = getOneDBValue( $sql );
201
   if ( isset( $backups_id ) ) {
202
      return $backups_id;
203
   } else {
204
      recordMessage( "Adding server $name to backups" );
205
      $sql = "insert into backups ( device_id,backups_server_id,notes ) values ( $device_id, 1, 'Automatically Added' )";
206
      $results = queryDatabaseExtended( $sql );
207
      return $results['insert_id'];
208
   }
209
}
23 rodolico 210
 
211
 
24 rodolico 212
/* 
213
 * Creates an entry in the backups_run table
214
 */ 
215
function recordReport( $report ) {
216
 
217
   $keys = array();
218
   $values = array();
219
 
220
   foreach ( $report as $keyfield => $value ) {
221
      if ( $keyfield == 'server_name' ) {
222
         $keys[] = 'backups_id';
223
         $device_id = findServer( $value );
224
         if ( isset( $device_id ) ) {
225
            $values[] = $device_id;
226
            $duplicate = checkDuplicate( $device_id, $report['report_date'] );
227
            if ( $duplicate )
228
               return $report['file_name'] . "\t$duplicate";
229
         } else {
230
            return $report['file_name'] . "\t4\tServer not found";
23 rodolico 231
         }
24 rodolico 232
      } else {
233
         $keys[] = $keyfield;
234
         $values[] = makeSafeSQLValue( $value );
23 rodolico 235
      }
24 rodolico 236
   }
25 rodolico 237
   $keys[] = 'added_date'; $values[] = 'now()';
24 rodolico 238
   $sql = 'insert into backups_run (' . implode( ',', $keys ) . ') values (' . implode( ',', $values ) . ')';
239
   // if we made it this far, we are ok, so just add the report id
240
   $result = queryDatabaseExtended( $sql );
241
   return $report['file_name'] . "\t0\tok";
242
} // recordReport
23 rodolico 243
 
244
 
245
/*
246
 * we don't know where the configuration file will be, so we have a list
247
 * below (searchPaths) to look for it. It will load the first one it 
248
 * finds, then exit. THUS, you could have multiple configuration files
249
 * but only the first one in the list will be used
250
 */
251
 
24 rodolico 252
$confFileName = "rsbackupRead.conf.yaml";
253
$searchPaths = array( '/etc/camp', '/opt/camp', '/opt/camp/rsbackup', $_SERVER['SCRIPT_FILENAME'], getcwd() );
23 rodolico 254
$configuration = array();
255
foreach ( $searchPaths as $path ) {
256
   if ( file_exists( "$path/$confFileName" ) ) {
257
      $configuration = yaml_parse_file( "$path/$confFileName" );
258
      break; // exit out of the loop; we don't try to load it more than once
259
   } // if
260
} // foreach
261
 
24 rodolico 262
 
23 rodolico 263
mysql_connect( $configuration['database']['databaseServer'], $configuration['database']['databaseUsername'], $configuration['database']['databasePassword'] ) or die(mysql_error());
264
mysql_select_db( $configuration['database']['database'] ) or die(mysql_error());
265
 
266
 
267
 
28 rodolico 268
$filename = $argv[1];
269
$report = parseFile( $filename, $configuration['datapath'] . '/' . $configuration['unprocessed_path'] );
35 rodolico 270
# print_r( $report ); print "\n";
28 rodolico 271
 
272
if ( isset( $report['error'] ) ) { // we had an error processing the report
273
   $result[] = "$filename\t" . $report['error']; 
274
} else {
275
   $result[] = recordReport( $report );
23 rodolico 276
}
277
 
24 rodolico 278
print implode( "\n", $result );
279
 
23 rodolico 280
?>