Задания

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

Предупреждение

Начиная с раздела «4. Типы данных в Python» для проверки заданий есть автоматические тесты. Они помогают проверить все ли соответствует поставленной задаче, а также дают обратный отклик по тому, что не соответствует задаче. Как правило, после первого периода адаптации к тестам, становится проще делать задания с тестами. Проверка заданий выполняется с помощью утилиты pyneng. Подробнее о том как работать с утилитой pyneng.

Задание 17.1

Создать функцию write_dhcp_snooping_to_csv, которая обрабатывает вывод команды show dhcp snooping binding из разных файлов и записывает обработанные данные в csv файл.

Аргументы функции:

  • filenames - список с именами файлов с выводом show dhcp snooping binding
  • output - имя файла в формате csv, в который будет записан результат

Функция ничего не возвращает.

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

MacAddress          IpAddress        Lease(sec)  Type           VLAN  Interface
------------------  ---------------  ----------  -------------  ----  --------------------
00:E9:BC:3F:A6:50   100.1.1.6        76260       dhcp-snooping   3    FastEthernet0/20
00:E9:22:11:A6:50   100.1.1.7        76260       dhcp-snooping   3    FastEthernet0/21
Total number of bindings: 2

В итоговом csv файле должно быть такое содержимое:

switch,mac,ip,vlan,interface
sw3,00:E9:BC:3F:A6:50,100.1.1.6,3,FastEthernet0/20
sw3,00:E9:22:11:A6:50,100.1.1.7,3,FastEthernet0/21

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

Проверить работу функции на содержимом файлов sw1_dhcp_snooping.txt, sw2_dhcp_snooping.txt, sw3_dhcp_snooping.txt.

Задание 17.2

В этом задании нужно:

  • взять содержимое нескольких файлов с выводом команды sh version
  • распарсить вывод команды с помощью регулярных выражений и получить информацию об устройстве
  • записать полученную информацию в файл в CSV формате

Для выполнения задания нужно создать две функции.

Функция parse_sh_version:

  • ожидает как аргумент вывод команды sh version одной строкой (не имя файла)
  • обрабатывает вывод, с помощью регулярных выражений
  • возвращает кортеж из трёх элементов:
    • ios - в формате «12.4(5)T»
    • image - в формате «flash:c2800-advipservicesk9-mz.124-5.T.bin»
    • uptime - в формате «5 days, 3 hours, 3 minutes»

У функции write_inventory_to_csv должно быть два параметра:

  • data_filenames - ожидает как аргумент список имен файлов с выводом sh version
  • csv_filename - ожидает как аргумент имя файла (например, routers_inventory.csv), в который будет записана информация в формате CSV

Функция write_inventory_to_csv записывает содержимое в файл, в формате CSV и ничего не возвращает

Функция write_inventory_to_csv должна делать следующее:

  • обработать информацию из каждого файла с выводом sh version:
    • sh_version_r1.txt, sh_version_r2.txt, sh_version_r3.txt
  • с помощью функции parse_sh_version, из каждого вывода должна быть получена информация ios, image, uptime
  • из имени файла нужно получить имя хоста
  • после этого вся информация должна быть записана в CSV файл

В файле routers_inventory.csv должны быть такие столбцы: hostname, ios, image, uptime

В скрипте, с помощью модуля glob, создан список файлов, имя которых начинается на sh_vers. вы можете раскомментировать строку print(sh_version_files), чтобы посмотреть содержимое списка.

Кроме того, создан список заголовков (headers), который должен быть записан в CSV.

import glob

sh_version_files = glob.glob("sh_vers*")
#print(sh_version_files)

headers = ["hostname", "ios", "image", "uptime"]

Задание 17.3

Создать функцию parse_sh_cdp_neighbors, которая обрабатывает вывод команды show cdp neighbors.

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

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

R4>show cdp neighbors

Device ID    Local Intrfce   Holdtme     Capability       Platform    Port ID
R5           Fa 0/1          122           R S I           2811       Fa 0/1
R6           Fa 0/2          143           R S I           2811       Fa 0/0

Функция должна вернуть такой словарь:

{"R4": {"Fa 0/1": {"R5": "Fa 0/1"},
        "Fa 0/2": {"R6": "Fa 0/0"}}}

Интерфейсы должны быть записаны с пробелом. То есть, так Fa 0/0, а не так Fa0/0.

Проверить работу функции на содержимом файла sh_cdp_n_sw1.txt

Задание 17.3a

Создать функцию generate_topology_from_cdp, которая обрабатывает вывод команды show cdp neighbor из нескольких файлов и записывает итоговую топологию в один словарь.

Функция generate_topology_from_cdp должна быть создана с параметрами:

  • list_of_files - список файлов из которых надо считать вывод команды sh cdp neighbor
  • save_to_filename - имя файла в формате YAML, в который сохранится топология.
    • значение по умолчанию - None. По умолчанию, топология не сохраняется в файл
    • топология сохраняется только, если save_to_filename как аргумент указано имя файла

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

