amegonの雑なブログ

日常的なものから技術的なものまでメモの雑記

JavaScript の jstree で MIB ツリーを作ってみた

前回からのあらすじ

前回からの続きです。
jstree が動く環境ができたので、この環境を使って MIB ツリーを表示できるようにしてみたいと思います。

注意事項

今回は MIB のツリーを作成していくことから MIB に関する固有の文言があちこちにでてくると思います。
気が付けば文言の説明ができればと思いますがきっとブログ初版では書けないと思うので、気になる単語が出てきたら調べてみてください。。

実装方法

以下のように機能をわけて実装したいと思います。

  • (1) ブラウザにツリーを描画する機能
  • (2) jstree がツリー描画に使用する json データの作成機能

まず (1) について。
jstree の機能を調べたところ、前回のブログに書いたような HTML にツリーの構成を <li><ul> を使用せずともツリー構成ができている json データを渡すことで実装できることがわかった。
仕様の詳細は以下を参照のこと。

www.jstree.com

なので、ツリーの機能としては 渡された json データをツリーとして描画する に特化してしまおうと考えた。
ツリーデータの作成が一緒になっちゃったりすると、肝心のツリーの描画に時間がかかるかなと思ったりしたので。

次に (2) について。
こちらはツリー描画に必要なデータを MIB から取得してくればいいなという漠然としたイメージあり。
実装しながらトライ & エラーでやっていきたいと思います。

実装

言語は何使う?

はじめは python 使おうかなとも思ったのですが、昔少し使ったことのある php にしました。
python を使って Web アプリを作れるかは興味があるので、php 版ができたら移植してみることも検討します。 (検討、って書いちゃうときっとやらないな。。)

(1) ブラウザにツリーを描画する機能

試行錯誤の結果、以下のようになりました。
いきなり結果ですが、ステップ数も多くないのでいいかなと思い。。。(笑)

