Ansibleを用いたz/OSカスタマイズ自動化 - (1) 概要/基本構成

# はじめに
インフラの構成をコードとして管理する、いわゆるIaC(Infrastructure as Code)という考え方があり、その代表的なツールとしてAnsibleというOSSがあります。最近はz/OSのインフラ操作をするためのAnsible用のモジュールも提供されるようになってきており、そのモジュールを利用することでz/OSをAnsibleの管理対象ノードとして扱うことができるようになっています。
Ansibleを用いてz/OSカスタマイズの自動化がどのように行えるのかを実際にやってみたいと思います。

## 関連記事
[Ansibleを用いたz/OSカスタマイズ自動化 - (1) 概要/基本構成](https://qiita.com/tomotagwork/items/44e6c02010c6e9025273)
[Ansibleを用いたz/OSカスタマイズ自動化 - (2) z/OS Core Collectionを試す](https://qiita.com/tomotagwork/items/2625d2d8a4a4aad6960b)
[Ansibleを用いたz/OSカスタマイズ自動化 - (3) Ansible提供モジュールを試す](https://qiita.com/tomotagwork/items/56ed181a209648b1e053)
[Ansibleを用いたz/OSカスタマイズ自動化 - (4) 雑多な考察](https://qiita.com/tomotagwork/items/ffd488a8e6e0f9e3b6d6)


# Ansibleについて
簡単にAnsibleについて補足しておきます。詳細は専門のドキュメントなどをご参照ください。
参考: [Ansible Documentation](https://docs.ansible.com/ansible/latest/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/3489409f-d3ac-dd25-b966-5590e8dab77d.png)

Ansibleを使ってインフラ構成を管理する場合、Control Nodeという管理用のサーバーを立ててそこから各サーバーを管理することになります。Ansible(Control Node)により管理される対象のサーバーはManaged Nodeと呼ばれます。

Control NodeはAnsibleを導入、セットアップをし、具体的にどのような構成を行うかを示したPlaybookと呼ばれる定義(yaml)を保持しています。Control Nodeから各Mnaged Nodeに対してこのPlyabookに従った指示を送ることで構成に関する操作(ユーザーの作成やS/Wのインストールなど)が行われます。

Control NodeからManaged Nodeに対してPlabook実行を行う時の動作イメージについて補足しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/6fd11316-e650-a0fb-4e37-728af65fd925.png)

参考: [Ansible architecture - Modules](https://docs.ansible.com/ansible/latest/dev_guide/overview_architecture.html#modules)
>Ansible works by connecting to your nodes and pushing out scripts called “Ansible modules” to them. Most modules accept parameters that describe the desired state of the system. Ansible then executes these modules (over SSH by default), and removes them when finished. Your library of modules can reside on any machine, and there are no servers, daemons, or databases required.


Ansibleは基本的にSSH経由でControl NodeからManaged Nodeの管理を行います。また、Ansible提供のモジュールはPythonをベースに作成されているため実行環境としてPythonが必要になります。
つまり、前提として以下のようなS/Wの構成が必要になります。

- **Control Node**: Ansible, Python, SSH Client
- **Managed Node**: SSH Server, Python

Control NodeからPlaybookを実行すると基本的には以下のような操作が行われることになります。

1. Playbookに記述された操作を行うためのモジュールを、管理対象のノードにSSH経由で転送
2. Managed Node側で転送されたモジュール(Pythonベース)を実行しPlaybookに記載された構成を行う
2. 転送されたモジュールを削除

<font color="red">
※Managed Node側にはAnsible固有のコンポーネントをインストールする必要は無く、SSHやPythonなどの一般的に広く使用されているコンポーネントのみあればよいというのが特筆すべき点です。
</font>

# z/OSのAnsible対応について

昨今ではAnsibleの管理対象としてz/OSを扱うことができるようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/db83c61b-45cf-1d87-2783-423d24b5f17a.png)

Control Nodeとしては別途Linuxなどのオープン系サーバーを用意する必要があります(z/OS上にControl Nodeは立てられない)。あくまでManaged Nodeとしてz/OSをAnsibleの管理対象に加えることができるという位置づけです。

z/OSをAnsibleから管理するためのモジュール群がいくつかの"Collection"という形で提供されています。これらのCollectionを使用することでAnsibleのPlaybookを用いてz/OS構成の管理が行えることになります。
例えば以下のようなCollectionが提供されています。

- **IBM z/OS core collection**: z/OSの基本的な構成管理用のモジュールを提供(JCL SubmitやMVSコマンド実行など)
- **IBM z/OS Management Facility (z/OSMF) collection**: WorkflowやProvisioningなどz/OSMF提供機能を利用するためのモジュールを提供
- **IBM z/OS CICS collection**: CICSの操作を行うためのモジュールを提供
- **IBM z/OS IMS collection**: IMSの操作を行うためのモジュールを提供

参考: [Red Hat Ansible Certified Content for IBM Z](https://ibm.github.io/z_ansible_collections_doc/)

これらのCollectionは、Ansible Galaxyのサイトから無償で入手できます。
[Ansible Galaxy - z/OS関連collection](https://galaxy.ansible.com/ui/namespaces/ibm/?sort=name&keywords=z%2Fos&page=1)

Managed Nodeとしてのz/OSについては、前述の通り基本的にはSSH Server, Pythonがあればよいですが、使用するCollectionによっては追加コンポーネントが必要になってきます。
例えば、z/OS管理の基本的な操作を行うためのz/OS core collectionとしては、ZOAU(IBM Z Open Automation Utility)を使用することが前提となっているため、追加でZOAUの導入/セットアップが必要になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/eada8b1c-74d4-5043-e6db-085a9942d3d7.png)

<font color="red">ここで示しているIBM z/OS core collectionに必要なz/OS側コンポーネント "SSH Server", "Python", "ZOAU" はいずれも追加ライセンス不要ですので、追加のS/Wコスト無しで利用することができます。ステキです！</font>


# 環境構築
さて、ここからは実際に環境を構築してAnsibleによるz/OS構成管理をどのように行うことができるのかを見ていきたいと思います。

## 全体像

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/627ff9d3-4506-0415-48d4-8a95b8a5050c.png)

今回のテスト環境では、Windows11上のWSL(Ubuntu)にAnsibleを導入/セットアップしてControl Nodeとして使用します。
管理対象のz/OSは、IBM Cloud上のWazi as a Serviceというz/OSの仮想サーバーを使用します。

**Control Node**:
Ubuntu 20.04.6 LTS (Focal Fossa)
Python: 3.11.8
Ansible: 2.15.9
IBM z/OS core collection: 1.8.0

**Managed Node**:
z/OS V2.5
Python: 3.11.4
ZOAU: 1.2.4.5

※各Collectionの細かな前提条件などは以下のサイトも要確認
[Requirements](https://ibm.github.io/z_ansible_collections_doc/requirements/requirements.html)
[Releases - z/OS Core collection](https://ibm.github.io/z_ansible_collections_doc/ibm_zos_core/docs/source/release_notes.html)

※Collectionのバージョン間非互換については、後続記事でも少し触れていますのでご参考まで。
[雑多な考察 - z/OS Core Collectionのバージョンについて](https://qiita.com/tomotagwork/items/ffd488a8e6e0f9e3b6d6#zos-core-collection%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)

## z/OS側 (管理対象ノード)

Wazi as a ServiceのStock Imageを使用する場合、SSH Server, Python, ZOAUは一通りセットアップ完了した状態の環境が提供されますので、ここではこれらのコンポーネントはセットアップ済みの前提とします。

各コンポーネントのセットアップについては以下が参考になるかと思います。

参考
**SSH**:
[z/OS 2.5 - Setting up the sshd daemon](https://www.ibm.com/docs/en/zos/2.5.0?topic=administrators-setting-up-sshd-daemon)
**Python**:
[Qiita: Python for z/OS のインストール](https://qiita.com/tomotagwork/items/effd08fa9b70f0e99213)
[IBM Open Enterprise SDK for Python 3.11 - Installing and configuring the pax format](https://www.ibm.com/docs/en/python-zos/3.11?topic=configuration-installing-configuring-pax-format)
**ZOAU**:
[Qiita: ZOAUのインストール](https://qiita.com/tomotagwork/items/57ebd1a2a7d4931f9603)
[Z Open Automation Utilities 1.2.x - Installing and configuring ZOAU](https://www.ibm.com/docs/en/zoau/1.2.x?topic=installing-configuring-zoau#install-zoau-python-apis-optional)
※以下のステップは(Optional)となっていますが、AnsibleのモジュールはPythonベースでPythonからZOAUを使用することになるのでこのステップも実施する必要があります。
[Install ZOAU Python APIs (optional)](https://www.ibm.com/docs/en/zoau/1.2.x?topic=installing-configuring-zoau#install-zoau-python-apis-optional)

USS上での確認

```
IBMUSER : /u/ibmuser : > echo $PATH
/usr/lpp/skrb/bin:/usr/sbin:/usr/bin:/bin:/sbin:/usr/lpp/db2d10/base/bin:/usr/lpp/java/java8/current/bin:/usr/lpp/IBM/cobol/igyv6r4/bin:/usr/lpp/IBM/pli/v6r1/bin:/usr/lpp/IBM/cyp/v3r11/pyz/bin:/usr/lpp/IBM/zoautil/bin:/usr/lpp/db2d10/jdbc/bin:/usr/lpp/java/java8/J8.0_64/bin:/usr/lpp/IBM/dbb/bin:/rsusr/ported/bin:/usr/lpp/IBM/cnj/njsc/bin:/usr/lpp/IBM/cnj/IBM/node-latest-os390-s390x/bin/:/usr/lpp/IBM/cvg/v1r19/go/bin

IBMUSER : /u/ibmuser : > echo $LIBPATH
/usr/lpp/IBM/cyp/v3r11/pyz/lib:/lib:/usr/lib:.:/usr/lpp/IBM/zoautil/lib:/usr/lpp/db2d10/jdbc/lib:/usr/lpp/db2d10/jdbc/lib:/usr/lpp/IBM/dbb/lib:/rsusr/ported/lib:/rsusr/ported/lib/perl5/5.24.0/s390/CORE


IBMUSER : /u/ibmuser : > python --version
Python 3.11.4

IBMUSER : /u/ibmuser : > zoaversion
2023/08/14 16:09:19 CUT V1.2.4.5 0800b632 3493 PH56007 921 8caa8747
```

補足: 
Pythonのインストール・パス: /usr/lpp/IBM/cyp/v3r11/pyz/
ZOAUのインストール・パス: /usr/lpp/IBM/zoautil/

## Ansible Controlノード

### バージョン選択
Ansibleのパッケージの名前とかバージョニングとかインストール方法などが結構分かりにくいです。基本的にはansible-coreというパッケージをインストールすればよさそう。
ansible-coreとpythonの依存関係や、ansible-coreと使用したいcollectionの依存関係などもあるので、その辺りはサポートされるバージョンの組み合わせを確認する必要があります。

今回はIBM z/OS core collectionを使用する想定です。

[Red Hat Ansible Certified Content for IBM Z - Requirement - Control Node](https://ibm.github.io/z_ansible_collections_doc/requirements/requirements.html#control-node)
>All IBM z/OS collections are either Ansible Automation Platform Certified Content (AAP) or undergoing certification. Thus, the supported versions of Ansible align with the AAP Life Cycle which currently is Ansible versions 2.9 - 2.15. For support, the controller must use the supported version of Ansible and when applicable the collections dependencies. Review the Ansible Automation Platform Certified Content to determine which versions of Ansible a collection is supporting.

[Ansible Galaxy - ibm.ibm_zos_core V1.8.0](https://galaxy.ansible.com/ui/repo/published/ibm/ibm_zos_core/docs/?version=1.8.0)
>Ansible version compatibility
This collection has been tested against Ansible Core versions >=2.14. The Ansible Core versions supported for this collection align to the ansible-core support matrix. Review the Ansible community changelogs for corresponding Ansible community packages and ansible-core.

基本的にはAnsible 2.9-2.15がサポートされるようですが、今回使用するIBM z/OS core collection V1.8.0(2024年3月時点での最新) はAnsible 2.14以降でテストされているもののようですので、2.14以降が安全でしょう。
ここではAnsible V2.15を使用することにします。

AnsibleとPythonのバージョンの依存関係も注意する必要があります。

[ansible-core support matrix](https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html#ansible-core-support-matrix)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/3b5f3e18-018d-73ff-24b2-8d6bd831d938.png)

Ansible V2.15を使用する場合、Control Node側のPythonバージョンは3.9-3.11、Managed Node(Target)側のPythonバージョンは2.7,3.6-3.12が必要ということになります。

ここでは、Managed Nodeに合わせてPython V3.11を使用することにします。

### Pythonインストール
Ubuntuの標準のリポジトリでは3.9までしか無いようでした。PPA(Personal Package Archive)として提供されているものがありましたが、あくまで公式ではないので自己責任で利用する必要があります。

この辺の記事を参考に...
参考: [Python3.11をインストール（WSL2 Ubuntu22.04）](https://qiita.com/lilacs/items/fbc1682e86dc58010298)

今回はテスト目的なので一旦こちらを参考にPython3.11をインストールしてみます。(3.9でもサポートされるはずですが)

以下の手順でPythonをインストールします。

```xxx:リポジトリ追加
$ sudo add-apt-repository ppa:deadsnakes/ppa
$ sudo apt update
```

```xxx:インストール
$ sudo apt install python3.11
```

```xxx:確認
$ python3.11 -V
Python 3.11.8
```

以下を参考にpip(Pythonのパッケージ管理システム)をインストールする
参考: [pip documentation v24.0 - Installation - get-pip.py](https://pip.pypa.io/en/stable/installation/#get-pip-py)

```xxx:get-pip.pyダウンロード
$ wget https://bootstrap.pypa.io/get-pip.py
```

```xxx:pipインストール
$ sudo python3.11 get-pip.py
```

```xxx:確認
$ pip -V
pip 24.0 from /home/user01/.local/lib/python3.11/site-packages/pip (python 3.11)
```


### Ansibleインストール

バージョンを指定してインストールする場合にはpipを使用してインストールする必要があるらしい。

以下を参考にAnsibleをインストールします。
参考: [Installing and upgrading Ansible with pip](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#pip-install)

```xxx:事前確認
$ python3.11 -m pip -V
pip 24.0 from /home/user01/.local/lib/python3.11/site-packages/pip (python 3.11)
```

```xxx:バージョン指定でansible-coreインストール
$ python3.11 -m pip install --user ansible-core==2.15.9
```

```xxx:確認
$ ansible --version
ansible [core 2.15.9]
  config file = /home/user01/.ansible.cfg
  configured module search path = ['/home/user01/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/user01/.local/lib/python3.11/site-packages/ansible
  ansible collection location = /home/user01/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/user01/.local/bin/ansible
  python version = 3.11.8 (main, Feb 25 2024, 16:41:26) [GCC 9.4.0] (/usr/bin/python3.11)
  jinja version = 3.1.3
  libyaml = False
```

※`~/.local/bin`以下にインストールされるので、PATHを通しておく必要があります。

## SSH接続構成

先に示した通りControl NodeからManaged Nodeを管理する際にはSSHの通信が行われることになりますので、Control NodeからManaged Nodeに対してSSH接続が行えるようにしておく必要があります。
具体的には、SSH接続用のユーザーをManaged Node側に用意しControl Node側には認証情報を準備しておくことになります。
ここでは、鍵認証によりSSH接続を行うことを想定します。一般的な鍵認証でSSH接続できる設定をすればよいです。

参考: [マルチ・プラットフォームを扱うインフラ屋さんのための連携技術: SSH編 - 公開鍵認証](https://qiita.com/tomotagwork/items/b35aa09c1aa1acb3d554#%E5%85%AC%E9%96%8B%E9%8D%B5%E8%AA%8D%E8%A8%BC)

今回はWazi aaSのStock Imageを使用する想定なので、IBMUSERをSSH接続ユーザーとすることとします。Private KeyはWazi aaSのインスタンス作成時に作成したものがそのまま使用できます。

## その他の構成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/25deb740-6c2a-4f8f-42ba-7ac3f124ed7a.png)

この辺りは必須の構成ではありませんが、PlaybookやAnsibleの構成ファイルなどはGitのRepositoryで管理しておくと、バージョン管理や複数ユーザーでのメンテナンスがやりやすくなるのでお勧めです。Control Node上にGit Clientを入れてGit Serverと連携できるようにしておくとよいでしょう。
また、Git管理やPlaybookの編集作業についてはVS Codeから操作できるようにしておくと便利です。WSLおよびRemote DevelopmentのExtensionを入れることでUbuntu上のリソースをVS Codeから利用できるようになります。
参考: [Linux 用 Windows サブシステムで Visual Studio Code の使用を開始する](https://learn.microsoft.com/ja-jp/windows/wsl/tutorials/wsl-vscode)

# シンプルなPlaybookを試してみる

基本的な構成ファイルと単純なPlaybookを含むGitHubリポジトリを以下に用意しました。

[GitHub Repository - tomotagwork/my_ansible_zos_sample](https://github.com/tomotagwork/my_ansible_zos_sample)

※リポジトリのトップのディレクトリにてansibleの各種操作を行うことを想定した構成となっています。オペレーションをする時のカレント・ディレクトリに注意してください。

## 各ファイルの補足

上のRepositoryに含まれるファイルを補足します。

### ansible.cfg

参考: [Ansible Configuration Settings](https://docs.ansible.com/ansible/latest/reference_appendices/config.html)

ansible関連の基本的な構成ファイルです。
上のガイドにあるように、構成ファイルは以下の順番で選択されます。

- 環境変数 `ANSIBLE_CONFIG`に指定されたファイル
- カレント・ディレクトリの`ansible.cfg`ファイル
- `~/.ansible.cfg`
- `/etc/ansible/ansible.cfg`

今回は環境変数を設定していない想定で、2つめのカレント・ディレクトリ下のansible.cfgファイルを使う想定です。すなわち、ローカル・リポジトリのディレクトリ下でPlaybook実行のコマンドを実行することで、リポジトリに含まれるansible.cfgが使われるということになります。

```ansible.cfg
[defaults]
inventory = inventory.yml
collections_paths = ./
```

補足:
- `inventory = inventory.yml`: inventoryファイル(管理対象のノードを記述するファイル)を示す
- `collections_paths = ./`: collectionのパス

### inventory.yml

参考: [Build Your Inventory](https://docs.ansible.com/ansible/latest/network/getting_started/first_inventory.html)

管理対象(ここではz/OS)の接続情報を指定します。

```inventory.yml
all:
  children:
    ungrouped: {}
    zos:
      hosts:
        <name>:
          ansible_host: xxx.xxx.xxx.xxx
          ansible_port: 22
          ansible_user: IBMUSER
          ansible_ssh_private_key_file: "~/.ssh/ssh_private_key.pem"
```

補足: 
- `<name>`: ansible上でハンドリングするターゲット環境(z/OS)の名前
- `ansible_host: xxx.xxx.xxx.xxx`: ターゲット環境(z/OS)のIPアドレスorホスト名
- `ansible_port: 22`: ターゲット環境(z/OS)がListenしているSSHポート番号
- `ansible_user: IBMUSER`: SSH接続ユーザー
- `ansible_ssh_private_key_file: "~/.ssh/ssh_private_key.pem"` : SSH接続ユーザーの認証に使用するPrivate Key

### ホストごとの環境変数ファイル

Ansibleでは管理対象のホストごと、グループごと、全体で共通のもの、など、様々な単位で環境変数を設定する仕組みが提供されています。ここではホスト単位に環境変数を設定するために、host_vars/以下にホスト名のyamlファイルを作成しています。

```host_vars/hostname.yml
PYZ: "/usr/lpp/IBM/cyp/v3r11/pyz"
ZOAU: "/usr/lpp/IBM/zoautil"
ansible_python_interpreter: "{{ PYZ }}/bin/python3"

environment_vars:
  _BPXK_AUTOCVT: "ALL"
  ZOAU_HOME: "{{ ZOAU }}"
  PYTHONPATH: "{{ PYZ }}/lib"
  LIBPATH: "{{ ZOAU }}/lib:{{ PYZ }}/lib:/lib:/usr/lib:."
  PATH: "{{ ZOAU }}/bin:{{ PYZ }}/bin:/bin:/var/bin"
  _CEE_RUNOPTS: "FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)"
  _TAG_REDIR_ERR: "txt"
  _TAG_REDIR_IN: "txt"
  _TAG_REDIR_OUT: "txt"
  LANG: "C"
  _BPX_SHAREAS: "YES"
  _BPX_BATCH_SPAWN: "YES"
```

補足
- `PYZ: "/usr/lpp/IBM/cyp/v3r11/pyz"`: ターゲット環境(z/OS)のPythonのインストール・パス
- `ZOAU: "/usr/lpp/IBM/zoautil"`: ターゲット環境(z/OS)のZOAUのインストール・パス
- `ansible_python_interpreter: "{{ PYZ }}/bin/python3"`: ターゲット環境(z/OS)のPythonプログラムのパス

### requirements.yml

z/OS関連のcollectionはAnsible GalaxyというAnsibleコミュニティーが作成したサイトから入手できます。Ansible GalaxyからCollectionを入手するには、ansibleにバンドルされている`ansible-galaxy`というコマンドが利用できます。この時必要なcollectionはrequirements.ymlというファイルで管理することができます。

```requirements.yml
---
collections:
- name: ibm.ibm_zos_core
  version: 1.8.0
```

今回作成したリポジトリに含まれるサンプルのPlaybookでは、IBM z/OS core collectionのV1.8.0を使用する想定となっていますので、そのcollectionの定義をrequirements.ymlに指定しています。

ローカル・リポジトリのディレクトリ(requirements.ymlがあるディレクトリ)で、以下のansible-galaxyコマンドを実行することで、requirements.ymlに指定されているIBM z/OS core collectionがインストールされることになります。

```sh
$ ansible-galaxy install -r requirements.yml
```

※Collectionは、ansible.cfgのcollections_pathsで指定したパス(`./`)つまり、ローカル・リポジトリのディレクトリ下の`ansible_collections`以下にインストールされることになります。

### サンプルPlaybook

sample/zos_operator.ymlに、単純なサンプルのPlaybookファイルがあります。

```yml:sample/zos_operator.yml
- name: submit a zos command
  hosts: ezdwazi04 
  environment: "{{ environment_vars }}"
  gather_facts: no
  
  tasks:
    - name: envvars
      debug:
        msg: "environemt_variables are {{ environment_vars }}"
        
    - name: execute an operator command
      ibm.ibm_zos_core.zos_operator:
        cmd: "D T"
      register: tmp_result
      changed_when: False

    - name: display results
      debug: 
        msg: "command output {{ tmp_result }}"
```

`hosts: ezdwazi04` という指定をしているので、このPlaybookはezdwazi04というホストに対して操作を実行することになります。inventory.ymlで管理対象ホストの名前(`<name>`)を変更した場合はそれに合わせて修正してください。
` environment: "{{ environment_vars }}"`の指定により、`host_vars/<name>.yml`から環境変数が読み込まれます。

このPlaybookは以下の3つのタスクから構成されています。

- **envvars**: 適用されている環境変数を出力します(デバッグ目的)
- **execute an operator command**: `D T`という時刻表示のためのMVSコマンドを実行し、結果を`tmp_result`変数に格納します
- **display results**: `tmp_result`変数に格納された値(`D T`コマンドの結果)を出力します

2つめのタスクのMVSコマンドを実行するところで、IBM z/OS core collectionが提供する`zos_operator`というモジュールを使用しています。

参考: [z/OS core collection - zos_operator](https://galaxy.ansible.com/ui/repo/published/ibm/ibm_zos_core/content/module/zos_operator/)

## Playbook実行

実際に上のサンプルPlaybookを実行してみます。

### 1. Ansibleコントロール・ノード上に当リポジトリをクローン

適当なディレクトリで以下のコマンドを実行します。

```sh
git clone https://github.com/tomotagwork/my_ansible_zos_sample.git
```

### 2. 前提となるCollectionをインストール

上で作成されたローカル・リポジトリのディレクトリ下で、以下のコマンドを実行します。

```sh
ansible-galaxy install -r requirements.yml
```

結果としてローカル・リポジトリのディレクトリ下のansible_collections以下に必要なcollectionがインストールされます。

### 3. 接続に関する設定をカスタマイズ

inventory.yml, host_vars/xxx.ymlファイルをカスタマイズします。
また、必要に応じてplaybook(`sample/zos_operator.yml`)のhosts指定(操作対象のホスト名)をinventoryに合わせて修正します。

### 4. サンプルのPlaybookを実行

ローカル・リポジトリのトップのディレクトリに移動し、念のためバージョン、構成ファイルのパスなどを確認しておきます。

```sh
$ ansible --version
ansible [core 2.15.9]
  config file = /home/user01/Ansible/VSCode_workspace/my_ansible_zos_sample/ansible.cfg
  configured module search path = ['/home/user01/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/user01/.local/lib/python3.11/site-packages/ansible
  ansible collection location = /home/user01/Ansible/VSCode_workspace/my_ansible_zos_sample
  executable location = /home/user01/.local/bin/ansible
  python version = 3.11.8 (main, Feb 25 2024, 16:41:26) [GCC 9.4.0] (/usr/bin/python3.11)
  jinja version = 3.1.3
  libyaml = False
```

ローカル・リポジトリのトップのディレクトリにて以下のコマンドを実行し、サンプルのPlaybook "zos_operator.yml"を実行。

```sh
ansible-playbook sample/zos_operator.yml 
```

実行結果例

```
$ ansible-playbook sample/zos_operator.yml

PLAY [submit a zos command] *********************************************************************************************************************************************

TASK [envvars] **********************************************************************************************************************************************************
ok: [ezdwazi04] => {
    "msg": "environemt_variables are {'_BPXK_AUTOCVT': 'ALL', 'ZOAU_HOME': '/usr/lpp/IBM/zoautil', 'PYTHONPATH': '/usr/lpp/IBM/cyp/v3r11/pyz/lib', 'LIBPATH': '/usr/lpp/IBM/zoautil/lib:/usr/lpp/IBM/cyp/v3r11/pyz/lib:/lib:/usr/lib:.', 'PATH': '/usr/lpp/IBM/zoautil/bin:/usr/lpp/IBM/cyp/v3r11/pyz/bin:/bin:/var/bin', '_CEE_RUNOPTS': 'FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)', '_TAG_REDIR_ERR': 'txt', '_TAG_REDIR_IN': 'txt', '_TAG_REDIR_OUT': 'txt', 'LANG': 'C', '_BPX_SHAREAS': 'YES', '_BPX_BATCH_SPAWN': 'YES'}"
}

TASK [execute an operator command] **************************************************************************************************************************************
ok: [ezdwazi04]

TASK [display results] **************************************************************************************************************************************************
ok: [ezdwazi04] => {
    "msg": "command output {'changed': False, 'rc': 0, 'elapsed': 1.02, 'content': ['VS01       2024070  07:06:07.00             ISF031I CONSOLE IBMU0000 ACTIVATED', 'VS01       2024070  07:06:07.00            -D T ', 'VS01       2024070  07:06:07.00             IEE136I LOCAL: TIME=07.06.06 DATE=2024.070  UTC: TIME=11.06.06 DATE=2024.070'], 'cmd': 'D T', 'wait_time_s': 1, 'failed': False}"
}

PLAY RECAP **************************************************************************************************************************************************************
ezdwazi04                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
```

z/OS上で実行された`D T`コマンドにより時刻情報が出力されました。
これで、IBM z/OS core collection提供モジュールを使用しAnsible Playbookからz/OSの操作を行う一連の流れを確認することができました。

# Tips

## 環境変数PYTHONPATH

上の例はWazi aaSのStock Imageを使用した場合の実行例です。
これとは別にZOAU、Pythonなどを導入した実z/OS環境をManaged NodeとしてAnsible Playbookを実行した時に、以下のようなエラーが出ることがありました。
```
TASK [execute an operator command] ***************************************************************************************************************************************************************************
The authenticity of host 'eplex1 (xx.xx.xx.xx)' can't be established.
ECDSA key fingerprint is SHA256:0/eNszUHfkn71nt6dQjuZ+fyJo04IH95pjsB6Yoa8E8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
fatal: [eplex1]: FAILED! => {"changed": false, "msg": "An unexpected error occurred: ImportError('ZOAU is not properly configured for Ansible. Unable to import zoautil_py. Ensure environment variables are properly configured in Ansible for use with ZOAU.')"}
```

メッセージ抜粋:
>ZOAU is not properly configured for Ansible. Unable to import zoautil_py. Ensure environment variables are properly configured in Ansible for use with ZOAU

この環境は、IDz付属のZOAUをSMP/Eで導入しています。この時、ZOAU Python API用のカスタマイズとして、[PYTHONPATH environment method](https://www.ibm.com/docs/en/zoau/1.2.x?topic=installing-configuring-zoau#pythonpath-environment-method) の手順を実行しています(SMP/Eによるインストールだとwhlファイルが提供されていなかったため)。
ZOAUがこの構成場合、host_vars/xxx.ymlにてPYTHONPATH環境変数にZOAUのlibを追加することで上のエラーは回避できました。

```yaml:xxx.yml
PYZ: "/usr/lpp/IBM/cyp/v3r11/pyz"
ZOAU: "/usr/lpp/IBM/zoautil"
ansible_python_interpreter: "{{ PYZ }}/bin/python3"

environment_vars:
  _BPXK_AUTOCVT: "ALL"
  ZOAU_HOME: "{{ ZOAU }}"
  PYTHONPATH: "{{ PYZ }}/lib:{{ ZOAU }}/lib"
...
```

※このようにZOAUのPython API用の構成によってPYTHONPATH環境変数指定方法が変わる可能性がありますのでご注意ください。