1. #!/usr/bin/perl
  2. #
  3. # This perl script uses the _admin volume to query nss volume and pool information.
  4. #
  5. # You need to run it like # ./check_oesnss_vol.pl -V DATA -w 10 -c 5
  6. # but take care that the user has apropriate right to write to the nss management file,
  7. # you might need sudo for the nagios user.
  8. #
  9. # You need to have the perl-XML-* modules installed on the system where you run
  10. # this script as well as have nss active :=))
  11. #
  12. # Brunold Rainer - version 1.3 - rainer.brunold@brunold.at
  13. #
  14. # changelog:
  15. # 2010/02/09 Brunold Rainer - 1.3
  16. # - adopted the performance data output to follow the official
  17. # plugin rules (thanks for the input to Sebastian and Kai)
  18. # 2009/12/13 Brunold Rainer - 1.2
  19. # - added percentage definition for warning and critical level
  20. # (requested by Roland Kool)
  21. # 2009/11/24 Brunold Rainer - 1.1
  22. # - used space was calculated the wrong way (freeable size was ignored)
  23. #
  24. use POSIX;
  25. use Getopt::Long;
  26. use XML::Parser;
  27. use XML::DOM;
  28. use strict;
  29.  
  30. use vars qw($sversion $help $debug $volume $xmlcommand $xmlreply $error $size);
  31. use vars qw($status $result $exitcode $warn $crit $mega $giga $kilo $ent $addcomp);
  32. use vars qw($div $percused $percfree $usedall $warnval $critval);
  33.  
  34. sub print_usage ();
  35.  
  36. my $version = "1.3";
  37. my $parservol = XML::DOM::Parser->new();
  38. my $parserpool = XML::DOM::Parser->new();
  39. my $nssmgmtfile = "+</_admin/Manage_NSS/manage.cmd";
  40.  
  41.  
  42. Getopt::Long::Configure('bundling');
  43. GetOptions
  44. ("v" => \$sversion, "sversion" => \$sversion,
  45. "w=s" => \$warn, "warn=s" => \$warn,
  46. "c=s" => \$crit, "crit=s" => \$crit,
  47. "h" => \$help, "help" => \$help,
  48. "d" => \$debug, "debug" => \$debug,
  49. "M" => \$mega, "mega" => \$mega,
  50. "G" => \$giga, "giga" => \$giga,
  51. "k" => \$kilo, "kilo" => \$kilo,
  52. "V=s" => \$volume, "volume=s" => \$volume);
  53.  
  54. # print the program version
  55. if ($sversion) {
  56. print "Program version: " . $version . "\n\n";
  57. exit 3;
  58. }
  59.  
  60. # print the help screen
  61. if ($help) {
  62. print_usage;
  63. exit 3;
  64. }
  65.  
  66. # check if the volume name is provided
  67. if (!$volume) {
  68. print "ERROR: missing volumes name \n\n";
  69. print_usage;
  70. exit 3;
  71. }
  72.  
  73. sub print_usage () {
  74. print "This check program queries several nss volume statistics and compare the
  75. the free space against the warning and critical levels. It provides automatically
  76. performance data and is highly exetnsible to all parameters that can be queried
  77. via the nss management file. As that nss management file ".$nssmgmtfile."
  78. is not writeable for all user, you might need to add a sudo entry for the nagios
  79. user to allow the access to that file.
  80.  
  81. You can define with the -M, -G and -k options in which format you would like to
  82. have the service results listed, the performance data itself is allways reported
  83. in bytes.
  84.  
  85.  
  86. Usage: check_oesnss_vol.pl -V <NSS Volume> -w <Warn Level> -c <Crit Value> [-d] [-h] [-v] [-M] [-G] [-k]
  87.  
  88. Parameters:
  89. -c ... critical level for the free space in [k|M|G|%]
  90. if no extension is given I assume it is in MB
  91. -d ... print debug information
  92. -h ... print help / usage
  93. -k ... results are shown in kB
  94. -G ... results are shown in GB
  95. -M ... results are shown in MB
  96. -v ... version
  97. -V <NSS Volume> ... define the NSS volume you want to monitor
  98. -w ... warning level for the free space in [k|M|G|%]
  99. if no extension is given I assume it is in MB
  100.  
  101. Samples:
  102. # check_oesnss_vol.pl -V DATAHK07 -w 10000 -c 5000 -M
  103. OK: NSS Vol: DATAHK07, Pool: DATAHK07, Size: 41000 MB, Used: 3423 MB, Free: 37577 MB, Files: 341, Purgeable: 3399 MB, addComp: 24 MB|vol=DATAHK07;size=42949672960;used=3585662976;free=39364009984;files=341;purgeable=3560329216;addcomp=24940544;percused=8;percfree=92
  104.  
  105. # check_oesnss_vol.pl -V DATA -w 20% -c 10%
  106. OK - 0% used, NSS Vol: DATA, Pool: POOL1, Size: 21472739328 Byte, Used: 692224 Byte, Free: 21472047104 Byte, Files: 39, Purgeable: 24576 Byte, addComp: 12288 Byte|vol=DATA;size==21472739328;used=692224;free=21472047104;files=39;purgeable=24576;addcomp=12288;percused=0;percfree=100
  107.  
  108.  
  109. The performance data has the following order:
  110.  
  111. 1. volume name
  112. 2. volume size in byte
  113. 3. used space in byte
  114. 4. free space in byte
  115. 5. number of files in this volume
  116. 6. purgable space in bytes
  117. 7. won space by compression in byte
  118. 8. percent used of this volume
  119. 9. percent free of this volume
  120.  
  121. If you want to see any enhancements, feel free to contact me via email.
  122. The email is in the header of the file.
  123.  
  124. Rainer Brunold, 17.10.2009 \n\n";
  125. }
  126.  
  127. sub query_nss_admin () {
  128. local($xmlcommand) = @_;
  129.  
  130. if ($debug) {
  131. print "NSS management file: " . $nssmgmtfile . "\n\n";
  132. print "NSS XML request: " . $xmlcommand . "\n\n";
  133. }
  134.  
  135. # open the nss management file
  136. open(NSSMGMT, $nssmgmtfile) or die "Error opening NSS management file ($!) on server";
  137.  
  138. if (!syswrite(NSSMGMT, $xmlcommand, length($xmlcommand)))
  139. {
  140. seek NSSMGMT, 0, 0; # set to the beginning of the file.
  141. sysread (NSSMGMT, $error, 10000); # check the error message.
  142. print "Error writing initialization to management file. \n";
  143. print "$error \n\n"; # print the error message to the screen.
  144. close (NSSMGMT);
  145. }
  146. else
  147. {
  148. seek NSSMGMT, 0, 0; # Make sure to start at the beginning of the file.
  149. sysread (NSSMGMT, $xmlreply, 10000); #Read the reply.
  150. close (NSSMGMT);
  151. if ($debug) {
  152. print "NSS XML response: " . $xmlreply . "\n\n";
  153. }
  154. return $xmlreply;
  155. }
  156. }
  157.  
  158. ###################################
  159. # START WITH NSS VOLUME INFORMATION
  160. ###################################
  161.  
  162. if ($debug) {
  163. print "NSS volume: " . $volume . "\n\n";
  164. }
  165.  
  166. # generate the xml query
  167. my $volcommand = "<virtualIO><datastream name=\"command\"/></virtualIO>".
  168. "<nssRequest><volume><getVolumeInfo><volumeName>".$volume.
  169. "</volumeName></getVolumeInfo></volume></nssRequest>";
  170.  
  171. my $volxml = &query_nss_admin($volcommand);
  172.  
  173. # sample response for a volume
  174.  
  175. # <nssReply>
  176. # <volume>
  177. # <getVolumeInfo>
  178. # <basicInfo>
  179. # <volumeName>DATAHK07</volumeName><mountPofloor>/media/nss/DATAHK07</mountPofloor><device>DATAHK07</device><poolName>DATAHK07</poolName><ndsVolumeName>.CN=CL_HK02_DATAHK07.OU=HK02.OU=CLUS.O=SERVICES.T=ALLIANZGRUPPE.</ndsVolumeName><ndsVolumeGUID>c2a8df7d-3288-4125-d3-9a-7ddfa8c28832</ndsVolumeGUID><volumeGUID>4641f3c6-b339-01de-80-00-574147f1d402</volumeGUID><owner>[Supervisor]</owner><volumeState>mounted</volumeState><nameSpaces value="23">DOS Long Macfloorosh Unix </nameSpaces>
  180. # <blockSize>4096</blockSize><volumeQuota>none</volumeQuota><usedSize>3557314560</usedSize><totalObjects>553</totalObjects><totalFiles>250</totalFiles><createdTime value="1254922784">Oct 7, 2009 3:39:44 pm</createdTime>
  181. # <modifiedTime value="1255001261">Oct 8, 2009 1:27:41 pm</modifiedTime>
  182. # <archivedTime value="0">Invalid UTC Time</archivedTime>
  183. # <volumeReadAhead>65536</volumeReadAhead><authorizationModel>NetWare</authorizationModel></basicInfo>
  184. # <attributeInfo>
  185. # <supportedAttributes value="16039018491"><volumeEncrypted/><volumeHardlinks/><salvage/><compression/><directoryQuota/><userQuota/><flushFiles/><cfsMaster/><mfl/><snapshot/><shredding/><userTransaction/><migration/><noAccessTime/></supportedAttributes>
  186. # <enabledAttributes value="4295228411"><salvage/><compression/><userQuota/><backup/></enabledAttributes>
  187. # </attributeInfo>
  188. # <salvageInfo>
  189. # <freeableSize>1774010368</freeableSize><nonFreeableSize>0</nonFreeableSize><deletedFiles>124</deletedFiles><oldestDeletedTime value="0">Invalid UTC Time</oldestDeletedTime>
  190. # <minKeepTime>0</minKeepTime><maxKeepTime>0</maxKeepTime><lowWaterMark>10</lowWaterMark><highWaterMark>20</highWaterMark></salvageInfo>
  191. # <compressionInfo>
  192. # <compressedFiles>91</compressedFiles><compressedDeletedFiles>91</compressedDeletedFiles><uncompressibleFiles>235</uncompressibleFiles><preCompressionBytes>9338880</preCompressionBytes><compressedBytes>2097152</compressedBytes></compressionInfo>
  193. # <result value="0"><description>success</description></result>
  194. # </getVolumeInfo>
  195. # </volume>
  196. # <result value="0"><description>zOK</description></result>
  197. # </nssReply>
  198.  
  199. my $doc = $parservol->parse($volxml);
  200. my $result = $doc->getElementsByTagName('result')->item(0)->getAttribute('value');
  201.  
  202. # check the result of the xml response to see if we got the volume info
  203. if ($result ne "0") {
  204. print "ERROR: problems getting volume information. Is the volume name correct ? \n";
  205. exit 3;
  206. }
  207.  
  208. # extract the different values
  209. my $bas = $doc->getElementsByTagName('basicInfo')->item(0);
  210. my $vol = $bas->getElementsByTagName("volumeName")->item(0)->getFirstChild->getData;
  211. my $pool = $bas->getElementsByTagName("poolName")->item(0)->getFirstChild->getData;
  212. my $usedall = $bas->getElementsByTagName("usedSize")->item(0)->getFirstChild->getData;
  213. my $quota = $bas->getElementsByTagName("volumeQuota")->item(0)->getFirstChild->getData;
  214. my $files = $bas->getElementsByTagName("totalFiles")->item(0)->getFirstChild->getData;
  215. my $sal = $doc->getElementsByTagName('salvageInfo')->item(0);
  216. my $purge = $sal->getElementsByTagName("freeableSize")->item(0)->getFirstChild->getData;
  217. my $comp = $doc->getElementsByTagName('compressionInfo')->item(0);
  218. my $precomp = $comp->getElementsByTagName("preCompressionBytes")->item(0)->getFirstChild->getData;
  219. my $postcomp = $comp->getElementsByTagName("compressedBytes")->item(0)->getFirstChild->getData;
  220.  
  221. # calculate the used space and recognize the freeable space
  222. my $used=$usedall-$purge;
  223.  
  224. # check if there is a quota set for this volume, otherwise we need to query the
  225. # nss pool size as well.
  226. if ($quota eq "none") {
  227.  
  228. ####################################
  229. # CONTINUE WITH NSS POOL INFORMATION
  230. ####################################
  231.  
  232. if ($debug) {
  233. print "NSS pool: " . $pool . "\n\n";
  234. }
  235.  
  236. # generate the xml query
  237. my $poolcommand = "<virtualIO><datastream name=\"command\"/></virtualIO>".
  238. "<nssRequest><pool><getPoolInfo><poolName>".$pool."</poolName>".
  239. "</getPoolInfo></pool></nssRequest>";
  240.  
  241. my $poolxml = &query_nss_admin($poolcommand);
  242.  
  243. # this is the reply we should get
  244.  
  245. # <nssReply>
  246. # <pool>
  247. # <getPoolInfo>
  248. # <basicInfo>
  249. # <poolName>DATAHK07</poolName><mountPofloor>/opt/novell/nss/mnt/.pools/DATAHK07</mountPofloor><ndsPoolName>.CN=CL_HK02_DATAHK07_POOL.OU=HK02.OU=CLUS.O=SERVICES.T=ALLIANZGRUPPE.</ndsPoolName><ndsPoolGUID>a63755a5-4b54-47fe-23-90-a55537a6544b</ndsPoolGUID><poolGUID>9155ed00-b338-01de-80-00-574147f1d402</poolGUID><poolState>active</poolState><nameSpaces value="3085691102">Long Macfloorosh Unix ExtendedAttribute DataStream </nameSpaces>
  250. # <blockSize>4096</blockSize><size>42949672960</size><usedSize>3685838848</usedSize><createdTime value="1254922678">Oct 7, 2009 3:37:58 pm</createdTime>
  251. # <modifiedTime value="1254922678">Oct 7, 2009 3:37:58 pm</modifiedTime>
  252. # <lssType>ZLSS</lssType></basicInfo>
  253. # <salvageInfo>
  254. # <freeableSize>1774010368</freeableSize><nonFreeableSize>0</nonFreeableSize></salvageInfo>
  255. # <attributeInfo>
  256. # <supportedAttributes value="251"><persistentFeatures/><shared/><verify/><rebuild/><multipleVolumes/><snapshot/><msap/></supportedAttributes>
  257. # <enabledAttributes value="187"><persistentFeatures/><shared/><verify/><rebuild/><multipleVolumes/><msap/></enabledAttributes>
  258. # </attributeInfo>
  259. # <volumeInfo>
  260. # <volumeName>DATAHK07</volumeName>
  261. # </volumeInfo>
  262. # <deletedVolumeInfo>
  263. # </deletedVolumeInfo>
  264. # <segmentInfo>
  265. # <segment>
  266. # <deviceName>sdc</deviceName><segmentName>sdc1.1</segmentName><deviceID>sdc</deviceID><segmentID>sdc1.1</segmentID><offset>32</offset><size>42950705152</size>
  267. # </segment>
  268. # </segmentInfo>
  269. # <result value="0"><description>success</description></result>
  270. # </getPoolInfo>
  271. # </pool>
  272. # <result value="0"><description>zOK</description></result>
  273. # </nssReply>
  274.  
  275. my $doc = $parserpool->parse($poolxml);
  276. my $bas = $doc->getElementsByTagName('basicInfo')->item(0);
  277. $size = $bas->getElementsByTagName("size")->item(0)->getFirstChild->getData;
  278.  
  279. }
  280. else
  281. {
  282.  
  283. $size = $quota;
  284.  
  285. }
  286.  
  287. my $free = $size - $used;
  288.  
  289. # recalculate warning and critical value depending on the value type
  290. # warning
  291. if (substr($warn,-1,1) eq "k") {
  292. $warnval=substr($warn,0,length($warn)-1)*1024;
  293. } elsif (substr($warn,-1,1) eq "M") {
  294. $warnval=substr($warn,0,length($warn)-1)*1047552;
  295. } elsif (substr($warn,-1,1) eq "G") {
  296. $warnval=substr($warn,0,length($warn)-1)*1073741824;
  297. } elsif (substr($warn,-1,1) eq "%") {
  298. $warnval=$size*substr($warn,0,length($warn)-1)/100;
  299. } else {
  300. # default value is in MB
  301. $warnval=$warn*1047552;
  302. }
  303. # critical
  304. if (substr($crit,-1,1) eq "k") {
  305. $critval=substr($crit,0,length($crit)-1)*1024;
  306. } elsif (substr($crit,-1,1) eq "M") {
  307. $critval=substr($crit,0,length($crit)-1)*1047552;
  308. } elsif (substr($crit,-1,1) eq "G") {
  309. $critval=substr($crit,0,length($crit)-1)*1073741824;
  310. } elsif (substr($crit,-1,1) eq "%") {
  311. $critval=$size*substr($crit,0,length($crit)-1)/100;
  312. } else {
  313. # default value is in MB
  314. $critval=$crit*1047552;
  315. }
  316.  
  317. if ($debug) {
  318. print "warning level: " . $warnval . " byte\n";
  319. print "critical level: " . $critval . " byte\n\n";
  320. }
  321.  
  322. # check the warning and critical levels
  323. if (!$warnval || !$critval || $warnval<$critval) {
  324. print "ERROR: incorrect warning and critial levels defined \n\n";
  325. print_usage;
  326. exit 3;
  327. }
  328.  
  329.  
  330. # critical and warning levels are defined in MB, therefor multiply it with
  331. # 1047552 to compare it against the current used space
  332. if (abs($free)<=($critval)) {
  333. $status="CRITICAL";
  334. $exitcode=2;
  335. } elsif (abs($free)<=($warnval)) {
  336. $status="WARNING";
  337. $exitcode=1;
  338. } else {
  339. $status="OK";
  340. $exitcode=0;
  341. }
  342.  
  343. # calculate the additional space used by compressed file
  344. $addcomp=$precomp-$postcomp;
  345.  
  346. # calculate the used space in percent
  347. $percused=($used/$size)*100;
  348. $percfree=($free/$size)*100;
  349.  
  350.  
  351. if ($giga) {
  352. $div = 1073741824;
  353. $ent = " GB";
  354. } elsif ($mega) {
  355. $div = 1047552;
  356. $ent = " MB";
  357. } elsif ($kilo) {
  358. $div = 1024;
  359. $ent = " kB";
  360. } else {
  361. $div = 1;
  362. $ent = " Byte";
  363. }
  364.  
  365. print $status . " - ";
  366. printf ("%.0f", $percused);
  367. print "% used";
  368. print ", NSS Vol: " . $vol .", Pool: " . $pool . ", Size: ";
  369. printf ("%.0f", $size/$div);
  370. print $ent . ", Used: ";
  371. printf ("%.0f", $used/$div);
  372. print $ent . ", Free: ";
  373. printf ("%.0f", $free/$div);
  374. print $ent . ", Files: " . $files . ", Purgeable: ";
  375. printf ("%.0f", $purge/$div);
  376. print $ent . ", addComp: ";
  377. printf ("%.0f", $addcomp/$div);
  378. print $ent . "|vol=" . $vol . ";size=" . $size . ";used=" . $used . ";free=" . $free . ";files=" . $files . ";purgeable=" . $purge . ";addcomp=" . $addcomp . ";percused=";
  379. printf ("%.0f", $percused);
  380. print ";percfree=";
  381. printf ("%.0f", $percfree);
  382. print "\n";
  383. exit $exitcode;
  384.