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