blog.serverclub.ru
Блог компании ServerClub

Запуск локальных ssh/telnet/vnc клиентов по ссылке из карты Zabbix

10 марта 2014 г. Просмотров: 1565 RSS Обсудить

Множество стоек, каждая плотно упакована серверами, маршрутизаторами, коммутаторами и прочими kvm'ами. Нужен какой-нибудь удобный способ рулить всем этим хозайством, быстро подключаться к нужному оборудованию и производить его настройку. Прямо чтобы пара кликов мышью и оп - перед тобой консоль нужного коммутатора.

Для мониторинга наших подопечных мы используем Zabbix. Так почему бы не приспособить сей дивный инструмент и для этой задачи. Ведь было бы очень удобно ткнуть в карте Zabbix на нужную стойку, перейти на её подкарту и, выбрав железку, запустить локальный ssh/telnet/vnc клиент на своем компьютере.

Озадачившись идеей, я начал мучать поисковые машины в надежде отыскать варианты реализации. Был найден данный тред на форуме Zabbix, но мне хотелось запускать именно локальные программы на моей машине кликом по ссылке в карте. Еще некоторое время поплутав по закоулкам всемирной паутины и помучав знакомых программистов глупыми вопросами я вспомнил о... Python.

Да, Python, не раз пришедший на помощь в трудную минуту. Питаю очень нежные чувства к этому языку за его простоту и приятный теплый синтаксис.

И так, вектор атаки изменился и поисковики замерли в ожидании нового вброса мыслеобразов...

Спустя некоторое время я уже четко представлял как буду решать задачу - напишу клиент-серверное приложение!

На моем компьютере будет ждать команд серверная часть, а на сервере мониторинга, при клике по ссылке, будет запускаться клиент и передавать нужную команду.

Результатом изысканий стало кроссплатформенное приложение, работает как на Linux, так и на Windows.

Эпопея проб и ошибок на пути к заветной цели ждет вас под катом.

Пролог

Начало пути.

В первую очередь отмечу, что синтаксис написанного справедлив для Python версии 2.7.

А версия Zabbix насчитала три двойки - Zabbix 2.2.2

Отвечать за коммуникацию клиента и сервера поручено Python библиотеке socket.

Помимо документации мне были полезны следующие источники:

1. http://www.binarytides.com/python-socket-programming-tutorial/

2. http://www.binarytides.com/code-chat-application-server-client-sockets-python/

3. http://java-developer.livejournal.com/6920.html

Наигравшись с примерами, подготовим основу будущего приложения.

Клиент:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
sock = socket.socket()
sock.connect(('localhost', 9090))
sock.send('/usr/bin/konsole -e  mc')
sock.close()

И сервер:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import subprocess
sock = socket.socket()
sock.bind(('localhost', 9090))
sock.listen(1)
while True:
        conn, addr = sock.accept()
        data = conn.recv(1024)
        if not data:
                break
        subprocess.call(data, shell=True)
conn.close()

Запущеный сервер "слушает" порт 9090 на интерфейсе обратной петли, выполнив клиента мы передаем команду для запуска новой консоли, а параметр -e mc указывает, что в консоли нужно запустить файловый менеджер midnight commander.

Краткая демонстрация

*Основной ОС для меня является Linux, а в качестве DE выступает KDE, но пусть вас это не смущает, итоговый вариант скриптов не будет привязан к ОС.

Основа положена, двигаемся далее!

Глава 1

В этой главе клиент научится понимать аргументы командной строки и мы отправим серверу первую команду с карты Zabbix.

Код серверной части пока не претерпел никаких изменений, а вот в код клиента добавился импорт библиотеки sys.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import sys
sock = socket.socket()
sock.connect(('localhost', 9090))
sock.send('/usr/bin/konsole -e ssh root@'+ sys.argv[1])
sock.close()

Сервер должен будет запустить консоль и инициировать подключение по ssh к IP из первого аргумента переданного клиенту.

Логином выступает root .

А теперь пришло время поместить скрипт клиента на сервер мониторинга.

В моем случае он уютно устроился здесь - /usr/local/bin/client.py

