vk_logo twitter_logo facebook_logo youtube_logo telegram_logo telegram_logo

Автоматизируем работу с коммутаторами SNR при помощи ANSIBLE

Дата публикации: 14.05.2020
Количество просмотров: 4299
Автор:

Тема автоматизации управления сетевым оборудованием активно развивается последние несколько лет в связи с ростом количества устройств и предоставляемых сервисов. Мы решили не обходить эту тему стороной и рассказать о том, как можно автоматизировать управление коммутаторами SNR при помощи ansible.

Ansible – один из наиболее популярных инструментов автоматизации, изначально созданный для управления конфигурациями серверов. Однако, сейчас он широко используется и для автоматизации управления сетевого оборудования. Я не буду подробно рассказывать о работе с ansible, в сети достаточно материалов на эту тему, например цикл видеоуроков по ansible на Youtube, или пособие по Ansible для сетевых инженеров от Натальи Самойленко.

Тем не менее, я расскажу базовые принципы работы ansible.

Ansible работает без установки агента на управляемые хосты и отправляет команды по SSH. 

Список устройств, к которым ansible будет подключаться, хранится в Inventory или инвентарном файле. В нем хранятся сгруппированные IP-адреса устройств и переменные.

Playbook (файл сценариев) - это файл, в котором описываются действия, которые нужно выполнить на определенной группе хостов. 

В качестве примера создадим сценарий для обновления ПО на коммутаторах SNR,  используя ansible версии 2.9.6.

Для начала создадим инвентарный файл с именем "invent", в котором укажем IP-адреса коммутаторов и необходимые переменные:

[S2985]
192.168.2.4
192.168.2.5

[S2985:vars]
model=SNR-S2985G-24T
lastFW=7.0.3.5(R0241.0339)
FWfilename="SNR-S2985G-48T(24T_8T)(POE)(UPS)(RPS)_7.0.3.5(R0241.0339)_nos.img"
upgradeurl=tftp://192.168.2.1/
FWSize ="13609688"

[S2985G] - в квадратных скобках определяется название группы хостов  и ниже указываются IP-адреса устройств, принадлежащих данной группе.

[S2985G:vars] - в таком формате определяются переменные, используемые при выполнении сценария над группой хостов.

Так как мы автоматизируем обновление ПО на коммутаторе, в переменных мы указываем модель коммутатора (model), актуальную версию прошивки (lastFW), имя файла для обновления (FWfilename) ,  URL сервера, на котором находится прошивка (upgradeurl) и размер прошивки (FWSize)

Файл inventory готов, можно переходить к созданию playbook. Playbook описывается в формате YAML и состоит из сценариев (Play) и задач (Tasks). Каждый сценарий состоит из одной или более задач. Итак, начнем создавать наш Playbook в файле UpgradeFW.yml. Для начала, он будет состоять из двух задач - получение вывода команды show version c коммутатора и его отображение.

---  
- name: Play 1 - upgrade FW on SNR-S2985G switches
  hosts: S2985
  gather_facts: false
  connection: network_cli

  vars:
    ansible_user: admin
    ansible_ssh_pass: admin
    ansible_network_os: ios

  tasks:
    - name: Get show version
      ios_command:
        commands: show version
      register: sh_ver

    - name: Display show version
      debug:
        msg: "{{sh_ver}}"


Любой Playbook должен начинаться с ‘---’, это требования формата YAML. Рассмотрим остальные ключевые слова:

  • name - определяет описание нашего сценария, ключ не обязательный, но настоятельно рекомендуемый к использованию. 
  • hosts - указание группы хостов из inventory файла, к которому будет применен сценарий.
  • gather_facts - сбор информации о хосте, поскольку для коммутаторов SNR это не поддерживается, то отключаем. 
  • connection: network_cli - определяет тип подключения к управляемому устройству, в данном случае CLI over SSH. 


Далее идут определения переменных,  которые будут использоваться в данном сценарии. В частности, логин, пароль и тип ОС коммутатора. Поскольку CLI на SNR в большей части совпадает с Cisco, указываем ansible_network_os: ios


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

    ansible_become: yes
    ansible_become_method: enable
    ansible_become_password: pass


