- en
 - Language: ru
 
- Documentation version: latest
 
Пример использования SQLite
В 15 разделе был пример разбора вывода команды show ip dhcp snooping binding. На выходе мы получили информацию о параметрах подключенных устройств (interface, IP, MAC, VLAN).
В таком варианте можно посмотреть только все подключенные устройства к коммутатору. Если же нужно узнать на основании одного из параметров другие, то в таком виде это не очень удобно.
Например, если нужно по IP-адресу получить информацию о том, к какому интерфейсу подключен компьютер, какой у него MAC-адрес и в каком он VLAN, то по выводу скрипта это сделать не очень просто и, главное, не очень удобно.
Запишем информацию, полученную из вывода sh ip dhcp snooping binding в SQLite. Это позволит делать запросы по любому параметру и получать недостающие. Для этого примера достаточно создать одну таблицу, где будет храниться информация.
Определение таблицы прописано в отдельном файле dhcp_snooping_schema.sql и выглядит так:
create table if not exists dhcp (
    mac          text not NULL primary key,
    ip           text,
    vlan         text,
    interface    text
);
Для всех полей определен тип данных «текст».
MAC-адрес является первичным ключом нашей таблицы, что вполне логично, так как MAC-адрес должен быть уникальным.
Кроме того, используется выражение create table if not exists -
SQLite создаст таблицу только в том случае, если она не существует.
Теперь надо создать файл БД, подключиться к базе данных и создать таблицу (файл create_sqlite_ver1.py):
Комментарии к файлу:
при выполнении строки
conn = sqlite3.connect('dhcp_snooping.db'):создается файл dhcp_snooping.db, если его нет
создается объект Connection
в БД создается таблица (если ее не было) на основании команд, которые указаны в файле dhcp_snooping_schema.sql:
открывается файл dhcp_snooping_schema.sql
schema = f.read()- весь файл считывается в одну строкуconn.executescript(schema)- метод executescript позволяет выполнять команды SQL, которые прописаны в файле
Выполнение скрипта:
$ python create_sqlite_ver1.py
Creating schema...
Done
В результате должен быть создан файл БД и таблица dhcp.
Проверить, что таблица создалась, можно с помощью утилиты sqlite3, которая позволяет выполнять запросы прямо в командной строке.
Список созданных таблиц выводится таким образом:
$ sqlite3 dhcp_snooping.db "SELECT name FROM sqlite_master WHERE type='table'"
dhcp
Теперь нужно записать информацию из вывода команды sh ip dhcp snooping binding в таблицу (файл dhcp_snooping.txt):
MacAddress          IpAddress        Lease(sec)  Type           VLAN  Interface
------------------  ---------------  ----------  -------------  ----  --------------------
00:09:BB:3D:D6:58   10.1.10.2        86250       dhcp-snooping   10    FastEthernet0/1
00:04:A3:3E:5B:69   10.1.5.2         63951       dhcp-snooping   5     FastEthernet0/10
00:05:B3:7E:9B:60   10.1.5.4         63253       dhcp-snooping   5     FastEthernet0/9
00:09:BC:3F:A6:50   10.1.10.6        76260       dhcp-snooping   10    FastEthernet0/3
Total number of bindings: 4
Во второй версии скрипта сначала вывод в файле dhcp_snooping.txt обрабатывается регулярными выражениями, а затем записи добавляются в БД (файл create_sqlite_ver2.py):
Примечание
Пока что файл БД каждый раз надо удалять, так как скрипт пытается его создать при каждом запуске.
Комментарии к скрипту:
в регулярном выражении, которое проходится по выводу команды sh ip dhcp snooping binding, используются не именованные группы, как в примере раздела Регулярные выражения, а нумерованные
группы созданы только для тех элементов, которые нас интересуют
result - это список, в котором хранится результат обработки вывода команды
но теперь тут не словари, а кортежи с результатами
это нужно для того, чтобы их можно было сразу передавать на запись в БД
Перебираем в полученном списке кортежей элементы
В этом скрипте используется еще один вариант записи в БД
строка query описывает запрос. Но вместо значений указываются знаки вопроса. Такой вариант записи запроса позволяет динамически подставлять значение полей
затем методу execute передается строка запроса и кортеж row, где находятся значения
Выполняем скрипт:
$ python create_sqlite_ver2.py
Creating schema...
Done
Inserting DHCP Snooping data
Проверим, что данные записались:
$ sqlite3 dhcp_snooping.db "select * from dhcp"
-- Loading resources from /home/vagrant/.sqliterc
mac                ip          vlan        interface
-----------------  ----------  ----------  ---------------
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/1
00:05:B3:7E:9B:60  10.1.5.4    5           FastEthernet0/9
00:09:BC:3F:A6:50  10.1.10.6   10          FastEthernet0/3
Теперь попробуем запросить по определенному параметру:
$ sqlite3 dhcp_snooping.db "select * from dhcp where ip = '10.1.5.2'"
-- Loading resources from /home/vagrant/.sqliterc
mac                ip          vlan        interface
-----------------  ----------  ----------  ----------------
00:04:A3:3E:5B:69  10.1.5.2    5           FastEthernet0/10
То есть, теперь на основании одного параметра можно получать остальные.
Переделаем скрипт таким образом, чтобы в нём была проверка на наличие файла dhcp_snooping.db. Если файл БД есть, то не надо создавать таблицу, считаем, что она уже создана.
Файл create_sqlite_ver3.py:
Теперь есть проверка наличия файла БД, и файл dhcp_snooping.db будет создаваться только в том случае, если его нет. Данные также записываются только в том случае, если не создан файл dhcp_snooping.db.
Примечание
Разделение процесса создания таблицы и заполнения ее данными вынесено в задания к разделу.
Если файла нет (предварительно его удалить):
$ rm dhcp_snooping.db
$ python create_sqlite_ver3.py
Creating schema...
Done
Inserting DHCP Snooping data
Проверим. В случае, если файл уже есть, но данные не записаны:
$ rm dhcp_snooping.db
$ python create_sqlite_ver1.py
Creating schema...
Done
$ python create_sqlite_ver3.py
Database exists, assume dhcp table does, too.
Inserting DHCP Snooping data
Если есть и БД и данные:
$ python create_sqlite_ver3.py
Database exists, assume dhcp table does, too.
Inserting DHCP Snooping data
Error occurred:  UNIQUE constraint failed: dhcp.mac
Error occurred:  UNIQUE constraint failed: dhcp.mac
Error occurred:  UNIQUE constraint failed: dhcp.mac
Error occurred:  UNIQUE constraint failed: dhcp.mac
Теперь делаем отдельный скрипт, который занимается отправкой запросов в БД и выводом результатов. Он должен:
ожидать от пользователя ввода параметров:
имя параметра
значение параметра
делать нормальный вывод данных по запросу
Файл get_data_ver1.py:
Комментарии к скрипту:
из аргументов, которые передали скрипту, считываются параметры key, value
из списка keys удаляется выбранный ключ. Таким образом, в списке остаются только те параметры, которые нужно вывести
подключаемся к БД
conn.row_factory = sqlite3.Row- позволяет далее обращаться к данным в колонках по имени колонки
из БД выбираются те строки, в которых ключ равен указанному значению
в SQL значения можно подставлять через знак вопроса, но нельзя подставлять имя столбца. Поэтому имя столбца подставляется через форматирование строк, а значение - штатным средством SQL.
Обратите внимание на
(value,)- таким образом передается кортеж с одним элементом
Полученная информация выводится на стандартный поток вывода: * перебираем полученные результаты и выводим только те поля, названия
которых находятся в списке keys
Проверим работу скрипта.
Показать параметры хоста с IP 10.1.10.2:
$ python get_data_ver1.py ip 10.1.10.2
Detailed information for host(s) with ip 10.1.10.2
----------------------------------------
mac         : 00:09:BB:3D:D6:58
vlan        : 10
interface   : FastEthernet0/1
----------------------------------------
Показать хосты в VLAN 10:
$ python get_data_ver1.py vlan 10
Detailed information for host(s) with vlan 10
----------------------------------------
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
----------------------------------------
Вторая версия скрипта для получения данных с небольшими улучшениями:
Вместо форматирования строк используется словарь, в котором описаны запросы, соответствующие каждому ключу.
Выполняется проверка ключа, который был выбран
Для получения заголовков всех столбцов, который соответствуют запросу, используется метод keys()
Файл get_data_ver2.py:
В этом скрипте есть несколько недостатков:
не проверяется количество аргументов, которые передаются скрипту
хотелось бы собирать информацию с разных коммутаторов. А для этого надо добавить поле, которое указывает, на каком коммутаторе была найдена запись
Кроме того, многое нужно доработать в скрипте, который создает БД и записывает данные.
Все доработки будут выполняться в заданиях этого раздела.