てくなべ

ネットワーク、自動化などの技術的なことを書いていきます。Ansible、StackStorm等

Ansible 2.7 で導入予定のネットワークモジュール cli_configを試す

■ はじめに

現在開発中の Ansible 2.7 (develブランチ) で、ネットワーク機器への 設定系 コマンドを投入するモジュール cli_config が登場しました。

なお、同じく Ansible 2.7 で開発中の 参照系 コマンドを実行するモジュール cli_command については過去記事「Ansible 2.7 で導入予定のネットワークモジュール cli_configを試す」をご参照ください。

この記事では、Junos で試した結果を記載します。

基本情報

cli_command モジュール 公式ドキュメント

cli_config - Push text based configuration to network devices over network_cli — Ansible Documentation

コード (cli_command.py)

ansible/cli_config.py at devel · ansible/ansible · GitHub

※現在(2018/8/14)開発中のため、仕様が変わる可能性があります。


■ 準備(開発版 Ansible のインストール)

pip install git+https://github.com/ansible/ansible.git@devel

現在、これで開発中の Ansible 2.7 がインストールされます。



■ Juniper Junos で試す

インベントリファイル

以下のインベントリファイルを用意します。今回は各変数は Playbook 内で定義することにします。

[junos]
172.16.0.1

Playbook(netconf指定で失敗パターン)

今回は、単純に set system ntp server 10.0.0.123 の1行を投入する Playbook を試すことにします。 junos_config モジュールの lines オプションはリストで指定できるのに対して、 cli_config モジュールの config オプションは文字列での指定になる点は注意が必要です。

コネクションプラグインには、junos_config モジュールと同じ調子で netconf を試してみます。(後述しますが失敗します)

- hosts: junos
  gather_facts: no

  tasks:
    - name: config test
      cli_config:
        config: set system ntp server 10.0.0.123

  vars:
    ansible_connection: netconf
    ansible_network_os: junos
    ansible_user: testuser
    ansible_ssh_pass: testuserpsss

実行(netconf指定で失敗パターン)

おっと、エラーになってしまいました。

(ansibledev) [vagrant@centos7 vagrant]$ ansible-playbook -i inventory cli_config.yml

PLAY [junos] **********************************************************************************************

TASK [config test] ****************************************************************************************
fatal: [172.16.0.1]: FAILED! => {"changed": false, "msg": "Connection type netconf is not valid for cli_config module"}
        to retry, use: --limit @/vagrant/cli_config.retry

PLAY RECAP ************************************************************************************************
172.16.0.1                 : ok=0    changed=0    unreachable=0    failed=1

どうやら、このモジュールは netconf コネクションプラグインは対応していないようです。

後で気がついたのですが、ドキュメントにきちんと

This module provides platform agnostic way of pushing text based configuration to network devices over network_cli connection plugin.

という記載がありました。

となれば、次に試すべきは network_cli コネクションプラグインなので試してみます。

Playbook(network_cli指定で成功パターン)

- hosts: junos
  gather_facts: no

  tasks:
    - name: config test
      cli_config:
        config: set system ntp server 10.0.0.123

  vars:
    ansible_connection: network_cli    # network_cli にしてみる
    ansible_network_os: junos
    ansible_user: testuser
    ansible_ssh_pass: testuserpsss

実行(network_cli指定で成功パターン)

今度は正常に完了しました。

(ansibledev) [vagrant@centos7 vagrant]$ ansible-playbook -i inventory cli_config.yml

PLAY [junos] **********************************************************************************************

TASK [config test] ****************************************************************************************
changed: [172.16.0.1]

PLAY RECAP ************************************************************************************************
172.16.0.1                 : ok=1    changed=1    unreachable=0    failed=0

念の為、Junos側で設定が入ったことを確認します。

root@vsrx1# show system ntp | display set
set system ntp server 10.0.0.123

無事に入りました。


■ まとめ

簡単ですが、 cli_config モジュールの動作を確認しました。 最近のネットワークモジュールは、プラットフォームに依存しないタイプ(内部で ansible_network_os変数を見てプラットフォーム固有モジュールを呼ぶ?)も増えてきており、 cli_config モジュールもその流れだと思います。

