«Сетевому администратору необходимо уметь программировать» — эта фраза часто вызывает возражения у многих сетевиков.

— Зачем? Руками оно надёжнее.
— Зато можно автоматизировать типовые операции.
— И положить кучу устройств, если что-то пойдёт не так?
— Положить кучу устройств можно и руками.

Вы прослушали краткое содержание типовых дискуссий по этому вопросу. Большинство админов останавливается на редактировании в текстом редакторе ранее скопированных кусков конфига и копировании их в консоль. Или подготовка типовых конфигурационных файлов, но добавление их на оборудование руками через консоль.

Если посмотреть в сторону производителей сетевого оборудования,
то окажется, что та же cisco уже давно предлагает разнообразные варианты для автоматизации работы с сетевым оборудованием: от TCL на IOS до Python на NX-OS и IOS-XR . Называется всё это network automation или network programmability, и у Cisco есть курсы по этому направлению.

И Cisco здесь не одинока: Juniper c PyEZ, HP, Huawei и тд.

Множество инструментов — Netconf, Restconf, Ansible, Puppet и Python, Python, Python. Анализ конкретных инструментов отложим на потом, перейдём к конкретному примеру.

Второй вопрос, который иногда вызывает бурные дискуссии, как правило приводящий к полному непониманию друг друга: «А нужны сетевику сетевые устройства в DNS?».
Оставим подробный анализ позиций участников на потом, сформулируя задачу, которая привела к Python и SNMP. А началось всё с traceroute.

Несмотря на наличие разнообразных систем мониторинга, которые бдят и видят многое, MPLS-TE, который разворачивает трафик причудливым образом, верный ICMP и утилиты traceroute и ping во многих случаях способны дать нужную информацию быстро и сейчас. Но вывод traceroute только ввиде IP адресов в большой сети потребует дополнительных усилий для понимания того, откуда именно пришли пакеты. Например, мы видим, что прямой и обратный трафик от пользователя идёт через разные маршрутизаторы, но по каким именно? Решение очевидно, занести адреса маршрутизаторов в DNS. А для корпоративных сетей, где редко используют unnumbered, ставя на соединители отдельные адреса, в случае занесения адресов интерфейсов в DNS, можно будет быстро понять, через какой интерфейс пакет ICMP вышел с маршрутизатора.

Однако вести вручную базу DNS на большой сети требует очень больших трудозатрат не самого сложного труда. А ведь доменное имя интерфейса будет состоят из названия интерфейса, description интерфейса, hostname маршрутизатора и названия домена. Всё это маршрутизатор несёт в своей конфигурации. Главное это собрать и правильно склеить и привязать к правильному адресу.

Значит эту задачу надо автоматизировать.

Первая мысль, анализ конфигураций, быстро угасла, сеть большая, многовендорная, да ещё и оборудование из разных поколений, поэтому идея парсить конфиги довольно быстро стала непопулярной.

Вторая мысль, использовать то, что даёт нужные ответы на универсальные запросы к оборудованию разных вендоров. Ответ был очевиден — SNMP. Он, при всех своих особенностях, реализован в ПО любого вендора.

Итак, начнём


Ставим Python.
sudo apt-get install python3

Нам понадобятся модули для работы с SNMP, IP адресами, со временем. Но для их установки необходимо поставить pip. Правда, сейчас он идёт в комплекте с python.
sudo apt install python3-pip

А теперь ставим модули.
pip3 install pysnmp

pip3 install datetime

pip3 install ipaddress

Попробуем получить с маршрутизатора его hostname. SNMP использует для запросов к хосту OID. На OID хост вернёт информацию, соответствующую этому OID. Хотим получить hostname — нужно запрашивать 1.3.6.1.2.1.1.5.0.

И так первый скрипт, который запрашивает только hostname.

# import section
from pysnmp.hlapi import *
from ipaddress import *
from datetime import datetime

# var section

#snmp
community_string = 'derfnutfo'  # From file
ip_address_host = '192.168.88.1'  # From file
port_snmp = 161
OID_sysName = '1.3.6.1.2.1.1.5.0'  # From SNMPv2-MIB hostname/sysname

# function section

def snmp_getcmd(community, ip, port, OID):
    return (getCmd(SnmpEngine(),
                   CommunityData(community),
                   UdpTransportTarget((ip, port)),
                   ContextData(),
                   ObjectType(ObjectIdentity(OID))))

def snmp_get_next(community, ip, port, OID):
    errorIndication, errorStatus, errorIndex, varBinds = next(snmp_getcmd(community, ip, port, OID))
    for name, val in varBinds:

        return (val.prettyPrint())

#code section

sysname = (snmp_get_next(community_string, ip_address_host, port_snmp, OID_sysName))
print('hostname= ' + sysname)

Запускаем и получаем:
hostname= MikroTik

Разберём скрипт поподробнее:

Сначала мы импортируем необходимые модули:

1. pysnmp — обеспечивает работу скрипта с хостом по SNMP

2. ipaddress — обеспечивает работу с адресами. Проверка адресов на корректность, проверка на вхождения адреса в адрес сети и тд.

3. datetime- получение текущего времени. В данной задаче нужен для организации логов.

Потом заводим четыре переменных:

1. community
2. адрес хоста
3. порт SNMP
4. значение OID

Две функции:

1. snmp_getcmd
2. snmp_get_next

Первая функция посылает запрос GET указанному хосту, по указанному порту, с указанным comminity и OID.
Вторая функция это генератор snmp_getcmd. Наверное разбивать на две функции было не совсем правильно, но уж так получилось:)

В этом скрипте не хватает некоторых вещей:

