check_cpqarray.c 10 KB

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