コンソール拡張の開発

コンソールの拡張

拡張は、プラグインとして新たな機能を Pandora コンソールに開発するためのものです。

この章では、拡張の開発の仕方を説明します。

「拡張」の種類

拡張には次の種類があります。

  • エージェントタブ拡張は、エージェント表示または編集画面のヘッダーのタブに表示されます。
  • 表示される拡張は、Pandora のメニューに表示されます。
  • 非表示の拡張は、Pandora メニューである index.php からロードされ実行されますが、Pandora メニューには表示されません。

「拡張」のディレクトリ

拡張のディレクトリは、Pandora FMS コンソールをインストールしたディレクトリ内の “extensions” というサブディレクトリです。

このディレクトリは、次のようは拡張が含まれています。

拡張のメインファイル

Pandora FMS コンソールにロードされるコードです。

拡張のサブディレクトリ

これはオプションで、メニュー内の拡張名の隣に表示されるアイコンの画像ファイル (18×18 のサイズ) および、その他、翻訳、モジュール、画像ファイルなどが含まれます。

「拡張」のテンプレート

<?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 */
add_operation_menu_option ('< Name Extension >', '< father ID menu >', '< relative path Icon >');
 
/* Adds the link in the godmode menu */
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 */
add_extension_main_function ('< name of main function >');
 
/* Sets the callback function to be called when the extension is selected in the godmode menu */
add_extension_godmode_function ('< name of godmode function >');
?>

「拡張」の API

拡張の API はまだ開発途上で、将来変更するかもしれません。

以下の章では、拡張に関する API の関数の説明をします。

extensions_add_operation_menu_option

extensions_add_operation_menu_option ('<名前文字列>', '<メニュー親ID>', '<アイコン相対パス>')

この関数は、拡張へのリンクを指定した名称で 操作(Operations) メニューに追加します。3番目のパラメータはオプションで、アイコン画像 (18×18 ピクセル) への相対パスを指定します。パラメータを設定しない場合は、コンセントのアイコン () が利用されます。

extensions_add_godmode_menu_option

extensions_add_godmode_menu_option ('<拡張名>', '<ACL レベル>' , '<メニュー親ID>', '<アイコン相対パス>')

この関数は、ユーザが 2番目のパラメータで指定された ACL レベルを満たす場合に、拡張へのリンクを指定した名称で システム管理(Godmode) メニューに追加します。4番目のパラメータはオプションで、アイコン画像 (18×18 ピクセル) への相対パスを指定します。パラメータを設定しない場合は、コンセントのアイコン () が利用されます。

extensions_add_main_function

extensions_add_main_function ('<メイン関数名>')

操作(operation)メニューで拡張のリンクをクリックしたときに呼び出される関数を設定します。

extensions_add_godmode_function

extensions_add_godmode_function ('<システム管理メニュー関数名>')

Pandora FMS コンソールのシステム管理メニューの拡張のリンクをクリックしたときに呼び出される関数を設定します。

extensions_add_login_function

extensions_add_login_function ('<ログイン関数名>')

Pandora FMS コンソールへユーザが正しくログインしたときに呼び出される関数を設定します。

extensions_add_godmode_tab_agent

extensions_add_godmode_tab_agent('<拡張タブID>', '<拡張タブ名>', '<画像ファイルの相対パス>', '<エージェント管理のタブから実行される関数名>')

エージェント編集画面に 1つ以上のタブを追加します。それが選択された場合は、指定した名前の関数が呼び出されます。

extensions_add_opemode_tab_agent

extensions_add_opemode_tab_agent('<拡張タブID>', '<拡張タブ名>', '<画像ファイルの相対パス>', '<エージェント参照のタブから実行される関数名>')

エージェント参照画面に 1つ以上のタブを追加します。それが選択された場合は、指定した名前の関数が呼び出されます。

extensions_add_translation_string_function

extensions_add_translation_string_function('<翻訳関数名>')

拡張共通の翻訳関数 ___() から呼び出される関数を設定します。

メニューの親 ID

拡張 API で利用できる ID 文字列を示します。呼び出し関数で指定しなかったり、以下に無いものを指定した場合は、拡張のサブメニューにのみ表示されます。

