Add module to ispmanager
This article describes how to write your own module for ispmanager that will be displayed in the Modules section of the panel.
Xml file with module description
To add your module to ispmanager, you need to add an xml file with a special structure to the /usr/local/mgr5/etc/plugins/ispmgr directory:
Create an exampleplugin.xml file with the following content:
<?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"><a href="http://example.com" target="_blank">Описание ссылки для версий Lite, Pro, Host</a></msg>
<msg name="msg_help_links" dist="3" lang="ru"><a href="https://rudocs.ispmanager.com/ispmanager-business/integratsiya-c-viruslive" target="_blank">Описание ссылки для версии Business</a></msg>
<msg name="msg_help_links" dist="1" lang="en"><a href="http://example.com" target="_blank">Link description for Lite, Pro, Host versions</a></msg>
<msg name="msg_help_links" dist="3" lang="en"><a href="http://example.com" target="_blank">Link description for Business version</a></msg>
</plugin>
</mgrdata>
Tag description:
- name parameter - the module name;
- <dist> - optional, indicates in which version the module will be used: 1 - lite, pro, host, 3 - business. If not available, it will be used in all versions;
- <weight> - optional, you can control the order of the modules in the Modules tab. Modules are ordered from higher weight to lower weight. If there is no weight, the module is placed at the end of the list.
- <pricelist> - optional, tariff id in the billing system (if BILLmanager is used);
- <license> - optional, the name of the license in the billing system (if BILLmanager is used);
- </free> - optional, adds a label to the module to indicate that it is free;
- <settings> - the name of the action to be performed when pressing the module Settings icon;
- <msg> - text messages to be displayed in the Modules tab
The <msg> tags have 2 parameters:
- lang - the language of the panel ("ru" - Russian, "eng" - English) in which the message will be displayed;
- dist - the version of ispmanager in which the message will be displayed, similar to the <dist> tag.
Messages:
- desc_short - short name of the module, used as a header;
- desc_full - detailed module description;
- msg_help_links - optional for adding links to the Show Useful Links menu.
The <weight> tag has been used since release 6.90 (dated 01/16/2024). In earlier versions, use <group>integration</group> or <group>antiviruses</group> instead to add the appropriate collapse to the current form. Without this, the module will be at the bottom with no group and an empty Categories column.
How to install and uninstall your module
The functions of installing and uninstalling a module are realized by working with a package named ispmanager-plugin-example. The Install and Uninstall buttons start the installation and uninstallation of packages via the package manager, respectively.
A file named ispmgr_mod_exampleplugin.xml in /usr/local/mgr5/etc/xml directory is considered to be a sign of the installed package.
How to add handler
For the handler to work, there must be a file named ispmgr_mod_exampleplugin.xml in the /usr/local/mgr5/etc/xml directory, where exampleplugin must match the value of the name tag.
The xml from the panel is passed to the handler in STDIN. In response, the handler must return the correct xml in STDOUT.
To debug your own handler, you can enable logging level 9 for core_module (Main Menu → Logging Settings). The panel log /usr/local/mgr5/var/ispmgr.log will record xml with the request to the handler and its response. If there is a bad xml in the response, it is not logged.
Create a file with the following content:
<?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>
Tag description:
- The values in the <plugin> tag subtags must match the values in exampleplugin.xml;
- The name parameter of the <handler> tag contains the name of the file containing the handler;
- <metadata> - contains a description of the form;
- <lang> - allows to control which language the described messages are used for.
The handler itself should be placed in the /usr/local/mgr5/addon directory. The filename must match the value of the name parameter of the <handler> tag.
You can use the following handler as an example:
#!/usr/bin/env python
from sys import stdin
import os
import xml.etree.ElementTree as etree
#Filling the form with values
def Get(root):
etree.SubElement(root, 'example_input').text = 'Do not change'
#Processing of clicking the "Save" button
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:
#Generating an error message
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__":
#Get parameter value passed by the panel from environment variables
func = os.getenv('PARAM_func')
correct_function = False
#Checking that the correct function is called
#Call a function by its name
if func == 'exampleplugin.settings':
correct_function = True
#Call and "Modules" forms
elif func == 'plugin.settings':
if os.getenv('PARAM_plugin_settings') == 'exampleplugin':
correct_function = True
if correct_function:
#Reading xml passed from panel from stdin
root = etree.parse(stdin).getroot()
#Checking that the "Save" button has been pressed
if os.getenv('PARAM_clicked_button') == 'ok':
Set(root)
else:
Get(root)
print etree.tostring(root, encoding='utf8')
quit(0)
When you click the Module Settings button, the handler is called and the form is displayed with the filled field value. If the field is changed and the Save button is pressed, an error is generated.
See the documentation for more information about handlers.