まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:domino

IBM LinuxONE(メインフレーム版 Linux)に IBM Domino をインストールすることに挑戦してみました:2017012200


いくつか前提を紹介します。まず LinuxONE の環境は IBM LinuxONE コミュニティクラウド上の RHEL 6.x のサーバーインスタンスを使うことにします(最大 120 日間無料で使えます)。また IBM Domino を導入する際にはその環境に X Window のデスクトップ GUI が必要です。これらの環境を用意するまでの手順はこちらを参照ください:
IBM LinuxONE コミュニティクラウド上で X Window のデスクトップ環境を構築する


次に IBM Domino ですが、これは無料で入手できるものではありません。IBM Domino のサブスクリプション契約をお持ちで、インストールモジュールをダウンロードする権利をお持ちの人のみが入手可能なものです。

(訂正)
IBM Domino は IBM 無料トライアルダウンロードプログラムに含まれており、IBM LinuxONE 向けのエディションもこの対象でした:
https://www.ibm.com/developerworks/downloads/ls/lsds/

2017012302


IBM ID をお持ちか作成いただくことで、こちらからトライアル版をダウンロードしてご利用いただくことも可能です:
2017012301



(有効なサブスクリプション契約をお持ちの場合は、)"Linux for z System" 向けの IBM Domino の最新版をダウンロードしてください。ちなみに 2017/Jan/22 時点では V9.0 英語版がパーツ番号 CIBM5EN で検索することで見つけることができるはずです。ファイル名は DOMINO_9.0_64BIT_LIN_ZS_EN.tar でした。このファイルを入手済みであるとして、以下を紹介します。

LinuxONE に限らないのですが、Linux 版の IBM Domino は導入前に root ではない実行時のユーザーおよびそのグループを OS 内に作成しておく必要があります。以下、notes グループの notes ユーザーによって実行する前提として、これらのグループとユーザーを作成しておきます:
# groupadd notes
# useradd notes -g notes

ユーザーを作成したら、ダウンロードしたインストールモジュールファイルを展開し、zlinux64/domino フォルダ内のインストーラー(install)をコマンドラインから実行してインストール作業を行います:
# cd /data
# ls
DOMINO_9.0_64BIT_LIN_ZS_EN.tar

# tar xvf DOMINO_9.0_64BIT_LIN_ZS_EN.tar

# cd zlinux64/domino

# ./install

インストーラーを実行すると、次のようなインストール画面に切り替わります。ここから次へは TAB、変更時はスペース+変更内容+Enter で、必要に応じてオプションを編集しながらインストーラーの作業を進めます:

2017012002


LinuxONE で利用する場合、唯一意識すべきはインストール先のディスクだと思われます。比較的メインディスクに空きがない状態で導入するには /data 以下を指定して導入するようにします。以下の例はデータディレクトリをデフォルトの /local/notesdata から /data/local/notesdata に変更している様子です:
2017012003


最終確認画面が表示されています。問題なければ TAB キーでインストールが開始されます:
2017012004


インストールが完了しても、IBM Domino の場合はセットアップを行わないと動きません。というわけでセットアップに移りますが、その前に1つ作業があります。 xhost の設定をしておかないとセットアップ時に利用する GUI のウィンドウが開かないのです。

またここからは X Window システムのデスクトップ GUI 環境が必要になります。というわけでまずは VNC クライアントを使ってこのサーバーのデスクトップを開いてターミナルを起動し、この xhost コマンドで notes ユーザーの画面でインストーラーウィンドウが開くようにしておきます:
# xhost +local:notes

そのまま続けて notes ユーザーに su し( root ユーザーでは server は起動しません)、ノーツデータディレクトリがカレントディレクトリになっている状態から server を実行します。これ実はサーバーの起動手順と同じですが、最初の一回はセットアップモードでの起動が行われます:
# su - notes

$ cd /data/local/notesdata
$ /opt/ibm/domino/bin/server

すると GUI に Domino セットアップのフラッシュスクリーンが表示され・・・
2017012005


しばらくすると、見慣れた Domino サーバーセットアップの画面に遷移します。ここからはいつもの(Windows とかの)セットアップと同じです:
2017012006