<html lang="ja>
  <head>
    <link rel="stylesheet" href="./js/jstree/style.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="./js/jstree/jstree.min.js"></script>
    <title>MIB ツリーサンプル</title>
    <?php
        $treedata_base_path = "http://<サイトのURL>/amibtree/treedata.json";
        $json_data = file_get_contents($treedata_base_path);
        $json_data = mb_convert_encoding($json_data, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');
    ?>
    <script>
      $(function(){$('#using_json_3').jstree({ 
        "core" : {
          "data" : <?php echo $json_data; ?>
        },
      });});
    </script>
  </head>
  <body>
    <div id="using_json_3">
  </body>
</html>

何をしているかというと、ツリー描画用のデータが記載されている json データを外部ファイルから読み込んで jstree に渡しているだけです。
"http://<サイトのURL>/amibtree/treedata.json" に (2) で実装する機能が作成した json データのファイルを指定します。
できあがりはそっけない GUI になってます。今後デコっていければ。

(2) jstree がツリー描画に使用する json データの作成機能

こちらは (1) の機能で読み込みすることになっている treedata.json を作成します。
なんとなくカテゴライズして以下に説明していきます。

ツリーデータの仕様

ツリーの描画をするためには jstree の仕様に従って id、parent、text を持つ json データの配列を作成する必要があります。
ざっくりそれぞれの要素について説明。

  • id:自身の識別子。他とかぶってはいけない。(一意である必要あり)
  • parent:自身がつながる親の id を指定。自分自身が親になる場合には "#" と記載する。
  • text:ツリー描画した際にブラウザに表示される文字列

今回 jstree で描画しようとしている MIB 情報はそもそもツリー構造なので、上記の jstree の仕様にあてはめて以下のように設定しようと思います。

  • id:自身のOID。
  • parent:親のOID。MIB ツリーの親である iso の場合は "#" を設定。
  • text:MIB 変数名とOIDを併記して表記する。

イメージとしては以下の感じです。

{"id":".1","parent":"#","text":"iso(.1)"},
{"id":".1.3","parent":".1","text":"org(.1.3)"},
{"id":".1.3.6","parent":".1.3","text":"dod(.1.3.6)"}

↑ のようなデータの塊が書かれた外部ファイルを作成していきたいと思います。

ツリーデータ作成の流れ

ツリーデータは以下の流れで作成していきます。

  1. MIBファイルの読み込み
  2. MIB の DEFINITIONS を取得
  3. MIB で定義されている以下のオブジェクトの MIB変数名を取得
    • OBJECT-TYPE
    • OBJECT IDENTIFIER
    • OBJECT-IDENTITY
    • MODULE-IDENTITY
  4. snmptranslate コマンドを用いて MIB 変数名の OID を取得
    • snmptranslate -On DEFINITIONS::<MIB変数名>
  5. json データの作成(ここでは作成した順に配列化)
  6. 外部ファイルに書き出す

実際のコードは以下のような感じ。

<?php

// json データを書き出すファイル名の設定
$output_file_name = "./treedata.json";

// 作成にかかった時間情報を表示したかったので、Time Zone の設定と現在時間の取得
date_default_timezone_set('Asia/Tokyo');
echo "Start => " . date("Y/m/d H:i:s") . "\n";
$start_time = time();

// MIB ファイルからツリーに描画するデータの読み込み
// ここに保存されている MIB ファイルを順に読みこんで json データを作成する
$files = glob('mibs/*.mib');

// json データを格納する配列の宣言と初期化
$mib_oids = array();

// MIB ツリーの上位にあたる iso(.1)が定義されている MIB を見つけられなかったので決め打ちで設定
array_push($mib_oids, array("id" => ".1", "parent" => "#", "text" => "iso(.1)"));

// MIB ファイルを順に読み込んで json データの作成実施
foreach ($files as $key => $value) {
    // どのファイルを読み込んだか表示
    echo("File = " . $value . "\n");

    // MIB ファイルを行ごとの配列に格納
    $lines = file($value);
    $mib_definition_name = "";

    // 1行ずつ処理実施
    foreach ($lines as $line) {
        // MIB の DEFINITIONS を取得
        // MIB ファイルによって DEFINITIONS の書き方がスペースあったりなかったりで面倒だったのでパターンごとに書いた。そのうちリファクタリングしたい。
        if($mib_definition_name == "") {
            if(strpos($line,'DEFINITIONS ::= BEGIN') !== false || strpos($line,'DEFINITIONS ::=BEGIN') !== false || strpos($line,'DEFINITIONS::=BEGIN') !== false || strpos($line,'DEFINITIONS::= BEGIN') !== false) {
                $mib_definition_name = strtok($line, " ");
            }
        }
        // MIB 変数名の取得
        // 今回はトラップ (TRAP-TYPE、Notification-Type) は取得していない
        if(strpos($line,'OBJECT-TYPE') !== false || strpos($line,'OBJECT IDENTIFIER ::=') !== false || strpos($line,'MODULE-IDENTITY') !== false || strpos($line,'OBJECT-IDENTITY') !== false) {
            $mib_object_name = strtok($line, " \t");

            // 途中経過が知りたかったので MIB 変数名を表示
            echo("  mib_object_name = " . $mib_object_name . "\n");

            unset($output);
            $output = array();
            $return = 0;

            // snmptranslate コマンドで OID の取得
            $command = "snmptranslate -On " . $mib_definition_name . "::" . $mib_object_name;
            exec($command, $output, $return);
            if ($return == 0 && mb_strlen($output[0]) > 0) {
                $parent = "";
                $parent = substr($output[0], 0, strrpos($output[0], '.', -1));
                $json_array = array("id" => $output[0], "parent" => $parent, "text" => $mib_object_name . "(" . $output[0] . ")");

                // たまに MIB の実装がおかしいのか同じ OID を持つ MIB 変数名が複数の MIB ファイルに定義されている
                // OID がかぶっているものは追加登録しないようにここでチェックをいれている
                if (in_array($json_array, $mib_oids) == false) {
                    array_push($mib_oids, $json_array);
                }
            }
        }
    }
}
// json データの配列であるツリーノードの数がいくつあるかを表示している
echo("Tree Node Count = " . count($mib_oids) . "\n");

// 配列を OID 順にソート
$ids = array_column($mib_oids, 'id');
array_multisort($ids, SORT_ASC, $mib_oids);
$output_array = json_encode($mib_oids);
file_put_contents($output_file_name , $output_array);

// 作成完了時間と作成にかかった時間の表示
echo "Finish => " . date("Y/m/d H:i:s") . "\n";
$finish_time = time();
$elapse_time = $finish_time - $start_time;
echo "Elapse time => " . gmdate("H:i:s", $elapse_time) . "\n";

?>

いったんの成果物?

上記の機能を組み合わせてみたら以下のようなツリーができました。

触って見れるものは別途準備できたらご紹介します。。

課題

今後の課題としては以下の通りです。

  • MIB ファイルを動的に追加してツリーを更新できるようにしたい
  • MIB ツリーで MIB 変数を選択すると MIB の説明がみれるようにしたい
    • この MIB 変数はシステムのメモリ情報を取得します、など
  • この MIB ツリーから選択したターゲットの MIB データを取得できるようにしたい:MIBブラウザ
    • これは面倒くさそうなのでやめようかなと思っている。。。