ヤマハ公式Ansibleモジュールでヤマハルータを操作する。（その２：モジュールの理解）

# はじめに
前回は`Ansible`の準備とヤマハ公式ページのサンプルを実行するまで行いましたが、今回は公式モジュールで何ができるかを見てみようと思います。

- 【前】[ヤマハ公式Ansibleモジュールでヤマハルータを操作する。（その１：モジュールのインストール）](https://qiita.com/sakai00kou/items/849d78ad6cc7d4e30a3e)

ヤマハ公式ページ

- [Ansibleによる運用自動化について](http://www.rtpro.yamaha.co.jp/RT/docs/ansible/index.html)
- [Ansible Galaxyヤマハコレクションページ](https://galaxy.ansible.com/yamaha_network/rtx)
- [GitHubリポジトリ](https://github.com/yamaha-network)

尚、ヤマハ公式モジュールは**1.0.0**のインストールバージョンで確認しているため、他バージョンの場合、動作が異なる場合があります

# ヤマハ公式モジュールの理解
[GitHubリポジトリの「README.md」](https://github.com/yamaha-network/ansible-collection-rtx)を見るとモジュールとしては`rtx_command`モジュールと`rtx_config`モジュールがあるそうです。
※各モジュールのパラメータは[GitHubリポジトリの「README.md」](https://github.com/yamaha-network/ansible-collection-rtx)参照

説明書きを見る限り、`rtx_command`モジュールが**非特権モードで実行可能なコマンドの実行**、`rtx_config`モジュールが**特権モードで実行可能なコマンドの実行**を行うためのモジュールのようですが、`rtx_command`で行う場合は**特権モードで実行できないというわけでは無い**ようです。

そのため、`rtx_command`モジュールで特権モードの設定を行うことも可能ですが、`ansible_become`の設定（権限昇格有無）で`false`となっていた場合の動作が異なり、`rtx_command`モジュールの場合は**一般ユーザでコマンド実行**、`rtx_config`モジュールの場合は**管理者権限に昇格できないため、コマンド失敗**となります。

また、`rtx_config`モジュールでコマンド実行した場合、`show environment`等の参照系コマンドを実行したとしても、設定のアップデートとして処理するようなので、コマンド実行結果は表示されません。

つまり、[ヤマハ公式ページの「プレイブックの作成」](http://www.rtpro.yamaha.co.jp/RT/docs/ansible/index.html)で`rtx_command`モジュールの処理で行っているような、コマンド実行結果を`register`変数に格納して、`debug`モジュールで表示させるようなことを`rtx_config`モジュールではできません。

`rtx_config`モジュールの場合、参照系コマンドのみ実行して設定の変更が無かったとしても、アップデート扱いとなってしまうため、`Ansible`実行結果は`changed`扱いとなってしまうことも注意が必要です。

以下、`rtx_command`モジュールと`rtx_config`モジュールそれぞれで`show environment`コマンドを実行した場合の`Ansible`実行結果の抜粋。

<details><summary>rtx_commandモジュールでshow_environmentを実行した場合の結果抜粋（展開して下さい）</summary><div>

```json:rtx_commandモジュールでshow_environmentを実行した場合の結果抜粋
TASK [get configuration] ********************************************************************
ok: [NVR500] => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "invocation": {
        "module_args": {
            "commands": [
                "show environment"
            ],
            "interval": 1,
            "match": "all",
            "retries": 10,
            "wait_for": null
        }
    },
    "stdout": [
        "NVR500 BootROM Ver. 1.01\nNVR500 FlashROM Table Ver. 1.00\nNVR500 Rev.11.00.38 (Fri Apr 20 08:32:26 2018)\n  main:  NVR500 ver=00 serial=XXXXXXXXX MAC-Address=XX:XX:XX:XX:XX:XX MAC-Address=XX:XX:XX:XX:XX:XX\nCPU:  16%(5sec)  10%(1min)   2%(5min)    Memory: 39% used\nPacket-buffer:   0%(small)   0%(middle)  12%(large)   0%(huge) used\nFirmware: internal  Config. file: 0  \nBoot time: 2020/05/05 12:24:01 +09:00\nCurrent time: 2021/04/04 16:23:02 +09:00\nElapsed time from boot: 334days 03:59:01\nSecurity Class: 1, FORGET: ON, TELNET: ON"
    ],
    "stdout_lines": [
        [
            "NVR500 BootROM Ver. 1.01",
            "NVR500 FlashROM Table Ver. 1.00",
            "NVR500 Rev.11.00.38 (Fri Apr 20 08:32:26 2018)",
            "  main:  NVR500 ver=00 serial=XXXXXXXXX MAC-Address=XX:XX:XX:XX:XX:XX MAC-Address=XX:XX:XX:XX:XX:XX",
            "CPU:  16%(5sec)  10%(1min)   2%(5min)    Memory: 39% used",
            "Packet-buffer:   0%(small)   0%(middle)  12%(large)   0%(huge) used",
            "Firmware: internal  Config. file: 0  ",
            "Boot time: 2020/05/05 12:24:01 +09:00",
            "Current time: 2021/04/04 16:23:02 +09:00",
            "Elapsed time from boot: 334days 03:59:01",
            "Security Class: 1, FORGET: ON, TELNET: ON"
        ]
    ]
}
```
</div></details>

<details><summary>rtx_configモジュールでshow_environmentを実行した場合の結果抜粋（展開して下さい）</summary><div>

```json:rtx_configモジュールでshow_environmentを実行した場合の結果抜粋
TASK [get environment] ********************************************************************
changed: [NVR500] => {
    "changed": true,
    "commands": [
        "show environment"
    ],
    "invocation": {
        "module_args": {
            "after": null,
            "backup": false,
            "backup_options": null,
            "before": null,
            "diff_against": null,
            "diff_ignore_lines": null,
            "intended_config": null,
            "lines": [
                "show environment"
            ],
            "match": "line",
            "parents": null,
            "replace": "line",
            "running_config": null,
            "save_when": "never",
            "src": null
        }
    },
    "updates": [
        "show environment"
    ]
}
```
</div></details>

## rtx_commandモジュールとrtx_configモジュールの違い
上記で説明した`rtx_command`モジュールと`rtx_config`モジュールの違いを以下表にまとめます。

||rtx_command|rtx_config|
|:--|:--|:--|
|ansible_become=false時の実行|一般ユーザで実行|実行失敗|
|registerの使用|使用可能|使用不可|
|参照系コマンド実行時のステータス|変更なし|変更扱い|

上記より、参照系コマンド結果の表示や、条件分岐のためにコマンド結果を取得したい場合等は`rtx_command`モジュールを使用して、設定追加・削除・変更を行う場合は`rtx_config`モジュールを使用するのが良いでしょう。

# rtx_configモジュールについて
基本的なパラメータは本家の説明を見てもらうとして、分かりづらかったパラメータについてまとめます。

- [GitHubリポジトリの「README.md」](https://github.com/yamaha-network/ansible-collection-rtx)

## after
`lines`パラメータでコマンド実行する前に行うコマンドをリスト形式で記載する。

例えば設定変更前に外部USBにコンフィグコピーしたり、設定前にVPN接続を切ったりする用途で使用する。

## before
`lines`パラメータでコマンド実行した後に行うコマンドをリスト形式で記載する。

使い方としては`after`と同じ。

## diff_against
`ansible-playbook`に`--diff`オプションを付与して実行した際の設定。

`--diff`オプションを付与した場合、実行時に差分箇所を表示してくれます。

デフォルトでは設定するコマンドと`running-config`を比較して、すでに設定されていれば`ok`ステータスで何もせず終了、設定されていなければ設定して`changed`ステータスで終了。

## intended_configとrunning_configパラメータ
`--diff`オプションを付与して実行した場合に比較対象とするファイルを指定します。

`intended_config`または`running_config`パラメータでファイルを指定する場合は`lookup`プラグインでファイルを指定する必要があります。

```yml:intended_config、running_configでのファイル指定例
intended_config: "{{ lookup('file', '/work/master.cfg') }}"
```

## save_when
設定後に保存を行うかどうかの設定。

`changed`オプションを指定した場合、設定変更された場合だけ保存されますが、`Playbook`実行時に表示される`changed`有無で判定しているわけでは無く、コンフィグ比較した結果、差分があれば保存を行う処理を行っているようです。

ただ、上述の`diff_against`の説明の通り、コンフィグ差分が無くても`changed`判定される場合があり、その場合、コンフィグ差分が無いため`save_when`の`changed`オプションで保存は行いませんが、コンフィグ自体は更新されてしまうようで、実機ログイン時に「不揮発性メモリに保存されていない設定変更があります」と表示される場合があります。

そのため、`rtx_config`モジュールを使用する場合は、常に保存する`always`にするのが良いと思います。

## src
`lines`パラメータで1つ1つコマンドを書かなくても、コマンドをまとめて記載したテキストファイルを`src`パラメータで指定することで`lines`と同様に実行できるようです。

`lines`パラメータとは排他となっているため、`src`パラメータを指定した場合は`lines`パラメータは指定できません。

また、取得したコンフィグファイルを丸ごと指定した場合、コーデックエラーが表示されたため、実際に適用したいコマンドだけ指定するのが良いでしょう。

# おわりに
使ってみた感じ、まだ不安定な点はありますが、やはり、コード化して残せるのとツールと簡単に連携できるのは良い点かと思います。

ヤマハ機器のユーザとしては継続的にモジュール開発を続けてもらえると嬉しいです。