1 /*
2 * File: check_netapp_spare.c
3 * Copyright: (c) 2006 by Peter Gritsch
4 * Email: s4nag@no-where.at
5 *
6 * This file is part of SNMP4Nagios.
7 *
8 * SNMP4Nagios is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * SNMP4Nagios is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with SNMP4Nagios; if not, write to the
20 *
21 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 * MA 02110-1301, USA
23 */
24
25 #if HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <errno.h>
30 #include "globals.h"
31 #include "nagiosif.h"
32 #include "snmpif.h"
33 #include "syslogif.h"
34 #include "strutils.h"
35 #include "utilities.h"
36
37
38 /* data type for storing scan results */
39 typedef struct
40 {
41 int pDrv ; /* spare drive index */
42 int v1; /* found spareIndex */
43 int v3; /* found spareStatus */
44 int v12; /* found spareShelf */
45 int v13; /* found spareBay */
46 int shelf; /* shelf */
47 int bay; /* bay */
48 } tScanRes;
49
50 /* data type for storing data */
51 typedef struct
52 {
53 int stat; /* status of the drive */
54 int shlf; /* shelf the drive is in */
55 int bay; /* bay the drive is in */
56 } tDataSet;
57
58 /* global input variables */
59 int pDrv;
60 int isPDrvSet = FALSE;
61
62 /*
63 * NETWORK-APPLIANCE-MIB::spareStatus.PDRV = 1.3.6.1.4.1.789.1.6.3.1.3.PDRV
64 * NETWORK-APPLIANCE-MIB::spareShelf.PDRV = 1.3.6.1.4.1.789.1.6.3.1.12.PDRV
65 * NETWORK-APPLIANCE-MIB::spareBay.PDRV = 1.3.6.1.4.1.789.1.6.3.1.13.PDRV
66 */
67 oid baseOID [] = { 1, 3, 6, 1, 4, 1, 789, 1, 6, 3, 1 };
68 size_t baseOIDLen = 11;
69
70 /* scan results */
71 tScanRes* scanRes = NULL;
72 int scanResLen = 0;
73
74 /* results of the SNMP queries */
75 tDataSet v;
76
77
SetGlobals()78 void SetGlobals ()
79 {
80 /* progName is set by ReadArgs() */
81 srvName = "check_netapp_spare";
82 progVersion = "0.3";
83 helpIndexP = "-d DRIVE";
84 helpThresP = NULL;
85 helpPurpose =
86 "Checks the state of a spare drive of a NetApp(R) Filer.";
87 /* community is set by ReadArgs() */
88 /* commFile is set by ReadArgs() */
89 /* rrdStep is unused */
90 /* rrdHBeat is unused */
91 supportsPerfLog = FALSE;
92 hasIndexParam = FALSE;
93 }
94
HelpSpecificParams()95 void HelpSpecificParams ()
96 {
97 printf (
98 "-d, --drive INTEGER\n"
99 " Index of the spare drive.\n"
100 "\n"
101 );
102 }
103
HelpExplain()104 void HelpExplain ()
105 {
106 printf (
107 "The plugin checks the overall state of a spare drive of a NetApp(R)\n"
108 "Filer."
109 "\n"
110 );
111 }
112
HelpPerformanceData()113 void HelpPerformanceData ()
114 {
115 printf (
116 "There is no performance data provided.\n"
117 "\n"
118 );
119 }
120
ChkOptSpecificParams(int argc,char ** argv,int * i)121 int ChkOptSpecificParams ( int argc, char** argv, int* i )
122 {
123 int ret = TRUE;
124 if ( !strcmp ( argv [(*i)], "-d" )
125 || !strcmp ( argv [(*i)], "--drive" ) )
126 {
127 isPDrvSet = TRUE;
128 (*i)++;
129 if ( (*i) < argc )
130 {
131 char *tail = argv [(*i)];
132 errno = 0;
133 pDrv = strtoul ( argv [(*i)++], &tail, 0 );
134 if ( errno || *tail ) Usage ( "Invalid 'drive' parameter" );
135 }
136 else Usage ( "Missing 'drive' parameter(s)" );
137 } else ret = FALSE;
138 return ( ret );
139 }
140
ScanResIndex(int aIndex)141 int ScanResIndex ( int aIndex )
142 {
143 int retVal = 0;
144 int found = FALSE;
145
146 while ( ( retVal < scanResLen ) && !found )
147 {
148 found = ( scanRes [retVal].pDrv == aIndex );
149 if ( !found ) retVal++;
150 }
151 if ( !found ) retVal = -1;
152 return retVal;
153 }
154
SnmpWalkHandleVariable(netsnmp_variable_list * aVar)155 void SnmpWalkHandleVariable ( netsnmp_variable_list* aVar )
156 {
157 if ( aVar->name_length == 13 )
158 {
159 if ( OidCmp ( aVar->name, baseOID, baseOIDLen ) == 0 )
160 {
161 int index;
162
163 switch ( aVar->name [11] )
164 {
165 case 1: /* spareIndex */
166 index = scanResLen;
167 scanResLen++;
168 scanRes = realloc ( scanRes,
169 sizeof ( tScanRes ) * scanResLen );
170 if ( scanRes == NULL ) ErrorMalloc ();
171 scanRes [index].pDrv = aVar->name [12];
172 scanRes [index].v1 = ( aVar->type == ASN_INTEGER );
173 scanRes [index].v3 = FALSE;
174 scanRes [index].v12 = FALSE;
175 scanRes [index].v13 = FALSE;
176 break;
177 case 3: /* spareStatus */
178 index = ScanResIndex ( aVar->name [12] );
179 scanRes [index].v3 = ( aVar->type == ASN_INTEGER );
180 break;
181 case 12: /* spareShelf */
182 index = ScanResIndex ( aVar->name [12] );
183 scanRes [index].v12 = ( aVar->type == ASN_INTEGER );
184 scanRes [index].shelf = *(aVar->val.integer);
185 break;
186 case 13: /* spareBay */
187 index = ScanResIndex ( aVar->name [12] );
188 scanRes [index].v13 = ( aVar->type == ASN_INTEGER );
189 scanRes [index].bay = *(aVar->val.integer);
190 break;
191 default:
192 /* don't care */
193 break;
194 }
195 } else Log ( LOG_CRIT, "Unexpected OID while scanning services" );
196 } else Log ( LOG_CRIT, "Wrong length while scanning services" );
197 }
198
ScanServices()199 int ScanServices ()
200 {
201 int i;
202 int retVal = STATE_UNKNOWN;
203
204 SnmpWalk ( baseOID, baseOIDLen );
205 for ( i = 0; i < scanResLen; i++ )
206 {
207 if ( scanRes [i].v1 && scanRes [i].v3 && scanRes [i].v12 &&
208 scanRes [i].v13 )
209 {
210 retVal = STATE_OK;
211 printf ( "OK drive: %i ; shelf: %i ; bay: %i\n",
212 scanRes [i].pDrv, scanRes [i].shelf, scanRes [i].bay );
213 }
214 }
215 if ( retVal == STATE_UNKNOWN ) printf ( "FAILED\n" );
216 return retVal;
217 }
218
ReadVals()219 void ReadVals ()
220 {
221 struct snmp_session sess1;
222 struct snmp_session* sess2;
223 oid o_stat [13];
224 oid o_shlf [13];
225 oid o_bay [13];
226 size_t oidLen;
227
228 OidCpy ( o_stat, &oidLen, baseOID, &baseOIDLen );
229 OidCpy ( o_shlf, &oidLen, baseOID, &baseOIDLen );
230 OidCpy ( o_bay, &oidLen, baseOID, &baseOIDLen );
231 o_stat [11] = 3; o_stat [12] = pDrv;
232 o_shlf [11] = 12; o_shlf [12] = pDrv;
233 o_bay [11] = 13; o_bay [12] = pDrv;
234 oidLen = 13;
235 ConfigureSession1 ( &sess1 );
236 sess2 = snmp_open ( &sess1 );
237 if ( sess2 == NULL ) Error ( LOG_ERR, "Could not open session!" );
238 v.stat = ReadInteger ( sess2, o_stat, oidLen );
239 v.shlf = ReadInteger ( sess2, o_shlf, oidLen );
240 v.bay = ReadInteger ( sess2, o_bay, oidLen );
241 free ( sess1.peername );
242 free ( sess1.community );
243 snmp_close_sessions ();
244 }
245
CreateDataFile(const char * aRRDFPath)246 void CreateDataFile ( const char* aRRDFPath )
247 {
248 /* performance data is not supported */
249 }
250
ParseData(const char * aData)251 void ParseData ( const char* aData )
252 {
253 /* performance data is not supported */
254 }
255
WriteData(const char * aRRDFPath)256 void WriteData ( const char* aRRDFPath )
257 {
258 /* performance data is not supported */
259 }
260
CheckData()261 int CheckData ()
262 {
263 int retVal = STATE_OK;
264 char* mStat = NULL;
265
266 ReadVals ();
267 switch ( v.stat )
268 {
269 case 1:
270 mStat = StrDup ( "spare" );
271 break;
272 case 2:
273 retVal = ( retVal < STATE_WARNING ) ? STATE_WARNING : retVal;
274 mStat = StrDup ( "adding spare" );
275 break;
276 case 3:
277 retVal = ( retVal < STATE_WARNING ) ? STATE_WARNING : retVal;
278 mStat = StrDup ( "bypassed" );
279 break;
280 case 4:
281 retVal = ( retVal < STATE_WARNING ) ? STATE_WARNING : retVal;
282 mStat = StrDup ( "unknown" );
283 break;
284 default:
285 retVal = ( retVal < STATE_WARNING ) ? STATE_WARNING : retVal;
286 mStat = StrDup ( "invalid" );
287 break;
288 }
289 PrintExit ( retVal );
290 printf ( " - shelf %i, bay %i: %s\n", v.shlf, v.bay, mStat );
291 free ( mStat );
292 return ( retVal );
293 }
294
main(int argc,char ** argv)295 int main ( int argc, char** argv )
296 {
297 int retVal = STATE_OK;
298
299 SetGlobals ();
300 ReadArgs ( argc, argv );
301 if ( checkData )
302 {
303 if ( !isPDrvSet ) Usage ( "Missing 'drive' parameters" );
304 }
305 if ( scanServices ) retVal = ScanServices ();
306 else
307 {
308 if ( checkData ) retVal = CheckData ();
309 }
310 if ( hostName != NULL ) free ( hostName );
311 if ( hostAddr != NULL ) free ( hostAddr );
312 if ( progName != NULL ) free ( progName );
313 return ( retVal );
314 }
315