class ZabbixAPI

TODO Create class to capture resultant data

Main Zabbix API class.

Attributes

auth[RW]
debug_level[RW]
method[RW]
params[RW]
proxy_server[RW]
verify_ssl[RW]

Public Class Methods

get_version() click to toggle source
# File zbxapi.rb, line 180
def self.get_version
  "#{ZBXAPI_VERSION}.#{ZBXAPI_REVISION}"
end
new(url,*args) { |self| ... } click to toggle source
The initialization routine for the Zabbix API class
* url is a string defining the url to connect to, it should only point to the base url for Zabbix, not the api directory
* debug_level is the default level to be used for debug messages
Upon successful initialization the class will be set up to allow a connection to the Zabbix server
A connection however will not have been made, to actually connect to the Zabbix server use the login method

options: Parameter Default Description :debug 0 Debug Level :returntype :result Return the value of “result” from the json result :verify_ssl true Enable checking the SSL Cert

# File zbxapi.rb, line 92
def initialize(url,*args)
  options=args[0]
  options ||= {}
  if options.is_a?(Integer)
    warn "WARNING: Initialization has changed, backwards compatability is being used."
    warn "WARNING: Use ZabbixAPI.new(url,:debug=>n,:returntype=>:result) to have the"
    warn "WARNING: same capability as previous versions."
    warn "WARNING: This depreciated functionality will be removed in a future release"
    options={:debug=>0,:returntype=>:result}
  end

  #intialization of instance variables must happen inside of instantiation
  @id=0
  @auth=''
  @url=nil
  @verify_ssl=true
  @proxy_server=nil
  @custom_headers={}
  @user_name=''
  @password=''

  set_debug_level(options[:debug] || 0)
  @returntype=options[:returntype] || :result
  @orig_url=url  #save the original url
  @url=URI.parse(url+'/api_jsonrpc.php')

  if options.has_key?:verify_ssl
    @verify_ssl=options[:verify_ssl]
  else
    @verify_ssl = true
  end

  if options.has_key?:http_timeout
    @http_timeout=options[:http_timeout]
  else
    #if not set, default http read_timeout=60
    @http_timeout=nil
  end

  if options.has_key?:custom_headers
    @custom_headers = options[:custom_headers] unless options[:custom_headers].nil?
  else
    @custom_headers = {}
  end

  #Generate the list of sub objects dynamically, from all objects
  #derived from ZabbixAPI_Base
  objects=true
  silence_warnings do
    objects=Object.constants.map do |i|
      obj=Object.const_get(i.intern)
      if obj.is_a?(Class) && ([ZabbixAPI_Base]-obj.ancestors).empty?
        obj
      else
        nil
      end
    end.compact-[ZabbixAPI_Base]
  end

  @objects={}

  objects.each do |i|
    i_s=i.to_s.downcase.intern
    @objects[i_s]=i.new(self)
    self.class.define_method(i_s) do
      instance_variable_get(:@objects)[i_s]
    end
  end

  @id=0

  debug(6,:msg=>"protocol: #{@url.scheme}, host: #{@url.host}")
  debug(6,:msg=>"port: #{@url.port}, path: #{@url.path}")
  debug(6,:msg=>"query: #{@url.query}, fragment: #{@url.fragment}")

  if block_given?
    yield(self)
  end
end

Public Instance Methods

API_version(options={}) click to toggle source

returns the version number for the API from the server

# File zbxapi.rb, line 309
def API_version(options={})
  return "#{@major}.#{@minor}"
end
api_call(method,options={}) click to toggle source

api_call This is the main function for performing api requests method is a string denoting the method to call options is a hash of options to be passed to the function

# File zbxapi.rb, line 345
def api_call(method,options={})
  debug(6,:msg=>"Method",:var=>method)
  debug(6,:msg=>"Options",:var=>options)

  obj=json_obj(method,options)
  result=do_request(obj)
  if @returntype==:result
    result["result"]
  else
    result.merge!({:method=>method, :params=>options})
    @returntype.new(result)
  end
end
api_info(request=:objects,*options) click to toggle source
# File zbxapi.rb, line 359
def api_info(request=:objects,*options)
  options = options[0] || {}
  version=options[:version] || nil
  request_type=options[:params] || :valid

  case request
    when :objects then
      @objects.keys.map { |k| k.to_s }
    else
      obj,meth=request.split(".")
      if meth then
        case request_type
          when :valid
            @objects[obj.intern].valid_params(meth.intern,version)
          when :required
            @objects[obj.intern].required_params(meth.intern,version)
        end
      else
        @objects[obj.intern].api_methods.map{ |m| m.to_s }
      end
  end
end
checkauth() click to toggle source

wrapper to loggedin? returns nothing, raises the exception ZbxAPI_ExceptionBadAuth if loggedin? returns false

# File zbxapi.rb, line 304
def checkauth
  raise ZbxAPI_ExceptionBadAuth, 'Not logged in' if !loggedin?
end
checkversion(major,minor,options=nil) click to toggle source

Function to test whether or not a function will work with the current API version of the server If no options are presented the major and minor are assumed to be the minimum version number suitable to run the function Does not explicitly return anything, but raises ZbxAPI_ExceptionVersion if there is a problem

# File zbxapi.rb, line 333
def checkversion(major,minor,options=nil)
  caller[0]=~/`(.*?)'/
  caller_func=$1

  raise ZbxAPI_ExceptionVersion, "#{caller_func} requires API version #{major}.#{minor} or higher" if major>@major or (minor>@minor and major>=@major)

end
json_obj(method,params={}) click to toggle source

wraps the given information into the appropriate JSON object

  • method is a string

  • params is a hash of the parameters for the method to be called

Returns a hash representing a Zabbix API JSON call

# File zbxapi.rb, line 188
def json_obj(method,params={})
  obj =
    {
      'jsonrpc'=>'2.0',
      'method'=>method,
      'params'=>params,
      'auth'=>@auth,
      'id'=>@id
    }

  # https://www.zabbix.com/documentation/2.4/manual/api/reference/apiinfo/version
  # https://www.zabbix.com/documentation/2.4/manual/api/reference/user/login
  # Zabbix Doc(2.4): This method is available to unauthenticated
  #  users and must be called without the auth parameter
  #  in the JSON-RPC request.
  debug(4, :var => method,:msg => "Method:")
  obj.delete("auth") if ["apiinfo.version",
                         "user.login",
                        ].any? { |str| method =~ /#{str}/i }

  debug(10, :msg=>"json_obj:  #{obj}")
  return obj.to_json
end
loggedin?() click to toggle source

Returns true if a login was performed

# File zbxapi.rb, line 298
def loggedin?
  !(@auth=='' or @auth.nil?)
end
login(user='',password='',save=true) click to toggle source

Performs a log in to the Zabbix server

  • user is a string with the username

  • password is a string with the user''s password

  • save tells the method to save the login details in internal class variables or not

Raises:

  • Zbx_API_ExeeptionBadAuth is raised when one of the following conditions is met

    1. no-string variables were passed in

    2. no username or password was passed in or saved from a previous login

    3. login details were rejected by the server

  • ZbxAPI_ExceptionBadServerUrl

    1. There was a socket error

    2. The url used to create the class was bad

    3. The connection to the server was refused

# File zbxapi.rb, line 228
def login(user='',password='',save=true)
  if user.class!=String or password.class!=String
    raise ZbxAPI_ExceptionBadAuth.new,'Login called with non-string values'
  end
  if (user!='' and password!='') then
    l_user = user
    l_password = password
    if save then
      @user_name=user
      @password=password
    end
  elsif (@user_name!='' and @password!='') then
    l_user = @user_name
    l_password = @password
  end

  #Somewhere in the 1.8.x cycle it was decided to do deprecate with user.authenticate
  #however it was not documented well, so we will try uer.login first, and fall
  #back to user.authenticate as user.login does not exist in 1.8.3
  login_methods=["user.login","user.authenticate"]

  begin
    result = do_request(json_obj(login_methods.first,{'user'=>l_user,'password'=>l_password}))
    @auth=result['result']

    #setup the version variables
    @major,@minor=do_request(json_obj('apiinfo.version',{}))['result'].split('.')
    @major=@major.to_i
    @minor=@minor.to_i
  rescue ZbxAPI_ExceptionLoginPermission => e
    login_methods.delete_at(0)
    if !login_methods.empty?
      retry
    else
      raise ZbxAPI_ExceptionBadAuth.new('Invalid User or Password',:error_code=>e.error_code)
    end
  rescue SocketError
    raise ZbxAPI_ExceptionBadServerUrl.new("Socket Error")
  rescue JSON::ParserError
    raise ZbxAPI_ExceptionBadServerUrl
  rescue Errno::ECONNREFUSED
    raise ZbxAPI_ExceptionBadServerUrl
  rescue => e
    raise ZbxAPI_ExceptionBadAuth.new('General Login error, check host connectivity.')
  end

  return self
end
logout() click to toggle source
# File zbxapi.rb, line 277
def logout
  do_request(json_obj('user.logout'))
end
raw_api(method,params=nil) click to toggle source

Provides raw access to the API via a small wrapper. method is the method to be called params are the parameters to be passed to the call returns a hash of the results from the server

# File zbxapi.rb, line 317
def raw_api(method,params=nil)
  debug(6,:var=>method,:msg=>"method")
  debug(6,:var=>params,:msg=>"Parameters")

  checkauth
  checkversion(1,1)
  params={} if params==nil

  obj=do_request(json_obj(method,params))
  return obj['result']
end
set_proxy(address,port,user=nil,password=nil) click to toggle source

Configure the information for the proxy server to be used to connect to the Zabbix server

# File zbxapi.rb, line 174
def set_proxy(address,port,user=nil,password=nil)
  @proxy_server={:address=>address,:port=>port,
                 :user=>user, :password=>password}
  return self
end
test_login() click to toggle source

Tests to determine if the login information is still valid returns: true if it is valid or false if it is not.

# File zbxapi.rb, line 283
def test_login
  if @auth!='' then
    result = do_request(json_obj('user.checkauth',
      {'sessionid'=>@auth}))
    if !result['result'] then
      @auth=''
      return false  #auth hash bad
    end
      return true   #auth hash good
  else
    return false
  end
end

Private Instance Methods

do_request(json_obj,truncate_length=5000) click to toggle source

Sends JSON encoded string to server truncate_length determines how many characters at maximum should be displayed while debugging before truncation should occur.

# File zbxapi.rb, line 404
  def do_request(json_obj,truncate_length=5000)
    redirects=0
    begin  # This is here for redirects
      http=select_http_obj
      response = nil
#    http.set_debug_output($stderr)                                  #Uncomment to see low level HTTP debug
      headers={
        'Content-Type'=>'application/json-rpc',
        'User-Agent'=>'Zbx Ruby CLI'
      }.merge(@custom_headers)

      debug(4,:msg=>"Sending: #{json_obj}")
      response = http.post(@url.path, json_obj,headers)
      debug(4,:msg=>"Response Code: #{response.code}")
      debug(4,:var=>response.body,:msg=>"Response Body",:truncate=>truncate_length)
      case response.code.to_i
        when 301
          puts "Redirecting to #{response['location']}"
          @url=URI.parse(response['location'])
          raise Redirect
        when 500
          raise ZbxAPI_GeneralError.new("Zabbix server returned an internal error\n Call: #{json_obj}", :retry=>true)
      end

      @id+=1  # increment the ID value for the API call

      # check return code and throw exception for error checking
      resp = JSON.parse(response.body) #parse the JSON Object so we can use it
      if !resp["error"].nil?
        errcode=resp["error"]["code"].to_i
        case errcode
          when -32602 then
            raise ZbxAPI_ExceptionLoginPermission.new(resp["error"],:error_code=>errcode,:retry=>true)
          when -32500 then
            raise ZbxAPI_ExceptionPermissionError.new(resp["error"],:error_code=>errcode,:retry=>true)
          else
            puts "other error"
            raise ZbxAPI_GeneralError, resp["error"]
        end
      end

      return resp

    rescue Redirect
      redirects+=1
      retry if redirects<=5
      raise ZbxAPI_GeneralError, "Too many redirects"
    rescue NoMethodError
      raise ZbxAPI_GeneralError.new("Unable to connect to #{@url.host}: \"#{e}\"", :retry=>false)
    end
  end
select_http_obj() click to toggle source

Select the http object to be used.

# File zbxapi.rb, line 385
def select_http_obj
  if @proxy_server
    http = Net::HTTP::Proxy(@proxy_server[:address],@proxy_server[:port],
          @proxy_server[:user],@proxy_server[:password]).new(@url.host,@url.port)
  else
    http = Net::HTTP.new(@url.host, @url.port)
  end
  http.use_ssl=true if @url.class==URI::HTTPS
  if !@verify_ssl
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @url.class==URI::HTTPS
  end
  http.read_timeout=@http_timeout unless @http_timeout.nil?

  http
end