てくなべ (tekunabe)

ansible / network automation / 学習メモ

【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 バージョンでそのモジュールが使えるかどうか、など。 この記事では、対応バージョンの確認方法と、バージョンの切り替え方法を説明します。

[2019/07/08 追記] 以下のようにドロップダウンリストでバージョンが選択できるようになりました。

f:id:akira6592:20190708170455p:plain:w300


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

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 までツッコミいただければ幸いです。

【Ansible】 junos モジュール使用時にエラー "'NoneType' object has no attribute 'startswith'" になる場合の対処

■ 現象

junos_command や junos_config モジュールを netconf 接続で使用時に、Playbook などの書き方の不備により

fatal: [172.16.0.1]: FAILED! => {"msg": "'NoneType' object has no attribute 'startswith'"}

というエラーになってしまうことがあります。 (Ansible 2.6.1/ 2.6.2 で確認)

  • playbook
- hosts: junos
  gather_facts: no

  tasks:
    - name: test
      junos_config:
        lines:
          - set system ntp server 10.0.0.123

  vars:
    ansible_connection: netconf
    ansible_user: testuser
    ansible_ssh_pass: testpass
  • インベントリファイル
[junos]
172.16.0.1
  • 実行結果(エラー)
(ansible262) [vagrant@centos7 vagrant]$ ansible-playbook -i inventory junos_26.yml

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

TASK [command test] ************************************************************************
fatal: [172.16.0.1]: FAILED! => {"msg": "'NoneType' object has no attribute 'startswith'"}
        to retry, use: --limit @/vagrant/junos_26.retry

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


■ 対処 (ansible_network_os: junos を指定)

公式ドキュメントに記載があるようにansible_network_os という変数に junos をセットします。

  • Playbook
- hosts: junos
  gather_facts: no

  tasks:
    - name: test
      junos_config:
        lines:
          - set system ntp server 10.0.0.123

  vars:
    ansible_connection: netconf
    ansible_network_os: junos     # 追加
    ansible_user: testuser
    ansible_ssh_pass: testpass

一方、junos_command モジュールと network_cli コネクションタイプ(netconfではなく)の組み合わせで、この ansible_network_os 変数の指定を忘れると

fatal: [172.16.0.1]: FAILED! => {"msg": "Unable to automatically determine host network os. Please manually configure ansible_network_os value for this host"}

という親切なエラーメッセージが表示されるので、エラーハンドリングが甘めになっているのかも知れません。

なお、現在開発中の Ansible 2.7 で ansible_network_os を指定せずに junos_config モジュールを試した場合、親切なエラーメッセージが表示され・・るのではなく、正常に設定変更できてしまいました。(本エントリ執筆時点)

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

■ はじめに

現在開発中の Ansible 2.7 (develブランチ) で、ネットワーク機器への 参照系コマンドを実行するモジュール cli_command が登場したことを知りました。

Ansible 2.7 の ROADMAP を眺めていたときにモジュール名だけは見たことがあったのですが、実際に devel にマージされたようなので、Junos と IOS で試した結果を記載します。

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

基本情報

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

cli_command - Run a cli command on cli-based network devices — Ansible Documentation

対応プルリク

github.com

コード (cli_command.py)

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

※現在(2018/8/7)開発中のため、仕様が変わる可能性があります。後日確認時点で、リストで指定する commands オプションから、文字列で指定する command オプションに変更されています。詳細は、公式ドキュメントをご参照ください。


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

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

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



■ Juniper Junos で試す

インベントリファイル

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

[junos]
172.16.0.1

Playbook

今回は、show version コマンドの結果を画面に表示するだけの、以下の Playbook を用意します。 ポイントは、コネクションタイプに network_cli を指定するところです。通常の、Junos に対しては、netconf を指定して、NETCONF で接続することが多いかと思いますが、 cli_command モジュールは netconf には対応していません。 他、ansible_network_os 変数も(私が)忘れがちですが、指定します。

- hosts: junos
  gather_facts: no

  tasks:
    - name: command test
      cli_command:
        commands:
          - show version
      register: result

    - name: debug 
      debug:
        msg: "{{ result.stdout_lines[0] }}"

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

実行

無事に実行され、 show version の結果が表示されました。

(ansible27) [vagrant@centos7 vagrant]$ ansible-playbook -i inventory junos_27.yml

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

TASK [command test] ********************************************************************
ok: [172.16.0.1]

TASK [debug] ***************************************************************************
ok: [172.16.0.1] => {
    "msg": [
        "Hostname: vsrx1",
        "Model: firefly-perimeter",
        "JUNOS Software Release [12.1X47-D15.4]"
    ]
}

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

なお、ansible_connection: netconf を指定した場合は、以下のエラーになります。

