1 /*----------------------------------------------------------------------------*/
2 /* Xymon message daemon. */
3 /* */
4 /* Client backend module for z/VM */
5 /* */
6 /* Copyright (C) 2005-2011 Henrik Storner <henrik@hswn.dk> */
7 /* Copyright (C) 2006-2008 Rich Smrcina */
8 /* */
9 /* This program is released under the GNU General Public License (GPL), */
10 /* version 2. See the file "COPYING" for details. */
11 /* */
12 /*----------------------------------------------------------------------------*/
13
14 static char zvm_rcsid[] = "$Id: zvm.c 7608 2015-03-21 15:00:40Z jccleaver $";
15
zvm_cpu_report(char * hostname,char * clientclass,enum ostype_t os,void * hinfo,char * fromline,char * timestr,char * cpuutilstr,char * uptimestr)16 static void zvm_cpu_report(char *hostname, char *clientclass, enum ostype_t os,
17 void *hinfo, char *fromline, char *timestr,
18 char *cpuutilstr, char *uptimestr)
19 {
20 char *p;
21 float load1, loadyellow, loadred;
22 int recentlimit, ancientlimit, uptimecolor, maxclockdiff, clockdiffcolor;
23 int uphour, upmin;
24 char loadresult[100];
25 char myupstr[100];
26 long uptimesecs = -1;
27 long upday;
28
29 int cpucolor = COL_GREEN;
30
31 char msgline[1024];
32 strbuffer_t *upmsg;
33
34 if (!want_msgtype(hinfo, MSG_CPU)) return;
35
36 if (!cpuutilstr) return;
37 if (!uptimestr) return;
38
39 uptimesecs = 0;
40
41 /*
42 * z/VM: "Uptime: 1 Days, 13 Hours, 38 Minutes"
43 */
44
45 sscanf(uptimestr,"Uptime: %ld Days, %d Hours, %d Minutes", &upday, &uphour, &upmin);
46 uptimesecs = upday * 86400;
47 uptimesecs += 60*(60*uphour + upmin);
48 sprintf(myupstr, "%s\n", uptimestr);
49
50 /*
51 * Looking for average CPU Utilization in 'IND' command response
52 * AVGPROC-000%
53 */
54 *loadresult = '\0';
55 p = strstr(cpuutilstr, "AVGPROC-") + 8 ;
56 if (p) {
57 if (sscanf(p, "%f%%", &load1) == 1) {
58 sprintf(loadresult, "z/VM CPU Utilization %3.0f%%\n", load1);
59 }
60 }
61
62 get_cpu_thresholds(hinfo, clientclass, &loadyellow, &loadred, &recentlimit, &ancientlimit, &uptimecolor, &maxclockdiff, &clockdiffcolor);
63
64 upmsg = newstrbuffer(0);
65
66 if (load1 > loadred) {
67 cpucolor = COL_RED;
68 addtobuffer(upmsg, "&red Load is CRITICAL\n");
69 }
70 else if (load1 > loadyellow) {
71 cpucolor = COL_YELLOW;
72 addtobuffer(upmsg, "&yellow Load is HIGH\n");
73 }
74
75 if ((uptimesecs != -1) && (recentlimit != -1) && (uptimesecs < recentlimit)) {
76 if (cpucolor != COL_RED) cpucolor = uptimecolor;
77 sprintf(msgline, "&%s Machine recently rebooted\n", colorname(uptimecolor));
78 addtobuffer(upmsg, msgline);
79 }
80 if ((uptimesecs != -1) && (ancientlimit != -1) && (uptimesecs > ancientlimit)) {
81 if (cpucolor != COL_RED) cpucolor = uptimecolor;
82 sprintf(msgline, "&%s Machine has been up more than %d days\n", colorname(uptimecolor), (ancientlimit / 86400));
83 addtobuffer(upmsg, msgline);
84 }
85
86 init_status(cpucolor);
87 sprintf(msgline, "status %s.cpu %s %s %s %s %s\n",
88 commafy(hostname), colorname(cpucolor),
89 (timestr ? timestr : "<no timestamp data>"),
90 loadresult,
91 myupstr,
92 cpuutilstr);
93 addtostatus(msgline);
94 if (STRBUFLEN(upmsg)) {
95 addtostrstatus(upmsg);
96 addtostatus("\n");
97 }
98
99 if (fromline && !localmode) addtostatus(fromline);
100 finish_status();
101
102 freestrbuffer(upmsg);
103 }
104
zvm_paging_report(char * hostname,char * clientclass,enum ostype_t os,void * hinfo,char * fromline,char * timestr,char * cpuutilstr)105 static void zvm_paging_report(char *hostname, char *clientclass, enum ostype_t os,
106 void *hinfo, char *fromline, char *timestr, char *cpuutilstr)
107 {
108 char *p;
109 int pagerate, pagingyellow, pagingred;
110 char pagingresult[100];
111
112 int pagingcolor = COL_GREEN;
113 char msgline[256];
114 strbuffer_t *upmsg;
115
116 if (!cpuutilstr) return;
117 /*
118 * Looking for Paging rate info in 'IND' command response
119 * PAGING-0000/SEC
120 */
121 *pagingresult = '\0';
122 /* Skip past three newlines in message to the PAGING text */
123 p=strstr(cpuutilstr,"PAGING-") + 7;
124 if (sscanf(p, "%d/SEC", &pagerate) == 1) {
125 sprintf(pagingresult, "z/VM Paging Rate %d per second\n", pagerate);
126 }
127
128 get_paging_thresholds(hinfo, clientclass, &pagingyellow, &pagingred);
129
130 upmsg = newstrbuffer(0);
131
132 if (pagerate > pagingred) {
133 pagingcolor = COL_RED;
134 addtobuffer(upmsg, "&red Paging Rate is CRITICAL\n");
135 }
136 else if (pagerate > pagingyellow) {
137 pagingcolor = COL_YELLOW;
138 addtobuffer(upmsg, "&yellow Paging Rate is HIGH\n");
139 }
140
141 init_status(pagingcolor);
142 sprintf(msgline, "status %s.paging %s %s %s %s\n",
143 commafy(hostname), colorname(pagingcolor),
144 (timestr ? timestr : "<no timestamp data>"),
145 pagingresult,
146 cpuutilstr);
147 addtostatus(msgline);
148 if (STRBUFLEN(upmsg)) {
149 addtostrstatus(upmsg);
150 addtostatus("\n");
151 }
152
153 if (fromline && !localmode) addtostatus(fromline);
154 finish_status();
155
156 freestrbuffer(upmsg);
157 }
158
zvm_mdc_report(char * hostname,char * clientclass,enum ostype_t os,void * hinfo,char * fromline,char * timestr,char * cpuutilstr)159 static void zvm_mdc_report(char *hostname, char *clientclass, enum ostype_t os,
160 void *hinfo, char *fromline, char *timestr, char *cpuutilstr)
161 {
162 char *p;
163 int mdcreads, mdcwrites, mdchitpct;
164 char mdcresult[100];
165
166 char msgline[256];
167 strbuffer_t *msg;
168
169 if (!cpuutilstr) return;
170 msg = newstrbuffer(0);
171
172 /*
173 * Looking for MDC info in 'IND' command response
174 * MDC READS-000001/SEC WRITES-000001/SEC HIT RATIO-098%
175 */
176 *mdcresult = '\0';
177 /* Skip past three newlines in message to the PAGING text */
178 p=strstr(cpuutilstr,"READS-");
179 if (p) {
180 p += 6;
181 sscanf(p, "%d/SEC", &mdcreads);
182 p=strstr(cpuutilstr,"WRITES-") + 7;
183 sscanf(p, "%d/SEC", &mdcwrites);
184 p=strstr(cpuutilstr,"RATIO-") + 6;
185 sscanf(p, "%d", &mdchitpct);
186
187 sprintf(msgline, "data %s.mdc\n%s\n%d:%d:%d\n", commafy(hostname), osname(os), mdcreads, mdcwrites, mdchitpct);
188 addtobuffer(msg, msgline);
189 combo_add(msg);
190 }
191
192 freestrbuffer(msg);
193 }
194
zvm_users_report(char * hostname,char * clientclass,enum ostype_t os,void * hinfo,char * fromline,char * timestr,char * psstr)195 static void zvm_users_report(char *hostname, char *clientclass, enum ostype_t os,
196 void *hinfo, char *fromline, char *timestr,
197 char *psstr)
198 {
199 int pscolor = COL_GREEN;
200
201 int pchecks;
202 int cmdofs = -1;
203 char msgline[4096];
204 strbuffer_t *monmsg;
205 static strbuffer_t *countdata = NULL;
206 int anycountdata = 0;
207 char *group;
208
209 if (!want_msgtype(hinfo, MSG_PROCS)) return;
210 if (!psstr) return;
211
212 if (!countdata) countdata = newstrbuffer(0);
213
214 clearalertgroups();
215 monmsg = newstrbuffer(0);
216
217 sprintf(msgline, "data %s.proccounts\n", commafy(hostname));
218 addtobuffer(countdata, msgline);
219
220 cmdofs = 0; /* Command offset for z/VM isn't necessary */
221
222 pchecks = clear_process_counts(hinfo, clientclass);
223
224 if (pchecks == 0) {
225 /* Nothing to check */
226 sprintf(msgline, "&%s No process checks defined\n", colorname(noreportcolor));
227 addtobuffer(monmsg, msgline);
228 pscolor = noreportcolor;
229 }
230 else if (cmdofs >= 0) {
231 /* Count how many instances of each monitored process is running */
232 char *pname, *pid, *bol, *nl;
233 int pcount, pmin, pmax, pcolor, ptrack;
234
235 bol = psstr;
236 while (bol) {
237 nl = strchr(bol, '\n');
238
239 /* Take care - the ps output line may be shorter than what we look at */
240 if (nl) {
241 *nl = '\0';
242
243 if ((nl-bol) > cmdofs) add_process_count(bol+cmdofs);
244
245 *nl = '\n';
246 bol = nl+1;
247 }
248 else {
249 if (strlen(bol) > cmdofs) add_process_count(bol+cmdofs);
250
251 bol = NULL;
252 }
253 }
254
255 /* Check the number found for each monitored process */
256 while ((pname = check_process_count(&pcount, &pmin, &pmax, &pcolor, &pid, &ptrack, &group)) != NULL) {
257 char limtxt[1024];
258
259 if (pmax == -1) {
260 if (pmin > 0) sprintf(limtxt, "%d or more", pmin);
261 else if (pmin == 0) sprintf(limtxt, "none");
262 }
263 else {
264 if (pmin > 0) sprintf(limtxt, "between %d and %d", pmin, pmax);
265 else if (pmin == 0) sprintf(limtxt, "at most %d", pmax);
266 }
267
268 if (pcolor == COL_GREEN) {
269 sprintf(msgline, "&green %s (found %d, req. %s)\n", pname, pcount, limtxt);
270 addtobuffer(monmsg, msgline);
271 }
272 else {
273 if (pcolor > pscolor) pscolor = pcolor;
274 sprintf(msgline, "&%s %s (found %d, req. %s)\n",
275 colorname(pcolor), pname, pcount, limtxt);
276 addtobuffer(monmsg, msgline);
277 addalertgroup(group);
278 }
279
280 if (ptrack) {
281 /* Save the count data for later DATA message to track process counts */
282 if (!pid) pid = "default";
283 sprintf(msgline, "%s:%u\n", pid, pcount);
284 addtobuffer(countdata, msgline);
285 anycountdata = 1;
286 }
287 }
288 }
289 else {
290 pscolor = COL_YELLOW;
291 sprintf(msgline, "&yellow Expected string not found in ps output header\n");
292 addtobuffer(monmsg, msgline);
293 }
294
295 /* Now we know the result, so generate a status message */
296 init_status(pscolor);
297
298 group = getalertgroups();
299 if (group) sprintf(msgline, "status/group:%s ", group); else strcpy(msgline, "status ");
300 addtostatus(msgline);
301
302 sprintf(msgline, "%s.procs %s %s - Processes %s\n",
303 commafy(hostname), colorname(pscolor),
304 (timestr ? timestr : "<No timestamp data>"),
305 ((pscolor == COL_GREEN) ? "OK" : "NOT ok"));
306 addtostatus(msgline);
307
308 /* And add the info about what's wrong */
309 if (STRBUFLEN(monmsg)) {
310 addtostrstatus(monmsg);
311 addtostatus("\n");
312 }
313
314 /* And the full virtual machine names output for those who want it */
315 if (pslistinprocs) {
316 /*
317 * Format the list of virtual machines into four per line,
318 * this list could be fairly long.
319 */
320 char *tmpstr, *tok, *nm[4];
321 int nmidx = 0;
322
323 /* Make a copy of psstr, strtok() will be changing it */
324 tmpstr = strdup(psstr);
325
326 /* Use strtok() to split string into pieces delimited by newline */
327 tok = strtok(tmpstr, "\n");
328
329 while (tok) {
330 nm[nmidx++] = tok;
331
332 if (nmidx == 4) {
333 sprintf(msgline, "%-8s %-8s %-8s %-8s\n", nm[0], nm[1], nm[2], nm[3]);
334 addtostatus(msgline);
335 nmidx = 0;
336 nm[0] = nm[1] = nm[2] = nm[3] = " ";
337 }
338 tok = strtok(NULL, "\n");
339 }
340 /* Print any remaining names */
341 if (nmidx > 0) {
342 sprintf(msgline, "%-8s %-8s %-8s %-8s\n", nm[0], nm[1], nm[2], nm[3]);
343 addtostatus(msgline);
344 }
345
346 free(tmpstr);
347 }
348
349 if (fromline && !localmode) addtostatus(fromline);
350 finish_status();
351
352 freestrbuffer(monmsg);
353
354 if (anycountdata) combo_add(countdata);
355 clearstrbuffer(countdata);
356 }
357
358
handle_zvm_client(char * hostname,char * clienttype,enum ostype_t os,void * hinfo,char * sender,time_t timestamp,char * clientdata)359 void handle_zvm_client(char *hostname, char *clienttype, enum ostype_t os,
360 void *hinfo, char *sender, time_t timestamp,
361 char *clientdata)
362 {
363 char *timestr;
364 char *cpuutilstr;
365 char *uptimestr;
366 char *dfstr;
367 char *usersstr; /* Logged on z/VM Users */
368 char *msgsstr;
369 char *ifstatstr;
370 char *portsstr;
371
372 char fromline[1024];
373
374 sprintf(fromline, "\nStatus message received from %s\n", sender);
375
376 splitmsg(clientdata);
377
378 timestr = getdata("date");
379 uptimestr = getdata("uptime");
380 cpuutilstr = getdata("cpu");
381 dfstr = getdata("df");
382 usersstr = getdata("UserID");
383 msgsstr = getdata("msgs");
384 portsstr = getdata("ports");
385 ifstatstr = getdata("ifstat");
386
387 zvm_cpu_report(hostname, clienttype, os, hinfo, fromline, timestr, cpuutilstr, uptimestr);
388 zvm_paging_report(hostname, clienttype, os, hinfo, fromline, timestr, cpuutilstr);
389 zvm_mdc_report(hostname, clienttype, os, hinfo, fromline, timestr, cpuutilstr);
390 zvm_users_report(hostname, clienttype, os, hinfo, fromline, timestr, usersstr);
391 unix_disk_report(hostname, clienttype, os, hinfo, fromline, timestr, "Available", "Capacity", "Mounted", dfstr);
392 unix_ports_report(hostname, clienttype, os, hinfo, fromline, timestr, 3, 4, 5, portsstr);
393 unix_ifstat_report(hostname, clienttype, os, hinfo, fromline, timestr, ifstatstr);
394 msgs_report(hostname, clienttype, os, hinfo, fromline, timestr, msgsstr);
395 file_report(hostname, clienttype, os, hinfo, fromline, timestr);
396 linecount_report(hostname, clienttype, os, hinfo, fromline, timestr);
397 deltacount_report(hostname, clienttype, os, hinfo, fromline, timestr);
398
399
400 splitmsg_done();
401 }
402