Структура словаря должна быть такой:

{"R4": {"Fa 0/1": {"R5": "Fa 0/1"},
        "Fa 0/2": {"R6": "Fa 0/0"}},
 "R5": {"Fa 0/1": {"R4": "Fa 0/1"}},
 "R6": {"Fa 0/0": {"R4": "Fa 0/2"}}}

Интерфейсы должны быть записаны с пробелом. То есть, так Fa 0/0, а не так Fa0/0.

Проверить работу функции generate_topology_from_cdp на списке файлов:

  • sh_cdp_n_sw1.txt
  • sh_cdp_n_r1.txt
  • sh_cdp_n_r2.txt
  • sh_cdp_n_r3.txt
  • sh_cdp_n_r4.txt
  • sh_cdp_n_r5.txt
  • sh_cdp_n_r6.txt

Проверить работу параметра save_to_filename и записать итоговый словарь в файл topology.yaml.

Задание 17.3b

Создать функцию transform_topology, которая преобразует топологию в формат подходящий для функции draw_topology.

Функция ожидает как аргумент имя файла в формате YAML, в котором хранится топология.

Функция должна считать данные из YAML файла, преобразовать их соответственно, чтобы функция возвращала словарь такого вида:

{("R4", "Fa 0/1"): ("R5", "Fa 0/1"),
 ("R4", "Fa 0/2"): ("R6", "Fa 0/0")}

Функция transform_topology должна не только менять формат представления топологии, но и удалять «дублирующиеся» соединения (их лучше всего видно на схеме, которую генерирует функция draw_topology из файла draw_network_graph.py). Тут «дублирующиеся» соединения, это ситуация когда в словаре есть два соединения:

("R1", "Eth0/0"): ("SW1", "Eth0/1")
("SW1", "Eth0/1"): ("R1", "Eth0/0")

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

Проверить работу функции на файле topology.yaml (должен быть создан в задании 17.3a). На основании полученного словаря надо сгенерировать изображение топологии с помощью функции draw_topology. Не копировать код функции draw_topology из файла draw_network_graph.py.

Результат должен выглядеть так же, как схема в файле task_17_3b_topology.svg

https://raw.githubusercontent.com/natenka/pyneng-examples-exercises/master/exercises/17_serialization/task_17_3b_topology.png

При этом:

  • Интерфейсы должны быть записаны с пробелом Fa 0/0
  • Расположение устройств на схеме может быть другим
  • Соединения должны соответствовать схеме
  • На схеме не должно быть дублирующихся линков

Примечание

Для выполнения этого задания, должен быть установлен graphviz: apt-get install graphviz

И модуль python для работы с graphviz: pip install graphviz

Задание 17.4

Создать функцию write_last_log_to_csv.

Аргументы функции:

  • source_log - имя файла в формате csv, из которого читаются данные (пример mail_log.csv)
  • output - имя файла в формате csv, в который будет записан результат

Функция ничего не возвращает.

Функция write_last_log_to_csv обрабатывает csv файл mail_log.csv. В файле mail_log.csv находятся логи изменения имени пользователя. При этом, email пользователь менять не может, только имя.

Функция write_last_log_to_csv должна отбирать из файла mail_log.csv только самые свежие записи для каждого пользователя и записывать их в другой csv файл. В файле output первой строкой должны быть заголовки столбцов, такие же как в файле source_log.

Для части пользователей запись только одна и тогда в итоговый файл надо записать только ее. Для некоторых пользователей есть несколько записей с разными именами. Например пользователь с email c3po@gmail.com несколько раз менял имя:

C=3PO,c3po@gmail.com,16/12/2019 17:10
C3PO,c3po@gmail.com,16/12/2019 17:15
C-3PO,c3po@gmail.com,16/12/2019 17:24

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

C-3PO,c3po@gmail.com,16/12/2019 17:24

Для сравнения дат удобно использовать объекты datetime из модуля datetime. Чтобы упростить работу с датами, создана функция convert_str_to_datetime - она конвертирует строку с датой в формате 11/10/2019 14:05 в объект datetime. Полученные объекты datetime можно сравнивать между собой. Вторая функция convert_datetime_to_str делает обратную операцию - превращает объект datetime в строку.

Функции convert_str_to_datetime и convert_datetime_to_str использовать не обязательно.

import datetime


def convert_str_to_datetime(datetime_str):
    """
    Конвертирует строку с датой в формате 11/10/2019 14:05 в объект datetime.
    """
    return datetime.datetime.strptime(datetime_str, "%d/%m/%Y %H:%M")


def convert_datetime_to_str(datetime_obj):
    """
    Конвертирует строку с датой в формате 11/10/2019 14:05 в объект datetime.
    """
    return datetime.datetime.strftime(datetime_obj, "%d/%m/%Y %H:%M")