Console Extensions Development
Introduction
Extensions are a way to develop new features for Pandora FMS Web Console as plugins.
Types of Extensions
An extension can be one (or more) of the following types:
- Agent tab: Extensions that appear in the tab header of the agent's operation and/or editing view.
- Visibles: Extensions that appear in Pandora FMS menu.
- Invisibles: Extensions that are loaded and executed in the
index.php
of Pandora FMS menu, but that do not appear in PFMS menu.
Extensions Directory
The extensions directory is a subdirectory inside the local installation of Pandora FMS Web Console that has the name extensions
. This directory contains the following for each extension:
Extension main file
This file has the code to be loaded in Pandora FMS Web Console.
Extension subdirectory
It is optional and may contain the icon image file (18 by 18 pixels) shown next to the extension name in the menu, as well as other files such as translations, modules and images.
Structure of the extension
<?php <Comments with license, author/s, etc...> <php auxiliary code as functions, variables, classes that your extension use> function <name of main function> () { <Main function Code> } /*-------------------------------------*/ /* Adds the link in the operation menu */ extensions_add_operation_menu_option ('<Name Extension>', '<father ID menu>', '<relative path Icon>'); /* Adds the link in the godmode menu */ extensions_add_godmode_menu_option ('<Name Extension>', '<ACL level>', '<father ID menu>', '<relative path Icon>') /*-------------------------------------*/ /* Sets the callback function to be called when the extension is selected in the operation menu */ extensions_add_main_function ('<name of main function>'); /* Sets the callback function to be called when the extension is selected in the godmode menu */ extensions_add_godmode_function('<name of godmode function>'); ?>
API for Extensions
The API for extensions is still under development and may change in the future.
extensions_add_operation_menu_option
extensions_add_operation_menu_option ('<string name>', '<father ID menu>', '<relative path Icon>')
This function adds the link to the extension with the name given in the Operations menu. The third parameter is optional and this is the optional field for the icon image (18 by 18 pixels) to appear next to the link.
If this last parameter is not defined, the icon of a plug will be used ().
extensions_add_godmode_menu_option
extensions_add_godmode_menu_option ('<Name Extension>', '<ACL level>' , '<father ID menu>', '<relative path Icon>')
This function adds the link to the extension with the name given in the Godmode menu if the user has the required ACL level as indicated by the second parameter. The fourth parameter is optional and is the relative field for the icon image (18 by 18 pixels) to appear next to the link.
If this last parameter is not defined, the icon of a plug will be used ( ).
extensions_add_main_function
extensions_add_main_function ('<name of main function>')
It sets the callback function to return when the user clicks on the extension link in the operation menu.
extensions_add_godmode_function
extensions_add_godmode_function ('<name of godmode function>')
It adds the extension function to call once the user goes to the extension in the godmode of Pandora FMS Web Console instead of loading the main function.
extensions_add_login_function
extensions_add_login_function ('<name of login function>')
It adds the extension function to call once the user successfully logs into Pandora FMS Web Console.
extensions_add_godmode_tab_agent
extensions_add_godmode_tab_agent('<ID of extension tab>', '<Name of extension tab>', '<Image file with relative dir>', '<Name of function to show content of godmode tab agent>')
It adds one more tab to the agent edit view so that when it is selected, the code of the function of the name added to it is executed.
extensions_add_opemode_tab_agent
extensions_add_opemode_tab_agent('<ID of extension tab>', '<Name of extension tab>', '<Image file with relative dir>', '<Name of function to show content of operation tab agent>')
It adds one more tabs to the agent operation view that causes the function code of the name that is added to it to be run when selected.
extensions_add_translation_string_function
extensions_add_translation_string_function('<Name of translation function>')
Adds the callback function to be called from the standard extension translation function.
Menu Father IDs
List of IP strings available for use in extension API. If you use a null value or do not include a parameter in the call
function, then the extension appears only in the extension submenu.
Operation
estado
: Monitoring view.network
: Network view.reporting
: Reporting and data display.gismaps
: GIS view.eventos
: Event view.workspace
: User workspace.
Administration
gagente
: Monitoring management.gmassive
: Massive operations.gmodules
: Module management.galertas
: Alert management.gusuarios
: User management.godgismaps
: GIS management.gserver
: Server management.glog
: System logs.gsetup
: Configuration.gdbman
: Database maintenance.gpolicies
: Policy management
Example
The extension displays a table where columns are groups of modules and rows are groups of agents. Each cell has a color with the following meanings:
- Green: When all the modules in the group are
OK
. - Yellow: When there is at least one monitor on alert.
- Red: When at least one monitor fails.
This extension stays in the Operation menu under Agents.
Source code
<?php /** * Pandora FMS - http://pandorafms.com * ================================================== * Copyright (c) 2005-2024 PFMS * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation for version 2. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ /** * Extension specific translation function */ function extensions_translation() { $translates = array( 'es' => array( "sentence" => "translated sentence" ), /* ... for other language's definitions. */ ); $args = func_get_args(); $string = array_shift($args); $user_language = get_user_language (); if(isset($translates[$user_language][$string])){ return vsprintf($translates[$user_language][$string], $args); } else{ return false; } } /** * Translate the array texts using gettext */ function translate(&$item, $key) { $item = ___($item); } /** * The main function of module groups and the enter point to * execute the code. */ function mainModuleGroups() { global $config; //the useful global var of Pandora Console, it has many data can you use //The big query $sql = "select COUNT(id_agente) AS count, estado FROM tagente_estado WHERE utimestamp != 0 AND id_agente IN (SELECT id_agente FROM tagente WHERE id_grupo = %d AND disabled IS FALSE) AND id_agente_modulo IN (SELECT id_agente_modulo FROM tagente_modulo WHERE id_module_group = %d AND disabled IS FALSE AND delete_pending IS FALSE) GROUP BY estado"; echo "<h1>" . ___("Combine table of agent group and module group") . "</h1>"; echo "<p>" . ___("This table show in columns the modules group and for rows agents group. The cell show all modules") . "</p>"; $agentGroups = get_user_groups ($config['id_user']); $modelGroups = get_all_model_groups(); array_walk($modelGroups, 'translate'); //Translate all head titles to language is set $head = $modelGroups; array_unshift($head, ' '); //Metaobject use in print_table $table = null; $table->align[0] = 'right'; //Align to right the first column. $table->style[0] = 'color: #ffffff; background-color: #778866; font-weight: bolder;'; $table->head = $head; //The content of table $tableData = array(); //Create rows and celds foreach ($agentGroups as $idAgentGroup => $name) { $row = array(); array_push($row, $name); foreach ($modelGroups as $idModelGroup => $modelGroup) { $query = sprintf($sql,$idAgentGroup, $idModelGroup); $rowsDB = get_db_all_rows_sql ($query); $states = array(); if ($rowsDB !== false) { foreach ($rowsDB as $rowDB) { $states[$rowDB['estado']] = $rowDB['count']; } } $count = 0; foreach ($states as $idState => $state) { $count = $state; } $color = 'transparent'; //Defaut color for cell if ($count == 0) { $color = '#babdb6'; //Grey when the cell for this model group and agent group hasn't modules. $alinkStart = ''; $alinkEnd = ''; } else { $alinkStart = '<a href="index.php?sec=estado&sec2=operation/agentes/status_monitor&status=-1&ag_group=' . $idAgentGroup . '&modulegroup=' . $idModelGroup . '">'; $alinkEnd = '</a>'; if (array_key_exists(0,$states) && (count($states) == 1)) $color = '#8ae234'; //Green when the cell for this model group and agent has OK state all modules. else { if (array_key_exists(1,$states)) $color = '#cc0000'; //Red when the cell for this model group and agent has at least one module in critical state and the rest in any state. else $color = '#fce94f'; //Yellow when the cell for this model group and agent has at least one in warning state and the rest in green state. } } array_push($row, '<div style="background: ' . $color . ' ; height: 15px; margin-left: auto; margin-right: auto; text-align: center; padding-top: 5px;"> ' . $alinkStart . $count . ' modules' . $alinkEnd . '</div>'); } array_push($tableData,$row); } $table->data = $tableData; print_table($table); echo "<p>" . ___("The colours meaning:") . "<ul>" . '<li style="clear: both;"> <div style="float: left; background: #babdb6; height: 20px; width: 80px;margin-right: 5px; margin-bottom: 5px;"> </div>' . ___("Grey when the cell for this model group and agent group hasn't modules.") . "</li>" . '<li style="clear: both;"> <div style="float: left; background: #8ae234; height: 20px; width: 80px;margin-right: 5px; margin-bottom: 5px;"> </div>' . ___("Green when the cell for this model group and agent has OK state all modules.") . "</li>" . '<li style="clear: both;"><div style="float: left; background: #cc0000; height: 20px; width: 80px;margin-right: 5px; margin-bottom: 5px;"> </div>' . ___("Red when the cell for this model group and agent has at least one module in critical state and the rest in any state.") . "</li>" . '<li style="clear: both;"><div style="float: left; background: #fce94f; height: 20px; width: 80px;margin-right: 5px; margin-bottom: 5px;"> </div>' . ___("Yellow when the cell for this model group and agent has at least one in warning state and the rest in green state.") . "</li>" . "</ul>" . "</p>"; } extensions_add_operation_menu_option("Modules groups", 'estado', 'module_groups/icon_menu.png'); extensions_add_main_function('mainModuleGroups'); extensions_add_translation_string_function('extensions_translation'); ?>
Explanation
There are two parts in the source code:
- The source code of the extension.
- The API call functions.
The order of the parts does not matter, it is better to place the “call API functions” under its main extension file because the style guides warn that this part should be placed underneath so that all extensions have approximately the same style.
Extension source code
In the case of this example there are two functions in the same file, if you had a more complex code then it would be better to split it into many files (and save it in subdirectory extension). The functions are:
- Function
extensions_translation()
Specific function for the translation extension. It is called from the main translations function. - Function
translate(&$item, $key)
The use of this function for callback in array_walk function, because the main function keeps the column titles and row titles selected without translations. - Function
mainModuleGroups()
It is the core of the extension and has a huge number of lines. Some important parts:
- The first one is the access to the
global var config
. Thisvar
has many configurations and default values for many elements of Pandora FMS Web Console. - The second
var
is the MySQL query in a string. The%d
is the format placeholder for Id Group and Id Module Group. These are the substitutes for the value in sprintf function. - Some
echo
command to print the text in front of the table. - Extract two selections from the DB with one dimension with the index as
id
and the content as the column title (Module groups) and rows (Agent group). - Translate the titles of the selection of the Module Group.
- Make the meta-object stable and fills it with rows and prints.
- In front of the
foreach ~ loops
, define as$table
the header and styles of the table. - The first loop is for the rows (each group of agents).
- The second cycle is for normal row columns (each group of modules).
- Then, for each cell, there are two numbers, id module group and id agent group. With these two numbers it queries the database and obtains the files.
- It processes the resulting selection to obtain another selection and the index is an integration of different types of monitor state and the content is a computation of the monitor in that state.
- The last thing to do is to fill the contents of the cell in HTML: If the count of all states is zero, the background color for
div
in CSS is gray. If$states[1] != 0
or there is at least one monitor in critical condition, then thediv
will have a red color. If the selection has only one cell and is in normal mode, then the green color will be in thisdiv
. For all other cases, yellow will be the color fordiv
. - Add a link in the cell if the count is greater than
0
. - Save the series in
$table
, and start another iteration offoreach
. - Print the table.
- Print the legend and other notes at the bottom of the page.
API call functions
- Insertion of the extension in Pandora FMS menu:
extensions_add_operation_menu_option("Modules groups", 'estado', 'module_groups/icon_menu.png');
Modules groups
is the name that appears in the agents submenu.estado
is the element hanging from the extension.module_groups/icon_menu.png
is the icon of the image that appears in the submenu, the field is related to the extension directory you have.- It defines the main function of this extension. It appears as
extensions_add_main_function('mainModuleGroups');
wheremainModuleGroups
is the name of the main function of the extension.
The order in which the functions are named is irrelevant.
Organization of the Board of Directors
The extension has this directory structure:
+module_groups | +--icon_menu.png | +module_groups.php
The directory extension is in /var/www/pandora_console
.
You should only copy all the extension files to the extension directory in installation of Pandora FMS Console. You should install the permissions so the Pandora FMS Console can read the files and the extension subdirectories. Pandora FMS console looks for new extensions and adds them to the system when it finds them.
Subdirectory
The example has only one subdirectory (and generally any extension should have a subdirectory). The subdirectory has the same name as the extension name and the main file. The subdirectory of the example has only one icon image file (icon_menu.png
). This icon will appear in Pandora FMS menu.