ZD&T環境にIMS-to-Db2レプリケーションのテスト環境を構築する


IMSの階層型DBは、CDC (Change Data Capture; 変更データキャプチャ)を嚙ませることで他のDBプラットフォームへレプリケーションすることができます。

たとえばDb2へ持っていく場合、

1. IMS (ソースDB)
2. Classic CDC (キャプチャー・サーバー：IMSDBのレコードやアクティビティーを読取って送信)
3. CDC RE for Db2 (アプライ・サーバー：送信された情報を受け取ってDb2へ適用)
4. Db2 (ターゲットDB)

と伝ってレプリケーションできます。
Db2がオープン環境にある場合、1. IMSと2. Classic CDCはホスト(メインフレーム)のz/OS上、3. CDC RE for Db2と4. Db2はオープン環境に置くことになります。

今回、ZD&Tを使ってこのホストIMSからオープンDb2へのレプリケーションをテストする小規模な環境を構築してみました。
下記のようなイメージです。

![Picture2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140745/c7980927-f293-e107-8a63-8dccc1b1bb48.png)

ZD&T (IBM Z Development and Test Environment) はメインフレーム(z/OS)の開発環境をエミュレートする製品です。通常Zメインフレーム・ハードウェア上で稼働するz/OSディストリビューションをIntelマシンのLinux環境で稼働させることができます。
これによって単一のLinux区画だけでレプリケーション環境を構築できました。あと余談ですが、ZD&Tには最初からIMSが使える状態で入っているのでIMSのセットアップがほとんど不要だったのも大いに助かりました。