Далее идет описание самой задачи: 

  • name как и в случае со сценарием служит для описания выполняемых действий. 
  • ios_command - модуль для выполнения комманд на оборудовании Cisco. Вследствие близкого синтаксиса он работает на коммутаторах SNR и имеет несколько полезных "фишек", которые я покажу далее.
  • commands: show version - собственно команда, которая выполняется на коммутаторе, в нашем случае "show version".
  • register - сохраняет результат выполнения команды в переменную (sh_ver), которую мы в дальнейшем будем использовать для определения версии модели и ПО коммутатора. 
  • debug - позволяет отобразить информацию в процессе выполнения ansible. В нашем случае мы будем её использовать для того, чтобы вывести содержимое переменной sh_ver(по правилам YAML переменная должна быть заключена в две фигурные скобки), в которую как вы помните мы записали вывод команды show version c коммутатора).


Поскольку соединение с хостом будет происходить по протоколу SSH, на коммутаторе требуется включить ssh-server (ssh-server enable). На ПК, в домашнем каталоге пользователя, от которого будет запускаться ansible, в файл /.ssh/config необходимо добавить строки: 

host *
     KexAlgorithms +diffie-hellman-group1-sha1
     Ciphers aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc

а также, добавить хост в .ssh/known_host .

Запускаем наш первый Playbook, ключ -i указывает на имя inventory файла. Затем,  указываем файл со сценарием:

ansible-playbook -i invent upgradeFW.yml

 

 

 

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

Для этого необходимо создать шаблон на основе регулярных выражений. В начале мы определяем переменные с указанием формата, а затем определяем, где взять значения этих переменных. Для проверки шаблонов есть удобный инструмент, который позволяет создать шаблон и проверить его на выводе CLI on-line.

Для парсинга вывода команды show version  коммутаторов SNR шаблон будет следующий:

Value Model (\S+)
Value Uptime (.*)
Value SoftwareVersion (\S+)
Value BootROMVersion (\S+)
Value CPUMAC (\S+)
Value VlanMAC (\S+)
Value SN (\S+)

Start
  ^\s*${Model} Device
  ^\s*SoftWare.*Version ${SoftwareVersion}
  ^\s*BootRom Version ${BootROMVersion}
  ^\s*Uptime is ${Uptime}
  ^\s*CPU Mac ${CPUMAC}
  ^\s*Vlan MAC ${VlanMAC}
  ^\s*Serial No.:${SN}

Изменим наш сценарий - вместо вывода команды show version, мы её разберем при помощи textFSM - sh_ver.stdout[0] | parse_cli_textfsm("sh_ver.textFSM") (sh_ver.textFSM - имя файла с шаблоном для парсинга), и запишем в переменную switch_facts при помощи ключевого слова set_fact. Затем, чтобы проверить правильность парсинга,  выведем его на экран.

Checking Model и Checking Version служат для того, чтобы остановить выполнение сценария, если модель коммутатора не совпадает с нужной или версия ПО не требует обновления. Делаем это с помощью ключевых слов when (выполняет задачу только если условие true) и fail (останавливает сценарий и выдает сообщение).

Получившийся сценарий:

---
- name: Play 1 - upgrade FW on SNR-S2985G switches 
  hosts: S2985
  gather_facts: false
  connection: network_cli

  vars:
    ansible_user: admin
    ansible_ssh_pass: admin
    ansible_network_os: ios

  tasks:
   - name: Get model and version
     ios_command:
       commands: show version
     register: sh_ver

   - name: Parse output
     set_fact:
        switch_facts: "{{sh_ver.stdout[0] | parse_cli_textfsm("sh_ver.textFSM") }}"
        
   - name: Print output
     debug:
       msg: "{{ switch_facts}}" 
         
   - name: Checking Model
     when:
       switch_facts[0]["Model"] != model
     fail:
       msg: Model is not {{model}} 
       
   - name: Checking Version
     when:
       switch_facts[0]["SoftwareVersion"] == lastFW
     fail:
       msg: Version is actual {{lastFW}}

