Мониторинг серверов Trassir

в 8:41, , рубрики: DSSL Trassir мониторинг php

Так сложилось, что есть необходимость администрирования большого количества (более 50 и будет кратно больше) серверов Trassir (сервера видеонаблюдения) расположенных в разных городах СНГ. В целом оборудование не плохое, но присутствуют проблемы с централизованным управлением в силу особенностей архитектуры системы, каждый сервер (NVR) живет своей жизнью. Некоторые возможности порулить сразу кучей устройств дает «родное» облако, но оно абсолютно неконфигурируемое и использовать его можно лишь как оно есть.

Утро каждого рабочего дня начинается с проверки каждого сервера на работоспособность, что отнимает очень много времени.

У DSSL есть SDK, полное описание доступно тут.

Потратил пару вечеров и написал класс на php, который позволяет веб-серверу проверять состояние Trassir серверов и выводить на страничку. Для доступа к Trassir серверам через web их необходимо сконфигурировать. Во-первых в настройках сервера включить «Разрешить доступ к Trassir из браузера», во — вторых «Trassir SDK» (и задать SDK пароль). Кроме того, рекомендую создать пользователя с усеченными правами для авторизации скрипта (в моем случае пользователь Monitoring, пароль 123, SDK пароль 12345).

image

В целом SDK дает огромные возможности, ознакомиться можно по ссылке что я давал выше.

Сам код класса:

<?php
class TrassirServer {
/*
	1. Создаем новый объект. $serv = new TrassirServer('10.18.242.33', 'Monitoring', '123', '12345');
	2. Обязательно проверяем онлайн ли он прежде чем работать с ним дальше! $serv->check_connection();
	3. Получение сессии $serv->get_sid();
	4. Получение списка объектов как массив $objects = $serv->get_objects(); Необходим пароль SDK
	5. Получение здоровья $serv->get_health(); Обязательно перед этим выполнить пункт 3 (get_sid())
*/

	public $status = array();
	//public $objects = array();
	private $ip_address, $name, $sid, $sdk_sid;
	private $user;

   public function __construct($ip_address, $user, $password, $sdk_password) {
		$this->ip_address = $ip_address;
		$this->status['ip_address']= $ip_address;
		$this->user = $user;
		$this->password = $password;
		$this->sdk_password = $sdk_password;
   }
		
	public function check_connection () {
		$url = 'http://'.trim($this->ip_address).':80/';
		$curlInit = curl_init($url);
		curl_setopt($curlInit,CURLOPT_CONNECTTIMEOUT,2); //время ожидания в секундах
		curl_setopt($curlInit,CURLOPT_HEADER,true);
		curl_setopt($curlInit,CURLOPT_NOBODY,true);
		curl_setopt($curlInit,CURLOPT_RETURNTRANSFER,true);
		$response = curl_exec($curlInit);
		curl_close($curlInit);
		if ($response){
			$this->status['online'] = true;
		} else {
			$this->status['online'] = false;
		}
		return $this->status['online'];
	}
	// получить sid
	/*    {
        "success" : "0",
        "error_code" : "invalid username or password"
    }

	/*

	Username and Password should match to one of the server users.

		*/
	
	public function get_sid(){  
		if ($this->status['online']){
			$url = 'https://' . trim($this->ip_address) . ':8080/login?username=' . $this->user  . '&password='.$this->password; //получаем объекты сервера по адресу		
			$responseJson_str = file_get_contents ($url);			
			$server_auth = json_decode ($responseJson_str, true); //переводим JSON в массив
			if($server_auth['success']==1){
				$this->status['sid'] = $server_auth['sid']; //записываем sid массив
			}	
			else{
				$this->status['sid'] = false;

			}
		}	
		return $this->status['sid'];	
	}
	