ZD&Tのセットアップではこちらの記事を参考にしました。
- [クラウド上でのメインフレーム開発環境構築](https://qiita.com/tomotagwork/items/3b0c918c37ccf54a9ce8)

Classic CDCについて詳しくはこちらをご覧ください。
- [IMSデータ活用、近くで見るか、遠くで見るか？　～IMSデータ活用ソリューションとしてのDVMとCCDCを比較する (i Magazine・IS magazine; 外部サイト)](https://www.imagazine.co.jp/ims-data-solution/)

# Classic CDC のインストール

Program Directoryに従います。

まずインストールファイルをzFSの`/tmp/ccdc`にアップロード。同梱されているJCL:GIMUNZIPを編集して実行、DOCLIB/RIMLIB/PGMDIRを展開します。ここではHLQ:`CCDC113.`下に展開。

`CCDC113.RIMLIB(UNZIPJCL)`を編集して`CBCACHE.IBM.HABIB30.F2.pax.Z`をunzipし、インストールサンプルJCLを得ます。
ここからはこれらのサンプルJCLを流していきます。

まず`CACALA`、JCL中の指示に合わせて適宜CSIデータセット名を編集して実行。

続いて`CACALB`、こちらも指示に従ってZONE名等を編集して実行。

次にインストールファイルをunzipし、製品のRECEIVEを行います。
RECEIVEする製品IDは下記の通り。

- HABIB30: Classic Fed/Rep/EP Core (Base)
- JABIB3H: Classic CDC Unique
- JABIB3I: Classic CDC IMS

該当する製品IDをファイル名に持つインストールファイルをunzipし、JCL: `CACRECV0`, `CACRECVH`, `CACRECVI`を編集して実行します。

`CACALLOC`を編集/実行してターゲットライブラリーおよびディストリビューションライブラリーを作成。

`CACDDDEF`を編集/実行してDDDEFを登録。

`CACAPPLY`を編集/実行してRECEIVEした製品ライブラリーをAPPLYし、`CACACCEP`でACCEPTしたらインストールは完了です。

# Classic CDCのセットアップ

### APF登録
CCDCの実行ライブラリー`CCDC113.SCACLOAD`をAPF登録します。上述の通り、`CCDC113.`は製品インストール時に指定したHLQです。
私の使ったZDT環境では`USER.Z25C.PARMLIB(PROG00)`が使われていたのでそこに追記し、動的APFリストにも突っ込みます。
```
SETPROG APF,ADD,DSN=CCDC113.SCACLOAD,VOLUME=CCDC00                  
CSV410I DATA SET CCDC113.SCACLOAD ON VOLUME CCDC00 ADDED TO APF LIST 
```

### サンプルのアロケーション
`CCDC113.SCACSAMP(CECCUSC1)`をカスタマイズして実行。
`CCDC113.USERSAMP`および`CCDC113.USERCONF`を生成します。これらはともにCCDCの管理に使うJCLや制御ファイルのサンプルが入ります。

### カスタマイズユーティリティー
パラメーターファイル`CCDC113.USERSAMP(CECCUSPC)`を適宜編集したのち、installation customization utility: `CCDC113.USERSAMP(CECCUSC2)`を実行。
CECCUSC2はパラメーターファイルを読み込んでオフラインでパラメーターをカスタマイズするユーティリティーです。
各パラメーターの説明は[*マニュアル*](https://www.ibm.com/docs/en/idr/11.3.3?topic=zos-configuration-parameters-classic-data-servers-services)を。パラメーターはいずれも後から変更できるので、よくわからなかったらデフォルトのままでいいと思います。

### ログストリームの作成
CCDCはイベントログと診断ログ(diagnostic log)の書き出し先としてそれぞれ個別のz/OSログストリームを用います。`CCDC113.USERSAMP(CECCDSLS)`を編集・実行してz/OSログストリームを作成。併せてSMSデータクラスを定義。
z/OSログストリームはCF上に作成するかDASD上に作成するかという選択肢があるのですが、CCDCの場合複数システムで共有することはないためDASD上での作成が推奨されています。

ちなみにサイズ見積りのBest Practiceがマニュアル上で公開されていて、サンプルJCLで作成されるz/OSログストリームは小さすぎると言われています。ガチで環境構築するのならこちらを見ておくといいでしょう。
> The shipped sizing for the diagnostic and event logs is generally too small.
> [Best practices - IBM Documentation](https://www.ibm.com/docs/en/idr/11.4.0?topic=zos-best-practices)

今回はゆるゆるテスト環境なのでサンプルの指定値そのままで。

### zFSメタデータカタログを作成
CCDCがマッピング情報などのメタデータを管理するメタデータカタログを作成します。
カタログのフォーマットとしてzFSファイル, VSAM Linearデータセット, PSファイルが選択できるのですが、可能ならばzFSファイルを使うのが最も苦労が少なくおすすめです。
`CCDC113.USERSAMP(CECCRZCT)`を編集してVSAMデータセット`CCDC113.ZFS`を作成、アグリゲートします。
しかるのちに`/opt/IBM/isclassic113/catalog`をmkdirして先ほどの`CCDC113.ZFS`へマウント。
そして`CCDC113.USERSAMP(CECCDCAT)`を流してメタデータカタログを作成します。

### サブスクリプションとレプリケーション・マッピングのデータセットを作成
`CCDC113.USERSAMP(CECCDSUB)`によってVSAMデータセット`CCDC113.CDCSRC.SUB`と`CCDC113.CDCSRC.RM`を作成。それぞれサブスクリプションとレプリケーション・マッピングが格納されます。

### 構成ファイル用データセットを作成
`CCDC113.USERSAMP(CECCDCFG)`によって`CCDC113.CDCSRC.CACCFGD`と`CCDC113.CDCSRC.CACCFGX`を作成。構成(config)情報が格納されます。

### ソースサーバー起動確認
CCDCソースサーバー起動JCL`CCDC113.USERSAMP(CECCDSRC)`を実行し、起動を確認します。
確認できたので`CECCDSRC`をJES2起動用のPROCLIB`USER.Z25C.PROCLIB`へコピーしました。

### メタデータカタログの稼働確認
ここではインストール検査用のサンプルJCL`CCDC113.USERSAMP(CECCDVCD)`を流してメタデータカタログがちゃんと機能していることを確認するのですが、その前に準備が必要です。

メタデータカタログはDb2のような権限体系を持っており、ユーザーIDに権限が紐づけられます。このユーザーIDはRACFユーザーIDです。
今回はユーザーID`IBMUSER`/パスワード`IBM`を使います。
管理ユーザーの割当てに先立って、管理ユーザーとして使うRACFユーザーIDのパスワードを暗号化します。
`CCDC113.USERCONF(CACPWDIN)`を編集し、以下のように書いておきました。
```
PASSWORD=IBM
```
次に`CCDC113.USERSAMP(CACENCRP)`を実行。すると先ほどの`CCDC113.USERCONF(CACPWDIN)`の中身が以下のようになっています。
```
PASSWORD=IBM                 
ENCRYPTED=x'5ca4ccab612297f6'
```
こうなったら暗号化成功です。

上記のインストール検査用JCLではメタデータカタログにアクセスするための接続情報として`CCDC113.USERCONF(CACMUCON)`を参照しています。このメンバーを編集し、以下を書き足しておきます。
```
USERID IBMUSER PASSWORD X'5ca4ccab612297f6'
```
最後に`CCDC113.USERSAMP(CECCDVCD)`を実行、RC=00ならば成功です。


# IMS側のセットアップ

### テスト用DBの準備
テスト用DBのDBDを編集し、以下のようにEXIT=ステートメントを書き足しておきます。
```
  DBD     NAME=APDB11,ACCESS=DEDB,RMNAME=DBFHDC40,                     X
               EXIT=(*,KEY,DATA,PATH,(CASCADE,KEY,DATA,PATH),LOG)       
```
細かい指定については[IMS側のDBDステートメントのマニュアル](https://www.ibm.com/docs/en/ims/15.1.0?topic=statements-dbd)に載っているのですが、基本的にCCDCによるIMS-to-RDBレプリケーションならこんな感じになるのではないかと思います。(IMS-to-IMSだと考えることが増えます)


### DRAのセットアップ
CCDCはDRA(database resource adapter)接続によってIMSに対してDL/Iコールを発行し直接読取りを行うことができます。フルリフレッシュ機能はこの直接読取りを使用します。

まず、CCDCのSTEPLIBに入れておいてDRA接続に使用させるDRA startup tableモジュールを作成します。
`MAXTHRD=`には5、`MINTHRD=`には3以上を指定するよう[*マニュアル*](https://www.ibm.com/docs/en/idr/11.3.3?topic=suia-setting-up-database-resource-adapter-dra-ims-access)に書かれているので従います。
私はこんな感じでモジュールDFSPZP01を作成しました：
```
//DFSPZPCM EXEC PROC=ASMDRA,MBR=DFSPZP01                                
//ASM.SYSIN DD *                                                        
PZP      TITLE 'DATABASE RESOURCE ADAPTER STARTUP PARAMETER TABLE'      
DFSPZP01 CSECT                                                          
         DFSPRP DSECT=NO,                                              X
               DDNAME=CCTLDD,     XXXXXXXX DDN FOR CCTL RESLIB DYNALOC X
               DSNAME=DFSF10.SDFSRESL,                                 X
               DBCTLID=IVP1,      NAME OF DBCTL REGION                 X
               USERID=,           XXXXXXXX NAME OF USER REGION         X
               MINTHRD=003,       XXX      MINIMUM THREADS             X
               MAXTHRD=005,       XXX      MAXIMUM THREADS             X
               TIMER=60,          XX       IDENTIFY TIMER VALUE - SECS X
               FPBUF=003,         XXX      FP FIXED BFRS PER THREAD    X
               FPBOF=005,         XXX      FP OVFLW BFRS PER THREAD    X
               SOD=X,             X        SNAP DUMP CLASS             X
               TIMEOUT=060,       XXX      DRATERM TIMEOUT IN SECONDS  X
               CNBA=0050,         XXX      TOTAL FP NBA BFRS FOR CCTL  X
               OPENTHRD=CCTL      XXX      OPEN THREAD DISABLE          
         END                                                            
//*                                                                     
```

次に、CCDCの`DRATABLESUFFIX`パラメーターに作成したモジュールのサフィックス(DFSPZPxxのxx部分)を指定します。
```
F CECCDSRC,SET,CONFIG,SERVICE=IMSDRA,DRATABLESUFFIX='01'               
CAC00200I SET,CONFIG,SERVICE=IMSDRA,DRATABLESUFFIX='01'                
CAC00243I SERVICE 'IMSDRA' OF SERVICE CLASS 'DRA' UPDATED SUCCESSFULLY.
```
上記はCCDC起動中にコマンドで指定した場合の例です。
上記「カスタマイズユーティリティー」の項のようにユーティリティーで設定しても、CCDC起動中にCDA(Classic Data Architect)から設定しても大丈夫です。

その後CCDCを再始動し、起動中のIMSに対してDRA接続に成功したことを確認しました。
```
CAC00136I DRA: CONNECTED TO IMS DBCTL 'IVP1'                       
CAC00138I DRA: CONNECTION USING OPEN THREAD TCB                    
/DIS CCTL ALL                                                      
DFS4445I CMD FROM MCS/E-MCS CONSOLE USERID=SUGI: DIS CCTL ALL IVP1 
DFS4444I DISPLAY FROM ID=IVP1 266                                  
    CCTL     PSEUDO-RTKN RECOVERY-TOKEN   REGID  PSBNAME   STATUS  
    DRAUSER                                                ATTACHED
     *23349/143709*                                                
```

#### 余談：DRA startup tableの指定FPバッファー数が多すぎたときのこと

CCDCを立ち上げると自動で行われるはずのDRA接続が完了せず、リトライし続けていました。
診断ログ(デフォルトではClassic CDCサーバー領域のSYSPRINTにも書かれます)を見てみると、下記のエラーが出ていました。
```
2023-12-15-14.21.03.631758 RC(04), SpcRC(00570082), Data(00000000,00000000)              
   Node(34), Task(9217984)                                                               
   *ALL*, func DRAmain, line 607 in SYS22032.T144226.RA000.CACBLDC0.PH41278.H02(MSLCIDRA)
   'The DRA initialization failed.                                    '                  
   'DRA INIT PAPLSFNC=2(x02),PAPLRCOD=5(x05),                         '                  
   'PAPLRETC=-2147483592(x80000038)                                   '                  
```

IMSのマニュアル[Reason codes from DRA to the control exit](https://www.ibm.com/docs/en/ims/15.1.0?topic=codes-reason-from-dra-control-exit)で`PAPLSFNC=2(x02),PAPLRCOD=5(x05)`を引いてみると「DBCTL returned an IMS abend code.」とあるのでIMSのアベンドコードを見に行きます。`x0038`=[0056](https://www.ibm.com/docs/en/ims/15.1.0?topic=0100-0056)を見てみると、CCTLがFPバッファーの獲得に失敗したそうな。

テスト環境のIMSに割当てられているFPバッファー総量に対してDRAスタートアップ・テーブルで要求したFPバッファーの数が多すぎたのが原因でした。

FPバッファー数(`FPBUF=`/`FPBOF=`/`CNBA=`)を減らしてDRAスタートアップ・テーブルを再作成したところ、無事DRA接続に成功しました。
```
CAC00136I DRA: CONNECTED TO IMS DBCTL 'IVP1'                       
CAC00138I DRA: CONNECTION USING OPEN THREAD TCB                    
/DIS CCTL ALL                                                      
DFS4445I CMD FROM MCS/E-MCS CONSOLE USERID=SUGI: DIS CCTL ALL IVP1 
DFS4444I DISPLAY FROM ID=IVP1 266                                  
    CCTL     PSEUDO-RTKN RECOVERY-TOKEN   REGID  PSBNAME   STATUS  
    DRAUSER                                                ATTACHED
     *23349/143709*                                                
```
さて、ここからは仮想z/OSの外での作業です。ここから先はあまり筆者を信用しないでください。

# Db2のインストール
こちらの記事をありがたく参考にさせていただきました。
[【備忘録】Db2 インストール手順まとめ（Linux）](https://qiita.com/Haruka-Ogawa/items/9576399209b32f3016ea)

# CDC for Db2のインストールとセットアップ

## 製品インストール
適当なディレクトリを掘り、DLした"IBM InfoSphere Data Replication V11.4 CDC for all Linux x86 Agents Multilingual"を放り込んで解凍。
セットアップモジュール`setup-iidr-11.4.0.0-5001-linux-x86.bin`を実行します。
マニュアル"[Installing the CDC Replication Engine for Db2® Database using an interactive installation (UNIX and Linux)](https://www.ibm.com/docs/en/idr/11.4.0?topic=icredd-installing-cdc-replication-engine-db2-database-using-interactive-installation-unix-linux)"を参考にしながら…

- 「ロケールの選択」で「2- 日本語」を選択。
- 「データ・ストア・タイプの選択」で「2- IBM DB2」を選択。
- 「オファリングの選択」で「4- IBM InfoSphere Data Replication」を選択。
- 最後に「構成ツールを起動しますか?」に対して「1=はい」を選択。

## CDCインスタンス作成
新規インスタンスの名前はなんでもいいのですが、今回は「idrdb2」としました。
ポート番号はデフォルトの10901をそのまま使います。
ターゲットとするDb2インスタンスおよびデータベースを選択、ターゲットDb2データベースへのアクセスに使用するユーザー名やメタデータ表のスキーマを選択します。

私はDb2インストール時に作ったdb2inst1を使ったのですが、詳しい人が見たらけしからんことをしているかもしれません。ごめんね。
```
    インスタンス idrdb2 が正常に作成されました。

    インスタンス idrdb2 を今すぐ開始しますか (y/n)?y

    インスタンス idrdb2 を開始しています。 お待ちください...

    インスタンス idrdb2 が正常に開始されました。 Enter キーを押してメインメニューに移動してください...


    メインメニュー
    --------------
    1. 現行インスタンスのリスト
    2. インスタンスの追加
    3. インスタンスの編集
    4. インスタンスの削除
    5. インスタンスの統合
    6. 終了

    番号を入力してください:1


    現行インスタンスのリスト
    ------------------------

    名前      サーバー・ポート データベース  スキーマ    状況
    --------- ---------------- ------------- ----------- ------------
    idrdb2    10901            testdb        db2inst1    実行中
```

# Access Serverのインストール
レプリケーションの定義や操作はManagement Consoleというワークステーション上のコンソールからリモートで行うことができるのですが、これらのクライアントに対してレプリケーションの定義や操作を提供するのがAccess Serverです。ソース/ターゲットと散らばる種々のレプリケーション・サーバーおよびそれらの間のレプリケーションを横断的に管理することができます。

これまたワークディレクトリーに放り込んだセットアップモジュール`iidraccess-11.4-10014-linux-x86-setup.bin`を実行し、[To install Access Server (UNIX and Linux)](https://www.ibm.com/docs/en/idr/11.4.0?topic=server-install-access-unix-linux)を見ながら、基本的にデフォルトを選択していきます。ポート番号もデフォルトの10101を使用。

インストールが完了したら以下のようにAccess Serverを始動し、
```
[ibmsys1@zvirsh work]$ /opt/IBM/InfoSphereDataReplication/AccessServer/bin/dmaccessserver &
[1] 751786
```

ユーザーアカウントを作成します。
```
[ibmsys1@zvirsh work]$ cd /opt/IBM/InfoSphereDataReplication/AccessServer
[ibmsys1@zvirsh AccessServer]$ bin/dmcreateuser admin admin admin-user admin SYSADMIN TRUE FALSE FALSE
```
構文は[*マニュアル*](https://www.ibm.com/docs/en/idr/11.4.0?topic=aas-creating-access-server-user-account-in-non-ldap-mode-unix-linux)にちゃんと載っていますが、上記の例は`admin`というユーザーを作成し、初期パスワードは`admin`です。

# iptables設定
さて、ポート番号10901を使用するCDCインスタンスと10101を使用するAccess Serverをセットアップしたわけですが、ローカルのManagement ConsoleからAccess Serverへアクセスする前にiptablesをしかるべく設定してあげないといけません。

筆者の使用した環境はポートフォワードによって特定ポート以外は仮想z/OSへフォワードされるようになっていたので、
- INPUTフィルタで10101と10901をACCEPTして、
- 両者をポートフォワードから外す

という設定を施しました。

ZD&T環境のネットワーク構成については下記の記事に詳しいです。
[クラウド上でのメインフレーム開発環境構築 - (7) ネットワーク構成補足](https://qiita.com/tomotagwork/items/369367bae3d3cd3c8a15)

設定後、Management Consoleから環境の10101番ポートへ接続し、上記の「ユーザーアカウントを作成します」で作成したadminユーザーへログオンできれば成功です。

# おわりに
z/OSのテスト環境やLinuxのテスト環境は持っていてもネットワーク的な問題で気軽に両者間のレプリケーションをテストできないというシチュエーションは少なくないのではないでしょうか。筆者はまさにその状況でした。そうしたときにLinux上で仮想z/OSをエミュレートできるZD&Tは願ったりでした。

実際はこのあとCCDC側でIMSDBのマッピングをしてManagement Consoleからサブスクリプションを作ってという過程を経てレプリケーションのテストをしました。それ以降もちょっとした機能テストやスキルトランスファーに役立ってくれています。

なおZD&T自体については筆者も大変お世話になった下記の記事シリーズでとても丁寧に解説されています。冒頭でもリンクしましたが再掲とともに改めてお礼申し上げます。
> ZD&Tにはいくつかエディションがありますが、ZD&T Enterprise Edition(ZD&T EE)はクラウド環境で稼働させることができるので、実際にIBM Cloudの仮想サーバー(IaaS)を使ってZD&Tを動かすということをやってみたいと思います。
> [クラウド上でのメインフレーム開発環境構築 - (1) 仮想サーバー作成](https://qiita.com/tomotagwork/items/3b0c918c37ccf54a9ce8)