1. В скрипт необходимо загрузить ip адреса хостов. Например, из текстового файла. При загрузке необходимо проверить загружаемый адрес на корректность, иначе pysnmp может очень сильно удивиться и скрипт остановится с traceback. Непринципиально, откуда вы будете брать адреса из файла, из базы даных, но вы должны быть уверены, что адреса, которые вы получили — корректные. И так, источник адресов текстовый файл, одна строка — один адрес в десятичной форме.

2. Сетевое оборудование может быть выключено на момент опроса, может быть неправильно настроено, в итоге pysnmp выдаст в этом случае совершенно не то, что мы ждём и при дальнейшей обработке полученной информации получим остановку скрипта с traceback. Нужен обработчик ошибок для нашего взаимодействия по SNMP.

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

Загружаем адреса и создаём лог файл


Вводим переменную для имени файла.
Пишем функцию check_ip на проверку корректности адреса.
Пишем функцию get_from_file загрузки адресов, которая проверяет каждый адрес на корректность и если это не так, записывает об этом сообщение в лог.
Реализуем загрузку данных в список.

filename_of_ip = 'ip.txt' # имя файла с Ip адресами
#log
filename_log = 'zone_gen.log' #   

def check_ip(ip): # проверка ip адреса корректность
    try:
        ip_address(ip)
    except ValueError:
        return False
    else:
        return True

def get_from_file(file, filelog): # выбирает ip адреса из файла. одна строка - один адрес в десятичной форме
    fd = open(file,'r')
    list_ip = []
    for line in fd:
       line=line.rstrip('\n')
       if check_ip(line):
           list_ip.append(line)
       else:
            filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ': Error Мусор в источнике ip адресов ' + line)
            print('Error Мусор в источнике ip адресов ' + line)
    fd.close()
    return list_ip

#code section

#открываем лог файл
filed = open(filename_log,'w')

# записываем текущее время
filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + '\n')

ip_from_file = get_from_file(filename_of_ip, filed)

for ip_address_host in ip_from_file:
    sysname = (snmp_get_next(community_string, ip_address_host, port_snmp, OID_sysName))
    print('hostname= ' + sysname)

filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + '\n')
filed.close()

Создадим файл ip.txt
192.168.88.1
172.1.1.1
12.43.dsds.f4
192.168.88.1

Второй адрес в этом списке не отвечает на snmp. Запустим скрипт и убедимся в необходимости обработчика ошибок для SNMP.
Error ip 12.43.dsds.f4
hostname= MikroTik
Traceback (most recent call last):
File "/snmp/snmp_read3.py", line 77, in print('hostname= ' + sysname)
TypeError: Can't convert 'NoneType' object to str implicitly

Process finished with exit code 1

Из содержимого traceback невозможно понять, что причиной сбоя стал недоступный хост. Попробуем перехватить возможные причины остановки скрипта и записать всю информацию в лог.

Создаём обработчик ошибок для pysnmp


В функции snmp_get_next уже есть вывод ошибок errorIndication, errorStatus, errorIndex, varBinds. В varBinds выгружаются полученные данные, в переменные, начинающиеся с error, выгружается информация по ошибкам. Это только нужно правильно обработать. Так как в дальнейшем в скрипте будет ещё несколько функций по работе с snmp, имеет смысл обработку ошибок вынести в отдельную функцию.

def errors(errorIndication, errorStatus, errorIndex, ip, file):
    #обработка ошибок В случае ошибок возвращаем False и пишем в файл
    if errorIndication:
        print(errorIndication, 'ip address ', ip)
        file.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + str(errorIndication) + ' = ip address = ' + ip + '\n')
        return False
    elif errorStatus:
        print(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + '%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
        file.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + '%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBinds[int(errorIndex) - 1][0] or '?' + '\n'))
        return False
    else:
        return True

И теперь добавляем в функцию snmp_get_next обработку ошибок и запись в лог файл. Функция теперь должна возвращать не только данные, но и сообщение о том, были ли ошибки.


def snmp_get_next(community, ip, port, OID, file):
    errorIndication, errorStatus, errorIndex, varBinds = next(snmp_getcmd(community, ip, port, OID))
    if errors(errorIndication, errorStatus, errorIndex, ip, file):
        for name, val in varBinds:
            return (val.prettyPrint(), True)
    else:
        file.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : Error snmp_get_next ip = ' + ip + ' OID = ' + OID + '\n')
        return ('Error', False)

Теперь необходимо немного переписать code section, с учётом того, что теперь есть сообщения об успешности запроса. Кроме этого, добавим несколько проверок:

1. Sysname меньше, чем три символа. Запишем в лог файл, чтобы потом присмотреться по пристальнее.

2. Обнаружим, что некоторые Huawei и Catos отдают на запрос только hostname. Так как отдельно выискивать для них OID совершенно не хочется (не факт, что он вообще есть, может это ошибка ПО), добавим таким хостам domain вручную.

3. Обнаружим, что хосты с неправильным comminity ведут себя по разному, большинство инициирует срабатывание обработчика ошибок, а некоторые почему-то отвечают, что скрипт воспринимает как нормальную ситуацию.

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

for ip_address_host in ip_from_file:
    #  получаем sysname hostname+domainname, флаг ошибки   
    sysname, flag_snmp_get = (snmp_get_next(community_string, ip_address_host, port_snmp, OID_sysName, filed))

    if flag_snmp_get:
        # Всё хорошо, хост ответил по snmp
        if sysname == 'No Such Object currently exists at this OID':
            #  а community неверный.надо пропускать хост, иначе словим traceback. Причём ты никак не поймаешь, что проблема в community, поэтому всегда надо запрашивать hostname, который отдают все устройства    
            print('ERROR community', sysname, ' ', ip_address_host)
            filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + 'ERROR community sysname = ' + sysname + '  ip = ' + ip_address_host + '\n')
        else:
            if log_level == 'debug':
                filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + '  sysname ' + sysname + ' type ' + str(type(sysname)) + ' len ' + str(len(sysname)) + ' ip ' + ip_address_host + '\n')
            if len(sysname) < 3
                if log_level == 'debug' or log_level == 'normal':
                    filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + 'Error sysname  3  = ' + sysname + '  ip = ' + ip_address_host + '\n')
            if sysname.find(domain) == -1:
                # что-то отдало hostname без домена, например Huawei или Catos
                sysname = sysname + '.' + domain
                  if log_level == 'debug' or log_level == 'normal':
                    filed.write("check domain     : " + sysname + " " + ip_address_host + " " + "\n")

        print('hostname= ' + sysname)

