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