Эта статья в основном для сетевых инженеров, которые пока не знакомы или очень слабо знакомы с Python. Мы рассмотрим пример скрипта для решения некоторых практических задач, который вы сразу сможете применять в своей работе.
Для начала расскажу, почему я выбрал Python.
Во-первых, это легкий в освоении язык программирования, который позволяет решать очень широкий круг задач.
Во-вторых, крупные производители сетевого оборудования, такие как Cisco, Juniper, Huawei, внедряют поддержку Python на своем оборудовании. У языка есть будущее в сетевой сфере, и его изучение не будет пустой тратой времени.
В-третьих, язык очень распространен. Для него написано много полезных библиотек, есть большое сообщество программистов, и найти ответы на большинство вопросов в интернете можно в первых строках поисковой выдачи.
Я занимаюсь проектированием и немного внедрением сетевых проектов. В одном из них потребовалось решить сразу две задачи.
- Пройтись по нескольким сотням филиальных маршрутизаторов и убедиться, что они настроены единообразно. Например, что для связи с ЦОД используется интерфейс Tunnel1, а не Tunnel0 или Tunnel99. И что эти интерфейсы настроены одинаково, за исключением их IP-адресов, естественно.
- Перенастроить все маршрутизаторы, в том числе добавить статический маршрут через IP-адрес местного провайдера. То есть эта команда будет уникальной для каждого маршрутизатора.
На помощь пришел скрипт на Python. Его разработка и тестирование заняли один день.
Первое, что нужно сделать, это установить Python и крайне желательно PyCharm CE. Скачиваем и устанавливаем Python 3 (сейчас последняя версия 3.6.2). При установке выбираем «Customize installation» и на этапе «Advanced Options» устанавливаем галку напротив «Add Python to environment variables».
PyCharm CE — это бесплатная среда разработки с очень удобным отладчиком. Скачиваем и устанавливаем.
Второй шаг — устанавливаем необходимую библиотеку netmiko. Она нужна для взаимодействия с устройствами по SSH или telnet. Библиотеку устанавливаем из командной строки:
pip install netmiko
Третьим шагом будет подготовка исходных данных и скрипта под наши задачи.
В качестве входных данных будем использовать текстовый файл “ip.txt”. В каждой строчке файла должен быть IP-адрес устройства, к которому мы подключаемся. Через запятую можно указать логин и пароль для конкретного устройства. Если этого не сделать, то будут использоваться те, которые вы введёте при запуске скрипта. Пробелы будут проигнорированы. Если первый символ в строке «#», то она считается комментарием и игнорируется. Вот пример корректного файла:
Сам скрипт логически состоит из двух частей: основной программы и функции
doRouter()
. Внутри неё выполняется подключение к маршрутизатору, отправка команд в CLI, получение и анализ ответов. Входными данными для функции являются: IP-адрес маршрутизатора, логин и пароль. При возникновении проблем функция вернёт IP-адрес маршрутизатора, мы его запишем в отдельный файл fail.txt. Если всё прошло хорошо, то будет просто выведено сообщение на экран.Почему нужно выносить взаимодействие с маршрутизаторами в отдельную функцию, а не выполнить всё в цикле в основной программе? Главная причина — продолжительность работы скрипта. Подключение поочередно ко всем маршрутизаторам заняло у меня 4 часа. В основном из-за того, что какие-то из них не отвечали и скрипт долго ждал истечения таймаута. Поэтому запускать мы будем параллельно по 10 экземпляров функций. В моём случае это сократило время выполнения скрипта до 10 минут.
Рассмотрим теперь подробнее основную программу.
Ради безопасности не будем хранить логин и пароль в скрипте. Поэтому выведим на экран приглашение для их ввода. Причем при вводе пароля он не будет отображаться. Эти глобальные переменные используем в процедуре
doRouter
. У меня были проблемы с работой getpass в PyCharm под Windows. Скрипт работал корректно, только если выполнять его в режиме Debug, а не Run. В командной строке всё работало без нареканий. Также скрипт тестировался в OS X, там проблем в PyCharm замечено не было.user_name = input("Enter Username: ")
pass_word = getpass()
Потом читаем файл с IP-адресами. Конструкция
try…except
позволит корректно обработать ошибку чтения файла. На выходе получим массив данных для подключения connection_data
, содержащий IP-адрес, логин и пароль.try:
f = open('ip.txt')
connection_data=[]
filelines = f.read().splitlines()
for line in filelines:
if line == "": continue
if line[0] == "#": continue
conn_data = line.split(',')
ipaddr=conn_data[0].strip()
username=global_username
password=global_password
if len(conn_data) > 1 and conn_data[1].strip() != "": username = conn_data[1].strip()
if len(conn_data) > 2 and conn_data[2].strip() != "": password = conn_data[2].strip()
connection_data.append((ipaddr, username, password))
f.close()
except:
sys.exit("Couldn't open or read file ip.txt")
Далее создаём список процессов и запускаем их. Метод создания процессов я задал как “spawn”, чтобы в Windows и OS X скрипт работал одинаково. Количество созданных процессов будет равно количеству IP-адресов. Но выполняться одновременно будут не более 10. В список
routers_with_issues
записываем то, что вернут функции doRouter
. В нашем случае это IP-адреса маршрутизаторов, с которыми были проблемы.multiprocessing.set_start_method("spawn")
with multiprocessing.Pool(maxtasksperchild=10) as process_pool:
routers_with_issues = process_pool.map(doRouter, connection_data, 1)
process_pool.close()
process_pool.join()
Команда
process_pool.join()
нужна для того, чтобы скрипт дождался завершения выполнения всех экземпляров функций doRouter()
и только потом продолжил выполнять основную программу.В конце создаем/переписываем текстовый файл, в котором у нас будут IP-адреса ненастроенных маршрутизаторов. Также выводим этот список на экран.
failed_file = open('fail.txt', 'w')
for item in routers_with_issues:
if item != None:
failed_file.write("%s\n" % item)
print(item)
Теперь разберем процедуру
doRouter()
. Первое, что нужно сделать, — обработать входные данные. С помощью ReGex проверяем, что функции был передан корректный IP-адрес.ip_check = re.findall("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", ip_address)
if ip_check == []:
print(bcolors.FAIL + "Invalid IP - " + str(ip_address) + bcolors.ENDC)
return ip_address
Далее создаём словарь с необходимыми для подключения данными и подключаемся к маршрутизатору.
device = {
'device_type': 'cisco_ios',
'ip': ip_address.strip(),
'username': username,
'password': password,
'port': 22, }
try:
config_ok = True
net_connect = ConnectHandler(**device)
Отправляем команды и анализируем полученный ответ от маршрутизатора. Он будет помещён в переменную
cli_response
. В этом примере мы проверяем текущие настройки. Результат выводим на экран. Данную часть нужно менять под разные задачи. В этом скрипте проверяем текущую конфигурацию маршрутизатора. Если она корректная, то вносим изменения. Если при проверке обнаружены проблемы, то присваиваем переменной config_ok
значение False
и не применяем изменения.cli_response = net_connect.send_command("sh dmvpn | i Interface")
cli_response = cli_response.replace("Interface: ", "")
cli_response = cli_response.replace(", IPv4 NHRP Details", "").strip()
if cli_response != "Tunnel1":
print(str(ip_address)+" - " + bcolors.WARNING + "WARNING - DMVPN not on Tunnel1. " + cli_response+ " " + bcolors.ENDC)
config_ok=False
Тут будут полезны следующие операции работы со строками.
Операция | Описание | Пример |
---|---|---|
+ | Объединение строк | s3 = s1 + s2 >>> print('Happy New ' + str(2017) + ' Year') Happy New 2017 Year |
len(s) | Определение длины строки | |
[] | Выделение подстроки (индекс начинается с нуля) | s[5] — шестой символ s[5:7] — символы с шестого по восьмой s[-1] — последний символ, то же, что s[len(s)-1] |
s.split() s.join() |
Разделить строки Объединить строки |
>>> 'Петя, Лёша, Коля'.split(',') ['Петя', 'Лёша', 'Коля'] >>> ','.join({'Петя', 'Лёша', 'Коля'}) 'Лёша, Петя, Коля' |
str(L) list(s) |
Преобразовать список в строку Преобразовать строку в список |
>>> str(['1', '2', '3']) "['1', '2', '3']" >>> list('Test') ['T', 'e', 's', 't'] |
% | Форматирование по шаблону | >>> s1, s2 = 'Митя', 'Василиса' >>> '%s + %s = любовь' % (s1, s2) 'Митя + Василиса = любовь' |
f | Подстановка переменных | >>> a='Максим' >>> f'Имя {a}' 'Имя Максим' |
str.find(substr) | Поиск подстроки substr в строке str Возвращает позицию первой найденной подстроки |
>>> 'This is a text'.find('a') 8 |
str.replace(old, new) | Замена подстроки old на подстроку new в строке str | >>> newstr = 'This is a text'.replace(' is ', ' is not ') >>> print(newstr) This is not a text |
str.strip() str.rstrip() |
Удалить пробелы и табуляции в начале и конце (или только в конце) | >>> ' This is a text \t\t\t'.strip() 'This is a text' |
Чтобы решить задачу по добавлению статического маршрута, для начала нужно определить IP-адрес
next-hop
. В моем случае самый простой способ — посмотреть адрес next-hop
у существующих статических маршрутов.cli_response2=net_connect.send_command("sh run | i ip route 8.8.8.8 255.255.255.255")
if cli_response2.strip() == "":
print(str(ip_address)+" — " + bcolors.FAIL + "WARNING — couldn't find static route to 8.8.8.8" + bcolors.ENDC)
config_ok=False
ip_next_hop = ""
if cli_response2 != "":
ip_next_hop = cli_response2.split(" ")[4]
if ip_next_hop == "":
print(str(ip_address)+" — " + bcolors.FAIL + "WARNING — couldn't find next-hop IP address " + bcolors.ENDC)
config_ok=False
Можно отправлять одну или несколько конфигурационных команд сразу. У меня плохо работала отправка больше 5 команд одновременно, при необходимости можно просто повторить конструкцию несколько раз.
config_commands = ['ip route 1.1.1.1 255.255.255.255 '+ip_next_hop,
'ip route 2.2.2.2 255.255.255.255 '+ip_next_hop]
net_connect.send_config_set(config_commands)
import sys
from netmiko import ConnectHandler
from getpass import getpass
import time
import multiprocessing
import re
start_time = time.time()
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
def doRouter(connection_data):
ip_address = connection_data[0]
username = connection_data[1]
password = connection_data[2]
ip_check = re.findall("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", ip_address)
if ip_check == []:
print(bcolors.FAIL + "Invalid IP - " + str(ip_address) + bcolors.ENDC)
return ip_address
device = {
'device_type': 'cisco_ios',
'ip': ip_address.strip(),
'username': username,
'password': password,
'port': 22, }
try:
config_ok = True
net_connect = ConnectHandler(**device)
cli_response = net_connect.send_command("sh dmvpn | i Interface")
cli_response = cli_response.replace("Interface: ", "")
cli_response = cli_response.replace(", IPv4 NHRP Details", "").strip()
if cli_response != "Tunnel1":
print(str(ip_address)+" - " + bcolors.WARNING + "WARNING - DMVPN not on Tunnel1. " + cli_response+ " " + bcolors.ENDC)
config_ok=False
cli_response2=net_connect.send_command("sh run | i ip route 1.1.1.1 255.255.255.255")
if cli_response2.strip() == "":
print(str(ip_address)+" - " + bcolors.WARNING + "WARNING - couldn't find static route to 8.8.8.8" + bcolors.ENDC)
config_ok=False
ip_next_hop = ""
if cli_response2 != "":
ip_next_hop = cli_response2.split(" ")[4]
if ip_next_hop == "":
print(str(ip_address)+" - " + bcolors.WARNING + "WARNING - couldn't find next-hop IP address " + bcolors.ENDC)
config_ok=False
if config_ok:
config_commands = ['ip route 1.1.1.1 255.255.255.255 '+ip_next_hop,
'ip route 2.2.2.2 255.255.255.255 '+ip_next_hop]
net_connect.send_config_set(config_commands)
print(str(ip_address) + " - " + "Static routes added")
else:
print(str(ip_address) + " - " + bcolors.FAIL + "Routes weren't added because config is incorrect" + bcolors.ENDC)
return ip_address
if config_ok:
net_connect.send_command_expect('write memory')
print(str(ip_address) + " - " + "Config saved")
net_connect.disconnect()
except:
print(str(ip_address)+" - "+bcolors.FAIL+"Cannot connect to this device."+bcolors.ENDC)
return ip_address
print(str(ip_address) + " - " + bcolors.OKGREEN + "Router configured sucessfully" + bcolors.ENDC)
if __name__ == '__main__':
# Enter valid username and password. Note password is blanked out using the getpass library
global_username = input("Enter Username: ")
global_password = getpass()
try:
f = open('ip.txt')
connection_data=[]
filelines = f.read().splitlines()
for line in filelines:
if line == "": continue
if line[0] == "#": continue
conn_data = line.split(',')
ipaddr=conn_data[0].strip()
username=global_username
password=global_password
if len(conn_data) > 1 and conn_data[1].strip() != "": username = conn_data[1].strip()
if len(conn_data) > 2 and conn_data[2].strip() != "": password = conn_data[2].strip()
connection_data.append((ipaddr, username, password))
f.close()
except:
sys.exit("Couldn't open or read file ip.txt")
multiprocessing.set_start_method("spawn")
with multiprocessing.Pool(maxtasksperchild=10) as process_pool:
routers_with_issues = process_pool.map(doRouter, connection_data, 1) # doRouter - function, iplist - argument
process_pool.close()
process_pool.join()
print("\n")
print("#These routers weren't configured#")
failed_file = open('fail.txt', 'w')
for item in routers_with_issues:
if item != None:
failed_file.write("%s\n" % item)
print(item)
#Completing the script and print running time
print("\n")
print("#This script has now completed#")
print("\n")
print("--- %s seconds ---" % (time.time() - start_time))
После подготовки скрипта выполнить его можно из командной строки или из PyCharm CE. Из командной строки запускаем командой:
python script.py
Я рекомендую пользоваться PyCharm CE. Там создаём новый проект, файл Python (File > New…) и вставляем в него наш скрипт. В папку со скриптом кладем файл ip.txt и запускаем скрипт (Run > Run)
Получаем следующий результат:
bash ~/PycharmProjects/p4ne $ python3 script.py
Enter Username: cisco
Password:
Invalid IP - 10.1.1.256
127.0.0.1 - Cannot connect to this device.
1.1.1.1 - Cannot connect to this device.
10.10.100.227 - Static routes added
10.10.100.227 - Config saved
10.10.100.227 - Router configured sucessfully
10.10.31.170 - WARNING - couldn't find static route to 8.8.8.8
10.10.31.170 - WARNING - couldn't find next-hop IP address
10.10.31.170 - Routes weren't added because config is incorrect
2.2.2.2 - Cannot connect to this device.
#These routers weren't configured#
10.1.1.256
127.0.0.1
217.112.31.170
1.1.1.1
2.2.2.2
#This script has now completed#
Пару слов о том, как отладить скрипт. Легче всего это делать в PyCharm. Отмечаем строчку, на которой хотим остановить выполнение скрипта, и запускаем выполнение в режиме отладки. После того, как скрипт остановится, можно будет посмотреть текущие значения всех переменных. Проверить, что передаются и принимаются корректные данные. Кнопками «Step Into» или «Step Into My Code» можно пошагово продолжить выполнение скрипта.
Ограничения описанной версии скрипта:
- тестировался только в Python 3
- не умеет обрабатывать ситуацию, когда вы в первый раз подключаетесь к маршрутизатору и получаете вопрос вида:
The authenticity of host '11.22.33.44 (11.22.33.44)' can't be established.
RSA key fingerprint is SHA256:C+BHaMBjuMIoEewAbjbQbRGdVkjs&840Ve3z4aJo.
Are you sure you want to continue connecting (yes/no)?
Этот скрипт был написан для решения конкретных задач. Однако он универсален и, надеюсь, поможет ещё кому-нибудь в работе. А самое главное — послужит первым шагом в освоении Python.
При написании скрипта использовались следующие ресурсы:
- https://github.com/ktbyers/netmiko — страница библиотеки netmiko на GitHub. Там есть документация и примеры.
- https://pynet.twb-tech.com/blog/automation/netmiko.html — ещё один пример с netmiko
- https://docs.Python .org/3/library/multiprocessing.html — описание и примеры библиотеки multiprocessing
Александр Гаршин, ведущий инженер-проектировщик систем передачи данных компании «Инфосистемы Джет»
Комментарии (43)
Numen_Divinum
29.08.2017 12:41+3karabanov
29.08.2017 22:28Пришёл разместить эту ссылку, а она уже здесь ;-)
Хороший курс. Рекомендую.
Cobolorum
29.08.2017 12:51-3Извини «автор» но на рисунке тянущие телегу на квадратных колесах это похоже ваши сотрудники. А мужичек предлагающий колеса это тот кто знает: bash, command line utilities.
Не гонитесь за популярностью изучайте классику.PO_Habr Автор
29.08.2017 13:23+2Если что-то изучать с нуля, то из бесплатных продуктов Python выглядит наиболее подходящим для сетевого инженера. Кроме изменения конфигурации через CLI его можно использовать для взаимодействия через RestAPI. Кроме того, у Cisco, Huawei и Juniper уже есть встроенный интерпретатор Python в некоторых маршрутизаторах и коммутаторах. Для Cisco это ISR 4000, Nexus 9000. Думаю, этот список будет расширяться.
VFedorV
29.08.2017 14:34а можно детальнее об этом:
python on Cisco это ISR 4000
? настраивал ISR 4331 и не заметил ничего :(PO_Habr Автор
29.08.2017 15:01+2Для ISR нужен отдельный софт из линейки Everest. Сейчас последний — isr4300-universalk9.16.06.01.SPA.bin. С версии Everest 16.5.1b появилась поддержка Python 2.7/3.0 для ISR 4k, CSR, ASR.
Вот полезная вводная статья:
https://communities.cisco.com/community/developer/blog/2017/04/17/introducing-python-and-guest-shell-on-ios-xe-165
mklochkov
29.08.2017 13:29+1Тут ведь как — если у вас в руках молоток, любая проблема будет казаться гвоздём.
Автор явно написал — ему нужно было «одинаково под Windows и Mac OS X». И какие есть возможности под Windows? Баша «из коробки» там нет, PowerShell — это свой отдельный мир, можно ещё cygwin поставить (большой, тяжёлый, со своими проблемами). Python в данном случае не худший выбор.
siziyman
29.08.2017 16:43+2Вот только сам Борн говорил в этом десятилетии, что решать сколько-нибудь большие задачи — не то, на что рассчитывались шелл-скрипты (в процессе дизайна, разработки языка), и рекомендовал избегать этого, иначе костылей в процессе собирается (и грабель проходится) немерено.
А в общем случае задачи системного администратора могут требовать довольно сложных комбинаций действий, и тогда становится и проще, и разумнее использовать тот же Python.
rSedoy
29.08.2017 12:51небольшой оффтопик: со стилем программирования на python от ученых и инженеров ничего не поделать, надо привыкать ;)
manefesto
29.08.2017 13:13согласен, например это
print(bcolors.FAIL + "Invalid IP - " + str(ip_address) + bcolors.ENDC)
очень красиво можно сделать так
print("%s Invalid IP - %s %s "%(bcolors.FAIL,ip_address,bcolors.ENDC))
rSedoy
29.08.2017 13:19+1да там много чего: несоблюдение pep8, общий except, открытие файла по-старому и т.д.
PO_Habr Автор
29.08.2017 14:24Спасибо за советы. Элегантность кода, надеюсь, появится с опытом.
g0rd1as
29.08.2017 17:37Оно может и некрасиво, но это простительно — вы в конце концов не программист. Главное, чтоб оно корректно работало. а под стандарты и представления о прекрасном можно и потом подогнать, если очень припрет.
Stillgray
29.08.2017 13:09А ещё есть expect: paulgporter.net/2012/12/08/30
ru.wikipedia.org/wiki/Expect
chicagoist
29.08.2017 14:23Я склоняюсь к тому, что Lua удобнее во всех отношениях по сравнению с Python. Для задач администрирования.
PO_Habr Автор
29.08.2017 14:23+1С Lua не работал, но насколько я знаю, там нет такого количества доступных библиотек, как для Python. В интернете по запросу cisco+lua находятся в основном статьи про SIP и CUCM. Не поделитесь ссылкой на какую-нибудь полезную статью про использование lua для работы с конфигами сетевых устройств? Будет интересно почитать.
chicagoist
29.08.2017 23:11Со стороны рынка и спроса — конечно Python несомненный лидер.
С академической точки зрения — Python это бастард.
К примеру Tcl, или Lua — то есть такие скриптовые языки,
которые ни на что серьёзное не претендуют, оставаясь именно что языками
командно-скриптовыми, предназначенными для управления другими программами.
Опять же, в администрении всё-таки чаще применяется Bourne Shell (при всей
его дубовости это однозначное must know для эксплуатационщика).
С моей точки зрения Python не имеет права на существование, как и Perl, и
Ruby, и вообще любой интерпретируемый (и тем более командно-скриптовой)
язык, имеющий претензии на роль языка общего назначения.
Но… рынок труда со мной не согласен. ;-)
P.S.
www.ibm.com/developerworks/ru/library/l-lua_3/index.html
robot-develop.org/archives/3717
mklochkov
29.08.2017 23:55+1Опять же, в администрении всё-таки чаще применяется Bourne Shell (при всей его дубовости это однозначное must know для эксплуатационщика).
Достоинство у него ровно одно — в любой юникс-подобной операционке он есть «из коробки». Никакой алгоритм, подразумевающий работу с данными, организованными более сложно, чем последовательность строк, на нём реализовать невозможно, просто нет соответствующих средств.
С моей точки зрения Python не имеет права на существование, как и Perl, и Ruby, и вообще любой интерпретируемый (и тем более командно-скриптовой)
язык, имеющий претензии на роль языка общего назначения.
А, собственно, почему? Даже спрошу иначе — а где, по вашему, проходит граница между компилируемым и интерпретируемым (Java какая?), а также командно-скриптовым и «не-скриптовым» языками (php какой)?khim
30.08.2017 01:59+1Никакой алгоритм, подразумевающий работу с данными, организованными более сложно, чем последовательность строк, на нём реализовать невозможно, просто нет соответствующих средств.
Да ладно вам. Я сам лично несколько лет назад писал скрипт, который олавливал зависимости между пакетами и делал удобный инсталлятор с помощью NSIS. Всё на bash, включая топологичествую сортировку, проверки зависимостей и прочее.
Дополнительный плюс: за 5 лет скрипт никто так и не изуродовал, так как никто просто не знает — с какой стороны к нему подступиться.
andjel
29.08.2017 14:25А может перестать бояться, изобретать велосипед, и освоить настоящий инструмент? :)
docs.ansible.com/ansible/latest/list_of_network_modules.htmlKarroplan
29.08.2017 14:33-1ansible — это довольно кривая и хреново документированная надстройка над голым питоном ) вместо того чтоб изучать питон, придется изучать ансибл, причем изучать по слухам, т.к. нормальной информации о том как оно работает нету.
нормальный инструмент называется HP Network Automation Toolmanefesto
29.08.2017 16:33советую почитать на досуге www.allitebooks.com/ansible-for-devops
Karroplan
29.08.2017 16:35а эта книга актуальна для какой версии ansible?
manefesto
30.08.2017 08:36Для любой, на всякий случай есть docs.ansible.com/ansible/latest/index.html где есть актуальная информация
Karroplan
30.08.2017 10:44уверены? там нет никакой актуальной информации про использование промежуточного hop-off сервера, например.
PO_Habr Автор
29.08.2017 14:50+1Это следующий шаг для администрирования. Модули для Ansible пишутся в том числе и на Python, поэтому знакомство с ним лишним не будет. Python сам по себе более гибкий инструмент и позволяет решать более широкий спектр задач. Например, можно написать скрипт, собирающий с оборудования необходимые данные и записывающий их в Excel-файл. И это могут быть не только конфигурации устройств, но и таблицы mac, ARP, RIB, состояние сессий протоколов маршрутизаций.
missing_thing
29.08.2017 19:33+1Используйте библиотеки. Например, вместо regex проверки IP можно использовать docs.python.org/3/library/socket.html#socket.inet_aton
DonAlPAtino
31.08.2017 16:06Сорри за дурацкий вопрос, а под Windows это вообще работоспособно? Сразу все упало с ModuleNotFoundError: No module named 'pyasn1' при том, что
D:\PycharmProjects\cisco>«C:\Program Files\Python36\Scripts\pip.exe» install pyasn1
Requirement already satisfied: pyasn1 in c:\program files\python36\lib\site-packages\pyasn1-0.3.3-py3.6.egg
Долго и нудно с библиотеками шаманить надо?PO_Habr Автор
31.08.2017 20:07Я использовал этот скрипт на Windows 10. Также перед публикацией пробовал запустить его на чистой Windows 7, действуя по шагам из статьи. То есть установив только Python 3.6 и библиотеку netmiko. К сожалению, такой ошибки ни разу не встречал. Pyasn1 нужен библиотеке paramiko, которая поставится сама при установке netmiko. Может, попробовать переустановить библиотеки pyasn1, netmiko и paramiko? (pip uninstall/pip install)
Также выложил скрипт на GitHub. Предлагаю скопировать его оттуда. В скрипте из статьи могут быть лишние символы.
https://github.com/aagarshin/habr/
manefesto
и чем он лучше paramiko?
Здесь например показано jessenoller.com/blog/2009/02/05/ssh-programming-with-paramiko-completely-different как через AutoAddPolicy() решить вопрос с RSA key fingerprint
Да, paramiko не умеет работать с telnet, но на большинстве коммутаторов, маршрутизаторов есть поддержка ssh
PO_Habr Автор
Paramiko хорошая альтернатива. Но конкретно мне нужен был telnet и SSHv1 для ASA, ввезённой без строгого шифрования.
Dimi3
«netmiko» это по факту и есть оболочка для «paramiko» (название намекает).
Просто в ней куски кода, которые сетевики писали раза от раза используя paramiko (распознование конца вывода, смена промпта, непосредственно процесс подключения и т.п.), объеденены в сподручные функции, и он из коробки довольно стабильно (у меня небыло глюков) работает с самыми распространенными осями сетевых устройств.