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

Diff of /monit/event.c

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

revision 1.50 by martinp, Sun Sep 25 20:59:49 2005 UTC revision 1.51 by martinp, Sat Nov 5 14:09:00 2005 UTC
# Line 27  Line 27 
27  #include <strings.h>  #include <strings.h>
28  #endif  #endif
29    
30    #ifdef HAVE_SYS_TYPES_H
31    #include <sys/types.h>
32    #endif
33    
34    #ifdef HAVE_SYS_STAT_H
35    #include <sys/stat.h>
36    #endif
37    
38    #ifdef HAVE_UNISTD_H
39    #include <unistd.h>
40    #endif
41    
42    #ifdef HAVE_DIRENT_H
43    #include <dirent.h>
44    #endif
45    
46  #include "monitor.h"  #include "monitor.h"
47  #include "alert.h"  #include "alert.h"
# Line 47  Line 62 
62  /* ------------------------------------------------------------- Definitions */  /* ------------------------------------------------------------- Definitions */
63    
64  EventTable_T Event_Table[]= {  EventTable_T Event_Table[]= {
65    {EVENT_CHANGED,    "Changed",                "Changed not"},    {EVENT_CHANGED,         "Changed",                "Changed not"},
66    {EVENT_CHECKSUM,   "Checksum failed",        "Checksum passed"},    {EVENT_CHECKSUM,        "Checksum failed",        "Checksum passed"},
67    {EVENT_CONNECTION, "Connection failed",      "Connection passed"},    {EVENT_CONNECTION,      "Connection failed",      "Connection passed"},
68    {EVENT_DATA,       "Data access error",      "Data access succeeded"},    {EVENT_DATA,            "Data access error",      "Data access succeeded"},
69    {EVENT_EXEC,       "Execution failed",       "Execution succeeded"},    {EVENT_EXEC,            "Execution failed",       "Execution succeeded"},
70    {EVENT_GID,        "GID failed",             "GID passed"},    {EVENT_GID,             "GID failed",             "GID passed"},
71    {EVENT_ICMP,       "ICMP failed",            "ICMP passed"},    {EVENT_ICMP,            "ICMP failed",            "ICMP passed"},
72    {EVENT_INVALID,    "Invalid type",           "Type passed"},    {EVENT_INSTANCE,        "Monit instance changed", "Monit instance changed not"},
73    {EVENT_MATCH,      "Regex match",            "No regex match"},    {EVENT_INVALID,         "Invalid type",           "Type passed"},
74    {EVENT_NONEXIST,   "Does not exist",         "Exists"},    {EVENT_MATCH,           "Regex match",            "No regex match"},
75    {EVENT_PERMISSION, "Permission failed",      "Permission passed"},    {EVENT_NONEXIST,        "Does not exist",         "Exists"},
76    {EVENT_RESOURCE,   "Resource limit matched", "Resource limit passed"},    {EVENT_PERMISSION,      "Permission failed",      "Permission passed"},
77    {EVENT_SIZE,       "Size failed",            "Size passed"},    {EVENT_RESOURCE,        "Resource limit matched", "Resource limit passed"},
78    {EVENT_TIMEOUT,    "Timeout",                "Timeout recovery"},    {EVENT_SIZE,            "Size failed",            "Size passed"},
79    {EVENT_TIMESTAMP,  "Timestamp failed",       "Timestamp passed"},    {EVENT_TIMEOUT,         "Timeout",                "Timeout recovery"},
80    {EVENT_UID,        "UID failed",             "UID passed"},    {EVENT_TIMESTAMP,       "Timestamp failed",       "Timestamp passed"},
81      {EVENT_UID,             "UID failed",             "UID passed"},
82    /* Virtual events */    /* Virtual events */
83    {EVENT_NULL,       "No Event",               "No Event"},    {EVENT_NULL,            "No Event",               "No Event"},
84  };  };
85    
86    
# Line 73  EventTable_T Event_Table[]= { Line 89  EventTable_T Event_Table[]= {
89    
90  static void handle_event(Event_T);  static void handle_event(Event_T);
91  static int  handle_action(Event_T, Action_T);  static int  handle_action(Event_T, Action_T);
92    static void Event_queue_add(Event_T);
93    
94    
95  /* ------------------------------------------------------------------ Public */  /* ------------------------------------------------------------------ Public */
# Line 105  void Event_post(Service_T service, long Line 122  void Event_post(Service_T service, long
122      if(state != STATE_FAILED && !(service->error & id))      if(state != STATE_FAILED && !(service->error & id))
123        return;        return;
124    
125      /* Initialize event list and add first event. */      /* Initialize event list and add first event. The manadatory informations
126         * are cloned so the event is as standalone as possible and may be saved
127         * to the queue without the dependency on the original service, thus
128         * persistent and managable across monit restarts */
129      NEW(e);      NEW(e);
130      e->id = id;      e->id = id;
131      e->collected = time(NULL);      e->collected = time(NULL);
132      e->source = service;      e->source = xstrdup(service->name);
133        e->group = service->group?xstrdup(service->group):xstrdup("");
134        e->mode = service->mode;
135        e->type = service->type;
136      e->state = STATE_INIT;      e->state = STATE_INIT;
137      e->state_map = state;      e->state_map = state;
138      e->action = action;      e->action = action;
# Line 168  void Event_post(Service_T service, long Line 191  void Event_post(Service_T service, long
191        if(state != STATE_FAILED)        if(state != STATE_FAILED)
192          return;          return;
193    
194        /* Event was not found in the pending events list, we will add it. */        /* Event was not found in the pending events list, we will add it.
195           * The manadatory informations are cloned so the event is as standalone
196           * as possible and may be saved to the queue without the dependency on
197           * the original service, thus persistent and managable across monit
198           * restarts */
199        NEW(e);        NEW(e);
200        e->id = id;        e->id = id;
201        e->collected = time(NULL);        e->collected = time(NULL);
202        e->source = service;        e->source = xstrdup(service->name);
203          e->group = service->group?xstrdup(service->group):xstrdup("");
204          e->mode = service->mode;
205          e->type = service->type;
206        e->state = STATE_INIT;        e->state = STATE_INIT;
207        e->state_map = state;        e->state_map = state;
208        e->action = action;        e->action = action;
# Line 221  void Event_post(Service_T service, long Line 251  void Event_post(Service_T service, long
251   */   */
252  Service_T Event_get_source(Event_T E) {  Service_T Event_get_source(Event_T E) {
253    
254      Service_T s = NULL;
255    
256      ASSERT(E);
257    
258      if(!(s = Util_getService(E->source)))
259      {
260        log("Service %s not found in monit configuration\n", E->source);
261      }
262    
263      return s;
264    
265    }
266    
267    
268    /**
269     * Get the Service name where the event orginated
270     * @param E An event object
271     * @return The Service name where the event orginated
272     */
273    char *Event_get_source_name(Event_T E) {
274    
275    ASSERT(E);    ASSERT(E);
276    
277    return E->source;    return (E->source);
278    
279    }
280    
281    
282    /**
283     * Get the group name of the service where the event orginated
284     * @param E An event object
285     * @return The group name of the service where the event orginated
286     */
287    char *Event_get_source_group(Event_T E) {
288    
289      ASSERT(E);
290    
291      return (E->group);
292    
293    }
294    
295    
296    /**
297     * Get the service type of the service where the event orginated
298     * @param E An event object
299     * @return The service type of the service where the event orginated
300     */
301    int Event_get_source_type(Event_T E) {
302    
303      ASSERT(E);
304    
305      return (E->type);
306    
307  }  }
308    
# Line 378  short Event_get_action(Event_T E) { Line 457  short Event_get_action(Event_T E) {
457    /* In the case of passive mode we replace the description of start, stop    /* In the case of passive mode we replace the description of start, stop
458     * or restart action for alert action, because these actions are passive in     * or restart action for alert action, because these actions are passive in
459     * this mode */     * this mode */
460    id= (E->source->mode == MODE_PASSIVE &&    id= (E->mode == MODE_PASSIVE &&
461         ((A->id == ACTION_START)||         ((A->id == ACTION_START)||
462          (A->id == ACTION_STOP) ||          (A->id == ACTION_STOP) ||
463          (A->id == ACTION_RESTART))          (A->id == ACTION_RESTART))
# Line 408  const char *Event_get_action_description Line 487  const char *Event_get_action_description
487  }  }
488    
489    
490    /**
491     * Reprocess the partialy handled event queue
492     */
493    void Event_queue_process() {
494    
495      DIR           *dir = NULL;
496      FILE          *file = NULL;
497      struct dirent *de = NULL;
498      EventAction_T  ea = NULL;
499      Action_T       a = NULL;
500    
501      if(! (dir = opendir(Run.eventlist_dir)) )
502      {
503        log("%s: cannot open the directory %s -- %s\n",
504          prog, Run.eventlist_dir, STRERROR);
505        return;
506      }
507    
508      if((de = readdir(dir)))
509      {
510        DEBUG("Processing postponed events queue\n");
511      }
512    
513      NEW(ea);
514      NEW(a);
515    
516      while(de)
517      {
518        int            size;
519        int           *version = NULL;
520        short         *action = NULL;
521        Event_T        e = NULL;
522        struct stat    st;
523        char           file_name[STRLEN];
524    
525        /* In the case that all handlers failed, skip the further processing in
526         * this cycle. Alert handler is currently defined anytime (either
527         * explicitly or localhost by default) */
528        if( (Run.collectors
529               &&
530             FLAG(Run.handler_flag, HANDLER_COLLECTOR)
531               &&
532             FLAG(Run.handler_flag, HANDLER_ALERT)
533            )
534              ||
535            FLAG(Run.handler_flag, HANDLER_ALERT))
536        {
537          break;
538        }
539    
540        snprintf(file_name, STRLEN,
541          "%s/%s",
542          Run.eventlist_dir, de->d_name);
543    
544        if(!stat(file_name, &st) && S_ISREG(st.st_mode))
545        {
546    
547          DEBUG("%s: processing queued event %s\n", prog, file_name);
548    
549          if(! (file = fopen(file_name, "r")) )
550          {
551            log("%s: Processing failed - cannot open the event file %s -- %s\n",
552              prog, file_name, STRERROR);
553            goto error;
554          }
555    
556          /* read event structure version */
557          if(!(version = File_readQueue(file, &size)) || size != sizeof(int))
558            goto error;
559          if(*version != EVENT_VERSION)
560          {
561            log("Aborting event %s - incompatible data format version %d\n",
562              file_name, *version);
563            unlink(file_name);
564            goto error;
565          }
566    
567          /* read event structure */
568          if(!(e = File_readQueue(file, &size)) || size != sizeof(*e))
569            goto error;
570    
571          /* read source */
572          if(!(e->source = File_readQueue(file, &size)))
573            goto error;
574    
575          /* read group */
576          if(!(e->group = File_readQueue(file, &size)))
577            goto error;
578    
579          /* read message */
580          if(!(e->message = File_readQueue(file, &size)))
581            goto error;
582    
583          /* read event action */
584          if(!(action = File_readQueue(file, &size)) || size != sizeof(short))
585            goto error;
586          a->id = *action;
587          if(e->state == STATE_FAILED)
588          {
589            ea->failed = a;
590          }
591          else
592          {
593            ea->passed = a;
594          }
595          e->action = ea;
596    
597          /* Retry all remaining handlers */
598    
599          /* alert */
600          if(
601            ((Run.handler_flag & HANDLER_ALERT) != HANDLER_ALERT)
602            &&
603            e->flag & HANDLER_ALERT
604          )
605          {
606            if( handle_alert(e) != HANDLER_ALERT )
607            {
608              e->flag &= ~HANDLER_ALERT;
609            }
610            else
611            {
612              log("Alert handler failed, retry scheduled for next cycle\n");
613              Run.handler_flag |= HANDLER_ALERT;
614            }
615          }
616    
617          /* collector */
618          if(
619            ((Run.handler_flag & HANDLER_COLLECTOR) != HANDLER_COLLECTOR)
620            &&
621            e->flag & HANDLER_COLLECTOR
622          )
623          {
624            if( handle_collector(e) != HANDLER_COLLECTOR )
625            {
626              e->flag &= ~HANDLER_COLLECTOR;
627            }
628            else
629            {
630              log("Collector handler failed, retry scheduled for next cycle\n");
631              Run.handler_flag |= HANDLER_COLLECTOR;
632            }
633          }
634    
635          /* If no error persists, remove it from the queue */
636          if(e->flag == HANDLER_PASSED)
637          {
638            DEBUG("Removing event %s from the queue for later external delivery\n",
639              file_name);
640            unlink(file_name);
641          }
642    
643          error:
644          FREE(version);
645          FREE(action);
646          FREE(e->source);
647          FREE(e->group);
648          FREE(e->message);
649          FREE(e);
650          fclose(file);
651        }
652        de = readdir(dir);
653      }
654      closedir(dir);
655      FREE(a);
656      FREE(ea);
657      return;
658    }
659    
660    
661  /* ----------------------------------------------------------------- Private */  /* ----------------------------------------------------------------- Private */
662    
663    
# Line 417  const char *Event_get_action_description Line 667  const char *Event_get_action_description
667   */   */
668  static void handle_event(Event_T E) {  static void handle_event(Event_T E) {
669    
670      Service_T S;
671    
672    ASSERT(E);    ASSERT(E);
673    ASSERT(E->action);    ASSERT(E->action);
674    ASSERT(E->action->failed);    ASSERT(E->action->failed);
# Line 435  static void handle_event(Event_T E) { Line 687  static void handle_event(Event_T E) {
687      log("%s\n", E->message);      log("%s\n", E->message);
688    }    }
689    
690      S = Event_get_source(E);
691      if(!S)
692      {
693        log("Event handling aborted\n");
694        return;
695      }
696    
697    if(E->state == STATE_FAILED)    if(E->state == STATE_FAILED)
698    {    {
699      E->source->error |= E->id;      S->error |= E->id;
700      handle_action(E, E->action->failed);      handle_action(E, E->action->failed);
701    }    }
702    else    else
703    {    {
704      E->source->error &= ~E->id;      S->error &= ~E->id;
705      handle_action(E, E->action->passed);      handle_action(E, E->action->passed);
706    }    }
707    
# Line 454  static void handle_event(Event_T E) { Line 713  static void handle_event(Event_T E) {
713    
714  static int handle_action(Event_T E, Action_T A) {  static int handle_action(Event_T E, Action_T A) {
715    
716      Service_T s;
717    
718    ASSERT(E);    ASSERT(E);
719    ASSERT(A);    ASSERT(A);
720    
721      E->flag = HANDLER_PASSED;
722    
723    if(A->id == ACTION_IGNORE)    if(A->id == ACTION_IGNORE)
724    {    {
725      return TRUE;      return TRUE;
726    }    }
727    
728    /* Alert and collector event notification are common actions */    /* Alert and collector event notification are common actions */
729    handle_alert(E);    E->flag |= handle_alert(E);
730    handle_collector(E);    E->flag |= handle_collector(E);
731    
732      /* In the case that some subhandler failed, enqueue the event for
733       * partial reprocessing */
734      if(E->flag != HANDLER_PASSED)
735      {
736        if(Run.eventlist_dir)
737        {
738          Event_queue_add(E);
739        }
740        else
741        {
742          log("Aborting event\n");
743        }
744      }
745    
746      s = Event_get_source(E);
747      if(!s)
748      {
749        log("Event action handling aborted\n");
750        return FALSE;
751      }
752    
753    switch(A->id)    switch(A->id)
754    {    {
# Line 473  static int handle_action(Event_T E, Acti Line 757  static int handle_action(Event_T E, Acti
757        break;        break;
758    
759    case ACTION_EXEC:    case ACTION_EXEC:
760        spawn(E->source, A->exec, EVENT_DESCRIPTION(E));        spawn(s, A->exec, Event_get_description(E));
761        break;        break;
762    
763    case ACTION_RESTART:    case ACTION_RESTART:
764        if(E->source->def_timeout)        if(s->def_timeout)
765          E->source->nstart++;          s->nstart++;
766        if((E->source->mode != MODE_PASSIVE))        if((s->mode != MODE_PASSIVE))
767        {        {
768          control_service(E->source->name, "restart");          control_service(s->name, "restart");
769        }        }
770        return FALSE;        return FALSE;
771    
772    case ACTION_START:    case ACTION_START:
773        if(E->source->def_timeout)        if(s->def_timeout)
774          E->source->nstart++;          s->nstart++;
775        if((E->source->mode != MODE_PASSIVE))        if((s->mode != MODE_PASSIVE))
776        {        {
777          control_service(E->source->name, "start");          control_service(s->name, "start");
778        }        }
779        return FALSE;        return FALSE;
780    
781    case ACTION_STOP:    case ACTION_STOP:
782        if((E->source->mode != MODE_PASSIVE))        if((s->mode != MODE_PASSIVE))
783        {        {
784          control_service(E->source->name, "stop");          control_service(s->name, "stop");
785        }        }
786        return FALSE;        return FALSE;
787    
788    case ACTION_UNMONITOR:    case ACTION_UNMONITOR:
789        control_service(E->source->name, "unmonitor");        control_service(s->name, "unmonitor");
790        return FALSE;        return FALSE;
791    
792    default:    default:
793        log("'%s' error -- unknown failure action: [%d]\n", E->source->name,        log("'%s' error -- unknown failure action: [%d]\n", s->name,
794          A->id);          A->id);
795        break;        break;
796    
797    }    }
798    
799    return TRUE;    return TRUE;
800  }  }
801    
802    
803    /**
804     * Add the partialy handled event to the global queue
805     * @param E An event object
806     */
807    static void Event_queue_add(Event_T E) {
808    
809      FILE        *file = NULL;
810      char         file_name[STRLEN];
811      int          version = EVENT_VERSION;
812      short        action = Event_get_action(E);
813      int          rv = FALSE;
814      sigset_t     ns;
815      sigset_t     os;
816    
817      ASSERT(E);
818      ASSERT(E->flag != HANDLER_PASSED);
819    
820      if(!File_checkQueueDirectory(Run.eventlist_dir, 700))
821      {
822        log("%s: Aborting event - cannot access the directory %s\n",
823          prog, Run.eventlist_dir);
824        return;
825      }
826        
827      if(!File_checkQueueLimit(Run.eventlist_dir, Run.eventlist_slots))
828      {
829        log("%s: Aborting event - queue over quota\n", prog);
830        return;
831      }
832        
833      set_signal_block(&ns, &os);
834    
835      /* compose the file name of actual timestamp and service name */
836      snprintf(file_name, STRLEN,
837        "%s/%ld_%s",
838        Run.eventlist_dir, time(NULL), E->source);
839    
840      DEBUG("%s: Adding event to the queue file %s for later delivery\n",
841        prog, file_name);
842    
843      if(! (file = fopen(file_name, "w")) )
844      {
845        log("%s: Aborting event - cannot open the event file %s -- %s\n",
846          prog, file_name, STRERROR);
847        return;
848      }
849    
850      /* write event structure version */
851      if(!(rv = File_writeQueue(file, &version, sizeof(int))))
852        goto error;
853    
854      /* write event structure */
855      if(!(rv = File_writeQueue(file, E, sizeof(*E))))
856        goto error;
857    
858      /* write source */
859      if(!(rv = File_writeQueue(file, E->source, E->source?strlen(E->source)+1:0)))
860        goto error;
861    
862      /* write group */
863      if(!(rv = File_writeQueue(file, E->group, E->group?strlen(E->group)+1:0)))
864        goto error;
865    
866      /* write message */
867      if(!(rv = File_writeQueue(file, E->message, E->message?strlen(E->message)+1:0)))
868        goto error;
869    
870      /* write event action */
871      if(!(rv = File_writeQueue(file, &action, sizeof(short))))
872        goto error;
873    
874      error:
875      if(!rv)
876      {
877        log("%s: Aborting event - unable to save event information to %s\n",
878          prog, file_name);
879        unlink(file_name);
880      }
881      else
882      {
883        fclose(file);
884      }
885    
886      unset_signal_block(&os);
887      return;
888    }
889    

Legend:
Removed from v.1.50  
changed lines
  Added in v.1.51

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