Guest User

ZabbixAPI.class.php

a guest
Mar 28th, 2016
760
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 14.13 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Zabbix PHP API (via the JSON-RPC Zabbix API)
  4.  * @version 1.0 Public Release - December 23, 2009
  5.  * @author Andrew Farley @ http://andrewfarley.com
  6.  * @see http://andrewfarley.com/zabbix_php_api
  7.  *
  8.  * Based on the Zabbix 1.8 API - The official docs are still slim...
  9.  * @see http://www.zabbix.com/documentation/1.8/api
  10.  *
  11.  * @requires PHP 5.2 or greater
  12.  * @requires PHP JSON functions (json_encode/json_decode)
  13.  * @requires PHP CURL
  14.  * @requires Zabbix to be 1.7.2 or greater (so it has the API), preferably 1.8
  15.  *
  16.  * @copyright 2009 Andrew Farley - http://andrewfarley.com
  17.  * @license Wishlist-ware
  18.  * --------------------------------------------------------------------------------
  19.  * Definition of "Wishlist-ware"
  20.  *
  21.  * Andrew Farley (andrewfarley.com) wrote this file. As long as you retain the
  22.  * copyright and license you can do whatever you want with this. If you use this
  23.  * and it helps benefit you or your company (and you can afford it) buy me an item
  24.  * from one of my wish lists (on my website) or if we cross paths buy me caffeine
  25.  * in some form and we'll call it even!
  26.  * --------------------------------------------------------------------------------
  27.  *
  28.  * Design Notes:
  29.  *      This was designed using a static design structure, where you call all
  30.  *      methods of this class statically, and it returns data from the Zabbix server
  31.  *      directly to you.  This was so that this class could remain abstracted and not
  32.  *      require instantiation all over the place on large and fractured codebases.
  33.  *
  34.  *      Note: None of the actual objects/methods were implemented in this class, this
  35.  *      leaves this class open to be able to use future methods and objects when they
  36.  *      implement them.  It also makes it easier to make a mistake in calling this
  37.  *      class though as it does no validation of your input, checking for a valid
  38.  *      method, or parameters before calling the remote API.  A future version of the
  39.  *      API will (possibly) create all the classes necessary to help validate data
  40.  *      and ease the use of this API.
  41.  *
  42.  * Simple Usage Examples:
  43.  *      This is necessary before doing anything.  Your user must have API privileges
  44.  *          ZabbixAPI::login('http://mywebsite.com/path/to/zabbix', 'api_user', 'api_pass');
  45.  *      With no parameters, this simply grabs all valid userid into an array
  46.  *          $users = ZabbixAPI::fetch_column('user','get');
  47.  *      If you want verbose output from any fetch request, add parameter (extendoutput = 1)
  48.  *          $all_hosts_verbose = ZabbixAPI::fetch_array('host','get',array('extendoutput'->1));
  49.  *      This is how you update a user's properties, you just need the userid, and the
  50.  *      value you want to set (in this case, refresh)
  51.  *          $result = ZabbixAPI::query('user','update',array('userid'=>1, 'refresh'=>1000));
  52.  *
  53.  *      NOTE: If any methods return PHP === FALSE, then you can use
  54.  *      ZabbixAPI::getLastError() to check what the problem was!  :)
  55.  */
  56. class ZabbixAPI {
  57.     /**
  58.      * Private constants, not intended to be changed or edited
  59.      */
  60.     CONST ZABBIX_API_URL = 'api_jsonrpc.php';
  61.     CONST PHPAPI_VERSION = '1.0';
  62.  
  63.     // The private instance of this class
  64.     private static $instance;
  65.    
  66.     /**
  67.      * Private class variables
  68.      */
  69.     protected $url              = '';
  70.     protected $username         = '';
  71.     protected $password         = '';
  72.     protected $auth_hash        = NULL;
  73.     protected $debug            = false;
  74.     protected $last_error       = false;
  75.    
  76.     // we don't permit an explicit call of the constructor! ($api = new ZabbixAPI())
  77.     protected function __construct() { }
  78.     // we don't permit cloning of this static class ($x = clone $v)
  79.     protected function __clone() { }
  80.    
  81.     /**
  82.      * Public facing functions
  83.      */
  84.      
  85.      /**
  86.       * Login, this will attempt to login to Zabbix with the specified username and password
  87.       */
  88.     public static function login($url, $username, $password) {
  89.         // Initialize instance if it isn't already
  90.         self::__init();
  91.         // Set properties
  92.         // Add ending / if it's not there
  93.         if (substr($url,strlen($url)-1,1) != '/')
  94.             $url .= '/';
  95.         self::$instance->url        = $url;
  96.         self::$instance->username   = $username;
  97.         self::$instance->password   = $password;
  98.         // Attempt to login
  99.         return self::$instance->__login();
  100.     }
  101.  
  102.      /**
  103.       * Logout, this will attempt to logout from Zabbix
  104.       */
  105.     public static function logout($url, $username) {
  106.         // Initialize instance if it isn't already
  107.         self::__init();
  108.         // Set properties
  109.         // Add ending / if it's not there
  110.         if (substr($url,strlen($url)-1,1) != '/')
  111.             $url .= '/';
  112.         self::$instance->url        = $url;
  113.         self::$instance->username   = $username;
  114.         // Attempt to login
  115.         return self::$instance->__logout();
  116.     }
  117.    
  118.     public static function debugEnabled($value) {
  119.         // Initialize instance if it isn't already
  120.         self::__init();
  121.         if ($value === TRUE)
  122.             self::$instance->debug = true;
  123.         else
  124.             self::$instance->debug = false;
  125.     }
  126.    
  127.     /**
  128.      * Generic API Call function, with no method or property validation
  129.      */
  130.     public static function fetch($object, $method, $properties = array()) {
  131.         return self::$instance->__callAPI($object.'.'.$method, $properties);
  132.     }
  133.    
  134.     /**
  135.      * Alias to fetch, but simply returns TRUE or FALSE.  This is typically for doing updates
  136.      * and other "set/update" type commands
  137.      */
  138.     public static function query($object, $method, $properties = array()) {
  139.         return ( self::fetch($object, $method, $properties) == FALSE ? FALSE : TRUE );
  140.     }
  141.  
  142.     /**
  143.      * Force return value to be an array
  144.      */
  145.     public static function fetch_array($object, $method, $properties = array()) {
  146.         $return = self::$instance->fetch($object, $method, $properties);
  147.         if (is_array($return))
  148.             return $return;
  149.         else
  150.             return array($return);
  151.     }
  152.    
  153.     /**
  154.      * Get the last error that
  155.      */
  156.     public static function getLastError() {
  157.         return self::$instance->last_error;
  158.     }
  159.    
  160.     /**
  161.      * Force return value to be a string
  162.      */
  163.     public static function fetch_string($object, $method, $properties = array()) {
  164.         $return = self::$instance->fetch($object, $method, $properties);
  165.         if (is_array($return))
  166.             return self::__return_first_string($return);
  167.         else
  168.             return $return;
  169.     }
  170.  
  171.     /**
  172.      * Force return value to be the first element of an array (first "row" or record)
  173.      */
  174.     public static function fetch_row($object, $method, $properties = array()) {
  175.         $return = self::$instance->fetch($object, $method, $properties);
  176.         if (is_array($return))
  177.             foreach ($return as $item)
  178.                 return $item;
  179.         else
  180.             return $return;
  181.     }
  182.    
  183.     /**
  184.      * Force return value to be the first column of the first row of an array, in the form of an array
  185.      */
  186.     public static function fetch_column($object, $method, $properties = array()) {
  187.         $return = self::$instance->fetch($object, $method, $properties);
  188.         if (!is_array($return))
  189.             return array($return);
  190.         else {
  191.             $output = array();
  192.             foreach ($return as $item) {
  193.                 $output[] = array_shift($item);
  194.             }
  195.             return $output;
  196.         }
  197.     }
  198.    
  199.     /**
  200.      * Private/protected functions, not to be called by any code outside this class
  201.      */
  202.      
  203.     /**
  204.      * Private init function, which is called to ensure our instance is initialized
  205.      */
  206.     private static function __init() {
  207.         if (get_class(self::$instance) != "ZabbixAPI")
  208.             self::$instance = new ZabbixAPI();
  209.     }
  210.    
  211.     /**
  212.      * Recursive function to get the first non array element of a multidimensional array
  213.      */
  214.     private static function __return_first_string($array) {
  215.         foreach($array as $item) {
  216.             if (is_array($item))
  217.                 return self::__return_first_string($item);
  218.             else
  219.                 return $item;
  220.         }
  221.     }
  222.    
  223.     /**
  224.      * Builds a JSON-RPC request, designed just for Zabbix
  225.      */
  226.     private static function __buildJSONRequest($method, $params = array()) {
  227.         // This is our default JSON array
  228.         $request = array(
  229.             'auth' => self::$instance->auth_hash,
  230.             'method' => $method,
  231.             'id' => 1,  // NOTE: this needs to be fixed I think?
  232.             'params' => ( is_array($params) ? $params : array() ),
  233.             'jsonrpc' => "2.0"
  234.         );
  235.         // Return our request, in JSON format
  236.         return json_encode($request);
  237.     }
  238.    
  239.     /**
  240.      * The private function that performs the call to a remote RPC/API call
  241.      */
  242.     private function __callAPI($method, $params = array()) {
  243.         // Initialize instance if it isn't already, so no fatal PHP errors
  244.         self::__init();
  245.        
  246.         // Reset our "last error" variable
  247.         self::$instance->last_error = false;
  248.        
  249.         // Make sure we're logged in, or trying to login...
  250.         if ($this->auth_hash == NULL && $method != 'user.authenticate')
  251.             return false;  // If we're not logged in, no wasting our time here
  252.        
  253.         // Try to retrieve this...
  254.         $data = self::__jsonRequest(
  255.             $this->url.self::ZABBIX_API_URL,
  256.             self::__buildJSONRequest( $method, $params )
  257.         );
  258.        
  259.         if ($this->debug)
  260.             echo "Got response from API: ($data)\n";
  261.        
  262.         // Convert return data (JSON) to PHP array
  263.         $decoded_data = json_decode($data, true);
  264.        
  265.         if ($this->debug)
  266.             echo "Response decoded: (".print_r($decoded_data,true)."\n";
  267.        
  268.         // Return the data if it's valid
  269.         if ( isset($decoded_data['id']) && $decoded_data['id'] == 1 && !empty($decoded_data['result']) ) {
  270.             return $decoded_data['result'];
  271.         } else {
  272.             // If we had a actual error, put it in our instance to be able to be retrieved/queried
  273.             if (!empty($decoded_data['error']))
  274.                 self::$instance->last_error = $decoded_data['error'];
  275.             return false;
  276.         }
  277.     }
  278.    
  279.     /**
  280.      * Private login function to perform the login
  281.      */
  282.     private function __login() {
  283.         // Try to login to our API
  284.         $data = $this->__callAPI('user.authenticate', array( 'password' => $this->password, 'user' => $this->username ));
  285.        
  286.         if ($this->debug)
  287.             echo "__login() Got response from API: ($data)\n";
  288.        
  289.         if (isset($data) && strlen($data) == 32) {
  290.             $this->auth_hash = $data;
  291.             return true;
  292.         } else {
  293.             $this->auth_hash = NULL;
  294.             return false;
  295.         }
  296.     }
  297.  
  298.     /**
  299.      * Private login function to perform the login
  300.      */
  301.     private function __logout() {
  302.         // Try to logout of our API
  303.         $data = $this->__callAPI('user.logout', array( 'user' => $this->username, 'auth' => self::$instance->auth_hash ));
  304.        
  305.         if ($this->debug)
  306.             echo "__logout() Got response from API: ($data)\n";
  307.        
  308.         if (isset($data) && strlen($data) == 1) {
  309.             $this->auth_hash = NULL;
  310.             return true;
  311.         } else {
  312.             $this->auth_hash = $data;
  313.             return false;
  314.         }
  315.     }
  316.    
  317.     /**
  318.      * Note: Headers must be in the string form, in an array...
  319.      *   eg. $headers  =  array('Content-Type: application/json-rpc', 'Another-Header: value goes here');
  320.      */
  321.     private static function __jsonRequest($url, $data = '', $headers = array()){
  322.         $c = curl_init($url);
  323.         // These are required for submitting JSON-RPC requests
  324.         $headers[]  = 'Content-Type: application/json-rpc';
  325.         // Well, ok this one isn't, but it's good to conform (sometimes)
  326.         $headers[]  = 'User-Agent: ZabbixAPI v'.ZabbixAPI::PHPAPI_VERSION.' - http://andrewfarley.com/zabbix_php_api';
  327.    
  328.         $opts = array(
  329.                 CURLOPT_RETURNTRANSFER => true,     // Allows for the return of a curl handle
  330.                 //CURLOPT_VERBOSE => true,          // outputs verbose curl information (like --verbose with curl on the cli)
  331.                 //CURLOPT_HEADER => true,           // In a verbose output, outputs headers
  332.                 CURLOPT_TIMEOUT => 30,              // Maximum number of seconds to allow curl to process the entire request
  333.                 CURLOPT_CONNECTTIMEOUT => 5,        // Maximm number of seconds to establish a connection, shouldn't take 5 seconds
  334.                 CURLOPT_SSL_VERIFYHOST => false,    // Incase we have a fake SSL Cert...
  335.                 CURLOPT_SSL_VERIFYPEER =>false,     //    Ditto
  336.                 CURLOPT_FOLLOWLOCATION => true,     // Incase there's a redirect in place (moved zabbix url), follow it automatically
  337.                 CURLOPT_FRESH_CONNECT => true       // Ensures we don't use a cached connection or response
  338.                  );
  339.    
  340.         // If we have headers set, put headers into our curl options
  341.         if(is_array($headers) && count($headers)){
  342.             $opts[CURLOPT_HTTPHEADER] = $headers;
  343.         }
  344.        
  345.         // This is a POST, not GET request
  346.         $opts[CURLOPT_CUSTOMREQUEST] = "POST";
  347.         $opts[CURLOPT_POSTFIELDS] = ( is_array($data) ? http_build_query($data) : $data );
  348.        
  349.         // This is useful, incase we're remotely attempting to consume Zabbix's API to compress our data, save some bandwidth
  350.         $opts[CURLOPT_ENCODING] = 'gzip';
  351.        
  352.         // If we're in debug mode
  353.         if (self::$instance->debug) {
  354.             echo "CURL URL: $url\n<br>";
  355.             echo "CURL Options: ".print_r($opts, true);
  356.         }
  357.  
  358.         // Go go gadget!  Do your magic!
  359.         curl_setopt_array($c, $opts);
  360.         $ret = @curl_exec($c);
  361.         curl_close($c);
  362.         return $ret;
  363.     }
  364. }
Advertisement
Add Comment
Please, Sign In to add comment