В веб интерфейсе Zabbix перейдем в Administration -> Scripts.

Создадим новый скрипт(Create new).

Через Zabbix макрос {HOST.IP} клиенту передается IP для подключения.

Перейдя на карту увидим, что у хостов появилось меню с именем вновь созданного скрипта.

Многие справедливо заметят - "Скрипт клиента до сих пор соединяется с localhost, но он же уже на сервере?!"

Все верно! Но для защиты взаимодействия сервера и клиента используется ssh туннель.

Все соединения устанавливаемые на localhost:9090 Zabbix сервера на самом деле устанавливаются со скриптом сервера на нашей локальной машине.

Для достижения такого "зеркалирования" на локальном компьютере нужно выполнить команду:

ssh -f -N -R 9090:127.0.0.1:9090  zabbix

Подробнее о ssh, и тоннелях в часности, можно прочесть в замечательных статьях на хабре - 1, 2

Видеоиллюстрация к первой главе

Глава 2

В этой главе скрипты еще немного поумнеют и научатся отличать Windows от Linux.

Идея состоит в том, чтобы клиент при соединении с сервером первым делом узнавал на какой ОС тот запущен.

И, получив это информацию, отдавал правильную команду.

Код обоих скриптов изменился.

Клиент:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import sys
sock = socket.socket()
sock.connect(('localhost', 9090))
os = sock.recv(64)
if  os == "Windows":
    sock.send('C:\\apps\\putty.exe -ssh root@' + sys.argv[1])
elif os == "Linux":
    sock.send('/usr/bin/konsole -e ssh root@'+ sys.argv[1])
sock.close()

Сервер:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import subprocess
OS = "Linux"
sock = socket.socket()
sock.bind(('127.0.0.1', 9090))
sock.listen(1)
while True:
    conn, addr = sock.accept()
    conn.sendall(OS)
    data = conn.recv(1024)
    print data
    if not data:
        break
    subprocess.call(data, shell=True)
conn.close()

* для Windows переменная OS должна быть изменена соответствующе

Как видно, при коннекте к серверу клиент перво-наперво получает строку с названием ОС, и только потом посылает команду.

Обратите внимание, что бекслэши в путях для ОС Windows нужно экранировать, т.е. ставить двойной \\

Видео ко второй главе

На видео:

"зеркалируем" порт в Windows запустив putty

запускаем сервер

кликаем ссылку для соединения с хостом

отключаем все в Windows и проделываем то же самое в Linux

Глава 3

В этой главе мы немного подправим код фронтенда Zabbix.

Научим его передавать скрипту-клиенту вторым аргументом логин зарегистрированного на веб интерфейсе администратора/оператора.

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

Но что если администраторов, пользующихся Zabbix, больше одного?

Нам нужно каким-то образом дать понять скрипту кто его запустил, попросту говоря кто "ткнул" ссылку в веб интерфейсе.

Решать будем поэтапно.

  • Закрепим за каждым администратором определенный порт.
  • Научим скрипт-клиент выбирать порт в зависимости от второго аргумента - логина.
  • Изменим код Zabbix для передачи второго аргумента при клике по ссылке из веб интерфейса.

Порты:

Admin - 9090

Admin1 - 9091

и т.д.

Код скрипта-клиента с нужными изменениями:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import sys
if sys.argv[2] == 'Admin':
        PORT=9090
elif sys.argv[2] == 'Admin1':
        PORT=9091
sock = socket.socket()
sock.connect(('localhost', PORT))
os = sock.recv(64)
if  os == "Windows":
        sock.send('C:\\apps\\putty.exe -ssh root@' + sys.argv[1])
elif os == "Linux":
        sock.send('/usr/bin/konsole -e ssh root@'+ sys.argv[1])
sock.close()

А вот решить последнюю задачу, в рамках данной главы, оказалось не так просто.

Пришлось существенно увеличить лимит кофе на эту смену и даже умыкнуть кота у жены из под бока.

Кофе был выпит, кот, промурлыкав положенное, давно свалил, а я ни на йоту не приблизился к решению...

