RUNES Bus Interface

まず仕様を固めねば。
ころころ気が変わって実装もままならない。

ここにメモしておくと、ドキュメントを書く段に楽になって良いんじゃないか。


というわけで、まずRUNESの基本構造:

/etc/RUNES/
  runes/     プラグイン(.bdl)を置く
  roles/     各種roleを定義
  work/      いわゆる/var
  interface/   プラグインごとにinterfaceを置く


これらのディレクトリへのパスは適用プログラムの引数に渡す。なので常に/etc/RUNES/runesがプラグインディレクトリとは限らない。

なので、これらのディレクトリへのパスやらやらいろいろを環境変数プラグインに渡す。





プラグイン適用時に設定されている環境変数
RUNES_SERVICES_DIR:runes/ディレクトリへのパス
RUNES_ROLES_DIR:roles/ディレクトリへのパス
RUNES_WORK_DIR:work/ディレクトリへのパス
RUNES_INTERFACE_DIR:interface/ディレクトリへのパス
RUNES_CONFIG_PATH:適用中のプラグインの設定ファイルへのパス
RUNES_RUNE_NAME:適用中のプラグインの名前


runes/ディレクトリには、プラグイン(つまり拡張子が.bdlのディレクトリ=プラグインバンドルと呼ぶ)を置く。runes/IPv4Network.bdlなど。





プラグインの構造:
ExamplePlugin.bdl/
  info.xml    メタデータ
  start      実行ファイル
  resourcs/    リソースディレクト
  default.conf  デフォルトの設定ファイル(オプション)


メタデータには、いろいろ書く。

 ExamplePlugin
 0.1
 0
 1
 linux-i386

 


  American english summary
  日本語で概要
  <ロシア語>とかとか
 

 
  /bin/bash
  ifconfig
  route
 

 
  
    
    

    
     
      Name
      Type
      Speed
     

    

  

  
    
     NetworkLinkName
    

    
     IPAddress
     NetMask
    
  

 

 
  American english long long description...
  長い長い説明。manページをここに書いてしまう。このXMLはXSLTでHTMLに加工してドキュメント化する意図あり。
 



どんどんメタデータに書く情報量が増えていく。要素と、が増えた。


一方で要素(このプラグインがリッスンするポート番号)を無くした。衝突してはマズイものはここに書いておくことで、プラグイン管理ツールの段階で衝突を検出できる。
でも、に書けば良いのでは無いかと。プラグイン管理ツールの仕事が増えるし…(←これが主な理由だったりする…)


あと、要素が無くなった。単純にパーサーを書き直したときに、要素のパース部分を作っていないため。どうしようかなぁ。作らないとダメだよなぁ…。



で、プラグインバンドルの直下には、これら以外のファイルとディレクトリは置いてはいけない。そういうものはresources/ディレクトリに入れる。






work/ディレクトリには、プラグインごとに名前空間が存在する。
空間名はプラグイン名。
つまり、Hogeプラグインは、work/Hogeを自由に使える。work/Hogeはファイルでもディレクトリでも良い。




さてさて、interface/ディレクトリがRUNES Bus Interfaceの舞台。
プラグインは、startの終了時にinterface/にプラグイン名(RUNES_RUNE_NAME環境変数)と同じ名前のプログラムファイルを出力する。
resources/ディレクトリに用意しておいたものをコピーしても良い。(シンボリックリンクはNG。runes/ディレクトリは全てのプラグインを適用し終わった後も存在しているかどうかは保証されていない! ←いつかプラグインをネットワークで共有するための絡みで…)



このプログラム(interfaceプログラム)は、メタデータの要素に書いたコマンド名を引数に取り、同じく要素に書いた引数を標準入力で受け取り、要素に書いた情報を標準出力に出力する。

…というのは予定で、今のところ要素に書いた引数は、標準入力では無く、プログラムの引数で受け取る。


あと、プログラムじゃなくて名前付きパイプとかでも良いかなと思ったけど、まぁ、いっか。
プログラムだと、ひとえにシェルスクリプトから使い易い。


interfaceを使う側は、このプログラムを意識する必要は無くて、RUNESが提供するAPIを使ってアクセスする。



APIはいろいろな言語に対応する。(予定)
シェルスクリプトだと、以下:
runes_interface [command_arguments...]


query_typeには、LOCALとALLとROLEがある。
たぶん、すぐにはLOCALしか実装できない。


LOCALの場合は、にプラグイン名を指定する。


で、これをevalの中で実行するのがポイント。
例えば、こう↓



eval `runes_interface ipv4_ LOCAL IPv4Network getIPInfo eth0`



これを実行すると、$ipv4_IPAddressなどの変数が定義される。があるのが親切親切。



で、たぶんすぐには実装できないけど、ALLやROLEの場合は、ホストをまたいだinterfaceにアクセスしたい。

それから、プラグイン名の代わりに「トピック名」を指定する方法も実装したい。

さらに、やっぱり引数は標準入力で渡したい。

たとえば、



runes_interface prefix_ ROLE WebServerRole TOPIC:NetworkInfrastructure getIPAddress # 引数は標準入力で渡す



標準入力と出力は、interfaceを呼び出す側と呼び出される側それぞれに、引数コンポーザ/パーサAPIを提供して、それらのインターフェースをXMLパーサー風する。
つまり、プラグイン間でXML-RPCがやりたい。(ただ実際の通信内容までXMLである必要は無い)


トピック名の指定は、特定のプラグインに依存しない問い合わせをしたいときに行う。
たとえば「ネットワーク回りのプラグインで、これこれのインターフェースを持っていればならどんなプラグインでも良いんだけど」と言う場合。

トピック名は別に無くても良いのだけど、特定の分野に関する問い合わせだよと限定しないと、名前が衝突しそう。



プラグインは1つのバスに繋がっていて、そこにメッセージを投げると、そのメッセージをサポートしているプラグインが答えてくれる。(実装的には、RUNESがメタデータを読んで、サポートしているプラグインまでルーティングする。


プラグインがネットワークの向こう側であろうとなかろうと、RUNESの方で隠蔽するので、プラグインはネットワークを意識する必要は無い。(もちろんその分RUNESが頑張る必要があるけども…



と、これで「Enterprise Service Bus」のアイディアを拝借したものであると分かる。





あー書いた書いた。はてなに書いた方が良かったかな。

このアイディアがスバラシイ!と思った方は、是非実装してくださいな。フリーなライセンスで…
少なくとも自分ではスバラシイ!と思っておるのです。