Back to index

nagios-plugins  1.4.16
check_cpqarray.c
Go to the documentation of this file.
00001 /*
00002    check_cpqarray, an extension for Netsaint / Nagios to check the
00003    status of a Compaq SmartArray controller from the commandline.
00004    Copyright (C) 2003  Guenther Mair
00005 
00006    based on the work and using main parts of
00007 
00008    CpqArray Deamon, a program to monitor and remotely configure a 
00009    SmartArray controller.
00010    Copyright (C) 1999  Hugo Trippaers
00011 
00012    This program is free software; you can redistribute it and/or modify
00013    it under the terms of the GNU General Public License as published by
00014    the Free Software Foundation; either version 2 of the License, or
00015    (at your option) any later version.
00016 
00017    This program is distributed in the hope that it will be useful,
00018    but WITHOUT ANY WARRANTY; without even the implied warranty of
00019    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020    GNU General Public License for more details.
00021 
00022    You should have received a copy of the GNU General Public License
00023    along with this program; if not, write to the Free Software
00024    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025  */
00026 
00027 #include <unistd.h>
00028 #include <sys/ioctl.h>
00029 #include <sys/utsname.h>
00030 #include <stdio.h>
00031 #include <fcntl.h>
00032 #include <string.h>
00033 #include <errno.h>
00034 
00035 #include "/usr/src/linux/drivers/block/ida_ioctl.h"
00036 #include "/usr/src/linux/drivers/block/ida_cmd.h"
00037 #include "/usr/src/linux/drivers/block/cpqarray.h"
00038 
00039 
00040 const char *controllers[] =
00041 {
00042   "/dev/ida/c0d0",
00043   "/dev/ida/c1d0",
00044   "/dev/ida/c2d0",
00045   "/dev/ida/c3d0",
00046   "/dev/ida/c4d0",
00047   "/dev/ida/c5d0",
00048   "/dev/ida/c6d0",
00049   "/dev/ida/c7d0"
00050 };
00051 
00052 const char *statusstr[] = {
00053         "Logical drive /dev/ida/c%dd%d: OK\n",
00054         "Logical drive /dev/ida/c%dd%d: FAILED\n",
00055         "Logical drive /dev/ida/c%dd%d: not configured.\n",
00056         "Logical drive /dev/ida/c%dd%d: using interim recovery mode, %3.2f%% done.\n",
00057         "Logical drive /dev/ida/c%dd%d: ready for recovery operation.\n",
00058         "Logical drive /dev/ida/c%dd%d: is currently recovering, %3.2f%% done.\n",
00059         "Wrong physical drive was replaced.\n",
00060         "A physical drive is not properly connected.\n",
00061         "Hardware is overheating.\n",
00062         "Hardware has overheated.\n",
00063         "Logical drive /dev/ida/c%dd%d: currently expanding, %3.2f%% done.\n",
00064         "Logical drive /dev/ida/c%dd%d: not yet available.\n",
00065         "Logical drive /dev/ida/c%dd%d: queued for expansion.\n",
00066 };
00067 
00068 extern char *optarg;
00069 extern int optind, opterr, optopt;
00070 
00071 int ctrls_found_num;
00072 int exit_code = 0;
00073 struct controller ctrls_found[8];
00074 
00075 #define DEBUG(x)  fprintf(stderr, x)
00076 
00077 struct opts 
00078 {
00079   char debug;
00080 };
00081 
00082 struct slog_disk
00083 {
00084   int status;
00085   float pvalue;
00086 };
00087 
00088 struct controller 
00089 {
00090   char ctrl_devicename[20];
00091   int num_logd_found;
00092   struct slog_disk log_disk[16];
00093 };
00094 
00095 
00096 
00097 int status_check (struct opts opts) 
00098 {
00099   int devicefd;
00100   int ctrl_cntr;
00101   int logd_cntr;
00102   ida_ioctl_t io, io2;
00103   int status, nr_blks, blks_tr;
00104   float pvalue;
00105   int counter;
00106     
00107   for ( ctrl_cntr=0;
00108         ctrl_cntr <  ctrls_found_num;
00109         ctrl_cntr++) {
00110     
00111     devicefd = open (controllers[ctrl_cntr], O_RDONLY);
00112     
00113     for ( logd_cntr=0;
00114           logd_cntr < ctrls_found[ctrl_cntr].num_logd_found;
00115           logd_cntr++) {
00116       
00117         memset (&io, 0, sizeof (io));
00118 
00119         io.cmd = SENSE_LOG_DRV_STAT;
00120         io.unit = logd_cntr  | UNITVALID;
00121         
00122         if (ioctl (devicefd, IDAPASSTHRU, &io) < 0)
00123           {
00124             perror ("SENSE_LOG_DRV_STAT ioctl");
00125             return 0;
00126           }
00127 
00128         status=io.c.sense_log_drv_stat.status;
00129         
00130         if ((status == 3) || (status == 5) || (status == 7)) {
00131           /* is a progress indicator required?
00132            */
00133           memset (&io2, 0, sizeof (io));
00134           
00135           io2.cmd = ID_LOG_DRV;
00136           io2.unit = logd_cntr  | UNITVALID;
00137           
00138           if (ioctl (devicefd, IDAPASSTHRU, &io2) < 0)
00139             {
00140               perror ("ID_LOG_DRV ioctl");
00141               /* return 0;   no return this isn't fatal for now */
00142             }
00143           else 
00144             {
00145               nr_blks = io2.c.id_log_drv.nr_blks;
00146               blks_tr = io.c.sense_log_drv_stat.blks_to_recover;
00147                   
00148               pvalue = ((float)(nr_blks - blks_tr)/(float)nr_blks) * 100;
00149             }
00150         }
00151         else {
00152           pvalue = 0.0;
00153         }
00154 
00155         if (opts.debug) {
00156          fprintf(stdout, "DEBUG: Status of controller %d unit %d is %d\n", 
00157                 ctrl_cntr, logd_cntr, status);
00158           fprintf(stdout, "DEBUG: ");
00159          fprintf(stdout, statusstr[status], 
00160                 ctrl_cntr, logd_cntr, pvalue);
00161          fprintf(stdout, "\n");
00162        }
00163        
00164        printf(statusstr[status], ctrl_cntr, logd_cntr, pvalue);
00165 
00166        switch(status)
00167          {
00168          case 1:
00169          case 2:
00170          case 6:
00171          case 7:
00172          case 9:
00173            /* CRITICAL */
00174            exit_code = 2;
00175            break;
00176          case 3:
00177          case 4:
00178          case 5:
00179          case 8:
00180          case 10:
00181          case 11:
00182          case 12:
00183            /* WARNING (only if not yet at CRITICAL LEVEL) */
00184            if (exit_code < 2) exit_code = 1;
00185            break;
00186          case 0:
00187          default:
00188            /* do nothing */
00189            break;
00190          }
00191 
00192        ctrls_found[ctrl_cntr].log_disk[logd_cntr].pvalue = pvalue;
00193        ctrls_found[ctrl_cntr].log_disk[logd_cntr].status = status;
00194     }
00195     close (devicefd);
00196   }
00197 
00198   return 1;
00199 }
00200 
00201 int discover_controllers (struct opts opts)
00202 {
00203   int cntr;
00204   int foundone = 0;
00205 
00206   for (cntr = 0; cntr < 8; cntr++)
00207     {
00208       /* does this device exist ? */
00209       if ((access (controllers[cntr], R_OK | F_OK)) == 0)
00210        {
00211          /* it does :) */
00212          if (interrogate_controller (opts, cntr))
00213            {
00214              foundone = 1;
00215              if (opts.debug) 
00216               fprintf (stderr, "DEBUG: %s is a existing controller\n",
00217                       controllers[cntr]);
00218            }
00219        }
00220       else if (opts.debug)
00221        {
00222          fprintf (stderr, "DEBUG: Device %s could not be opened\n", controllers[cntr]);
00223          perror ("DEBUG: reason");
00224        }
00225     }
00226    return foundone;
00227 }
00228 
00229 void boardid2str (unsigned long board_id, char *name)
00230 {
00231   switch (board_id)
00232     {
00233     case 0x0040110E:        /* IDA */
00234       strcpy (name, "Compaq IDA");
00235       break;
00236     case 0x0140110E:        /* IDA-2 */
00237       strcpy (name, "Compaq IDA-2");
00238       break;
00239     case 0x1040110E:        /* IAES */
00240       strcpy (name, "Compaq IAES");
00241       break;
00242     case 0x2040110E:        /* SMART */
00243       strcpy (name, "Compaq SMART");
00244       break;
00245     case 0x3040110E:        /* SMART-2/E */
00246       strcpy (name, "Compaq SMART-2/E");
00247       break;
00248     case 0x40300E11:        /* SMART-2/P or SMART-2DH */
00249       strcpy (name, "Compaq SMART-2/P (2DH)");
00250       break;
00251     case 0x40310E11:        /* SMART-2SL */
00252       strcpy (name, "Compaq SMART-2SL");
00253       break;
00254     case 0x40320E11:        /* SMART-3200 */
00255       strcpy (name, "Compaq SMART-3200");
00256       break;
00257     case 0x40330E11:        /* SMART-3100ES */
00258       strcpy (name, "Compaq SMART-3100ES");
00259       break;
00260     case 0x40340E11:        /* SMART-221 */
00261       strcpy (name, "Compaq SMART-221");
00262       break;
00263     case 0x40400E11:        /* Integrated Array */
00264       strcpy (name, "Compaq Integrated Array");
00265       break;
00266     case 0x40500E11:        /* Smart Array 4200 */
00267       strcpy (name, "Compaq Smart Array 4200");
00268       break;
00269     case 0x40510E11:        /* Smart Array 4250ES */
00270       strcpy (name, "Compaq Smart Array 4250ES");
00271       break;
00272     case 0x40580E11:        /* Smart Array 431 */
00273       strcpy (name, "Compaq Smart Array 431");
00274       break;
00275     default:
00276       /*
00277        * Well, its a SMART-2 or better, don't know which
00278        * kind.
00279        */
00280       strcpy (name, "Unknown Controller Type");
00281     }
00282 }
00283 
00284 int interrogate_controller (struct opts opts, int contrnum)
00285 {
00286   int devicefd;
00287   ida_ioctl_t io;
00288   char buffer[30];
00289   int foundone = 0;
00290   int cntr;
00291  
00292   devicefd = open (controllers[contrnum], O_RDONLY);
00293   /* no checks, did that before */
00294 
00295   /* clear io */
00296   memset (&io, 0, sizeof (io));
00297 
00298   io.cmd = ID_CTLR;
00299 
00300   if (ioctl (devicefd, IDAPASSTHRU, &io) < 0)
00301     {
00302       if (opts.debug) perror ("DEBUG: ioctl");
00303       return 0;
00304     }
00305 
00306   boardid2str (io.c.id_ctlr.board_id, buffer);
00307 
00308   strncpy (ctrls_found[ctrls_found_num].ctrl_devicename, 
00309           buffer, 20);
00310 
00311   ctrls_found[ctrls_found_num].num_logd_found = 0;
00312 
00313   for (cntr = 0; cntr < io.c.id_ctlr.nr_drvs; cntr++)
00314     {
00315       if (interrogate_logical (opts, devicefd, cntr))
00316        {
00317          /* logical drive found, this could be used later one */
00318          foundone = 1;
00319        }
00320     }
00321 
00322   switch (ctrls_found[ctrls_found_num].num_logd_found)
00323     {
00324     case 0:
00325       printf("Found a %s with no logical drives.\n", buffer);
00326       break;
00327     case 1:
00328       printf("Found a %s with one Logical drive.\n", buffer,
00329        ctrls_found[ctrls_found_num].num_logd_found);
00330       break;
00331     default:
00332       printf("Found a %s with %d Logical drives.\n", buffer,
00333        ctrls_found[ctrls_found_num].num_logd_found);
00334       break;
00335     }
00336 
00337   ctrls_found_num++;
00338 
00339   close (devicefd);
00340   return 1;
00341 }
00342 
00343 int interrogate_logical (struct opts opts, int devicefd, int unit_nr)
00344 {
00345   ida_ioctl_t io;
00346   ida_ioctl_t io2;
00347   int nr_blks, blks_tr;
00348 
00349   if (opts.debug) printf ("DEBUG: interrogating unit %d\n", unit_nr);
00350 
00351   memset (&io, 0, sizeof (io));
00352 
00353   io.cmd = ID_LOG_DRV;
00354   io.unit = unit_nr | UNITVALID;
00355 
00356   if (ioctl (devicefd, IDAPASSTHRU, &io) < 0)
00357     {
00358       perror ("FATAL: ID_LOG_DRV ioctl");
00359       return 0;
00360     }
00361 
00362   memset (&io2, 0, sizeof (io2));
00363 
00364   io2.cmd = SENSE_LOG_DRV_STAT;
00365   io2.unit = unit_nr | UNITVALID;
00366 
00367   if (ioctl (devicefd, IDAPASSTHRU, &io2) < 0)
00368     {
00369       perror ("FATAL: SENSE_LOG_DRV_STAT ioctl");
00370       return 0;
00371     }
00372   
00373   ctrls_found[ctrls_found_num].num_logd_found++;
00374   /*  ctrls_found[ctrls_found_num].log_disk[unit_nr].status =
00375    * io2.c.sense_log_drv_stat.status;
00376 
00377    * nr_blks = io2.c.id_log_drv.nr_blks;
00378    * blks_tr = io.c.sense_log_drv_stat.blks_to_recover;
00379    * ctrls_found[ctrls_found_num].log_disk[unit_nr].pvalue =
00380    *  ((float)(nr_blks - blks_tr)/(float)nr_blks) * 100;
00381    */
00382   ctrls_found[ctrls_found_num].log_disk[unit_nr].status = 0;
00383   ctrls_found[ctrls_found_num].log_disk[unit_nr].pvalue = 0;
00384 
00385   return 1;
00386 }
00387 
00388 
00389 void print_usage() 
00390 {
00391   printf("cpqarrayd [options]\n");
00392   printf("   -h         prints this text\n");
00393   printf("   -d         enables debugging\n");
00394 }
00395 
00396 
00397 int main(int argc, char *argv[]) 
00398 {
00399   char option;
00400   struct opts opts; /* commandline options */
00401   
00402   memset(&opts, 0, sizeof(struct opts));
00403   
00404   /* check options */
00405   while ((option = getopt (argc, argv, "dh:")) != EOF)
00406     {
00407       switch (option)
00408         {
00409        case 'd':
00410          opts.debug = 1;
00411          break;
00412        case '?':
00413        case 'h':
00414        default:
00415          print_usage();
00416          exit(0);
00417          break;
00418        }
00419     }
00420   
00421   /* Check for existance of array controllers */
00422   if (!discover_controllers(opts)) {
00423     printf("No array controller found!\n\n");
00424     exit(1);
00425   }
00426 
00427   status_check(opts);
00428 
00429   return exit_code;
00430 }