zaki work log

作業ログやら生活ログやらなんやら

[NetBox] AnsibleのNetBoxモジュールを使ってVMやIPアドレス情報を登録

以前REST APIを使った入力を試したけど、今回はAnsibleのNetboxモジュールを使った入力について。

docs.ansible.com

準備

pynetbox のインストール

NetBoxをAnsibleから操作する場合は、基本的に(全部チェックしたわけじゃないけどたぶん)全てpynetboxモジュールが必要。
pipでインストールする。

$ pip install pynetbox

無いとエラー。

TASK [create vm sample] *******************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ModuleNotFoundError: No module named 'pynetbox'
failed: [localhost] (item=k8s-master01) => changed=false 
  ansible_loop_var: item
  item: k8s-master01
  msg: Failed to import the required Python library (pynetbox) on cloud-dev's Python /home/zaki/src/ansible-sample/venv/a2.10/bin/python3. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter

netbox.netboxコレクション

Ansible 2.10のフルセット(pip install ansibleでインストールした場合)はNetBoxのコレクションが含まれるので追加インストールは不要。
Ansible 2.10をansible-baseでインストールした場合、また、Ansible 2.9の場合は、netbox.netboxコレクションが追加で必要なのでansible-galaxyでインストールする。

ansible-galaxy collection install netbox.netbox

galaxy.ansible.com

Playbookサンプル

全部をチェックしたわけじゃないけど、VMの作成を試してみた限りでは「REST APIをAnsibleモジュールでラッピングしている」感じ。
なので、RESTを使った操作をチェックすればAnsibleモジュールの使い方もそのまま行ける。

ただ、RESTと違ってIDでなくVM名とかをそのまま使うことができてわかりやすい。
また、既にある場合はokとなって冪等な処理になり、VM名はそのままで例えばstatusを変更すれば「更新」動作になるので使い勝手は良い。

APIエンドポイントとトーク

各モジュールで共通して以下のパラメタが用意されている。

  • netbox_url
  • netbox_token

書いてみればすぐわかるけど、さらにdataといパラメタに、モジュールに対するパラメタ(つまりNetBoxへ操作を行いたいパラメタ)を指定していく。
基本的にNetBoxのweb上の画面とモジュールのドキュメントのExampleを見比べれば使い方は雰囲気でわかるはず。

VM作成

docs.ansible.com

    - name: create vm sample
      netbox.netbox.netbox_virtual_machine:
        netbox_url: "{{ netbox_url }}"
        netbox_token: "{{ netbox_token }}"
        data:
          name: "{{ item }}"
          cluster: vm network
      with_items:
        - k8s-master01

RESTだと必須だったclusterはドキュメントにはRequired設定されてないが、やっぱり必須。

clusterを指定しなかったらこの通り。

TASK [create vm sample] *******************************************************
failed: [localhost] (item=k8s-master01) => changed=false 
  ansible_loop_var: item
  item: k8s-master01
  msg: '{"cluster":["This field is required."]}'

clusterを指定(RESTの場合と異なり、clusterのIDでなくcluster名の文字列を指定)して実行すればこの通り。

(a2.10) [zaki@cloud-dev netbox (master)]$ ansible-playbook sample.yml -v
Using /home/zaki/src/ansible-sample/netbox/ansible.cfg as config file
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] **************************************************************

TASK [create vm sample] *******************************************************
changed: [localhost] => (item=k8s-master01) => changed=true 
  ansible_loop_var: item
  item: k8s-master01
  msg: virtual_machine k8s-master01 created
  virtual_machine:
    cluster: 3
    comments: ''
    config_context: {}
    created: '2021-01-13'
    custom_fields: {}
    disk: null
    id: 7
    last_updated: '2021-01-13T13:54:24.961868Z'
    local_context_data: null
    memory: null
    name: k8s-master01
    platform: null
    primary_ip: null
    primary_ip4: null
    primary_ip6: null
    role: null
    site: 1
    status: active
    tags: []
    tenant: null
    url: http://192.168.0.19:28080/api/virtualization/virtual-machines/7/
    vcpus: null

