/[monit]/monit/validate.c
ViewVC logotype

Diff of /monit/validate.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.46 by hauk, Wed Jul 2 19:32:03 2003 UTC revision 1.47 by chopp, Thu Jul 3 11:43:32 2003 UTC
# Line 72  static sigjmp_buf timeout; Line 72  static sigjmp_buf timeout;
72    
73  static int  check_skip(Service_T);  static int  check_skip(Service_T);
74  static void connection_timeout(int);  static void connection_timeout(int);
 static int  check_timeout(Service_T);  
 static int  check_checksum(Service_T);  
 static int  do_not_validate(Service_T);  
75  static int  compare_value(int, int, int);  static int  compare_value(int, int, int);
76  static void reset_resource_counter(Service_T);  static void reset_resource_counter(Service_T);
77    
78    static int  check_process(Service_T, ProcessTree_T *, int);
79  static int  check_process_state(Service_T, char *);  static int  check_process_state(Service_T, char *);
80  static int  check_device(Service_T, Device_T, char *);  static int  check_process_resources(Service_T, Resource_T, char *);
81  static int  check_connection(Service_T, Port_T, char *);  static int  check_process_connection(Service_T, Port_T, char *);
 static void do_validate(Service_T, ProcessTree_T *, int);  
 static int  check_resources(Service_T, Resource_T, char *);  
 static int  check_timestamp(Service_T, Timestamp_T, char *);  
 static void vlog(char * report, int n, Service_T s, char *m,...);  
