Иногда, в нашей работе, возникает потребность учёта всего сетевого оборудования: типы, модели, адреса, прошивки, схемы соединений и так далее. И вот, просмотрев несколько вариантов ПО, выбор пал на открытый проект GLPI. Функционал у системы богатый, конкретно в нашем случае, использовалась для учёта «железа» и, главное, для учёта схем соединения (какой порт какого коммутатора куда подключен). В рамках осуществления основной деятельности организации (предоставление доступка к интернету), возникла (конечно не вдруг, а сугубо по плану) потребность резервного копирования конфигурации коммутаторов, зачем и почему данная операция необходима — это должно быть всем известно. А о том, как это реализовать, в связке с GLPI и будет данная статья.
Для осуществления задуманного, необходим список адресов оборудования и список производителей, все эти данные есть в БД GLPI, конечно если Вы их туда предварительно занесли. IP-адреса нужны для соединения по сети, а для чего нам знать производителя? Дело в том, что каждый изготовитель сетевого оборудования, в силу разных причин, привносит туда свои «оригинальные» идеи и посему команды для управления железками различаются. В нашем конкретном случае производителей всего два, но ничто не мешает список расширить.
Операцию копирования конфига будем выполнять через telnet-соединение, тоже самое можно делать и через SNMP, но в данном случае на всём железе SNMP на запись (выполнение команд) закрыт.
Языком реализации выбран был PERL. Отчего так? Ну, в то время мной пилилось, на нём-же, ещё кое-какое ПО (сборщик и разборщик RDR, вэб морда к нему) и, по сему — перл. В качестве ОС — GNU/Linux.
Приступим к коду:
Подключаем необходимые модули:
Функция удаления пробелов, реализована самостоятельно, отчего и почему, уже не помню но пусть будет:
Дабы два раза не вставать, в скрипте параллельно реализовано архивирование, копирование и удаление старых файлов. По возможности используются системные команды:
Подключаемся к БД:
Выбираем необходимые адреса коммутаторов нужного производителя и, соответсвенно, «дёргаем» потребные нам процедуры (которые будут описаны ниже):
Стоит отметить, что значения manufacturers_id и states_id (первое — код производителя, второе — статус оборудования («введён в эксплуатацию», «в проекте» и т.д.)) могут, да и скорее всего будут, различаться, т.к. создаются они автоматически при добавлении позиций в БД. В данном случае производитель «1» — это EdgeCore («3» — D-Link) и статус «1» — «Включен» т.е. введён в эксплуатацию. Отслеживание статуса необходимо, дабы исключить попытки соединения с неактивными, по разным причинам, железяками.
Далее две, почти одинаковые, процедуры, реализующие диалог между скриптом и коммутатором на тему «а скопируй-ка братец свой текущий конфиг на tftp-сервер»:
Адрес сервера и параметров соединения с БД, логичней было вынести в отдельный файлик, но в силу расположения небесных тел в тот момент, было оставлено так. Команды print оставлены для вывода в лог. Запуск скрипта производится по времени cron-ом.
Вот так просто и непринуждённо была автоматизирована рутинная операция. Традиционно, исходники доступны тут.
P.S. Думал в какой поток разместить статью, метался между «Администрированием» и «Разработкой», в итоге остановился на первом варианте.
Для осуществления задуманного, необходим список адресов оборудования и список производителей, все эти данные есть в БД GLPI, конечно если Вы их туда предварительно занесли. IP-адреса нужны для соединения по сети, а для чего нам знать производителя? Дело в том, что каждый изготовитель сетевого оборудования, в силу разных причин, привносит туда свои «оригинальные» идеи и посему команды для управления железками различаются. В нашем конкретном случае производителей всего два, но ничто не мешает список расширить.
Операцию копирования конфига будем выполнять через telnet-соединение, тоже самое можно делать и через SNMP, но в данном случае на всём железе SNMP на запись (выполнение команд) закрыт.
Языком реализации выбран был PERL. Отчего так? Ну, в то время мной пилилось, на нём-же, ещё кое-какое ПО (сборщик и разборщик RDR, вэб морда к нему) и, по сему — перл. В качестве ОС — GNU/Linux.
Приступим к коду:
Подключаем необходимые модули:
#!/usr/bin/perl use Net::Telnet (); use IO::File; use Getopt::Long; use DBI;
Функция удаления пробелов, реализована самостоятельно, отчего и почему, уже не помню но пусть будет:
# функция удаления пробельных символов sub trim { my($string)=@_; for ($string) { s/^\s+//; s/\s+$//; } return $string; }
Дабы два раза не вставать, в скрипте параллельно реализовано архивирование, копирование и удаление старых файлов. По возможности используются системные команды:
# Архивируем конфиги $date = `/bin/date "+%Y%m%d"`; $date = trim($date); $arch = "tar -czvf /var/srv/backup/conf/conf-".$date.".tgz /var/lib/tftpboot/"; my $result = `$arch`; # удаляем архивы давностью в неделю $del = '/bin/find /var/srv/backup/conf/ -ctime +7 -name conf-*.tgz -exec rm {} \; -print > /var/log/switch-conf_backup.log'; my $delResult = `$del`;
Подключаемся к БД:
# конектимся к GLPI базе my $dsn = 'DBI:mysql:glpi:192.168.123.222'; my $db_user_name = 'user'; my $db_password = 'password'; my ($id, $password); my $dbh = DBI->connect($dsn, $db_user_name, $db_password);
Выбираем необходимые адреса коммутаторов нужного производителя и, соответсвенно, «дёргаем» потребные нам процедуры (которые будут описаны ниже):
my $sth = $dbh->prepare(qq{SELECT ip FROM glpi_networkequipments WHERE manufacturers_id=1 AND states_id=1}); $sth->execute(); while (my ($ip) = $sth->fetchrow_array()) { # print "$ip\n"; if ($ip eq "" || $ip =~ /^#+/) { # не делать ничего. Тут криво, согласен :) } else { # Запускаем соответствующую процедуру connectSwitchEdgeCore("$ip"); } } $sth->finish(); # выбираем все D-Link со статусом "Включен" my $sth = $dbh->prepare(qq{SELECT ip FROM glpi_networkequipments WHERE manufacturers_id=3 AND states_id=1}); $sth->execute(); while (my ($ip) = $sth->fetchrow_array()) { if ($ip eq "" || $ip =~ /^#+/) { } else { connectSwitchDlink("$ip"); } } $sth->finish(); $dbh->disconnect();
Стоит отметить, что значения manufacturers_id и states_id (первое — код производителя, второе — статус оборудования («введён в эксплуатацию», «в проекте» и т.д.)) могут, да и скорее всего будут, различаться, т.к. создаются они автоматически при добавлении позиций в БД. В данном случае производитель «1» — это EdgeCore («3» — D-Link) и статус «1» — «Включен» т.е. введён в эксплуатацию. Отслеживание статуса необходимо, дабы исключить попытки соединения с неактивными, по разным причинам, железяками.
Далее две, почти одинаковые, процедуры, реализующие диалог между скриптом и коммутатором на тему «а скопируй-ка братец свой текущий конфиг на tftp-сервер»:
# telnet-ом цепляемся к коммутаторам и сливаем конфиг на tftp сервер # слив конфигурации с коммутатора EdgeCore sub connectSwitchEdgeCore { $hostname = "$_[0]"; $username = "user"; $passwd = "password"; $date = `/bin/date "+%Y%m%d"`; $str_fn=$hostname; print $str_fn; $tftpserver="20.20.20.20"; $conn = new Net::Telnet ( Timeout=>3, Errmode=>'return', Prompt => '/\#.?$/i'); $conn->open(Host => $hostname); $conn->waitfor('/ame[: ]*$/'); $conn->print($username); $conn->waitfor('/ord[: ]*$/'); $conn->print($passwd); $conn->print("copy running-config tftp"); $conn->waitfor('/ess[: ]*$/'); $conn->print($tftpserver); $conn->waitfor('/ame[: ]*$/'); $conn->print($str_fn); $conn->print("exit"); $conn->print("logout"); } # слив конфигурации с коммутатора D-Link sub connectSwitchDlink { $hostname = "$_[0]"; $username = "user"; $passwd = "password"; $date = `/bin/date "+%Y%m%d"`; $str_fn=$hostname; print "$str_fn\n"; $tftpserver="20.20.20.20"; $conn = new Net::Telnet ( Timeout=>3, Errmode=>'return', Prompt => '/\#.?$/i'); $conn->open(Host => $hostname); $conn->waitfor('/ame[: ]*$/'); $conn->print($username); $conn->waitfor('/ord[: ]*$/'); $conn->print($passwd); $conn->print("upload cfg_toTFTP $tftpserver dest_file $hostname"); $conn->waitfor('/Success/'); $conn->print("logout"); }
Адрес сервера и параметров соединения с БД, логичней было вынести в отдельный файлик, но в силу расположения небесных тел в тот момент, было оставлено так. Команды print оставлены для вывода в лог. Запуск скрипта производится по времени cron-ом.
Вот так просто и непринуждённо была автоматизирована рутинная операция. Традиционно, исходники доступны тут.
P.S. Думал в какой поток разместить статью, метался между «Администрированием» и «Разработкой», в итоге остановился на первом варианте.
