В предыдущих сериях АДСМ мы выработали фреймворк автоматизации, разобрались с тем, зачем появилась виртуализация и как она работает. В последней части мы выбрали и обосновали дизайн сети, роли устройств, производителей, определились с LLD (адресацией, маршрутизацией, номерами Автономных Систем).
Теперь мы готовы подумать о том, как всю эту гору информации хранить и в дальнейшем удобно извлекать.
Нет, есть, конечно, и сегодня компании, которые ведут учёт выделенных IP-адресов в таблице Excel. Но это не наш путь.
Даже для самой маленькой конторки размеров в пару филиалов наличие централизованной системы управления IP-пространством не повредит.
Необходимость системы инвентаризации очевидна без лишних слов.
![](https://fs.linkmeup.ru/images/adsm/3/kdpv_ipam.svg)
Все выпуски АДСМ:
0. АДСМ. Часть Нулевая. Планирование
1. АДСМ. Часть Первая (которая после нулевой). Виртуализация сети
2. АДСМ. Часть Вторая. Дизайн сети
3. АДСМ. Часть Третья. IPAM/DCIM-система
Этот выпуск я посвящу неотъемлемым системам в сетевой автоматизации — системе управления адресным пространством и инвентарной системе.
Мы выберем и установим её, разберёмся с архитектурой, схемой БД, интерфейсами взаимодействия и наполним её. А в следующих частях начнём писать несложные скрипты, автоматизирующие повторяющиеся операции, такие как добавление новых стоек.
Кроме того, я уже опубликовал отдельную статью о RESTful API, в которой сделал короткий обзор его принципов и работы, это нам понадобится.
Сегодня рынок предлагает около дюжины инструментов, реализующих эту задачу: как платных, так и Open Source.
Для задач этой серии статей я выбрал NetBox по следующим причинам:
Иными словами все компоненты зрелые и проверенные.
По словам автора NetBox отражает не реальное состояние сети, а целевое. Поэтому ничего не подгружается в NetBox из сети — это сеть настраивается в соответствие с содержимым NetBox.
Таким образом NetBox выступает единственным источником истины (калька с single source of truth).
И изменения на сети должны быть инициированы изменениями в NetBox.
А это очень неплохо ложится на идеологию, которую я исповедую в этой серии статей — хочешь сделать изменения на сети — сначала внеси их в системы.
Две главные задачи, которые решает NetBox: управление адресным пространством и инвентаризация.
NetBox едва ли станет единственной системой инвентаризации в компании, скорее, это будет специфическая дополнительная система для инвентаризации именно сети, забирающая данные из основной.
Очевидно, в нашем случае для целей АДСМ будет только NetBox.
Функции NetBox:
В этой статье я коснусь следующих вещей: DCIM — Data Center Infrastructure Management, IPAM — IP Address Management, Виртуализация, Дополнительные приятные вещи.
Обо всём по порядку.
Самая важная часть — это, несомненно, какое оборудование у нас стоит и как оно друг к другу подключено. Но начинается всё с того, где оно стоит.
В парадигме NetBox устройство устанавливается на сайт, сайт принадлежит региону, регионы могут быть вложены. При этом устройство не может быть установлено просто в регионе. Если такая необходимость есть, должен быть заведён отдельный сайт.
Для нашего случая это может (и будет) выглядеть так:
![](https://fs.linkmeup.ru/images/adsm/3/sites.png)
Напоминаю где и как мы планировали нашу сеть: АДСМ2. Дизайн сети
![](https://fs.linkmeup.ru/images/adsm/3/topology.png)
![](https://fs.linkmeup.ru/images/adsm/3/sites_mlg.png)
Давайте посмотрим, что позволяет API.
Вот так можно вывести список всех регионов:
Список сайтов конкретного региона:
Само устройство обладает какой-то ролью, например, leaf, spine, edge, border.
Оно, очевидно, является какой-то моделью какого-то вендора.
Например, Arista.
Таким образом, сначала создаётся вендор, далее внутри него модели.
Модель характеризуется именем, набором сервисных интерфейсов, интерфейсом удалённого управления, консольным портом и набором модулей питания.
Помимо коммутаторов, маршрутизаторов и хостов, обладающих Ethernet-интерфейсами, можно создавать консольные сервера.
![](https://fs.linkmeup.ru/images/adsm/3/devices.png)
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/c81/cce/0f9/c81cce0f9d543eedd4f7c1e1ede5f43f.png)
Получить список всех устройств:
Всех устройств конкретного сайта:
Всех устройств определённой модели
Всех устройств определённой роли:
Устройство может быть в разных статусах: Active, Offline, Planned итд.
Все активные устройства:
NetBox поддерживает множество типов физических интерфейсов и LAG, однако все виртуальные, такие как Vlan/IRB и loopback объединены под одним типом — Virtual.
Каждый интерфейс привязан к какому-либо устройству.
Интерфейсы устройств могут быть подключены друг к другу. Это будет отображаться как в интерфейсе, так и в ответах API (атрибут connected_endpoint).
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/aea/c56/b47/aeac56b47e58145211f5726c8e48cb91.png)
Интерфейс может быть в различных режимах: Tagged или Access.
Соответственно, в него могут быть спущены с тегом или без VLAN'ы — данного сайта или глобальные.
Получить список всех интерфейсов устройства:
Получить список VLAN'ов конкретного интерфейса.
Узнать имя интерфейса управления:
Консольные порты не являются интерфейсами, поэтому вынесены как отдельные эндпоинты.
Порты устройства можно связать с портами консольного сервера.
Выяснить к какому порту какого консольного сервера подключено конкретное устройство.
Могут быть привязаны к локации — полезно для VLAN.
При создании VRF можно указать, допускается ли пересечение адресного пространства с другими VRF.
Получить список всех VLAN:
Получить список всех VRF:
Имеют иерархическую структуру. Может принадлежать какому-либо VRF (если не принадлежит — то Global).
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/94b/ea6/8c4/94bea68c425c9a8bd601c9a0da74193e.png)
В NetBox очень удобное визуальное представление свободных префиксов:
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/1be/90e/14d/1be90e14da8f4c3bedc4bcb892cb5156.png)
Выделить можно просто кликом на зелёную строчку.
Может быть привязан к локации. Можно через API выделить следующий свободный под-префикс нужного размера или следующий свободный IP-адрес.
Галочка/параметр «Is a pool» определяет, будет ли при автоматическом выделении выделяться 0-й адрес из этого префикса, или начнётся с 1-го.
Получить список IP-префиксов сайта Малага c ролью Underlay и длиной 19:
Получить список свободных префиксов в регионе Россия c ролью Underlay:
Выделить следующий свободный префикс длиной в 24:
Если есть включающий этот адрес префикс, то будут его частью. Могут быть и сами по себе.
Могут принадлежать какому-либо VRF или быть в Global.
Могут быть привязаны к интерфейсу, а могут висеть в воздухе.
Можно выделить следующий свободный IP-адрес в префиксе.
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/4a1/c4d/442/4a1c4d4428f703d9a90766ffa9351fe8.png)
Чтобы сделать это, просто нужно кликнуть по зелёной строчке.
Получить список IP-адресов конкретного интерфейса:
Или:
Получить список всех IP-адресов устройства:
Получить список доступных IP-адресов префикса:
Мы же всё-таки боремся за звание современного ДЦ. Куда же без виртуализации.
NetBox не выглядит и не является местом, где стоит хранить информацию о виртуальных машинах (даже о необходимости хранения в нём физических машин можно порассуждать). Однако нам это может оказаться полезным, например, можно занести информация о Route Reflector'ах, о служебных машинах, таких как NTP, Syslog, S-Flow-серверах, о машинах-управляках.
ВМ обладает своим списком интерфейсов — они отличны от интерфейсов физических устройств и имеют свой отдельный Endpoint.
Так можно вывести список всех виртуальных машин:
Так — всех интерфейсов всех ВМ:
Для ВМ нельзя указать конкретный гипервизор/физическую машину, на котором она запущена, но можно указать кластер. Хотя не всё так безнадёжно. Читаем дальше.
Основная функциональность NetBox закрывает большинство задач многих пользователей, но не все. Всё-таки изначально продукт написан для решения задач конкретной компании. Однако он активно развивается и новые релизы выходят довольно часто. Соответственно появляются и новые функции.
Так, например, с моей первой установки NetBox пару лет назад в нём появились теги, config contexts, webhooks, кэширование, supervisord сменился на systemd, внешние хранилища для файлов.
Cледите.
Иногда хочется к какой-либо сущности добавить поле, в которое можно было бы поместить произвольные данные.
Например, указать номер договора поставки, по которому был приобретён коммутатор или имя физической машины, на которой запущена ВМ.
Тут на помощь и приходит custom fields — как раз такое поле с текстовым значением, которое можно добавить почти к любой сущности в NetBox.
Создаётся Custom fields в админской панели
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/1cf/10e/568/1cf10e56808f227ce7f7270581b84a31.png)
Вот так это выглядит при редактировании устройства, для которого был создан custom field:
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/d3a/c2b/c78/d3ac2bc78d80acccc3895463f7ed7295.png)
Запросить список устройств по значению custom_field
Иногда хочется чего-то большего, чем неструктурированный текст. Тогда на помощь приходит Config Context.
Это возможность ввести набор структурированных данных в формате JSON, который больше некуда поместить.
Это может быть, например, набор BGP communities или список Syslog-серверов.
Config Context может быть локальным — настроенным для конкретного объекта — или глобальным, когда он настраивается однажды, а затем распространяется на все объекты, удовлетворяющие определённым условиям (например, расположенные на одном сайте, или запущенные на одной платформе).
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/97a/406/224/97a406224499ed35e9c471c3709a8d98.png)
Config Context автоматически добавляется к результатам запроса. При этом локальные и глобальные контексты сливаются в один.
Например, для устройства just a simple russian girl, для которого есть локальный контекст, в выводе будет ключ «config_context»:
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/031/608/4bd/0316084bd52d028434631298a22ba33e.png)
Про теги сложно сказать что-то новое. Они есть. Они удобны для добавления какого-либо признака. К примеру, можно пометить тегом «бяда» коммутаторы из партии, в которой сбоит память.
Незаменимая вещь, когда нужно, чтобы об изменениях в NetBox'е узнавали другие сервисы.
Например, при заведении нового коммутатора отправляется хука в систему автоматизации, которая запускает процесс настройки устройства и ввода в эксплуатацию.
В этой статье я не преследую цель рассмотреть все возможности NetBox, поэтому всё остальное отдаю вам на откуп. Разбирайтесь, пробуйте.
Далее в рамках построения системы автоматизации я буду касаться только тех частей, которые нам действительно нужны.
Итак, выше я коротко рассказал о том, что из себя представляет NetBox, и как в нём хранятся данные.
Повторюсь, что почти все необходимые данные я туда уже внёс, и вы можете утащить себе дамп БД.
Всё готово к следующему этапу автоматизации: написанию системы (ахаха, просто скриптов) инициализации устройств и управления конфигурацией.
Но, прежде чем закончить статью я ещё скажу пару слов об установке и работе компонентов NetBox.
Я не буду описывать процесс инсталляции в деталях — он более чем классно описан в официальной документации.
Посмотреть на процесс запуска docker-образа NetBox и работу в GUI можно в видео Димы Фиголя (раз и два) и Эмиля Гарипова.
В целом, если следовать шагам установки/запуска неукоснительно, то всё получится.
Но вот какие есть нюансы, про которые случайно можно забыть.
Для подключения к серверу:
Например:
Для вывода всех таблиц:
Для выхода:
Для дампа БД:
Если не хочется каждый раз вводить пароль:
Если у вас есть своя инсталляция и не хочется вносить всё руками, можно просто сделать так, взяв дамп текущей БД NetBox тут:
Если предварительно нужно дропнуть все таблицы (а сделать это придётся), то можно подготовить заранее файл:
Теперь мы готовы подумать о том, как всю эту гору информации хранить и в дальнейшем удобно извлекать.
Нет, есть, конечно, и сегодня компании, которые ведут учёт выделенных IP-адресов в таблице Excel. Но это не наш путь.
Даже для самой маленькой конторки размеров в пару филиалов наличие централизованной системы управления IP-пространством не повредит.
Необходимость системы инвентаризации очевидна без лишних слов.
Все выпуски АДСМ:
0. АДСМ. Часть Нулевая. Планирование
1. АДСМ. Часть Первая (которая после нулевой). Виртуализация сети
2. АДСМ. Часть Вторая. Дизайн сети
3. АДСМ. Часть Третья. IPAM/DCIM-система
Этот выпуск я посвящу неотъемлемым системам в сетевой автоматизации — системе управления адресным пространством и инвентарной системе.
Мы выберем и установим её, разберёмся с архитектурой, схемой БД, интерфейсами взаимодействия и наполним её. А в следующих частях начнём писать несложные скрипты, автоматизирующие повторяющиеся операции, такие как добавление новых стоек.
Кроме того, я уже опубликовал отдельную статью о RESTful API, в которой сделал короткий обзор его принципов и работы, это нам понадобится.
Содержание
- Архитектура системы
- Схема данных NetBox
- Заключение
- Некоторые нюансы установки NetBox
- Немного о PostgreSQL
- Полезные ссылки
Сегодня рынок предлагает около дюжины инструментов, реализующих эту задачу: как платных, так и Open Source.
Для задач этой серии статей я выбрал NetBox по следующим причинам:
- Это бесплатно
- Он содержит в себе обе необходимые части — инвентаризацию и управление IP-пространством.
- У него есть RESTful API-интерфейс.
- Его разработал Digital Ocean (а конкретнее, любимый всеми Jeremy Stretch) для себя, то есть для дата-центров. Поэтому тут есть почти всё, что нужно, и почти ничего лишнего.
- Он активно поддерживается (Slack, Github, Google-рассылки) и обновляется.
- Это Open Source
Для нужд АДСМ я развернул NetBox в виртуалочке на нашем сервере (спасибо Антону Клочкову и Мирану): http://netbox.linkmeup.ru:45127Немного полезного перед началом:
Кроме того я заполнил почти все необходимые нам в дальнейшем данные.
Поэтому вы можете попробовать почти все примеры и изучать схему данных в режиме чтения, пока не развернули свою инсталляцию.
- Сам NetBox на github
- Контейнерная версия
- Полная инструкция по установке и вся документация по продукту
- SDK для работы с NetBox в Python
- Документация по API
- Mailing list
- Slack-канал NetworkToCode
- Что такое REST
- Инсталляция NetBox для нужд АДСМ
Архитектура системы
- NetBox написан на Python3. Что хорошо, потому что ряд других решений написан на php и изменять их при необходимости не так уж просто.
- Фреймворк для самого сайта — Django.
- В качестве БД используется PostgreSQL.
- WEB-frontend (HTTP-сервис) — NGINX — он проксирует запросы в Gunicron.
- WSGI — Gunicorn — интерфейс между Nginx и самим приложением.
- Фреймворк для документации по API — Swagger.
- Чтобы демонизировать NetBox — Systemd.
NetBox — проект молодой и быстро развивающийся. Например, в 2.7 отказались от supervisord и тянущегося за ним Python 2.7 в пользу systemd. Не так давно там не было ни кэширования, ни Webhooks.
Поэтому меняется всё быстро и информация в статье может устареть к моменту чтения.
Иными словами все компоненты зрелые и проверенные.
По словам автора NetBox отражает не реальное состояние сети, а целевое. Поэтому ничего не подгружается в NetBox из сети — это сеть настраивается в соответствие с содержимым NetBox.
Таким образом NetBox выступает единственным источником истины (калька с single source of truth).
И изменения на сети должны быть инициированы изменениями в NetBox.
А это очень неплохо ложится на идеологию, которую я исповедую в этой серии статей — хочешь сделать изменения на сети — сначала внеси их в системы.
Схема данных NetBox
Две главные задачи, которые решает NetBox: управление адресным пространством и инвентаризация.
NetBox едва ли станет единственной системой инвентаризации в компании, скорее, это будет специфическая дополнительная система для инвентаризации именно сети, забирающая данные из основной.
Очевидно, в нашем случае для целей АДСМ будет только NetBox.
К данному моменту бо́льшая часть начальных данных в NetBox уже внесена.В общих чертах схему данных можно увидеть по схеме БД в Postgres'е
На этих данных я буду демонстрировать различные примеры работы через API.
Вы можете просто полазить и посмотреть: netbox.linkmeup.ru:45127
И эти же данные понадобятся в дальнейшем, когда мы перейдём к автоматизации.
List of relations
Schema | Name | Type | Owner
--------+------------------------------------+-------+--------
public | auth_group | table | netbox
public | auth_group_permissions | table | netbox
public | auth_permission | table | netbox
public | auth_user | table | netbox
public | auth_user_groups | table | netbox
public | auth_user_user_permissions | table | netbox
public | circuits_circuit | table | netbox
public | circuits_circuittermination | table | netbox
public | circuits_circuittype | table | netbox
public | circuits_provider | table | netbox
public | dcim_cable | table | netbox
public | dcim_consoleport | table | netbox
public | dcim_consoleporttemplate | table | netbox
public | dcim_consoleserverport | table | netbox
public | dcim_consoleserverporttemplate | table | netbox
public | dcim_device | table | netbox
public | dcim_devicebay | table | netbox
public | dcim_devicebaytemplate | table | netbox
public | dcim_devicerole | table | netbox
public | dcim_devicetype | table | netbox
public | dcim_frontport | table | netbox
public | dcim_frontporttemplate | table | netbox
public | dcim_interface | table | netbox
public | dcim_interface_tagged_vlans | table | netbox
public | dcim_interfacetemplate | table | netbox
public | dcim_inventoryitem | table | netbox
public | dcim_manufacturer | table | netbox
public | dcim_platform | table | netbox
public | dcim_powerfeed | table | netbox
public | dcim_poweroutlet | table | netbox
public | dcim_poweroutlettemplate | table | netbox
public | dcim_powerpanel | table | netbox
public | dcim_powerport | table | netbox
public | dcim_powerporttemplate | table | netbox
public | dcim_rack | table | netbox
public | dcim_rackgroup | table | netbox
public | dcim_rackreservation | table | netbox
public | dcim_rackrole | table | netbox
public | dcim_rearport | table | netbox
public | dcim_rearporttemplate | table | netbox
public | dcim_region | table | netbox
public | dcim_site | table | netbox
public | dcim_virtualchassis | table | netbox
public | django_admin_log | table | netbox
public | django_content_type | table | netbox
public | django_migrations | table | netbox
public | django_session | table | netbox
public | extras_configcontext | table | netbox
public | extras_configcontext_platforms | table | netbox
public | extras_configcontext_regions | table | netbox
public | extras_configcontext_roles | table | netbox
public | extras_configcontext_sites | table | netbox
public | extras_configcontext_tags | table | netbox
public | extras_configcontext_tenant_groups | table | netbox
public | extras_configcontext_tenants | table | netbox
public | extras_customfield | table | netbox
public | extras_customfield_obj_type | table | netbox
public | extras_customfieldchoice | table | netbox
public | extras_customfieldvalue | table | netbox
public | extras_customlink | table | netbox
public | extras_exporttemplate | table | netbox
public | extras_graph | table | netbox
public | extras_imageattachment | table | netbox
public | extras_objectchange | table | netbox
public | extras_reportresult | table | netbox
public | extras_tag | table | netbox
public | extras_taggeditem | table | netbox
public | extras_webhook | table | netbox
public | extras_webhook_obj_type | table | netbox
public | ipam_aggregate | table | netbox
public | ipam_ipaddress | table | netbox
public | ipam_prefix | table | netbox
public | ipam_rir | table | netbox
public | ipam_role | table | netbox
public | ipam_service | table | netbox
public | ipam_service_ipaddresses | table | netbox
public | ipam_vlan | table | netbox
public | ipam_vlangroup | table | netbox
public | ipam_vrf | table | netbox
public | secrets_secret | table | netbox
public | secrets_secretrole | table | netbox
public | secrets_secretrole_groups | table | netbox
public | secrets_secretrole_users | table | netbox
public | secrets_sessionkey | table | netbox
public | secrets_userkey | table | netbox
public | taggit_tag | table | netbox
public | taggit_taggeditem | table | netbox
public | tenancy_tenant | table | netbox
public | tenancy_tenantgroup | table | netbox
public | users_token | table | netbox
public | virtualization_cluster | table | netbox
public | virtualization_clustergroup | table | netbox
public | virtualization_clustertype | table | netbox
public | virtualization_virtualmachine | table | netbox
Функции NetBox:
- IP address management (IPAM) — IP-префиксы, адреса, VRF'ы и VLAN'ы
- Equipment racks — Стойки для оборудования, организованные по сайтам, группам и ролям
- Devices — Устройства, их модели, роли, комплектующие и расположение
- Connections — Сетевые, консольные и силовые соединения между устройствами
- Virtualization — Виртуальные машины и вычислительные кластера
- Data circuits — Подключения к провайдерам
- Secrets — Зашифрованное хранилище учётных данных пользователей
В этой статье я коснусь следующих вещей: DCIM — Data Center Infrastructure Management, IPAM — IP Address Management, Виртуализация, Дополнительные приятные вещи.
Обо всём по порядку.
DCIM
Самая важная часть — это, несомненно, какое оборудование у нас стоит и как оно друг к другу подключено. Но начинается всё с того, где оно стоит.
Регионы и сайты (regions/sites)
В парадигме NetBox устройство устанавливается на сайт, сайт принадлежит региону, регионы могут быть вложены. При этом устройство не может быть установлено просто в регионе. Если такая необходимость есть, должен быть заведён отдельный сайт.
Для нашего случая это может (и будет) выглядеть так:
![](https://fs.linkmeup.ru/images/adsm/3/sites.png)
Напоминаю где и как мы планировали нашу сеть: АДСМ2. Дизайн сети
![](https://fs.linkmeup.ru/images/adsm/3/topology.png)
![](https://fs.linkmeup.ru/images/adsm/3/sites_mlg.png)
Давайте посмотрим, что позволяет API.
Вот так можно вывести список всех регионов:
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/regions/" -H "Accept: application/json; indent=4"
nb.dcim.regions.all()
Здесь и далее я буду приводить примеры curl и pynetbox без вывода результата.Получить список сайтов:
Не забудьте слэш в конце URL — без него не заработает.
Как использовать pynetbox я рассказывал в статье про RESTful API.
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/sites/" -H "Accept: application/json; indent=4"
nb.dcim.sites.all()
Список сайтов конкретного региона:
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/sites/?region=ru" -H "Accept: application/json; indent=4"
nb.dcim.sites.filter(region="ru")
Обратите внимание, что поиск идёт не по полному имени, а по так называемому slug.
Slug — это идентификатор, содержащий только безопасные символы: [0-9A-Za-z-_], который можно использовать в URL. Задаётся он при создании объекта, например, «bcn» вместо «Барселона».
Устройства
Само устройство обладает какой-то ролью, например, leaf, spine, edge, border.
Оно, очевидно, является какой-то моделью какого-то вендора.
Например, Arista.
Таким образом, сначала создаётся вендор, далее внутри него модели.
Модель характеризуется именем, набором сервисных интерфейсов, интерфейсом удалённого управления, консольным портом и набором модулей питания.
Помимо коммутаторов, маршрутизаторов и хостов, обладающих Ethernet-интерфейсами, можно создавать консольные сервера.
![](https://fs.linkmeup.ru/images/adsm/3/devices.png)
![](https://habrastorage.org/getpro/habr/post_images/c81/cce/0f9/c81cce0f9d543eedd4f7c1e1ede5f43f.png)
Получить список всех устройств:
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/devices/" -H "Accept: application/json; indent=4"
nb.dcim.devices.all()
Всех устройств конкретного сайта:
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/devices/?site=mlg" -H "Accept: application/json; indent=4"
nb.dcim.devices.filter(site="mlg")
Всех устройств определённой модели
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/devices/?model=veos" -H "Accept: application/json; indent=4"
nb.dcim.devices.filter(device_type_id=2)
Всех устройств определённой роли:
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/devices/?role=leaf" -H "Accept: application/json; indent=4"
nb.dcim.devices.filter(role="leaf")
Устройство может быть в разных статусах: Active, Offline, Planned итд.
Все активные устройства:
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/devices/?status=active" -H "Accept: application/json; indent=4"
nb.dcim.devices.filter(status="active")
Интерфейсы
NetBox поддерживает множество типов физических интерфейсов и LAG, однако все виртуальные, такие как Vlan/IRB и loopback объединены под одним типом — Virtual.
Каждый интерфейс привязан к какому-либо устройству.
Интерфейсы устройств могут быть подключены друг к другу. Это будет отображаться как в интерфейсе, так и в ответах API (атрибут connected_endpoint).
![](https://habrastorage.org/getpro/habr/post_images/aea/c56/b47/aeac56b47e58145211f5726c8e48cb91.png)
Интерфейс может быть в различных режимах: Tagged или Access.
Соответственно, в него могут быть спущены с тегом или без VLAN'ы — данного сайта или глобальные.
Получить список всех интерфейсов устройства:
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/interfaces/?device=mlg-leaf-0" -H "Accept: application/json; indent=4"
nb.dcim.interfaces.filter(device="mlg-leaf-0")
Получить список VLAN'ов конкретного интерфейса.
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/interfaces/?device=mlg-leaf-0&name=Ethernet7" -H "Accept: application/json; indent=4"
nb.dcim.interfaces.get(device="mlg-leaf-0", name="Ethernet7").untagged_vlan.vid
Обратите внимание, что тут я уже использую метод get вместо filter. Filter возвращает список, даже если результат — один единственный объект. Get — возвращает один объект или падает с ошибкой, если результатом запроса является список объектов.Выяснить к какому интерфейсу какого устройства подключен определённый интерфейс:
Поэтому get следует использовать только тогда, когда вы абсолютно уверены, что результат будет в единственном экземпляре.
Ещё здесь же прямо после запроса я обращаюсь к атрибутам объекта. Строго говоря, это неправильно: если по запросу ничего не найдено, то pynetbox вернёт None, а у него нет атрибута «untagged_vlan».
И ещё обратите внимание, что не везде pynetbox ожидает slug, где-то и name.
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/interfaces/?device=mlg-leaf-0&name=Ethernet1" -H "Accept: application/json; indent=4"
iface = nb.dcim.interfaces.get(device="mlg-leaf-0", name="Ethernet1")
iface.connected_endpoint.device
iface.connected_endpoint.name
Узнать имя интерфейса управления:
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/interfaces/?device=mlg-leaf-0&mgmt_only=true" -H "Accept: application/json; indent=4"
nb.dcim.interfaces.get(device="mlg-leaf-0", mgmt_only=True)
Консольные порты
Консольные порты не являются интерфейсами, поэтому вынесены как отдельные эндпоинты.
Порты устройства можно связать с портами консольного сервера.
Выяснить к какому порту какого консольного сервера подключено конкретное устройство.
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/console-ports/?device=mlg-leaf-0" -H "Accept: application/json; indent=4"
nb.dcim.console_ports.get(device="mlg-leaf-0").serialize()
Метод serialize в pynetbox позволяет преобразовать атрибуты экземпляра класса в словарь.
IPAM
VLAN и VRF
Могут быть привязаны к локации — полезно для VLAN.
При создании VRF можно указать, допускается ли пересечение адресного пространства с другими VRF.
Получить список всех VLAN:
curl -X GET "http://netbox.linkmeup.ru:45127/api/ipam/vlans/" -H "Accept: application/json; indent=4"
nb.ipam.vlans.all()
Получить список всех VRF:
curl -X GET "http://netbox.linkmeup.ru:45127/api/ipam/vrfs/" -H "Accept: application/json; indent=4"
nb.ipam.vrfs.all()
IP-префиксы
Имеют иерархическую структуру. Может принадлежать какому-либо VRF (если не принадлежит — то Global).
![](https://habrastorage.org/getpro/habr/post_images/94b/ea6/8c4/94bea68c425c9a8bd601c9a0da74193e.png)
В NetBox очень удобное визуальное представление свободных префиксов:
![](https://habrastorage.org/getpro/habr/post_images/1be/90e/14d/1be90e14da8f4c3bedc4bcb892cb5156.png)
Выделить можно просто кликом на зелёную строчку.
Может быть привязан к локации. Можно через API выделить следующий свободный под-префикс нужного размера или следующий свободный IP-адрес.
Галочка/параметр «Is a pool» определяет, будет ли при автоматическом выделении выделяться 0-й адрес из этого префикса, или начнётся с 1-го.
Получить список IP-префиксов сайта Малага c ролью Underlay и длиной 19:
curl -X GET "http://netbox.linkmeup.ru:45127/api/ipam/prefixes/?site=mlg&role=underlay&mask_length=19" -H "Accept: application/json; indent=4"
prefix = nb.ipam.prefixes.get(site="mlg", role="underlay", mask_length="19")
Получить список свободных префиксов в регионе Россия c ролью Underlay:
curl -X GET "http://netbox.linkmeup.ru:45127/api/ipam/prefixes/40/available-prefixes/" -H "Accept: application/json; indent=4"
prefix.available_prefixes.list()
Выделить следующий свободный префикс длиной в 24:
curl -X POST "http://netbox.linkmeup.ru:45127/api/ipam/prefixes/40/available-prefixes/" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: TOKEN a9aae70d65c928a554f9a038b9d4703a1583594f" \
-d "{\"prefix_length\": 24}"
prefix.available_prefixes.create({"prefix_length":24})
Когда внутри одного объекта нам нужно выделить какой-то дочерний, используется метод POST и нужно указать ID родительского объекта — в данном случае — 40. Его мы выяснили вызовом из предыдущего примера.
В случае pynetbox мы сначала (в предыдущем примере) сохранили результат в переменную prefix, а далее обратились к его атрибуту available_prefixes и методу create.
Этот пример у вас не сработает, поскольку токен с правом записи уже недействителен.
IP-адреса
Если есть включающий этот адрес префикс, то будут его частью. Могут быть и сами по себе.
Могут принадлежать какому-либо VRF или быть в Global.
Могут быть привязаны к интерфейсу, а могут висеть в воздухе.
Можно выделить следующий свободный IP-адрес в префиксе.
![](https://habrastorage.org/getpro/habr/post_images/4a1/c4d/442/4a1c4d4428f703d9a90766ffa9351fe8.png)
Чтобы сделать это, просто нужно кликнуть по зелёной строчке.
Получить список IP-адресов конкретного интерфейса:
curl -X GET "http://netbox.linkmeup.ru:45127/api/ipam/ip-addresses/?interface_id=8" -H "Accept: application/json; indent=4"
nb.ipam.ip_addresses.filter(interface_id=8)
Или:
curl -X GET "http://netbox.linkmeup.ru:45127/api/ipam/ip-addresses/?device=mlg-leaf-0&interface=Ethernet1" -H "Accept: application/json; indent=4"
nb.ipam.ip_addresses.filter(device="mlg-leaf-0", interface="Ethernet1")
Получить список всех IP-адресов устройства:
curl -X GET "http://netbox.linkmeup.ru:45127/api/ipam/ip-addresses/?device=mlg-leaf-0" -H "Accept: application/json; indent=4"
nb.ipam.ip_addresses.filter(device="mlg-leaf-0")
Получить список доступных IP-адресов префикса:
curl -X GET "http://netbox.linkmeup.ru:45127/api/ipam/prefixes/28/available-ips/" -H "Accept: application/json; indent=4"
prefix = nb.ipam.prefixes.get(site="mlg", role="leaf-loopbacks")
prefix.available_ips.list()
Здесь снова нужно в URL указать ID префикса, из которого выделяем адрес — на сей раз это 28.Выделить следующий свободный IP-адрес в префиксе:
curl -X POST "http://netbox.linkmeup.ru:45127/api/ipam/prefixes/28/available-ips/" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: TOKEN a9aae70d65c928a554f9a038b9d4703a1583594f"
prefix.available_ips.create()
Виртуализация
Мы же всё-таки боремся за звание современного ДЦ. Куда же без виртуализации.
NetBox не выглядит и не является местом, где стоит хранить информацию о виртуальных машинах (даже о необходимости хранения в нём физических машин можно порассуждать). Однако нам это может оказаться полезным, например, можно занести информация о Route Reflector'ах, о служебных машинах, таких как NTP, Syslog, S-Flow-серверах, о машинах-управляках.
ВМ обладает своим списком интерфейсов — они отличны от интерфейсов физических устройств и имеют свой отдельный Endpoint.
Так можно вывести список всех виртуальных машин:
curl -X GET "http://netbox.linkmeup.ru:45127/api/virtualization/virtual-machines/" -H "Accept: application/json; indent=4"
nb.virtualization.virtual_machines.all()
Так — всех интерфейсов всех ВМ:
curl -X GET "http://netbox.linkmeup.ru:45127/api/virtualization/interfaces/" -H "Accept: application/json; indent=4"
nb.virtualization.interfaces.all()
Для ВМ нельзя указать конкретный гипервизор/физическую машину, на котором она запущена, но можно указать кластер. Хотя не всё так безнадёжно. Читаем дальше.
Дополнительные приятные вещи
Основная функциональность NetBox закрывает большинство задач многих пользователей, но не все. Всё-таки изначально продукт написан для решения задач конкретной компании. Однако он активно развивается и новые релизы выходят довольно часто. Соответственно появляются и новые функции.
Так, например, с моей первой установки NetBox пару лет назад в нём появились теги, config contexts, webhooks, кэширование, supervisord сменился на systemd, внешние хранилища для файлов.
Cледите.
Custom fields
Иногда хочется к какой-либо сущности добавить поле, в которое можно было бы поместить произвольные данные.
Например, указать номер договора поставки, по которому был приобретён коммутатор или имя физической машины, на которой запущена ВМ.
Тут на помощь и приходит custom fields — как раз такое поле с текстовым значением, которое можно добавить почти к любой сущности в NetBox.
Создаётся Custom fields в админской панели
![](https://habrastorage.org/getpro/habr/post_images/1cf/10e/568/1cf10e56808f227ce7f7270581b84a31.png)
Вот так это выглядит при редактировании устройства, для которого был создан custom field:
![](https://habrastorage.org/getpro/habr/post_images/d3a/c2b/c78/d3ac2bc78d80acccc3895463f7ed7295.png)
Запросить список устройств по значению custom_field
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/devices/?cf_contract_number=0123456789" -H "Accept: application/json; indent=4"
nb.dcim.devices.filter(cf_contract_number="0123456789")
Config Context
Иногда хочется чего-то большего, чем неструктурированный текст. Тогда на помощь приходит Config Context.
Это возможность ввести набор структурированных данных в формате JSON, который больше некуда поместить.
Это может быть, например, набор BGP communities или список Syslog-серверов.
Config Context может быть локальным — настроенным для конкретного объекта — или глобальным, когда он настраивается однажды, а затем распространяется на все объекты, удовлетворяющие определённым условиям (например, расположенные на одном сайте, или запущенные на одной платформе).
![](https://habrastorage.org/getpro/habr/post_images/97a/406/224/97a406224499ed35e9c471c3709a8d98.png)
Config Context автоматически добавляется к результатам запроса. При этом локальные и глобальные контексты сливаются в один.
Например, для устройства just a simple russian girl, для которого есть локальный контекст, в выводе будет ключ «config_context»:
curl -X GET "http://netbox.linkmeup.ru:45127/api/dcim/devices/?q=russian" -H "Accept: application/json; indent=4"
![](https://habrastorage.org/getpro/habr/post_images/031/608/4bd/0316084bd52d028434631298a22ba33e.png)
Теги
Про теги сложно сказать что-то новое. Они есть. Они удобны для добавления какого-либо признака. К примеру, можно пометить тегом «бяда» коммутаторы из партии, в которой сбоит память.
Webhooks
Незаменимая вещь, когда нужно, чтобы об изменениях в NetBox'е узнавали другие сервисы.
Например, при заведении нового коммутатора отправляется хука в систему автоматизации, которая запускает процесс настройки устройства и ввода в эксплуатацию.
Заключение
В этой статье я не преследую цель рассмотреть все возможности NetBox, поэтому всё остальное отдаю вам на откуп. Разбирайтесь, пробуйте.
Далее в рамках построения системы автоматизации я буду касаться только тех частей, которые нам действительно нужны.
Итак, выше я коротко рассказал о том, что из себя представляет NetBox, и как в нём хранятся данные.
Повторюсь, что почти все необходимые данные я туда уже внёс, и вы можете утащить себе дамп БД.
Всё готово к следующему этапу автоматизации: написанию системы (ахаха, просто скриптов) инициализации устройств и управления конфигурацией.
Но, прежде чем закончить статью я ещё скажу пару слов об установке и работе компонентов NetBox.
Некоторые нюансы установки NetBox
Я не буду описывать процесс инсталляции в деталях — он более чем классно описан в официальной документации.
Посмотреть на процесс запуска docker-образа NetBox и работу в GUI можно в видео Димы Фиголя (раз и два) и Эмиля Гарипова.
В целом, если следовать шагам установки/запуска неукоснительно, то всё получится.
Но вот какие есть нюансы, про которые случайно можно забыть.
- В файле configuration.py должен быть заполнен параметр ALLOWED_HOSTS:
ALLOWED_HOSTS = ['netbox.linkmeup.ru', 'localhost']
Тут нужно указать все возможные имена NetBox, к которым вы будете обращаться, например, может быть внешний IP-адрес или 127.0.0.1 или DNS-alias.
Если этого не будет сделано, сайт NetBox не откроется и будет показывать 400. - В этом же файле должен быть указан SECRET_KEY, который можно выдумать самому или сгенерировать скриптом.
- Главная страница будет показывать 502 Bad Gateway, если что-то не так с настройкой базы PostgreSQL: проверьте хост(если ставили на другую машину), порт, имя базы, имя пользователя, пароль.
- С некоторых пор NetBox по умолчанию не даёт никаких прав на чтение без авторизации.
Изменяется это всё в том же configuration.py:
EXEMPT_VIEW_PERMISSIONS = ['*']
- А ещё API запросы будут возвращать 200 и не работать, если в API URL не будет слэша в конце.
curl -X GET -H "Accept: application/json; indent=4" "http://netbox.linkmeup.ru:45127/api/dcim/devices"
Немного о PostgreSQL
Для подключения к серверу:
psql -U <i>username</i> -h <i>hostname</i> <i>db_name</i>
Например:
psql -U netbox -h localhost netbox
Для вывода всех таблиц:
/dt
Для выхода:
/q
Для дампа БД:
pg_dump -U <i>username</i> -h <i>hostname</i> <i>db_name</i> > netbox.sql
Если не хочется каждый раз вводить пароль:
echo *:*:*:<i>username</i>:<i>password</i> > ~/.pgpass
chmod 600 ~/.pgpass
Если у вас есть своя инсталляция и не хочется вносить всё руками, можно просто сделать так, взяв дамп текущей БД NetBox тут:
psql -U <i>username</i> -h <i>hostname</i> <i>db_name</i> < netbox_initial_db.sql
Если предварительно нужно дропнуть все таблицы (а сделать это придётся), то можно подготовить заранее файл:
psql -U <i>username</i> -h <i>hostname</i> <i>db_name</i>
\o drop_all_tables.sql
select 'drop table ' || tablename || ' cascade;' from pg_tables;
\q
psql -U <i>username</i> -h <i>hostname</i> <i>db_name</i> -f drop_all_tables.sql
Полезные ссылки
- Сам NetBox на guthub
- Контейнерная версия
- Полная инструкция по установке и вся документация по продукту
- Documenting your network infrastructure in NetBox, integrating with Ansible over REST API
- IPAM NetBox and its API, Docker, Postman
- IPAM NetBox and its API, configuration templates with Python
- SDK для работы с NetBox в Python
- Документация по API
- Mailing list
- Slack-канал NetworkToCode
- Что такое REST
- Инсталляция NetBox для нужд АДСМ