40 |
#include "net.h" |
#include "net.h" |
41 |
#include "monit_process.h" |
#include "monit_process.h" |
42 |
|
|
|
/* Private variables */ |
|
|
static sigjmp_buf timeout; |
|
|
|
|
|
/* Private Prototypes */ |
|
|
static void do_validate(Process_T, ProcessTree_T *, int); |
|
|
static void do_restart(Process_T, char *, ...) ; |
|
|
static void do_start(Process_T, char *, ...) ; |
|
|
static void do_stop(Process_T, char *, ...); |
|
|
static int do_not_validate(Process_T); |
|
|
static int check_connection(Process_T, Port_T, char *); |
|
|
static int check_resources(Process_T, Resource_T, char *); |
|
|
static int check_process_state(Process_T, char *); |
|
|
static int check_skip(Process_T); |
|
|
static int check_timeout(Process_T); |
|
|
static int check_checksum(Process_T); |
|
|
static int checksum_helper(Process_T, char *, char *); |
|
|
static int check_timestamp(Process_T, Timestamp_T, char *); |
|
|
static int check_device(Process_T, Device_T, char *); |
|
|
static void connection_timeout(int); |
|
|
static void reset_resource_counter(Process_T); |
|
|
static void vlog(char * report, int n, Process_T p, char *m,...); |
|
|
static int compare_value(int, int, int); |
|
43 |
|
|
44 |
/** |
/** |
45 |
* This function contains the main process and check machinery for |
* This function contains the main process and check machinery for |
46 |
* monit. The validate function check processes in the process list |
* monit. The validate function check services in the service list |
47 |
* to see if they are running and that they accepts connections if |
* to see if they are running and that they accepts connections if |
48 |
* ports are defined. Not running processes are restarted. This |
* ports are defined. Not running services are restarted. This |
49 |
* function also handles the various tests per process that are |
* function also handles the various tests per service that are |
50 |
* defined in the control file. |
* defined in the control file. |
51 |
* |
* |
52 |
* @author Jan-Henrik Haukeland, <hauk@tildeslash.com> |
* @author Jan-Henrik Haukeland, <hauk@tildeslash.com> |
60 |
*/ |
*/ |
61 |
|
|
62 |
|
|
63 |
|
/* ------------------------------------------------------- Private variables */ |
64 |
|
|
65 |
|
|
66 |
|
static sigjmp_buf timeout; |
67 |
|
|
68 |
|
|
69 |
|
/* -------------------------------------------------------------- Prototypes */ |
70 |
|
|
71 |
|
|
72 |
|
static int check_skip(Service_T); |
73 |
|
static void connection_timeout(int); |
74 |
|
static int check_timeout(Service_T); |
75 |
|
static int check_checksum(Service_T); |
76 |
|
static int do_not_validate(Service_T); |
77 |
|
static int compare_value(int, int, int); |
78 |
|
static void do_stop(Service_T, char *, ...); |
79 |
|
static void do_start(Service_T, char *, ...); |
80 |
|
static void reset_resource_counter(Service_T); |
81 |
|
static void do_restart(Service_T, char *, ...); |
82 |
|
static int check_process_state(Service_T, char *); |
83 |
|
static int check_device(Service_T, Device_T, char *); |
84 |
|
static int check_connection(Service_T, Port_T, char *); |
85 |
|
static void do_validate(Service_T, ProcessTree_T *, int); |
86 |
|
static int check_resources(Service_T, Resource_T, char *); |
87 |
|
static int check_timestamp(Service_T, Timestamp_T, char *); |
88 |
|
static void vlog(char * report, int n, Service_T s, char *m,...); |
89 |
|
|
90 |
|
|
91 |
/* ---------------------------------------------------------------- Public */ |
/* ---------------------------------------------------------------- Public */ |
92 |
|
|
93 |
|
|
94 |
/** |
/** |
95 |
* Walk the process-list and validate each process |
* Walk the service-list and validate each service |
96 |
*/ |
*/ |
97 |
void validate() { |
void validate() { |
98 |
|
|
99 |
Process_T p; |
Service_T s; |
100 |
ProcessTree_T * pt; |
int treesize= 0; |
101 |
int treesize = 0; |
ProcessTree_T *pt; |
102 |
|
|
103 |
if (Run.doprocess) { |
if(Run.doprocess) { |
104 |
|
|
105 |
treesize = initprocesstree(&pt); |
treesize = initprocesstree(&pt); |
106 |
|
|
112 |
|
|
113 |
} |
} |
114 |
|
|
115 |
for(p= processlist; p; p= p->next) { |
for(s= servicelist; s; s= s->next) { |
116 |
if(p->visited) |
if(s->visited) |
117 |
continue; |
continue; |
118 |
do_validate(p, pt, treesize); |
do_validate(s, pt, treesize); |
119 |
} |
} |
120 |
|
|
121 |
reset_depend(); |
reset_depend(); |
133 |
|
|
134 |
|
|
135 |
/** |
/** |
136 |
* Validate the given process - If the process is not running, start |
* Validate the given service - If the service is not running, start |
137 |
* it. If the process listens on a port try to connect to the port and |
* it. If the service listens on a port try to connect to the port and |
138 |
* test the stated protocol at the port. If any of the various tests |
* test the stated protocol at the port. If any of the various tests |
139 |
* fails then do the specified action on the process. |
* fails then do the specified action on the service. |
140 |
* |
* |
141 |
* We block for the signals SIGTERM while in this function. |
* We block for the signals SIGTERM while in this function. |
142 |
*/ |
*/ |
143 |
static void do_validate(Process_T p, ProcessTree_T * pt, int treesize) { |
static void do_validate(Service_T s, ProcessTree_T * pt, int treesize) { |
144 |
|
|
145 |
Port_T pp; |
Port_T pp; |
146 |
|
Device_T td; |
147 |
Resource_T pr; |
Resource_T pr; |
148 |
Timestamp_T tl; |
Timestamp_T tl; |
|
Device_T td; |
|
149 |
pid_t pid= -1; |
pid_t pid= -1; |
150 |
sigset_t ns,os; |
sigset_t ns,os; |
|
struct stat stat_buf; |
|
151 |
char report[STRLEN]; |
char report[STRLEN]; |
152 |
|
struct stat stat_buf; |
153 |
|
|
154 |
ASSERT(p); |
ASSERT(s); |
155 |
ASSERT(p->path); |
ASSERT(s->path); |
156 |
|
|
157 |
/* Obtain process action mutex */ |
/* Obtain service action mutex */ |
158 |
LOCK(p->mutex) |
LOCK(s->mutex) |
159 |
|
|
160 |
/* First, check for pre-conditions */ |
/* First, check for pre-conditions */ |
161 |
if(do_not_validate(p)) { |
if(do_not_validate(s)) { |
162 |
/* Release process action mutex */ |
/* Release service action mutex */ |
163 |
pthread_mutex_unlock(&p->mutex); |
pthread_mutex_unlock(&s->mutex); |
164 |
return; |
return; |
165 |
} |
} |
166 |
|
|
171 |
|
|
172 |
|
|
173 |
/** Context specific task actions */ |
/** Context specific task actions */ |
174 |
switch(p->task) { |
switch(s->task) { |
175 |
|
|
176 |
case TASK_PROCESS: |
case TASK_PROCESS: |
177 |
|
|
178 |
/* Test for running process */ |
/* Test for running process */ |
179 |
if(!(pid= is_process_running(p))) { |
if(!(pid= is_process_running(s))) { |
180 |
|
|
181 |
/* Reset the proc info object to prevent false data in the first run */ |
/* Reset the proc info object to prevent false data in the first run */ |
182 |
memset(p->procinfo, 0, sizeof *(p->procinfo)); |
memset(s->procinfo, 0, sizeof *(s->procinfo)); |
183 |
|
|
184 |
do_start(p, "Reason: Process is not running."); |
do_start(s, "Reason: Process is not running."); |
185 |
goto reinstall; |
goto reinstall; |
186 |
|
|
187 |
} else { |
} else { |
188 |
|
|
189 |
DEBUG("'%s' is running with pid %d\n", p->name, (int)pid); |
DEBUG("'%s' is running with pid %d\n", s->name, (int)pid); |
190 |
|
|
191 |
} |
} |
192 |
|
|
193 |
if(Run.doprocess) { |
if(Run.doprocess) { |
194 |
|
|
195 |
if(update_process_data(p, pt, treesize, pid)) { |
if(update_process_data(s, pt, treesize, pid)) { |
196 |
|
|
197 |
if(! check_process_state(p, report)) { |
if(! check_process_state(s, report)) { |
198 |
|
|
199 |
smtp_alert_resource(p, "Reason: %s\n", report); |
smtp_alert_resource(s, "Reason: %s\n", report); |
200 |
|
|
201 |
} else { |
} else { |
202 |
|
|
203 |
DEBUG("'%s' check_process_state() passed.\n", p->name); |
DEBUG("'%s' check_process_state() passed.\n", s->name); |
204 |
|
|
205 |
} |
} |
206 |
|
|
207 |
for(pr= p->resourcelist; pr; pr= pr->next) { |
for(pr= s->resourcelist; pr; pr= pr->next) { |
208 |
|
|
209 |
if(!check_resources(p, pr, report)) { |
if(!check_resources(s, pr, report)) { |
210 |
|
|
211 |
switch(pr->action) { |
switch(pr->action) { |
212 |
case ACTION_ALERT: |
case ACTION_ALERT: |
213 |
if(p->def_timeout) p->nstart++; |
if(s->def_timeout) s->nstart++; |
214 |
smtp_alert_resource(p, "Reason: %s\n", report); |
smtp_alert_resource(s, "Reason: %s\n", report); |
215 |
/* We are also interested in other alerts/stops/restarts! */ |
/* We are also interested in other alerts/stops/restarts! */ |
216 |
pr->cycle=0; |
pr->cycle=0; |
217 |
break; |
break; |
218 |
|
|
219 |
case ACTION_STOP: |
case ACTION_STOP: |
220 |
do_stop(p, "Reason: %s\n", report); |
do_stop(s, "Reason: %s\n", report); |
221 |
reset_resource_counter(p); |
reset_resource_counter(s); |
222 |
goto reinstall; |
goto reinstall; |
223 |
|
|
224 |
case ACTION_RESTART: |
case ACTION_RESTART: |
225 |
do_restart(p, "Reason: %s\n", report); |
do_restart(s, "Reason: %s\n", report); |
226 |
reset_resource_counter(p); |
reset_resource_counter(s); |
227 |
goto reinstall; |
goto reinstall; |
228 |
|
|
229 |
default: |
default: |
230 |
log("'%s' Unknow resource failure action.\n", p->name); |
log("'%s' Unknow resource failure action.\n", s->name); |
231 |
break; |
break; |
232 |
} |
} |
233 |
|
|
237 |
|
|
238 |
} else { |
} else { |
239 |
|
|
240 |
log("'%s' failed to get process data\n", p->name); |
log("'%s' failed to get service data\n", s->name); |
241 |
|
|
242 |
} |
} |
243 |
|
|
244 |
} |
} |
245 |
|
|
246 |
/* Test each host:port and protocol in the process's portlist */ |
/* Test each host:port and protocol in the service's portlist */ |
247 |
for(pp= p->portlist; pp; pp= pp->next) { |
for(pp= s->portlist; pp; pp= pp->next) { |
248 |
|
|
249 |
if(!check_connection(p, pp, report)) { |
if(!check_connection(s, pp, report)) { |
250 |
|
|
251 |
do_restart(p, "Reason: %s\n", report); |
do_restart(s, "Reason: %s\n", report); |
252 |
goto reinstall; |
goto reinstall; |
253 |
|
|
254 |
} |
} |
259 |
case TASK_DEVICE: |
case TASK_DEVICE: |
260 |
|
|
261 |
/* Test devices */ |
/* Test devices */ |
262 |
if(p->devicelist) { |
if(s->devicelist) { |
263 |
|
|
264 |
if(!get_fsusage(p->path, p->devinfo)) { |
if(!get_fsusage(s->path, s->devinfo)) { |
265 |
do_restart(p, "Reason: unable to read device state\n"); |
do_restart(s, "Reason: unable to read device state\n"); |
266 |
goto reinstall; |
goto reinstall; |
267 |
} |
} |
268 |
|
|
269 |
for(td= p->devicelist; td; td= td->next) { |
for(td= s->devicelist; td; td= td->next) { |
270 |
|
|
271 |
if(!check_device(p, td, report)) { |
if(!check_device(s, td, report)) { |
272 |
|
|
273 |
switch(td->action) { |
switch(td->action) { |
274 |
case ACTION_ALERT: |
case ACTION_ALERT: |
275 |
smtp_alert_resource(p, "Reason: %s\n", report); |
smtp_alert_resource(s, "Reason: %s\n", report); |
276 |
break; |
break; |
277 |
|
|
278 |
case ACTION_STOP: |
case ACTION_STOP: |
279 |
do_stop(p, "Reason: %s\n", report); |
do_stop(s, "Reason: %s\n", report); |
280 |
goto reinstall; |
goto reinstall; |
281 |
|
|
282 |
case ACTION_RESTART: |
case ACTION_RESTART: |
283 |
do_restart(p, "Reason: %s\n", report); |
do_restart(s, "Reason: %s\n", report); |
284 |
goto reinstall; |
goto reinstall; |
285 |
|
|
286 |
default: |
default: |
287 |
log("'%s' Unknow device failure action.\n", p->name); |
log("'%s' Unknow device failure action.\n", s->name); |
288 |
break; |
break; |
289 |
} |
} |
290 |
|
|
297 |
|
|
298 |
case TASK_FILE: |
case TASK_FILE: |
299 |
|
|
300 |
if(stat(p->path, &stat_buf) != 0) { |
if(stat(s->path, &stat_buf) != 0) { |
301 |
log("'%s' doesn't exist\n", p->name); |
log("'%s' doesn't exist\n", s->name); |
302 |
do_restart(p, "Reason: file doesn't exist\n"); |
do_restart(s, "Reason: file doesn't exist\n"); |
303 |
goto reinstall; |
goto reinstall; |
304 |
} |
} |
305 |
|
|
306 |
if(!S_ISREG(stat_buf.st_mode)) { |
if(!S_ISREG(stat_buf.st_mode)) { |
307 |
log("'%s' is not regular file\n", p->name); |
log("'%s' is not regular file\n", s->name); |
308 |
do_restart(p, "Reason: object is not file\n"); |
do_restart(s, "Reason: object is not file\n"); |
309 |
goto reinstall; |
goto reinstall; |
310 |
} |
} |
311 |
|
|
312 |
if( p->perm != -1 && (stat_buf.st_mode & 07777) != p->perm ) { |
if( s->perm != -1 && (stat_buf.st_mode & 07777) != s->perm ) { |
313 |
log("'%s' permission test failed -- current permission: %o\n", |
log("'%s' permission test failed -- current permission: %o\n", |
314 |
p->name, stat_buf.st_mode&07777); |
s->name, stat_buf.st_mode&07777); |
315 |
do_restart(p, "Reason: permission test failed: %o\n", stat_buf.st_mode&07777); |
do_restart(s, "Reason: permission test failed: %o\n", |
316 |
|
stat_buf.st_mode&07777); |
317 |
goto reinstall; |
goto reinstall; |
318 |
} |
} |
319 |
|
|
320 |
DEBUG("'%s' file permission check passed [current permission=%o]\n", |
DEBUG("'%s' file permission check passed [current permission=%o]\n", |
321 |
p->name, stat_buf.st_mode&07777); |
s->name, stat_buf.st_mode&07777); |
322 |
|
|
323 |
break; |
break; |
324 |
|
|
325 |
case TASK_DIRECTORY: |
case TASK_DIRECTORY: |
326 |
|
|
327 |
if(stat(p->path, &stat_buf) != 0) { |
if(stat(s->path, &stat_buf) != 0) { |
328 |
log("'%s' doesn't exist\n", p->name); |
log("'%s' doesn't exist\n", s->name); |
329 |
do_restart(p, "Reason: directory doesn't exist\n"); |
do_restart(s, "Reason: directory doesn't exist\n"); |
330 |
goto reinstall; |
goto reinstall; |
331 |
} |
} |
332 |
|
|
333 |
if(!S_ISDIR(stat_buf.st_mode)) { |
if(!S_ISDIR(stat_buf.st_mode)) { |
334 |
log("'%s' is not directory\n", p->name); |
log("'%s' is not directory\n", s->name); |
335 |
do_restart(p, "Reason: object is not directory\n"); |
do_restart(s, "Reason: object is not directory\n"); |
336 |
goto reinstall; |
goto reinstall; |
337 |
} |
} |
338 |
|
|
339 |
if( p->perm != -1 && (stat_buf.st_mode & 07777) != p->perm ) { |
if( s->perm != -1 && (stat_buf.st_mode & 07777) != s->perm ) { |
340 |
log("'%s' permission test failed -- current permission: %o\n", |
log("'%s' permission test failed -- current permission: %o\n", |
341 |
p->name, stat_buf.st_mode&07777); |
s->name, stat_buf.st_mode&07777); |
342 |
do_restart(p, "Reason: permission test failed: %o\n", stat_buf.st_mode&07777); |
do_restart(s, "Reason: permission test failed: %o\n", |
343 |
|
stat_buf.st_mode&07777); |
344 |
goto reinstall; |
goto reinstall; |
345 |
} |
} |
346 |
|
|
347 |
DEBUG("'%s' directory permission check passed [current permission=%o]\n", |
DEBUG("'%s' directory permission check passed [current permission=%o]\n", |
348 |
p->name, stat_buf.st_mode&07777); |
s->name, stat_buf.st_mode&07777); |
349 |
|
|
350 |
break; |
break; |
351 |
|
|
356 |
|
|
357 |
|
|
358 |
/** Common task actions */ |
/** Common task actions */ |
359 |
for(tl= p->timestamplist; tl; tl= tl->next) { |
for(tl= s->timestamplist; tl; tl= tl->next) { |
360 |
|
|
361 |
if(!check_timestamp(p, tl, report)) { |
if(!check_timestamp(s, tl, report)) { |
362 |
|
|
363 |
switch(tl->action) { |
switch(tl->action) { |
364 |
case ACTION_ALERT: |
case ACTION_ALERT: |
365 |
if(p->def_timeout) p->nstart++; |
if(s->def_timeout) s->nstart++; |
366 |
smtp_alert_timestamp(p, "Reason: %s\n", report); |
smtp_alert_timestamp(s, "Reason: %s\n", report); |
367 |
break; /* continue */ |
break; /* continue */ |
368 |
|
|
369 |
case ACTION_STOP: |
case ACTION_STOP: |
370 |
do_stop(p, "Reason: %s\n", report); |
do_stop(s, "Reason: %s\n", report); |
371 |
goto reinstall; |
goto reinstall; |
372 |
|
|
373 |
case ACTION_RESTART: |
case ACTION_RESTART: |
374 |
do_restart(p, "Reason: %s\n", report); |
do_restart(s, "Reason: %s\n", report); |
375 |
goto reinstall; |
goto reinstall; |
376 |
|
|
377 |
default: |
default: |
378 |
log("'%s' Unknow timestamp failure action.\n", p->name); |
log("'%s' Unknow timestamp failure action.\n", s->name); |
379 |
break; |
break; |
380 |
|
|
381 |
} |
} |
389 |
/* Remove the SIGTERM block */ |
/* Remove the SIGTERM block */ |
390 |
pthread_sigmask(SIG_SETMASK, &os, NULL); |
pthread_sigmask(SIG_SETMASK, &os, NULL); |
391 |
|
|
392 |
/* Release process action mutex */ |
/* Release service action mutex */ |
393 |
END_LOCK; |
END_LOCK; |
394 |
|
|
395 |
} |
} |
396 |
|
|
397 |
|
|
398 |
/** |
/** |
399 |
* Restart the process if the start and stop |
* Restart the service if the start and stop |
400 |
* program is defined, and validate is TRUE. |
* program is defined, and validate is TRUE. |
401 |
*/ |
*/ |
402 |
static void do_restart(Process_T p, char *m, ...) { |
static void do_restart(Service_T s, char *m, ...) { |
403 |
|
|
404 |
va_list ap; |
va_list ap; |
405 |
char *tmp = NULL; |
char *tmp = NULL; |
406 |
|
|
407 |
ASSERT(p); |
ASSERT(s); |
408 |
|
|
409 |
if(!p->do_validate) |
if(!s->do_validate) |
410 |
return; |
return; |
411 |
|
|
412 |
if(p->def_timeout) |
if(s->def_timeout) |
413 |
p->nstart++; |
s->nstart++; |
414 |
|
|
415 |
va_start(ap, m); |
va_start(ap, m); |
416 |
if(m) |
if(m) |
417 |
tmp=format(m, ap); |
tmp=format(m, ap); |
418 |
va_end(ap); |
va_end(ap); |
419 |
|
|
420 |
if(p->mode!=MODE_PASSIVE && p->start && p->stop) { |
if(s->mode!=MODE_PASSIVE && s->start && s->stop) { |
421 |
|
|
422 |
log("Trying to restart '%s'\n", p->name); |
log("Trying to restart '%s'\n", s->name); |
423 |
check_process(p->name, "restart"); |
check_service(s->name, "restart"); |
424 |
smtp_alert_restart(p, "%s", tmp); |
smtp_alert_restart(s, "%s", tmp); |
425 |
|
|
426 |
} else { |
} else { |
427 |
|
|
428 |
smtp_alert_failed(p, "%s", tmp); |
smtp_alert_failed(s, "%s", tmp); |
429 |
|
|
430 |
} |
} |
431 |
|
|
435 |
|
|
436 |
|
|
437 |
/** |
/** |
438 |
* Start the process if the start program is defined, |
* Start the service if the start program is defined, |
439 |
* and validate is TRUE. |
* and validate is TRUE. |
440 |
*/ |
*/ |
441 |
static void do_start(Process_T p, char *m, ...) { |
static void do_start(Service_T s, char *m, ...) { |
442 |
|
|
443 |
va_list ap; |
va_list ap; |
444 |
char *tmp = NULL; |
char *tmp = NULL; |
445 |
|
|
446 |
ASSERT(p); |
ASSERT(s); |
447 |
|
|
448 |
if(!p->do_validate) |
if(!s->do_validate) |
449 |
return; |
return; |
450 |
|
|
451 |
if(p->def_timeout) |
if(s->def_timeout) |
452 |
p->nstart++; |
s->nstart++; |
453 |
|
|
454 |
va_start(ap, m); |
va_start(ap, m); |
455 |
if(m) |
if(m) |
456 |
tmp=format(m, ap); |
tmp=format(m, ap); |
457 |
va_end(ap); |
va_end(ap); |
458 |
|
|
459 |
if(p->mode!= MODE_PASSIVE && p->start) { |
if(s->mode!= MODE_PASSIVE && s->start) { |
460 |
|
|
461 |
check_process(p->name, "start"); |
check_service(s->name, "start"); |
462 |
smtp_alert_restart(p, "%s", tmp); |
smtp_alert_restart(s, "%s", tmp); |
463 |
|
|
464 |
} else { |
} else { |
465 |
|
|
466 |
smtp_alert_failed(p, "%s", tmp); |
smtp_alert_failed(s, "%s", tmp); |
467 |
|
|
468 |
} |
} |
469 |
|
|
473 |
|
|
474 |
|
|
475 |
/** |
/** |
476 |
* Stop the process if the stop program is defined, |
* Stop the service if the stop program is defined, |
477 |
* and validate is TRUE. |
* and validate is TRUE. |
478 |
*/ |
*/ |
479 |
static void do_stop(Process_T p, char *m, ...) { |
static void do_stop(Service_T s, char *m, ...) { |
480 |
|
|
481 |
va_list ap; |
va_list ap; |
482 |
char *tmp = NULL; |
char *tmp = NULL; |
483 |
|
|
484 |
ASSERT(p); |
ASSERT(s); |
485 |
|
|
486 |
if(!p->do_validate) |
if(!s->do_validate) |
487 |
return; |
return; |
488 |
|
|
489 |
va_start(ap, m); |
va_start(ap, m); |
492 |
va_end(ap); |
va_end(ap); |
493 |
|
|
494 |
LOCK(Run.mutex) |
LOCK(Run.mutex) |
495 |
p->do_validate= FALSE; |
s->do_validate= FALSE; |
496 |
END_LOCK; |
END_LOCK; |
497 |
|
|
498 |
if(p->mode!= MODE_PASSIVE && p->stop) { |
if(s->mode!= MODE_PASSIVE && s->stop) { |
499 |
|
|
500 |
smtp_alert_stop(p, "%s", tmp); |
smtp_alert_stop(s, "%s", tmp); |
501 |
check_process(p->name, "stop"); |
check_service(s->name, "stop"); |
502 |
|
|
503 |
} else { |
} else { |
504 |
|
|
505 |
if(p->def_timeout) |
if(s->def_timeout) |
506 |
p->nstart++; |
s->nstart++; |
507 |
|
|
508 |
smtp_alert_failed(p, "%s", tmp); |
smtp_alert_failed(s, "%s", tmp); |
509 |
|
|
510 |
} |
} |
511 |
|
|
518 |
* Returns the logical OR of pre-condition tests. |
* Returns the logical OR of pre-condition tests. |
519 |
* A variant of the template-method pattern |
* A variant of the template-method pattern |
520 |
*/ |
*/ |
521 |
static int do_not_validate(Process_T p) { |
static int do_not_validate(Service_T s) { |
522 |
|
|
523 |
ASSERT(p); |
ASSERT(s); |
524 |
|
|
525 |
return(!p->do_validate || |
return(!s->do_validate || |
526 |
check_skip(p) || |
check_skip(s) || |
527 |
check_timeout(p) || |
check_timeout(s) || |
528 |
check_checksum(p)); |
check_checksum(s)); |
529 |
|
|
530 |
} |
} |
531 |
|
|
534 |
* Returns TRUE if the connection and protocol test succeeded |
* Returns TRUE if the connection and protocol test succeeded |
535 |
* otherwise FALSE. |
* otherwise FALSE. |
536 |
*/ |
*/ |
537 |
static int check_connection(Process_T p, Port_T pp, char *report) { |
static int check_connection(Service_T s, Port_T pp, char *report) { |
538 |
|
|
539 |
volatile int rv= TRUE; |
volatile int rv= TRUE; |
540 |
|
|
541 |
ASSERT(p && pp); |
ASSERT(s && pp); |
542 |
|
|
543 |
/* Control comes here if a timeout occures */ |
/* Control comes here if a timeout occures */ |
544 |
if(sigsetjmp(timeout, TRUE)) { |
if(sigsetjmp(timeout, TRUE)) { |
547 |
"timed out when testing %s [%s]", |
"timed out when testing %s [%s]", |
548 |
pp->address, pp->protocol->name); |
pp->address, pp->protocol->name); |
549 |
|
|
550 |
log("'%s' %s\n", p->name, report); |
log("'%s' %s\n", s->name, report); |
551 |
|
|
552 |
rv= FALSE; |
rv= FALSE; |
553 |
goto error; |
goto error; |
565 |
"does not accept connection at %s.", |
"does not accept connection at %s.", |
566 |
pp->address); |
pp->address); |
567 |
|
|
568 |
log("'%s' %s\n", p->name, report); |
log("'%s' %s\n", s->name, report); |
569 |
|
|
570 |
rv= FALSE; |
rv= FALSE; |
571 |
goto error; |
goto error; |
572 |
|
|
573 |
} else { |
} else { |
574 |
|
|
575 |
DEBUG("'%s' succeeded connecting to %s\n", p->name, pp->address); |
DEBUG("'%s' succeeded connecting to %s\n", s->name, pp->address); |
576 |
|
|
577 |
} |
} |
578 |
|
|
583 |
"socket at %s is not ready for i|o -- %s", |
"socket at %s is not ready for i|o -- %s", |
584 |
pp->address, STRERROR); |
pp->address, STRERROR); |
585 |
|
|
586 |
log("'%s' %s\n", p->name, report); |
log("'%s' %s\n", s->name, report); |
587 |
|
|
588 |
rv= FALSE; |
rv= FALSE; |
589 |
goto error; |
goto error; |
598 |
"failed establish SSL communication on socket at %s", |
"failed establish SSL communication on socket at %s", |
599 |
pp->address); |
pp->address); |
600 |
|
|
601 |
log("'%s' %s\n", p->name, report); |
log("'%s' %s\n", s->name, report); |
602 |
rv= FALSE; |
rv= FALSE; |
603 |
goto error; |
goto error; |
604 |
|
|
612 |
"md5sums of SSL certificates do not match at %s", |
"md5sums of SSL certificates do not match at %s", |
613 |
pp->address); |
pp->address); |
614 |
|
|
615 |
log("'%s' %s\n", p->name, report); |
log("'%s' %s\n", s->name, report); |
616 |
rv= FALSE; |
rv= FALSE; |
617 |
goto error; |
goto error; |
618 |
|
|
629 |
"test with protocol [%s] failed at %s.", |
"test with protocol [%s] failed at %s.", |
630 |
pp->protocol->name, pp->address); |
pp->protocol->name, pp->address); |
631 |
|
|
632 |
log("'%s' %s\n", p->name, report); |
log("'%s' %s\n", s->name, report); |
633 |
|
|
634 |
rv= FALSE; |
rv= FALSE; |
635 |
goto error; |
goto error; |
637 |
} else { |
} else { |
638 |
|
|
639 |
DEBUG("'%s' succeeded testing protocol [%s] at %s\n", |
DEBUG("'%s' succeeded testing protocol [%s] at %s\n", |
640 |
p->name, pp->protocol->name, pp->address); |
s->name, pp->protocol->name, pp->address); |
641 |
} |
} |
642 |
|
|
643 |
error: |
error: |
661 |
* Returns TRUE if the process state (e.g. Zombie) test succeeded |
* Returns TRUE if the process state (e.g. Zombie) test succeeded |
662 |
* otherwise FALSE. |
* otherwise FALSE. |
663 |
*/ |
*/ |
664 |
static int check_process_state(Process_T p, char *report) { |
static int check_process_state(Service_T s, char *report) { |
665 |
|
|
666 |
ProcInfo_T pi; |
ProcInfo_T pi; |
667 |
|
|
668 |
ASSERT(p); |
ASSERT(s); |
669 |
|
|
670 |
pi= p->procinfo; |
pi= s->procinfo; |
671 |
|
|
672 |
if(pi->status_flag & PROCESS_ZOMBIE) { |
if(pi->status_flag & PROCESS_ZOMBIE) { |
673 |
|
|
674 |
snprintf(report, STRLEN, |
snprintf(report, STRLEN, |
675 |
"process with pid %d is a zombie\n", pi->pid); |
"process with pid %d is a zombie\n", pi->pid); |
676 |
|
|
677 |
log("'%s' %s\n", p->name, report); |
log("'%s' %s\n", s->name, report); |
678 |
|
|
679 |
/* We do not check the process anymore if it's a zombie |
/* We do not check the process anymore if it's a zombie |
680 |
since such a process is (usually) unmanageable */ |
since such a process is (usually) unmanageable */ |
681 |
LOCK(Run.mutex) |
LOCK(Run.mutex) |
682 |
p->do_validate= FALSE; |
s->do_validate= FALSE; |
683 |
END_LOCK; |
END_LOCK; |
684 |
|
|
685 |
return FALSE; |
return FALSE; |
687 |
} else { |
} else { |
688 |
|
|
689 |
DEBUG("'%s' zombie check passed [status_flag=%04x]\n", |
DEBUG("'%s' zombie check passed [status_flag=%04x]\n", |
690 |
p->name, pi->status_flag); |
s->name, pi->status_flag); |
691 |
|
|
692 |
} |
} |
693 |
|
|
699 |
/** |
/** |
700 |
* Resets the resource counter |
* Resets the resource counter |
701 |
*/ |
*/ |
702 |
static void reset_resource_counter(Process_T p) { |
static void reset_resource_counter(Service_T s) { |
703 |
|
|
704 |
Resource_T pr; |
Resource_T pr; |
705 |
|
|
706 |
ASSERT(p); |
ASSERT(s); |
707 |
|
|
708 |
for(pr= p->resourcelist; pr; pr= pr->next) { |
for(pr= s->resourcelist; pr; pr= pr->next) { |
709 |
|
|
710 |
pr->cycle=0; |
pr->cycle=0; |
711 |
|
|
718 |
* Returns TRUE if the proc test succeeded |
* Returns TRUE if the proc test succeeded |
719 |
* otherwise FALSE. |
* otherwise FALSE. |
720 |
*/ |
*/ |
721 |
static int check_resources(Process_T p, Resource_T pr, char *report) { |
static int check_resources(Service_T s, Resource_T pr, char *report) { |
722 |
|
|
723 |
ProcInfo_T pi; |
ProcInfo_T pi; |
724 |
int okay= TRUE; |
int okay= TRUE; |
725 |
|
|
726 |
ASSERT(p); |
ASSERT(s); |
727 |
ASSERT(pr); |
ASSERT(pr); |
728 |
|
|
729 |
pi= p->procinfo; |
pi= s->procinfo; |
730 |
|
|
731 |
switch(pr->resource_id) { |
switch(pr->resource_id) { |
732 |
case RESOURCE_ID_CPU_PERCENT: |
case RESOURCE_ID_CPU_PERCENT: |
733 |
if(compare_value(pr->operator, pi->cpu_percent, pr->limit)) { |
if(compare_value(pr->operator, pi->cpu_percent, pr->limit)) { |
734 |
|
|
735 |
vlog(report, STRLEN, p, |
vlog(report, STRLEN, s, |
736 |
"cpu usage of %.1f%% matches resource limit [cpu usage%s%.1f%%]", |
"cpu usage of %.1f%% matches resource limit [cpu usage%s%.1f%%]", |
737 |
pi->cpu_percent/10.0, operatorshortnames[pr->operator], |
pi->cpu_percent/10.0, operatorshortnames[pr->operator], |
738 |
pr->limit/10.0); |
pr->limit/10.0); |
742 |
} else { |
} else { |
743 |
|
|
744 |
DEBUG("'%s' cpu usage check passed [current cpu usage=%.1f%%]\n", |
DEBUG("'%s' cpu usage check passed [current cpu usage=%.1f%%]\n", |
745 |
p->name, pi->cpu_percent/10.0); |
s->name, pi->cpu_percent/10.0); |
746 |
|
|
747 |
} |
} |
748 |
break; |
break; |
750 |
case RESOURCE_ID_MEM_PERCENT: |
case RESOURCE_ID_MEM_PERCENT: |
751 |
if(compare_value(pr->operator, pi->mem_percent, pr->limit)) { |
if(compare_value(pr->operator, pi->mem_percent, pr->limit)) { |
752 |
|
|
753 |
vlog(report, STRLEN, p, |
vlog(report, STRLEN, s, |
754 |
"mem usage of %.1f%% matches resource limit [mem usage%s%.1f%%]", |
"mem usage of %.1f%% matches resource limit [mem usage%s%.1f%%]", |
755 |
pi->mem_percent/10.0, operatorshortnames[pr->operator], |
pi->mem_percent/10.0, operatorshortnames[pr->operator], |
756 |
pr->limit/10.0); |
pr->limit/10.0); |
761 |
|
|
762 |
|
|
763 |
DEBUG("'%s' mem usage check passed [current mem usage=%.1f%%]\n", |
DEBUG("'%s' mem usage check passed [current mem usage=%.1f%%]\n", |
764 |
p->name, pi->mem_percent/10.0); |
s->name, pi->mem_percent/10.0); |
765 |
|
|
766 |
} |
} |
767 |
break; |
break; |
770 |
|
|
771 |
if(compare_value(pr->operator, pi->mem_kbyte, pr->limit)) { |
if(compare_value(pr->operator, pi->mem_kbyte, pr->limit)) { |
772 |
|
|
773 |
vlog(report, STRLEN, p, |
vlog(report, STRLEN, s, |
774 |
"mem amount of %ldkB matches resource limit [mem amount%s%ldkB]", |
"mem amount of %ldkB matches resource limit [mem amount%s%ldkB]", |
775 |
pi->mem_kbyte, operatorshortnames[pr->operator], |
pi->mem_kbyte, operatorshortnames[pr->operator], |
776 |
pr->limit); |
pr->limit); |
781 |
|
|
782 |
|
|
783 |
DEBUG("'%s' mem amount check passed [current mem amount=%ldkB]\n", |
DEBUG("'%s' mem amount check passed [current mem amount=%ldkB]\n", |
784 |
p->name, pi->mem_kbyte); |
s->name, pi->mem_kbyte); |
785 |
|
|
786 |
} |
} |
787 |
break; |
break; |
790 |
|
|
791 |
if(compare_value(pr->operator, (int)(Run.loadavg[0]*10.0), pr->limit)) { |
if(compare_value(pr->operator, (int)(Run.loadavg[0]*10.0), pr->limit)) { |
792 |
|
|
793 |
vlog(report, STRLEN, p, |
vlog(report, STRLEN, s, |
794 |
"loadavg(1min) of %.1f matches resource limit " |
"loadavg(1min) of %.1f matches resource limit " |
795 |
"[loadavg(1min)%s%.1f]", |
"[loadavg(1min)%s%.1f]", |
796 |
Run.loadavg[0], operatorshortnames[pr->operator], |
Run.loadavg[0], operatorshortnames[pr->operator], |
802 |
|
|
803 |
|
|
804 |
DEBUG("'%s' loadavg(1min) check passed [current loadavg(1min)=%.1f]\n", |
DEBUG("'%s' loadavg(1min) check passed [current loadavg(1min)=%.1f]\n", |
805 |
p->name, Run.loadavg[0]); |
s->name, Run.loadavg[0]); |
806 |
|
|
807 |
} |
} |
808 |
break; |
break; |
811 |
|
|
812 |
if(compare_value(pr->operator, (int)(Run.loadavg[1]*10.0), pr->limit)) { |
if(compare_value(pr->operator, (int)(Run.loadavg[1]*10.0), pr->limit)) { |
813 |
|
|
814 |
vlog(report, STRLEN, p, |
vlog(report, STRLEN, s, |
815 |
"loadavg(5min) of %.1f matches resource limit " |
"loadavg(5min) of %.1f matches resource limit " |
816 |
"[loadavg(5min)%s%.1f]", |
"[loadavg(5min)%s%.1f]", |
817 |
Run.loadavg[1], operatorshortnames[pr->operator], |
Run.loadavg[1], operatorshortnames[pr->operator], |
823 |
|
|
824 |
|
|
825 |
DEBUG("'%s' loadavg(5min) check passed [current loadavg(5min)=%.1f]\n", |
DEBUG("'%s' loadavg(5min) check passed [current loadavg(5min)=%.1f]\n", |
826 |
p->name, Run.loadavg[1]); |
s->name, Run.loadavg[1]); |
827 |
|
|
828 |
} |
} |
829 |
break; |
break; |
832 |
|
|
833 |
if(compare_value(pr->operator, (int)(Run.loadavg[2]*10.0), pr->limit)) { |
if(compare_value(pr->operator, (int)(Run.loadavg[2]*10.0), pr->limit)) { |
834 |
|
|
835 |
vlog(report, STRLEN, p, |
vlog(report, STRLEN, s, |
836 |
"loadavg(15min) of %.1f matches resource limit " |
"loadavg(15min) of %.1f matches resource limit " |
837 |
"[loadavg(15min)%s%.1f]", |
"[loadavg(15min)%s%.1f]", |
838 |
Run.loadavg[2], operatorshortnames[pr->operator], |
Run.loadavg[2], operatorshortnames[pr->operator], |
844 |
|
|
845 |
DEBUG("'%s' loadavg(15min) check passed " |
DEBUG("'%s' loadavg(15min) check passed " |
846 |
"[current loadavg(15min)=%.1f]\n", |
"[current loadavg(15min)=%.1f]\n", |
847 |
p->name, Run.loadavg[2]); |
s->name, Run.loadavg[2]); |
848 |
|
|
849 |
} |
} |
850 |
break; |
break; |
853 |
|
|
854 |
if(compare_value(pr->operator, pi->children, pr->limit)) { |
if(compare_value(pr->operator, pi->children, pr->limit)) { |
855 |
|
|
856 |
vlog(report, STRLEN, p, |
vlog(report, STRLEN, s, |
857 |
"children of %i matches resource limit " |
"children of %i matches resource limit " |
858 |
"[children%s%i]", |
"[children%s%i]", |
859 |
pi->children, operatorshortnames[pr->operator], |
pi->children, operatorshortnames[pr->operator], |
865 |
|
|
866 |
DEBUG("'%s' children check passed " |
DEBUG("'%s' children check passed " |
867 |
"[current children=%i]\n", |
"[current children=%i]\n", |
868 |
p->name, pi->children); |
s->name, pi->children); |
869 |
|
|
870 |
} |
} |
871 |
break; |
break; |
874 |
|
|
875 |
if(compare_value(pr->operator, pi->total_mem_kbyte, pr->limit)) { |
if(compare_value(pr->operator, pi->total_mem_kbyte, pr->limit)) { |
876 |
|
|
877 |
vlog(report, STRLEN, p, |
vlog(report, STRLEN, s, |
878 |
"total mem amount of %ldkB matches resource limit" |
"total mem amount of %ldkB matches resource limit" |
879 |
" [total mem amount%s%ldkB]", |
" [total mem amount%s%ldkB]", |
880 |
pi->total_mem_kbyte, operatorshortnames[pr->operator], |
pi->total_mem_kbyte, operatorshortnames[pr->operator], |
886 |
|
|
887 |
DEBUG("'%s' total mem amount check passed" |
DEBUG("'%s' total mem amount check passed" |
888 |
" [current total mem amount=%ldkB]\n", |
" [current total mem amount=%ldkB]\n", |
889 |
p->name, pi->total_mem_kbyte); |
s->name, pi->total_mem_kbyte); |
890 |
|
|
891 |
} |
} |
892 |
break; |
break; |
893 |
|
|
894 |
default: |
default: |
895 |
|
|
896 |
log("'%s' error: unknow resource ID: [%d]\n", p->name, pr->resource_id); |
log("'%s' error: unknow resource ID: [%d]\n", s->name, pr->resource_id); |
897 |
|
|
898 |
} |
} |
899 |
|
|
919 |
|
|
920 |
|
|
921 |
/** |
/** |
922 |
* Returns TRUE if the process timed out, otherwise FALSE. |
* Returns TRUE if the service timed out, otherwise FALSE. |
923 |
*/ |
*/ |
924 |
static int check_timeout(Process_T p) { |
static int check_timeout(Service_T s) { |
925 |
|
|
926 |
ASSERT(p); |
ASSERT(s); |
927 |
|
|
928 |
if(!p->def_timeout) { |
if(!s->def_timeout) { |
929 |
|
|
930 |
return FALSE; |
return FALSE; |
931 |
|
|
934 |
/* |
/* |
935 |
* Start counting cycles |
* Start counting cycles |
936 |
*/ |
*/ |
937 |
if(p->nstart > 0) { |
if(s->nstart > 0) { |
938 |
|
|
939 |
p->ncycle++; |
s->ncycle++; |
940 |
|
|
941 |
} |
} |
942 |
|
|
943 |
/* |
/* |
944 |
* Check timeout |
* Check timeout |
945 |
*/ |
*/ |
946 |
if(p->nstart >= p->to_start && p->ncycle <= p->to_cycle) { |
if(s->nstart >= s->to_start && s->ncycle <= s->to_cycle) { |
947 |
|
|
948 |
/* |
/* |
949 |
* Got timeout - Set do not validate flag. This statement is |
* Got timeout - Set do not validate flag. This statement is |
951 |
* thread |
* thread |
952 |
*/ |
*/ |
953 |
LOCK(Run.mutex) |
LOCK(Run.mutex) |
954 |
p->do_validate= FALSE; |
s->do_validate= FALSE; |
955 |
END_LOCK; |
END_LOCK; |
956 |
|
|
957 |
/* |
/* |
958 |
* Log and notify the user that a timeout occured |
* Log and notify the user that a timeout occured |
959 |
*/ |
*/ |
960 |
log("**Alert** process '%s' timed out and will not be checked anymore.\n", |
log("**Alert** service '%s' timed out and will not be checked anymore.\n", |
961 |
p->name); |
s->name); |
962 |
|
|
963 |
smtp_alert_timeout(p, NULL); |
smtp_alert_timeout(s, NULL); |
964 |
|
|
965 |
return TRUE; |
return TRUE; |
966 |
|
|
970 |
* Stop counting and reset if the |
* Stop counting and reset if the |
971 |
* cycle interval is passed |
* cycle interval is passed |
972 |
*/ |
*/ |
973 |
if(p->ncycle > p->to_cycle) { |
if(s->ncycle > s->to_cycle) { |
974 |
|
|
975 |
p->ncycle= 0; |
s->ncycle= 0; |
976 |
p->nstart= 0; |
s->nstart= 0; |
977 |
|
|
978 |
} |
} |
979 |
|
|
984 |
|
|
985 |
/** |
/** |
986 |
* Returns TRUE if validation should be skiped for |
* Returns TRUE if validation should be skiped for |
987 |
* this process in this cycle, otherwise FALSE |
* this service in this cycle, otherwise FALSE |
988 |
*/ |
*/ |
989 |
static int check_skip(Process_T p) { |
static int check_skip(Service_T s) { |
990 |
|
|
991 |
ASSERT(p); |
ASSERT(s); |
992 |
|
|
993 |
if(!p->def_every) { |
if(!s->def_every) { |
994 |
|
|
995 |
return FALSE; |
return FALSE; |
996 |
|
|
997 |
} |
} |
998 |
|
|
999 |
if(++p->nevery < p->every) { |
if(++s->nevery < s->every) { |
1000 |
|
|
1001 |
return TRUE; |
return TRUE; |
1002 |
|
|
1003 |
} |
} |
1004 |
|
|
1005 |
p->nevery= 0; |
s->nevery= 0; |
1006 |
|
|
1007 |
return FALSE; |
return FALSE; |
1008 |
|
|
1014 |
* programs and send an alert warning. Also make sure that the program |
* programs and send an alert warning. Also make sure that the program |
1015 |
* will not be validated, started or restarted again in this |
* will not be validated, started or restarted again in this |
1016 |
* session. Returns FALSE if the checksum is the same or not defined |
* session. Returns FALSE if the checksum is the same or not defined |
1017 |
* for this process. |
* for this service. |
1018 |
*/ |
*/ |
1019 |
static int check_checksum(Process_T p) { |
static int check_checksum(Service_T s) { |
1020 |
|
|
1021 |
Checksum_T c; |
Checksum_T c; |
1022 |
|
|
1023 |
ASSERT(p); |
ASSERT(s); |
1024 |
|
|
1025 |
if(!p->def_checksum) { |
if(!s->def_checksum) { |
1026 |
|
|
1027 |
return FALSE; |
return FALSE; |
1028 |
|
|
1029 |
} |
} |
1030 |
|
|
1031 |
for(c= p->checksumlist; c; c= c->next) { |
for(c= s->checksumlist; c; c= c->next) { |
|
|
|
|
if(! checksum_helper(p, c->file, c->md5)) { |
|
|
|
|
|
return TRUE; |
|
|
|
|
|
} |
|
1032 |
|
|
1033 |
} |
if(c->file && c->md5 && !check_md5(c->file, c->md5)) { |
|
|
|
|
DEBUG("'%s' have valid checksums\n", p->name); |
|
|
|
|
|
return FALSE; |
|
|
|
|
|
} |
|
|
|
|
1034 |
|
|
1035 |
/** |
log("'%s' CHECKSUM ERROR for %s\n", s->name, c->file); |
1036 |
* Helper function that does all the checksum work; Returns TRUE if |
smtp_alert_checksum(s, NULL); |
|
* the checksum is okay or not defined, otherwise issue a warning, do |
|
|
* alert and turn of any start/stop/restart action for the process and |
|
|
* return FALSE |
|
|
*/ |
|
|
static int checksum_helper(Process_T p, char *program, char *sum) { |
|
|
|
|
|
int rv= TRUE; |
|
|
|
|
|
ASSERT(p); |
|
|
|
|
|
if(program && sum) { |
|
|
|
|
|
if(!check_md5(program, sum)) { |
|
|
|
|
|
log("'%s' **Alert** checksum error for %s\n", p->name, program); |
|
|
|
|
|
smtp_alert_checksum(p, NULL); |
|
1037 |
|
|
1038 |
LOCK(Run.mutex) |
LOCK(Run.mutex) |
1039 |
p->do_validate= FALSE; |
s->do_validate= FALSE; |
1040 |
p->has_checksum_error= TRUE; |
s->has_checksum_error= TRUE; |
1041 |
END_LOCK; |
END_LOCK; |
1042 |
|
|
1043 |
rv= FALSE; |
return TRUE; |
1044 |
|
|
1045 |
} |
} |
1046 |
|
|
1047 |
} |
} |
1048 |
|
|
1049 |
return rv; |
DEBUG("'%s' have valid checksums\n", s->name); |
1050 |
|
|
1051 |
|
return FALSE; |
1052 |
|
|
1053 |
} |
} |
1054 |
|
|
1056 |
/** |
/** |
1057 |
* Returns TRUE if the timestamp test succeded, otherwise FALSE |
* Returns TRUE if the timestamp test succeded, otherwise FALSE |
1058 |
*/ |
*/ |
1059 |
static int check_timestamp(Process_T p, Timestamp_T t, char *report) { |
static int check_timestamp(Service_T s, Timestamp_T t, char *report) { |
1060 |
|
|
1061 |
time_t now; |
time_t now; |
1062 |
time_t timestamp; |
time_t timestamp; |
1063 |
|
|
1064 |
ASSERT(p); |
ASSERT(s); |
1065 |
ASSERT(t); |
ASSERT(t); |
1066 |
|
|
1067 |
if((int)time(&now) == -1) { |
if((int)time(&now) == -1) { |
1068 |
vlog(report, STRLEN, p, "can't get actual time"); |
vlog(report, STRLEN, s, "can't get actual time"); |
1069 |
return FALSE; |
return FALSE; |
1070 |
} |
} |
1071 |
|
|
1072 |
if(!(timestamp= get_timestamp(t->pathname, S_IFDIR|S_IFREG))) { |
if(!(timestamp= get_timestamp(t->pathname, S_IFDIR|S_IFREG))) { |
1073 |
vlog(report, STRLEN, p, "can't get timestamp for %s", t->pathname); |
vlog(report, STRLEN, s, "can't get timestamp for %s", t->pathname); |
1074 |
return FALSE; |
return FALSE; |
1075 |
} |
} |
1076 |
|
|
1077 |
if(compare_value(t->operator, (int)(now - timestamp), t->time)) { |
if(compare_value(t->operator, (int)(now - timestamp), t->time)) { |
1078 |
vlog(report, STRLEN, p, "timestamp test failed for %s", t->pathname); |
vlog(report, STRLEN, s, "timestamp test failed for %s", t->pathname); |
1079 |
return FALSE; |
return FALSE; |
1080 |
} |
} |
1081 |
|
|
1082 |
DEBUG("'%s' timestamp test passed for %s\n", p->name, t->pathname); |
DEBUG("'%s' timestamp test passed for %s\n", s->name, t->pathname); |
1083 |
|
|
1084 |
return TRUE; |
return TRUE; |
1085 |
|
|
1090 |
* Returns TRUE if the device test succeeded |
* Returns TRUE if the device test succeeded |
1091 |
* otherwise FALSE. |
* otherwise FALSE. |
1092 |
*/ |
*/ |
1093 |
static int check_device(Process_T t, Device_T td, char *report) { |
static int check_device(Service_T t, Device_T td, char *report) { |
1094 |
|
|
1095 |
ASSERT(t); |
ASSERT(t); |
1096 |
ASSERT(td); |
ASSERT(td); |
1117 |
|
|
1118 |
if(compare_value( |
if(compare_value( |
1119 |
td->operator, |
td->operator, |
1120 |
100 * (t->devinfo->f_files - t->devinfo->f_filesfree) / t->devinfo->f_files, |
100 * (t->devinfo->f_files - t->devinfo->f_filesfree) / |
1121 |
td->limit_percent)) { |
t->devinfo->f_files, td->limit_percent)) { |
1122 |
|
|
1123 |
vlog(report, STRLEN, t, |
vlog(report, STRLEN, t, |
1124 |
"inode usage %d%% matches resource limit [inode usage%s%d%%]", |
"inode usage %d%% matches resource limit [inode usage%s%d%%]", |
1125 |
100 * (t->devinfo->f_files - t->devinfo->f_filesfree) / t->devinfo->f_files, |
100 * (t->devinfo->f_files - t->devinfo->f_filesfree) / |
1126 |
|
t->devinfo->f_files, |
1127 |
operatorshortnames[td->operator], |
operatorshortnames[td->operator], |
1128 |
td->limit_percent); |
td->limit_percent); |
1129 |
|
|
1133 |
|
|
1134 |
} else { |
} else { |
1135 |
|
|
1136 |
if(compare_value(td->operator, t->devinfo->f_files - t->devinfo->f_filesfree, td->limit_absolute)) { |
if(compare_value(td->operator, t->devinfo->f_files - |
1137 |
|
t->devinfo->f_filesfree, td->limit_absolute)) { |
1138 |
|
|
1139 |
vlog(report, STRLEN, t, |
vlog(report, STRLEN, t, |
1140 |
"inode usage %d matches resource limit [inode usage%s%d]", |
"inode usage %d matches resource limit [inode usage%s%d]", |
1150 |
|
|
1151 |
DEBUG("'%s' inode usage check passed [current inode usage=%.1f%%]\n", |
DEBUG("'%s' inode usage check passed [current inode usage=%.1f%%]\n", |
1152 |
t->name, |
t->name, |
1153 |
(float) 100 * (t->devinfo->f_files - t->devinfo->f_filesfree) / t->devinfo->f_files); |
(float) 100 * (t->devinfo->f_files - t->devinfo->f_filesfree) / |
1154 |
|
t->devinfo->f_files); |
1155 |
|
|
1156 |
return TRUE; |
return TRUE; |
1157 |
|
|
1161 |
|
|
1162 |
if(compare_value( |
if(compare_value( |
1163 |
td->operator, |
td->operator, |
1164 |
100 * (t->devinfo->f_blocks - t->devinfo->f_blocksfree) / t->devinfo->f_blocks, |
100 * (t->devinfo->f_blocks - t->devinfo->f_blocksfree) / |
1165 |
td->limit_percent)) { |
t->devinfo->f_blocks, td->limit_percent)) { |
1166 |
|
|
1167 |
vlog(report, STRLEN, t, |
vlog(report, STRLEN, t, |
1168 |
"space usage %d%% matches resource limit [space usage%s%d%%]", |
"space usage %d%% matches resource limit [space usage%s%d%%]", |
1169 |
100 * (t->devinfo->f_blocks - t->devinfo->f_blocksfree) / t->devinfo->f_blocks, |
100 * (t->devinfo->f_blocks - t->devinfo->f_blocksfree) / |
1170 |
operatorshortnames[td->operator], |
t->devinfo->f_blocks, operatorshortnames[td->operator], |
1171 |
td->limit_percent); |
td->limit_percent); |
1172 |
|
|
1173 |
return FALSE; |
return FALSE; |
1174 |
|
|
1176 |
|
|
1177 |
} else { |
} else { |
1178 |
|
|
1179 |
if(compare_value(td->operator, t->devinfo->f_blocks - t->devinfo->f_blocksfree, td->limit_absolute)) { |
if(compare_value(td->operator, t->devinfo->f_blocks - |
1180 |
|
t->devinfo->f_blocksfree, td->limit_absolute)) { |
1181 |
|
|
1182 |
vlog(report, STRLEN, t, |
vlog(report, STRLEN, t, |
1183 |
"space usage %d blocks matches resource limit [space usage%s%d blocks]", |
"space usage %d blocks matches resource limit [space usage%s%d blocks]", |
1184 |
t->devinfo->f_blocks - t->devinfo->f_blocksfree, |
t->devinfo->f_blocks - t->devinfo->f_blocksfree, |
1185 |
operatorshortnames[td->operator], |
operatorshortnames[td->operator], |
1186 |
td->limit_absolute); |
td->limit_absolute); |
1193 |
|
|
1194 |
DEBUG("'%s' space usage check passed [current space usage=%.1f%%]\n", |
DEBUG("'%s' space usage check passed [current space usage=%.1f%%]\n", |
1195 |
t->name, |
t->name, |
1196 |
(float) 100 * (t->devinfo->f_blocks - t->devinfo->f_blocksfree) / t->devinfo->f_blocks); |
(float) 100 * (t->devinfo->f_blocks - t->devinfo->f_blocksfree) / |
1197 |
|
t->devinfo->f_blocks); |
1198 |
|
|
1199 |
return TRUE; |
return TRUE; |
1200 |
|
|
1221 |
/** |
/** |
1222 |
* Logging with report generation |
* Logging with report generation |
1223 |
*/ |
*/ |
1224 |
static void vlog(char * report, int n, Process_T p, char *m,...) { |
static void vlog(char * report, int n, Service_T s, char *m,...) { |
1225 |
|
|
1226 |
va_list ap; |
va_list ap; |
1227 |
char *tmp = NULL; |
char *tmp = NULL; |
1237 |
va_end(ap); |
va_end(ap); |
1238 |
|
|
1239 |
strncpy(report, tmp, n); |
strncpy(report, tmp, n); |
1240 |
log("'%s' %s\n", p->name, report); |
log("'%s' %s\n", s->name, report); |
1241 |
|
|
1242 |
free(tmp); |
free(tmp); |
1243 |
} |
} |