645

Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

  • Upload
    others

  • View
    22

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно
Page 2: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

1.1

1.2

1.3

1.4

1.5

1.6

1.7

1.7.1

1.7.2

1.7.3

1.7.4

1.7.5

1.8

1.8.1

1.8.2

1.8.2.1

1.8.3

1.9

1.9.1

1.9.2

1.9.2.1

1.9.2.2

1.9.3

1.9.3.1

1.9.3.2

1.9.4

1.9.4.1

1.9.4.2

1.9.4.2.1

1.9.5

СодержаниеВведение

Окурсе

Какучитьсяпоэтомукурсу

Примерпланаобучения

FAQ

Благодарности

1.Подготовкакработе

ОСиредактор

Системауправленияпакетамиpip

virtualenv,virtualenvwrapper

ИнтерпретаторPython(проверка)

Задания

2.НачалоработысPython

СинтаксисPython

ИнтерпретаторPython.iPython

МагияiPython

Переменные

3.ТипыданныхвPython

Числа

Строки(Strings)

Полезныеметодыдляработысостроками

Форматированиестрок

Список(List)

Полезныеметодыдляработысосписками

Вариантысозданиясписка

Словарь(Dictionary)

Полезныеметодыдляработысословарями

Вариантысозданиясловаря

Словарьиздвухсписков(advanced)

Кортеж(Tuple)

2

Page 3: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

1.9.6

1.9.6.1

1.9.6.2

1.9.6.3

1.9.7

1.9.8

1.9.9

1.10

1.10.1

1.10.2

1.10.3

1.11

1.11.1

1.11.2

1.11.2.1

1.11.2.2

1.11.2.3

1.11.3

1.11.4

1.11.5

1.11.6

1.11.7

1.12

1.12.1

1.12.2

1.12.3

1.12.4

1.12.5

1.12.6

1.13

1.13.1

1.13.2

1.13.3

1.13.3.1

Множество(Set)

Полезныеметодыдляработысмножествами

Операциисмножествами

Вариантысозданиямножества

Преобразованиетипов

Проверкатипов

Задания

4.Созданиебазовыхскриптов

Передачааргументовскрипту

Вводинформациипользователем

Задания

5.Контрольходапрограммы

if/elif/else

for

Вложенныеfor

Совмещениеforиif

Итераторenumerate

while

break,continue,pass

for/else,while/else

Работасисключениямиtry/except/else/finally

Задания

6.Работасфайлами

Открытиефайлов

Чтениефайлов

Записьфайлов

Закрытиефайлов

Конструкцияwith

Задания

7.Функции

Созданиефункций

Пространстваимен.Областивидимости

Параметрыиаргументыфункций

Типыпараметров

3

Page 4: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

1.13.3.2

1.13.3.3

1.13.3.4

1.13.3.5

1.13.4

1.14

1.14.1

1.14.2

1.14.3

1.15

1.15.1

1.15.2

1.15.3

1.15.4

1.15.4.1

1.15.5

1.16

1.16.1

1.16.2

1.16.3

1.16.4

1.17

1.17.1

1.17.2

1.17.3

1.17.3.1

1.17.3.2

1.17.3.3

1.17.3.4

1.17.3.5

1.17.3.6

1.17.3.7

1.17.3.8

Типыаргументов

Аргументыпеременнойдлины

Распаковкааргументов

Примериспользования

Задания

8.Модули

Импортмодуля

Созданиесвоихмодулей

Задания

9.Регулярныевыражения

Модульre

Специальныесимволы

Жадностьрегулярныхвыражений

Группировкавыражений

Разборвыводакомандыshowipdhcpsnoopingспомощьюименованныхгрупп

Задания

10.Сериализацияданных

CSV

JSON

YAML

Задания

11.Работасбазамиданных

SQL

SQLite

ОсновыSQL(вsqlite3CLI)

CREATE

DROP

INSERT

SELECT

WHERE

ALTER

UPDATE

REPLACE

4

Page 5: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

1.17.3.9

1.17.3.10

1.17.4

1.17.4.1

1.17.5

1.18

1.18.1

1.18.2

1.18.3

1.18.4

1.18.5

1.18.5.1

1.18.6

1.18.6.1

1.18.6.2

1.18.7

1.19

1.19.1

1.19.2

1.19.3

1.19.3.1

1.19.3.2

1.19.3.3

1.19.3.4

1.19.3.5

1.19.3.6

1.19.3.7

1.19.3.8

1.19.4

1.19.5

1.20

1.20.1

1.20.2

DELETE

ORDERBY

Модульsqlite3

ПримериспользованияSQLite

Задания

12.Подключениекоборудованию

Вводпароля

Pexpect

Telnetlib

Paramiko

Netmiko

Возможностиnetmiko

Одновременноеподключениекнесколькимустройствам

Модульthreading

Модульmultiprocessing

Задания

13.ШаблоныконфигурацийсJinja

ПримериспользованияJinja

ПримериспользованияJinjaскорректнымиспользованиемпрограммногоинтерфейса

СинтаксисшаблоновJinja2

Контрольсимволовwhitespace

Переменные

for

if/elif/else

Фильтры

Тесты

Присваивание(set)

Include

Наследованиешаблонов

Задания

14.TextFSM.Обработкавыводакоманд

СинтаксисшаблоновTextFSM

ПримерыиспользованияTextFSM

5

Page 6: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

1.20.3

1.20.4

1.21

1.21.1

1.21.1.1

1.21.1.2

1.21.1.3

1.21.1.4

1.21.2

1.21.2.1

1.21.2.2

1.21.3

1.21.3.1

1.21.3.2

1.21.3.3

1.21.3.3.1

1.21.3.3.2

1.21.3.3.3

1.21.3.3.4

1.21.3.3.5

1.21.3.3.6

1.21.3.3.7

1.21.3.3.8

1.21.3.3.9

1.21.3.3.10

1.21.3.3.11

1.21.3.4

1.21.4

1.21.5

1.22

1.22.1

1.22.1.1

1.22.1.2

CLITable

Задания

15.Ansible

ОсновыAnsible

Инвентарныйфайл

Ad-Hocкоманды

Конфигурационныйфайл

Модули

Основыplaybook

Переменные

Результатвыполнениямодуля

Сетевыемодули

ios_command

ios_facts

ios_config

lines(commands)

parents

Отображениеобновлений

save

backup

defaults

after

before

match

replace

src

ntc_ansible

ПодробнееобAnsible

Задания

Дополнительнаяинформация

Полезныемодули

Модульsubprocess

Модульos

6

Page 7: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

1.22.1.3

1.22.1.4

1.22.2

1.22.2.1

1.22.2.2

1.22.2.3

1.22.2.4

1.22.2.5

1.22.2.6

1.22.3

1.22.3.1

1.23

1.23.1

1.23.2

1.24

Модульargparse

Модульipaddress

Полезныефункции

Функцияsorted

Функцияlambda

Функцияzip

Функцияmap

Функцияfilter

Функцииanyиall

Соглашениеобименах

Подчеркиваниевименах

Полезныессылки

Материалыпотемамкурса

Продолжениеобучения

Отзывы

7

Page 8: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Pythonдлясетевыхинженеров

Автор:НаташаСамойленко

ПрисоединяйтеськкомандеPyNEngвslack

Зачемвамучитьсяпрограммировать?Знаниепрограммированиядлясетевогоинженера,сравнимосознаниеманглийского.

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

доступновразыбольшелитературы,форумов,блоговпрактическидлялюбоговопроса/проблемыестьрешение,есливыввелизапросвгуглнаанглийском

Знаниепрограммированиявэтомоченьпохоже.Есливызнаете,например,Python,хотябынабазовомуровне,выужеоткрываетемассуновыхвозможностейдлясебя.

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

ОкурсеЕсливдвухсловах,тоэтотакой“CCNA”попитону.Соднойстороны,курсдостаточнобазовый,чтобыегомогодолетьлюбойжелающий,сдругойстороны,вкурсерассматриваютсявсеосновныетемы,которыепозволятдальшерастисамостоятельно.

КурснеставитсвоейцельюглубокоерассмотрениеязыкаPython.Задачакурса,объяснитьпонятнымязыкомосновыPythonидатьнеобходимыеинструментыдляегопрактическогоиспользования.

Введение

8

Page 9: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

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

ДлякогоэтоткурсДлясетевыхинженеровсопытомпрограммированияибез.

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

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

Ещёнерешилинуженликурс?Почитайтеотзывы.

ThisworkislicensedunderaCreativeCommonsAttribution-ShareAlike4.0InternationalLicense.

Введение

9

Page 10: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Окурсе

Краткоесодержаниекурса1.Подготовкакработе2.НачалоработысPython3.ТипыданныхвPython4.Созданиебазовыхскриптов5.Контрольходапрограммы6.Работасфайлами7.Функции8.Модули9.Регулярныевыражения10.Сериализацияданных11.Работасбазамиданных12.Подключениекоборудованию13.ШаблоныконфигурацийсJinja14.TextFSM.Обработкавыводакоманд15.AnsibleДополнительнаяинформацияПолезныессылки

ЕсливыскачалиPDFииспугались,чтовкурсепочти600страниц,непереживайте.Половинукурсазанимаютразделы12-15.Внихмноговыводов,которыепоказываютрезультатывыполненияскриптов,поэтомуобъемполучилсябольшой.

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

ОС,Python

Вкурсеиспользуются:

DebianLinuxPython2.7

ПозжекурсбудетпереведеннаPython3.x.

Окурсе

10

Page 11: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Длякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Примеры

Всепримеры,которыеиспользуютсявкурсе,можноскачатьоднимархивомвzipилиtar.gz.

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

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

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

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

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

Задания

Всезаданияивспомогательныефайлыможноскачатьоднимархивомвzipилиtar.gz.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Однако,еслиполучается,лучшеделатьзаданияпопорядку.

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

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

Окурсе

11

Page 12: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Наstackoverflowестьответыпрактическиналюбыевопросы.Такчто,еслигуглотправилвастуда,значит,сбольшойвероятностью,ответнайден.Запросы,конечноже,лучшеписатьнаанглийском.ПоPythonоченьмногоматериалови,какправило,подсказкунайтилегко.

Ответымоглибыпоказать,какещёможновыполнитьзаданиеиликакболееправильно/корочевыполнитьего.Но,наэтотсчет,тоженепереживайте,таккак,скореевсего,вследующихразделахвстретитсяпример,вкоторомбудетпоказано,какписатьтакойкод.

Презентации

Длячаститемкурсаестьпрезентации.Понимудобнобыстропросматриватьинформациюиповторять.Ониособеннополезныдлябазовыхтем.

Скачатьвсепрезентацииоднимархивом.

Современем,будутдобавленыпрезентациидлявсехразделов.

ОбновлениекурсаКурсбылполностьюзавершен07.02.2017.

Но,вразделдополнительнаяинформацияещёбудутдобавленынесколькоподразделов.Также,скореевсего,будутдобавленыновыезадания.

Поэтому,есливынебудетечитатькурсвближайшеевремя,толучшесохранитессылкунаонлайнверсиюкурса,анеPDF/mobi/epub.А,когдарешитечитать,скачаете,еслинужно,свежуюверсию.

Дополнениябудутделатьсявближайшие2-6месяцевинебудутвлиятьнаизначальнуюструктурукурса.

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

Окурсе

12

Page 13: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ФорматыкурсаКурсможночитатьвнесколькихформатах:

онлайнPDF/ePub/Mobi

Ониавтоматическиобновляются,поэтомувсегдасодержатодинаковуюинформацию.

Пожалуйста,невыкладывайтескачанныеверсиикурса.Вместоэтого,простодавайтессылкунакурс.

КомментарииGitBookпозволяетоставлятькомментарииусоответствующейчастикурса.ДляэтогонужнозарегистрироватьсянаGitBookизайтиподсвоимакаунтом.

Вонлайнверсиикурса,еслинавестикурсорнакакой-тоабзацтекста,справапоявитсяплюс:

Еслинажатьнанего,откроетсяокнодлянаборасообщения:

Окурсе

13

Page 14: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Еслижекомментарийбылонепонятноммоментевкурсе,комментарийостанется,вместесмоимипояснениями.

Комментарии,соответственно,доступнывонлайнверсиикурса,рядомстекстом:

Атакже,наглавнойстраницекурса:

Окурсе

14

Page 15: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Окурсе

15

Page 16: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Какучитьсяпоэтомукурсу

1вариант:

Этотвариантподходитвтакихслучаях:

Есливынеуверены,чтохотитепроходитьвеськурсЕсливамнужнопростоавтоматизироватьподключениекустройствамивыполнениекомандЕсливынеуверены,чтохотитеизучатьPython

Вэтомслучае,начнитесAnsible.

ДляегоустановкиибазовогоиспользованиянетребуетсязнатьPython.ДостаточноустановитьAnsible,взятьпримериспользованияипопробоватьвыполнитькомандыshowнаоборудовании.

Послеэтого,можноиспользоватьAnsibleдляотправкикоманд,которыеневлияютнапередачутрафика:

подписьинтерфейсовнастройкаобщихпараметров,такихкак,например,aliasгенерацияконфигурациипошаблону,дляпервичнойнастройкиоборудования

Есликакие-тозадачинеполучаетсярешитьсAnsible,иливыпростозахотитеизучитьPython,переходитекварианту2.

2вариант:ЕсливыужерешилиизучатьPython

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

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

Обязательнопрактикуйтесь:

пробуйтевоспроизвестивсепримерывглавах(набирайтепримерывручнуюилипробуйтеповторятьпопамяти)пробуйтеменятькакие-топараметрывпримерах,чтобыпосмотреть"аможнолитаксделать"обязательновыполняйтевсезаданияпослеглав

Какучитьсяпоэтомукурсу

16

Page 17: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

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

Еслиследоватьрасписанию,пустьиснебольшимиизмениями,токконцукурсанаберетсядвамесяцапрактики.Заэтовремявсебазовыепонятияхорошоусвоятсяи,главное,послезавершениякурса,небросатьпрактиковатьсяиучиться.

Походукурса,скореевсего,будутвозникатьидеи,чтосделатьпоработе.Этоотлично!Делайтеобязательно.Записывайтеидеи,чтобынезабыть,еслинеможетесразусделатьэто.

Примерыиспользования,которыепридумываетевы,будутособенносильнопомогатьрасти.Таккакониестественнымобразомбудутразвиваться:будетдобавлятьсяфункционал,будутулучшения,которыенужныименновам.

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

Послекурса

Ксожалению,новыезнанияоченьбыстрозабываютсябезпримененияибезповторения.

Неделайтеслишкомбольшойперерывпослекурса.Еслиоставитьновыезнаниябезпримененияна2-4недели,тобольшаячастьизнихсущественновыветрится.

Есливамудалосьнапридумыватьсебезадач,походукурса-отлично.Реализуйтеих.Напишитесписокиделайтезадачипостепенно.Этоотличныйспособизучатьдальшеиповторятьпройденное.

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

Создайтерепозиторийнаgithubивыкладывайтетудасвоискрипты.Дорабатывайтеих,поделитесьсколлегами.

Отличныйспособзапомнитьлучшекакую-тотему-рассказатьдругому.

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

Какучитьсяпоэтомукурсу

17

Page 18: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

дальше.

Иобязательнопрактикуйтесь.Толькочитатькнигу/статьюилисмотретьвидео,недостаточно.Обязательнопишитечто-то.

Какучитьсяпоэтомукурсу

18

Page 19: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПримерпланаобученияТутнаходитсяпримерплана,покоторомуможноучитьсяпоэтомукурсу.

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

Например,можночитатьтемыввыходные,анарабочейнеделевыполнятьзаданияпоэтойтеме.

Неделя Темы Задания

0 Подготовкакработе Подготовкакработе

1НачалоработысPythonТипыданныхвPythonСозданиебазовыхскриптов

ТипыданныхБазовыескрипты

2 КонтрольходапрограммыРаботасфайлами

КонтрольходапрограммыФайлы

3 Функции Функции

4 МодулиРегулярныевыражения

МодулиРегулярныевыражения

5 Сериализацияданных Сериализацияданных

6 Работасбазамиданных Базыданных

7 Подключениекоборудованию Подключениекоборудованию

8 ШаблоныконфигурацийсJinja Jinja2

9 ОбработканеструктурированноговыводакомандсTextFSM TextFSM

10 Ansible Ansible

Примерпланаобучения

19

Page 20: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Чемэтоотличаетсяотобычноговводногокурсапопитону?

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

Ясетевик.Длячегомненуженэтоткурс?

Впервуюочередь,дляавтоматизициирутинныхзадач.

Автоматизациядаетнесколькопреимуществ:

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

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

каждоеизменениекакправило,сопряженосриском,таккаксетьэтоосноваработывсехприложенийиценаошибки,какправило,высока

выполучаетеконсистентнуюконфигурацию,отнастроенныхпользователейиподписейинтерфейсов,дофункционалабезопасности

выможетенепереживатьотом,незабылиливычто-то

Конечно,небудеттакого,чтопослекурсавы"всёавтоматизируетеинаступитсчастье".Ноэтошагвэтусторону.

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

Но,еслиегонет,илиесливыпростоещёотакомнедумали,попробуйтеначатьспростого.Ansible,например,дастсразудовольномного.

Зачемтогдаучитьpython?Проблемавтом,чтототжеAnsibleнерешитвсевопросы.И,возможно,вампонадобитсядобавитькакой-тофункционалсамостоятельно.

И,кроменепосредственнойнастройкиоборудования,естьежедневныерутинныезадачи,которыеможноавтоматизироватьспомощьюPython.

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

FAQ

20

Page 21: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Еслижевыпотомвойдетевовкусизахотитедобавитьчто-тосвое,чегонетвAnsible,возвращайтесь:)

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

Pythonпоможетвамрешатьиподобныезадачи.

Почему"длясетевыхинженеров"?

Естьнесколькопричин:

сетевыеинженерыужеобладаютопытомработывИТичастьконцепцийимзнакома.

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

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

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

ПочемуPython?

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

Pythonдостаточнопростдляизучения.Конечно,этовсёотносительноикому-тоболеепростымможетбытьдругойязык,носкорееэтобудетиз-заопытаработысязыком,анепотому,чтоPythonсложный

СPythonвыврядлибыстродойдетедограницвозможностейязыка.Pythonможетиспользоватьсянетолькодляскриптинга,ноидляразработкиприложений.Конечно,дляэтогокурсаэтоневажно,но,покрайнеймере,выпотратитевремянаязык,которыйпозволитвамлегкошагнутьдальше,чемпростыескрипты

FAQ

21

Page 22: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

изсетевойсферы,например,наPythonнаписанGNS3

Иещеодинмомент,вконтекстекурса,Pythonнужнорассматриватьнекакединственноправильныйвариант,некак"правильный"язык.Нет,этопростоинструмент.

Инструменткакотвертка,например.Мыучимсяимпользоваться,дляконкретныхзадач.

Тоесть,никакойидеологическойподоплекитутнет.Никакого"толькоPython"тоже.Никакого"поклонения"темболее.

Страннопоклонятьсяотвертке:)

Тутвсёпросто.Естьхорошийудобныйинструмент,которыйподойдеткразнымзадачам.Оннелучшийвовсемидалеконеединственныйязыквпринципе.

Начнитеснего.Потомвысможетесамостоятельновыбратьчто-тодругое,еслизахотите.Этизнаниявсёравнонепропадут.

Почемуpython2,анеpython3.x?

Опятьпроотвертку:)

Естьотверткаобычная(python2)иновая(python3),классная,сулучшеннымдизайном,болеебезопасная,красиваяитакдалее.

Длянашихзадачподойдетиобычная:)

Есливыпишетеприложение,анепростопарускриптов,токонечнолучшеписатьнаpython3.x.

Грубоговоря,намраноотакомдумать.

Аеслисеръезно,то,ксожалению,наданныймоментневсепроектыподдерживаютpython3.Поэтому,покачто,вкурсебудетиспользоватьсяpython2.

Вдальнейшем,скореевсего,курсбудетпеределаннаpython3.x.

Янезнаюнужнолимнеэто.

Яконечножесчитаю,чтонужно:)Иначе,ябынеписалаэтоткурс.

Нода,совсемнефакт,чтовамзахочетсяпогружатьсявэтовсё.Поэтому,дляначала,попробуйтеразобратьсясAnsible.Возможно,вамхватитегодостаточнонадолго.

FAQ

22

Page 23: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Начнитеспростыхкомандshow.Попробуйтеподключитьсясначалактестовомуоборудованию(виртуалкам).

Затемпопробуйтевыполнитькомандуshowнареальнойсети,на2-3устройствах.Потомнабольшемколичестве.

Есливамэтогодостаточно,можноостановитьсятут.

СледующимшагомябыпопробовалаиспользоватьAnsibleдлягенерациишаблоновконфигурации.

Зачемсетевомуинженерупрограммирование?

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

рутиннымизадачамиспроблемамиирешениями,которыенадопротестироватьсбольшимобъемомоднотипныхзадачсбольшимколичествомповторяющихсязадачсбольшимколичествомоборудования

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

Ивитогемывручнуюсноваисноваделаемодноитоже.

Дажетакиебанальныевещикак:отправитьоднуитужекомандуshowна20устройств,уженевсегдапростосделать.Да,допустимвашSSHклиентподдерживаетэтувозможность.Аесливамтеперьнадопроанализироватьвывод?

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

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

Сейчасявнонаблюдаетсятенденция"Всеучимсяпрограммировать".Иэтохорошо,вцелом.Нопрограммированиеэтонечто-тоэлементарное.Этосложно,вэтонужновкладыватьмноговремени,особенно,есливыникогданеимелиотношениякинженерному/техническомумиру.

FAQ

23

Page 24: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Атоиногдаскладываетсявпечатление,чтодостаточнопройти"вотэтивоткурсы"ичерез3месяцавыкрутойпрограммистсвысокойзарплатой.Нет,этоткурснеобэтом:)

Мынеговоримвэтомкурсеопрограммированиикакпрофессииинеставимтакуюцель.Мыговоримопрограммированиикакинструменте,такомкак:знаниеCLIunix,например.

Иделоневтом,чтоинженерыкакие-тоособенные.Апросто,какправило:

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

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

Курсбудеткогда-топлатным?

Нет,курс,которыйопубликовантут,всегдабудетбесплатным.

Ячитаюплатноонлайнкурс"Pythonдлясетевыхинженеров".Ноэтонебудетвлиятьнаэтоткурс.Онвсегдабудетбесплатным.

FAQ

24

Page 25: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

БлагодарностиСпасибовсем,ктопроявилинтерескпервомуанонсукурса.Вашинтересподтвердил,чтоэтобудеткому-тонужно.

ПавелПасынок,спасиботебезато,чтосогласилсянакурс.Свамибылоинтересноработатьиэтодобавиломнемотивациизавершитькурс.Ияособеннорада,чтознания,которыевыполучилинакурсе,нашлипрактическоеприменение.

АлексейКириллов,самоебольшоеспасиботебе:)Явсегдамоглаобсудитьстобойлюбойвопроспокурсу.Тыпомогалмнеподдерживатьмотивациюинеуходитьвдебри.Общениестобойвдохновляломеняпродолжать,особенновсложныемоменты.Спасиботебезавдохновение,положительныеэмоциииподдержку!

Благодарности

25

Page 26: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

ЕсливыиспользуетеLinux/Unix/MacOS,то,скореевсего,Pythonужеустановлен.Инужнотолькопроверить,чтоустановленаверсия2.7(котораяиспользуетсявкурсе).

ЕсливыиспользуетеWindows,то,скореевсего,Pythonнужнобудетустановить.ОдинизсамыхпростыхвариантовдляWindows,установитьокружениеAnaconda.ВокружениитакжеестьIDESpyder,которыйможноиспользоватьвместоредактора.

ДляустановкиAnsibleпонадобитсяLinux.

Ещёодинважныймомент-выборредактора.ВследующемразделеприведеныпримерыредакторовдляразныхОС.

ВместоредактораможноиспользоватьIDE(Integrateddevelopmentenvironment).

IDEэтохорошаявещь,но,нестоитпереходитьнаIDEиз-затакихвещейкак:

подсветкакодаподсказкисинтаксисаавтоматическиеотступы(важнодляPython)

Всёэтоестьвлюбомхорошемредакторе.Какправило,дляэтогоможетпотребоватьсяустановитьдополнительныемодули.

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

СписокIDEдляPythonможноможнопосмотретьтут.Например,можновыбратьPyCharmили(дляWindows)Spyder.

ИдеальнымвариантомдлякурсабудетиспользованиевиртуалкиподуправлениемLinux/Unix.Этонеобязательно,номногиевещибудутнамногоудобней.Плюс,ненадобудетпереживатьзасвоюОС,зато,чтобынесделатьчего-толишнего.

1.Подготовкакработе

26

Page 27: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ОСиредакторДлятого,чтобыначатьработатьсPython,надоопределитьсяснесколькимивещами:

КакаяоперационнаясистемабудетиспользоватьсяКакойредакторбудетиспользоватьсяКакаяверсияPythonбудетиспользоваться

МожновыбратьлюбуюОСилюбойредактор.Но,желательноиспользоватьPythonверсии2.7,таккаквэтомкурсебудетиспользоватьсяэтаверсия.

ДлякурсажелательноиспользоватьнеWindows,таккак,например,AnsibleможноустановитьтольконаLinux/Unix.

Таккакпочтидлявсехразделов,подойдетлюбаяОС,можноотложитьвопросдоразделапоAnsible.

Вкурсеиспользуются:

DebianLinuxvim(редакторнеимеетпринципиальногозначения,лучшевыбратьнаиболееудобный)Python2.7

УстановкаPython2.7,еслиегонетвОС,выполняетсясамостоятельно.

ПопулярныередакторыдляразныхОС(vimиemacsнеуказаны):

Linux:gEditnanoSublimeTextgeany

MacOSTextMateTextWrangler

Windows:Notepad++

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

Далеевыводыкоманд,интерпретатора,скриптов,выполняютсянаDebianLinux.ВдругихОСвыводможетнезначительноотличаться.

ОСиредактор

27

Page 28: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ОСиредактор

28

Page 29: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

СистемауправленияпакетамиpipДляустановкипакетовPython,которыепонадобятсявкурсе,будетиспользоватьсяpip.

pip-этосистемауправленияпакетами,котораяиспользуетсядляустановкипакетовизPythonPackageIndex(PyPi).

Скореевсего,еслиувасужеустановленPython,тоустановлениpip.

Проверкаpip:

$pip--version

pip1.1from/usr/lib/python2.7/dist-packages(python2.7)

Есликомандавыдалаошибку,значитpipнеустановлен.Установитьегоможнотак:

apt-getinstallpython-pip

Системауправленияпакетамиpip

29

Page 30: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

virtualenv,virtualenvwrappervirtualenv-этоинструмент,которыйпозволяетсоздаватьвиртуальныеокружения.

Виртуальныеокружения:

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

Например,есливпроекте1требуетсяпакетверсии1.0,авпроекте2требуетсятотжепакет,новерсии3.1

пакеты,которыеустановленыввиртуальныхокружениях,неперебиваютглобальныепакеты

Вкурсеиспользуетсяvirtualenvwrapper:онпозволяетнемногопрощеработатьсvirtualenv.

Установкаvirtualenvwrapperспомощьюpip:

pipinstallvirtualenvwrapper

Послеустановки,в.bashrcнужнодобавитьнесколькострок

exportWORKON_HOME=~/venv

./usr/local/bin/virtualenvwrapper.sh

WORKON_HOME-указываетрасположениевиртуальныхокружений.Автораястрока-гденаходитсяскрипт,установленныйспакетомvirtualenvwrapper):

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

execbash

Такойвариантможетбытьневсегдаправильным.Подробнеевответенаstackoverflow.

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

Созданиеновоговиртуальногоокружения:

virtualenv,virtualenvwrapper

30

Page 31: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$mkvirtualenvPyNEng

NewpythonexecutableinPyNEng/bin/python

Installingdistribute........................done.

Installingpip...............done.

(PyNEng)$

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

ВvirtualenvwrapperпоTabработаетавтопродолжениеименивиртуальногоокружения.

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

Теперьвтомкаталоге,которыйбылуказанвWORKON_HOME,созданкаталогPyNEng:

(PyNEng)$ls-lsvenv

total52

....

4-rwxr-xr-x1natanata99Sep3016:41preactivate

4-rw-r--r--1natanata76Sep3016:41predeactivate

4-rwxr-xr-x1natanata91Sep3016:41premkproject

4-rwxr-xr-x1natanata130Sep3016:41premkvirtualenv

4-rwxr-xr-x1natanata111Sep3016:41prermvirtualenv

4drwxr-xr-x6natanata4096Sep3016:42PyNEng

Выйтиизвиртуальногоокружения:

(PyNEng)$deactivate

$

Дляпереходавсозданноевиртуальноеокружение,надовыполнитькомандуworkon:

$workonPyNEng

(PyNEng)$

Еслинеобходимоперейтиизодноговиртуальногоокружениявдругое,тонеобязательноделатьdeactivate,можноперейтисразучерезworkon:

$workonTest

(Test)$workonPyNEng

(PyNEng)$

virtualenv,virtualenvwrapper

31

Page 32: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Есливиртуальноеокружениенужноудалить,используетсякомандаrmvirtualenv:

$rmvirtualenvTest

RemovingTest...

$

Посмотретькакиепакетыустановленыввиртуальномокружении:

(PyNEng)$lssitepackages

ANSI.pypexpect-3.3-py2.7.egg-info

ANSI.pycpickleshare-0.5-py2.7.egg-info

decorator-4.0.4-py2.7.egg-infopickleshare.py

decorator.pypickleshare.pyc

decorator.pycpip-1.1-py2.7.egg

distribute-0.6.24-py2.7.eggpxssh.py

easy-install.pthpxssh.pyc

fdpexpect.pyrequests

fdpexpect.pycrequests-2.7.0-py2.7.egg-info

FSM.pyscreen.py

FSM.pycscreen.pyc

IPythonsetuptools.pth

ipython-4.0.0-py2.7.egg-infosimplegeneric-0.8.1-py2.7.egg-info

ipython_genutilssimplegeneric.py

ipython_genutils-0.1.0-py2.7.egg-infosimplegeneric.pyc

path.pytest_path.py

path.py-8.1.1-py2.7.egg-infotest_path.pyc

path.pyctraitlets

pexpecttraitlets-4.0.0-py2.7.egg-info

Зависимости(requirements)

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

ВPythonестьвозможность(ипринято)записатьвсезависимостивотдельныйфайл.

Этоделаетсятакимобразом:

(PyNEng)$pipfreeze>requirements.txt

Теперьвфайлеrequirements.txtнаходятсявсезависимости,сверсиямипакетов(файлrequirements.txt):

virtualenv,virtualenvwrapper

32

Page 33: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Jinja2==2.8

pexpect==4.0.1

tornado==4.3

...

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

$pipinstall-rrequirements.txt

Тутвприглашениинетименивиртуальногоокружения,таккакустанавливатьтакимобразомзависимостиможнонетольковвиртуальномокружении,ноивсистемевцелом.

Установкапакетов

Например,установимввиртуальномокружениипакетsimplejson.

(PyNEng)$pipinstallsimplejson

...

Successfullyinstalledsimplejson

Cleaningup...

Еслиперейтивipython(рассматриваетсявразделеipython)иимпортироватьsimplejson,тоондоступениникакихошибокнет:

(PyNEng)$ipython

In[1]:importsimplejson

In[2]:simplejson

simplejson

In[2]:simplejson.

simplejson.Decimalsimplejson.decoder

simplejson.JSONDecodeErrorsimplejson.dump

simplejson.JSONDecodersimplejson.dumps

simplejson.JSONEncodersimplejson.encoder

simplejson.JSONEncoderForHTMLsimplejson.load

simplejson.OrderedDictsimplejson.loads

simplejson.absolute_importsimplejson.scanner

simplejson.compatsimplejson.simple_first

virtualenv,virtualenvwrapper

33

Page 34: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

(PyNEng)$deactivate

$ipython

In[1]:importsimplejson

------------------------------------------------------------------

ImportErrorTraceback(mostrecentcalllast)

<ipython-input-1-ac998a77e3e2>in<module>()

---->1importsimplejson

ImportError:Nomodulenamedsimplejson

virtualenv,virtualenvwrapper

34

Page 35: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ИнтерпретаторPython(проверка)Передначаломработы,надопроверить,чтопривызовеинтерпретатораPython,выводбудеттаким:

$python

Python2.7.3(default,Mar132014,11:03:55)

[GCC4.7.2]onlinux2

Type"help","copyright","credits"or"license"formoreinformation.

>>>

Выводпоказывает,чтоустановленPython2.7.Приглашение>>>этостандартноеприглашениеинтерпретатораPython.

Вызовинтерпретаторавыполняетсяпокомандеpython,чтобывыйтинужнонабратьquit()либонажатьCtrl+D

ИнтерпретаторPython(проверка)

35

Page 36: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание1.1

Единственноезаданиевэтомразделе:подготовкакработе.

Дляэтогонужно:

определитьсясОС,которуювыбудетеиспользоватьтаккаквсепримерывкурсеориентированынаLinux(Debian),желательноиспользоватьегожелательноиспользоватьновуювиртуальнуюмашину,чтобыбылоспокойнейэкспериментировать

установитьPython2.7проверить,чтоPythonиpipустановлены

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

Задания

36

Page 37: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

НачалоработысPythonВэтомразделерассматриваются:

синтаксисPythonработавинтерактивномрежимепеременныевPython

2.НачалоработысPython

37

Page 38: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

СинтаксисPythonПервое,что,какправило,бросаетсявглаза,еслиговоритьосинтаксисеPython,этото,чтоотступыимеютзначение:

ониопределяюткакиевыраженияпопадаютвблоккодакогдаблоккодазаканчивается

ПримеркодаPython:

a=10

b=5

ifa>b:

print"AбольшеB"

print"Тутможновыполнитьещёчто-то"

else:

print"BбольшеилиравноA"

print"Продолжаемтутже"

print"TheEnd"

Обратитевнимание,чтотуткодпоказандлядемонстрациисинтаксиса.ВследующихразделахрассматриваютсятипыданныхPythonисозданиескриптов.

Несмотрянато,чтоещенерассматриваласьконструкцияif/else,всёдолжнобытьпонятно.

Pythonпонимаеткакиестрокиотносятсякifнаосновеотступов.Выполнениечастиifa>bзаканчивается,когдавстречаетсястрокастемжеотступом,чтоисамастрокаifa>b.

Аналогичносблокомelse.

ВтораяособенностьPython:посленекоторыхвыраженийдолжноидтидвоеточие(например,послеifa>bилипослеelse).

Несколькоправилирекомендаций:

ВкачествеотступовмогутиспользоватьсяTabилипробелы.лучшеиспользоватьпробелы

аточнее,настроитьредактортак,чтобыTabбылравен4пробелам(тогда,прииспользованииTab,будутставиться4пробела)

Количествопробеловдолжнобытьодинаковымводномблоке.лучшечтобыколичествопробеловбылоодинаковымвовсемкоде

СинтаксисPython

38

Page 39: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

популярныйвариантиспользовать2-4пробела(вкурсеиспользуются4пробела)

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

Ещеоднаособенностьприведенногопримеракода:пустыестроки.Такимобразомкодформатируется,чтобыегобылопрощечитать.

ОстальныеособенностисинтаксисабудутпоказанывпроцессезнакомствасструктурамиданныхвPython.

Комментарии

Принаписаниикода,частонужнонаписатькомментарий.Например,чтобыописатьособенностиработыкода.

КомментариивPythonмогутбытьоднострочными:

#Оченьважныйкомментарий

a=10

b=5#Оченьнужныйкомментарий

Однострочныекомментарииначинаютсясознака#.

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

Принеобходимостинаписатьнесколькострокскомментариями,чтобынеставитьпередкаждойрешетку,можносделатьмногострочныйкомментарий:

"""Оченьважный

идлинныйкомментарий

"""

a=10

b=5

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

СинтаксисPython

39

Page 40: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ИнтерпретаторPython.iPythonИнтерпретаторпозволяетполучатьмоментальныйоткликнавыполненныедействия.

Можносказать,чтоинтерпретаторработаеткаккоманднаястрокасетевыхустройств:каждаякомандабудетвыполнятьсясразупосленажатияenter(покрайнеймере,похоженаcisco).

НодляинтерпретатораPythonестьисключение:болеесложныеобъекты(например,циклы,функции)выполняются,толькопосленажатияenterдвараза..

Впредыдущемразделе,дляпроверкиустановкиPython,вызвалсястандартныйинтерпретатор.

Но,кроменего,вPythonестьусовершенствованныйинтерпретаторiPython(документацияiPython).

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

Несколькопримеров(возможностиipythonнамногошире):

автопродолжениекомандпоTabилиподсказка,есливариантовкоманднесколькоболееструктурированныйипонятныйвыводкомандавтоматическиеотступывциклахидругихобъектахисториявыполнениякоманд

понейможнопередвигатьсяилипосмотреть"волшебной"командой%history

УстановитьiPythonможноспомощьюpip(есливиртуальнаямашинаустанавливаетсяснуля):

apt-getinstallpython-pippython-dev

pipinstall—upgradepip

pipinstallipython

Еслисустановкойipythonвозникаютпроблемы,послекоторыхнеработаетpip,выполнитетакиедействия:

Еслиставиличерезaptpip,тонадоегоудалить:

apt-getremovepython-pip

ИнтерпретаторPython.iPython

40

Page 41: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Послеэтогозановопереустановитьpipиустановитьipythonтакимобразом:

wgethttps://bootstrap.pypa.io/get-pip.py

pythonget-pip.py

apt-getinstallpython-dev

pipinstallipython

ДалеекакинтерпретаторбудетиспользоватьсяiPython.

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

In[1]:1+2

Out[1]:3

In[2]:22*45

Out[2]:990

In[3]:2**3

Out[3]:8

ВiPythonвводивыводподписаны:

In-этото,чтонаписалпользовательOut-этовыводкоманды(еслионесть)ЧислапослеInиOutэтонумерациявыполненныхкомандвтекущейсессииiPython

Примервыводастроки:

In[4]:print'Hello!'

Hello!

Когдавинтерпретаторесоздается,например,цикл,товнутрициклаприглашениеменяетсяна....Длявыполненияциклаивыходаизэтогоподрежима,необходимодваждынажатьEnter:

In[5]:foriinrange(5):

...:printi

...:

0

1

2

3

4

ИнтерпретаторPython.iPython

41

Page 42: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

print

Операторprintпозволяетвывестиинформациюнастандартныйпотоквывода.

Еслинеобходимовывестистроку,тоеенужнообязательнозаключитьвкавычки(двойныеилиодинарные).Еслиженужновывести,например,результатвычисленияилипросточисло,токавычкиненужны:

In[6]:print'Hello!'

Hello!

In[7]:print5*5

25

Еслинужновывестинесколькозначений,можноперечислитьихчереззапятую:

In[8]:print1*5,2*5,3*5,4*5

5101520

In[9]:print'one','two','three'

onetwothree

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

Допустим,естьфайлfile4.py(обратитевниманиеназапятуюпослепервойстроки):

print'Hello!',

print'Hello!'

Тогдапривыполнениискрипта,выводбудетвыглядетьтак(послепервогоHelloнетпереводастроки,ноестьпробел):

Hello!Hello!

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

dir

Командаdir()можетиспользоватьсядлятого,чтобыпосмотретькакиеатрибутыиметодыестьуобъекта.

ИнтерпретаторPython.iPython

42

Page 43: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Например,длячиславыводбудеттаким(обратитевниманиенаразличныеметоды,которыепозволяютделатьарифметическиеоперации):

In[10]:dir(5)

Out[10]:

['__abs__',

'__add__',

'__and__',

...

'bit_length',

'conjugate',

'denominator',

'imag',

'numerator',

'real']

Длястроки:

In[11]:dir('hello')

Out[11]:

['__add__',

'__class__',

'__contains__',

...

'startswith',

'strip',

'swapcase',

'title',

'translate',

'upper',

'zfill']

Есливыполнитькомандубезпередачизначения,тоонапоказываетсуществующиеметоды,атрибутыипеременные,определенныевтекущейсессииинтерпретатора:

ИнтерпретаторPython.iPython

43

Page 44: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[12]:dir()

Out[12]:

['__builtin__',

'__builtins__',

'__doc__',

'__name__',

'_dh',

...

'_oh',

'_sh',

'exit',

'get_ipython',

'i',

'quit']

Примерпослесозданияпеременнойaифункцииtest:

In[13]:a='hello'

In[14]:deftest():

....:print'test'

....:

In[15]:dir()

Out[15]:

...

'a',

'exit',

'get_ipython',

'i',

'quit',

'test']

ИнтерпретаторPython.iPython

44

Page 45: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

MagiccommandsВIPythonестьспециальныекоманды,которыеупрощаютработусинтерпретатором.Всеониначинаютсяна%.

%history

Например,команда%historyпозволяетпросмотретьисториютекущейсессии:

In[1]:a=10

In[2]:b=5

In[3]:ifa>b:

...:print"Aisbigger"

...:

Aisbigger

In[4]:%history

a=10

b=5

ifa>b:

print"Aisbigger"

%history

Такимобразомможноскопироватькакой-тоблоккода.

%cpaste

Ещеоднаоченьполезнаяволшебнаякоманда%cpaste

ПривставкекодасотступамивIPython,из-заавтоматическихотступовсамогоipython,начинаетсдвигатьсякод:

МагияiPython

45

Page 46: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[1]:a=10

In[2]:b=5

In[3]:ifa>b:

...:print"Aisbigger"

...:else:

...:print"Aislessorequal"

...:

Aisbigger

In[4]:%hist

a=10

b=5

ifa>b:

print"Aisbigger"

else:

print"Aislessorequal"

%hist

In[5]:ifa>b:

...:print"Aisbigger"

...:else:

...:print"Aislessorequal"

...:

File"<ipython-input-8-4d18ff094f5c>",line3

else:

^

IndentationError:unindentdoesnotmatchanyouterindentationlevel

IfyouwanttopastecodeintoIPython,trythe%pasteand%cpastemagicfunctions.

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

Команды%pasteи%cpasteработаютнемногопо-разному.

%cpaste(послетогокаквсестрокископированы,надозавершитьработукомандынабрав'--'):

In[9]:%cpaste

Pastingcode;enter'--'aloneonthelinetostoporuseCtrl-D.

:ifa>b:

:print"Aisbigger"

:else:

:print"Aislessorequal"

:--

Aisbigger

%paste(требуетустановленногоTkinter):

МагияiPython

46

Page 47: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[10]:%paste

ifa>b:

print"Aisbigger"

else:

print"Aislessorequal"

##--Endpastedtext--

Aisbigger

ПодробнееобIPythonможнопочитатьвдокументацияIPython.

КороткоинформациюможнопосмотретьвсамомIPythonкомандой%quickref:

МагияiPython

47

Page 48: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

IPython--AnenhancedInteractivePython-QuickReferenceCard

===========================================================

obj?,obj??:Gethelp,ormorehelpforobject(alsoworksas

?obj,??obj).

?foo.*abc*:Listnamesin'foo'containing'abc'inthem.

%magic:InformationaboutIPython's'magic'%functions.

Magicfunctionsareprefixedby%or%%,andtypicallytaketheirarguments

withoutparentheses,quotesorevencommasforconvenience.Linemagicstakea

single%andcellmagicsareprefixedwithtwo%%.

Examplemagicfunctioncalls:

%aliasdls-F:'d'isnowanaliasfor'ls-F'

aliasdls-F:Worksif'alias'notapythonname

alist=%alias:Getlistofaliasesto'alist'

cd/usr/share:Obvious.cd-<tab>tochoosefromvisiteddirs.

%cd??:SeehelpANDsourceformagic%cd

%timeitx=10:timethe'x=10'statementwithhighprecision.

%%timeitx=2**100

x**100:time'x**100'withasetupof'x=2**100';setupcodeisnot

counted.Thisisanexampleofacellmagic.

Systemcommands:

!cpa.txtb/:Systemcommandescape,callsos.system()

cpa.txtb/:after%rehashx,mostsystemcommandsworkwithout!

cp${f}.txt$bar:Variableexpansioninmagicsandsystemcommands

files=!ls/usr:Capturesytemcommandoutput

files.s,files.l,files.n:"abc",['a','b','c'],'a\nb\nc'

History:

_i,_ii,_iii:Previous,nextprevious,nextnextpreviousinput

_i4,_ih[2:5]:Inputhistoryline4,lines2-4

exec_i81:Executeinputhistoryline#81again

%rep81:Editinputhistoryline#81

_,__,___:previous,nextprevious,nextnextpreviousoutput

_dh:Directoryhistory

_oh:Outputhistory

%hist:Commandhistoryofcurrentsession.

%hist-gfoo:Searchcommandhistoryof(almost)allsessionsfor'foo'.

%hist-g:Commandhistoryof(almost)allsessions.

%hist1/2-8:Commandhistorycontaininglines2-8ofsession1.

%hist1/~2/:Commandhistoryofsession1and2sessionsbeforecurrent.

МагияiPython

48

Page 49: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПеременныеПеременныевPython:

нетребуютобъявлениятипапеременной(Pythonязыксдинамическойтипизацией)являютсяссылкаминаобластьпамяти

Правилаименованияпеременных:

имяпеременнойможетсостоятьтолькоизбукв,цифризнакаподчеркиванияимянеможетначинатьсясцифрыимянеможетсодержатьспециальныхсимволов@,$,%

СоздаватьпеременныевPythonоченьпросто:

In[1]:a=3

In[2]:b='Hello'

In[3]:c,d=9,'Test'

In[4]:printa,b,c,d

3Hello9Test

Обратитевнимание,чтовPythonненужноуказывать,чтоaэточисло,аbэтострока.

Переменныеявляютсяссылкаминаобластьпамяти.Этолегкопродемонстрироватьспомощьюфункцииid(),котораяпоказываетидентификаторобъекта:

In[5]:a=b=c=33

In[6]:id(a)

Out[6]:31671480

In[7]:id(b)

Out[7]:31671480

In[8]:id(c)

Out[8]:31671480

Вэтомпримеревидно,чтовсетриимениссылаютсянаодинитотжеидентификатор.Тоесть,этоодинитотжеобъект,накоторыйуказываюттриссылкиa,bиc.

Счислами,уPythonестьещёоднаособенность,котораяможетнемногосбить.Числаот-5до256заранеесозданыихранятсявмассиве(списке).Поэтому,присозданиичислаизэтогодиапазона,фактическисоздаетсяссылканачисловсозданноммассиве.

Переменные

49

Page 50: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЭтаособенностьхарактернаименнодляреализацииCPython,котораярассматриваетсявкурсе.

Этоможнопроверитьтакимобразом:

In[9]:a=3

In[10]:b=3

In[11]:id(a)

Out[11]:4400936168

In[12]:id(b)

Out[12]:4400936168

In[13]:id(3)

Out[13]:4400936168

Обратитевнимание,чтоуa,bичисла3одинаковыеидентификаторы.Всеонипростоявляютсяссылкаминасуществующеечисловсписке.

Но,еслисделатьтожесамоесчисломбольше256:

In[14]:a=500

In[15]:b=500

In[16]:id(a)

Out[16]:140239990503056

In[17]:id(b)

Out[17]:140239990503032

In[18]:id(500)

Out[18]:140239990502960

Идентификаторыувсехразные.

Приэтом,еслисделатьприсваиваниетакоговида:

In[19]:a=b=c=500

Идентификаторыбудутувсеходинаковые:

Переменные

50

Page 51: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[20]:id(a)

Out[20]:140239990503080

In[21]:id(b)

Out[21]:140239990503080

In[22]:id(c)

Out[22]:140239990503080

Таккак,втакомвариантеa,bиcпростоссылаютсянаодинитотжеобъект.

Именапеременных

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

ВPythonестьрекомендациипоименованиюфункций,классовипеременных:

именапеременныхобычнопишутсяполностьюбольшимиилималенькимибуквами

DB_NAMEdb_name

именафункцийзадаютсямаленькимибуквами,сподчеркиваниямимеждусловами

get_namesименаклассовзадаютсясловамисзаглавнымибуквами,безпробелов

CiscoSwitch

Переменные

51

Page 52: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ТипыданныхвPythonВPythonестьнесколькостандартныхтиповданных:

Numbers(числа)Strings(строки)Lists(списки)Dictionary(словари)Tuples(кортежи)Sets(множества)Boolean

Этитипыданныхможно,всвоюочередь,классифицироватьпонесколькимпризнакам:

Изменяемые:СпискиСловариМножества

НеизменяемыеЧислаСтрокиКортежи

Упорядоченные:СпискиКортежиСтроки

Неупорядоченные:СловариМножества

3.ТипыданныхвPython

52

Page 53: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЧислаПримерразличныхтиповчисловыхзначений:

int(40,-80)float(1.5,-30.7)long(52934861L)

Счисламиможновыполнятьразличныематематическиеоперации.

In[1]:1+2

Out[1]:3

In[2]:1.0+2

Out[2]:3.0

In[3]:10-4

Out[3]:6

In[4]:2**3

Out[4]:8

Обратитевниманиенаотличияделенияintиfloat:

In[5]:10/3

Out[5]:3

In[6]:10/3.0

Out[6]:3.3333333333333335

In[7]:10/float(3)

Out[7]:3.3333333333333335

In[8]:float(10)/3

Out[8]:3.3333333333333335

Спомощьюфункцииroundможноокруглятьчисладонужногоколичествазнаков:

In[9]:round(10/3.0,2)

Out[9]:3.33

In[10]:round(10/3.0,4)

Out[10]:3.3333

Остатокотделения:

Числа

53

Page 54: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[11]:10%3

Out[11]:1

Операторысравнения

In[12]:10>3.0

Out[12]:True

In[13]:10<3

Out[13]:False

In[14]:10==3

Out[14]:False

In[15]:10==10

Out[15]:True

In[16]:10<=10

Out[16]:True

In[17]:10.0==10

Out[17]:True

Функцияint()позволяетвыполнятьконвертациювтипint.Вовторомаргументеможноуказыватьсистемуисчисления:

In[18]:a='11'

In[19]:int(a)

Out[19]:11

Еслиуказать,чтострокуaнадовосприниматькакдвоичноечисло,торезультатбудеттаким:

In[20]:int(a,2)

Out[20]:3

Конвертациявintтипаfloat:

In[21]:int(3.333)

Out[21]:3

In[22]:int(3.9)

Out[22]:3

Числа

54

Page 55: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Функцияbinпозволяетполучитьдвоичноепредставлениечисла(обратитевнимание,чторезультатстрока):

In[23]:bin(8)

Out[23]:'0b1000'

In[24]:bin(255)

Out[24]:'0b11111111'

Аналогично,функцияhex()позволяетполучитьшестнадцатеричноезначение:

In[25]:hex(10)

Out[25]:'0xa'

И,конечноже,можноделатьнесколькопреобразованийодновременно:

In[26]:int('ff',16)

Out[26]:255

In[27]:bin(int('ff',16))

Out[27]:'0b11111111'

Дляболеесложныхматематическихфункций,вPythonестьмодульmath:

In[28]:importmath

In[29]:math.sqrt(9)

Out[29]:3.0

In[30]:math.sqrt(10)

Out[30]:3.1622776601683795

In[31]:math.factorial(3)

Out[31]:6

In[32]:math.pi

Out[32]:3.141592653589793

Числа

55

Page 56: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Строки(Strings)СтрокавPython-этопоследовательностьсимволов,заключеннаявкавычки.

Строки-этонеизменяемый,упорядоченныйтипданных.

Примерыстрок:

In[9]:'Hello'

Out[9]:'Hello'

In[10]:"Hello"

Out[10]:'Hello'

In[11]:tunnel="""

....:interfaceTunnel0

....:ipaddress10.10.10.1255.255.255.0

....:ipmtu1416

....:ipospfhello-interval5

....:tunnelsourceFastEthernet1/0

....:tunnelprotectionipsecprofileDMVPN

....:"""

In[12]:tunnel

Out[12]:'\ninterfaceTunnel0\nipaddress10.10.10.1255.255.255.0\nipmtu1416\nip

ospfhello-interval5\ntunnelsourceFastEthernet1/0\ntunnelprotectionipsecprofi

leDMVPN\n'

In[13]:printtunnel

interfaceTunnel0

ipaddress10.10.10.1255.255.255.0

ipmtu1416

ipospfhello-interval5

tunnelsourceFastEthernet1/0

tunnelprotectionipsecprofileDMVPN

Строкиможносуммировать.Тогдаониобъединяютсяводнустроку:

In[14]:intf='interface'

In[15]:tun='Tunnel0'

In[16]:intf+tun

Out[16]:'interfaceTunnel0'

In[17]:intf+''+tun

Out[17]:'interfaceTunnel0'

Строки(Strings)

56

Page 57: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Строкуможноумножатьначисло.Вэтомслучае,строкаповторяетсяуказанноеколичествораз:

In[18]:intf*5

Out[18]:'interfaceinterfaceinterfaceinterfaceinterface'

In[19]:'#'*40

Out[19]:'########################################'

То,чтострокиявляютсяупорядоченнымтипомданныхпозволяетобращатьсяксимволамвстрокепономеру,начинаяснуля:

In[20]:string1='interfaceFastEthernet1/0'

In[21]:string1[0]

Out[21]:'i'

Нумерациявсехсимволоввстрокеидетснуля.Но,еслинужнообратитьсяккакому-топосчетусимволу,начинаясконца,томожноуказыватьотрицательныезначения(наэтотразсединицы).

In[22]:string1[1]

Out[22]:'n'

In[23]:string1[-1]

Out[23]:'0'

Кромеобращениякконкретномусимволу,можноделатьсрезыстроки,указавдиапазонномеров(срезвыполняетсяповтороечисло,невключаяего):

In[24]:string1[0:9]

Out[24]:'interface'

In[25]:string1[10:22]

Out[25]:'FastEthernet'

Еслинеуказываетсявтороечисло,тосрезбудетдоконцастроки:

In[26]:string1[10:]

Out[26]:'FastEthernet1/0'

Срезатьтрипоследнихсимволастроки:

Строки(Strings)

57

Page 58: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[27]:string1[-3:]

Out[27]:'1/0'

Строкавобратномпорядке:

In[28]:a='0123456789'

In[29]:a[::]

Out[29]:'0123456789'

In[30]:a[::-1]

Out[30]:'9876543210'

Записиa[::]иa[:]даютодинаковыйрезультат,нодвойноедвоеточиепозволяетуказывать,чтонадобратьнекаждыйэлемент,а,например,каждыйвторой.

Например,такимобразом,можнополучитьвсечетныечисластрокиa:

In[31]:a[::2]

Out[31]:'02468'

Такможнополучитьнечетные:

In[32]:a[1::2]

Out[32]:'13579'

Строки(Strings)

58

Page 59: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Полезныеметодыдляработысостроками

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

Знаниеразличныхметодов(тоесть,действий),которыеможноприменятькстрокам,помогаетболееэффективноработатьсними.

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

upper(),lower(),swapcase(),capitalize()

Методыupper(),lower(),swapcase(),capitalize()выполняютпреобразованиерегистрастроки:

In[25]:string1='FastEthernet'

In[26]:string1.upper()

Out[26]:'FASTETHERNET'

In[27]:string1.lower()

Out[27]:'fastethernet'

In[28]:string1.swapcase()

Out[28]:'fASTeTHERNET'

In[29]:string2='tunnel0'

In[30]:string2.capitalize()

Out[30]:'Tunnel0'

Оченьважнообращатьвниманиенато,чточастометодывозвращаютпреобразованнуюстроку.И,значит,надонезабытьприсвоитьеекакой-топеременной(можнотойже).

In[31]:string1=string1.upper()

In[32]:printstring1

FASTETHERNET

Такпроисходитиз-затого,чтострокаэтонеизменяемыйтипданных.

count()

Полезныеметодыдляработысостроками

59

Page 60: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Методcount()используетсядляподсчетатого,сколькоразсимволилиподстрока,встречаютсявстроке:

In[33]:string1='Hello,hello,hello,hello'

In[34]:string1.count('hello')

Out[34]:3

In[35]:string1.count('ello')

Out[35]:4

In[36]:string1.count('l')

Out[36]:8

find()

Методуfind()можнопередатьподстрокуилисимволионпокажетнакакойпозициинаходитсяпервыйсимволподстроки(дляпервогосовпадения):

In[37]:string1='interfaceFastEthernet0/1'

In[38]:string1.find('Fast')

Out[38]:10

In[39]:string1[string1.find('Fast')::]

Out[39]:'FastEthernet0/1'

startswith(),endswith()

Проверканатоначинается(илизаканчивается)листроканаопределенныесимволы(методыstartswith(),endswith()):

In[40]:string1='FastEthernet0/1'

In[41]:string1.startswith('Fast')

Out[41]:True

In[42]:string1.startswith('fast')

Out[42]:False

In[43]:string1.endswith('0/1')

Out[43]:True

In[44]:string1.endswith('0/2')

Out[44]:False

Полезныеметодыдляработысостроками

60

Page 61: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

replace()

Заменапоследовательностисимволоввстроке,надругуюпоследовательность(методreplace()):

In[45]:string1='FastEthernet0/1'

In[46]:string1.replace('Fast','Gigabit')

Out[46]:'GigabitEthernet0/1'

strip()

Частоприобработкефайла,файлоткрываетсяпострочно.Новконцекаждойстроки,какправило,естькакие-тоспецсимволы(амогутбытьивначале).Например,переводстроки.

Длятого,чтобыизбавитьсяотних,оченьудобноиспользоватьметодstrip():

In[47]:string1='\n\tinterfaceFastEthernet0/1\n'

In[48]:printstring1

interfaceFastEthernet0/1

In[49]:string1

Out[49]:'\n\tinterfaceFastEthernet0/1\n'

In[50]:string1.strip()

Out[50]:'interfaceFastEthernet0/1'

Методstrip()убираетспецсимволыивначалеивконцестроки.Еслинеобходимоубратьсимволытолькослеваилитолькосправа,можноиспользовать,соответственно,методыlstrip()иrstrip().

split()

Методsplit()разбиваетстрокуначасти,используякакразделителькакой-тосимвол(илисимволы).Поумолчанию,вкачестверазделителяиспользуетсяпробел.Новскобкахможноуказатьлюбойразделитель.

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

Полезныеметодыдляработысостроками

61

Page 62: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[51]:string1='switchporttrunkallowedvlan10,20,30,100-200'

In[52]:string1.split()

Out[52]:['switchport','trunk','allowed','vlan','10,20,30,100-200']

Ещеодинпример:

In[53]:string1='switchporttrunkallowedvlan10,20,30,100-200\n'

In[54]:commands=string1.strip().split()

In[55]:printcommands

['switchport','trunk','allowed','vlan','10,20,30,100-200']

In[56]:vlans=commands[-1].split(',')

In[57]:printvlans

['10','20','30','100-200']

Встрокеstring1былсимволпробелавначалеисимволпереводастрокивконце.Встрокеномер54,спомощьюметодаstrip(),этисимволыудаляются.

Методstrip()возвращаетстроку,котораяобрабатываетсяметодомsplit()иразделяетстрокуначасти,используяпробел,какразделитель.Итоговаястрокаприсваиваетсяпеременнойcommands.

Используятотжеспособ,чтоисостроками,кпоследнемуобъектувспискеvlans,применяетсяметодsplit().Но,наэтотраз,внутрискобокуказываетсядругойразделитель-запятая.Витоге,вспискеvlans,находятсяномераVLAN.

Уметодаsplit()естьещёоднахорошаяособенность:поумолчанию,методразбиваетстрокунепоодномупробелу,аполюбомуколичествупробелов.Этобудеточеньполезнымприобработкекомандshow.Например:

In[58]:sh_ip_int_br="FastEthernet0/015.0.15.1YESmanualup

up"

In[59]:sh_ip_int_br.split()

Out[59]:['FastEthernet0/0','15.0.15.1','YES','manual','up','up']

Авоттаквыглядитразделениетойжестроки,когдаодинпробелиспользуетсякакразделитель:

Полезныеметодыдляработысостроками

62

Page 63: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[60]:sh_ip_int_br.split('')

Out[60]:

['FastEthernet0/0','','','','','','','','','','','','15.0.15.1','','','

','','','','YES','manual','up','','','','','','','','','','','','',

'','','','','','','','up']

Полезныеметодыдляработысостроками

63

Page 64: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Форматированиестрок

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

Этоможноделатьобъединяячастистрокииданные,новPythonестьболееудобныйспособ:форматированиестрок.

Существуетдвавариантаформатированиястрок:

соператором%(болеестарыйвариант)методомformat()(новыйвариант)

Несмотрянато,чторекомендуетсяиспользоватьметодformat,частоможновстретитьформатированиестрокичерезоператор%.

Примериспользованияметодаformat:

In[1]:"interfaceFastEthernet0/{}".format('1')

Out[1]:'interfaceFastEthernet0/1'

Аналогичныйпримерсоператором%:

In[2]:"interfaceFastEthernet0/%s"%'1'

Out[2]:'interfaceFastEthernet0/1'

Вформатированиистрокспециальныесимволыуказываюткакойтипданныхбудетподставляться:

%s-строкаилилюбойдругойобъектвкотороместьстроковоепредставление%d-integer%f-float

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

Например,такимобразомможновывестиданныестолбцамиодинаковойшириныпо15символовсвыравниваниемпоправойстороне:

Форматированиестрок

64

Page 65: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[3]:vlan,mac,intf=['100','aabb.cc80.7000','Gi0/1']

In[4]:print"%15s%15s%15s"%(vlan,mac,intf)

100aabb.cc80.7000Gi0/1

In[5]:print"{:>15}{:>15}{:>15}".format(vlan,mac,intf)

100aabb.cc80.7000Gi0/1

Выравниваниеполевойстороне:

In[6]:print"%-15s%-15s%-15s"%(vlan,mac,intf)

100aabb.cc80.7000Gi0/1

In[7]:print"{:15}{:15}{:15}".format(vlan,mac,intf)

100aabb.cc80.7000Gi0/1

Спомощьюформатированиястрок,можнотакжевлиятьнаотображениечисел.

Например,можноуказатьсколькоцифрпослезапятойвыводить:

In[8]:print"%.3f"%(10.0/3)

3.333

In[9]:print"{:.3f}".format(10.0/3)

3.333

Конвертироватьвдвоичныйформат,указатьсколькоцифрдолжнобытьвотображениичислаидополнитьнедостающеенулями:

In[10]:'{:08b}'.format(10)

Out[10]:'00001010'

Аналогичныйрезультатможнополучитьспомощьюметодаzfill:

In[11]:bin(10)[2:].zfill(8)

Out[11]:'00001010'

Уформатированиястрокестьещёмноговозможностей.Хорошиепримерыиобъяснениядвухвариантовформатированиястрокможнонайтитут.

Форматированиестрок

65

Page 66: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Список(List)Списокэтоизменяемыйупорядоченныйтипданных.

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

Примерысписков:

In[1]:list1=[10,20,30,77]

In[2]:list2=['one','dog','seven']

In[3]:list3=[1,20,4.0,'word']

Таккаксписок-этоупорядоченныйтипданных,то,какивстроках,вспискахможнообращатьсякэлементупономеру,делатьсрезы:

In[4]:list3=[1,20,4.0,'word']

In[5]:list3[1]

Out[5]:20

In[6]:list3[1::]

Out[6]:[20,4.0,'word']

In[7]:list3[-1]

Out[7]:'word'

In[8]:list3[::-1]

Out[8]:['word',4.0,20,1]

Перевернутьсписокнаоборот,можноиспомощьюметодаreverse():

In[10]:vlans=['10','15','20','30','100-200']

In[11]:vlans.reverse()

In[12]:vlans

Out[12]:['100-200','30','20','15','10']

Таккакспискиизменяемые,элементыспискаможноменять:

Список(List)

66

Page 67: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[13]:list3

Out[13]:[1,20,4.0,'word']

In[14]:list3[0]='test'

In[15]:list3

Out[15]:['test',20,4.0,'word']

Можносоздаватьисписоксписков.И,какивобычномсписке,можнообращатьсякэлементамвовложенныхсписках:

In[16]:interfaces=[['FastEthernet0/0','15.0.15.1','YES','manual','up','up'],

....:['FastEthernet0/1','10.0.1.1','YES','manual','up','up'],

....:['FastEthernet0/2','10.0.2.1','YES','manual','up','down']]

In[17]:interfaces[0][0]

Out[17]:'FastEthernet0/0'

In[18]:interfaces[2][0]

Out[18]:'FastEthernet0/2'

In[19]:interfaces[2][1]

Out[19]:'10.0.2.1'

Список(List)

67

Page 68: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Полезныеметодыдляработысосписками

join()

Методjoin()собираетсписокстрокводнустрокусразделителем,которыйуказанвjoin():

In[16]:vlans=['10','20','30','100-200']

In[17]:','.join(vlans[:-1])

Out[17]:'10,20,30'

append()

Методappend()добавляетвконецспискауказанныйэлемент:

In[18]:vlans=['10','20','30','100-200']

In[19]:vlans.append('300')

In[20]:vlans

Out[20]:['10','20','30','100-200','300']

extend()

Еслинужнообъединитьдвасписка,томожноиспользоватьдваспособа.Методextend()иоперациюсложения:

In[21]:vlans=['10','20','30','100-200']

In[22]:vlans2=['300','400','500']

In[23]:vlans.extend(vlans2)

In[24]:vlans

Out[24]:['10','20','30','100-200','300','400','500']

In[25]:vlans+vlans2

Out[25]:['10','20','30','100-200','300','400','500','300','400','500']

In[26]:vlans

Out[26]:['10','20','30','100-200','300','400','500']

Полезныеметодыдляработысосписками

68

Page 69: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Ноприэтомметодextend()расширяетсписок"наместе",априоперациисложениявыводитсяитоговыйсуммарныйсписок,ноисходныеспискинеменяются.

pop()

Методpop()удаляетэлемент,которыйсоответствуетуказанномуномеру.Но,чтоважно,приэтомметодвозвращаетэтотэлемент:

In[28]:vlans=['10','20','30','100-200']

In[29]:vlans.pop(-1)

Out[29]:'100-200'

In[30]:vlans

Out[30]:['10','20','30']

Безуказанияномераудаляетсяпоследнийэлементсписка.

remove()

Методremove()удаляетуказанныйэлемент.

remove()невозвращаетудаленныйэлемент:

In[31]:vlans=['10','20','30','100-200']

In[32]:vlans.remove('20')

In[33]:vlans

Out[33]:['10','30','100-200']

Вметодеremoveнадоуказыватьсамэлемент,которыйнадоудалить,анеегономервсписке.Еслиуказатьномерэлемента,возникнетошибка:

In[34]:vlans.remove(-1)

-------------------------------------------------

ValueErrorTraceback(mostrecentcalllast)

<ipython-input-32-f4ee38810cb7>in<module>()

---->1vlans.remove(-1)

ValueError:list.remove(x):xnotinlist

index()

Полезныеметодыдляработысосписками

69

Page 70: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Методindex()используетсядлятого,чтобыпроверитьподкакимномеромвспискехранитсяэлемент:

In[35]:vlans=['10','20','30','100-200']

In[36]:vlans.index('30')

Out[36]:2

insert()

Методinsert()позволяетвставитьэлементнаопределенноеместовсписке:

In[37]:vlans=['10','20','30','100-200']

In[38]:vlans.insert(1,'15')

In[39]:vlans

Out[39]:['10','15','20','30','100-200']

Полезныеметодыдляработысосписками

70

Page 71: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Вариантысозданиясписка

Созданиеспискаспомощьюлитерала:

In[1]:vlans=[10,20,30,50]

Литерал-этовыражение,котороесоздаетобъект.

Созданиеспискаспомощьюфункцииlist():

In[2]:list1=list('router')

In[3]:printlist1

['r','o','u','t','e','r']

Генераторысписков:

In[4]:list2=['FastEthernet0/'+str(i)foriinrange(10)]

In[5]:list2

Out[6]:

['FastEthernet0/0',

'FastEthernet0/1',

'FastEthernet0/2',

'FastEthernet0/3',

'FastEthernet0/4',

'FastEthernet0/5',

'FastEthernet0/6',

'FastEthernet0/7',

'FastEthernet0/8',

'FastEthernet0/9']

Вариантысозданиясписка

71

Page 72: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Словарь(Dictionary)Словари-этоизменяемый,неупорядоченныйтипданных(кслову,вмодулеcollectionsдоступныупорядоченныеобъекты,внешнеидентичныесловарямOrderedDict).

Словарь(ассоциативныймассив,хеш-таблица):

данныевсловареэтопарыключ:значениедоступкзначениямосуществляетсяпоключу,анепономеру,каквспискахсловаринеупорядоченны,поэтомунестоитполагатьсянапорядокэлементовсловарятаккаксловариизменяемы,тоэлементысловаряможноменять,добавлять,удалятьключдолженбытьобъектомнеизменяемоготипа:

числострокакортеж

значениеможетбытьданнымилюбоготипа

Примерсловаря:

london={'name':'London1','location':'LondonStr','vendor':'Cisco','model':'44

51','IOS':'15.4'}

Можнозаписыватьитак:

london={

'id':1,

'name':'London',

'IT_VLAN':320,

'User_VLAN':1010,

'Mngmt_VLAN':99,

'to_name':None,

'to_id':None,

'port':'G1/0/11'

}

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

Словарь(Dictionary)

72

Page 73: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[1]:london={'name':'London1','location':'LondonStr'}

In[2]:london['name']

Out[2]:'London1'

In[3]:london['location']

Out[3]:'LondonStr'

Аналогичнымобразомможнодобавитьновуюпаруключ:значение:

In[4]:london['vendor']='Cisco'

In[5]:printlondon

{'vendor':'Cisco','name':'London1','location':'LondonStr'}

Всловаревкачествезначенияможноиспользоватьсловарь:

london_co={

'r1':{

'hostname':'london_r1',

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'4451',

'IOS':'15.4',

'IP':'10.255.0.1'

},

'r2':{

'hostname':'london_r2',

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'4451',

'IOS':'15.4',

'IP':'10.255.0.2'

},

'sw1':{

'hostname':'london_sw1',

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'3850',

'IOS':'3.6.XE',

'IP':'10.255.0.101'

}

}

Получитьзначенияизвложенногословаряможнотак:

Словарь(Dictionary)

73

Page 74: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[7]:london_co['r1']['IOS']

Out[7]:'15.4'

In[8]:london_co['r1']['model']

Out[8]:'4451'

In[9]:london_co['sw1']['IP']

Out[9]:'10.255.0.101'

Словарь(Dictionary)

74

Page 75: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Полезныеметодыдляработысословарями

clear()

Методclear()позволяеточиститьсловарь:

In[1]:london={'name':'London1','location':'LondonStr','vendor':'Cisco','mod

el':'4451','IOS':'15.4'}

In[2]:london.clear()

In[3]:london

Out[3]:{}

copy()

Методcopy()позволяетсоздатьполнуюкопиюсловаря.

Еслиуказать,чтоодинсловарьравендругому:

In[4]:london={'name':'London1','location':'LondonStr','vendor':'Cisco'}

In[5]:london2=london

In[6]:id(london)

Out[6]:25489072

In[7]:id(london2)

Out[7]:25489072

In[8]:london['vendor']='Juniper'

In[9]:london2['vendor']

Out[9]:'Juniper'

Вэтомслучаеlondon2этоещеодноимя,котороессылаетсянасловарь.И,приизмененияхсловаряlondon,меняетсяисловарьlondon2,таккакэтоссылкинаодинитотжеобъект.

Поэтому,еслинужносделатькопиюсловаря,надоиспользоватьметодcopy():

Полезныеметодыдляработысословарями

75

Page 76: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[10]:london={'name':'London1','location':'LondonStr','vendor':'Cisco'}

In[11]:london2=london.copy()

In[12]:id(london)

Out[12]:25524512

In[13]:id(london2)

Out[13]:25563296

In[14]:london['vendor']='Juniper'

In[15]:london2['vendor']

Out[15]:'Cisco'

get()

Еслиприобращенииксловарюуказываетсяключ,которогонетвсловаре,возникаетошибка:

In[16]:london={'name':'London1','location':'LondonStr','vendor':'Cisco'}

In[17]:london['IOS']

---------------------------------------------------------------------------

KeyErrorTraceback(mostrecentcalllast)

<ipython-input-17-b4fae8480b21>in<module>()

---->1london['IOS']

KeyError:'IOS'

Методget()запрашиваетключи,еслиегонет,вместоошибкивозвращаетNone.

In[18]:london={'name':'London1','location':'LondonStr','vendor':'Cisco'}

In[19]:printlondon.get('IOS')

None

Методget()позволяетуказыватьдругоезначение,вместоNone:

In[20]:printlondon.get('IOS','Ooops')

Ooops

keys(),values(),items()

Методыkeys(),values(),items():

Полезныеметодыдляработысословарями

76

Page 77: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[24]:london={'name':'London1','location':'LondonStr','vendor':'Cisco'}

In[25]:london.keys()

Out[25]:['vendor','name','location']

In[26]:london.values()

Out[26]:['Cisco','London1','LondonStr']

In[27]:london.items()

Out[27]:[('vendor','Cisco'),('name','London1'),('location','LondonStr')]

del

Удалитьключизначение:

In[28]:london={'name':'London1','location':'LondonStr','vendor':'Cisco'}

In[29]:del(london['name'])

In[30]:london

Out[30]:{'location':'LondonStr','vendor':'Cisco'}

Полезныеметодыдляработысословарями

77

Page 78: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Вариантысозданиясловаря

Словарьможносоздатьспомощьюлитерала:

In[1]:r1={'model':'4451','IOS':'15.4'}

Конструкторdictпозволяетсоздаватьсловарьнесколькимиспособами.

Есливролиключейиспользуютсястроки,можноиспользоватьтакойвариантсозданиясловаря:

In[2]:r1=dict(model='4451',IOS='15.4')

In[3]:r1

Out[3]:{'IOS':'15.4','model':'4451'}

Второйвариантсозданиясловаряспомощьюdict:

In[4]:r1=dict([('model','4451'),('IOS','15.4')])

In[5]:r1

Out[5]:{'IOS':'15.4','model':'4451'}

Вситуации,когданадосоздатьсловарьсизвестнымиключами,но,покачто,пустымизначениями(илиодинаковымизначениями),оченьудобенметодfromkeys():

In[5]:d_keys=['hostname','location','vendor','model','IOS','IP']

In[6]:r1=dict.fromkeys(d_keys,None)

In[7]:r1

Out[7]:

{'IOS':None,

'IP':None,

'hostname':None,

'location':None,

'model':None,

'vendor':None}

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

Вариантысозданиясловаря

78

Page 79: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[16]:d_keys=['hostname','location','vendor','model','IOS','IP']

In[17]:d={x:Noneforxind_keys}

In[18]:d

Out[18]:

{'IOS':None,

'IP':None,

'hostname':None,

'location':None,

'model':None,

'vendor':None}

Вариантысозданиясловаря

79

Page 80: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Словарьиздвухсписков(advanced)

Слово'advanced'взаголовке,означает,чтото,чторассматриваетсявэтомразделеещёнебыловтемахкурса.Но,вдальнейшем,такойприемможетпригодится.

Вразделевариантысозданиясловарярассматривалсятакойвариантсозданиясловаря:

In[4]:r1=dict([('model','4451'),('IOS','15.4')])

In[5]:r1

Out[5]:{'IOS':'15.4','model':'4451'}

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

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

Дляэтоговоспользуемсяфункциейzip(),котораявозвращаетсписоккортежей:

In[1]:a=[1,2,3]

In[2]:b=[100,200,300]

In[3]:zip(a,b)

Out[3]:[(1,100),(2,200),(3,300)]

Теперьнаболееполезномпримере:

Вариантысозданиясловаря

80

Page 81: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[4]:d_keys=['hostname','location','vendor','model','IOS','IP']

In[5]:d_values=['london_r1','21NewGlobeWalk','Cisco','4451','15.4','10.255

.0.1']

In[6]:zip(d_keys,d_values)

Out[6]:

[('hostname','london_r1'),

('location','21NewGlobeWalk'),

('vendor','Cisco'),

('model','4451'),

('IOS','15.4'),

('IP','10.255.0.1')]

In[7]:dict(zip(d_keys,d_values))

Out[7]:

{'IOS':'15.4',

'IP':'10.255.0.1',

'hostname':'london_r1',

'location':'21NewGlobeWalk',

'model':'4451',

'vendor':'Cisco'}

In[8]:r1=dict(zip(d_keys,d_values))

In[9]:r1

Out[9]:

{'IOS':'15.4',

'IP':'10.255.0.1',

'hostname':'london_r1',

'location':'21NewGlobeWalk',

'model':'4451',

'vendor':'Cisco'}

Впримеренижеестьотдельныйсписок,вкоторомхранятсяключи,исловарь,вкоторомхранитсяввидесписка(чтобысохранитьпорядок)информацияокаждомустройстве.

Соберемихвсловарьсключамиизспискаиинформациейизсловаряdata:

Вариантысозданиясловаря

81

Page 82: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[10]:d_keys=['hostname','location','vendor','model','IOS','IP']

In[11]:data={

....:'r1':['london_r1','21NewGlobeWalk','Cisco','4451','15.4','10.255.0.1'

],

....:'r2':['london_r2','21NewGlobeWalk','Cisco','4451','15.4','10.255.0.2'

],

....:'sw1':['london_sw1','21NewGlobeWalk','Cisco','3850','3.6.XE','10.255

.0.101']

....:}

In[12]:london_co={}

In[13]:forkindata.keys():

....:london_co[k]=dict(zip(d_keys,data[k]))

....:

In[14]:london_co

Out[14]:

{'r1':{'IOS':'15.4',

'IP':'10.255.0.1',

'hostname':'london_r1',

'location':'21NewGlobeWalk',

'model':'4451',

'vendor':'Cisco'},

'r2':{'IOS':'15.4',

'IP':'10.255.0.2',

'hostname':'london_r2',

'location':'21NewGlobeWalk',

'model':'4451',

'vendor':'Cisco'},

'sw1':{'IOS':'3.6.XE',

'IP':'10.255.0.101',

'hostname':'london_sw1',

'location':'21NewGlobeWalk',

'model':'3850',

'vendor':'Cisco'}}

Вариантысозданиясловаря

82

Page 83: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Кортеж(Tuple)Кортежэтонеизменяемыйупорядоченныйтипданных.

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

Грубоговоря,кортеж-этосписок,которыйнельзяизменить.Тоесть,вкортежеестьтолькоправаначтение.Этоможетбытьзащитойотслучайныхизменений.

Создатьпустойкортеж:

In[1]:tuple1=tuple()

In[2]:printtuple1

()

Кортежизодногоэлемента(обратитевниманиеназапятую):

In[3]:tuple2=('password',)

Кортежизсписка:

In[4]:list_keys=['hostname','location','vendor','model','IOS','IP']

In[5]:tuple_keys=tuple(list_keys)

In[6]:tuple_keys

Out[6]:('hostname','location','vendor','model','IOS','IP')

Кобъектамвкортежеможнообращатьсякакикобъектамсписка,попорядковомуномеру:

In[7]:tuple_keys[0]

Out[7]:'hostname'

Нотаккаккортежнеизменяем,присвоитьновоезначениенельзя:

Кортеж(Tuple)

83

Page 84: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[8]:tuple_keys[1]='test'

---------------------------------------------------------------------------

TypeErrorTraceback(mostrecentcalllast)

<ipython-input-9-1c7162cdefa3>in<module>()

---->1tuple_keys[1]='test'

TypeError:'tuple'objectdoesnotsupportitemassignment

Кортеж(Tuple)

84

Page 85: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Множество(Set)Множество-этоизменяемыйнеупорядоченныйтипданных.Вмножествевсегдасодержатсятолькоуникальныеэлементы.

МножествовPython-этопоследовательностьэлементов,которыеразделенымеждусобойзапятойизаключенывфигурныескобки.

Спомощьюмножестваможнолегкоубратьповторяющиесяэлементы:

In[1]:vlans=[10,20,30,40,100,10]

In[2]:set(vlans)

Out[2]:{10,20,30,40,100}

In[3]:set1=set(vlans)

In[4]:printset1

set([40,100,10,20,30])

Множество(Set)

85

Page 86: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Полезныеметодыдляработысмножествами

add()

Методadd()добавляетэлементвомножество:

In[1]:set1={10,20,30,40}

In[2]:set1.add(50)

In[3]:set1

Out[3]:{10,20,30,40,50}

discard()

Методdiscard()позволяетудалятьэлементы,невыдаваяошибку,еслиэлементавмножественет:

In[3]:set1

Out[3]:{10,20,30,40,50}

In[4]:set1.discard(55)

In[5]:set1

Out[5]:{10,20,30,40,50}

In[6]:set1.discard(50)

In[7]:set1

Out[7]:{10,20,30,40}

clear()

Методclear()очищаетмножество:

In[8]:set1={10,20,30,40}

In[9]:set1.clear()

In[10]:set1

Out[10]:set()

Полезныеметодыдляработысмножествами

86

Page 87: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Полезныеметодыдляработысмножествами

87

Page 88: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Операциисмножествами

Множестваполезнытем,чтоснимиможноделатьразличныеоперацииинаходитьобъединениемножеств,пересечениеитакдалее.

Объединениемножествможнополучитьспомощьюметодаunion()илиоператора|:

In[1]:vlans1={10,20,30,50,100}

In[2]:vlans2={100,101,102,102,200}

In[3]:vlans1.union(vlans2)

Out[3]:{10,20,30,50,100,101,102,200}

In[4]:vlans1|vlans2

Out[4]:{10,20,30,50,100,101,102,200}

Пересечениемножествможнополучитьспомощьюметодаintersection()илиоператора&:

In[5]:vlans1={10,20,30,50,100}

In[6]:vlans2={100,101,102,102,200}

In[7]:vlans1.intersection(vlans2)

Out[7]:{100}

In[8]:vlans1&vlans2

Out[8]:{100}

Операциисмножествами

88

Page 89: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Вариантысозданиямножества

Нельзясоздатьпустоемножествоспомощьюлитерала(таккаквтакомслучаеэтобудетнемножество,асловарь):

In[1]:set1={}

In[2]:type(set1)

Out[2]:dict

Нопустоемножествоможносоздатьтакимобразом:

In[3]:set2=set()

In[4]:type(set2)

Out[4]:set

Множествоизстроки:

In[5]:set('longlonglonglongstring')

Out[5]:{'','g','i','l','n','o','r','s','t'}

Множествоизсписка:

In[6]:set([10,20,30,10,10,30])

Out[6]:{10,20,30}

Генератормножеств:

In[7]:set2={i+100foriinrange(10)}

In[8]:set2

Out[8]:{100,101,102,103,104,105,106,107,108,109}

In[9]:printset2

set([100,101,102,103,104,105,106,107,108,109])

Вариантысозданиямножества

89

Page 90: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

int()

int()-преобразуетстрокувint:

In[1]:int("10")

Out[1]:10

Спомощьюфункцииintможнопреобразоватьичисловдвоичнойзаписивдесятичную(двоичнаязаписьдолжнабытьввидестроки)

In[2]:int("11111111",2)

Out[2]:255

bin()

Преобразоватьдесятичноечисловдвоичныйформатможноспомощьюbin():

In[3]:bin(10)

Out[3]:'0b1010'

In[4]:bin(255)

Out[4]:'0b11111111'

hex()

Аналогичнаяфункцияестьидляпреобразованиявшестнадцатиричныйформат:

In[5]:hex(10)

Out[5]:'0xa'

In[6]:hex(255)

Out[6]:'0xff'

list()

Преобразованиетипов

90

Page 91: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Функцияlist()преобразуетаргументвсписок:

In[7]:list("string")

Out[7]:['s','t','r','i','n','g']

In[8]:list({1,2,3})

Out[8]:[1,2,3]

In[9]:list((1,2,3,4))

Out[9]:[1,2,3,4]

set()

Функцияset()преобразуетаргументвмножество:

In[10]:set([1,2,3,3,4,4,4,4])

Out[10]:{1,2,3,4}

In[11]:set((1,2,3,3,4,4,4,4))

Out[11]:{1,2,3,4}

In[12]:set("stringstring")

Out[12]:{'','g','i','n','r','s','t'}

Этафункцияоченьполезна,когданужнополучитьуникальныеэлементывпоследовательности.

tuple()

Функцияtuple()преобразуетаргументвкортеж:

In[13]:tuple([1,2,3,4])

Out[13]:(1,2,3,4)

In[14]:tuple({1,2,3,4})

Out[14]:(1,2,3,4)

In[15]:tuple("string")

Out[15]:('s','t','r','i','n','g')

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

str()

Функцияstr()преобразуетаргументвстроку:

Преобразованиетипов

91

Page 92: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[16]:str(10)

Out[16]:'10'

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

Еслисделатьjoinдляспискачисел,возникнетошибка:

In[17]:vlans=[10,20,30,40]

In[18]:','.join(vlans)

------------------------------------------------------

TypeErrorTraceback(mostrecentcalllast)

<ipython-input-39-d705aed3f1b3>in<module>()

---->1','.join(vlans)

TypeError:sequenceitem0:expectedstring,intfound

Чтобыисправитьэто,нужнопреобразоватьчиславстроки.Этоудобноделатьспомощьюlistcomprehensions:

In[19]:','.join([str(vlan)forvlaninvlans])

Out[19]:'10,20,30,40'

Преобразованиетипов

92

Page 93: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Проверкатипов

Припреобразованиитиповданных,могутвозникнутьошибкитакогорода:

In[1]:int('a')

------------------------------------------------------

ValueErrorTraceback(mostrecentcalllast)

<ipython-input-42-b3c3f4515dd4>in<module>()

---->1int('a')

ValueError:invalidliteralforint()withbase10:'a'

Ошибкаабсолютнологичная.Мыпытаемсяпреобразоватьвдесятичныйформатстроку'a'.

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

Чтобыизбежатьеё,былобыхорошоиметьвозможностьпроверитьсчеммыработаем.

isdigit()

ВPythonтакиеметодыесть.Например,чтобыпроверитьсостоитлистрокаизоднихцифр,можноиспользоватьметодisdigit():

In[2]:"a".isdigit()

Out[2]:False

In[3]:"a10".isdigit()

Out[3]:False

In[4]:"10".isdigit()

Out[4]:True

Примериспользованияметода:

In[5]:vlans=['10','20','30','40','100-200']

In[6]:[int(vlan)forvlaninvlansifvlan.isdigit()]

Out[6]:[10,20,30,40]

isalpha()

Проверкатипов

93

Page 94: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Методisalpha()позволяетпроверитьсостоитлистрокаизоднихбукв:

In[7]:"a".isalpha()

Out[7]:True

In[8]:"a100".isalpha()

Out[8]:False

In[9]:"a--".isalpha()

Out[9]:False

In[10]:"a".isalpha()

Out[10]:False

isalnum()

Методisalnum()позволяетпроверитьсостоитлистрокаизбуквицифр:

In[11]:"a".isalnum()

Out[1]:True

In[12]:"a10".isalnum()

Out[12]:True

type()

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

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

Вэтомможетпомочьфункцияtype():

In[13]:type("string")

Out[13]:str

In[14]:type("string")isstr

Out[14]:True

Аналогичноскортежем(идругимитипамиданных):

Проверкатипов

94

Page 95: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[15]:type((1,2,3))

Out[15]:tuple

In[16]:type((1,2,3))istuple

Out[16]:True

In[17]:type((1,2,3))islist

Out[17]:False

Проверкатипов

95

Page 96: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание3.1

Обработатьстрокуospf_routeивывестиинформациюввиде:

Protocol:OSPF

Prefix:10.0.24.0/24

AD/Metric:110/41

Next-Hop:10.0.13.3

Lastupdate:3d18h

OutboundInterface:FastEthernet0/0

ВразделеФорматированиестрокдобавилисьпримеры,которыепомогутсотображениемвыводастолбцами.

ospf_route="O10.0.24.0/24[110/41]via10.0.13.3,3d18h,FastEthernet0/0"

Задание3.2

ПреобразоватьстрокуMACсформатаXXXX:XXXX:XXXXвXXXX.XXXX.XXXX

MAC="AAAA:BBBB:CCCC"

Задания

96

Page 97: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Задание3.3

ПолучитьизстрокиCONFIGсписокVLANвида['1','3','10','20','30','100'].

CONFIG="switchporttrunkallowedvlan1,3,10,20,30,100"

Задание3.4

Изстрокcommand1иcommand2получитьсписокVLAN,которыеестьивкомандеcommand1ивкомандеcommand2.Неиспользоватьдлярешениязадачициклы,операторif.

Дляданногопримера,результатомдолженбытьсписок:[1,3,100]

command1="switchporttrunkallowedvlan1,3,10,20,30,100"

command2="switchporttrunkallowedvlan1,3,100,200,300"

Задание3.5

СписокVLANS-этосписокVLANов,собранныхсовсехустройствсети,поэтомувспискеестьповторяющиесяномераVLAN.

ИзсписканужнополучитьуникальныйсписокVLANов,отсортированныйповозрастаниюномеров.

Неиспользоватьдлярешениязадачициклы,операторif.

VLANS=[10,20,30,1,2,100,10,30,3,4,10]

Задание3.6

ОбработатьстрокуNATтакимобразом,чтобывимениинтерфейсавместоFastEthernetбылоGigabitEthernet.

NAT="ipnatinsidesourcelistACLinterfaceFastEthernet0/1overload"

Задание3.7

ПреобразоватьMAC-адресвдвоичнуюстроку(бездвоеточий).

MAC="AAAA:BBBB:CCCC"

Задания

97

Page 98: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Задание3.8

ПреобразоватьIP-адрес(переменнаяIP)вдвоичныйформативывестивыводстолбцами,такимобразом:

первойстрокойдолжныидтидесятичныезначениябайтоввторойстрокойдвоичныезначения

Выводдолженбытьупорядочентакже,каквпримере:

столбцамиширинастолбца10символов

Примервывода:

10111

00001010000000010000000100000001

IP='192.168.3.1'

Задание3.9

Найтииндекспоследнеговхожденияэлементасконца.

Например,дляспискаnum_list,индекспоследнеговхожденияэлемента10-4;дляспискаword_list,индекспоследнеговхожденияэлемента'ruby'-6.

Сделатьрешениеобщим(тоесть,непривязыватьсякконкретномуэлементу)ипроверитьнаразныхспискахиэлементах.

Неиспользоватьдлярешенияциклы(for,while)иусловия(if/else).

Подсказка:функцияlen()возвращаетдлинусписка.

num_list=[10,2,30,100,10,50,11,30,15,7]

word_list=['python','ruby','perl','ruby','perl','python','ruby','perl']

Задания

98

Page 99: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

СозданиебазовыхскриптовЕслиговоритьвцелом,тоскрипт-этообычныйфайл.Вэтомфайлехранитсяпоследовательностькоманд,которыенеобходимовыполнить.

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

Дляэтогонадосоздатьфайлaccess_template.pyстакимсодержимым:

access_template=['switchportmodeaccess',

'switchportaccessvlan%d',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

print'\n'.join(access_template)%5

Сначалаэлементыспискаобъединяютсявстроку,котораяразделенасимволом\n,австрокуподставляетсяномерVLAN,используяформатированиестрок.

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

Таквыглядитвыполнениескрипта:

$pythonaccess_template.py

switchportmodeaccess

switchportaccessvlan5

switchportnonegotiate

spanning-treeportfast

spanning-treebpduguardenable

Ставитьрасширение.pyуфайланеобязательно.

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

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

Кодировка

4.Созданиебазовыхскриптов

99

Page 100: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Теперьпопробуемвывеститекст,набранныйкириллицей,настандартныйпотоквывода(файлaccess_template_encoding.py):

access_template=['switchportmodeaccess',

'switchportaccessvlan%d',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

print"Конфигурацияинтерфейсаврежимеaccess:"

print'\n'.join(access_template)%5

Припопыткезапуститьскриптполучаемтакуюошибку:

$pythonaccess_template_encoding.py

File"access_template_encoding.py",line7

SyntaxError:Non-ASCIIcharacter'\xd0'infileaccess_template_encoding.pyonline7,

butnoencodingdeclared;seehttp://python.org/dev/peps/pep-0263/fordetails

Длятогочтобынебылотакойошибки,необходимодобавитьвначалефайлатакуюстроку:

#-*-coding:utf-8-*-

Тогдаскриптaccess_template_encoding.pyбудетвыглядетьтак:

#-*-coding:utf-8-*-

access_template=['switchportmodeaccess',

'switchportaccessvlan%d',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

print"Конфигурацияинтерфейсаврежимеaccess:"

print'\n'.join(access_template)%5

Теперьошибкинет:

4.Созданиебазовыхскриптов

100

Page 101: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythonaccess_template_encoding.py

Конфигурацияинтерфейсаврежимеaccess:

switchportmodeaccess

switchportaccessvlan5

switchportnonegotiate

spanning-treeportfast

spanning-treebpduguardenable

Исполняемыйфайл

Длятого,чтобыфайлбылисполняемыминенужнобылокаждыйразписатьpythonпередвызовомфайла,нужно:

сделатьфайлисполняемым(дляlinux)впервойстрокефайладолжнанаходитсястрока#!/usr/bin/envpython

Примерфайлаaccess_template_exec.py:

#!/usr/bin/envpython

access_template=['switchportmodeaccess',

'switchportaccessvlan%d',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

print'\n'.join(access_template)%5

Послеэтого:

chmod+xaccess_template_exec.py

Теперьможновызыватьфайлтакимобразом:

$./access_template_exec.py

4.Созданиебазовыхскриптов

101

Page 102: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

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

ВPython,вмодулеsysестьоченьпростойиудобныйспособдляработысаргументами-argv.

Посмотримнапример(файлaccess_template_argv.py):

fromsysimportargv

interface,vlan=argv[1:]

access_template=['switchportmodeaccess',

'switchportaccessvlan%d',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

print'interface%s'%interface

print'\n'.join(access_template)%int(vlan)

Проверяемработускрипта:

$pythonaccess_template_argv.pyGi0/74

interfaceGi0/7

switchportmodeaccess

switchportaccessvlan4

switchportnonegotiate

spanning-treeportfast

spanning-treebpduguardenable

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

Тутнадопояснитьнесколькомоментов:

argvэтосписокargvсодержитнетолькоаргументы,которыепередалискрипту,ноиназваниесамогоскрипта

Передачааргументовскрипту

102

Page 103: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Вданномслучае,вспискеargvнаходятсятакиеэлементы:

['access_template_argv.py','Gi0/7','4']

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

Ещёодинмомент,которыйможетбытьнеоченьпонятным:

interface,vlan=argv[1:]

Выражениеargv[1:]должнобытьзнакомым.Этосрезсписка.Тоесть,вправойсторонеостаетсясписок,сдвумяэлементами:['Gi0/7','4'].

Разберемсясдвойнымприсваиванием.

ВPythonестьвозможностьзаразприсвоитьзначениянесколькимпеременным.Простойпример:

In[16]:a=5

In[17]:b=6

In[18]:c,d=5,6

In[19]:c

Out[19]:5

In[20]:d

Out[20]:6

Есливместочиселсписок,каквслучаесargv:

In[21]:arg=['Gi0/7','4']

In[22]:interface,vlan=arg

In[23]:interface

Out[23]:'Gi0/7'

In[24]:vlan

Out[24]:'4'

Обратитевнимание,чтоargvвсегдавозвращаетаргументыввидестроки.А,таккаквспискеaccess_templateвсинтаксисеформатированиястрок,указаночисло,переменнуюvlanнужнопреобразоватьвчисло(последняястрока).

Передачааргументовскрипту

103

Page 104: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

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

Дляполученияинформацииотпользователяиспользуетсяфункцияraw_input():

In[1]:printraw_input('Твойлюбимыйпротоколмаршрутизации?')

Твойлюбимыйпротоколмаршрутизации?OSPF

OSPF

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

In[2]:protocol=raw_input('Твойлюбимыйпротоколмаршрутизации?')

Твойлюбимыйпротоколмаршрутизации?OSPF

In[3]:printprotocol

OSPF

Вскобкахобычнопишетсякакой-товопрос,которыйуточняет,какуюинформациюнужноввести.

Текствскобках,впринципе,писатьнеобязательно.Иможносделатьтакойжевыводспомощьюоператораprint:

In[4]:print'Твойлюбимыйпротоколмаршрутизации?'

Твойлюбимыйпротоколмаршрутизации?

In[5]:protocol=raw_input()

OSPF

In[6]:printprotocol

OSPF

Но,какправило,нагляднееписатьтекствсамойфункцииraw_print().

Запрашиваниеинформацииизскрипта(файлaccess_template_raw_input.py):

Вводинформациипользователем

104

Page 105: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

interface=raw_input('Enterinterfacetypeandnumber:')

vlan=int(raw_input('EnterVLANnumber:'))

access_template=['switchportmodeaccess',

'switchportaccessvlan%d',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

print'\n'+'-'*30

print'interface%s'%interface

print'\n'.join(access_template)%vlan

Впервыхдвухстроках,запрашиваетсяинформацияупользователя.Функцияraw_input(),какиargvвозвращаетданныеввидестрок.Поэтому,параметрvlanпреобразуемвчисло.

Ещепоявиласьстрокаprint'\n'+'-'*30.Онаиспользуетсяпростодлятого,чтобыотделитьзапросинформацииотвывода.

Выполняемскрипт:

$pythonaccess_template_raw_input.py

Enterinterfacetypeandnumber:Gi0/3

EnterVLANnumber:55

------------------------------

interfaceGi0/3

switchportmodeaccess

switchportaccessvlan55

switchportnonegotiate

spanning-treeportfast

spanning-treebpduguardenable

Разницамеждуфункциямиraw_input()иinput()хорошоописананаstackoverflow

Вводинформациипользователем

105

Page 106: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание4.1

ЗапроситьупользователявводIP-сетивформате:10.1.1.0/24

Затемвывестиинформациюосетиимаскевтакомформате:

Network:

10110

00001010000000010000000100000000

Mask:

/24

2552552550

11111111111111111111111100000000

Проверитьработускриптанаразныхкомбинацияхсеть/маска.

Задание4.1a

Всё,каквзадании4.1.Но,еслипользовательввеладресхоста,анеадрессети,тонадоадресхостапреобразоватьвадрессетиивывестиадрессетиимаску,каквзадании4.1.

Задания

106

Page 107: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Примерадресасети(всебитыхостовойчастиравнынулю):

10.0.1.0/24190.1.0.0/16

Примерадресахоста:

10.0.1.1/24-хостизсети10.0.1.0/2410.0.5.1/30-хостизсети10.0.5.0/30

Network:

10110

00001010000000010000000100000000

Mask:

/24

2552552550

11111111111111111111111100000000

Проверитьработускриптанаразныхкомбинацияхсеть/маска.

Задание4.1b

Преобразоватьскриптиззадания4.1aтакимобразом,чтобысеть/масканезапрашивалисьупользователя,апередавалиськакаргументскрипту.

Задание4.2

Вэтойзадаченельзяиспользоватьусловиеifинельзяизменятьсловарьlondon_co.

Взаданиисоздансловарьсинформациейоразныхустройствах.

Вамнужнозапроситьупользователявводимениустройства(r1,r2илиsw1).Ивывестиинформациюосоответствующемустройственастандартныйпотоквывода(информациябудетввидесловаря).

Примервыполненияскрипта:

$pythontask_4_2.py

Enterdevicename:r1

{'ios':'15.4','model':'4451','vendor':'Cisco','location':'21NewGlobeWalk','

ip':'10.255.0.1'}

Задания

107

Page 108: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

london_co={

'r1':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'4451',

'ios':'15.4',

'ip':'10.255.0.1'

},

'r2':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'4451',

'ios':'15.4',

'ip':'10.255.0.2'

},

'sw1':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'3850',

'ios':'3.6.XE',

'ip':'10.255.0.101',

'vlans':'10,20,30',

'routing':True

}

}

Задание4.2a

Вэтойзадаченельзяиспользоватьусловиеifинельзяизменятьсловарьlondon_co.

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

Вывестиинформациюосоответствующемпараметре,указанногоустройства.

Примервыполненияскрипта:

$pythontask_4_2a.py

Enterdevicename:r1

Enterparametername:ios

15.4

Задания

108

Page 109: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

london_co={

'r1':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'4451',

'ios':'15.4',

'ip':'10.255.0.1'

},

'r2':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'4451',

'ios':'15.4',

'ip':'10.255.0.2'

},

'sw1':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'3850',

'ios':'3.6.XE',

'ip':'10.255.0.101',

'vlans':'10,20,30',

'routing':True

}

}

Задание4.2b

Вэтойзадаченельзяиспользоватьусловиеifинельзяизменятьсловарьlondon_co.

Переделатьскриптиззадания4.2aтакимобразом,чтобы,призапросепараметра,отображалсясписоквозможныхпараметров.

Вывестиинформациюосоответствующемпараметре,указанногоустройства.

Примервыполненияскрипта:

$pythontask_4_2b.py

Enterdevicename:r1

Enterparametername(ios,model,vendor,location,ip):ip

10.255.0.1

Задания

109

Page 110: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

london_co={

'r1':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'4451',

'ios':'15.4',

'ip':'10.255.0.1'

},

'r2':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'4451',

'ios':'15.4',

'ip':'10.255.0.2'

},

'sw1':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'3850',

'ios':'3.6.XE',

'ip':'10.255.0.101',

'vlans':'10,20,30',

'routing':True

}

}

Задание4.2c

Вэтойзадаченельзяиспользоватьусловиеifинельзяизменятьсловарьlondon_co.

Переделатьскриптиззадания4.2bтакимобразом,чтобы,призапросепараметра,которогонетвсловареустройства,отображалосьсообщение'Такогопараметранет'.

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

Есливыбрансуществующийпараметр,вывестиинформациюосоответствующемпараметре,указанногоустройства.

Примервыполненияскрипта:

$pythontask_4_2c.py

Enterdevicename:r1

Enterparametername(ios,model,vendor,location,ip):io

Такогопараметранет

Задания

110

Page 111: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

london_co={

'r1':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'4451',

'ios':'15.4',

'ip':'10.255.0.1'

},

'r2':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'4451',

'ios':'15.4',

'ip':'10.255.0.2'

},

'sw1':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'3850',

'ios':'3.6.XE',

'ip':'10.255.0.101',

'vlans':'10,20,30',

'routing':True

}

}

Задание4.2d

Вэтойзадаченельзяиспользоватьусловиеifинельзяизменятьсловарьlondon_co.

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

Примервыполненияскрипта:

$pythontask_4_2d.py

Enterdevicename:r1

Enterparametername(ios,model,vendor,location,ip):IOS

15.4

Задания

111

Page 112: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

london_co={

'r1':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'4451',

'ios':'15.4',

'ip':'10.255.0.1'

},

'r2':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'4451',

'ios':'15.4',

'ip':'10.255.0.2'

},

'sw1':{

'location':'21NewGlobeWalk',

'vendor':'Cisco',

'model':'3850',

'ios':'3.6.XE',

'ip':'10.255.0.101',

'vlans':'10,20,30',

'routing':True

}

}

Задание4.3

(Задачанаосновепримероввразделе)

Вэтойзадаченельзяиспользоватьусловиеif.

Скриптдолжензапрашиватьупользователя:

информациюорежимеинтерфейса(access/trunk),примертекстазапроса:'Enterinterfacemode(access/trunk):'

номереинтерфейса(типиномер,видаGi0/3)примертекстазапроса:'Enterinterfacetypeandnumber:'

номерVLANа(длярежимаtrunkбудетвводитьсясписокVLANов)примертекстазапроса:'Entervlan(s):'

Взависимостиотвыбранногорежима,настандартныйпотоквывода,должнавозвращатьсясоответствующаяконфигурацияaccessилиtrunk(шаблоныкоманднаходятсявспискахaccess_templateиtrunk_template).

Приэтом,сначаладолжнаидтистрокаinterfaceиподставленномеринтерфейса,азатемсоответствующийшаблон,вкоторыйподставленномерVLANа(илисписокVLANов).

Задания

112

Page 113: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Примервыполненияскрипта,привыборережимаaccess:

$pythontask_4_3.py

Enterinterfacemode(access/trunk):access

Enterinterfacetypeandnumber:Fa0/6

Entervlan(s):3

interfaceFa0/6

switchportmodeaccess

switchportaccessvlan3

switchportnonegotiate

spanning-treeportfast

spanning-treebpduguardenable

Примервыполненияскрипта,привыборережимаtrunk:

$pythontask_4_3.py

Enterinterfacemode(access/trunk):trunk

Enterinterfacetypeandnumber:Fa0/7

Entervlan(s):2,3,4,5

interfaceFa0/7

switchporttrunkencapsulationdot1q

switchportmodetrunk

switchporttrunkallowedvlan2,3,4,5

Начальноесодержимоескрипта:

access_template=['switchportmodeaccess',

'switchportaccessvlan%s',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

trunk_template=['switchporttrunkencapsulationdot1q',

'switchportmodetrunk',

'switchporttrunkallowedvlan%s']

Задание4.3a

Вэтойзадаченельзяиспользоватьусловиеif.

Дополнитьскриптиззадания4.3такимобразом,чтобы,взависимостиотвыбранногорежима,задавалисьразныевопросывзапросеономереVLANаилиспискаVLANов:

Задания

113

Page 114: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

дляaccess:'EnterVLANnumber:'дляtrunk:'EnterallowedVLANs:'

access_template=['switchportmodeaccess',

'switchportaccessvlan%s',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

trunk_template=['switchporttrunkencapsulationdot1q',

'switchportmodetrunk',

'switchporttrunkallowedvlan%s']

Задания

114

Page 115: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

КонтрольходапрограммыВэтомразделерассматриваютсявозможностиPythonвуправленииходомпрограммы.

Какминимум,стоитразобратьсясконструкциями:

if/elif/else

цикломforцикломwhile

Остальныеразделыможнопрочестьпозже.

Разделпроконструкцииfor/elseиwhile/else,возможно,будетпрощепонять,еслипрочестьихпослеразделаобобработкеисключений.

5.Контрольходапрограммы

115

Page 116: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

if/elif/elseКонструкцияif/elif/elseдаетвозможностьвыполнятьразличныедействиявзависимостиотусловий.

Вэтойконструкциитолькоifявляетсяобязательным,elifиelseопциональны:

Проверкаifвсегдаидетпервой.Послеоператораifдолжнобытькакое-тоусловие:еслиэтоусловиевыполняется(возвращаетTrue),тодействиявблокеifвыполняются.Спомощьюelifможносделатьнесколькоразветвлений.Тоесть,проверятьвходящиеданныенаразныеусловия.

блокelifэтототжеif,нотолькоследующаяпроверка.Грубоговоря,это"аесли..."блоковelifможетбытьмного

Блокelseвыполняетсявтомслучае,еслиниодноизусловийifилиelifнебылоистинным.

Примерконструкции:

In[1]:a=9

In[2]:ifa==0:

...:print'aравно0'

...:elifa<10:

...:print'aменьше10'

...:else:

...:print'aбольше10'

...:

aменьше10

Условиямипослеifилиelifмогутбыть,например,такиеконструкции:

if/elif/else

116

Page 117: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[7]:5>3

Out[7]:True

In[8]:5==5

Out[8]:True

In[9]:'vlan'in'switchporttrunkallowedvlan10,20'

Out[9]:True

In[10]:1in[1,2,3]

Out[10]:True

In[11]:0in[1,2,3]

Out[11]:False

TrueиFalse

ВPython:

True(истина)любоененулевоечислолюбаянепустаястрокалюбойнепустойобъект

False(ложь)0Noneпустаястрокапустойобъект

ОстальныезначенияTrueилиFalse,какправило,логическиследуютизусловия.

Например,таккакпустойсписокэтоложь,проверитьпустойлисписокможнотакимобразом:

In[12]:list_to_test=[1,2,3]

In[13]:iflist_to_test:

....:print"Вспискеестьобъекты"

....:

Вспискеестьобъекты

Тотжерезультатможнобылобыполучитьтакимобразом:

if/elif/else

117

Page 118: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[14]:iflen(list_to_test)!=0:

....:print"Вспискеестьобъекты"

....:

Вспискеестьобъекты

Операторысравнения

Операторысравнения,которыемогутиспользоватьсявусловиях:

In[3]:5>6

Out[3]:False

In[4]:5>2

Out[4]:True

In[5]:5<2

Out[5]:False

In[6]:5==2

Out[6]:False

In[7]:5==5

Out[7]:True

In[8]:5>=5

Out[8]:True

In[9]:5<=10

Out[9]:True

In[10]:8!=10

Out[10]:True

Обратитевнимание,чторавенствопроверяетсядвойным==.

Операторin

Операторinпозволяетвыполнятьпроверкунаналичиеэлементавпоследовательности(например,элементавспискеилиподстрокивстроке):

if/elif/else

118

Page 119: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[8]:'Fast'in'FastEthernet'

Out[8]:True

In[9]:'Gigabit'in'FastEthernet'

Out[9]:False

In[10]:vlan=[10,20,30,40]

In[11]:10invlan

Out[11]:True

In[12]:50invlan

Out[12]:False

Прииспользованиисословарямиусловиеinвыполняетпроверкупоключамсловаря:

In[15]:r1={

....:'IOS':'15.4',

....:'IP':'10.255.0.1',

....:'hostname':'london_r1',

....:'location':'21NewGlobeWalk',

....:'model':'4451',

....:'vendor':'Cisco'}

In[16]:'IOS'inr1

Out[16]:True

In[17]:'4451'inr1

Out[17]:False

Операторыand,or,not

Вусловияхмогуттакжеиспользоватьсялогическиеоператорыand,or,not:

if/elif/else

119

Page 120: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[15]:r1={

....:'IOS':'15.4',

....:'IP':'10.255.0.1',

....:'hostname':'london_r1',

....:'location':'21NewGlobeWalk',

....:'model':'4451',

....:'vendor':'Cisco'}

In[18]:vlan=[10,20,30,40]

In[19]:'IOS'inr1and10invlan

Out[19]:True

In[20]:'4451'inr1and10invlan

Out[20]:False

In[21]:'4451'inr1or10invlan

Out[21]:True

In[22]:not'4451'inr1

Out[22]:True

In[23]:'4451'notinr1

Out[23]:True

Операторand

ВPythonоператорandвозвращаетнебулевозначение,азначениеодногоизоператоров.

Еслиобаоперандаявляютсяистиной,результатомвыражениябудетпоследнеезначение:

In[24]:'string1'and'string2'

Out[24]:'string2'

In[25]:'string1'and'string2'and'string3'

Out[25]:'string3'

Еслиодинизоператоровявляетсяложью,результатомвыражениябудетпервоеложноезначение:

In[26]:''and'string1'

Out[26]:''

In[27]:''and[]and'string1'

Out[27]:''

if/elif/else

120

Page 121: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Операторor

Операторor,какиоператорand,возвращаетзначениеодногоизоператоров.

Приоценкеоперандов,возвращаетсяпервыйистинныйоперанд:

In[28]:''or'string1'

Out[28]:'string1'

In[29]:''or[]or'string1'

Out[29]:'string1'

In[30]:'string1'or'string2'

Out[30]:'string1'

Есливсезначенияявляютсяложью,возвращаетсяпоследнеезначение:

In[31]:''or[]or{}

Out[31]:{}

Важнаяособенностьработыоператораor-операнды,которыенаходятсяпослеистинного,невычисляются:

In[32]:defprint_str(string):

....:printstring

....:

In[33]:''orprint_str('teststring')

teststring

In[34]:''or'string1'orprint_str('teststring')

Out[34]:'string1'

Примериспользованияконструкцииif/elif/else

Примерскриптаcheck_password.py,которыйпроверяетдлинупароляиестьливпаролеимяпользователя:

if/elif/else

121

Page 122: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

#-*-coding:utf-8-*-

username=raw_input('Введитеимяпользователя:')

password=raw_input('Введитепароль:')

iflen(password)<8:

print'Парольслишкомкороткий'

elifusernameinpassword:

print'Парольсодержитимяпользователя'

else:

print'Парольдляпользователя%sустановлен'%username

Проверкаскрипта:

$pythoncheck_password.py

Введитеимяпользователя:nata

Введитепароль:nata1234

Парольсодержитимяпользователя

$pythoncheck_password.py

Введитеимяпользователя:nata

Введитепароль:123nata123

Парольсодержитимяпользователя

$pythoncheck_password.py

Введитеимяпользователя:nata

Введитепароль:1234

Парольслишкомкороткий

$pythoncheck_password.py

Введитеимяпользователя:nata

Введитепароль:123456789

Парольдляпользователяnataустановлен

Трехместноевыражение(Ternaryexpressions)

Иногдаудобнееиспользоватьтернарныйоператор,нежелиразвернутуюформу:

s=[1,2,3,4]

result=Trueiflen(s)>5elseFalse

if/elif/else

122

Page 123: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

forЦиклforпроходитсяпоуказаннойпоследовательностиивыполняетдействия,которыеуказанывблокеfor.

Примерыпоследовательностей,покоторымможетпроходитьсяциклfor:

строкасписоксловарьфункция'''range()'''илиитератор'''xrange()'''любойдругойитератор(например,'''sorted()''','''enumerate()''')

Вкурсенерассматривается,чтотакоеитератор,но,есливдвухсловах,этотакойспециальныйобъект,которыйдаетследующеезначениетолькотогда,когдаононужно.Например,еслиприиспользованиивыраженияrange(10),функциявернетсписокчиселот0до9(включительно)сразу.Еслижевоспользоватьсяитераторомxrange(),тоонвернетспециальныйобъект.Инебудетвозвращатьчисла,покакнемунебудутобращаться,например,вциклеfor.Из-затакихособенностей,всегда,когданадоработатьсбольшимколичествомобъектов,лучшеиспользоватьитератор.Вобщемслучае,еголучшеиспользоватьвезде,гдеонподходитпофункциональности.

Циклforпроходитсяпостроке:

In[1]:forletterin'Teststring':

...:printletter

...:

T

e

s

t

s

t

r

i

n

g

Вциклеиспользуетсяпеременнаясименемletter.Хотяимяможетбытьлюбое,удобно,когдаимяподсказываетчерезкакиеобъектыпроходитцикл.

Примерциклаforсфункцией(итератором)xrange():

for

123

Page 124: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[2]:foriinxrange(10):

...:print'interfaceFastEthernet0/'+str(i)

...:

interfaceFastEthernet0/0

interfaceFastEthernet0/1

interfaceFastEthernet0/2

interfaceFastEthernet0/3

interfaceFastEthernet0/4

interfaceFastEthernet0/5

interfaceFastEthernet0/6

interfaceFastEthernet0/7

interfaceFastEthernet0/8

interfaceFastEthernet0/9

Вэтомциклеиспользуетсяxrange(10).Этотитераторгенерируетчиславдиапазонеотнуля,доуказанногочисла(до10),невключаяего.

Вэтомпримере,циклпроходитпоспискуVLANов,поэтомупеременнуюможноназватьvlan:

In[3]:vlans=[10,20,30,40,100]

In[4]:forvlaninvlans:

...:print'vlan%d'%vlan

...:print'nameVLAN_%d'%vlan

...:

vlan10

nameVLAN_10

vlan20

nameVLAN_20

vlan30

nameVLAN_30

vlan40

nameVLAN_40

vlan100

nameVLAN_100

Когдациклидетпословарю,тофактическионпроходитсяпоключам:

for

124

Page 125: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[5]:r1={

'IOS':'15.4',

'IP':'10.255.0.1',

'hostname':'london_r1',

'location':'21NewGlobeWalk',

'model':'4451',

'vendor':'Cisco'}

In[6]:forkinr1:

....:printk

....:

vendor

IP

hostname

IOS

location

model

Еслинеобходимовыводитьпарыключ-значениевцикле:

In[7]:forkeyinr1:

....:printkey+'=>'+r1[key]

....:

vendor=>Cisco

IP=>10.255.0.1

hostname=>london_r1

IOS=>15.4

location=>21NewGlobeWalk

model=>4451

Всловареестьспециальныйметодitems,которыйпозволяетпроходитсявциклесразупопареключ,значение:

In[8]:forkey,valueinr1.items():

....:printkey+'=>'+value

....:

vendor=>Cisco

IP=>10.255.0.1

hostname=>london_r1

IOS=>15.4

location=>21NewGlobeWalk

model=>4451

Методitems,вместословаря,возвращаетсписоккортежей:

for

125

Page 126: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[9]:r1.items()

Out[9]:

[('vendor','Cisco'),

('IP','10.255.0.1'),

('hostname','london_r1'),

('IOS','15.4'),

('location','21NewGlobeWalk'),

('model','4451')]

Такжеестьметодiteritems().Онполностьюаналогиченметодуitems,новозвращаетитератор,анесписоккортежей:

In[10]:r1.iteritems()

Out[10]:<dictionary-itemiteratorat0x102daff18>

for

126

Page 127: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Вложенныеfor

Циклыforможновкладыватьдругвдруга.

Вэтомпримере,вспискеcommandsхранятсякоманды,которыенадовыполнитьдлякаждогоизинтерфейсоввспискеfast_int:

In[7]:commands=['switchportmodeaccess','spanning-treeportfast','spanning-tree

bpduguardenable']

In[8]:fast_int=['0/1','0/3','0/4','0/7','0/9','0/10','0/11']

In[9]:forintfinfast_int:

...:print'interfaceFastEthernet'+intf

...:forcommandincommands:

...:print'%s'%command

...:

interfaceFastEthernet0/1

switchportmodeaccess

spanning-treeportfast

spanning-treebpduguardenable

interfaceFastEthernet0/3

switchportmodeaccess

spanning-treeportfast

spanning-treebpduguardenable

interfaceFastEthernet0/4

switchportmodeaccess

spanning-treeportfast

spanning-treebpduguardenable

...

Первыйциклforпроходитсяпоинтерфейсамвспискеfast_int,авторойпокомандамвспискеcommands.

Вложенныеfor

127

Page 128: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Совмещениеforиif

Рассмотримпримерсовмещенияforиif.

Файлgenerate_access_port_config.py:

access_template=['switchportmodeaccess',

'switchportaccessvlan',

'spanning-treeportfast',

'spanning-treebpduguardenable']

fast_int={'access':{'0/12':'10',

'0/14':'11',

'0/16':'17',

'0/17':'150'}}

forintfinfast_int['access']:

print'interfaceFastEthernet'+intf

forcommandinaccess_template:

ifcommand.endswith('accessvlan'):

print'%s%s'%(command,fast_int['access'][intf])

else:

print'%s'%command

Комментарииккоду:

Впервомциклеforперебираютсяключивовложенномсловареfast_int['access']Текущийключ,наданныймоментцикла,хранитсявпеременнойintfВыводитсястрокаinterfaceFastEthernetсдобавлениемкнейномераинтерфейсаВовторомциклеforперебираютсякомандыизспискаaccess_templateТаккакккомандеswitchportaccessvlan,надодобавитьномерVLAN:

внутривторогоциклаforпроверяютсякомандыесликомандазаканчиваетсянаaccessvlan

выводитсякомандаикнейдобавляетсяномерVLAN,обратившиськвложенномусловарюпотекущемуключуintf

вовсехостальныхслучаях,простовыводитсякоманда

Результатвыполненияскрипта:

Совмещениеforиif

128

Page 129: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythongenerate_access_port_config.py

interfaceFastEthernet0/12

switchportmodeaccess

switchportaccessvlan10

spanning-treeportfast

spanning-treebpduguardenable

interfaceFastEthernet0/14

switchportmodeaccess

switchportaccessvlan11

spanning-treeportfast

spanning-treebpduguardenable

interfaceFastEthernet0/16

switchportmodeaccess

switchportaccessvlan17

spanning-treeportfast

spanning-treebpduguardenable

Совмещениеforиif

129

Page 130: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Итераторenumerate()

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

Но,гораздоудобнееэтоделатьспомощьюитератораenumerate().

Базовыйпример:

In[1]:list1=['str1','str2','str3']

In[2]:forposition,stringinenumerate(list1):

...:printposition,string

...:

0str1

1str2

2str3

enumerate()умеетсчитатьнетолькоснуля,ноислюбогозначение,котороеемууказалипослеобъекта:

In[1]:list1=['str1','str2','str3']

In[2]:forposition,stringinenumerate(list1,100):

...:printposition,string

...:

100str1

101str2

102str3

ПримериспользованияenumerateдляEEM(advanced)

Слово'advanced'взаголовке,означает,чтото,чторассматриваетсявэтомразделеещёнебыловтемахкурса.Но,вдальнейшем,такойприемможетпригодится.

ВэтомпримереиспользуетсяCiscoEEM.Есливдвухсловах,тоEEMпозволяетвыполнятькакие-тодействия(action)вответнасобытие(event).

ВыглядитappletEEMтак:

Итераторenumerate

130

Page 131: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

eventmanagerappletFa0/1_no_shut

eventsyslogpattern"LineprotocolonInterfaceFastEthernet0/0,changedstatetodo

wn"

action1clicommand"enable"

action2clicommand"conft"

action3clicommand"interfacefa0/1"

action4clicommand"nosh"

ВEEM,вситуации,когдадействийвыполнитьнужномного,неудобнокаждыйразнабиратьactionxclicommand.Плюс,чащевсего,ужеестьготовыйкусокконфигурации,которыйдолженвыполнитьEEM.

СпомощьюпростогоскриптаPython,можносгенерироватькомандыEEM,наоснованиисуществующегоспискакоманд(файлeem.py):

importsys

config=sys.argv[1]

withopen(config,'r')asfile:

for(i,command)inenumerate(file,1):

print'action%04dclicommand"%s"'%(i,command.rstrip())

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

КонструкцияwithикакработатьсфайламирассмотриваютсявразделеРаботасфайлами

Файлскомандамивыглядиттак(r1_config.txt):

en

conft

nointGi0/0/0.300

nointGi0/0/0.301

nointGi0/0/0.302

intrangegi0/0/0-2

channel-group1modeactive

interfacePort-channel1.300

encapsulationdot1Q300

vrfforwardingManagement

ipaddress10.16.19.35255.255.255.248

Выводбудеттаким:

Итераторenumerate

131

Page 132: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythoneem.pyr1_config.txt

action0001clicommand"en"

action0002clicommand"conft"

action0003clicommand"nointGi0/0/0.300"

action0004clicommand"nointGi0/0/0.301"

action0005clicommand"nointGi0/0/0.302"

action0006clicommand"intrangegi0/0/0-2"

action0007clicommand"channel-group1modeactive"

action0008clicommand"interfacePort-channel1.300"

action0009clicommand"encapsulationdot1Q300"

action0010clicommand"vrfforwardingManagement"

action0011clicommand"ipaddress10.16.19.35255.255.255.248"

Упростим,иуберемсчитываниефайла,чтобыбылопрощепонять.

Теперькомандыхранятсявсписке:

In[1]:list1=['en\n',

...:'conft\n',

...:'nointGi0/0/0.300\n',

...:'nointGi0/0/0.301\n',

...:'nointGi0/0/0.302\n',

...:'intrangegi0/0/0-2\n',

...:'channel-group1modeactive\n',

...:'interfacePort-channel1.300\n',

...:'encapsulationdot1Q300\n',

...:'vrfforwardingManagement\n',

...:'ipaddress10.16.19.35255.255.255.248\n']

Повторяемциклизфайла:

In[2]:for(i,command)inenumerate(list1,1):

...:print'action%04dclicommand"%s"'%(i,command.rstrip())

...:

action0001clicommand"en"

action0002clicommand"conft"

action0003clicommand"nointGi0/0/0.300"

action0004clicommand"nointGi0/0/0.301"

action0005clicommand"nointGi0/0/0.302"

action0006clicommand"intrangegi0/0/0-2"

action0007clicommand"channel-group1modeactive"

action0008clicommand"interfacePort-channel1.300"

action0009clicommand"encapsulationdot1Q300"

action0010clicommand"vrfforwardingManagement"

action0011clicommand"ipaddress10.16.19.35255.255.255.248"

Итераторenumerate

132

Page 133: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Итераторenumerate

133

Page 134: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

whileЦиклwhileэтоещеоднаразновидностьциклавPython.

Вциклеwhile,какиввыраженииif,надописатьусловие.Еслиусловиеистинно,выполняютсядействиявнутриблокаwhile.Но,вотличииотif,послевыполненияwhileвозвращаетсявначалоцикла.

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

Рассмотримпростойпример:

In[1]:a=5

In[2]:whilea>0:

...:printa

...:a-=1#Этазаписьравнозначнаa=a-1

...:

5

4

3

2

1

Сначаласоздаетсяпеременнаяа,созначением5.

Затем,вциклеwhileуказаноусловиеa>0.Тоесть,показначениеабольше0,будутвыполнятьсядействиявтелецикла.Вданномслучае,будетвыводитьсязначениепеременнойа.

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

Записьa-=1можетбытьнемногонеобычной.Pythonпозволяетиспользоватьтакойформат,вместоa=a-1.

Аналогичнымобразомможнописать:a+=1,a*=2,a/=2.

Таккакзначениеауменьшается,циклнебудетбесконечнымивкакой-томоментвыражениеa>0станетложным.

Следующийпримерпостроеннаосновепримерапропарольизразделаоконструкцииif.Втомпримере,приходилосьзановозапускатьскрипт,еслипарольнесоответствовалтребованиям.

while

134

Page 135: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Спомощьюциклаwhile,можносделатьтак,чтоскриптсамбудетзапрашиватьпарользаново,еслионнесоответствуеттребованиям.

Файлcheck_password_with_while.py:

#-*-coding:utf-8-*-

username=raw_input('Введитеимяпользователя:')

password=raw_input('Введитепароль:')

pass_OK=False

whilenotpass_OK:

iflen(password)<8:

print'Парольслишкомкороткий\n'

password=raw_input('Введитепарольещераз:')

elifusernameinpassword:

print'Парольсодержитимяпользователя\n'

password=raw_input('Введитепарольещераз:')

else:

print'Парольдляпользователя%sустановлен'%username

pass_OK=True

Вэтомслучаециклwhileполезен,таккаконвозвращаетскриптсновавначалопроверок,позволяетснованабратьпароль,ноприэтомнетребуетперезапускасамогоскрипта.

Теперьскриптотрабатываеттак:

$pythoncheck_password_with_while.py

Введитеимяпользователя:nata

Введитепароль:nata

Парольслишкомкороткий

Введитепарольещераз:natanata

Парольсодержитимяпользователя

Введитепарольещераз:123345345345

Парольдляпользователяnataустановлен

while

135

Page 136: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

break,continue,passВPythonестьнесколькооператоров,которыепозволяютменятьповедениецикловпоумолчанию.

Операторbreak

Операторbreakпозволяетдосрочнопрерватьцикл:

breakпрерываеттекущийциклипродолжаетвыполнениеследующихвыраженийеслииспользуетсянескольковложенныхциклов,breakпрерываетвнутреннийциклипродолжаетвыполнятьвыраженияследующиезаблокомbreakможетиспользоватьсявциклахforиwhile

Примерсцикломfor:

In[1]:fornuminrange(10):

...:ifnum<7:

...:printnum

...:else:

...:break

...:

0

1

2

3

4

5

6

Примерсцикломwhile:

In[2]:i=0

In[3]:whilei<10:

...:ifi==5:

...:break

...:else:

...:printi

...:i+=1

...:

0

1

2

3

4

break,continue,pass

136

Page 137: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Ещёпример:

#-*-coding:utf-8-*-

username=raw_input('Введитеимяпользователя:')

password=raw_input('Введитепароль:')

whileTrue:

iflen(password)<8:

print'Парольслишкомкороткий\n'

password=raw_input('Введитепарольещераз:')

elifusernameinpassword:

print'Парольсодержитимяпользователя\n'

password=raw_input('Введитепарольещераз:')

else:

print'Парольдляпользователя%sустановлен'%username

break

Операторcontinue

Операторcontinueвозвращаетуправлениевначалоцикла.Тоесть,continueпозволяет"перепрыгнуть"оставшиесявыражениявциклеиперейтикследующейитерации.

Примерсцикломfor:

In[4]:fornuminrange(5):

...:ifnum==3:

...:continue

...:else:

...:printnum

...:

0

1

2

4

Примерсцикломwhile:

break,continue,pass

137

Page 138: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[5]:i=0

In[6]:whilei<6:

....:i+=1

....:ifi==3:

....:print"Пропускаем3"

....:continue

....:print"Этониктонеувидит"

....:else:

....:print"Текущеезначение:",i

....:

Текущеезначение:1

Текущеезначение:2

Пропускаем3

Текущеезначение:4

Текущеезначение:5

Текущеезначение:6

Операторpass

Операторpassничегонеделает.Фактическиэтотакаязаглушкадляобъектов.

Например,passможетпомочьвситуации,когданужнопрописатьструктурускрипта.Егоможноставитьвциклах,функциях,классах.Иэтонебудетвлиятьнаисполнениекода.

Примериспользованияpass:

In[6]:fornuminrange(5):

....:ifnum<3:

....:pass

....:else:

....:printnum

....:

3

4

break,continue,pass

138

Page 139: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

for/else,while/elseВциклахforиwhileопциональноможетиспользоватьсяблокelse.

for/else

Вциклеfor:

блокelseвыполняетсявтомслучае,еслициклзавершилитерациюсписканоelseневыполняется,есливциклебылвыполненbreak

Примерциклаforсelse(блокelseвыполняетсяпослезавершенияциклаfor):

In[1]:fornuminrange(5):

....:printnum

....:else:

....:print"Числазакончились"

....:

0

1

2

3

4

Числазакончились

Примерциклаforсelseиbreakвцикле(из-заbreak,блокelseневыполняется):

In[2]:fornuminrange(5):

....:ifnum==3:

....:break

....:else:

....:printnum

....:else:

....:print"Числазакончились"

....:

0

1

2

Примерциклаforсelseиcontinueвцикле(continueневлияетнаблокelse):

for/else,while/else

139

Page 140: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[3]:fornuminrange(5):

....:ifnum==3:

....:continue

....:else:

....:printnum

....:else:

....:print"Числазакончились"

....:

0

1

2

4

Числазакончились

while/else

Вциклеwhile:

блокelseвыполняетсявтомслучае,еслициклзавершилитерациюсписканоelseневыполняется,есливциклебылвыполненbreak

Примерциклаwhileсelse(блокelseвыполняетсяпослезавершенияциклаwhile):

In[4]:i=0

In[5]:whilei<5:

....:printi

....:i+=1

....:else:

....:print"Конец"

....:

0

1

2

3

4

Конец

Примерциклаwhileсelseиbreakвцикле(из-заbreak,блокelseневыполняется):

for/else,while/else

140

Page 141: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[6]:i=0

In[7]:whilei<5:

....:ifi==3:

....:break

....:else:

....:printi

....:i+=1

....:else:

....:print"Конец"

....:

0

1

2

for/else,while/else

141

Page 142: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Работасисключениямиtry/except/else/finally

try/except

Есливыповторялипримеры,которыеиспользовалисьранее,тонавернякабылиситуации,когдавыскакивалаошибка.Скореевсего,этобылаошибкасинтаксиса,когданехватало,например,двоеточия.

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

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

Примерыисключений:

In[1]:2/0

-----------------------------------------------------

ZeroDivisionError:integerdivisionormodulobyzero

In[2]:'test'+2

-----------------------------------------------------

TypeError:cannotconcatenate'str'and'int'objects

Вданномслучае,возниклодваисключения:ZeroDivisionErrorиTypeError.

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

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

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

Когдавпрограммевозникаетисключение,онасразузавершаетработу.

Дляработысисключениямииспользуетсяконструкцияtry/except:

Работасисключениямиtry/except/else/finally

142

Page 143: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[3]:try:

...:2/0

...:exceptZeroDivisionError:

...:print"Youcan'tdividebyzero"

...:

Youcan'tdividebyzero

Конструкцияtryработаеттакимобразом:

сначалавыполняютсявыражения,которыезаписанывблокеtryеслипривыполненияблокаtry,невозниклоникакихисключений,блокexceptпропускается.Ивыполняетсядальнейшийкодесливовремявыполненияблокаtry,вкаком-томесте,возниклоисключение,оставшаясячастьблокаtryпропускается

есливблокеexceptуказаноисключение,котороевозникло,выполняетсякодвблокеexceptеслиисключение,котороевозникло,неуказановблокеexcept,выполнениепрограммыпрерываетсяивыдаетсяошибка

Обратитевнимание,чтострока'Cool!'вблокеtryневыводится:

In[4]:try:

...:print"Let'sdividesomenumbers"

...:2/0

...:print'Cool!'

...:exceptZeroDivisionError:

...:print"Youcan'tdividebyzero"

...:

Let'sdividesomenumbers

Youcan'tdividebyzero

Вконструкцииtry/exceptможетбытьмногоexcept,еслинужныразныедействия,взависимостиотошибки.

Например,скриптdivide.pyделитдвачиславведенныхпользователем:

#-*-coding:utf-8-*-

try:

a=raw_input("Введитепервоечисло:")

b=raw_input("Введитевтороечисло:")

print"Результат:",int(a)/int(b)

exceptValueError:

print"Пожалуйста,вводитетолькочисла"

exceptZeroDivisionError:

print"Нанольделитьнельзя"

Работасисключениямиtry/except/else/finally

143

Page 144: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Примерывыполненияскрипта:

$pythondivide.py

Введитепервоечисло:3

Введитевтороечисло:1

Результат:3

$pythondivide.py

Введитепервоечисло:5

Введитевтороечисло:0

Результат:Нанольделитьнельзя

$pythondivide.py

Введитепервоечисло:qewr

Введитевтороечисло:3

Результат:Пожалуйста,вводитетолькочисла

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

ИсключениеZeroDivisionErrorвозникаетвслучае,есливтороечислобылоравным0.

ЕслинетнеобходимостивыводитьразличныесообщениянаошибкиValueErrorиZeroDivisionError,можносделатьтак(файлdivide_ver2.py):

#-*-coding:utf-8-*-

try:

a=raw_input("Введитепервоечисло:")

b=raw_input("Введитевтороечисло:")

print"Результат:",int(a)/int(b)

except(ValueError,ZeroDivisionError):

print"Что-топошлонетак..."

Проверка:

$pythondivide_ver2.py

Введитепервоечисло:wer

Введитевтороечисло:4

Результат:Что-топошлонетак...

$pythondivide_ver2.py

Введитепервоечисло:5

Введитевтороечисло:0

Результат:Что-топошлонетак...

Работасисключениямиtry/except/else/finally

144

Page 145: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Этоделатьнерекомендуется!

try/except/else

Вконструкцииtry/exceptестьопциональныйблокelse.Онвыполняетсявтомслучае,еслинебылоисключения.

Например,еслинеобходимовыполнятьвдальнейшемкакие-тооперациисданными,которыеввелпользователь,можнозаписатьихвблокеelse(файлdivide_ver3.py):

#-*-coding:utf-8-*-

try:

a=raw_input("Введитепервоечисло:")

b=raw_input("Введитевтороечисло:")

result=int(a)/int(b)

except(ValueError,ZeroDivisionError):

print"Что-топошлонетак..."

else:

print"Результатвквадрате:",result**2

Примервыполнения:

$pythondivide_ver3.py

Введитепервоечисло:10

Введитевтороечисло:2

Результатвквадрате:25

$pythondivide_ver3.py

Введитепервоечисло:werq

Введитевтороечисло:3

Что-топошлонетак...

try/except/finally

Блокfinallyэтоещеодинопциональныйблоквконструкцииtry.Онвыполняетсявсегда,независимооттого,былолиисключениеилинет.

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

Файлdivide_ver4.pyсблокомfinally:

Работасисключениямиtry/except/else/finally

145

Page 146: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

#-*-coding:utf-8-*-

try:

a=raw_input("Введитепервоечисло:")

b=raw_input("Введитевтороечисло:")

result=int(a)/int(b)

except(ValueError,ZeroDivisionError):

print"Что-топошлонетак..."

else:

print"Результатвквадрате:",result**2

finally:

print"Вотисказочкеконец,актослушал-молодец."

Проверка:

$pythondivide_ver4.py

Введитепервоечисло:10

Введитевтороечисло:2

Результатвквадрате:25

Вотисказочкеконец,актослушал-молодец.

$pythondivide_ver4.py

Введитепервоечисло:qwerewr

Введитевтороечисло:3

Что-топошлонетак...

Вотисказочкеконец,актослушал-молодец.

$pythondivide_ver4.py

Введитепервоечисло:4

Введитевтороечисло:0

Что-топошлонетак...

Вотисказочкеконец,актослушал-молодец.

Работасисключениямиtry/except/else/finally

146

Page 147: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание5.1

1. ЗапроситьупользователявводIP-адресавдесятично-точечномформате.2. ОпределитькакомуклассупринадлежитIP-адрес.3. Взависимостиотклассаадреса,вывестинастандартныйпотоквывода:

'unicast'-еслиIP-адреспринадлежитклассуA,BилиC'multicast'-еслиIP-адреспринадлежитклассуD'localbroadcast'-еслиIP-адресравен255.255.255.255'unassigned'-еслиIP-адресравен0.0.0.0'unused'-вовсехостальныхслучаях

Подсказкапоклассам(диапазонзначенийпервогобайтавдесятичномформате):

A:1-127B:128-191C:192-223D:224-239

Задание5.1a

Сделатькопиюскриптазадания5.1.

Задания

147

Page 148: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Дополнитьскрипт:

ДобавитьпроверкувведенногоIP-адреса.Адрессчитаетсякорректнозаданным,еслион:

состоитиз4чиселразделенныхточкой,каждоечисловдиапазонеот0до255.

Еслиадресзаданнеправильно,выводитьсообщение:

'IncorrectIPv4address'

Задание5.1b

Сделатькопиюскриптазадания5.1a.

Дополнитьскрипт:

Еслиадресбылвведеннеправильно,запроситьадресснова.

Задание5.2

СписокmacсодержитMAC-адресавформатеXXXX:XXXX:XXXX.

Однако,воборудованииCiscoMAC-адресаиспользуютсявформатеXXXX.XXXX.XXXX.

Создатьскрипт,которыйпреобразуетMAC-адресавформатciscoидобавляетихвновыйсписокmac_cisco.

Усложненныйвариант:сделатьпреобразованиеводнойстрокескрипта.

mac=['aabb:cc80:7000','aabb:dd80:7340','aabb:ee80:7000','aabb:ff80:7000']

mac_cisco=[]

Задание5.3

Вскриптесделангенераторконфигурациидляaccess-портов.

Сделатьаналогичныйгенераторконфигурациидляпортовtrunk.

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

Поэтомувсоответствиикаждомупортустоитсписокипервый(нулевой)элементспискауказываеткаквосприниматьномераVLAN,которыеидутдальше:

Задания

148

Page 149: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

add-значитVLANынадобудетдобавить(командаswitchporttrunkallowedvlanadd10,20)del-значитVLANынадоудалитьизспискаразрешенных(командаswitchporttrunkallowedvlanremove17)only-значит,чтонаинтерфейседолжныостатьсяразрешеннымитолькоуказанныеVLANы(командаswitchporttrunkallowedvlan11,30)

Задачадляпортов0/1,0/2,0/4:

сгенерироватьконфигурациюнаосновешаблонаtrunk_templateсучетомключевыхсловadd,del,only

access_template=['switchportmodeaccess',

'switchportaccessvlan',

'spanning-treeportfast',

'spanning-treebpduguardenable']

trunk_template=['switchporttrunkencapsulationdot1q',

'switchportmodetrunk',

'switchporttrunkallowedvlan']

fast_int={'access':{'0/12':'10','0/14':'11','0/16':'17','0/17':'150'},

'trunk':{'0/1':['add','10','20'],

'0/2':['only','11','30'],

'0/4':['del','17']}}

forintinfast_int['access']:

print'interfaceFastEthernet'+int

forcommandinaccess_template:

ifcommand.endswith('accessvlan'):

print'%s%s'%(command,fast_int['access'][int])

else:

print'%s'%command

Задания

149

Page 150: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Приработессетевымоборудованием(инетолько),файламимогутбыть:

конфигурации(простые,неструктурированныетекстовыефайлы)работаснимирассматриваетсявэтомразделе

шаблоныконфигурацийкакправило,этокакой-тоспециальныйформатфайлов.вразделеШаблоныконфигурацийсJinjaрассматриваетсяиспользованиеJinja2длясозданияшаблоновконфигураций

файлыспараметрамиподключенийкакправило,этоструктурированныефайлы,вкаком-тоопределенномформате:YAML,JSON,CSVвразделеСериализацияданныхрассматриваетсякакработатьстакимифайлами

другиескриптыPythonвразделеМодулирассматриваетсякакработатьсмодулями(другимискриптамиPython)

Вэтомразделерассматриваетсяработаспростымитекстовымифайлами.Например,конфигурационныйфайлCisco.

Вработесфайламиестьнесколькоаспектов:

открытие/закрытиечтениезапись

Вэтомразделерассматриваетсятольконеобходимыйминимумдляработысфайлами.Подробнее,вдокументацииPython.

6.Работасфайлами

150

Page 151: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ОткрытиефайловДляначалаработысфайлом,егонадооткрыть.

open()

Дляоткрытияфайлов,чащевсего,используетсяфункцияopen():

file=open('file_name.txt','r')

Вфункцииopen():

'file_name.txt'-имяфайлатутможноуказыватьнетолькоимя,ноипуть(абсолютныйилиотносительный)

'r'-режимоткрытияфайла

Функцияopen()создаетобъектfile,ккоторомупотомможноприменятьразличныеметоды,дляработысним.

Режимыоткрытияфайлов:

r-открытьфайлтолькодлячтения(значениепоумолчанию)r+-открытьфайлдлячтенияизаписиw-открытьфайлдлязаписи

еслифайлсуществует,тоегосодержимоеудаляетсяеслифайлнесуществует,тосоздаетсяновый

w+-открытьфайлдлячтенияизаписиеслифайлсуществует,тоегосодержимоеудаляетсяеслифайлнесуществует,тосоздаетсяновый

a-открытьфайлдлядополнениязаписи.Данныедобавляютсявконецфайлаa+-открытьфайлдлячтенияизаписи.Данныедобавляютсявконецфайла

Обычно,возникаетпутаницасрежимамиw+иr+.Разницамеждунимивтом,чтоw+,приоткрытии,удаляетсодержимоефайла,аr+-нет.

Открытиефайлов

151

Page 152: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЧтениефайловВPythonестьнесколькометодовчтенияфайла:

read()-считываетсодержимоефайлавстрокуreadline()-считываетфайлпострочноreadlines()-считываетстрокифайлаисоздаетсписокизстрок

Посмотримкаксчитыватьсодержимоефайлов,напримерефайлаr1.txt:

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

read()

Методread()-считываетвесьфайлводнустроку.

Примериспользованияметодаread():

In[1]:f=open('r1.txt')

In[2]:f.read()

Out[2]:'!\nservicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear\nservi

cetimestampslogdatetimemseclocaltimeshow-timezoneyear\nservicepassword-encrypt

ion\nservicesequence-numbers\n!\nnoipdomainlookup\n!\nipsshversion2\n!\n'

In[3]:f.read()

Out[3]:''

Приповторномчтениифайлав3строке,отображаетсяпустаястрока.Такпроисходитиз-затого,чтопривызовеметодаread(),считываетсявесьфайл.Ипослетого,какфайлбылсчитан,курсоростаетсявконцефайла.Управлятьположениемкурсораможноспомощьюметодаseek().

readline()

Чтениефайлов

152

Page 153: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Построчнофайлможносчитатьспомощьюметодаreadline():

In[4]:f=open('r1.txt')

In[5]:f.readline()

Out[5]:'!\n'

In[6]:f.readline()

Out[6]:'servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear\n'

Но,чащевсего,прощепройтисьпообъектуfileвцикле,неиспользуяметодыread...:

In[7]:f=open('r1.txt')

In[8]:forlineinf:

...:printline

...:

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

readlines()

Ещеодинполезныйметод-readlines().Онсчитываетстрокифайлавсписок:

Чтениефайлов

153

Page 154: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[9]:f=open('r1.txt')

In[10]:f.readlines()

Out[10]:

['!\n',

'servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear\n',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear\n',

'servicepassword-encryption\n',

'servicesequence-numbers\n',

'!\n',

'noipdomainlookup\n',

'!\n',

'ipsshversion2\n',

'!\n']

Еслинужнополучитьстрокифайла,нобезпереводастрокивконце,можновоспользоватьсяметодомsplitикакразделитель,указатьсимвол\n:

In[11]:f=open('r1.txt')

In[12]:f.read().split('\n')

Out[12]:

['!',

'servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

'servicepassword-encryption',

'servicesequence-numbers',

'!',

'noipdomainlookup',

'!',

'ipsshversion2',

'!',

'']

Обратитевнимание,чтопоследнийэлементсписка-пустаястрока.

Еслипередвыполнениемsplit(),воспользоватьсяметодомrstrip(),списокбудетбезпустойстрокивконце:

Чтениефайлов

154

Page 155: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[13]:f=open('r1.txt')

In[14]:f.read().rstrip().split('\n')

Out[14]:

['!',

'servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

'servicepassword-encryption',

'servicesequence-numbers',

'!',

'noipdomainlookup',

'!',

'ipsshversion2',

'!']

seek()

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

Чтобыещёразсчитатьинформациюизфайла,нужновоспользоватьсяметодомseek,которыйперемещаеткурсорвнеобходимоеположение.

Примероткрытияфайлаисчитываниясодержимого:

In[15]:f=open('r1.txt')

In[16]:printf.read()

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

Есливызыватьещёразметодread,возвращаетсяпустаястрока:

In[17]:printf.read()

Но,спомощьюметодаseek,можноперейтивначалофайла(0означаетначалофайла):

Чтениефайлов

155

Page 156: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[18]:f.seek(0)

Послетого,как,спомощьюseek,курсорбылпереведенвначалофайла,можноопятьсчитыватьсодержимое:

In[19]:printf.read()

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

Чтениефайлов

156

Page 157: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаписьфайловПризаписи,оченьважноопределитьсясрежимомоткрытияфайла,чтобыслучайноегонеудалить:

append-добавитьстрокивсуществующийфайлwrite-перезаписатьфайлобарежимасоздаютфайл,еслионнесуществует

Длязаписивфайлиспользуютсятакиеметоды:

write()-записатьвфайлоднустрокуwritelines()-позволяетпередаватьвкачествеаргументасписокстрок

write()

Методwriteожидаетстроку,длязаписи.

Дляпримера,возьмемсписокстроксконфигурацией:

In[1]:cfg_lines=['!',

...:'servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

...:'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

...:'servicepassword-encryption',

...:'servicesequence-numbers',

...:'!',

...:'noipdomainlookup',

...:'!',

...:'ipsshversion2',

...:'!']

Открытиефайлаr2.txtврежимедлязаписи:

In[2]:f=open('r2.txt','w')

Преобразуемсписоккомандводнубольшуюстрокуспомощьюjoin:

In[3]:cfg_lines_as_string='\n'.join(cfg_lines)

In[4]:cfg_lines_as_string

Out[4]:'!\nservicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear\nservi

cetimestampslogdatetimemseclocaltimeshow-timezoneyear\nservicepassword-encrypt

ion\nservicesequence-numbers\n!\nnoipdomainlookup\n!\nipsshversion2\n!'

Записьфайлов

157

Page 158: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Записьстрокивфайл:

In[5]:f.write(cfg_lines_as_string)

Аналогичноможнодобавитьстрокувручную:

In[6]:f.write('\nhostnamer2')

Послезавершенияработысфайлом,егонеобходимозакрыть:

In[7]:f.close()

Таккакipythonподдерживаеткомандуcat,можнолегкопосмотретьсодержимоефайла:

In[8]:catr2.txt

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

hostnamer2

writelines()

Методwritelines()ожидаетсписокстрок,какаргумент.

Записьспискастрокcfg_linesвфайл:

Записьфайлов

158

Page 159: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[1]:cfg_lines=['!',

...:'servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

...:'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

...:'servicepassword-encryption',

...:'servicesequence-numbers',

...:'!',

...:'noipdomainlookup',

...:'!',

...:'ipsshversion2',

...:'!']

In[9]:f=open('r2.txt','w')

In[10]:f.writelines(cfg_lines)

In[11]:f.close()

In[12]:catr2.txt

!servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyearservicetimestamps

logdatetimemseclocaltimeshow-timezoneyearservicepassword-encryptionservicesequ

ence-numbers!noipdomainlookup!ipsshversion2!

Врезультате,всестрокиизсписка,записалисьводнустрокуфайла,таккаквконцестрокнебылосимвола\n.

Добавитьпереводстрокиможнопо-разному.Например,можнопростообработатьсписоквцикле:

In[13]:cfg_lines2=[]

In[14]:forlineincfg_lines:

....:cfg_lines2.append(line+'\n')

....:

In[15]:cfg_lines2

Out[15]:

['!\n',

'servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear\n',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear\n',

'servicepassword-encryption\n',

'servicesequence-numbers\n',

'!\n',

'noipdomainlookup\n',

'!\n',

'ipsshversion2\n',

Илииспользоватьlistcomprehensions:

Записьфайлов

159

Page 160: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[16]:cfg_lines3=[line+'\n'forlineincfg_lines]

In[17]:cfg_lines3

Out[17]:

['!\n',

'servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear\n',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear\n',

'servicepassword-encryption\n',

'servicesequence-numbers\n',

'!\n',

'noipdomainlookup\n',

'!\n',

'ipsshversion2\n',

'!\n']

Еслилюбой,изполучившихсясписковзаписатьзанововфайл,товнемужебудутпереводыстрок:

In[18]:f=open('r2.txt','w')

In[19]:f.writelines(cfg_lines3)

In[20]:f.close()

In[21]:catr2.txt

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

Записьфайлов

160

Page 161: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗакрытиефайловВреальнойжизни,длязакрытияфайлов,чащевсего,используетсяконструкцияwith.Еёнамногоудобнейиспользовать,чемзакрыватьфайлявно.Но,таккаквжизниможновстретитьиметодclose,вэтомразделерассматриваетсякакегоиспользовать.

Послезавершенияработысфайлом,егонужнозакрыть.Внекоторыхслучаях,Pythonможетсамостоятельнозакрытьфайл.Нолучшенаэтонерассчитыватьизакрыватьфайлявно.

close()

Методcloseвстречалсявразделезаписьфайлов.Тамонбылнужендлятого,чтобысодержимоефайлабылозаписанонадиск.

Дляэтого,вPythonестьотдельныйметодflush().Но,таккак,впримересзаписьюфайлов,ненужнобылобольшевыполнятьникакихопераций,файлможнобылозакрыть.

Откроемфайлr1.txt:

In[1]:f=open('r1.txt','r')

Теперьможносчитатьсодержимое:

In[2]:printf.read()

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

Уобъектаfileестьспециальныйатрибутclosed,которыйпозволяетпроверитьзакрытфайлилинет.Еслифайлоткрыт,онвозвращаетFalse:

Закрытиефайлов

161

Page 162: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[3]:f.closed

Out[3]:False

Теперьзакрываемфайлисновапроверяемclosed:

In[4]:f.close()

In[5]:f.closed

Out[5]:True

Еслипопробоватьпрочитатьфайл,возникнетисключение:

In[6]:printf.read()

------------------------------------------------------------------

ValueErrorTraceback(mostrecentcalllast)

<ipython-input-53-2c962247edc5>in<module>()

---->1printf.read()

ValueError:I/Ooperationonclosedfile

Использованиеtry/finallyдляработысфайлами

Спомощьюобработкиисключений,можно:

перехватыватьисключения,которыевозникают,припопыткепрочитатьнесуществующийфайлзакрыватьфайл,послевсехопераций,вблокеfinally

Еслипопытатьсяоткрытьдлячтенияфайл,которогонесуществует,возникнеттакоеисключение:

In[7]:f=open('r3.txt','r')

---------------------------------------------------------------------------

IOErrorTraceback(mostrecentcalllast)

<ipython-input-54-1a33581ca641>in<module>()

---->1f=open('r3.txt','r')

IOError:[Errno2]Nosuchfileordirectory:'r3.txt'

Спомощьюконструкцииtry/except,можноперехватитьэтоисключениеивывестисвоёсообщение:

Закрытиефайлов

162

Page 163: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[8]:try:

....:f=open('r3.txt','r')

....:exceptIOError:

....:print'Nosuchfile'

....:

Nosuchfile

Аспомощьючастиfinally,можнозакрытьфайл,послевсехопераций:

In[9]:try:

....:f=open('r1.txt','r')

....:printf.read()

....:exceptIOError:

....:print'Nosuchfile'

....:finally:

....:f.close()

....:

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

In[10]:f.closed

Out[10]:True

Закрытиефайлов

163

Page 164: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

КонструкцияwithКонструкцияwithназываетсяменеджерконтекста.

ВPythonсуществуетболееудобныйспособработысфайлами,чемте,которыеиспользовалисьдосихпор-конструкцияwith:

In[1]:withopen('r1.txt','r')asf:

....:forlineinf:

....:printline

....:

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

Крометого,конструкцияwithгарантируетзакрытиефайлаавтоматически.

Обратитевниманиенато,каксчитываютсястрокифайла:

forlineinf:

printline

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

Впредыдущемвыводе,междустрокамифайлабылилишниепустыестроки,таккакprintдобавляетещёодинпереводстроки.

Чтобыизбавитьсяотэтого,можнопоставитьзапятуювконцевыраженияprintиливызватьметодrstrip:

Конструкцияwith

164

Page 165: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[2]:withopen('r1.txt','r')asf:

....:forlineinf:

....:printline.rstrip()

....:

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

In[3]:f.closed

Out[3]:True

И,конечноже,сконструкциейwithможноиспользоватьнетолькотакойпострочныйвариантсчитывания,всеметоды,которыерассматривалисьдоэтого,такжеработают:

In[4]:withopen('r1.txt','r')asf:

....:printf.read()

....:

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

Конструкцияwithможетиспользоватьсянетолькосфайлами.

Подробнееобэтомможнопочитатьпоссылке:http://stackoverflow.com/questions/3012488/what-is-the-python-with-statement-designed-for

Конструкцияwith

165

Page 166: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание6.1

Аналогичнозаданию3.1обработатьстрокиизфайлаospf.txtивывестиинформациюпокаждойвтакомвиде:

Protocol:OSPF

Prefix:10.0.24.0/24

AD/Metric:110/41

Next-Hop:10.0.13.3

Lastupdate:3d18h

OutboundInterface:FastEthernet0/0

Таккакэтопервоезаданиесоткрытиемфайла,заготовкадляоткрытияфайлаужесделана.

withopen('ospf.txt','r')asf:

forlineinf:

printline

Задание6.2

Создатьскрипт,которыйбудетобрабатыватьконфигурационныйфайлconfig_sw1.txt:

Задания

166

Page 167: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

имяфайлапередаетсякакаргументскрипту

Скриптдолженвозвращатьнастандартныйпотоквыводакомандыизпереданногоконфигурационногофайла,исключаястроки,которыеначинаютсяс'!'.

Междустрокаминедолжнобытьдополнительногосимволапереводастроки.

Задание6.2a

Сделатькопиюскриптазадания6.2.

Дополнитьскрипт:

Скриптнедолженвыводитькоманды,вкоторыхсодержатсяслова,которыеуказанывспискеignore.

ignore=['duplex','alias','Currentconfiguration']

Задание6.2b

Дополнитьскриптиззадания6.2a:

вместовыводанастандартныйпотоквывода,скриптдолжензаписатьполученныестрокивфайлconfig_sw1_cleared.txt

Приэтом,должныбытьотфильтрованыстроки,которыесодержатсявспискеignore.

Строки,которыеначинаютсяна'!'отфильтровыватьненужно.

ignore=['duplex','alias','Currentconfiguration']

Задание6.2c

Переделатьскриптиззадания6.2b:

передаватькакаргументы:имяисходногофайлаконфигурацииимяитоговогофайлаконфигурации

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

Проверитьработускриптанапримерефайлаconfig_sw1.txt.

Задания

167

Page 168: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ignore=['duplex','alias','Currentconfiguration']

Задание6.3

СкриптдолженобрабатыватьзаписивфайлеCAM_table.txtтакимобразомчтобы:

считывалисьтолькостроки,вкоторыхуказаныMAC-адресакаждаястрока,гдеестьMAC-адрес,должнаобрабатыватьсятакимобразом,чтобынастандартныйпотоквыводабылавыведенатаблицавида:

100aabb.cc80.7000Gi0/1

200aabb.cc80.7000Gi0/2

300aabb.cc80.7000Gi0/3

100aabb.cc80.7000Gi0/4

500aabb.cc80.7000Gi0/5

200aabb.cc80.7000Gi0/6

300aabb.cc80.7000Gi0/7

Задание6.3a

Сделатькопиюскриптазадания6.3

Дополнитьскрипт:

ОтсортироватьвыводпономеруVLAN

Задание6.3b

Сделатькопиюскриптазадания6.3a

Дополнитьскрипт:

ЗапроситьупользователявводномераVLAN.ВыводитьинформациютолькопоуказанномуVLAN.

Задания

168

Page 169: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ФункцииФункция-этоблоккода,выполняющийопределенныедействия:

уфункцииестьимя,спомощьюкоторогоможнозапускатьэтотблоккодасколькоугоднораз

запусккодафункции,называетсявызовомфункцииприсозданиифункции,какправило,определяютсяпараметрыфункции.

параметрыфункцииопределяюткакиеаргументыфункцияможетприниматьфункциямможнопередаватьаргументы

соответственно,кодфункциибудетвыполнятьсясучетомуказанныхаргументов

Зачемнужныфункции?

Какправило,задачи,которыерешаеткод,оченьпохожиичастоимеютчто-тообщее.

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

открытиефайлаудаление(илипропуск)строк,которыеначинаютсяназнаквосклицания(дляCisco)удаление(илипропуск)пустыхстрокудалениесимволовпереводастрокивконцестрокпреобразованиеполученногорезультатавсписок

Дальшедействиямогутотличаться,взависимостиоттого,чтонужноделать.

Частополучается,чтоестькусоккода,которыйповторяется.Конечно,егоможнокопироватьизодногоскриптавдругой.Ноэтооченьнеудобно,таккак,привнесенииизмененийвкод,нужнобудетобновитьегововсехфайлах,вкоторыеонскопирован.

Гораздопрощеиправильнейвынестиэтоткодвфункцию(этоможетбытьинесколькофункций).

Итогда,вэтомфайле,иликаком-тодругом,этафункцияпростобудетиспользоваться.

Вэтомразделерассматриваесяситуациякогдафункциянаходитсявтомжефайле.

АвразделеМодулибудетрассматриватьсякакповторноиспользоватьобъекты,которыенаходятсявдругихскриптах.

7.Функции

169

Page 170: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

7.Функции

170

Page 171: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

СозданиефункцийСозданиефункции:

функциисоздаютсяспомощьюзарезервированногословаdefзаdefследуютимяфункцииикруглыескобкивнутрискобокмогутуказыватьсяпараметры,которыефункцияпринимаетпослекруглыхскобокидетдвоеточиеисновойстроки,сотступом,идетблоккода,которыйвыполняетфункцияпервойстрокой,опционально,можетбытькомментарий,такназываемаяdocstringвфункцияхможетиспользоватьсяоператорreturn

ониспользуетсядляпрекращенияработыфункцииивыходаизнеечащевсего,операторreturnвозвращаеткакое-тозначение

Кодфункций,которыеиспользуютсявэтомразделе,можноскопироватьизфайлаcreate_func.py

Примерфункции:

In[1]:defopen_file(filename):

...:"""Documentationstring"""

...:withopen(filename)asf:

...:printf.read()

...:

Когдафункциясоздана,онаещёничегоневыполняет.Толькопривызывефункции,действия,которыевнейперечислены,будутвыполняться.Эточем-топохоженаACLвсетевомоборудовании:присозданииACLвконфигурации,онничегонеделаетдотехпор,поканебудеткуда-топрименен.

Вызовфункции

Привызовефункции,нужноуказатьеёимяипередатьаргументы,еслинужно.

Параметры-этопеременные,которыеиспользуются,присозданиифункции.

Аргументы-этофактическиезначения(данные),которыепередаютсяфункции,привызове.

Этафункцияожидаетимяфайла,вкачествеаргумента,изатемвыводитсодержимоефайла:

Созданиефункций

171

Page 172: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[2]:open_file('r1.txt')

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

In[3]:open_file('ospf.txt')

routerospf1

router-id10.0.0.3

auto-costreference-bandwidth10000

network10.0.1.00.0.0.255area0

network10.0.2.00.0.0.255area2

network10.1.1.00.0.0.255area0

Перваястрокавопределениифункции-этоdocstring,строкадокументации.Этокомментарий,которыйиспользуетсякакописаниефункции.Егоможноотобразитьтак:

In[4]:open_file.__doc__

Out[4]:'Documentationstring'

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

Операторreturn

Операторreturnиспользуетсядляпрекращенияработыфункции,выходаизнее,и,какправило,возвратакакого-тозначения.ФункцияможетвозвращатьлюбойобъектPython.

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

Вданномслучае,еслиприсвоитьвыводфункциипеременнойresult,результатбудеттаким:

Созданиефункций

172

Page 173: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[5]:result=open_file('ospf.txt')

routerospf1

router-id10.0.0.3

auto-costreference-bandwidth10000

network10.0.1.00.0.0.255area0

network10.0.2.00.0.0.255area2

network10.1.1.00.0.0.255area0

In[6]:printresult

None

ПеременнаяresultравнаNone.Такполучилосьиз-затого,чтофункцияничегоневозвращает.Онапростовыводитсообщениенастандартныйпотоквывода.

Длятого,чтобыфункциявозвращалазначение,котороепотомможно,например,присвоитьпеременной,используетсяоператорreturn:

In[7]:defopen_file(filename):

...:"""Documentationstring"""

...:withopen(filename)asf:

...:returnf.read()

...:

In[8]:result=open_file('r1.txt')

In[9]:printresult

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

Теперьвпеременойresultнаходитсясодержимоефайла.

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

Ещёодинважныйаспектработыоператораreturn:выражения,которыеидутпослеreturn,невыполняются.

Тоесть,вфункцииниже,строка"Done"небудетвыводиться,таккаконастоитпослеreturn:

Созданиефункций

173

Page 174: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[10]:defopen_file(filename):

...:print"Readingfile",filename

...:withopen(filename)asf:

...:returnf.read()

...:print"Done"

...:

In[11]:result=open_file('r1.txt')

Readingfiler1.txt

Созданиефункций

174

Page 175: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Пространстваимен.ОбластивидимостиУпеременныхвPythonестьобластьвидимости.Взависимостиотместавкоде,гдепеременнаябылаопределена,определяетсяиобластьвидимости,тоесть,гдепеременнаябудетдоступна.

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

УPythonестьправилоLEGB,которымонпользуетсяприпоискепеременных.

Например,есливнутрифункции,выполняетсяобращениекименипеременной,Pythonищетпеременнуювтакомпорядкепообластямвидимости(допервогосовпадения):

L(local)-влокальной(внутрифункции)E(enclosing)-влокальнойобластиобъемлющихфункций(этотефункции,внутрикоторыхнаходитсянашафункция)G(global)-вглобальной(вскрипте)B(built-in)-ввстроенной(зарезервированныезначенияPython)

Соответственноестьлокальныеиглобальныепеременные:

локальныепеременные:переменные,которыеопределенывнутрифункцииэтипеременныестановятсянедоступнымипослевыходаизфункции

глобальныепеременныепеременные,которыеопределенывнефункцииэтипеременные'глобальны'тольковпределахмодуля

например,чтобыонибылидоступнывдругоммодуле,ихнадоимпортировать

Примерлокальнойиглобальнойпеременнойresult:

Пространстваимен.Областивидимости

175

Page 176: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[1]:result='teststring'

In[2]:defopen_file(filename):

...:withopen(filename)asf:

...:result=f.read()

...:returnresult

...:

In[3]:open_file('r1.txt')

Out[3]:'!\nservicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear\nservi

cetimestampslogdatetimemseclocaltimeshow-timezoneyear\nservicepassword-encrypt

ion\nservicesequence-numbers\n!\nnoipdomainlookup\n!\nipsshversion2\n!\n'

In[4]:result

Out[4]:'teststring'

Обратитевнимание,чтопеременнаяresultпо-прежнемуосталасьравной'teststring'.Несмотрянато,чтовнутрифункцииейприсвоеносодержимоефайла.

Пространстваимен.Областивидимости

176

Page 177: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПараметрыиаргументыфункцийЦельсозданияфункции,какправило,заключаетсявтом,чтобывынестикусоккода,которыйвыполняетопределеннуюзадачу,вотдельныйобъект.Этопозволяетиспользоватьэтоткусоккодамногократно,несоздаваяегозанововпрограмме.

Какправило,функциядолжнавыполнятькакие-тодействиясвходящимизначениямиинавыходевыдаватьрезультат.

Приработесфункциями,важноразличать:

параметры-этопеременные,которыеиспользуются,присозданиифункции.аргументы-этофактическиезначения(данные),которыепередаютсяфункции,привызове.

Кодфункций,которыеиспользуютсявэтомразделе,можноскопироватьизфайлаfunc_params_args.py

Длятогочтобыфункциямоглаприниматьвходящиезначения,еенужносоздатьспараметрами:

In[1]:defdelete_exclamation_from_cfg(in_cfg,out_cfg):

...:withopen(in_cfg)asin_file:

...:result=in_file.readlines()

...:withopen(out_cfg,'w')asout_file:

...:forlineinresult:

...:ifnotline.startswith('!'):

...:out_file.write(line)

...:

Вданномслучае,уфункцииdelete_exclamation_from_cfgдвапараметра:in_cfgиout_cfg.

Функцияоткрываетфайлin_cfg,читаетсодержимоевсписок;затемоткрываетфайлout_cfgизаписываетвнеготолькотестроки,которыененачинаютсяназнаквосклицания.

Вданномслучаефункцияничегоневозвращает.

Файлr1.txtбудетиспользоватьсякакпервыйаргумент(in_cfg):

Параметрыиаргументыфункций

177

Page 178: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[2]:catr1.txt

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

Примериспользованияфункцииdelete_exclamation_from_cfg:

In[3]:delete_exclamation_from_cfg('r1.txt','result.txt')

Файлresult.txtвыглядиттак:

In[4]:catresult.txt

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

noipdomainlookup

ipsshversion2

Притакомопределениифункции,надообязательнопередатьобааргумента.Еслипередатьтолькоодинаргумент,возникнетошибка.Аналогично,возникнетошибка,еслипередатьтриибольшеаргументов:

In[5]:delete_exclamation_from_cfg('r1.txt')

---------------------------------------------------------------------------

TypeErrorTraceback(mostrecentcalllast)

<ipython-input-7-66ae381f1c4f>in<module>()

---->1delete_exclamation_from_cfg('r1.txt')

TypeError:delete_exclamation_from_cfg()takesexactly2arguments(1given)

Параметрыиаргументыфункций

178

Page 179: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Соответственно,функцияможетбытьсозданаспараметрами:

обязательныминеобязательными(опциональными,параметрамисозначениемпоумолчанию)

Кодфункций,которыеиспользуютсявэтомразделе,можноскопироватьизфайлаfunc_params_types.py

Обязательныепараметры

Обязательныепараметры-определяюткакиеаргументынужнопередатьфункцииобязательно.Приэтом,ихнужнопередатьровностолько,сколькоуказанопараметровфункции(нельзяуказатьбольшееилименьшееколичествоаргументов)

Функциясобязательнымипараметрами:

In[1]:defcfg_to_list(cfg_file,delete_exclamation):

....:result=[]

....:withopen(cfg_file)asf:

....:forlineinf:

....:ifdelete_exclamationandline.startswith('!'):

....:pass

....:else:

....:result.append(line.rstrip())

....:returnresult

Функцияcfg_to_listожидаетдвааргумента:cfg_fileиdelete_exclamation.

Внутри,онаоткрываетфайлcfg_fileдлячтения,проходитсяповсемстроками,еслиаргументdelete_exclamationистинаистроканачинаетсясвосклицательногознака,строкапропускается.Операторpassозначает,чтоничегоневыполняется.

Вовсехостальныхслучаях,встрокесправаудаляютсясимволыпереводастрокиистрокадобавляетсявсловарьresult.

Примервызовафункции:

Типыпараметров

179

Page 180: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[2]:cfg_to_list('r1.txt',True)

Out[2]:

['servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

'servicepassword-encryption',

'servicesequence-numbers',

'noipdomainlookup',

'ipsshversion2']

Таккакаргументуdelete_exclamationпереданозначениеTrue,витоговомсловаренетстроксвосклицательнымизнаками.

Вызовфункции,созначениемFalseдляаргументаdelete_exclamation:

In[3]:cfg_to_list('r1.txt',False)

Out[3]:

['!',

'servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

'servicepassword-encryption',

'servicesequence-numbers',

'!',

'noipdomainlookup',

'!',

'ipsshversion2',

'!']

Необязательныепараметры(параметрысозначениемпоумолчанию)

Присозданиифункции,можноуказыватьзначениепоумолчаниюдляпараметра:

In[4]:defcfg_to_list(cfg_file,delete_exclamation=True):

....:result=[]

....:withopen(cfg_file)asf:

....:forlineinf:

....:ifdelete_exclamationandline.startswith('!'):

....:pass

....:else:

....:result.append(line.rstrip())

....:returnresult

....:

Таккактеперьупараметраdelete_exclamationзначениепоумолчаниюравноTrue,соответствующийаргументможнонеуказыватьпривызовефункции,еслизначениепоумолчаниюподходит:

Типыпараметров

180

Page 181: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[5]:cfg_to_list('r1.txt')

Out[5]:

['servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

'servicepassword-encryption',

'servicesequence-numbers',

'noipdomainlookup',

'ipsshversion2']

Но,можноиуказать,еслинужнопоменятьзначениепоумолчанию:

In[6]:cfg_to_list('r1.txt',False)

Out[6]:

['!',

'servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

'servicepassword-encryption',

'servicesequence-numbers',

'!',

'noipdomainlookup',

'!',

'ipsshversion2',

'!']

Типыпараметров

181

Page 182: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ТипыаргументовфункцииПривызовефункцииаргументыможнопередаватьдвумяспособами:

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

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

Кодфункций,которыеиспользуютсявэтомразделе,можноскопироватьизфайлаfunc_args_types.py

Посмотримнаразныеспособыпередачиаргументов,напримерефункции:

In[1]:defcfg_to_list(cfg_file,delete_exclamation):

....:result=[]

....:withopen(cfg_file)asf:

....:forlineinf:

....:ifdelete_exclamationandline.startswith('!'):

....:pass

....:else:

....:result.append(line.rstrip())

....:returnresult

....:

Позиционныеаргументы

Позиционныеаргументы,привызовефункции,надопередатьвправильномпорядке(поэтомуонииназываютсяпозиционные)

Типыаргументов

182

Page 183: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[2]:cfg_to_list('r1.txt',False)

Out[2]:

['!',

'servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

'servicepassword-encryption',

'servicesequence-numbers',

'!',

'noipdomainlookup',

'!',

'',

'',

'ipsshversion2',

'!']

Еслипривызовефункциипоменятьаргументыместами,скореевсего,возникнетошибка,взависимостиотконкретнойфункции.

Вслучаесфункциейcfg_to_list,получитсятакойрезультат:

In[3]:cfg_to_list(False,'r1.txt')

---------------------------------------------------------------------------

TypeErrorTraceback(mostrecentcalllast)

<ipython-input-18-e6da7e2657eb>in<module>()

---->1cfg_to_list(False,'r1.txt')

<ipython-input-15-21a013e5e92c>incfg_to_list(cfg_file,delete_exclamation)

1defcfg_to_list(cfg_file,delete_exclamation):

2result=[]

---->3withopen(cfg_file)asf:

4forlineinf:

5ifdelete_exclamationandline.startswith('!'):

TypeError:coercingtoUnicode:needstringorbuffer,boolfound

Ключевыеаргументы

Ключевыеаргументы:

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

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

Типыаргументов

183

Page 184: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[4]:cfg_to_list(delete_exclamation=False,cfg_file='r1.txt')

Out[4]:

['!',

'servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

'servicepassword-encryption',

'servicesequence-numbers',

'!',

'noipdomainlookup',

'!',

'ipsshversion2',

'!']

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

Еслисделатьнаоборот,возникнетошибка:

In[5]:cfg_to_list(delete_exclamation=False,'r1.txt')

File"<ipython-input-19-5efdee7ce6dd>",line1

cfg_to_list(delete_exclamation=False,'r1.txt')

SyntaxError:non-keywordargafterkeywordarg

Новтакойкомбинацииможно:

In[6]:cfg_to_list('r1.txt',delete_exclamation=True)

Out[6]:

['servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

'servicepassword-encryption',

'servicesequence-numbers',

'noipdomainlookup',

'ipsshversion2']

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

Например,вфункцииcfg_to_list,понятно,чтоаргументdelete_exclamationприводиткудалениювосклицательныхзнаков.

Типыаргументов

184

Page 185: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

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

Позиционныеаргументыпеременнойдлины

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

Примерфункции:

In[1]:defsum_arg(a,*args):

....:printa,args

....:returna+sum(args)

....:

Функцияsum_argсозданасдвумяпараметрами:

параметрaеслипередаетсякакпозиционныйаргумент,долженидтипервымеслипередаетсякакключевойаргумент,топорядокневажен

параметр*args-ожидаетаргументыпеременнойдлинысюдапопадутвсеостальныеаргументыввидекортежаэтиаргументымогутотсутствовать

Вызовфункциюсразнымколичествомаргументов:

Аргументыпеременнойдлины

185

Page 186: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[2]:sum_arg(1,10,20,30)

1(10,20,30)

Out[2]:61

In[3]:sum_arg(1,10)

1(10,)

Out[3]:11

In[4]:sum_arg(1)

1()

Out[4]:1

Можносоздатьитакуюфункцию:

In[5]:defsum_arg(*args):

....:printarg

....:returnsum(arg)

....:

In[6]:sum_arg(1,10,20,30)

(1,10,20,30)

Out[6]:61

In[7]:sum_arg()

()

Out[7]:0

Ключевыеаргументыпеременнойдлины

Параметр,которыйпринимаетключевыеаргументыпеременнойдлины,создаетсядобавлениемпередименемпараметрадвухзвездочек.Имяпараметраможетбытьлюбым,но,подоговоренности,чащевсего,используютимя**kwargs(отkeywordarguments).

Примерфункции:

In[8]:defsum_arg(a,**kwargs):

....:printa,kwargs

....:returna+sum(kwargs.values())

....:

Функцияsum_argсозданасдвумяпараметрами:

параметрaеслипередаетсякакпозиционныйаргумент,долженидтипервымеслипередаетсякакключевойаргумент,топорядокневажен

Аргументыпеременнойдлины

186

Page 187: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

параметр**kwargs-ожидаетключевыеаргументыпеременнойдлинысюдапопадутвсеостальныеключевыеаргументыввидесловаряэтиаргументымогутотсутствовать

Вызовфункциюсразнымколичествомключевыхаргументов:

In[9]:sum_arg(a=10,b=10,c=20,d=30)

10{'c':20,'b':10,'d':30}

Out[9]:70

In[10]:sum_arg(b=10,c=20,d=30,a=10)

10{'c':20,'b':10,'d':30}

Out[10]:70

Обратитевнимание,что,хотяaможноуказыватькакпозиционныйаргумент,нельзяуказыватьпозиционныйаргументпослеключевого:

In[11]:sum_arg(10,b=10,c=20,d=30)

10{'c':20,'b':10,'d':30}

Out[11]:70

In[12]:sum_arg(b=10,c=20,d=30,10)

File"<ipython-input-6-71c121dc2cf7>",line1

sum_arg(b=10,c=20,d=30,10)

SyntaxError:non-keywordargafterkeywordarg

Аргументыпеременнойдлины

187

Page 188: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

РаспаковкааргументовВPython,выражения*argsи**kwargsпозволяютвыполнятьещёоднузадачу-распаковкуаргументов.

Досихпор,мывызываливсефункциивручную.И,соответственно,передаваливсенужныеаргументы.

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

Распаковкапозиционныхаргументов

Дляпримера,используемфункциюconfig_interface(файлfunc_args_var_unpacking.py):

defconfig_interface(intf_name,ip_address,cidr_mask):

interface='interface%s'

no_shut='noshutdown'

ip_addr='ipaddress%s%s'

result=[]

result.append(interface%intf_name)

result.append(no_shut)

mask_bits=int(cidr_mask.split('/')[-1])

bin_mask='1'*mask_bits+'0'*(32-mask_bits)

dec_mask='.'.join([str(int(bin_mask[i:i+8],2))foriin[0,8,16,24]])

result.append(ip_addr%(ip_address,dec_mask))

returnresult

Функцияожидаеткакаргумент:

intf_name-имяинтерфейсаip_address-IP-адресcidr_mask-маскувформатеCIDR(допускаетсяиформат/24ипросто24)

Навыходе,онавыдаетсписокстрок,длянастройкиинтерфейса.

Например:

Распаковкааргументов

188

Page 189: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[1]:config_interface('Fa0/1','10.0.1.1','/25')

Out[1]:['interfaceFa0/1','noshutdown','ipaddress10.0.1.1255.255.255.128']

In[2]:config_interface('Fa0/3','10.0.0.1','/18')

Out[2]:['interfaceFa0/3','noshutdown','ipaddress10.0.0.1255.255.192.0']

In[3]:config_interface('Fa0/3','10.0.0.1','/32')

Out[3]:['interfaceFa0/3','noshutdown','ipaddress10.0.0.1255.255.255.255']

In[4]:config_interface('Fa0/3','10.0.0.1','/30')

Out[4]:['interfaceFa0/3','noshutdown','ipaddress10.0.0.1255.255.255.252']

In[5]:config_interface('Fa0/3','10.0.0.1','30')

Out[5]:['interfaceFa0/3','noshutdown','ipaddress10.0.0.1255.255.255.252']

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

Например,списокinterfaces_info,вкоторомнаходятсяпараметрыдлянастройкиинтерфейсов:

In[6]:interfaces_info=[['Fa0/1','10.0.1.1','/24'],

....:['Fa0/2','10.0.2.1','/24'],

....:['Fa0/3','10.0.3.1','/24'],

....:['Fa0/4','10.0.4.1','/24'],

....:['Lo0','10.0.0.1','/32']]

Еслипройтисьпоспискувциклеипередаватьвложенныйсписок,какаргументфункции,возникнетошибка:

In[7]:forinfoininterfaces_info:

....:printconfig_interface(info)

....:

---------------------------------------------------------------------------

TypeErrorTraceback(mostrecentcalllast)

<ipython-input-32-fb83ecc1fbcf>in<module>()

1forinfoininterfaces_info:

---->2printconfig_interface(info)

3

TypeError:config_interface()takesexactly3arguments(1given)

Ошибкавполнелогичная:функцияожидаеттриаргумента,аейпередан1аргумент-список.

Втакойситуации,пригодитсяраспаковкааргументов.Достаточнодобавить*передпередачейсписка,какаргумента,иошибкиуженебудет:

Распаковкааргументов

189

Page 190: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[8]:forinfoininterfaces_info:

....:printconfig_interface(*info)

....:

['interfaceFa0/1','noshutdown','ipaddress10.0.1.1255.255.255.0']

['interfaceFa0/2','noshutdown','ipaddress10.0.2.1255.255.255.0']

['interfaceFa0/3','noshutdown','ipaddress10.0.3.1255.255.255.0']

['interfaceFa0/4','noshutdown','ipaddress10.0.4.1255.255.255.0']

['interfaceLo0','noshutdown','ipaddress10.0.0.1255.255.255.255']

Pythonсам'распакует'списокinfoипередаствфункциюэлементысписка,какаргументы.

Такимжеобразомможнораспаковыватьикортеж.

Распаковкаключевыхаргументов

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

Функцияconfig_to_list:

defconfig_to_list(cfg_file,delete_excl=True,

delete_empty=True,strip_end=True):

result=[]

withopen(cfg_file)asf:

forlineinf:

ifstrip_end:

line=line.rstrip()

ifdelete_emptyandnotline:

pass

elifdelete_exclandline.startswith('!'):

pass

else:

result.append(line)

returnresult

Функцияберетфайлсконфигурацией,убираетчастьстрокивозвращаетостальныестрокикаксписок.

Веськодфункцииможновставитьвipythonспомощьюкоманды%cpaste.

Примериспользования:

Распаковкааргументов

190

Page 191: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[9]:config_to_list('r1.txt')

Out[9]:

['servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

'servicepassword-encryption',

'servicesequence-numbers',

'noipdomainlookup',

'ipsshversion2']

Списоксловарейcfg,вкоторыхуказаноимяфайлаивсеаргументы:

In[10]:cfg=[dict(cfg_file='r1.txt',delete_excl=True,delete_empty=True,strip_end=

True),

....:dict(cfg_file='r2.txt',delete_excl=False,delete_empty=True,strip_en

d=True),

....:dict(cfg_file='r3.txt',delete_excl=True,delete_empty=False,strip_en

d=True),

....:dict(cfg_file='r4.txt',delete_excl=True,delete_empty=True,strip_end=

False)]

Еслипередатьсловарьфункцииconfig_to_list,возникнетошибка:

In[11]:fordincfg:

....:printconfig_to_list(d)

....:

---------------------------------------------------------------------------

TypeErrorTraceback(mostrecentcalllast)

<ipython-input-40-1affbd99c2f5>in<module>()

1fordincfg:

---->2printconfig_to_list(d)

3

<ipython-input-35-6337ba2bfe7a>inconfig_to_list(cfg_file,delete_excl,delete_empty,

strip_end)

2delete_empty=True,strip_end=True):

3result=[]

---->4withopen(cfg_file)asf:

5forlineinf:

6ifstrip_end:

TypeError:coercingtoUnicode:needstringorbuffer,dictfound

Ошибкатакая,таккаквсепараметры,кромеименифайла,опциональны.Инастадииоткрытияфайла,возникаетошибка,таккаквместофайла,передансловарь.

Еслидобавить**передпередачейсловаряфункции,функциянормальноотработает:

Распаковкааргументов

191

Page 192: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[12]:fordincfg:

...:printconfig_to_list(**d)

...:

['servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear','servicetimes

tampslogdatetimemseclocaltimeshow-timezoneyear','servicepassword-encryption',

'servicesequence-numbers','noipdomainlookup','ipsshversion2']

['!','servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear','service

timestampslogdatetimemseclocaltimeshow-timezoneyear','servicepassword-encrypti

on','servicesequence-numbers','!','noipdomainlookup','!','ipsshversion2',

'!']

['servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear','servicetimes

tampslogdatetimemseclocaltimeshow-timezoneyear','servicepassword-encryption',

'servicesequence-numbers','','','','ipsshversion2','']

['servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear\n','servicetim

estampslogdatetimemseclocaltimeshow-timezoneyear\n','servicepassword-encryptio

n\n','servicesequence-numbers\n','noipdomainlookup\n','ipsshversion2\n']

Pythonраспаковываетсловарьипередаетеговфункциюкакключевыеаргументы.

Распаковкааргументов

192

Page 193: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Спомощьюаргументовпеременнойдлиныираспаковкиаргументов,можнопередаватьаргументымеждуфункциями.Посмотримнапримере.

Функцияconfig_to_list(файлkwargs_example.py):

defconfig_to_list(cfg_file,delete_excl=True,

delete_empty=True,strip_end=True):

result=[]

withopen(cfg_file)asf:

forlineinf:

ifstrip_end:

line=line.rstrip()

ifdelete_emptyandnotline:

pass

elifdelete_exclandline.startswith('!'):

pass

else:

result.append(line)

returnresult

Веськодфункцииможновставитьвipythonспомощьюкоманды%cpaste.

Функцияберетфайлсконфигурацией,убираетчастьстрокивозвращаетостальныестрокикаксписок.

Вызовфункциивipython:

In[1]:config_to_list('r1.txt')

Out[1]:

['servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

'servicepassword-encryption',

'servicesequence-numbers',

'noipdomainlookup',

'ipsshversion2']

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

Вызовфункциисозначениемdelete_empty=False:

Примериспользования

193

Page 194: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[2]:config_to_list('r1.txt',delete_empty=False)

Out[2]:

['servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear',

'servicetimestampslogdatetimemseclocaltimeshow-timezoneyear',

'servicepassword-encryption',

'servicesequence-numbers',

'noipdomainlookup',

'',

'',

'ipsshversion2']

Теперьпустыестрокипоявилисьвсписке.

Сделаем'оберточную'функциюclear_cfg_and_write_to_file,котораяберетфайлконфигурации,спомощьюфункцииconfig_to_list,удаляетлишниестрокиизатемзаписываетстрокивуказанныйфайл.

Но,приэтом,мынехотимтерятьвозможностьуправлятьтем,какиестрокибудутотброшены.Тоесть,необходимочтобыфункцияclear_cfg_and_write_to_fileподдерживалатежепараметры,чтоифункцияconfig_to_list.

Конечно,можнопростопродублироватьвсепараметрыфункцииипередатьихвфункциюconfig_to_list:

defclear_cfg_and_write_to_file(cfg,to_file,delete_excl=True,

delete_empty=True,strip_end=True):

cfg_as_list=config_to_list(cfg,delete_excl=delete_excl,

delete_empty=delete_empty,strip_end=strip_end)

withopen(to_file,'w')asf:

f.write('\n'.join(cfg_as_list))

Но,есливоспользоватьсявозможностьюPythonприниматьаргументыпеременнойдлины,можносделатьфункциюclear_cfg_and_write_to_fileтакой:

defclear_cfg_and_write_to_file(cfg,to_file,**kwargs):

cfg_as_list=config_to_list(cfg,**kwargs)

withopen(to_file,'w')asf:

f.write('\n'.join(cfg_as_list))

Вфункцииclear_cfg_and_write_to_fileявнопрописаныеёаргументы,авсёостальноепопадетвпеременнуюkwargs.Затемпеременнаяkwargsпередается,какаргумент,вфункциюconfig_to_list.Но,таккакпеременнаяkwargsэтословарь,еёнадораспаковать,припередачефункцииconfig_to_list.

Примериспользования

194

Page 195: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Вэтомпримере,**kwargsиспользуетсяидлятого,чтобыуказать,чтофункцияclear_cfg_and_write_to_fileможетприниматьаргументыпеременнойдлины,идлятого,чтобы'распаковать'словарьkwargs,когдамыпередаемеговфункциюconfig_to_list.

Примериспользования

195

Page 196: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание7.1

Создатьфункцию,котораягенерируетконфигурациюдляaccess-портов.

Параметрaccessожидает,какаргумент,словарьaccess-портов,вида:

{'FastEthernet0/12':10,

'FastEthernet0/14':11,

'FastEthernet0/16':17,

'FastEthernet0/17':150}

Функциядолжнавозвращатьсписоквсехпортовврежимеaccessсконфигурациейнаосновешаблонаaccess_template.

Вконцестроквспискенедолжнобытьсимволапереводастроки.

Примеритоговогосписка:

Задания

196

Page 197: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

[

'interfaceFastEthernet0/12',

'switchportmodeaccess',

'switchportaccessvlan10',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable',

'interfaceFastEthernet0/17',

'switchportmodeaccess',

'switchportaccessvlan150',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable',

...]

Проверитьработуфункциинапримересловаряaccess_dict.

defgenerate_access_config(access):

"""

access-словарьaccess-портов,

длякоторыхнеобходимосгенерироватьконфигурацию,вида:

{'FastEthernet0/12':10,

'FastEthernet0/14':11,

'FastEthernet0/16':17}

Возвращаетсписоквсехпортовврежимеaccessсконфигурациейнаосновешаблона

"""

access_template=['switchportmodeaccess',

'switchportaccessvlan',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

access_dict={'FastEthernet0/12':10,

'FastEthernet0/14':11,

'FastEthernet0/16':17,

'FastEthernet0/17':150}

Задание7.1a

Сделатькопиюскриптазадания7.1.

Дополнитьскрипт:

ввестидополнительныйпараметр,которыйконтролируетбудетлинастроенport-security

имяпараметра'psecurity'

Задания

197

Page 198: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

поумолчаниюзначениеFalse

Проверитьработуфункциинапримересловаряaccess_dict,сгенерациейконфигурацииport-securityибез.

defgenerate_access_config(access):

"""

access-словарьaccess-портов,

длякоторыхнеобходимосгенерироватьконфигурацию,вида:

{'FastEthernet0/12':10,

'FastEthernet0/14':11,

'FastEthernet0/16':17}

psecurity-контролируетнужналинастройкаPortSecurity.ПоумолчаниюзначениеF

alse

-еслизначениеTrue,тонастройкавыполняетсясдобавлениемшаблонаport_secu

rity

-еслизначениеFalse,тонастройканевыполняется

Возвращаетсписоквсехкоманд,которыебылисгенерированынаосновешаблона

"""

access_template=['switchportmodeaccess',

'switchportaccessvlan',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

port_security=['switchportport-securitymaximum2',

'switchportport-securityviolationrestrict',

'switchportport-security']

access_dict={'FastEthernet0/12':10,

'FastEthernet0/14':11,

'FastEthernet0/16':17,

'FastEthernet0/17':150}

Задание7.1b

Сделатькопиюскриптазадания7.1a.

Изменитьскрипттакимобразом,чтобыфункциявозвращаланесписоккоманд,асловарь:

ключи:именаинтерфейсов,вида'FastEthernet0/12'значения:списоккоманд,которыйнадовыполнитьнаэтоминтерфейсе:

Задания

198

Page 199: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

['switchportmodeaccess',

'switchportaccessvlan10',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

Проверитьработуфункциинапримересловаряaccess_dict,сгенерациейконфигурацииport-securityибез.

defgenerate_access_config(access):

"""

access-словарьaccess-портов,

длякоторыхнеобходимосгенерироватьконфигурацию,вида:

{'FastEthernet0/12':10,

'FastEthernet0/14':11,

'FastEthernet0/16':17}

psecurity-контролируетнужналинастройкаPortSecurity.ПоумолчаниюзначениеF

alse

-еслизначениеTrue,тонастройкавыполняетсясдобавлениемшаблонаport_secu

rity

-еслизначениеFalse,тонастройканевыполняется

Функциявозвращаетсловарь:

-ключи:именаинтерфейсов,вида'FastEthernet0/1'

-значения:списоккоманд,которыйнадовыполнитьнаэтоминтерфейсе

"""

access_template=['switchportmodeaccess',

'switchportaccessvlan',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

port_security=['switchportport-securitymaximum2',

'switchportport-securityviolationrestrict',

'switchportport-security']

access_dict={'FastEthernet0/12':10,

'FastEthernet0/14':11,

'FastEthernet0/16':17,

'FastEthernet0/17':150}

Задание7.2

Создатьфункцию,котораягенерируетконфигурациюдляtrunk-портов.

Параметрtrunk-этословарьtrunk-портов.

Задания

199

Page 200: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Словарьtrunkимееттакойформат(тестовыйсловарьtrunk_dictужесоздан):

{'FastEthernet0/1':[10,20],

'FastEthernet0/2':[11,30],

'FastEthernet0/4':[17]}

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

Вконцестроквспискенедолжнобытьсимволапереводастроки.

Проверитьработуфункциинапримересловаряtrunk_dict.

defgenerate_trunk_config(trunk):

"""

trunk-словарьtrunk-портовдлякоторыхнеобходимосгенерироватьконфигурацию.

Возвращаетсписоквсехкоманд,которыебылисгенерированынаосновешаблона

"""

trunk_template=['switchporttrunkencapsulationdot1q',

'switchportmodetrunk',

'switchporttrunknativevlan999',

'switchporttrunkallowedvlan']

trunk_dict={'FastEthernet0/1':[10,20,30],

'FastEthernet0/2':[11,30],

'FastEthernet0/4':[17]}

Задание7.2a

Сделатькопиюскриптазадания7.2

Изменитьскрипттакимобразом,чтобыфункциявозвращаланесписоккоманд,асловарь:

ключи:именаинтерфейсов,вида'FastEthernet0/1'значения:списоккоманд,которыйнадовыполнитьнаэтоминтерфейсе

Проверитьработуфункциинапримересловаряtrunk_dict.

Задания

200

Page 201: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

defgenerate_trunk_config(trunk):

"""

trunk-словарьtrunk-портов,

длякоторыхнеобходимосгенерироватьконфигурацию,вида:

{'FastEthernet0/1':[10,20],

'FastEthernet0/2':[11,30],

'FastEthernet0/4':[17]}

Возвращаетсловарь:

-ключи:именаинтерфейсов,вида'FastEthernet0/1'

-значения:списоккоманд,которыйнадовыполнитьнаэтоминтерфейсе

"""

trunk_template=['switchporttrunkencapsulationdot1q',

'switchportmodetrunk',

'switchporttrunknativevlan999',

'switchporttrunkallowedvlan']

trunk_dict={'FastEthernet0/1':[10,20,30],

'FastEthernet0/2':[11,30],

'FastEthernet0/4':[17]}

Задание7.3

Создатьфункциюget_int_vlan_map,котораяобрабатываетконфигурационныйфайлкоммутатораивозвращаетдваобъекта:

словарьпортовврежимеaccess,гдеключиномерапортов,азначенияaccessVLAN:

{'FastEthernet0/12':10,

'FastEthernet0/14':11,

'FastEthernet0/16':17}

словарьпортовврежимеtrunk,гдеключиномерапортов,азначениясписокразрешенныхVLAN:

{'FastEthernet0/1':[10,20],

'FastEthernet0/2':[11,30],

'FastEthernet0/4':[17]}

Функцияожидаетвкачествеаргументаимяконфигурационногофайла.

Проверитьработуфункциинапримерефайлаconfig_sw1.txt

Задание7.3a

Задания

201

Page 202: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Сделатькопиюскриптазадания7.3.

Дополнитьскрипт:

добавитьподдержкуконфигурации,когданастройкаaccess-портавыглядиттак:

interfaceFastEthernet0/20

switchportmodeaccess

duplexauto

Тоесть,портнаходитсявVLAN1

Втакомслучае,всловарьпортовдолжнадобавлятьсяинформация,чтопортвVLAN1

Примерсловаря:

{'FastEthernet0/12':10,

'FastEthernet0/14':11,

'FastEthernet0/20':1}

Функцияожидаетвкачествеаргументаимяконфигурационногофайла.

Проверитьработуфункциинапримерефайлаconfig_sw2.txt

Задание7.4

Создатьфункцию,котораяобрабатываетконфигурационныйфайлкоммутатораивозвращаетсловарь:

Всекомандыверхнегоуровня(глобальногорежимаконфигурации),будутключами.Еслиукомандыверхнегоуровняестьподкоманды,онидолжныбытьвзначенииусоответствующегоключа,ввидесписка(пробелывначалеможнооставлять).Еслиукомандыверхнегоуровнянетподкоманд,тозначениебудетпустымсписком

Функцияожидаетвкачествеаргументаимяконфигурационногофайла.

Проверитьработуфункциинапримерефайлаconfig_sw1.txt

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

Дляпроверкинадолиигнорироватьстроку,использоватьфункциюignore_command.

Задания

202

Page 203: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ignore=['duplex','alias','Currentconfiguration']

defignore_command(command,ignore):

"""

Функцияпроверяетсодержитсяливкомандесловоизспискаignore.

command-строка.Команда,которуюнадопроверить

ignore-список.Списокслов

ВозвращаетTrue,есливкомандесодержитсясловоизспискаignore,False-еслине

т

"""

ignore_command=False

forwordinignore:

ifwordincommand:

returnTrue

returnignore_command

defconfig_to_dict(config):

"""

config-имяконфигурационногофайлакоммутатора

Возвращаетсловарь:

-Всекомандыверхнегоуровня(глобальногорежимаконфигурации),будутключами.

-Еслиукомандыверхнегоуровняестьподкоманды,

онидолжныбытьвзначенииусоответствующегоключа,ввидесписка(пробелывнач

алеможнооставлять).

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

"""

pass

Задание7.4a

Задачатакаяже,какизадании7.4.Проверитьработуфункциинадонапримерефайлаconfig_r1.txt

Обратитевниманиенаконфигурационныйфайл.Внеместьразделысбольшейвложенностью,например,разделы:

interfaceEthernet0/3.100routerbgp100

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

Теперь:

Задания

203

Page 204: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

еслиуровня2,токомандыверхнегоуровнябудутключамисловаря,акомандыподуровней-списками;еслиуровня3,тосамыйвложенныйдолженбытьсписком,аостальные-словарями.

НапримереinterfaceEthernet0/3.100

{'interfaceEthernet0/3.100':{

'encapsulationdot1Q100':[],

'xconnect10.2.2.212100encapsulationmpls':

['backuppeer10.4.4.414100',

'backupdelay11']}}

ignore=['duplex','alias','Currentconfiguration']

defcheck_ignore(command,ignore):

"""

Функцияпроверяетсодержитсяливкомандесловоизспискаignore.

command-строка.Команда,которуюнадопроверить

ignore-список.Списокслов

ВозвращаетTrue,есливкомандесодержитсясловоизспискаignore,False-еслине

т

"""

ignore_command=False

forwordinignore:

ifwordincommand:

ignore_command=True

returnignore_command

defconfig_to_dict(config):

"""

config-имяконфигурационногофайла

"""

pass

Задания

204

Page 205: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодулиМодульвPythonэтообычныйтекстовыйфайлскодомPythonирасширением.py.Онпозволяетлогическиупорядочитьисгруппироватькод.

Разделениенамодулиможетбыть,например,потакойлогике:

разделениеданных,форматированияилогикикодагруппировкафункцийидругихобъектовпофункционалу

Модулихорошитем,чтопозволяютповторноиспользоватьуженаписанныйкодинекопироватьего(например,некопироватькогда-тонаписаннуюфункцию).

8.Модули

205

Page 206: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ИмпортмодуляВPythonестьнесколькоспособовимпортамодуля:

importmodule

importmoduleas

frommoduleimportobject

frommoduleimport*

importmodule

Вариантimportmodule:

In[1]:dir()

Out[1]:

['In',

'Out',

...

'exit',

'get_ipython',

'quit']

In[2]:importos

In[3]:dir()

Out[3]:

['In',

'Out',

...

'exit',

'get_ipython',

'os',

'quit']

Послеимпорта,модульosпоявилсяввыводеdir().Этозначит,чтоонтеперьвтекущемименномпространстве.

Чтобывызватькакую-тофункциюилиметодизмодуляos,надоуказатьos.изатемимяобъекта:

In[4]:os.getlogin()

Out[4]:'natasha'

Импортмодуля

206

Page 207: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Этотспособимпортахороштем,чтообъектымодулянепопадаютвименноепространствотекущейпрограммы.Тоесть,еслисоздатьфункциюсименемgetlogin(),онанебудетконфликтоватьсаналогичнойфункциеймодуляos.

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

importmoduleas

Конструкцияimportmoduleasпозволяетимпортироватьмодульподдругимименем(какправило,болеекоротким):

In[1]:importsubprocessassp

In[2]:sp.check_output('ping-c2-n8.8.8.8',shell=True)

Out[2]:'PING8.8.8.8(8.8.8.8):56databytes\n64bytesfrom8.8.8.8:icmp_seq=0ttl=

48time=49.880ms\n64bytesfrom8.8.8.8:icmp_seq=1ttl=48time=46.875ms\n\n---8.8.

8.8pingstatistics---\n2packetstransmitted,2packetsreceived,0.0%packetloss\n

round-tripmin/avg/max/stddev=46.875/48.377/49.880/1.503ms\n'

frommoduleimportobject

Вариантfrommoduleimportobjectудобноиспользовать,когдаизвсегомодулянужнытолькоодна-двефункции:

In[1]:fromosimportgetlogin,getcwd

Теперьэтифункциидоступнывтекущемименномпространстве:

In[2]:dir()

Out[2]:

['In',

'Out',

...

'exit',

'get_ipython',

'getcwd',

'getlogin',

'quit']

Ихможновызыватьбезименимодуля:

Импортмодуля

207

Page 208: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[3]:getlogin()

Out[3]:'natasha'

In[4]:getcwd()

Out[4]:'/Users/natasha/Desktop/Py_net_eng/code_test'

frommoduleimport*

Вариантfrommoduleimport*импортируетвсеименамодулявтекущееименноепространство:

In[1]:fromosimport*

In[2]:dir()

Out[2]:

['EX_CANTCREAT',

'EX_CONFIG',

...

'wait',

'wait3',

'wait4',

'waitpid',

'walk',

'write']

In[3]:len(dir())

Out[3]:218

Вмодулеosоченьмногообъектов,поэтомувыводсокращен.Вконцеуказанадлинаспискаиментекущегоименногопространства.

Такойвариантимпорталучшенеиспользовать.Притакомимпорте,покодунепонятно,чтокакая-тофункциявзятаизмодуляos,например.Этозаметноусложняетпониманиекода.

Импортмодуля

208

Page 209: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

СозданиесвоихмодулейТаккакмодульэтопростофайлсрасширение.pyикодомPython,мыможемлегкосоздатьнесколькосвоихмодулей.

Например,разделимскриптизразделаСовмещениеforиifнанесколькочастей:шаблоныпортов,данныеиформированиекомандбудутвразныхфайлах.

Файлsw_int_templates.py:

access_template=['switchportmodeaccess',

'switchportaccessvlan',

'spanning-treeportfast',

'spanning-treebpduguardenable']

trunk_template=['switchporttrunkencapsulationdot1q',

'switchportmodetrunk',

'switchporttrunkallowedvlan']

l3int_template=['noswitchport','ipaddress']

Файлsw_data.py:

sw1_fast_int={

'access':{

'0/12':'10',

'0/14':'11',

'0/16':'17'}}

Совмещаемвсёвместевфайлеgenerate_sw_int_cfg.py:

Созданиесвоихмодулей

209

Page 210: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importsw_int_templates

fromsw_dataimportsw1_fast_int

defgenerate_access_cfg(sw_dict):

result=[]

forintfinsw_dict['access']:

result.append('interfaceFastEthernet'+intf)

forcommandinsw_int_templates.access_template:

ifcommand.endswith('accessvlan'):

result.append('%s%s'%(command,sw_dict['access'][intf]))

else:

result.append('%s'%command)

returnresult

print'\n'.join(generate_access_cfg(sw1_fast_int))

Впервыхдвухстрокахимпортируютсяобъектыиздругихфайлов:

importsw_int_templates-импортвсегоизфайлапримериспользованияодногоизшаблонов:sw_int_templates.access_template

fromsw_dataimportsw1_fast_int-измодуляsw_dataимпортируетсятолькоsw1_fast_int

притакомимпорте,можнонапрямуюобращатьсякимениsw1_fast_int

Результатвыполненияскрипта:

$pythongenerate_sw_int_cfg.py

interfaceFastEthernet0/12

switchportmodeaccess

switchportaccessvlan10

spanning-treeportfast

spanning-treebpduguardenable

interfaceFastEthernet0/14

switchportmodeaccess

switchportaccessvlan11

spanning-treeportfast

spanning-treebpduguardenable

interfaceFastEthernet0/16

switchportmodeaccess

switchportaccessvlan17

spanning-treeportfast

spanning-treebpduguardenable

if__name__=="__main__"

Созданиесвоихмодулей

210

Page 211: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Добавимещёодинскрипт,кпредыдущемупримеру,которыйбудетимпортироватьфункциюизфайлаgenerate_sw_int_cfg.py.

Файлsw_cfg_templates.pyсшаблонамиконфигурации:

basic_cfg="""

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

"""

lines_cfg="""

!

linecon0

loggingsynchronous

historysize100

linevty04

loggingsynchronous

historysize100

transportinputssh

!

"""

Вфайлеgenerate_sw_cfg.pyимпортируютсяшаблоныизsw_cfg_templates.pyифункцииизпредыдущихфайлов:

fromsw_dataimportsw1_fast_int

fromgenerate_sw_int_cfgimportgenerate_access_cfg

fromsw_cfg_templatesimportbasic_cfg,lines_cfg

printbasic_cfg

print'\n'.join(generate_access_cfg(sw1_fast_int))

printlines_cfg

Врезультате,должныотобразитьсятакиечастиконфигурации,попорядку:шаблонbasic_cfg,настройкаинтерфейсов,шаблонlines_cfg.

Созданиесвоихмодулей

211

Page 212: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Обратитевнимание,чтоизфайламожноимпортироватьнесколькообъектов:

fromsw_cfg_templatesimportbasic_cfg,lines_cfg

Результатвыполнения:

Созданиесвоихмодулей

212

Page 213: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythongenerate_sw_cfg.py

interfaceFastEthernet0/12

switchportmodeaccess

switchportaccessvlan10

spanning-treeportfast

spanning-treebpduguardenable

interfaceFastEthernet0/14

switchportmodeaccess

switchportaccessvlan11

spanning-treeportfast

spanning-treebpduguardenable

interfaceFastEthernet0/16

switchportmodeaccess

switchportaccessvlan17

spanning-treeportfast

spanning-treebpduguardenable

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

interfaceFastEthernet0/12

switchportmodeaccess

switchportaccessvlan10

spanning-treeportfast

spanning-treebpduguardenable

interfaceFastEthernet0/14

switchportmodeaccess

switchportaccessvlan11

spanning-treeportfast

spanning-treebpduguardenable

interfaceFastEthernet0/16

switchportmodeaccess

switchportaccessvlan17

spanning-treeportfast

spanning-treebpduguardenable

!

linecon0

loggingsynchronous

historysize100

linevty04

loggingsynchronous

historysize100

transportinputssh

!

Созданиесвоихмодулей

213

Page 214: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Полученныйвыводнесовсемправильный:передстрокамишаблонаbasic_cfg,идетлишняяконфигурацияинтерфейсов.

Такполучилосьиз-застрокиprintвфайлеgenerate_sw_int_cfg.py:

print'\n'.join(generate_access_cfg(sw1_fast_int))

Когдаскриптимпортируеткакой-томодуль,всё,чтонаходитсявмодуле,выполняется.И,таккаквданномслучае,вфайлеgenerate_sw_int_cfg.pyестьстрокасprint,настандартныйпотоквыводапопадаетрезультатвыполненияэтоговыражения,призапускефайлаgenerate_sw_int_cfg.py.

ВPythonестьспециальныйприем,которыйпозволяетуказать,чтокакой-токоддолженвыполняться,толькокогдафайлзапускаетсянапрямую.

Файлgenerate_sw_int_cfg2.py:

importsw_int_templates

fromsw_dataimportsw1_fast_int

defgenerate_access_cfg(sw_dict):

result=[]

forintfinsw_dict['access']:

result.append('interfaceFastEthernet'+intf)

forcommandinsw_int_templates.access_template:

ifcommand.endswith('accessvlan'):

result.append('%s%s'%(command,sw_dict['access'][intf]))

else:

result.append('%s'%command)

returnresult

if__name__=="__main__":

print'\n'.join(generate_access_cfg(sw1_fast_int))

Обратитевниманиеназапись:

if__name__=="__main__":

print'\n'.join(generate_access_cfg(sw1_fast_int))

Переменная__name__этоспециальнаяпеременная,котораявыставляетсяравной"__main__",еслифайлзапускаетсякакосновнаяпрограмма.Ивыставляетсяравнойименимодуля,еслимодульимпортируется.

Такимобразом,условиеif__name__=="__main__"проверяетбыллифайлзапущеннапрямую.

Созданиесвоихмодулей

214

Page 215: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Изменитевфайлеgenerate_sw_cfg.pyстроку:

fromgenerate_sw_int_cfgimportgenerate_access_cfg

настроку:

fromgenerate_sw_int_cfg2importgenerate_access_cfg

Ипопробуйтезапуститьскрипт:

$pythongenerate_sw_cfg.py

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

interfaceFastEthernet0/12

switchportmodeaccess

switchportaccessvlan10

spanning-treeportfast

spanning-treebpduguardenable

interfaceFastEthernet0/14

switchportmodeaccess

switchportaccessvlan11

spanning-treeportfast

spanning-treebpduguardenable

interfaceFastEthernet0/16

switchportmodeaccess

switchportaccessvlan17

spanning-treeportfast

spanning-treebpduguardenable

!

linecon0

loggingsynchronous

historysize100

linevty04

loggingsynchronous

historysize100

transportinputssh

!

Теперьprintизфайлаgenerate_sw_int_cfg2.pyневыводится.

Созданиесвоихмодулей

215

Page 216: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Созданиесвоихмодулей

216

Page 217: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание8.1

Создатьотдельныйфайлmy_func.py.

Перенестивнегофункциииззаданий:

7.1или7.1a7.27.3или7.3a

Создатьфайлmain.py:

Походузаданияимпортироватьнужныефункцииизфайлаmy_func.Файлmain.pyдолженожидатькакаргументимяконфигурационногофайлакоммутатора.Имяконфигурационногофайлапередатькакаргументфункцииget_int_vlan_map(иззадания7.3-7.3a)

Навыходефункции,мыдолжныполучитькортеждвухсловарей.Словари,соответственно,надопередатьфункциям:

generate_access_config(иззадания7.1-7.1a)generate_trunk_config(иззадания7.2)

Этифункции,всвоюочередь,возвращаютсписоксострокамиготовойконфигурациикоторуюнадозаписатьвфайлresult.txtввидестандартного

Задания

217

Page 218: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

конфига(тоесть,строк)

Задание8.2

Создатьфункциюparse_cdp_neighbors,котораяобрабатываетвыводкомандыshowcdpneighbors.

Функцияожидает,какаргумент,выводкомандыоднойстрокой.

Функциядолжнавозвращатьсловарь,которыйописываетсоединениямеждуустройствами.

Например,есликакаргументбылпередантакойвывод:

R4>showcdpneighbors

DeviceIDLocalIntrfceHoldtmeCapabilityPlatformPortID

R5Fa0/1122RSI2811Fa0/1

R6Fa0/2143RSI2811Fa0/0

Функциядолжнавернутьтакойсловарь:

{('R4','Fa0/1'):('R5','Fa0/1'),

('R4','Fa0/2'):('R6','Fa0/0')}

Проверитьработуфункциинасодержимомфайлаsw1_sh_cdp_neighbors.txt

Задание8.2a

Длявыполненияэтогозадания,долженбытьустановленgraphviz:

apt-getinstallgraphviz

Имодульpythonдляработысgraphviz:

pipinstallgraphviz

Спомощьюфункцииparse_cdp_neighborsиззадания8.2ифункцииdraw_topologyизфайлаdraw_network_graph.py,сгенерироватьтопологию,котораясоответствуетвыводукомандыshcdpneighborвфайлеsw1_sh_cdp_neighbors.txt

Некопироватькодфункцийparse_cdp_neighborsиdraw_topology.

Витоге,долженбытьсгенерированоизображениетопологии.Результатдолженвыглядетьтакже,каксхемавфайлеtask_8_2a_topology.svg

Задания

218

Page 219: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Задание8.2b

Длявыполненияэтогозадания,долженбытьустановленgraphviz:

apt-getinstallgraphviz

Имодульpythonдляработысgraphviz:

pipinstallgraphviz

Спомощьюфункцииparse_cdp_neighborsиззадания8.2ифункцииdraw_topologyизфайлаdraw_network_graph.py,сгенерироватьтопологию,котораясоответствуетвыводукомандыshcdpneighborизфайлов:

sh_cdp_n_sw1.txtsh_cdp_n_r1.txtsh_cdp_n_r2.txtsh_cdp_n_r3.txt

Некопироватькодфункцийparse_cdp_neighborsиdraw_topology.

Витоге,долженбытьсгенерированоизображениетопологии.Результатдолженвыглядетьтакже,каксхемавфайлеtask_8_2b_topology.svg

Задания

219

Page 220: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Задания

220

Page 221: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Приработессетевымоборудованием,регулярныевыражениямогутиспользоваться,например,дляобработкивыводакомандshow.Например,еслисовсегооборудованиянадособратьинформациюпроверсиюОСиuptime,можнополучитьэтуинформациюизвыводаshowversion,обработавегоспомощьюрегулярныхвыражений

Всамомсетевомоборудовании,регулярныевыраженияможноиспользоватьдляфильтрациивыводалюбыхкомандshowиmore.Или,например,дляфильтрациитаблицыBGP.

Отличныйсайтдлятестированиярегулярныхвыражений:regex101.com

9.Регулярныевыражения

221

Page 222: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодульreВPythonдляработысрегулярнымивыражениямииспользуетсямодульre.

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

Вэтомразделеиспользуетсяпримерпоискаподстрокивстроке,безспециальныхсимволов,чтобысосредоточитьсянавозможностяхмодуляre.Вследующихразделахбудутиспользоватьсяболеесложныепримеры.

Основныефункциимодуляre:

match()-ищетпоследовательностьвначалестрокиsearch()-ищетпервоесовпадениесшаблономfindall()-ищетвсесовпадениясшаблоном.Выдаетрезультирующиестрокиввидеспискаfinditer()-ищетвсесовпадениясшаблоном.Выдаетитераторcompile()-компилируетрегулярноевыражение.Кэтомуобъектузатемможноприменятьвсеперечисленныефункции

search()

Функцияsearch():

используетсядляпоискаподстроки,котораясоответствуетшаблонувозвращаетобъектMatch,еслиподстроканайденавозвращаетNone,еслиподстроканенайдена

Поискподстрокивстроке:

In[1]:importre

In[2]:line='00:09:BB:3D:D6:5810.1.10.286250dhcp-snooping10FastEth

ernet0/1'

In[3]:printre.search('dhcp',line)

<_sre.SRE_Matchobjectat0x10edeb9f0>

In[4]:printre.search('dhcpd',line)

None

ИзобъектаMatchможнополучитьнескольковариантовполезнойинформации.

Модульre

222

Page 223: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Например,спомощьюметодаspan(),можнополучитьчисла,указывающиеначалоиконецподстроки:

In[5]:match=re.search('dhcp',line)

In[6]:match.span()

Out[6]:(49,53)

In[7]:line[49:53]

Out[7]:'dhcp'

Методgroup()позволяетполучитьподстроку,котораясоответствуетшаблону:

In[15]:match.group()

Out[15]:'dhcp'

Важныймоментвиспользованиифункцииsearch(),точтоонаищеттолькопервоесовпадениевстроке,котороесоответствуетшаблону:

In[16]:line2='testdhcp,test2dhcp2'

In[17]:match=re.search('dhcp',line2)

In[18]:match.group()

Out[18]:'dhcp'

In[19]:match.span()

Out[19]:(5,9)

findall()

Длятогочтобынайтивсесовпадения,можноиспользоватьфункциюfindall():

In[20]:line2='testdhcp,test2dhcp2'

In[21]:match=re.findall('dhcp',line2)

In[22]:printmatch

['dhcp','dhcp']

Особенностьфункцииfindall()втом,чтоонавозвращаетсписокподстрок,которыесоответствуютшаблону,анеобъектMatch.Поэтомунельзявызватьметоды,которыеиспользовалисьвфункцииsearch().

Модульre

223

Page 224: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

finditer()

Длятогочтобыполучитьвсесовпадения,ноприэтом,получитьсовпаденияввидеобъектаMatch(),можноиспользоватьфункциюfinditer():

In[23]:line2='testdhcp,test2dhcp2'

In[24]:match=re.finditer('dhcp',line2)

In[25]:printmatch

<callable-iteratorobjectat0x10efd2cd0>

In[26]:foriinmatch:

....:printi.span()

....:

(5,9)

(17,21)

In[27]:line2[5:9]

Out[27]:'dhcp'

In[28]:line2[17:21]

Out[28]:'dhcp'

Можновоспользоватьсяиметодамиstart(),end()(такудобнееполучитьпозицииподстрок):

In[29]:line2='testdhcp,test2dhcp2'

In[30]:match=re.finditer('dhcp',line2)

In[31]:foriinmatch:

....:b=i.start()

....:e=i.end()

....:printline2[b:e]

....:

dhcp

dhcp

compile()

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

Примеркомпиляциирегулярноговыраженияиегоиспользования:

Модульre

224

Page 225: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[32]:line2='testdhcp,test2dhcp2'

In[33]:regex=re.compile('dhcp')

In[34]:match=regex.finditer(line2)

In[35]:foriinmatch:

....:b=i.start()

....:e=i.end()

....:printline2[b:e]

....:

dhcp

dhcp

Модульre

225

Page 226: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

СпециальныесимволыПолностьювозможностирегулярныхвыраженийпроявляютсяприиспользованииспециальныхсимволов.

Специальныесимволы:

.-любойсимвол,кромесимволановойстроки(опцияmпозволяетвключитьисимволновойстроки) -началостроки$-конецстроки[abc]-любойсимволвскобках[^abc]-любойсимвол,крометех,чтовскобкахa|b-элементaилиb(regex)-выражениерассматриваетсякакодинэлемент.Текст,которыйсовпалсвыражением,запоминается

Повторение:

regex*-нольилиболееповторенийпредшествующегоэлементаregex+-одинилиболееповторенийпредшествующегоэлементаregex?-нольилиодноповторениепредшествующегоэлементаregex{n}-ровноnповторенийпредшествующегоэлементаregex{n,m}-отnдоmповторенийпредшествующегоэлементаregex{n,}-nилиболееповторенийпредшествующегоэлемента

Предопределенныенаборысимволов:

\d-любаяцифра\D-любоенечисловоезначение\s-whitespace(\t\n\r\f\v)\S-все,кромеwhitespace\w-любаябукваилицифра\W-все,кромебуквицифр

Посмотримнапримерыиспользованияспециальныхсимволов:

In[1]:importre

In[2]:line="FastEthernet0/110.0.12.1YESmanualup

up"

Специальныесимволы

226

Page 227: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Точкаобозначаетлюбойсимвол,поэтомувстрокеlineнайдено3совпадениясрегулярнымвыражением.0:

In[3]:printre.findall('.0',line)

['t0','10','.0']

Символ означаетначалостроки.Выражению Fсоотвествуеттолькооднаподстрока:

In[4]:printre.findall('^F',line)

['F']

Выражению .aсоответствуетподстрока'Fa':

In[5]:printre.findall('^.a',line)

['Fa']

Символ$обозначаетконецстроки:

In[6]:printre.findall('up$',line)

['up']

In[7]:printre.findall('up',line)

['up','up']

Символы,которыеперечисленывквадратныхскобках,означают,чтолюбойизэтихсимволовбудетсовпадением.Такимобразомможноописыватьразныерегистры:

In[8]:printre.findall('[Ff]ast',line)

['Fast']

In[9]:printre.findall('[Ff]ast[Ee]thernet',line)

['FastEthernet']

Еслипослеоткрывающейсяквадратнойскобки,указансимвол ,совпадениембудетлюбойсимвол,кромеуказанныхвскобках(вданномслучае,всё,кромебуквипробела):

In[10]:printre.findall('[^a-zA-Z]',line)

['0','/','1','1','0','.','0','.','1','2','.','1']

Вертикальнаячертаработаеткак'или':

Специальныесимволы

227

Page 228: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[11]:printre.findall('up|down',line)

['up','up']

Специальныесимволы

228

Page 229: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЖадностьрегулярныхвыраженийПоумолчанию,символыповторенияврегулярныхвыраженияхжадные(greedy).Этозначит,чторезультирующаяподстрока,котораясоответствуетшаблону,будетнаиболеедлинной.

Примержадногоповедения:

In[1]:importre

In[2]:line='<textline>sometext>'

In[3]:match=re.search('<.*>',line)

In[4]:match.group()

Out[4]:'<textline>sometext>'

Тоесть,вданомслучаевыражениезахватиломаксимальновозможныйкусоксимволов,заключенныйв<>.

Еслинужноотключитьжадность,достаточнодобавитьзнаквопросапослесимволовповторения:

In[5]:line='<textline>sometext>'

In[6]:match=re.search('<.*?>',line)

In[7]:match.group()

Out[7]:'<textline>'

Обратитевнимание,чтожадностькасаетсяименносимволовповторения

Жадностьрегулярныхвыражений

229

Page 230: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Группировкавыражений

Нумерованныегруппы

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

Группаопределяетсяпомещениемвыражениявкруглыескобки().

Внутривыражения,группынумеруютсяслеванаправо,начинаяс1.Затемкгруппамможнообращатьсяпономерамиполучатьтекст,которыесоответствуетвыражениювгруппе.

Примериспользованиягрупп:

In[8]:line="FastEthernet0/110.0.12.1YESmanualup

up"

In[9]:match=re.search('(\S+)\s+([\w\.]+)\s+.*',line)

Вданномпримереуказаныдвегруппы:

перваягруппа-любыесимволы,кромеwhitespaces.Этагруппанежаднаявтораягруппа-любаябукваилицифра(символ\w)илиточка.Этагруппанежадная

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

Теперьможнообращатьсякгруппампономеру.Группа0этострока,котораясоответствуетвсемушаблону:

In[10]:match.group(0)

Out[10]:'FastEthernet0/110.0.12.1YESmanualup

up'

In[11]:match.group(1)

Out[11]:'FastEthernet0/1'

In[12]:match.group(2)

Out[12]:'10.0.12.1'

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

Группировкавыражений

230

Page 231: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[13]:match.groups()

Out[13]:('FastEthernet0/1','10.0.12.1')

Именованныегруппы

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

Именованныегруппыпозволяютзадаватьгруппеимя.

Синтаксисименованнойгруппы(?P<name>regex):

In[14]:line="FastEthernet0/110.0.12.1YESmanualup

up"

In[15]:match=re.search('(?P<intf>\S+)\s+(?P<address>[\d\.]+)\s+',line)

Теперькэтимгруппамможнообращатьсяпоимени:

In[15]:match.group('intf')

Out[15]:'FastEthernet0/1'

In[16]:match.group('address')

Out[16]:'10.0.12.1'

Такжеоченьполезното,чтоспомощьюметодаgroupdict(),можнополучитьсловарь,гдеключи-именагрупп,азначения-подстроки,которыеимсоответствуют:

In[17]:match.groupdict()

Out[17]:{'address':'10.0.12.1','intf':'FastEthernet0/1'}

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

In[18]:match=re.search('(?P<intf>\S+)\s+(?P<address>[\d\.]+)\s+[\w\s]+(?P<status>

up|down|administrativelydown)\s+(?P<protocol>up|down)',line)

In[19]:match.groupdict()

Out[19]:

{'address':'10.0.12.1',

'intf':'FastEthernet0/1',

'protocol':'up',

'status':'up'}

Группировкавыражений

231

Page 232: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Группировкавыражений

232

Page 233: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Разборвыводакомандыshowipdhcpsnoopingспомощьюименованныхгрупп

Рассмотримещеодинпримериспользованияименованныхгрупп.Вэтомпримере,задачавтом,чтобыполучитьизвыводакомандыshowipdhcpsnoopingbindingполя:MAC-адрес,IP-адрес,VLANиинтерфейс.

Вфайлеdhcp_snooping.txtнаходитсявыводкомандыshowipdhcpsnoopingbinding:

MacAddressIpAddressLease(sec)TypeVLANInterface

----------------------------------------------------------------------------

----

00:09:BB:3D:D6:5810.1.10.286250dhcp-snooping10FastEthernet0/1

00:04:A3:3E:5B:6910.1.5.263951dhcp-snooping5FastEthernet0/1

0

00:05:B3:7E:9B:6010.1.5.463253dhcp-snooping5FastEthernet0/9

00:09:BC:3F:A6:5010.1.10.676260dhcp-snooping10FastEthernet0/3

Totalnumberofbindings:4

Дляначала,попробуемразобратьоднустроку:

In[1]:line='00:09:BB:3D:D6:5810.1.10.286250dhcp-snooping10FastEthernet0

/1'

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

In[2]:match=re.search('(?P<mac>.+?)+(?P<ip>.*?)+(\d+)+([\w-]+)+(?P<vlan>\d+)+

(?P<int>.*$)',line)

Комментариикрегулярномувыражению:

(?P<mac>.+?)+-вгруппусименем'mac'попадаютлюбыесимволы.Но,таккаквыражениенежадное,аследомуказано,чтодолжныидтипробелы(одинилиболее),получается,чтовыражениеописываетпоследовательностьлюбыхсимволов,допробела(?P<ip>.*?)+-тутаналогично,последовательностьлюбыхсимволовдопробела.Имягруппы'ip'(\d+)+-числоваяпоследовательность(однаилиболеецифр),азатемодинилиболеепробелов

сюдапопадетзначениеLease([\w-]+)+-буквыили-,вколичествеодногоилиболее

Разборвыводакомандыshowipdhcpsnoopingспомощьюименованныхгрупп

233

Page 234: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

сюдапопадаеттипсоответствия(вданномслучае,всеониdhcp-snooping)(?P<vlan>\d+)+-именованнаягруппа'vlan'.Сюдапопадаюттолькочисловыепоследовательности,соднимилиболеесимволами(?P<int>.*$)-именованнаягруппа'int'.Сюдапопадаютлюбыесимволы,которыенаходятсявконцестроки(впредыдущемвыраженииэтагруппаограниченапробелом)

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

Дляостальныхжадностьможнонеотключать,таккаквнихболеечеткоуказаныкакиеименносимволыдолжныбыть.

Врезультате,методgroupdictвернеттакойсловарь:

In[3]:match.groupdict()

Out[3]:

{'int':'FastEthernet0/1',

'ip':'10.1.10.2',

'mac':'00:09:BB:3D:D6:58',

'vlan':'10'}

Таккакрегулярноевыражениеотработалокакнужно,можносоздаватьскрипт.Вскрипте,перебираютсявсестрокифайлаdhcp_snooping.txtинастандартныйпотоквывода,выводитсяинформацияобустройствах.

Файлparse_dhcp_snooping.py:

#-*-coding:utf-8-*-

importre

regex=re.compile('(?P<mac>.+?)+(?P<ip>.*?)+(\d+)+([\w-]+)+(?P<vlan>\d+)+(?P<int

>.*$)')

result=[]

withopen('dhcp_snooping.txt')asdata:

forlineindata:

ifline[0].isdigit():

result.append(regex.search(line).groupdict())

print"Ккоммутаторуподключено%dустройства"%len(result)

fornum,compinenumerate(result,1):

print"Параметрыустройства%s:"%num

forkeyincomp:

print"\t%s:\t%s"%(key,comp[key])

Результатвыполнения:

Разборвыводакомандыshowipdhcpsnoopingспомощьюименованныхгрупп

234

Page 235: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythonparse_dhcp_snooping.py

Ккоммутаторуподключено4устройства

Параметрыустройства1:

int:FastEthernet0/1

ip:10.1.10.2

mac:00:09:BB:3D:D6:58

vlan:10

Параметрыустройства2:

int:FastEthernet0/10

ip:10.1.5.2

mac:00:04:A3:3E:5B:69

vlan:5

Параметрыустройства3:

int:FastEthernet0/9

ip:10.1.5.4

mac:00:05:B3:7E:9B:60

vlan:5

Параметрыустройства4:

int:FastEthernet0/3

ip:10.1.10.6

mac:00:09:BC:3F:A6:50

vlan:10

Разборвыводакомандыshowipdhcpsnoopingспомощьюименованныхгрупп

235

Page 236: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание9.1

Создатьскрипт,которыйбудетожидатьдвааргумента:

1. имяфайла,вкоторомнаходитсявыводкомандыshow2. регулярноевыражение

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

Проверитьработускриптанапримеревыводакомандыshipintbr(файлsh_ip_int_br.txt).Например,попробуйтевывестиинформациютолькопоинтерфейсуFastEthernet0/1.

Вданномслучае,скриптбудетработатькакфильтрincludeвCLICisco.Выможетепопробоватьиспользоватьрегулярныевыражениядляфильтрациивыводакомандshow.

Пример:shipintbr|includeup+up

Задание9.1a

Задания

236

Page 237: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Проверьтерегулярноевыражение,используяскрипт,которыйбылсозданвзадании9.1,ифайлsh_ip_int_br.txt.

Задание9.1b

Переделайтерегулярноевыражениеиззадания9.1aтакимобразом,чтобыоно,по-прежнему,отображалострокисинтерфейсами0/1и0/3,но,приэтом,врегулярномвыражениибылонеболее7символов(несчитаякавычкивокругрегулярноговыражения).

Проверьтерегулярноевыражение,используяскрипт,которыйбылсозданвзадании9.1,ифайлsh_ip_int_br.txt.

Задание9.1c

Проверитьработускриптаиззадания9.1ирегулярноговыраженияиззадания9.1aили9.1bнавыводеshipintbrизфайлаsh_ip_int_br_switch.txt.

Если,врезультатевыполненияскрипта,быливыведенынетолькострокисинтерфейсами0/1и0/3,исправитьрегулярноевыражение.Врезультате,должнывыводитьсятолькострокисинтерфейсами0/1и0/3.

Задание9.2

Создатьфункциюreturn_match,котораяожидаетдвааргумента:

имяфайла,вкоторомнаходитсявыводкомандыshowрегулярноевыражение

Функциядолжнаобрабатыватьвыводкомандыshowпострочноивозвращатьсписокподстрок,которыесовпалисрегулярнымвыражением(невсюстроку,гдебылонайденосовпадение,атолькотуподстроку,котораясовпаласвыражением).

Проверитьработуфункциинапримеревыводакомандыshipintbr(файлsh_ip_int_br.txt).ВывестисписоквсехIP-адресовизвыводакоманды.

Соответственно,регулярноевыражениедолжноописыватьподстрокусIP-адресом(тоесть,совпадениемдолженбытьIP-адрес).

Задания

237

Page 238: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Задание9.3

Создатьфункциюparse_cfg,котораяожидаеткакаргументимяфайла,вкоторомнаходитсяконфигурацияустройства.

ФункциядолжнаобрабатыватьконфигурациюивозвращатьIP-адресаимаски,которыенастроенынаинтерфейсах,ввидеспискакортежей:

первыйэлементкортежа-IP-адресвторойэлементкортежа-маска

Например(взятыпроизвольныеадреса):[('10.0.1.1','255.255.255.0'),('10.0.2.1','255.255.255.0')]

Дляполучениятакогорезультата,используйтерегулярныевыражения.

Проверитьработуфункциинапримерефайлаconfig_r1.txt.

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

Задание9.3a

Переделатьфункциюparse_cfgиззадания9.3такимобразом,чтобыонавозвращаласловарь:

ключ:имяинтерфейсазначение:кортежсдвумястроками:

IP-адресмаска

Например(взятыпроизвольныеадреса):

{'FastEthernet0/1':('10.0.1.1','255.255.255.0'),

'FastEthernet0/2':('10.0.2.1','255.255.255.0')}

Дляполучениятакогорезультата,используйтерегулярныевыражения.

Проверитьработуфункциинапримерефайлаconfig_r1.txt.

Задания

238

Page 239: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Задание9.3b

Проверитьработуфункцииparse_cfgиззадания9.3aнаконфигурацииconfig_r2.txt.

Обратитевнимание,чтонаинтерфейсеe0/1назначеныдваIP-адреса:

interfaceEthernet0/1

ipaddress10.255.2.2255.255.255.0

ipaddress10.254.2.2255.255.255.0secondary

Авсловаре,которыйвозвращаетфункцияparse_cfg,интерфейсуEthernet0/1соответствуеттолькоодинизних(второй).

Переделайтефункциюparse_cfgиззадания9.3aтакимобразом,чтобыонавозвращаласписоккортежейдлякаждогоинтерфейса.Еслинаинтерфейсеназначентолькоодинадрес,вспискебудетодинкортеж.ЕслиженаинтерфейсенастроенынесколькоIP-адресов,товспискебудетнесколькокортежей.

Проверьтефункциюнаконфигурацииconfig_r2.txtиубедитесь,чтоинтерфейсуEthernet0/1соответствуетсписокиздвухкортежей.

Задание9.4

Создатьфункциюparse_sh_ip_int_br,котораяожидаеткакаргументимяфайла,вкоторомнаходитсявыводкомандыshow

Функциядолжнаобрабатыватьвыводкомандыshowipintbrивозвращатьтакиеполя:

InterfaceIP-AddressStatusProtocol

Информациядолжнавозвращатьсяввидеспискакортежей:[('FastEthernet0/0','10.0.1.1','up','up'),('FastEthernet0/1','10.0.2.1','up','up'),('FastEthernet0/2','unassigned','up','up')]

Дляполучениятакогорезультата,используйтерегулярныевыражения.

Проверитьработуфункциинапримерефайлаsh_ip_int_br_2.txt.

Задание9.4a

Создатьфункциюconvert_to_dict,котораяожидаетдвааргумента:

Задания

239

Page 240: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

списоксназваниямиполейсписоккортежейсрезультатамиотработкифункцииparse_sh_ip_int_brиззадания9.4

Функциявозвращаетрезультатввидеспискасловарей(порядокполейможетбытьдругой):[{'interface':'FastEthernet0/0','status':'up','protocol':'up','address':'10.0.1.1'},{'interface':'FastEthernet0/1','status':'up','protocol':'up','address':'10.0.2.1'}]

Проверитьработуфункциинапримерефайлаsh_ip_int_br_2.txt:

первыйаргумент-списокheadersвторойаргумент-результат,которыйвозвращаетфункцииparse_showизпрошлогозадания.

Функциюparse_sh_ip_int_brненужнокопировать.Надоимпортироватьилисамуфункцию,ииспользоватьтожерегулярноевыражение,чтоивзадании9.4,илиимпортироватьрезультатвыполненияфункцииparse_show.

headers=['interface','address','status','protocol']

Задания

240

Page 241: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

СериализацияданныхСериализацияданных-этосохранениеданныхвкаком-тоформате.Чащевсего,этосохранениевкаком-тоструктурированномформате.

Например,этомогутбыть:

файлывформатеYAMLилиJSONфайлывформатеCSVбазаданных

Крометого,Pythonпозволяетзаписыватьобъектысамогоязыка(этотаспектвкурсенерассматривается,но,есливаминтересно,посмотритенамодульPickle).

ВэтомразделерассматриваютсяформатыCSV,JSON,YAML,авследующемразделе-базыданных.

ДлячегомогутпригодитсяформатыYAML,JSON,CSV:

увасмогутбытьданныеоIP-адресахиподобнойинформации,которуюнужнообработать,втаблицах

таблицуможноэкспортироватьвформатCSVиобрабатыватьеёспомощьюPython

управляющийсофтможетвозвращатьданныевJSON.Соответственно,преобразовавэтиданныевобъектPython,снимиможноработатьиделать,чтоугодноYAMLоченьудобноиспользоватьдляописанияпараметров,таккакунегодовольноприятныйсинтаксис

например,этомогутбытьпараметрынастройкиразличныхобъектов(IP-адреса,VLANидр)какминимум,знаниеформатаYAMLпригодитсяприиспользованииAnsible

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

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

CSVJSON

10.Сериализацияданных

241

Page 242: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

YAML

10.Сериализацияданных

242

Page 243: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

РаботасфайламивформатеCSVCSV(comma-separatedvalue)-этоформатпредставлениятабличныхданных(например,этомогутбытьданныеизтаблицы,илиданныеизБД).

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

И,хотяуформатовсдругимразделителемможетбытьисобственноеназвание,например,TSV(tabseparatedvalues),темнеменееподформатомCSVпонимают,какправило,любыеразделители.

ПримерфайлавформатеCSV(sw_data.csv):

hostname,vendor,model,location

sw1,Cisco,3750,London

sw2,Cisco,3850,Liverpool

sw3,Cisco,3650,Liverpool

sw4,Cisco,3650,London

ВстандартнойбиблиотекеPythonестьмодульcsv,которыйпозволяетработатьсфайламивCSVформате.

Чтение

Примериспользованиямодуляcsv(файлcsv_read.py):

importcsv

withopen('sw_data.csv')asf:

reader=csv.reader(f)

forrowinreader:

printrow

Выводбудеттаким:

$pythoncsv_read.py

['hostname','vendor','model','location']

['sw1','Cisco','3750','London']

['sw2','Cisco','3850','Liverpool']

['sw3','Cisco','3650','Liverpool']

['sw4','Cisco','3650','London']

CSV

243

Page 244: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

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

ДляэтоговмодулеестьDictReader(файлcsv_read_dict.py):

importcsv

withopen('sw_data.csv')asf:

reader=csv.DictReader(f)

forrowinreader:

printrow

Выводбудеттаким:

$pythoncsv_read_dict.py

{'model':'3750','hostname':'sw1','vendor':'Cisco','location':'London'}

{'model':'3850','hostname':'sw2','vendor':'Cisco','location':'Liverpool'}

{'model':'3650','hostname':'sw3','vendor':'Cisco','location':'Liverpool'}

{'model':'3650','hostname':'sw4','vendor':'Cisco','location':'London'}

Обратитевнимание,чтосамreaderэтоитератор.Поэтому,еслипростовывестиreader,товыводбудеттаким:

In[1]:importcsv

In[2]:withopen('sw_data.csv')asf:

...:reader=csv.reader(f)

...:printreader

...:

<_csv.readerobjectat0x10385b050>

Но,еслинужновсеобъектыпередатькуда-тодальше,егоможнопревратитьвсписоктакимобразом:

In[3]:withopen('sw_data.csv')asf:

...:reader=csv.reader(f)

...:printlist(reader)

...:

[['hostname','vendor','model','location'],['sw1','Cisco','3750','London'],['sw

2','Cisco','3850','Liverpool'],['sw3','Cisco','3650','Liverpool'],['sw4','Cis

co','3650','London']]

CSV

244

Page 245: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Запись

Аналогичнымобразом,спомощьюмодуляcsv,можноизаписатьфайлвформатеCSV(файлcsv_write.py):

importcsv

data=[['hostname','vendor','model','location'],

['sw1','Cisco','3750','London,Beststr'],

['sw2','Cisco','3850','Liverpool,Betterstr'],

['sw3','Cisco','3650','Liverpool,Betterstr'],

['sw4','Cisco','3650','London,Beststr']]

withopen('sw_data_new.csv','w')asf:

writer=csv.writer(f)

forrowindata:

writer.writerow(row)

withopen('sw_data_new.csv')asf:

printf.read()

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

Выводбудеттаким:

$pythoncsv_write.py

hostname,vendor,model,location

sw1,Cisco,3750,"London,Beststr"

sw2,Cisco,3850,"Liverpool,Betterstr"

sw3,Cisco,3650,"Liverpool,Betterstr"

sw4,Cisco,3650,"London,Beststr"

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

Такполучилосьиз-затого,чтовпоследнейстрокеестьзапятая.Икавычкиуказываютнато,чтоименноявляетсяцелойстрокой.Когдазапятаянаходятсявкавычках,модульcsvневоспринимаетеёкакразделитель.

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

Модульcsvпозволяетуправлятьэтим.Длятого,чтобывсестрокизаписывалисьвфайлcsvскавычками,надоизменитьскрипттакимобразом(файлcsv_write_ver2.py):

CSV

245

Page 246: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importcsv

data=[['hostname','vendor','model','location'],

['sw1','Cisco','3750','London,Beststr'],

['sw2','Cisco','3850','Liverpool,Betterstr'],

['sw3','Cisco','3650','Liverpool,Betterstr'],

['sw4','Cisco','3650','London,Beststr']]

withopen('sw_data_new.csv','w')asf:

writer=csv.writer(f,quoting=csv.QUOTE_NONNUMERIC)

forrowindata:

writer.writerow(row)

withopen('sw_data_new.csv')asf:

printf.read()

Теперьвыводбудеттаким:

$pythoncsv_write_ver2.py

"hostname","vendor","model","location"

"sw1","Cisco","3750","London,Beststr"

"sw2","Cisco","3850","Liverpool,Betterstr"

"sw3","Cisco","3650","Liverpool,Betterstr"

"sw4","Cisco","3650","London,Beststr"

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

Указаниеразделителя

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

Например,есливфайлеиспользуетсяразделитель;(файлsw_data2.csv):

hostname;vendor;model;location

sw1;Cisco;3750;London

sw2;Cisco;3850;Liverpool

sw3;Cisco;3650;Liverpool

sw4;Cisco;3650;London

Достаточнопростоуказатькакойразделительиспользуетсявreader(файлcsv_read_delimiter.py):

CSV

246

Page 247: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importcsv

withopen('sw_data2.csv')asf:

reader=csv.reader(f,delimiter=';')

forrowinreader:

printrow

CSV

247

Page 248: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

РаботасфайламивформатеJSONJSON(JavaScriptObjectNotation)-этотекстовыйформатдляхраненияиобменаданными.

JSONпосинтаксисуоченьпохожнасловаривPython.Идостаточноудобендлявосприятия.

КакивслучаесCSV,вPythonестьмодуль,которыйпозволяетлегкозаписыватьичитатьданныевформатеJSON.

Чтение

Файлsw_templates.json:

{

"access":[

"switchportmodeaccess",

"switchportaccessvlan",

"switchportnonegotiate",

"spanning-treeportfast",

"spanning-treebpduguardenable"

],

"trunk":[

"switchporttrunkencapsulationdot1q",

"switchportmodetrunk",

"switchporttrunknativevlan999",

"switchporttrunkallowedvlan"

]

}

Длячтения,вмодулеjsonестьдваметода:

json.load()-методсчитываетфайливозвращаетобъектыPythonjson.loads()-методсчитываетстрокувформатеJSONивозвращаетобъектыPython

json.load()

ЧтениефайлавобъектPython:

JSON

248

Page 249: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[1]:importjson

In[2]:withopen('sw_templates.json')asf:

...:templates=json.load(f)

...:

In[3]:templates

Out[3]:

{u'access':[u'switchportmodeaccess',

u'switchportaccessvlan',

u'switchportnonegotiate',

u'spanning-treeportfast',

u'spanning-treebpduguardenable'],

u'trunk':[u'switchporttrunkencapsulationdot1q',

u'switchportmodetrunk',

u'switchporttrunknativevlan999',

u'switchporttrunkallowedvlan']}

In[4]:forsection,commandsintemplates.items():

...:printsection

...:print'\n'.join(commands)

...:

access

switchportmodeaccess

switchportaccessvlan

switchportnonegotiate

spanning-treeportfast

spanning-treebpduguardenable

trunk

switchporttrunkencapsulationdot1q

switchportmodetrunk

switchporttrunknativevlan999

switchporttrunkallowedvlan

Результатчтения-словарь.Обратитевнимание,чтопричтенииизфайлавформатеJSON,строкибудутвunicode.

МынебудемрассматриватьработусUnicode.Хорошийдокументоработесunicode:UnicodeHowTo.

json.loads()

СчитываниестрокивформатеJSONвобъектPython:

JSON

249

Page 250: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[5]:withopen('sw_templates.json')asf:

...:templates=json.loads(f.read())

...:

In[6]:templates

Out[6]:

{u'access':[u'switchportmodeaccess',

u'switchportaccessvlan',

u'switchportnonegotiate',

u'spanning-treeportfast',

u'spanning-treebpduguardenable'],

u'trunk':[u'switchporttrunkencapsulationdot1q',

u'switchportmodetrunk',

u'switchporttrunknativevlan999',

u'switchporttrunkallowedvlan']}

Запись

ЗаписьфайлавформатеJSONтакжеосуществляетсядостаточнолегко.

ДлязаписиинформациивформатеJSONвмодулеjsonтакжедваметода:

json.dump()-методзаписываетобъектPythonвфайл,вформатеJSONjson.dumps()-методвозвращаетстрокувформатеJSON

json.dump()

ЗаписьобъектаPythonвфайл:

JSON

250

Page 251: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[7]:trunk_template=['switchporttrunkencapsulationdot1q',

...:'switchportmodetrunk',

...:'switchporttrunknativevlan999',

...:'switchporttrunkallowedvlan']

...:

...:

...:access_template=['switchportmodeaccess',

...:'switchportaccessvlan',

...:'switchportnonegotiate',

...:'spanning-treeportfast',

...:'spanning-treebpduguardenable']

...:

...:to_json={'trunk':trunk_template,'access':access_template}

...:

In[8]:withopen('sw_templates.json','w')asf:

...:json.dump(to_json,f)

...:

In[9]:catsw_templates.json

{"access":["switchportmodeaccess","switchportaccessvlan","switchportnonegotiat

e","spanning-treeportfast","spanning-treebpduguardenable"],"trunk":["switchport

trunkencapsulationdot1q","switchportmodetrunk","switchporttrunknativevlan99

9","switchporttrunkallowedvlan"]}

КогданужнозаписатьинформациювформатеJSONвфайл,лучшеиспользоватьметодdump.

json.dumps()

ПреобразованиеобъектавстрокувформатеJSON:

In[10]:withopen('sw_templates.json','w')asf:

...:f.write(json.dumps(to_json))

...:

In[11]:catsw_templates.json

{"access":["switchportmodeaccess","switchportaccessvlan","switchportnonegotiat

e","spanning-treeportfast","spanning-treebpduguardenable"],"trunk":["switchport

trunkencapsulationdot1q","switchportmodetrunk","switchporttrunknativevlan99

9","switchporttrunkallowedvlan"]}

Методjson.dumps()подходитдляситуаций,когданадовернутьстрокувформатеJSON.

Дополнительныепараметрыметодовзаписи

JSON

251

Page 252: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Методамdumpиdumpsможнопередаватьдополнительныепараметрыдляуправленияформатомвывода.

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

Ксчастью,модульjsonпозволяетуправлятьподобнымивещами.

Передавдополнительныепараметрыметодуdump(илиметодуdumps),можнополучитьболееудобныйдлячтениевывод(файлjson_write_ver2.py):

In[13]:withopen('sw_templates.json','w')asf:

...:json.dump(to_json,f,sort_keys=True,indent=2)

...:

Теперьсодержимоефайлаsw_templates.jsonвыглядиттак:

In[14]:catsw_templates.json

{

"access":[

"switchportmodeaccess",

"switchportaccessvlan",

"switchportnonegotiate",

"spanning-treeportfast",

"spanning-treebpduguardenable"

],

"trunk":[

"switchporttrunkencapsulationdot1q",

"switchportmodetrunk",

"switchporttrunknativevlan999",

"switchporttrunkallowedvlan"

]

}

Изменениетипаданных

Ещеодинважныйаспектпреобразованияданныхвформатjson:данныеневсегдабудуттогожетипа,чтоисходныеданныевPython.

Такаяситуацияужевозникаласостроками-онибыливформатеunicode.Крометого,призаписивJSONкортежей,онипревращаютсявсписки.

Например:

JSON

252

Page 253: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[15]:importjson

In[16]:trunk_template=('switchporttrunkencapsulationdot1q',

...:'switchportmodetrunk',

...:'switchporttrunknativevlan999',

...:'switchporttrunkallowedvlan')

In[17]:printtype(trunk_template)

<type'tuple'>

In[18]:withopen('trunk_template.json','w')asf:

...:json.dump(trunk_template,f,sort_keys=True,indent=2)

...:

In[19]:cattrunk_template.json

[

"switchporttrunkencapsulationdot1q",

"switchportmodetrunk",

"switchporttrunknativevlan999",

"switchporttrunkallowedvlan"

]

In[20]:templates=json.load(open('trunk_template.json'))

In[21]:type(templates)

Out[21]:list

In[22]:printtemplates

[u'switchporttrunkencapsulationdot1q',u'switchportmodetrunk',u'switchporttrunk

nativevlan999',u'switchporttrunkallowedvlan']

Ограничениепотипамданных

ВформатJSONнельзязаписатьсловарьукоторогоключи-кортежи:

In[23]:to_json={('trunk','cisco'):trunk_template,'access':access_template}

In[24]:withopen('sw_templates.json','w')asf:

...:json.dump(to_json,f)

...:

...

TypeError:key('trunk','cisco')isnotastring

Но,спомощьюдополнительногопараметраможноигнорироватьподобныеключи:

JSON

253

Page 254: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[25]:to_json={('trunk','cisco'):trunk_template,'access':access_template}

In[26]:withopen('sw_templates.json','w')asf:

...:json.dump(to_json,f,skipkeys=True)

...:

...:

In[27]:catsw_templates.json

{"access":["switchportmodeaccess","switchportaccessvlan","switchportnonegotiat

e","spanning-treeportfast","spanning-treebpduguardenable"]}

JSON

254

Page 255: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

РаботасфайламивформатеYAMLYAML(YAMLAin'tMarkupLanguage)-ещеодинтекстовыйформатдлязаписиданных.

YAMLболееприятендлявосприятиячеловеком,чемJSON,поэтомуегочастоиспользуютдляописаниясценариеввПО.Например,вAnsible.

СинтаксисYAML

КакиPython,YAMLиспользуетотступыдляуказанияструктурыдокумента.НовYAMLможноиспользоватьтолькопробелыинельзяиспользоватьзнакитабуляции.

ЕщеоднасхожестьсPython:комментарииначинаютсяссимвола#ипродолжаютсядоконцастроки.

ПройдемсяпотомукаквYAMLзаписываютсяразличныеформатыданных.

Список

Списокможетбытьзаписанводнустроку:

[switchportmodeaccess,switchportaccessvlan,switchportnonegotiate,spanning-tree

portfast,spanning-treebpduguardenable]

Иликаждыйэлементспискавсвоейстроке:

-switchportmodeaccess

-switchportaccessvlan

-switchportnonegotiate

-spanning-treeportfast

-spanning-treebpduguardenable

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

Словарь

Словарьтакжеможетбытьзаписанводнустроку:

{vlan:100,name:IT}

YAML

255

Page 256: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Илиблоком:

vlan:100

name:IT

Строки

СтрокивYAMLнеобязательнобратьвкавычки.Этоудобно,ноиногдавсёжеследуетиспользоватькавычки.Например,когдавстрокеиспользуетсякакой-тоспециальныйсимвол(специальныйдляYAML).

Такуюстроку,например,нужновзятьвкавычки,чтобыонабылакорректновоспринятаYAML:

command:"shinterface|includeQueueingstrategy:"

Комбинацияэлементов

Словарь,вкотороместьдваключа:accessиtrunk.Значения,которыесоответствуютэтимключам-спискикоманд:

access:

-switchportmodeaccess

-switchportaccessvlan

-switchportnonegotiate

-spanning-treeportfast

-spanning-treebpduguardenable

trunk:

-switchporttrunkencapsulationdot1q

-switchportmodetrunk

-switchporttrunknativevlan999

-switchporttrunkallowedvlan

Списоксловарей:

YAML

256

Page 257: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

-BS:1550

IT:791

id:11

name:Liverpool

to_id:1

to_name:LONDON

-BS:1510

IT:793

id:12

name:Bristol

to_id:1

to_name:LONDON

-BS:1650

IT:892

id:14

name:Coventry

to_id:2

to_name:Manchester

МодульPyYAML

ДляработысYAMLвPythonиспользуетсямодульPyYAML.Онневходитвстандартнуюбиблиотекумодулей,поэтомуегонужноустановить:

pipinstallpyyaml

Работасниманалогичнамодулямcsvиjson.

ЧтениеизYAML

ПопробуемпреобразоватьданныеизфайлаYAMLвобъектыPython.

Файлinfo.yaml:

YAML

257

Page 258: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

-BS:1550

IT:791

id:11

name:Liverpool

to_id:1

to_name:LONDON

-BS:1510

IT:793

id:12

name:Bristol

to_id:1

to_name:LONDON

-BS:1650

IT:892

id:14

name:Coventry

to_id:2

to_name:Manchester

ЧтениеизYAMLвыполняетсяоченьпросто:

In[1]:importyaml

In[2]:withopen('info.yaml')asf:

...:templates=yaml.load(f)

...:

In[3]:templates

Out[3]:

[{'BS':1550,

'IT':791,

'id':11,

'name':'Liverpool',

'to_id':1,

'to_name':'LONDON'},

{'BS':1510,

'IT':793,

'id':12,

'name':'Bristol',

'to_id':1,

'to_name':'LONDON'},

{'BS':1650,

'IT':892,

'id':14,

'name':'Coventry',

'to_id':2,

'to_name':'Manchester'}]

YAML

258

Page 259: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ФорматYAMLоченьудобендляхраненияразличныхпараметров.Особенно,еслионизаполняютсявручную.

ЗаписьвYAML

ЗаписьобъектовPythonвYAML(файлyaml_write.py):

importyaml

trunk_template=['switchporttrunkencapsulationdot1q',

'switchportmodetrunk',

'switchporttrunknativevlan999',

'switchporttrunkallowedvlan']

access_template=['switchportmodeaccess',

'switchportaccessvlan',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

to_yaml={'trunk':trunk_template,'access':access_template}

withopen('sw_templates.yaml','w')asf:

f.write(yaml.dump(to_yaml))

withopen('sw_templates.yaml')asf:

printf.read()

Файлsw_templates.yamlвыглядиттакимобразом:

access:[switchportmodeaccess,switchportaccessvlan,switchportnonegotiate,spann

ing-tree

portfast,spanning-treebpduguardenable]

trunk:[switchporttrunkencapsulationdot1q,switchportmodetrunk,switchporttrunk

nativevlan999,switchporttrunkallowedvlan]

Тоесть,поумолчанию,списокзаписалсяводнустроку.Этоможноизменить.

Длятого,чтобыизменитьформатзаписи,надодобавитьпараметрdefault_flow_style=False(файлyaml_write_ver2.py):

YAML

259

Page 260: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importyaml

trunk_template=['switchporttrunkencapsulationdot1q',

'switchportmodetrunk',

'switchporttrunknativevlan999',

'switchporttrunkallowedvlan']

access_template=['switchportmodeaccess',

'switchportaccessvlan',

'switchportnonegotiate',

'spanning-treeportfast',

'spanning-treebpduguardenable']

to_yaml={'trunk':trunk_template,'access':access_template}

withopen('sw_templates.yaml','w')asf:

f.write(yaml.dump(to_yaml,default_flow_style=False))

withopen('sw_templates.yaml')asf:

printf.read()

Теперьсодержимоефайлаsw_templates.yamlвыглядиттакимобразом:

access:

-switchportmodeaccess

-switchportaccessvlan

-switchportnonegotiate

-spanning-treeportfast

-spanning-treebpduguardenable

trunk:

-switchporttrunkencapsulationdot1q

-switchportmodetrunk

-switchporttrunknativevlan999

-switchporttrunkallowedvlan

YAML

260

Page 261: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание10.1

Вэтомзаданиинужно:

взятьсодержимоенесколькихфайловсвыводомкомандыshversionраспарситьвыводкомандыспомощьюрегулярныхвыраженийиполучитьинформациюобустройствезаписатьполученнуюинформациювфайлвCSVформате

Длявыполнениязаданиянужносоздатьдвефункции.

Функцияparse_sh_version:

ожидаетаргументoutputвкоторомнаходитсявыводкомандыshversionобрабатываетвывод,спомощьюрегулярныхвыраженийвозвращаеткортежизтрёхэлементов:

ios-вформате"12.4(5)T"image-вформате"flash:c2800-advipservicesk9-mz.124-5.T.bin"uptime-вформате"5days,3hours,3minutes"

Функцияwrite_to_csv:

ожидаетдвааргумента:

Задания

261

Page 262: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

имяфайла,вкоторыйбудетзаписанаинформациявформатеCSVданныеввидеспискасписков,где:

первыйсписок-заголовкистолбцов,остальныесписки-содержимое

функциязаписываетсодержимоевфайл,вформатеCSVиничегоневозвращает

Остальноесодержимоескриптаможетбытьвскрипте,аможетбытьвещёоднойфункции.

Скриптдолжен:

обработатьинформациюизкаждогофайласвыводомshversion:sh_version_r1.txt,sh_version_r2.txt,sh_version_r3.txt

спомощьюфункцииparse_sh_version,изкаждоговыводадолжнабытьполученаинформацияios,image,uptimeизименифайланужнополучитьимяхостапослеэтоговсяинформациядолжнабытьзаписанавфайлrouters_inventory.csv

Вскрипте,спомощьюмодуляglob,создансписокфайлов,имякоторыхначинаетсянаsh_vers.Выможетераскомментироватьстрокуprintsh_version_files,чтобыпосмотретьсодержимоесписка.

Крометого,создансписокзаголовков(headers),которыйдолженбытьзаписанвCSV.

importglob

sh_version_files=glob.glob('sh_vers*')

#printsh_version_files

headers=['hostname','ios','image','uptime']

Задание10.2

Создатьфункции:

generate_access_config-генерируетконфигурациюдляaccess-портов,наосновесловарейaccessиpsecurityизфайлаsw_templates.yamlgenerate_trunk_config-генерируетконфигурациюдляtrunk-портов,наосновесловаряtrunkизфайлаsw_templates.yamlgenerate_mngmt_config-генерируетконфигурациюменеджментнастроек,наосновесловаряmngmtизфайлаtemplates.yamlgenerate_ospf_config-генерируетконфигурациюospf,наосновесловаряospfизфайлаtemplates.yamlgenerate_alias_config-генерируетконфигурациюalias,наосновесловаряaliasиз

Задания

262

Page 263: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

файлаtemplates.yamlgenerate_switch_config-генерируетконфигурациюкоммутатора,взависимостиотпереданныхпараметров,используетдляэтогоостальныефункции

importyaml

access_dict={'FastEthernet0/12':10,

'FastEthernet0/14':11,

'FastEthernet0/16':17,

'FastEthernet0/17':150}

trunk_dict={'FastEthernet0/1':[10,20,30],

'FastEthernet0/2':[11,30],

'FastEthernet0/4':[17]}

defgenerate_access_config(access,psecurity=False):

"""

access-словарьaccess-портов,

длякоторыхнеобходимосгенерироватьконфигурацию,вида:

{'FastEthernet0/12':10,

'FastEthernet0/14':11,

'FastEthernet0/16':17}

psecurity-контролируетнужналинастройкаPortSecurity.ПоумолчаниюзначениеF

alse

-еслизначениеTrue,тонастройкавыполняетсясдобавлениемшаблонаport_secu

rity

-еслизначениеFalse,тонастройканевыполняется

Возвращаетсписоквсехкоманд,которыебылисгенерированынаосновешаблона

"""

pass

defgenerate_trunk_config(trunk):

"""

trunk-словарьtrunk-портов,

длякоторыхнеобходимосгенерироватьконфигурацию,вида:

{'FastEthernet0/1':[10,20],

'FastEthernet0/2':[11,30],

'FastEthernet0/4':[17]}

Возвращаетсписоквсехкоманд,которыебылисгенерированынаосновешаблона

"""

pass

defgenerate_ospf_config(filename):

"""

filename-имяфайлавформатеYAML,вкоторомнаходитсяшаблонospf.

Возвращаетсписоквсехкоманд,которыебылисгенерированынаосновешаблона

"""

Задания

263

Page 264: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

templates=yaml.load(open(filename))

defgenerate_mngmt_config(filename):

"""

filename-имяфайлавформатеYAML,вкоторомнаходитсяшаблонmngmt.

Возвращаетсписоквсехкоманд,которыебылисгенерированынаосновешаблона

"""

pass

defgenerate_alias_config(filename):

"""

filename-имяфайлавформатеYAML,вкоторомнаходитсяшаблонalias.

Возвращаетсписоквсехкоманд,которыебылисгенерированынаосновешаблона

"""

pass

defgenerate_switch_config(access=True,psecurity=False,trunk=True,

ospf=True,mngmt=True,alias=False):

"""

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

Поумолчанию,будетнастроеновсе,кромеpsecurityиalias.

Возвращаетсписоквсехкоманд,которыебылисгенерированынаосновешаблона

"""

pass

#Сгенерироватьконфигурациидляразныхкоммутаторов:

sw1=generate_switch_config()

sw2=generate_switch_config(psecurity=True,alias=True)

sw3=generate_switch_config(ospf=False)

Задание10.3

Создатьфункциюparse_sh_cdp_neighbors,котораяобрабатываетвыводкомандыshowcdpneighbors.

Функцияожидает,какаргумент,выводкомандыоднойстрокой.

Функциядолжнавозвращатьсловарь,которыйописываетсоединениямеждуустройствами.

Например,есликакаргументбылпередантакойвывод:

Задания

264

Page 265: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

R4>showcdpneighbors

DeviceIDLocalIntrfceHoldtmeCapabilityPlatformPortID

R5Fa0/1122RSI2811Fa0/1

R6Fa0/2143RSI2811Fa0/0

Функциядолжнавернутьтакойсловарь:

{'R4':{'Fa0/1':{'R5':'Fa0/1'},

'Fa0/2':{'R6':'Fa0/0'}}}

Проверитьработуфункциинасодержимомфайлаsh_cdp_n_sw1.txt

Задание10.3a

Спомощьюфункцииparse_sh_cdp_neighborsиззадания10.3,обработатьвыводкомандыshcdpneighborизфайлов:

sh_cdp_n_sw1.txtsh_cdp_n_r1.txtsh_cdp_n_r2.txtsh_cdp_n_r3.txtsh_cdp_n_r4.txtsh_cdp_n_r5.txtsh_cdp_n_r6.txt

Объединитьвсесловари,которыевозвращаетфункцияparse_sh_cdp_neighbors,водинсловарьtopologyизаписатьегосодержимоевфайлtopology.yaml.

Структурасловаряtopologyдолжнабытьтакой:

{'R4':{'Fa0/1':{'R5':'Fa0/1'},

'Fa0/2':{'R6':'Fa0/0'}},

'R5':{'Fa0/1':{'R4':'Fa0/1'}},

'R6':{'Fa0/0':{'R4':'Fa0/2'}}}

Некопироватькодфункцииparse_sh_cdp_neighbors

Задание10.3b

Переделатьфункциональностьскриптаиззадания10.3a,вфункциюgenerate_topology_from_cdp.

Задания

265

Page 266: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Функцияgenerate_topology_from_cdpдолжнабытьсозданаспараметрами:

list_of_files-списокфайловизкоторыхнадосчитатьвыводкомандыshcdpneighborsave_to_file-этотпараметруправляеттем,будетлизаписанвфайл,итоговыйсловарь

значениепоумолчанию-Truetopology_filename-имяфайла,вкоторыйсохранитсятопология.

поумолчанию,должноиспользоватьсяимяtopology.yaml.топологиясохраняетсятолько,еслиаргументsave_to_fileуказанравнымTrue

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

Проверитьработуфункцииgenerate_topology_from_cdpнафайлах:

sh_cdp_n_sw1.txtsh_cdp_n_r1.txtsh_cdp_n_r2.txtsh_cdp_n_r3.txtsh_cdp_n_r4.txtsh_cdp_n_r5.txtsh_cdp_n_r6.txt

Записатьполученныйсловарьвфайлtopology.yaml.

Некопироватькодфункцииparse_sh_cdp_neighbors

Задание10.3c

Спомощьюфункцииdraw_topologyизфайлаdraw_network_graph.pyсгенерироватьтопологию,котораясоответствуетописаниювфайлеtopology.yaml

Обратитевниманиенато,какойформатданныхожидаетфункцияdraw_topology.Описаниетопологииизфайлаtopology.yamlнужнопреобразоватьсоответствующимобразом,чтобыиспользоватьфункциюdraw_topology.

Длярешениязаданияможносоздатьлюбыевспомогательныефункции.

Витоге,должнобытьсгенерированоизображениетопологии.Результатдолженвыглядетьтакже,каксхемавфайлеtask_10_3c_topology.svg

Некопироватькодфункцииdraw_topology.

Длявыполненияэтогозадания,долженбытьустановленgraphviz:pipinstallgraphviz

Задания

266

Page 267: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Задания

267

Page 268: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

РаботасбазамиданныхИспользованиебазданных-этоещеодинспособхраненияинформации.

Базаданных(БД)-этоданные,которыехранятсявсоответствиисопределеннойсхемой.Вэтойсхемекаким-тообразомописанысоотношениямеждуданными.

ЯзыкБД(лингвистическиесредства)-используетсядляописанияструктурыБД,управленияданными(добавление,изменение,удаление,получение),управленияправамидоступакБДиееобъектам,управлениятранзакциями.

Системауправлениябазамиданных(СУБД)-этопрограммныесредства,которыедаютвозможностьуправлятьБД.СУБДдолжныподдерживатьсоответствующийязык(языки)дляуправленияБД.

Вразговорнойречи(ноивлитературетакже)частоможновстретитьиспользованиетерминаБД,вместотерминаСУБД.Этонесовсемкорректно,но,темнеменее,встречаетсядовольночасто.

11.Работасбазамиданных

268

Page 269: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

SQLSQL(structuredquerylanguage)-используетсядляописанияструктурыБД,управленияданными(добавление,изменение,удаление,получение),управленияправамидоступакБДиееобъектам,управлениятранзакциями.

ЯзыкSQLподразделяетсянатакиекатегории:

DDL(DataDefinitionLanguage)-языкописанияданныхDML(DataManipulationLanguage)-языкманипулированияданнымиDCL(DataControlLanguage)-языкопределениядоступакданнымTCL(TransactionControlLanguage)-языкуправлениятранзакциями

Вкаждойкатегорииестьсвоиоператоры(перечисленыневсеоператоры):

DDLCREATE-созданиеновойтаблицы,СУБД,схемыALTER-изменениесуществующейтаблицы,колонкиDROP-удалениесуществующихобъектовизСУБД

DMLSELECT-выборданныхINSERT-добавлениеновыхданныхUPDATE-обновлениесуществующихданныхDELETE-удалениеданных

DCLGRANT-предоставлениепользователямразрешенияначтение/записьопределенныхобъектоввСУБДREVOKE-отзывранеепредоставленыхразрешений

TCLCOMMITTransaction-применениетранзакцииROLLBACKTransaction-откатвсехизмененийсделанныхвтекущейтранзакции

SQLиPython

ДляработысреляционнойСУБДвPythonможноиспользоватьдваподхода:

работатьсбиблиотекой,котораясоответствуетконкретнойСУБДииспользоватьдляработысБДязыкSQL

Например,дляработысSQLiteиспользуетсямодульsqlite3работатьсORM,котораяиспользуетобъектно-ориентированныйподходдля

SQL

269

Page 270: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

работысБДНапример,SQLAlchemy

SQL

270

Page 271: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

SQLiteSQLite—встраиваемаявпроцессреализацияSQL-машины.

СловоSQL-серверздесьнеиспользуем,потомучтокактаковойсервертамненужен—весьфункционал,которыйвстраиваетсявSQL-сервер,реализованвнутрибиблиотеки(и,соответственно,внутрипрограммы,котораяеёиспользует).

Напрактике,SQLiteчастоиспользуетсякаквстроеннаяСУБДвприложениях.

SQLiteCLI

ВкомплектепоставкиSQLiteидёттакжеутилитадляработысSQLiteвкоманднойстроке.Утилитапредставленаввидеисполняемогофайлаsqlite3(sqlite3.exeдляWindows)исеепомощьюможновручнуювыполнятькомандыSQL.

СпомощьюэтойутилитыоченьудобнопроверятьправильностькомандSQL,атакжевцеломзнакомитьсясязыкомSQL.

ПопробуемспомощьюэтойутилитыразобратьсясбазовымикомандамиSQL,которыепонадобятсядляработысБД.

ДляначаларазберемсякаксоздаватьБД.

ЕсливыиспользуетеLinuxилиMacOS,то,скореевсего,sqlite3установлен.ЕсливыиспользуетеWindows,томожноскачатьsqlite3тут.

ДлятогочтобысоздатьБД(илиоткрытьужесозданную)надопростовызватьsqlite3такимобразом:

$sqlite3testDB.db

SQLiteversion3.7.132012-06-1102:05:22

Enter".help"forinstructions

EnterSQLstatementsterminatedwitha";"

sqlite>

Внутриsqlite3можновыполнятькомандыSQLили,такназываемые,метакоманды(илиdot-команды).

Метакоманды

SQLite

271

Page 272: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Кметакомандамотносятсянесколькоспециальныхкоманд,дляработысSQLite.Ониотносятсятолькокутилитеsqlite3,анекSQLязыку.Вконцеэтихкоманд;ставитьненужно.

Примерыметакоманд:

.help-подсказкасоспискомвсехметакоманд.exitили.quit-выходизсессииsqlite3.databases-показываетприсоединенныеБД.tables-показываетдоступныетаблицы

Примерывыполнения:

sqlite>.help

.backup?DB?FILEBackupDB(default"main")toFILE

.bailON|OFFStopafterhittinganerror.DefaultOFF

.databasesListnamesandfilesofattacheddatabases

...

sqlite>.databases

seqnamefile

---------------------------------------------

0main/home/nata/py_for_ne/db/db_article/testDB.db

SQLite

272

Page 273: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ОсновыSQL(вsqlite3CLI)ВэтомразделерассматриваетсясинтаксисязыкаSQL.

ЕсливызнакомысбазовымсинтаксисомSQL,этотразделможнопропуститьисразуперейтикразделу"Модульsqlite3".

ОсновыSQL(вsqlite3CLI)

273

Page 274: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

CREATE

Операторcreateпозволяетсоздаватьтаблицы.

Создадимтаблицуswitch,вкоторойхранитсяинформацияокоммутаторах:

sqlite>CREATEtableswitch(

...>mactextprimarykey,

...>hostnametext,

...>modeltext,

...>locationtext

...>);

Аналогичноможнобылосоздатьтаблицуитакимобразом:

sqlite>createtableswitch(mactextprimarykey,hostnametext,modeltext,location

text);

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

Крометого,полеmacявляетсяпервичнымключом.Этоавтоматическизначит,что:

поледолжнобытьуникальнымвнемнеможетнаходитьсязначениеNULL

Вэтомпримереэтовполнелогично,таккакMAC-адресдолженбытьуникальным.

Наданныймоментзаписейвтаблиценет,естьтолькоееопределение.Просмотретьопределениеможнотакойкомандой:

sqlite>.schemaswitch

CREATETABLEswitch(

mactextprimarykey,

hostnametext,

modeltext,

locationtext

);

CREATE

274

Page 275: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

DROP

Операторdropудаляеттаблицувместесосхемойивсемиданными.

Удалитьтаблицуможнотак:

sqlite>DROPtableswitch;

DROP

275

Page 276: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

INSERT

Операторinsertиспользуетсядлядобавленияданныхвтаблицу.

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

Еслиуказываютсязначениядлявсехполей,добавитьзаписьможнотакимобразом(порядокполейдолженсоблюдаться):

sqlite>INSERTintoswitchvalues('0000.AAAA.CCCC','sw1','Cisco3750','London,Gre

enStr');

Еслинужноуказатьневсеполя,илиуказатьихвпроизвольномпорядке,используетсятакаязапись:

sqlite>INSERTintoswitch(mac,model,location,hostname)

...>values('0000.BBBB.CCCC','Cisco3850','London,GreenStr','sw5');

INSERT

276

Page 277: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

SELECT

Операторselectпозволяетзапрашиватьинформациювтаблице.

Например:

sqlite>SELECT*fromswitch;

0000.AAAA.CCCC|sw1|Cisco3750|London,GreenStr

0000.BBBB.CCCC|sw5|Cisco3850|London,GreenStr

select*означает,чтонужновывестивсеполятаблицы.Следом,указываетсяизкакойтаблицызапрашиваютсяданные:fromswitch.

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

sqlite>.headersON

sqlite>SELECT*fromswitch;

mac|hostname|model|location

0000.AAAA.CCCC|sw1|Cisco3750|London,GreenStr

0000.BBBB.CCCC|sw5|Cisco3850|London,GreenStr

Теперьотобразилисьзаголовки,новцелом,отображениенеоченьприятное.Хотелосьбы,чтобывсевыводилосьввидеколонок.Заформатированиевыводаотвечаеткоманда.mode.

Режим.modecolumnвключаетотображениеввидеколонок:

sqlite>.modecolumn

sqlite>SELECT*fromswitch;

machostnamemodellocation

---------------------------------------------------

0000.AAAA.CCCCsw1Cisco3750London,GreenStr

0000.BBBB.CCCCsw5Cisco3850London,GreenStr

Прижелании,можновыставитьиширинуколонок.Дляэтогоиспользуетсякоманда.width.Например,попробуйтевыставить.width20.

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

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

SELECT

277

Page 278: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

.headerson

.modecolumn

SELECT

278

Page 279: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

WHERE

ОператорWHEREиспользуетсядляуточнениязапроса.Спомощьюэтогооператораможноуказыватьопределенныеусловия,покоторымотбираютсяданные.Еслиусловиевыполнено,возвращаетсясоответствующеезначениеизтаблицы,еслинет,невозвращается.

Например,таблицаswitchвыглядиттак:

sqlite>SELECT*fromswitch;

machostnamemodellocationmngmt_ipmngmt_vidmng

mt_vname

--------------------------------------------------------------------------

--------

0000.DDDD.DDDDsw1Cisco3850London,GreenStr10.255.0.1255MNG

MT

0000.BBBB.CCCCsw5Cisco3850London,GreenStr10.255.0.5255MNG

MT

0000.2222.CCCCsw2Cisco3750London,GreenStr10.255.0.2255MNG

MT

0000.3333.CCCCsw3Cisco3750London,GreenStr10.255.0.3255MNG

MT

0000.4444.CCCCsw4Cisco3650London,GreenStr10.255.0.4255MNG

MT

Показатьтолькотекоммутаторы,моделькоторых3750:

sqlite>SELECT*fromswitchWHEREmodel='Cisco3750';

machostnamemodellocationmngmt_ipmngmt_vidmng

mt_vname

--------------------------------------------------------------------------

--------

0000.2222.CCCCsw2Cisco3750London,GreenStr10.255.0.2255MNG

MT

0000.3333.CCCCsw3Cisco3750London,GreenStr10.255.0.3255MNG

MT

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

LIKEспомощьюсимволов_и%указываетначтодолжнобытьпохожезначение:

_-обозначаетодинсимволиличисло%-обозначаетноль,одинилимногосимволов

WHERE

279

Page 280: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Например,есливтаблицеполеmodelзаписановразномформате:

sqlite>SELECT*fromswitch;

machostnamemodellocationmngmt_ipmngmt_vidmng

mt_vname

--------------------------------------------------------------------------

--------

0000.DDDD.DDDDsw1Cisco3850London,GreenStr10.255.0.1255MNG

MT

0000.BBBB.CCCCsw5Cisco3850London,GreenStr10.255.0.5255MNG

MT

0000.2222.CCCCsw2C3750London,GreenStr10.255.0.2255MNG

MT

0000.3333.CCCCsw3Cisco3750London,GreenStr10.255.0.3255MNG

MT

0000.4444.CCCCsw4Cisco3650London,GreenStr10.255.0.4255MNG

MT

ВтакомвариантепредыдущийзапроссоператоромWHEREнепоможет:

sqlite>SELECT*fromswitchWHEREmodel='Cisco3750';

machostnamemodellocationmngmt_ipmngmt_vidmng

mt_vname

--------------------------------------------------------------------------

--------

0000.3333.CCCCsw3Cisco3750London,GreenStr10.255.0.3255MNG

MT

Но,есливместесоператоромWHEREиспользоватьоператорLIKE:

sqlite>SELECT*fromswitchWHEREmodelLIKE'%3750';

machostnamemodellocationmngmt_ipmngmt_vidmng

mt_vname

--------------------------------------------------------------------------

--------

0000.2222.CCCCsw2C3750London,GreenStr10.255.0.2255MNG

MT

0000.3333.CCCCsw3Cisco3750London,GreenStr10.255.0.3255MNG

MT

WHERE

280

Page 281: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ALTER

Операторalterпозволяетменятьсуществующуютаблицу:добавлятьновыеколонкиилипереименовыватьтаблицу.

Добавимвтаблицуновыеполя:

mngmt_ip-IP-адрескоммутаторавменеджментVLANmngmt_vid-VLANID(номерVLAN)дляменеджментVLANmngmt_vname-ИмяVLAN,которыйиспользуетсядляменеджмента

ДобавлениезаписейспомощьюкомандыALTER:

sqlite>ALTERtableswitchADDCOLUMNmngmt_iptext;

sqlite>ALTERtableswitchADDCOLUMNmngmt_vidvarchar(10);

sqlite>ALTERtableswitchADDCOLUMNmngmt_vnametext;

Теперьтаблицавыглядиттак(новыеполяустановленывзначениеNULL):

sqlite>SELECT*fromswitch;

machostnamemodellocationmngmt_ipmngmt_vidmng

mt_vname

--------------------------------------------------------------------------

--------

0000.AAAA.CCCCsw1Cisco3750London,GreenStr

0000.BBBB.CCCCsw5Cisco3850London,GreenStr

ALTER

281

Page 282: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

UPDATE

Операторupdateиспользуетсядляизменениясуществующейзаписитаблицы.

Обычно,updateиспользуетсявместесоператоромwhere,чтобыуточнитькакуюименнозаписьнеобходимоизменить.

Например,предположим,чтоsw1былзамененсмодели3750намодель3850.Соответственно,изменилосьнетолькополемодель,ноиполеMAC-адрес.

Внесениеизменений:

sqlite>UPDATEswitchsetmodel='Cisco3850'wherehostname='sw1';

sqlite>UPDATEswitchsetmac='0000.DDDD.DDDD'wherehostname='sw1';

Результатбудеттаким:

sqlite>SELECT*fromswitch;

machostnamemodellocationmngmt_ipmngmt_vidmng

mt_vname

--------------------------------------------------------------------------

--------

0000.DDDD.DDDDsw1Cisco3850London,GreenStr10.255.0.1255MNG

MT

0000.BBBB.CCCCsw5Cisco3850London,GreenStr10.255.0.5255MNG

MT

Обновлениенесколькихполей:

sqlite>UPDATEswitchsetmac='0000.EEEE.EEEE',model='Cisco3750'wherehostname

='sw1';

sqlite>select*fromswitch;

machostnamemodellocationmngmt_ipmngmt_vidmng

mt_vname

--------------------------------------------------------------------------

--------

0000.EEEE.EEEEsw1Cisco3750London,GreenStr10.255.0.1255MNG

MT

0000.BBBB.CCCCsw5Cisco3850London,GreenStr10.255.0.5255MNG

MT

UPDATE

282

Page 283: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

REPLACE

Операторreplaceиспользуетсядлядобавленияилизаменыданныхвтаблице.

ОператорreplaceможетподдерживатьсяневовсехСУБД.

Когдавозникаетнарушениеусловияуникальностиполя,выражениесоператоромreplace:

удаляетсуществующуюстроку,котораявызваланарушениедобавляетновуюстроку

Увыраженияreplaceестьдвавида:

sqlite>INSERTORREPLACEINTOswitch

...>VALUES('0000.DDDD.CCCC','sw4','Cisco3850','London,GreenStr');

Илиболеекороткийвариант:

sqlite>REPLACEINTOswitch

...>VALUES('0000.DDDD.CCCC','sw4','Cisco3850','London,GreenStr');

Примериспользованияоператораreplace

Примертаблицы:

sqlite>createtableswitch(mactextprimarykey,hostnametext,modeltext,location

text);

sqlite>INSERTintoswitchvalues('0000.AAAA.CCCC','sw1','Cisco3750','London,Gre

enStr');

sqlite>INSERTintoswitchvalues('0000.BBBB.CCCC','sw2','Cisco3850','London,Gre

enStr');

sqlite>INSERTintoswitchvalues('0000.CCCC.CCCC','sw3','Cisco3850','London,Gre

enStr');

sqlite>select*fromswitch;

machostnamemodellocation

---------------------------------------------------

0000.AAAA.CCCCsw1Cisco3750London,GreenStr

0000.BBBB.CCCCsw2Cisco3850London,GreenStr

0000.CCCC.CCCCsw3Cisco3850London,GreenStr

Придобавлениизаписи,длякоторойневозникаетнарушенияуникальностиполя,replaceработаеткакобычныйinsert:

REPLACE

283

Page 284: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

sqlite>replaceintoswitchvalues('0000.DDDD.CCCC','sw4','Cisco3850','London,Gr

eenStr');

sqlite>select*fromswitch;

machostnamemodellocation

---------------------------------------------------

0000.AAAA.CCCCsw1Cisco3750London,GreenStr

0000.BBBB.CCCCsw2Cisco3850London,GreenStr

0000.CCCC.CCCCsw3Cisco3850London,GreenStr

0000.DDDD.CCCCsw4Cisco3850London,GreenStr

Но,есливозникаетнарушение,выполняетсязамена:

sqlite>insertorreplaceintoswitchvalues('0000.DDDD.CCCC','sw5','Cisco3850','

London,GreenStr');

sqlite>select*fromswitch;

machostnamemodellocation

---------------------------------------------------

0000.AAAA.CCCCsw1Cisco3750London,GreenStr

0000.BBBB.CCCCsw2Cisco3850London,GreenStr

0000.CCCC.CCCCsw3Cisco3850London,GreenStr

0000.DDDD.CCCCsw5Cisco3850London,GreenStr

ВданномслучаеMAC-адресвновойзаписисовпадаетсужесуществующей,поэтомупроисходитзамена.

Еслибылиуказаныневсеполя,вновойзаписибудуттолькотеполя,которыебылиуказаны:

sqlite>replaceintoswitch(mac,hostname,model)

...>values('0000.DDDD.CCCC','sw5','Cisco3850');

sqlite>select*fromswitch;

machostnamemodellocation

---------------------------------------------------

0000.AAAA.CCCCsw1Cisco3750London,GreenStr

0000.BBBB.CCCCsw2Cisco3850London,GreenStr

0000.CCCC.CCCCsw3Cisco3850London,GreenStr

0000.DDDD.CCCCsw5Cisco3850

Этосвязаностем,чтоreplaceсначалаудаляетсуществующуюзапись.

REPLACE

284

Page 285: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

DELETE

Операторdeleteиспользуетсядляудалениязаписей.

Какправило,ониспользуетсявместесоператоромwhere.

Например:

sqlite>DELETEfromswitchwherehostname='sw4';

DELETE

285

Page 286: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ORDERBY

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

Например,выведемвсезаписивтаблицеswitchиотсортируемихпоименикоммутаторов:

sqlite>SELECT*fromswitchORDERBYhostnameASC;

machostnamemodellocationmngmt_ipmngmt_vidmng

mt_vname

--------------------------------------------------------------------------

--------

0000.DDDD.DDDDsw1Cisco3850London,GreenStr10.255.0.1255MNG

MT

0000.2222.CCCCsw2C3750London,GreenStr10.255.0.2255MNG

MT

0000.3333.CCCCsw3Cisco3750London,GreenStr10.255.0.3255MNG

MT

0000.BBBB.CCCCsw5Cisco3850London,GreenStr10.255.0.5255MNG

MT

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

ORDERBY

286

Page 287: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Модульsqlite3ДляработысSQLiteвPythonиспользуетсямодульsqlite3.

Connection

ОбъектConnection-этоподключениекконкретнойБД.Можносказать,чтоэтотобъектпредставляетБД.

Примерсозданияподключения:

importsqlite3

connection=sqlite3.connect('dhcp_snooping.db')

Cursor

Послесозданиясоединения,надосоздатьобъектCursor-этоосновнойспособработысБД.

СоздаетсякурсоризсоединениясБД:

connection=sqlite3.connect('dhcp_snooping.db')

cursor=connection.cursor()

ВыполнениекомандSQL

ДлявыполнениякомандSQLвмодулеестьнесколькометодов:

execute()-методдлявыполненияодноговыраженияSQLexecutemany()-методпозволяетвыполнитьодновыражениеSQLдляпоследовательностипараметров(илидляитератора)executescript()-методпозволяетвыполнитьнескольковыраженийSQLзаодинраз

Методexecute

МетодexecuteпозволяетвыполнитьоднукомандуSQL.

Сначаланадосоздатьсоединениеикурсор:

Модульsqlite3

287

Page 288: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[1]:importsqlite3

In[2]:connection=sqlite3.connect('sw_inventory.db')

In[3]:cursor=connection.cursor()

Созданиетаблицыswitchспомощьюметодаexecute:

In[4]:cursor.execute("createtableswitch(mactextprimarykey,hostnametext,mode

ltext,locationtext)")

Out[4]:<sqlite3.Cursorat0x1085be880>

ВыраженияSQLмогутбытьпараметризированы-вместоданныхможноподставлятьспециальныезначения.ЗасчетэтогоможноиспользоватьоднуитужекомандуSQLдляпередачиразныхданных.

Например,таблицуswitchнужнозаполнитьданнымиизспискаdata:

In[5]:data=[

...:('0000.AAAA.CCCC','sw1','Cisco3750','London,GreenStr'),

...:('0000.BBBB.CCCC','sw2','Cisco3780','London,GreenStr'),

...:('0000.AAAA.DDDD','sw3','Cisco2960','London,GreenStr'),

...:('0011.AAAA.CCCC','sw4','Cisco3750','London,GreenStr')]

Дляэтогоможноиспользоватьзапросвида:

In[6]:query="INSERTintoswitchvalues(?,?,?,?)"

Знакивопросавкомандеиспользуютсядляподстановкиданных,которыебудутпередаватьсяметодуexecute.

Теперьможнопередатьданныетакимобразом:

In[7]:forrowindata:

...:cursor.execute(query,row)

...:

Второйаргумент,которыйпередаетсяметодуexecute,долженбытькортежем.Еслинужнопередатькортежсоднимэлементом,используетсязапись(value,).

Чтобыизмененияприменились,нужновыполнитьcommit(обратитевнимание,чтометодcommitвызываетсяусоединения):

Модульsqlite3

288

Page 289: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[8]:connection.commit()

Теперь,призапросеизкоманднойстрокиsqlite3,можноувидетьэтистрокивтаблицеswitch:

$sqlite3sw_inventory.db

sqlite>select*fromswitch;

machostnamemodellocation

---------------------------------------------------

0000.AAAA.CCCCsw1Cisco3750London,GreenStr

0000.BBBB.CCCCsw2Cisco3780London,GreenStr

0000.AAAA.DDDDsw3Cisco2960London,GreenStr

0011.AAAA.CCCCsw4Cisco3750London,GreenStr

Методexecutemany

МетодexecutemanyпозволяетвыполнитьоднукомандуSQLдляпоследовательностипараметров(илидляитератора).

Спомощьюметодаexecutemany,втаблицуswitchможнодобавитьаналогичныйсписокданныходнойкомандой.

Например,втаблицуswitchнадодобавитьданныеизспискаdata2:

In[9]:data2=[

...:('0000.1111.0001','sw5','Cisco3750','London,GreenStr'),

...:('0000.1111.0002','sw6','Cisco3750','London,GreenStr'),

...:('0000.1111.0003','sw7','Cisco3750','London,GreenStr'),

...:('0000.1111.0004','sw8','Cisco3750','London,GreenStr')]

Дляэтогонужноиспользоватьаналогичныйзапросвида:

In[10]:query="INSERTintoswitchvalues(?,?,?,?)"

Теперьможнопередатьданныеметодуexecutemany:

In[11]:cursor.executemany(query,data2)

Out[11]:<sqlite3.Cursorat0x10ee5e810>

In[12]:connection.commit()

Послевыполненияcommit,данныедоступнывтаблице:

Модульsqlite3

289

Page 290: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

sqlite>select*fromswitch;

machostnamemodellocation

---------------------------------------------------

0000.AAAA.CCCCsw1Cisco3750London,GreenStr

0000.BBBB.CCCCsw2Cisco3780London,GreenStr

0000.AAAA.DDDDsw3Cisco2960London,GreenStr

0011.AAAA.CCCCsw4Cisco3750London,GreenStr

0000.1111.0001sw5Cisco3750London,GreenStr

0000.1111.0002sw6Cisco3750London,GreenStr

0000.1111.0003sw7Cisco3750London,GreenStr

0000.1111.0004sw8Cisco3750London,GreenStr

МетодexecutemanyподставилсоответствующиекортеживкомандуSQLивседанныедобавилисьвтаблицу.

Методexecutescript

МетодexecutescriptпозволяетвыполнитьнескольковыраженийSQLзаодинраз.

Особенноудобноиспользоватьэтотметодприсозданиитаблиц:

In[14]:connection=sqlite3.connect('new_db.db')

In[15]:cursor=connection.cursor()

In[16]:cursor.executescript("""

...:createtableswitches(

...:hostnametextprimarykey,

...:locationtext

...:);

...:

...:createtabledhcp(

...:mactextprimarykey,

...:iptext,

...:vlantext,

...:interfacetext,

...:switchtextnotnullreferencesswitches(hostname)

...:);

...:""")

Out[16]:<sqlite3.Cursorat0x10efd67a0>

Получениерезультатовзапроса

Дляполучениярезультатовзапросавsqlite3естьнесколькоспособов:

использованиеметодовfetch...()-взависимостиотметодавозвращаютсяодна,несколькоиливсестроки

Модульsqlite3

290

Page 291: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

использованиекурсоракакитератора-возвращаетсяитератор

Методfetchone

Методfetchoneвозвращаетоднустрокуданных.

Примерполученияинформацииизбазыданныхsw_inventory.db:

In[1]:importsqlite3

In[2]:connection=sqlite3.connect('sw_inventory.db')

In[3]:cursor=connection.cursor()

In[4]:cursor.execute('select*fromswitch')

Out[4]:<sqlite3.Cursorat0x104eda810>

In[5]:cursor.fetchone()

Out[5]:(u'0000.AAAA.CCCC',u'sw1',u'Cisco3750',u'London,GreenStr')

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

Еслиповторновызватьметод,онвернетследующуюстроку:

In[6]:printcursor.fetchone()

(u'0000.BBBB.CCCC',u'sw2',u'Cisco3780',u'London,GreenStr')

Аналогичнымобразомметодбудетвозвращатьследующиестроки.Послеобработкивсехстрок,методначинаетвозвращатьNone.

Засчетэтого,методможноиспользоватьвцикле,например,так:

Модульsqlite3

291

Page 292: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[7]:cursor.execute('select*fromswitch')

Out[7]:<sqlite3.Cursorat0x104eda810>

In[8]:whileTrue:

...:next_row=cursor.fetchone()

...:ifnext_row:

...:printnext_row

...:else:

...:break

...:

(u'0000.AAAA.CCCC',u'sw1',u'Cisco3750',u'London,GreenStr')

(u'0000.BBBB.CCCC',u'sw2',u'Cisco3780',u'London,GreenStr')

(u'0000.AAAA.DDDD',u'sw3',u'Cisco2960',u'London,GreenStr')

(u'0011.AAAA.CCCC',u'sw4',u'Cisco3750',u'London,GreenStr')

(u'0000.1111.0001',u'sw5',u'Cisco3750',u'London,GreenStr')

(u'0000.1111.0002',u'sw6',u'Cisco3750',u'London,GreenStr')

(u'0000.1111.0003',u'sw7',u'Cisco3750',u'London,GreenStr')

(u'0000.1111.0004',u'sw8',u'Cisco3750',u'London,GreenStr')

Методfetchmany

Методfetchmanyвозвращаетвозвращаетсписокстрокданных.

Синтаксисметода:

cursor.fetchmany([size=cursor.arraysize])

Спомощьюпараметраsize,можноуказыватькакоеколичествостроквозвращается.Поумолчанию,параметрsizeравензначениюcursor.arraysize:

In[9]:printcursor.arraysize

1

Например,такимобразомможновозвращатьпотристрокииззапроса:

Модульsqlite3

292

Page 293: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[10]:cursor.execute('select*fromswitch')

Out[10]:<sqlite3.Cursorat0x104eda810>

In[11]:whileTrue:

...:three_rows=cursor.fetchmany(3)

...:ifthree_rows:

...:printthree_rows

...:print

...:else:

...:break

...:

[(u'0000.AAAA.CCCC',u'sw1',u'Cisco3750',u'London,GreenStr'),

(u'0000.BBBB.CCCC',u'sw2',u'Cisco3780',u'London,GreenStr')

(u'0000.AAAA.DDDD',u'sw3',u'Cisco2960',u'London,GreenStr')]

[(u'0011.AAAA.CCCC',u'sw4',u'Cisco3750',u'London,GreenStr'),

(u'0000.1111.0001',u'sw5',u'Cisco3750',u'London,GreenStr'),

(u'0000.1111.0002',u'sw6',u'Cisco3750',u'London,GreenStr')]

[(u'0000.1111.0003',u'sw7',u'Cisco3750',u'London,GreenStr'),

(u'0000.1111.0004',u'sw8',u'Cisco3750',u'London,GreenStr')]

Методвыдаетнужноеколичествострок,аеслистрокосталосьменьшечемпараметрsize,тооставшиесястроки.

Методfetchall

Методfetchallвозвращаетвсестрокиввидесписка:

In[12]:cursor.execute('select*fromswitch')

Out[12]:<sqlite3.Cursorat0x104eda810>

In[13]:cursor.fetchall()

Out[13]:

[(u'0000.AAAA.CCCC',u'sw1',u'Cisco3750',u'London,GreenStr'),

(u'0000.BBBB.CCCC',u'sw2',u'Cisco3780',u'London,GreenStr'),

(u'0000.AAAA.DDDD',u'sw3',u'Cisco2960',u'London,GreenStr'),

(u'0011.AAAA.CCCC',u'sw4',u'Cisco3750',u'London,GreenStr'),

(u'0000.1111.0001',u'sw5',u'Cisco3750',u'London,GreenStr'),

(u'0000.1111.0002',u'sw6',u'Cisco3750',u'London,GreenStr'),

(u'0000.1111.0003',u'sw7',u'Cisco3750',u'London,GreenStr'),

(u'0000.1111.0004',u'sw8',u'Cisco3750',u'London,GreenStr')]

Важныйаспектработыметода-онвозвращаетвсеоставшиесястроки.

Тоесть,еслидометодаfetchall,использовался,например,методfetchone,тометодfetchallвернетоставшиесястрокизапроса:

Модульsqlite3

293

Page 294: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[14]:cursor.execute('select*fromswitch')

Out[14]:<sqlite3.Cursorat0x104eda810>

In[15]:cursor.fetchone()

Out[15]:(u'0000.AAAA.CCCC',u'sw1',u'Cisco3750',u'London,GreenStr')

In[16]:cursor.fetchone()

Out[16]:(u'0000.BBBB.CCCC',u'sw2',u'Cisco3780',u'London,GreenStr')

In[17]:cursor.fetchall()

Out[17]:

[(u'0000.AAAA.DDDD',u'sw3',u'Cisco2960',u'London,GreenStr'),

(u'0011.AAAA.CCCC',u'sw4',u'Cisco3750',u'London,GreenStr'),

(u'0000.1111.0001',u'sw5',u'Cisco3750',u'London,GreenStr'),

(u'0000.1111.0002',u'sw6',u'Cisco3750',u'London,GreenStr'),

(u'0000.1111.0003',u'sw7',u'Cisco3750',u'London,GreenStr'),

(u'0000.1111.0004',u'sw8',u'Cisco3750',u'London,GreenStr')]

Методfetchmany,вэтомаспекте,работаетаналогично.

Cursorкакитератор

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

Прииспользованииметодовexecute,возвращаетсякурсор.А,таккаккурсорможноиспользоватькакитератор,можноиспользоватьего,например,вциклеfor:

In[18]:result=cursor.execute('select*fromswitch')

In[19]:forrowinresult:

...:printrow

...:

(u'0000.AAAA.CCCC',u'sw1',u'Cisco3750',u'London,GreenStr')

(u'0000.BBBB.CCCC',u'sw2',u'Cisco3780',u'London,GreenStr')

(u'0000.AAAA.DDDD',u'sw3',u'Cisco2960',u'London,GreenStr')

(u'0011.AAAA.CCCC',u'sw4',u'Cisco3750',u'London,GreenStr')

(u'0000.1111.0001',u'sw5',u'Cisco3750',u'London,GreenStr')

(u'0000.1111.0002',u'sw6',u'Cisco3750',u'London,GreenStr')

(u'0000.1111.0003',u'sw7',u'Cisco3750',u'London,GreenStr')

(u'0000.1111.0004',u'sw8',u'Cisco3750',u'London,GreenStr')

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

Модульsqlite3

294

Page 295: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[20]:forrowincursor.execute('select*fromswitch'):

...:printrow

...:

(u'0000.AAAA.CCCC',u'sw1',u'Cisco3750',u'London,GreenStr')

(u'0000.BBBB.CCCC',u'sw2',u'Cisco3780',u'London,GreenStr')

(u'0000.AAAA.DDDD',u'sw3',u'Cisco2960',u'London,GreenStr')

(u'0011.AAAA.CCCC',u'sw4',u'Cisco3750',u'London,GreenStr')

(u'0000.1111.0001',u'sw5',u'Cisco3750',u'London,GreenStr')

(u'0000.1111.0002',u'sw6',u'Cisco3750',u'London,GreenStr')

(u'0000.1111.0003',u'sw7',u'Cisco3750',u'London,GreenStr')

(u'0000.1111.0004',u'sw8',u'Cisco3750',u'London,GreenStr')

Использованиемодуляsqlite3

Безявногосозданиякурсора

МетодыexecuteдоступныивобъектеConnection.Приихиспользованиикурсорсоздается,нонеявно.Однако,методыfetchвConnectionнедоступны.

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

Примеритоговогоскрипта(файлcreate_sw_inventory_ver1.py):

#-*-coding:utf-8-*-

importsqlite3

data=[('0000.AAAA.CCCC','sw1','Cisco3750','London,GreenStr'),

('0000.BBBB.CCCC','sw2','Cisco3780','London,GreenStr'),

('0000.AAAA.DDDD','sw3','Cisco2960','London,GreenStr'),

('0011.AAAA.CCCC','sw4','Cisco3750','London,GreenStr')]

con=sqlite3.connect('sw_inventory2.db')

con.execute("createtableswitch(mactextprimarykey,hostnametext,modeltext,loc

ationtext)")

query="INSERTintoswitchvalues(?,?,?,?)"

con.executemany(query,data)

con.commit()

forrowincon.execute("select*fromswitch"):

printrow

con.close()

Результатвыполнениябудеттаким:

Модульsqlite3

295

Page 296: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythoncreate_sw_inventory_ver1.py

(u'0000.AAAA.CCCC',u'sw1',u'Cisco3750',u'London,GreenStr')

(u'0000.BBBB.CCCC',u'sw2',u'Cisco3780',u'London,GreenStr')

(u'0000.AAAA.DDDD',u'sw3',u'Cisco2960',u'London,GreenStr')

(u'0011.AAAA.CCCC',u'sw4',u'Cisco3750',u'London,GreenStr')

Обработкаисключений

Посмотримнапримериспользованияметодаexecute,привозникновенииошибки.

Втаблицеswitchполеmacдолжнобытьуникальным.И,еслипопытатьсязаписатьпересекающийсяMAC-адрес,возникнетошибка:

In[22]:con=sqlite3.connect('sw_inventory2.db')

In[23]:query="INSERTintoswitchvalues('0000.AAAA.DDDD','sw7','Cisco2960','L

ondon,GreenStr')"

In[24]:con.execute(query)

---------------------------------------------------------------------------

IntegrityErrorTraceback(mostrecentcalllast)

<ipython-input-56-ad34d83a8a84>in<module>()

---->1con.execute(query)

IntegrityError:UNIQUEconstraintfailed:switch.mac

Соответственно,можноперехватитьисключение:

In[25]:try:

...:con.execute(query)

...:exceptsqlite3.IntegrityErrorase:

...:print"Erroroccured:",e

...:

Erroroccured:UNIQUEconstraintfailed:switch.mac

Обратитевнимение,чтонадоперехватыватьисключениеsqlite3.IntegrityError,анеIntegrityError.

Connectionкакменеджерконтекста

Послевыполненияопераций,изменениядолжныбытьсохранены(надовыполнитьcommit()),азатемможнозакрытьсоединение,еслионобольшененужно.

PythonпозволяетиспользоватьобъектConnection,какменеджерконтекста.Втакомслучае,ненужноявноделатьcommitизакрыватьсоединение.Приэтом:

Модульsqlite3

296

Page 297: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

привозникновенииисключения,транзакцияавтоматическиоткатываетсяеслиисключениянебыло,автоматическивыполняетсяcommit

Примериспользованиясоединениясбазой,какменеджераконтекстов(create_sw_inventory_ver2.py):

#-*-coding:utf-8-*-

importsqlite3

data=[('0000.AAAA.CCCC','sw1','Cisco3750','London,GreenStr'),

('0000.BBBB.CCCC','sw2','Cisco3780','London,GreenStr'),

('0000.AAAA.DDDD','sw3','Cisco2960','London,GreenStr'),

('0011.AAAA.CCCC','sw4','Cisco3750','London,GreenStr')]

con=sqlite3.connect('sw_inventory3.db')

con.execute("createtableswitch(mactextprimarykey,hostnametext,modeltext,loc

ationtext)")

try:

withcon:

query="INSERTintoswitchvalues(?,?,?,?)"

con.executemany(query,data)

exceptsqlite3.IntegrityErrorase:

print"Erroroccured:",e

forrowincon.execute("select*fromswitch"):

printrow

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

Дляпроверкиэтогофункционала,попробуемзаписатьвтаблицуданные,вкоторыхMAC-адресповторяется(файлcreate_sw_inventory_ver3.py):

Модульsqlite3

297

Page 298: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

#-*-coding:utf-8-*-

importsqlite3

data=[('0000.AAAA.CCCC','sw1','Cisco3750','London,GreenStr'),

('0000.BBBB.CCCC','sw2','Cisco3780','London,GreenStr'),

('0000.AAAA.DDDD','sw3','Cisco2960','London,GreenStr'),

('0011.AAAA.CCCC','sw4','Cisco3750','London,GreenStr')]

con=sqlite3.connect('sw_inventory3.db')

con.execute("createtableswitch(mactextprimarykey,hostnametext,modeltext,loc

ationtext)")

try:

withcon:

query="INSERTintoswitchvalues(?,?,?,?)"

con.executemany(query,data)

exceptsqlite3.IntegrityErrorase:

print"Erroroccured:",e

forrowincon.execute("select*fromswitch"):

printrow

print'-'*30

#MAC-адресsw7совпадаетсMAC-адресомсуществующегокоммутатора-sw3

data2=[('0055.AAAA.CCCC','sw5','Cisco3750','London,GreenStr'),

('0066.BBBB.CCCC','sw6','Cisco3780','London,GreenStr'),

('0000.AAAA.DDDD','sw7','Cisco2960','London,GreenStr'),

('0088.AAAA.CCCC','sw8','Cisco3750','London,GreenStr')]

try:

withcon:

query="INSERTintoswitchvalues(?,?,?,?)"

con.executemany(query,data2)

exceptsqlite3.IntegrityErrorase:

print"Erroroccured:",e

forrowincon.execute("select*fromswitch"):

printrow

Перваячастьскриптаосталасьнеизменной.После,аналогичнымобразомзаписываютсяданные,новспискеdata2укоммутатораsw7MAC-адрессовпадаетсужесуществующимкоммутаторомsw3.

Результатвыполненияскрипта:

Модульsqlite3

298

Page 299: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythoncreate_sw_inventory_ver3.py

(u'0000.AAAA.CCCC',u'sw1',u'Cisco3750',u'London,GreenStr')

(u'0000.BBBB.CCCC',u'sw2',u'Cisco3780',u'London,GreenStr')

(u'0000.AAAA.DDDD',u'sw3',u'Cisco2960',u'London,GreenStr')

(u'0011.AAAA.CCCC',u'sw4',u'Cisco3750',u'London,GreenStr')

------------------------------

Erroroccured:UNIQUEconstraintfailed:switch.mac

(u'0000.AAAA.CCCC',u'sw1',u'Cisco3750',u'London,GreenStr')

(u'0000.BBBB.CCCC',u'sw2',u'Cisco3780',u'London,GreenStr')

(u'0000.AAAA.DDDD',u'sw3',u'Cisco2960',u'London,GreenStr')

(u'0011.AAAA.CCCC',u'sw4',u'Cisco3750',u'London,GreenStr')

Обратитевнимание,чтосодержимоетаблицыswitchдоипослевторогодобавленияинформации-одинаково.Этозначит,чтонезаписаласьниоднастрокаизспискаdata2.

Такполучилосьиз-затого,чтоиспользуетсяметодexecutemanyивпределаходнойтранзакциимыпытаемсязаписатьвсе4строки.Есливозникаетошибкасоднойизних-откатываютсявсеизменения.

Иногда,этоименнотоповедение,котороенужно.Еслиженадочтобыигнорировалисьтолькострокисошибками,надоиспользоватьметодexecuteизаписыватькаждуюстрокуотдельно.

Файлcreate_sw_inventory_ver4.py:

Модульsqlite3

299

Page 300: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

#-*-coding:utf-8-*-

importsqlite3

data=[('0000.AAAA.CCCC','sw1','Cisco3750','London,GreenStr'),

('0000.BBBB.CCCC','sw2','Cisco3780','London,GreenStr'),

('0000.AAAA.DDDD','sw3','Cisco2960','London,GreenStr'),

('0011.AAAA.CCCC','sw4','Cisco3750','London,GreenStr')]

con=sqlite3.connect('sw_inventory3.db')

con.execute("createtableswitch(mactextprimarykey,hostnametext,modeltext,loc

ationtext)")

try:

withcon:

query="INSERTintoswitchvalues(?,?,?,?)"

con.executemany(query,data)

exceptsqlite3.IntegrityErrorase:

print"Erroroccured:",e

forrowincon.execute("select*fromswitch"):

printrow

print'-'*30

#MAC-адресsw7совпадаетсMAC-адресомсуществующегокоммутатора-sw3

data2=[('0055.AAAA.CCCC','sw5','Cisco3750','London,GreenStr'),

('0066.BBBB.CCCC','sw6','Cisco3780','London,GreenStr'),

('0000.AAAA.DDDD','sw7','Cisco2960','London,GreenStr'),

('0088.AAAA.CCCC','sw8','Cisco3750','London,GreenStr')]

forrowindata2:

try:

withcon:

query="INSERTintoswitchvalues(?,?,?,?)"

con.execute(query,row)

exceptsqlite3.IntegrityErrorase:

print"Erroroccured:",e

forrowincon.execute("select*fromswitch"):

printrow

Теперьрезультатвыполнениябудеттаким(пропущентолькоsw7):

Модульsqlite3

300

Page 301: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythoncreate_sw_inventory_ver4.py

(u'0000.AAAA.CCCC',u'sw1',u'Cisco3750',u'London,GreenStr')

(u'0000.BBBB.CCCC',u'sw2',u'Cisco3780',u'London,GreenStr')

(u'0000.AAAA.DDDD',u'sw3',u'Cisco2960',u'London,GreenStr')

(u'0011.AAAA.CCCC',u'sw4',u'Cisco3750',u'London,GreenStr')

------------------------------

Erroroccured:UNIQUEconstraintfailed:switch.mac

(u'0000.AAAA.CCCC',u'sw1',u'Cisco3750',u'London,GreenStr')

(u'0000.BBBB.CCCC',u'sw2',u'Cisco3780',u'London,GreenStr')

(u'0000.AAAA.DDDD',u'sw3',u'Cisco2960',u'London,GreenStr')

(u'0011.AAAA.CCCC',u'sw4',u'Cisco3750',u'London,GreenStr')

(u'0055.AAAA.CCCC',u'sw5',u'Cisco3750',u'London,GreenStr')

(u'0066.BBBB.CCCC',u'sw6',u'Cisco3780',u'London,GreenStr')

(u'0088.AAAA.CCCC',u'sw8',u'Cisco3750',u'London,GreenStr')

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

Модульsqlite3

301

Page 302: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПримериспользованияSQLiteВразделеРегулярныевыражениябылпримерразборавыводакомандыshowipdhcpsnoopingbinding.Навыходе,мыполучилиинформациюопараметрахподключенныхустройств(interface,IP,MAC,VLAN).

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

Например,еслинужнопоIP-адресуполучитьинформациюотом,ккакомуинтерфейсуподключенкомпьютер,какойунегоMAC-адресивкакомонVLAN,топовыводускриптаэтосделатьнеоченьпростои,главное,неоченьудобно.

ЗапишеминформациюполученнуюизвыводаshipdhcpsnoopingbindingвSQLite.Этопозволитделатьзапросыполюбомупараметруиполучатьнедостающие.

Дляэтогопримера,достаточносоздатьоднутаблицу,гдебудетхранитьсяинформация.

Определениетаблицыпрописановотдельномфайлеdhcp_snooping_schema.sqlивыглядиттак:

createtabledhcp(

mactextprimarykey,

iptext,

vlantext,

interfacetext

);

Длявсехполейопределентипданных"текст".ИMAC-адресявляетсяпервичнымключомнашейтаблицы.Чтовполнелогично,таккак,MAC-адресдолженбытьуникальным.

ТеперьнадосоздатьфайлБД,подключитьсякбазеданныхисоздатьтаблицу(файлcreate_sqlite_ver1.py):

ПримериспользованияSQLite

302

Page 303: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importsqlite3

withsqlite3.connect('dhcp_snooping.db')asconn:

print'Creatingschema...'

withopen('dhcp_snooping_schema.sql','r')asf:

schema=f.read()

conn.executescript(schema)

print"Done"

Комментариикфайлу:

используетсяменеджерконтекстаwithпривыполнениистрокиwithsqlite3.connect('dhcp_snooping.db')asconn:

создаетсяфайлdhcp_snooping.db,еслиегонетсоздаетсяобъектConnection

вБДсоздаетсятаблица,наоснованиикоманд,которыеуказанывфайлеdhcp_snooping_schema.sql:

открываемфайлdhcp_snooping_schema.sqlschema=f.read()-считываемвесьфайлкакоднустрокуconn.executescript(schema)-методexecutescriptпозволяетвыполнятькомандыSQL,которыепрописанывфайле

Выполняемскрипт:

$pythoncreate_sqlite_ver1.py

Creatingschema...

Done

ВрезультатедолженбытьсозданфайлБДитаблицаdhcp.

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

Выведемсписоксозданныхтаблиц(запростакоговидапозволяетпроверитькакиетаблицысозданывDB):

$sqlite3dhcp_snooping.db"SELECTnameFROMsqlite_masterWHEREtype='table'"

dhcp

Теперьнужнозаписатьинформациюизвыводакомандыshipdhcpsnoopingbindingвтаблицу(файлdhcp_snooping.txt):

ПримериспользованияSQLite

303

Page 304: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

MacAddressIpAddressLease(sec)TypeVLANInterface

----------------------------------------------------------------------------

----

00:09:BB:3D:D6:5810.1.10.286250dhcp-snooping10FastEthernet0/1

00:04:A3:3E:5B:6910.1.5.263951dhcp-snooping5FastEthernet0/1

0

00:05:B3:7E:9B:6010.1.5.463253dhcp-snooping5FastEthernet0/9

00:09:BC:3F:A6:5010.1.10.676260dhcp-snooping10FastEthernet0/3

Totalnumberofbindings:4

Вовторойверсиискрипта,сначалавыводвфайлеdhcp_snooping.txtобрабатываетсярегулярнымивыражениями,азатем,добавляютсязаписивБД(файлcreate_sqlite3_ver2.py):

importsqlite3

importre

regex=re.compile('(.+?)+(.*?)+\d++[\w-]++(\d+)+(.*$)')

result=[]

withopen('dhcp_snooping.txt')asdata:

forlineindata:

ifline[0].isdigit():

result.append(regex.search(line).groups())

withsqlite3.connect('dhcp_snooping.db')asconn:

print'Creatingschema...'

withopen('dhcp_snooping_schema.sql','r')asf:

schema=f.read()

conn.executescript(schema)

print"Done"

print'InsertingDHCPSnoopingdata'

forrowinresult:

query="""insertintodhcp(mac,ip,vlan,interface)

values(?,?,?,?)"""

conn.execute(query,row)

Покачто,файлБДкаждыйразнадоудалять,таккакскриптпытаетсяегосоздатьприкаждомзапуске.

Комментариикскрипту:

врегулярномвыражении,котороепроходитсяповыводукомандыshipdhcpsnoopingbinding,используютсянеименованныегруппы,каквпримереразделаРегулярныевыражения,анумерованные

ПримериспользованияSQLite

304

Page 305: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

группысозданытолькодлятехэлементов,которыенасинтересуютresult-этосписок,вкоторомхранитсярезультатобработкивыводакоманды

нотеперьтутнесловари,акортежисрезультатамиэтонужнодлятого,чтобыихможнобылосразупередаватьназаписьвБД

Перебираемвполученномспискекортежей,элементыВэтомскриптеиспользуетсяещеодинвариантзаписивБД

строкаqueryописываетзапрос.Но,вместозначенийуказываютсязнакивопроса.Такойвариантзаписизапроса,позволяетдинамическиподставлятьзначениеполейзатемметодуexecuteпередаетсястроказапросаикортежrow,гденаходятсязначения

Выполняемскрипт:

$pythoncreate_sqlite_ver2.py

Creatingschema...

Done

InsertingDHCPSnoopingdata

Проверим,чтоданныезаписались:

$sqlite3dhcp_snooping.db"select*fromdhcp"

00:09:BB:3D:D6:58|10.1.10.2|10|FastEthernet0/1

00:04:A3:3E:5B:69|10.1.5.2|5|FastEthernet0/10

00:05:B3:7E:9B:60|10.1.5.4|5|FastEthernet0/9

00:07:BC:3F:A6:50|10.1.10.6|10|FastEthernet0/3

Теперьпопробуемзапроситьпоопределенномупараметру:

$sqlite3dhcp_snooping.db"select*fromdhcpwhereip='10.1.5.2'"

00:04:A3:3E:5B:69|10.1.5.2|5|FastEthernet0/10

Тоесть,теперьнаоснованииодногопараметра,можнополучатьостальные.

Переделаемнашскрипттакимобразом,чтобывнёмбылапроверкананаличиефайлаdhcp_snooping.db.ЕслифайлБДесть,тоненадосоздаватьтаблицу,считаем,чтоонаужесоздана.

Файлcreate_sqlite_ver3.py:

ПримериспользованияSQLite

305

Page 306: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importos

importsqlite3

importre

data_filename='dhcp_snooping.txt'

db_filename='dhcp_snooping.db'

schema_filename='dhcp_snooping_schema.sql'

regex=re.compile('(.+?)+(.*?)+\d++[\w-]++(\d+)+(.*$)')

withopen(data_filename)asdata:

result=[regex.search(line).groups()forlineindataifline[0].isdigit()]

db_exists=os.path.exists(db_filename)

withsqlite3.connect(db_filename)asconn:

ifnotdb_exists:

print'Creatingschema...'

withopen(schema_filename,'r')asf:

schema=f.read()

conn.executescript(schema)

print'Done'

else:

print'Databaseexists,assumedhcptabledoes,too.'

print'InsertingDHCPSnoopingdata'

forvalinresult:

query="""insertintodhcp(mac,ip,vlan,interface)

values(?,?,?,?)"""

conn.execute(query,val)

ТеперьестьпроверканаличияфайлаБД,ифайлdhcp_snooping.dbбудетсоздаватьсятольковтомслучае,еслиегонет.Данныетакжезаписываютсятольковтомслучае,еслинесозданфайлdhcp_snooping.db.

Проверим.Вслучаееслифайлужеесть:

$pythoncreate_sqlite_ver3.py

Databaseexists,assumedhcptabledoes,too.

Еслифайланет(предварительноегоудалить):

$rmdhcp_snooping.db

$pythoncreate_sqlite_ver3.py

Creatingschema...

Done

InsertingDHCPSnoopingdata

ПримериспользованияSQLite

306

Page 307: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Теперьделаемотдельныйскрипт,которыйзанимаетсяотправкойзапросоввБДивыводомрезультатов.Ондолжен:

ожидатьотпользователявводапараметров:имяпараметразначениепараметра

делатьнормальныйвыводданныхпозапросу

Файлget_data_ver1.py:

#-*-coding:utf-8-*-

importsqlite3

importsys

db_filename='dhcp_snooping.db'

key,value=sys.argv[1:]

keys=['mac','ip','vlan','interface']

keys.remove(key)

withsqlite3.connect(db_filename)asconn:

#Позволяетдалееобращатьсякданнымвколонках,поимениколонки

conn.row_factory=sqlite3.Row

print"\nDetailedinformationforhost(s)with",key,value

print'-'*40

query="select*fromdhcpwhere{}=?".format(key)

result=conn.execute(query,(value,))

forrowinresult:

forkinkeys:

print"{:12}:{}".format(k,row[k])

print'-'*40

Комментариикскрипту:

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

подключаемсякБДconn.row_factory=sqlite3.Row-позволяетдалееобращатьсякданнымвколонках,поимениколонки

изБДвыбираютсятестроки,вкоторыхключравенуказанномузначениювSQLзначенияможноподставлятьчереззнаквопроса,нонельзяподставлятьимястолбца.Поэтому,имястолбцаподставляетсячерез

ПримериспользованияSQLite

307

Page 308: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

форматированиестрок,азначение-штатнымсредствомSQL.Обратитевниманиена(value,)такимобразомпередаетсякортежсоднимэлементом

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

Проверимработускрипта.

ПоказатьпараметрыхостасIP10.1.10.2:

$pythonget_data_ver1.pyip10.1.10.2

Detailedinformationforhost(s)withip10.1.10.2

----------------------------------------

mac:00:09:BB:3D:D6:58

vlan:10

interface:FastEthernet0/1

----------------------------------------

ПоказатьхостывVLAN10:

$pythonget_data_ver1.pyvlan10

Detailedinformationforhost(s)withvlan10

----------------------------------------

mac:00:09:BB:3D:D6:58

ip:10.1.10.2

interface:FastEthernet0/1

----------------------------------------

mac:00:07:BC:3F:A6:50

ip:10.1.10.6

interface:FastEthernet0/3

----------------------------------------

Втораяверсияскриптадляполученияданных,снебольшимиулучшениями:

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

Файлget_data_ver2.py:

ПримериспользованияSQLite

308

Page 309: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

#-*-coding:utf-8-*-

importsqlite3

importsys

db_filename='dhcp_snooping.db'

query_dict={'vlan':"select*fromdhcpwherevlan=?",

'mac':"select*fromdhcpwheremac=?",

'ip':"select*fromdhcpwhereip=?",

'interface':"select*fromdhcpwhereinterface=?"}

key,value=sys.argv[1:]

keys=query_dict.keys()

ifnotkeyinkeys:

print"Enterkeyfrom{}".format(','.join(keys))

else:

withsqlite3.connect(db_filename)asconn:

conn.row_factory=sqlite3.Row

print"\nDetailedinformationforhost(s)with",key,value

print'-'*40

query=query_dict[key]

result=conn.execute(query,(value,))

#методdescriptionпозволяетполучитьзаголовкиполученныхстолбцов.

#Внембудутнаходитьсятолькотестолбцы,которыйсоответствуютзапросу.

all_rows=[r[0]forrinresult.description]

forrowinresult:

forrow_nameinall_rows:

print"{:12}:{}".format(row_name,row[row_name])

print'-'*40

Вэтомскриптеестьнескольконедостатков:

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

Крометого,многоенужнодоработатьвскрипте,которыйсоздаетБДизаписываетданные.

Вседоработкибудутвыполнятьсявупражненияхкэтомуразделу.

ПримериспользованияSQLite

309

Page 310: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание11.1

Наосновефайлаcreate_sqlite_ver3.pyизраздела,необходимосоздатьдваскрипта:

create_db.pyсюдадолжнабытьвынесенафункциональностьпосозданиюБД:должнавыполнятьсяпроверканаличияфайлаБДеслифайланет,согласноописаниюсхемыБДвфайлеdhcp_snooping_schema.sql,должнабытьсозданаБД(БДотличаетсяотпримеравразделе)

add_data.pyспомощьюэтогоскрипта,выполняетсядобавлениеданныхвБДдобавлятьнадонетолькоданныеизвыводаshipdhcpsnoopingbinding,ноиинформациюокоммутаторах

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

ВБДтеперьдветаблицы(схемаописанавфайлеdhcp_snooping_schema.sql):

switches-внейнаходятсяданныеокоммутаторахdhcp-этатаблицаосталасьтакойжекаквпримере,заисключениемполяswitch

этополессылаетсянаполеhostnameвтаблицеswitches

Задания

310

Page 311: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Соответственно,вфайлеadd_data.pyдвечасти:

информацияокоммутаторахдобавляетсявтаблицуswitchesданныеокоммутаторах,находятсявфайлеswitches.yml

информациянаоснованиивыводаshipdhcpsnoopingbindingдобавляетсявтаблицуdhcp

выводстрёхкоммутаторов:файлыsw1_dhcp_snooping.txt,sw2_dhcp_snooping.txt,sw3_dhcp_snooping.txt

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

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

Задание11.1a

Добавитьвфайлadd_data.py,иззадания11.1,проверкунаналичиеБД:

еслифайлБДесть,записатьданныееслифайлаБДнет,вывестисообщение,чтоБДнетиеёнеобходимосначаласоздать

Задание11.2

Наосновефайлаget_data_ver1.pyизраздела,создатьскриптget_data.py.

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

Впримереизраздела,скриптупередавалисьдвааргумента:

key-имястолбца,покоторомунадонайтиинформациюvalue-значение

Теперьнеобходиморасширитьфункциональностьтакимобразом:

еслискриптбылвызванбезаргументов,вывестивсёсодержимоетаблицыdhcpотформатироватьвыводввидестолбцов

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

ФайлБДможноскопироватьизпрошлыхзаданий

Задания

311

Page 312: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Витоге,выводдолженвыглядетьтак:

$pythonget_data.py

Втаблицеdhcpтакиезаписи:

----------------------------------------------------------------------

00:09:BB:3D:D6:5810.1.10.210FastEthernet0/1sw1

00:04:A3:3E:5B:6910.1.5.25FastEthernet0/10sw1

00:05:B3:7E:9B:6010.1.5.45FastEthernet0/9sw1

00:07:BC:3F:A6:5010.1.10.610FastEthernet0/3sw1

00:09:BC:3F:A6:50192.168.1.100100FastEthernet0/5sw1

00:A9:BB:3D:D6:5810.1.10.2010FastEthernet0/7sw2

00:B4:A3:3E:5B:6910.1.5.205FastEthernet0/5sw2

00:C5:B3:7E:9B:6010.1.5.405FastEthernet0/9sw2

00:A9:BC:3F:A6:50100.1.1.63FastEthernet0/20sw3

$pythonget_data.pyip10.1.10.2

Detailedinformationforhost(s)withip10.1.10.2

----------------------------------------

mac:00:09:BB:3D:D6:58

vlan:10

interface:FastEthernet0/1

switch:sw1

----------------------------------------

$pythonget_data.pyvlan10

Detailedinformationforhost(s)withvlan10

----------------------------------------

mac:00:09:BB:3D:D6:58

ip:10.1.10.2

interface:FastEthernet0/1

switch:sw1

----------------------------------------

mac:00:07:BC:3F:A6:50

ip:10.1.10.6

interface:FastEthernet0/3

switch:sw1

----------------------------------------

mac:00:A9:BB:3D:D6:58

ip:10.1.10.20

interface:FastEthernet0/7

switch:sw2

----------------------------------------

$pythonget_data.pyvlan

Пожалуйста,введитедваилинольаргументов

Задание11.2a

Задания

312

Page 313: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Дополнитьскриптget_data.pyиззадания11.2

Теперьдолжнавыполнятьсяпроверканетолькопоколичествуаргументов,ноипозначениюаргументов.Еслиимяаргументавведенонеправильно,надовывестисообщениеобошибке(примерсообщенияниже).

ФайлБДможноскопироватьизпрошлыхзаданий

Витоге,выводдолженвыглядетьтак:

$pythonget_data.pyvln10

Данныйпараметрнеподдерживается.

Допустимыезначенияпараметров:mac,ip,vlan,interface,switch

Задание11.3

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

Попробуйтевыполнитьскриптadd_data.pyповторно,насуществующейБД.Должнавозникнутьошибка.

ПрисозданиисхемыБД,былоявноуказано,чтополеMAC-адрес,должнобытьуникальным.Поэтому,придобавлениизаписистакимжеMAC-адресом,возникаетошибка.

Но,нужнокаким-тообразомобновлятьБД,чтобывнейхраниласьактуальнаяинформация.

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

Но,впринципе,стараяинформациятожеможетпригодиться.

Поэтому,мыбудемделатьнемногопо-другому.Создадимновоеполеactive,котороебудетуказыватьявляетсялизаписьактуальной.

Полеactiveдолжноприниматьтакиезначения:

0-означаетFalse.Ииспользуетсядлятого,чтобыотметитьзаписькакнеактивную1-True.Используетсячтобыуказать,чтозаписьактивна

Каждыйраз,когдаинформацияизфайловсвыводомDHCPsnoopingдобавляетсязаново,надопометитьвсесуществующиезаписи(дляданногокоммутатора),какнеактивные(active=0).Затемможнообновлятьинформациюипометитьновыезаписи,какактивные(active=1).

Задания

313

Page 314: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Такимобразом,вБДостанутсяистарыезаписи,дляMAC-адресов,которыесейчаснеактивны,ипоявитсяобновленнаяинформациядляактивныхадресов.

НоваясхемаБДнаходитсявфайлеdhcp_snooping_schema.sql

Изменитескриптadd_data.pyтакимобразом,чтобывыполнялисьновыеусловияизаполнялосьполеactive.

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

ДляпроверкикорректностизапросаSQL,можновыполнитьеговкоманднойстроке,спомощьюутилитыsqlite3.

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

Задание11.4

Обновитьфайлget_dataиззадания11.2или11.2a.

Теперь,призапросеинформации,сначаладолжныотображатьсяактивныезаписи,азатем,неактивные.

Например:

$pythonget_data.pyip10.1.10.2

Detailedinformationforhost(s)withip10.1.10.2

----------------------------------------

mac:00:09:BB:3D:D6:58

vlan:10

interface:FastEthernet0/1

switch:sw1

----------------------------------------

=======================================

Inactivevalues:

----------------------------------------

mac:00:09:23:34:16:18

vlan:10

interface:FastEthernet0/4

switch:sw1

----------------------------------------

Задание11.5

Задания

314

Page 315: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ТеперьвБДостаетсяистараяинформация.И,есликакой-тоMAC-адреснепоявлялсявновыхзаписях,записьсним,можетоставатьсявБДоченьдолго.

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

Например,еслизаписьвБДужебольшемесяца,тоеёможноудалить.

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

Новоеполеназываетсяlast_activeивнемдолжнанаходитьсястрока,вформате:YYYY-MM-DDHH:MM:SS.

Вэтомзаданиинеобходимо:

изменить,соответственно,таблицуdhcpидобавитьновоеполе.таблицуможнопоменятьизclisqlite,нофайлdhcp_snooping_schema.sqlтоженеобходимоизменить

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

Какполучитьстрокусовременемидатой,вуказанномформате,показановзадании.Раскомментируйтестрокуипосмотритекаконавыглядит.

importdatetime

now=str(datetime.datetime.today().replace(microsecond=0))

#printnow

Задание11.5a

Послевыполнениязадания11.5,втаблицеdhcpестьновоеполеlast_active.

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

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

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

Задания

315

Page 316: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

fromdatetimeimporttimedelta,datetime

now=datetime.today().replace(microsecond=0)

week_ago=now-timedelta(days=7)

#printnow

#printweek_ago

#printnow>week_ago

#printstr(now)>str(week_ago)

Задание11.6

Вэтомзаданиивыложенфайлparse_dhcp_snooping.py.

Вфайлесозданынесколькофункцийиописаныаргументыкоманднойстроки,которыепринимаетфайл.

Вфайлеparse_dhcp_snooping.pyнельзяничегоменять.

Естьподдержкааргументовдлявыполнениявсехдействий,которые,впредыдущихзаданиях,выполнялисьвфайлахcreate_db.py,add_data.pyиget_data.py.

Вфайлеparse_dhcp_snooping.pyестьтакаястрока:

importparse_dhcp_snooping_functionsaspds

Изадачаэтогозаданиявтом,чтобысоздатьвсенеобходимыефункции,вфайлеparse_dhcp_snooping_functions.pyнаосновеинформациивфайлеparse_dhcp_snooping.py.

Изфайлаparse_dhcp_snooping.py,необходимоопределить:

какиефункциидолжныбытьвфайлеparse_dhcp_snooping_functions.pyкакиепараметрысоздатьвэтихфункциях

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

Всянеобходимаяинформация,присутствуетвфункцияхcreate,add,get,вфайлеparse_dhcp_snooping.py.

Впринципе,длявыполнениязадания,необязательноразбиратьсясмодулемargparse.Но,выможетепочитатьонемвразделеДополнительнаяинформация.

Задания

316

Page 317: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Длятого,чтобыбылопрощеначать,попробуйтесоздатьнеобходимыефункциивфайлеparse_dhcp_snooping_functions.pyи,например,простовыведитеаргументыфункций,используяprint.

Потом,можносоздатьфункции,которыезапрашиваютинформациюизБД(базуданныхможноскопироватьизпредыдущихзаданий).

Можносоздаватьлюбыевспомогательныефункциивфайлеparse_dhcp_snooping_functions.py,анетолькоте,которыевызываютсяизфайлаparse_dhcp_snooping.py.

Проверьтевсеоперации:

созданиеБДдобавлениеинформацииокоммутаторахдобавлениеинформациинаоснованиивыводаshipdhcpsnoopingbindingизфайловвыборкуинформацииизБД(попараметруивсюинформацию)

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

$pythonparse_dhcp_snooping.py-h

usage:parse_dhcp_snooping.py[-h]{create_db,add,get}...

optionalarguments:

-h,--helpshowthishelpmessageandexit

subcommands:

validsubcommands

{create_db,add,get}additionalinfo

create_dbcreatenewdb

addadddatatodb

getgetdatafromdb

$pythonparse_dhcp_snooping.pyget-h

usage:parse_dhcp_snooping.pyget[-h][--dbDB_FILE]

[-k{mac,ip,vlan,interface,switch}]

[-vVALUE][-a]

optionalarguments:

-h,--helpshowthishelpmessageandexit

--dbDB_FILEdbname

-k{mac,ip,vlan,interface,switch}

hostkey(parameter)tosearch

-vVALUEvalueofkey

-ashowdbcontent

Задания

317

Page 318: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythonparse_dhcp_snooping.pyadd-h

usage:parse_dhcp_snooping.pyadd[-h][--dbDB_FILE][-s]

filename[filename...]

positionalarguments:

filenamefile(s)toaddtodb

optionalarguments:

-h,--helpshowthishelpmessageandexit

--dbDB_FILEdbname

-saddswitchdataifset,elseaddnormaldata

$pythonparse_dhcp_snooping.pycreate_db-h

usage:parse_dhcp_snooping.pycreate_db[-h][-nNAME][-sSCHEMA]

optionalarguments:

-h,--helpshowthishelpmessageandexit

-nNAMEdbfilename

-sSCHEMAdbschemafilename

$pythonparse_dhcp_snooping.pyget

Showingdhcp_snooping.dbcontent...

----------------------------------------------------------------------

00:09:BB:3D:D6:5810.1.10.210FastEthernet0/1sw1

00:04:A3:3E:5B:6910.1.5.25FastEthernet0/10sw1

00:05:B3:7E:9B:6010.1.5.45FastEthernet0/9sw1

00:07:BC:3F:A6:5010.1.10.610FastEthernet0/3sw1

00:09:BC:3F:A6:50192.168.1.100100FastEthernet0/5sw1

00:A9:BB:3D:D6:5810.1.10.2010FastEthernet0/7sw2

00:B4:A3:3E:5B:6910.1.5.205FastEthernet0/5sw2

00:C5:B3:7E:9B:6010.1.5.405FastEthernet0/9sw2

00:A9:BC:3F:A6:50100.1.1.63FastEthernet0/20sw3

$pythonparse_dhcp_snooping.pyget-kvlan-v10

GetingdatafromDB:dhcp_snooping.db

Requestdataforhost(s)withvlan10

Detailedinformationforhost(s)withvlan10

----------------------------------------

mac:00:09:BB:3D:D6:58

ip:10.1.10.2

interface:FastEthernet0/1

switch:sw1

----------------------------------------

mac:00:07:BC:3F:A6:50

ip:10.1.10.6

interface:FastEthernet0/3

switch:sw1

----------------------------------------

mac:00:A9:BB:3D:D6:58

ip:10.1.10.20

interface:FastEthernet0/7

switch:sw2

Задания

318

Page 319: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

----------------------------------------

$pythonparse_dhcp_snooping.pyaddsw1_dhcp_snooping.txtsw2_dhcp_snooping.txtsw3_dh

cp_snooping.txt

Readinginfofromfile(s)

sw1_dhcp_snooping.txt,sw2_dhcp_snooping.txt,sw3_dhcp_snooping.txt

Задания

319

Page 320: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПодключениекоборудованиюВэтомразделерассматриваетсякакподключитьсякоборудованиюпопротоколам:

SSHTelnet

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

pexpect-этореализацияexpectнаPythonэтотмодульпозволяетработатьслюбойинтерактивнойсессией:ssh,telnet,sftpидр.крометого,онпозволяетвыполнятьразличныекомандывОС(этоможноделатьиспомощьюдругихмодулей)несмотрянато,чтоpexpectможетбытьменееудобнымвиспользовании,чемдругиемодули,онреализуетболееобщийфункционалиэтопозволяетиспользоватьеговситуациях,когдадругиемодулинеработают

telnetlib-этотмодульпозволяетподключатьсяпоTelnetвверсии1.0netmikoтакжепоявиласьподдержкаTelnet,поэтому,еслиnetmikoподдерживаеттооборудование,котороеиспользуетсяувас,удобнейбудетиспользоватьего

paramiko-этомодуль,которыйпозволяетподключатьсяпоSSHv2онболееудобенвиспользовании,чемpexpect,носболееузкойфункциональностью(поддерживаеттолькоSSH)

netmiko-этомодуль,которыйупрощаетиспользованиеparamikoдлясетевыхустройств

netmikoэто"обертка"вокругparamiko,котораяориентировананаработуссетевымоборудованием

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

Дляработыссетевымоборудованием,удобнееиспользоватьnetmiko.

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

Параметры,которыеиспользуютсявразделе:

пользователь:ciscoпароль:cisco

12.Подключениекоборудованию

320

Page 321: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

парольнарежимenable:ciscoSSHверсии2IP-адреса:192.168.100.1,192.168.100.2,192.168.100.3

12.Подключениекоборудованию

321

Page 322: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ВводпароляПриподключениикоборудованиювручную,какправило,парольтакжевводитсявручную.

Приавтоматизизацииподключения,надорешитькакимобразомбудетпередаватьсяпароль:

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

записыватьлогинипарольвкаком-тофайлеэтонеоченьбезопасно

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

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

Ксожалению,еслииспользоватьraw_input(),набираемыйпарольбудетвиден.Ахотелосьбы,чтобыпривводепаролявводимыесимволынеотображались.

Модульgetpass

Модульgetpassпозволяетзапрашиватьпароль,неотображаявводимыесимволы:

In[1]:importgetpass

In[2]:password=getpass.getpass()

Password:

In[3]:printpassword

testpass

Переменныеокружения

Ещеодинвариантхраненияпароля(аможноипользователя)-переменныеокружения.

Например,такимобразомлогинипарользаписываютсявпеременные:

Вводпароля

322

Page 323: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$exportSSH_USER=user

$exportSSH_PASSWORD=userpass

Азатем,вPython,считываютсязначениявпеременныевскрипте:

importos

USERNAME=os.environ.get('SSH_USER')

PASSWORD=os.environ.get('SSH_PASSWORD')

Вводпароля

323

Page 324: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодульpexpectМодульpexpectпозволяетавтоматизироватьинтерактивныеподключения,такиекак:

telnetsshftp

Дляначала,модульpexpectнужноустановить:

pipinstallpexpect

PexpectэтореализацияexpectнаPython.

Логикаработыpexpectтакая:

запускаетсякакая-топрограммаpexpectожидаетопределенныйвывод(приглашение,запроспароляиподобное)получиввывод,онотправляеткоманды/данныепоследниедвадействияповторяютсястолько,скольконужно

Приэтом,самpexpectнереализуетразличныеутилиты,аиспользуетужеготовые.

Вpexpectестьдваосновныхинструмента:

функцияrun()классspawn

pexpect.run()

Функцияrun()позволяетлегковызватькакую-топрограммуивернутьеёвывод.

Например:

Pexpect

324

Page 325: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[1]:importpexpect

In[2]:output=pexpect.run('ls-ls')

In[3]:printoutput

total368

8-rw-r--r--1natashastaff372Sep2608:36LICENSE.md

8-rw-r--r--1natashastaff3483Sep2608:36README.md

16-rw-r--r--1natashastaff7098Oct511:41SUMMARY.md

8-rw-r--r--1natashastaff70Sep2519:01about.md

0drwxr-xr-x17natashastaff578Sep2519:05book

8-rw-r--r--1natashastaff239Sep2706:32book.json

288-rw-r--r--1natashastaff146490Sep2709:11cover.jpg

0drwxr-xr-x6natashastaff204Sep2519:01exercises

24-rw-r--r--1natashastaff10024Sep2519:01faq.md

0drwxr-xr-x3natashastaff102Sep2716:25resources

8-rw-r--r--1natashastaff3633Sep2715:52schedule.md

pexpect.spawn

Классspawnподдерживаетбольшевозможностей.Онпозволяетвзаимодействоватьсвызваннойпрограммой,отправляяданныеиожидаяответ.

Простойпримериспользованияpexpect.spawn:

t=pexpect.spawn('[email protected]')

t.expect('Password:')

t.sendline("userpass")

t.expect('>')

СначалавыполняетсяподключениепоSSH,затемpexpectожидаетстрокуPassword:.Кактолькоэтастрокапоявилась,отправляетсяпароль.Послеотправки,pexpectожидаетстроку>.

Примериспользованияpexpect

Примериспользованияpexpectдляподключениякоборудованиюипередачикомандыshow(файл1_pexpect.py):

Pexpect

325

Page 326: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importpexpect

importgetpass

importsys

COMMAND=sys.argv[1]

USER=raw_input("Username:")

PASSWORD=getpass.getpass()

ENABLE_PASS=getpass.getpass(prompt='Enterenablepassword:')

DEVICES_IP=['192.168.100.1','192.168.100.2','192.168.100.3']

forIPinDEVICES_IP:

print"Connectiontodevice%s"%IP

t=pexpect.spawn('ssh%s@%s'%(USER,IP))

t.expect('Password:')

t.sendline(PASSWORD)

t.expect('>')

t.sendline('enable')

t.expect('Password:')

t.sendline(ENABLE_PASS)

t.expect('#')

t.sendline("terminallength0")

t.expect('#')

t.sendline(COMMAND)

t.expect('#')

printt.before

Комментариисскрипту:

команда,которуюнужновыполнить,передаетсякакаргументзатемзапрашиваетсялогин,парольипарольнарежимenable

паролизапрашиваютсяспомощьюмодуляgetpassip_listэтосписокIP-адресовустройств,ккоторымбудетвыполнятьсяподключениевцикле,выполняетсяподключениекустройствамизспискавклассеspawnвыполняетсяподключениепоSSHктекущемуадресу,используяуказанноеимяпользователяпослеэтого,начинаютчередоватьсяпарыметодов:expectиsendline

expect-ожиданиеподстрокиsendline-когдастрокапоявилась,отправляетсякоманда

такпроисходитдоконцацикла,итолькопоследняякомандаотличается:

Pexpect

326

Page 327: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

beforeпозволяетсчитатьвсё,чтопоймалpexpectдопредыдущейподстрокивexpect

Выполнениескриптавыглядиттак:

$python1_pexpect.py"shipintbr"

Username:nata

Password:

Enterenablesecret:

Connectiontodevice192.168.100.1

shipintbr

InterfaceIP-AddressOK?MethodStatusProtocol

FastEthernet0/0192.168.100.1YESNVRAMupup

FastEthernet0/1unassignedYESNVRAMupup

FastEthernet0/1.1010.1.10.1YESmanualupup

FastEthernet0/1.2010.1.20.1YESmanualupup

FastEthernet0/1.3010.1.30.1YESmanualupup

FastEthernet0/1.4010.1.40.1YESmanualupup

FastEthernet0/1.5010.1.50.1YESmanualupup

FastEthernet0/1.6010.1.60.1YESmanualupup

FastEthernet0/1.7010.1.70.1YESmanualupup

R1

Connectiontodevice192.168.100.2

shipintbr

InterfaceIP-AddressOK?MethodStatusProtocol

FastEthernet0/0192.168.100.2YESNVRAMupup

FastEthernet0/1unassignedYESNVRAMupup

FastEthernet0/1.1010.2.10.1YESmanualupup

FastEthernet0/1.2010.2.20.1YESmanualupup

FastEthernet0/1.3010.2.30.1YESmanualupup

FastEthernet0/1.4010.2.40.1YESmanualupup

FastEthernet0/1.5010.2.50.1YESmanualupup

FastEthernet0/1.6010.2.60.1YESmanualupup

FastEthernet0/1.7010.2.70.1YESmanualupup

R2

Connectiontodevice192.168.100.3

shipintbr

InterfaceIP-AddressOK?MethodStatusProtocol

FastEthernet0/0192.168.100.3YESNVRAMupup

FastEthernet0/1unassignedYESNVRAMupup

FastEthernet0/1.1010.3.10.1YESmanualupup

FastEthernet0/1.2010.3.20.1YESmanualupup

FastEthernet0/1.3010.3.30.1YESmanualupup

FastEthernet0/1.4010.3.40.1YESmanualupup

FastEthernet0/1.5010.3.50.1YESmanualupup

FastEthernet0/1.6010.3.60.1YESmanualupup

FastEthernet0/1.7010.3.70.1YESmanualupup

R3

Обратитевнимание,что,таккаквпоследнемexpectуказано,чтонадоожидатьподстроку#,методbeforeпоказаликомандуиимяхоста.

Pexpect

327

Page 328: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Специальныесимволывshell

Pexpectнеинтерпретируетспециальныесимволыshell,такиекак>,|,*.

Длятогочтобы,например,командаls-ls|grepSUMMARYотработала,нужнозапуститьshellтакимобразом:

In[1]:importpexpect

In[2]:p=pexpect.spawn('/bin/bash-c"ls-ls|grepSUMMARY"')

In[3]:p.expect(pexpect.EOF)

Out[3]:0

In[4]:printp.before

16-rw-r--r--1natashastaff7156Oct513:05SUMMARY.md

pexpect.EOF

Впредыдущемпримеревстретилосьиспользованиеpexpect.EOF.

EOF(endoffile)—конецфайла

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

Привызовекомандыls-ls,pexpectнеполучаетинтерактивныйсеанс.Командавыполняетсяивсё,наэтомзавершаетсяеёработа.

Поэтому,еслизапуститьеёиуказатьвexpectприглашение,возникнетошибка:

In[5]:p=pexpect.spawn('/bin/bash-c"ls-ls|grepSUMMARY"')

In[6]:p.expect('nattaur')

---------------------------------------------------------------------------

EOFTraceback(mostrecentcalllast)

<ipython-input-9-9c71777698c2>in<module>()

---->1p.expect('nattaur')

/Library/Python/2.7/site-packages/pexpect/spawnbase.pycinexpect(self,pattern,timeo

ut,searchwindowsize,async)

313compiled_pattern_list=self.compile_pattern_list(pattern)

314returnself.expect_list(compiled_pattern_list,

-->315timeout,searchwindowsize,async)

316

317defexpect_list(self,pattern_list,timeout=-1,searchwindowsize=-1,

/Library/Python/2.7/site-packages/pexpect/spawnbase.pycinexpect_list(self,pattern_l

ist,timeout,searchwindowsize,async)

Pexpect

328

Page 329: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

337returnexpect_async(exp,timeout)

338else:

-->339returnexp.expect_loop(timeout)

340

341defexpect_exact(self,pattern_list,timeout=-1,searchwindowsize=-1,

/Library/Python/2.7/site-packages/pexpect/expect.pycinexpect_loop(self,timeout)

100timeout=end_time-time.time()

101exceptEOFase:

-->102returnself.eof(e)

103exceptTIMEOUTase:

104returnself.timeout(e)

/Library/Python/2.7/site-packages/pexpect/expect.pycineof(self,err)

47iferrisnotNone:

48msg=str(err)+'\n'+msg

--->49raiseEOF(msg)

50

51deftimeout(self,err=None):

EOF:EndOfFile(EOF).Emptystringstyleplatform.

<pexpect.pty_spawn.spawnobjectat0x107100b10>

command:/bin/bash

args:['/bin/bash','-c','ls-ls|grepSUMMARY']

searcher:None

buffer(last100chars):''

before(last100chars):'16-rw-r--r--1natashastaff7156Oct513:05SUMMA

RY.md\r\n'

after:<class'pexpect.exceptions.EOF'>

match:None

match_index:None

exitstatus:0

flag_eof:True

pid:85765

child_fd:7

closed:False

timeout:30

delimiter:<class'pexpect.exceptions.EOF'>

logfile:None

logfile_read:None

logfile_send:None

maxread:2000

ignorecase:False

searchwindowsize:None

delaybeforesend:0.05

delayafterclose:0.1

delayafterterminate:0.1

Но,еслипередатьвexpectEOF,ошибкинебудет.

Возможностиpexpect.expect

Pexpect

329

Page 330: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

pexpect.expectвкачествешаблонаможетприниматьнетолькостроку.

Чтоможетиспользоватьсякакшаблонвpexpect.expect:

строкаEOF-этотшаблонпозволяетсреагироватьнаисключениеEOFTIMEOUT-исключениеtimeout(поумолчаниюзначениеtimeout=30секунд)compiledre

Ещеоднаоченьполезнаявозможностьpexpect.expect:можнопередаватьнеоднозначение,асписок.

Например:

In[7]:p=pexpect.spawn('/bin/bash-c"ls-ls|grepSUMMARY"')

In[8]:p.expect(['nattaur',pexpect.TIMEOUT,pexpect.EOF])

Out[8]:2

Тутнескольковажныхмоментов:

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

вданномслучае,номер2,таккакисключениеEOFнаходитсявспискеподномеромдва

засчеттакогоформата,можноделатьответвлениявпрограмме,взависимостиоттогоскакимэлементомбылосовпадение

Документацияpexpect

Документациямодуля:pexpect.

Pexpect

330

Page 331: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодульtelnetlibМодульtelnetlibвходитвстандартнуюбиблиотекуPython.Этореализацияклиентаtelnet.

Подключитьсяпоtelnetможноииспользуяpexpect.Плюсtelnetlibвтом,чтоэтотмодульвходитвстандартнуюбиблиотекуPython.

Принципработыtelnetlibнапоминаетpexpect,поэтомупримернижедолженбытьпонятен.

Файл2_telnetlib.py:

importtelnetlib

importtime

importgetpass

importsys

COMMAND=sys.argv[1]

USER=raw_input("Username:")

PASSWORD=getpass.getpass()

ENABLE_PASS=getpass.getpass(prompt='Enterenablepassword:')

DEVICES_IP=['192.168.100.1','192.168.100.2','192.168.100.3']

forIPinDEVICES_IP:

print"Connectiontodevice%s"%IP

t=telnetlib.Telnet(IP)

t.read_until("Username:")

t.write(USER+'\n')

t.read_until("Password:")

t.write(PASSWORD+'\n')

t.write("enable\n")

t.read_until("Password:")

t.write(ENABLE_PASS+'\n')

t.write("terminallength0\n")

t.write(COMMAND+'\n')

time.sleep(5)

output=t.read_very_eager()

printoutput

Telnetlib

331

Page 332: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Востальном,telnetlibоченьпохожнаpexpect:

t=telnetlib.Telnet(ip)-классTelnetпредставляетсоединениексерверу.вданномслучае,емупередаетсятолькоIP-адрес,номожнопередатьипорт,ккоторомунужноподключаться

read_until-похожнаметодexpectвмодулеpexpect.Указываетдокакойстрокиследуетсчитыватьвыводwrite-передатьстрокуread_very_eager-считатьвсё,чтополучается

Выполнениескрипт:

Telnetlib

332

Page 333: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$python2_telnetlib.py"shipintbr"

Username:nata

Password:

Enterenablesecret:

Connectiontodevice192.168.100.1

R1#terminallength0

R1#shipintbr

InterfaceIP-AddressOK?MethodStatusProtocol

FastEthernet0/0192.168.100.1YESNVRAMupup

FastEthernet0/1unassignedYESNVRAMupup

FastEthernet0/1.1010.1.10.1YESmanualupup

FastEthernet0/1.2010.1.20.1YESmanualupup

FastEthernet0/1.3010.1.30.1YESmanualupup

FastEthernet0/1.4010.1.40.1YESmanualupup

FastEthernet0/1.5010.1.50.1YESmanualupup

FastEthernet0/1.6010.1.60.1YESmanualupup

FastEthernet0/1.7010.1.70.1YESmanualupup

R1#

Connectiontodevice192.168.100.2

R2#terminallength0

R2#shipintbr

InterfaceIP-AddressOK?MethodStatusProtocol

FastEthernet0/0192.168.100.2YESNVRAMupup

FastEthernet0/1unassignedYESNVRAMupup

FastEthernet0/1.1010.2.10.1YESmanualupup

FastEthernet0/1.2010.2.20.1YESmanualupup

FastEthernet0/1.3010.2.30.1YESmanualupup

FastEthernet0/1.4010.2.40.1YESmanualupup

FastEthernet0/1.5010.2.50.1YESmanualupup

FastEthernet0/1.6010.2.60.1YESmanualupup

FastEthernet0/1.7010.2.70.1YESmanualupup

R2#

Connectiontodevice192.168.100.3

R3#terminallength0

R3#shipintbr

InterfaceIP-AddressOK?MethodStatusProtocol

FastEthernet0/0192.168.100.3YESNVRAMupup

FastEthernet0/1unassignedYESNVRAMupup

FastEthernet0/1.1010.3.10.1YESmanualupup

FastEthernet0/1.2010.3.20.1YESmanualupup

FastEthernet0/1.3010.3.30.1YESmanualupup

FastEthernet0/1.4010.3.40.1YESmanualupup

FastEthernet0/1.5010.3.50.1YESmanualupup

FastEthernet0/1.6010.3.60.1YESmanualupup

FastEthernet0/1.7010.3.70.1YESmanualupup

R3#

Telnetlib

333

Page 334: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Мынебудемподробнееостанавливатьсянаtelnetlib.Остальныеметоды,которыеподдерживаетмодуль,можнопосмотретьвдокументации.

Документациямодуляtelnetlib:telnetlib

Telnetlib

334

Page 335: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодульparamikoParamikoэтореализацияпротоколаSSHv2наPython.Paramikoпредоставляетфункциональностьклиентаисервера.Мыбудемрассматриватьтолькофункциональностьклиента.

ТаккакParamikoневходитвстандартнуюбиблиотекумодулейPython,егонужноустановить:

pipinstallparamiko

ПримериспользованияParamiko(файл3_paramiko.py):

importparamiko

importgetpass

importsys

importtime

COMMAND=sys.argv[1]

USER=raw_input("Username:")

PASSWORD=getpass.getpass()

ENABLE_PASS=getpass.getpass(prompt='Enterenablepassword:')

DEVICES_IP=['192.168.100.1','192.168.100.2','192.168.100.3']

forIPinDEVICES_IP:

print"Connectiontodevice%s"%IP

client=paramiko.SSHClient()

client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

client.connect(hostname=IP,username=USER,password=PASSWORD,look_for_keys=False,

allow_agent=False)

ssh=client.invoke_shell()

ssh.send("enable\n")

ssh.send(ENABLE_PASS+'\n')

time.sleep(1)

ssh.send("terminallength0\n")

time.sleep(1)

printssh.recv(1000)

ssh.send(COMMAND+"\n")

time.sleep(2)

result=ssh.recv(5000)

printresult

Paramiko

335

Page 336: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Комментариикскрипту:

client=paramiko.SSHClient()

этоткласспредставляетсоединениекSSH-серверу.Онвыполняетаутентификациюклиента.

client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

set_missing_host_key_policy-устанавливаеткакуюполитикуиспользовать,когдавыполнятсяподключениексерверу,ключкоторогонеизвестен.paramiko.AutoAddPolicy()-политика,котораяавтоматическидобавляетновоеимяхостаиключвлокальныйобъектHostKeys.

client.connect(IP,username=USER,password=PASSWORD,look_for_keys=False,

allow_agent=False)

client.connect-метод,которыйвыполняетподключениекSSH-серверуиаутентифицируетподключение

hostname-имяхостаилиIP-адресusername-имяпользователяpassword-парольlook_for_keys-поумолчаниюparamikoвыполняетаутентификациюпоключам.Чтобыотключитьэто,надопоставитьпоставивFalseallow_agent-paramikoможетподключатьсяклокальномуSSHагентуОС.Этонужноприработесключами,атаккак,вданномслучае,аутентификациявыполняетсяпологину/паролю,этонужноотключить.

ssh=client.invoke_shell()

послевыполненияпредыдущейкомандыужеестьподключениексерверу.Методinvoke_shellпозволяетустановитьинтерактивнуюсессиюSSHссервером.

Внутриустановленнойсессиивыполняютсякомандыиполучаютсяданные:ssh.send-отправляетуказаннуюстрокувсессиюssh.recv-получаетданныеизсессии.Вскобкахуказываетсямаксимальноезначениевбайтах,котороеможнополучить.Этотметодвозвращаетсчитаннуюстроку

Кромеэтого,междуотправкойкомандыисчитыванием,кое-гдестоитстрокаtime.sleep

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

Таквыглядитрезультатвыполненияскрипта:

$python3_paramiko.py"shipintbr"

Username:cisco

Password:

Paramiko

336

Page 337: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Enterenablesecret:

Connectiontodevice192.168.100.1

R1>enable

Password:

R1#terminallength0

R1#

shipintbr

InterfaceIP-AddressOK?MethodStatusProtocol

FastEthernet0/0192.168.100.1YESNVRAMupup

FastEthernet0/1unassignedYESNVRAMupup

FastEthernet0/1.1010.1.10.1YESmanualupup

FastEthernet0/1.2010.1.20.1YESmanualupup

FastEthernet0/1.3010.1.30.1YESmanualupup

FastEthernet0/1.4010.1.40.1YESmanualupup

FastEthernet0/1.5010.1.50.1YESmanualupup

FastEthernet0/1.6010.1.60.1YESmanualupup

FastEthernet0/1.7010.1.70.1YESmanualupup

R1#

Connectiontodevice192.168.100.2

R2>enable

Password:

R2#terminallength0

R2#

shipintbr

FastEthernet0/0192.168.100.2YESNVRAMupup

FastEthernet0/1unassignedYESNVRAMupup

FastEthernet0/1.1010.2.10.1YESmanualupup

FastEthernet0/1.2010.2.20.1YESmanualupup

FastEthernet0/1.3010.2.30.1YESmanualupup

FastEthernet0/1.4010.2.40.1YESmanualupup

FastEthernet0/1.5010.2.50.1YESmanualupup

FastEthernet0/1.6010.2.60.1YESmanualupup

FastEthernet0/1.7010.2.70.1YESmanualupup

R2#

Connectiontodevice192.168.100.3

R3>enable

Password:

R3#terminallength0

R3#

shipintbr

InterfaceIP-AddressOK?MethodStatusProtocol

FastEthernet0/0192.168.100.3YESNVRAMupup

FastEthernet0/1unassignedYESNVRAMupup

FastEthernet0/1.1010.3.10.1YESmanualupup

FastEthernet0/1.2010.3.20.1YESmanualupup

FastEthernet0/1.3010.3.30.1YESmanualupup

FastEthernet0/1.4010.3.40.1YESmanualupup

FastEthernet0/1.5010.3.50.1YESmanualupup

Paramiko

337

Page 338: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

FastEthernet0/1.6010.3.60.1YESmanualupup

FastEthernet0/1.7010.3.70.1YESmanualupup

R3#

Обратитевнимание,чтоввыводпопалипроцессвводапароляenableикомандаterminallength.

Этосвязаностем,чтоparamikoсобираетвесьвыводвбуфер.И,привызовеметодаrecv(например,ssh.recv(1000)),paramikoвозвращаетвсё,чтоестьвбуфере.Послевыполненияrecv,буферпуст.

Поэтому,еслинужнополучитьтольковыводкомандыshipintbr,тонадооставитьrecv,нонеделатьprint:

ssh.send("enable\n")

ssh.send(ENABLE_PASS+'\n')

time.sleep(1)

ssh.send("terminallength0\n")

time.sleep(1)

#Тутмывызываемrecv,ноневыводимсодержимоебуфера

ssh.recv(1000)

ssh.send(COMMAND+"\n")

time.sleep(3)

result=ssh.recv(5000)

printresult

ДокументацияParamiko

Всё,чтокасаетсяклиента:ParamikoClientВсё,чтокасаетсясоединения(внашемпримере,всё,чтоотноситсякпеременнойssh):ParamikoChannel

Paramiko

338

Page 339: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодульnetmikoNetmikoэтомодуль,которыйпозволяетупроститьиспользованиеparamikoдлясетевыхустройств.

Грубоговоря,netmikoэтотакая"обертка"дляparamiko.

Сначалаnetmikoнужноустановить:

pipinstallnetmiko

Примериспользованияnetmiko(файл4_netmiko.py):

fromnetmikoimportConnectHandler

importgetpass

importsys

COMMAND=sys.argv[1]

USER=raw_input("Username:")

PASSWORD=getpass.getpass()

ENABLE_PASS=getpass.getpass(prompt='Enterenablepassword:')

DEVICES_IP=['192.168.100.1','192.168.100.2','192.168.100.3']

forIPinDEVICES_IP:

print"Connectiontodevice%s"%IP

DEVICE_PARAMS={'device_type':'cisco_ios',

'ip':IP,

'username':USER,

'password':PASSWORD,

'secret':ENABLE_PASS}

ssh=ConnectHandler(**DEVICE_PARAMS)

ssh.enable()

result=ssh.send_command(COMMAND)

printresult

Посмотритенасколькопрощевыглядитэтотпримерсnetmiko.

Разберемсяссодержимымскрипта:

DEVICE_PARAMS-этословарь,вкоторомуказываютсяпараметрыустройстваdevice_type-этопредопределенныезначения,которыепонимаетnetmiko

вданномслучае,таккакподключениевыполняетсякустройствусCisco

Netmiko

339

Page 340: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

IOS,используетсязначение'cisco_ios'ssh=ConnectHandler(**DEVICE_PARAMS)-устанавливаетсясоединениесустройством,наосновепараметров,которыенаходятсявсловаре

двезвездочкипередсловарем,этораспаковкасловаря(подробнеевразделеРаспаковкааргументов)

ssh.enable()-переходврежимenableпарольпередаетсяавтоматическииспользуетсязначениеключаsecret,которыйуказанвсловареDEVICE_PARAMS

result=ssh.send_command(COMMAND)-отправкакомандыиполучениевывода

Вэтомпримеренепередаетсякомандаterminallength,таккакnetmikoпоумолчанию,выполняетэтукоманду.

Таквыглядитрезультатвыполненияскрипта:

Netmiko

340

Page 341: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$python4_netmiko.py"shipintbr"

Username:cisco

Password:

Enterenablepassword:

Connectiontodevice192.168.100.1

InterfaceIP-AddressOK?MethodStatusProtocol

FastEthernet0/0192.168.100.1YESNVRAMupup

FastEthernet0/1unassignedYESNVRAMupup

FastEthernet0/1.1010.1.10.1YESmanualupup

FastEthernet0/1.2010.1.20.1YESmanualupup

FastEthernet0/1.3010.1.30.1YESmanualupup

FastEthernet0/1.4010.1.40.1YESmanualupup

FastEthernet0/1.5010.1.50.1YESmanualupup

FastEthernet0/1.6010.1.60.1YESmanualupup

FastEthernet0/1.7010.1.70.1YESmanualupup

Connectiontodevice192.168.100.2

InterfaceIP-AddressOK?MethodStatusProtocol

FastEthernet0/0192.168.100.2YESNVRAMupup

FastEthernet0/1unassignedYESNVRAMupup

FastEthernet0/1.1010.2.10.1YESmanualupup

FastEthernet0/1.2010.2.20.1YESmanualupup

FastEthernet0/1.3010.2.30.1YESmanualupup

FastEthernet0/1.4010.2.40.1YESmanualupup

FastEthernet0/1.5010.2.50.1YESmanualupup

FastEthernet0/1.6010.2.60.1YESmanualupup

FastEthernet0/1.7010.2.70.1YESmanualupup

Connectiontodevice192.168.100.3

InterfaceIP-AddressOK?MethodStatusProtocol

FastEthernet0/0192.168.100.3YESNVRAMupup

FastEthernet0/1unassignedYESNVRAMupup

FastEthernet0/1.1010.3.10.1YESmanualupup

FastEthernet0/1.2010.3.20.1YESmanualupup

FastEthernet0/1.3010.3.30.1YESmanualupup

FastEthernet0/1.4010.3.40.1YESmanualupup

FastEthernet0/1.5010.3.50.1YESmanualupup

FastEthernet0/1.6010.3.60.1YESmanualupup

FastEthernet0/1.7010.3.70.1YESmanualupup

Ввыводенетникакихлишнихприглашений,тольковыводкомандыshipintbr.

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

Netmiko

341

Page 342: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПоддерживаемыетипыустройствNetmikoподдерживаетнесколькотиповустройств:

AristavEOSCiscoASACiscoIOSCiscoIOS-XRCiscoSG300HPComware7HPProCurveJuniperJunosLinuxидругие

Актуальныйсписокможнопосмотретьврепозиториимодуля.

Словарь,определяющийпараметрыустройствВсловаремогутуказыватьсятакиепараметры:

cisco_router={'device_type':'cisco_ios',#предопределенныйтипустройства

'ip':'192.168.1.1',#адресустройства

'username':'user',#имяпользователя

'password':'userpass',#парольпользователя

'secret':'enablepass',#парольрежимаenable

'port':20022,#портSSH,поумолчанию22

}

ПодключениепоSSH

ssh=ConnectHandler(**cisco_router)

РежимenableПерейтиврежимenable:

Возможностиnetmiko

342

Page 343: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ssh.enable()

Выйтиизрежимаenable:

ssh.exit_enable_mode()

ОтправкакомандВnetmikoестьнесколькоспособовотправкикоманд:

send_command-отправитьоднукомандуsend_config_set-отправитьсписоккомандsend_config_from_file-отправитькомандыизфайла(используетвнутриметодsend_config_set)send_command_timing-отправитькомандуиподождатьвыводнаоснованиитаймера

send_command

Методsend_commandпозволяетотправитьоднукомандунаустройство.

Например:

result=ssh.send_command("showipintbr")

Методработаеттакимобразом:

отправляеткомандунаустройствоиполучаетвыводдострокисприглашениемилидоуказаннойстроки

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

методвозвращаетвыводкомандыметодуможнопередаватьтакиепараметры:

command_string-командаexpect_string-докакойстрокисчитыватьвывод```delay_factor-параметрпозволяетувеличитьзадержкудоначалапоискастроки

Возможностиnetmiko

343

Page 344: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

max_loops-количествоитераций,дотогокакметодвыдастошибку(исключение).Поумолчанию500strip_prompt-удалитьприглашениеизвывода.Поумолчаниюудаляетсяstrip_command-удалитьсамукомандуизвывода

Вбольшинствеслучаев,достаточнобудетуказатьтолькокоманду.

send_config_set

Методsend_config_setпозволяетотправитьнесколькокомандконфигурационногорежима.

Примериспользования:

commands=["routerospf1",

"network10.0.0.00.255.255.255area0",

"network192.168.100.00.0.0.255area1"]

result=ssh.send_config_set(commands)

Методработаеттакимобразом:

заходитвконфигурационныйрежим,затемпередаетвсекомандыивыходитизконфигурационногорежима

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

send_config_from_file

Методsend_config_from_fileотправляеткомандыизуказанногофайлавконфигурационныйрежим.

Примериспользования:

result=ssh.send_config_from_file("config_ospf.txt")

Методоткрываетфайл,считываеткомандыипередаетихметодуsend_config_set.

Дополнительныеметоды

Возможностиnetmiko

344

Page 345: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Кромеперечисленныхметодовдляотправкикоманд,netmikoподдерживаеттакиеметоды:

config_mode-перейтиврежимконфигурацииssh.config_mode()

exit_config_mode-выйтиизрежимаконфигурацииssh.exit_config_mode()

check_config_mode-проверитьнаходитсялиnetmikoврежимеконфигурации(возвращаетTrue,есливрежимеконфигурациииFalse-еслинет)

ssh.check_config_mode()

find_prompt-возвращаеттекущееприглашениеустройстваssh.find_prompt()

commit-выполнитьcommitнаIOS-XRиJuniperssh.commit()

disconnect-завершитьсоединениеSSH

ТутsshэтосозданноепредварительносоединениеSSH:ssh=ConnectHandler(**cisco_router)

TelnetСверсии1.0.0netmikoподдерживаетподключенияпоTelnet.Покачто,толькодляCiscoIOSустройств.

Внутри,netmikoиспользуетtelnetlib,дляподключенияпоTelnet.Но,приэтом,предоставляеттотжеинтерфейсдляработы,чтоиподключениепоSSH.

Длятого,чтобыподключитьсяпоTelnet,достаточновсловаре,которыйопределяетпараметрыподключения,указатьтипустройства'cisco_ios_telnet':

DEVICE_PARAMS={'device_type':'cisco_ios_telnet',

'ip':IP,

'username':USER,

'password':PASSWORD,

'secret':ENABLE_PASS}

Востальном,методы,которыеприменимыкSSH,применимыикTelnet.Пример,аналогичныйпримерусSSH(файл4_netmiko_telnet.py):

Возможностиnetmiko

345

Page 346: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

fromnetmikoimportConnectHandler

importgetpass

importsys

importtime

COMMAND=sys.argv[1]

USER=raw_input("Username:")

PASSWORD=getpass.getpass()

ENABLE_PASS=getpass.getpass(prompt='Enterenablepassword:')

DEVICES_IP=['192.168.100.1','192.168.100.2','192.168.100.3']

forIPinDEVICES_IP:

print"Connectiontodevice%s"%IP

DEVICE_PARAMS={'device_type':'cisco_ios_telnet',

'ip':IP,

'username':USER,

'password':PASSWORD,

'secret':ENABLE_PASS,

'verbose':True}

ssh=ConnectHandler(**DEVICE_PARAMS)

ssh.enable()

result=ssh.send_command(COMMAND)

printresult

Аналогичноработаютиметоды:

send_command_timing()

find_prompt()

send_config_set()

send_config_from_file()

check_enable_mode()

disconnect()

Возможностиnetmiko

346

Page 347: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПараллельныесессииКогданужноопроситьмногоустройств,выполнениеподключенийпоочередно,будетдостаточнодолгим.Конечно,этобудетбыстрее,чемподключениевручную.Но,хотелосьбыполучатьоткликкакможнобыстрее.

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

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

threadingmultiprocessing

ИзмерениевременивыполненияскриптаДляоценкивременивыполненияскриптаестьнескольковариантов.Вкурсеиспользуютсясамыепростыеварианты:

утилитуLinuxtimeимодульPythondatetime

Рассматриваютсяобаварианта,натотслучай,еслииспользуетсяWindows.

Приоценкевременивыполненияскрипта,вданномслучае,неважнавысокаяточность.Главное,сравнитьвремявыполненияскриптавразныхвариантах.

time

УтилитаtimeвLinuxпозволяетзамеритьвремявыполненияскрипта.Например:

$timepythonthread_paramiko.py

...

real0m4.712s

user0m0.336s

sys0m0.064s

Насинтересуетrealвремя.Вданномслучае,это4.7секунд.

Дляиспользованияутилитыtimeдостаточнонаписатьtimeпередстрокойзапускаскрипта.

Одновременноеподключениекнесколькимустройствам

347

Page 348: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

datetime

Второйвариант-модульdatetime.ЭтотмодульпозволяетработатьсвременемидатамивPython.

Примериспользования:

fromdatetimeimportdatetime

importtime

start_time=datetime.now()

#Тутвыполняютсядействия

time.sleep(5)

printdatetime.now()-start_time

Результатвыполнения:

$pythontest.py

0:00:05.004949

ПроблемыспотокамивPython(CPython)

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

Дляначала,намнужноразобратьсястерминами:

процесс(process)-это,грубоговоря,запущеннаяпрограмма.Процессувыделяютсяотдельныересурсы:память,процессорноевремяпоток(thread)-этоединицаисполнениявпроцессе.Потокиразделяютресурсыпроцесса,ккоторомуониотносятся.

Python(аточнее,CPython-реализациякотораяиспользуетсявкурсе)оптимизировандляработыводнопоточномрежиме.Этохорошо,есливпрограммеиспользуетсятолькоодинпоток.

И,втожевремя,уPythonестьопределенныенюансыработывмногопоточномрежиме.Связаныонистем,чтоCPythonиспользуетGIL(globalinterpreterlock).

Одновременноеподключениекнесколькимустройствам

348

Page 349: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

GILнедаетнесколькимпотокамисполнятьодновременнокодPython.Еслиневдаватьсявподробности,тоGILможнопредставитькакнекийпереходящийфлаг,которыйразрешаетпотокамвыполняться.Укогофлаг,тотможетвыполнятьработу.

Флагпередаетсялибокаждыесколько-тоинструкцийPython,либо,например,когдавыполняютсякакие-тооперацииввода-вывода.

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

Но,невсётакплохо.Есливпрограммеестьнекое"ожидание":пакетовизсети,запросапользователя,паузатипаsleep,товтакойпрограммепотокибудутвыполнятьсякак-будтопараллельно.Авсёпотому,что,вовремятакихпауз,флаг(GIL)можнопередатьдругомупотоку.

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

Влюбомслучае,употоковвPythonестьсвоиобластиприменения.ВследующихразделахрассматриваетсякакиспользоватьпотокидляподключенияпоTelnet/SSH.Ипроверяется,какоесуммарноевремябудетзаниматьисполнениескрипта,посравнениюспоследовательнымисполнениемисиспользованиемпроцессов.

ПроцессыОбычно,чтобынепогружатьсявовсеэтитонкостисGILипотокамивPython,прощепростоиспользоватьмодульmultiprocessingивсё.

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

ДополнительнаяинформацияЕсливыхотитеподробнееразобратьсясэтимивопросами,илизахотитевернутьсякнимпозже,несколькоссылок:

GIL:GIL(нарусском)InsidethePythonGIL

ОтличнаястатьяPythonthreadsandtheGILКороткооGIL,threads,processes:

Одновременноеподключениекнесколькимустройствам

349

Page 350: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

http://stackoverflow.com/questions/3044580/multiprocessing-vs-threading-pythonhttp://stackoverflow.com/questions/18114285/python-what-are-the-differences-between-the-threading-and-multiprocessing-modul

Одновременноеподключениекнесколькимустройствам

350

Page 351: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодульthreadingМодульthreadingможетбытьполезендлятакихзадач:

фоновоевыполнениекаких-тозадач:например,отправкапочтывовремяожиданияответаотпользователя

параллельноевыполнениезадачсвязанныхсвводом/выводоможиданиевводаотпользователячтение/записьфайлов

задачи,гдеприсутствуютпаузы:например,паузыспомощьюsleep

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

Рассмотримпримериспользованиямодуляthreadingвместеспоследнимпримеромсnetmiko.

Таккакдляработысthreading,удобнееиспользоватьфункции,кодизменен:

кодподключенияпоSSHперенесенвфункциюпараметрыустройствперенесенывотдельныйфайлвформатеYAML

Файлnetmiko_function.py:

fromnetmikoimportConnectHandler

importsys

importyaml

COMMAND=sys.argv[1]

devices=yaml.load(open('devices.yaml'))

defconnect_ssh(device_dict,command):

print"Connectiontodevice%s"%device_dict['ip']

ssh=ConnectHandler(**device_dict)

ssh.enable()

result=ssh.send_command(command)

printresult

forrouterindevices['routers']:

connect_ssh(router,COMMAND)

Модульthreading

351

Page 352: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Файлdevices.yamlспараметрамиподключениякустройствам:

routers:

-device_type:cisco_ios

ip:192.168.100.1

username:cisco

password:cisco

secret:cisco

-device_type:cisco_ios

ip:192.168.100.2

username:cisco

password:cisco

secret:cisco

-device_type:cisco_ios

ip:192.168.100.3

username:cisco

password:cisco

secret:cisco

Времявыполненияскрипта(выводскриптаудален):

$timepythonnetmiko_function.py"shipintbr"

...

real0m6.189s

user0m0.336s

sys0m0.080s

ПримериспользованиямодуляthreadingдляподключенияпоSSHспомощьюnetmiko(файлnetmiko_threading.py):

Модульthreading

352

Page 353: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

fromnetmikoimportConnectHandler

importsys

importyaml

importthreading

COMMAND=sys.argv[1]

devices=yaml.load(open('devices.yaml'))

defconnect_ssh(device_dict,command):

ssh=ConnectHandler(**device_dict)

ssh.enable()

result=ssh.send_command(command)

print"Connectiontodevice%s"%device_dict['ip']

printresult

defconn_threads(function,devices,command):

threads=[]

fordeviceindevices:

th=threading.Thread(target=function,args=(device,command))

th.start()

threads.append(th)

forthinthreads:

th.join()

conn_threads(connect_ssh,devices['routers'],COMMAND)

Времявыполнениякода:

$timepythonnetmiko_function_threading.py"shipintbr"

...

real0m2.229s

user0m0.408s

sys0m0.068s

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

Комментариикфункцииconn_threads:

threading.Thread-класс,которыйсоздаетпотокемупередаетсяфункция,которуюнадовыполнить,иеёаргументы

th.start()-запускпотокаthreads.append(th)-потокдобавляетсявсписокth.join()-методожидаетзавершенияработыпотока

Модульthreading

353

Page 354: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Получениеданныхизпотоков

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

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

Очередьэтоструктураданных,котораяиспользуетсяивработессетевымоборудованием.ОбъектQueue.Queue()-этоFIFOочередь.

Очередьпередаетсякакаргументвфункциюconnect_ssh,котораяподключаетсякустройствупоSSH.Результатвыполнениякомандыдобавляетсявочередь.

Примериспользованияпотоковсполучениемданных(файлnetmiko_threading_data.py):

Модульthreading

354

Page 355: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

#-*-coding:utf-8-*-

fromnetmikoimportConnectHandler

importsys

importyaml

importthreading

fromQueueimportQueue

COMMAND=sys.argv[1]

devices=yaml.load(open('devices.yaml'))

defconnect_ssh(device_dict,command,queue):

ssh=ConnectHandler(**device_dict)

ssh.enable()

result=ssh.send_command(command)

print"Connectiontodevice%s"%device_dict['ip']

#Добавляемсловарьвочередь

queue.put({device_dict['ip']:result})

defconn_threads(function,devices,command):

threads=[]

#Создаемочередь

q=Queue()

fordeviceindevices:

#Передаемочередькакаргумент,функции

th=threading.Thread(target=function,args=(device,command,q))

th.start()

threads.append(th)

forthinthreads:

th.join()

results=[]

#Беремрезультатыизочередиидобавляемихвсписокresults

fortinthreads:

results.append(q.get())

returnresults

printconn_threads(connect_ssh,devices['routers'],COMMAND)

Обратитевнимание,чтовфункцииconnect_sshдобавилсяаргументqueue.

Очередьвполнеможновосприниматькаксписок:

методqueue.put()равнозначенlist.append()методqueue.get()равнозначенlist.pop(0)

Модульthreading

355

Page 356: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Примерсосписком,скореевсего,будетпрощепонять.Поэтомунижеаналогичныйкод,носиспользованиемобычногосписка,вместоочереди(файлnetmiko_threading_data_list.py):

#-*-coding:utf-8-*-

fromnetmikoimportConnectHandler

importsys

importyaml

importthreading

COMMAND=sys.argv[1]

devices=yaml.load(open('devices.yaml'))

defconnect_ssh(device_dict,command,queue):

ssh=ConnectHandler(**device_dict)

ssh.enable()

result=ssh.send_command(command)

print"Connectiontodevice%s"%device_dict['ip']

#Добавляемсловарьвсписок

queue.append({device_dict['ip']:result})

defconn_threads(function,devices,command):

threads=[]

q=[]

fordeviceindevices:

#Передаемсписоккакаргумент,функции

th=threading.Thread(target=function,args=(device,command,q))

th.start()

threads.append(th)

forthinthreads:

th.join()

#Этачастьнамненужна,таккак,прииспользованиисписка,

#мыпростоможемвернутьего

#results=[]

#fortinthreads:

#results.append(q.get())

returnq

printconn_threads(connect_ssh,devices['routers'],COMMAND)

Модульthreading

356

Page 357: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Модульthreading

357

Page 358: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодульmultiprocessingМодульmultiprocessingиспользуетинтерфейсподобныймодулюthreading.Поэтомуперенестикодсиспользованияпотоковнаиспользованиепроцессов,обычно,достаточнолегко.

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

Примериспользованиямодуляmultiprocessing(файлnetmiko_multiprocessing.py):

Модульmultiprocessing

358

Page 359: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importmultiprocessing

fromnetmikoimportConnectHandler

importsys

importyaml

COMMAND=sys.argv[1]

devices=yaml.load(open('devices.yaml'))

defconnect_ssh(device_dict,command,queue):

ssh=ConnectHandler(**device_dict)

ssh.enable()

result=ssh.send_command(command)

print"Connectiontodevice%s"%device_dict['ip']

queue.put({device_dict['ip']:result})

defconn_processes(function,devices,command):

processes=[]

queue=multiprocessing.Queue()

fordeviceindevices:

p=multiprocessing.Process(target=function,args=(device,command,queue)

)

p.start()

processes.append(p)

forpinprocesses:

p.join()

results=[]

forpinprocesses:

results.append(queue.get())

returnresults

print(conn_processes(connect_ssh,devices['routers'],COMMAND))

Обратитевнимание,чтоэтотпримераналогиченпоследнемупримеру,которыйиспользовалсясмодулемthreading.Единственноеотличиевтом,чтовмодулеmultiprocessingестьсвояреализацияочереди,поэтомунетнеобходимостииспользоватьмодульQueue.

Еслипроверитьвремяисполненияэтогоскрипта,аналогичногодлямодуляthreadingипоследовательногоподключения,тополучаемтакуюкартину:

Модульmultiprocessing

359

Page 360: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

последовательное:5.833s

threading:2.225s

multiprocessing:2.365s

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

Модульmultiprocessing

360

Page 361: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание12.1

Создатьфункциюsend_show_command.

ФункцияподключаетсяпоSSH(спомощьюnetmiko)кустройствамизсписка,ивыполняеткомандунаоснованиипереданныхаргументов.

Параметрыфункции:

devices_list-списоксловарейспараметрамиподключениякустройствам,которымнадопередатькомандыcommand-команда,которуюнадовыполнить

Функциявозвращаетсловарьсрезультатамивыполнениякоманды:

ключ-IPустройствазначение-результатвыполнениякоманды

Проверитьработуфункциинапримере:

устройствизфайлаdevices.yaml(дляэтогонадосчитатьинформациюизфайла)икомандыcommand

Задания

361

Page 362: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importnetmiko

command="shipintbr"

defsend_show_command(device_list,command):

"""

ФункцияподключаетсяпоSSHкустройствамизсписка,ивыполняеткоманду

наоснованиипереданныхаргументов.

Параметрыфункции:

-devices_list-списоксловарейспараметрамиподключениякустройствам,

которымнадопередатькоманды

-command-команда,которуюнадовыполнить

Функциявозвращаетсловарьсрезультатамивыполнениякоманды:

-ключ-IPустройства

-значение-результатвыполнениякоманды

"""

Задание12.2

Создатьфункциюsend_config_commands

ФункцияподключаетсяпоSSH(спомощьюnetmiko)кустройствамизсписка,ивыполняетпереченькомандвконфигурационномрежименаоснованиипереданныхаргументов.

Параметрыфункции:

devices_list-списоксловарейспараметрамиподключениякустройствам,которымнадопередатькомандыconfig_commands-списоккоманд,которыенадовыполнить

Функциявозвращаетсловарьсрезультатамивыполнениякоманды:

ключ-IPустройствазначение-выводсвыполнениемкоманд

Проверитьработуфункциинапримере:

устройствизфайлаdevices.yaml(дляэтогонадосчитатьинформациюизфайла)испискакомандcommands

Задания

362

Page 363: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importnetmiko

commands=['logging10.255.255.1',

'loggingbuffered20010',

'nologgingconsole']

defsend_config_commands(device_list,config_commands):

"""

ФункцияподключаетсяпоSSHкустройствамизсписка,

ивыполняеткомандывконфигурационномрежиме.

Параметрыфункции:

-devices_list-списоксловарейспараметрамиподключениякустройствам,кото

рымнадопередатькоманды

-config_commands-списоккоманд,которыенадовыполнить

Функциявозвращаетсловарьсрезультатамивыполнениякоманды:

-ключ-IPустройства

-значение-выводсвыполнениемкоманд

"""

Задание12.2a

Дополнитьфункциюsend_config_commandsиззадания12.2

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

Задание12.2b

Дополнитьфункциюsend_config_commandsиззадания12.2aили12.2

Добавитьпроверкунаошибки:

Привыполнениикоманд,скриптдолженпроверятьрезультатнатакиеошибки:Invalidinputdetected,Incompletecommand,Ambiguouscommand

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

Проверитьфункциюнакомандесошибкой.

Задание12.3

Задания

363

Page 364: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Создатьфункциюsend_commands(дляподключенияпоSSHиспользуетсяnetmiko).

Параметрыфункции:

devices_list-списоксловарейспараметрамиподключениякустройствам,которымнадопередатькомандыshow-однакомандаshow(строка)filename-имяфайла,вкоторомнаходятсякоманды,которыенадовыполнить(строка)config-списокскомандами,которыенадовыполнитьвконфигурационномрежиме

Взависимостиоттого,какойаргументбылпередан,функциявызываетразныефункциивнутри.

Далеекомбинацияизаргументаисоответствующейфункции:

show--функцияsend_show_commandиззадания12.1config--функцияsend_config_commandsиззадания12.2,12.2aили12.2bfilename--функцияsend_commands_from_file(еетакженадонаписатьпоаналогииспредыдущими)

Функциявозвращаетсловарьсрезультатамивыполнениякоманды:

ключ-IPустройствазначение-выводсвыполнениемкоманд

Проверитьработуфункциинапримере:

устройствизфайлаdevices.yaml(дляэтогонадосчитатьинформациюизфайла)иразличныхкомбинацияаргументаскомандами:

спискакомандcommandsкомандыcommandфайлаconfig.txt

Задания

364

Page 365: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

fromnetmikoimportConnectHandler

commands=['logging10.255.255.1',

'loggingbuffered20010',

'nologgingconsole']

command="shipintbr"

defsend_show_command(device_list,show_command):

pass

defsend_config_commands(device_list,config_commands,output=True):

pass

defsend_commands_from_file(device_list,filename):

pass

defsend_commands(device_list,config=[],show='',filename=''):

pass

Задание12.3a

Изменитьфункциюsend_commandsтакимобразом,чтобывспискесловарейdevice_listненадобылоуказыватьимяпользователя,пароль,ипарольнаenable.

Функциядолжназапрашиватьимяпользователя,парольипарольнаenableпристарте.Парольнедолженотображатьсяпринаборе.

Вфайлеdevices2.yamlэтипараметрыужеудалены.

Задание12.3b

Дополнитьфункциюsend_commandsтакимобразом,чтобыпередподключениемкустройствампоSSH,выполняласьпроверкадоступностиустройстваpingом(можновызватькомандуpingвОС).

КаквыполнятькомандыОС,описановразделеsubprocess.Тамжеестьпримерфункциисотправкойping.

Еслиустройстводоступно,можновыполнятьподключение.Еслинедоступно,вывестисообщениеотом,чтоустройствосопределеннымIP-адресомнедоступноиневыполнятьподключение.

Дляудобстваможносделатьотдельнуюфункциюдляпроверкидоступностиизатемиспользоватьеевфункцииsend_commands.

Задания

365

Page 366: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Задание12.4

Взаданиииспользуетсяпримеризразделапромодульthreading.

Переделатьпримертакимобразом,чтобы:

вместофункцииconnect_ssh,использоваласьфункцияsend_commandsиззадания12.3

переделатьфункциюsend_commands,чтобыиспользоваласьочередьифункцияconn_threadsпо-прежнемувозвращаласловарьсрезультатами.Проверитьработусоспискомкоманд,скомандамиизфайла,скомандойshow

Примеризраздела:

Задания

366

Page 367: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

fromnetmikoimportConnectHandler

importsys

importyaml

importthreading

fromQueueimportQueue

COMMAND=sys.argv[1]

devices=yaml.load(open('devices.yaml'))

defconnect_ssh(device_dict,command,queue):

ssh=ConnectHandler(**device_dict)

ssh.enable()

result=ssh.send_command(command)

print"Connectiontodevice%s"%device_dict['ip']

queue.put({device_dict['ip']:result})

defconn_threads(function,devices,command):

threads=[]

q=Queue()

fordeviceindevices:

th=threading.Thread(target=function,args=(device,command,q))

th.start()

threads.append(th)

forthinthreads:

th.join()

results=[]

fortinthreads:

results.append(q.get())

returnresults

printconn_threads(connect_ssh,devices['routers'],COMMAND)

Задание12.5

Использоватьфункцииполученныеврезультатевыполнениязадания12.4.

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

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

Задания

367

Page 368: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Задание12.6

Взаданиииспользуетсяпримеризразделапромодульmultiprocessing.

Переделатьпримертакимобразом,чтобы:

вместофункцииconnect_ssh,использоваласьфункцияsend_commandsиззадания12.3

переделатьфункциюsend_commands,чтобыиспользоваласьочередьифункцияconn_processesпо-прежнемувозвращаласловарьсрезультатами.Проверитьработусоспискомкоманд,скомандамиизфайла,скомандойshow

Примеризраздела:

Задания

368

Page 369: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importmultiprocessing

fromnetmikoimportConnectHandler

importsys

importyaml

COMMAND=sys.argv[1]

devices=yaml.load(open('devices.yaml'))

defconnect_ssh(device_dict,command,queue):

ssh=ConnectHandler(**device_dict)

ssh.enable()

result=ssh.send_command(command)

print"Connectiontodevice%s"%device_dict['ip']

queue.put({device_dict['ip']:result})

defconn_processes(function,devices,command):

processes=[]

queue=multiprocessing.Queue()

fordeviceindevices:

p=multiprocessing.Process(target=function,args=(device,command,queue)

)

p.start()

processes.append(p)

forpinprocesses:

p.join()

results=[]

forpinprocesses:

results.append(queue.get())

returnresults

print(conn_processes(connect_ssh,devices['routers'],COMMAND))

Задание12.7

Использоватьфункцииполученныеврезультатевыполнениязадания12.6.

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

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

Задания

369

Page 370: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Задания

370

Page 371: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ШаблоныконфигурацийсJinjaJinja2этоязыкшаблонов,которыйиспользуетсявPython.Jinjaэтонеединственныйязыкшаблонов(шаблонизатор)дляPythonи,конечноже,неединственныйязыкшаблоноввцелом.

Jinja2используетсядлягенерациидокументовнаосновеодногоилинесколькихшаблонов.

Примерыиспользования:

шаблоныдлягенерацииHTML-страницшаблоныдлягенерацииконфигурационныхфайловвUnix/Linuxшаблоныдлягенерацииконфигурационныхфайловсетевыхустройств

УстановитьJinja2можноспомощьюpip:

pipinstalljinja2

ДалеетерминыJinjaиJinja2используютсявзаимозаменяемо.

ИдеяJinjaоченьпроста:разделениеданныхишаблона.Этопозволяетиспользоватьодинитотжешаблон,ноподставлятьвнегоразныеданные.

Всамомпростомслучае,шаблонэтопростотекстовыйфайл,вкоторомуказаныместаподстановкизначений,спомощьюпеременныхJinja.

ПримершаблонаJinja:

hostname{{name}}

!

interfaceLoopback255

descriptionManagementloopback

ipaddress10.255.{{id}}.1255.255.255.255

!

interfaceGigabitEthernet0/0

descriptionLANto{{name}}sw1{{int}}

ipaddress{{ip}}255.255.255.0

!

routerospf10

router-id10.255.{{id}}.1

auto-costreference-bandwidth10000

network10.0.0.00.255.255.255area0

13.ШаблоныконфигурацийсJinja

371

Page 372: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Комментариикшаблону:

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

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

ПримерскриптасгенерациейфайланаосновешаблонаJinja(файлbasic_generator.py):

fromjinja2importTemplate

template=Template(u"""

hostname{{name}}

!

interfaceLoopback255

descriptionManagementloopback

ipaddress10.255.{{id}}.1255.255.255.255

!

interfaceGigabitEthernet0/0

descriptionLANto{{name}}sw1{{int}}

ipaddress{{ip}}255.255.255.0

!

routerospf10

router-id10.255.{{id}}.1

auto-costreference-bandwidth10000

network10.0.0.00.255.255.255area0

""")

liverpool={'id':'11','name':'Liverpool','int':'Gi1/0/17','ip':'10.1.1.10'}

printtemplate.render(liverpool)

Комментариикфайлуbasic_generator.py:

впервойстрокеизJinja2импортируетсяклассTemplateсоздаетсяобъектtemplate,которомупередаетсяшаблон

вшаблонеиспользуютсяпеременныевсинтаксисеJinjaвсловареliverpoolключидолжныбытьтакимиже,какименапеременныхвшаблоне

значения,которыесоответствуютключам,этотеданные,которыебудутподставленынаместопеременных

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

Еслизапуститьскриптbasic_generator.py,товыводбудеттаким:

13.ШаблоныконфигурацийсJinja

372

Page 373: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythonbasic_generator.py

hostnameLiverpool

!

interfaceLoopback255

descriptionManagementloopback

ipaddress10.255.11.1255.255.255.255

!

interfaceGigabitEthernet0/0

descriptionLANtoLiverpoolsw1Gi1/0/17

ipaddress10.1.1.10255.255.255.0

!

routerospf10

router-id10.255.11.1

auto-costreference-bandwidth10000

network10.0.0.00.255.255.255area0

13.ШаблоныконфигурацийсJinja

373

Page 374: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПримериспользованияJinja2Вэтомпримерелогикаразнесенав3разныхфайла(всефайлынаходятсявкаталоге1_example):

router_template.py-шаблонrouters_info.yml-вэтомфайле,ввидеспискасловарей(вформатеYAML),находитсяинформацияомаршрутизаторах,длякоторыхнужносгенерироватьконфигурационныйфайлrouter_config_generator.py-вэтомскриптеимпортируетсяфайлсшаблономисчитываетсяинформацияизфайлавформатеYAML,азатемгенерируютсяконфигурационныефайлымаршрутизаторов

Файлrouter_template.py

ПримериспользованияJinja

374

Page 375: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

#-*-coding:utf-8-*-

fromjinja2importTemplate

importsys

reload(sys)

sys.setdefaultencoding('utf-8')

template_r1=Template(u"""

hostname{{name}}

!

interfaceLoopback10

descriptionMPLSloopback

ipaddress10.10.{{id}}.1255.255.255.255

!

interfaceGigabitEthernet0/0

descriptionWANto{{name}}sw1G0/1

!

interfaceGigabitEthernet0/0.1{{id}}1

descriptionMPLSto{{to_name}}

encapsulationdot1Q1{{id}}1

ipaddress10.{{id}}.1.2255.255.255.252

ipospfnetworkpoint-to-point

ipospfhello-interval1

ipospfcost10

!

interfaceGigabitEthernet0/1

descriptionLAN{{name}}tosw1G0/2!

interfaceGigabitEthernet0/1.{{IT}}

descriptionPWIT{{name}}-{{to_name}}

encapsulationdot1Q{{IT}}

xconnect10.10.{{to_id}}.1{{id}}11encapsulationmpls

backuppeer10.10.{{to_id}}.2{{id}}21

backupdelay11

!

interfaceGigabitEthernet0/1.{{BS}}

descriptionPWBS{{name}}-{{to_name}}

encapsulationdot1Q{{BS}}

xconnect10.10.{{to_id}}.1{{to_id}}{{id}}11encapsulationmpls

backuppeer10.10.{{to_id}}.2{{to_id}}{{id}}21

backupdelay11

!

routerospf10

router-id10.10.{{id}}.1

auto-costreference-bandwidth10000

network10.0.0.00.255.255.255area0

!

""")

ПримериспользованияJinja

375

Page 376: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Этистрокименяюткодировкупоумолчаниюasciiнаutf-8:

reload(sys)

sys.setdefaultencoding('utf-8')

Файлrouters_info.yml

-id:11

name:Liverpool

to_name:LONDON

IT:791

BS:1550

to_id:1

-id:12

name:Bristol

to_name:LONDON

IT:793

BS:1510

to_id:1

-id:14

name:Coventry

to_name:Manchester

IT:892

BS:1650

to_id:2

Файлrouter_config_generator.py

#-*-coding:utf-8-*-

importyaml

fromjinja2importTemplate

fromrouter_templateimporttemplate_r1

routers=yaml.load(open('routers_info.yml'))

forrouterinrouters:

r1_conf=router['name']+'_r1.txt'

withopen(r1_conf,'w')asf:

f.write(template_r1.render(router))

Файлrouter_config_generator.py:

импортируетшаблонtemplate_r1изфайлаrouters_info.ymlсписокпараметровсчитываетсявпеременнуюrouters

Затемвциклеперебираютсяобъекты(словари)вспискеrouters:

ПримериспользованияJinja

376

Page 377: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

названиефайла,вкоторыйзаписываетсяитоговаяконфигурация,состоитизполяnameвсловареистроки_r1.txt

например,Liverpool_r1.txtфайлстакимименемоткрываетсяврежимедлязаписивфайлзаписываетсярезультатрендерингашаблонасиспользованиемтекущегословаряконструкцияwithсамазакрываетфайлуправлениевозвращаетсявначалоцикла(поканепереберутсявсесловари)

Запускаемфайлrouter_config_generator.py:

$pythonrouter_config_generator.py

Врезультатеполучатсятриконфигурационныхфайла:

Liverpool_r1.txtBristol_r1.txtCoventry_r1.txt

ПримериспользованияJinja

377

Page 378: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

hostnameLiverpool

!

interfaceLoopback10

descriptionMPLSloopback

ipaddress10.10.11.1255.255.255.255

!

interfaceGigabitEthernet0/0

descriptionWANtoLiverpoolsw1G0/1

!

interfaceGigabitEthernet0/0.1111

descriptionMPLStoLONDON

encapsulationdot1Q1111

ipaddress10.11.1.2255.255.255.252

ipospfnetworkpoint-to-point

ipospfhello-interval1

ipospfcost10

!

interfaceGigabitEthernet0/1

descriptionLANLiverpooltosw1G0/2

!

interfaceGigabitEthernet0/1.791

descriptionPWITLiverpool-LONDON

encapsulationdot1Q791

xconnect10.10.1.11111encapsulationmpls

backuppeer10.10.1.21121

backupdelay11

!

interfaceGigabitEthernet0/1.1550

descriptionPWBSLiverpool-LONDON

encapsulationdot1Q1550

xconnect10.10.1.111111encapsulationmpls

backuppeer10.10.1.211121

backupdelay11

!

routerospf10

router-id10.10.11.1

auto-costreference-bandwidth10000

network10.0.0.00.255.255.255area0

!

ПримериспользованияJinja

378

Page 379: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

hostnameBristol

!

interfaceLoopback10

descriptionMPLSloopback

ipaddress10.10.12.1255.255.255.255

!

interfaceGigabitEthernet0/0

descriptionWANtoBristolsw1G0/1

!

interfaceGigabitEthernet0/0.1121

descriptionMPLStoLONDON

encapsulationdot1Q1121

ipaddress10.12.1.2255.255.255.252

ipospfnetworkpoint-to-point

ipospfhello-interval1

ipospfcost10

!

interfaceGigabitEthernet0/1

descriptionLANBristoltosw1G0/2

!

interfaceGigabitEthernet0/1.793

descriptionPWITBristol-LONDON

encapsulationdot1Q793

xconnect10.10.1.11211encapsulationmpls

backuppeer10.10.1.21221

backupdelay11

!

interfaceGigabitEthernet0/1.1510

descriptionPWBSBristol-LONDON

encapsulationdot1Q1510

xconnect10.10.1.111211encapsulationmpls

backuppeer10.10.1.211221

backupdelay11

!

routerospf10

router-id10.10.12.1

auto-costreference-bandwidth10000

network10.0.0.00.255.255.255area0

!

ПримериспользованияJinja

379

Page 380: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

hostnameCoventry

!

interfaceLoopback10

descriptionMPLSloopback

ipaddress10.10.14.1255.255.255.255

!

interfaceGigabitEthernet0/0

descriptionWANtoCoventrysw1G0/1

!

interfaceGigabitEthernet0/0.1141

descriptionMPLStoManchester

encapsulationdot1Q1141

ipaddress10.14.1.2255.255.255.252

ipospfnetworkpoint-to-point

ipospfhello-interval1

ipospfcost10

!

interfaceGigabitEthernet0/1

descriptionLANCoventrytosw1G0/2

!

interfaceGigabitEthernet0/1.892

descriptionPWITCoventry-Manchester

encapsulationdot1Q892

xconnect10.10.2.11411encapsulationmpls

backuppeer10.10.2.21421

backupdelay11

!

interfaceGigabitEthernet0/1.1650

descriptionPWBSCoventry-Manchester

encapsulationdot1Q1650

xconnect10.10.2.121411encapsulationmpls

backuppeer10.10.2.221421

backupdelay11

!

routerospf10

router-id10.10.14.1

auto-costreference-bandwidth10000

network10.0.0.00.255.255.255area0

!

ПримериспользованияJinja

380

Page 381: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПримериспользованияJinjaскорректнымиспользованиемпрограммногоинтерфейсаДлятогочтобыразобратьсясJinja2,лучшеиспользоватьпредыдущиепримеры.ВэтомразделеописываетсякорректноеиспользованиеJinja.Втакомвариантеданные,шаблонискрипт,которыйгенерируетитоговуюинформацию,разделены.

Термин"программныйинтерфейс"относитсякспособуработыJinjaсвводнымиданнымиишаблоном,длягенерацииитоговыхфайлов.

Переделанныйпримерпредыдущегоскрипта,шаблонаифайласданными(всефайлынаходятсявкаталоге2_example):

Шаблонtemplates/router_template.txtэтообычныйтекстовыйфайл:

ПримериспользованияJinjaскорректнымиспользованиемпрограммногоинтерфейса

381

Page 382: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

hostname{{name}}

!

interfaceLoopback10

descriptionMPLSloopback

ipaddress10.10.{{id}}.1255.255.255.255

!

interfaceGigabitEthernet0/0

descriptionWANto{{name}}sw1G0/1

!

interfaceGigabitEthernet0/0.1{{id}}1

descriptionMPLSto{{to_name}}

encapsulationdot1Q1{{id}}1

ipaddress10.{{id}}.1.2255.255.255.252

ipospfnetworkpoint-to-point

ipospfhello-interval1

ipospfcost10

!

interfaceGigabitEthernet0/1

descriptionLAN{{name}}tosw1G0/2!

interfaceGigabitEthernet0/1.{{IT}}

descriptionPWIT{{name}}-{{to_name}}

encapsulationdot1Q{{IT}}

xconnect10.10.{{to_id}}.1{{id}}11encapsulationmpls

backuppeer10.10.{{to_id}}.2{{id}}21

backupdelay11

!

interfaceGigabitEthernet0/1.{{BS}}

descriptionPWBS{{name}}-{{to_name}}

encapsulationdot1Q{{BS}}

xconnect10.10.{{to_id}}.1{{to_id}}{{id}}11encapsulationmpls

backuppeer10.10.{{to_id}}.2{{to_id}}{{id}}21

backupdelay11

!

routerospf10

router-id10.10.{{id}}.1

auto-costreference-bandwidth10000

network10.0.0.00.255.255.255area0

!

Файлсданнымиrouters_info.yml

ПримериспользованияJinjaскорректнымиспользованиемпрограммногоинтерфейса

382

Page 383: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

-id:11

name:Liverpool

to_name:LONDON

IT:791

BS:1550

to_id:1

-id:12

name:Bristol

to_name:LONDON

IT:793

BS:1510

to_id:1

-id:14

name:Coventry

to_name:Manchester

IT:892

BS:1650

to_id:2

Скриптдлягенерацииконфигурацийrouter_config_generator_ver2.py

#-*-coding:utf-8-*-

fromjinja2importEnvironment,FileSystemLoader

importyaml

importsys

reload(sys)

sys.setdefaultencoding('utf-8')

env=Environment(loader=FileSystemLoader('templates'))

template=env.get_template('router_template.txt')

routers=yaml.load(open('routers_info.yml'))

forrouterinrouters:

r1_conf=router['name']+'_r1.txt'

withopen(r1_conf,'w')asf:

f.write(template.render(router))

Файлrouter_config_generator.pyимпортируетизмодуляjinja2:

FileSystemLoader-загрузчик,которыйпозволяетработатьсфайловойсистемойтутуказываетсяпутьккаталогу,гденаходятсяшаблонывданномслучае,шаблоннаходитсявкаталогеtemplates

Environment-классдляописанияпараметровокружения:вданномслучае,указантолькозагрузчикновнемможноуказыватьметодыобрабаткишаблона

ПримериспользованияJinjaскорректнымиспользованиемпрограммногоинтерфейса

383

Page 384: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Обратитевнимание,чтошаблонтеперьнаходитсявкаталогеtemplates.

Еслишаблонынаходятсявтекущемкаталоге,надодобавитьпарустрокиизменитьзначениевзагрузчике:

importos

curr_dir=os.path.dirname(os.path.abspath(__file__))

env=Environment(loader=FileSystemLoader(curr_dir))

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

Методget_template()используетсядлятого,чтобыполучитьшаблон.Вскобкахуказываетсяимяфайла.

Последняячастьосталасьнеизменной.

ПримериспользованияJinjaскорректнымиспользованиемпрограммногоинтерфейса

384

Page 385: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

СинтаксисшаблоновJinja2Досихпор,впримерахшаблоновJinja2использоваласьтолькоподстановкапеременных.Этосамыйпростойипонятныйпримериспользованияшаблонов.НосинтаксисшаблоновJinjaнаэтомнеограничивается.

ВшаблонахJinja2можноиспользовать:

переменныеусловия(if/else)циклы(for)фильтры-специальныевстроенныеметоды,которыепозволяютделатьпреобразованияпеременныхтесты-используютсядляпроверкисоответствуетлипеременнаякакому-тоусловию

Крометого,Jinjaподдерживаетнаследованиемеждушаблонами.Атакжепозволяетдобавлятьсодержимоеодногошаблонавдругой.

Мыразберемсясосновамиэтихвозможностей.ПодробнееошаблонахJinja2можнопочитатьвдокументации.

Всефайлы,которыеиспользуютсякакпримерывэтомподразделе,находятсявкаталоге3_template_syntax/

Длягенерациишаблоновбудетиспользоватьскриптcfg_gen.py

#-*-coding:utf-8-*-

fromjinja2importEnvironment,FileSystemLoader

importyaml

importsys

reload(sys)

sys.setdefaultencoding('utf-8')

TEMPLATE_DIR,template=sys.argv[1].split('/')

VARS_FILE=sys.argv[2]

env=Environment(loader=FileSystemLoader(TEMPLATE_DIR),

trim_blocks=True,lstrip_blocks=True)

template=env.get_template(template)

vars_dict=yaml.load(open(VARS_FILE))

printtemplate.render(vars_dict)

СинтаксисшаблоновJinja2

385

Page 386: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

шаблонфайлспеременными,вформатеYAML

Результатбудетвыведеннастандартныйпотоквывода.

Примерзапускаскрипта:

$pythoncfg_gen.pytemplates/variables.txtdata_files/vars.yml

Параметрыtrim_blocksиlstrip_blocksописыванывследующемподразделе.

СинтаксисшаблоновJinja2

386

Page 387: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Контрольсимволовwhitespace

trim_blocks,lstrip_blocks

Параметрtrim_blocksудаляетпервуюпустуюстрокупослеблокаконструкции,еслиегозначениеравноTrue(поумолчаниюFalse).

Посмотримнаэффектпримененияфлаганапримерешаблонаtemplates/env_flags.txt:

routerbgp{{bgp.local_as}}

{%foribgpinbgp.ibgp_neighbors%}

neighbor{{ibgp}}remote-as{{bgp.local_as}}

neighbor{{ibgp}}update-source{{bgp.loopback}}

{%endfor%}

Еслискриптcfg_gen.pyзапускаетсябезфлаговtrim_blocks,lstrip_blocks:

env=Environment(loader=FileSystemLoader(TEMPLATE_DIR))

Выводбудеттаким:

$pythoncfg_gen.pytemplates/env_flags.txtdata_files/router.yml

routerbgp100

neighbor10.0.0.2remote-as100

neighbor10.0.0.2update-sourcelo100

neighbor10.0.0.3remote-as100

neighbor10.0.0.3update-sourcelo100

Из-заблока{%foribgpinbgp.ibgp_neighbors%}появляютсяпереводыстрок.Поумолчанию,такоежеповедениебудетслюбымидругимиблокамиJinja.

Придобавлениифлагаtrim_blocksтакимобразом:

env=Environment(loader=FileSystemLoader(TEMPLATE_DIR),trim_blocks=True)

Результатвыполнениябудеттаким:

Контрольсимволовwhitespace

387

Page 388: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythoncfg_gen.pytemplates/env_flags.txtdata_files/router.yml

routerbgp100

neighbor10.0.0.2remote-as100

neighbor10.0.0.2update-sourcelo100

neighbor10.0.0.3remote-as100

neighbor10.0.0.3update-sourcelo100

Былиудаленыпустыестрокипослеблока.

Нопередстрокамиneighbor...remote-asпоявилисьдвапробела.Такполучилосьиз-затого,чтопередблоком{%foribgpinbgp.ibgp_neighbors%}стоитпробел.Послетого,какбылотключенлишнийпереводстроки,пробелыитабыпередблокомдобавляютсякпервойстрокеблока.

Ноэтоневлияетнаследующиестроки.Поэтомустрокисneighbor...update-sourceотображаютсясоднимпробелом.

Параметрlstrip_blocksконтролируетто,будутлиудалятьсяпробелыитабыотначаластрокидоначалаблока(дооткрывающейсяфигурнойскобки).

Еслидобавитьаргументlstrip_blocks=Trueтакимобразом:

env=Environment(loader=FileSystemLoader(TEMPLATE_DIR),trim_blocks=True,lstrip_bl

ocks=True)

Результатвыполнениябудеттаким:

$pythoncfg_gen.pytemplates/env_flags.txtdata_files/router.yml

routerbgp100

neighbor10.0.0.2remote-as100

neighbor10.0.0.2update-sourcelo100

neighbor10.0.0.3remote-as100

neighbor10.0.0.3update-sourcelo100

Отключениеlstrip_blocksдляблока

Иногда,нужноотключитьфункциональностьlstrip_blocksдляблока.

Например,еслипараметрlstrip_blocksустановленравнымTrueвокружении,нонужноотключитьегодлявторогоблокавшаблоне(файлtemplates/env_flags2.txt):

Контрольсимволовwhitespace

388

Page 389: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

routerbgp{{bgp.local_as}}

{%foribgpinbgp.ibgp_neighbors%}

neighbor{{ibgp}}remote-as{{bgp.local_as}}

neighbor{{ibgp}}update-source{{bgp.loopback}}

{%endfor%}

routerbgp{{bgp.local_as}}

{%+foribgpinbgp.ibgp_neighbors%}

neighbor{{ibgp}}remote-as{{bgp.local_as}}

neighbor{{ibgp}}update-source{{bgp.loopback}}

{%endfor%}

Результатбудеттаким:

$pythoncfg_gen.pytemplates/env_flags2.txtdata_files/router.yml

routerbgp100

neighbor10.0.0.2remote-as100

neighbor10.0.0.2update-sourcelo100

neighbor10.0.0.3remote-as100

neighbor10.0.0.3update-sourcelo100

routerbgp100

neighbor10.0.0.2remote-as100

neighbor10.0.0.2update-sourcelo100

neighbor10.0.0.3remote-as100

neighbor10.0.0.3update-sourcelo100

Плюспослезнакапроцентаотключаетlstrip_blocksдляблока.Вданномслучае,толькодляначалаблока.

Еслисделатьтакимобразом(плюсдобавленввыражениидлязавершенияблока):

routerbgp{{bgp.local_as}}

{%foribgpinbgp.ibgp_neighbors%}

neighbor{{ibgp}}remote-as{{bgp.local_as}}

neighbor{{ibgp}}update-source{{bgp.loopback}}

{%endfor%}

routerbgp{{bgp.local_as}}

{%+foribgpinbgp.ibgp_neighbors%}

neighbor{{ibgp}}remote-as{{bgp.local_as}}

neighbor{{ibgp}}update-source{{bgp.loopback}}

{%+endfor%}

Онбудетотключенидляконцаблока:

Контрольсимволовwhitespace

389

Page 390: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythoncfg_gen.pytemplates/env_flags2.txtdata_files/router.yml

routerbgp100

neighbor10.0.0.2remote-as100

neighbor10.0.0.2update-sourcelo100

neighbor10.0.0.3remote-as100

neighbor10.0.0.3update-sourcelo100

routerbgp100

neighbor10.0.0.2remote-as100

neighbor10.0.0.2update-sourcelo100

neighbor10.0.0.3remote-as100

neighbor10.0.0.3update-sourcelo100

Удалениеwhitespaceвблоке

Аналогичнымобразомможноконтролироватьудалениеwhitespaceдляблока.

Дляэтогопримеравокруженииневыставленыфлаги:

env=Environment(loader=FileSystemLoader(TEMPLATE_DIR))

Шаблонtemplates/env_flags3.txt:

routerbgp{{bgp.local_as}}

{%foribgpinbgp.ibgp_neighbors%}

neighbor{{ibgp}}remote-as{{bgp.local_as}}

neighbor{{ibgp}}update-source{{bgp.loopback}}

{%endfor%}

routerbgp{{bgp.local_as}}

{%-foribgpinbgp.ibgp_neighbors%}

neighbor{{ibgp}}remote-as{{bgp.local_as}}

neighbor{{ibgp}}update-source{{bgp.loopback}}

{%endfor%}

Обратитевниманиенаминусвначалевторогоблока.Минутудаляетвсеwhitespaceсимволы.Вданномслучае,вначалеблока.

Результатбудеттаким:

Контрольсимволовwhitespace

390

Page 391: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythoncfg_gen.pytemplates/env_flags3.txtdata_files/router.yml

routerbgp100

neighbor10.0.0.2remote-as100

neighbor10.0.0.2update-sourcelo100

neighbor10.0.0.3remote-as100

neighbor10.0.0.3update-sourcelo100

routerbgp100

neighbor10.0.0.2remote-as100

neighbor10.0.0.2update-sourcelo100

neighbor10.0.0.3remote-as100

neighbor10.0.0.3update-sourcelo100

Еслидобавитьминутвконецблока:

routerbgp{{bgp.local_as}}

{%foribgpinbgp.ibgp_neighbors%}

neighbor{{ibgp}}remote-as{{bgp.local_as}}

neighbor{{ibgp}}update-source{{bgp.loopback}}

{%endfor%}

routerbgp{{bgp.local_as}}

{%-foribgpinbgp.ibgp_neighbors%}

neighbor{{ibgp}}remote-as{{bgp.local_as}}

neighbor{{ibgp}}update-source{{bgp.loopback}}

{%-endfor%}

Удалитсяпустаястрокаивконцеблока:

$pythoncfg_gen.pytemplates/env_flags3.txtdata_files/router.yml

routerbgp100

neighbor10.0.0.2remote-as100

neighbor10.0.0.2update-sourcelo100

neighbor10.0.0.3remote-as100

neighbor10.0.0.3update-sourcelo100

routerbgp100

neighbor10.0.0.2remote-as100

neighbor10.0.0.2update-sourcelo100

neighbor10.0.0.3remote-as100

neighbor10.0.0.3update-sourcelo100

Контрольсимволовwhitespace

391

Page 392: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Попробуйтедобавитьминусвконцевыраженийописывающихблокипосмотретьнарезультат:

routerbgp{{bgp.local_as}}

{%foribgpinbgp.ibgp_neighbors%}

neighbor{{ibgp}}remote-as{{bgp.local_as}}

neighbor{{ibgp}}update-source{{bgp.loopback}}

{%endfor%}

routerbgp{{bgp.local_as}}

{%-foribgpinbgp.ibgp_neighbors-%}

neighbor{{ibgp}}remote-as{{bgp.local_as}}

neighbor{{ibgp}}update-source{{bgp.loopback}}

{%-endfor-%}

Контрольсимволовwhitespace

392

Page 393: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПеременныеПеременныевшаблонеуказываютсявдвойныхфигурныхскобках:

hostname{{name}}

interfaceLoopback0

ipaddress10.0.0.{{id}}255.255.255.255

Значенияпеременныхподставляютсянаосновесловаря,которыйпередаетсяшаблону.

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

Примершаблонаtemplates/variables.txt,сиспользованиемразныхвариантовпеременных:

hostname{{name}}

interfaceLoopback0

ipaddress10.0.0.{{id}}255.255.255.255

vlan{{vlans[0]}}

routerospf1

router-id10.0.0.{{id}}

auto-costreference-bandwidth10000

network{{ospf.network}}area{{ospf['area']}}

Исоответствующийфайлdata_files/vars.ymlспеременными:

id:3

name:R3

vlans:

-10

-20

-30

ospf:

network:10.0.1.00.0.0.255

area:0

Обратитевниманиенаиспользованиепеременнойvlansвшаблоне:

Переменные

393

Page 394: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

таккакпеременнаяvlansэтосписок,можноуказыватькакойименноэлементизсписканамнужен

Еслипередаетсясловарь(каквслучаеспеременнойospf),товнутришаблонаможнообращатьсякобъектамсловаря,используяодинизвариантов:

ospf.networkилиospf['network']

Результатзапускаскриптабудеттаким:

$pythoncfg_gen.pytemplates/variables.txtdata_files/vars.yml

hostnameR3

interfaceLoopback0

ipaddress10.0.0.3255.255.255.255

vlan10

routerospf1

router-id10.0.0.3

auto-costreference-bandwidth10000

network10.0.1.00.0.0.255area0

Переменные

394

Page 395: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЦиклforЦиклforпозволяетпроходитьсяпоэлементампоследовательности.

Циклforдолженнаходитьсявнутрисимволов{%%}.Крометого,нужноявноуказыватьзавершениецикла:

{%forvlaninvlans%}

vlan{{vlan}}

{%endfor%}

Примершаблонаtemplates/for.txtсиспользованиемцикла:

hostname{{name}}

interfaceLoopback0

ipaddress10.0.0.{{id}}255.255.255.255

{%forvlan,nameinvlans.iteritems()%}

vlan{{vlan}}

name{{name}}

{%endfor%}

routerospf1

router-id10.0.0.{{id}}

auto-costreference-bandwidth10000

{%fornetworksinospf%}

network{{networks.network}}area{{networks.area}}

{%endfor%}

Файлdata_files/for.ymlспеременными:

id:3

name:R3

vlans:

10:Marketing

20:Voice

30:Management

ospf:

-network:10.0.1.00.0.0.255

area:0

-network:10.0.2.00.0.0.255

area:2

-network:10.1.1.00.0.0.255

area:0

for

395

Page 396: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Вциклеforможнопроходитьсякакпоэлементамсписка(например,списокospf),такипословарю(словарьvlans).И,аналогичнымобразом,полюбойпоследовательности.

Элементысловарянеупорядочены.Поэтому,еслинужнополучитьупорядоченныеэлементы,можнолибоиспользоватьотсортированныйсписоккортежей,либоиспользоватьупорядоченныйсловарьcollections.OrderedDict.

Результатвыполнениябудеттаким:

$pythoncfg_gen.pytemplates/for.txtdata_files/for.yml

hostnameR3

interfaceLoopback0

ipaddress10.0.0.3255.255.255.255

vlan10

nameMarketing

vlan20

nameVoice

vlan30

nameManagement

routerospf1

router-id10.0.0.3

auto-costreference-bandwidth10000

network10.0.1.00.0.0.255area0

network10.0.2.00.0.0.255area2

network10.1.1.00.0.0.255area0

for

396

Page 397: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

if/elif/elseifпозволяетдобавлятьусловиевшаблон.Например,можноиспользоватьifчтобыдобавлятькакие-точастишаблона,взависимостиотналичияпеременныхвсловаресданными.

Конструкцияifтакжедолжнанаходитьсявнутри{%%}.Инужноявноуказыватьокончаниеусловия:

{%ifospf%}

routerospf1

router-id10.0.0.{{id}}

auto-costreference-bandwidth10000

{%endif%}

Примершаблонаtemplates/if.txt:

hostname{{name}}

interfaceLoopback0

ipaddress10.0.0.{{id}}255.255.255.255

{%forvlan,nameinvlans.iteritems()%}

vlan{{vlan}}

name{{name}}

{%endfor%}

{%ifospf%}

routerospf1

router-id10.0.0.{{id}}

auto-costreference-bandwidth10000

{%fornetworksinospf%}

network{{networks.network}}area{{networks.area}}

{%endfor%}

{%endif%}

Выражениеifospfработаеттакже,каквPython:еслипеременнаясуществуетинепустая,результатбудетTrue.Еслипеременнойнет,илионапустая,результатбудетFalse.

Тоесть,вэтомшаблонеконфигурацияOSPFгенерируетсятольковтомслучае,еслипеременнаяospfсуществуетинепустая.

Конфигурациябудетгенерироватьсясдвумявариантамиданных.

if/elif/else

397

Page 398: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Сначала,сфайломdata_files/if.yml,вкоторомнетпеременнойospf:

id:3

name:R3

vlans:

10:Marketing

20:Voice

30:Management

Результатбудеттаким:

$pythoncfg_gen.pytemplates/if.txtdata_files/if.yml

hostnameR3

interfaceLoopback0

ipaddress10.0.0.3255.255.255.255

vlan10

nameMarketing

vlan20

nameVoice

vlan30

nameManagement

Теперьаналогичныйшаблон,носфайломdata_files/if_ospf.yml:

id:3

name:R3

vlans:

10:Marketing

20:Voice

30:Management

ospf:

-network:10.0.1.00.0.0.255

area:0

-network:10.0.2.00.0.0.255

area:2

-network:10.1.1.00.0.0.255

area:0

Теперьрезультатвыполнениябудеттаким:

if/elif/else

398

Page 399: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

hostnameR3

interfaceLoopback0

ipaddress10.0.0.3255.255.255.255

vlan10

nameMarketing

vlan20

nameVoice

vlan30

nameManagement

routerospf1

router-id10.0.0.3

auto-costreference-bandwidth10000

network10.0.1.00.0.0.255area0

network10.0.2.00.0.0.255area2

network10.1.1.00.0.0.255area0

КакивPython,вJinjaможноделатьответвлениявусловии.

Примершаблонаtemplates/if_vlans.txt:

{%forintf,paramsintrunks.iteritems()%}

interface{{intf}}

{%ifparams.action=='add'%}

switchporttrunkallowedvlanadd{{params.vlans}}

{%elifparams.action=='delete'%}

switchporttrunkallowedvlanremove{{params.vlans}}

{%else%}

switchporttrunkallowedvlan{{params.vlans}}

{%endif%}

{%endfor%}

Файлdata_files/if_vlans.ymlсданными:

trunks:

Fa0/1:

action:add

vlans:10,20

Fa0/2:

action:only

vlans:10,30

Fa0/3:

action:delete

vlans:10

if/elif/else

399

Page 400: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Вданномпримере,взависимостиотзначенияпараметраaction,генерируютсяразныекоманды.

Вшаблонеможнобылоиспользоватьитакойвариантобращенияквложеннымсловарям:

{%forintfintrunks%}

interface{{intf}}

{%iftrunks[intf]['action']=='add'%}

switchporttrunkallowedvlanadd{{trunks[intf]['vlans']}}

{%eliftrunks[intf]['action']=='delete'%}

switchporttrunkallowedvlanremove{{trunks[intf]['vlans']}}

{%else%}

switchporttrunkallowedvlan{{trunks[intf]['vlans']}}

{%endif%}

{%endfor%}

Витоге,будетсгенерированатакаяконфигурация:

$pythoncfg_gen.pytemplates/if_vlans.txtdata_files/if_vlans.yml

interfaceFa0/1

switchporttrunkallowedvlanadd10,20

interfaceFa0/3

switchporttrunkallowedvlanremove10

interfaceFa0/2

switchporttrunkallowedvlan10,30

Также,спомощьюif,можнофильтроватьпокакимэлементампоследовательностипройдетсяциклfor.

Примершаблонаtemplates/if_for.txtсфильтром,вциклеfor:

{%forvlan,nameinvlans.iteritems()ifvlan>15%}

vlan{{vlan}}

name{{name}}

{%endfor%}

Файлсданными(data_files/if_for.yml):

vlans:

10:Marketing

20:Voice

30:Management

Результатвыполнения:

if/elif/else

400

Page 401: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythoncfg_gen.pytemplates/if_for.txtdata_files/if_for.yml

vlan20

nameVoice

vlan30

nameManagement

if/elif/else

401

Page 402: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ФильтрыВJinjaпеременныеможноизменятьспомощьюфильтров.Фильтрыотделяютсяотпеременнойвертикальнойчертой(pipe|)имогутсодержатьдополнительныеаргументы.

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

Jinjaподдерживаетбольшоеколичествовстроенныхфильтров.Мырассмотримлишьнесколькоизних.Остальныефильтрыможнонайтивдокументации.

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

default

Фильтрdefaultпозволяетуказатьдляпеременнойзначениепоумолчанию.Еслипеременнаяопределена,будетвыводитьсяпеременная,еслипеременнаянеопределена,будетвыводитьсязначение,котороеуказановфильтреdefault.

Примершаблонаtemplates/filter_default.txt:

routerospf1

auto-costreference-bandwidth{{ref_bw|default(10000)}}

{%fornetworksinospf%}

network{{networks.network}}area{{networks.area}}

{%endfor%}

Еслипеременнаяref_bwопределенавсловаре,будетподставленоеёзначение.Еслижепеременнойнет,будетподставленозначение10000.

Файлсданными(data_files/filter_default.yml):

ospf:

-network:10.0.1.00.0.0.255

area:0

-network:10.0.2.00.0.0.255

area:2

-network:10.1.1.00.0.0.255

area:0

Фильтры

402

Page 403: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Результатвыполнения:

$pythoncfg_gen.pytemplates/filter_default.txtdata_files/filter_default.yml

routerospf1

auto-costreference-bandwidth10000

network10.0.1.00.0.0.255area0

network10.0.2.00.0.0.255area2

network10.1.1.00.0.0.255area0

Поумолчанию,еслипеременнаяопределенаиеёзначениепустойобъект,будетсчитаться,чтопеременнаяиеёзначениеесть.

Еслинужносделатьтак,чтобызначениепоумолчаниюподставлялосьивтомслучае,когдапеременнаяпустая(тоесть,обрабатываетсякакFalseвPython),надоуказатьдополнительныйпараметрboolean=true.

Например,еслифайлданныхбылбытаким:

ref_bw:''

ospf:

-network:10.0.1.00.0.0.255

area:0

-network:10.0.2.00.0.0.255

area:2

-network:10.1.1.00.0.0.255

area:0

Товитогесгенерировалсятакойрезультат:

$pythoncfg_gen.pytemplates/filter_default.txtdata_files/filter_default.yml

routerospf1

auto-costreference-bandwidth

network10.0.1.00.0.0.255area0

network10.0.2.00.0.0.255area2

network10.1.1.00.0.0.255area0

Еслиже,притакомжефайледанных,изменитьшаблонтакимобразом:

routerospf1

auto-costreference-bandwidth{{ref_bw|default(10000,boolean=true)}}

{%fornetworksinospf%}

network{{networks.network}}area{{networks.area}}

{%endfor%}

Вместоdefault(10000,boolean=true),можнонаписатьdefault(10000,true)

Фильтры

403

Page 404: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Результатужебудеттаким(значениепоумолчаниюподставится):

$pythoncfg_gen.pytemplates/filter_default.txtdata_files/filter_default.yml

routerospf1

auto-costreference-bandwidth10000

network10.0.1.00.0.0.255area0

network10.0.2.00.0.0.255area2

network10.1.1.00.0.0.255area0

dictsort

Фильтрdictsortпозволяетсортироватьсловарь.Поумолчанию,сортировкавыполняетсяпоключам.Но,изменивпараметрыфильтра,можновыполнятьсортировкупозначениям.

Синтаксисфильтра:

dictsort(value,case_sensitive=False,by='key')

Послетого,какdictsortотсортировалсловарь,онвозвращаетсписоккортежей,анесловарь.

Примершаблонаtemplates/filter_dictsort.txtсиспользованиемфильтраdictsort:

{%forintf,paramsintrunks|dictsort%}

interface{{intf}}

{%ifparams.action=='add'%}

switchporttrunkallowedvlanadd{{params.vlans}}

{%elifparams.action=='delete'%}

switchporttrunkallowedvlanremove{{params.vlans}}

{%else%}

switchporttrunkallowedvlan{{params.vlans}}

{%endif%}

{%endfor%}

Обратитевнимание,чтофильтрожидаетсловарь,анесписоккортежейилиитератор.

Файлсданными(data_files/filter_dictsort.yml):

Фильтры

404

Page 405: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

trunks:

Fa0/1:

action:add

vlans:10,20

Fa0/2:

action:only

vlans:10,30

Fa0/3:

action:delete

vlans:10

Результатвыполнениябудеттаким(интерфейсыупорядочены):

$pythoncfg_gen.pytemplates/filter_dictsort.txtdata_files/filter_dictsort.yml

interfaceFa0/1

switchporttrunkallowedvlanadd10,20

interfaceFa0/2

switchporttrunkallowedvlan10,30

interfaceFa0/3

switchporttrunkallowedvlanremove10

join

Фильтрjoinработаеттакже,какиметодjoinвPython.

Спомощьюфильтраjoinможнообъединятьэлементыпоследовательностивстроку,сопциональнымразделителеммеждуэлементами.

Примершаблонаtemplates/filter_join.txtсиспользованиемфильтраjoin:

{%forintf,paramsintrunks|dictsort%}

interface{{intf}}

{%ifparams.action=='add'%}

switchporttrunkallowedvlanadd{{params.vlans|join(',')}}

{%elifparams.action=='delete'%}

switchporttrunkallowedvlanremove{{params.vlans|join(',')}}

{%else%}

switchporttrunkallowedvlan{{params.vlans|join(',')}}

{%endif%}

{%endfor%}

Файлсданными(data_files/filter_join.yml):

Фильтры

405

Page 406: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

trunks:

Fa0/1:

action:add

vlans:

-10

-20

Fa0/2:

action:only

vlans:

-10

-30

Fa0/3:

action:delete

vlans:

-10

Результатвыполнения:

$pythoncfg_gen.pytemplates/filter_join.txtdata_files/filter_join.yml

interfaceFa0/1

switchporttrunkallowedvlanadd10,20

interfaceFa0/2

switchporttrunkallowedvlan10,30

interfaceFa0/3

switchporttrunkallowedvlanremove10

Фильтры

406

Page 407: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ТестыКромефильтров,Jinjaтакжеподдерживаеттесты.Тестыпозволяютпроверятьпеременныенакакое-тоусловие.

Jinjaподдерживаетбольшоеколичествовстроенныхтестов.Мырассмотримлишьнесколькоизних.Остальныетестывыможетенайтивдокументации.

Тесты,какифильтры,можносоздаватьсамостоятельно.

defined

Тестdefinedпозволяетпроверитьестьлипеременнаявсловареданных.

Примершаблонаtemplates/test_defined.txt:

routerospf1

{%ifref_bwisdefined%}

auto-costreference-bandwidth{{ref_bw}}

{%else%}

auto-costreference-bandwidth10000

{%endif%}

{%fornetworksinospf%}

network{{networks.network}}area{{networks.area}}

{%endfor%}

Этотпримерболеегромоздкий,чемвариантсиспользованиемфильтраdefault,ноэтоттестможетбытьполезенвтомслучае,если,взависимостиоттого,определенапеременнаяилинет,нужновыполнятьразныекоманды.

Файлсданными(data_files/test_defined.yml):

ospf:

-network:10.0.1.00.0.0.255

area:0

-network:10.0.2.00.0.0.255

area:2

-network:10.1.1.00.0.0.255

area:0

Результатвыполнения:

Тесты

407

Page 408: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythoncfg_gen.pytemplates/test_defined.txtdata_files/test_defined.yml

routerospf1

auto-costreference-bandwidth10000

network10.0.1.00.0.0.255area0

network10.0.2.00.0.0.255area2

network10.1.1.00.0.0.255area0

iterable

Тестiterableпроверяетявляетсялиобъектитератором.

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

Шаблонtemplates/test_iterable.txt(сделаныотступы,чтобыбылипонятнейответвления):

{%forintf,paramsintrunks|dictsort%}

interface{{intf}}

{%ifparams.vlansisiterable%}

{%ifparams.action=='add'%}

switchporttrunkallowedvlanadd{{params.vlans|join(',')}}

{%elifparams.action=='delete'%}

switchporttrunkallowedvlanremove{{params.vlans|join(',')}}

{%else%}

switchporttrunkallowedvlan{{params.vlans|join(',')}}

{%endif%}

{%else%}

{%ifparams.action=='add'%}

switchporttrunkallowedvlanadd{{params.vlans}}

{%elifparams.action=='delete'%}

switchporttrunkallowedvlanremove{{params.vlans}}

{%else%}

switchporttrunkallowedvlan{{params.vlans}}

{%endif%}

{%endif%}

{%endfor%}

Файлсданными(data_files/test_iterable.yml):

Тесты

408

Page 409: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

trunks:

Fa0/1:

action:add

vlans:

-10

-20

Fa0/2:

action:only

vlans:

-10

-30

Fa0/3:

action:delete

vlans:10

Обратитевниманиенапоследнююстроку:vlans:10.Вданномслучае,10ужененаходитсявспискеифильтрjoinвтакомслучаенеработает.Но,засчеттестаisiterable(вэтомслучаерезультатбудетfalse),вэтомслучаешаблонуходитвветкуelse.

Результатвыполнения:

$pythoncfg_gen.pytemplates/test_iterable.txtdata_files/test_iterable.yml

interfaceFa0/1

switchporttrunkallowedvlanadd10,20

interfaceFa0/2

switchporttrunkallowedvlan10,30

interfaceFa0/3

switchporttrunkallowedvlanremove10

Такиеотступыполучилисьиз-затого,чтовшаблонеиспользуютсяотступы,нонеустановленоlstrip_blocks=True(онудалетпробелыитабывначалестроки).

Тесты

409

Page 410: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

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

Примершаблонаtemplates/set.txt,вкоторомвыражениеsetиспользуетсячтобызадатьболеекороткиеименапараметрам:

{%forintf,paramsintrunks|dictsort%}

{%setvlans=params.vlans%}

{%setaction=params.action%}

interface{{intf}}

{%ifvlansisiterable%}

{%ifaction=='add'%}

switchporttrunkallowedvlanadd{{vlans|join(',')}}

{%elifaction=='delete'%}

switchporttrunkallowedvlanremove{{vlans|join(',')}}

{%else%}

switchporttrunkallowedvlan{{vlans|join(',')}}

{%endif%}

{%else%}

{%ifaction=='add'%}

switchporttrunkallowedvlanadd{{vlans}}

{%elifaction=='delete'%}

switchporttrunkallowedvlanremove{{vlans}}

{%else%}

switchporttrunkallowedvlan{{vlans}}

{%endif%}

{%endif%}

{%endfor%}

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

{%setvlans=params.vlans%}

{%setaction=params.action%}

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

Присваивание(set)

410

Page 411: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Файлсданными(data_files/set.yml):

trunks:

Fa0/1:

action:add

vlans:

-10

-20

Fa0/2:

action:only

vlans:

-10

-30

Fa0/3:

action:delete

vlans:10

Результатвыполнения:

$pythoncfg_gen.pytemplates/set.txtdata_files/set.yml

interfaceFa0/1

switchporttrunkallowedvlanadd10,20

interfaceFa0/2

switchporttrunkallowedvlan10,30

interfaceFa0/3

switchporttrunkallowedvlanremove10

Присваивание(set)

411

Page 412: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

includeВыражениеincludeпозволяетдобавитьодиншаблонвдругой.

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

Шаблонtemplates/vlans.txt:

{%forvlan,nameinvlans.items()%}

vlan{{vlan}}

name{{name}}

{%endfor%}

Шаблонtemplates/ospf.txt:

routerospf1

auto-costreference-bandwidth10000

{%fornetworksinospf%}

network{{networks.network}}area{{networks.area}}

{%endfor%}

Шаблонtemplates/bgp.txt:

routerbgp{{bgp.local_as}}

{%foribgpinbgp.ibgp_neighbors%}

neighbor{{ibgp}}remote-as{{bgp.local_as}}

neighbor{{ibgp}}update-source{{bgp.loopback}}

{%endfor%}

{%forebgpinbgp.ebgp_neighbors%}

neighbor{{ebgp}}remote-as{{bgp.ebgp_neighbors[ebgp]}}

{%endfor%}

Шаблонtemplates/switch.txtиспользуетсозданныешаблоныospfиvlans:

{%include'vlans.txt'%}

{%include'ospf.txt'%}

Файлсданными,длягенерацииконфигурации(data_files/switch.yml):

Include

412

Page 413: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

vlans:

10:Marketing

20:Voice

30:Management

ospf:

-network:10.0.1.00.0.0.255

area:0

-network:10.0.2.00.0.0.255

area:2

-network:10.1.1.00.0.0.255

area:0

Результатвыполненияскрипта:

$pythoncfg_gen.pytemplates/switch.txtdata_files/switch.yml

vlan10

nameMarketing

vlan20

nameVoice

vlan30

nameManagement

routerospf1

auto-costreference-bandwidth10000

network10.0.1.00.0.0.255area0

network10.0.2.00.0.0.255area2

network10.1.1.00.0.0.255area0

Итоговаяконфигурацияполучиласьтакой,как-будтострокиизшаблоновospf.txtиvlans.txt,находилисьвшаблонеswitch.txt.

Шаблонtemplates/router.txt:

{%include'ospf.txt'%}

{%include'bgp.txt'%}

logging{{log_server}}

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

Файлсданными(data_files/router.yml):

Include

413

Page 414: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ospf:

-network:10.0.1.00.0.0.255

area:0

-network:10.0.2.00.0.0.255

area:2

-network:10.1.1.00.0.0.255

area:0

bgp:

local_as:100

loopback:lo100

ibgp_neighbors:

-10.0.0.2

-10.0.0.3

ebgp_neighbors:

90.1.1.1:500

80.1.1.1:600

log_server:10.1.1.1

Результатвыполненияскриптабудеттаким:

$pythoncfg_gen.pytemplates/router.txtdata_files/router.yml

routerospf1

auto-costreference-bandwidth10000

network10.0.1.00.0.0.255area0

network10.0.2.00.0.0.255area2

network10.1.1.00.0.0.255area0

routerbgp100

neighbor10.0.0.2remote-as100

neighbor10.0.0.2update-sourcelo100

neighbor10.0.0.3remote-as100

neighbor10.0.0.3update-sourcelo100

neighbor90.1.1.1remote-as500

neighbor80.1.1.1remote-as600

logging10.1.1.1

Благодаряinclude,шаблонtemplates/ospf.txtиспользуетсяившаблонеtemplates/switch.txt,ившаблонеtemplates/router.txt,вместотого,чтобыповторятьодноитожедважды.

Include

414

Page 415: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Прииспользованиинаследованияразличают:

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

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

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

Примербазовогошаблонаtemplates/base_router.txt:

Наследованиешаблонов

415

Page 416: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

!

{%blockservices%}

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

{%endblock%}

!

noipdomainlookup

!

ipsshversion2

!

{%blockospf%}

routerospf1

auto-costreference-bandwidth10000

{%endblock%}

!

{%blockbgp%}

{%endblock%}

!

{%blockalias%}

{%endblock%}

!

linecon0

loggingsynchronous

historysize100

linevty04

loggingsynchronous

historysize100

transportinputssh

!

Обратитевниманиеначетыреблока,которыесозданывшаблоне:

Наследованиешаблонов

416

Page 417: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

{%blockservices%}

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

{%endblock%}

!

{%blockospf%}

routerospf1

auto-costreference-bandwidth10000

{%endblock%}

!

{%blockbgp%}

{%endblock%}

!

{%blockalias%}

{%endblock%}

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

Дочернийшаблонtemplates/hq_router.txt:

{%extends"base_router.txt"%}

{%blockospf%}

{{super()}}

{%fornetworksinospf%}

network{{networks.network}}area{{networks.area}}

{%endfor%}

{%endblock%}

{%blockalias%}

aliasconfigureshdosh

aliasexecospfshrun|s^routerospf

aliasexecbrishowipintbri|excunass

aliasexecidshowintdesc

aliasexectopshproccpusorted|excl0.00%__0.00%__0.00%

aliasexeccconft

aliasexecdiffsharchiveconfigdifferencesnvram:startup-configsystem:running-conf

ig

aliasexecdescshintdesc|exdown

{%endblock%}

Перваястрокавшаблонеtemplates/hq_router.txtоченьважна:

{%extends"base_router.txt"%}

Наследованиешаблонов

417

Page 418: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Именноонаговоритотом,чтошаблонhq_router.txtбудетпостроеннаосновешаблонаbase_router.txt.

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

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

Вбазовомшаблонечетыреблока:services,ospf,bgp,alias.Вдочернемшаблонезаполненытолькодваизних:ospfиalias.

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

Приэтом,блокиospfиaliasиспользуютсяпо-разному.Вбазовомшаблоне,вблокеospfужебылачастьконфигурации:

{%blockospf%}

routerospf1

auto-costreference-bandwidth10000

{%endblock%}

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

Вданномслучае,конфигурациядополняется.Именнопоэтомувдочернемшаблонеtemplates/hq_router.txtблокospfначинаетсясвыражения{{super()}}:

{%blockospf%}

{{super()}}

{%fornetworksinospf%}

network{{networks.network}}area{{networks.area}}

{%endfor%}

{%endblock%}

{{super()}}переноситвдочернийшаблонсодержимоеэтогоблокаизродительскогошаблона.Засчетэтого,вдочернийшаблонперенесутсястрокиизродительского.

Выражениеsuperнеобязательнодолжнонаходитсявсамомначалеблока.Ономожетбытьвлюбомместеблока.Содержимоебазовогошаблона,перенесетсявтоместо,гденаходитсявыражениеsuper.

Наследованиешаблонов

418

Page 419: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Подытожимправилаработысблоками.Есливродительскомшаблонесозданблок:

безсодержимого-вдочернемшаблонеможнозаполнитьэтотблокилиигнорировать.Еслиблокзаполнен,внембудеттолькото,чтобылонаписановдочернемшаблоне(пример-блокalias)ссодержимым,товдочернемшаблонеможновыполнитьтакиедействия:

игнорироватьблок-втакомслучаевдочернийшаблонпопадетсодержимое,котороенаходилосьвэтомблокевродительскомшаблоне(пример-блокservices)переписатьблок-тогдавдочернемшаблонебудеттолькото,чтоуказановнемперенестисодержимоеблокаизродительскогошаблонаидополнитьего-тогдавдочернемшаблонебудетисодержимоеблокаизродительскогошаблонаисодержимоеиздочернегошаблона.Дляпереносасодержимогоизродительскогошаблонаиспользуетсявыражение{{super()}}(пример-блокospf)

Файлсданнымидлягенерацииконфигурациипошаблону(data_files/hq_router.yml):

ospf:

-network:10.0.1.00.0.0.255

area:0

-network:10.0.2.00.0.0.255

area:2

-network:10.1.1.00.0.0.255

area:0

Результатвыполнениябудеттаким:

Наследованиешаблонов

419

Page 420: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythoncfg_gen.pytemplates/hq_router.txtdata_files/hq_router.yml

!

servicetimestampsdebugdatetimemseclocaltimeshow-timezoneyear

servicetimestampslogdatetimemseclocaltimeshow-timezoneyear

servicepassword-encryption

servicesequence-numbers

!

noipdomainlookup

!

ipsshversion2

!

routerospf1

auto-costreference-bandwidth10000

network10.0.1.00.0.0.255area0

network10.0.2.00.0.0.255area2

network10.1.1.00.0.0.255area0

!

!

aliasconfigureshdosh

aliasexecospfshrun|s^routerospf

aliasexecbrishowipintbri|excunass

aliasexecidshowintdesc

aliasexectopshproccpusorted|excl0.00%__0.00%__0.00%

aliasexeccconft

aliasexecdiffsharchiveconfigdifferencesnvram:startup-configsystem:running-conf

ig

aliasexecdescshintdesc|exdown

!

linecon0

loggingsynchronous

historysize100

linevty04

loggingsynchronous

historysize100

transportinputssh

!

Обратитевнимание,чтовблокеospfестьикомандыизбазовогошаблона,икомандыиздочернегошаблона.

Наследованиешаблонов

420

Page 421: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание13.1

Переделатьскриптcfg_gen.pyвфункциюgenerate_cfg_from_template.

Функцияожидаетдвааргумента:

путькшаблонуфайлспеременнымивформатеYAML

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

Проверитьработуфункциинашаблонеtemplates/for.txtиданныхdata_files/for.yml.

Задания

421

Page 422: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

fromjinja2importEnvironment,FileSystemLoader

importyaml

importsys

reload(sys)

sys.setdefaultencoding('utf-8')

TEMPLATE_DIR,template=sys.argv[1].split('/')

VARS_FILE=sys.argv[2]

env=Environment(loader=FileSystemLoader(TEMPLATE_DIR),trim_blocks=True)

template=env.get_template(template)

vars_dict=yaml.load(open(VARS_FILE))

printtemplate.render(vars_dict)

Задание13.1a

Переделатьфункциюgenerate_cfg_from_template:

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

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

Можнопроверитьнатехжешаблонеиданных,чтоивпрошломзадании:

шаблонеtemplates/for.txt(носкопироватьеговтекущийкаталог)иданныхdata_files/for.yml

Задание13.1b

Дополнитьфункциюgenerate_cfg_from_templateиззадания13.1или13.1a:

добавитьподдержкуаргументовокружения(Environment)

Функцияgenerate_cfg_from_templateдолжнаприниматьлюбыеаргументы,которыепринимаетклассEnvironmentипростопередаватьихему.

Проверитьфункциональностьнааргументах:

trim_blockslstrip_blocks

Задание13.1c

Задания

422

Page 423: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Дополнитьфункциюgenerate_cfg_from_templateиззадания13.1,13.1aили13.1b:

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

Должныподдерживатьсятакиеформаты:

YAMLJSONсловарьPython

Сделатьдлякаждогоформатасвойпараметрфункции.Например:

YAML-yaml_fileJSON-json_fileсловарьPython-py_dict

Проверитьработуфункциинашаблонеtemplates/for.txtиданных:

data_files/for.ymldata_files/for.jsonсловареdata_dict

data_dict={'vlans':{

10:'Marketing',

20:'Voice',

30:'Management'},

'ospf':[{'network':'10.0.1.00.0.0.255','area':0},

{'network':'10.0.2.00.0.0.255','area':2},

{'network':'10.1.1.00.0.0.255','area':0}],

'id':3,

'name':'R3'}

Задание13.1d

Переделатьфункциюgenerate_cfg_from_templateиззадания13.1,13.1a,13.1bили13.1c:

сделатьавтоматическоераспознаваниеразныхформатовдляфайласданнымидляпередачиразныхтиповданных,должениспользоватьсяодинитотжепараметрdata

Должныподдерживатьсятакиеформаты:

YAML-файлысрасширениемymlилиyamlJSON-файлысрасширениемjsonсловарьPython

Задания

423

Page 424: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Еслинеполучилосьопределитьтипданных,вывестисообщениеerror_message(перенеститекстсообщениявтелофункции),завершитьработуфункцииивернутьNone.

Проверитьработуфункциинашаблонеtemplates/for.txtиданных:

data_files/for.ymldata_files/for.jsonсловареdata_dict

error_message="""

Неполучилосьопределитьформатданных.

Поддерживаютсяфайлысрасширением.json,.yml,.yamlисловариPython

"""

data_dict={'vlans':{

10:'Marketing',

20:'Voice',

30:'Management'},

'ospf':[{'network':'10.0.1.00.0.0.255','area':0},

{'network':'10.0.2.00.0.0.255','area':2},

{'network':'10.1.1.00.0.0.255','area':0}],

'id':3,

'name':'R3'}

Задание13.2

Наосновеконфигурацииconfig_r1.txt,создатьшаблоны:

templates/cisco_base.txt-внемдолжныбытьвсестроки,кроменастройкиaliasиeventmanager

имяхостадолжнобытьпеременнойhostnametemplates/alias.txt-вэтотшаблонперенестивсеaliastemplates/eem_int_desc.txt-вэтомшаблонедолженбытьeventmanagerapplet

Вшаблонахtemplates/alias.txtиtemplates/eem_int_desc.txtпеременныхнет.

Создатьшаблонtemplates/cisco_router_base.txt.Вшаблондолжнобытьвключеносодержимоешаблонов:

templates/cisco_base.txttemplates/alias.txttemplates/eem_int_desc.txt

Приэтом,нельзякопироватьтекстшаблонов.

Задания

424

Page 425: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Проверьтешаблонtemplates/cisco_router_base.txt,спомощьюфункцииgenerate_cfg_from_templateиззадания13.1-13.1d.Некопируйтекодфункции.

Вкачестведанных,используйтесловарьrouter_info

router_info={'hostname':'R1'}

Задание13.3

Создайтешаблонtemplates/ospf.txtнаосновеконфигурацииOSPFвфайлеcisco_ospf.txt.Примерконфигурациидан,чтобынапомнитьсинтаксис.

Какиезначениядолжныбытьпеременными:

номерпроцесса.Имяпеременной-processrouter-id.Имяпеременной-router_idreference-bandwidth.Имяпеременной-ref_bwинтерфейсы,накоторыхнужновключитьOSPF.Имяпеременной-ospf_intf

наместеэтойпеременнойожидаетсясписоксловарейстакимиключами:name-имяинтерфейса,видаFa0/1,VLan10,Gi0/0ip-IP-адресинтерфейса,вида10.0.1.1area-номерзоныpassive-являетсялиинтерфейспассивным.Допустимыезначения:TrueилиFalse

Длявсехинтерфейсоввспискеospf_intf,надосгенерироватьстроки:

networkx.x.x.x0.0.0.0areax

Еслиинтерфейспассивный,длянегодолжнабытьдобавленастрока:

passive-interfacex

Дляинтерфейсов,которыенеявляютсяпассивными,врежимеконфигурацииинтерфейса,надодобавитьстроку:

ipospfhello-interval1

Всекомандыдолжныбытьвсоответствующихрежимах.

Задания

425

Page 426: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Проверьтеполучившийсяшаблонtemplates/ospf.txt,наданныхвфайлеdata_files/ospf.yml,спомощьюфункцииgenerate_cfg_from_templateиззадания13.1-13.1d.Некопируйтекодфункции.

Задание13.3a

Изменитешаблонtemplates/ospf.txtтакимобразом,чтобыдляперечисленныхпеременныхбылиуказанызначенияпоумолчанию,которыеиспользуютсявтомслучае,еслипеременнаянезадана.

Неиспользоватьдляэтоговыраженияif/else.

Задатьвшаблонезначенияпоумолчаниюдлятакихпеременных:

process-значениепоумолчанию1ref_bw-значениепоумолчанию10000

Проверьтеполучившийсяшаблонtemplates/ospf.txt,наданныхвфайлеdata_files/ospf2.yml,спомощьюфункцииgenerate_cfg_from_templateиззадания13.1-13.1d.Некопируйтекодфункции.

Задание13.3b

Изменитешаблонtemplates/ospf.txtиззадания13.3aтакимобразом,чтобыдляперечисленныхпеременныхбылиуказанызначенияпоумолчанию,которыеиспользуютсявтомслучае,еслипеременнаянезаданаили,есливпеременнойпустоезначение.

Неиспользоватьдляэтоговыраженияif/else.

Задатьвшаблонезначенияпоумолчаниюдлятакихпеременных:

process-значениепоумолчанию1ref_bw-значениепоумолчанию10000

Проверьтеполучившийсяшаблонtemplates/ospf.txt,наданныхвфайлеdata_files/ospf3.yml,спомощьюфункцииgenerate_cfg_from_templateиззадания13.1-13.1d.Некопируйтекодфункции.

Задание13.4

Создайтешаблонtemplates/add_vlan_to_switch.txt,которыйбудетиспользоватьсяпринеобходимостидобавитьVLANнакоммутатор.

Вшаблонедолжныподдерживатьсявозможности:

Задания

426

Page 427: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

добавленияVLANиимениVLANдобавленияVLANкакaccess,науказанноминтерфейседобавленияVLANвсписокразрешенных,науказанныетранки

ЕслиVLANнеобходимодобавитькакaccess,тонадонастроитьирежиминтерфейсаидобавитьеговVLAN:

interfaceGi0/1

switchportmodeaccess

switchportaccessvlan5

Длятранков,необходимотолькодобавитьVLANвсписокразрешенных:

interfaceGi0/10

switchporttrunkallowedvlanadd5

Именапеременныхнадовыбратьнаоснованиипримераданных,вфайлеdata_files/add_vlan_to_switch.yaml.

Проверьтешаблонtemplates/add_vlan_to_switch.txtнаданныхвфайлеdata_files/add_vlan_to_switch.yaml,спомощьюфункцииgenerate_cfg_from_templateиззадания13.1-13.1d.Некопируйтекодфункции.

Задания

427

Page 428: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ОбработкавыводакомандсTextFSMНаоборудовании,котороенеподдерживаеткакого-топрограммногоинтерфейса,выводкомандshowвозвращаетсяввидестроки.И,хотяотчастионаструктурирована,новсёжеэтопростострока.Иеёнадокак-тообработать,чтобыполучитьобъектыPython,например,словарьилисписок.

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

TextFSMэтобиблиотекасозданнаяGoogleдляобработкивыводассетевыхустройств.Онапозволяетсоздаватьшаблоны,покоторымбудетобрабатыватьсявыводкоманды.

ИспользованиеTextFSMлучше,чемпростаяпострочнаяобработка,таккакшаблоныдаютлучшеепредставлениеотом,каквыводбудетобрабатыватьсяишаблонамипрощеподелиться.Азначит,прощенайтиужесозданныешаблоныииспользоватьих.Илиподелитьсясвоими.

Дляначала,библиотекунадоустановить:

pipinstallgtextfsm

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

Примервыводакомандыtraceroute:

r2#traceroute90.0.0.9source33.0.0.2

traceroute90.0.0.9source33.0.0.2

Typeescapesequencetoabort.

Tracingtherouteto90.0.0.9

VRFinfo:(vrfinname/id,vrfoutname/id)

110.0.12.11msec0msec0msec

215.0.0.50msec5msec4msec

357.0.0.74msec1msec4msec

479.0.0.94msec*1msec

Например,извыводанадополучитьхопы,черезкоторыепрошелпакет.

Втакомслучае,шаблонTextFSMбудетвыглядетьтак(файлtraceroute.template):

14.TextFSM.Обработкавыводакоманд

428

Page 429: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ValueID(\d+)

ValueHop(\d+(\.\d+){3})

Start

^${ID}${Hop}->Record

Первыедвестрокиопределяютпеременные:

ValueID(\d+)-этастрокаопределяетпеременнуюID,котораяописываетрегулярноевыражение:(\d+)-однаилиболеецифр

сюдапопадутномерахоповValueHop(\d+(\.\d+){3})-этастрокаопределяетпеременнуюHop,котораяописываетIP-адрестакимрегулярнымвыражением:(\d+(\.\d+){3})

ПослестрокиStartначинаетсясамшаблон.Вданномслучае,оноченьпростой:

${ID}${Hop}->Record

сначалаидетсимволначаластроки,затемдвапробелаипеременныеIDиHopвTextFSMпеременныеописываютсятакимобразом:${имяпеременной}словоRecordвконцеозначает,чтостроки,которыепопадутподописанныйшаблон,будутобработаныивыведеныврезультатыTextFSM(сэтимподробнеемыразберемсявследующемразделе)

СкриптдляобработкивыводакомандыtracerouteспомощьюTextFSM(parse_traceroute.py):

importtextfsm

traceroute="""

r2#traceroute90.0.0.9source33.0.0.2

traceroute90.0.0.9source33.0.0.2

Typeescapesequencetoabort.

Tracingtherouteto90.0.0.9

VRFinfo:(vrfinname/id,vrfoutname/id)

110.0.12.11msec0msec0msec

215.0.0.50msec5msec4msec

357.0.0.74msec1msec4msec

479.0.0.94msec*1msec

"""

template=open('traceroute.textfsm')

fsm=textfsm.TextFSM(template)

result=fsm.ParseText(traceroute)

printfsm.header

printresult

14.TextFSM.Обработкавыводакоманд

429

Page 430: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Результатвыполненияскрипта:

$pythonparse_traceroute.py

['ID','Hop']

[['1','10.0.12.1'],['2','15.0.0.5'],['3','57.0.0.7'],['4','79.0.0.9']]

Строки,которыесовпалисописаннымшаблоном,возвращаютсяввидеспискасписков.Каждыйэлементэтосписок,которыйсостоитиздвухэлементов:номерахопаиIP-адреса.

Разберемсяссодержимымскрипта:

traceroute-этопеременная,котораясодержитвыводкомандыtraceroutetemplate=open('traceroute.textfsm')-содержимоефайласшаблономTextFSMсчитываетсявпеременнуюtemplatefsm=textfsm.TextFSM(template)-класс,которыйобрабатываетшаблонисоздаетизнегообъектвTextFSMresult=fsm.ParseText(traceroute)-метод,которыйобрабатываетпереданныйвыводсогласношаблонуивозращаетсписоксписков,вкоторомкаждыйэлементэтообработаннаястрокаВконцевыводитсязаголовок:printfsm.header,которыйсодержитименапеременныхирезультатобработки

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

ДляработысTextFSMнужнывыводкомандыишаблон:

дляразныхкоманднужныразныешаблоныTextFSMвозвращаетрезультатобработкивтабличномвиде(ввидеспискасписков)

этотвыводлегкопреобразоватьвcsvформатиливсписоксловарей

14.TextFSM.Обработкавыводакоманд

430

Page 431: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

СинтаксисшаблоновTextFSMШаблонTextFSMописываеткакимобразомданныедолжныобрабатываться.

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

Любойшаблонсостоитиздвухчастей:

определенияпеременныхэтипеременныеописываюткакиестолбцыбудутвтабличномпредставлении

определениясостояний

Примерразборакомандыtraceroute:

#Определениепеременных:

ValueID(\d+)

ValueHop(\d+(\.\d+){3})

#СекциясопределениемсостоянийвсегдадолжнаначинатьсяссостоянияStart

Start

#Переменныедействие

^${ID}${Hop}->Record

Определениепеременных

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

Вэтомразделенедолжнобытьпустыхстрок.ДляTextFSMпустаястрокаозначаетзавершениесекцииопределенияпеременных.

Форматописанияпеременных:

Value[option[,option...]]nameregex

Синтаксисописанияпеременных(длякаждойопциинижемырассмотримпримеры):

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

СинтаксисшаблоновTextFSM

431

Page 432: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

option-опции,которыеопределяюткакработатьспеременной.Еслинужноуказатьнесколькоопций,онидолжныбытьотделенызапятой,безпробелов.Поддерживаютсятакиеопции:

Filldown-значение,котороеранеесовпалосрегулярнымвыражением,запоминаетсядоследующейобработкистроки(еслинебылоявноочищеноилисновасовпалорегулярноевыражение).

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

Key-определяет,чтоэтополесодержитуникальныйидентификаторстрокиRequired-строка,котораяобрабатывается,будетзаписанатольковтомслучае,еслиэтапеременнаяприсутствует.List-значениеэтосписокикаждоесовпадениесрегулярнымвыражениембудетдобавлятьвсписокэлемент.Поумолчанию,каждоеследующеесовпадениеперезаписываетпредыдущее.Fillup-работаеткакFilldown,нозаполняетпустыезначениевыше,дотехпор,поканенайдетсовпадение.НесовместимосRequired.

name-имяпеременной,котороебудетиспользоватьсякакимяколонки.Зарезервированныеименанедолжныиспользоватьсякакимяпеременной.regex-регулярноевыражение,котороеописываетпеременную.Регулярноевыражениедолжнобытьвскобках.

Определениесостояний

Послеопределенияпеременных,нужноописатьсостояния:

каждоеопределениесостояниядолжнобытьотделенопустойстрокой(какминимум,одной)перваястрока-имясостояниязатемидутстроки,которыеописываютправила

правиладолжныначинатьсяспробелаисимвола

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

Проверкавыполняетсяпострочно,поканебудетдостигнутEOF(конецфайла)илитекущеесостояниеперейдетвсостояниеEnd.

Зарезервированныесостояния

Зарезервированытакиесостояния:

СинтаксисшаблоновTextFSM

432

Page 433: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

EOF

^.*->Record

EOFзаписываеттекущуюстроку,преждечемобработказавершается.Еслиэтоповедениенужноизменить,надоявно,вконцешаблона,написатьEOF:

EOF

ПравиласостоянийКаждоесостояниесостоитизодногоилиболееправил:

TextFSMобрабатываетвходящиестрокиисравниваетихсправиламиеслиправило(регулярноевыражение)совпадаетсострокой,выполняютсядействия,которыеописанывправилеидляследующейстрокипроцессповторяетсязаново,сначаласостояния.

Правиладолжныбытьописанывтакомформате:

^regex[->action]

Вправиле:

каждоеправилодолжноначинатьсяспробелаисимвола

символ означаетначалострокиивсегдадолженуказыватьсяявноregex-эторегулярноевыражение,вкотороммогутиспользоватьсяпеременные

дляуказанияпеременной,можетиспользоватьсясинтаксис$ValueNameили${ValueName}(этотформатпредпочтителен)вправиле,наместопеременныхподставляютсярегулярныевыражения,которыеониописываютеслинужноявноуказатьсимволконцастроки,используетсязначение$$

Действиявправилах

СинтаксисшаблоновTextFSM

433

Page 434: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Послерегулярноговыражения,вправилемогутуказыватьсядействия:

междурегулярнымвыражениемидействием,долженбытьсимвол->действиямогутсостоятьизтрехчастей,втакомформатеL.RS

L-LineAction-действия,которыеприменяютсяквходящейстрокеR-RecordAction-действия,которыеприменяютсяксобраннымзначениямS-StateAction-переходвдругоесостояние

еслинетуказанныхдействий,топоумолчаниюиспользуетсядействиеNext.NoRecord.

LineActions

LineActions:

Next-обработатьстроку,прочитатьследующуюиначатьпроверятьеёсначаласостояния.Этодействиеиспользуетсяпоумолчанию,еслинеуказанодругоеContinue-продолжитьобработкуправил,как-будтосовпадениянебыло,приэтомзначенияприсваиваются

RecordAction

RecordAction-опциональноедействие,котороеможетбытьуказанопослеLineAction.Онидолжныбытьразделеныточкой.Типыдействий:

NoRecord-невыполнятьничего.Этодействиепоумолчанию,когдадругоенеуказаноRecord-запомнитьзначение,которыесовпалисправилом.Всепеременные,крометех,гдеуказанаопцияFilldown,обнуляются.Clear-обнулитьвсепеременные,крометех,гдеуказанаопцияFilldown.Clearall-обнулитьвсепеременные.

Разделятьдействияточкойнужнотольковтомслучае,еслинужноуказатьиLineиRecordдействия.Еслинужноуказатьтолькоодноизних,точкуставитьненужно.

StateTransition

Последействия,можетбытьуказаноновоесостояние:

состояниедолжнобытьоднимиззарезервированныхилисостояниеопределенныхвшаблонеесливходнаястрокасовпала:

вседействиявыполняются,

СинтаксисшаблоновTextFSM

434

Page 435: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Есливправилеиспользуетсядействие,товнемнельзяиспользоватьпереходвдругоесостояние.Этоправилонужнодлятого,чтобывпоследовательностисостоянийнебылопетель.

ErrorAction

СпециальноедействиеErrorостанавливаетвсюобработкустрок,отбрасываетвсестроки,которыебылисобраныдосихпоривозвращаетисключение.

Синтаксисэтогодействиятакой:

^regex->Error[word|"string"]

СинтаксисшаблоновTextFSM

435

Page 436: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПримерыиспользованияTextFSMВэтомразделерассматриваютсяпримерышаблоновииспользованияTextFSM.

Дляобработкивыводакомандпошаблону,вразделеиспользуетсяскриптparse_output.py.Оннепривязанкконкретномушаблонуивыводу:шаблонивыводкомандыбудутпередаватьсякакаргументы:

importsys

importtextfsm

fromtabulateimporttabulate

template=sys.argv[1]

output_file=sys.argv[2]

f=open(template)

output=open(output_file).read()

re_table=textfsm.TextFSM(f)

header=re_table.header

result=re_table.ParseText(output)

printtabulate(result,headers=header)

Примерзапускаскрипта:

$pythonparse_output.pytemplatecommand_output

Модульtabulateиспользуетсядляотображенияданныхвтабличномвиде(егонужноустановить,еслихотитеиспользоватьэтотскрипт).Аналогичныйвыводможнобылосделатьиспомощьюформатированиястрок,носtabulate,этосделатьпроще.

Обработкаданныхпошаблонувсегдавыполняетсяодинаково.Поэтомускриптбудетодинаковыйитолькошаблониданныеотличаться.

Начинаяспростогопримера,разберемсястемкакиспользоватьTextFSM.

showclock

Первыйпример-разборвыводакомандыshclock(файлoutput/sh_clock.txt):

ПримерыиспользованияTextFSM

436

Page 437: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

15:10:44.867UTCSunNov132016

Дляначала,вшаблоненадоопределитьпеременные:

вначалекаждойстрокидолжнобытьключевоесловоValueкаждаяпеременнаяопределяетстолбецвтаблице

следующееслово-названиепеременнойпосленазвания,вскобках,регулярноевыражение,котороеописываетзначениепеременной

Определениепеременныхвыглядиттак:

ValueTime(..:..:..)

ValueTimezone(\S+)

ValueWeekDay(\w+)

ValueMonth(\w+)

ValueMonthDay(\d+)

ValueYear(\d+)

Подсказкапоспецсимволам:

.-любойсимвол+-одноилиболееповторенийпредыдущегосимвола\S-всесимволы,кромеwhitespace\w-любаябукваилицифра\d-любаяцифра

Послеопределенияпеременных,должнаидтипустаястрокаисостояниеStart,апосле,начинаяспробелаисимвола ,идетправило(файлtemplates/sh_clock.template):

ValueTime(..:..:..)

ValueTimezone(\S+)

ValueWeekDay(\w+)

ValueMonth(\w+)

ValueMonthDay(\d+)

ValueYear(\d+)

Start

^${Time}.*${Timezone}${WeekDay}${Month}${MonthDay}${Year}->Record

ПримерыиспользованияTextFSM

437

Page 438: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

КогдаTextFSMобрабатываетстрокивывода,онподставляетвместопеременных,ихзначения.Витогеправилобудетвыглядетьтак:

^(..:..:..).*(\S+)(\w+)(\w+)(\d+)(\d+)

Когдаэторегулярноевыражениеприменяетсяввыводуshowclock,вкаждойгрупперегулярноговыражения,будетнаходитьсясоответствующеезначение:

1группа:15:10:442группа:UTC3группа:Sun4группа:Nov5группа:136группа:2016

Вправиле,кромеявногодействияRecord,котороеуказывает,чтозаписьнадопоместитьвфинальнуютаблицу,поумолчаниютакжеиспользуетсяправилоNext.Оноуказывает,чтонадоперейтикследующейстрокетекста.Таккакввыводекомандыshclock,толькооднастрока,обработказавершается.

Результатотработкискриптабудеттаким:

$pythonparse_output.pytemplates/sh_clock.templateoutput/sh_clock.txt

TimeTimezoneWeekDayMonthMonthDayYear

--------------------------------------------------

15:10:44UTCSunNov132016

showcdpneighborsdetail

Теперьпопробуемобработатьвыводкомандыshowcdpneighborsdetail.

Особенностьэтойкомандывтом,чтоданныенаходятсяневоднойстроке,авразных.

Вфайлеoutput/sh_cdp_n_det.txtнаходитсявыводкомандыshowcdpneighborsdetail:

SW1#showcdpneighborsdetail

-------------------------

DeviceID:SW2

Entryaddress(es):

IPaddress:10.1.1.2

ПримерыиспользованияTextFSM

438

Page 439: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Platform:ciscoWS-C2960-8TC-L,Capabilities:SwitchIGMP

Interface:GigabitEthernet1/0/16,PortID(outgoingport):GigabitEthernet0/1

Holdtime:164sec

Version:

CiscoIOSSoftware,C2960Software(C2960-LANBASEK9-M),Version12.2(55)SE9,RELEASES

OFTWARE(fc1)

TechnicalSupport:http://www.cisco.com/techsupport

Copyright(c)1986-2014byCiscoSystems,Inc.

CompiledMon03-Mar-1422:53byprod_rel_team

advertisementversion:2

VTPManagementDomain:''

NativeVLAN:1

Duplex:full

Managementaddress(es):

IPaddress:10.1.1.2

-------------------------

DeviceID:R1

Entryaddress(es):

IPaddress:10.1.1.1

Platform:Cisco3825,Capabilities:RouterSwitchIGMP

Interface:GigabitEthernet1/0/22,PortID(outgoingport):GigabitEthernet0/0

Holdtime:156sec

Version:

CiscoIOSSoftware,3800Software(C3825-ADVENTERPRISEK9-M),Version12.4(24)T1,RELEA

SESOFTWARE(fc3)

TechnicalSupport:http://www.cisco.com/techsupport

Copyright(c)1986-2009byCiscoSystems,Inc.

CompiledFri19-Jun-0918:40byprod_rel_team

advertisementversion:2

VTPManagementDomain:''

Duplex:full

Managementaddress(es):

-------------------------

DeviceID:R2

Entryaddress(es):

IPaddress:10.2.2.2

Platform:Cisco2911,Capabilities:RouterSwitchIGMP

Interface:GigabitEthernet1/0/21,PortID(outgoingport):GigabitEthernet0/0

Holdtime:156sec

Version:

CiscoIOSSoftware,2900Software(C3825-ADVENTERPRISEK9-M),Version15.2(2)T1,RELEAS

ESOFTWARE(fc3)

TechnicalSupport:http://www.cisco.com/techsupport

Copyright(c)1986-2009byCiscoSystems,Inc.

CompiledFri19-Jun-0918:40byprod_rel_team

ПримерыиспользованияTextFSM

439

Page 440: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

advertisementversion:2

VTPManagementDomain:''

Duplex:full

Managementaddress(es):

Извыводакомандынадополучитьтакиеполя:

LOCAL_HOST-имяустройстваизприглашенияDEST_HOST-имясоседаMGMNT_IP-IP-адрессоседаPLATFORM-модельсоседнегоустройстваLOCAL_PORT-локальныйинтерфейс,которыйсоединенссоседомREMOTE_PORT-портсоседнегоустройстваIOS_VERSION-версияIOSсоседа

Шаблонвыглядиттакимобразом(файлtemplates/sh_cdp_n_det.template):

ValueLOCAL_HOST(\S+)

ValueDEST_HOST(\S+)

ValueMGMNT_IP(.*)

ValuePLATFORM(.*)

ValueLOCAL_PORT(.*)

ValueREMOTE_PORT(.*)

ValueIOS_VERSION(\S+)

Start

^${LOCAL_HOST}[>#].

^DeviceID:${DEST_HOST}

^.*IPaddress:${MGMNT_IP}

^Platform:${PLATFORM},

^Interface:${LOCAL_PORT},PortID\(outgoingport\):${REMOTE_PORT}

^.*Version${IOS_VERSION},

Результатвыполненияскрипта:

$pythonparse_output.pytemplates/sh_cdp_n_det.templateoutput/sh_cdp_n_det.txt

LOCAL_HOSTDEST_HOSTMGMNT_IPPLATFORMLOCAL_PORTREMOTE_PORT

IOS_VERSION

----------------------------------------------------------------------------

-------------------

SW1R210.2.2.2Cisco2911GigabitEthernet1/0/21GigabitEther

net0/015.2(2)T1

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

ПримерыиспользованияTextFSM

440

Page 441: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

итоговойтаблицы.

Обратитевнимание,чтовфайлеsh_cdp_n_det.txtнаходитсявыводстремясоседями,автаблицетолькоодинсосед,последний.

Record

Такполучилосьиз-затого,чтовшаблоненеуказанодействиеRecord.Ивитоге,вфинальнойтаблицеосталасьтолькопоследняястрока.

Исправленыйшаблон:

ValueLOCAL_HOST(\S+)

ValueDEST_HOST(\S+)

ValueMGMNT_IP(.*)

ValuePLATFORM(.*)

ValueLOCAL_PORT(.*)

ValueREMOTE_PORT(.*)

ValueIOS_VERSION(\S+)

Start

^${LOCAL_HOST}[>#].

^DeviceID:${DEST_HOST}

^.*IPaddress:${MGMNT_IP}

^Platform:${PLATFORM},

^Interface:${LOCAL_PORT},PortID\(outgoingport\):${REMOTE_PORT}

^.*Version${IOS_VERSION},->Record

Теперьрезультатзапускаскриптавыглядиттак:

$pythonparse_output.pytemplates/sh_cdp_n_det.templateoutput/sh_cdp_n_det.txt

LOCAL_HOSTDEST_HOSTMGMNT_IPPLATFORMLOCAL_PORTRE

MOTE_PORTIOS_VERSION

----------------------------------------------------------------------------

-----------------------------

SW1SW210.1.1.2ciscoWS-C2960-8TC-LGigabitEthernet1/0/16Gi

gabitEthernet0/112.2(55)SE9

R110.1.1.1Cisco3825GigabitEthernet1/0/22Gi

gabitEthernet0/012.4(24)T1

R210.2.2.2Cisco2911GigabitEthernet1/0/21Gi

gabitEthernet0/015.2(2)T1

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

Filldown

ПримерыиспользованияTextFSM

441

Page 442: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Этосвязаностем,чтоприглашение,изкотороговзятозначениепеременной,появляетсятолькоодинраз.И,длятого,чтобыонопоявлялосьивпоследующихстроках,надоиспользоватьдействиеFilldownдляпеременнойLOCAL_HOST:

ValueFilldownLOCAL_HOST(\S+)

ValueDEST_HOST(\S+)

ValueMGMNT_IP(.*)

ValuePLATFORM(.*)

ValueLOCAL_PORT(.*)

ValueREMOTE_PORT(.*)

ValueIOS_VERSION(\S+)

Start

^${LOCAL_HOST}[>#].

^DeviceID:${DEST_HOST}

^.*IPaddress:${MGMNT_IP}

^Platform:${PLATFORM},

^Interface:${LOCAL_PORT},PortID\(outgoingport\):${REMOTE_PORT}

^.*Version${IOS_VERSION},->Record

Теперьмыполучилитакойвывод:

$pythonparse_output.pytemplates/sh_cdp_n_det.templateoutput/sh_cdp_n_det.txt

LOCAL_HOSTDEST_HOSTMGMNT_IPPLATFORMLOCAL_PORTRE

MOTE_PORTIOS_VERSION

----------------------------------------------------------------------------

-----------------------------

SW1SW210.1.1.2ciscoWS-C2960-8TC-LGigabitEthernet1/0/16Gi

gabitEthernet0/112.2(55)SE9

SW1R110.1.1.1Cisco3825GigabitEthernet1/0/22Gi

gabitEthernet0/012.4(24)T1

SW1R210.2.2.2Cisco2911GigabitEthernet1/0/21Gi

gabitEthernet0/015.2(2)T1

SW1

ТеперьзначениепеременнойLOCAL_HOSTпоявилосьвовсехтрёхстроках.Нопоявилсяещёодинстранныйэффект-последняястрока,вкоторойзаполненатолькоколонкаLOCAL_HOST.

Required

Деловтом,чтовсепеременные,которыемыопределили,опциональны.Ктомуже,однапеременнаяспараметромFilldown.И,чтобыизбавитьсяотпоследнейстроки,нужносделатьхотябыоднупеременнуюобязательной,спомощьюпараметраRequired:

ПримерыиспользованияTextFSM

442

Page 443: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ValueFilldownLOCAL_HOST(\S+)

ValueRequiredDEST_HOST(\S+)

ValueMGMNT_IP(.*)

ValuePLATFORM(.*)

ValueLOCAL_PORT(.*)

ValueREMOTE_PORT(.*)

ValueIOS_VERSION(\S+)

Start

^${LOCAL_HOST}[>#].

^DeviceID:${DEST_HOST}

^.*IPaddress:${MGMNT_IP}

^Platform:${PLATFORM},

^Interface:${LOCAL_PORT},PortID\(outgoingport\):${REMOTE_PORT}

^.*Version${IOS_VERSION},->Record

Теперьмыполучимкорректныйвывод:

$pythonparse_output.pytemplates/sh_cdp_n_det.templateoutput/sh_cdp_n_det.txt

LOCAL_HOSTDEST_HOSTMGMNT_IPPLATFORMLOCAL_PORTRE

MOTE_PORTIOS_VERSION

----------------------------------------------------------------------------

-----------------------------

SW1SW210.1.1.2ciscoWS-C2960-8TC-LGigabitEthernet1/0/16Gi

gabitEthernet0/112.2(55)SE9

SW1R110.1.1.1Cisco3825GigabitEthernet1/0/22Gi

gabitEthernet0/012.4(24)T1

SW1R210.2.2.2Cisco2911GigabitEthernet1/0/21Gi

gabitEthernet0/015.2(2)T1

showipinterfacebrief

Вслучае,когданужнообработатьданные,которыевыведеныстолбцами,шаблонTextFSM,наиболееудобен.

Шаблондлявыводакомандыshowipinterfacebrief(файлtemplates/sh_ip_int_br.template):

ValueINTF(\S+)

ValueADDR(\S+)

ValueSTATUS(up|down|administrativelydown)

ValuePROTO(up|down)

Start

^${INTF}\s+${ADDR}\s+\w+\s+\w+\s+${STATUS}\s+${PROTO}->Record

Вэтомслучае,правиломожноописатьоднойстрокой.

ПримерыиспользованияTextFSM

443

Page 444: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Выводкоманды(файлoutput/sh_ip_int_br.txt):

R1#showipinterfacebrief

InterfaceIP-AddressOK?MethodStatusProtocol

FastEthernet0/015.0.15.1YESmanualupup

FastEthernet0/110.0.12.1YESmanualupup

FastEthernet0/210.0.13.1YESmanualupup

FastEthernet0/3unassignedYESunsetupup

Loopback010.1.1.1YESmanualupup

Loopback100100.0.0.1YESmanualupup

Результатвыполнениябудеттаким:

$pythonparse_output.pytemplates/sh_ip_int_br.templateoutput/sh_ip_int_br.txt

INTADDRSTATUSPROTO

----------------------------------------

FastEthernet0/015.0.15.1upup

FastEthernet0/110.0.12.1upup

FastEthernet0/210.0.13.1upup

FastEthernet0/3unassignedupup

Loopback010.1.1.1upup

Loopback100100.0.0.1upup

showiprouteospf

Рассмотримслучай,когданамнужнообработатьвыводкомандыshowiprouteospfивтаблицемаршрутизацииестьнесколькомаршрутовкоднойсети.

Длямаршрутовкоднойитойжесети,вместонесколькихстрок,гдебудетповторятьсясеть,будетсозданаодназапись,вкоторойвседоступныеnext-hopадресасобранывсписок.

Примервыводакомандыshowiprouteospf(файлoutput/sh_ip_route_ospf.txt):

ПримерыиспользованияTextFSM

444

Page 445: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

R1#shiprouteospf

Codes:L-local,C-connected,S-static,R-RIP,M-mobile,B-BGP

D-EIGRP,EX-EIGRPexternal,O-OSPF,IA-OSPFinterarea

N1-OSPFNSSAexternaltype1,N2-OSPFNSSAexternaltype2

E1-OSPFexternaltype1,E2-OSPFexternaltype2

i-IS-IS,su-IS-ISsummary,L1-IS-ISlevel-1,L2-IS-ISlevel-2

ia-IS-ISinterarea,*-candidatedefault,U-per-userstaticroute

o-ODR,P-periodicdownloadedstaticroute,H-NHRP,l-LISP

+-replicatedroute,%-nexthopoverride

Gatewayoflastresortisnotset

10.0.0.0/8isvariablysubnetted,10subnets,2masks

O10.0.24.0/24[110/20]via10.0.12.2,1w2d,Ethernet0/1

O10.0.34.0/24[110/20]via10.0.13.3,1w2d,Ethernet0/2

O10.2.2.2/32[110/11]via10.0.12.2,1w2d,Ethernet0/1

O10.3.3.3/32[110/11]via10.0.13.3,1w2d,Ethernet0/2

O10.4.4.4/32[110/21]via10.0.13.3,1w2d,Ethernet0/2

[110/21]via10.0.12.2,1w2d,Ethernet0/1

[110/21]via10.0.14.4,1w2d,Ethernet0/3

O10.5.35.0/24[110/20]via10.0.13.3,1w2d,Ethernet0/2

Дляэтогопримераупрощаемзадачуисчитаем,чтомаршрутымогутбытьтолькоOSPFисобозначением,толькоO(тоесть,тольковнутризональныемаршруты).

Перваяверсияшаблонавыглядиттак:

ValueNetwork(([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}))

ValueMask(\/\d{1,2})

ValueDistance(\d+)

ValueMetric(\d+)

ValueNextHop([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3})

Start

^O+${Network}${Mask}\s\[${Distance}\/${Metric}\]\svia\s${NextHop},->Record

Результатполучилсятакой:

NetworkMaskDistanceMetricNextHop

------------------------------------------

10.0.24.0/241102010.0.12.2

10.0.34.0/241102010.0.13.3

10.2.2.2/321101110.0.12.2

10.3.3.3/321101110.0.13.3

10.4.4.4/321102110.0.13.3

10.5.35.0/241102010.0.13.3

ПримерыиспользованияTextFSM

445

Page 446: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Всёнормально,нопотерялисьвариантыпутейдлямаршрута10.4.4.4/32.Этологично,ведьнетправила,котороеподошлобыдлятакойстроки.

List

ВоспользуемсяопциейListдляпеременнойNextHop:

ValueNetwork(([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}))

ValueMask(\/\d{1,2})

ValueDistance(\d+)

ValueMetric(\d+)

ValueListNextHop([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3})

Start

^O+${Network}${Mask}\s\[${Distance}\/${Metric}\]\svia\s${NextHop},->Record

Теперьвыводполучилсятаким:

NetworkMaskDistanceMetricNextHop

----------------------------------------------

10.0.24.0/2411020['10.0.12.2']

10.0.34.0/2411020['10.0.13.3']

10.2.2.2/3211011['10.0.12.2']

10.3.3.3/3211011['10.0.13.3']

10.4.4.4/3211021['10.0.13.3']

10.5.35.0/2411020['10.0.13.3']

Изменилосьто,чтовстолбцеNextHopотображаетсясписок,нопокасоднимэлементом.

Таккак,передзаписьюмаршрута,длякоторогоестьнесколькопутей,надодобавитькнемувседоступныеадресаNextHop,надоперенестидействиеRecord.

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

^O->Continue.Record

ВнейдействиеRecordговорит,чтонадозаписатьтекущеезначениепеременных.А,таккаквэтомправиленетпеременных,записываетсято,чтобыловпредыдущихзначениях.

ДействиеContinueговорит,чтонадопродолжитьработатьстекущейстрокойтак,какбудтосовпадениянебыло.Засчетэтого,сработаетследующаястрока.

ПримерыиспользованияTextFSM

446

Page 447: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Остаетсядобавитьправило,котороебудетописыватьдополнительныемаршрутыксети(внихнетсетиимаски):

^\s+\[${Distance}\/${Metric}\]\svia\s${NextHop},

Итоговыйшаблонвыглядиттак(файлtemplates/sh_ip_route_ospf.template):

ValueNetwork(([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}))

ValueMask(\/\d{1,2})

ValueDistance(\d+)

ValueMetric(\d+)

ValueListNextHop([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3})

Start

^O->Continue.Record

^O+${Network}${Mask}\s\[${Distance}\/${Metric}\]\svia\s${NextHop},

^\s+\[${Distance}\/${Metric}\]\svia\s${NextHop},

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

Врезультате,мыполучимтакойвывод:

NetworkMaskDistanceMetricNextHop

------------------------------------------------------------------------

10.0.24.0/2411020['10.0.12.2']

10.0.34.0/2411020['10.0.13.3']

10.2.2.2/3211011['10.0.12.2']

10.3.3.3/3211011['10.0.13.3']

10.4.4.4/3211021['10.0.13.3','10.0.12.2','10.0.14.4']

10.5.35.0/2411020['10.0.13.3']

showetherchannelsummary

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

Примервыводакомандыshowetherchannelsummary(файлoutput/sh_etherchannel_summary.txt):

ПримерыиспользованияTextFSM

447

Page 448: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

sw1#shetherchannelsummary

Flags:D-downP-bundledinport-channel

I-stand-alones-suspended

H-Hot-standby(LACPonly)

R-Layer3S-Layer2

U-inusef-failedtoallocateaggregator

M-notinuse,minimumlinksnotmet

u-unsuitableforbundling

w-waitingtobeaggregated

d-defaultport

Numberofchannel-groupsinuse:2

Numberofaggregators:2

GroupPort-channelProtocolPorts

------+-------------+-----------+-----------------------------------------------

1Po1(SU)LACPFa0/1(P)Fa0/2(P)Fa0/3(P)

3Po3(SU)-Fa0/11(P)Fa0/12(P)Fa0/13(P)Fa0/14(P)

Вданномслучае,нужнополучить:

имяиномерport-channel.Например,Po1списоквсехпортоввнем.Например,['Fa0/1','Fa0/2','Fa0/3']

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

Перваяверсияшаблонавыглядиттак:

ValueCHANNEL(\S+)

ValueListMEMBERS(\w+\d+\/\d+)

Start

^\d++${CHANNEL}\(\S++[\w-]++[\w]++${MEMBERS}\(->Record

Вшаблонедвепеременные:

CHANNEL-имяиномерагрегированногопортаMEMBERS-списокпортов,которыевходятвагрегированныйпорт.Дляэтойпеременнойуказантип-List

Результат:

ПримерыиспользованияTextFSM

448

Page 449: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

CHANNELMEMBERS

-------------------

Po1['Fa0/1']

Po3['Fa0/11']

Покачтоввыводетолькопервыйпорт,анужночтобыпопаливсепорты.Вданномслучае,надопродолжитьобработкустрокиспортами,посленайденногосовпадения.Тоесть,использоватьдействиеContinueиописатьследующеевыражение.

Единственнаястрока,котораяестьвшаблоне,описываетпервыйпорт.Надодобавитьстроку,котораяописываетследующийпорт.

Следующаяверсияшаблона:

ValueCHANNEL(\S+)

ValueListMEMBERS(\w+\d+\/\d+)

Start

^\d++${CHANNEL}\(\S++[\w-]++[\w]++${MEMBERS}\(->Continue

^\d++${CHANNEL}\(\S++[\w-]++[\w]++\S++${MEMBERS}\(->Record

Втораястрокаописываеттакоежевыражение,нопеременнаяMEMBERSсмещаетсянаследующийпорт.

Результат:

CHANNELMEMBERS

-----------------------------

Po1['Fa0/1','Fa0/2']

Po3['Fa0/11','Fa0/12']

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

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

Итоговыйшаблон(файлtemplates/sh_etherchannel_summary.txt):

ПримерыиспользованияTextFSM

449

Page 450: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ValueCHANNEL(\S+)

ValueListMEMBERS(\w+\d+\/\d+)

Start

^\d+.*->Continue.Record

^\d++${CHANNEL}\(\S++[\w-]++[\w]++\S++${MEMBERS}\(->Continue

^\d++${CHANNEL}\(\S++[\w-]++[\w]++(\S++){2}+${MEMBERS}\(->Continue

^\d++${CHANNEL}\(\S++[\w-]++[\w]++(\S++){3}+${MEMBERS}\(->Continue

Результатобработки:

CHANNELMEMBERS

-------------------------------------------------

Po1['Fa0/1','Fa0/2','Fa0/3']

Po3['Fa0/11','Fa0/12','Fa0/13','Fa0/14']

Теперьвсепортыпопаливвывод.

Шаблонпредполагает,чтоводнойстрокебудетмаксимумчетырепорта.Еслипортовможетбытьбольше,надодобавитьсоответствующиестрокившаблон.

Возможенещёодинвариантвыводакомандыshetherchannelsummary(файлoutput/sh_etherchannel_summary2.txt):

sw1#shetherchannelsummary

Flags:D-downP-bundledinport-channel

I-stand-alones-suspended

H-Hot-standby(LACPonly)

R-Layer3S-Layer2

U-inusef-failedtoallocateaggregator

M-notinuse,minimumlinksnotmet

u-unsuitableforbundling

w-waitingtobeaggregated

d-defaultport

Numberofchannel-groupsinuse:2

Numberofaggregators:2

GroupPort-channelProtocolPorts

------+-------------+-----------+-----------------------------------------------

1Po1(SU)LACPFa0/1(P)Fa0/2(P)Fa0/3(P)

3Po3(SU)-Fa0/11(P)Fa0/12(P)Fa0/13(P)Fa0/14(P)

Fa0/15(P)Fa0/16(P)

ПримерыиспользованияTextFSM

450

Page 451: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Втакомвыводепоявляетсяновыйвариант-строки,вкоторыхнаходятсятолькопорты.

Длятогочтобышаблонобрабатывалиэтотвариант,надоегомодифицировать(файлtemplates/sh_etherchannel_summary2.txt):

ValueCHANNEL(\S+)

ValueListMEMBERS(\w+\d+\/\d+)

Start

^\d+.*->Continue.Record

^\d++${CHANNEL}\(\S++[\w-]++[\w]++${MEMBERS}\(->Continue

^\d++${CHANNEL}\(\S++[\w-]++[\w]++\S++${MEMBERS}\(->Continue

^\d++${CHANNEL}\(\S++[\w-]++[\w]++(\S++){2}+${MEMBERS}\(->Continue

^\d++${CHANNEL}\(\S++[\w-]++[\w]++(\S++){3}+${MEMBERS}\(->Continue

^+${MEMBERS}->Continue

^+\S++${MEMBERS}->Continue

^+(\S++){2}+${MEMBERS}->Continue

^+(\S++){3}+${MEMBERS}->Continue

Результатбудеттаким:

CHANNELMEMBERS

---------------------------------------------------------------------

Po1['Fa0/1','Fa0/2','Fa0/3']

Po3['Fa0/11','Fa0/12','Fa0/13','Fa0/14','Fa0/15','Fa0/16']

НаэтоммызаканчиваемразбиратьсясшаблонамиTextFSM.

ПримерышаблоновдляCiscoидругогооборудованияможнопосмотретьвпроектеntc-ansible.

ПримерыиспользованияTextFSM

451

Page 452: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

TextFSMCLITableБлагодаряTextFSM,можнообрабатыватьвыводкомандиполучатьструктурированныйрезультат.Но,всёещёнадовручнуюпрописыватькакимшаблономобрабатыватькомандыshow,каждыйраз,когдаиспользуетсяTextFSM.

Былобынамногоудобнейиметькакое-тосоответствиемеждукомандойишаблоном.Чтобыможнобылонаписатьобщийскрипт,которыйвыполняетподключениякустройствам,отправляеткоманды,самвыбираетшаблонипарситвыводвсоответствиисшаблоном.

ВTextFSMестьтакаявозможность.

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

Этотфайлдолженнаходитьсявкаталогесшаблонамиидолжениметьтакойформат:

перваястрока-названияколоноккаждаяследующаястрока-этосоответствиешаблонакомандеобязательныеколонки,местоположениекоторыхфиксировано(должныбытьобязательнопервойипоследней,соответственно):

перваяколонка-именашаблоновпоследняяколонка-соответствующаякоманда

вэтойколонкеиспользуетсяспециальныйформат,чтобыописатьто,чтокомандаможетбытьнаписананеполностью

остальныеколонкимогутбытьлюбыминапример,впримеренижебудутколонкиHostname,Vendor.Онипозволяютуточнитьинформациюобустройстве,чтобыопределитькакойшаблониспользовать.

например,командаshowversionможетбытьуоборудованияCiscoиHP.Соответственно,толькокомандынедостаточно,чтобыопределитькакойшаблониспользовать.Втакомслучае,можнопередатьинформациюотом,какойтипоборудованияиспользуется,вместескомандой,итогдаполучитсяопределитьправильныйшаблон.

вовсехстолбцах,кромепервого,поддерживаютсярегулярныевыражениявкомандах,внутри[[]]регулярныевыражениянеподдерживаются

Примерфайлаindex:

CLITable

452

Page 453: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Template,Hostname,Vendor,Command

sh_cdp_n_det.template,.*,Cisco,sh[[ow]]cdpne[[ighbors]]de[[tail]]

sh_clock.template,.*,Cisco,sh[[ow]]clo[[ck]]

sh_ip_int_br.template,.*,Cisco,sh[[ow]]ipint[[erface]]br[[ief]]

sh_ip_route_ospf.template,.*,Cisco,sh[[ow]]iprou[[te]]o[[spf]]

Обратитевниманиенато,какзаписаныкоманды:

sh[[ow]]ipint[[erface]]br[[ief]]

этазаписьбудетпреобразованаввыражениеsh((ow)?)?ipint((erface)?)?br((ief)?)?этозначит,чтоTextFSMсможетопределитькакойшаблониспользовать,дажеесликоманданабрананеполностьюнапример,такиевариантыкомандысработают:

shipintbrshowipinterbri

КакиспользоватьCLItable

Посмотримкакпользоватьсяклассомclitableифайломindex.

Вкаталогеtemplatesтакиешаблоныифайлindex:

sh_cdp_n_det.template

sh_clock.template

sh_ip_int_br.template

sh_ip_route_ospf.template

index

СначалапопробуемпоработатьсCLITableвipython,чтобыпосмотретькакиевозможностиестьуэтогокласса,азатемпосмотримнафинальныйскрипт.

Еслиприработесclitableвозникнетошибка,чтонетмодуляterminal,посмотритевкаталоге,вкоторомнаходитсяустановленныйTextFSM(взависимостиотОС),файлterminal.py.Еслиегонет,простосоздайтееговручнуюископируйтесодержимоеэтогофайлаизрепозиторияTextFSM.Определить,гденаходитсямодуль,можнотакимобразом:printtextfsm.__file__

Дляначала,импортируемклассclitable:

In[1]:importtextfsm.clitableasclitable

CLITable

453

Page 454: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Проверятьработуclitableбудемнапоследнемпримереизпрошлогораздела-выводекомандыshowiprouteospf.Считываемвывод,которыйхранитсявфайлеoutput/sh_ip_route_ospf.txt,встроку:

In[2]:output_sh_ip_route_ospf=open('output/sh_ip_route_ospf.txt').read()

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

In[3]:cli_table=clitable.CliTable('index','templates')

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

In[4]:attributes={'Command':'showiprouteospf','Vendor':'Cisco'}

МетодуParseCmdнадопередатьвыводкомандыисловарьспараметрами:

In[5]:cli_table.ParseCmd(output_sh_ip_route_ospf,attributes)

Врезультате,вобъектеcli_table,получаемобработанныйвыводкомандыshiprouteospf.

Методыcli_table(чтобыпосмотретьвсеметоды,надовызватьdir(cli_table)):

CLITable

454

Page 455: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[6]:cli_table.

cli_table.AddColumncli_table.NewRowcli_table.indexcli_t

able.size

cli_table.AddKeyscli_table.ParseCmdcli_table.index_filecli_t

able.sort

cli_table.Appendcli_table.ReadIndexcli_table.nextcli_t

able.superkey

cli_table.CsvToTablecli_table.Removecli_table.rawcli_t

able.synchronised

cli_table.FormattedTablecli_table.Resetcli_table.rowcli_t

able.table

cli_table.INDEXcli_table.RowWithcli_table.row_classcli_t

able.template_dir

cli_table.KeyValuecli_table.extendcli_table.row_index

cli_table.LabelValueTablecli_table.headercli_table.separator

Например,есливызватьprintcli_table,получимтакойвывод:

In[7]:printcli_table

Network,Mask,Distance,Metric,NextHop

10.0.24.0,/24,110,20,['10.0.12.2']

10.0.34.0,/24,110,20,['10.0.13.3']

10.2.2.2,/32,110,11,['10.0.12.2']

10.3.3.3,/32,110,11,['10.0.13.3']

10.4.4.4,/32,110,21,['10.0.13.3','10.0.12.2','10.0.14.4']

10.5.35.0,/24,110,20,['10.0.13.3']

МетодFormattedTableпозволяетполучитьвыводввидетаблицы:

In[8]:printcli_table.FormattedTable()

NetworkMaskDistanceMetricNextHop

====================================================================

10.0.24.0/241102010.0.12.2

10.0.34.0/241102010.0.13.3

10.2.2.2/321101110.0.12.2

10.3.3.3/321101110.0.13.3

10.4.4.4/321102110.0.13.3,10.0.12.2,10.0.14.4

10.5.35.0/241102010.0.13.3

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

Чтобыполучитьизобъектаcli_tableструктурированныйвывод,например,списоксписков,надообратитьсякобъектутакимобразом:

CLITable

455

Page 456: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[9]:data_rows=[]

In[10]:forrowincli_table:

....:current_row=[]

....:forvalueinrow:

....:current_row.append(value)

....:data_rows.append(current_row)

....:

In[11]:data_rows

Out[11]:

[['10.0.24.0','/24','110','20',['10.0.12.2']],

['10.0.34.0','/24','110','20',['10.0.13.3']],

['10.2.2.2','/32','110','11',['10.0.12.2']],

['10.3.3.3','/32','110','11',['10.0.13.3']],

['10.4.4.4','/32','110','21',['10.0.13.3','10.0.12.2','10.0.14.4']],

['10.5.35.0','/24','110','20',['10.0.13.3']]]

Отдельноможнополучитьназваниястолбцов:

In[12]:cli_table.header.viewvalues()

Out[12]:dict_values([])

In[13]:header=[]

In[13]:fornameincli_table.header:

....:header.append(name)

....:

In[14]:header

Out[14]:['Network','Mask','Distance','Metric','NextHop']

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

Соберемвсёводинскрипт(файлtextfsm_clitable.py):

CLITable

456

Page 457: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importtextfsm.clitableasclitable

output_sh_ip_route_ospf=open('output/sh_ip_route_ospf.txt').read()

cli_table=clitable.CliTable('index','templates')

attributes={'Command':'showiprouteospf','Vendor':'Cisco'}

cli_table.ParseCmd(output_sh_ip_route_ospf,attributes)

print"CLITableoutput:\n",cli_table

print"FormattedTable:\n",cli_table.FormattedTable()

data_rows=[]

forrowincli_table:

current_row=[]

forvalueinrow:

current_row.append(value)

data_rows.append(current_row)

header=[]

fornameincli_table.header:

header.append(name)

printheader

forrowindata_rows:

printrow

Вупражненияхкэтомуразделубудетзадание,вкоторомнадообъединитьописаннуюпроцедурувфункцию.Атакжевариантсполучениемспискасловарей.

Выводбудеттаким:

CLITable

457

Page 458: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythontextfsm_clitable.py

CLITableoutput:

Network,Mask,Distance,Metric,NextHop

10.0.24.0,/24,110,20,['10.0.12.2']

10.0.34.0,/24,110,20,['10.0.13.3']

10.2.2.2,/32,110,11,['10.0.12.2']

10.3.3.3,/32,110,11,['10.0.13.3']

10.4.4.4,/32,110,21,['10.0.13.3','10.0.12.2','10.0.14.4']

10.5.35.0,/24,110,20,['10.0.13.3']

FormattedTable:

NetworkMaskDistanceMetricNextHop

====================================================================

10.0.24.0/241102010.0.12.2

10.0.34.0/241102010.0.13.3

10.2.2.2/321101110.0.12.2

10.3.3.3/321101110.0.13.3

10.4.4.4/321102110.0.13.3,10.0.12.2,10.0.14.4

10.5.35.0/241102010.0.13.3

['Network','Mask','Distance','Metric','NextHop']

['10.0.24.0','/24','110','20',['10.0.12.2']]

['10.0.34.0','/24','110','20',['10.0.13.3']]

['10.2.2.2','/32','110','11',['10.0.12.2']]

['10.3.3.3','/32','110','11',['10.0.13.3']]

['10.4.4.4','/32','110','21',['10.0.13.3','10.0.12.2','10.0.14.4']]

['10.5.35.0','/24','110','20',['10.0.13.3']]

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

CLITable

458

Page 459: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание14.1

Переделатьпример,которыйиспользовалсявразделеTextFSM,вфункцию.

Функциядолжнаназыватьсяparse_output.Параметрыфункции:

template-шаблонTextFSM(этодолжнобытьимяфайла,вкоторомнаходитсяшаблон)output-выводсоответствующейкомандыshow(строка)

Функциядолжнавозвращатьсписок:

первыйэлемент-этосписоксназваниямистолбцов(впримерениже,находитсявпеременнойheader)остальныеэлементыэтосписки,вкоторыхнаходятсярезультатыобработкивывода(впримерениже,находитсявпеременнойresult)

Проверитьработуфункциинакаком-тоизпримеровраздела.

Примеризраздела:

Задания

459

Page 460: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importsys

importtextfsm

fromtabulateimporttabulate

template=sys.argv[1]

output_file=sys.argv[2]

f=open(template)

output=open(output_file).read()

re_table=textfsm.TextFSM(f)

header=re_table.header

result=re_table.ParseText(output)

printtabulate(result,headers=header)

Задание14.1a

Переделатьфункциюparse_outputиззадания14.1такимобразом,чтобы,вместоспискасписков,онавозвращалаодинсписоксловарей:

ключи-названиястолбцов,значения,соответствующиезначениявстолбцах.

Тоесть,длякаждойстрокибудетодинсловарьвсписке.

Задание14.2

Вэтомзаданиинужноиспользоватьфункциюparse_outputиззадания14.1.Онаиспользуетсядлятого,чтобыполучитьструктурированныйвыводврезультатеобработкивыводакоманды.

ПолученныйвыводнужнозаписатьвCSVформате.

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

список:первыйэлемент-этосписоксназваниямизаголовковостальныеэлементыэтосписки,вкоторомнаходятсярезультатыобработкивывода

имяфайла,вкоторыйнужнозаписатьданныевCSVформате

Проверитьработуфункциинапримереобработкикомандыshipintbr(шаблонивыводестьвразделе).

Задания

460

Page 461: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Задание14.3

СделатьшаблонTextFSMдляобработкивыводаshipdhcpsnoopingbinding.Выводкомандынаходитсявфайлеoutput/sh_ip_dhcp_snooping.txt.

Шаблондолженобрабатыватьивозвращатьзначениятакихстолбцов:

MacAddressIpAddressVLANInterface

Проверитьработушаблонаспомощьюфункциииззадания14.1.

Задание14.4

Наосновепримераизразделаclitableсделатьфункциюparse_command_dynamic.

Параметрыфункции:

словарьатрибутов,вкоторомнаходятсятакиепарыключ:значение:'Command':команда'Vendor':вендор(обратитевнимание,чтофайлindexотличаетсяотпримера,которыйиспользовалсявразделе,поэтомувамнужноподставитьтутправильноезначение)

имяфайла,гдехранитсясоответствиемеждукомандамиишаблонами(строка)значениепоумолчаниюаргумента-index

каталог,гдехранятсяшаблоныифайлссоответствиями(строка)значениепоумолчаниюаргумента-templates

выводкоманды(строка)

Функциядолжнавозвращатьсписоксловарейсрезультатамиобработкивыводакоманды(каквзадании14.1a):

ключи-названиястолбцовзначения-соответствующиезначениявстолбцах

Проверитьработуфункциинапримеревыводакомандыshipintbr.

Примеризраздела:

Задания

461

Page 462: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importtextfsm.clitableasclitable

output_sh_ip_route_ospf=open('output/sh_ip_route_ospf.txt').read()

cli_table=clitable.CliTable('index','templates')

attributes={'Command':'showiprouteospf','Vendor':'Cisco'}

cli_table.ParseCmd(output_sh_ip_route_ospf,attributes)

print"CLITableoutput:\n",cli_table

print"FormattedTable:\n",cli_table.FormattedTable()

data_rows=[]

forrowincli_table:

current_row=[]

forvalueinrow:

current_row.append(value)

data_rows.append(current_row)

header=[]

fornameincli_table.header:

header.append(name)

printheader

forrowindata_rows:

printrow

Задание14.4a

Переделатьфункциюиззадания14.4:

добавитьаргументshow_output,которыйконтролируетбудетливыводитьсярезультатобработкикомандынастандартныйпотоквывода

поумолчаниюFalse,чтозначитрезультатнебудетвыводитьсярезультатдолженотображатьсяввиде,которыйвозвращаетметодFormattedTable(примерестьвразделе)

Задание14.5

ВэтомзаданиисоединяетсяфункциональностьTextFSMиподключениекоборудованию.

Задачатакая:

подключитьсякоборудованиювыполнитькомандуshowполученныйвыводпередаватьнаобработкуTextFSMвернутьрезультатобработки

Задания

462

Page 463: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Дляэтого,воспользуемсяфункциями,которыебылисозданыранее:

функциейsend_show_commandизупражнения12.1функциейparse_command_dynamicизупражнения14.4

Вэтомупражнениинужносоздатьфункциюsend_and_parse_command:

функциядолжнаиспользоватьвнутрисебяфункцииparse_command_dynamicиsend_show_command.какиеаргументыдолжныбытьуфункцииsend_and_parse_command,нужнорешитьсамостоятельно

но,надоиметьввиду,какиеаргументыожидаютдвеготовыефункции,которыемыиспользуем

функцияsend_and_parse_commandдолжнавозвращать:функцияsend_show_commandвозвращаетсловарьсрезультатамивыполнениякоманды:

ключ-IPустройствазначение-результатвыполнениякоманды

затем,нужноотправитьполученныйвыводнаобработкуфункцииparse_command_dynamicврезультате,долженполучитьсясловарь,вкотором:

ключ-IPустройствазначение-списоксловарей(тоесть,тотвывод,которыйбылполученизфункцииparse_command_dynamic)

Дляфункцииsend_show_commandсозданфайлdevices.yaml,вкоторомнаходятсяпараметрыподключениякустройствам.

Проверитьработуфункцииsend_and_parse_commandнакомандеshipintbr.

Задание14.6

Этозаданиепохоженазадание14.5,новэтомзаданииподключениянадовыполнятьпараллельно.

Дляэтогонадоиспользоватьфункцииconnect_sshиconn_processes(примеризразделаmultiprocessing)ифункциюparse_command_dynamicизупражнения14.4.

Вэтомупражнениинужносоздатьфункциюsend_and_parse_command_parallel:

онадолжнаиспользоватьвнутрисебяфункцииconnect_ssh,conn_processesиparse_command_dynamicкакиеаргументыдолжныбытьуфункцииsend_and_parse_command_parallel,нужнорешитьсамостоятельно

Задания

463

Page 464: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

нонадоиметьввиду,какиеаргументыожидаюттриготовыефункции,которыеиспользуются

функцияsend_and_parse_command_parallelдолжнавозвращатьсловарь,вкотором:

ключ-IPустройствазначение-списоксловарей(тоесть,тотвывод,которыйбылполученизфункцииparse_command_dynamic)

Дляфункцииconn_processesсозданфайлdevices.yaml,вкоторомнаходятсяпараметрыподключениякустройствам.

Проверитьработуфункцииsend_and_parse_command_parallelнакомандеshipintbr.

Примеризразделаmultiprocessing:

Задания

464

Page 465: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importmultiprocessing

fromnetmikoimportConnectHandler

importsys

importyaml

COMMAND=sys.argv[1]

devices=yaml.load(open('devices.yaml'))

defconnect_ssh(device_dict,command,queue):

ssh=ConnectHandler(**device_dict)

ssh.enable()

result=ssh.send_command(command)

print"Connectiontodevice%s"%device_dict['ip']

queue.put({device_dict['ip']:result})

defconn_processes(function,devices,command):

processes=[]

queue=multiprocessing.Queue()

fordeviceindevices:

p=multiprocessing.Process(target=function,args=(device,command,queue)

)

p.start()

processes.append(p)

forpinprocesses:

p.join()

results=[]

forpinprocesses:

results.append(queue.get())

returnresults

print(conn_processes(connect_ssh,devices['routers'],COMMAND))

Задания

465

Page 466: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

AnsibleAnsible-этосистемауправленияконфигурациями.Ansibleпозволяетавтоматизироватьиупроститьнастройку,обслуживаниеиразвертываниесерверов,служб,ПОидр.

Наданныймоментсуществуетнесколькосистемуправленияконфигурациями.

Однако,дляработыссетевымоборудованием,чащевсегоиспользуетсяAnsible.Связаноэтостем,чтоAnsibleнетребуетустановкиагентанауправляемыехосты.Особенноактуальноэтодляустройств,которыепозволяютработатьснимитолькочерезCLI.

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

Некотороесетевоеоборудованиеподдерживаетдругиесистемыуправленияконфигурациями(позволяетустановитьагента).

ОдноизважныхпреимуществAnsibleзаключаетсявтом,чтооноченьпроствиспользовании.Иегодовольнолегконачатьиспользовать.

Примерызадач,которыепоможетрешитьAnsible:

подключениепоSSHкустройствампаралелльноеподключениекустройствампоSSH(можноуказыватькосколькиустройствамподключатьсяодновременно)

отправкакоманднаустройстваудобныйсинтаксисописанияустройств:

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

поддержкашаблоновконфигурацийсJinja2

ЭтовсеголишьнескольковозможностейAnsible,которыеотносятсяксетевомуоборудованию.Ониперечисленыдлятого,чтобыпоказать,чтоэтизадачиAnsibleсразуснимаетиможнонеиспользоватьдляэтогокакие-тоскрипты.

УстановкаAnsible

15.Ansible

466

Page 467: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Требованиякуправляющемухосту:

поддержкаPython2.7(или2.6)Windowsнеможетбытьуправляющимхостом

Ansibleдовольночастообновляется,поэтомулучшеустановитьеговвиртуальномокружении.

УстановитьAnsibleможнопо-разному.

Например,спомощьюpip:

$pipinstallansible==2.2.0.0

Покачто,лучшепоставитьAnsibleсявнымуказаниемверсии,таккаквверсии2.2.1.0быливнесеныизмененияиз-закоторыхчастьфункционалаработаетсошибками.Скореевсего,этоскороисправят,нопримоейпоследнейпроверке(05.02.2017),былипроблемы.

ПараметрыоборудованияВпримерахразделаиспользуютсятримаршрутизатораиодинкоммутатор.Книмнетникакихтребований,тольконастроенныйSSH.

Параметры,которыеиспользуютсявразделе:

пользователь:ciscoпароль:ciscoпарольнарежимenable:ciscoSSHверсии2IP-адреса:

R1:192.168.100.1R2:192.168.100.2R3:192.168.100.3SW1:192.168.100.100

Есливыбудетеиспользоватьдругиепараметры,изменитесоответственноинвентарныйфайл,конфигурационныйфайлAnsibleифайлgroup_vars/all.yml.

15.Ansible

467

Page 468: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

15.Ansible

468

Page 469: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ОсновыAnsibleAnsible:

РаботаетбезустановкиагентанауправляемыехостыИспользуетSSHдляподключениякуправляемымхостамВыполняетизменения,спомощьюмодулейPython,которыевыполняютсянауправляемыххостахМожетвыполнятьдействиялокально,науправляющемхостеИспользуетYAMLдляописаниясценариевСодержитмножествомодулей(ихколичествопостояннорастет)Легкописатьсвоимодули

Терминология

Controlmachine—управляющийхост.СерверAnsible,скоторогопроисходитуправлениедругимихостамиManagenode—управляемыехостыInventory—инвентарныйфайл.Вэтомфайлеописываютсяхосты,группыхостов.АтакжемогутбытьсозданыпеременныеPlaybook—файлсценариевPlay—сценарий(наборзадач).Связываетзадачисхостами,длякоторыхэтизадачинадовыполнитьTask—задача.ВызываетмодульсуказаннымипараметрамиипеременнымиModule—модульAnsible.Реализуетопределенныефункции

Списоктерминоввдокументации.

Quickstart

СAnsibleоченьпростоначатьработать.Минимум,которыйнужендляначалаработы:

инвентарныйфайл-внемописываютсяустройстваизменитьконфигурациюAnsible,дляработыссетевымоборудованиемразобратьсясad-hocкомандами-этовозможностьвыполнятьпростыедействиясустройствамиизкоманднойстроки

например,спомощьюad-hocкоманд,можноотправитькомандуshowнанесколькоустройств

ОсновыAnsible

469

Page 470: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Намногобольшевозможностейпоявится,прииспользованииplaybook(файлысценариев).Ноad-hocкомандынамногопрощеначатьиспользовать.ИснимилегченачатьразбиратьсясAnsible.

ОсновыAnsible

470

Page 471: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ИнвентарныйфайлИнвентарныйфайл-этофайл,вкоторомописываютсяустройства,ккоторымAnsibleбудетподключаться.

Хостыигруппы

ВинвентарномфайлеустройствамогутуказыватьсяиспользуяIP-адресаилиимена.Устройствамогутбытьуказаныпоодномуилиразбитынагруппы.

ФайлописываетсявформатеINI.Примерфайла:

r5.example.com

[cisco-routers]

192.168.255.1

192.168.255.2

192.168.255.3

192.168.255.4

[cisco-edge-routers]

192.168.255.1

192.168.255.2

Название,котороеуказановквадратныхскобках-этоназваниегруппы.Вданномслучае,созданыдвегруппыустройств:cisco-routersиcisco-edge-routers.

Обратитевнимание,чтоадреса192.168.255.1и192.168.255.2находятсявдвухгруппах.Этонормальнаяситуация,одинитотжеадресилиимяхоста,можнопомещатьвразныегруппы.

Такимобразомможноприменятьотдельнокакие-тополитикидлягруппыcisco-edge-routers,новтожевремя,когданеобходимонастроитьчто-то,чтокасаетсявсехмаршрутизаторов,можноиспользоватьгруппуcisco-routers.

Поумолчанию,файлнаходитсяв/etc/ansible/hosts.

Номожносоздаватьсвойинвентарныйфайлииспользоватьего.Дляэтогонужно,либоуказатьегопризапускеansible,используяопцию-i<путь>,либоуказатьфайлвконфигурационномфайлеAnsible.

Есликакое-тоизустройствиспользуетнестандартныйпортSSH,портможноуказатьпослеимениилиадресаустройства,черездвоеточие(нижепоказанпример).

Инвентарныйфайл

471

Page 472: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ТакойвариантуказанияпортаработаеттолькосподключениямиOpenSSHинеработаетсparamiko.

Примеринвентарногофайла,сиспользованиемнестандартныхпортовдляSSH:

[cisco-routers]

192.168.255.1:22022

192.168.255.2:22022

192.168.255.3:22022

[cisco-switches]

192.168.254.1

192.168.254.2

Есливгруппунадодобавитьнесколькоустройствсоднотипнымиименами,можноиспользоватьтакойвариантзаписи:

[cisco-routers]

192.168.255.[1-5]

Такаязаписьозначает,чтовгруппупопадутустройствасадресами192.168.255.1-192.168.255.5.

Группаизгрупп

Ansibleтакжепозволяетобъединятьгруппыустройстввобщуюгруппу.Дляэтогоиспользуетсяспециальныйсинтаксис:

[cisco-routers]

192.168.255.1

192.168.255.2

192.168.255.3

[cisco-switches]

192.168.254.1

192.168.254.2

[cisco-devices:children]

cisco-routers

cisco-switches

Инвентарныйфайл

472

Page 473: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

AdHocкоманды

Ad-hocкоманды-этовозможностьзапуститькакое-тодействиеAnsibleизкоманднойстроки.

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

Влюбомслучае,этопростойибыстрыйспособначатьиспользоватьAnsible.

Сначаланужносоздатьвлокальномкаталогеинвентарныйфайл.Назовемегоmyhosts:

[cisco-routers]

192.168.100.1

192.168.100.2

192.168.100.3

[cisco-switches]

192.168.100.100

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

Примерad-hocкоманды:

$ansiblecisco-routers-imyhosts-mraw-a"shipintbr"-ucisco--ask-pass

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

cisco-routers-группаустройств,ккоторымнужноприменитьдействияэтагруппадолжнасуществоватьвинвентарномфайлеэтоможетбытьконкретноеимяилиадресеслинужноуказатьвсехостыизфайла,можноиспользоватьзначениеallили*Ansibleподдерживаетболеесложныевариантыуказанияхостов,срегулярнымивыражениямииразнымишаблонами.Подробнееобэтомвдокументации

-imyhosts-параметр-iпозволяетуказатьинвентарныйфайл

Ad-Hocкоманды

473

Page 474: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

-mraw-a"shipintbr"-параметр-mrawозначает,чтоиспользуетсямодульraw

этотмодульпозволяетотправлятькомандывSSHсессии,ноприэтомнезагружаетнахостмодульPython.Тоесть,этотмодульпростоотправляетуказаннуюкомандукакстрокуивсёплюсмодуляrawвтом,чтоонможетиспользоватьсядлялюбойсистемы,которуюподдерживаетAnsible-a"shipintbr"-параметр-aуказываеткакуюкомандуотправить

-ucisco-подключениевыполняетсяотименипользователяcisco--ask-pass-параметркоторыйнужноуказать,чтобыаутентификациябылапопаролю,анепоключам

Результатвыполнениябудеттаким:

$ansiblecisco-routers-imyhosts-mraw-a"shipintbr"-ucisco--ask-pass

Ошибказначит,чтонужноустановитьпрограммуsshpass.Этаособенностьвозникаеттолькокогдаиспользуетсяаутентификациюпопаролю.

Установкаsshpass:

$sudoapt-getinstallsshpass

Командунадовыполнитьповторно:

$ansiblecisco-routers-imyhosts-mraw-a"shipintbr"-ucisco--ask-pass

Ad-Hocкоманды

474

Page 475: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Теперьвсёпрошлоуспешно.Командавыполниласьиотобразилсявыводскаждогоустройства.

Аналогичнымобразомможнопопробоватьвыполнятьидругиекомандыи/илинадругихкомбинацияхустройств.

Ad-Hocкоманды

475

Page 476: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

КонфигурационныйфайлНастройкиAnsibleможноменятьвконфигурационномфайле.

КонфигурационныйфайлAnsibleможетхранитьсявразныхместах(файлыперечисленывпорядкеуменьшенияприоритетности):

ANSIBLE_CONFIG(переменнаяокружения)ansible.cfg(втекущемкаталоге).ansible.cfg(вдомашнемкаталогепользователя)/etc/ansible/ansible.cfg

Ansibleищетфайлконфигурациивуказанномпорядкеииспользуетпервыйнайденный(конфигурацияизразныхфайловнесовмещается).

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

Втекущемкаталогедолженбытьинвентарныйфайлmyhosts:

[cisco-routers]

192.168.100.1

192.168.100.2

192.168.100.3

[cisco-switches]

192.168.100.100

Втекущемкаталогенадосоздатьтакойконфигурационныйфайлansible.cfg:

[defaults]

inventory=./myhosts

remote_user=cisco

ask_pass=True

Настройкивконфигурационномфайле:

[defaults]-этосекцияконфигурацииописываетобщиепараметрыпоумолчаниюinventory=./myhosts-параметрinventoryпозволяетуказатьместоположениеинвентарногофайла.

Еслинастроитьэтотпараметр,непридетсяуказывать,гденаходитсяфайл,прикаждомзапускеAnsible

Конфигурационныйфайл

476

Page 477: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

remote_user=cisco-отименикакогопользователябудетподключатьсяAnsibleask_pass=True-этотпараметраналогиченопции--ask-passвкоманднойстроке.ЕслионвыставленвконфигурацииAnsible,тоужененужноуказыватьеговкоманднойстроке.

Теперьвызовad-hocкомандыбудетвыглядетьтак:

$ansiblecisco-routers-mraw-a"shipintbr"

Теперьненужноуказыватьинвентарныйфайл,пользователяиопцию--ask-pass.

gathering

Поумолчанию,Ansibleсобираетфактыобустройствах.

Факты-этоинформацияохостах,ккоторымподключаетсяAnsible.Этифактыможноиспользоватьвplaybookишаблонахкакпеременные.

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

Но,длясетевогооборудования,модульsetupнеподходит,поэтомусборфактовнадоотключить.ЭтоможносделатьвконфигурационномфайлеAnsibleиливplaybook.

Длясетевогооборудованиянужноиспользоватьотдельныемодулидлясборафактов(еслиониесть).Эторассматриваетсявразделеios_facts.

Отключениесборафактоввконфигурационномфайле:

gathering=explicit

host_key_checking

Параметрhost_key_checkingотвечаетзапроверкyключей,приподключениипоSSH.Еслиуказатьвконфигурационномфайлеhost_key_checking=False,проверкабудетотключена.

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

Чтобыпроверитьэтотфункционал,надоудалитьсохраненныеключидляустройствCisco,ккоторымужевыполнялосьподкление.

Влинуксонинаходятсявфайле~/.ssh/known_hosts.

Есливыполнитьad-hocкоманду,послеудаленияключей,выводбудеттаким:

Конфигурационныйфайл

477

Page 478: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$ansiblecisco-routers-mraw-a"shipintbr"

Добавляемвконфигурационныйфайлпараметрhost_key_checking:

[defaults]

inventory=./myhosts

remote_user=cisco

ask_pass=True

host_key_checking=False

Иповторимad-hocкоманду:

$ansiblecisco-routers-mraw-a"shipintbr"

Конфигурационныйфайл

478

Page 479: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Warning:Permanentlyadded'192.168.100.1'(RSA)tothelistofknownhosts.

Ansibleсамдобавилключиустройстввфайл~/.ssh/known_hosts.Приподключениивследующийразэтогосообщенияуженебудет.

Другиепараметрыконфигурационногофайламожнопосмотретьвдокументации.ПримерконфигурационногофайлаврепозиторииAnsible.

Конфигурационныйфайл

479

Page 480: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Конфигурационныйфайл

480

Page 481: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодулиAnsibleВместесустановкойAnsibleустанавливаетсятакжебольшоеколичествомодулей(библиотекамодулей).Втекущейбиблиотекемодулей,находитсяпорядка200модулей.

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

Модулиможновыполнятьотдельно,вad-hocкомандахилисобиратьвопределенныйсценарий(play),азатемвplaybook.

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

Например,мыужевыполнялиad-hocкоманды,используямодульraw.Ипередавалиемуаргументы:

$ansiblecisco-routers-imyhosts-mraw-a"shipintbr"-ucisco--ask-pass

Выполнениетакойжезадачивplaybookбудетвыглядетьтак(playbookрассматриваетсявследующемразделе):

-name:runshipintbr

raw:shipintbr|exunass

Послевыполнения,модульвозвращаетрезультатывыполнениявформатеJSON.

МодулиAnsible,какправило,идемпотентны.Этоозначает,чтомодульможновыполнятьсколькоугоднораз,ноприэтоммодульбудетвыполнятьизменения,толькоеслисистеманенаходитсявжелаемомсостоянии.

ВAnsibleмодулиразделенынадвекатегории:

core-этомодули,которыевсегдаустанавливаютсявместесAnible.ИхподдерживаетосновнаякомандаразработчиковAnsible.extra-этомодулинаданныймоментустанавливаютсясAnsible,нонетгарантии,чтоониидальшебудутустанавливатьсясAnsible.Возможно,вбудущем,ихнужнобудетустанавливатьотдельно.Большинствоэтихмодулейподдерживаютсясообществом.

Модули

481

Page 482: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ТакжевAnsibleмодулиразделеныпофункциональности.Списоквсехкатегорийнаходитсявдокументации.

Модули

482

Page 483: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ОсновыplaybooksPlaybook(файлсценариев)—этофайлвкоторомописываютсядействия,которыенужновыполнитьнакакой-тогруппехостов.

Внутриplaybook:

play-этонаборзадач,которыенужновыполнитьдлягруппыхостовtask-этоконкретнаязадача.Взадачеесть,какминимум:

описание(названиезадачиможнонеписать,нооченьрекомендуется)модульикоманда(действиевмодуле)

СинтаксисplaybookPlaybookописываютсявформатеYAML.

СинтаксисYAMLописанвразделеYAMLиливдокументацииAnsible.

Примерсинтаксисаplaybook

Всепримерыэтогоразделанаходятсявкаталоге2_playbook_basics

Примерplabook1_show_commands_with_raw.yml:

Основыplaybook

483

Page 484: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:Runshowcommandsonrouters

hosts:cisco-routers

gather_facts:false

tasks:

-name:runshipintbr

raw:shipintbr|exunass

-name:runshiproute

raw:shiproute

-name:Runshowcommandsonswitches

hosts:cisco-switches

gather_facts:false

tasks:

-name:runshintstatus

raw:shintstatus

-name:runshvlan

raw:showvlan

Вplaybookдвасценария(play):

name:Runshowcommandsonrouters-имясценария(play).Этотпараметробязательнодолженбытьвлюбомсценарииhosts:cisco-routers-сценарийбудетприменятьсякустройствамвгруппеcisco-routers

тутможетбытьуказаноинесколькогрупп,например,такимобразом:hosts:cisco-routers:cisco-switches.Подробнее,вдокументации

обычно,вplayнадоуказыватьпараметрremote_user.Но,таккакмыуказалиеговконфигурационномфайлеAnsible,можнонеуказыватьеговplay.gather_facts:false-отключениесборафактовобустройстве,таккакдлясетевогооборудованиянадоиспользоватьотдельныемодулидлясборафактов.

вразделеконфигурационныйфайлрассматривалоськакотключитьсборфактовпоумолчанию.Еслионотключен,топараметрgather_factsвplayненужноуказывать.

tasks:-дальшеидетпереченьзадачвкаждойзадаченастроеноимя(опционально)идействие.Действиеможетбытьтолькоодно.вдействииуказываетсякакоймодульиспользоватьипараметрымодуля.

Основыplaybook

484

Page 485: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Итотжеplaybookсотображениемэлементов:

Таквыглядитвыполнениеplaybook:

$ansible-playbook1_show_commands_with_raw.yml

Основыplaybook

485

Page 486: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Обратитевнимание,чтодлязапускаplaybookиспользуетсядругаякоманда.Дляad-hocкоманды,использоваласькомандаansible.Адляplaybook-ansible-playbook.

Длятого,чтобыубедиться,чтокоманды,которыеуказанывзадачах,выполнилисьнаустройствах,запуститеplaybookсопцией-v(выводсокращен):

$ansible-playbook1_show_commands_with_raw.yml-v

Основыplaybook

486

Page 487: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Вследующихразделахмынаучимсяотображатьэтиданныевнормальномформатеипосмотрим,чтоснимиможноделать.

Порядоквыполнениязадачисценариев

Сценарии(play)изадачи(task)выполняютсяпоследовательно,втомпорядке,вкоторомониописанывplaybook.

Есливсценарии,например,двезадачи,тосначалаперваязадачадолжнабытьвыполненадлявсехустройств,которыеуказанывпараметреhosts.Толькопослетого,какперваязадачабылавыполненадлявсеххостов,начинаетсявыполнениевторойзадачи.

Есливходевыполненияplaybook,возниклаошибкавзадаченакаком-тоустройстве,этоустройствоисключается,идругиезадачинанемвыполнятьсянебудут.

Например,заменимпарольпользователяciscoнаcisco123(правильныйcisco)намаршрутизаторе192.168.100.1,изапустимplaybookзаново:

$ansible-playbook1_show_commands_with_raw.yml

Основыplaybook

487

Page 488: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Обратитевниманиенаошибкуввыполнениипервойзадачидлямаршрутизатора192.168.100.1.

Вовторойзадаче'TASK[runshiproute]',Ansibleужеисключилмаршрутизаторивыполняетзадачутолькодлямаршрутизаторов192.168.100.2и192.168.100.3.

Ещеодинважныйаспект-Ansibleвыдалсообщение:

toretry,use:--limit@/home/nata/pyneng_course/chapter15/1_show_commands_with_raw.re

try

Если,привыполненииplaybook,накаком-тоустройствевозниклаошибка,Ansibleсоздаетспециальныйфайл,которыйназываетсяточнотакжекакplaybook,норасширениеменяетсянаretry.(Есливывыполняетезаданияпараллельно,тоэтотфайлдолженпоявитьсяувас)

Вэтомфайлехранитсяимяилиадресустройстванакоторомвозниклаошибка.Таквыглядитфайл1_show_commands_with_raw.retryсейчас:

192.168.100.1

Создаетсяэтотфайлдлятого,чтобыможнобылоперезапуститьplaybookзановотолькодляпроблемногоустройства(устройств).Тоесть,надоисправитьпроблемусустройством,изановозапуститьplaybook.

Настраиваемправильныйпарольнамаршрутизаторе192.168.100.1,азатемперезапускаемplaybookтакимобразом:

$ansible-playbook1_show_commands_with_raw.yml--limit@/home/nata/pyneng_course/chap

ter15/1_show_commands_with_raw.retry

Ansibleвзялсписокустройств,которыеперечисленывфайлеretryивыполнилplaybookтолькодляних.

Основыplaybook

488

Page 489: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Можнобылозапуститьplaybookитак(тоесть,писатьнеполныйпутькфайлуretry):

$ansible-playbook1_show_commands_with_raw.yml--limit@1_show_commands_with_raw.retr

y

Параметр--limitоченьполезнаявещь.Онпозволяетограничивать,длякакиххостовилигруппбудетвыполнятьсяplaybook,приэтом,неменяясамplaybook.

Например,такимобразомplaybookможнозапуститьтолькодлямаршрутизатора192.168.100.1:

$ansible-playbook1_show_commands_with_raw.yml--limit192.168.100.1

Идемпотентность

МодулиAnsibleидемпотентны.Этоозначает,чтомодульможновыполнятьсколькоугоднораз,ноприэтоммодульбудетвыполнятьизменения,толькоеслисистеманенаходитсявжелаемомсостоянии.

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

Но,если,например,взадачеуказано,чтонасерверLinuxнадоустановитьпакетhttpd,тоонбудетустановлентольковтомслучае,еслиегонет.Тоесть,действиенебудетповторятьсясноваиснова,прикаждомзапуске.Алишьтогда,когдапакетанет.

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

Основыplaybook

489

Page 490: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПеременныеПеременнойможетбыть,например:

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

ИменапеременныхВAnsibleестьопределенныеограниченияпоформатуименпеременных:

Переменныемогутсостоятьизбукв,чиселисимвола_Переменныедолжныначинатьсясбуквы

Крометого,можносоздаватьсловариспеременными(вформатеYAML):

R1:

IP:10.1.1.1/24

DG:10.1.1.100

Обращатьсякпеременнымвсловареможнодвумявариантами:

R1['IP']

R1.IP

Правда,прииспользованиивтороговарианта,могутбытьпроблемы,еслиназваниеключасовпадаетсзарезервированнымсловом(методомилиатрибутом)вPythonилиAnsible.

ГдеможноопределятьпеременныеПеременныеможносоздавать:

винвентарномфайлевplaybookвспециальныхфайлахдлягруппы/устройствавотдельныхфайлах,которыедобавляютсявplaybookчерезinclude(каквJinja2)

Переменные

490

Page 491: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

вролях,которыезатемиспользуютсяможнодажепередаватьпеременныепривызовеplaybook

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

Переменныевинвентарномфайле

Винвентарномфайлеможноуказыватьпеременныедлягруппы:

[cisco-routers]

192.168.100.1

192.168.100.2

192.168.100.3

[cisco-switches]

192.168.100.100

[cisco-routers:vars]

ntp_server=192.168.255.100

log_server=10.255.100.1

Переменыеntp_serverиlog_serverотносятсякгруппеcisco-routersимогутиспользоваться,например,пригенерацииконфигурации,наосновешаблона.

Переменныевplaybook

Переменныеможнозадаватьпрямовplaybook.Этоможетбытьудобнотем,чтопеременныенаходятсятамже,гдевседействия.

Например,можнозадатьпеременныеntp_serverиlog_serverвplaybookтакимобразом:

Переменные

491

Page 492: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:Runshowcommandsonrouters

hosts:cisco-routers

gather_facts:false

vars:

ntp_server:192.168.255.100

log_server:10.255.100.1

tasks:

-name:runshipintbr

raw:shipintbr|exunass

-name:runshiproute

raw:shiproute

Переменныевспециальныхфайлахдлягруппы/устройства

Ansibleпозволяетхранитьпеременныедлягруппы/устройствавспециальныхфайлах:

Длягруппустройств,переменныедолжнынаходитьсявкаталогеgroup_vars,вфайлах,которыеназываются,какимягруппы.

Крометого,можносоздаватьвкаталогеgroup_varsфайлall,вкоторомбудутнаходитьсяпеременные,которыеотносятсяковсемгруппам.

Дляконкретныхустройств,переменныедолжнынаходитьсявкаталогеhost_vars,вфайлах,которыесоответствуютимениилиадресухоста.Всефайлыспеременными,должныбытьвформатеYAML.Расширениефайламожетбытьтаким:yml,yaml,jsonилибезрасширениякаталогиgroup_varsиhost_varsдолжнынаходитьсявтомжекаталоге,чтоиplaybook.Илимогутнаходитьсявнутрикаталогаinventory(первыйвариантболеераспространенный).

есликаталогиифайлыназваныправильноирасположенывуказанныхкаталогах,Ansibleсамразпознаетфайлыибудетиспользоватьпеременные

Например,еслиинвентарныйфайлmyhostsвыглядиттак:

Переменные

492

Page 493: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

[cisco-routers]

192.168.100.1

192.168.100.2

192.168.100.3

[cisco-switches]

192.168.100.100

Можносоздатьтакуюструктурукаталогов:

├──group_vars_

│├──all.yml|

│├──cisco-routers.yml|Каталогспеременнымидлягруппустройств

│└──cisco-switches.yml_|

|

├──host_vars_

│├──192.168.100.1|

│├──192.168.100.2|

│├──192.168.100.3|Каталогспеременнымидляустройств

│└──192.168.100.100_|

|

└──myhosts|Инвентарныйфайл

Нижепримерсодержимогофайловпеременныхдлягруппустройствидляотдельныххостов.

group_vars/all.yml(вэтомфайлеуказываютсязначенияпоумолчанию,которыеотносятсяковсемустройствам):

---

cli:

host:"{{inventory_hostname}}"

username:"cisco"

password:"cisco"

transport:cli

authorize:yes

auth_pass:"cisco"

Вданномслучае,указываютсяпеременные,которыепредопределенысамимAnsible.

Вфайлеgroup_vars/all.ymlсоздансловарьcli.Вэтомсловареперечисленытеаргументы,которыедолжнызадаватьсядляработыссетевымоборудованиемчерезвстроенныемодулиAnsible(рассматриваетсявразделесетевыемодули)

Интересныймоментвэтомфайле-переменнаяhost:"{{inventory_hostname}}":

Переменные

493

Page 494: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

inventory_hostname-этоспециальнаяпеременная,котораяуказываетнатотхост,длякоторогоAnsibleвыполняетдействия.синтаксис{{inventory_hostname}}-этоподстановкапеременных.ИспользуетсяформатJinja

group_vars/cisco-routers.yml

---

log_server:10.255.100.1

ntp_server:10.255.100.1

users:

user1:pass1

user2:pass2

user3:pass3

Вфайлеgroup_vars/cisco-routers.ymlнаходятсяпеременные,которыеуказываютIP-адресLogиNTPсерверовинесколькихпользователей.Этипеременныемогутиспользоваться,например,вшаблонахконфигурации.

group_vars/cisco-switches.yml

---

vlans:

-10

-20

-30

Вфайлеgroup_vars/cisco-switches.ymlуказанапеременнуаяvlansсоспискомVLANов.

Файлыспеременнымидляхостоводнотипныивнихменяютсятолькоадресаиимена:

Файлhost_vars/192.168.100.1

---

hostname:london_r1

mgmnt_loopback:100

mgmnt_ip:10.0.0.1

ospf_ints:

-192.168.100.1

-10.0.0.1

-10.255.1.1

Переменные

494

Page 495: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Файлhost_vars/192.168.100.2

---

hostname:london_r2

mgmnt_loopback:100

mgmnt_ip:10.0.0.2

ospf_ints:

-192.168.100.2

-10.0.0.2

-10.255.2.2

Файлhost_vars/192.168.100.3

---

hostname:london_r3

mgmnt_loopback:100

mgmnt_ip:10.0.0.3

ospf_ints:

-192.168.100.3

-10.0.0.3

-10.255.3.3

Файлhost_vars/192.168.100.100

---

hostname:london_sw1

mgmnt_int:VLAN100

mgmnt_ip:10.0.0.100

ПриоритетностьпеременныхВэтомразделенерассматриваетсяразмещениепеременных:

вотдельныхфайлах,которыедобавляютсявplaybookчерезinclude(каквJinja2)вролях,которыезатемиспользуютсяпередачапеременныхпривызовеplaybook

ЭторассматриваетсявкурсеAnsibleдлясетевыхинженеров

Переменные

495

Page 496: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Приоритетпеременных(последниезначенияпереписываютпредыдущие):

Значенияпеременныхвроляхзадачивроляхбудутвидетьсобственныезначения.Задачи,которыеопределенывнероли,будутвидетьпоследниезначенияпеременныхроли

переменныевинвентарномфайлепеременныедлягруппыхостоввинвентарномфайлепеременныедляхостоввинвентарномфайлепеременныевкаталогеgroup_varsпеременныевкаталогеhost_varsфактыхостапеременныесценария(play)переменныесценария,которыезапрашиваютсячерезvars_promptпеременные,которыепередаютсявсценарийчерезvars_filesпеременныеполученныечерезпараметрregisterset_factsпеременныеизролиипомещенныечерезincludeпеременныеблока(переписываютдругиезначениятолькодляблока)переменныезадачи(task)(переписываютдругиезначениятолькодлязадачи)переменные,которыепередаютсяпривызовеplaybookчерезпараметр--extra-vars(всегданаиболееприоритетные)

Переменные

496

Page 497: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Примерыиспользуютмодульraw,ноаналогичныепринципыработаютисдругимимодулями.

verbose

Впредыдущихразделах,одинизспособовотобразитьрезультатвыполнениякоманд,ужеиспользовался-флагverbose.

Конечно,выводнеоченьудобночитать,но,какминимум,онпозволяетувидеть,чтокомандывыполнились.ТакжеэтотфлагпозволяетподробнопосмотретькакиешагивыполняетAnsible.

Примерзапускаplaybookсфлагомverbose(выводсокращен):

ansible-playbook1_show_commands_with_raw.yml-v

Приувеличенииколичествабуквvвфлаге,выводстановитсяболееподробным.Попробуйтевызыватьэтотжеplaybookидобавлятькфлагубуквыv(5ибольшепоказываютодинаковыйвывод),такимобразом:

ansible-playbook1_show_commands_with_raw.yml-vvv

Ввыводевиднырезультатывыполнениязадачи,онивозвращаютсявформатеJSON:

Результатвыполнениямодуля

497

Page 498: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

changed-ключ,которыйуказываетбылиливнесеныизмененияrc-returncode.Этополепоявляетсяввыводетехмодулей,которыевыполняюткакие-токомандыstderr-ошибки,привыполнениикоманды.Этополепоявляетсяввыводетехмодулей,которыевыполняюткакие-токомандыstdout-выводкомандыstdout_lines-выводввидеспискакоманд,разбитыхпострочно

register

Параметрregisterсохраняетрезультатвыполнениямодулявпеременную.Затемэтапеременнаяможетиспользоватьсявшаблонах,впринятиирешенийоходесценарияилидляотображениявывода.

Попробуемсохранитьрезультатвыполнениякоманды.

Вplaybook2_register_vars.yml,спомощьюregister,выводкомандыshipintbrсохраненвпеременнуюsh_ip_int_br_result:

---

-name:Runshowcommandsonrouters

hosts:cisco-routers

gather_facts:false

tasks:

-name:runshipintbr

raw:shipintbr|exunass

register:sh_ip_int_br_result

Еслизапуститьэтотplaybook,выводнебудетотличаться,таккаквыводтолькозаписанвпеременную,носпеременнойневыполяетсяникакихдействий.Следующийшаг-отобразитьрезультатвыполнениякоманды,спомощьюмодуляdebug.

debug

Модульdebugпозволяетотображатьинформациюнастандартныйпотоквывода.Этоможетбытьпроизвольнаястрока,переменная,фактыобустройстве.

Дляотображениясохраненныхрезультатоввыполнениякоманды,вplaybook2_register_vars.ymlдобавленазадачасмодулемdebug:

Результатвыполнениямодуля

498

Page 499: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:Runshowcommandsonrouters

hosts:cisco-routers

gather_facts:false

tasks:

-name:runshipintbr

raw:shipintbr|exunass

register:sh_ip_int_br_result

-name:Debugregisteredvar

debug:var=sh_ip_int_br_result.stdout_lines

Обратитевнимание,чтовыводитсяневсёсодержимоепеременнойsh_ip_int_br_result,атолькосодержимоеstdout_lines.Вsh_ip_int_br_result.stdout_linesнаходитсясписокстрок,поэтомувыводбудутструктурирован.

Результатзапускаplaybookвыглядиттак:

$ansible-playbook2_register_vars.yml

Результатвыполнениямодуля

499

Page 500: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

register,debug,when

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

whenвAnsibleиспользуетсякакifвPython.

Примерplaybook3_register_debug_when.yml:

Результатвыполнениямодуля

500

Page 501: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:Runshowcommandsonrouters

hosts:cisco-routers

gather_facts:false

tasks:

-name:runshipintbr

raw:shipintbri|exunass

register:sh_ip_int_br_result

-name:Debugregisteredvar

debug:

msg:"Errorincommand"

when:"'invalid'insh_ip_int_br_result.stdout"

Впоследнемзаданиинесколькоизменений:

модульdebugотображаетнесодержимоесохраненнойпеременной,асообщение,котороеуказановпеременнойmsg.условиеwhenуказывает,чтоданнаязадачавыполнитсятолькопривыполненииусловия

when:"'invalid'insh_ip_int_br_result.stdout"-этоусловиеозначает,чтозадачабудетвыполненатольковтомслучае,есливвыводеsh_ip_int_br_result.stdoutбудетнайденастрокаinvalid(например,когданеправильновведенакоманда)

Модули,которыеработаютссетевымоборудованием,автоматическипроверяютошибки,привыполнениикоманд.ТутэтотпримериспользуетсядлядемонстрациивозможностейAnsible.

Выполнениеplaybook:

$ansible-playbook3_register_debug_when.yml

Результатвыполнениямодуля

501

Page 502: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Обратитевниманиенасообщенияskipping-этоозначает,чтозадачаневыполняласьдляуказанныхустройств.Невыполниласьонапотому,чтоусловиевwhenнебыловыполнено.

Выполнениетогожеplaybook,носошибкойвкоманде:

---

-name:Runshowcommandsonrouters

hosts:cisco-routers

gather_facts:false

tasks:

-name:runshipintbr

raw:shhipintbri|exunass

register:sh_ip_int_br_result

-name:Debugregisteredvar

debug:

msg:"Errorincommand"

when:"'invalid'insh_ip_int_br_result.stdout"

Теперьрезультатвыполнениятакой:

$ansible-playbook3_register_debug_when.yml

Результатвыполнениямодуля

502

Page 503: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Таккаккомандабыласошибкой,сработалоусловие,котороеописановwhenизадачавывеласообщение,спомощьюмодуляdebug.

Результатвыполнениямодуля

503

Page 504: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодулидляработыссетевымоборудованиемВпредыдущихразделахдляотправкикоманднаоборудование,использовалсямодульraw.Онуниверсаленисегопомощьюможноотправлятькомандыналюбоеустройство.

Вэтомразделе,рассматриваютсямодули,которыеработаютссетевымоборудованием.

Глобально,модулидляработыссетевымоборудованием,можноразделитьнадвечасти:

модулидляоборудованиясподдержкойAPIмодулидляоборудования,котороеработаеттолькочерезCLI

ЕслиоборудованиеподдерживаетAPI,какнапример,NXOS,тодлянегосозданобольшоеколичествомодулей,которыевыполняютконкретныедействия,понастройкефункционала(например,дляNXOSсозданоболее60модулей).

Дляоборудования,котороеработаеттолькочерезCLI,Ansibleподдерживаеттакиетритипамодулей:

os_command-выполняеткомандыshowos_facts-собираетфактыобустройствахos_config-выполняеткомандыконфигурации

Соответственно,дляразныхоперационныхсистем,будутразныемодули.Например,дляCiscoIOS,модулибудутназываться:

ios_commandios_configios_facts

АналогичныетримодулядоступныдлятакихОС:

Dellos10Dellos6Dellos9EOSIOSIOSXRJUNOS

Сетевыемодули

504

Page 505: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

SROSVyOS

Полныйсписоквсехсетевыхмодулей,которыеподдерживаетAnsibleвдокументации.

Обратитевнимание,чтоAnsibleоченьактивноразвиваетсявсторонуподдержкиработыссетевымоборудованием,ивследующейверсииAnsible,могутбытьдополнительныемодули.Поэтому,еслинамоментчтениякурса,ужеестьследующаястабильнаяверсияAnsible(версиявкурсе2.2),используйтееёипосмотритевдокументации,какиеновыевозможностиимодулипоявились.

Вкурсе,всерассматриваетсянапримеремодулейдляработысCiscoIOS:

ios_commandios_configios_facts

Аналогичныемодулиcommand,configиfactsдлядругихвендоровиОСработаютодинаково,поэтому,еслиразобратьсякакработатьсмодулямидляIOS,состальнымивсёбудетаналогично.

Крометого,вкурсерассматриваетсямодульntc-ansible,которыйневходитвcoreмодулиAnsible.

Вариантыподключения

Ansibleподдерживаеттакиетипыподключений:

paramikoSSH-OpenSSH.Используетсяпоумолчаниюlocal-действиявыполняютсялокально,науправляющемхосте

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

Поумолчанию,AnsibleзагружаетмодульPythonнаустройство,длятого,чтобывыполнитьдействия.ЕслижеоборудованиенеподдерживаетPython,каквслучаесдоступомксетевомуоборудованиючерезCLI,нужноуказать,чтомодульдолжензапускатьсялокально,науправляющемхостеAnsible.

Особенностиподключенияксетевомуоборудованию

Приработессетевымоборудованием,естьнесколькопараметроввplaybook,которыенужноменять:

Сетевыемодули

505

Page 506: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

gather_facts-надоотключить,таккакдлясетевогооборудованияиспользуютсясвоимодулисборафактовconnection-управляеттем,какименнобудетпроисходитьподключение.Длясетевогооборудованиянеобходимоустановитьвlocal

Тоесть,длякаждогосценария(play),нужноуказывать:

gather_facts:falseconnection:local

Пример:

---

-name:Runshowcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

ВAnsibleпеременныеможноуказыватьвразныхместах,поэтомутеженастройкиможноуказатьпо-другому.

Например,вразделеоконфигурационномфайлерассматривалоськакотключитьсборфактовпоумолчанию(файлansible.cfg):

[defaults]

gathering=explicit

Такойвариантподходитвтомслучае,когдаAnsibleиспользуетсябольшедляподключенияксетевымустройствам(или,локальныеplaybookиспользуютсядляподключенияксетевомуоборудованию).

Втакомслучае,нужнобудетнаоборотявновключатьсборфактов,еслионнужен.

Указать,чтонужноиспользоватьлокальноеподключение,такжеможнопо-разному.

Винвентарномфайле:

Сетевыемодули

506

Page 507: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

[cisco-routers]

192.168.100.1

192.168.100.2

192.168.100.3

[cisco-switches]

192.168.100.100

[cisco-routers:vars]

ansible_connection=local

Иливфайлахпеременных,например,вgroup_vars/all.yml:

---

ansible_connection:local

Вследующихразделахбудетиспользоватьсятакойвариант:

---

-name:Runshowcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

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

Аргументprovider

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

Длякаждойзадачидолжныбытьуказанытакиеаргументы:

host-имяилиIP-адресудаленногоустройстваport-ккакомупортуподключатьсяusername-имяпользователяpassword-парольtransport-типподключения:CLIилиAPI.Поумолчанию-cliauthorize-нужнолипереходитьвпривилегированныйрежим(enable,дляCisco)auth_pass-парольдляпривилегированногорежима

ЕслидляподключенияAnsibleсозданотдельныйпользовательсprivilege15,можнонеиспользоватьпараметрыauthorizeиauth_pass.

Сетевыемодули

507

Page 508: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Но,Ansibleтакжепозволяетсобратьихводинаргумент-provider.

Примерзаданиявсехаргументоввзадаче(task):

tasks:

-name:runshowversion

ios_command:

commands:showversion

host:"{{inventory_hostname}}"

username:cisco

password:cisco

transport:cli

Аргументысозданыкакпеременнаяcliвplaybook,азатемпередаютсякакпеременнаяаргументуprovider:

vars:

cli:

host:"{{inventory_hostname}}"

username:cisco

password:cisco

transport:cli

tasks:

-name:runshowversion

ios_command:

commands:showversion

provider:"{{cli}}"

И,самыйудобныйвариант,задаватьаргументывкаталогеgroup_vars.

Например,еслиувсехустройстводинаковыезначенияаргументов,можнозадатьихвфайлеgroup_vars/all.yml:

---

cli:

host:"{{inventory_hostname}}"

username:cisco

password:cisco

transport:cli

authorize:yes

auth_pass:cisco

Затемпеременнаяиспользуетсявplaybookтакже,какивслучаеуказанияпеременныхвplaybook:

Сетевыемодули

508

Page 509: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

tasks:

-name:runshowversion

ios_command:

commands:showversion

provider:"{{cli}}"

Крометого,Ansibleподдерживаетзаданиепараметроввпеременныхокружения:

ANSIBLE_NET_USERNAME-дляпеременнойusernameANSIBLE_NET_PASSWORD-passwordANSIBLE_NET_SSH_KEYFILE-ssh_keyfileANSIBLE_NET_AUTHORIZE-authorizeANSIBLE_NET_AUTH_PASS-auth_pass

Приоритетностьзначенийвпорядкевозрастанияприоритетности:

значенияпоумолчаниюзначенияпеременныхокруженияпараметрproviderаргументызадачи(task)

Подготовкакработессетевымимодулями

Вследующихразделахрассматриваетсяработасмодулямиios_command,ios_factsиios_config.Длятого,чтобывсепримерыplaybookработали,надосоздатьнесколькофайлов(проверить,чтоониесть).

Инвентарныйфайлmyhosts:

[cisco-routers]

192.168.100.1

192.168.100.2

192.168.100.3

[cisco-switches]

192.168.100.100

Конфигурационныйфайлansible.cfg:

[defaults]

inventory=./myhosts

remote_user=cisco

ask_pass=True

Сетевыемодули

509

Page 510: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Вфайлеgroup_vars/all.ymlнадосоздатьпеременнуюcli,чтобынеуказыватькаждыйразвсепараметры,которыенужнопередатьаргументуprovider:

---

cli:

host:"{{inventory_hostname}}"

username:"cisco"

password:"cisco"

transport:cli

authorize:yes

auth_pass:"cisco"

Сетевыемодули

510

Page 511: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Модульios_commandМодульios_command-отправляеткомандуshowнаустройствоподуправлениемIOSивозвращаетрезультатвыполнениякоманды.

Модульios_commandнеподдерживаетотправкукомандвконфигурационномрежиме.Дляэтогоиспользуетсяотдельныймодуль-ios_config.

Передотправкойсамойкоманды,модуль:

выполняетаутентификациюпоSSH,переходитврежимenableвыполняеткомандуterminallength0,чтобывыводкомандshowотражалсяполностью,анепостранично.

Примериспользованиямодуляios_command(playbook1_ios_command.yml):

---

-name:Runshowcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:runshipintbr

ios_command:

commands:showipintbr

provider:"{{cli}}"

register:sh_ip_int_br_result

-name:Debugregisteredvar

debug:var=sh_ip_int_br_result.stdout_lines

Модульios_commandожидаетпараметры:

commands-списоккоманд,которыенужноотправитьнаустройствоprovider-словарьспараметрамиподключения

внашемслучае,онуказанвфайлеgroup_vars/all.yml

Обратитевнимание,чтопараметрregisterнаходитсянаодномуровнесименемзадачиимодулем,аненауровнепараметровмодуляios_command.

ios_command

511

Page 512: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Результатвыполненияplaybook:

$ansible-playbook1_ios_command.yml

Вотличиеотиспользованиямодуляraw,playbookнеуказывает,чтобыливыполненыизменения.

Выполнениенесколькихкоманд

ios_command

512

Page 513: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Модульios_commandпозволяетвыполнятьнесколькокоманд.

Playbook2_ios_command.ymlвыполняетнесколькокомандиполучаетихвывод:

---

-name:Runshowcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:runshowcommands

ios_command:

commands:

-showipintbr

-shiproute

provider:"{{cli}}"

register:show_result

-name:Debugregisteredvar

debug:var=show_result.stdout_lines

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

Результатвыполненияplaybook(выводсокращен):

$ansible-playbook2_ios_command.yml

ios_command

513

Page 514: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Обекомандывыполнилисьнавсехустройствах.

Еслимодулюпередаютсянесколькокоманд,результатвыполнениякоманднаходитсявпеременныхstdoutиstdout_linesвсписке.Выводбудетвтомпорядке,вкоторомкомандыописанывзадаче.

Засчетэтого,например,можновывестирезультатвыполненияпервойкоманды,указав:

-name:Debugregisteredvar

debug:var=show_result.stdout_lines[0]

Обработкаошибок

ios_command

514

Page 515: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Например,еслисделатьошибкувкоманде,изапуститьplaybookещераз

$ansible-playbook2_ios_command.yml

Ansibleобнаружилошибкуивозвращаетсообщениеошибки.Вданномслучае-'Invalidinput'.

Аналогичнымобразоммодульобнаруживаетошибки:

AmbiguouscommandIncompletecommand

ios_command

515

Page 516: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Модульios_factsМодульios_facts-собираетинформациюсустройствподуправлениемIOS.

Информацияберетсяизтакихкоманд:

dirshowversionshowmemorystatisticsshowinterfacesshowipv6interfaceshowlldpshowlldpneighborsdetailshowrunning-config

Длятого,чтобывидетькакиекомандыAnsibleвыполняетнаоборудовании,можнонастроитьEEMapplet,которыйбудетгенерироватьлогсообщенияовыполненныхкомандах.

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

Какуюинформациюсобирать,указываетсявпараметреgather_subset.Поддерживаютсятакиеварианты(указанытакжекоманды,которыебудутвыполнятьсянаустройстве):

allhardware

dirshowversionshowmemorystatistics

configshowversionshowrunning-config

interfacesdirshowversionshowinterfacesshowipv6interfaceshowlldp

ios_facts

516

Page 517: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

showlldpneighborsdetail

Собратьвсефакты:

-ios_facts:

gather_subset:all

provider:"{{cli}}"

Собратьтолькоподмножествоinterfaces:

-ios_facts:

gather_subset:

-interfaces

provider:"{{cli}}"

Собратьвсё,кромеhardware:

-ios_facts:

gather_subset:

-"!hardware"

provider:"{{cli}}"

Ansibleсобираеттакиефакты:

ansible_net_all_ipv4_addresses-списокIPv4адресовнаустройствеansible_net_all_ipv6_addresses-списокIPv6адресовнаустройствеansible_net_config-конфигурация(дляCiscoshrun)ansible_net_filesystems-файловаясистемаустройстваansible_net_gather_subset-какаяинформациясобирается(hardware,default,interfaces,config)ansible_net_hostname-имяустройстваansible_net_image-имяипутьОСansible_net_interfaces-словарьсовсемиинтерфейсамиустройства.Именаинтерфейсов-ключи,аданные-параметрыкаждогоинтерфейсаansible_net_memfree_mb-сколькосвободнойпамятинаустройствеansible_net_memtotal_mb-сколькопамятинаустройствеansible_net_model-модельустройстваansible_net_serialnum-серийныйномерansible_net_version-версияIOS

Использованиемодуля

ios_facts

517

Page 518: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Примерplaybook1_ios_facts.ymlсиспользованиеммодуляios_facts(собираютсявсефакты):

---

-name:CollectIOSfacts

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Facts

ios_facts:

gather_subset:all

provider:"{{cli}}"

$ansible-playbook1_ios_facts.yml

Длятого,чтобыпосмотреть,какиеименнофактысобираютсясустройства,можнодобавитьфлаг-v(информациясокращена):

$ansible-playbook1_ios_facts.yml-v

Using/home/nata/pyneng_course/chapter15/ansible.cfgasconfigfile

ios_facts

518

Page 519: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Послетого,какAnsibleсобралфактысустройства,всефактыдоступныкакпеременныевplaybook,шаблонахит.д.

Например,можноотобразитьсодержимоефактаспомощьюdebug(playbook2_ios_facts_debug.yml):

---

-name:CollectIOSfacts

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:Facts

ios_facts:

gather_subset:all

provider:"{{cli}}"

-name:Showansible_net_all_ipv4_addressesfact

debug:var=ansible_net_all_ipv4_addresses

-name:Showansible_net_interfacesfact

debug:var=ansible_net_interfaces['Ethernet0/0']

Результатвыполненияplaybook:

$ansible-playbook2_ios_facts_debug.yml

ios_facts

519

Page 520: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Сохранениефактов

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

Дляэтогобудетиспользоватьсямодульcopy.

Playbook3_ios_facts.ymlсобираетвсюинформациюобустройствахизаписываетвразныефайлы(создайтекаталогall_factsпередзапускомplaybookилираскомментируйтезадачуCreateall_factsdirиAnsibleсоздасткаталогсам):

ios_facts

520

Page 521: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:CollectIOSfacts

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Facts

ios_facts:

gather_subset:all

provider:"{{cli}}"

register:ios_facts_result

#-name:Createall_factsdir

#file:

#path:./all_facts/

#state:directory

#mode:0755

-name:Copyfactstofiles

copy:

content:"{{ios_facts_result|to_nice_json}}"

dest:"all_facts/{{inventory_hostname}}_facts.json"

Модульcopyпозволяеткопироватьфайлысуправляющегохоста(накоторомустановленAnsible)наудаленныйхост.Но,таккаквэтомслучае,указанпараметрconnection:local,файлыбудутскопированыналокальныйхост.

Чащевсего,модульcopyиспользуетсятакимобразом:

-copy:

src:/srv/myfiles/foo.conf

dest:/etc/foo.conf

Но,вданномслучае,нетисходногофайла,содержимоекоторогонужноскопировать.Вместоэтого,естьсодержимоепеременнойios_facts_result,котороенужноперенестивфайлall_facts/{{inventory_hostname}}_facts.json.

Длятогочтобыперенестисодержимоепеременнойвфайл,вмодулеcopy,вместоsrc,используетсяпараметрcontent.

Встрокеcontent:"{{ios_facts_result|to_nice_json}}"

параметрto_nice_json-этофильтрJinja2,которыйпреобразуетинформациюпеременнойвформат,вкоторомудобнейчитатьинформациюпеременнаявформатеJinja2должнабытьзаключенавдвойныефигурные

ios_facts

521

Page 522: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

скобки,атакжеуказанавдвойныхкавычках

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

Результатвыполненияplaybook:

$ansible-playbook3_ios_facts.yml

Послеэтого,вкаталогеall_factsнаходятсятакиефайлы:

192.168.100.1_facts.json

192.168.100.2_facts.json

192.168.100.3_facts.json

Содержимоефайлаall_facts/192.168.100.1_facts.json:

{

"ansible_facts":{

"ansible_net_all_ipv4_addresses":[

"192.168.200.1",

"192.168.100.1",

"10.1.1.1"

],

"ansible_net_all_ipv6_addresses":[],

"ansible_net_config":"Buildingconfiguration...\n\nCurrentconfiguration:

...

ios_facts

522

Page 523: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Приповторномвыполненииplaybook,Ansibleнебудетизменятьинформациювфайлах,еслифактыобустройственеизменились

Еслиинформацияизменилась,длясоответствующегоустройства,будетвыставленстатусchanged.Такимобразом,повыполнениюplaybookвсегдапонятно,когдакакая-тоинформацияизменилась.

Повторныйзапускplaybook(безизменений):

$ansible-playbook3_ios_facts.yml

Изменениясопцией--diff

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

Примерзапускаplaybookсопцией--diffисвнесеннымиизмененияминаодномизустройств:

$ansible-playbook3_ios_facts.yml--diff--limit=192.168.100.1

ios_facts

523

Page 524: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

ios_facts

524

Page 525: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Модульios_configМодульios_config-позволяетнастраиватьустройстваподуправлениемIOS,атакже,генерироватьшаблоныконфигурацийилиотправлятькомандынаоснованиишаблона.

Параметрымодуля:

after-какиедействиявыполнитьпослекомандbefore-какиедействиявыполнитьдокомандbackup-параметр,которыйуказываетнужнолиделатьрезервнуюкопиютекущейконфигурацииустройствапередвнесениемизменений.Файлбудеткопироватьсявкаталогbackup,относительнокаталогавкоторомнаходитсяplaybookconfig-параметр,которыйпозволяетуказатьбазовыйфайлконфигурации,скоторымбудутсравниватьсяизменения.Еслионуказан,модульнебудетскачиватьконфигурациюсустройства.defaults-параметруказываетнужнолисобиратьвсюинформациюсустройства,втомчисле,изначенияпоумолчанию.Есливключитьэтотпараметр,томодульбудетсобиратьтекущуюкофигурациюспомощьюкомандыshrunall.Поумолчаниюэтотпараметротключениконфигурацияпроверяетсякомандойshrunlines(commands)-списоккоманд,которыедолжныбытьнастроены.Командынужноуказыватьбезсокращенийировновтомвиде,вкоторомонибудутвконфигурации.match-параметруказываеткакименнонужносравниватькомандыparents-названиесекции,вкоторойнужноприменитькоманды.Есликоманданаходитсявнутривложеннойсекции,нужноуказыватьвесьпуть.Еслиэтотпараметрнеуказан,тосчитается,чтокомандадолжныбытьвглобальномрежимеконфигурацииreplace-параметруказываеткаквыполнятьнастройкуустройстваsave-сохранятьлитекущуюконфигурациювстартовую.Поумолчаниюконфигурациянесохраняетсяsrc-параметруказываетпутькфайлу,вкоторомнаходитсяконфигурацияилишаблонконфигурации.Взаимоисключающийпараметрсlines(тоесть,можноуказыватьилиlinesилиsrc).Заменяетмодульios_template,которыйскоробудетудален.

ios_config

525

Page 526: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

lines(commands)Самыйпростойспособиспользоватьмодульios_config-отправлятькомандыглобальногоконфигурационногорежимаспараметромlines.

Дляпараметраlinesестьaliascommands,тоесть,можновместоlinesписатьcommands.

Примерplaybook1_ios_config_lines.yml:

---

-name:Runcfgcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Configpasswordencryption

ios_config:

lines:

-servicepassword-encryption

provider:"{{cli}}"

Используетсяпеременнаяcli,котораяуказанавфайлеgroup_vars/all.yml.

Результатвыполненияplaybook:

$ansible-playbook1_ios_config_lines.yml

Ansibleвыполняеттакиекоманды:

ios_config

526

Page 527: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

terminallength0enableshowrunning-config-чтобыпроверитьестьлиэтакоманданаустройстве.Есликомандаесть,задачавыполнятьсянебудет.Есликомандынет,задачавыполнитсяесликоманды,котораяуказанавзадаченетвконфигурации:

configureterminalservicepassword-encryptionend

Таккакмодулькаждыйразпроверяетконфигурацию,преждечемпримениткоманду,модульидемпотентен.Тоесть,еслиещёраззапуститьplaybook,изменениянебудутвыполнены:

$ansible-playbook1_ios_config_lines.yml

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

Параметрlinesпозволяетотправлятьинесколькокоманд(playbook1_ios_config_mult_lines.yml):

ios_config

527

Page 528: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:Runcfgcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Sendconfigcommands

ios_config:

lines:

-servicepassword-encryption

-noiphttpserver

-noiphttpsecure-server

-noipdomainlookup

provider:"{{cli}}"

Результатвыполнения:

$ansible-playbook1_ios_config_mult_lines.yml

ios_config

528

Page 529: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Например,необходимоприменитьтакиекоманды:

linevty04

loginlocal

transportinputssh

Втакомслучае,playbook2_ios_config_parents_basic.ymlбудетвыглядетьтак:

---

-name:Runcfgcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Configlinevty

ios_config:

parents:

-linevty04

lines:

-loginlocal

-transportinputssh

provider:"{{cli}}"

Запускбудетвыполнятьсяаналогичнопредыдущимplaybook:

$ansible-playbook2_ios_config_parents_basic.yml

ios_config

529

Page 530: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Есликоманданаходитсявнесколькихвложенныхрежимах,подрежимыуказываютсявспискеparents.

Например,необходимовыполнитьтакиекоманды:

policy-mapOUT_QOS

classclass-default

shapeaverage1000000001000000

Тогдаplaybook2_ios_config_parents_mult.ymlбудетвыглядетьтак:

---

-name:Runcfgcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:ConfigQoSpolicy

ios_config:

parents:

-policy-mapOUT_QOS

-classclass-default

lines:

-shapeaverage1000000001000000

provider:"{{cli}}"

ios_config

530

Page 531: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ОтображениеобновленийВэтомразделерассматриваютсявариантыотображенияинформациюобобновлениях,которыевыполнилмодульios_config.

Playbook2_ios_config_parents_basic.yml:

---

-name:Runcfgcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Configlinevty

ios_config:

parents:

-linevty04

lines:

-loginlocal

-transportinputssh

provider:"{{cli}}"

Длятого,чтобыplaybookчто-томенял,нужносначалаотменитькоманды.Либовручную,либоизменивplaybook.Например,намаршрутизаторе192.168.100.1,вместострокиtransportinputssh,вручнуюпрописатьстрокуtransportinputall.

Например,можновыполнитьplaybookсфлагомverbose:

$ansible-playbook2_ios_config_parents_basic.yml-v

ios_config

531

Page 532: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Обратитевнимание,чтокомандаloginlocalнеотправлялась,таккаконанастроена.

Полеupdatesввыводеестьтольковтомслучае,когдаестьизменения.

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

Новыйplaybook3_ios_config_debug.ymlнаоснове2_ios_config_parents_basic.yml:

---

-name:Runcfgcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Configlinevty

ios_config:

parents:

-linevty04

lines:

-loginlocal

-transportinputssh

provider:"{{cli}}"

register:cfg

-name:Showconfigupdates

debug:var=cfg.updates

when:cfg.changed

ios_config

532

Page 533: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Изменениявplaybook:

результатработыпервойзадачисохраняетсявпеременнуюcfg.вследующейзадачемодульdebugвыводитсодержимоеполяupdates.

нотаккакполеupdatesввыводеестьтольковтомслучае,когдаестьизменения,ставитсяусловиеwhen,котороепроверяетбылилиизменениязадачабудетвыполнятьсятолькоеслинаустройствебыливнесеныизменения.вместоwhen:cfg.changedможнонаписатьwhen:cfg.changed==true

Еслизапуститьповторноplaybook,когдаизмененийнебыло,задачаShowconfigupdates,пропускается:

$ansible-playbook3_ios_config_debug.yml

Есливнестиизменениявконфигурациюмаршрутизатора192.168.100.1(изменитьtransportinputsshнаtransportinputall):

$ansible-playbook3_ios_config_debug.yml

ios_config

533

Page 534: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

ios_config

534

Page 535: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

saveПараметрsaveпозволяетуказатьнужнолисохранятьтекущуюконфигурациювстартовую.Поумолчанию,значениепараметра-no.

Доступныевариантызначений:

no(илиfalse)yes(илиtrue)

Ксожалению,наданныймомент(версияansible2.2),этотпараметрнеотрабатываеткорректно,таккакнаустройствоотправляетсякомандаcopyrunning-configstartup-config,но,приэтом,неотправляетсяподтверждениенасохранение.Из-заэтого,призапускеplaybookспараметромsaveвыставленнымвyes,появляетсятакаяошибка:

$ansible-playbook4_ios_config_save.yml

Но,можносамостоятельносделатьсохранение,используямодульios_command.

Playbook4_ios_config_save.yml:

ios_config

535

Page 536: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:Runcfgcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Configlinevty

ios_config:

parents:

-linevty04

lines:

-loginlocal

-transportinputssh

#save:yes-вверсии2.2неработаеткорректно

provider:"{{cli}}"

register:cfg

-name:Saveconfig

ios_command:

commands:

-write

provider:"{{cli}}"

when:cfg.changed

Надовнестиизменениянамаршрутизаторе192.168.100.1.Например,изменитьстрокуtransportinputallнаtransportinputssh.

Выполнениеplaybook:

$ansible-playbook4_ios_config_save.yml

ios_config

536

Page 537: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ios_config

537

Page 538: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

backupПараметрbackupуказываетнужнолиделатьрезервнуюкопиютекущейконфигурацииустройствапередвнесениемизменений.Файлбудеткопироватьсявкаталогbackup,относительнокаталогавкоторомнаходитсяplaybook(есликаталогнесуществует,онбудетсоздан).

Playbook5_ios_config_backup.yml:

---

-name:Runcfgcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Configlinevty

ios_config:

parents:

-linevty04

lines:

-loginlocal

-transportinputssh

backup:yes

provider:"{{cli}}"

Теперь,каждыйраз,когдавыполняетсяplaybook(дажееслиненужновноситьизменениявконфигурацию),вкаталогbackupбудеткопироватьсятекущаяконфигурация:

$ansible-playbook5_ios_config_backup.yml-v

ios_config

538

Page 539: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Вкаталогеbackupтеперьнаходятсяфайлытакоговида(прикаждомзапускеplaybookониперезаписываются):

192.168.100.1_config.2016-12-10@10:42:34

192.168.100.2_config.2016-12-10@10:42:34

192.168.100.3_config.2016-12-10@10:42:34

ios_config

539

Page 540: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

defaultsПараметрdefaultsуказываетнужнолисобиратьвсюинформациюсустройства,втомчислеизначенияпоумолчанию.Есливключитьэтотпараметр,модульбудетсобиратьтекущуюкофигурациюспомощьюкомандыshrunall.Поумолчаниюэтотпараметротключениконфигурацияпроверяетсякомандойshrun.

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

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

Присходитэтопотому,чтоAnsibleкаждыйразвначалепроверяетналичиекомандвсоответствующемрежиме.Есликоманднет,тосоответствующаязадачавыполняется.

Например,втакомplaybook,каждыйразбудутвноситьсяизменения(попробуйтезапуститьегосамостоятельно):

---

-name:Runcfgcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Configinterface

ios_config:

parents:

-interfaceEthernet0/2

lines:

-ipaddress192.168.200.1255.255.255.0

-ipmtu1500

provider:"{{cli}}"

Еслидобавитьпараметрdefaults:yes,измененияуженебудутвнесены,еслинехваталотолькокомандыipmtu1500(playbook6_ios_config_defaults.yml):

ios_config

540

Page 541: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:Runcfgcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Configinterface

ios_config:

parents:

-interfaceEthernet0/2

lines:

-ipaddress192.168.200.1255.255.255.0

-ipmtu1500

defaults:yes

provider:"{{cli}}"

Запускplaybook:

$ansible-playbook6_ios_config_defaults.yml

ios_config

541

Page 542: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

afterПараметрafterуказываеткакиекомандывыполнитьпослекомандвспискеlines(илиcommands).

Команды,которыеуказанывпараметреafter:

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

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

Например,командаnoshutdownнесохраняетсявконфигурациимаршрутизатора.И,еслидобавитьеёвсписокlines,изменениябудутвноситьсякаждыйраз,привыполненииplaybook.

Но,еслинаписатькомандуnoshutdownвспискеafter,тоонабудетпримененатольковтомслучае,еслинужновноситьизменения(согласноспискаlines).

Примериспользованияпараметраafterвplaybook7_ios_config_after.yml:

---

-name:Runcfgcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:Configinterface

ios_config:

parents:

-interfaceEthernet0/3

lines:

-ipaddress192.168.230.1255.255.255.0

after:

-noshutdown

provider:"{{cli}}"

Первыйзапускplaybook,свнесениемизменений:

$ansible-playbook7_ios_config_after.yml-v

ios_config

542

Page 543: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Второйзапускplaybook(измененийнет,поэтомукомандаnoshutdownневыполняется):

$ansible-playbook7_ios_config_after.yml-v

Рассмотримещёодинпримериспользованияafter.

Спомощьюafterможносохранятьконфигурациюустройства(playbook7_ios_config_after_save.yml):

ios_config

543

Page 544: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:Runcfgcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Configlinevty

ios_config:

parents:

-linevty04

lines:

-loginlocal

-transportinputssh

after:

-end

-write

provider:"{{cli}}"

Результатвыполненияplaybook(изменениятольконамаршрутизаторе192.168.100.1):

$ansible-playbook7_ios_config_after_save.yml-v

ios_config

544

Page 545: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

beforeПараметрbeforeуказываеткакиедействиявыполнитьдокомандвспискеlines.

Команды,которыеуказанывпараметреbefore:

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

Параметрbeforeполезенвситуациях,когдакакие-тодействиянеобходимовыполнитьпередвыполнениемкомандвспискеlines.

Приэтом,какиafter,параметрbeforeневлияетнато,какиекомандысравниваютсясконфигурацией.Тоесть,по-прежнему,сравниваютсятолькокомандывспискеlines.

Playbook8_ios_config_before.yml:

---

-name:Runcfgcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:ConfigACL

ios_config:

before:

-noipaccess-listextendedIN_to_OUT

parents:

-ipaccess-listextendedIN_to_OUT

lines:

-permittcp10.0.1.00.0.0.255anyeqwww

-permittcp10.0.1.00.0.0.255anyeq22

-permiticmpanyany

provider:"{{cli}}"

Вplaybook8_ios_config_before.ymlACLIN_to_OUTсначалаудалятся,спомощьюпараметраbefore,азатемсоздаетсязаново.

ТакимобразомвACLвсегданаходятсятолькотестроки,которыезаданывспискеlines.

Запускplaybookсизменениями:

ios_config

545

Page 546: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$ansible-playbook8_ios_config_before.yml-v

Запускplaybookбезизменений(командавспискеbeforeневыполняется):

$ansible-playbook8_ios_config_before.yml-v

ios_config

546

Page 547: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

matchПараметрmatchуказываеткакименнонужносравниватькоманды(чтосчитаетсяизменением):

line-командыпроверяютсяпострочно.Этотрежимиспользуетсяпоумолчаниюstrict-должнысовпастьнетолькосамикоманды,ноихположениеотносительнодругдругаexact-командыдолжнывточностисопадатьсконфигурациейинедолжнобытьникакихлишнихстрокnone-модульнебудетсравниватькомандыстекущейконфигурацией

match:line

Режимmatch:lineиспользуетсяпоумолчанию.

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

Намаршрутизаторе192.168.100.1настроентакойACL:

R1#shrun|saccess

ipaccess-listextendedIN_to_OUT

permittcp10.0.1.00.0.0.255anyeq22

Примериспользованияplaybook9_ios_config_match_line.ymlврежимеline:

ios_config

547

Page 548: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:Runcfgcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:ConfigACL

ios_config:

parents:

-ipaccess-listextendedIN_to_OUT

lines:

-permittcp10.0.1.00.0.0.255anyeqwww

-permittcp10.0.1.00.0.0.255anyeq22

-permiticmpanyany

provider:"{{cli}}"

Результатвыполненияplaybook:

$ansible-playbook9_ios_config_match_line.yml-v

Обратитевнимание,чтовспискеupdatesтолькодвеизтрёхстрокACL.Таккакврежимеlinesмодульсравниваеткомандынезависимодруготдруга,онобнаружил,чтонехватаеттолькодвухкомандизтрех.

Витогеконфигурациянамаршрутизаторевыглядиттак:

R1#shrun|saccess

ipaccess-listextendedIN_to_OUT

permittcp10.0.1.00.0.0.255anyeq22

permittcp10.0.1.00.0.0.255anyeqwww

permiticmpanyany

ios_config

548

Page 549: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Еслиповторнозапуститьplaybook,притакойконфигурации,оннебудетвыполнятьизменения,таккаквсестрокибылинайдены.

match:exact

Пример,вкоторомпорядоккомандважен.

ACLнамаршрутизаторе:

R1#shrun|saccess

ipaccess-listextendedIN_to_OUT

permittcp10.0.1.00.0.0.255anyeq22

permittcp10.0.1.00.0.0.255anyeqwww

denyipanyany

Playbook9_ios_config_match_exact.yml(будетпостепеннодополняться):

---

-name:Runcfgcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:ConfigACL

ios_config:

parents:

-ipaccess-listextendedIN_to_OUT

lines:

-permittcp10.0.1.00.0.0.255anyeqwww

-permittcp10.0.1.00.0.0.255anyeq22

-permiticmpanyany

-denyipanyany

provider:"{{cli}}"

Еслизапуститьplaybook,результатбудеттаким:

$ansible-playbook9_ios_config_match_exact.yml-v

ios_config

549

Page 550: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ТеперьACLвыглядиттак:

R1#shrun|saccess

ipaccess-listextendedIN_to_OUT

permittcp10.0.1.00.0.0.255anyeq22

permittcp10.0.1.00.0.0.255anyeqwww

denyipanyany

permiticmpanyany

Конечноже,втакомслучае,последнееправилоникогданесработает.

МожнодобавитькэтомуplaybookпараметрbeforeисначалаудалитьACL,азатемприменятькоманды:

---

-name:Runcfgcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:ConfigACL

ios_config:

before:

-noipaccess-listextendedIN_to_OUT

parents:

-ipaccess-listextendedIN_to_OUT

lines:

-permittcp10.0.1.00.0.0.255anyeqwww

-permittcp10.0.1.00.0.0.255anyeq22

-permiticmpanyany

-denyipanyany

provider:"{{cli}}"

ios_config

550

Page 551: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Еслиприменитьplaybookкпоследнемусостояниюмаршрутизатора,тоизмененийнебудетникаких,таккаквсестрокиужеесть.

ПопробуемначатьстакогосостоянияACL:

R1#shrun|saccess

ipaccess-listextendedIN_to_OUT

permittcp10.0.1.00.0.0.255anyeq22

permittcp10.0.1.00.0.0.255anyeqwww

denyipanyany

Результатбудеттаким:

$ansible-playbook9_ios_config_match_exact.yml-v

И,соответственно,намаршрутизаторе:

R1#shrun|saccess

ipaccess-listextendedIN_to_OUT

permiticmpanyany

ТеперьвACLосталасьтолькооднастрока:

МодульпроверилкакихкоманднехватаетвACL(таккакрежимпоумолчаниюmatch:line),обнаружил,чтонехватаеткомандыpermiticmpanyanyидобавилеё

Но,таккаквplaybookACLсначалаудаляется,азатемприменяетсясписоккомандlines,получилось,чтовитогевACLоднастрока.

Поможет,втакойситуации,вариантmatch:exact:

ios_config

551

Page 552: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:Runcfgcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:ConfigACL

ios_config:

before:

-noipaccess-listextendedIN_to_OUT

parents:

-ipaccess-listextendedIN_to_OUT

lines:

-permittcp10.0.1.00.0.0.255anyeqwww

-permittcp10.0.1.00.0.0.255anyeq22

-permiticmpanyany

-denyipanyany

match:exact

provider:"{{cli}}"

Применениеplaybook9_ios_config_match_exact.ymlктекущемусостояниюмаршрутизатора(вACLоднастрока):

$ansible-playbook9_ios_config_match_exact.yml-v

Теперьрезультаттакой:

ios_config

552

Page 553: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

R1#shrun|saccess

ipaccess-listextendedIN_to_OUT

permittcp10.0.1.00.0.0.255anyeqwww

permittcp10.0.1.00.0.0.255anyeq22

permiticmpanyany

denyipanyany

Тоесть,теперьACLвыглядитточнотакже,какистрокивспискеlinesивтомжепорядке.

ВверсииAnsible2.1match:exactработалпо-другомуитакойрезультатдостигалсякомбинациейпараметровmatch:exactиreplace:block.Вверсии2.2достаточноmatch:exact.

И,длятогочтобыокончательноразобратьсяспараметромmatch:exact,ещёодинпример.

ЗакомментируемвplaybookстрокисудалениемACL:

---

-name:Runcfgcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:ConfigACL

ios_config:

#before:

#-noipaccess-listextendedIN_to_OUT

parents:

-ipaccess-listextendedIN_to_OUT

lines:

-permittcp10.0.1.00.0.0.255anyeqwww

-permittcp10.0.1.00.0.0.255anyeq22

-permiticmpanyany

-denyipanyany

match:exact

provider:"{{cli}}"

ВначалоACLдобавленастрока:

ios_config

553

Page 554: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ipaccess-listextendedIN_to_OUT

permitudpanyany

permittcp10.0.1.00.0.0.255anyeqwww

permittcp10.0.1.00.0.0.255anyeq22

permiticmpanyany

denyipanyany

Тоесть,последние4строкивыглядяттак,какнужно,ивтомпорядке,которомнужно.Но,приэтом,естьлишняястрока.Длявариантаmatch:exact-этоуженесовпадение.

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

$ansible-playbook9_ios_config_match_exact.yml-v

Этозначит,чтоприиспользованииmatch:exact,важно,чтобыбылкакой-тоспособудалитьконфигурацию,еслионанесоответствуеттому,чтодолжнобыть(иличтобыкомандыперезаписывались).Иначе,этазадачабудетвыполнятьсякаждыйраз,призапускеplaybook.

match:strict

Вариантmatch:strictнетребует,чтобыобъектбылвточностикакуказановзадаче,но,команды,которыеуказанывспискеlines,должныбытьвтомжепорядке.

Еслиуказансписокparents,командывспискеlinesдолжныидтисразузакомандамиparents.

НамаршрутиазаторетакойACL:

ios_config

554

Page 555: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ipaccess-listextendedIN_to_OUT

permittcp10.0.1.00.0.0.255anyeqwww

permittcp10.0.1.00.0.0.255anyeq22

permiticmpanyany

denyipanyany

Playbook9_ios_config_match_strict.yml:

---

-name:Runcfgcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:ConfigACL

ios_config:

before:

-noipaccess-listextendedIN_to_OUT

parents:

-ipaccess-listextendedIN_to_OUT

lines:

-permittcp10.0.1.00.0.0.255anyeqwww

-permittcp10.0.1.00.0.0.255anyeq22

-permiticmpanyany

match:strict

provider:"{{cli}}"

Выполнениеplaybook:

$ansible-playbook9_ios_config_match_strict.yml-v

Таккакизмененийнебыло,ACLосталсятакимже.

ios_config

555

Page 556: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Втакойжеситуации,прииспользованииmatch:exact,былобыобнаруженоизменениеиACLбысостоялтолькоизстроквспискеlines.

match:none

Использованиеmatch:noneотключаетидемпотентностьзадачи:каждыйразпривыполненииplaybook,будутотправлятьсякоманды,которыеуказанывзадаче.

Примерplaybook9_ios_config_match_none.yml:

---

-name:Runcfgcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:ConfigACL

ios_config:

before:

-noipaccess-listextendedIN_to_OUT

parents:

-ipaccess-listextendedIN_to_OUT

lines:

-permittcp10.0.1.00.0.0.255anyeqwww

-permittcp10.0.1.00.0.0.255anyeq22

-permiticmpanyany

match:none

provider:"{{cli}}"

Каждыйразпризапускеplaybookрезультатбудеттаким:

$ansible-playbook9_ios_config_match_none.yml-v

ios_config

556

Page 557: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Использованиеmatch:noneподходитвтехслучаях,когда,независимооттекущейконфигурации,нужноотправитьвсекоманды.

ios_config

557

Page 558: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

replaceПараметрreplaceуказываеткакименнонужнозаменятьконфигурацию:

line-вэтомрежимеотправляютсятолькотекоманды,которыхнетвконфигурации.Этотрежимиспользуетсяпоумолчаниюblock-вэтомрежимеотправляютсявсекоманды,еслихотябыоднойкомандынет

replace:line

Режимreplace:line-эторежимработыпоумолчанию.Вэтомрежиме,еслибылиобнаруженыизменения,отправляютсятольконедостающиестроки.

Например,намаршрутизаторетакойACL:

R1#shrun|saccess

ipaccess-listextendedIN_to_OUT

permittcp10.0.1.00.0.0.255anyeqwww

permittcp10.0.1.00.0.0.255anyeq22

permiticmpanyany

Попробуемзапуститьтакойplaybook10_ios_config_replace_line.yml:

---

-name:Runcfgcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:ConfigACL

ios_config:

before:

-noipaccess-listextendedIN_to_OUT

parents:

-ipaccess-listextendedIN_to_OUT

lines:

-permittcp10.0.1.00.0.0.255anyeqwww

-permittcp10.0.1.00.0.0.255anyeq22

-permiticmpanyany

-denyipanyany

provider:"{{cli}}"

ios_config

558

Page 559: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Выполнениеplaybook:

$ansible-playbook10_ios_config_replace_line.yml-v

ПослеэтогонамаршрутизаторетакойACL:

R1#shrun|saccess

ipaccess-listextendedIN_to_OUT

denyipanyany

Вданномслучае,модульпроверилкакихкоманднехватаетвACL(таккакрежимпоумолчаниюmatch:line),обнаружил,чтонехватаеткомандыdenyipanyanyидобавилеё.Но,таккакACLсначалаудаляется,азатемприменяетсясписоккомандlines,получилось,чтоутеперьACLсоднойстрокой.

Втакихситуацияхподходитрежимreplace:block.

replace:block

Врежимеreplace:blockотправляютсявсекомандыизспискаlines(иparents),еслинаустройственетхотябыоднойизэтихкоманд.

Повторимпредыдущийпример.

ACLнамаршрутизаторе:

R1#shrun|saccess

ipaccess-listextendedIN_to_OUT

permittcp10.0.1.00.0.0.255anyeqwww

permittcp10.0.1.00.0.0.255anyeq22

permiticmpanyany

Playbook10_ios_config_replace_block.yml:

ios_config

559

Page 560: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:Runcfgcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:ConfigACL

ios_config:

before:

-noipaccess-listextendedIN_to_OUT

parents:

-ipaccess-listextendedIN_to_OUT

lines:

-permittcp10.0.1.00.0.0.255anyeqwww

-permittcp10.0.1.00.0.0.255anyeq22

-permiticmpanyany

-denyipanyany

replace:block

provider:"{{cli}}"

Выполнениеplaybook:

$ansible-playbook10_ios_config_replace_block.yml-v

ВрезультатенамаршрутизаторетакойACL:

R1#shrun|saccess

ipaccess-listextendedIN_to_OUT

permittcp10.0.1.00.0.0.255anyeqwww

permittcp10.0.1.00.0.0.255anyeq22

permiticmpanyany

denyipanyany

ios_config

560

Page 561: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ios_config

561

Page 562: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Этотпараметрвзаимоисключающийсlines(тоесть,можноуказыватьилиlinesилиsrc).Онзаменяетмодульios_template,которыйскоробудетудален.

Конфигурация

Примерplaybook11_ios_config_src.yml:

---

-name:Runcfgcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:ConfigACL

ios_config:

src:templates/acl_cfg.txt

provider:"{{cli}}"

Вфайлеtemplates/acl_cfg.txtнаходитсятакаяконфигурация:

ipaccess-listextendedIN_to_OUT

permittcp10.0.1.00.0.0.255anyeqwww

permittcp10.0.1.00.0.0.255anyeq22

permiticmpanyany

denyipanyany

УдаляемнамаршрутизатореэтотACL,еслионосталсяспрошлыхразделов,изапускаемplaybook:

$ansible-playbook11_ios_config_src.yml-v

ios_config

562

Page 563: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

ТеперьнамаршрутизаторенастроенACL:

R1#shrun|saccess

ipaccess-listextendedIN_to_OUT

permittcp10.0.1.00.0.0.255anyeqwww

permittcp10.0.1.00.0.0.255anyeq22

permiticmpanyany

denyipanyany

Еслизапуститьplaybookещёраз,ноникакихизмененийнебудет,таккакэтотпараметртакжеидемпотентен:

$ansible-playbook11_ios_config_src.yml-v

ШаблонJinja2

ВпараметреsrcможноуказыватьшаблонJinja2.

Примершаблона(файлtemplates/ospf.j2):

ios_config

563

Page 564: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

routerospf1

router-id{{mgmnt_ip}}

ispf

auto-costreference-bandwidth10000

{%foripinospf_ints%}

network{{ip}}0.0.0.0area0

{%endfor%}

Вшаблонеиспользуютсядвепеременные:

mgmnt_ip-IP-адрес,которыйбудетиспользоватьсякакrouter-idospf_ints-списокIP-адресовинтерфейсов,накоторыхнужновключитьOSPF

ДлянастройкиOSPFнатрёхмаршрутизаторах,нужноиметьвозможностьиспользоватьразныезначенияэтихпеременныхдляразныхустройств.Длятакихзадачиспользуютсяфайлыспеременнымивкаталогеhost_vars.

Вкаталогеhost_varsнужносоздатьтакиефайлы(еслиониещёнесозданы):

Файлhost_vars/192.168.100.1:

---

hostname:london_r1

mgmnt_loopback:100

mgmnt_ip:10.0.0.1

ospf_ints:

-192.168.100.1

-10.0.0.1

-10.255.1.1

Файлhost_vars/192.168.100.2:

---

hostname:london_r2

mgmnt_loopback:100

mgmnt_ip:10.0.0.2

ospf_ints:

-192.168.100.2

-10.0.0.2

-10.255.2.2

Файлhost_vars/192.168.100.3:

ios_config

564

Page 565: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

hostname:london_r3

mgmnt_loopback:100

mgmnt_ip:10.0.0.3

ospf_ints:

-192.168.100.3

-10.0.0.3

-10.255.3.3

Теперьможносоздаватьplaybook11_ios_config_src_jinja.yml:

---

-name:Runcfgcommandsonrouter

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:ConfigOSPF

ios_config:

src:templates/ospf.j2

provider:"{{cli}}"

ТаккакAnsibleсамнайдетпеременныевкаталогеhost_vars,ихненужноуказывать.Можносразузапускатьplaybook:

$ansible-playbook11_ios_config_src_jinja.yml-v

ТеперьнавсехмаршрутизаторахнастроенOSPF:

ios_config

565

Page 566: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

R1#shrun|sospf

routerospf1

router-id10.0.0.1

ispf

auto-costreference-bandwidth10000

network10.0.0.10.0.0.0area0

network10.255.1.10.0.0.0area0

network192.168.100.10.0.0.0area0

R2#shrun|sospf

routerospf1

router-id10.0.0.2

ispf

auto-costreference-bandwidth10000

network10.0.0.20.0.0.0area0

network10.255.2.20.0.0.0area0

network192.168.100.20.0.0.0area0

routerospf1

router-id10.0.0.3

ispf

auto-costreference-bandwidth10000

network10.0.0.30.0.0.0area0

network10.255.3.30.0.0.0area0

network192.168.100.30.0.0.0area0

Еслизапуститьplaybookещёраз,ноникакихизмененийнебудет:

$ansible-playbook11_ios_config_src_jinja.yml-v

Совмещениесдругимипараметрами

Параметрsrcсовместимстакимипараметрами:

ios_config

566

Page 567: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

backupconfigdefaultssave(ноусамогоsaveвAnsible2.2проблемысработой)

ios_config

567

Page 568: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ntc-ansiblentc-ansible-этомодульдляработыссетевымоборудованием,которыйнетольковыполняеткомандынаоборудовании,ноиобрабатываетвыводкомандипреобразуетспомощьюTextFSM.

ЭтотмодульневходитвчислоcoreмодулейAnsible,поэтомуегонужноустановить.

НопрежденужноуказатьAnsible,гдеискатьсторонниемодули.Указываетсяпутьвфайлеansible.cfg:

[defaults]

inventory=./myhosts

remote_user=cisco

ask_pass=True

library=./library

Послеэтого,нужноклонироватьрепозиторийntc-ansible,находясьвкаталогеlibrary:

[~/pyneng_course/chapter15/library]

$gitclonehttps://github.com/networktocode/ntc-ansible--recursive

Cloninginto'ntc-ansible'...

remote:Countingobjects:2063,done.

remote:Compressingobjects:100%(5/5),done.

remote:Total2063(delta1),reused0(delta0),pack-reused2058

Receivingobjects:100%(2063/2063),332.15KiB|334.00KiB/s,done.

Resolvingdeltas:100%(1157/1157),done.

Checkingconnectivity...done.

Submodule'ntc-templates'(https://github.com/networktocode/ntc-templates)registered

forpath'ntc-templates'

Cloninginto'ntc-templates'...

remote:Countingobjects:902,done.

remote:Compressingobjects:100%(34/34),done.

remote:Total902(delta16),reused0(delta0),pack-reused868

Receivingobjects:100%(902/902),161.11KiB|0bytes/s,done.

Resolvingdeltas:100%(362/362),done.

Checkingconnectivity...done.

Submodulepath'ntc-templates':checkedout'89c57342b47c9990f0708226fb3f268c6b8c1549'

Азатемустановитьзависимостимодуля:

ntc_ansible

568

Page 569: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

pipinstallntc-ansible

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

ТаккаквтекущейверсииAnsibleужеестьмодули,которыеработаютссетевымоборудованиемипозволяютвыполнятькоманды,извсехвозможностейntc-ansible,наиболееполезнойбудетотправкакомандshowиполучениеструктурированноговывода.Заэтоотвечаетмодульntc_show_command.

ntc_show_commandМодульиспользуетnetmikoдляподключениякоборудованию(netmikoдолженбытьустановлен)и,послевыполнениякоманды,преобразуетвыводкомандыshowспомощьюTextFSMвструктурированныйвывод(списоксловарей).

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

Какиспредыдущимисетевымимодулями,вntc-ansibleнужноуказыватьрядпараметровдляподключения:

connection-тутвозможныдваварианта:ssh(подключениеnetmiko)илиoffline(чтениеизфайладлятестовыхцелей)platform-платформа,котораясуществуетвindexфайле(library/ntc-ansible/ntc-templates/templates/index)command-команда,которуюнужновыполнитьнаустройствеhost-IP-адресилиимяустройстваusername-имяпользователяpassword-парольtemplate_dir-путьккаталогувкоторомнаходятсяшаблоны(втекущемвариантеустановкионинаходятсявкаталогеlibrary/ntc-ansible/ntc-templates/templates

Примерplaybook1_ntc_ansible.yml:

ntc_ansible

569

Page 570: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

---

-name:Runshowcommandsonrouter

hosts:192.168.100.1

gather_facts:false

connection:local

tasks:

-name:Runshipintbr

ntc_show_command:

connection:ssh

platform:"cisco_ios"

command:"shipintbr"

host:"{{inventory_hostname}}"

username:"cisco"

password:"cisco"

template_dir:"library/ntc-ansible/ntc-templates/templates"

register:result

-debug:var=result

Результатвыполненияplaybook:

$ansible-playbook1_ntc-ansible.yml

ntc_ansible

570

Page 571: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Впеременнойresponseнаходитсяструктурированныйвыводввидеспискасловарей.Ключивсловаряхполученынаоснованиипеременных,которыеописанывшаблонеlibrary/ntc-ansible/ntc-templates/templates/cisco_ios_show_ip_int_brief.template(единственноеотличие-регистр):

ntc_ansible

571

Page 572: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ValueINTF(\S+)

ValueIPADDR(\S+)

ValueSTATUS(up|down|administrativelydown)

ValuePROTO(up|down)

Start

^${INTF}\s+${IPADDR}\s+\w+\s+\w+\s+${STATUS}\s+${PROTO}->Record

Длятого,чтобыполучитьвыводпропервыйинтерфейс,можнопоменятьвыводмодуляdebug,такимобразом:

-debug:var=result.response[0]

Сохранениерезультатоввыполнениякоманды

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

Примерplaybook2_ntc_ansible_save.ymlссохранениемрезультатовкоманды:

---

-name:Runshowcommandsonrouters

hosts:cisco-routers

gather_facts:false

connection:local

tasks:

-name:Runshipintbr

ntc_show_command:

connection:ssh

platform:"cisco_ios"

command:"shipintbr"

host:"{{inventory_hostname}}"

username:"cisco"

password:"cisco"

template_dir:"library/ntc-ansible/ntc-templates/templates"

register:result

-name:Copyfactstofiles

copy:

content:"{{result.response|to_nice_json}}"

dest:"all_facts/{{inventory_hostname}}_sh_ip_int_br.json"

Результатвыполнения:

ntc_ansible

572

Page 573: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$ansible-playbook2_ntc-ansible_save.yml

Врезультате,вкаталогеall_factsповяляютсясоответствующиефайлыдлякаждогомаршрутизатора.Примерфайлаall_facts/192.168.100.1_sh_ip_int_br.json:

ntc_ansible

573

Page 574: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

[

{

"intf":"Ethernet0/0",

"ipaddr":"192.168.100.1",

"proto":"up",

"status":"up"

},

{

"intf":"Ethernet0/1",

"ipaddr":"192.168.200.1",

"proto":"up",

"status":"up"

},

{

"intf":"Ethernet0/2",

"ipaddr":"unassigned",

"proto":"down",

"status":"administrativelydown"

},

{

"intf":"Ethernet0/3",

"ipaddr":"unassigned",

"proto":"up",

"status":"up"

},

{

"intf":"Loopback0",

"ipaddr":"10.1.1.1",

"proto":"up",

"status":"up"

}

]

ШаблоныJinja2ДляCiscoIOSвntc-ansibleестьтакиешаблоны:

ntc_ansible

574

Page 575: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

cisco_ios_dir.template

cisco_ios_show_access-list.template

cisco_ios_show_aliases.template

cisco_ios_show_archive.template

cisco_ios_show_capability_feature_routing.template

cisco_ios_show_cdp_neighbors_detail.template

cisco_ios_show_cdp_neighbors.template

cisco_ios_show_clock.template

cisco_ios_show_interfaces_status.template

cisco_ios_show_interfaces.template

cisco_ios_show_interface_transceiver.template

cisco_ios_show_inventory.template

cisco_ios_show_ip_arp.template

cisco_ios_show_ip_bgp_summary.template

cisco_ios_show_ip_bgp.template

cisco_ios_show_ip_int_brief.template

cisco_ios_show_ip_ospf_neighbor.template

cisco_ios_show_ip_route.template

cisco_ios_show_lldp_neighbors.template

cisco_ios_show_mac-address-table.template

cisco_ios_show_processes_cpu.template

cisco_ios_show_snmp_community.template

cisco_ios_show_spanning-tree.template

cisco_ios_show_standby_brief.template

cisco_ios_show_version.template

cisco_ios_show_vlan.template

cisco_ios_show_vtp_status.template

Списоквсехшаблоновможнопосмотретьлокально,еслиntc-ansibleустановлен:

ls-lslibrary/ntc-ansible/ntc-templates/templates/

Иливрепозиториипроекта.

ИспользуяTextFSMможносамостоятельносоздаватьдополнительныешаблоны.

И,длятого,чтобыntc-ansibleихиспользовалавтоматически,добавитьихвфайлindex(library/ntc-ansible/ntc-templates/templates/index):

ntc_ansible

575

Page 576: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

#Firstlineistheheaderfieldsforcolumnsandismandatory.

#Regularexpressionsaresupportedinallfieldsexceptthefirst.

#Lastfieldsupportsvariablelengthcommandcompletion.

#abc[[xyz]]isexpandedtoabc(x(y(z)?)?)?,regexpinside[[]]isnotsupported

#

Template,Hostname,Platform,Command

cisco_asa_dir.template,.*,cisco_asa,dir

cisco_ios_show_archive.template,.*,cisco_ios,sh[[ow]]arc[[hive]]

cisco_ios_show_capability_feature_routing.template,.*,cisco_ios,sh[[ow]]cap[[abil

ity]]f[[eature]]r[[outing]]

cisco_ios_show_aliases.template,.*,cisco_ios,sh[[ow]]alia[[ses]]

...

СинтаксисшаблоновифайлаindexописанывразделеTextFSM.

ntc_ansible

576

Page 577: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

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

А,возможно,накаком-тоэтапе,понадобитсянаписатьсвоймодуль.

ВсёэтоAnsibleпозволяетсделать,ноэтовыходитзарамкиэтогокурса.ЭтаинформациявынесенавотдельныйкурсAnsibleдлясетевыхинженеров.Основы,которыерассматриваютсятут,вкурсеповторяются,поэтому,есливыпрочиталивесьразделAnsibleвэтомкурсе,можетеначатьсразусчетвертогоразделаPlaybook.

Есликакие-тотемынерассмотренывкурсе"Ansibleдлясетевыхинженеров",незабывайте,чтоуAnsibleотличнаядокументация.

ПодробнееобAnsible

577

Page 578: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ЗаданияВсезаданияивспомогательныефайлыможноскачатьоднимархивомzipилиtar.gz.

Такжедлякурсаподготовленыдвевиртуальныемашинынавыбор:VagrantилиVMware.Внихустановленывсепакеты,которыеиспользуютсявкурсе.

Есливзаданияхразделаестьзаданиясбуквами(например,5.2a),томожновыполнитьсначалазаданиябезбукв,азатемсбуквами.Заданиясбуквами,какправило,немногосложнеезаданийбезбуквиразвивают/усложняютидеювсоответствующемзаданиибезбуквы.

Например,есливразделеестьзадания:5.1,5.2,5.2a,5.2b,5.3,5.3a.Сначала,можновыполнитьзадания5.1,5.2,5.3.Азатем5.2a,5.2b,5.3a.

Однако,еслизаданиясбуквамиполучаетсясделатьсразу,можноделатьихпопорядку.

Задание15.1

Создайтеplaybook,которыйвыполняеттакиезадачи:

подключаетсякмаршрутизаторамивыполняеткомандуsharpрезультатзаписываетвпеременнуюsh_arp_output

отображаетсодержимоепеременнойsh_arp_output

Проверьтеработуplaybookнамаршрутизаторах.

Задание15.1a

Создайтеplaybook,которыйвыполняеттакиезадачи:

подключаетсякмаршрутизаторамивыполняеткомандуsharpрезультатзаписываетвпеременнуюsh_arp_output

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

Проверьтеработуplaybookнамаршрутизаторах.

Задание15.1b

Задания

578

Page 579: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Создайтеplaybook,которыйвыполняеттакиезадачи:

подключаетсякмаршрутизаторамивыполняеткомандыsharpиshipintbrобекомандыдолжнывыполнятьсяводнойзадачерезультатзаписываетвпеременнуюresult

втораязадачаотображаетрезультатвыполнениякоманд

Проверьтеработуplaybookнамаршрутизаторах.

Задание15.1c

Создайтеplaybook,которыйвыполняеттакиезадачи:

подключаетсякмаршрутизаторамивыполняеткомандыsharpиshipintbrобекомандыдолжнывыполнятьсяводнойзадачерезультатзаписываетвпеременнуюresult

втораязадачаотображаетрезультатвыполнениякомандыsharpтретяязадачаотображаетрезультатвыполнениякомандыshipintbr

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

Проверьтеработуplaybookнамаршрутизаторах.

Задание15.2

Создайтеplaybook,которыйвыполняеттакиезадачи:

собираетвсефактысмаршрутизатороврезультатнельзязаписыватьвпеременную

отображаетсодержимоефактаобинтерфейсах(вфактенаходитсясловарьсинтерфейсамииихпараметрами)

Проверьтеработуplaybookнамаршрутизаторах.

Задание15.2a

Создайтеplaybook,которыйвыполняеттакиезадачи:

собираетвсефактысмаршрутизатороврезультатнельзязаписыватьвпеременную

записываетсодержимоефактаобинтерфейсахвфайлвкаталогall_facts:имяфайладолжнобытьтакоговида:hostname_intf_facts.yamlhostname-этоимятекущегоустройства,длякоторогособираютсяфактыфайлдолженбытьвформатеYAML,ввиде,которыйудобнейдлячтения

Задания

579

Page 580: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

человеком

Проверьтеработуplaybookнамаршрутизаторах.

Задание15.2b

Создайтеplaybook,которыйвыполняеттакиезадачи:

собираетвсефактысмаршрутизатороврезультатнезаписыватьвпеременную

выполняеткомандуshipv6intbrвыводкомандызаписываетвпеременнуюshow_result

отображаетсодержимоепеременнойshow_result,нотольковтомслучае,когдафакт,вкоторомсодержатсяIPv6адресаввидесписка,непустой

Проверьтеработуplaybookнамаршрутизаторах.

Задание15.3

Вplaybooktask_15_3.ymlописанаодназадача.

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

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

Задание15.4

Создайтеplaybook,которыйвыполняеттакуюзадачу:

создаетACLINET-to-LANиприменяетегокинтерфейсуEthernet0/1

Приэтом,подразумевается,чтонастройкаACLвыполняетсятолькоспомощьюPlaybook.Поэтому,вACLдолжныбытьтолькотестроки,которыеуказанывзадачеplaybook.

Задачадолжнавыполнятьтакиедействия:

удалитьACLсинтерфейсаудалитьACLсоздатьACLинастроитьправилаACLприменитьACLкинтерфейсу

ACLдолженбытьтаким:

Задания

580

Page 581: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ipaccess-listextendedINET-to-LAN

permittcp10.0.1.00.0.0.255anyeqwww

permittcp10.0.1.00.0.0.255anyeq22

permiticmpanyany

ПроверьтеработуplaybookнамаршрутизатореR1.

Задание15.4a

Проверьтеработуplaybookиззадания15.4,вситуации,когдавACLдобавленаещёоднастрока.

Если,последобавлениястрокивзадачеивыполненияplaybook,ACLнамаршрутизаторевыглядиттакже,какописановplaybook,значитзаданиевыполнено.

Еслинет,исправьтесоответственнозадачу.

Добавьте,например,такуюстрокувACL:

permittcp10.0.1.00.0.0.255anyeqtelnet

ПроверьтеработуplaybookнамаршрутизатореR1.

Задание15.4b

Добавьтевplaybookиззадания15.4aещёоднузадачу:

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

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

еслинужно,можноизменятьипервуюзадачу

ПроверьтеработуplaybookнамаршрутизатореR1.

Задание15.4c

Изменитеplaybookиззадания15.4bтакимобразом,чтобыимяинтерфейса,которыйуказываетсявзадаче,указывалоськакпеременнаяoutside_intf.

СоздайтепеременнуюдлямаршрутизатораR1,всоответствующемфайлекаталогаhost_vars.

ПроверьтеработуplaybookнамаршрутизатореR1.

Задания

581

Page 582: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Задания

582

Page 583: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Дополнительнаяинформация

583

Page 584: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПолезныемодулиВэтомразделеописанытакиемодули:

subprocessosargparseipaddress

Полезныемодули

584

Page 585: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодульsubprocessМодульsubprocessпозволяетсоздаватьновыепроцессы.Приэтом,онможетподключатьсякстандартнымпотокамввода/вывода/ошибокиполучатькодвозврата.

Спомощьюsubprocess,можно,например,выполнятьлюбыекомандыLinuxизскрипта.И,взависимостиотситуации,получатьвыводилитолькопроверять,чтокомандавыполниласьбезошибок.

Функцияsubprocess.call()

Функцияcall():

позволяетвыполнитькомандуприэтом,онаожидаетзавершениякоманды.

функциявозращаеткодвозврата

Примервыполнениякомандыls:

In[1]:importsubprocess

In[2]:result=subprocess.call('ls')

LICENSE.mdcourse_presentationsfaq.md

README.mdcourse_presentations.ziphowto.md

SUMMARY.mdcover.jpgimages

ToDo.mdexamplesresources

about.mdexamples.zipschedule.md

bookexercises

book.jsonexercises.zip

Впеременнойresultтеперьсодержитсякодвозврата(код0означает,чтопрограммавыполниласьуспешно):

In[3]:printresult

0

Обратитевнимание,что,еслинеобходимовызватькомандусаргументами,еёнужнопередаватьтакимобразом(каксписок):

Модульsubprocess

585

Page 586: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[4]:result=subprocess.call(['ls','-ls'])

total3624

8-rw-r--r--1natanata372Dec1021:34LICENSE.md

16-rw-r--r--1natanata4528Jan1209:16README.md

32-rw-r--r--1natanata12480Jan2311:15SUMMARY.md

8-rw-r--r--1natanata2196Jan2309:16ToDo.md

8-rw-r--r--1natanata70Dec1021:34about.md

0drwxr-xr-x19natanata646Jan2311:05book

8-rw-r--r--1natanata355Jan1209:16book.json

0drwxr-xr-x16natanata544Dec1021:34course_presentations

2176-rw-r--r--1natanata1111234Dec1021:34course_presentations.zip

528-rw-r--r--@1natanata267824Dec1108:25cover.jpg

0drwxr-xr-x20natanata680Jan2313:05examples

360-rw-r--r--1natanata181075Jan2114:10examples.zip

0drwxr-xr-x19natanata646Jan1710:24exercises

416-rw-r--r--1natanata210621Jan2114:10exercises.zip

32-rw-r--r--1natanata14684Jan1805:33faq.md

16-rw-r--r--1natanata7043Jan1710:28howto.md

0drwxr-xr-x4natanata136Jan1411:01images

0drwxr-xr-x10natanata340Jan1708:44resources

16-rw-r--r--@1natanata6219Jan1711:37schedule.md

Всефайлы,срасширениемmd:

In[5]:result=subprocess.call(['ls','-ls','*md'])

ls:*md:Nosuchfileordirectory

Возниклаошибка.

Чтобывызыватькоманды,вкоторыхиспользуютсярегулярныевыражения,нужнодобавлятьпараметрshell:

In[6]:result=subprocess.call(['ls','-ls','*md'],shell=True)

LICENSE.mdcourse_presentationsfaq.md

README.mdcourse_presentations.ziphowto.md

SUMMARY.mdcover.jpgimages

ToDo.mdexamplesresources

about.mdexamples.zipschedule.md

bookexercises

book.jsonexercises.zip

Еслиустанавленаргументshell=True,указаннаякомандавыполняетсячерезshell.Втакомслучае,командуможноуказыватьтак:

Модульsubprocess

586

Page 587: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[7]:result=subprocess.call('ls-ls*md',shell=True)

8-rw-r--r--1natanata372Dec1021:34LICENSE.md

16-rw-r--r--1natanata4528Jan1209:16README.md

32-rw-r--r--1natanata12480Jan2311:15SUMMARY.md

8-rw-r--r--1natanata2196Jan2309:16ToDo.md

8-rw-r--r--1natanata70Dec1021:34about.md

32-rw-r--r--1natanata14684Jan1805:33faq.md

16-rw-r--r--1natanata7043Jan1710:28howto.md

16-rw-r--r--@1natanata6219Jan1711:37schedule.md

Ещёоднаособенностьфункцииcall()-онаожидаетзавершениявыполнениякоманды.Еслипопробовать,например,запуститькомандуping,тоэтотаспектбудетзаметен:

In[8]:reply=subprocess.call(['ping','-c','3','-n','8.8.8.8'])

PING8.8.8.8(8.8.8.8):56databytes

64bytesfrom8.8.8.8:icmp_seq=0ttl=48time=49.868ms

64bytesfrom8.8.8.8:icmp_seq=1ttl=48time=49.243ms

64bytesfrom8.8.8.8:icmp_seq=2ttl=48time=50.029ms

---8.8.8.8pingstatistics---

3packetstransmitted,3packetsreceived,0.0%packetloss

round-tripmin/avg/max/stddev=49.243/49.713/50.029/0.339ms

Особенно,еслипопробоватьпинганутькакой-тонедоступныйIP-адрес.

Функцияcall()подходит,еслинужно:

подождатьвыполненияпрограммы,преждечемвыполнятьследующиешагинужнополучитьтолькокодвыполненияиненуженвывод

Ещёодинаспектработыфункцииcall(),онавыводитрезультатвыполнениякоманды,настандартныйпотоквывода.

Файлsubprocess_call.py:

importsubprocess

reply=subprocess.call(['ping','-c','3','-n','8.8.8.8'])

ifreply==0:

print"Alive"

else:

print"Unreachable"

Результатвыполнениябудеттаким:

Модульsubprocess

587

Page 588: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythonsubprocess_call.py

PING8.8.8.8(8.8.8.8):56databytes

64bytesfrom8.8.8.8:icmp_seq=0ttl=48time=49.930ms

64bytesfrom8.8.8.8:icmp_seq=1ttl=48time=48.981ms

64bytesfrom8.8.8.8:icmp_seq=2ttl=48time=48.360ms

---8.8.8.8pingstatistics---

3packetstransmitted,3packetsreceived,0.0%packetloss

round-tripmin/avg/max/stddev=48.360/49.090/49.930/0.646ms

Alive

Тоесть,результатвыполнениякоманды,выводитсянастандартныйпотоквывода.

Еслинужноэтоотключитьиневыводитьрезультатвыполнения,надоперенаправитьstdoutвdevnull(файлsubprocess_call_devnull.py):

importsubprocess

importos

DNULL=open(os.devnull,'w')

reply=subprocess.call(['ping','-c','3','-n','8.8.8.8'],stdout=DNULL)

ifreply==0:

print"Alive"

else:

print"Unreachable"

Теперьрезультатвыполнениябудеттаким:

$pythonsubprocess_call_devnull.py

Alive

Функцияsubprocess.check_output()

Функцияcheck_output():

позволяетвыполнитькомандуприэтом,онаожидаетзавершениякоманды.

есликомандаотработалакорректно(кодвозврата0),функциявозращаетрезультатвыполнениякомандыесливозниклаошибка,привыполнениикоманды,функциягенерируетисключение

Примериспользованияфункцииcheck_output()(файлsubprocess_check_output.py):

Модульsubprocess

588

Page 589: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importsubprocess

reply=subprocess.check_output(['ping','-c','3','-n','8.8.8.8'])

print"Result:"

printreply

Результатвыполнения(еслиубратьстрокуprintreply,настандартныйпотоквыводаничегонебудетвыведено):

$pythonsubprocess_check_output.py

Result:

PING8.8.8.8(8.8.8.8):56databytes

64bytesfrom8.8.8.8:icmp_seq=0ttl=48time=49.785ms

64bytesfrom8.8.8.8:icmp_seq=1ttl=48time=57.231ms

64bytesfrom8.8.8.8:icmp_seq=2ttl=48time=51.071ms

---8.8.8.8pingstatistics---

3packetstransmitted,3packetsreceived,0.0%packetloss

round-tripmin/avg/max/stddev=49.785/52.696/57.231/3.250ms

Есливыполнитькоманду,котораявызоветошибкуи,соответственно,кодвозратабудетне0(файлsubprocess_check_output_catch_exception.py):

$pythonsubprocess_check_output_catch_exception.py

ping:cannotresolvea:Unknownhost

Traceback(mostrecentcalllast):

File"subprocess_check_output_catch_exception.py",line3,in<module>

reply=subprocess.check_output(['ping','-c','3','-n','a'])

File"/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/p

ython2.7/subprocess.py",line573,incheck_output

raiseCalledProcessError(retcode,cmd,output=output)

subprocess.CalledProcessError:Command'['ping','-c','3','-n','a']'returnednon-z

eroexitstatus68

ВозниклоисключениеCalledProcessErrorисоответствующеесообщениеобошибке.

Функцияcheck_output()всегдабудетвозвращатьэтоисключение,когдакодвозвратанеравен0.

Этозначит,чтовскриптеможнонаписатьвыражениеtry/except,спомощьюкоторогобудетвыполнятьсяпроверкакорректнолиотработалакоманда(дополняемфайлsubprocess_check_output_catch_exception.py):

Модульsubprocess

589

Page 590: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importsubprocess

try:

reply=subprocess.check_output(['ping','-c','3','-n','a'])

exceptsubprocess.CalledProcessErrorase:

print"Erroroccurred"

print"Returncode:",e.returncode

Результатвыполнения:

$pythonsubprocess_check_output_catch_exception.py

ping:cannotresolvea:Unknownhost

Erroroccurred

Returncode:68

Теперьпрограммазавершиласькорректноивывеласообщениеобошибкеикодвозврата.И,хотясообщениеобошибке,невыводилось,онопопалонастандартныйпотоквывода.

Попробуемсобратьвсёвфинальнуюфункциюидобавимперехватсообщенияобошибке:

importsubprocess

fromtempfileimportTemporaryFile

defping_ip(ip_address):

"""

PingIPaddressandreturntuple:

Onsuccess:

*returncode=0

*commandoutput

Onfailure:

*returncode

*erroroutput(stderr)

"""

withTemporaryFile()astemp:

try:

output=subprocess.check_output(['ping','-c','3','-n',ip_address],

stderr=temp)

return0,output

exceptsubprocess.CalledProcessErrorase:

temp.seek(0)

returne.returncode,temp.read()

printping_ip('8.8.8.8')

printping_ip('a')

Модульsubprocess

590

Page 591: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Результатвыполнениябудеттаким:

$pythonsubprocess_ping_function.py

(0,'PING8.8.8.8(8.8.8.8):56databytes\n64bytesfrom8.8.8.8:icmp_seq=0ttl=48t

ime=46.106ms\n64bytesfrom8.8.8.8:icmp_seq=1ttl=48time=46.114ms\n64bytesfrom

8.8.8.8:icmp_seq=2ttl=48time=47.390ms\n\n---8.8.8.8pingstatistics---\n3packet

stransmitted,3packetsreceived,0.0%packetloss\nround-tripmin/avg/max/stddev=4

6.106/46.537/47.390/0.603ms\n')

(68,'ping:cannotresolvea:Unknownhost\n')

Впримереиспользованыидеиизответанаstackoverflow

МодульtempfileвходитвстандартнуюбиблиотекуPythonииспользуетсятутдлятого,чтобысохранитьсообщениеобошибке.ФункцияTemporaryFileсоздаетвременныйфайлиудаляетегоавтоматически,послетого,какфайлзакрывается.

ПодробнееомодулеtempfileможнопочитатьнасайтеPyMOTW.

Наосновеэтойфункции,можносделатьфункцию,котораябудетпроверятьсписокIP-адресовивозвращать,врезультатевыполнения,двасписка:доступныеинедоступныеадреса.

ЕсликоличествоIP-адресов,которыенужнопроверить,большое,можноиспользоватьмодульmultiprocessing,чтобыускоритьпроверку.

Этовынесеновзаданиякразделу.

Этодалеконевсевозможностимодуляsubprocess.ПодробнееонёмможнопочитатьвдокументациииливстатьеPyMOTW

Модульsubprocess

591

Page 592: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодульosМодульosпозволяетработатьсфайловойсистемой,сокружением,управлятьпроцессами.

Мырассмотримлишьнесколькополезныхвозможностей.Заболееполнымописаниемвозможностеймодуля,выможетеобратитьсякдокументацииилистатьенасайтеPyMOTW.

Модульosпозволяетсоздаватькаталоги:

In[1]:importos

In[2]:os.mkdir('test')

In[3]:ls-ls

total0

0drwxr-xr-x2natanata68Jan2318:58test/

Крометого,вмодулеестьсоответствующиепроверкинасуществование.Например,еслипопробоватьповторносоздатькаталог,возникнетошибка:

In[4]:os.mkdir('test')

---------------------------------------------------------------------------

OSErrorTraceback(mostrecentcalllast)

<ipython-input-4-cbf3b897c095>in<module>()

---->1os.mkdir('test')

OSError:[Errno17]Fileexists:'test'

Втакомслучае,пригодитсяпроверкаos.path.exists:

In[5]:os.path.exists('test')

Out[5]:True

In[6]:ifnotos.path.exists('test'):

...:os.mkdir('test')

...:

Методlistdir,позволяетпосмотретьсодержимоекаталога:

In[7]:os.listdir('.')

Out[7]:['cover3.png','dir2','dir3','README.txt','test']

Модульos

592

Page 593: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Спомощьюпроверокos.path.isdirиos.path.isfile,можнополучитьотдельносписокфайловисписоккаталогов:

In[8]:dirs=[dfordinos.listdir('.')ifos.path.isdir(d)]

In[9]:dirs

Out[9]:['dir2','dir3','test']

In[10]:files=[fforfinos.listdir('.')ifos.path.isfile(f)]

In[11]:files

Out[11]:['cover3.png','README.txt']

Такжевмодулеестьотдельныеметодыдляработыспутями:

In[12]:os.path.basename(file)

Out[12]:'README.md'

In[13]:os.path.dirname(file)

Out[13]:'Programming/PyNEng/book/16_additional_info'

In[14]:os.path.split(file)

Out[14]:('Programming/PyNEng/book/16_additional_info','README.md')

Модульos

593

Page 594: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Модульargparseargparse-этомодульдляобработкиаргументовкоманднойстроки.

Примерытого,чтопозволяетделатьмодуль:

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

argparseнеединственныймодульдляобработкиаргументовкоманднойстроки.Идаже,неединственныйтакоймодульвстандартнойбиблиотеке.

Мыбудемрассматриватьтолькоargparse.Но,есливыстолкнетесьснеобходимостьюиспользоватьподобныемодули,обязательнопосмотритеинатемодули,которыеневходятвстандартнуюбиблиотекуPython.Например,наclick.

Оченьхорошаястатья,котораясравниваетразныемодулиобработкиаргументовкоманднойстроки(рассматриваютсяargparse,clickиdocopt).

Примерскриптаping_function.py:

Модульargparse

594

Page 595: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importsubprocess

fromtempfileimportTemporaryFile

importargparse

defping_ip(ip_address,count=3):

"""

PingIPaddressandreturntuple:

Onsuccess:(returncode=0,commandoutput)

Onfailure:(returncode,erroroutput(stderr))

"""

withTemporaryFile()astemp:

try:

output=subprocess.check_output(['ping','-c',str(count),'-n',ip_addre

ss],

stderr=temp)

return0,output

exceptsubprocess.CalledProcessErrorase:

temp.seek(0)

returne.returncode,temp.read()

parser=argparse.ArgumentParser(description='Pingscript')

parser.add_argument('-a',action="store",dest="ip")

parser.add_argument('-c',action="store",dest="count",default=2,type=int)

args=parser.parse_args()

printargs

rc,message=ping_ip(args.ip,args.count)

printmessage

Созданиепарсера:

parser=argparse.ArgumentParser(description='Pingscript')

Добавлениеаргументов:

parser.add_argument('-a',action="store",dest="ip")

аргумент,которыйпередаетсяпослеопции-a,сохранитсявпеременнуюipparser.add_argument('-c',action="store",dest="count",default=2,type=int)

аргумент,которыйпередаетсяпослеопции-c,будетсохраненвпеременнуюcount,но,прежде,будетконвертированвчисло.Еслиаргументнебылоуказан,поумолчанию,будетзначение2

Строкаargs=parser.parse_args()указывается,послетогокакопределенывсеаргументы.

Модульargparse

595

Page 596: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Послееёвыполнения,впеременнойargsсодержатсявсеаргументы,которыебылипереданыскрипту.Книмможнообращаться,используясинтаксисargs.ip.

Попробуемвызватьскриптсразнымиаргументами.

Еслипереданыобааргумента:

$pythonping_function.py-a8.8.8.8-c5

Namespace(count=5,ip='8.8.8.8')

PING8.8.8.8(8.8.8.8):56databytes

64bytesfrom8.8.8.8:icmp_seq=0ttl=48time=48.673ms

64bytesfrom8.8.8.8:icmp_seq=1ttl=48time=49.902ms

64bytesfrom8.8.8.8:icmp_seq=2ttl=48time=48.696ms

64bytesfrom8.8.8.8:icmp_seq=3ttl=48time=50.040ms

64bytesfrom8.8.8.8:icmp_seq=4ttl=48time=48.831ms

---8.8.8.8pingstatistics---

5packetstransmitted,5packetsreceived,0.0%packetloss

round-tripmin/avg/max/stddev=48.673/49.228/50.040/0.610ms

Namespaceэтообъект,которыйвозвращаетметодparse_args()

ПередаемтолькоIP-адрес:

$pythonping_function.py-a8.8.8.8

Namespace(count=2,ip='8.8.8.8')

PING8.8.8.8(8.8.8.8):56databytes

64bytesfrom8.8.8.8:icmp_seq=0ttl=48time=48.563ms

64bytesfrom8.8.8.8:icmp_seq=1ttl=48time=49.616ms

---8.8.8.8pingstatistics---

2packetstransmitted,2packetsreceived,0.0%packetloss

round-tripmin/avg/max/stddev=48.563/49.090/49.616/0.526ms

Вызовскриптабезаргументов:

Модульargparse

596

Page 597: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythonping_function.py

Namespace(count=2,ip=None)

Traceback(mostrecentcalllast):

File"ping_function.py",line31,in<module>

rc,message=ping_ip(args.ip,args.count)

File"ping_function.py",line16,inping_ip

stderr=temp)

File"/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/p

ython2.7/subprocess.py",line566,incheck_output

process=Popen(stdout=PIPE,*popenargs,**kwargs)

File"/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/p

ython2.7/subprocess.py",line710,in__init__

errread,errwrite)

File"/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/p

ython2.7/subprocess.py",line1335,in_execute_child

raisechild_exception

TypeError:execv()arg2mustcontainonlystrings

Еслибыфункциябылавызванабезаргументов,когданеиспользуетсяargparse,возниклаошибка,чтоневсеаргументыуказаны.

Но,из-заargparse,фактическиаргументпередается,толькоонравенNone.ЭтовидновстрокеNamespace(count=2,ip=None).

Втакомскрипте,очевидно,IP-адреснеобходимоуказыватьвсегда.Ивargparseможноуказать,чтоаргументявляетсяобязательным.

Надоизменитьопцию-a:добавитьвконцеrequired=True:

parser.add_argument('-a',action="store",dest="ip",required=True)

Теперь,есливызватьскриптбезаргументов,выводбудеттаким:

$pythonping_function.py

usage:ping_function.py[-h]-aIP[-cCOUNT]

ping_function.py:error:argument-aisrequired

Теперьотображаетсяпонятноесообщение,чтонадоуказатьобязательныйаргумент.Иподсказкаusage.

Также,благодаряargparse,доступенhelp:

Модульargparse

597

Page 598: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythonping_function.py-h

usage:ping_function.py[-h]-aIP[-cCOUNT]

Pingscript

optionalarguments:

-h,--helpshowthishelpmessageandexit

-aIP

-cCOUNT

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

ЗададимIP-адрес,какпозиционныйаргумент.

Файлping_function_ver2.py:

Модульargparse

598

Page 599: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

importsubprocess

fromtempfileimportTemporaryFile

importargparse

defping_ip(ip_address,count=3):

"""

PingIPaddressandreturntuple:

Onsuccess:(returncode=0,commandoutput)

Onfailure:(returncode,erroroutput(stderr))

"""

withTemporaryFile()astemp:

try:

output=subprocess.check_output(['ping','-c',str(count),'-n',ip_addre

ss],

stderr=temp)

return0,output

exceptsubprocess.CalledProcessErrorase:

temp.seek(0)

returne.returncode,temp.read()

parser=argparse.ArgumentParser(description='Pingscript')

parser.add_argument('host',action="store",help="IPornametoping")

parser.add_argument('-c',action="store",dest="count",default=2,type=int,

help="Numberofpackets")

args=parser.parse_args()

printargs

rc,message=ping_ip(args.host,args.count)

printmessage

Теперь,вместоуказанияопции-a,можнопростопередатьIP-адрес.Онбудетавтоматическисохраненвпеременнойhost.Иавтоматическисчитаетсяобязательным.

Тоесть,теперьненужноуказыватьrequired=Trueиdest="ip".

Крометого,вскриптеуказанысообщения,которыебудутвыводиться,привызовеhelp.

Теперьвызовскриптавыглядиттак:

Модульargparse

599

Page 600: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythonping_function_ver2.py8.8.8.8-c2

Namespace(host='8.8.8.8',count=2)

PING8.8.8.8(8.8.8.8):56databytes

64bytesfrom8.8.8.8:icmp_seq=0ttl=48time=49.203ms

64bytesfrom8.8.8.8:icmp_seq=1ttl=48time=51.764ms

---8.8.8.8pingstatistics---

2packetstransmitted,2packetsreceived,0.0%packetloss

round-tripmin/avg/max/stddev=49.203/50.484/51.764/1.280ms

Асообщениеhelpтак:

$pythonping_function_ver2.py-h

usage:ping_function_ver2.py[-h][-cCOUNT]host

Pingscript

positionalarguments:

hostIPornametoping

optionalarguments:

-h,--helpshowthishelpmessageandexit

-cCOUNTNumberofpackets

Вложенныепарсеры

Рассмотримодинизспособоворганизацииболеесложнойиерархииаргументов.

Этотпримерпокажетбольшевозможностейargparse,ноониэтимнеограничиваются,поэтому,есливыбудетеиспользоватьargparse,обязательнопосмотритедокументациюмодуляилистатьюнаPyMOTW.

Файлparse_dhcp_snooping.py:

#-*-coding:utf-8-*-

importargparse

#Defaultvalues:

DFLT_DB_NAME='dhcp_snooping.db'

DFLT_DB_SCHEMA='dhcp_snooping_schema.sql'

defcreate(args):

print"CreatingDB%swithDBschema%s"%(args.name,args.schema)

defadd(args):

ifargs.sw_true:

Модульargparse

600

Page 601: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

print"Addingswitchdatatodatabase"

else:

print"Readinginfofromfile(s)\n%s"%','.join(args.filename)

print"\nAddingdatatodb%s"%args.db_file

defget(args):

ifargs.keyandargs.value:

print"GetingdatafromDB:%s"%args.db_file

print"Requestdataforhost(s)with%s%s"%(args.key,args.value)

elifargs.keyorargs.value:

print"Pleasegivetwoorzeroargs\n"

else:

print"Showing%scontent..."%args.db_file

parser=argparse.ArgumentParser()

subparsers=parser.add_subparsers(title='subcommands',

description='validsubcommands',

help='description')

create_parser=subparsers.add_parser('create_db',help='createnewdb')

create_parser.add_argument('-n',metavar='db-filename',dest='name',

default=DFLT_DB_NAME,help='dbfilename')

create_parser.add_argument('-s',dest='schema',default=DFLT_DB_SCHEMA,

help='dbschemafilename')

create_parser.set_defaults(func=create)

add_parser=subparsers.add_parser('add',help='adddatatodb')

add_parser.add_argument('filename',nargs='+',help='file(s)toaddtodb')

add_parser.add_argument('--db',dest='db_file',default=DFLT_DB_NAME,help='dbname')

add_parser.add_argument('-s',dest='sw_true',action='store_true',

help='addswitchdataifset,elseaddnormaldata')

add_parser.set_defaults(func=add)

get_parser=subparsers.add_parser('get',help='getdatafromdb')

get_parser.add_argument('--db',dest='db_file',default=DFLT_DB_NAME,help='dbname')

get_parser.add_argument('-k',dest="key",

choices=['mac','ip','vlan','interface','switch'],

help='hostkey(parameter)tosearch')

get_parser.add_argument('-v',dest="value",help='valueofkey')

get_parser.add_argument('-a',action='store_true',help='showdbcontent')

get_parser.set_defaults(func=get)

if__name__=='__main__':

args=parser.parse_args()

args.func(args)

Модульargparse

601

Page 602: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

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

Например,вэтойчасти,созданвложенныйпарсерcreate_dbикнемудобавленаопция-n:

create_parser=subparsers.add_parser('create_db',help='createnewdb')

create_parser.add_argument('-n',dest='name',default=DFLT_DB_NAME,

help='dbfilename')

Синтаксиссозданиявложенныхпарсеровидобавлениякнимаргументов,одинаков:

create_parser=subparsers.add_parser('create_db',help='createnewdb')

create_parser.add_argument('-n',metavar='db-filename',dest='name',

default=DFLT_DB_NAME,help='dbfilename')

create_parser.add_argument('-s',dest='schema',default=DFLT_DB_SCHEMA,

help='dbschemafilename')

create_parser.set_defaults(func=create)

Методadd_argumentдобавляетаргумент.Тутсинтаксисточнотакойже,какибезиспользованиявложенныхпарсеров.

Встроке``create_parser.set_defaults(func=create)указывается,что,привызовепарсераcreate_parser```,будетвызванафункцияcreate.

Функцияcreateполучаеткакаргумент,всеаргументы,которыебылипереданы.И,внутрифункции,можнообращатьсякнужным:

defcreate(args):

print"CreatingDB%swithDBschema%s"%(args.name,args.schema)

Есливызватьhelpдляэтогоскрипта,выводбудеттаким:

Модульargparse

602

Page 603: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythonparse_dhcp_snooping.py-h

usage:parse_dhcp_snooping.py[-h]{create_db,add,get}...

optionalarguments:

-h,--helpshowthishelpmessageandexit

subcommands:

validsubcommands

{create_db,add,get}description

create_dbcreatenewdb

addadddatatodb

getgetdatafromdb

Обратитевнимание,чтокаждыйвложенныйпарсер,которыйсозданвскрипте,отображаетсякаккомандавподсказкеusage:

usage:parse_dhcp_snooping.py[-h]{create_db,add,get}...

Укаждоговложенногопарсератеперьестьсвойhelp:

$pythonparse_dhcp_snooping.pycreate_db-h

usage:parse_dhcp_snooping.pycreate_db[-h][-ndb-filename][-sSCHEMA]

optionalarguments:

-h,--helpshowthishelpmessageandexit

-ndb-filenamedbfilename

-sSCHEMAdbschemafilename

Кромевложенныхпарсеров,вэтомпримеретакжеестьнескольконовыхвозможностейargparse.

metavar

Впарсереcreate_parserиспользуетсяновыйаргумент-metavar:

create_parser.add_argument('-n',metavar='db-filename',dest='name',

default=DFLT_DB_NAME,help='dbfilename')

create_parser.add_argument('-s',dest='schema',default=DFLT_DB_SCHEMA,

help='dbschemafilename')

Аргументmetavarпозволяетуказыватьимяаргументадлявыводавсообщенииusageиhelp:

Модульargparse

603

Page 604: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythonparse_dhcp_snooping.pycreate_db-h

usage:parse_dhcp_snooping.pycreate_db[-h][-ndb-filename][-sSCHEMA]

optionalarguments:

-h,--helpshowthishelpmessageandexit

-ndb-filenamedbfilename

-sSCHEMAdbschemafilename

Посмотритенаразницумеждуопциями-nи-s:

послеопции-n,ивusage,ивhelp,указываетсяимя,котороеуказановпараметреmetavarпослеопции-sуказываетсяимяпеременной,вкоторуюсохраняетсязначение

nargs

Впарсереadd_parserиспользуетсяnargs:

add_parser.add_argument('filename',nargs='+',help='file(s)toaddtodb')

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

Сообщениеhelp,втакомслучае,выглядиттак:

$pythonparse_dhcp_snooping.pyadd-h

usage:parse_dhcp_snooping.pyadd[-h][--dbDB_FILE][-s]

filename[filename...]

positionalarguments:

filenamefile(s)toaddtodb

optionalarguments:

-h,--helpshowthishelpmessageandexit

--dbDB_FILEdbname

-saddswitchdataifset,elseaddnormaldata

Еслипередатьнесколькофайлов,онипопадутвсписок.А,таккакфункцияadd,простовыводитименафайлов,выводполучитсятаким:

Модульargparse

604

Page 605: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythonparse_dhcp_snooping.pyaddfilenametest1.txttest2.txt

Readinginfofromfile(s)

filename,test1.txt,test2.txt

Addingdatatodbdhcp_snooping.db

nargsподдерживаеттакиезначения:

N-должнобытьуказанноеколичествоаргументов.Аргументыбудутвсписке(даже,еслиуказан1)?-0или1аргумент*-всеаргументыпопадутвсписок+-всеаргумнетыпопадутвсписок,нодолженбытьпередан,хотябы,одинаргумент

choices

Впарсереget_parserиспользуетсяchoices:

get_parser.add_argument('-k',dest="key",

choices=['mac','ip','vlan','interface','switch'],

help='hostkey(parameter)tosearch')

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

Дляэтогопарсера,helpвыглядиттак:

$pythonparse_dhcp_snooping.pyget-h

usage:parse_dhcp_snooping.pyget[-h][--dbDB_FILE]

[-k{mac,ip,vlan,interface,switch}]

[-vVALUE][-a]

optionalarguments:

-h,--helpshowthishelpmessageandexit

--dbDB_FILEdbname

-k{mac,ip,vlan,interface,switch}

hostkey(parameter)tosearch

-vVALUEvalueofkey

-ashowdbcontent

А,есливыбратьнеправильныйвариант:

Модульargparse

605

Page 606: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

$pythonparse_dhcp_snooping.pyget-ktest

usage:parse_dhcp_snooping.pyget[-h][--dbDB_FILE]

[-k{mac,ip,vlan,interface,switch}]

[-vVALUE][-a]

parse_dhcp_snooping.pyget:error:argument-k:invalidchoice:'test'(choosefrom'm

ac','ip','vlan','interface','switch')

Вданномпримереважноуказатьвариантынавыбор,таккакзатем,наоснованиивыбранноговарианта,генерируетсяSQL-запрос.И,благодаряchoices,нетвозможноуказатькакой-топараметр,кромеразрешенных.

Импортпарсера

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

if__name__=='__main__':

args=parser.parse_args()

args.func(args)

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

Попробуемимпортироватьпарсервдругойфайл(файлcall_pds.py):

fromparse_dhcp_snoopingimportparser

args=parser.parse_args()

args.func(args)

Вызовсообщенияhelp:

$pythoncall_pds.py-h

usage:call_pds.py[-h]{create_db,add,get}...

optionalarguments:

-h,--helpshowthishelpmessageandexit

subcommands:

validsubcommands

{create_db,add,get}description

create_dbcreatenewdb

addadddatatodb

getgetdatafromdb

Модульargparse

606

Page 607: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Вызоваргумента:

$pythoncall_pds.pyaddtest.txttest2.txt

Readinginfofromfile(s)

test.txt,test2.txt

Addingdatatodbdhcp_snooping.db

Всёработаетбезпроблем.

Передачааргументоввручную

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

Аргументыможнопередатькаксписок,привызовеметодаparse_args()(файлcall_pds2.py):

fromparse_dhcp_snoopingimportparser,get

args=parser.parse_args('addtest.txttest2.txt'.split())

args.func(args)

Необходимоиспользоватьметодsplit(),таккакметодparse_args,ожидаетсписокаргументов.

Результатбудеттаким,какеслибыскриптбылвызвансаргументами:

$pythoncall_pds2.py

Readinginfofromfile(s)

test.txt,test2.txt

Addingdatatodbdhcp_snooping.db

Модульargparse

607

Page 608: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МодульipaddressМодульipaddressможетпригодитсядляработысIP-адресами.

ОнневходитвстандартнуюбиблиотекуPython,поэтомуегонужноустановить:

$pipinstallipaddress

Дляработысмодулемipaddress,нужно,чтобыстроки,вкоторыхописываетсяIP-адрес,быливформатеunicode.

Дляэтого,надолибоконвертироватьстрокивunicode(еслиадресзадаетсявручную):

ipaddress.ip_address(u'1.2.3.4')

илитак:

ipaddress.ip_address(unicode('1.2.3.4'))

либоимпортироватьunicode_literalsтакимобразом:

from__future__importunicode_literals

Подробнееонюансахиспользованияunicode_literalsвPython2

Впоследнемслучае,всестрокибудутunicode.

Такоеособенностисвязаныстем,чтомодульipaddressсоздавалсядляPython3.Авнёмвсестрокиunicode.

ipaddress.ip_address()

Функцияipaddress.ip_address()позволяетсоздаватьобъектIPv4AddressилиIPv6Address,соответственно.

IPv4адрес:

Модульipaddress

608

Page 609: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[1]:importipaddress

In[2]:ipv4=ipaddress.ip_address(u'10.0.1.1')

In[3]:ipv4

Out[3]:IPv4Address(u'10.0.1.1')

In[4]:printipv4

10.0.1.1

Уобъектаестьнесколькометодовиатрибутов:

In[5]:ipv4.

ipv4.compressedipv4.is_loopbackipv4.is_unspecifiedipv4.version

ipv4.explodedipv4.is_multicastipv4.max_prefixlen

ipv4.is_globalipv4.is_privateipv4.packed

ipv4.is_link_localipv4.is_reservedipv4.reverse_pointer

Спомощьюатрибутовis_можнопроверитьккакомудиапазонупринадлежитадрес:

In[6]:ipv4.is_loopback

Out[6]:False

In[7]:ipv4.is_multicast

Out[7]:False

In[8]:ipv4.is_reserved

Out[8]:False

In[9]:ipv4.is_private

Out[9]:True

Сполученнымиобъектами,можновыполнятьразличныеоперации:

Модульipaddress

609

Page 610: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[10]:ip1=ipaddress.ip_address(u'10.0.1.1')

In[11]:ip2=ipaddress.ip_address(u'10.0.2.1')

In[12]:ip1>ip2

Out[12]:False

In[13]:ip2>ip1

Out[13]:True

In[14]:ip1==ip2

Out[14]:False

In[15]:ip1!=ip2

Out[15]:True

In[16]:str(ip1)

Out[16]:'10.0.1.1'

In[17]:int(ip1)

Out[17]:167772417

In[18]:ip1+5

Out[18]:IPv4Address(u'10.0.1.6')

In[19]:ip1-5

Out[19]:IPv4Address(u'10.0.0.252')

ipaddress.ip_network()

Функцияipaddress.ip_network()позволяетсоздатьобъект,которыйописываетсеть(IPv4илиIPv6).

СетьIPv4:

In[20]:subnet1=ipaddress.ip_network(u'80.0.1.0/28')

Какиуадреса,усетиестьразличныеатрибутыиметоды:

Модульipaddress

610

Page 611: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[21]:subnet1.broadcast_address

Out[21]:IPv4Address(u'80.0.1.15')

In[22]:subnet1.with_netmask

Out[22]:u'80.0.1.0/255.255.255.240'

In[23]:subnet1.with_hostmask

Out[23]:u'80.0.1.0/0.0.0.15'

In[24]:subnet1.prefixlen

Out[24]:28

In[25]:subnet1.num_addresses

Out[25]:16

Методhosts()возвращаетгенератор,поэтому,чтобыпосмотретьвсехосты,надоприменитьфункциюlist:

In[26]:list(subnet1.hosts())

Out[26]:

[IPv4Address(u'80.0.1.1'),

IPv4Address(u'80.0.1.2'),

IPv4Address(u'80.0.1.3'),

IPv4Address(u'80.0.1.4'),

IPv4Address(u'80.0.1.5'),

IPv4Address(u'80.0.1.6'),

IPv4Address(u'80.0.1.7'),

IPv4Address(u'80.0.1.8'),

IPv4Address(u'80.0.1.9'),

IPv4Address(u'80.0.1.10'),

IPv4Address(u'80.0.1.11'),

IPv4Address(u'80.0.1.12'),

IPv4Address(u'80.0.1.13'),

IPv4Address(u'80.0.1.14')]

Методsubnetsпозволяетразбиватьнаподсети.Поумолчанию,онразбиваетнадвеподсети:

In[27]:list(subnet1.subnets())

Out[27]:[IPv4Network(u'80.0.1.0/29'),IPv4Network(u'80.0.1.8/29')]

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

Модульipaddress

611

Page 612: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[28]:list(subnet1.subnets(prefixlen_diff=2))

Out[28]:

[IPv4Network(u'80.0.1.0/30'),

IPv4Network(u'80.0.1.4/30'),

IPv4Network(u'80.0.1.8/30'),

IPv4Network(u'80.0.1.12/30')]

Или,спомощьюпараметраnew_prefix,простоуказатькакаямаскадолжнабытьуподсетей:

In[29]:list(subnet1.subnets(new_prefix=30))

Out[29]:

[IPv4Network(u'80.0.1.0/30'),

IPv4Network(u'80.0.1.4/30'),

IPv4Network(u'80.0.1.8/30'),

IPv4Network(u'80.0.1.12/30')]

In[30]:list(subnet1.subnets(new_prefix=29))

Out[30]:[IPv4Network(u'80.0.1.0/29'),IPv4Network(u'80.0.1.8/29')]

ПоIP-адресамвсетиможнопроходитсявцикле:

In[31]:foripinsubnet1:

....:printip

....:

80.0.1.0

80.0.1.1

80.0.1.2

80.0.1.3

80.0.1.4

80.0.1.5

80.0.1.6

80.0.1.7

80.0.1.8

80.0.1.9

80.0.1.10

80.0.1.11

80.0.1.12

80.0.1.13

80.0.1.14

80.0.1.15

Илиобращатьсякконкретномуадресу:

Модульipaddress

612

Page 613: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[32]:subnet1[0]

Out[32]:IPv4Address(u'80.0.1.0')

In[33]:subnet1[5]

Out[33]:IPv4Address(u'80.0.1.5')

ТакимобразомможнопроверятьнаходитсялиIP-адресвсети:

In[34]:ip1=ipaddress.ip_address(u'80.0.1.3')

In[35]:ip1insubnet1

Out[35]:True

ipaddress.ip_interface()

Функцияipaddress.ip_interface()позволяетсоздаватьобъектIPv4InterfaceилиIPv6Interface,соответственно.

Попробуемсоздатьинтерфейс:

In[36]:int1=ipaddress.ip_interface(u'10.0.1.1/24')

ИспользуяметодыобъектаIPv4Interface,можнополучатьадрес,маскуилисетьинтерфеса:

In[37]:int1.ip

Out[37]:IPv4Address(u'10.0.1.1')

In[38]:int1.network

Out[38]:IPv4Network(u'10.0.1.0/24')

In[39]:int1.netmask

Out[39]:IPv4Address(u'255.255.255.0')

Примериспользованиямодуля

Таккаквмодульвстроеныпроверкикорректностиадресов,можноимипользоваться,например,чтобыпроверитьявляетсялиадресадресомсетиилихоста:

Модульipaddress

613

Page 614: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[40]:IP1=u'10.0.1.1/24'

In[41]:IP2=u'10.0.1.0/24'

In[42]:defcheck_if_ip_is_network(ip_address):

....:try:

....:ipaddress.ip_network(ip_address)

....:returnTrue

....:exceptValueError:

....:returnFalse

....:

In[43]:check_if_ip_is_network(IP1)

Out[43]:False

In[44]:check_if_ip_is_network(IP2)

Out[44]:True

Модульipaddress

614

Page 615: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ПолезныефункцииВэтомразделеописанытакиефункции:

formatsortedlambdazipmapfilterall,any

Полезныефункции

615

Page 616: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ФункцияsortedФункцияsorted()-возвращаетновыйотсортированныйсписок,которыйполученизпоследовательности,котораябылапереданакакаргумент.Функциятакжеподдерживаетдополнительныепараметры,которыепозволяютуправлятьсортировкой.

Первыйаспектнакоторыйважнообратитьвнимание-sortedвозвращаетсписок.

Соответственно,еслисортироватьсписокэлементов,товозвращаетсяновыйсписок:

In[1]:list_of_words=['one','two','list','','dict']

In[2]:sorted(list_of_words)

Out[2]:['','dict','list','one','two']

Сортировкакортежа:

In[3]:tuple_of_words=('one','two','list','','dict')

In[4]:sorted(tuple_of_words)

Out[4]:['','dict','list','one','two']

Сортировкамножества:

In[5]:set_of_words={'one','two','list','','dict'}

In[6]:sorted(set_of_words)

Out[6]:['','dict','list','one','two']

Сортировкастроки:

In[7]:string_to_sort='longstring'

In[8]:sorted(string_to_sort)

Out[8]:['','g','g','i','l','n','n','o','r','s','t']

Еслипередатьsortedсловарь,функциявернетотсортированныйсписокключей:

Функцияsorted

616

Page 617: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[9]:dict_for_sort={

...:'id':1,

...:'name':'London',

...:'IT_VLAN':320,

...:'User_VLAN':1010,

...:'Mngmt_VLAN':99,

...:'to_name':None,

...:'to_id':None,

...:'port':'G1/0/11'

...:}

In[10]:sorted(dict_for_sort)

Out[10]:

['IT_VLAN',

'Mngmt_VLAN',

'User_VLAN',

'id',

'name',

'port',

'to_id',

'to_name']

reverse

Флагreverseпозволяетуправлятьпорядкомсортировки.Поумолчаниюсортировкабудетповозрастаниюэлементов.

Указавфлагreverse,можнопоменятьпорядок:

In[11]:list_of_words=['one','two','list','','dict']

In[12]:sorted(list_of_words)

Out[12]:['','dict','list','one','two']

In[13]:sorted(list_of_words,reverse=True)

Out[13]:['two','one','list','dict','']

key

Спомощьюпараметраkeyможноуказыватькакименновыполнятьсортировку.Параметрkeyожидаетфункцию,спомощьюкоторойдолжнобытьвыполненосравнение.

Например,такимобразомможноотсортироватьсписокстрокподлинестроки:

Функцияsorted

617

Page 618: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[14]:list_of_words=['one','two','list','','dict']

In[15]:sorted(list_of_words,key=len)

Out[15]:['','one','two','list','dict']

Еслинужноотсортироватьключисловаря,ноприэтомигнорироватьрегистрстрок:

In[16]:dict_for_sort={

...:'id':1,

...:'name':'London',

...:'IT_VLAN':320,

...:'User_VLAN':1010,

...:'Mngmt_VLAN':99,

...:'to_name':None,

...:'to_id':None,

...:'port':'G1/0/11'

...:}

In[17]:sorted(dict_for_sort,key=str.lower)

Out[17]:

['id',

'IT_VLAN',

'Mngmt_VLAN',

'name',

'port',

'to_id',

'to_name',

'User_VLAN']

Кромевстроенныхфункций,можнотакжеиспользоватьсвоифункции.Такжетутудобноиспользоватьанонимнуюфункциюlambda.

Также,спомощьюпараметраkey,можносортироватьобъектынепопервомуэлементу,аполюбомудругому.Нодляэтогонадоиспользоватьилифункциюlambdaилиспециальныефункцииизмодуляoperator.

Например,чтобыотсортироватьсписоккортежейиздвухэлементовповторомуэлементу,надоиспользоватьтакойприем:

Функцияsorted

618

Page 619: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[18]:fromoperatorimportitemgetter

In[19]:list_of_tuples=[('IT_VLAN',320),

...:('Mngmt_VLAN',99),

...:('User_VLAN',1010),

...:('DB_VLAN',11)]

In[20]:sorted(list_of_tuples,key=itemgetter(1))

Out[20]:[('DB_VLAN',11),('Mngmt_VLAN',99),('IT_VLAN',320),('User_VLAN',1010)]

Функцияsorted

619

Page 620: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

АнонимнаяфункцияlambdaВPythonвыражениеlambdaпозволяетсоздаватьанонимныефункции-функции,которыенепривязаныкимени.

Ванонимнойфункцииlambda:

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

Стандартнаяфункция:

In[1]:defsum_arg(a,b):returna+b

In[2]:sum_arg(1,2)

Out[2]:3

Аналогичнаяанонимнаяфункцияlanbda:

In[3]:sum_arg=lambdaa,b:a+b

In[4]:sum_arg(1,2)

Out[4]:3

Обратитевнимание,чтовопределенииlambdaнетоператораreturn,таккаквэтойфункцииможетбытьтолькоодновыражение,котороевсегдавозвращаетзначениеизавершаетработуфункции.

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

Например,вфункцииsortedlambdaможноиспользоватьдляуказанияключадлясортировки:

In[5]:list_of_tuples=[('IT_VLAN',320),

...:('Mngmt_VLAN',99),

...:('User_VLAN',1010),

...:('DB_VLAN',11)]

In[6]:sorted(list_of_tuples,key=lambdax:x[1])

Out[6]:[('DB_VLAN',11),('Mngmt_VLAN',99),('IT_VLAN',320),('User_VLAN',1010)]

Функцияlambda

620

Page 621: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Такжефункцияlambdaпригодитсявфункцияхmapиfilter,которыебудутрассматриватьсявследующихразделах.

Функцияlambda

621

Page 622: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ФункцияzipФункцияzip():

навходфункциипередаютсяпоследовательностиzip()возвращаетсписоккортежей,вкоторомn-ыйкортежсостоитизn-ыхэлементовпоследовательностей,которыебылипереданыкакаргументы

например,десятыйкортежбудетсодержатьдесятыйэлементкаждойизпереданныхпоследовательностей

еслинавходбылипереданыпоследовательностиразнойдлинны,товсеонибудутотрезаныпосамойкороткойпоследовательностипорядокэлементовсоблюдается

Примериспользованияzip:

In[1]:a=[1,2,3]

In[2]:b=[100,200,300]

In[3]:zip(a,b)

Out[3]:[(1,100),(2,200),(3,300)]

Использованиеzip()соспискамиразнойдлины:

In[4]:a=[1,2,3,4,5]

In[5]:b=[10,20,30,40,50]

In[6]:c=[100,200,300]

In[7]:zip(a,b,c)

Out[7]:[(1,10,100),(2,20,200),(3,30,300)]

Использованиеzipдлясозданиясловаря:

Функцияzip

622

Page 623: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[8]:d_keys=['hostname','location','vendor','model','IOS','IP']

In[8]:d_values=['london_r1','21NewGlobeWalk','Cisco','4451','15.4','10.255

.0.1']

In[9]:zip(d_keys,d_values)

Out[9]:

[('hostname','london_r1'),

('location','21NewGlobeWalk'),

('vendor','Cisco'),

('model','4451'),

('IOS','15.4'),

('IP','10.255.0.1')]

In[10]:dict(zip(d_keys,d_values))

Out[10]:

{'IOS':'15.4',

'IP':'10.255.0.1',

'hostname':'london_r1',

'location':'21NewGlobeWalk',

'model':'4451',

'vendor':'Cisco'}

In[11]:r1=dict(zip(d_keys,d_values))

Функцияzip

623

Page 624: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ФункцияmapФункцияmapприменяетфункциюккаждомуэлементупоследовательностиивозвращаетсписокрезультатов.

Например,спомощьюmapможновыполнятьпреобразованияэлементов.Перевестивсестрокивверхнийрегистр:

In[1]:list_of_words=['one','two','list','','dict']

In[2]:map(str.upper,list_of_words)

Out[2]:['ONE','TWO','LIST','','DICT']

Конвертациявчисла:

In[3]:list_of_str=['1','2','5','10']

In[4]:map(int,list_of_str)

Out[4]:[1,2,5,10]

Вместесmapудобноиспользоватьlambda:

In[5]:vlans=[100,110,150,200,201,202]

In[6]:map(lambdax:'vlan{}'.format(x),vlans)

Out[6]:['vlan100','vlan110','vlan150','vlan200','vlan201','vlan202']

Еслифункция,которуюиспользуетmap(),ожидаетдвааргумента,топередаютсядвасписка:

In[7]:nums=[1,2,3,4,5]

In[8]:nums2=[100,200,300,400,500]

In[9]:map(lambdax,y:x*y,nums,nums2)

Out[9]:[100,400,900,1600,2500]

Функцияmap

624

Page 625: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ФункцияfilterФункцияfilter()применяетфункциюковсемэлементампоследовательности,ивозвращаеттеобъекты,длякоторыхфункциявернулаTrue.

Например,вернутьтолькотестроки,вкоторыхнаходятсячисла:

In[1]:list_of_strings=['one','two','list','','dict','100','1','50']

In[2]:filter(str.isdigit,list_of_strings)

Out[2]:['100','1','50']

Например,изспискачиселоставитьтольконечетные:

In[3]:filter(lambdax:x%2,[10,111,102,213,314,515])

Out[3]:[111,213,515]

Аналогично,толькочетные:

In[4]:filter(lambdax:notx%2,[10,111,102,213,314,515])

Out[4]:[10,102,314]

Изспискасловоставитьтолькоте,укоторыхколичествобуквбольшедвух:

In[5]:list_of_words=['one','two','list','','dict']

In[6]:filter(lambdax:len(x)>2,list_of_words)

Out[6]:['one','two','list','dict']

Функцияfilter

625

Page 626: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ФункцияallФункцияall()возвращаетTrue,есливсеэлементыистина(илиобъектпустой).

In[1]:all([False,True,True])

Out[1]:False

In[2]:all([True,True,True])

Out[2]:True

In[3]:all([])

Out[3]:True

Например,спомощьюallможнопроверитьвселиоктетывIP-адресеявляютсячислами:

In[4]:IP='10.0.1.1'

In[5]:all(i.isdigit()foriinIP.split('.'))

Out[5]:True

In[6]:all(i.isdigit()foriin'10.1.1.a'.split('.'))

Out[6]:False

ФункцияanyФункцияany()возвращаетTrue,еслихотябыодинэлементистина(илиобъектпустой).

In[7]:any([False,True,True])

Out[7]:True

In[8]:any([False,False,False])

Out[8]:False

In[9]:any([])

Out[9]:False

In[10]:any(i.isdigit()foriin'10.1.1.a'.split('.'))

Out[10]:True

Функцииanyиall

626

Page 627: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Функцииanyиall

627

Page 628: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

СоглашениеобименахВPythonестьопределенныесоглашенияобименованииобъектов.

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

Вэтомразделеописаныневсеправила.ПодробнееможнопочитатьвдокументеPEP8наанглийскомилинарусском.

Именапеременных

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

Именапеременныхобычнопишутсяполностьюбольшимиилималенькимибуквами.Впределаходногоскрипта/модуля/пакеталучшепридерживатьсяодногоизвариантов.

Еслипеременные-константыдлямодуля,толучшеиспользоватьименанаписанныезаглавнымибуквами:

DB_NAME='dhcp_snooping.db'

TESTING=True

Дляобычныхпеременныхлучшеиспользоватьименавнижнемрегистре:

db_name='dhcp_snooping.db'

testing=True

Именамодулейипакетов

Именамодулейипакетовзадаютсямаленькимибуквами.

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

Именафункций

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

Соглашениеобименах

628

Page 629: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

defignore_command(command,ignore):

ignore_command=False

forwordinignore:

ifwordincommand:

returnTrue

returnignore_command

Именаклассов

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

classCiscoSwitch:

def__init__(self,name,vendor='cisco',model='3750'):

self.name=name

self.vendor=vendor

self.model=model

Соглашениеобименах

629

Page 630: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Подчеркиваниекакимя

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

Например,еслиизстрокиlineнадополучитьMAC-адрес,IP-адрес,VLANиинтерфейсиотброситьостальныеполя,можноиспользоватьтакойвариант:

In[1]:line='00:09:BB:3D:D6:5810.1.10.286250dhcp-snooping10FastEthernet0

/1'

In[2]:mac,ip,_,_,vlan,intf=line.split()

In[3]:printmac,ip,vlan,intf

00:09:BB:3D:D6:5810.1.10.210FastEthernet0/1

Такаязаписьговоритотом,чтонамненужнытретийичетвертыйэлементы.

Можносделатьтак:

In[4]:mac,ip,lease,entry_type,vlan,intf=line.split()

Нотогдадальшеможетбытьнепонятнопочемупеременныеleaseиentry_typeнеиспользуютсядальше.Еслипонятнейиспользоватьимена,толучшеназватьпеременныеименамивроде-ignored.

Аналогичныйприемможетиспользоваться,когдапеременнаяцикланенужна:

In[5]:[0for_inrange(10)]

Out[5]:[0,0,0,0,0,0,0,0,0,0]

Подчеркиваниевинтерпретаторе

Винтерпретатореpythonиipythonподчеркиваниеиспользуетсядляполучениярезультатапоследнеговыражения

Подчеркиваниевименах

630

Page 631: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[6]:[0for_inrange(10)]

Out[6]:[0,0,0,0,0,0,0,0,0,0]

In[7]:_

Out[7]:[0,0,0,0,0,0,0,0,0,0]

In[8]:a=_

In[9]:a

Out[9]:[0,0,0,0,0,0,0,0,0,0]

Одноподчеркивание

Одноподчеркиваниепередименем

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

Например,еслиодноподчеркиваниеуказановименифункцииилиметода,этоозначает,тоэтотобъектявляетсявнутреннейособенностьюреализацииинестоитегоиспользоватьнапрямую.

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

Например,вфайлеexample.pyтакиепеременныеифункции:

db_name='dhcp_snooping.db'

_path='/home/nata/pyneng/'

deffunc1(arg):

printarg

def_func2(arg):

printarg

Еслиимпортироватьвсеобъектыизмодуля,тоте,которыеначинаютсясподчеркиваниянебудутимпортированы:

Подчеркиваниевименах

631

Page 632: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[7]:fromexampleimport*

In[8]:db_name

Out[8]:'dhcp_snooping.db'

In[9]:_path

...

NameError:name'_path'isnotdefined

In[10]:func1(1)

1

In[11]:_func2(1)

...

NameError:name'_func2'isnotdefined

Одноподчеркиваниепослеимени

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

Пример:

In[12]:line='00:09:BB:3D:D6:5810.1.10.286250dhcp-snooping10FastEthernet

0/1'

In[13]:mac,ip,lease,type_,vlan,intf=line.split()

Дваподчеркивания

Дваподчеркиванияпередименем

Дваподчеркиванияпередименемметода,используютсянепростокакдоговоренность.Такиеименатрасформируютсявформат"имякласса+имяметода".Этопозволяетсоздаватьуникальныеметодыиатрибутыклассов.

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

Подчеркиваниевименах

632

Page 633: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[14]:classSwitch(object):

...:__quantity=0

...:def__configure(self):

...:pass

...:

In[15]:dir(Switch)

Out[15]:

['_Switch__configure','_Switch__quantity',...]

Хотяметодысоздавалисьбезприставки_Switch,онабыладобавлена.

Еслисоздатьподкласс,тометод__configureнеперепишетметодродительскогоклассаSwitch:

In[16]:classCiscoSwitch(Switch):

...:__quantity=0

...:def__configure(self):

...:pass

...:

In[17]:dir(CiscoSwitch)

Out[17]:

['_CiscoSwitch__configure','_CiscoSwitch__quantity','_Switch__configure','_Switch__

quantity',...]

Дваподчеркиванияпередипослеимени

Такимобразомобозначаютсяспециальныепеременныеиметоды.

Например,вмодулеPythonестьтакиеспециальныепеременные:

__name__-этапеременнаяравнастроке__main__,когдаскриптзапускаетсянапрямую.Иравенименимодуля,когдаимпортируется__file__-этапеременнаяравнаименискрипта,которыйбылзапущеннапрямую.Иравнаполномупутикмодулю,когдаонимпортируется

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

Подчеркиваниевименах

633

Page 634: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

defmultiply(a,b):

returna*b

if__name__=="__main__":

printmultiply(3,5)

Апеременная__file__можетбытьполезнавопределениитекущегопутикфайлускрипта:

importos

print'__file__',__file__

printos.path.abspath(__file__)

Выводбудеттаким:

__file__example2.py

/Users/natasha/Desktop/current/pyneng_things/example2.py

Крометого,такимобразомвPythonобозначаютсяспециальныеметоды.ЭтиметодывызываютсяприиспользованиифункцийиоператоровPythonипозволяютреализоватьопределенныйфункционал.

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

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

Ещёодинспециальныйметод__str__вызывается,когдаиспользуетсяоператорprintиливызываетсяфункцияstr().Еслинеобходимо,чтобыприэтомотображениебыловопределенномвиде,надосоздатьэтотметодвклассе:

Подчеркиваниевименах

634

Page 635: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

In[10]:classSwitch(object):

...:

...:defset_name(self,name):

...:self.name=name

...:

...:def__configure(self):

...:pass

...:

...:def__str__(self):

...:return'Switch{}'.format(self.name)

...:

In[11]:sw1=Switch()

In[12]:sw1.set_name('sw1')

In[13]:printsw1

Switchsw1

In[14]:str(sw1)

Out[14]:'Switchsw1'

ТакихспециальныхметодоввPythonоченьмного.Несколькополезныхссылок,гдеможнопочитатьпроконкретныйметод:

документацияDiveIntoPython3-хотятутпримерыдляPython3,большинствометодовработаютаналогично.Вэтойкнигеотличнорасписаныэтыметоды.

Подчеркиваниевименах

635

Page 636: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ДополнительныересурсыКакправило,информациютяжелоусвоитьспервогораза.Особенно,новуюинформацию.

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

ВэтомразделесобраныссылкинаразличныересурсыпоPython,связанныессетямиинет.Этирусурсыпозволятвамповторитьинформацию,почитать(посмотреть,послушать)тожесамое,нодругимисловами.Крометого,данынесколькоресурсовдляпродолженияобучения.

ПодкастыобавтоматизациисPythonХорошоподходятдлявдохновлениятемойавтоматизации

PacketPushersShow176–IntroToPython&AutomationForNetworkEngineersPacketPushersShow198–KirkByersOnNetworkAutomationWithPython&AnsiblePacketPushersShow270:Design&Build9:AutomationWithPythonAndNetmikoPQShow99:Netmiko&NAPALMForNetworkAutomationNetworkautomationtoolswithJasonEdelmanonSofwareGoneWildPacketPushersShow332:Don’tBelieveTheProgrammingHype-отличныйподкастобавтоматизации,программировании,скриптингеикаквсёэтоотноситсяксетевыминженерам.PacketPushersShow333:Automation&OrchestrationInNetworking

Блоги(python+network)KirkByersJasonEdelmanMattOswaltMichaelKashinHenryÖlsnerMatWood

Полезныессылки

636

Page 637: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Платныеибесплатныекурсы(python+network)

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

Бесплатныекурсы:

БесплатныйemailкурсотKirkByersNetworkProgrammabilityandNetworkAutomationusingGNS3andPythonКурсынаCiscoDevNet

Платныекурсы

PythonforNetworkEngineers(курсотKirkByers)КурсыотNetworktoCodePythonProgrammingforNetworkEngineers(INE)NetworkAutomationwithAnsible(INE)PythonProgrammingForNetworkEngineers(Udemy)PythonNetworkProgramming-Part1:Build7PythonApps(GNS3Academy)NetworkAutomationusingPythonforEngineers(ehackingacademy)Networkautomationwebinars(IvanPepelnjak)

Полезныессылки

637

Page 638: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

МатериалыпотемамкурсаТутсобраныссылкипотемамкурса.Большаячастьизнихпересекаютсястемамикурса,ноестьидополнения.Влюбомслучае,дажете,которыепересекаютсяполезнопочитать.

Ссылкинастатьиидругиересурсы

ОсновыPython

КнигипоPython:

AByteofPythonэтажекниганарусском

Python101LearnPythontheHardWay

КурсыпоосновамPython:

ПрограммированиенаPython

Регулярныевыражения

Статьи:

ParseCiscoIOSconfigurationsusingRegExUsingPythontogenerateCiscoconfigs

Сайтдляпроверкирегулярныхвыражений:

regex101

Базыданных

БолееподробноеописаниевозможностейSQLite:

SQLitetutorial

Telnet,SSH

Статьи:

Материалыпотемамкурса

638

Page 639: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

NetmikoLibraryAutomateSSHconnectionswithnetmikoNetworkAutomationUsingPython:BGPConfiguration

Jinja2

Статьи:

NetworkConfigurationTemplatesUsingJinja2.MattOswaltPythonAndJinja2Tutorial.JeremySchulmanConfigurationGeneratorwithPythonandJinja2CustomfiltersforaJinja2basedConfigGenerator

TextFSM

Статьи:

ProgrammaticAccesstoCLIDeviceswithTextFSM.JasonEdelman(26.02.2015)-основыTextFSMиидеиоразвитии,которыелегливосновумодуляntc-ansibleParseCLIoutputswithTextFSM.HenryÖlsner(24.08.2015)-примериспользованияTextFSMдляразборабольшогофайласвыводомshinventory.ПодробнееобъясняетсясинтаксисTextFSMCreatingTemplatesforTextFSMandntc_show_command.JasonEdelman(27.08.2015)-подробнеерассматриваетсясинтаксисTextFSMипоказаныпримерыиспользованиямодуляntc-ansible(обратитевнимание,чтосинтаксисмодуляуженемногоизменился)TextFSMandStructuredData.KirkByers(22.10.2015)-вводнаястатьяоTextFSM.Тутнеописываетсясинтаксис,нодаетсяобщеепредставлениеотом,чтотакоеTextFSMипримерегоиспользования

Проекты,которыеиспользуютTextFSM:

Модульntc-ansible

ШаблоныTextFSM(измодуляntc-ansible):

ntc-templates

Ansible

УAnsibleоченьхорошаядокументация:

http://docs.ansible.com/ansible/

Материалыпотемамкурса

639

Page 640: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ОтличныевидеоотAnsible:

AUTOMATINGYOURNETWORKРепозиторийспримерамиизвебинара

Ansibleбезпривязкиксетевомуоборудованию

Оченьхорошаясериявидео,странскриптомихорошимиссылками:

https://sysadmincasts.com/episodes/43-19-minutes-with-ansible-part-1-4

ПримерыиспользованияAnsible:

https://github.com/ansible/ansible-examples

ПримерыPlaybookсдемонстрациейразличныхвозможностей

https://github.com/ansible/ansible-examples/tree/master/language_features

Ansiblefornetworkdevices

Обращайтевниманиенавремянаписаниястатьи.ВAnsibleсущественноизменилисьмодулидляработыссетевымоборудованием.Ивстатьяхмогутбытьещёстарыепримеры.

NetworkConfigTemplatingusingAnsible(KirkByers):

https://pynet.twb-tech.com/blog/ansible/ansible-cfg-template.htmlhttps://pynet.twb-tech.com/blog/ansible/ansible-cfg-template-p2.htmlhttps://pynet.twb-tech.com/blog/ansible/ansible-cfg-template-p3.html

Статьи:

http://jedelman.com/home/ansible-for-networking/http://jedelman.com/home/network-automation-with-ansible-dynamically-configuring-interface-descriptions/http://www.packetgeek.net/2015/08/using-ansible-to-push-cisco-ios-configurations/

Оченьхорошаясериястатей.Постепенноповышаетсяуровеньсложности:

http://networkop.github.io/blog/2015/06/24/ansible-intro/http://networkop.github.io/blog/2015/07/03/parser-modules/http://networkop.github.io/blog/2015/07/10/test-verification/http://networkop.github.io/blog/2015/07/17/tdd-quickstart/http://networkop.github.io/blog/2015/08/14/automating-legacy-networks/http://networkop.github.io/blog/2015/08/26/automating-network-build-p1/

Материалыпотемамкурса

640

Page 642: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

Продолжениеобучения

Pythonбезпривязкиксетевомуоборудованию

ЕсливаминтересноразвиватьсвоизнанияпоPythonвцелом,ниженесколькополезныхссылок.

TheHitchhiker’sGuidetoPython!BestPythonResources-подборкассылокнахорошиересурсыпоPythonAutomatetheBoringStuffwithPythonProblemSolvingwithAlgorithmsandDataStructuresusingPython-отличнаякнигапоструктурамданныхиалгоритмам.Многопримеровидомашнихзаданий.

нарусском

Онлайнкурсы:

MITx-6.00.1xIntroductiontoComputerScienceandProgrammingUsingPython

Видеокурсы:

PythonотComputerScienceCenter

Сайтысзадачами:

CodeEvalHackerRank

Python+network

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

Еслиговоритьоразвитиидальшеприменимоксетямисетевомуоборудованию,тотутвариантовмного.Это,втомчисле,иразвитиезнанийпоPythonвцелом,нотакжеиболееспецифическиевещи,такиекакдоступксетевомуоборудованиючерезAPI,идр.Нижессылкинанекоторыепроекты,которыевасмогутзаинтересовать.

Проекты:

ScapyCiscoConfParse

Продолжениеобучения

642

Page 644: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

ОтзывычитателейислушателейкурсаНаxgu.ruнаходиласьинформацияизпервыходинадцатиразделов.Сейчассxgu.ruвсёудаленоиперенесенонаGitBook.

Ильяпроверсиюкурсанаxgu.ru

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

ПростотаиграциозностьописанияавтоматизациипроцессовНаташиСамойленкопозволиламнеоткрытьдверьвранеенедоступныймодный"DevOps".Всвязисэтим,помиморазвитиясвоихпрофессиональныхнавыков,ятакжеполучилзначительныйбонуснарынкетрудаввидедополнительныхзнаний.МнекакчеловекукоторыйизучалнемногоDelphiвуниверситете,даитонедостаточноглубоко,былодовольноинтересноиувлекательноразбиратьсясновойдляменястязей.Подачаматериалакрайне"легка"длявосприятия,инаглядна.Хорошиеиполезныевежедневнойработепримеры.

СпасибоНаташезаотличныйкурс

АлексейКирилловпроонлайнкурс

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

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

Отзывы

644

Page 645: Содержание - ITG.BY · Если в двух словах, то это такой “ccna” по питону. С одной стороны, курс достаточно

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

Отзывы

645