Руководство для разработчиков

Добавление собственного модуля

В данной статье описано, как написать собственный модуль для ispmanager, который появится в панели в разделе Модули.

Для добавления своего модуля в ispmanager нужно добавить в директорию /usr/local/mgr5/etc/plugins/ispmgr xml-файл со специальной структурой:

Создайте файл exampleplugin.xml со следующим содержанием:

<?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
  <plugin name="exampleplugin">
   	<dist>1</dist>
	<weight>1</weight>
   	<pricelist>12345</pricelist>
   	<license>ExampleLicense</license>
<free/>
	<settings>exampleplugin.settings</settings>
	<msg name="desc_short" lang="ru">Модуль Example</msg>
	<msg name="desc_short" lang="en">Module Example</msg>
	<msg name="desc_full" lang="ru">Пример добавления модуля в ispmanager</msg>
	<msg name="desc_full" lang="en">Example of adding custom module to ispmanager</msg>
	<msg name="msg_help_links" dist="1" lang="ru">&lt;a href="http://example.com" target="_blank"&gt;Описание ссылки для версий Lite, Pro, Host&lt;/a&gt;</msg>
	<msg name="msg_help_links" dist="3" lang="ru">&lt;a href="https://rudocs.ispmanager.com/ispmanager-business/integratsiya-c-viruslive" target="_blank"&gt;Описание ссылки для версии Business&lt;/a&gt;</msg>
	<msg name="msg_help_links" dist="1" lang="en">&lt;a href="http://example.com" target="_blank"&gt;Link description for Lite, Pro, Host versions&lt;/a&gt;</msg>
	<msg name="msg_help_links" dist="3" lang="en">&lt;a href="http://example.com" target="_blank"&gt;Link description for Business version&lt;/a&gt;</msg>
  </plugin>
</mgrdata>

Описание тэгов:

  • Параметр name - имя модуля;
  • <dist> - опционально, указывает в какой версии будет использоваться модуль: 1 - lite, pro, host, 3 - business. При отсутствии будет использоваться во всех версиях;
  • <weight> - опционально, позволяет управлять порядком модуля во вкладке “Модули”. Модули выстраиваются в порядке от большего веса к меньшему. При отсутствии веса модуль будет в конце списка.
  • <pricelist> - опционально, id тарифа в биллинговой системе (если используется BILLmanager);
  • <license> - опционально, имя лицензии в биллинговой системе (если используется BILLmanager);
  • <free/> - опционально, добавляет для модуля метку, что он бесплатный;
  • <settings> - имя действия, которое будет выполняться при нажатии на кнопку настроек модуля;
  • <msg> - текстовые сообщения для отображения во вкладке модули

У тэгов <msg> есть 2 параметра:

  • lang - язык панели (“ru” - русский, “eng” - английский), в котором будет отображаться сообщение;
  • dist - версия ispmanager, в которой будет отображаться сообщение, аналогично тэгу <dist>.

Сообщения:

  • desc_short - краткое название модуля, используется в качестве заголовка;
  • desc_full - подробное описание модуля;
  • msg_help_links - опционально для добавления ссылок в меню “Показать полезные ссылки”.

Обратите внимание!

Тэг <weight> используется с релиза 6.90 (от 16.01.2024). В более ранних версиях использовать вместо него <group>integration</group> или <group>antiviruses</group> для добавления в соответствующий коллапс на текущей форме. Без этого Модуль будет в самом низу без группы и с пустой графой “Категории”   

Функции установки и удаления модуля реализуются через работу с пакетом с именем “ispmanager-plugin-example”. Кнопки Установить и Удалить запускают установку или удаление пакетов соответственно через менеджер пакетов.

Признаком установленного пакета считается наличие файла с именем вида ispmgr_mod_exampleplugin.xml в директории /usr/local/mgr5/etc/xml.

Для работы обработчика необходимо наличие файла с именем вида ispmgr_mod_exampleplugin.xml в директории /usr/local/mgr5/etc/xml, где exampleplugin должно совпадать со значением тэга name

Обработчику в STDIN подается xml от панели. В ответ обработчик должен вернуть корректный xml в STDOUT.

Для отладки своего обработчика можно включить для core_module уровень логирования 9 (Основное меню  Настройки логирования). В логе панели /usr/local/mgr5/var/ispmgr.log будут записываться xml с запросом к обработчику и ответом от него. В случае некорректного xml в ответе, логироваться он не будет.