Проверим этот скрипт на том же файле ip.txt
Error Мусор в источнике ip адресов 12.43.dsds.f4
hostname= MikroTik.mydomain.ru
No SNMP response received before timeout ip address 172.1.1.1
hostname= MikroTik.mydomain.ru

Всё отработало штатно, мы поймали все ошибки, скрипт пропустил хосты с ошибками. Теперь этим скриптом можно собрать hostname cо всех устройств, отвечающих на snmp.

Полный текст скрипта прячу под спойлер.

Скрипт

# import section
from pysnmp.hlapi import *
from ipaddress import *
from datetime import datetime

# var section

#snmp
community_string = 'derfnutfo'  
ip_address_host = '192.168.88.1'  
port_snmp = 161
OID_sysName = '1.3.6.1.2.1.1.5.0'  # From SNMPv2-MIB hostname/sysname
filename_of_ip = 'ip.txt' #    Ip 
#log
filename_log = 'zone_gen.log'  # для лог файла
log_level = 'debug'

domain='mydomain.ru'

# function section

def snmp_getcmd(community, ip, port, OID):
# type class 'generator' errorIndication, errorStatus, errorIndex, result[3] - список
# метод get получаем результат обращения к устойстройству по SNMP с указаным OID
    return (getCmd(SnmpEngine(),
                   CommunityData(community),
                   UdpTransportTarget((ip, port)),
                   ContextData(),
                   ObjectType(ObjectIdentity(OID))))

def snmp_get_next(community, ip, port, OID, file):
# метод обрабатывает class generator от def snmp_get
# обрабатываем errors, выдаём тип class 'pysnmp.smi.rfc1902.ObjectType' с OID (в name) и значением  (в val)
# получаем одно скалярное значение
    errorIndication, errorStatus, errorIndex, varBinds = next(snmp_getcmd(community, ip, port, OID))

    if errors(errorIndication, errorStatus, errorIndex, ip, file):
        for name, val in varBinds:
            return (val.prettyPrint(), True)
    else:
        file.write(datetime.strftime(datetime.now(),
                                     "%Y.%m.%d %H:%M:%S") + ' : Error snmp_get_next ip = ' + ip + ' OID = ' + OID + '\n')
        return ('Error', False)

def get_from_file(file, filelog):  
#Загрузка ip адресов из файла file, запись ошибок в filelog     
     fd = open(file, 'r')
     list_ip = []
     for line in fd:
         line=line.rstrip('\n')
         if check_ip(line):
            list_ip.append(line)
         else:
            filed.write(datetime.strftime(datetime.now(),
                                              "%Y.%m.%d %H:%M:%S") + ': Error    ip  ' + line)
            print('Error    ip  ' + line)
     fd.close()

     return list_ip

def check_ip(ip): 
#  Проверка ip адреса на корректность. False проверка не пройдена.
    try:
       ip_address(ip)
    except ValueError:
        return False
    else:
        return True

def errors(errorIndication, errorStatus, errorIndex, ip, file):
    #  обработка ошибок в случае ошибок возвращаем False и пишем в файл file
    if errorIndication:
       print(errorIndication, 'ip address ', ip)
       file.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + str(
                errorIndication) + ' = ip address = ' + ip + '\n')
       return False
    elif errorStatus:
         print(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + '%s at %s' % (
         errorStatus.prettyPrint(),
         errorIndex and varBinds[int(errorIndex) - 1][0] or '?' ))
         file.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + '%s at %s' % (
         errorStatus.prettyPrint(),
         errorIndex and varBinds[int(errorIndex) - 1][0] or '?' + '\n'))
         return False
    else:
         return True

#code section

#открываем лог файл
filed = open(filename_log,'w')

# записываем текущее время
filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + '\n')

ip_from_file = get_from_file(filename_of_ip, filed)

for ip_address_host in ip_from_file:
    # получаем sysname hostname+domainname, флаг ошибки
    sysname, flag_snmp_get = (snmp_get_next(community_string, ip_address_host, port_snmp, OID_sysName, filed))

    if flag_snmp_get:
        # Всё хорошо, хост ответил по snmp
        if sysname == 'No Such Object currently exists at this OID':
             # а community неверный.надо пропускать хост, иначе словим traceback. Причём ты никак не поймаешь, что проблема в community, поэтому всегда надо запрашивать hostname, который отдают все устройства
            print('ERROR community', sysname, ' ', ip_address_host)
            filed.write(datetime.strftime(datetime.now(),
                                          "%Y.%m.%d %H:%M:%S") + ' : ' + 'ERROR community sysname = ' + sysname + '  ip = ' + ip_address_host + '\n')
        else:

            if log_level == 'debug':
                filed.write(datetime.strftime(datetime.now(),
                                              "%Y.%m.%d %H:%M:%S") + ' : ' + '  sysname ' + sysname + ' type ' + str(
                    type(sysname)) + ' len ' + str(len(sysname)) + ' ip ' + ip_address_host + '\n')
            if len(sysname) < 3:
                sysname = 'None_sysname'
                if log_level == 'debug' or log_level == 'normal':
                    filed.write(datetime.strftime(datetime.now(),
                                                  "%Y.%m.%d %H:%M:%S") + ' : ' + 'Error sysname  3  = ' + sysname + '  ip = ' + ip_address_host + '\n')
            if sysname.find(domain) == -1:
                # что-то отдало hostname без домена, например Huawei или Catos
                sysname = sysname + '.' + domain
                if log_level == 'debug' or log_level == 'normal':
                    filed.write("check domain     : " + sysname + " " + ip_address_host + " " + "\n")

        print('hostname= ' + sysname)