PLAY RECAP ********************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

VM情報が登録されたのち、同じPlaybookで再実行するとokになり変化しない。

(a2.10) [zaki@cloud-dev netbox (master)]$ ansible-playbook sample.yml -v
Using /home/zaki/src/ansible-sample/netbox/ansible.cfg as config file
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] **************************************************************

TASK [create vm sample] *******************************************************
ok: [localhost] => (item=k8s-master01) => changed=false 
  ansible_loop_var: item
  item: k8s-master01
  msg: virtual_machine k8s-master01 already exists
  virtual_machine:
    cluster: 3
    comments: ''
    config_context: {}
    created: '2021-01-13'
    custom_fields: {}
    disk: null
    id: 7
    last_updated: '2021-01-13T13:54:24.961868Z'
    local_context_data: null
    memory: null
    name: k8s-master01
    platform: null
    primary_ip: null
    primary_ip4: null
    primary_ip6: null
    role: null
    site: 1
    status: active
    tags: []
    tenant: null
    url: http://192.168.0.19:28080/api/virtualization/virtual-machines/7/
    vcpus: null

PLAY RECAP ********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

(a2.10) [zaki@cloud-dev netbox (master)]$ 

以下についてもRESTのときとまったく同じ要領。
ただし前述の通り、IDでなく名前を指定する。

インベントリ変数やvarsなどで変数化しておけば、Primary設定のための「VM情報の更新」を行うnetbox_virtual_machineモジュール再実行も上記リンク先のサンプルのように簡単にできるはず。

Clusterの作成

せっかくなのでVM作成のパラメタのClusterも作成してみる。
Clusterの作成にはCluster Typeが必須なので、これもセットで作る。

作成に使用するパラメタをYAMLで変数定義しておく。

    cluster: vm network
    cluster_type:
      name: ESXi
      slug: esxi

これに対して、「Cluster Type作成 (netbox_cluster_type)」と「Cluster作成 (netbox_cluster)」が順に実行されるようにplaybookを書けばOK。

    - name: create cluster-type
      netbox.netbox.netbox_cluster_type:
        netbox_url: "{{ netbox_url }}"
        netbox_token: "{{ netbox_token }}"
        data:
          name: "{{ cluster_type.name }}"
          slug: "{{ cluster_type.slug }}"

    - name: create cluster
      netbox.netbox.netbox_cluster:
        netbox_url: "{{ netbox_url }}"
        netbox_token: "{{ netbox_token }}"
        data:
          name: "{{ cluster }}"
          cluster_type: "{{ cluster_type }}"

こんな感じ。

環境

NetBoxのバージョンはv2.10.3 (構築時と同じ)

Ansibleは以下の2パターンで確認。

Ansible 2.10

ansible 2.10.2
  config file = /home/zaki/src/ansible-sample/netbox/ansible.cfg
  configured module search path = ['/home/zaki/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/zaki/src/ansible-sample/venv/a2.10/lib64/python3.6/site-packages/ansible
  executable location = /home/zaki/src/ansible-sample/venv/a2.10/bin/ansible
  python version = 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
  • pynetbox: 5.3.0
  • netbox.netbox collections: 1.1.0

Ansible 2.9

ansible 2.9.16
  config file = /home/zaki/src/ansible-sample/netbox/ansible.cfg
  configured module search path = ['/home/zaki/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/zaki/src/ansible-sample/venv/2.9/lib64/python3.6/site-packages/ansible
  executable location = /home/zaki/src/ansible-sample/venv/2.9/bin/ansible
  python version = 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
  • pynetbox: 5.3.1
  • netbox.netbox collections: 2.0.0

あれ?いつのまにか2.0.0になってた。

サンプルコード

github.com


今回は「基本的に」が多いな。。触ってみたモジュールはだいたい同じ使い勝手だったけど、使い方が全く違うものが有るかもしれないし無いかもしれない(^^;


RESTを使った場合はこちら。

zaki-hmkc.hatenablog.com