Plug-ins (DNSmanager)

From ISPWiki

Jump to: navigation, search

Contents

Introduction

Plug-ins are used to add modules to the control panel. This article walks you through the steps involved in creating the module that will work with a list of random lines in the /etc/myconfig file. Using this example you can create your own control panel plug-ins.

Follow the instructions below to add your plug-ins.

First step

Add an XML-document that will describe all the functions that are processed by this plug-in, and all the interface elements required for the module to be displayed in the control panel.

Second step

Write a program or a script that implements the function.

Create XML-document

Locate the XML document that describes the required extension interface into the /usr/local/ispmgr/etc folder and name it BINNAME_mod_xxx.xml, where BINNAME is a name of the control panel's file that is to be run (ispmgr, billmgr, vdsmgr, etc), and xxx is a random value. For example, myconfig (vdsmgr_mod_myconfig.xml). The document should have UTF-8 encoding something like the followings:

<?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
  description of plug-in's function 
  description of the menu elements 
  description of tables and forms 
  description of messages 
</mgrdata>

Describing plug-in's function

This part of the XML-document defines a program or script's name that will implement the functions, type of interaction between the program and the control panel, as well as the functions provided in this plug-in. For example:

<handler name="program" type="type">
  <func>function1</func>
  <func>function2</func>
  ...
</handler>

Provide a program name as the name attribute, such as myconfig.pl. Provide a method of integration of your control panel and program as the type attribute. Two type are currently available:

cgi
The program has the CGI interface, i.e. receives data from the environment variables or/and STDIN.
xml
The program receives an XML-document from the standard input that describes data transferred by the control panel.

Then you need to specify the functions that you wish to provide in the plug-in. The functions are as follows:

List of elements
the table with a toolbar.
Element parameters
form that is used to add a new element or edit an existing one. It can be used if your module cannot work with multiple elements, but is supposed to set up certain parameters.


Action function type does not provide private elements of the interface. It is used to perform a certain action over one or several elements.

The function name must contain alpha-numeric characters, digits and dots. It must be unique. You can get a list of available functions by the command:

/usr/local/ispmgr/sbin/mgrctl -m BINNAME eventlist

Where BINNAME is a name of the control panel file, such as ispmgr, billmgr, vdsmgr, etc.

Describing Menu elements

To access your plug-in, you should create an element for the control panel navigation. Add the following block into your XML-document.

<mainmenu level="access level">
  <node name="category name">
    <node name="function1"/>
    <node name="function2"/>
  </node>
</mainmenu>

In the level attribute specify a figure corresponding to the access level. If you want the module to be available in several levels, add the mainmenu block for each of them.

For a category name provide a name from the name attribute of the node corresponding to the category of the navigation menu described in /usr/local/ispmgr/etc/BINNAME_menu.xml. For example, you want to grant access to a plug-in to all VPS owners and locate a corresponding module in the "Tools" section. To do that, locate a mainmenu level="5" section and a corresponding section node name="tool". A tool value is to be provided as a category name.

Then, you add one or several menu elements into the corresponding section of the navigation menu. Add nodes. For the name attribute provide a function name that should be called when clicking the corresponding icon.

Tables and forms

Describe the interface for functions provided by this plug-in. Our test module should allow us to view existing records in the /etc/myconfig file, add new records and edit existing ones. It should provide a removal function, but this function refers to the action and does not require the interface.

To enable the list of records, add the following block into the XML-document:

<metadata name="function1" type="list" key="filed_name">
  <toolbar>
    <toolbtn func="function2" type="new"  img="t-new.gif" name="new"/>
    <toolbtn func="function2" type="edit" img="t-edit.gif" name="edit" default="yes"/>
    <toolbtn func="function3" type="group" img="t-delete.gif" name="delete"/>
  </toolbar>
  <coldata>
    <col sort="alpha" sorted="yes" name="field_name" type="data"/>
  </coldata>
</metadata>

It describes that we want to add the type (type="list") interface to our "function1" function list, with the key element "field_name". The unique key element is required to identify a record in the list. This function will be transferred to such as, view element parameters, delete, etc.

Then you describe the toolbar that contains three icons: new (name="new"), edit (name="edit") and delete (name="delete") element. You can provide the action that will be executed when double-clicking a record by adding the default="yes" attribute into a required node that describes the control panel's element. Double-clicking the record will call a function to edit the record's parameter. The same function name is specified as the func attribute in two first control panel icons, because one function will implement creation, view and edit of record's parameters. The function type is determined by a type attribute:

new
add a new element.
edit
edit an existing element.
group
an operation against a group of elements.
editlist
child list associated with one of the current list elements.
list
child list which is not associated with any element of the current list.

There is a coldata block . You add a required number of col nodes, one for each table column. In our case, the table consists of one column where a "field_name" field will be displayed. You should specify the type of the column values. The following types are currently supported:

data
the column of this type is used to display information about each element sent to the field which name is specified in the name attribute ("field_name").
msg
this type can be used if you have a finite set of values that are returned into a filed which name is specified in the name attribute, such as the record's status (enabled, disabled, etc.), and you want these values to be displayed differently depending on a language of the control panel. In this case, the values must consist of the Latin letters, digits, dots and "_" symbols.
indicator
this column displays indicators of usage of a certain resource, such as traffic or disk space. For this type you should add an XML-node with the name of this column's list and add two attributes into this node: used="number" and limit="number".