ネットワークモジュールとしては、cli_configcli_command モジュールの登場が Ansible 2.7 の特徴の一つと言えるでしょう。

【Ansible】ping 系モジュールまとめ(ping/win_ping/ios_ping/nxos_ping/net_ping)

Ansible には ping モジュールや net_ping モジュールなど、モジュール名に ping が含まれるものがいくつかあります。 名前は似ていますが、どこからどこへの ping なのか、何のプロトコルを使うのか、などの点で性質が異なります。

例えば、 公式ドキュメントの ping モジュールの説明には

For Network targets, use the net_ping module instead.

とありますが、net_ping モジュールは ping モジュールとは用途や性質が異なり、代わりにはならず混乱してしまうのではないかと思い、一旦以下にまとめます。

モジュール名 from to プロトコル 補足
ping コントロールホスト ターゲットホスト コネクションプラグインに依存(*1)
win_ping コントロールホスト ターゲットホスト WinRM
ios_ping ターゲットホスト dest オプション指定先 ICMP Cisco IOSping コマンドを生成して、ターゲットホスト上で実行する
nxos_ping ターゲットホスト dest オプション指定先 ICMP Cisco NX-OS の ping コマンドを生成して、ターゲットホスト上で実行する
net_ping ターゲットホスト dest オプション指定先 ICMP ansible_network_os 変数に応じて、ios_pingnxos_ping モジュールを利用する
  • *1 : ping モジュールのプロトコルについて
    • 利用するコネクションプラグインに依存します
      • ssh: sshPython スクリプトを送って実行できるか
      • network_cli: SSH でネットワーク機器に接続できるか
      • netconf: NETCONF でネットワーク機器に接続できるか

参考

【Ansible】when はタスクの最後に指定しなくても良い

(このツイートのブログ版です)

■ はじめに

Ansible の Playbook では、特定の条件を満たすときのみそのタスクを実行するという指定に when が利用できます。

上記のサンプルでもタスクの最後に when を指定していて、Web上などの他のサンプルでも最後に指定しているものが多い印象があります。 ですが、実際は YAML 的にはマッピング(ディクショナリ)なので、順番にどこでも大丈夫です。以下にパターンを記載します。

■ タスクの最後に when を指定する例

よくあるパターンです。大丈夫です。

---
- hosts: junos
  gather_facts: no

  tasks:
    - junos_command:
        commands:
          - show version
      when: true == true    # ここに書くサンプルが多い

■ タスクの最初に when を指定する例

---
- hosts: junos
  gather_facts: no

  tasks:
    - when: true == true    # ここでもOK
      junos_command:
        commands:
          - show version

コードの if分のイメージに近いでしょうか。

if true == true:
  do_something()

■ タスクの途中に when を指定する例

途中でも大丈夫です。

- hosts: junos
  gather_facts: no

  tasks:
    - name: commandtest
      when: true == true    # ここでもOK
      junos_command:
        commands:
          - show version

■ 注意点

この記事は「こう書いても動く」ということを示すのみであり、特にどれが推奨という意図はありません。 プロジェクト指定の書き方や、慣例に合わせるなどの事情に従っていただければと思います。

【Ansible】junos_facts でバージョン情報が取得できない場合の対処

■ はじめに

Ansible には junos_facts という Juniper Junos の機器のファクトを収集するモジュールがあります。

通常であれば、 ansible_net_version または、 ansible_facts.net_version という変数で、Junos のバージョンを取得できるのですが、(そそらく)古いバージョンの Junos の場合は取得できません。

この記事では、どうにかして取得する方法をご紹介します。

動作確認環境: Ansible 2.6.2

junos_facts モジュールの gather_subest オプションで ofacts を指定できる Ansible 2.6.2以上のバージョンである必要があります。 )


■ 正常に取得できる場合

Junos の 15.1F4.15 というバージョンでの確認です。

  • Playbook
- hosts: junos
  gather_facts: no
  
  tasks:
    - junos_facts:

    - name: ansible_net_version
      debug: var=ansible_net_version

    - name: ansible_facts.net_version
      debug: var=ansible_facts.net_version

  vars:
    ansible_connection: netconf
    ansible_network_os: junos
    ansible_user: testuser
    ansible_ssh_pass: testpass
  • 実行