filed.close()

Теперь осталось собрать имена интерфейсов, description интерфейсов, адреса интерфейсов и правильно разложить в конфигуционные файлы bind. Но об этом во второй части.

P.S.: Отмечу, что по-хорошему сообщения в лог файл следует формировать по-другому принципу.
Например: время спецсимвол код_ошибки спецсимвол описание_ошибки спецсимвол дополнительная_информация. Это поможет потом настроить автоматическую обработку лога.
UPD: исправление ошибок.
Поделиться с друзьями
-->

Комментарии (45)


  1. Fox_exe
    18.07.2017 15:49
    -11

    Python сисадмину?
    У Windows есть PowerShell (Или bat/cmd если чтото совсем простое).
    У *nix'ов — Bash.
    Обычно их возможностей обычному сисадмину более чем достаточно. А если нет — тут уже встает вопрос о написании (Покупке?) собственной софтины. А тут выбор языка зависит больше от предпочтений прогера. (Ну или от задач, которые должна решать софтина)


    1. SicYar
      18.07.2017 16:01
      +3

      Ок, а если Вам будет надо например ходить скриптом и на вин и на никс?
      Пайтон он везде пайтон, а бат на никсах особо не запустишь.
      Ну ок, Вы решили заюзать Ansible, хоп, нужен свой модуль. Опять пайтон.
      Надо быстренько парсинг какой нибудь логов или конфигов с подменой сделать и его запустить и в никсах и вин?
      Покупать софтину для парсинга конфигов? У меня вот старый проект, приходится работать на никсах и вин одновременно, не могу отказать от какой то оси.


      1. Fox_exe
        18.07.2017 16:41
        -6

        Я чет так и не придумал, где может пригодится скрипт, который должен работать и там и там…
        Обычно скрипты пишутся или для конкретной машины, либо для работы с сетевыми устройствами (А там другие вопроы возникают).

        С другой стороны — Bash на Windows тоже есть (Порт, хотя в Win 10 — уже «нативно»… хотя это костыль, да...)

        Для меня основной «Минус» питона — необходимость ставить интерпритатор. Особенно это актуально на всяких Embebed-девайсах, где банально может не быт места для установки оного.
        А вот Bash/SH и CMD/PS есть «Изкаробки»…


        1. habradante
          18.07.2017 16:49

          Вот пример: Пришла железка, и ее надо настроить так же, как и в другом филиале. Но в новом филиале все на виндах, а в другом было на *nix. С помощью питоновского скрипта можно настроить железку абсолютно так же, но из-под другой операционки.


          1. Fox_exe
            18.07.2017 16:51
            -3

            Спорный вариант — Толковый сисадмин хранит подобные скрипты на рабочем ноуте (Чтобы были всегда под рукой). А в случае «Форс мажора» все вручную настраивается.


            1. SicYar
              18.07.2017 16:58
              +2

              Ну я сейчас приведу такой ОЧЕНЬ частный случай( но на самом деле это рабочий момент).
              Есть например мифическая разработка, внутренняя, она шлет какой то траф.
              Я хочу проверить работу, урезая скорость и помониторить и послать себе писем.
              Есть версия 1.0, она на вин сервере работает, есть версия 3.0 она на никс сервере работает.
              Пишу какой то скрипт, он делает что надо, метрики мне шлет в течении например трех четырех дней.
              Какие то если есть различия в вин и никс, можно через sys args, а в остальном логика одинакова работы на разных платформах.
              Профит: мои 100 строк скрипта работают и там и там, не надо писать два разных, тестировать могу под никс (мне так удобнее).


        1. evseev
          19.07.2017 10:22
          +1

          Это запросто может быть. Например по корпоративной политике на рабочих машинах стоит Windows, а сервера, с которыми вы работаете на Windows и на Linux. Причем сервера вполне могут выполнять одни и те-же функции. И было бы хорошо, что бы скрипт работал и там и там. У меня на работе именно такой случай.

          Про Win10 говорить рано. Еще только для тех, кто решился быть подопытной мышью. Да и не будем забывать, что полно оборудования где WinNT живее всех живых и Win2k3 цветет и пахнет.

          На железках такого плана места действительно кот наплакал. Но там, зачастую, и скрипт не запустишь. Просто нет возможности. Но удаленно команды давать можно. Так что поставить Python нужно только в одном месте. Но я, если честно, совсем не жалуюсь. Если железка 1-2-10 вполне возможно туда что-то внедрить. Хотя то же сомнительно. А если их несколько тысяч? Лично я за то, что бы удаленно команды давать ;)


      1. varnav
        19.07.2017 11:46

        Пайтон он везде пайтон


        Ах если бы, ах если бы… Постоянно возникают проблемы когда скрипт, работающий на линухе, под виндой не пашет.


        1. SicYar
          19.07.2017 13:17

          А окружение настроено одинаково? Версия пайтона, дополнительные либы, права, пути? И при таких условиях есть скрипты, рабочие в никсах, но не рабочие в винде?


          1. varnav
            19.07.2017 13:30

            Ну как можно одинаково настроить окружение в линухе и винде? Там же разная структура путей, прав, и вообще всего.
            С либами не всё гладко — нет pycurl для windows под python 3.6
            Установка сертификатов для curl под Windows — отдельная морока.
            В консоли могут быть ошибки если не

            chcp 65001
            set PYTHONIOENCODING=utf-8
            


            в начале. Вместо расцветки могут быть крякозябрики. И так далее.


            1. SicYar
              19.07.2017 13:34

              С локалями согласен, проблемы тоже ловил.
              Возможно разные задачи у нас с Вами, поэтому Ваших проблем не встречал.
              В корпоративной сети до сих пор используем 3.5, с либами да, но обычно есть пара-тройка похожих либ, одна из которых обычно отрабатывает как надо)


      1. varnav
        19.07.2017 13:41

        Powershell для никсов:
        https://github.com/PowerShell/PowerShell/blob/master/docs/installation/linux.md

        Bash для винды:
        https://msdn.microsoft.com/en-us/commandline/wsl/about


        1. Fox_exe
          19.07.2017 15:16
          -1

          Собственно о том и речь — Либо ставить питон + либы, либо портированный под винду Bash + wget/curl/sed/и т.д.
          Но, увы, меня не понял и заминусовали :(


    1. habradante
      18.07.2017 16:11
      +6

      Вы верно подметили, у Windows — PowerShell, у *nix — Bash. Поэтому, чтобы работало и там и там берут Python. :)


      1. varnav
        19.07.2017 13:42
        -1

        PowerShell и Bash нынче под обе ОС.


    1. navion
      18.07.2017 16:57
      +2

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


      1. mickvav
        19.07.2017 03:43
        +4

        Просто bash не упоминают, потому что линуксовый админ без bash — оксюморон.


        1. navion
          19.07.2017 15:30

          По-моему bash и perl в Линуксе разделили судьбу bat/vbs на Винде, где их полностью заменил PowerShell.

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


  1. vvpoloskin
    18.07.2017 15:58
    +1

    В штате у любых сетевиков при накоплении определенной массы активных устройств всегда появляется тот, кто потихоньку начинает скриптовать. Пусть даже на банальной задаче добавить еще одно snmp-community или сменить пароль локального пользователя на 100 устройств делать в ручном режиме совсем не эффективно. Что уж говорить про более сложную логику в виде резервного upload-а конфигов, визуального интерфейса для примитивных действий для смены и т.д.


  1. conformist
    18.07.2017 16:00
    +1

    Если ставить python3, то и pip ставить нужно его же — python3-pip. datetime входит в стандартную поставку python.

    Теперь осталось собрать имена интерфейсов, description интерфейсов, адреса интерфейсов и правильно разложить в конфигуционные файлы bind.

    Пока собрали только имена хостов и то не всех. Фраза напоминает картинку — как нарисовать сову?


    1. Shtucer
      18.07.2017 16:22
      +2

      Если ставить python3.4+ или python2.7.9, то pip ставить не нужно, начиная с python3.4 и python2.7.9 pip входит в комплект.


    1. zw_irk
      19.07.2017 05:08

      Если ставить python3, то и pip ставить нужно его же — python3-pip. datetime входит в стандартную поставку python


      Справедливое замечание. Я понял, почему так — у меня по умолчанию главный в системе python3. Поэтому pip у меня ссылается на pip3.
      Сейчас внесу исправления.


  1. KorP
    18.07.2017 18:00
    +1

    Вдохновлялся несколько лет назад книжкой «Python в системном администрировании» или что то похожее.
    Сам уже пару лет использую питон для этих целей в своей работе (хотя выбор языка — это больше идеология, надо брать то, что больше/лучше знаешь/хочешь знать).
    Правда я больше всё же через ssh работаю с схд/коммутаторами. Что то призвано автоматизировать рутину, а что то и просто ускоряет процесс работы с оборудованием. Сейчас как раз дописываю для личного блога статью по fc зоннигду и следующей статьёй хотел рассказать про работы с brocade при помощи скриптов, для облегчения жизни :)


  1. q1b
    18.07.2017 23:54

    Считаю, что для сетевых скриптов хорошо подходит PHP. Есть все необходимые функции: snmpget, snmpwalk, все необходимые функции для подключения по SSH, поддержка expect, правда, только для PHP5, вспомогательные сетевые функции типа (long2ip, gethostbynamel и т.п.).
    Правда, в больших задачах, где требуется распараллеливание опроса хостов, встречаются проблемы. Но выбор между двумя языками, считаю, это дело вкуса.


    1. evseev
      19.07.2017 11:56

      Писать можно на чем угодно. И если вы уже знаете PHP, то почему-бы и нет? Но большинство производителей оборудования предлагают именно Python. И это о чем-то да и говорит.


      1. q1b
        20.07.2017 09:14

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


        1. Shtucer
          20.07.2017 10:05

          Python, обычно, уже установлен вместе с системой. Чтобы установить php, скорее всего, придется для начала настроить сеть.


          1. q1b
            20.07.2017 10:57

            Вы серьезно? Вы хотите писать сетевые скрипты без настроенной сети?

            Python, обычно, уже установлен вместе с системой
            На голом установленном Python'e Вы тоже далеко не уедете

            Чтобы установить php, скорее всего, придется для начала настроить сеть.
            Ну да, надо на Python'e написать скрипт для настройки сети, иначе это сделать никак не получится))


            1. Shtucer
              20.07.2017 11:34

              Вы серьезно? Вы хотите писать сетевые скрипты без настроенной сети?

              Ну, по крайней мере, я могу. И даже смогу их выполнить. В отличие от.


              На голом установленном Python'e Вы тоже далеко не уедете

              От задачи зависит.


              Ну да, надо на Python'e написать скрипт для настройки сети, иначе это сделать никак не получится))

              Предположу, что они уже написаны, остается только запустить. Эдакий постинсталл. Допустим, я выдумаю какую-то странную ситуацию про хитровыдуманную сеть с зубодробительными роутингами-шмоутингами и прочими айпитеблезами. Эти настройки вполне пишутся на "голом" питоне. Надуманная ситуация, разумеется. Да даже, если я от лени напишу что-то такое, делающее рутинную настройку интерфейсов. Типа ввел адрес-маску, оно само апнуло фейсы, и сделало что-то там ещё. Вот теперь можете ставить пхп и писать на нем. Кардинальная разница только в этом.


            1. evseev
              21.07.2017 07:12

              Подождите. Давайте смотреть. У вас есть огромная сеть. Есть сервер, с которой эта сеть управляется. На сервере, зачастую, стоит древняя версия например Linux. Python с библиотеками уже стоят. Потому, что это предлагает поставщик. Этот сервер стоит во внутренней сети и закрыт со всех сторон фаерволами. Выхода в интернет у этого сервера, понятное дело, нет. Что бы поставить PHP вы не ставите его сами. Вы идете в службу безопасности просите, что бы вам разрешили подключить сервер с интернету для обновления и затягивания нужных пакетов. Они смотрят на вас как на двинутого и говорят нет. Точнее они говорят «Ты что вообще дебил?!!!». А вы сами расшифровываете. Потом вы решаете идти другим путем. Вы обращаетесь к поставщику. А он в свою очередь говорит, что если он поставит вам PHP, то это будет стоить столько-то денег и вообще еще нужно вот такие фичи купить. Иначе они ни за что не отвечают. А если вы что-то поставите сами и это выяснится при аудите, то сервер за все вот эти кучи денег будет снят с супорта. И даже если вам подтвердят возможность установки самостоятельно вам придется все делать руками. Это вам не aptitude install и сиди жди. Это все качать руками, приносить не место, разворачивать. А потом вот этого не хватает, а это нужно другой версии, а это слишком новое, а это… И на сервере заменять библиотеки нельзя. Может сломаться основная часть. А вам она ведь то же нужна.

              Я был в такой ситуации. Поверьте. Выучить Python- плевое дело.


              1. q1b
                21.07.2017 11:13

                Есть сервер, с которой эта сеть управляется. На сервере, зачастую, стоит древняя версия например Linux.
                Что ж у вас все так плохо?
                Python с библиотеками уже стоят.
                Интересно как они там оказались? Сейчас смотрю:
                -Ubuntu Server 16.04 LTS: есть python3, нет pip, нет pysnmp (из вашей статьи)
                -Debian 7: нет python3, нет pip, нет pysnmp, нет ipaddress (из вашей статьи)
                -CentOS Linux 7: python3, нет pip, нет pysnmp, нет ipaddress (из вашей статьи)
                Других вспомогательных библиотек для работы с сетевыми устройствами, понятное дело, тоже нет.

                Этот сервер стоит во внутренней сети и закрыт со всех сторон фаерволами. Выхода в интернет у этого сервера, понятное дело, нет. Что бы поставить PHP вы не ставите его сами. Вы идете в службу безопасности просите, что бы вам разрешили подключить сервер с интернету для обновления и затягивания нужных пакетов. Они смотрят на вас как на двинутого и говорят нет. Точнее они говорят «Ты что вообще дебил?!!!».
                Однако у себя в статье эту ситуацию вы не рассматриваете и ставите нужные пакеты прямо из репозиториев. Оно и понятно, ведь цель статьи показать язык в конкретной задаче, а не о том, что он хорош тем, что предустановлен в системе.

                Вы обращаетесь к поставщику. А он в свою очередь говорит, что если он поставит вам PHP, то это будет стоить столько-то денег и вообще еще нужно вот такие фичи купить. Иначе они ни за что не отвечают. А если вы что-то поставите...
                Не следует свои частные случаи из жизни приводить как аргумент в общем споре. Спор шел о «PHP vs Python в программировании для сети». Главный аргумент ваш и Shtucer это «PHP надо установить, а Python уже установлен», а то, что библиотеки для Python тоже надо устанавливать, вы игнорируете. Ваша позиция мне ясна.

                Или обижаться или выучить Python
                Я программирую на обоих языках. Поэтому я сравниваю в своем первом комментарии языки, а не способы их установки.


                1. evseev
                  21.07.2017 15:30
                  +1

                  Почему плохо? Часто это нормально. Все что нужно работает. Тем более, что упор делается на прикладной софт, а не на систему. А обновление может запросто все сломать. А это риски. А еще за уровень софта часто нужно заплатить. И заплатить немало.

                  Откуда они там оказались? Когда вы покупаете сервер для контроля всей сети это не железо с Linux на борту в стандартной комплектации. Это решение. Вам продают настроенную систему с целой кучей софта, который помогает вам делать все-все-все. К этому прилагается документация и поддержка на определенное время на определенных условиях. Т.е. вы звоните или пишите и вам в сжатые сроки предоставляют решения ваших проблем. И если в документации написано, что вот так вы можете использовать рекомендуемый нами Python, но так не работает, то поставщик обязан это все исправить. И не всегда это ему обходится бесплатно. Поэтому поверьте. Указанная версия стоит со всем библиотеками.

                  В скобках написано «из вашей статьи» и дальше вы говорите «у себя в статье». Это не моя статья. Я никак не связан ни с автором, ни с этой статьей. А вот ситуация, когда сервер стоит под семью замками и пользоваться предустановленным — самый здравый вариант мне очень хорошо знаком.

                  Возможно вас ввело в заблуждение название «сервер». Правильнее было бы его называть Operation Support System (OSS). Это комплекс, который используется для работы с сетью и представляет готовую систему для обслуживающего персонала. Т.е. он уже выполняет целый ряд стандартных функций таких как отслеживание аварий, статистика, билинг, конфигурирование, обновление программного обеспечения и многое-многое другое.

                  В смысле частные случаи? Это самый обычный случай в связи. Я не знаю о каких сетях говорите вы, а я говорю о сетях национального масштаба с тысячами роутеров. Я даже не могу себе представить идиотов, которые бы взялись это обслуживать вручную. И даже не смотря на то, что это стоит безумных денег это все покупается. Просто потому, что по-другому не получится. И еще раз повторяю. На OSS есть все, о чем заявили.

                  Я в самом начале написал, что можно писать на чем угодно. И готов это повторить. Вопрос не в языке. Вопрос в поддержке. Когда вы пишете на рекомендуемом языке вы используете библиотеку, которую вам предоставил производитель и работу которой он гарантирует. Вы не городите велосипеды. Вы говорите connect и библиотека сама продирается через уровни security и сама запихивает ваши команды на нужный узел или узлы. И если мы говорим о ssh, то вопросов почти нет. Во всяком случае они все решаемые. А если протокол закрыт? Допустим вы таки смогли разобраться. Но что-то пошло не так. И вы обращаетесь за консультацией к поставщику. А он мало того, что обиделся, что вы его протокол ковыряли (и еще хорошо, что санкций не последовало), так еще и очень вежливо говорит, что не собирается разбираться почему в вашем велосипедике когда вы крутите педали он мало того, что едет назад, так еще и поворачивает. И это будет очень здорово, что именно этим все закончится.

                  Сейчас многие производители рекомендуют Python. А с учетом того, что все сейчас ломанулись в облака, то без OpenStack точно не обойдется. А значит Python еще сильнее укрепит свои позиции как в сетях, так и в связи в целом.


        1. evseev
          21.07.2017 07:00
          +1

          Вы не найдете никаких особых отличий и в других языках. Как я уже и писал можно автоматизировать на любом из них. Даже на самых экзотических. Как-то мне попалась статья, где автоматизация делалась на Haskell.

          Но дело не в самих языках. Дело в производителях. Они ведь не только говорят, что используйте Python потому, что нам так нравится. Когда у вас сеть из сотен, а то и тысяч устройств вы покупаете OSS сервер (как бы он не назывался в каждом конкретном случае), который уже обладает целым рядом инструментов, но если вам нужно что-то сделать дополнительно, то у вас есть выбор написать все нужные велосипеды, а потом то, что вам нужно на любом нравящемся языке, а можно воспользоваться уже готовыми библиотеками, которые помогают вам получать данные о сети и всех устройствах, ходить на них и там получать нужные параметры, работать с данными на самом сервере. Ведь обработку статистики или обработку аварий никто не отменял. Кроме скриптом в у вас еще куча другой работы. На велосипеды просто не остается времени. Поэтому да, Python, зачастую, хороший выбор уже просто потому, что его уже выбрали.

          Может быть это несколько обидно, что обошли вниманием по всей видимости любимый вами PHP, но тут только два пути. Или обижаться или выучить Python. Лично я предпочитаю второй путь. Поэтому я писал на многих языках. В том числе и на всякой экзотике, которую предлагают производители. Они могут быть кривыми и неудобными, но они позволяют быстро сделать то, что мне нужно. И это в них главное.


  1. kireevco
    19.07.2017 01:04
    +1

    Когда-то написал вот такой вот инструмент: https://github.com/kireevco/inventory-tamer сканирует сеть при помощи nmap, логинится через ssh по базе известных пар юзернейм-пароль, узнает ОС, если VMWare добывает еще информацию о том какие виртуалки работают складывает все в отчет нужного формата.


    Пригодилось несколько раз когда приходишь в организацию с запущенным инвентарем


    Сейчас для управления зоопарками использую Ansible, души в нем не чаю.
    Кстати, inventory-tamer может генерировать inventory для того же Ansible :)


  1. Punyaan
    19.07.2017 05:09

    Весьма хорошее применение Python. Спасибо за статью.
    Но есть пара вопросов больше с точки зрения необходимости использования таких методов при решении подобной задачи. У меня нет опыта работы с большой сетью так что у меня возникает вопрос.
    Я так понимаю что Hostname и ip железки редко меняющиеся параметры, тогда этот скрипт будет работать с отдачей по всем хостам 1 раз. Далее просто будут добавлять записи в DNS чуть ли не по 1 штуке при подключении нового оборудования.
    Разве задача решаемая этим скриптом не одноразовая, разве далее не целесообразней просто сразу заносить в DNS записи об оборудовании(руками или конфигурирующим скриптом)? Если при конфигурировании железки соблюдать регламенты(представим сферического коня/ИТ-службу в вакууме), то и скрип станет просто не нужен.


    1. zw_irk
      19.07.2017 05:21

      Тут вот в чём дело, в DNS планируется добавлять и интерфейсы тоже. А значит при каждом изменении description, адреса придётся руками менять записи в файлах зон. Проще запускать раз в неделю/месяц скрипт, который полностью заменит существующие файлы. Если на момент запуска скрипта часть устройств будет недоступна, это не критично, так как процент таковых будет очень мал.
      Конечно, идею можно развить: хранить собираемое в базе данных, генерировать файлы зон из базы. Убирать из базы записи, если устройство с ними не отвечало, например, две недели. Но, наверно, тут лучше адреса брать не из файла, а из базы системы мониторинга.
      Если же в DNS добавляется только один адрес с устройства, то можно и вручную заполнять. Но скрипт точно будет без опечаток:)


    1. evseev
      19.07.2017 11:28

      Если вы что-то автоматизировали и это отработало только один раз- это нормально и в этом нет ничего плохого. Но один раз получается очень не часто. Если мы говорим про большую сеть, то ее обслуживает и большое количество людей. И такие сети могут покрывать огромные расстояния. Вы можете даже никогда не увидеть людей, с которыми сотрудничаете годами. Представьте себе вышел из строя роутер за сотни километров от вас. Его заменил кто-то на месте и допустил ошибку при конфигурировании. И совсем не обязательно это вылезет сразу. И тут скриптик понадобится еще раз. И было бы хорошо иметь данные для сравнения и разницу получать на почту. В общем нет предела совершенству.

      К тому-же если скрипт написан, то его содержание всегда можно изменить на нужное. Остальные части уже готовы. И скрипт уже будет запущен еще раз, а потом и еще раз ;)


  1. sizziff
    19.07.2017 10:17

    Ребята а как же NOC? Он же специально заточен под сетевые девайсы. Да и питона там хватает.

    Лично у меня есть небольшой опыт работы с c++, VBS, Delphi, powershell… т.е. я имею представление о синтаксисе этих языков, владею такими штуками как указатели, ссылки, классы, коллекции… и каждый раз когда возникала необходимось что то автоматизировать — в большинстве случаев это был notepad++ т.к. трудозатраты на код были слишком большими. Но самая большая проблема — это выход из зоны комфорта т.к. программироавание это не основрой навык. К питону относился со скепсисом потому что там нет скобочек, да и в целом питон — не звучит…

    Но вот как то сел на него и… Код пишется буквально налету. Получается сразу! Практически любая идея заканчивается небольшим куском рабочего кода. Куча библиотек. Куча готового кода. Поддержка вендоров.

    Хочу добавить, что сетевику так же необходимо освоить регулярные выражения. Это отдельный непростой слой. В отличае от питона — высокий порог вхождения, но надо. К тому же регулярные выражения нужны и в powershell и в bash.


    1. zw_irk
      19.07.2017 10:21

      Со всем согласен

      сетевику так же необходимо освоить регулярные выражения

      а тут не соглашусь:) Сложно понять логику регулярных выражений. Однако, CLI ведущих вендоров поддерживает регулярные выражения для фильтрации выводов команда типа show. Там всё проще и наглядно.


      1. evseev
        19.07.2017 11:50

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

        Не все поставщики позволяют фильтровать вывод. А те, что позволяют, не всегда дают достаточно свободы. Если у вас на работе приняты внутренние стандарты на все, то вы может и будете знать как будут выглядеть нужные вам поля. А если нет? Скажем вам нужно угадать как будет называться конфиг если вы знаете только то, что он может заканчиваться на cfg, cf или conf. А у особых раздолбаев и вообще быть без расширения. И тогда вам остается или все проверять руками или таки научится пользоваться Re.

        PS: Если регулярки действительно очень тяжело идут, то можно использовать специальные программы, которые почти все сделают за вас. Вам останется только вставить готовую строку в ваш скрипт. На память помню только RegexBuddy, но для понимания о чем я говорю думаю хватит.


    1. zw_irk
      20.07.2017 07:53

      Должен поправиться: комментарий «а тут не соглашусь:) » относился к фразе «Это отдельный непростой слой».
      Регулярные выражения просты, но не интуитивны для начинающего. Самый простой способ начать их использовать в CLI сетевого оборудования, или, как уже написал evseev, использовать готовые утилиты, бросая им на вход текст и регулярные выражения, анализируя результат.


  1. chemtech
    19.07.2017 13:36

    zw_irk продолжение будет?


    1. zw_irk
      19.07.2017 14:15

      Обязательно. Скрипт уже год формирует зоны bind на реальной сети. Сейчас, фактически, я заново, поэтапно восстанавливаю процесс его написания. По идее, потом, на основе этого скрипта и статей, каждый сможет собрать из кусочков свои скрипты, использующие snmp.
      Я опасаюсь давать какие-нибудь обещания по поводу сроков написания второй статьи, так как сейчас пишу с больницы. Но первая страница черновика уже набрана.


  1. AVX
    19.07.2017 15:26

    Python — мощная штука. Достаточно взглянуть на примеры из комплекта — очень похоже, что на нём можно чуть ли не пол-линукса написать (большинство утилит точно можно).
    Так что, если где-то нет возможности поставить какой-то софт (зависимости там или ещё что), то вполне можно написать свой велосипед на пайтон (никак не могу отучить себя от привычки называть его питон).

    P.S. Тут упоминали про скрипты, которые везде работают — так вот, писал я скрипт, который (один и тот же файл) работал и на винде, и в линуксе, да ещё и с GUI, если надо. В одном файле код для bash, cmd, powershell, (ну и чуть всякого для GUI — из hta, IE, KDE). Основная проблема — код для разных ОС всё-таки разный, и для его модификации нужно и там и там править и отлаживать. Писалось это не для рабочих целей, а так, just for fun.


    1. evseev
      19.07.2017 17:58

      Написать можно, но результат не всегда вам будет нравится. Нет, работать все будет. Тут вопросов нет. Но чистый Python очень медленный. Скажем в 1000 раз медленнее, чем С++ или Java. И это не всегда подходит.

      Если нет возможности поставить другой софт, то почему все будет хорошо с Python? Он, конечно, малюсенький по современным меркам, но ни как не меньше 20МB. Да и с библиотеками можно попасть в неприятную ситуацию. Особенно если это какая-то специализированная система со старым Linux. Я как-то имел удовольствие с таким повозится. Было не очень.

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