пятница, 16 марта 2012 г.

Слияние дорог - все дороги ведут в Рим?

В последние полгода я плотно засел за изучение PHP и MySQL, а в качестве тренировочной задачи для их освоения выбрал создание веб-интерфейса для управления почтовым сервером на работе. Можно сказать, что освоение состоялось - и там и там я чувствую себя довольно уверенно, а почтовый сервер обзавёлся многими полезными функциями. Некоторые функции я попробовал реализовать на Perl (пересчёт квот почтовых ящиков, удаление неиспользуемых ящиков).

Большинство задач для почтового сервера было уже решено и я стал подумывать, как бы расширить этот веб-интерфейс, чтобы он управлял не только почтовым сервером, но и дополнительно, например, прокси-сервером или DHCP-сервером. Я уже начал было расширение программы, хотел добавить в неё группы пользователей, но, реализовав задачу на 80%, остановился. Мной овладело чувство, что я делаю уже что-то не то. В качестве более универсальной базы данных для задач хранения информации о пользователях и настройках различных систем напрашивался LDAP.

Примерно два месяца назад я купил книжку "Основы SNMP" и потихоньку её читал. Даже настроил построение различных графиков с помощью пакетов Net-SNMP и RRDTool. В коммутаторах на работе я нашёл несколько полезных веток SNMP, которыми воспользовался при написании ещё одного скрипта на Perl. Этот скрипт получал списки MAC-адресов на портах управляемых коммутаторов и пытался строить таблицу соответствия IP-адреса компьютера, его MAC-адреса, имени в DNS, коммутатора и порта, к которому наиболее вероятно подключен этот компьютер. В ходе написания этого скрипта я воспользовался модулями DBI (пользовался в предыдущих скриптах на Perl), Net::DNS и Net::Ping. Для работы с SNMP я пользовался вызовом команд из пакета Net-SNMP, хотя по-хорошему лучше бы воспользоваться для этого модулем Net::SNMP.

Возвращаясь к веб-интерфейсу управления почтовым сервером: я хотел дописать к своей админке модуль синхронизации с Active Directory (основа которого - LDAP) и попытался написать его на PHP. Но у нас на работе (по всей России) используется очень много контроллеров домена, из которых только 7 работают в режиме репликации Master-Master. Остальные работают в режиме репликации Master-Slave, только лишь принимая реплики с основных серверов, и по сути выполняют функции кэширования данных каталога. Модуль на PHP работал нормально только при чтении, а в режиме обновления данных выдавал совершенно невнятную ошибку.

Я попытался реализовать то же самое на Perl с использованием модуля Net::LDAP и получил более вменяемую ошибку. Даже не ошибку, а вполне предсказуемое поведение - кэширующий сервер вернул мне т.н. Referrer, то есть отсылку на сервер, который может внести изменения в каталог. Текст ошибки был понятен, но главное заключалось в том, что из ответа сервера в Perl Net::LDAP можно было извлечь ссылку на сервер, а в PHP ни продиагностировать толком ошибку, ни извлечь адрес отсылки было нельзя. Можно было, конечно, прописать в модуле синхронизации данных два разных сервера для чтения и для записи или пользоваться только тем сервером, который имеет права на запись. Но если сейчас поступить так - это значит согласиться в дальнейшем терпеть ограничения PHP во всём, поэтому я реализовал этот модуль в виде отдельного скрипта на Perl, запускаемого по расписанию.

Теперь, собственно, о слиянии дорог. Когда я начал читать об устройстве LDAP и просмотрел файлы схем, я сразу понял, что LDAP очень похож на SNMP, хотя это две разные системы с разными задачами. Сходство заключается в использовании OID и ASN.1 для описания схем LDAP, причём дерево LDAP и дерево SNMP не пересекаются и даже растут из одного корня! SNMP растёт из 1.3.6.1.2, а LDAP - из 1.3.6.1.1, и оба они допускают использование частных схем, которые растут из 1.3.6.1.4. Частный номер, полученный в IANA для SNMP можно использовать и для LDAP. Есть даже рекомендации создавать частные MIB SNMP в ветке 1, а частные атрибуты и классы LDAP в веткe 2 - http://www.pro-ldap.ru/tr/zytrax/apa/oid.html.

Дорога разработки своего веб-приложения привела меня к LDAP.

Ранее я планировал изучить Perl, потому как мне он казался более перспективным и серьёзным языком, нежели PHP. И мои интуитивные предположения подтвердились - Perl действительно оказался более серьёзным языком, причём серьёзность его заключается вовсе не в его языковых свойствах, а в его педантично написанных модулях, которые позволяют в одном скрипте задействовать самые разные протоколы и технологии на полную катушку. Perl довольно сложен и уродлив, но он обладает уникальным свойством - позволяет легко склеивать самые разные технологии и протоколы.

Так течение несёт меня к от PHP и MySQL к Perl и LDAP. В ближайшее время собираюсь подвести итог разработки своей веб-админки, причесать её, описать и выложить в общий доступ, поскольку дальше развивать её я, видимо, не стану.

Конкуренцию Perl, насколько я понимаю, способна составить только Java (взять хотя-бы модули SNMP4J и JNDI), однако она не кажется мне средством быстрой разработки приложений. Она более строга и поэтому требует писать больше и более вдумчиво - энтерпрайз, ё-моё. Её я тоже планирую когда-нибудь попробовать, но почему то она мне заранее не нравится, хотя её строгость может показаться более притягательной после долгого знакомства с излишне свободным Perl.