connection type netconf is not valid forthis module



Cisco IOS で試す

インベントリファイル

Junosのときと同様、変数は Playbook 内で定義することにします。

[ios]
172.16.0.2

Playbook

- hosts: ios
  gather_facts: no

  tasks:
    - name: command test
      cli_command:
        commands:
          - show version
      register: result

    - name: debug 
      debug:
        msg: "{{ result.stdout_lines[0] }}"

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

実行

無事に実行され、 show version の結果が表示されました。

(ansible27) [vagrant@centos7 vagrant]$ ansible-playbook -i inventory ios_27.yml

PLAY [ios] *******************************************************************************************************************

TASK [command test] **********************************************************************************************************
ok: [172.16.0.2]

TASK [debug] *****************************************************************************************************************
ok: [172.16.0.2] => {
    "msg": [
        "Cisco IOS XE Software, Version 16.08.01a",
        "Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.8.1a, RELEASE SOFTWARE (fc1)",
        "Technical Support: http://www.cisco.com/techsupport",
        "Copyright (c) 1986-2018 by Cisco Systems, Inc.",
        "Compiled Tue 03-Apr-18 18:43 by mcpre",
        (...略...)
    ]
}

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



■ Junos も IOS もまとめて試す

お気づきかもしれませんが、前述の Junos 向け Playbook と、IOS 向け Playbook の差分は、 hostsansible_network_os しかありません。そのため、変数定義の方法を工夫することで、Playbook は1つにまとめる事ができます。

準備するファイルは、インベントリファイル、変数ファイル、Playbook です。

イベントリファイル

[junos]
172.16.0.1

[ios]
172.16.0.2

変数ファイル

  • group_vars/junos.yml
ansible_connection: network_cli
ansible_network_os: junos
ansible_user: testuser
ansible_ssh_pass: testuserpass
  • group_vars/ios.yml
ansible_connection: network_cli
ansible_network_os: ios
ansible_user: testuser
ansible_ssh_pass: testuserpass

もっと工夫の余地がありますが、あまりファイル数が増えてもサンプルとして見通しが悪くなるため、この辺にしておきます。

Playboook

前述のプラットフォーム別の Playbook との違いは hosts: all にしたことと、変数定義をしなくなったことです。 これでプラットフォーム固有の記述はなくなりました。

- hosts: all
  gather_facts: no

  tasks:
    - name: command test
      cli_command:
        commands:
          - show version
      register: result

    - name: debug 
      debug:
        msg: "{{ result.stdout_lines[0] }}"

実行

1つの Playbook で Junos、IOS の両方の show version コマンドの結果を表示することができました。

(ansible27) [vagrant@centos7 vagrant]$ ansible-playbook -i inventory all_27.yml

PLAY [all] ************************************************************************************

TASK [command test] ***************************************************************************
ok: [172.16.0.1]
ok: [172.16.0.2]

TASK [debug] **********************************************************************************
ok: [172.16.0.2] => {
    "msg": [
        "Cisco IOS XE Software, Version 16.08.01a",
        "Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.8.1a, RELEASE SOFTWARE (fc1)",
        "Technical Support: http://www.cisco.com/techsupport",
        "Copyright (c) 1986-2018 by Cisco Systems, Inc.",
        "Compiled Tue 03-Apr-18 18:43 by mcpre",
        (...略...)
    ]
}
ok: [172.16.0.1] => {
    "msg": [
        "Hostname: vsrx1",
        "Model: firefly-perimeter",
        "JUNOS Software Release [12.1X47-D15.4]"
    ]
}

PLAY RECAP *********************************************************************************
172.16.0.1                 : ok=2    changed=0    unreachable=0    failed=0
172.16.0.2                 : ok=2    changed=0    unreachable=0    failed=0


■ まとめ

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

社内技術イベントで「無料で仮想Junos環境を手元に作ろう」という発表をしました

はじめに

弊社では年に数回、AP Tech Fest という社内向けの技術イベントを開催しています。(参考:2017年11月開催分

大体毎回何かしらの発表しているのですが、2018/07/18 開催分では「無料で仮想Junos環境を手元に作ろう」という発表をしました。

資料

最初から資料を社外公開できる内容で作っているので、資料を公開します。

www.slideshare.net

以下のエントリの内容をベースにしています。

tekunabe.hatenablog.jp

発表しようと思った経緯

4月からの新人研修で Cisco IOS を使ってCCNAや実機研修をされているところは多いと思いますが、実際業務についたら IOS以外を扱うことも多いです。例えば Juniper(Junos) を業務で使うことになって、自分でも勉強したいけど環境をどう作ったらよいか悩んでいる人向けに発表しました。時期としてもちょうどよいと思いましたので。

参考

www.ap-com.co.jp