セットアップが完了し、再度 server コマンドを実行すると、今度は Domino サーバーがコンソール内で起動し、Domino サーバーとして利用可能になります:
zdomino


IBM Domino は有料のソフトウェア製品であり、この製品(特に IBM z Systems 版)を無料で入手する方法は限られてしまいますが、その手段をお持ちの方であればのインストールモジュールを入手する方法がちと面倒ではありますが、IBM Domino はメインフレーム上のパブリッククラウド Linux に導入して使うまでの環境は(IBM LinuxONE コミュニティクラウドを使うことで)無料で用意できることになります。

試験的な利用も含め、パブリッククラウド上で IBM Domino の環境を作って動かしてみたい、という方は是非一度お試しください。

先日のブログで、IBM Domino のログを外部の Web API 経由で取得する、という方法を紹介しました:
ノーツの Web エージェントで外部からログを取得する

要は log.nsf には手を付けずに、log.nsf の中身を取得して XML 出力するような API を外部データベースに Web エージェントとして作成して呼び出す、 という内容でした:
2016120302


今回はその応用編です。API でログが取得できるようになったので、その取得したログの(テキストの)内容を更に分析してみます。

今回新たに使う API は Watson Tone Analyzer です:
2016120500


Tone Analyzer は IBM Watson が提供するコグニティブ API の1つで、会話の中で発生する喜び、悲しみ、怒りといった「トーン」をテキストの内容から検出する API です。現在は大きな分類として「感情(怒り:Anger、嫌悪:Disgust、不安:Fear、喜び:Joy、悲しみ:Sadness)」、「社交性(開放性:Openness、誠実性:Conscientiousness、外向性:Extraversion、協調性:Agreeableness、情緒不安定性:Emotional Range)、「文体(分析的:Analytical、確信的:Confident、あいまい:Tentative)」という3種類のトーンを分析します:
2016120501


なお 2016/Dec/05 時点では、この API は日本語テキストには未対応です。なので、日本語の会話テキストをそのまま API のインプットデータに使うことは現時点ではできません。今の段階では使い方も限られてしまいますが、英語テキストを使えばどんな API なのかを確認する程度のことはできると思います。


この API は与えられたテキストをもとに、上記3種類のトーン毎に各要素の割合を識別して結果を 0 から 1 までの数値で返してくれます。結果の判断の方法は一概に言えないのですが、一般的には 0.75 以上であればその要素が表面化していて、0.5 以上の場合は表面化せずにも含まれている(それ以下は要素として見られない)と判断するようです。この辺りの数値結果の考え方について詳しくはこちらを参照ください:
Understand your tone score


というわけで、IBM Domino の log.nsf から取り出したログの英語テキストを、この Tone Analyzer API を使って「IBM Domino はどんな感情のログを吐いているか?」を調べてみることにします。ちなみに PHP 版のソースコードはこちらに公開しておきます:
https://github.com/dotnsf/ToneAnalyzerWithDominoLog

上記リポジトリの内容をダウンロード&展開するかクローンして、credentials.php ファイルの内容を自分の環境(Domino ログを取得する歳の URL と、Tone Analyzer の username 及び password)に合わせて編集します。そして index.php をブラウザから呼びだすと、こんな感じの画面が表示されると思います:
2016120502


index.php の内容を見ていただくとわかりますが、まず前回紹介した内容を使って Domino の log.nsf からログを Web エージェント経由で取得します。そしてその取得したテキストログをまとめて Tone Analyzer へ送り、感情分析結果を取得して、表にしている、というものです。jquery-ui を使って、感情スコアのスライダー表示も実装しています。

この表の部分だけを拡大したものがこちらです:
2016120503


