Механизм расширений (plugins) ISPmanager предназначен для добавления собственных модулей в панель управления. В данном документе приводится пример создания модуля, который будет работать со списком произвольных строк в файле /etc/myconfig. По аналогии с этим примером вы сможете создавать собственные расширения панели управления.
Процесс создания собственного расширения можно разделить на два этапа. Первый - это создание XML-документа, в котором будут описаны все функции, обрабатываемые данным расширением, а также все элементы интерфейса, необходимые для того, чтобы вы увидели ваш модуль в панели управления. Второй этап - это разработка программы или скрипта, который будет реализовывать обработку данных в процессе работы расширения, то есть реализовывать функции.
XML-документ, в котором описывается интерфейс вашего расширения панели управления, должен располагаться в папке /usr/local/ispmgr/etc и называться ispmgr_mod_xxx.xml, где вместо xxx вы можете указать любое название, например, myconfig (ispmgr_mod_myconfig.xml). Документ обязательно должен быть в кодировке UTF-8 и иметь следующий вид:
<?xml version="1.0" encoding="UTF-8"?> <mgrdata> описание функций расширения описание элементов меню описание таблиц и форм описание сообщений </mgrdata>
Данная часть XML-документа определяет имя программы или скрипта, который будет реализовывать функции, тип взаимодействия программы и панели управления, а также набор функций, предоставляемые данным расширением. Она должна иметь следующий вид:
<handler name="программа" type="тип"> <func>функция1</func> <func>функция2</func> ... </handler>
В качестве атрибута name укажите имя программы, которая реализует функции, например, myconfig.pl. В качества атрибута type укажите тип взаимодействия панели управления и вашей программы. На текущий момент возможны два типа:
![]() |
cgi - программа имеет интерфейс CGI, то есть получает данные из переменных окружения и/или стандартного ввода (POST). |
![]() |
xml - программа получает из стандартного ввода XML-документ, описывающий данные, которые передала панель управления. |
После этого нужно определить, какие функции будет предоставлять ваше расширение. Все функции можно поделить на три типа:
![]() |
Список элементов - таблица с панелью инструментов. |
![]() |
Свойства элемента - форма, которая применяется для создания нового либо изменения существующего элемента. Также форма может применяться, если ваш модуль не рассчитан на работу с множеством элементов, а служит для настройки набора каких-либо параметров. |
![]() |
Действие - данный тип функций не предусматривает наличия собственных элементов интерфейса, а является операцией над одним или несколькими элементами из списка. |
Имена функций могут содержать буквы латинского алфавита, цифры и точки и должны быть уникальными. Список имеющихся функций можно найти в файле /usr/local/ispmgr/etc/ispmgr.xml.
Для того, чтобы вы могли осуществить доступ к вашему расширению, необходимо создать соответствующие элементы меню навигации панели управления. Для этого вы должны добавить в ваш XML-документ следующий блок:
<mainmenu level="уровень доступа"> <node name="название категории"> <node name="функция1"/> <node name="функция2"/> </node> </mainmenu>
Во-первых, вы должны определиться, на каком уровне доступа вы хотите видеть ваше расширение. На текущий момент доступны следующие уровни доступа к панели управления:
![]() |
7 - администратор сервера (root). |
![]() |
6 - реселлер (только в ISPmanager Pro). |
![]() |
5 - пользователь. |
![]() |
4 - пользователь с доступом к shell. |
![]() |
3 - FTP аккаунт. |
![]() |
2 - почтовый аккаунт. |
В атрибуте level укажите цифру, соответствующую уровню доступа. Если вы хотите, чтобы модуль был доступен на нескольких уровнях, добавьте отдельный блок mainmenu для каждого из них.
В качестве названия категории укажите имя, указанное в атрибуте name узла node для соответствующей категории меню навигации, описанному в файле /usr/local/ispmgr/etc/ispmgr.xml. Предположим, вы хотите дать доступ к вашему расширению всем пользователям и разместить соответствующий пункт меню в раздел "Инструменты" меню навигации. Для этого необходимо найти раздел <mainmenu level="5"> и соответствующий раздел <node name="tool">. То есть в качестве названия категории мы должны указать значение tool.
После этого необходимо добавить один или несколько элементов меню в соответствующий раздел меню навигации. Для этого добавляем узлы node и в качестве атрибута name указываем имя функции, к которой необходимо обратиться при нажатии соответствующего пункта меню.
Далее нужно описать интерфейс для функций, предоставляемых вашим расширением. Наш тестовый модуль предполагает наличие возможности просмотра существующих записей в файле /etc/myconfig, а также добавления новых и изменения существующих записей. Также нужна возможность удаления, но эта функция относится к разряду действие и наличия интерфейса не предполагает.
Итак, для того, чтобы реализовать список записей, нужно добавить следующий блок в XML-документ:
<metadata name="функция1" type="list" key="имя_поля"> <toolbar> <toolbtn func="функция2" type="new" img="t-new.gif" name="new"/> <toolbtn func="функция2" type="edit" img="t-edit.gif" name="edit" default="yes"/> <toolbtn func="функция3" type="group" img="t-delete.gif" name="delete"/> </toolbar> <coldata> <col sort="alpha" sorted="yes" name="имя_поля" type="data"/> </coldata> </metadata>
Здесь написано, что мы хотим добавить интерфейс к нашей функции "функция1" типа список (type="list"), в котором ключевым элементом будет "имя_поля". Уникальный ключевой элемент необходим для того, чтобы однозначно идентифицировать запись в списке. Именно это значение будет передано функциям, работающим с элементами списка, таким как просмотр параметров элемента, удаление и прочим.
После этого описывается панель инструментов, в котором присутствуют три кнопки: создать (name="new"), редактировать (name="edit") и удалить (name="delete") элемент. Вы можете указать действие, которое будет осуществляться при двойном щелчке по записи путём добавления атрибута default="yes" в нужный узел, описывающий элемент панели инструментов. В нашем случае при двойном щелчке по записи будет вызвана функция редактирования параметров записи. Как вы могли заметить, в качестве атрибута func в первых двух кнопках панели инструментов указано одно и то же имя функции. Это получается вследствие того, что в нашем случае одна функция будет реализовывать создание, а также просмотр и редактирование параметров записей. Тип функции определяется атрибутом type:
![]() |
new - создание нового элемента. |
![]() |
edit - редактирование существующего элемента. |
![]() |
group - операция над группой элементов. |
![]() |
editlist - дочерний список, связанный с одним из элементов текущего списка. |
![]() |
list - дочерний список, не привязанный ни к одному из элементов текущего списка. |
Далее указывается блок coldata, в который нужно добавить необходимое количество узлов col, по одному на каждую колонку в таблице. В нашем случае таблица состоит из единственной колонки, в которой будет отображаться поле "имя_поля", которое будет возвращать функция создания списка для каждого элемента. Вы должны указать тип записей в колонке. На текущий момент существует три типа:
![]() |
data - в данной колонке будет отображаться информация по каждому элементу, переданная в поле с именем, указанным в атрибуте name (в нашем случае это "имя_поля"). |
![]() |
msg - этот тип может быть полезен, если вы имеете конечный набор значений, возвращаемых в поле с именем, указанным в атрибуте name, например, статус записи (включено,отключено и т.п.), и хотите, чтобы эти значения отображались по разному, в зависимости от языка панели управления. В этом случае значения, возвращаемые в этом поле, должны состоять из букв латинского алфавита, цифр, точек и знаков "_". |
![]() |
indicator - в данной колонке будeт отображаться индикаторы использования того или иного ресурса, например, дискового пространства или трафика. В этом случае для каждого элемента, для которого необходимо вывести индикатор, следует добавить XML-узел с именем данной колонки списка и добавить в этот узел два атрибута: used="число" и limit="число". |
Если вы хотите, чтобы данные в столбце можно было сортировать, добавьте атрибут sort, в котором укажите одно из следующих значений, зависящее от типа данных в данном столбце:
![]() |
alpha - строки из букв латинского алфавита и цифр. |
![]() |
digit - числа. |
![]() |
indicator - индикаторы (например, дисковое пространство, трафик и прочее). |
![]() |
ip - IP-адреса. |
![]() |
prop - набор параметров (например, включен/отключен). |
Если вы хотите, чтобы записи в таблице автоматически сортировались по одному из столбцов при входе в модуль, добавьте атрибут sorted="yes"
Если же вы хотите, чтобы на основе данных, содержащихся в одном или нескольких столбцах, отображалась статистическая информация, добавьте атрибут stat="yes".
После этого нужно добавить описание интерфейса для формы создания и редактирования свойств записи. Для этого добавьте следующий блок в XML-документ:
<metadata name="функция2" type="form"> <form> <field name="сообщение"> <input type="text" name="имя_поля"/> </field> </form> </metadata>
Здесь указывается, что мы хотим добавить форму (type="form") для работы с функцией "функция2". Для каждого элемента управления необходимо добавить отдельный блок field, состоящий из заголовка поля и, собственно, самого элемента управления. Заголовок для данного поля указывается с помощью атрибута name="сообщение". При этом необходимо добавить соответствующий узел в блок сообщений для данной функции. О правилах составления блоков сообщений будет сказано ниже. После этого нужно добавить элемент управления. Встречаются три типа элементов управления:
![]() |
input - поле ввода. Существует несколько типов полей ввода, которые указываются в атрибуте type:
|
||||||
![]() |
textarea - многострочное поле ввода. | ||||||
![]() |
select - выпадающий список. |
С помощью атрибута name необходимо указать имя параметра функции, который связан с данным элементом управления. Если вы хотите задать некоторое значение по умолчанию для элемента управления, вы можете использовать атрибут value="значение_по_умолчанию".
Также существуют дополнительные атрибуты для полей field. Если вы хотите, чтобы поле было скрыто по умолчанию, и управлять его видимостью с помощью javascript, добавьте атрибут hidden="yes". Если же вы используете в качестве элемента управления <input type="text"/>, и это текстовое поле подразумевает ввод нескольких значений, вы можете добавить атрибут zoom="5". При этом рядом с текстовым полем появится дополнительная кнопка, при нажатии на которую текстовое поле будет расширяться на количество строк, указанных в значении данного атрибута, что позволит вводить данные построчно.
Сообщения ISPmanager являются по сути всем тем текстом, который вы видите в панели управления, и который не привязан непосредственно к данным, полученным в результате выполнения функций. Сообщения делятся по языкам интерфейса. Для каждого языка необходимо добавить блок:
<lang name="язык"> сообщения меню навигации сообщения функций </lang>
В качестве языка необходимо указать одно из следующих значений:
![]() |
de - немецкий |
![]() |
en - английский |
![]() |
es - испанский |
![]() |
fr - французский |
![]() |
ru - русский |
Основным языком интерфейса является английский. Если в качестве языка панели управления выбран другой язык, и необходимое сообщение не найдено, будет использовано аналогичное сообщения из английского языка.
Далее необходимо добавить в этот блок сообщения для всех пунктов меню, которые вы создали в описании элементов меню. Для этого добавим блок следующего вида:
<messages name="desktop"> <msg name="menu_функция1">сообщение1</msg> <msg name="menu_функция2">сообщение2</msg> </messages>
То есть для каждого пункта меню вида <node name="функция1"/> необходимо добавить сообщение вида <msg name="menu_функция1">сообщение1</msg>. В качестве сообщение1 укажите текст пункта меню в кодировке UTF-8.
Все остальные сообщения делятся по функциям, поэтому для каждой функции, предоставляемой вашим расширением ISPmanager, необходимо добавить в XML-документ блок следующего вида:
<messages name="функция1"> <msg name="имя_сообщения">сообщение</msg> ... </messages>
Существуют следующие стандартные типы сообщений для модулей ISPmanager (данные названия необходимо указать вместо имя_сообщения):
![]() |
title - заголовок модуля (списка или формы). |
![]() |
title_new - заголовок формы создания нового элемента. |
![]() |
hint_default - подсказка о назначении данного модуля |
Все остальные сообщения делятся на следующие типы:
![]() |
названия столбцов списка - в качестве имени сообщения необходимо указать значения, указанные в атрибуте name узла col. |
![]() |
значения для столбцов типа msg - в качестве имени сообщения необходимо указать значение, которое может быть передано в соответствующем параметре элемента, возвращённого функцией. Если значений несколько, необходимо создать отдельное сообщение для каждого из них. |
![]() |
названия полей формы - в качестве имени сообщения необходимо указать значения, указанные в атрибуте name узла field. |
![]() |
значения для элементов управления типа select - в качестве имени сообщения необходимо указать то значение, которое может быть передано в этом списке. Если соответствующее сообщение не будет найдено, будет отображено само значение, возвращённое функцией. Если значений может быть несколько, необходимо создать отдельное сообщение для каждого из них. |
![]() |
подсказки к полям формы - в качестве имени сообщения необходимо указать значения, указанные в атрибуте name узла field с префиксом hint_, например, hint_username. |
![]() |
подсказки к кнопкам в панели инструментов - в качестве имени сообщения необходимо указать значения, указанные в атрибуте name узла toolbtn с префиксом hint_, например, hint_new. |
![]() |
сообщения javascript - к ним относятся все сообщения, используемые в javascript. К стандартным сообщениям такого рода можно отнести сообщение подтверждения удаления элемента. В этом случае в качестве имени сообщение необходимо указать msg_функция1_delete, где в качестве значения "функция1" необходимо указать имя функции из расширения. |
Ещё раз следует обратить ваше внимание на тот факт, что все сообщения должны быть представлены в кодировке UTF-8. В противном случае XML-документ не сможет быть загружен и ISPmanager не запустится.
Ниже приведён пример XML-документа ispmgr_mod_myconf.xml
<?xml version="1.0" encoding="UTF-8"?> <mgrdata> <handler name="myconf.pl" type="cgi"> <func>myconf</func> <func>myconf.edit</func> <func>myconf.delete</func> </handler> <metadata name="myconf" type="list" key="item"> <toolbar> <toolbtn func="myconf.edit" type="new" img="t-new.gif" name="new"/> <toolbtn func="myconf.edit" type="edit" img="t-edit.gif" name="edit" default="yes"/> <toolbtn func="myconf.delete" type="group" img="t-delete.gif" name="delete"/> </toolbar> <coldata> <col sort="alpha" sorted="yes" name="item" type="data"/> </coldata> </metadata> <metadata name="myconf.edit" type="form"> <form> <field name="item"> <input type="text" name="item"/> </field> </form> </metadata> <mainmenu level="7"> <node name="tool"> <node name="myconf"/> </node> </mainmenu> <lang name="en"> <messages name="desktop"> <msg name="menu_myconf">Test module</msg> </messages> <messages name="myconf"> <msg name="title">Test module</msg> <msg name="item">Item from myconf</msg> <msg name="msg_myconf_delete">Delete item </msg> <msg name="hint_new">New item</msg> <msg name="hint_edit">Edit item</msg> <msg name="hint_delete">Delete item</msg> </messages> <messages name="myconf.edit"> <msg name="title">Edit item</msg> <msg name="title_new">New item</msg> <msg name="item">Item value</msg> <msg name="hint_item">The value of the item from myconf</msg> </messages> </lang> <lang name="ru"> <messages name="desktop"> <msg name="menu_myconf">Тестовый модуль</msg> </messages> <messages name="myconf"> <msg name="title">Тестовый модуль</msg> <msg name="item">Элемент из myconf</msg> <msg name="msg_myconf_delete">Удалить элемент </msg> <msg name="hint_new">Новый элемент</msg> <msg name="hint_edit">Редактировать элемент</msg> <msg name="hint_delete">Удалить элемент</msg> </messages> <messages name="myconf.edit"> <msg name="title">Редактировать элемент</msg> <msg name="title_new">Новый элемент</msg> <msg name="item">Значение</msg> <msg name="hint_item">Значение элемента из myconf</msg> </messages> </lang> </mgrdata>
После того, как мы подготовили XML-документ, описывающий интерфейс расширения, необходимо написать программу или скрипт, который будет обрабатывать данные для расширения. Данная программа должна располагаться в директории /usr/local/ispmgr/addon, принадлежать пользователю root и иметь права доступа 700. Имя программы должно совпадать со значением, указанным в атрибуте name узла handler XML-документа.
В качестве результата работы программы должен быть XML-документ в формате вывода результатов выполнения функций ISPmanager 4.
Для того, чтобы выяснить от имени какого пользователя была вызвана функция ISPmanager, которая привела к выполнению вашей программы, можно использовать переменную окружения REMOTE_USER. При этом вы можете быть уверены, что данный пользователь был авторизован.
Ниже приведён пример CGI-программы myconf.pl, написанной на языке perl.
#!/usr/bin/perl use CGI qw/:standard/; $Q = new CGI; $func = $Q->param(func); print "<doc>"; if( $func eq "myconf" ){ &List; } elsif( $func eq "myconf.delete" ){ &Delete; } elsif( $func eq "myconf.edit" ){ if( $Q->param( "sok" ) ){ if( $Q->param( "elid" ) ){ &Set; } else{ &New; } print "<ok/>"; } else{ &Get; } } print "</doc>"; exit 0; sub List { if( open( IN, "/etc/myconf" ) ){ while( <IN> ){ chomp; print "<elem><item>$_</item></elem>"; } close( IN ); } } sub Get { $elid = $Q->param( "elid" ); print "<elid>$elid</elid><item>$elid</item>" if( $elid ); } sub Set { $elid = $Q->param( "elid" ); $item = $Q->param( "item" ); if( open( IN, "/etc/myconf" ) ){ if( open( OUT, ">/etc/myconf.new" ) ){ for( <IN> ){ chomp; if( $_ eq $elid ){ print OUT "$item\n"; $ok = 1; } else { print OUT "$_\n"; } } close( OUT ); } close( IN ); } if( $ok ){ rename( "/etc/myconf.new", "/etc/myconf" ); print "<ok/>"; } else { print "<error>Item hasn`t been updated</error>"; } } sub New { $elid = $Q->param( "elid" ); $item = $Q->param( "item" ); if( open( ADD, ">>/etc/myconf" ) ){ print ADD "$item\n"; close( ADD ); print "<ok/>"; } else { print "<error>Item hasn`t been added</error>"; } } sub Delete { $elid = $Q->param( "elid" ); if( open( IN, "/etc/myconf" ) ){ if( open( OUT, ">/etc/myconf.new" ) ){ for( <IN> ){ chomp; print OUT "$_\n" if( $_ ne $elid ); } close( OUT ); } close( IN ); } rename( "/etc/myconf.new", "/etc/myconf" ); print "<ok/>"; }
Если же вы используете программу в режиме xml, то, как было сказано выше, она получает из стандартного ввода XML, в котором также могут присутствовать блоки описания интерфейса для построения списков или форм, который вы описали в вашем XML-документе. У вас есть возможность корректировать с помощью вашей программы эти данные с целью изменения набора столбцов списка, полей форм, либо кнопок в панели инструментов. Также ваша программа должна добавить в этот документ необходимые XML-узлы с данными в формате вывода результатов выполнения функций ISPmanager 4 и возвратить его на стандартный вывод.