TASK [ansible_facts.net_version] ***********************************************
ok: [172.16.0.15]] => {
    "msg": "15.1F4.15"
}

TASK [ansible_net_version] *****************************************************
ok: [172.16.0.15] => {
    "msg": "15.1F4.15"
}

無事にバージョン情報が取得できました。


■ 取得できない場合

一方、Junos の 12.1X47-D15.4 というバージョンでの確認です。(vsrxのvagrant box

先ほどと同じ Playbook を実行します。

  • 実行
TASK [ansible_facts.net_version] ***********************************************
ok: [172.16.0.1] => {
    "msg": ""
}

TASK [ansible_net_version] *****************************************************
ok: [172.16.0.1] => {
    "msg": null
}

空文字や null になってしまいました。

対策

junos_facts モジュールの、どのようなファクトを取得するか指定するオプション gather_subsetofacts を指定します。

この指定により「old style facts」(ドキュメント上の表記)を取得できるようになります。このオプションのデフォルトは ['!config', '!ofacts'] なので、ofacts は含まれません。(!は否定表現)

また、この ofacts を取得する場合は、 junos_facts モジュールに provider オプションによる、認証情報の指定が必要になります。Ansible 2.5 からこの指定方法は推奨はされていませんが、制約がある以上は仕方なしとします。

- hosts: junos
  gather_facts: no
  
  tasks:
    - name: gather junos facts
      junos_facts:
        gather_subset: ofacts    # point!
        provider:
            host: "{{ inventory_hostname }}"
            username: "{{ ansible_user }}"
            password: "{{ ansible_ssh_pass }}"

    - name: ansible_facts.version
      debug:
        msg: "{{ ansible_facts.version }}"

  vars:
    ansible_connection: netconf
    ansible_network_os: junos 
    ansible_user: testuser
    ansible_ssh_pass: testpass
  • 実行
TASK [ansible_facts.version] ******************************************************************
ok: [172.16.0.1] => {
    "msg": "12.1X47-D15.4"
}

無事、ansible_facts.version という変数名で Junos のバージョン情報が取得できました。

注意点

ansible_version と ansible_facts.version が別物に

Ansible 2.5 で ファクト は ansible_facts.* という名前空間でも参照できるようになりました。 https://www.ansible.com/blog/ansible-2.5-traveling-space-and-time

そのため、通常であれば ansible_hogehogeansible_facts.hogehoge は同じ値になるはずですが、今回のケースでは、

  • ansible_version にはコントロールノードの Ansible のバージョン情報
  • ansible_facts.version には Junos のバージョン情報

が入り、異なるものになります。

【Ansible】公式ドキュメントの対応バージョンの確認と切り替え方法

■ はじめに

Ansible の調べ物をしていて、モジュールの説明ページなどを見るときは、そのドキュメントの対応バージョンを気にするようにしています。 使っている Ansible バージョンでそのモジュールが使えるかどうか、など。 この記事では、対応バージョンの確認方法と、バージョンの切り替え方法を説明します。


■ 対応バージョンの確認方法

f:id:akira6592:20180809102127p:plain

ドキュメントの左上に 2.6 などと、対応バージョンが書いてあります。

devel と書いある場合は、今でいうと開発中の 2.7 のことです。(10月リリース予定

もし、諸事情で開発中のバージョンを使いたいときは、

pip install git+https://github.com/ansible/ansible.git@devel

でインストールできます。


■ 対応バージョンの切り替え方法

その1: トップページから切り替える方法

ドキュメントトップのメニューの Previous Version からバージョンを切り替えることができます。

その2: URLを書き換えて切り替える方法

例えば、

https://docs.ansible.com/ansible/latest/modules/ios_command_module.html

というURLの場合、 latest のところを書き換えると、バージョンを切り替える事ができます。

  • 指定例(2018/8/9現在)
    • devel: 2.7
    • latest: 2.6
    • 2.6: 2.6
    • 2.5: 2.5

モジュール説明ページのURLを書き換えた結果、 Not Found になるのであれば、そのバージョンにはそのモジュールが無いということになります。 (ページ内に書いてある New in version 2.7. といった記載で判断するのが手っ取り早いです)

例えば、

https://docs.ansible.com/ansible/devel/modules/vmware_deploy_ovf_module.html

devel (2.7) を latest (2.6) に書き換えて、

https://docs.ansible.com/ansible/latest/modules/vmware_deploy_ovf_module.html

を表示したときに、Not Found になるのは、 2.6 にそのモジュールがないためです。

注意点

Ansible 2.4 から 2.5 になったタイミングで、ドキュメントの階層が変わりました。 そのため、これらのバージョンをまたいで切り替えるときは注意が必要です。

【Ansible】net_get モジュールで SCP でコンフィグをバックアップする

■ はじめに

Ansible 2.6 で SCP/SFTP でネットワーク機器とファイルを送受信する net_get モジュールと、 net_put モジュール ができました。 このうち、この記事ではファイルを受信する net_get モジュールを使って、Cisco IOSstartup-config のバックアップを、Anislbe ホストにファイルとしてバックアップしてみたいと思います。 (Ansible 2.6.2 で確認)


■ 準備

IOS

予め IOS 側で SSH のほかに、SCP を有効にします。

ip scp server enable

Ansible ホスト側

Python (Ansible) で SCP するためのパッケージをインストールします。

pip install scp


■ Playbook

- hosts: ios
  gather_facts: no

  tasks:
    - name: scp test
      net_get:
        src: startup-config
        dest: ios_startp-config.txt

  vars:
    ansible_connection: network_cli
    ansible_network_os: ios
    ansible_user: testuser
    ansible_ssh_pass: testpass

■ インベントリファイル

必要な変数はすべて Playbook 側で定義済みです

[ios]
172.16.0.2


■ 実行

Playbook を実行します。

(ansible262) [vagrant@centos7 vagrant]$ ansible-playbook -i inventory net_get.yml 
PLAY [ios] ***************************************************************************

TASK [scp test] **********************************************************************
changed: [172.16.0.2]

PLAY RECAP ***************************************************************************
172.16.0.2                : ok=1    changed=1    unreachable=0    failed=0

無事に実行されました。

■ 確認

Ansible ホスト側で、ファイルが保存されたか確認します。

(ansible262) [vagrant@centos7 vagrant]$ cat ios_startp-config.txt

!
! Last configuration change at 12:24:10 UTC Tue Aug 7 20
18 by testuser
!
version 16.8
service timestamps debug datetime msec
service timestamps log datetime msec
platform qfp utilization monitor load 80
no platform punt-keepalive disable-kernel-core
platform console virtual
!
hostname RouterA

(...略...)

無事に保存されました。


■ まとめ

コンフィグをファイルとしてバックアップするだけでしたら、 ios_command モジュール や、ios_facts モジュール でも可能ですが、事情により、プラットフォーム非依存のモジュール(ansible_network_os 変数の定義は必要ですが)を利用したい場合は、この方法もありかと思います。

【StackStorm】様々な Pack の更新状況をWebで確認する

StackStorm には Ansible や Zabbix、Slackなどのツールと連携するための Pack という機能単位があり、StackStorm Exchange というサイトで一覧が確認できます。

新しい Pack が追加されたときは公式ブログで紹介されるので気がつけるのですが、既存の Pack の機能追加は気がつけません。

どうしたら気がつけるかなと思ったのですが、私は StackStorm Exchange pack index のリポジトリv1/pack 配下の History を直接確認するのが良いかなと思いました。

こちらです。

github.com

この一覧で、どの Pack で何かしらの更新があったことがわかります。 機能の追加があったかも知れませんし、メタ情報の更新だけもしれません。

詳細を確認したいタイトルをクリックします。例えば、以下の Update slack pack をクリックします。 f:id:akira6592:20180807164728p:plain

すると、差分が表示され、パッと見で Actionの数が113から143に増えたことがわかります。何が増えたかは更に下を見ればわかりそうです。 f:id:akira6592:20180807164927p:plain

よさそうな機能追加があれば、Packのインストールなり、アップデートなりをすると良いと思います。


他にもっと良い方法があれば twitter: @akira6592 までツッコミいただければ幸いです。