А АSunday, 1 January 2023

Тестирование инфраструктуры c pyATS #3.

undercons
Всем привет. 

Продолжаю нашу тему фреймворков для тестирования инфраструктры. Сегодня мой пост является беглым отчетом по выполнению работы "7.6.3 Lab - Automated Testing Using pyATS and Genie" из Cisco DevNet.

Знакомтесь - pyATS (https://developer.cisco.com/pyats/). Это экосистема сквозного тестирования, изначально разработанная компанией Cisco и ставшая открытой в конце 2017 года. Ранее библиотека pyATS называлась Genie; эти названия используются в одном и том же контексте. Ввиду своего происхождения этот фреймворк целиком и полностью ориентирован на тестирование сетей.

Фреймворк доступен в PyPI:

(venv) $ pip install pyats[full]

Для начала рассмотрим некоторые демонстрационные сценарии из GitHub-репозитория:

git clone https://github.com/CiscoTestAutomation/examples

Мы сходу можем прогнать тест-пустышку чтобы оценить как все происходит:

pyats run job examples/basic/basic_example_job.py

Следом можно охватить отчетность по всем проведенным PyATS-тестам в формате HTML:

pyats logs view

P.S.: имейте ввиду - порт web-сервера отчетов динамический.

logs

Ок, реальные тесты начинаются с создания файла испытательной модели (testbed) в формате YAML. Создадим простой testbed-файл testbed-pyats.yml для нашего устройства CSR1000v. Он похож на файл реестра hosts, знакомый нам от Ansible:

testbed: 

    name: pyATS

    credentials:

        default:

            username: admin

            password: super

        enable:

            password: super


devices:

    CSR: 

        alias: CSR

        type: iosxe

        connections:

            defaults:

                class: unicon.Unicon  

            vty:

                ip: 192.168.1.19

                protocol: ssh -o KexAlgorithms=diffie-hellman-group14-sha1

В нашем первом сценарии, pyats_1.py, мы загрузим testbed-файл, подключимся к устройству, выполним команду show version и затем отключимся от устройства:

from pyats.topology import loader

# load testbed

testbed = loader.load('yaml/testbed-pyats.yml')

# access the device

testbed.devices

ios_1 = testbed.devices['CSR']

# establish connectivity

ios_1.connect()

# issue command

print(ios_1.execute('show version'))

# disconnect

ios_1.disconnect()


Запустив этот сценарий, мы увидим смесь из сообщений о подготовке pyATS и вывода самого устройства. Это похоже на сценарии Paramiko, которые мы видели ранее, но в данном случае соединение устанавливает pyATS:

(venv) $ python pyats_1.py

[2019-11-10 08:11:55,901] +++  CSR logfile /tmp/ CSR-default-

20191110T081155900.log +++

[2019-11-10 08:11:55,901] +++ Unicon plugin generic +++

<опущено>

[2019-11-10 08:11:56,249] +++ connection to spawn: ssh -l cisco

172.16.1.20, id: 140357742103464 +++

[2019-11-10 08:11:56,250] connection to  CSR

[2019-11-10 08:11:56,314] +++ initializing handle +++

[2019-11-10 08:11:56,315] +++  CSR: executing command 'term length 0' +++

term length 0  CSR#

[2019-11-10 08:11:56,354] +++  CSR: executing command 'term width 0' +++

term width 0  CSR#

[2019-11-10 08:11:56,386] +++  CSR: executing command 'show version' +++

show version

<опущено>


Второй пример более развернутый. Он включает настройку и установку соединения, сами тесты и последующее отключение от устройства. В сценарии pyats_2.py используются различные декораторы из модуля aetest, входящего в состав pyATS. Помимо методов подготовки и очистки, в классе PingTestCase имеется тест ping:

from pyats import aetest

import re

class CommonSetup(aetest.CommonSetup):

    @aetest.subsection

    def establish_test(self, testbed, iosv1_name = 'CSR'):

        ios1 = testbed.devices[iosv1_name]

        self.parent.parameters.update(ios1 = ios1)


    @aetest.subsection

    def establish_connections(self, steps, ios1):

        with steps.start('Connecting to %s' % ios1.name):

            ios1.connect()


@aetest.loop(device = ('ios1',))


class PingTestcase(aetest.Testcase):

    @aetest.test.loop(destination = ('192.168.1.180','192.168.1.3'))

    def ping(self, device, destination):

        try:

            result = self.parameters[device].ping(destination)

        except Exception as e:

            self.failed('Ping {} from device {} failed with error: {}'.format(

                                destination,

                                device,

                                str(e),

                            ),

                        goto = ['exit'])

        else:

            match = re.search(r'Success rate is (?P<rate>\d+) percent', result)

            success_rate = match.group('rate')


class CommonCleanup(aetest.CommonCleanup):

    @aetest.subsection

    def disconnect(self, steps, ios1):

        with steps.start('Disconnecting from %s' % ios1.name):

            ios1.disconnect()


if __name__ == '__main__':

    import argparse

    from pyats.topology import loader

    parser = argparse.ArgumentParser()

    parser.add_argument('--testbed', dest = 'testbed', type = loader.load)

    args, unknown = parser.parse_known_args()

    aetest.main(**vars(args))


На практике предпочтительнее передавать testbed-файл как аргумент командной строки:

(venv) $ python pyats_2.py --testbed testbed_pyats.yml

Вывод этого сценария похож на тот, что мы видели в предыдущем примере, если не считать дополнительных разделов STEPS Report и Detailed Results в каждом тесте. В выводе также указано имя журнального файла, сохраненного в каталоге /tmp:

pyats

Фреймворк pyATS отлично подходит для автоматизированного тестирования. Но, учитывая его происхождение, ему не хватает поддержки других производителей, окромя Cisco.

Мы еще можем использовать фреймворк Genie которая позволяет парсить вывод IOS в формате JSON. Если вы ставили PyATS то Genie у вас уже присутствует. Также Genie  позволяет  зашифровать пароли в testbed. Первое что мы сделаем это создадим новый testbed в диалоговом режиме:

genie create testbed interactive --output yaml/testbed.yml --encode-password

где

  • Device hostname - имя нашего подопытного устройства, мое CSR
  • IP address - его IPv4 address
  • Username - local username used for ssh
  • Default password - local password used for ssh
  • Enable password - у меня совпадает с default
  • Protocol - указываю SSH
  • OS - указываю iosxe.


Мы получим в итоге файлик yaml/testbed.yml такого содержания:

devices:

  CSR:

    connections:

      cli:

        ip: 192.168.1.19

        protocol: ssh -o KexAlgorithms=diffie-hellman-group14-sha1

    credentials:

      default:

        password: '%ENC{w53DmsOUw6jDmMOR}'

        username: admin

      enable:

        password: '%ENC{w53DmsOUw6jDmMOR}'

    os: iosxe

    type: iosxe


Далее можем запросить что угодно с CSR. Собственно вы можете видеть что Genie пересылает 

наши команды устройству и читает ответы на них:

genie parse "show ip interface brief" --testbed-file yaml/testbed.yml --devices CSR

или

genie parse "show version" --testbed-file yaml/testbed.yml --devices CSR

genie

Еще одна полезная возможность это сравнивать конфигурации До и После. Переведем вывод запроса в файл:

genie parse "show ipv6 interface gig 1" --testbed-file yaml/testbed.yml --devices CSR --output verify-ipv6-1

Что-то поменяем в ipv6 и выполним запрос еще раз:

genie parse "show ipv6 interface gig 1" --testbed-file yaml/testbed.yml --devices CSR --output verify-ipv6-2

А теперь смотрим разницу:

genie diff verify-ipv6-1 verify-ipv6-2

diff

На десерт - существует еще один открытый инструмент для проверки сетей Batfish от IntentionNet (https://github.com/batfish/batfish).  Его прямое назначение - проверка изменений в конфигурации перед развертыванием. И он может цепляться не только к Cіsco!)

Вот собственно и все. Пользуйтесь и удачи.

1 comment:

blank
Anonymous said...

genie validate testbed testbed.yml

Post a Comment

А что вы думаете по этому поводу?

Версия на печать

Популярное