1 /*----------------------------------------------------------------------------*/
2 /* Xymon message daemon.                                                      */
3 /*                                                                            */
4 /* Client backend module for MQ collector                                     */
5 /*                                                                            */
6 /* Copyright (C) 2009-2011 Henrik Storner <henrik@hswn.dk>                    */
7 /*                                                                            */
8 /* This program is released under the GNU General Public License (GPL),       */
9 /* version 2. See the file "COPYING" for details.                             */
10 /*                                                                            */
11 /*----------------------------------------------------------------------------*/
12 
13 static char mqcollect_rcsid[] = "$Id: mqcollect.c 7060 2012-07-14 16:32:11Z storner $";
14 
mqcollect_flush_status(int color,char * fromline,time_t timestamp,char * hostname,char * qmid,strbuffer_t * redsummary,strbuffer_t * yellowsummary,strbuffer_t * greensummary,char * clienttext)15 void mqcollect_flush_status(int color, char *fromline, time_t timestamp,
16 			    char *hostname, char *qmid,
17 			    strbuffer_t *redsummary, strbuffer_t *yellowsummary, strbuffer_t *greensummary,
18 			    char *clienttext)
19 {
20 	char *groups;
21 	char msgline[1024];
22 
23 	/* Generate the status message */
24 	groups = getalertgroups();
25 	init_status(color);
26 	if (groups) sprintf(msgline, "status/group:%s ", groups); else strcpy(msgline, "status ");
27 	addtostatus(msgline);
28 	sprintf(msgline, "%s.mq %s %s\n",
29 		hostname,
30 		colorname(color), ctime(&timestamp));
31 	addtostatus(msgline);
32 	if (STRBUFLEN(redsummary) > 0) {
33 		addtostrstatus(redsummary);
34 		addtostatus("\n");
35 	}
36 	if (STRBUFLEN(yellowsummary) > 0) {
37 		addtostrstatus(yellowsummary);
38 		addtostatus("\n");
39 	}
40 	if (STRBUFLEN(greensummary) > 0) {
41 		addtostrstatus(greensummary);
42 		addtostatus("\n");
43 	}
44 	addtostatus(clienttext);
45 	addtostatus("\n");
46 	addtostatus(fromline);
47 	finish_status();
48 }
49 
handle_mqcollect_client(char * hostname,char * clienttype,enum ostype_t os,void * hinfo,char * sender,time_t timestamp,char * clientdata)50 void handle_mqcollect_client(char *hostname, char *clienttype, enum ostype_t os,
51 				void *hinfo, char *sender, time_t timestamp,
52 				char *clientdata)
53 {
54 	char *qmline = "Starting MQSC for queue manager ";
55 	strbuffer_t *redsummary = newstrbuffer(0);
56 	strbuffer_t *yellowsummary = newstrbuffer(0);
57 	strbuffer_t *greensummary = newstrbuffer(0);
58 	char *bol, *eoln, *clienttext;
59 	int color = COL_GREEN;
60 	char fromline[1024], msgline[1024];
61 	char *qmid = NULL, *qnam = NULL; int qlen = -1, qage = -1; char *chnnam = NULL, *chnstatus = NULL;
62 	enum { PARSING_QL, PARSING_QS, PARSING_CHS, PARSER_FLOAT } pstate = PARSER_FLOAT;
63 	int lastline = 0;
64 
65 	sprintf(fromline, "\nStatus message received from %s\n", sender);
66 
67 	bol = strchr(clientdata, '\n'); if (bol) bol++; clienttext = bol;
68 	while (bol) {
69 		eoln = strchr(bol, '\n'); if (eoln) *eoln = '\0'; else lastline = 1;
70 		bol += strspn(bol, " \t");
71 
72 		if (strncmp(bol, qmline, strlen(qmline)) == 0) {
73 			char *p;
74 
75 			if (qmid) xfree(qmid);
76 			qmid = strdup(bol+strlen(qmline));
77 			p = strrchr(qmid, '.'); if (p) *p = '\0';
78 		}
79 
80 		else if ( (strncmp(bol, "AMQ8409:", 8) == 0) ||		/* "ql" command - Queue details, incl. depth */
81 		          (strncmp(bol, "AMQ8450:", 8) == 0) ||		/* "qs" command - Queue status */
82 		          (strncmp(bol, "AMQ8417:", 8) == 0) ||		/* "chs" command - Channel status */
83 			  lastline                              ) {
84 
85 			if ( ((pstate == PARSING_QL) || (pstate == PARSING_QS)) && qmid && qnam && (qlen >= 0)) {
86 				/* Got a full queue depth status */
87 				int warnlen, critlen, warnage, critage;
88 				char *trackid;
89 				get_mqqueue_thresholds(hinfo, clienttype, qmid, qnam, &warnlen, &critlen, &warnage, &critage, &trackid);
90 
91 				if ((critlen != -1) && (qlen >= critlen)) {
92 					color = COL_RED;
93 					sprintf(msgline, "&red Queue %s:%s has depth %d (critical: %d, warn: %d)\n",
94 						qmid, qnam, qlen, critlen, warnlen);
95 					addtobuffer(redsummary, msgline);
96 				}
97 				else if ((warnlen != -1) && (qlen >= warnlen)) {
98 					if (color < COL_YELLOW) color = COL_YELLOW;
99 					sprintf(msgline, "&yellow Queue %s:%s has depth %d (warn: %d, critical: %d)\n",
100 						qmid, qnam, qlen, warnlen, critlen);
101 					addtobuffer(yellowsummary, msgline);
102 				}
103 				else if ((warnlen != -1) || (critlen != -1)) {
104 					sprintf(msgline, "&green Queue %s:%s has depth %d (warn: %d, critical: %d)\n",
105 						qmid, qnam, qlen, warnlen, critlen);
106 					addtobuffer(greensummary, msgline);
107 				}
108 
109 				if ((pstate == PARSING_QS) && (qage >= 0)) {
110 					if ((critage != -1) && (qage >= critage)) {
111 						color = COL_RED;
112 						sprintf(msgline, "&red Queue %s:%s has age %d (critical: %d, warn: %d)\n",
113 								qmid, qnam, qage, critage, warnage);
114 						addtobuffer(redsummary, msgline);
115 					}
116 					else if ((warnage != -1) && (qage >= warnage)) {
117 						if (color < COL_YELLOW) color = COL_YELLOW;
118 						sprintf(msgline, "&yellow Queue %s:%s has age %d (warn: %d, critical: %d)\n",
119 								qmid, qnam, qage, warnage, critage);
120 						addtobuffer(yellowsummary, msgline);
121 					}
122 					else if ((warnage != -1) || (critage != -1)) {
123 						sprintf(msgline, "&green Queue %s:%s has age %d (warn: %d, critical: %d)\n",
124 								qmid, qnam, qage, warnage, critage);
125 						addtobuffer(greensummary, msgline);
126 					}
127 				}
128 
129 				if (trackid) {
130 					/* FIXME: Send "data" message for creating queue-length RRD */
131 				}
132 
133 				pstate = PARSER_FLOAT;
134 			}
135 
136 			if ((pstate == PARSING_CHS) && qmid && chnnam && chnstatus) {
137 				/* Got a full channel status */
138 				int chncolor;
139 
140 				if (get_mqchannel_params(hinfo, clienttype, qmid, chnnam, chnstatus, &chncolor)) {
141 					if (chncolor > color) color = chncolor;
142 					switch (chncolor) {
143 						case COL_RED:
144 							sprintf(msgline, "&red Channel %s:%s has status %s\n", qmid, chnnam, chnstatus);
145 							addtobuffer(redsummary, msgline);
146 							break;
147 						case COL_YELLOW:
148 							sprintf(msgline, "&yellow Channel %s:%s has status %s\n", qmid, chnnam, chnstatus);
149 							addtobuffer(yellowsummary, msgline);
150 							break;
151 						case COL_GREEN:
152 							sprintf(msgline, "&green Channel %s:%s has status %s\n", qmid, chnnam, chnstatus);
153 							addtobuffer(greensummary, msgline);
154 							break;
155 					}
156 				}
157 
158 				pstate = PARSER_FLOAT;
159 			}
160 
161 			if (qnam) xfree(qnam);
162 			qlen = qage = -1;
163 			if (chnnam) xfree(chnnam);
164 			if (chnstatus) xfree(chnstatus);
165 
166 			if (strncmp(bol, "AMQ8409:", 8) == 0) pstate = PARSING_QL;
167 			else if (strncmp(bol, "AMQ8450:", 8) == 0) pstate = PARSING_QS;
168 			else if (strncmp(bol, "AMQ8417:", 8) == 0) pstate = PARSING_CHS;
169 			else pstate = PARSER_FLOAT;
170 		}
171 		else if ((pstate == PARSING_QL) || (pstate == PARSING_QS)) {
172 			char *bdup = strdup(bol);
173 			char *tok = strtok(bdup, " \t");
174 			while (tok) {
175 				if (strncmp(tok, "QUEUE(", 6) == 0) {
176 					char *p;
177 
178 					qnam = strdup(tok+6);
179 					p = strchr(qnam, ')');
180 					if (p) *p = '\0';
181 				}
182 				else if (strncmp(tok, "CURDEPTH(", 9) == 0) {
183 					qlen = atoi(tok+9);
184 				}
185 				else if (strncmp(tok, "MSGAGE(", 7) == 0) {
186 					if (isdigit(*(tok+7))) qage = atoi(tok+7);
187 				}
188 
189 				tok = strtok(NULL, " \t");
190 			}
191 
192 			xfree(bdup);
193 		}
194 		else if (pstate == PARSING_CHS) {
195 			char *bdup = strdup(bol);
196 			char *tok = strtok(bdup, " \t");
197 			while (tok) {
198 				if (strncmp(tok, "CHANNEL(", 8) == 0) {
199 					char *p;
200 
201 					chnnam = strdup(tok+8);
202 					p = strchr(chnnam, ')');
203 					if (p) *p = '\0';
204 				}
205 				else if (strncmp(tok, "STATUS(", 7) == 0) {
206 					char *p;
207 
208 					chnstatus = strdup(tok+7);
209 					p = strchr(chnstatus, ')');
210 					if (p) *p = '\0';
211 				}
212 
213 				tok = strtok(NULL, " \t");
214 			}
215 			xfree(bdup);
216 		}
217 
218 		if (eoln) {
219 			*eoln = '\n';
220 			bol = eoln+1;
221 		}
222 		else
223 			bol = NULL;
224 	}
225 
226 	mqcollect_flush_status(color, fromline, timestamp,
227 			       hostname, qmid,
228 			       redsummary, yellowsummary, greensummary,
229 			       clienttext);
230 
231 	if (qmid) xfree(qmid);
232 	freestrbuffer(greensummary);
233 	freestrbuffer(yellowsummary);
234 	freestrbuffer(redsummary);
235 }
236 
237