Но ощущение близости отгадки не давало мне покоя, оно крепко вцепилось в мой мозг своими клешнями, и я знал, что яблоко вот-вот должно свалиться мне на голову.

И оно свалилось!(не в прямом смысле конечно)

Работающий вариант, как это часто бывает, был практически на поверхности.

Для выполнения всех скриптов, вызванных из веб интерфейса, используется scripts_exec.php, расположеный в корневом каталоге установленного Zabbix.

Описание скриптов хранится в MySQL базе.

Значит исправив должным образом scripts_exec.php мы сможем передавать логин как второй аргумент для нашего скрипта-клиента при клике по ссылке.

Код и описание исправленного scripts_exec.php под спойлером

Показать...

А вот как это выглядит:

Смотреть лучше без звука, ноут у меня разбушевался уж очень)

Глава 4

В этой главе мы научим Zabbix запускать vnc и telnet клиентов.

Поговорим о скриптах-клиентах для прочих, перечисленных в заголовке, протоколов.

Листинг директории /usr/local/bin на Zabbix сервере :

-rwxr-xr-x 1 root staff 429 Mar 17 03:06 client_ssh.py
-rwxr-xr-x 1 root staff 418 Mar 17 04:58 client_telnet.py
-rwxr-xr-x 1 root staff 412 Mar 17 05:00 client_vnc.py

Листинг каждого скрипта-клиента под спойлером

Показать...

Подробно останавливаться на коде не будем, в предыдущих главах это уже было сделано.

Скажу лишь, что для Windows я скачал portable версию vnc клиента и положил все в c:\apps\

Для telnet и vnc из скриптов нужно повторить шаги из главы 1, в веб интерфейсе Zabbix, а для ssh достаточно скорректировать название.

Файл scripts_exeс.php так же нуждается в изменении.

Вновь измененный код scripts_exeс.php

Показать...

Уже традиционное видео.

Здесь тоже лучше без звука.

Заключение.

Наведем порядок и придадим некоторый лоск нашей разработке.

Строго говоря, здесь кросплатформеность и заканчивается.

Для ОС Linux, из множества примеров, был собран демон на Python.

Он выполняет дабл форк и преспокойно ждет команд от скриптов-клиентов.

В ОС Windows все оказалось сложнее, но, обо всем по порядку.

Листинг директории с необходимыми скриптами для ОС Linux:

fessae@workbook:~/sh/python > pwd
/home/fessae/sh/python
fessae@workbook:~/sh/python > ll
total 12
-rwxr-xr-x 1 fessae fessae 2880 Feb 28 02:56 daemon.py*
-rwxr-xr-x 1 fessae fessae  710 Mar 17 03:36 server.py*
-rwxr-xr-x 1 fessae fessae 1122 Mar 13 04:59 ZabbixTeams.py*

Код каждого из скриптов серверной части Linux

Показать...

Для запуска демона набираем

python ZabbixTeams.py start

Для остановки соответственно

python ZabbixTeams.py stop

Обратите внимание на строку

sys.path.append("/home/fessae/sh/python")

из ZabbixTeams.py, она подключает врзможность импортировать скрипты из этого каталога.

Исправьте её в соответствии вашему окружению.

Получившийся демон можно стартовать руками, прилипить иконку для его запуска, завернуть в австостарт DE или ОС.

Это уже кому как нравится.

ОС Windows.

Для написания/исправления кода я пользовался Python IDE PyCharm, поэтому и скрипты разместились по пути:

Правильнее, конечно, было бы написать сервис для этой ОС при помощи pywin32.

Но в скриптах использованы блокирующие сокеты и не отказавшись от них полноценный сервис у меня не получался.

Возможно позже я возьмусь за asyncore или вообще перепишу все на twisted, но пока мне не хотелось усложнять.

Поэтому запуск демона на Windows выглядит следующим образом:

Показать...

Итоговое видео.

*со звуком все в порядке ;)

Благодарю за внимание.

twitter.com facebook.com vkontakte.ru odnoklassniki.ru mail.ru ya.ru pikabu.ru blogger.com liveinternet.ru livejournal.ru google.com yandex.ru
Оставьте комментарий!

grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

Имя и сайт используются только при регистрации