COREmanager Documentation

How to add a custom module

 

This article walks you through the steps you need to perform to edit a list of elements.

Task

  • ISPmanager control panel
  • The /etc/myconf file contains a list of elements. If you want to edit the element, you need to create the interface.

Implementation

1) Create the /usr/local/mgr5/etc/xml/ispmgr_mod_myconf.xml file with the following contents describing your plug-in

 <?xml version="1.0" encoding="UTF-8"?>
 <mgrdata>
      <handler name="myconf" type="cgi">
       <func name="myconf"/>
       <func name="myconf.edit"/>
       <func name="myconf.delete"/>
    </handler>

<mainmenu level="30">
      <node name="tool">
        <node name="myconf"/>
      </node>
    </mainmenu>

<metadata name="myconf" type="list" key="item">
      <toolbar>
        <toolbtn func="myconf.edit" type="new"  img="t-new" name="new"/>
        <toolbtn func="myconf.edit" type="edit" img="t-edit" name="edit" default="yes"/>
        <toolbtn func="myconf.delete" type="group" img="t-delete" 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>

<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">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 the elemen</msg>
        <msg name="hint_new">New element</msg>
        <msg name="hint_edit">Edit the element</msg>
        <msg name="hint_delete">Delete the element</msg>
      </messages>
      <messages name="myconf.edit">
        <msg name="title">Edit the element</msg>
        <msg name="title_new">New element</msg>
        <msg name="item">Valaue</msg>
        <msg name="hint_item">Element value from myconf</msg>
      </messages>
    </lang>
 </mgrdata>

2) Create the /usr/local/mgr5/addon/myconf.pl handler

 #!/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 {
 	$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 {
        @all_elem = split(", ", $Q->param( "elid" ));
 	if( open( IN, "/etc/myconf" ) ){
 		if( open( OUT, ">/etc/myconf.new" ) ){
 			for( <IN> ){
 				chomp;
                                $found = "0";
                                for my $elid (@all_elem) {
                                   if ($elem eq $_) {
                                     $found = "1";
                                     last;
                                   }
                                }
 				print OUT "$_\n" if( $found ne "1" );
 			}
 			close( OUT );
 		}
 		close( IN );
 	}
 
 	rename( "/etc/myconf.new", "/etc/myconf" );
 	print "<ok/>";
 }

3) Set permissions for the file

chmod 750 /usr/local/mgr5/addon/myconf.pl
chown 0:0 /usr/local/mgr5/addon/myconf.pl

4) Restart ISPmanager

/usr/local/mgr5/sbin/mgrctl -m ispmgr exit

Notes

Describe the handler script and specify that it will be called when calling your custom functions. Use the same description as for events, using the func tag instead of event

   <handler name="myconf.pl" type="cgi">
      <func>myconf</func>
      <func>myconf.edit</func>
      <func>myconf.delete</func>
   </handler>

Describe the menu link

   <mainmenu level="30">
     <node name="tool">
       <node name="myconf"/>
     </node>
   </mainmenu>

Describe the data table:

   <metadata name="myconf" type="list" key="item">
     <toolbar>
       <toolbtn func="myconf.edit" type="new"  img="t-new" name="new"/>
       <toolbtn func="myconf.edit" type="edit" img="t-edit" name="edit" default="yes"/>
       <toolbtn func="myconf.delete" type="group" img="t-delete" name="delete"/>
     </toolbar>
     <coldata>
       <col sort="alpha" sorted="yes" name="item" type="data"/>
     </coldata>
   </metadata>

In the example above, the table contains one column, and the toolbar contains 3 buttons - Add, Edit, and Delete. For more information about tags and attributes, refer to the article Description of lists.

Describe the edit form:

   <metadata name="myconf.edit" type="form">
     <form>
       <field name="item">
         <input type="text" name="item"/>
       </field>
     </form>
   </metadata>

In the example above, the form contains one input field. For more information about tags and attributes, refer to the article Description of forms.

Describe messages for new interfaces. For more information, please refer to the article https://ispsystem.atlassian.net/wiki/spaces/COREmgrEN/pages/9601388.

Let's consider a handler script

Get the data and define the name of the function to call

 use CGI qw/:standard/;

$Q = new CGI;
 $func = $Q->param(func);

Depending on the function, you should call the corresponding procedure

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;
	}
}

Data list output

sub List {
	if( open( IN, "/etc/myconf" ) ){
		while( <IN> ){
			chomp;
			print "<elem><item>$_</item></elem>";
		}
		close( IN );
	}
}

Read the data file "/etc/myconf" and form an XML-document. The elem tag contains child elements describing data by columns, you can use any name for the item tag making sure it corresponds to the name attribute in the table column description (the col tag)

Read data when opening the element edit form

sub Get {
	$elid = $Q->param( "elid" );
	print "<elid>$elid</elid><item>$elid</item>" if( $elid );
}


This function will be called when opening the edit form to create edit the element. If the elid parameter is not empty, we edit the element. This parameter contains a value from the column of the list, which name is specified in the key attribute of the metadata tag in the data table interface description.

As our interface is rather simple, and the form contains only one field, we don't read anything from the files, and will only return a parameter of the required element. We recommend that you make sure that the data file contains the element. If not, the error message will be displayed. The elid tag specifies the key value for the element, that value will be displayed in the form heading. The item tag contains the value that will be displayed in the item input field.

Edit the record

sub Set {
	$elid = $Q->param( "elid" );
	$item = $Q->param( "item" );
       .......
} 

Pay attention to two parameters. elid - contains the name (key field) of the element you want to edit, the item parameter contains the value that a user entered into the item field. We should read our data file, find the element from the elid parameter, and change its value into the value from the item parameter. If the required element is not found, the error message will be displayed.

Create a new element

sub New {
	$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>";
	}
}

Get a value from the item parameter, and add it into the end of our data file. If you failed to open the file, the error message will be displayed.

Delete the element from the list

sub Delete {
	@all_elem = split(", ", $Q->param( "elid" ));
       ......
}

The Delete operation enables to delete multiple elements at once, thus the elid parameter may contain several names separated by ", " (comma, space). Form an array of the elements you want to delete, read our data file, and delete the lines that are specified in the array of the elements you want to delete.

 

In this article