Ansibleのmodule_utilsに追加されたVMware REST Clientを使ってみる

Ansibleのmodule_utilsにVMwareのREST Clientモジュールが追加されてたのでREST Clientを使ったモジュールを作ってみました。

# 1. REST Clientモジュール

[https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/vmware_rest_client.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/vmware_rest_client.py)

# 2. REST Clientを動かすには？

module_utilsに追加されたモジュールを動かすには `VMware vSphere Automation SDK for Python` が必要です。

[VMware vSphere Automation SDK for Python](https://github.com/vmware/vsphere-automation-sdk-python)

# 3. VMware vSphere Automation SDK for Pythonドキュメント

vCenterとのやりとりをする場合は以下のドキュメントを参照ください。

[https://vdc-download.vmware.com/vmwb-repository/dcr-public/3f9d46be-a5f4-452c-8b1c-ae2bb05bc0a6/58d6917d-4da9-45b1-869a-f68550834f8e/vsphere/index.html](https://vdc-download.vmware.com/vmwb-repository/dcr-public/3f9d46be-a5f4-452c-8b1c-ae2bb05bc0a6/58d6917d-4da9-45b1-869a-f68550834f8e/vsphere/index.html)

# 4. 開発環境

|   項目  |  バージョン   |
|---------|---------------|
| vCenter | 6.5.0 7119157 |
| python  | 2.7.13        |
| ansible | 2.7.0dev0     |
| RHEL    | 7.5           |

# 5. インストール

## 5-1. パッケージインストール

(1) RHELのリポジトリから必要なパッケージをインストールします。

```bash
[root@localhost ~]# subscription-manager repos --enable rhel-server-rhscl-7-rpms
[root@localhost ~]# yum -y install python27-python-pip git gcc python27-python-devel
```

(2) インストールしたpipを有効化します。

```
[root@localhost ~]# scl enable python27 bash
```

## 5-2. Ansibleインストール

(1) 今回はdevelリポジトリのものを使用します。gitからリポジトリをcloneします。

```bash
[root@localhost ~]# git clone https://github.com/ansible/ansible.git
```

(2) ansibleをインストールします。

```bash
[root@localhost ~]# cd ansible
[root@localhost ansible]# python setup.py install
```

以下のエラーが発生した場合はpipでアップグレードします。

`RuntimeError: cryptography requires setuptools 18.5 or newer, please upgrade to a newer version of setuptools`

```bash
[root@localhost ansible]# pip install --upgrade setuptools
```

## 5-3. VMware vSphere Automation SDK for Pythonインストール

(1) gitからリポジトリをcloneします。

```bash
[root@localhost ~]# git clone https://github.com/vmware/vsphere-automation-sdk-python.git
```

(2) VMware vSphere Automation SDK for Pythonをインストールします。

```bash
[root@localhost ~]# cd vsphere-automation-sdk-python
[root@localhost vsphere-automation-sdk-python]# pip install --upgrade --force-reinstall -r requirements.txt --extra-index-url file://`pwd`/lib
```

# 6. Ansibleモジュール作成

## 6-1. 簡単な動作確認

例として、簡単なVM情報を取得するモジュールを作成してみます。

### 6-1-1. vmware_rest_client_testモジュール

```python
#!/usr/bin/python
#-*- coding: utf-8 -*-
from ansible.module_utils.vmware_rest_client import VmwareRestClient
from ansible.module_utils.basic import AnsibleModule
from com.vmware import vcenter_client

def main():
    result = dict(changed=False)
    argument_spec = VmwareRestClient.vmware_client_argument_spec()
    argument_spec.update(name=dict(type="str"))

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    # vCenterへ接続
    obj = VmwareRestClient(module)
    vm_svc = vcenter_client.VM(obj.connect)

    # VM情報を取得
    vm = vm_svc.get(module.params["name"])

    # 結果
    result['r'] = vm.to_dict()
    module.exit_json(**result)

if __name__ == "__main__":
    main()
```

### 6-1-2. Playbook

```yaml
---
- name: Test
  hosts: localhost
  gather_facts: no
  tasks:
    - vmware_rest_client_test:
        hostname: vcenter.local
        username: administrator@vsphere.local
        password: secret
        validate_certs: no
        protocol: https
        name: vm-101
      register: r

    - debug: var=r
```

### 6-1-3. 実行

こんな感じに情報が取得できます。

```bash
[root@localhost devel]# ls
main.yml  vmware_rest_client_test.py
[root@localhost devel]# ansible-playbook main.yml --module-path .
 [WARNING]: Unable to parse /etc/ansible/hosts as an inventory source

 [WARNING]: No inventory was parsed, only implicit localhost is available

 [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'


PLAY [Test] ************************************************************************************************************************************

TASK [vmware_rest_client_test] *****************************************************************************************************************
ok: [localhost]

TASK [debug] ***********************************************************************************************************************************
ok: [localhost] => {
    "r": {
        "changed": false,
        "failed": false,
        "r": {
            "boot": {
                "delay": 0,
                "enter_setup_mode": false,
                "retry": false,
                "retry_delay": 10000,
                "type": "BIOS"
            },
            "boot_devices": [],
            "cdroms": [
                {
                    "key": "16000",
                    "value": {
                        "allow_guest_control": true,
                        "backing": {
                            "device_access_type": "EMULATION",
                            "type": "CLIENT_DEVICE"
                        },
                        "label": "CD/DVD drive 1",
                        "sata": {
                            "bus": 0,
                            "unit": 0
                        },
                        "start_connected": true,
                        "state": "NOT_CONNECTED",
                        "type": "SATA"
                    }
                }
            ],
            "cpu": {
                "cores_per_socket": 1,
                "count": 1,
                "hot_add_enabled": false,
                "hot_remove_enabled": false
            },
            "disks": [
                {
(snip)
}

PLAY RECAP *************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0
```

ただ、これだと `Managed Object ID` が必要でわかりにくいため `name` にはVMの名前を指定できるようにしてみます。

## 6-2. VMの情報を取得するモジュール

[vmware_vm_facts](http://docs.ansible.com/ansible/latest/modules/vmware_vm_facts_module.html#vmware-vm-facts-module) のようなモジュールをREST APIを使って作ってみます。

### 6-2-1. vmware_rest_vm_factsモジュール

コードは以下を参照ください。

[https://github.com/sky-joker/ore-ore-ansible/blob/master/modules/cloud/vmware/vmware_rest_vm_facts.py](https://github.com/sky-joker/ore-ore-ansible/blob/master/modules/cloud/vmware/vmware_rest_vm_facts.py)

```bash
[root@localhost devel]# curl -L https://raw.githubusercontent.com/sky-joker/ore-ore-ansible/master/modules/cloud/vmware/vmware_rest_vm_facts.py -O
```

### 6-2-2. Playbook

`devel` という仮想マシンの情報のみ取得する場合は以下のようにします。

```yaml
---
- name: Test
  hosts: localhost
  gather_facts: no
  tasks:
    - vmware_rest_vm_facts:
        hostname: vcenter.local
        username: administrator@vsphere.local
        password: secret
        validate_certs: no
        protocol: https
        name: devel
      register: r

    - debug: var=r
```

全てのVM情報を取得する場合は `name` を指定しません。

```yaml
---
- name: Test
  hosts: localhost
  gather_facts: no
  tasks:
    - vmware_rest_vm_facts:
        hostname: vcenter.local
        username: administrator@vsphere.local
        password: secret
        validate_certs: no
        protocol: https
      register: r

    - debug: var=r
```

# 7. 最後に

module_utilsにREST Clientが追加されたので今後はSOAPだけではなくRESTのモジュールも出てきそうですね。
現状は以下のモジュールがREST Clientを使って実装されています。

* [vmware_tag](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/cloud/vmware/vmware_tag.py)
* [vmware_tag_facts](https://github.com/ansible/ansible/blob/5c39c3b2d16acc0415de146c31c4b8ecaf01fb7d/lib/ansible/modules/cloud/vmware/vmware_tag_facts.py)