この結果から、0.75 を超えているのは感情の5要素にはありません。機械的なログを分析しているので、これはある意味で正しい結果と考えられます。次に文体の3要素の中では Analytical(分析的)が 0.75 を超えているので、分析的なテキストであったといえます(これもログなのである意味正しいと言えます)。そして社交性の5要素のうちでは Conscientiousness(誠実性)と Emotional Range(情緒不安定性) が 0.75 を超えていました。な、なんかメンヘラっぽいけど、うちの Domino サーバーは大丈夫なんだろうか? (^^;


と、まあ Tone Analyzer はこんな感じで使えます。このブログでは IBM Domino のログを対象に解析していますが、もちろん他のミドルウェアサーバーのログや、テキストを元に解析できます。現状は日本語未対応なのでできることも限られてしまいますが、ある意味今のうちにいい勉強ができるともいえます。

なお、Watson Tone Analyzer はサンプルアプリのサイトから実際にテキストを与えて、感情分析結果を確認することも可能です。試してみたいテキストがあればこちらから確認してみてください:
https://tone-analyzer-demo.mybluemix.net/


先日紹介したこのエントリの続きです。今度はノーツデータベースの中身を取得する Web API をエージェントで作成してみます:
ノーツの Web エージェント


対象とするノーツデータベースは「ログ」にします:
2016120301


このログデータベースは Domino サーバー上に log.nsf として存在しています。個々のログ内容は Events フォームのドキュメント内の EventList フィールド内に配列の形で格納されています:
2016120303


というわけで、同データベースからログを取り出して、XML 化して出力する、という Web API(Web エージェント)を作ってみました。基本的な考え方や作り方は前回紹介したものと同様ですが、実際の処理内容だけを変えています:
  :
:
public class JavaAgent extends AgentBase{ public void NotesMain(){ try{ Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) String xml = "<?xml version=\"1.0\"?>\n<eventlist>\n"; //. 直近1週間のログのみ対象とする Date dt0 = new Date(); long t = dt0.getTime(); t -= ( 7 * 24 * 60 * 60 * 1000 ); dt0.setTime( t ); //. この(エージェントのある)データベースと同じサーバー上の log.nsf を対象とする Database cdb = session.getCurrentDatabase(); String server = cdb.getServer(); Database logdb = session.getDatabase( server, "log.nsf" ); //. Events フォームの文書を取り出す DocumentCollection docs = logdb.search( "Form=\"Events\"" ); for( int i = 1; i <= docs.getCount(); i ++ ){ Document doc = docs.getNthDocument( i ); //. EventList フィールドの配列値を取り出す Vector eventlist = doc.getItemValue( "EventList" ); Enumeration event = eventlist.elements(); while( event.hasMoreElements() ){ String line = ( String )event.nextElement();      //. 日付とログ文字列に分離 int x = line.indexOf( " " ); if( x > 0 ){ String dt = line.substring( 0, x ); //. YYYY/MM/DD hh:mm:ss String msg = line.substring( x + 3 ); //. 対象日(7日以内)のログかどうかを確認 Date dt1 = new Date( dt ); if( dt1.after( dt0 ) ){ //. XML 用にサニタイズ msg = msg.replaceAll( "\n", "" ); msg = msg.replaceAll( "\r", "" ); msg = msg.replaceAll( "&", "&amp;" ); msg = msg.replaceAll( "<", "&lt;" ); msg = msg.replaceAll( ">", "&gt;" ); msg = msg.replaceAll( "\"", "&quot;" ); xml += ( "<event datetime=\"" + dt + "\">" + msg + "</event>\n" ); } } } } xml += "</eventlist>\n"; //. 画面に出力 PrintWriter pw = getAgentOutput(); pw.println( "Content-Type: text/xml" ); pw.println( "" ); pw.println( xml ); pw.close(); }catch( Exception e ){ e.printStackTrace(); } } }

↑基本的な考え方は前回紹介したものと同じです。出力内容は log.nsf の内容なので、このデータベースを取得して、対象(1週間以内)のログを探して1行ずつ XML を生成し、最後に text/xml として出力する、という内容を Java で記述しています。

※同様の Web エージェントを LotusScript で記述する場合、最後の出力部分は Print 文で代用してください。


このエージェントをブラウザから
  http://(domino サーバー名)/(DB名)/(エージェント名)?OpenAgent
という URL を指定して実行します
2016120302


Domino サーバーのログの内容が Web API で外部から取得できるようになりました。他のデータベースでも同様に応用できると思います。

IBM Domino 上で Java サーブレットを動かすまでの設定と実装を紹介します。なお、今回は Domino バージョン 9 上で実行することを想定しています。


まずは Domino 上で Java サーブレットが動作するよう設定します。Domino 導入後、管理クライアントを開きます(ウェブ版でも構いません。その場合は webadmin.nsf を開きます)。サーバー設定文書を編集モードで開いて、"Internet Protocol" - "Domino Web Engine" - "Java servlet support" を "Domino Servlet Manager" に設定します。また必要に応じて Servlet URL path(デフォルトで /servlet)や Class path(同 domino/servlet)を編集して保存します。これで Domino サーバー側の設定は完了です:
2016102201


次に Java サーブレットを実装します。Domino 上の Java サーブレットは war ファイルを読み込む、といったことができないので、JDK でサーブレットの class ファイルを用意します。この辺り詳しくは以下のエントリも参照ください:
Eclipse(IDE) を使わずにJavaサーブレットを作る



上記エントリで紹介した HelloWorld サーブレットを動かしてもいいのですが、せっかくなので Domino のクラスを使って情報を取得して表示する内容にします。以下のソースコードを DominoInfo.java というファイル名で、UTF-8 で記述して保存します(青字部分で Domino クラスを使っています):
//. DominoInfo.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import lotus.domino.*;

public class DominoInfo extends HttpServlet{
  @Override
  protected void doGet( HttpServletRequest req, HttpServletResponse res ){
    try{
      NotesThread.sinitThread();
      Session session = NotesFactory.createSessionWithFullAccess();
      String username = session.getUserName();
      String version = session.getNotesVersion();
      
      res.setContentType( "text/plain; charset=UTF-8" );
      res.getWriter().println( username + " : " + version );
    }catch( Exception e ){
      e.printStackTrace();
    }finally{
      NotesThread.stermThread();
    }
  }
}

↑このサーブレットを実行するユーザー(つまりサーバー ID のユーザー)名と、実行中の Domino のバージョンを取得して表示する、という内容です。

これを javac でコンパイルします。このエントリでも紹介しましたが、javac のパラメータで UTF-8 エンコードであることと、ServletAPI.jar のクラスパスを指定する必要がありますが、更に加えて以下の2点を指定してコンパイルします:

(1) lotus.domino.* クラスを利用するので、Notes.jar のクラスパスを指定(以下のコマンド例では C:\IBM\Notes\jvm\lib\ext\Notes.jar に存在していると仮定)
(2) Domino 9 で使われている Java のバージョンは 6 (つまり JDK 1.6)なので、このバージョン互換でコンパイルするよう指定


具体的には以下のようなコマンドを実行します:
C:\tmp>javac -classpath c:\arc\servlet-api-3.1.jar;c:\IBM\Notes\jvm\lib\ext\Notes.jar -encoding utf-8 -source 1.6 -target 1.6 DominoInfo.java

コンパイルに成功すると DominoInfo.class というファイルが出来上がります。これを上記で設定した Domino の classpath(上の例だと domino/servlet)フォルダにコピーして、Domino を再起動します。

再起動後、ウェブブラウザで Domino サーバーの /servlet/DominoInfo にアクセスしてサーブレットを実行し、以下のような結果になることを確認します:
2016102202


↑サーバーを実行しているユーザーの名前(CN=Domino/O=Dot123)と、Domino サーバーのバージョン(Build V90_C06_12072012|December 07, 2012)が表示できました。 本来、これらの情報は Notes クライアントなどの特殊環境からでないと取得できないものですが、そのロジックを Java サーブレットという仕様でラッピングすることで HTTP アクセスで取得することができるようになったことが分かります。Notes/Domino データベースへの読み書きを実現するための1つの方法として使えます。

とうとう IBM Bluemix 上のランタイムとして Domino サーバーが登場しました。詳しくはこちらを参照ください:
Domino on Bluemix


IBM Notes/Domino は IBM が開発/販売しているコラボレーションプラットフォームです。多くの企業でエンドユーザーコンピューティングやグループウェアの基盤として使われ、多くのビジネスパートナー様による関連製品/サービスもリリースされています:
2015081202



今回リリースされた XPages(Domino) ランタイムは、パブリッククラウドである Bluemix 上で、サーバー機能である Domino が稼働する環境を提供するものです。そこだけを見ると嬉しいニュースなのですが、ではこの Domino は Bluemix とどこまで親和性があるのでしょうか? たとえば Bluemix では Java や PHP などのアプリサーバーと、DB2 や MySQL などのデータベースサーバーは分離されています。そのため、アプリサーバー部分だけを負荷に合わせて手動でスケールアウトさせることもできますし、そのスケールイン/アウトを自動化させる、いわゆる「オートスケール」の設定を組み込むことも可能です。

一方、Domino サーバーは「オールインワン」型でした。アプリサーバーもデータストアもその中で動くアプリケーションも、更にはユーザーディレクトリや HTTP, タスクスケジューラといったサブタスクも全て一元化されたサーバーを使っていました。考え方としては1つのサーバーが全ての機能を持ち、負荷分散でサーバーを複数台対応させる場合にはデータも複製して対応する、というアプローチでした。

ある意味で相反する考え方を持つ Bluemix のランタイムと Domino ですが、ではこの Domino ランタイムが Bluemix 上で動く場合に、Bluemix のスケーリングの考えは適用できるのかどうか?という疑問が生じます。

具体的には Bluemix 上の Domino は Java や PHP アプリサーバーのように簡単に複数台対応できるのか?同様にオートスケール設定ができるのか?その場合のデータの整合性はどのようにして保つのか/保たれるのか? といった疑問です。


結論を先に言うと、Bluemix 上の Domino は(条件付きで)スケール対応します。Java や PHP と同様のインターフェースやオートスケールサービスを使って、動的に Domino サーバーを複数台対応させることができます。その際に Domino 固有のデータ複製設定などは必要ありません。

でも「なぜそんなことが可能なのか?」という疑問が生じるはずです。それについて正確に表現すると「Bluemix 上で .nsf ファイルを XPages 設計要素と、ビュー/フォーム/文書の要素に分けてプッシュする形でデータベースアプリケーションをデプロイすればスケーリングに対応できる、ということになります。つまり .nsf ファイルを設計とデータとに分離します。そして前者をランタイムで、後者をサービスで運用する形を取り、更にランタイムから分離先のデータサービスを正しく参照して文書データをデータサービス内だけに保存するような設計にするという条件を付けることでスケーリングが可能になる、ということです(ランタイム側にもサービス側にも .nsf ファイルが必要です):
2015081201


これを実現するには XPages の仕組みが必要になり、加えて既存 XPages アプリの設計を少し改良する必要もあります。具体的には、例えば XPages の設計要素でデータベースファイルを指定する箇所を以下のように指定します:
<xp:dominoView databaseName="myapp_data.nsf"> 
  ↓
<xp:dominoView databaseName="#{javascript:bluemixContext.isRunningOnBluemix()? bluemixContext.getDataService().findDatabaseName() : 'myapp_data.nsf'}"> 


この処理内容は XPages 内で JavaScript を使って「Bluemix 環境であればバインドされているデータベースを使う、Bluemix 環境でなければ myapp_data.nsf を使う」という処理を記述しています。つまり Bluemix 環境上で動いている時とそうでない時に分けてデータベースファイルを指定しています。Bluemix 向けに拡張された Domino Designer ではこのような記述も可能になります。このような仕組みによって Bluemix 上でスケールできるよう対応させる必要があるとも言えます。それが "(Domino on Bluemix ではなく)XPages on Bluemix" という名称にも現れているのだと思います。


というわけで、エントリ冒頭の疑問に対する答はこちらです: 
IBM Domino はスケールイン/アウトできます。Bluemix と XPages があればね♪


なお、Bluemix 上の XPages 関連ランタイムやサービスは2015年8月12日現在ではまだ「試験提供」のステータスです。上記内容は試験提供内容を元に記述しています。正式提供に向けて今後仕様変更があるかもしれないことはご了承ください。


このページのトップヘ