	//получаем объекты сервера
	public function get_objects(){
		if ($this->status['online']){
		
			$url = 'https://' . trim($this->ip_address) . ':8080/objects/?password='.$this->sdk_password;
			$responseJson_str = file_get_contents ($url); //получаем объекты сервера по адресу		
			$comment_position = strripos ($responseJson_str, '/*');	//отрезаем комментарий в конце ответа сервера
			$responseJson_str = substr ($responseJson_str, 0, $comment_position);
			//$server_objects = json_decode ($responseJson_str, true); //переводим JSON в массив
				$objects = json_decode ($responseJson_str, true); 			
			return $objects;
		}
		
	}
	


	
	//заполнить массив $status
	/*
	{
    "disks": "1",
    "database": "1",
    "channels_total": "10",
    "channels_online": "5",
    "uptime": "12902",
    "cpu_load": "22.50",
    "network": "1",
    "automation": "1",
    "disks_stat_main_days": "56.15",
    "disks_stat_priv_days": "35.03",
    "disks_stat_subs_days": "40.20"
	}
	*/
	public function get_health() {	
		if ($this->status['online'] && $this->status['sid']){		
			$url = 'https://' . trim($this->ip_address) . ':8080/health?sid='.$this->status['sid'];
			$responseJson_str = file_get_contents ($url); //получаем состояние сервера по адресу		
			$comment_position = strripos ($responseJson_str, '/*');	//отрезаем комментарий в конце ответа сервера
			$responseJson_str = substr ($responseJson_str, 0, $comment_position);
			$server_health = json_decode ($responseJson_str, true); //переводим JSON в массив
			foreach ($server_health as $key => $value){
				
				if (($key == 'disks' || $key == 'database' || $key == 'network' || $key == 'automation')&& $value=='1') 
					{
						echo '<div class = "OK">';
						echo $key . ': ';
						echo 'OK';
						echo '</div>';
					}
					else if ($key == 'cpu_load' && $value <= 75)
					{
						echo '<div class = "OK">';
						echo 'Загрузка ЦП: ';
						echo $value . '%';
						echo '</div>';			
					}	
					else if ($key == 'uptime' && $value > 3600)
					{
						echo '<div class = "OK">';
						echo 'Аптайм: ';				
							$day = floor($value/86400);				
							$value1 = $value - $day*86400;
							$hour = floor(($value - $day*86400)/3600);
							echo $day.' days '.$hour . ' hours';
						echo '</div>';			
					}	
					else if ($key == 'uptime' && $value <= 3600)
					{
						echo '<div class = "error">';
						echo $key . ' less than hour : ';
						echo $value . ' seconds';
						echo '</div>';			
					}			
					else if ($key == 'channels_total')
					{
						echo '<div class = "OK">';
						echo 'Каналов всего: ';
						echo $value;
						$ch_total = $value;
						echo '</div>';			
					}	
					else if ($key == 'channels_online' && $value == $ch_total)
					{
						echo '<div class = "OK">';
						echo 'Каналов онлайн: ';
						echo $value;
						$ch_total = $value;
						echo '</div>';	
					}		
					else if (($key == 'disks_stat_main_days' || $key == 'disks_stat_subs_days')&& $value > 45)
					{
						echo '<div class = "OK">';
						echo $key . ': ';
						echo $value;
						echo '</div>';			
					}
					else if ( $key == 'disks_stat_priv_days')
					{
						echo '<div class = "OK">';
						echo $key . ': ';
						echo $value;
						echo '</div>';
					}
					else 
					{
						echo '<div class = "error">';
						echo $key . ': ';
						echo $value;
						echo '</div>';
					}	
				}
		}
	}

	
}

?>

Пример использования подразумевает наличие трех файлов, index.php, view.css (таблица стилей, необязательна, но без нее все будет грустно), list_of_servers.txt (текстовый файл, в котором указаны IP адреса всех серверов для проверки, каждый с новой строки).

view.css:

.error{
	background-color: cc3f5b;
	#border: 1px dotted red;
	#width: 99%;
	padding-left: 5px;
	
}

.trassir_server{
	#border-bottom: 1px solid black;
	width: 250px;
	height: 240px;
	background-color: #4682B4;
	color: white;
	margin-top: 15px;
	margin-left: 5px;
	display: inline-block;
	vertical-align: top;

}

.OK{
	background-color:  #4169E0;	
	border-bottom: 1px solid black;
	padding-left: 5px;
}

.trassir_server_name{
		font-size: 20px;
		text-align: center;
		height: 30px;
		
}

body{
		background-color: #DCDCDC;
}

index.php

<?php
header('Content-Type: text/html; charset=utf-8');
error_reporting(E_ALL);	
require ('classes/TrassirServer.php');

ini_set('max_execution_time', 60);	
echo "<link rel='stylesheet' href='./css/view.css'>";
echo '<body>';

$user = 'Monitoring';
$password = '123';
$sdk_password = '12345';

function trassir_server_monitor($ip, $user, $password, $sdk_password){
	
	$serv = new TrassirServer($ip, $user, $password, $sdk_password);
	echo '<div class = "trassir_server">';
	
		$serv->check_connection();
			if ($serv->status['online']) {
				
				$serv->get_sid();
				if ($serv->status['sid']) {
					
					$objects = $serv->get_objects();
					if($objects){
						foreach ($objects as $obj) //в массиве объектов ищем имя сервера
						{
							if ($obj['class'] == 'Server')
								{
									
									$serv->status['name']= $obj['name'];	
								}
						}
					}
					
						echo '<div class = "trassir_server_name">';	
							echo  $serv->status['name'];	
						echo '</div>';
						echo '<div class = "trassir_server_status">';	
							$serv->get_health();
						echo '</div>';
							
					
					
				}
			}
			if (!$serv->status['online'] || !$serv->status['sid'] || !$objects){
				echo '<div class = "error">';	
					echo 'server ' . $ip . '</br>';
					echo 'connection error';
				echo '</div>';	
			}
		echo '</div>';

}


$list_of_servers = fopen("conf/list_of_servers.txt", "r");
$array = null;
if ($list_of_servers) {
    while (($buffer = fgets($list_of_servers)) !== false) {

		trassir_server_monitor($buffer, $user, $password, $sdk_password);
    }
}
fclose($list_of_servers);
echo '<br/>';


echo '</body>';
?>

Результат в моем случае (на период тестирования всего 4 сервера):

image

В планах:

  1. Автоматический регулярный запуск скрипта (пару раз в сутки) и сохранение статистики состояния серверов в БД.
  2. Возможно централизованное управление УЗ пользователей, если будет актуально к тому моменту когда смогу реализовать первое.

Если есть еще «счастливые» администраторы данной системы, буду рад помощи при желании совместной доработки функционала. Так же если кому-то интересен итоговый результат, но разработкой заниматься не готов — пишите на denis.glushakov@bk.ru, постараюсь про вас не забыть.

Советы по оптимизации кода с радостью приму в комментариях.

Автор: Denissko

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js