AnsibleでJUNOS(JUNiper Operating System)を操作する方法を説明します。showコマンドの出力を得たい時はjunos_commandを使用し、複数の設定を投入したい時はjunos_configを使います。その他、冪等性を担保しつつ慎重な設定を行うjunos_user, junos_systemなどのモジュールもあります。
JUNOSへの接続方法が分からない方は「Ansible操作例 – NETCONFを用いたJUNOSへの接続方法」を参照ください。
showコマンドの実行
プレイブック作成
以下のようなプレイブックを作成します。
着目して欲しいのはregister句です。Ansibleは実行結果を変数に格納する事ができ、その変数名を定義するのがregister句です。以下のプレイブックは、「show version」の実行結果を変数「junos_result」に格納し、変数「junos_result」をdebugで出力する例です。
cat << EOF > junos_show_version.yml
---
- hosts: junos
gather_facts: no
tasks:
- name: send show version
junos_command:
commands: "show version"
register: junos_results
- name: display show version
debug:
var: junos_results
EOF
戻り値の一覧
Ansibleは実行結果を変数に格納する事ができます。この実行結果をプログラミングの文脈では「戻り値」と呼ぶ事が多く、公式ドキュメントでは「Return Value」との表現を使っています。実行結果にどのような値が格納されているかは、公式ドキュメントをマニュアルを参照ください。この場合ならば、「junos command モジュール」に記載されています。