82    
83    static int  check_device(Service_T);
84    static int  check_device_resources(Service_T, Device_T, char *);
85    
86    static int  check_file(Service_T);
87    
88    static int  check_directory(Service_T);
89    
90    static int  check_timestamps(Service_T);
91    static int  check_timestamp_item(Service_T, Timestamp_T, char *);
92    
93    static int  check_timeout(Service_T);
94    
95    static int  check_checksum(Service_T);
96    
97    static void do_validate(Service_T, ProcessTree_T *, int);
98    static int  do_not_validate(Service_T);
99    static void vlog(char *, int, Service_T, char *,...);
100    static int  eval_actions(int, Service_T, char *, char *, int);
101    
102  /* ---------------------------------------------------------------- Public */  /* ---------------------------------------------------------------- Public */
103    
# Line 140  void validate() { Line 153  void validate() {
153   */   */
154  static void do_validate(Service_T s, ProcessTree_T * pt, int treesize) {  static void do_validate(Service_T s, ProcessTree_T * pt, int treesize) {
155        
   Port_T pp;  
   Device_T td;  
   Resource_T pr;  
   Timestamp_T tl;  
   pid_t  pid= -1;  
156    sigset_t ns,os;    sigset_t ns,os;
   char report[STRLEN];  
   struct stat stat_buf;  
157    
158    ASSERT(s);    ASSERT(s);
159    ASSERT(s->path);    ASSERT(s->path);
# Line 173  static void do_validate(Service_T s, Pro Line 179  static void do_validate(Service_T s, Pro
179    
180    case TASK_PROCESS:    case TASK_PROCESS:
181    
182      /* Test for running process */      if (! check_process(s, pt, treesize))
183      if(!(pid= is_process_running(s))) {        goto reinstall;
184    
185        /* Reset the proc info object to prevent false data in the first run */      break;
186        memset(s->procinfo, 0, sizeof *(s->procinfo));  
187          case TASK_DEVICE:
188        Event_post(s, EVENT_START, "Reason: Process is not running.");  
189        if (! check_device(s))
190        goto reinstall;        goto reinstall;
       
     } else {  
       
         DEBUG("'%s' is running with pid %d\n", s->name, (int)pid);  
       
     }  
191    
192      if(Run.doprocess) {      break;
193    
194        if(update_process_data(s, pt, treesize, pid)) {  
195      case TASK_FILE:
196    
197        if (! check_file(s))
198          goto reinstall;
199    
200        break;
201    
202      case TASK_DIRECTORY:
203    
204        if (! check_directory(s))
205          goto reinstall;
206    
207        break;
208    
209      default:
210        break;
211    
212      }
213    
214      /** Common task actions */
215      if (! check_timestamps(s))
216        goto reinstall;
217    
218          
219      reinstall:
220        
221          if(! check_process_state(s, report)) {    /* Remove the SIGTERM block */
222      pthread_sigmask(SIG_SETMASK, &os, NULL);
223    
224            Event_post(s, EVENT_RESOURCE, "Reason: %s\n", report);    /* Release service action mutex */
225      END_LOCK;
226    
227    }
228    
229    
230    /**
231     * Returns the logical OR of pre-condition tests.
232     * A variant of the template-method pattern
233     */
234    static int do_not_validate(Service_T s) {
235    
236      ASSERT(s);
237      
238      return(!s->do_monitor  ||
239             check_skip(s)    ||
240             check_timeout(s) ||
241             check_checksum(s));
242    
243    }
244    
245    
246    /**
247     * Evaluate actions of a service.  Post appropriate actions if necessary.
248     * Return FALSE in case of a fatal event.
249     */
250    static int eval_actions(int action, Service_T s, char *report, char *check,
251                            int alert_event) {
252    
253      ASSERT(s);
254      ASSERT(report);
255      ASSERT(check);
256    
257      switch(action) {
258      case ACTION_ALERT:
259        if(s->def_timeout) s->nstart++;
260        Event_post(s, alert_event, "Reason: %s\n", report);
261        break; /* continue */
262            
263          } else {    case ACTION_STOP:
264              Event_post(s, EVENT_STOP, "Reason: %s\n", report);
265            DEBUG("'%s' check_process_state() passed.\n", s->name);      return FALSE;
         
         }  
266            
267          for(pr= s->resourcelist; pr; pr= pr->next) {    case ACTION_RESTART:
268              Event_post(s, EVENT_RESTART, "Reason: %s\n", report);
269            if(!check_resources(s, pr, report)) {      return FALSE;
270                
271              switch(pr->action) {    default:
272              case ACTION_ALERT:      log("'%s' Unknow %s failure action.\n", s->name, check);
273                if(s->def_timeout) s->nstart++;      break;
274                Event_post(s, EVENT_RESOURCE, "Reason: %s\n", report);      
275                /* We are also interested in other alerts/stops/restarts! */    }
               pr->cycle=0;  
               break;  
276    
277              case ACTION_STOP:    return TRUE;
278                Event_post(s, EVENT_STOP, "Reason: %s\n", report);  }
               reset_resource_counter(s);  
               goto reinstall;  
279    
             case ACTION_RESTART:  
               Event_post(s, EVENT_RESTART, "Reason: %s\n", report);  
               reset_resource_counter(s);  
               goto reinstall;  
280    
281              default:  /**
282                log("'%s' Unknow resource failure action.\n", s->name);   * Validate all given timestamps of a service s.  Events are posted according
283                break;   * to its configuration.  In case of a fatal event FALSE is returned.
284              }   */
285    static int check_timestamps(Service_T s) {
286    
287            }    Timestamp_T tl;
288            char report[STRLEN];
         }  
           
       } else {  
289    
290          log("'%s' failed to get service data\n", s->name);    for(tl= s->timestamplist; tl; tl= tl->next) {
291                
292        }      if(!check_timestamp_item(s, tl, report)) {
293            
294          if (! eval_actions(tl->action, s, report, "timestamp",
295                             EVENT_TIMESTAMP)) {
296            
297            return FALSE;
298    
299      }        }
300    
     /* Test each host:port and protocol in the service's portlist */  
     for(pp= s->portlist; pp; pp= pp->next) {  
       
       if(!check_connection(s, pp, report)) {  
         
         Event_post(s, EVENT_RESTART, "Reason: %s\n", report);  
         goto reinstall;  
         
       }  
       
301      }      }
     break;  
302    
303    case TASK_DEVICE:    }    
304    
305      /* Test devices */    return TRUE;
     if(s->devicelist) {  
306    
307        if(!get_fsusage(s->path, s->devinfo)) {  }
         Event_post(s, EVENT_RESTART, "Reason: unable to read device state\n");  
         goto reinstall;  
       }  
308    
309        for(td= s->devicelist; td; td= td->next) {  /**
310     * Validate a given directory service s.  Events are posted according to
311     * its configuration.  In case of a fatal event FALSE is returned.
312     */
313    static int check_directory(Service_T s) {
314    
315          if(!check_device(s, td, report)) {    struct stat stat_buf;
316    
317            switch(td->action) {    if(stat(s->path, &stat_buf) != 0) {
           case ACTION_ALERT:  
             Event_post(s, EVENT_RESOURCE, "Reason: %s\n", report);  
             break;  
   
           case ACTION_STOP:  
             Event_post(s, EVENT_STOP, "Reason: %s\n", report);  
             goto reinstall;  
   
           case ACTION_RESTART:  
             Event_post(s, EVENT_RESTART, "Reason: %s\n", report);  
             goto reinstall;  
   
           default:  
             log("'%s' Unknow device failure action.\n", s->name);  
             break;  
           }  
318    
319          }      log("'%s' doesn't exist\n", s->name);
320        Event_post(s, EVENT_RESTART, "Reason: directory doesn't exist\n");
321        return FALSE;
322    
323        }    }
324    
325      }    if(!S_ISDIR(stat_buf.st_mode)) {
     break;  
326    
327    case TASK_FILE:      log("'%s' is not directory\n", s->name);
328        Event_post(s, EVENT_RESTART, "Reason: object is not directory\n");
329        return FALSE;
330    
331      if(stat(s->path, &stat_buf) != 0) {    }
       log("'%s' doesn't exist\n", s->name);  
       Event_post(s, EVENT_RESTART, "Reason: file doesn't exist\n");  
       goto reinstall;  
     }  
332    
333      if(!S_ISREG(stat_buf.st_mode)) {    if( s->perm != -1 && (stat_buf.st_mode & 07777) != s->perm ) {
       log("'%s' is not regular file\n", s->name);  
       Event_post(s, EVENT_RESTART, "Reason: object is not file\n");  
       goto reinstall;  
     }  
334    
335      if( s->perm != -1 && (stat_buf.st_mode & 07777) != s->perm ) {      log("'%s' permission test failed -- current permission: %o\n",
       log("'%s' permission test failed -- current permission: %o\n",  
336          s->name, stat_buf.st_mode&07777);          s->name, stat_buf.st_mode&07777);
337        Event_post(s, EVENT_RESTART, "Reason: permission test failed: %o\n",      Event_post(s, EVENT_RESTART, "Reason: permission test failed: %o\n",
338                   stat_buf.st_mode&07777);                 stat_buf.st_mode&07777);
339        goto reinstall;      return FALSE;
     }  
340    
341      DEBUG("'%s' file permission check passed [current permission=%o]\n",    }
       s->name, stat_buf.st_mode&07777);  
342    
343      break;    DEBUG("'%s' directory permission check passed [current permission=%o]\n",
344            s->name, stat_buf.st_mode&07777);
345    
346    case TASK_DIRECTORY:    return TRUE;
347    
348      if(stat(s->path, &stat_buf) != 0) {  }
       log("'%s' doesn't exist\n", s->name);  
       Event_post(s, EVENT_RESTART, "Reason: directory doesn't exist\n");  
       goto reinstall;  
     }  
349    
350      if(!S_ISDIR(stat_buf.st_mode)) {  /**
351        log("'%s' is not directory\n", s->name);   * Validate a given file service s.  Events are posted according to
352        Event_post(s, EVENT_RESTART, "Reason: object is not directory\n");   * its configuration.  In case of a fatal event FALSE is returned.
353        goto reinstall;   */
354      }  static int check_file(Service_T s) {
355    
356      if( s->perm != -1 && (stat_buf.st_mode & 07777) != s->perm ) {    struct stat stat_buf;
       log("'%s' permission test failed -- current permission: %o\n",  
         s->name, stat_buf.st_mode&07777);  
       Event_post(s, EVENT_RESTART, "Reason: permission test failed: %o\n",  
                  stat_buf.st_mode&07777);  
       goto reinstall;  
     }  
357    
358      DEBUG("'%s' directory permission check passed [current permission=%o]\n",    if(stat(s->path, &stat_buf) != 0) {
       s->name, stat_buf.st_mode&07777);  
359    
360      break;      log("'%s' doesn't exist\n", s->name);
361        Event_post(s, EVENT_RESTART, "Reason: file doesn't exist\n");
362        return FALSE;
363    
364    default:    }
365      break;    
366      if(!S_ISREG(stat_buf.st_mode)) {
367    
368        log("'%s' is not regular file\n", s->name);
369        Event_post(s, EVENT_RESTART, "Reason: object is not file\n");
370        return FALSE;
371    
372    }    }
373      
374      if( s->perm != -1 && (stat_buf.st_mode & 07777) != s->perm ) {
375    
376        log("'%s' permission test failed -- current permission: %o\n",
377            s->name, stat_buf.st_mode&07777);
378        Event_post(s, EVENT_RESTART, "Reason: permission test failed: %o\n",
379                   stat_buf.st_mode&07777);
380        return FALSE;
381    
382    /** Common task actions */    }
383    for(tl= s->timestamplist; tl; tl= tl->next) {    
384      DEBUG("'%s' file permission check passed [current permission=%o]\n",
385            s->name, stat_buf.st_mode&07777);
386    
387      return TRUE;
388    
389    }
390    
391    /**
392     * Validate a given device service s.  Events are posted according to
393     * its configuration.  In case of a fatal event FALSE is returned.
394     */
395    static int check_device(Service_T s) {
396    
397      Device_T td;
398      char report[STRLEN];
399    
400      /* Test devices */
401      if(s->devicelist) {
402        
403        if(!get_fsusage(s->path, s->devinfo)) {
404                
405      if(!check_timestamp(s, tl, report)) {        Event_post(s, EVENT_RESTART, "Reason: unable to read device state\n");
406          return FALSE;
407          
408        }
409        
410        for(td= s->devicelist; td; td= td->next) {
411          
412          if(!check_device_resources(s, td, report)) {
413                    
414        switch(tl->action) {          if (! eval_actions(td->action, s, report, "device",
415        case ACTION_ALERT:                             EVENT_RESOURCE)) {
           if(s->def_timeout) s->nstart++;  
           Event_post(s, EVENT_TIMESTAMP, "Reason: %s\n", report);  
           break; /* continue */  
416                        
417        case ACTION_STOP:            return FALSE;
418            Event_post(s, EVENT_STOP, "Reason: %s\n", report);            
419            goto reinstall;          }
420            
       case ACTION_RESTART:  
           Event_post(s, EVENT_RESTART, "Reason: %s\n", report);  
           goto reinstall;  
   
       default:  
           log("'%s' Unknow timestamp failure action.\n", s->name);  
           break;  
   
421        }        }
422    
423      }      }
424        
425      }
426    
427    }        return TRUE;
         
   reinstall:  
     
   /* Remove the SIGTERM block */  
   pthread_sigmask(SIG_SETMASK, &os, NULL);  
428    
   /* Release service action mutex */  
   END_LOCK;  
   
429  }  }
430    
   