Создайте файл со следующим содержимым:

<?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
  <plugin name="exampleplugin">
	<dist>1</dist>
	<settings>exampleplugin.settings</settings>
	<free/>
  </plugin>
  <handler name="exampleplugin.py" type="xml">
	<func name="exampleplugin.settings"/>
  </handler>
  <metadata name="exampleplugin.settings" type="form" mgr="ispmgr">
	<form>
  	<field name="example_field" noname="yes" fullwidth="yes">
    	<textdata name="example_msg" type="msg"/>
  	</field>
      <field name="example_input">
   	 <input type="text" name="example_input" required="yes"/>
      </field>
	</form>
	<buttons>
  	<button name="ok" type="ok"/>
  	<button name="cancel" type="cancel"/>
	</buttons>
  </metadata>
  <lang name="ru">
	<messages name="exampleplugin.settings">
      <msg name="title">Пример формы</msg>
      <msg name="example_msg">Пример сообщения</msg>
      <msg name="example_input">Пример поля для ввода</msg>
      <msg name="msg_create">Сохранить</msg>
	</messages>
	<messages name="mgrerror_exampleplugin">
  	<msg name="msg_error_exampleplugin">Возникла ошибка в работе примера формы: __object__</msg>
      <msg name="wrong_value">некорректное введенное значение __value__</msg>
	</messages>
  </lang>
  <lang name="en">
	<messages name="exampleplugin.settings">
      <msg name="title">Form example</msg>
      <msg name="example_msg">Message example</msg>
      <msg name="example_input">Input field example</msg>
      <msg name="msg_create">Save</msg>
	</messages>
	<messages name="mgrerror_exampleplugin">
  	<msg name="msg_error_exampleplugin">Error in form example: __object__</msg>
      <msg name="wrong_value">incorrect input value __value__</msg>
	</messages>
  </lang>
</mgrdata>

Описание тэгов:

  • Значения в подтэгах тэга <plugin> должны совпадать со значениями из файла exampleplugin.xml;
  • Параметр name тэга <handler> содержит имя файла, содержащего обработчик;
  • <metadata> - содержит описание формы;
  • <lang>  - позволяет контролировать, для какого языка будут использоваться сообщения, описанные внутри него.

Сам обработчик должен быть помещен в директорию /usr/local/mgr5/addon. Имя файла должно совпадать со значением параметра name тэга <handler>

Для примера используем следующий обработчик:

#!/usr/bin/env python

from sys import stdin
import os
import xml.etree.ElementTree as etree

#Заполнение формы значениями
def Get(root):
  etree.SubElement(root, 'example_input').text = 'Do not change'
 
#Обработка нажатия на кнопку “Сохранить”
def Set(root):
  val = os.getenv('PARAM_example_input')
  if val == 'Do not change':
	file = open(r'/usr/local/mgr5/var/exampleplugin.output', 'w')
	file.write('Good job!\n')
	file.close()
	etree.SubElement(root, 'ok')
  else:
  #Формирование сообщения об ошибке
	error = etree.SubElement(root, 'error')
	error.set('code', '1')
	error.set('type', 'exampleplugin')
	error.set('object', 'wrong_value')
	param = etree.SubElement(error, 'param')
	param.text = 'wrong_value'
	param.set('name', 'object')
	param.set('type', 'msg')
	param = etree.SubElement(error, 'param')
	param.set('name', 'value')
	param.text = val

if __name__ == "__main__":
#получение значения параметра, переданного панелью из переменных окружения
  func = os.getenv('PARAM_func')
  correct_function = False
#Проверка, что вызывается нужная функция
#Вызов функции по ее имени
  if func == 'exampleplugin.settings':
	correct_function = True
#Вызов и формы "Модули"
  elif func == 'plugin.settings':
	if os.getenv('PARAM_plugin_settings') == 'exampleplugin':
  	correct_function = True
  if correct_function:
#Чтение xml, переданного из панели, из stdin
	root = etree.parse(stdin).getroot()
#Проверка, что нажата кнопка "Сохранить”
	if os.getenv('PARAM_clicked_button') == 'ok':
  	Set(root)
	else:
  	Get(root)
  print etree.tostring(root, encoding='utf8')
  quit(0)

При нажатии на кнопку настроек модуля будет вызываться обработчик и показываться форма с заполненным значением поля. При изменении поля и нажатии на кнопку Сохранить будет сгенерирована ошибка.