実行結果
実行結果は以下のようになります。
# ansible-playbook -i inventory.ini junos_show_version.yml
PLAY [junos] *******************************************************************
TASK [send show version] *******************************************************
ok: [junos63]
TASK [display show version] ****************************************************
ok: [junos63] => {
"junos_results": {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"failed": false,
"stdout": [
"Hostname: R63\nModel: vsrx\nJunos: 19.3R2.9\nJUNOS OS Kernel 64-bit [20191120.0ebd4bf_builder_stable_11]\nJUNOS OS libs [20191120.0ebd4bf_builder_stable_11]\nJUNOS OS runtime [20191120.0ebd4bf_builder_stable_11]\nJUNOS OS time zone information [20191120.0ebd4bf_builder_stable_11]\nJUNOS OS libs compat32 [20191120.0ebd4bf_builder_stable_11]\nJUNOS OS 32-bit compatibility [20191120.0ebd4bf_builder_stable_11]\nJUNOS py extensions [20191122.214114_builder_junos_193_r2]\nJUNOS py base [20191122.214114_builder_junos_193_r2]\nJUNOS OS vmguest [20191120.0ebd4bf_builder_stable_11]\nJUNOS OS crypto [20191120.0ebd4bf_builder_stable_11]\nJUNOS network stack and utilities [20191122.214114_builder_junos_193_r2]\nJUNOS libs [20191122.214114_builder_junos_193_r2]\nJUNOS libs compat32 [20191122.214114_builder_junos_193_r2]\nJUNOS runtime [20191122.214114_builder_junos_193_r2]\nJUNOS na telemetry [19.3R2.9]\nJUNOS Web Management Platform Package [20191122.214114_builder_junos_193_r2]\nJUNOS srx libs compat32 [20191122.214114_builder_junos_193_r2]\nJUNOS srx runtime [20191122.214114_builder_junos_193_r2]\nJUNOS srx platform support [20191122.214114_builder_junos_193_r2]\nJUNOS common platform support [20191122.214114_builder_junos_193_r2]\nJUNOS srxtvp runtime [20191122.214114_builder_junos_193_r2]\nJUNOS pppoe [20191122.214114_builder_junos_193_r2]\nJUNOS Openconfig [19.3R2.9]\nJUNOS mtx network modules [20191122.214114_builder_junos_193_r2]\nJUNOS modules [20191122.214114_builder_junos_193_r2]\nJUNOS srxtvp modules [20191122.214114_builder_junos_193_r2]\nJUNOS srxtvp libs [20191122.214114_builder_junos_193_r2]\nJUNOS srx libs [20191122.214114_builder_junos_193_r2]\nJUNOS srx Data Plane Crypto Support [20191122.214114_builder_junos_193_r2]\nJUNOS daemons [20191122.214114_builder_junos_193_r2]\nJUNOS srx daemons [20191122.214114_builder_junos_193_r2]\nJUNOS SRX TVP AppQos Daemon [20191122.214114_builder_junos_193_r2]\nJUNOS High End AppQos Daemon [20191122.214114_builder_junos_193_r2]\nJUNOS Extension Toolkit [20191122.214114_builder_junos_193_r2]\nJUNOS Phone-home [20191122.214114_builder_junos_193_r2]\nJUNOS Juniper Malware Removal Tool (JMRT) [1.0.0+20191122.214114_builder_junos_193_r2]\nJUNOS J-Insight [20191122.214114_builder_junos_193_r2]\nJUNOS Online Documentation [20191122.214114_builder_junos_193_r2]\nJUNOS jail runtime [20191120.0ebd4bf_builder_stable_11]\nJUNOS FIPS mode utilities [20191122.214114_builder_junos_193_r2]"
],
"stdout_lines": [
[
"Hostname: R63",
"Model: vsrx",
"Junos: 19.3R2.9",
"JUNOS OS Kernel 64-bit [20191120.0ebd4bf_builder_stable_11]",
"JUNOS OS libs [20191120.0ebd4bf_builder_stable_11]",
"JUNOS OS runtime [20191120.0ebd4bf_builder_stable_11]",
"JUNOS OS time zone information [20191120.0ebd4bf_builder_stable_11]",
"JUNOS OS libs compat32 [20191120.0ebd4bf_builder_stable_11]",
"JUNOS OS 32-bit compatibility [20191120.0ebd4bf_builder_stable_11]",
"JUNOS py extensions [20191122.214114_builder_junos_193_r2]",
"JUNOS py base [20191122.214114_builder_junos_193_r2]",
"JUNOS OS vmguest [20191120.0ebd4bf_builder_stable_11]",
"JUNOS OS crypto [20191120.0ebd4bf_builder_stable_11]",
"JUNOS network stack and utilities [20191122.214114_builder_junos_193_r2]",
"JUNOS libs [20191122.214114_builder_junos_193_r2]",
"JUNOS libs compat32 [20191122.214114_builder_junos_193_r2]",
"JUNOS runtime [20191122.214114_builder_junos_193_r2]",
"JUNOS na telemetry [19.3R2.9]",
"JUNOS Web Management Platform Package [20191122.214114_builder_junos_193_r2]",
"JUNOS srx libs compat32 [20191122.214114_builder_junos_193_r2]",
"JUNOS srx runtime [20191122.214114_builder_junos_193_r2]",
"JUNOS srx platform support [20191122.214114_builder_junos_193_r2]",
"JUNOS common platform support [20191122.214114_builder_junos_193_r2]",
"JUNOS srxtvp runtime [20191122.214114_builder_junos_193_r2]",
"JUNOS pppoe [20191122.214114_builder_junos_193_r2]",
"JUNOS Openconfig [19.3R2.9]",
"JUNOS mtx network modules [20191122.214114_builder_junos_193_r2]",
"JUNOS modules [20191122.214114_builder_junos_193_r2]",
"JUNOS srxtvp modules [20191122.214114_builder_junos_193_r2]",
"JUNOS srxtvp libs [20191122.214114_builder_junos_193_r2]",
"JUNOS srx libs [20191122.214114_builder_junos_193_r2]",
"JUNOS srx Data Plane Crypto Support [20191122.214114_builder_junos_193_r2]",
"JUNOS daemons [20191122.214114_builder_junos_193_r2]",
"JUNOS srx daemons [20191122.214114_builder_junos_193_r2]",
"JUNOS SRX TVP AppQos Daemon [20191122.214114_builder_junos_193_r2]",
"JUNOS High End AppQos Daemon [20191122.214114_builder_junos_193_r2]",
"JUNOS Extension Toolkit [20191122.214114_builder_junos_193_r2]",
"JUNOS Phone-home [20191122.214114_builder_junos_193_r2]",
"JUNOS Juniper Malware Removal Tool (JMRT) [1.0.0+20191122.214114_builder_junos_193_r2]",
"JUNOS J-Insight [20191122.214114_builder_junos_193_r2]",
"JUNOS Online Documentation [20191122.214114_builder_junos_193_r2]",
"JUNOS jail runtime [20191120.0ebd4bf_builder_stable_11]",
"JUNOS FIPS mode utilities [20191122.214114_builder_junos_193_r2]"
]
],
"warnings": [
"arguments wait_for, match, rpcs are not supported when using transport=cli"
]
}
}
PLAY RECAP *********************************************************************
junos63 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
複数コマンドの実行
プレイブック作成
複数のコマンドを同時に投入したい時はjunos_configモジュールを使用すると便利です。以下はIRBインターフェースに対してIPv4アドレスを付与する例です。
cat << EOF > junos_add_ipv4_address.yml
---
- hosts: junos
gather_facts: no
tasks:
- name: Set routed VLAN interface (RVI) IPv4 address
junos_config:
lines:
- set vlans vlan01 vlan-id 1
- set interfaces irb unit 10 family inet address 10.0.0.1/24
- set vlans vlan01 l3-interface irb.10
EOF
プレイブック実行
プレイブックを実行すると以下のように出力されます。
新しいバージョンのjunos_configモジュールはnetwork_cliによる接続を切り捨てています。新しいバージョンを使う場合はnetconfを使用ください。
# ansible-playbook -i inventory.ini junos_add_ipv4_address.yml PLAY [junos] ******************************************************************* TASK [Set routed VLAN interface (RVI) IPv4 address] **************************** ok: [junos63] PLAY RECAP ********************************************************************* junos63 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
プレイブック確認
確かにプレイブックで記載された設定が投入されている事を確認します。
admin@R63> show interfaces irb.10
Logical interface irb.10 (Index 73) (SNMP ifIndex 520)
Flags: Hardware-Down Up SNMP-Traps 0x4004000 Encapsulation: ENET2
Bandwidth: 1Gbps
Routing Instance: default-switch Bridging Domain: vlan01
Input packets : 0
Output packets: 0
Security: Zone: Null
Protocol inet, MTU: 1514
Max nh cache: 100000, New hold nh limit: 100000, Curr nh cnt: 0,
Curr new hold cnt: 0, NH drop cnt: 0
Flags: None
Addresses, Flags: Dest-route-down Is-Preferred Is-Primary
Destination: 10.0.0/24, Local: 10.0.0.1, Broadcast: 10.0.0.255
テンプレートの利用
xxx_configという名前の付くAnsibleモジュールは、多くの場合、Jinja2テンプレートによる操作を備えています。ですが、JUNOSの場合はJinja2テンプレートによる操作機能は存在しません。そもそも、JUNOSは1件ずつsetコマンドを入力する設計思想なので、テンプレートによる操作は設計思想に合いません。
手堅い設定投入
概要
Ansibleは、前述のjunos_command, junos_config以外のモジュールを使用する事を推奨しています。junos_user, junos_systemなどのモジュールが該当し、これらは「冪等性」が担保されたモジュールです。
「冪等性」とは「再実行しても得られる結果が同じ」という意味ですが、私個人の見解としては、「一般的な意味の冪等性」と「Ansibleの文脈での冪等性」はニュアンスが異なると理解しています。前述のjunos_configは何度実行しても「changed」と表示されますが、junos_user, junos_systemなどのモジュールは設定変更が発生してない場合は「ok」のみが表示されます。Ansibleの文脈での「冪等性」とは、プレイブックを何度も実行するような運用において、changeなのかokなのかが目視チェックしやすい仕組みと理解した方が良いでしょう。
例えば、以下スクリーンショットならば、ユーザは設定変更されたもののDNSはそのままである事が一目瞭然です。

