~ubuntu-branches/ubuntu/lucid/monit/lucid

« back to all changes in this revision

Viewing changes to event.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Alfredsson
  • Date: 2009-08-18 22:49:13 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20090818224913-6z5wghd0qfiuy7fh
Tags: 1:5.0.3-3
* Daemon poll interval moved to rc-file instead of defaults
  (Closes: #541425)
* Package upgraded (Closes: 453248)
* Configuration snippets are included from /etc/monit/conf.d/*
  (Closes: #296479)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C), 2000-2007 by the monit project group.
3
 
 * All Rights Reserved.
 
2
 * Copyright (C) 2009 Tildeslash Ltd. All rights reserved.
4
3
 *
5
4
 * This program is free software: you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation, either version 3 of the License, or
8
 
 * (at your option) any later version.
 
5
 * it under the terms of the GNU General Public License version 3.
9
6
 *
10
7
 * This program is distributed in the hope that it will be useful,
11
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
11
 *
15
12
 * You should have received a copy of the GNU General Public License
16
13
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
14
 *
 
15
 * In addition, as a special exception, the copyright holders give
 
16
 * permission to link the code of portions of this program with the
 
17
 * OpenSSL library under certain conditions as described in each
 
18
 * individual source file, and distribute linked combinations
 
19
 * including the two.
 
20
 *
 
21
 * You must obey the GNU General Public License in all respects
 
22
 * for all of the code used other than OpenSSL.  If you modify
 
23
 * file(s) with this exception, you may extend this exception to your
 
24
 * version of the file(s), but you are not obligated to do so.  If you
 
25
 * do not wish to do so, delete this exception statement from your
 
26
 * version.  If you delete this exception statement from all source
 
27
 * files in the program, then also delete it here.
17
28
 */
18
29
 
19
30
#include "config.h"
30
41
#include <sys/types.h>
31
42
#endif
32
43
 
 
44
#ifdef HAVE_SYS_TIME_H
 
45
#include <sys/time.h>
 
46
#endif
 
47
 
 
48
#ifdef HAVE_TIME_H
 
49
#include <time.h>
 
50
#endif
 
51
 
 
52
 
33
53
#ifdef HAVE_SYS_STAT_H
34
54
#include <sys/stat.h>
35
55
#endif
53
73
 *
54
74
 * @author Jan-Henrik Haukeland, <hauk@tildeslash.com>
55
75
 * @author Martin Pala <martinp@tildeslash.com>
56
 
 * @version \$Id: event.c,v 1.66 2007/07/25 12:54:28 hauk Exp $
 
76
 * @version \$Id: event.c,v 1.99 2009/05/28 21:35:29 martinp Exp $
57
77
 * @file
58
78
 */
59
79
 
61
81
/* ------------------------------------------------------------- Definitions */
62
82
 
63
83
EventTable_T Event_Table[]= {
64
 
  {EVENT_CHANGED,         "Changed",                "Changed not"},
65
 
  {EVENT_CHECKSUM,        "Checksum failed",        "Checksum passed"},
66
 
  {EVENT_CONNECTION,      "Connection failed",      "Connection passed"},
67
 
  {EVENT_DATA,            "Data access error",      "Data access succeeded"},
68
 
  {EVENT_EXEC,            "Execution failed",       "Execution succeeded"},
69
 
  {EVENT_GID,             "GID failed",             "GID passed"},
70
 
  {EVENT_ICMP,            "ICMP failed",            "ICMP passed"},
71
 
  {EVENT_INSTANCE,        "Monit instance changed", "Monit instance changed not"},
72
 
  {EVENT_INVALID,         "Invalid type",           "Type passed"},
73
 
  {EVENT_MATCH,           "Regex match",            "No regex match"},
74
 
  {EVENT_NONEXIST,        "Does not exist",         "Exists"},
75
 
  {EVENT_PERMISSION,      "Permission failed",      "Permission passed"},
76
 
  {EVENT_RESOURCE,        "Resource limit matched", "Resource limit passed"},
77
 
  {EVENT_SIZE,            "Size failed",            "Size passed"},
78
 
  {EVENT_TIMEOUT,         "Timeout",                "Timeout recovery"},
79
 
  {EVENT_TIMESTAMP,       "Timestamp failed",       "Timestamp passed"},
80
 
  {EVENT_UID,             "UID failed",             "UID passed"},
 
84
  {EVENT_ACTION,     "Action done",             "Action done",                "Action done",              "Action done"},
 
85
  {EVENT_CHECKSUM,   "Checksum failed",         "Checksum succeeded",         "Checksum changed",         "Checksum not changed"},
 
86
  {EVENT_CONNECTION, "Connection failed",       "Connection succeeded",       "Connection changed",       "Connection not changed"},
 
87
  {EVENT_CONTENT,    "Content failed",          "Content succeeded",          "Content match",            "Content doesn't match"},
 
88
  {EVENT_DATA,       "Data access error",       "Data access succeeded",      "Data access changed",      "Data access not changed"},
 
89
  {EVENT_EXEC,       "Execution failed",        "Execution succeeded",        "Execution changed",        "Execution not changed"},
 
90
  {EVENT_FSFLAG,     "Filesystem flags failed", "Filesystem flags succeeded", "Filesystem flags changed", "Filesystem flags not changed"},
 
91
  {EVENT_GID,        "GID failed",              "GID succeeded",              "GID changed",              "GID not changed"},
 
92
  {EVENT_HEARTBEAT,  "Heartbeat failed",        "Heartbeat succeeded",        "Heartbeat changed",        "Heartbeat not changed"},
 
93
  {EVENT_ICMP,       "ICMP failed",             "ICMP succeeded",             "ICMP changed",             "ICMP not changed"},
 
94
  {EVENT_INSTANCE,   "Monit instance failed",   "Monit instance succeeded",   "Monit instance changed",   "Monit instance not changed"},
 
95
  {EVENT_INVALID,    "Invalid type",            "Type succeeded",             "Type changed",             "Type not changed"},
 
96
  {EVENT_NONEXIST,   "Does not exist",          "Exists",                     "Existence changed",        "Existence not changed"},
 
97
  {EVENT_PERMISSION, "Permission failed",       "Permission succeeded",       "Permission changed",       "Permission not changed"},
 
98
  {EVENT_PID,        "PID failed",              "PID succeeded",              "PID changed",              "PID not changed"},
 
99
  {EVENT_PPID,       "PPID failed",             "PPID succeeded",             "PPID changed",             "PPID not changed"},
 
100
  {EVENT_RESOURCE,   "Resource limit matched",  "Resource limit succeeded",   "Resource limit changed",   "Resource limit not changed"},
 
101
  {EVENT_SIZE,       "Size failed",             "Size succeeded",             "Size changed",             "Size not changed"},
 
102
  {EVENT_TIMEOUT,    "Timeout",                 "Timeout recovery",           "Timeout changed",          "Timeout not changed"},
 
103
  {EVENT_TIMESTAMP,  "Timestamp failed",        "Timestamp succeeded",        "Timestamp changed",        "Timestamp not changed"},
 
104
  {EVENT_UID,        "UID failed",              "UID succeeded",              "UID changed",              "UID not changed"},
81
105
  /* Virtual events */
82
 
  {EVENT_NULL,            "No Event",               "No Event"},
 
106
  {EVENT_NULL,       "No Event",                "No Event",                   "No Event",                 "No Event"}
83
107
};
84
108
 
85
109
 
89
113
static void handle_event(Event_T);
90
114
static void handle_action(Event_T, Action_T);
91
115
static void Event_queue_add(Event_T);
 
116
static void Event_queue_update(Event_T, const char *);
92
117
 
93
118
 
94
119
/* ------------------------------------------------------------------ Public */
102
127
 * @param action Description of the event action
103
128
 * @param s Optional message describing the event
104
129
 */
105
 
void Event_post(Service_T service, long id, short state, EventAction_T action,
106
 
  char *s, ...) {
107
 
 
108
 
  Event_T e = service->eventlist;
 
130
void Event_post(Service_T service, long id, short state, EventAction_T action, char *s, ...) {
 
131
  Event_T e;
109
132
 
110
133
  ASSERT(service);
111
134
  ASSERT(action);
112
 
  ASSERT(state == STATE_FAILED || state == STATE_PASSED);
 
135
  ASSERT(state == STATE_FAILED || state == STATE_SUCCEEDED || state == STATE_CHANGED || state == STATE_CHANGEDNOT);
113
136
 
114
 
  if(e == NULL)
115
 
  {
116
 
    /* Only first failed event can initialize the queue for given event type,
117
 
     * thus passed events are ignored until first error. However, in the case
118
 
     * that the error flag is set for the passed event, we will allow it (i.e.
119
 
     * event queue was flushed during monit reload and the service was in
120
 
     * failed state before reload) */
121
 
    if(state != STATE_FAILED && !(service->error & id))
 
137
  if ((e = service->eventlist) == NULL) {
 
138
    /* Only first failed/changed event can initialize the queue for given event type,
 
139
     * thus succeeded events are ignored until first error. */
 
140
    if (state == STATE_SUCCEEDED || state == STATE_CHANGEDNOT)
122
141
      return;
123
142
 
124
143
    /* Initialize event list and add first event. The manadatory informations
127
146
     * persistent and managable across monit restarts */
128
147
    NEW(e);
129
148
    e->id = id;
130
 
    e->collected = time(NULL);
 
149
    gettimeofday(&e->collected, NULL);
131
150
    e->source = xstrdup(service->name);
132
 
    e->group = service->group?xstrdup(service->group):xstrdup("");
 
151
    e->group = service->group ? xstrdup(service->group) : xstrdup("");
133
152
    e->mode = service->mode;
134
153
    e->type = service->type;
135
154
    e->state = STATE_INIT;
136
 
    e->state_map = state;
 
155
    e->state_map = 1;
137
156
    e->action = action;
138
 
    if(s)
139
 
    {
 
157
    if (s) {
140
158
      long l;
141
159
      va_list ap;
142
160
 
144
162
      e->message = Util_formatString(s, ap, &l);
145
163
      va_end(ap);
146
164
    }
147
 
    pthread_mutex_init(&e->mutex, NULL);
148
165
    service->eventlist = e;
149
 
  }
150
 
  else
151
 
  {
 
166
  } else {
152
167
    /* Try to find the event with the same origin and type identification.
153
168
     * Each service and each test have its own custom actions object, so
154
169
     * we share actions object address to identify event source. */
155
 
    do
156
 
    {
157
 
      if(e->action == action && e->id == id)
158
 
      {
159
 
        LOCK(e->mutex)
160
 
          e->collected = time(NULL);
161
 
 
162
 
          /* Shift the existing event flags to the left
163
 
           * and set the first bit based on actual state */
164
 
          e->state_map <<= 1;
165
 
          e->state_map |= state;
166
 
 
167
 
          /* Update the message */
168
 
          if(s)
169
 
          {
170
 
            long l;
171
 
            va_list ap;
172
 
 
173
 
            FREE(e->message);
174
 
            va_start(ap, s);
175
 
            e->message = Util_formatString(s, ap, &l);
176
 
            va_end(ap);
177
 
          }
178
 
 
179
 
        END_LOCK;
 
170
    do {
 
171
      if (e->action == action && e->id == id) {
 
172
        gettimeofday(&e->collected, NULL);
 
173
 
 
174
        /* Shift the existing event flags to the left
 
175
         * and set the first bit based on actual state */
 
176
        e->state_map <<= 1;
 
177
        e->state_map |= ((state == STATE_SUCCEEDED || state == STATE_CHANGEDNOT) ? 0 : 1);
 
178
 
 
179
        /* Update the message */
 
180
        if (s) {
 
181
          long l;
 
182
          va_list ap;
 
183
 
 
184
          FREE(e->message);
 
185
          va_start(ap, s);
 
186
          e->message = Util_formatString(s, ap, &l);
 
187
          va_end(ap);
 
188
        }
180
189
        break;
181
190
      }
182
191
      e = e->next;
183
 
    }
184
 
    while(e);
 
192
    } while (e);
185
193
 
186
 
    if(!e)
187
 
    {
188
 
      /* Only first failed event can initialize the queue for given event type,
189
 
       * thus passed events are ignored until first error */
190
 
      if(state != STATE_FAILED)
 
194
    if (!e) {
 
195
      /* Only first failed/changed event can initialize the queue for given event type,
 
196
       * thus succeeded events are ignored until first error. */
 
197
      if (state == STATE_SUCCEEDED || state == STATE_CHANGEDNOT)
191
198
        return;
192
199
 
193
200
      /* Event was not found in the pending events list, we will add it.
197
204
       * restarts */
198
205
      NEW(e);
199
206
      e->id = id;
200
 
      e->collected = time(NULL);
 
207
      gettimeofday(&e->collected, NULL);
201
208
      e->source = xstrdup(service->name);
202
 
      e->group = service->group?xstrdup(service->group):xstrdup("");
 
209
      e->group = service->group ? xstrdup(service->group) : xstrdup("");
203
210
      e->mode = service->mode;
204
211
      e->type = service->type;
205
212
      e->state = STATE_INIT;
206
 
      e->state_map = state;
 
213
      e->state_map = 1;
207
214
      e->action = action;
208
 
      if(s)
209
 
      {
 
215
      if (s) {
210
216
        long l;
211
217
        va_list ap;
212
218
 
214
220
        e->message = Util_formatString(s, ap, &l);
215
221
        va_end(ap);
216
222
      }
217
 
      pthread_mutex_init(&e->mutex, NULL);
218
223
      e->next = service->eventlist;
219
224
      service->eventlist = e;
220
225
    }
223
228
  e->state_changed = Event_check_state(e, state);
224
229
 
225
230
  /* In the case that the state changed, update it and reset the counter */
226
 
  if(e->state_changed)
227
 
  {
 
231
  if (e->state_changed) {
228
232
    e->state = state;
229
233
    e->count = 1;
230
 
  }
231
 
  else
232
 
  {
 
234
  } else
233
235
    e->count++;
234
 
  }
235
 
 
236
 
  LOCK(e->mutex)
237
 
    handle_event(e);
238
 
  END_LOCK;
239
 
 
 
236
 
 
237
  handle_event(e);
240
238
}
241
239
 
242
240
 
249
247
 * @return The Service where the event orginated
250
248
 */
251
249
Service_T Event_get_source(Event_T E) {
252
 
 
253
250
  Service_T s = NULL;
254
251
 
255
252
  ASSERT(E);
256
253
 
257
 
  if(!(s = Util_getService(E->source)))
258
 
  {
 
254
  if (!(s = Util_getService(E->source)))
259
255
    LogError("Service %s not found in monit configuration\n", E->source);
260
 
  }
261
256
 
262
257
  return s;
263
 
 
264
258
}
265
259
 
266
260
 
270
264
 * @return The Service name where the event orginated
271
265
 */
272
266
char *Event_get_source_name(Event_T E) {
273
 
 
274
267
  ASSERT(E);
275
 
 
276
268
  return (E->source);
277
 
 
278
269
}
279
270
 
280
271
 
284
275
 * @return The group name of the service where the event orginated
285
276
 */
286
277
char *Event_get_source_group(Event_T E) {
287
 
 
288
278
  ASSERT(E);
289
 
 
290
279
  return (E->group);
291
 
 
292
280
}
293
281
 
294
282
 
298
286
 * @return The service type of the service where the event orginated
299
287
 */
300
288
int Event_get_source_type(Event_T E) {
301
 
 
302
289
  ASSERT(E);
303
 
 
304
290
  return (E->type);
305
 
 
306
291
}
307
292
 
308
293
 
311
296
 * @param E An event object
312
297
 * @return The Event timestamp
313
298
 */
314
 
time_t Event_get_collected(Event_T E) {
315
 
 
 
299
struct timeval *Event_get_collected(Event_T E) {
316
300
  ASSERT(E);
317
 
  
318
 
  return E->collected;
319
 
 
 
301
  return &E->collected;
320
302
}
321
303
 
322
304
 
326
308
 * @return The Event raw state
327
309
 */
328
310
short Event_get_state(Event_T E) {
329
 
 
330
311
  ASSERT(E);
331
 
  
332
312
  return E->state;
333
 
 
334
313
}
335
314
 
336
315
 
342
321
 * @return The Event raw state
343
322
 */
344
323
short Event_check_state(Event_T E, short S) {
345
 
 
346
324
  int       i;
347
325
  int       count = 0;
 
326
  short     state = (S == STATE_SUCCEEDED || S == STATE_CHANGEDNOT) ? 0 : 1; /* translate to 0/1 class */
348
327
  Action_T  action;
349
328
  Service_T service;
350
329
  long long flag;
351
330
 
352
331
  ASSERT(E);
353
332
 
354
 
  if(!(service = Event_get_source(E)))
 
333
  if (!(service = Event_get_source(E)))
355
334
    return TRUE;
356
335
 
357
 
  /* Only the true failed state condition can change the initial state */
358
 
  if(S == STATE_PASSED && E->state == STATE_INIT && !(service->error & E->id))
359
 
  {
 
336
  /* Only true failed/changed state condition can change the initial state */
 
337
  if (!state && E->state == STATE_INIT && !(service->error & E->id))
360
338
    return FALSE;
361
 
  }
362
339
 
363
 
  action = (S == STATE_PASSED)?E->action->passed:E->action->failed;
 
340
  action = !state ? E->action->succeeded : E->action->failed;
364
341
 
365
342
  /* Compare as many bits as cycles able to trigger the action */
366
 
  for(i = 0; i < action->cycles; i++)
367
 
  {
 
343
  for (i = 0; i < action->cycles; i++) {
368
344
    /* Check the state of the particular cycle given by the bit position */
369
345
    flag = (E->state_map >> i) & 0x1;
370
346
 
371
347
    /* Count occurences of the posted state */
372
 
    if(flag == S)
373
 
    {
 
348
    if (flag == state)
374
349
      count++;
375
 
    }
376
350
  }
377
351
 
378
 
  if(count >= action->count && S != E->state)
379
 
  {
 
352
  /* the internal instance and action events are handled as changed any time since we need to deliver alert whenever it occurs */
 
353
  if (E->id == EVENT_INSTANCE || E->id == EVENT_ACTION || (count >= action->count && S != E->state))
380
354
    return TRUE;
381
 
  }
382
355
  
383
356
  return FALSE;
384
 
 
385
357
}
386
358
 
387
359
 
391
363
 * @return The Event type
392
364
 */
393
365
int Event_get_id(Event_T E) {
394
 
 
395
366
  ASSERT(E);
396
 
  
397
367
  return E->id;
398
 
 
399
368
}
400
369
 
401
370
 
406
375
 * @return The Event message. May be NULL
407
376
 */
408
377
const char *Event_get_message(Event_T E) {
409
 
 
410
378
  ASSERT(E);
411
 
 
412
379
  return E->message;
413
 
 
414
380
}
415
381
 
416
382
 
417
383
/**
418
 
 * Get a textual description of actual event type. For instance if the
419
 
 * event type is possitive EVENT_TIMESTAMP, the textual description is
420
 
 * "Timestamp error". Likewise if the event type is negative EVENT_CHECKSUM
421
 
 * the textual description is "Checksum recovery" and so on.
 
384
 * Get a textual description of actual event type.
422
385
 * @param E An event object
423
386
 * @return A string describing the event type in clear text. If the
424
387
 * event type is not found NULL is returned.
425
388
 */
426
389
const char *Event_get_description(Event_T E) {
427
 
 
428
390
  EventTable_T *et= Event_Table;
429
391
 
430
392
  ASSERT(E);
431
393
 
432
 
  while((*et).id)
433
 
  {
434
 
    if(E->id == (*et).id)
435
 
    {
436
 
      return E->state?(*et).description_failed:(*et).description_passed;
 
394
  while ((*et).id) {
 
395
    if (E->id == (*et).id) {
 
396
      switch (E->state) {
 
397
        case STATE_SUCCEEDED:
 
398
          return (*et).description_succeeded;
 
399
        case STATE_FAILED:
 
400
          return (*et).description_failed;
 
401
        case STATE_INIT:
 
402
          return (*et).description_failed;
 
403
        case STATE_CHANGED:
 
404
          return (*et).description_changed;
 
405
        case STATE_CHANGEDNOT:
 
406
          return (*et).description_changednot;
 
407
        default:
 
408
          break;
 
409
      }
437
410
    }
438
411
    et++;
439
412
  }
440
413
  
441
414
  return NULL;
442
 
 
443
415
}
444
416
 
445
417
 
449
421
 * @return An action id
450
422
 */
451
423
short Event_get_action(Event_T E) {
452
 
 
453
 
  short id;
454
424
  Action_T A;
455
425
 
456
426
  ASSERT(E);
457
427
 
458
 
  A = E->state?E->action->failed:E->action->passed;
 
428
  A = E->state ? E->action->failed : E->action->succeeded;
 
429
  switch (E->state) {
 
430
    case STATE_SUCCEEDED:
 
431
    case STATE_CHANGEDNOT:
 
432
      A = E->action->succeeded;
 
433
      break;
 
434
    case STATE_FAILED:
 
435
    case STATE_CHANGED:
 
436
    case STATE_INIT:
 
437
      A = E->action->failed;
 
438
      break;
 
439
    default:
 
440
      break;
 
441
  }
 
442
 
 
443
  if (! A)
 
444
    return ACTION_IGNORE;
459
445
 
460
446
  /* In the case of passive mode we replace the description of start, stop
461
447
   * or restart action for alert action, because these actions are passive in
462
448
   * this mode */
463
 
  id= (E->mode == MODE_PASSIVE &&
464
 
       ((A->id == ACTION_START)||
465
 
        (A->id == ACTION_STOP) ||
466
 
        (A->id == ACTION_RESTART))
467
 
      )?ACTION_ALERT:A->id;
468
 
 
469
 
  return id;
470
 
 
 
449
  return (E->mode == MODE_PASSIVE && ((A->id == ACTION_START) || (A->id == ACTION_STOP) || (A->id == ACTION_RESTART))) ? ACTION_ALERT : A->id;
471
450
}
472
451
 
473
452
 
482
461
 * event type is not found NULL is returned.
483
462
 */
484
463
const char *Event_get_action_description(Event_T E) {
485
 
 
486
464
  ASSERT(E);
487
 
 
488
465
  return actionnames[Event_get_action(E)];
489
 
 
490
466
}
491
467
 
492
468
 
493
469
/**
494
 
 * Reprocess the partialy handled event queue
 
470
 * Reprocess the partially handled event queue
495
471
 */
496
472
void Event_queue_process() {
497
 
 
498
473
  DIR           *dir = NULL;
499
474
  FILE          *file = NULL;
500
475
  struct dirent *de = NULL;
502
477
  Action_T       a = NULL;
503
478
 
504
479
  /* return in the case that the eventqueue is not enabled or empty */
505
 
  if( !Run.eventlist_dir ||
506
 
     (
507
 
      !Run.handler_init                     &&
508
 
      !Run.handler_queue[HANDLER_ALERT]     &&
509
 
      !Run.handler_queue[HANDLER_COLLECTOR]
510
 
     )
511
 
    )
512
 
  {
513
 
    return;
514
 
  }
515
 
 
516
 
  if(! (dir = opendir(Run.eventlist_dir)) )
517
 
  {
518
 
    if(errno != ENOENT) {
519
 
      LogError("%s: cannot open the directory %s -- %s\n",
520
 
        prog, Run.eventlist_dir, STRERROR);
521
 
    }
522
 
    return;
523
 
  }
524
 
 
525
 
  if((de = readdir(dir)))
526
 
  {
 
480
  if (! Run.eventlist_dir || (! Run.handler_init && ! Run.handler_queue[HANDLER_ALERT] && ! Run.handler_queue[HANDLER_MMONIT]))
 
481
    return;
 
482
 
 
483
  if (! (dir = opendir(Run.eventlist_dir)) ) {
 
484
    if (errno != ENOENT)
 
485
      LogError("%s: cannot open the directory %s -- %s\n", prog, Run.eventlist_dir, STRERROR);
 
486
    return;
 
487
  }
 
488
 
 
489
  if ((de = readdir(dir)))
527
490
    DEBUG("Processing postponed events queue\n");
528
 
  }
529
491
 
530
492
  NEW(ea);
531
493
  NEW(a);
532
494
 
533
 
  while(de)
534
 
  {
 
495
  while (de) {
535
496
    int            size;
 
497
    int            handlers_passed = 0;
536
498
    int           *version = NULL;
537
499
    short         *action = NULL;
538
500
    Event_T        e = NULL;
542
504
    /* In the case that all handlers failed, skip the further processing in
543
505
     * this cycle. Alert handler is currently defined anytime (either
544
506
     * explicitly or localhost by default) */
545
 
    if( (Run.collectors
546
 
           &&
547
 
         FLAG(Run.handler_flag, HANDLER_COLLECTOR)
548
 
           &&
549
 
         FLAG(Run.handler_flag, HANDLER_ALERT)
550
 
        )
551
 
          ||
552
 
        FLAG(Run.handler_flag, HANDLER_ALERT))
553
 
    {
 
507
    if ( (Run.mmonits && FLAG(Run.handler_flag, HANDLER_MMONIT) && FLAG(Run.handler_flag, HANDLER_ALERT)) || FLAG(Run.handler_flag, HANDLER_ALERT))
554
508
      break;
555
 
    }
556
 
 
557
 
    snprintf(file_name, STRLEN,
558
 
      "%s/%s",
559
 
      Run.eventlist_dir, de->d_name);
560
 
 
561
 
    if(!stat(file_name, &st) && S_ISREG(st.st_mode))
562
 
    {
563
 
 
 
509
 
 
510
    snprintf(file_name, STRLEN, "%s/%s", Run.eventlist_dir, de->d_name);
 
511
 
 
512
    if (!stat(file_name, &st) && S_ISREG(st.st_mode)) {
564
513
      DEBUG("%s: processing queued event %s\n", prog, file_name);
565
514
 
566
 
      if(! (file = fopen(file_name, "r")) )
567
 
      {
568
 
        LogError("%s: Processing failed - cannot open the event file %s -- %s\n",
569
 
          prog, file_name, STRERROR);
 
515
      if (! (file = fopen(file_name, "r")) ) {
 
516
        LogError("%s: Processing failed - cannot open the event file %s -- %s\n", prog, file_name, STRERROR);
570
517
        goto error1;
571
518
      }
572
519
 
573
520
      /* read event structure version */
574
 
      if(!(version = File_readQueue(file, &size)) || size != sizeof(int)) {
575
 
        LogError("skipping %s - unknown data format\n",
576
 
          file_name, *version);
577
 
        goto error2;
578
 
      }
579
 
      if(*version != EVENT_VERSION)
580
 
      {
581
 
        LogError("Aborting event %s - incompatible data format version %d\n",
582
 
          file_name, *version);
583
 
        goto error2;
 
521
      if (!(version = File_readQueue(file, &size))) {
 
522
        LogError("skipping %s - unknown data format\n", file_name);
 
523
        goto error2;
 
524
      }
 
525
      if (size != sizeof(int)) {
 
526
        LogError("Aborting event %s - invalid size %d\n", file_name, size);
 
527
        goto error3;
 
528
      }
 
529
      if (*version != EVENT_VERSION) {
 
530
        LogError("Aborting event %s - incompatible data format version %d\n", file_name, *version);
 
531
        goto error3;
584
532
      }
585
533
 
586
534
      /* read event structure */
587
 
      if(!(e = File_readQueue(file, &size)) || size != sizeof(*e))
588
 
        goto error2;
 
535
      if (!(e = File_readQueue(file, &size)))
 
536
        goto error3;
 
537
      if (size != sizeof(*e))
 
538
        goto error4;
589
539
 
590
540
      /* read source */
591
 
      if(!(e->source = File_readQueue(file, &size)))
592
 
        goto error3;
 
541
      if (!(e->source = File_readQueue(file, &size)))
 
542
        goto error4;
593
543
 
594
544
      /* read group */
595
 
      if(!(e->group = File_readQueue(file, &size)))
596
 
        goto error3;
 
545
      if (!(e->group = File_readQueue(file, &size)))
 
546
        goto error5;
597
547
 
598
548
      /* read message */
599
 
      if(!(e->message = File_readQueue(file, &size)))
600
 
        goto error3;
 
549
      if (!(e->message = File_readQueue(file, &size)))
 
550
        goto error6;
601
551
 
602
552
      /* read event action */
603
 
      if(!(action = File_readQueue(file, &size)) || size != sizeof(short))
604
 
        goto error3;
 
553
      if (!(action = File_readQueue(file, &size)))
 
554
        goto error7;
 
555
      if (size != sizeof(short))
 
556
        goto error8;
605
557
      a->id = *action;
606
 
      if(e->state == STATE_FAILED)
607
 
      {
 
558
      if (e->state == STATE_FAILED)
608
559
        ea->failed = a;
609
 
      }
610
560
      else
611
 
      {
612
 
        ea->passed = a;
613
 
      }
 
561
        ea->succeeded = a;
614
562
      e->action = ea;
615
563
 
616
564
      /* Retry all remaining handlers */
617
565
 
618
566
      /* alert */
619
 
      if(e->flag & HANDLER_ALERT)
620
 
      {
621
 
        if(Run.handler_init)
622
 
        {
 
567
      if (e->flag & HANDLER_ALERT) {
 
568
        if (Run.handler_init)
623
569
          Run.handler_queue[HANDLER_ALERT]++;
624
 
        }
625
 
        if((Run.handler_flag & HANDLER_ALERT) != HANDLER_ALERT)
626
 
        {
627
 
          if( handle_alert(e) != HANDLER_ALERT )
628
 
          {
 
570
        if ((Run.handler_flag & HANDLER_ALERT) != HANDLER_ALERT) {
 
571
          if ( handle_alert(e) != HANDLER_ALERT ) {
629
572
            e->flag &= ~HANDLER_ALERT;
630
573
            Run.handler_queue[HANDLER_ALERT]--;
631
 
          }
632
 
          else
633
 
          {
 
574
            handlers_passed++;
 
575
          } else {
634
576
            LogError("Alert handler failed, retry scheduled for next cycle\n");
635
577
            Run.handler_flag |= HANDLER_ALERT;
636
578
          }
637
579
        }
638
580
      }
639
581
 
640
 
      /* collector */
641
 
      if(e->flag & HANDLER_COLLECTOR)
642
 
      {
643
 
        if(Run.handler_init)
644
 
        {
645
 
          Run.handler_queue[HANDLER_COLLECTOR]++;
646
 
        }
647
 
        if((Run.handler_flag & HANDLER_COLLECTOR) != HANDLER_COLLECTOR)
648
 
        {
649
 
          if( handle_collector(e) != HANDLER_COLLECTOR )
650
 
          {
651
 
            e->flag &= ~HANDLER_COLLECTOR;
652
 
            Run.handler_queue[HANDLER_COLLECTOR]--;
653
 
          }
654
 
          else
655
 
          {
656
 
            LogError("Collector handler failed, retry scheduled for next cycle\n");
657
 
            Run.handler_flag |= HANDLER_COLLECTOR;
 
582
      /* mmonit */
 
583
      if (e->flag & HANDLER_MMONIT) {
 
584
        if (Run.handler_init)
 
585
          Run.handler_queue[HANDLER_MMONIT]++;
 
586
        if ((Run.handler_flag & HANDLER_MMONIT) != HANDLER_MMONIT) {
 
587
          if ( handle_mmonit(e) != HANDLER_MMONIT ) {
 
588
            e->flag &= ~HANDLER_MMONIT;
 
589
            Run.handler_queue[HANDLER_MMONIT]--;
 
590
            handlers_passed++;
 
591
          } else {
 
592
            LogError("M/Monit handler failed, retry scheduled for next cycle\n");
 
593
            Run.handler_flag |= HANDLER_MMONIT;
658
594
          }
659
595
        }
660
596
      }
661
597
 
662
598
      /* If no error persists, remove it from the queue */
663
 
      if(e->flag == HANDLER_PASSED)
664
 
      {
665
 
        DEBUG("Removing event %s from the queue for later external delivery\n",
666
 
          file_name);
667
 
        unlink(file_name);
 
599
      if (e->flag == HANDLER_SUCCEEDED) {
 
600
        DEBUG("Removing event %s from the queue for later external delivery\n", file_name);
 
601
        if (unlink(file_name) < 0)
 
602
          LogError("Failed to remove queued event file '%s' -- %s\n", file_name, STRERROR);
 
603
      } else if (handlers_passed > 0) {
 
604
        DEBUG("Updating queued event %s (some handlers passed)\n", file_name);
 
605
        Event_queue_update(e, file_name);
668
606
      }
669
607
 
670
 
      error3:
 
608
error8:
 
609
      FREE(action);
 
610
error7:
 
611
      FREE(e->message);
 
612
error6:
 
613
      FREE(e->group);
 
614
error5:
671
615
      FREE(e->source);
672
 
      FREE(e->group);
673
 
      FREE(e->message);
 
616
error4:
674
617
      FREE(e);
675
 
      FREE(action);
676
 
      error2:
 
618
error3:
677
619
      FREE(version);
 
620
error2:
678
621
      fclose(file);
679
622
    }
680
 
    error1:
 
623
error1:
681
624
    de = readdir(dir);
682
625
  }
683
626
  Run.handler_init = FALSE;
696
639
 * @param E An event
697
640
 */
698
641
static void handle_event(Event_T E) {
699
 
 
700
642
  Service_T S;
701
643
 
702
644
  ASSERT(E);
703
645
  ASSERT(E->action);
704
646
  ASSERT(E->action->failed);
705
 
  ASSERT(E->action->passed);
 
647
  ASSERT(E->action->succeeded);
706
648
 
707
 
  /* We will handle only first passed event, recurrent passed events
708
 
   * or insufficient passed events during failed service state are
 
649
  /* We will handle only first succeeded event, recurrent succeeded events
 
650
   * or insufficient succeeded events during failed service state are
709
651
   * ignored. Failed events are handled each time. */
710
 
  if(!E->state_changed && (E->state == STATE_PASSED || ((E->state_map & 0x1) ^ 0x1)))
711
 
  {
 
652
  if (!E->state_changed && (E->state == STATE_SUCCEEDED || E->state == STATE_CHANGEDNOT || ((E->state_map & 0x1) ^ 0x1)))
712
653
    return;
713
 
  }
714
 
 
715
 
  if(E->message)
716
 
  {
717
 
    /* In the case that the service state is yet initializing and error
718
 
     * occured, log it and exit. Passed events in init state are not
719
 
     * logged. */
720
 
    if(E->state != STATE_INIT || E->state_map & 0x1)
721
 
    {
722
 
      if(E->id == EVENT_INSTANCE || E->state == STATE_PASSED) {
723
 
        LogInfo("%s\n", E->message);
724
 
      } else {
725
 
        LogError("%s\n", E->message);
726
 
      }
727
 
    }
728
 
    if(E->state == STATE_INIT)
729
 
    {
730
 
      return;
731
 
    }
732
 
  }
733
654
 
734
655
  S = Event_get_source(E);
735
 
  if(!S)
736
 
  {
 
656
  if (!S) {
737
657
    LogError("Event handling aborted\n");
738
658
    return;
739
659
  }
740
660
 
741
 
  if(E->state == STATE_FAILED)
742
 
  {
743
 
    S->error |= E->id;
 
661
  if (E->message) {
 
662
    /* In the case that the service state is initializing yet and error
 
663
     * occured, log it and exit. Succeeded events in init state are not
 
664
     * logged. Instance and action events are logged always with priority
 
665
     * info. */
 
666
    if (E->state != STATE_INIT || E->state_map & 0x1) {
 
667
      if (E->state == STATE_SUCCEEDED || E->state == STATE_CHANGEDNOT || E->id == EVENT_INSTANCE || E->id == EVENT_ACTION)
 
668
        LogInfo("'%s' %s\n", S->name, E->message);
 
669
      else
 
670
        LogError("'%s' %s\n", S->name, E->message);
 
671
    }
 
672
    if (E->state == STATE_INIT)
 
673
      return;
 
674
  }
 
675
 
 
676
  if (E->state == STATE_FAILED || E->state == STATE_CHANGED) {
 
677
    if (E->id != EVENT_INSTANCE && E->id != EVENT_ACTION) { // We are not interested in setting error flag for instance and action events
 
678
      S->error |= E->id;
 
679
      /* The error hint provides second dimension for error bitmap and differentiates between failed/changed event states (failed=0, chaged=1) */
 
680
      if (E->state == STATE_CHANGED)
 
681
        S->error_hint |= E->id;
 
682
      else
 
683
        S->error_hint &= ~E->id;
 
684
    }
744
685
    handle_action(E, E->action->failed);
745
 
  }
746
 
  else
747
 
  {
 
686
  } else {
748
687
    S->error &= ~E->id;
749
 
    handle_action(E, E->action->passed);
 
688
    handle_action(E, E->action->succeeded);
750
689
  }
751
690
 
752
691
  /* Possible event state change was handled so we will reset the flag. */
753
692
  E->state_changed = FALSE;
754
 
 
755
693
}
756
694
 
757
695
 
758
696
static void handle_action(Event_T E, Action_T A) {
759
 
 
760
697
  Service_T s;
761
698
 
762
699
  ASSERT(E);
763
700
  ASSERT(A);
764
701
 
765
 
  E->flag = HANDLER_PASSED;
 
702
  E->flag = HANDLER_SUCCEEDED;
766
703
 
767
 
  if(A->id == ACTION_IGNORE)
768
 
  {
 
704
  if (A->id == ACTION_IGNORE)
769
705
    return;
770
 
  }
771
706
 
772
 
  /* Alert and collector event notification are common actions */
 
707
  /* Alert and mmonit event notification are common actions */
 
708
  E->flag |= handle_mmonit(E);
773
709
  E->flag |= handle_alert(E);
774
 
  E->flag |= handle_collector(E);
775
710
 
776
711
  /* In the case that some subhandler failed, enqueue the event for
777
712
   * partial reprocessing */
778
 
  if(E->flag != HANDLER_PASSED)
779
 
  {
780
 
    if(Run.eventlist_dir)
781
 
    {
 
713
  if (E->flag != HANDLER_SUCCEEDED) {
 
714
    if (Run.eventlist_dir)
782
715
      Event_queue_add(E);
783
 
    }
784
716
    else
785
 
    {
786
717
      LogError("Aborting event\n");
787
 
    }
788
718
  }
789
719
 
790
 
  if(!(s = Event_get_source(E)))
791
 
  {
 
720
  if (!(s = Event_get_source(E))) {
792
721
    LogError("Event action handling aborted\n");
793
722
    return;
794
723
  }
795
724
 
796
 
  if(A->id == ACTION_ALERT)
797
 
  {
798
 
    return;     /* Already handled */
799
 
  }
800
 
  else if(A->id == ACTION_EXEC)
801
 
  {
 
725
  /* Action event is handled already. For Instance events
 
726
   * we don't wan't actions like stop to be executed
 
727
   * to prevent the disabling of system service monitoring */
 
728
  if (A->id == ACTION_ALERT || E->id == EVENT_INSTANCE) {
 
729
    return;
 
730
  } else if (A->id == ACTION_EXEC) {
 
731
    LogInfo("'%s' exec: %s\n", s->name, A->exec->arg[0]);
802
732
    spawn(s, A->exec, Event_get_description(E));
803
733
    return;
804
 
  }
805
 
  else 
806
 
  {
807
 
    if(s->def_timeout &&
808
 
         (A->id == ACTION_START ||
809
 
          A->id == ACTION_RESTART))
810
 
    {
 
734
  } else {
 
735
    if (s->def_timeout && (A->id == ACTION_START || A->id == ACTION_RESTART))
811
736
      s->nstart++;
812
 
    }
813
737
 
814
 
    if(s->mode == MODE_PASSIVE &&
815
 
         (A->id == ACTION_START ||
816
 
          A->id == ACTION_STOP  ||
817
 
          A->id == ACTION_RESTART))
818
 
    {
 
738
    if (s->mode == MODE_PASSIVE && (A->id == ACTION_START || A->id == ACTION_STOP  || A->id == ACTION_RESTART))
819
739
      return;
820
 
    }
821
740
 
822
741
    control_service(s->name, A->id);
823
742
  }
829
748
 * @param E An event object
830
749
 */
831
750
static void Event_queue_add(Event_T E) {
832
 
 
833
751
  FILE        *file = NULL;
834
752
  char         file_name[STRLEN];
835
753
  int          version = EVENT_VERSION;
836
754
  short        action = Event_get_action(E);
837
755
  int          rv = FALSE;
838
756
  mode_t       mask;
839
 
  sigset_t     ns;
840
 
  sigset_t     os;
841
757
 
842
758
  ASSERT(E);
843
 
  ASSERT(E->flag != HANDLER_PASSED);
 
759
  ASSERT(E->flag != HANDLER_SUCCEEDED);
844
760
 
845
 
  if(!File_checkQueueDirectory(Run.eventlist_dir, 0700))
846
 
  {
847
 
    LogError("%s: Aborting event - cannot access the directory %s\n",
848
 
      prog, Run.eventlist_dir);
 
761
  if (!File_checkQueueDirectory(Run.eventlist_dir, 0700)) {
 
762
    LogError("%s: Aborting event - cannot access the directory %s\n", prog, Run.eventlist_dir);
849
763
    return;
850
764
  }
851
765
    
852
 
  if(!File_checkQueueLimit(Run.eventlist_dir, Run.eventlist_slots))
853
 
  {
 
766
  if (!File_checkQueueLimit(Run.eventlist_dir, Run.eventlist_slots)) {
854
767
    LogError("%s: Aborting event - queue over quota\n", prog);
855
768
    return;
856
769
  }
857
770
    
858
 
  set_signal_block(&ns, &os);
859
 
 
860
771
  /* compose the file name of actual timestamp and service name */
861
 
  snprintf(file_name, STRLEN,
862
 
    "%s/%ld_%s",
863
 
    Run.eventlist_dir, (long int)time(NULL), E->source);
 
772
  snprintf(file_name, STRLEN, "%s/%ld_%s", Run.eventlist_dir, (long int)time(NULL), E->source);
864
773
 
865
 
  DEBUG("%s: Adding event to the queue file %s for later delivery\n",
866
 
    prog, file_name);
 
774
  DEBUG("%s: Adding event to the queue file %s for later delivery\n", prog, file_name);
867
775
 
868
776
  mask = umask(QUEUEMASK);
869
777
  file = fopen(file_name, "w");
870
778
  umask(mask);
871
 
  if(! file)
872
 
  {
873
 
    LogError("%s: Aborting event - cannot open the event file %s -- %s\n",
874
 
      prog, file_name, STRERROR);
 
779
  if (! file) {
 
780
    LogError("%s: Aborting event - cannot open the event file %s -- %s\n", prog, file_name, STRERROR);
875
781
    return;
876
782
  }
877
783
 
878
784
  /* write event structure version */
879
 
  if(!(rv = File_writeQueue(file, &version, sizeof(int))))
 
785
  if (!(rv = File_writeQueue(file, &version, sizeof(int))))
880
786
    goto error;
881
787
 
882
788
  /* write event structure */
883
 
  if(!(rv = File_writeQueue(file, E, sizeof(*E))))
 
789
  if (!(rv = File_writeQueue(file, E, sizeof(*E))))
884
790
    goto error;
885
791
 
886
792
  /* write source */
887
 
  if(!(rv = File_writeQueue(file, E->source, E->source?strlen(E->source)+1:0)))
 
793
  if (!(rv = File_writeQueue(file, E->source, E->source ? strlen(E->source)+1 : 0)))
888
794
    goto error;
889
795
 
890
796
  /* write group */
891
 
  if(!(rv = File_writeQueue(file, E->group, E->group?strlen(E->group)+1:0)))
 
797
  if (!(rv = File_writeQueue(file, E->group, E->group ? strlen(E->group)+1 : 0)))
892
798
    goto error;
893
799
 
894
800
  /* write message */
895
 
  if(!(rv = File_writeQueue(file, E->message, E->message?strlen(E->message)+1:0)))
 
801
  if (!(rv = File_writeQueue(file, E->message, E->message ? strlen(E->message)+1 : 0)))
896
802
    goto error;
897
803
 
898
804
  /* write event action */
899
 
  if(!(rv = File_writeQueue(file, &action, sizeof(short))))
 
805
  if (!(rv = File_writeQueue(file, &action, sizeof(short))))
900
806
    goto error;
901
807
 
902
808
  error:
903
 
  if(!rv)
904
 
  {
905
 
    LogError("%s: Aborting event - unable to save event information to %s\n",
906
 
      prog, file_name);
907
 
    unlink(file_name);
908
 
  }
909
 
  else
910
 
  {
911
 
    if(!Run.handler_init && E->flag & HANDLER_ALERT)
912
 
    {
 
809
  fclose(file);
 
810
  if (!rv) {
 
811
    LogError("%s: Aborting event - unable to save event information to %s\n",  prog, file_name);
 
812
    if (unlink(file_name) < 0)
 
813
      LogError("Failed to remove event file '%s' -- %s\n", file_name, STRERROR);
 
814
  } else {
 
815
    if (!Run.handler_init && E->flag & HANDLER_ALERT)
913
816
      Run.handler_queue[HANDLER_ALERT]++;
914
 
    }
915
 
    if(!Run.handler_init && E->flag & HANDLER_COLLECTOR)
916
 
    {
917
 
      Run.handler_queue[HANDLER_COLLECTOR]++;
918
 
    }
919
 
    fclose(file);
920
 
  }
921
 
 
922
 
  unset_signal_block(&os);
 
817
    if (!Run.handler_init && E->flag & HANDLER_MMONIT)
 
818
      Run.handler_queue[HANDLER_MMONIT]++;
 
819
  }
 
820
 
 
821
  return;
 
822
}
 
823
 
 
824
 
 
825
/**
 
826
 * Update the partialy handled event in the global queue
 
827
 * @param E An event object
 
828
 * @param file_name File name
 
829
 */
 
830
static void Event_queue_update(Event_T E, const char *file_name) {
 
831
  FILE        *file = NULL;
 
832
  int          version = EVENT_VERSION;
 
833
  short        action = Event_get_action(E);
 
834
  int          rv = FALSE;
 
835
  mode_t       mask;
 
836
 
 
837
  ASSERT(E);
 
838
  ASSERT(E->flag != HANDLER_SUCCEEDED);
 
839
 
 
840
  if (!File_checkQueueDirectory(Run.eventlist_dir, 0700)) {
 
841
    LogError("%s: Aborting event - cannot access the directory %s\n", prog, Run.eventlist_dir);
 
842
    return;
 
843
  }
 
844
    
 
845
  DEBUG("%s: Updating event in the queue file %s for later delivery\n", prog, file_name);
 
846
 
 
847
  mask = umask(QUEUEMASK);
 
848
  file = fopen(file_name, "w");
 
849
  umask(mask);
 
850
  if (! file)
 
851
  {
 
852
    LogError("%s: Aborting event - cannot open the event file %s -- %s\n", prog, file_name, STRERROR);
 
853
    return;
 
854
  }
 
855
 
 
856
  /* write event structure version */
 
857
  if (!(rv = File_writeQueue(file, &version, sizeof(int))))
 
858
    goto error;
 
859
 
 
860
  /* write event structure */
 
861
  if (!(rv = File_writeQueue(file, E, sizeof(*E))))
 
862
    goto error;
 
863
 
 
864
  /* write source */
 
865
  if (!(rv = File_writeQueue(file, E->source, E->source ? strlen(E->source)+1 : 0)))
 
866
    goto error;
 
867
 
 
868
  /* write group */
 
869
  if (!(rv = File_writeQueue(file, E->group, E->group ? strlen(E->group)+1 : 0)))
 
870
    goto error;
 
871
 
 
872
  /* write message */
 
873
  if (!(rv = File_writeQueue(file, E->message, E->message ? strlen(E->message)+1 : 0)))
 
874
    goto error;
 
875
 
 
876
  /* write event action */
 
877
  if (!(rv = File_writeQueue(file, &action, sizeof(short))))
 
878
    goto error;
 
879
 
 
880
  error:
 
881
  fclose(file);
 
882
  if (!rv) {
 
883
    LogError("%s: Aborting event - unable to update event information to %s\n",  prog, file_name);
 
884
    if (unlink(file_name) < 0)
 
885
      LogError("Failed to remove event file '%s' -- %s\n", file_name, STRERROR);
 
886
  }
 
887
 
923
888
  return;
924
889
}
925
890