If you want to sort the data in the column, add a sorted="yes" attribute that will provide one of the following values:

alpha
lines that contain the Latin alphabet letter and digits.
digit
digits.
indicator
indicators (such as, traffic or disk space).
ip
IP-addresses.
prop
set of parameters (such as, enabled\disabled).

If you wish the elements of the table to be sorted automatically by one of the columns when entering the module, add the a sorted="yes" attribute.

If you wish the data of one or several columns to be used for statistic information, add a stat="yes" attribute.

Then you add description of the interface of the create and edit forms. To do that, add the following block into the XML-document:


<metadata name="function2" type="form">
  <form>
    <field name="message">
      <input type="text" name="filed_name"/>
    </field>
  </form>
</metadata>

This block provides that we want to add a form (type="form") for "function2". Each control element must have a separate field block which consists of a filed heading and control element. The field heading is provided with the name="message" attribute. You must add a corresponding node into the message block for this function. The procedures on how to create messages blocks will be described below. Then you add a control element. The following types are available::

input
input field. There are several types of input fields which are specified in the type attribute:
text
line input field.
password
password field; when entering a password, all characters are replaced with asterisks.
checkbox
check box type.
textarea
multiline input field.
select
drop-down list.

Using a name attribute you must provide a name of the function parameter which is associated with the selected control element. If you wish to specify a default value for this control element, use a value attribute (value="default_value").

Additional attributes for fields are also available. If you wish the field to be hidden by default, and manage its with javascript, add a hidden="yes" attribute . If you use <input type="text"/> as an element, and several elements should be entered, you can add the zoom="5" attribute. This attribute provides an additional icon next to the text field. Clicking the icon will enlarge the field by the number of lines specified in the attribute value.

Messages

The ISPmanager message is a text that you can view in the control panel. It is not associated with data received after execution of the functions. The messages are divided into groups by interface languages. You must add the following block for each interface language:

<lang name="language">
  navigation menu messages
  function messages 
</lang>

Use one of the following values to specify a language:

de
German
en
English
es
Spanish
fr
French
ru
Russian


Default interface language is English. If another language is used for the control panel interface and the required message in that language can not be found, the appropriate English message will be used.

Further you should add the messages for all menu items that you created in the Elements description menu. To do so, add the following block:

<messages name="desktop">
  <msg name="menu_function1">message1</msg>
  <msg name="menu_function2">message2</msg>
</messages>


That is for each menu item we have to add the message message1. Replace the "message1" with real name of the menu item in UTF-8 encoding.

All other messages are divided by functions, that's why each function provided by your control panel plug-in, should add the following block into the XML-document:


<messages name="function1">
  <msg name="message_name">message</msg>
  ...
</messages>

There are the following standard messages for modules (the following names should be used instead of "message_name"):

title
module heading (list or form).
title_new
heading for a creation from.
hint_default
hint for the module function.

All other messages are divided into the following types:

list columns' names
provide the values from the name attribute of the col node
values for msg type column
provide the value which can be send in the corresponding element parameter returned by the function. If there are several values, you add a separate message for each of them.
form fields names
provide the value from the name attribute of the field node.
values of a select control elements
provide the value which will be send in this list. If the corresponding message is not found, the value returned by the function will be displayed. If there are several values, you add a separate message for each of them.
form field hints
provide the value from the name attribute of the field node with hint_, such as, hint_username.
toolbar icon hints
provide the value from name attribute of the toolbtn node with hint_ prefix, such as, hint_new.
javascript messages
all messages used in javascript scenarios. Standard messages of this type are various confirmation messages, for example those used when removing element. In this case you should use msg_function1_delete, where function1 is the name of the function from the plug-in.

All message should be encoded in the UTF-8 character set. Otherwise, the XML-document won't load and ISPmanager won't start.


Example of the ispmgr_mod_myconf.xml xml-document:

<?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">Item value from myconf</msg>
     </messages>
   </lang>
   <lang name="ru">
     <messages name="desktop">
       <msg name="menu_myconf">Test module</msg>
     </messages>
     <messages name="myconf">
       <msg name="title">Test module</msg>
       <msg name="item">Element from myconf</msg>
       <msg name="msg_myconf_delete">Delete element </msg>
       <msg name="hint_new">New element</msg>
       <msg name="hint_edit">Edit element</msg>
       <msg name="hint_delete">Delete element</msg>
     </messages>
     <messages name="myconf.edit">
       <msg name="title">Edit element</msg>
       <msg name="title_new">New element</msg>
       <msg name="item">Value</msg>
       <msg name="hint_item">Element value from myconf</msg>
     </messages>
   </lang>
 </mgrdata>

Writing a program

Once you have created the XML-document with interface description, you write a program or script that will process the data for the plug-in. This program should be located in /usr/local/ispmgr/addon, belong to root and have permissions 700. Its should match the value specified in the name attribute of the XML-document handler node.


Execution of the program should be a XML document in result output format.

To locate a user who has called the function to start your program, use the REMOTE_USER environment variable. Make sure that this user has been authorized.

Below is the example of the myconf.pl CGI-program written in 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/>";
}

If you use the program in the xml mode, as was mentioned above, it receives the XML from the standard input which can contain blocks of lists and description of the interface forms that you have described in your XML-document. You can edit these data with your program in order to change the set, list columns, form fields or icons of the toolbar. Your program can add the required XML-nodes with the data in the function output results format and return it to the standard output.

Was this helpful? Yes | No
Personal tools