はじめに
これまで、ZD&Tで提供されているADCDパッケージをベースにz/OS環境を構築する手順を見てきましたが、開発環境を整備する場合、実際のz/OS環境に近づけるようにカスタマイズを実施することになると思います。ZD&T EEでは元となるz/OSのイメージからZD&Tインスタンスのコピーを作成する機能を提供していますが、その元になるものとして製品提供のADCDを使うだけではなく、既存のZD&T環境の情報を使用することもできます。
例えば、最初にADCDを元にZD&Tインスタンスを作成し、開発環境としてのカスタマイズを行ったら、それをマスターとして同じ環境のインスタンスを複製していく、ということができます。
ここでは、カスタマイズしたZD&T環境から複製の元になる"イメージ"を作成する所をやってみます。
関連記事
クラウド上でのメインフレーム開発環境構築 - (1) 仮想サーバー作成
クラウド上でのメインフレーム開発環境構築 - (2) ZD&T管理サーバーのインストール
クラウド上でのメインフレーム開発環境構築 - (3) ライセンス管理
クラウド上でのメインフレーム開発環境構築 - (4) ZD&Tインスタンス作成概要(ADCD)
クラウド上でのメインフレーム開発環境構築 - (5) ZD&Tインスタンス作成詳説(ADCD)
クラウド上でのメインフレーム開発環境構築 - (6) DeviceMapファイル補足
クラウド上でのメインフレーム開発環境構築 - (7) ネットワーク構成補足
クラウド上でのメインフレーム開発環境構築 - (8) ADCD IPL, Shutdown補足
クラウド上でのメインフレーム開発環境構築 - (9) DASD管理補足
クラウド上でのメインフレーム開発環境構築 - (10)既存ZD&Tからイメージ作成
全体像
ZD&Tインスタンスをカスタマイズしたものを元にイメージを作成する、という手順について記載します。
論理的なイメージとしては上の図ですが、テスト環境としてはLinuxが2つしかないので、一度ADCDを元に作成したZD&Tインスタンスを既存ZD&Tインスタンスにみたてて、その情報をイメージ・ストレージ・サーバーに吸い上げる、ということを実施します。
事前準備
データ吸い上げ対象となるLinuxに対して以下のような環境を整える必要があります。
管理サーバーとの接続
ZD&T管理サーバー(Webサーバー、イメージ・ストレージ・サーバー)と以下の通信ができるようにしておく必要があります。
- Webサーバーから対象Linuxに対してZD&T起動ユーザーでSSH接続できること。
- 対象Linuxからイメージ・ストレージ・サーバーに対してFTP接続できること。
今回はZD&T EEでADCDを元に作成したZD&Tインスタンスを対象とするので、上の環境は既に整っている想定です。
圧縮用ディレクトリの準備
DASDイメージファイルを圧縮してイメージ・ストレージ・サーバーに転送するため、圧縮したファイルを一時的に保持しておくディレクトリを用意しておく必要があります(圧縮無しで転送することも可能ですのでその場合は不要です)。
ここでは、/mnt/ibmsys1/zdt/archive_temp
というディレクトリを作っておくことにします。
吸い上げるDASDイメージファイルを圧縮したものが格納されますが、全てのDASDイメージファイルの圧縮ファイルが一度に保持される訳ではありません。gzipで圧縮したDASDイメージファイルのうち最大のものが保持できるサイズがあればOKです。
DeviceMapファイルとDASDイメージファイルの精査
特定のZD&Tインスタンスをマスターとして、それをベースにクローンを作成していくイメージにしています。コピーする際に不要なDASDなどがあれば、それを排除したDeviceMapファイルを作成しておいてそちらを取り込むようにするとよいです。不要なDASDが大量にあると、ファイル転送の時間やディスクの消費サイズに大きく影響することになるので、必要最低限のセットをそろえるようにするとよいです。
ZD&Tインスタンス停止
対象となるZD&Tインスタンスは停止しておきましょう。稼働したままデータを吸い上げると中途半端な状態でコピーされてしまい複製先でうまく起動できなくなってしまうリスクがあります。
既存ZD&Tからイメージを作成する手順例
ZD&T管理コンソール(Webサーバー)のメニューから"既存コンテンツのインポート"を選択
データ吸い上げ対象となるLinuxへSSHで接続するための情報を指定します。
DeviceMapファイルと、圧縮用ディレクトリを指定します。
イメージ名やIPL関連情報を指定して"イメージの作成"をクリックします。
※デバイス・アドレス、IODFアドレス、LOASxxサフィックスなどはADCDから変更していないので同じものを指定しています。
インポートが開始されると以下のメッセージが表示されます。モニターをクリックします。
裏では、DASDイメージ・ファイルの圧縮=>イメージ・ストレージ・サーバーへの転送が繰り返されています。
経過を見ていると、DASDイメージ・ファイルを1つずつgzipで圧縮しては転送する、ということを繰り返しているようです(まとめて圧縮して一気に転送するのではない)。
あとはひたすら待つのみです。1つ1つDASDイメージ・ファイルを処理しているので結構時間がかかります。
※これ、完全にシーケンシャルに処理が行われています。例えば前のファイルを転送している間次のDASDイメージファイルの圧縮とかしてもいいと思うんですがそうはなっていません。gzipの圧縮でCPU負荷がかかっている状態と、FTP転送でネットワークI/O負荷がかかっている状態の繰り返しでひたすら時間がかかる感じです。非常に効率悪いっすね。
最終的にモニター画面でイメージ名の横の進行中のアイコンが無くなれば完了です。
処理内容イメージ
ここで実施される処理の流れを図示すると以下のようなイメージになります。
転送対象のDASDは、指定したDeviceMapファイルに定義されている情報から判断しているようです。
結果
イメージ・ストレージ・サーバー上には、イメージ・ストレージ・サーバー構成時に指定したディレクトリ(/home/ftpuser/ZDT_Image: 実体は/mnt/ZDT_Imageへのシンボリックリンク)配下に、既存ZD&T用のディレクトリが作成され、さらにその下に対象のサーバー名のディレクトリが作成されて、そこにDeviceMapファイル、および、DASDイメージ・ファイルが作成されます。
以下のような構造で各ファイルが格納されます。
[taguchi@zdt01 /mnt/ZDT_Image/zdt]$ tree . --charset=C
.
`-- zdt02
|-- aprof1
`-- volumes
|-- A4C551_2020_11_22_00_17_45.gz
|-- A4CFG1_2020_11_21_23_59_38.gz
|-- A4DBAR_2020_11_21_22_59_47.gz
|-- A4DBC1_2020_11_21_23_52_33.gz
|-- A4DBC2_2020_11_21_23_51_15.gz
|-- A4DIS1_2020_11_21_23_36_34.gz
|-- A4DIS2_2020_11_21_23_24_05.gz
|-- A4DIS3_2020_11_21_23_44_00.gz
|-- A4PAGA_2020_11_21_22_52_47.gz
|-- A4PAGB_2020_11_21_22_55_47.gz
|-- A4PAGC_2020_11_21_23_05_43.gz
|-- A4PRD1_2020_11_22_00_00_37.gz
|-- A4PRD2_2020_11_22_00_08_35.gz
|-- A4PRD3_2020_11_21_23_15_23.gz
|-- A4PRD4_2020_11_21_23_07_21.gz
|-- A4RES1_2020_11_22_00_20_31.gz
|-- A4RES2_2020_11_21_23_56_51.gz
|-- A4SYS1_2020_11_21_22_54_33.gz
|-- A4USR1_2020_11_21_23_00_47.gz
|-- A4USS1_2020_11_21_23_27_17.gz
|-- A4USS2_2020_11_21_23_35_13.gz
|-- A4ZCX1_2020_11_22_00_23_46.gz
|-- DASD01_2020_11_22_00_28_29.gz
|-- SARES1_2020_11_21_22_57_26.gz
`-- ZDTDPY_2020_11_22_00_28_29.gz
2 directories, 26 files
DASDイメージ・ファイルのタイムスタンプみるとこんな感じです。
[taguchi@zdt01 /mnt/ZDT_Image/zdt/zdt02/volumes]$ ls -ltra
total 30126628
drwxr-xr-x. 3 ftpuser ftpuser 4096 Nov 21 22:52 ..
-rw-r--r--. 1 ftpuser ftpuser 255477588 Nov 21 22:54 A4PAGA_2020_11_21_22_52_47.gz
-rw-r--r--. 1 ftpuser ftpuser 96912344 Nov 21 22:55 A4SYS1_2020_11_21_22_54_33.gz
-rw-r--r--. 1 ftpuser ftpuser 220343830 Nov 21 22:57 A4PAGB_2020_11_21_22_55_47.gz
-rw-r--r--. 1 ftpuser ftpuser 475503098 Nov 21 22:59 SARES1_2020_11_21_22_57_26.gz
-rw-r--r--. 1 ftpuser ftpuser 26702636 Nov 21 23:00 A4DBAR_2020_11_21_22_59_47.gz
-rw-r--r--. 1 ftpuser ftpuser 1658121405 Nov 21 23:05 A4USR1_2020_11_21_23_00_47.gz
-rw-r--r--. 1 ftpuser ftpuser 217313031 Nov 21 23:07 A4PAGC_2020_11_21_23_05_43.gz
-rw-r--r--. 1 ftpuser ftpuser 2829082249 Nov 21 23:15 A4PRD4_2020_11_21_23_07_21.gz
-rw-r--r--. 1 ftpuser ftpuser 3584605752 Nov 21 23:24 A4PRD3_2020_11_21_23_15_23.gz
-rw-r--r--. 1 ftpuser ftpuser 715258909 Nov 21 23:27 A4DIS2_2020_11_21_23_24_05.gz
-rw-r--r--. 1 ftpuser ftpuser 3088902207 Nov 21 23:35 A4USS1_2020_11_21_23_27_17.gz
-rw-r--r--. 1 ftpuser ftpuser 193300366 Nov 21 23:36 A4USS2_2020_11_21_23_35_13.gz
-rw-r--r--. 1 ftpuser ftpuser 2643496186 Nov 21 23:43 A4DIS1_2020_11_21_23_36_34.gz
-rw-r--r--. 1 ftpuser ftpuser 2635005204 Nov 21 23:51 A4DIS3_2020_11_21_23_44_00.gz
-rw-r--r--. 1 ftpuser ftpuser 104944699 Nov 21 23:52 A4DBC2_2020_11_21_23_51_15.gz
-rw-r--r--. 1 ftpuser ftpuser 1229113785 Nov 21 23:56 A4DBC1_2020_11_21_23_52_33.gz
-rw-r--r--. 1 ftpuser ftpuser 697183754 Nov 21 23:59 A4RES2_2020_11_21_23_56_51.gz
-rw-r--r--. 1 ftpuser ftpuser 22997238 Nov 22 00:00 A4CFG1_2020_11_21_23_59_38.gz
-rw-r--r--. 1 ftpuser ftpuser 3386960443 Nov 22 00:08 A4PRD1_2020_11_22_00_00_37.gz
-rw-r--r--. 1 ftpuser ftpuser 3628266658 Nov 22 00:17 A4PRD2_2020_11_22_00_08_35.gz
-rw-r--r--. 1 ftpuser ftpuser 888867213 Nov 22 00:20 A4C551_2020_11_22_00_17_45.gz
-rw-r--r--. 1 ftpuser ftpuser 729649120 Nov 22 00:23 A4RES1_2020_11_22_00_20_31.gz
-rw-r--r--. 1 ftpuser ftpuser 1510594075 Nov 22 00:28 A4ZCX1_2020_11_22_00_23_46.gz
-rw-r--r--. 1 ftpuser ftpuser 460881 Nov 22 00:28 ZDTDPY_2020_11_22_00_28_29.gz
drwxr-xr-x. 2 ftpuser ftpuser 4096 Nov 22 00:29 .
-rw-r--r--. 1 ftpuser ftpuser 10499603 Nov 22 00:29 DASD01_2020_11_22_00_28_29.gz
最初のファイルから最後のファイルが作成されるまで約1時間半くらいかかっているのが分かります。もちろん圧縮するマシンスペックやネットワークの速度などにも依存しますが。
DASDイメージ・ファイルのサイズの合計値は、圧縮前:約200GB, 圧縮後:30GB くらいです。
このようにイメージ・ストレージ・サーバーに取り込みが完了したら、それを元にZD&Tインスタンスを作成することができます。以下のように、デプロイ時のメニューで、取り込んだイメージを選択してZD&Tインスタンスを作成できるようになります。
その後のZD&Tインスタンス作成はADCDの場合と同じように実施できます。
補足: 問題判別メモ
ZD&Tの管理コンソールや、イメージ作成機能はLiberty上のWebアプリケーションとして実装されているようです。また内部的に各種管理情報を保持していますが、その実体としてはPostgreSQLを使用しているようです。
既存ZD&Tからイメージ作成を行う際、トライ&エラーを繰り返していると、ゴミがPostgresSQL上に残ってしまってどうにもならなくなったので、無理やりPostgreSQL上のデータを削除して対処しました(この辺の作りは結構甘くて色々問題ありそう...)。
※ここでのやり方は公式にサポートされた方法ではありません。たまたまうまくいっただけで、あくまで参考という位置づけととらえてください。不測の事態が生じた場合は基本的には正式な対処はサポート部門からの指示に従ってください。
【事象】
既存コンテンツのインポートをしようとした時、最初にZD&Tシステム情報を入力する際に、SSHのポート番号を誤って22を設定してしまいました。そのままイメージの生成を勧めようとすると当然失敗します。その後設定を修正してトライしようとしましたが、"予期しない例外"のようなエラーが出て進めなくなりました。
モニター画面に残っていたアプリケーション・イメージを削除してからリトライしてもNG、Libertyを再起動してもNGでした。
【調査/対応】
Libertyのエラー・メッセージを見ると、以下のようなメッセージが出ていました。
...
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "uk_sourcesystem"
Detail: Key (hostname, port)=(zdt02, 22) already exists.
Error Code: 0
Call: INSERT INTO ZDTTOOLS.SOURCESYSTEM (CONCURRENT_EXTRACTION_NUMBER, DESCRIPTION, HOSTNAME, PORT, TIMEZONE_ABBR, TIMEZONE_ID, TYPE, ADCD_PACKAGE_ID, USER_ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
bind => [9 parameters bound]
Query: InsertObjectQuery(ZSystem [hostname=zdt02])
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl$1.handleException(EntityManagerSetupImpl.java:787)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.handleException(AbstractSynchronizationListener.java:277)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:172)
at org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:70)
at com.ibm.tx.jta.impl.RegisteredSyncs.coreDistributeBefore(RegisteredSyncs.java:247)
at com.ibm.tx.jta.impl.RegisteredSyncs.distributeBefore(RegisteredSyncs.java:148)
at com.ibm.tx.jta.impl.TransactionImpl.prePrepare(TransactionImpl.java:1402)
at com.ibm.tx.jta.impl.TransactionImpl.stage1CommitProcessing(TransactionImpl.java:793)
at com.ibm.tx.jta.impl.TransactionImpl.processCommit(TransactionImpl.java:768)
... 85 more
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.5.v20191016-ea124dd158): org.eclipse.persistence.exceptions.DatabaseException
...
PostgreSQL上のDBにソースとなるシステム情報を管理していて、そのレコードをインサートしようとしたがキーがかぶるものが既にあるのでそこでエラーになっているようです。最初に操作を失敗した時の情報がゴミとして残っていてそれが悪さをしているようにみえます。(エラー時の削除処理がうまく働いていない様子。)
Libertyの構成情報を確認。
...
<!-- ZD&T EE persistence data source -->
<dataSource id="postgresDS" jndiName="jdbc/zdttools">
<jdbcDriver javax.sql.ConnectionPoolDataSource="org.postgresql.ds.PGConnectionPoolDataSource"
javax.sql.DataSource="org.postgresql.ds.PGSimpleDataSource" javax.sql.XADataSource="org.postgresql.xa.PGXADataSource">
<library>
<fileset dir="${env.POSTGRES_DRIVER_DIR}" includes="postgresql-42.2.9.jar" />
</library>
</jdbcDriver>
<properties databaseName="${env.POSTGRES_NAME}" password="${env.POSTGRES_PASSWORD}"
portNumber="${env.POSTGRES_PORT}" serverName="${env.POSTGRES_SERVER}" user="${env.POSTGRES_USER}" />
</dataSource>
...
PostgreSQL関連の環境変数はこの辺で設定されているようです。
WLP_SKIP_UMASK=true
WLP_SKIP_MAXPERMSIZE=true
POSTGRES_SERVER=localhost
POSTGRES_PORT=5433
POSTGRES_NAME=zdtee
POSTGRES_USER=zdt
POSTGRES_PASSWORD=
POSTGRES_DRIVER_DIR=/opt/ibm/zDT/Liberty/usr/servers/zDTServer/postgresql
また、/mnt/opt_ibm/zDT/postgresql/bin/
以下に、PostgreSQLを操作するためのpsql
コマンドが導入されていました。
これを使ってDBの中身を確認してみます。
[taguchi@zdt01 /opt/ibm/zDT/Liberty/usr/servers/zDTServer]$/mnt/opt_ibm/zDT/postgresql/bin/psql -h localhost -p 5433 -U zdt -d zdtee
zdtee=# \dt zdttools.*
List of relations
Schema | Name | Type | Owner
----------+---------------------------------+-------+-------
zdttools | adcdpackage | table | zdt
zdttools | adsystem | table | zdt
zdttools | application | table | zdt
zdttools | application_component | table | zdt
zdttools | application_extraction_schedule | table | zdt
zdttools | application_extravolume | table | zdt
zdttools | application_snapshot | table | zdt
zdttools | application_tcpprofile | table | zdt
zdttools | application_volume | table | zdt
zdttools | cics_region | table | zdt
zdttools | cics_selected_csd | table | zdt
zdttools | cics_selected_group | table | zdt
zdttools | cloudplatform | table | zdt
zdttools | communication_device | table | zdt
zdttools | component | table | zdt
zdttools | component_dataset | table | zdt
zdttools | component_ddl | table | zdt
zdttools | component_group_table | table | zdt
zdttools | component_table | table | zdt
zdttools | component_volume | table | zdt
zdttools | databaseversion | table | zdt
zdttools | dataset | table | zdt
zdttools | dataset_volume | table | zdt
zdttools | db2database | table | zdt
zdttools | db2ddl | table | zdt
zdttools | db2group_table | table | zdt
zdttools | db2grouptable | table | zdt
zdttools | db2schema | table | zdt
zdttools | db2subsystem | table | zdt
zdttools | db2table | table | zdt
zdttools | deploy_dataset | table | zdt
zdttools | deploy_db2component | table | zdt
zdttools | deploysteps | table | zdt
zdttools | display_device | table | zdt
zdttools | docker_provision | table | zdt
zdttools | docker_provision_ports | table | zdt
zdttools | docker_provision_volume | table | zdt
zdttools | docker_provision_zvolume | table | zdt
zdttools | docker_system | table | zdt
zdttools | docker_system_credentials | table | zdt
zdttools | emulatorstate | table | zdt
zdttools | ftpsystem | table | zdt
zdttools | licensingsystem | table | zdt
zdttools | linux_deploy_volume | table | zdt
zdttools | privilegecommandoption | table | zdt
zdttools | provision_request | table | zdt
zdttools | provision_workflow | table | zdt
zdttools | role | table | zdt
zdttools | sourcesystem | table | zdt
zdttools | system_application | table | zdt
zdttools | targetnewvolume | table | zdt
zdttools | targetsystem | table | zdt
zdttools | tcpipinterface | table | zdt
zdttools | tokensystem | table | zdt
zdttools | user | table | zdt
zdttools | user_role | table | zdt
zdttools | volumehistory | table | zdt
zdttools | volumeimagefile | table | zdt
zdttools | zsystem_crypto | table | zdt
zdttools | zsysteminformation | table | zdt
(60 rows)
上のように、psqlで接続してスキーマ"zdttools"のテーブルをリストしてみると60テーブルありました。
エラーになっていたのはzdttools.sourcesystemというテーブルなので、その中身を見てみます。
zdtee=# select * from zdttools.sourcesystem;
id | hostname | description | type | port | timezone_id | timezone_abbr | adcd_package_id | concurrent_extraction_number | uuid | creation_time | user_id
----+----------+---------------------------------------------------+------+------+-------------+---------------+-----------------+------------------------------+--------------------------------------+----------------------------+---------
1 | 2019_11 | | 2 | 22 | | | 1 | 0 | 73724c40-0bb5-4dd8-b75d-e9ad90caa848 | 2020-10-27 00:33:49.255485 |
2 | zdt02 | Source system entry for an existing ZD&T instance | 1 | 22 | | | | 0 | d9faf39f-6366-4f7f-bf63-8fdf1bc41d29 | 2020-11-21 20:39:06.329438 |
(2 rows)
zdt02というホスト名、ポートが22となっているレコードがあります。これが残ってしまっているのがまずいのではないかと思われます。
(2019_11というホスト名のレコードも以前の操作で残ってしまったゴミのような気もしますが、影響がよくわからないのでここでは放置します。ADCD取り込むとこういうレコードできるのかもしれないし...)
zdt02のレコードを消します。
zdtee=# delete from zdttools.sourcesystem where hostname='zdt02';
DELETE 1
zdtee=# select * from zdttools.sourcesystem;
id | hostname | description | type | port | timezone_id | timezone_abbr | adcd_package_id | concurrent_extraction_number | uuid | creation_time | user_id
----+----------+-------------+------+------+-------------+---------------+-----------------+------------------------------+--------------------------------------+----------------------------+---------
1 | 2019_11 | | 2 | 22 | | | 1 | 0 | 73724c40-0bb5-4dd8-b75d-e9ad90caa848 | 2020-10-27 00:33:49.255485 |
(1 row)
zdtee=# \q
これでLibertyを再起動してリトライしたらうまくいきました。
※PostgreSQL上のテーブルも60くらいあって内部的に色々情報を管理しているようですが、内部でどういう処理がされているかはマニュアル上ほとんど記載されていませんし、ちょっとしたことで機能不全に陥る可能性があるので、Webコンソールでの操作時はパラメーター設定などなるべく慎重に行ったほうがよさそうです。