Code

Fix for regex input of '|', being output causing problems with Nagios' parsing of
[nagiosplug.git] / contrib / check_cpqarray.c
1 /*
2    check_cpqarray, an extension for Netsaint / Nagios to check the
3    status of a Compaq SmartArray controller from the commandline.
4    Copyright (C) 2003  Guenther Mair
6    based on the work and using main parts of
8    CpqArray Deamon, a program to monitor and remotely configure a 
9    SmartArray controller.
10    Copyright (C) 1999  Hugo Trippaers
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
27 #include <unistd.h>
28 #include <sys/ioctl.h>
29 #include <sys/utsname.h>
30 #include <stdio.h>
31 #include <fcntl.h>
32 #include <string.h>
33 #include <errno.h>
35 #include "/usr/src/linux/drivers/block/ida_ioctl.h"
36 #include "/usr/src/linux/drivers/block/ida_cmd.h"
37 #include "/usr/src/linux/drivers/block/cpqarray.h"
40 const char *controllers[] =
41 {
42   "/dev/ida/c0d0",
43   "/dev/ida/c1d0",
44   "/dev/ida/c2d0",
45   "/dev/ida/c3d0",
46   "/dev/ida/c4d0",
47   "/dev/ida/c5d0",
48   "/dev/ida/c6d0",
49   "/dev/ida/c7d0"
50 };
52 const char *statusstr[] = {
53         "Logical drive /dev/ida/c%dd%d: OK\n",
54         "Logical drive /dev/ida/c%dd%d: FAILED\n",
55         "Logical drive /dev/ida/c%dd%d: not configured.\n",
56         "Logical drive /dev/ida/c%dd%d: using interim recovery mode, %3.2f%% done.\n",
57         "Logical drive /dev/ida/c%dd%d: ready for recovery operation.\n",
58         "Logical drive /dev/ida/c%dd%d: is currently recovering, %3.2f%% done.\n",
59         "Wrong physical drive was replaced.\n",
60         "A physical drive is not properly connected.\n",
61         "Hardware is overheating.\n",
62         "Hardware has overheated.\n",
63         "Logical drive /dev/ida/c%dd%d: currently expanding, %3.2f%% done.\n",
64         "Logical drive /dev/ida/c%dd%d: not yet available.\n",
65         "Logical drive /dev/ida/c%dd%d: queued for expansion.\n",
66 };
68 extern char *optarg;
69 extern int optind, opterr, optopt;
71 int ctrls_found_num;
72 int exit_code = 0;
73 struct controller ctrls_found[8];
75 #define DEBUG(x)  fprintf(stderr, x)
77 struct opts 
78 {
79   char debug;
80 };
82 struct slog_disk
83 {
84   int status;
85   float pvalue;
86 };
88 struct controller 
89 {
90   char ctrl_devicename[20];
91   int num_logd_found;
92   struct slog_disk log_disk[16];
93 };
97 int status_check (struct opts opts) 
98 {
99   int devicefd;
100   int ctrl_cntr;
101   int logd_cntr;
102   ida_ioctl_t io, io2;
103   int status, nr_blks, blks_tr;
104   float pvalue;
105   int counter;
106     
107   for ( ctrl_cntr=0;
108         ctrl_cntr <  ctrls_found_num;
109         ctrl_cntr++) {
110     
111     devicefd = open (controllers[ctrl_cntr], O_RDONLY);
112     
113     for ( logd_cntr=0;
114           logd_cntr < ctrls_found[ctrl_cntr].num_logd_found;
115           logd_cntr++) {
116       
117         memset (&io, 0, sizeof (io));
119         io.cmd = SENSE_LOG_DRV_STAT;
120         io.unit = logd_cntr  | UNITVALID;
121         
122         if (ioctl (devicefd, IDAPASSTHRU, &io) < 0)
123           {
124             perror ("SENSE_LOG_DRV_STAT ioctl");
125             return 0;
126           }
128         status=io.c.sense_log_drv_stat.status;
129         
130         if ((status == 3) || (status == 5) || (status == 7)) {
131           /* is a progress indicator required?
132            */
133           memset (&io2, 0, sizeof (io));
134           
135           io2.cmd = ID_LOG_DRV;
136           io2.unit = logd_cntr  | UNITVALID;
137           
138           if (ioctl (devicefd, IDAPASSTHRU, &io2) < 0)
139             {
140               perror ("ID_LOG_DRV ioctl");
141               /* return 0;   no return this isn't fatal for now */
142             }
143           else 
144             {
145               nr_blks = io2.c.id_log_drv.nr_blks;
146               blks_tr = io.c.sense_log_drv_stat.blks_to_recover;
147                   
148               pvalue = ((float)(nr_blks - blks_tr)/(float)nr_blks) * 100;
149             }
150         }
151         else {
152           pvalue = 0.0;
153         }
155         if (opts.debug) {
156           fprintf(stdout, "DEBUG: Status of controller %d unit %d is %d\n", 
157                   ctrl_cntr, logd_cntr, status);
158           fprintf(stdout, "DEBUG: ");
159           fprintf(stdout, statusstr[status], 
160                   ctrl_cntr, logd_cntr, pvalue);
161           fprintf(stdout, "\n");
162         }
163         
164         printf(statusstr[status], ctrl_cntr, logd_cntr, pvalue);
166         switch(status)
167           {
168           case 1:
169           case 2:
170           case 6:
171           case 7:
172           case 9:
173             /* CRITICAL */
174             exit_code = 2;
175             break;
176           case 3:
177           case 4:
178           case 5:
179           case 8:
180           case 10:
181           case 11:
182           case 12:
183             /* WARNING (only if not yet at CRITICAL LEVEL) */
184             if (exit_code < 2) exit_code = 1;
185             break;
186           case 0:
187           default:
188             /* do nothing */
189             break;
190           }
192         ctrls_found[ctrl_cntr].log_disk[logd_cntr].pvalue = pvalue;
193         ctrls_found[ctrl_cntr].log_disk[logd_cntr].status = status;
194     }
195     close (devicefd);
196   }
198   return 1;
201 int discover_controllers (struct opts opts)
203   int cntr;
204   int foundone = 0;
206   for (cntr = 0; cntr < 8; cntr++)
207     {
208       /* does this device exist ? */
209       if ((access (controllers[cntr], R_OK | F_OK)) == 0)
210         {
211           /* it does :) */
212           if (interrogate_controller (opts, cntr))
213             {
214               foundone = 1;
215               if (opts.debug) 
216                 fprintf (stderr, "DEBUG: %s is a existing controller\n",
217                          controllers[cntr]);
218             }
219         }
220       else if (opts.debug)
221         {
222           fprintf (stderr, "DEBUG: Device %s could not be opened\n", controllers[cntr]);
223           perror ("DEBUG: reason");
224         }
225     }
226    return foundone;
229 void boardid2str (unsigned long board_id, char *name)
231   switch (board_id)
232     {
233     case 0x0040110E:            /* IDA */
234       strcpy (name, "Compaq IDA");
235       break;
236     case 0x0140110E:            /* IDA-2 */
237       strcpy (name, "Compaq IDA-2");
238       break;
239     case 0x1040110E:            /* IAES */
240       strcpy (name, "Compaq IAES");
241       break;
242     case 0x2040110E:            /* SMART */
243       strcpy (name, "Compaq SMART");
244       break;
245     case 0x3040110E:            /* SMART-2/E */
246       strcpy (name, "Compaq SMART-2/E");
247       break;
248     case 0x40300E11:            /* SMART-2/P or SMART-2DH */
249       strcpy (name, "Compaq SMART-2/P (2DH)");
250       break;
251     case 0x40310E11:            /* SMART-2SL */
252       strcpy (name, "Compaq SMART-2SL");
253       break;
254     case 0x40320E11:            /* SMART-3200 */
255       strcpy (name, "Compaq SMART-3200");
256       break;
257     case 0x40330E11:            /* SMART-3100ES */
258       strcpy (name, "Compaq SMART-3100ES");
259       break;
260     case 0x40340E11:            /* SMART-221 */
261       strcpy (name, "Compaq SMART-221");
262       break;
263     case 0x40400E11:            /* Integrated Array */
264       strcpy (name, "Compaq Integrated Array");
265       break;
266     case 0x40500E11:            /* Smart Array 4200 */
267       strcpy (name, "Compaq Smart Array 4200");
268       break;
269     case 0x40510E11:            /* Smart Array 4250ES */
270       strcpy (name, "Compaq Smart Array 4250ES");
271       break;
272     case 0x40580E11:            /* Smart Array 431 */
273       strcpy (name, "Compaq Smart Array 431");
274       break;
275     default:
276       /*
277        * Well, its a SMART-2 or better, don't know which
278        * kind.
279        */
280       strcpy (name, "Unknown Controller Type");
281     }
284 int interrogate_controller (struct opts opts, int contrnum)
286   int devicefd;
287   ida_ioctl_t io;
288   char buffer[30];
289   int foundone = 0;
290   int cntr;
291  
292   devicefd = open (controllers[contrnum], O_RDONLY);
293   /* no checks, did that before */
295   /* clear io */
296   memset (&io, 0, sizeof (io));
298   io.cmd = ID_CTLR;
300   if (ioctl (devicefd, IDAPASSTHRU, &io) < 0)
301     {
302       if (opts.debug) perror ("DEBUG: ioctl");
303       return 0;
304     }
306   boardid2str (io.c.id_ctlr.board_id, buffer);
308   strncpy (ctrls_found[ctrls_found_num].ctrl_devicename, 
309            buffer, 20);
311   ctrls_found[ctrls_found_num].num_logd_found = 0;
313   for (cntr = 0; cntr < io.c.id_ctlr.nr_drvs; cntr++)
314     {
315       if (interrogate_logical (opts, devicefd, cntr))
316         {
317           /* logical drive found, this could be used later one */
318           foundone = 1;
319         }
320     }
322   switch (ctrls_found[ctrls_found_num].num_logd_found)
323     {
324     case 0:
325       printf("Found a %s with no logical drives.\n", buffer);
326       break;
327     case 1:
328       printf("Found a %s with one Logical drive.\n", buffer,
329         ctrls_found[ctrls_found_num].num_logd_found);
330       break;
331     default:
332       printf("Found a %s with %d Logical drives.\n", buffer,
333         ctrls_found[ctrls_found_num].num_logd_found);
334       break;
335     }
337   ctrls_found_num++;
339   close (devicefd);
340   return 1;
343 int interrogate_logical (struct opts opts, int devicefd, int unit_nr)
345   ida_ioctl_t io;
346   ida_ioctl_t io2;
347   int nr_blks, blks_tr;
349   if (opts.debug) printf ("DEBUG: interrogating unit %d\n", unit_nr);
351   memset (&io, 0, sizeof (io));
353   io.cmd = ID_LOG_DRV;
354   io.unit = unit_nr | UNITVALID;
356   if (ioctl (devicefd, IDAPASSTHRU, &io) < 0)
357     {
358       perror ("FATAL: ID_LOG_DRV ioctl");
359       return 0;
360     }
362   memset (&io2, 0, sizeof (io2));
364   io2.cmd = SENSE_LOG_DRV_STAT;
365   io2.unit = unit_nr | UNITVALID;
367   if (ioctl (devicefd, IDAPASSTHRU, &io2) < 0)
368     {
369       perror ("FATAL: SENSE_LOG_DRV_STAT ioctl");
370       return 0;
371     }
372   
373   ctrls_found[ctrls_found_num].num_logd_found++;
374   /*  ctrls_found[ctrls_found_num].log_disk[unit_nr].status =
375    * io2.c.sense_log_drv_stat.status;
377    * nr_blks = io2.c.id_log_drv.nr_blks;
378    * blks_tr = io.c.sense_log_drv_stat.blks_to_recover;
379    * ctrls_found[ctrls_found_num].log_disk[unit_nr].pvalue =
380    *  ((float)(nr_blks - blks_tr)/(float)nr_blks) * 100;
381    */
382   ctrls_found[ctrls_found_num].log_disk[unit_nr].status = 0;
383   ctrls_found[ctrls_found_num].log_disk[unit_nr].pvalue = 0;
385   return 1;
389 void print_usage() 
391   printf("cpqarrayd [options]\n");
392   printf("   -h         prints this text\n");
393   printf("   -d         enables debugging\n");
397 int main(int argc, char *argv[]) 
399   char option;
400   struct opts opts; /* commandline options */
401   
402   memset(&opts, 0, sizeof(struct opts));
403   
404   /* check options */
405   while ((option = getopt (argc, argv, "dh:")) != EOF)
406     {
407       switch (option)
408         {
409         case 'd':
410           opts.debug = 1;
411           break;
412         case '?':
413         case 'h':
414         default:
415           print_usage();
416           exit(0);
417           break;
418         }
419     }
420   
421   /* Check for existance of array controllers */
422   if (!discover_controllers(opts)) {
423     printf("No array controller found!\n\n");
424     exit(1);
425   }
427   status_check(opts);
429   return exit_code;