プレイブック作成
ユーザとDNSサーバを設定する例を紹介します。
cat << EOF > junos_modify_junos_services.yml
---
- hosts: junos
gather_facts: no
tasks:
- name: set user password
junos_user:
name: ansible
role: super-user
encrypted_password: "{{ 'my-password' | password_hash('sha512') }}"
state: present
- name: configure name servers
junos_system:
name_servers:
- 8.8.8.8
- 8.8.4.4
EOF
プレイブック実行
プレイブックを実行すると以下のように出力されます。
# ansible-playbook -i inventory.ini junos_modify_junos_services.yml PLAY [junos] ******************************************************************* TASK [set user password] ******************************************************* changed: [junos63] TASK [configure name servers] ************************************************** changed: [junos63] PLAY RECAP ********************************************************************* junos63 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
プレイブック確認
確かにプレイブックで記載された設定が投入されている事を確認します。
admin@R63> show configuration | display set | match "user ansible" set system login user ansible uid 2001 set system login user ansible class super-user set system login user ansible authentication encrypted-password "$6$/DKkyNGOnZz30Zxp$YirlV6V3LW9Zhkg5nMkhq8bGerMoA8UAAC6wG7upHr0z3qqnilYY.XvqH3tyHGf3pysz6E5VHhzbSqZibWbjz1" admin@R63> show configuration | display set | match "name-server" set system name-server 8.8.8.8 set system name-server 8.8.4.4 admin@R63>