Запускаем новый сценарий:

 

 

Как видим, вывод show version разобран корректно, а задачи Checking Model и Checking Version пропущены, поскольку условия в when: не соблюдаются - модель верная и ПО требуется обновить.

Теперь можно приступать к самому обновлению коммутатора. Для этого добавляем в наш сценарий следующие задачи:

   - name: Upgrading FW
     ios_command:
       commands:
        - command: "copy {{upgradeurl}}/{{FWfilename}} nos.img"
          prompt: "\[Y/N\]:"
          answer: "y"
     vars:
        ansible_command_timeout: 300
     register: cmd_res

Этой задачей мы запускаем копирование файла с прошивкой на коммутатор. Поскольку при перезаписи существующего файла необходимо дать подтверждение, мы используем возможность модуля ios_command  - prompt и answer. В prompt указываем строку с вопросом, действительно ли мы хотим переписать файл  (достаточно последних символов) , а в answer - ответ.

Поскольку копирование прошивки занимает несколько минут, а стандартный таймаут на выполнение команды  ansible - 30 сек., мы увеличиваем его, устанавливая переменную ansible_command_timeout.

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

Следующая задача - проверка результата обновления: 

   - name: Check upgrade result
     when:
         cmd_res.stdout[0].find("Write ok.") == -1 or
         cmd_res.stdout[0].find("Recv total {{FWSize}} bytes") == -1
     fail:
        msg: Upgrade fail {{ cmd_res.stdout}}

При успешной записи файла вывод в CLI выглядит следующим образом:

File transfer complete.
Recv total 727952 bytes

Begin to write local file, please wait...

Write ok.
close tftp client.

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

Следующими задачами мы сохраняем конфигурацию и перезагружаемся, используя уже знакомый инструмент prompt/answer.

   - name: Switch save
     ios_command:
       commands:
         - command: "write"
           prompt: "\[Y/N\]:"
           answer: "y"        

   - name: Switch reboot
     ios_command:
       commands:
         - command: "reload"
           prompt: "\[Y/N\]"
           answer: "y"          
     ignore_errors: yes

В задачу  Switch reboot пришлось добавить строку  ignore_errors: yes, при которой игнорируются ошибки при выполнении задачи и сценарий не останавливается,  поскольку на некоторых моделях SNR, в частности SNR-S2995, перезагрузка выполняется, но задача завершается с ошибкой по таймауту. Причину такого поведения пока обнаружить не удалось, поэтому ошибку просто игнорируем.

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

   - name: WAIT FOR SWITCH TO RETURN
     wait_for:
        host: "{{inventory_hostname}}"
        port: 22
        delay: 60
        timeout: 600
     delegate_to: localhost

   - name: Get model and version
     ios_command:
       commands: show version
     register: sh_ver

   - name: Parse output
     set_fact:
       switch_facts: "{{sh_ver.stdout[0] | parse_cli_textfsm("sh_ver.textFSM") }}"

   - name: Checking Version
     debug:
        msg: "{{switch_facts[0]["SoftwareVersion"]}}"

Результат выполнения сценария должен быть следующим:

 

 

Ansible выдает предупреждение о том, что в задаче Check upgrade result не должны использоваться jinja2 шаблоны, но её можно игнорировать, так как задача выполняется корректно.

На этом наш сценарий завершен. Как видно, ansible достаточно простой в освоении инструмент с широким функционалом.  Полные версии playbook, inventory и шаблона textFSM можно скачать тут.

На этом, я надеюсь, цикл статей про автоматизацию SNR при помощи ansible не закончится, в планах написать статью про использование шаблонов Jinja2 совместно с ansible.

Как всегда комментарии и критика приветствуются.

От редакции: если у вас есть чем поделиться с коллегами по отрасли, приглашаем к сотрудничеству
Ссылка на материал, для размещения на сторонних ресурсах
/articles/article/106939/avtomatiziruem-rabotu-s-kommutatorami-snr-pri-pomoschi-ansible.html

Обсудить на форуме

Оставлять комментарии могут только зарегистрированные пользователи

Зарегистрироваться