Disabled DEBUG output
[gnucomo.git] / src / gcm_daemon / gcm_daemon.php
1 #!/usr/bin/php
2 <?PHP
3 /**********************************************************************************
4 **  (c) Copyright 2002, Brenno J.S.A.A.F. de Winter, De Winter Information Solutions
5 ** This is free software; you can redistribute it and/or modify it under the
6 ** terms of the GNU General Public License, see the file COPYING.
7 ***********************************************************************************/
8
9
10 /*
11    NAME         : gcm_daemon
12    AUTHOR       : Brenno J.S.A.A.F. de Winter
13                   De Winter Information Solutions
14    COPYRIGHT    : 2002 - De Winter Information Solutions,
15                   Brenno J.S.A.A.F. de Winter
16
17    * DATES *
18    First        : November 8th 2002
19    Gnucomo-0.0.3: December 6th 2002
20
21  $Log: gcm_daemon.php,v $
22  Revision 1.13  2003-08-14 10:22:42  arjen
23  Disabled DEBUG output
24
25  Revision 1.12  2003/08/05 07:46:37  arjen
26  BUGFIX: Print an error message if a parameter does not have
27  any history.
28
29  Revision 1.11  2003/07/09 07:25:02  arjen
30  Gcm_daemon gathers statistics on parameters, notifications, etc. for all objects.
31
32  Revision 1.10  2003/03/29 08:33:58  arjen
33  In phpclasses/db.class.php: Added the database connection string as
34  an argument to the function copy_db_class.
35  Fixed the PHP member function db::db_connect(). The Postgres connection
36  string is now passed as an argument to that function.
37
38  Revision 1.9  2003/02/21 08:37:59  arjen
39  Added new table to the database: log_adv_daemon_email.
40
41
42 */
43
44 // $Id: gcm_daemon.php,v 1.13 2003-08-14 10:22:42 arjen Exp $
45
46 ini_set('include_path', '.:./classes:../phpclasses');
47
48 //Tell the log that we're up.
49 define_syslog_variables();
50 openlog("gnucomo", LOG_PID, LOG_DAEMON);
51 syslog(LOG_INFO, "gcm_daemon started");
52
53 require_once "gnucomo_config.php";
54 require_once "db.class.php";
55 require_once "gnucomo.process_log.php";
56
57 // Set the standard variables //
58 $project_name   = "gnucomo";    //name of the entire project
59 $app_name       = "gcm_daemon"; //name of the application running
60 $developrelease = "FALSE";      //Indicates if special debug settings are needed
61 $db_version     = 42;           //The db_version indicates what the level of
62                                 //the database should be. If the database is
63                                 //old an update will be generated.
64 $gcmd_version   = 5;            //This value indicates the active version of the gcm_daemon,
65                                 //which is saved in the database. Log records that were not
66                                 //recognized before will now be recognized. The version doesn't
67                                 //mean anything in the overall gnucomo project.
68
69 //Avoid time-limit issues
70 set_time_limit(0);
71
72
73 // Read the database settings //
74 $class_settings = new gnucomo_config();
75 $class_settings->read($project_name);
76
77 //Open an connection to the database
78 $dbms_type = $class_settings->find_parameter("database", "type");
79 $dbms_host = $class_settings->find_parameter("database", "host");
80 $dbms_name = $class_settings->find_parameter("database", "name");
81 $dbms_user = $class_settings->find_parameter("gcm_daemon", "user");
82 $dbms_password = $class_settings->find_parameter("gcm_daemon", "password");
83
84 db_select($dbms_type);
85 $dbms = new db();
86 $dbms->db_host = $dbms_host;
87 $dbms->db_name = $dbms_name;
88 $dbms->db_user = $dbms_user;
89 $dbms->db_password = $dbms_password;
90 $dbms->db_connect($class_settings->database());
91
92 if ($dbms->have_db_connection() == "FALSE") {
93   exit ("Database connection failed.");
94 } else {
95   //The database connection has been made.
96   $dbms_working = copy_db_class($dbms, $class_settings->database());
97 }
98
99 //Verify if the database is up-to-date by checking the versionnumber
100 $local_sql = "SELECT setting_value FROM db_value WHERE setting = 'db_version' ";
101 $dbms->query($local_sql);
102
103 if ($dbms->fetch_row() == "TRUE") {
104   $active_version = $dbms->db_result_row[0];
105
106   //Update the database to the most recent version.
107   if ($active_version < $db_version) {
108      include ("gnucomo_db_version.php");
109   }
110 } else {
111   syslog (LOG_INFO, "Couldn't initialize database version. Is this a gnucomo database?");
112   die ("Couldn't initialize database version.\n");
113 }
114
115 //If there is a new gcm_daemon_version the logrecords that couldn't be understood can be
116 //reprocessed. For this reason processed is now changed to false again for not recognized
117 //records.
118 $local_sql = "SELECT setting_value FROM db_value WHERE setting = 'gcm_daemon_version'";
119 $dbms->query($local_sql);
120
121 if ($dbms->fetch_row() == "TRUE") {
122    if ($dbms->db_result_row[0] < $gcmd_version) {
123       //Reactive log-records that weren't understood earlier.
124       $local_sql = "UPDATE log SET processed = false WHERE logid NOT IN (SELECT DISTINCT logid FROM log_adv)";
125       $dbms->query($local_sql);
126
127       //Update de gcm_daemon version in the database
128       $local_sql = "UPDATE db_value SET setting_value = '".$gcmd_version;
129       $local_sql .= "' WHERE setting = 'gcm_daemon_version'";
130       $dbms->query($local_sql);
131
132    }
133
134 }
135
136 //Now we loop the tasks that we have to do.
137
138
139 do {
140
141    //  Gather the statistics for each object
142
143    $obj_result = $dbms->query("SELECT objectid FROM object");
144    for ($obj = 0; $obj < $dbms->num_rows($obj_result); $obj++)
145    {
146       $object = $dbms->fetch_object($obj_result, $obj);
147       echo "Gathering statistics for object " . $object->objectid . "\n";
148       GatherStatistics($object->objectid);
149    }
150
151   //At this place we start processing new log-lines
152   process_log ();
153   //notificationstats();  //  This function is obsolete
154   find_notifications();
155
156   $keep_running = 'FALSE';
157
158 } while ($keep_running == 'TRUE');
159
160 //Tell the log that we're ending our efforts in a nice way
161 syslog (LOG_INFO, "gcm_daemon ended nicely");
162
163 function process_log () {
164
165  /* This function will walk through the log-records that haven't been processed
166   * first a snapshot will be created of a the non-processed records.
167   * sequentially each record will dealt with. By doing that changes will be made
168   * in several log_adv_xxx tables
169   * INPUT  : NONE
170   * OUTPUT : NONE
171   */
172   global $dbms;
173   global $dbms_working;
174   global $class_settings;
175
176   //Find records in log that still have to be processed.
177
178   $local_sql = "SELECT setting_value FROM db_value WHERE setting = 'log_processing'";
179   $dbms->query($local_sql);
180
181   if ($dbms->fetch_row() == "TRUE") {
182      $last_log = $dbms->db_result_row[0];
183   }
184
185   //Query the log-table
186   $local_sql = "SELECT * FROM log WHERE logid > CAST(".$last_log." AS BIGINT) order by logid";
187   $dbms->query($local_sql);
188
189   //Update the log-statistics in the object-table
190   $local_statistics_db = copy_db_class($dbms, $class_settings->database());
191   $local_findobject_db = copy_db_class($dbms, $class_settings->database());
192
193   //Make totals
194   $local_upper_row = $dbms->num_rows() + $last_log + 1;
195   $local_sql = "SELECT COUNT(logid), objectid from log WHERE logid > CAST(". $last_log .
196       " AS BIGINT) AND logid < CAST (" . $local_upper_row . " AS BIGINT) GROUP BY objectid";
197   $local_statistics_db->query ($local_sql);
198
199   //Loop the objects
200   for ($i = 1; $i <= $local_statistics_db->num_rows(); $i++) {
201       $local_object_row = $local_statistics_db->fetch_row();
202       $local_sql = "UPDATE object SET log_count = log_count + " .
203           $local_statistics_db->db_result_row[0] . " WHERE objectid = '" .
204           $local_statistics_db->db_result_row[1] . "'";
205       $local_findobject_db->query($local_sql);
206   }
207
208   $local_counter = 0;
209
210   if ($dbms->num_rows() > 0) {
211
212     //Create a database connection for changes in the database.
213     $dbms_changes = copy_db_class($dbms, $class_settings->database());
214     if ($dbms_changes->have_db_connection() == 'TRUE') {
215
216        $local_sql               = 0 ;
217        $local_sql_statistics    = "";
218        $local_object_os         = "";
219        $local_object_os_version = "";
220
221        while ($local_counter < $dbms->num_rows()) {
222
223          $local_return_row = $dbms->fetch_row();
224          if ($local_return_row == 'TRUE') {
225             //Work on active rows
226             $local_log_id = $dbms->db_result_row[0];
227
228             $local_sql_findobject = "SELECT os, os_version FROM object WHERE objectid = '".$dbms->db_result_row[1]."'";
229             $local_findobject_db->query($local_sql_findobject);
230             $local_findobject_result = $local_findobject_db->fetch_row();
231             if ($local_findobject_result == 'TRUE') {
232                 
233                 //Now work on the OS again
234                 $local_object_os = $local_findobject_db->db_result_row[0];
235                 if  ($local_object_os == "") {
236                     $local_object_os = "Linux";
237                     $local_object_os_version = "Unknown assuming Linux";
238                 } else {
239                   $local_object_os_version = $local_findobject_db->db_result_row[1];
240                 }
241              }
242
243             switch (strtolower($local_object_os)) {
244               case "linux":
245                 $local_process_return = linux_log ();
246                 break;
247               default:
248                 syslog (LOG_INFO, "Couldn't find suitable OS for processing the logline");
249                 break;
250              }
251
252             if ($local_process_return <> 'TRUE') {
253                $local_process_return = 'FALSE';
254             }
255
256          } else {
257
258            break;
259
260          }
261          $local_counter++;
262        }
263
264        //Register that the logrecords have been processed.
265        $local_sql = "UPDATE db_value SET setting_value = '".$local_log_id."' where setting = 'log_processing'";
266        $dbms->query($local_sql);
267
268
269        //Update the statistics for the object-table
270
271
272      } else {
273        syslog (LOG_INFO, "Couldn't clone database connection.");
274        die ("Couldn't reconnect to the database.\n");
275     }
276    }
277
278 }
279
280 /*
281  *   Update a single statistic for some object.
282  *   If it does not yet exist, it will be created.
283  */
284
285 function UpdateStatistic($objectid, $name, $value)
286 {
287    global $dbms;
288
289    $result = $dbms->query("SELECT objectid FROM object_statistics WHERE
290              objectid='$objectid' AND statname='$name'");
291    if ($dbms->num_rows() == 0)
292    {
293       $dbms->query("INSERT INTO object_statistics VALUES
294                     ('$objectid', '$name', '$value')");
295    }
296    else
297    {
298       $dbms->query("UPDATE object_statistics SET statvalue='$value' WHERE
299            statname='$name' AND objectid='$objectid'");
300    }
301 }
302
303 /*
304  *   Gather the statistics for a single object ($objectid).
305  *   We count the number of parameters, removed parameters, notifications
306  *   closed notifications and log entries. The totals of these are
307  *   maintained in a separate table: object_statistics.
308  */
309
310 function GatherStatistics($objectid)
311 {
312    global $dbms;
313
314    //  Gather statistics on parameters
315
316    $r = $dbms->query("SELECT paramid FROM parameter WHERE objectid=CAST('"
317                         . $objectid . "' AS BIGINT)");
318    $nr_parameters = $dbms->num_rows($r);
319
320    $removed_parameters = 0;
321    for ($p = 0; $p < $nr_parameters; $p++)
322    {
323       $param = pg_fetch_object($r, $p);
324       $qry ="select change_nature from history where paramid= CAST('";
325       $qry .= $param->paramid . "' AS BIGINT) order by modified desc";
326       $rhist = $dbms->query($qry);
327       if ($dbms->num_rows($rhist) == 0)
328       {
329          echo "ERROR: No history for parameter id " . $param->paramid . "\n";
330       }
331       else
332       {
333          $hist = $dbms->fetch_object($rhist, 0);
334          if ($hist->change_nature == "REMOVED")
335          {
336             $removed_parameters++;
337          }
338       }
339    }
340
341    UpdateStatistic($objectid, 'parameters', $nr_parameters);
342    UpdateStatistic($objectid, 'removed_parameters', $removed_parameters);
343
344    //  Gather statistics on notifications
345
346    $r = $dbms->query("SELECT count(notificationid) FROM notification WHERE
347                        objectid = CAST('" . $objectid . "' AS BIGINT)");
348    $cnt = $dbms->fetch_object($r, 0);
349    UpdateStatistic($objectid, 'notifications', $cnt->count);
350
351    $r = $dbms->query("SELECT count(notificationid) FROM notification WHERE
352                        objectid = CAST('" . $objectid . "' AS BIGINT) AND statuscode ='cls'");
353    $cnt = $dbms->fetch_object($r, 0);
354    UpdateStatistic($objectid, 'closed_notifications', $cnt->count);
355
356    //  Gather statistics on log entries
357
358    $r = $dbms->query("SELECT count(logid) FROM log WHERE
359                        objectid = CAST('" . $objectid . "' AS BIGINT)");
360    $cnt = $dbms->fetch_object($r, 0);
361    UpdateStatistic($objectid, 'logs', $cnt->count);
362 }
363
364 function notificationstats ()
365 {
366
367   //    OBSOLETE   //
368
369 /* This routine will determine how many new notifications have arrived and will
370  * update the statistics in the object-table to keep the performance acceptable
371  * INPUT  : NONE
372  * OUTPUT : NONE
373  */
374
375  global $dbms, $class_settings;
376
377  //Find records in log that still have to be processed.
378  $local_sql = "SELECT setting_value FROM db_value WHERE setting = 'last_notification'";
379  $dbms->query($local_sql);
380  $local_dbms = copy_db_class($dbms, $class_settings->database());
381
382  //Determine the last notification
383  if ($dbms->fetch_row() == "TRUE") {
384     $last_notification = $dbms->db_result_row[0];
385  }
386
387  //Determine how many records we are going to analyse.
388  $local_sql = "SELECT MAX(notificationid) FROM notification " .
389    "WHERE notificationid > CAST ('" . $last_notification . "' AS BIGINT)";
390  $dbms->query($local_sql);
391
392  //Only process data if there are new notifications
393  if ($dbms->fetch_row() == "TRUE") {
394   if (intval($dbms->db_result_row[0])>0) {
395      $local_upper = $dbms->db_result_row[0] + 1;
396      $local_max   = $dbms->db_result_row[0];
397      $local_sql   = "SELECT COUNT(objectid), objectid FROM notification " .
398        "WHERE notificationid > CAST ('" .  $last_notification ."' AS BIGINT) " .
399        "AND   notificationid < CAST ('" .  $local_upper .
400        "' AS BIGINT) GROUP BY objectid";
401      $dbms->query($local_sql);
402
403
404      for ($i=0; $i < $dbms->num_rows(); $i++) {
405        $dbms->fetch_row();
406
407        $local_sql = "UPDATE object SET notification_count = notification_count + " . $dbms->db_result_row[0] .
408          " WHERE objectid = '" . $dbms->db_result_row[1] . "'";
409       $local_dbms->query($local_sql);
410      }
411
412      $local_sql = "UPDATE db_value SET setting_value = '" . $local_max .
413        "' WHERE setting = 'last_notification'";
414      $dbms->query($local_sql);
415   }
416  }
417 }
418
419 function find_notifications () {
420
421 /*
422  *  Do something with notification checks.
423  *
424  * INPUT  : NONE
425  * OUTPUT : NONE
426  */
427
428  global $dbms;
429
430  //Find checks that have to be executed.
431  $local_sql = "select * from notification_check where age(last_execution) > time_between_executions";
432  $dbms->query($local_sql);
433  for ($i=0; $i<$dbms->num_rows(); $i++) {
434      //A check has been found that has to be executed
435      $dbms->fetch_row();
436  }
437 }
438
439 ?>
440