431  /**  /**
432   * Returns the logical OR of pre-condition tests.   * Validate a given process service s.  Events are posted according to
433   * A variant of the template-method pattern   * its configuration.  In case of a fatal event FALSE is returned.
434   */   */
435  static int do_not_validate(Service_T s) {  static int check_process(Service_T s, ProcessTree_T * pt, int treesize) {
436    
437    ASSERT(s);    Port_T pp;
438      Resource_T pr;
439      pid_t  pid= -1;
440      char report[STRLEN];
441        
442    return(!s->do_monitor  ||        /* Test for running process */
443           check_skip(s)    ||      if(!(pid= is_process_running(s))) {
          check_timeout(s) ||  
          check_checksum(s));  
444    
445  }        /* Reset the proc info object to prevent false data in the first run */
446          memset(s->procinfo, 0, sizeof *(s->procinfo));
447        
448          Event_post(s, EVENT_START, "Reason: Process is not running.");
449          return FALSE;
450        
451        } else {
452        
453            DEBUG("'%s' is running with pid %d\n", s->name, (int)pid);
454        
455        }
456    
457        if(Run.doprocess) {
458    
459          if(update_process_data(s, pt, treesize, pid)) {
460      
461            if(! check_process_state(s, report)) {
462    
463              Event_post(s, EVENT_RESOURCE, "Reason: %s\n", report);
464        
465            } else {
466          
467              DEBUG("'%s' check_process_state() passed.\n", s->name);
468          
469            }
470        
471            for(pr= s->resourcelist; pr; pr= pr->next) {
472          
473              if(!check_process_resources(s, pr, report)) {
474            
475                pr->cycle=0;
476    
477                if (! eval_actions(pr->action, s, report, "resource",
478                                   EVENT_TIMESTAMP)) {
479                  
480                  reset_resource_counter(s);
481                  return FALSE;
482    
483                }
484    
485              }
486          
487            }
488            
489          } else {
490    
491            log("'%s' failed to get service data\n", s->name);
492          
493          }
494    
495        }
496    
497        /* Test each host:port and protocol in the service's portlist */
498        for(pp= s->portlist; pp; pp= pp->next) {
499        
500          if(!check_process_connection(s, pp, report)) {
501          
502            Event_post(s, EVENT_RESTART, "Reason: %s\n", report);
503    
504            return FALSE;
505          }
506        
507        }
508    
509    
510        return TRUE;
511        
512    }
513    
514  /**  /**
515   * Returns TRUE if the connection and protocol test succeeded   * Returns TRUE if the connection and protocol test succeeded
516   * otherwise FALSE.   * otherwise FALSE.
517   */   */
518  static int check_connection(Service_T s, Port_T pp, char *report) {  static int check_process_connection(Service_T s, Port_T pp, char *report) {
519    
520    volatile int rv= TRUE;    volatile int rv= TRUE;
521    
# Line 597  static void reset_resource_counter(Servi Line 699  static void reset_resource_counter(Servi
699   * Returns TRUE if the proc test succeeded   * Returns TRUE if the proc test succeeded
700   * otherwise FALSE.   * otherwise FALSE.
701   */   */
702  static int check_resources(Service_T s, Resource_T pr, char *report) {  static int check_process_resources(Service_T s, Resource_T pr, char *report) {
703    
704    ProcInfo_T pi;    ProcInfo_T pi;
705    int okay= TRUE;    int okay= TRUE;
# Line 935  static int check_checksum(Service_T s) { Line 1037  static int check_checksum(Service_T s) {
1037  /**  /**
1038   * Returns TRUE if the timestamp test succeded, otherwise FALSE   * Returns TRUE if the timestamp test succeded, otherwise FALSE
1039   */   */
1040  static int check_timestamp(Service_T s, Timestamp_T t, char *report) {  static int check_timestamp_item(Service_T s, Timestamp_T t, char *report) {
1041    
1042    time_t now;    time_t now;
1043    time_t timestamp;    time_t timestamp;
# Line 969  static int check_timestamp(Service_T s, Line 1071  static int check_timestamp(Service_T s,
1071   * Returns TRUE if the device test succeeded   * Returns TRUE if the device test succeeded
1072   * otherwise FALSE.   * otherwise FALSE.
1073   */   */
1074  static int check_device(Service_T t, Device_T td, char *report) {  static int check_device_resources(Service_T t, Device_T td, char *report) {
1075    
1076    ASSERT(t);    ASSERT(t);
1077    ASSERT(td);    ASSERT(td);

Legend:
Removed from v.1.46  
changed lines
  Added in v.1.47

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26