Advertisement
jonwitts

Nagios HP MSA P2000 Status and Performance Monitor

Aug 21st, 2013
4,643
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 16.23 KB | None | 0 0
  1. #!/usr/bin/php
  2. <?php
  3. /*Nagios Exit codes
  4.         0 = OK
  5.         1 = WARNING
  6.         2 = CRITICAL
  7.         3 = UNKNOWN
  8.  
  9. perfdata output rta=35.657001ms;1000.000000;3000.000000;0.000000 pl=0%;80;100;0
  10.  
  11. */
  12.  
  13.  
  14. //Set provided variables
  15. $arguements = getopt("H:U:P:s:c:S:u:w:C:t:");
  16.  
  17. $secure = isset($arguements['s']) ? $arguements['s'] : 0;
  18. $command = isset($arguements['c']) ? $arguements['c'] : "status";
  19. $stat = isset($arguements['S']) ? $arguements['S'] : "iops";
  20. $uom = isset($arguements['u']) ? $arguements['u'] : "";
  21. $warnType = isset($arguements['t']) ? $arguements['t'] : "greaterthan";
  22.  
  23. if(isset($arguements['w']) || isset($arguements['C'])) {
  24.     if(!isset($arguements['w']) || !isset($arguements['C'])) {
  25.         echo "Specify warning/critical threshold \n\r";
  26.         Usage();
  27.         exit(3);
  28.     }
  29.     else {
  30.         $warning = $arguements['w'];
  31.         $critical = $arguements['C'];
  32.     }
  33. }
  34.  
  35. //Validate Provided arguements
  36. if(!isset($arguements['H']) || !isset($arguements['U']) || !isset($arguements['P'])) {
  37.     Usage();
  38.     exit(3);
  39. }
  40. else {
  41.     //Concatenate Username and password into auth string
  42.     $concatAuth = $arguements['U'] . "_" . $arguements['P'];
  43.     $concatMD5 = md5($concatAuth);
  44.     $hostAddr = $arguements['H'];
  45.     $auth = $concatMD5;
  46.     $authstr = "/api/login/".$auth;
  47. }
  48.  
  49. $successful =0;
  50.  
  51.  
  52. //Set up HTTP request depending on whether secure or not.
  53. if($secure) {
  54.     $url = "https://".$hostAddr."/api/";
  55.  
  56.     $ssl_array = array('version' => 3);
  57.     $r = new HttpRequest("$url", HttpRequest::METH_POST, array('ssl' => $ssl_array));
  58. }
  59. else {
  60.     $url = "http://".$hostAddr."/api/";
  61.  
  62.     $r = new HttpRequest("$url", HttpRequest::METH_POST);
  63. }
  64.  
  65. //Send the Authorisation String
  66. $r->setBody("$authstr");
  67.  
  68.  
  69. //Send HTTP Request
  70. try {
  71.     $responce = $r->send()->getBody();
  72.     //echo($responce);
  73. } catch (HttpException $ex) {
  74.     if (isset($ex->innerException)){
  75.             returnNagios("UNKNOWN",$ex->innerException->getMessage());
  76.     }
  77.     else {
  78.         returnNagios("UNKNOWN", $ex->getMessage());
  79.     }
  80. }
  81.  
  82.  
  83. //Check to see if the Authorisation was successful
  84. try {
  85.     $xmlResponse = @new SimpleXMLElement($responce);
  86. }
  87. catch(Exception $e) {
  88.     returnNagios("UNKNOWN", $e->getMessage().". Is this a HP MSA P2000?");
  89. }
  90.  
  91. foreach($xmlResponse->OBJECT->PROPERTY as $Property) {
  92.  
  93.     foreach($Property->attributes() as $name => $val) {
  94.         if($name =="name" && $val =="response-type" && $Property == "success") {
  95.             $successful =1;
  96.         }
  97.     }
  98. }
  99.  
  100.  
  101. //If Auth was successfull continue
  102. if($successful) {
  103.     $sessionVariable =  (string) $xmlResponse->OBJECT->PROPERTY[2];
  104.    
  105.    
  106.     switch($command) {
  107.         case "status":
  108.             try {
  109.                
  110.                 //Get Disk Info
  111.                                 $regXML = getRequest($sessionVariable, "{$url}show/disks", $secure);
  112.                                 $regXML = new SimpleXMLElement($regXML);
  113.  
  114.                 foreach($regXML->OBJECT as $obj) {
  115.                                         $attr = $obj->attributes();
  116.                                         //Get HDD Statuses
  117.                                         if($attr['name']== "drive") {
  118.                                                 $type = "Disks";
  119.                                                 $statuses[$type][]= getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>'health'));
  120.                                         }
  121.                                 }
  122.                
  123.  
  124.                 //Get Sensor Information
  125.                                 $regXML = getRequest($sessionVariable, "{$url}show/sensor-status", $secure);
  126.                                 $regXML = new SimpleXMLElement($regXML);
  127.  
  128.                                 foreach($regXML->OBJECT as $obj) {
  129.                                         $attr = $obj->attributes();
  130.                                         if($attr['name']== "sensor") {
  131.                         switch((string) getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>'sensor-type'))) {
  132.                             case "3":
  133.                                 $type = "Temperature";
  134.                                 break;
  135.                             case "9":
  136.                                 $type = "Voltage";
  137.                                 break;
  138.                             case "2":
  139.                                 $type = "Overall";
  140.                                 break;
  141.                         }
  142.                                                 $statuses[$type][]= getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>'status'));
  143.                                         }
  144.                                 }
  145.  
  146.  
  147.                 //Get FRU Information
  148.                                 $regXML = getRequest($sessionVariable, "{$url}show/frus", $secure);
  149.                                 $regXML = new SimpleXMLElement($regXML);
  150.  
  151.                                 foreach($regXML->OBJECT as $obj) {
  152.                                         $attr = $obj->attributes();
  153.                                         if($attr['name']== "fru") {
  154.                                                 $type = (string) getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>'fru-shortname'));
  155.                                                 $statuses[$type][]= getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>'fru-status'));
  156.                                         }
  157.                                 }
  158.  
  159.  
  160.                 //Get Enclosure Information
  161.                                 $regXML = getRequest($sessionVariable, "{$url}show/enclosures", $secure);
  162.                                 $regXML = new SimpleXMLElement($regXML);
  163.  
  164.                                 foreach($regXML->OBJECT as $obj) {
  165.                                         $attr = $obj->attributes();
  166.                                         if($attr['name']== "enclosures") {
  167.                                                 $type = "Enclosures";
  168.                                                 $statuses[$type][]= getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>'health'));
  169.                                         }
  170.                                 }
  171.  
  172.    
  173.            
  174.                 if(count($statuses) < 1) {
  175.                     //Use API to run command and get XML
  176.                     $regXML = getRequest($sessionVariable, "{$url}show/enclosure-status", $secure);
  177.                     $regXML = new SimpleXMLElement($regXML);
  178.        
  179.            
  180.                     foreach($regXML->OBJECT as $obj) {
  181.                         //get statuses of components and enclosures and enter status into array
  182.  
  183.                         $attr = $obj->attributes();
  184.                         //Get all the enlosure components HDD, FAN, PSU etc
  185.                         if($attr['name']== "enclosure-component") {
  186.                             $type = (string) getEnclosureStatus($obj->PROPERTY, array('name'=>'display-name', 'value'=>'Type'));
  187.                             $statuses[$type][]= getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>'status'));
  188.                         }
  189.            
  190.                         //Get all overall enclosure status
  191.                         if($attr['name'] == "enclosure-environmental") {
  192.                             $type = "Enclosure";
  193.                             $statuses[$type][]= getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>'status'));              
  194.                         }
  195.                     }
  196.                 }
  197.                
  198.                 //print_r($statuses);
  199.             }
  200.             catch(Exception $e) {
  201.                 returnNagios("UNKNOWN", $e->getMessage());
  202.             }
  203.  
  204.             //loop through statuses array and create the Output. Also get the overall state.
  205.             //Use highest status as overall status.
  206.             //Count each type and produce output.
  207.    
  208.             if(isset($statuses)) {
  209.                 $overallStatus = "OK";
  210.                 $output = "";
  211.                 foreach($statuses as $typ=>$arrType) {
  212.                     $output .= $typ;
  213.                     $typeWarn =0;
  214.                     $typeOK =0;
  215.                     $typeCrit = 0; 
  216.    
  217.                     foreach($arrType as $arrTypeStatus) {
  218.                         switch($arrTypeStatus) {
  219.                             case "Fault" :
  220.                                 $typeCrit++;
  221.                                 break; 
  222.  
  223.                             case "Warning" :
  224.                                 $typeWarn++;
  225.                                 break;
  226.    
  227.                             case "OK" :
  228.                                 $typeOK++;
  229.                                 break;
  230.                             default:
  231.                                 $typeCrit++;
  232.                                 break;
  233.                         }
  234.                     }
  235.                
  236.                     if($typeWarn >0 && $typeCrit ==0) {
  237.                         $output .= " $typeWarn Warning, ";
  238.                         $overallStatus = "WARNING";
  239.                     }
  240.                     if($typeCrit > 0) {
  241.                         $output .= " $typeCrit Critical, ";
  242.                         $overallStatus = "CRITICAL";
  243.                     }
  244.                     if($typeCrit ==0 && $typeWarn ==0) {
  245.                         $output .= " $typeOK OK, ";
  246.                     }
  247.                 }
  248.             }
  249.             else {
  250.                 returnNagios("UNKNOWN", "Could Not Read API");
  251.             }
  252.             break;
  253.  
  254.         case "disk":
  255.             try {
  256.                 //Use API to run command and get XML
  257.                 $regXML = getRequest($sessionVariable, "{$url}show/disk-statistics", $secure);
  258.                 $regXML = new SimpleXMLElement($regXML);
  259.        
  260.                 foreach($regXML->OBJECT as $obj) {
  261.                     $attr = $obj->attributes();
  262.                        
  263.                     if($attr['name']=="disk-statistics") {
  264.                         $diskName = (string) getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>'durable-id'));
  265.                         $perfstats[$diskName]= getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>$stat), 1);
  266.                     }
  267.                 }
  268.             }
  269.             catch(Exception $e) {
  270.                 returnNagios("UNKNOWN", $e->getMessage().". Check firmware supports command.");
  271.             }
  272.             break;
  273.  
  274.         case "controller":
  275.             try {
  276.                 //Use API to run command and get XML
  277.                 $regXML = getRequest($sessionVariable, "{$url}show/controller-statistics", $secure);
  278.                 $regXML = new SimpleXMLElement($regXML);
  279.        
  280.                 foreach($regXML->OBJECT as $obj) {
  281.                     $attr = $obj->attributes();
  282.                        
  283.                     if($attr['name']=="controller-statistics") {
  284.                         $controllerName = (string) getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>'durable-id'));
  285.                         $perfstats[$controllerName]= getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>$stat));
  286.                     }
  287.                 }
  288.             }
  289.             catch(Exception $e) {
  290.                 returnNagios("UNKNOWN", $e->getMessage().". Check firmware supports command.");
  291.             }
  292.             break;
  293.  
  294.         case "vdisk":
  295.             try {
  296.                 //Use API to run command and get XML
  297.                 $regXML = getRequest($sessionVariable, "{$url}show/vdisk-statistics", $secure);
  298.                 $regXML = new SimpleXMLElement($regXML);
  299.        
  300.                 foreach($regXML->OBJECT as $obj) {
  301.                     $attr = $obj->attributes();
  302.                        
  303.                     if($attr['name']=="vdisk-statistics") {
  304.                         $vdiskName = (string) getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>'name'));
  305.                         $perfstats[$vdiskName]= getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>$stat));
  306.                     }
  307.                 }
  308.             }
  309.             catch(Exception $e) {
  310.                 returnNagios("UNKNOWN", $e->getMessage().". Check firmware supports command.");
  311.             }
  312.             break;
  313.  
  314.         case "volume":
  315.             try {
  316.                 //Use API to run command and get XML
  317.                 $regXML = getRequest($sessionVariable, "{$url}show/volume-statistics", $secure);
  318.                 $regXML = new SimpleXMLElement($regXML);
  319.        
  320.                 foreach($regXML->OBJECT as $obj) {
  321.                     $attr = $obj->attributes();
  322.                        
  323.                     if($attr['name']=="volume-statistics") {
  324.                         $volumeName = (string) getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>'volume-name'));
  325.                         $perfstats[$volumeName]= getEnclosureStatus($obj->PROPERTY, array('name'=>'name', 'value'=>$stat));
  326.                     }
  327.                 }
  328.             }
  329.             catch(Exception $e) {
  330.                 returnNagios("UNKNOWN", $e->getMessage().". Check firmware supports command.");
  331.             }
  332.             break;
  333.        
  334.         default :
  335.             echo "Unknown command specified";
  336.             Usage();
  337.             exit(3);
  338.             break;
  339.     }      
  340.  
  341.     if($command != "status") {
  342.    
  343.         if(isset($warning) && isset($critical)) {
  344.             $perfOutput = parsePerfData($perfstats, $uom,  $warnType, $warning, $critical);
  345.             $overallStatus = $perfOutput[1];
  346.             $output = "{$command} {$stat} - ".$perfOutput[0];
  347.         }
  348.         else {
  349.             $perfOutput = parsePerfData($perfstats, $uom);
  350.             $output = "{$command} {$stat} - ";
  351.             $output .= $perfOutput;
  352.             $overallStatus = "OK";
  353.         }
  354.     }
  355.  
  356.     returnNagios($overallStatus, $output);
  357.  
  358. }
  359. else {
  360.     //if Auth is unsucessful return Status UKNOWN
  361.     returnNagios("UNKNOWN", "Authentication Unsuccessful");
  362. }
  363.  
  364. function parsePerfData($perfData, $uom="", $warnType=false, $warning=0, $critical=0) {
  365.     $output ="";
  366.     $perfOutput ="";
  367.     $overallState = "OK";
  368.  
  369.     foreach($perfData as $key => $val) {
  370.         $perfOutput .= " {$key}={$val}{$uom};";    
  371.         if($warnType != false) {
  372.             switch($warnType) {
  373.                 case "lessthan":
  374.                     if($val < $warning && $val > $critical) {
  375.                         $overallState = "WARNING";
  376.                         $output .= "WARNING ";     
  377.                     }
  378.                     if($val < $critical) {
  379.                         $overallState = "CRITICAL";
  380.                         $output .= "CRITICAL ";
  381.                     }
  382.                     break;
  383.  
  384.                 case "greaterthan":
  385.                     if($val > $warning && $val < $critical) {
  386.                         $overallState = "WARNING";
  387.                         $output .= "WARNING ";     
  388.                     }
  389.                     if($val > $critical) {
  390.                         $overallState = "CRITICAL";
  391.                         $output .= "CRITICAL ";
  392.                     }
  393.                        
  394.                     break;
  395.             }
  396.  
  397.             $perfOutput .=$warning.";".$critical."; ";
  398.         }
  399.         else {
  400.             $perfOutput .= ";; ";
  401.         }
  402.         $output .= " {$key} {$val}{$uom}, ";
  403.     }
  404.     $output = $output."|".$perfOutput;
  405.    
  406.     if($warnType != false) {
  407.         $arrReturn = array($output, $overallState);
  408.         return $arrReturn;
  409.     }
  410.     else {
  411.         return $output;
  412.     }
  413. }
  414.  
  415. function getEnclosureStatus($encXML, $propertyName) {
  416.  
  417.     //Loop through all Property Values in the Object and match values passed in with array key value pair
  418.     foreach($encXML as $prop) {
  419.         $attr = $prop->attributes();
  420.         if($attr[$propertyName['name']] == $propertyName['value']) {
  421.             $status = (string)$prop;
  422.         }
  423.     }
  424.    
  425.     if(!isset($status)) {
  426.         throw new Exception('No Value Found'); 
  427.     }
  428.  
  429.     return $status;
  430. }
  431.  
  432. function getRequest($sessionKey, $reqUrl, $secure) {
  433.    
  434.     //Send HTTP request to API and return response
  435.  
  436.     if($secure) {
  437.         $ssl_array = array('version' => 3);
  438.         $r = new HttpRequest("$reqUrl", HttpRequest::METH_GET, array('ssl' => $ssl_array));
  439.     }
  440.     else {
  441.         $r = new HttpRequest("$reqUrl", HttpRequest::METH_GET);
  442.     }
  443.  
  444.     $r->setOptions(array('cookies'=>array('wbisessionkey'=>$sessionKey, 'wbiusername'=>'')));
  445.     $r->setBody();
  446.  
  447.     try {
  448.         $responce = $r->send()->getBody();
  449.         return $responce;
  450.     } catch (HttpException $ex) {
  451.             throw($ex);
  452.     }
  453. }
  454.  
  455. function Usage() {
  456.     //echo usage for the script
  457.  
  458.     echo "
  459. This script sends HTTP Requests to the specified HP P2000 Array to determine its health
  460. and outputs performance data fo other checks.
  461. Required Variables:
  462.     -H Hostname or IP Address
  463.     -U Username
  464.     -P Password
  465.        
  466. Optional Variables:
  467.     These options are not required. Both critical and warning must be specified together
  468.     If warning/critical is specified -t must be specified or it defaults to greaterthan.               
  469.     -s Set to 1 for Secure HTTPS Connection
  470.     -c Sets what you want to do
  471.         status - get the status of the SAN
  472.         disk - Get performance data of the disks
  473.         controller - Get performance data of the controllers
  474.         vdisk - Get performance data of the VDisks
  475.         volume - Get performance data of the volumes
  476.     -S specify the stats to get for performance data. ONLY works when -c is specified
  477.     -u Units of measure. What should be appended to performance values. ONLY used when -c specified.
  478.     -w Specify Warning value
  479.     -C Specify Critical value
  480.     -t Specify how critical warning is calculated (DEFAULT greaterthan)
  481.         lessthan - if value is lessthan warning/critical return warning/critical
  482.         greaterthan - if value is greaterthan warning/critical return warning/critical
  483.    
  484. Examples
  485.     Just get the status of the P2000
  486.     ./check_p2000_api.php -H 192.168.0.2 -U manage -P !manage
  487.  
  488.     Get the CPU load of the controllers and append % to the output
  489.     ./check_p2000_api.php -H 192.168.0.2 -U manage -P !manage -s 1 -c controller -S cpu-load -u \"%\"
  490.  
  491.     Get the CPU load of the controllers and append % to the output warning if its over 30 or critical if its over 60
  492.     ./check_p2000_api.php -H 192.168.0.2 -U manage -P !manage -s 1 -c controller -S cpu-load -u \"%\" -w 30 -C 60
  493.  
  494. Setting option -c to anything other than status will output performance data for Nagios to process.
  495. You can find certain stat options to use by logging into SAN Manager through the web interface and
  496. manually running the commands in the API. Some options are iops, bytes-per-second-numeric, cpu-load,
  497. write-cache-percent and others. If using Warning/Critical options specify a stat without any Units
  498. otherwise false states will be returned. You can specify units yourself using -u option.
  499.  
  500. ";
  501. }
  502.  
  503. function returnNagios($Result="UNKNOWN", $message="") {
  504.     //Return to nagios with appropriate exit code
  505.  
  506.         switch($Result) {
  507.                 case "OK":
  508.                         echo "OK : ".$message;
  509.                         exit(0);
  510.                 case "WARNING":
  511.                         echo "WARNING : ".$message;
  512.                         exit(1);
  513.                 case "CRITICAL":
  514.                         echo "CRITICAL : ".$message;
  515.                         exit(2);
  516.                 case "UNKNOWN":
  517.                         echo "UNKNOWN: ".$message;
  518.                         exit(3);
  519.         }
  520. }
  521.  
  522. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement