Pull to refresh

Разбираемся с Zabbix API в C#

Reading time4 min
Views11K
У заббикса есть открытое API для доступа к функциям сервера мониторинга. К сожалению реализация библиотеки для доступа к API существует только для Ruby, PHP и Python. Пришлось изобретать велосипед самостоятельно. Доступ ко всем функциям идет через JSONRPC. Для примера запрос, ответ функции получения версии Zabbix API выглядит примерно так:
{ "jsonrpc":"2.0", "method":"apiinfo.version", "params":[], "auth":"a6e895b98fde40f4f7badf112fd983bf", "id":2 } <br>{ "jsonrpc":"2.0", "result":"1.3", "id":2 } * This source code was highlighted with Source Code Highlighter.


Подробное описание протокола JSON-RPC не входит в цель статьи, приступим к реализации:
  1.     private string GetWebRequest(string body)
  2.     {
  3.       WebRequest wb = WebRequest.Create(url);
  4.       wb.ContentType = @"application/json-rpc";
  5.       wb.Credentials = CredentialCache.DefaultCredentials;
  6.       ASCIIEncoding encoding = new ASCIIEncoding();
  7.       string postData = body;
  8.       byte[] data = encoding.GetBytes(postData);
  9.       wb.Method = "POST";
  10.       wb.ContentLength = data.Length;
  11.       Stream newStream = wb.GetRequestStream();
  12.       newStream.Write(data, 0, data.Length);
  13.       newStream.Close();
  14.       HttpWebResponse response = (HttpWebResponse)wb.GetResponse();
  15.       Stream dataStream = response.GetResponseStream();
  16.       StreamReader reader = new StreamReader(dataStream);
  17.       return reader.ReadToEnd();
  18.     }    
  19.     public string obj2json(object obj)
  20.     {
  21.       JavaScriptSerializer serializer = new JavaScriptSerializer();
  22.       return serializer.Serialize(obj);
  23.     }
  24.     public string CallApi(string method, object param)
  25.     {
  26.       object Query = new
  27.       {
  28.         jsonrpc = "2.0",
  29.         auth = auth_hash,
  30.         id = id.ToString(),
  31.         method = method,
  32.         Params = param
  33.       };
  34.       String qr = obj2json(Query);
  35.       qr=qr.Replace("Params", "params");
  36.       id++;
  37.       string result = GetWebRequest(qr);
  38.       return result;
  39.     }

* This source code was highlighted with Source Code Highlighter.

Функция CallAPI выполняет вызов API функции. Принимает метод и его параметры (в виде объекта согласно документации Zabbix API). Примеры использования будут чуть ниже. Предназначение obj2json, и GetWebRequest думаю очевидно, добавлю лишь что запрос отправляется методом POST. Рассмотрим использование этой функции на примере авторизации на сервере. Для авторизации нам необходимо отправить запрос метода «user.authenticate» с параметрами user и password. Результатом будет auth_hash, который является полем каждого последующего запроса. Готовая функция для авторизации с учетом вышесказанного будет выглядеть примерно так:
  1.     public bool login()
  2.     {
  3.       bool res;
  4.       Update(new UpdateInfoMessage(this) { message = "Попытка авторизоваться", status = "LOGIN" });
  5.       try
  6.       {
  7.         var userinfo = new { user = _user, password = _password };
  8.         string result = CallApi("user.authenticate", userinfo);
  9.         auth_hash = (serializer.Deserialize<string>(result)).result;
  10.         res=true;
  11.         Update(new UpdateInfoMessage(this) { message = "Авторизация произошла успешно", status = "LOGIN" });
  12.       }
  13.       catch (Exception ex)
  14.       {
  15.         Update(new UpdateInfoMessage(this) { message = "Ошибка авторизации:" + ex.Message, status = "LOGIN" });
  16.         res= false;
  17.       }
  18.       return res;
  19.     }

* This source code was highlighted with Source Code Highlighter.

Как видим логика до безобразия проста, описываем параметры, задаем имя метода, вызываем функцию. Если все прошло успешно и есть auth_hash, то сохраняем его в глобальном поле класса и возвращаяем положительный результат. Если пошло что то не так — отлавливаем ошибку и возвращаем ложь. Так же следует упомянуть о функции Update — она служит для уведомления основного приложения об изменениях в нашем классе. Итак, мы научились выполнять запрос и получать простые ответы от сервера. Но большая часть ответов от сервера представляют из себя массивы совершенно различных элементов. Для упращения добавления нового функционала был создан следующий обобщенный класс:
  1.   public class Result:IEnumerable
      {

        // храниться результат выполнения запроса к серверу   
        public T[] result;
     
        /// Активное соединение с сервером
        public ZabbixConnection server;       
     
        // метод Из Zabbix API, например maps.get, triggers.update и т.д
        protected string method;          
     
        // Объект с параметрами запроса к серверу
        protected object Params;           
     
        // строковое значение ответа сервера, используется в основном для отладки
        public string stringResult;          
     
        // Объект для синхронизации доступа из разных потоков.
        public object SyncRoot;           
     
     
        // процедура для переопределения в Классах наследниках, используется для инициализации параметров запроса "method" и "Params"
        protected virtual void init() { }      
     
        public Result(ZabbixConnection Server)
        {
          init();
          server = Server;
          SyncRoot = new object();
        }
        public Result()
        {
          init();
        }
     
        // Получение данных от сервера, результат заноситься в переменную result и collection
        public virtual void get()
        {
          JavaScriptSerializer serializer = new JavaScriptSerializer();
          lock (SyncRoot)
          {
            stringResult = (server.CallApi(method, Params));        
            result = serializer.Deserialize<Result>(stringResult).result;
            if (result==null){result=new T[1];}
          }
        }
     
        public T this[int index]
        {
          get
          {
            return result[index];
          }
        }
     
        public IEnumerator GetEnumerator()
        {
          foreach (T item in result)
          {
            yield return item;
          }
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
          return GetEnumerator();
        }
      }



    Это обобщенный класс, для использования создаем нужную структуру данных согласно описанию в Zabbix API. Наследуем класс с уже определенным типом , переопределяем метод Init, в котором задаем имя метода и параметры запроса к серверу. Рассмотрим конкретный вариант:
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Collections.ObjectModel;
    4. using System.Linq;
    5. using System.Text;
    6.  
    7. namespace Zabbix
    8. {
    9.   public class Hosts:Result
        {
          protected override void init()
          {
            method = "host.get";
            Params = new { output = "extend" };
          }
       
          public Hosts(ZabbixConnection Server) : base(Server) { }
       
        }
        public class Host
        {
          public string host;
          public string hostid;
          public string ip;
          public override string ToString()
          {
            return host;
          }
        }
      }

    Думаю тут тоже все достаточно просто, аналогичным образом можно получить любые данные, будь то триггеры, группы хостов, события или данные графиков. Описания всех методов и параметров можно найти в разделе документации к Zabbix API. Чувствую топик и так получился не маленький, и пора закругляться. Я как можно короче описал способ использования Zabbix API в .NET приложениях. Более полный код библиотеки, а также пример клиента на WPF, можно скачать тут: https://github.com/p1nger/odzl
Tags:
Hubs:
+5
Comments4

Articles