操作
  • estado: エージェント参照(View agents)
  • network: ネットワーク表示(Network view)
  • reporting: レポート(Reporting)
  • gismaps: GIS 表示(GIS view)
  • eventos: イベント参照(View events)
  • workspace: ユーザのワークスペース(User's workspace)
システム管理
  • gagente: エージェント管理(Manage agents)
  • gmassive: 一括操作(Massive operations)
  • gmodules: モジュール管理(Manage modules)
  • galertas: アラート管理(Manage alerts)
  • gusuarios: ユーザ管理(Manage users)\
  • godgismaps: GIS管理(Manage GIS)
  • gservers: サーバ管理(Manage servers)
  • glog: システム監査ログ(System audit log)
  • gsetup: 設定(Setup)
  • gdbman: DBメンテナンス(DB maintenance)
  • gpolicies: ポリシー管理

列がモジュールのグループ、行がエージェントグループの表を表示する拡張です。また、それぞれのセルは、次のような意味の色が表示されます。

  • : すべてのモジュールが正常
  • 黄色: 少なくとも一つのモニタ項目が警告状態
  • : 少なくとも一つのモニタ項目が障害状態

そして、この拡張は、操作メニューのエージェント参照から呼び出されます。

ソースコード

<?php
/**
 * Pandora FMS- http://pandorafms.com
 * ==================================================
 * Copyright (c) 2005-2009 Artica Soluciones Tecnologicas
 *
 * 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');
?>

説明

ソースコードは、2つのパーツにわかれています。

  • 拡張のソースコード
  • API を呼び出す関数

パーツの順番は関係ありませんが、APIを呼び出す関数は拡張ファイルの下の方が良いです。なぜなら、スタイルのガイドラインでは、この部分を下に書くようにアドバイスしているためです。それにより、すべての拡張は同じようなスタイルになります。

拡張のソースコード

この例の場合、同じファイルに 3つの関数があります。しかし、共通のコードがあるのであれば、複数ファイルに分割する方が良いです(そして、拡張のサブディレクトリに保存します)。関数は次の通りです。

  • extensions_translation() 関数
    拡張独自の翻訳に使用されます。共通の翻訳関数から呼び出されます。
  • translate(&$item, $key) 関数
    この関数は、array_walk 関数内のコールバックに使われます。なぜなら、メイン関数は、配列の行と列のタイトルを変換せずに維持するためです。
  • mainModuleGroups() 関数
    これは、拡張のコードで何行もあります。重要な部分のみ示します。
    • 最初は、設定のグローバル変数へのアクセスです。この変数に、Pandora コンソールに関する多くの設定やデフォルト値が含まれます。
    • 2つ目の変数は、MySQLのクエリを文字列で設定しています。ここで、%d は、グループID および モジュールグループID を示す、書式化文字列です。これらの変数は、foreach ループの中の sprintf 関数 で使われます。
    • 次に表示するためのいくつかの echo があります。
    • DB のデータを 1次元の 2つの配列に展開し、id がインデックスで、内容は列(モジュールグループと行(エージェントグループ)にタイトルです。
    • モジュールグループ配列のタイトルを変換します。
    • メタオブジェクトの $table を作成し、行を埋めて表示します。
      • foreach ループの前に、$table に、テーブルのヘッダとスタイルを定義します。
      • 最初のループは行のデータ用です。(それぞれのエージェントグループ)
        • 2つ目のループは、現在の行に対する列のデータ用です。(それぞれのモジュールグループ)
          • そして、それぞれのセルに、モジュールグループとエージェントグループの ID の 2つの数字が当てはまり、この 2つの数字を使ってデータベースクエリを実施し、データを取得します。
          • 異なる種類のモニタ状態および、状態の数の合計の結果の配列を生成します。
          • そして残りは、セルを html に整形する処理です。仕組みは簡単です。すべての状態の合計がゼロであれば、CSS の div で背景をグレーにします。もし、$states[1] != 0 もしくは、何らかの文字で、少なくとも一つのモニタ状態が障害であれば、div を赤にします。配列が一つのセルで正常状態であれば、div を緑にします。そして、その他の場合は、div を黄色にします。
          • 合計が 0 より大きければ、セルにリンクを加えます。
          • 行を $table に保存し、foreach で繰り返します。
    • 表を表示します。
    • 凡例とその他注意をページの下に表示します。

API 呼び出し関数

数行のコードです。この行で行う処理は次の通りです。

  • 拡張を Pandora FMS メニューへ挿入
  • そして、呼び出し
extensions_add_operation_menu_option("Modules groups", 'estado', 'module_groups/icon_menu.png');

ここで、

  • 'Modules groups' は、エージェントのサブメニューに表示される名前です。
  • 'estado' は、拡張に関連付けるエレメントです。
  • 'module_groups/icon_menu.png' は、サブメニューに表示されるアイコンです。パスは、拡張のディレクトリからの相対パスです。
  • この拡張のメイン関数の定義
    extensions_add_main_function('mainModuleGroups'); を呼び出すことによって行います。ここで、
    • 'mainModuleGroups' は、拡張のメイン関数名です。

呼び出す関数の順番に指定はありません。いずれかを最初に呼び出して、2つ目に他の関数などを呼び出すことができます。

ディレクトリ構成

拡張のインストールはとても簡単です。なぜなら、Pandora FMS コンソールは新たな拡張を検索し、それを見つけたらシステムに追加します。 拡張のファイルすべてを Pandora FMS コンソールをインストールした extension ディレクトリにコピーするだけです。ただし、Pandora FMS コンソールが拡張のファイルおよびサブディレクトリを読めるようにパーミッションを設定する必要があります。

画面例では、extension は次のようなディレクトリ構造になっています。

  • module_groups
    • icon_menu.png
  • module_groups.php

そして、例では extension ディレクトリは、/var/www/pandora_console にあります。

サブディレクトリ

この場合、例では一つのサブディレクトリがあります。そして、通常、拡張は一つのサブディレクトリを持つ必要があります。サブディレクトリは、拡張のメインファイルと同じ名前です。この例のサブディレクトリには、アイコンファイル (icon_menu.png) のみがあります。このアイコンは、 Pandora FMS メニューに表示されます。