チャットツールからコマンド一つでストレージパスの正常性を確認できるようにしてみた 

## 背景
当社では以前から業務の自動化/効率化を推し進ており、私の所属するクラウド設備の運用を担う部署でも各種正常性確認や復旧処理実行等をチャットツールからのコマンド一つで実施できるような環境が構築されております。現在の部署に配属されてから約1年となり、私自身も自動化について学習し、より迅速な対応ができるよな環境を整えていきたいと考え、自動化手法の学習も兼ねて1つ新たな自動化コマンドを実装してみることにしてみました。

今回、実装しようと考えたのはクラウド設備のストレージパスの正常性確認コマンドです。
ストレージ関連の障害時や作業実施時にこれまではvCenterのGUIから対象のパスについて探して状態を確認していましたが、コマンドひとつで全体のパス状態についてわかりやすい形で確認できるようにしたいと考えました。

## 利用したもの
- Ansible
- AWX
- Hubot
- Gitlab
- PowerCLI

## 仕組み
- ストレージパス情報はPowerCLIでvCenterから取得する
- ストレージパス正常性確認処理の実行はチャットツールの特定文字列(コマンド)の投稿をキックに実施する
  - チャットツールとHubotを連携させ特定文字列(コマンド)の入力があった際にAWXのテンプレートを実行
- AWXテンプレートが実行されるとAWX上の認証情報等をもとにAWXテンプレートに紐づくGitLab上のPlaybookを実行
- Playbookにより、PowerCLIスクリプト実行用コンテナを一時的に運用管理VM dev-mng01上に作成し、そのコンテナからPowerCLIスクリプトを実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917475/16504653-633f-113d-3d8e-8fa095e38582.png)


## コマンド動作フロー
1. チャットツールからコマンドを実行
1. Hubotがコマンドを検知しAWXテンプレートを実行
1. AWX上のテンプレートに紐づくplaybootが参照/実行される
1. playbookに従いPowerCLIスクリプト実行用のコンテナを作成して、PowerCLIスクリプトを実行
1. PowerCLIスクリプトによって対象のvCenterに接続しストレージパス状態を取得する
1. AWXへ取得情報を返す
1. PowerCLIスクリプト実行用コンテナを削除
1. チャットツールに結果を出力


## コマンド仕様/出力例
- コマンド仕様
  - @clBot2 storagepathchk \<pod>
    - botにメンションを付けて実行
    - \<pod>：ストレージパス情報取得対象のクラウド設備の世代を指定 

## コマンド結果出力例
|  VMHost  |  HBA  |   Active  | Dead | Standby
| ---- | ---- | ---- | ---- | ---- |
|  ホスト001   | vmhba64 | 184 | 0 | 0 |
|  ホスト002   | vmhba64 | 184 | 0 | 0 |
|  ホスト003   | vmhba64 | 184 | 0 | 0 |
|  ホスト004   | vmhba64 | 184 | 0 | 0 |
|  ホスト005   | vmhba64 | 184 | 0 | 0 |
|  ・・・   | ・・・ | ・・・ | ・・・ | ・・・ |

各ホストに対してのパスが正常(Active)なのか一目で確認することができます。

### プログラム
参考までにソースコードの一部を記載いたします。※一部情報は伏せさせていただいたおります
- Hubotスクリプト
```javascript:storagepathchk.js
module.exports = (robot) => {
    robot.respond(/storagepathchk (.*)/i, (res) => {
        var request = require('request')
        var chat = require('./chatToken.js')
        var url = 'http://***AWXのIPアドレス***/api/v2/job_templates/16/launch/'
        var pod = res.match[1].toLowerCase()
        var msg = {
            "extra_vars":
            {
                "pod": pod,
                "url": "***チャットツールIPアドレス***",
                "token": chat(res.message.room)
            }
        }
        var options = {
            url: url,
            method: "POST",
            json: msg,
            agentOptions: {
                rejectUnauthorized: false,
            }
        }
        request(options,
            function (e, response, body) {
                var jobID = body.job;
                res.send("job番号"+jobID+"(Storageとhost間のパス状態確認)を受け付けました。");
                console.log(body.related.stdout);
            }
        );
    });
}
```

- Playbook
```yml:main.yml
- name: Storage_path_check
  hosts: dev-mng01
  gather_facts: no
  vars:
    host_mount_point: ***マウントポイントのパス***
    docker_mount_point: /root/PowerCLI-Example-Scripts
    image: vmware/powerclicore:12.7
    _command: "pwsh /root/PowerCLI-Example-Scripts/storage_path_check.ps1 -POD "
    _args: "-esxi"
    server_esxi: "***コンテナ作成先ホスト***"

  tasks:
    - name: Chat_tool
      block:
        - name: messages
          set_fact:
            pod: "{{ pod }}"
          run_once: true

    - name: Storage path check
      block:
        - name: docker run
          command: "docker run --rm -it -v {{ host_mount_point }}:{{ docker_mount_point }} {{ image }} {{ _command }} {{ pod }} {{ _args }} {{ server_esxi }}"
          register: r
          run_once: true
          become: true
    
        - name: Chat_tool_response
          community.general.rocketchat:
            domain: "{{ url }}"
            token: "{{ token }}"
            protocol: http
            validate_certs: no
            msg: "{{ pod }}のストレージ～ホスト間のパスの状態一覧"
            attachments:
              - text: ""
                title: "一覧"
                fields:
                  - title: ""
                    value: "```{{ r.stdout_lines | to_nice_yaml }}```"
                    short: false
              
          run_once: true
          delegate_to: localhost
```


## 工夫点
:::note info
powerCLIの実行元をコンテナとし、コマンド実行の都度作成/削除することで、powerCLIの実行元の管理の手間を減らしました
:::

:::note info
powerCLIで取得した情報を整形し、一目で状態がわかるような結果表示としました
:::

## 終わりに
本コマンドを作成する前までは自動化のフロー/各種ツールの連携について何となく知っている程度でしたが、今回の取り組みを通してトライ＆エラーを繰り返すことで明確に理解できました。それらを理解したことで、他の処理についても自動化の構想が頭の中でより明確にできるようになったので、これからも自動化を推し進めていきたい。また、このナレッジを他のメンバーにも共有し、よりよい環境を作り上げていきたいと思います。