はじめに
本記事は、前回投稿した Ansibleのcommand系ネットワークモジュールを自作した話 の続きになります。
前回のお話
前回の記事の中で、neko_command
という自作モジュールをご紹介しました。本モジュールは、ios_command
やcli_command
と同じく、ネットワーク機器でshowコマンド等を取得するためのモジュールです。
通常は、InventoryやVariableファイル内で、ansible_network_os
というパラメータにOSタイプを指定する必要があります。一方、自作モジュールではダミーの(適当な)OSタイプを指定してあげれば、OSの違いを意識することなくコマンドを取得できました。
ただし、このモジュールには以下の課題がありました。
-
ansible_network_os
で関係ないOSタイプを指定するのがイケていない。 - 汎用性に欠ける。(設定変更系のモジュールであるxxx_configで同じことをやりたい場合、もう一つ個別にモジュールを作らないといけない。)
- OS自動検出処理に時間がかかる。(1台の所要時間は30秒くらい。)
これらの内、1と2を解決するため、Connectionプラグインnetwork_cli
のコードを修正し、ansible_network_os
の値をautodetect
にすると、NetmikoによるOS自動検出を行い、ユーザがOSタイプを意識することなく既存のcli_command
やcli_config
モジュールを使えるようにしてみました。
試した環境
Ansible 「2.7.0」で動作確認しています。Ansibleは頻繁にバージョンアップが行われており、既にnetwork_cli
でも改修が入っているので、最新版で動作するかは不明です。
修正内容
修正前は、network_cli.pyの_connect
関数の冒頭で、self._network_os
がNull
(OSタイプが指定されていない)場合、「OSタイプを自動検知できないので、手動で設定して下さい」というメッセージが出てFailするようになっています。
<--中略-->
def _connect(self):
'''
Connects to the remote device and starts the terminal
'''
if not self.connected:
if not self._network_os:
raise AnsibleConnectionFailure(
'Unable to automatically determine host network os. Please '
'manually configure ansible_network_os value for this host'
)
display.display('network_os is set to %s' % self._network_os, log_only=True)
<--中略-->
この前段で、self._network_os
がautodetect
だった場合、(1) ログイン情報を取得し、(2) NetmikoでOS自動検出を行い、(3) 返ってきた値best_match
をAnsibleが使用するOSタイプに名称変換の上、self._network_os
に格納する処理を加えています。
from netmiko import ConnectHandler
from netmiko.ssh_autodetect import SSHDetect
<--中略-->
def _connect(self):
'''
Connects to the remote device and starts the terminal
'''
if not self.connected:
if self._network_os == 'autodetect':
# (1) define login information
remote_device = {
'device_type': 'autodetect',
'ip': self._play_context.remote_addr,
'username': self._play_context.remote_user,
'password': self._play_context.password,
'port' : self._play_context.port, # optional, defaults to 22
'secret': self._play_context.become_pass, # optional, defaults to ''
'verbose': False, # optional, defaults to False
}
# (2) autodetect device type
guesser = SSHDetect(**remote_device)
best_match = guesser.autodetect()
# (3) convert netmiko device name to ansible_network_os name
if best_match == 'cisco_ios':
self._network_os = 'ios'
elif best_match == 'cisco_nxos':
self._network_os = 'nxos'
elif best_match == 'cisco_asa':
self._network_os = 'asa'
elif best_match == 'cisco_xr':
self._network_os = 'iosxr'
elif best_match == 'juniper_junos':
self._network_os = 'junos'
elif best_match == 'arista_eos':
self._network_os = 'eos'
if not self._network_os:
raise AnsibleConnectionFailure(
'Unable to automatically determine host network os. Please '
'manually configure ansible_network_os value for this host'
)
display.display('network_os is set to %s' % self._network_os, log_only=True)
<--中略-->
これ以降で、修正したコードでPlaybookを実行した結果を見て行きます。
Inventoryファイル
前回同様、Cisco IOS機器test
とNX-OS機器sbx-n9kv-ao
に対して操作を行います。
[all]
test ansible_host=192.168.100.200
sbx-n9kv-ao ansible_host=sbx-nxos-mgmt.cisco.com ansible_user=admin ansible_password=Admin_1234! ansible_port=8181
[all:vars]
ansible_network_os=autodetect
ansible_connection=network_cli
ansible_user=test
ansible_password=cisco
Playbook(コマンド取得)
show versionコマンドの実行および出力を行います。
---
- hosts: all
gather_facts: no
tasks:
- name: run show command on remote devices
cli_command:
command: show version
register: result
- name: debug
debug:
msg: "{{ result.stdout_lines }}"
実行結果(コマンド取得)
いずれも問題なく結果が出力されています。
[centos@localhost ansible]$ ansible-playbook -i inventory202 playbook1-2.yml
PLAY [all] *******************************************************************************************************************************************************************
TASK [run show command on remote devices] ************************************************************************************************************************************
ok: [test]
ok: [sbx-n9kv-ao]
TASK [debug] *****************************************************************************************************************************************************************
ok: [test] => {
"msg": [
"Cisco IOS XE Software, Version 03.17.02.S - Standard Support Release",
"Cisco IOS Software, CSR1000V Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 15.6(1)S2, RELEASE SOFTWARE (fc1)",
"Technical Support: http://www.cisco.com/techsupport",
"Copyright (c) 1986-2016 by Cisco Systems, Inc.",
"Compiled Mon 06-Jun-16 22:04 by mcpre",
<--中略-->
]
}
ok: [sbx-n9kv-ao] => {
"msg": [
"Cisco Nexus Operating System (NX-OS) Software",
"TAC support: http://www.cisco.com/tac",
"Documents: http://www.cisco.com/en/US/products/ps9372/tsd_products_support_series_home.html",
"Copyright (c) 2002-2018, Cisco Systems, Inc. All rights reserved.",
"The copyrights to certain works contained herein are owned by",
"other third parties and are used and distributed under license.",
"Some parts of this software are covered under the GNU Public",
"License. A copy of the license is available at",
"http://www.gnu.org/licenses/gpl.html.",
"",
"Nexus 9000v is a demo version of the Nexus Operating System",
"",
"Software",
" BIOS: version ",
" NXOS: version 9.2(1)",
" BIOS compile time: ",
" NXOS image file is: bootflash:///nxos.9.2.1.bin",
" NXOS compile time: 7/17/2018 16:00:00 [07/18/2018 00:21:19]",
<--中略-->
]
}
PLAY RECAP *******************************************************************************************************************************************************************
sbx-n9kv-ao : ok=2 changed=0 unreachable=0 failed=0
test : ok=2 changed=0 unreachable=0 failed=0
Playbook(設定変更)
今度は、設定変更を行ってみます。内容は、インターフェースLoopback 78を新規作成するというものです。
---
- hosts: all
gather_facts: no
tasks:
- name: change configuration on remote devices
cli_config:
config: interface loopback 78
出力結果(設定変更)
こちらも問題なく設定変更(ok=1 changed=1)できました。ここには記載していませんが、2回実行した時の冪等性も問題なしです。
[centos@localhost ansible]$ ansible-playbook -i inventory202 playbook1-2-1.yml
PLAY [all] *******************************************************************************************************************************************************************
TASK [change configuration on remote devices] ********************************************************************************************************************************
changed: [test]
changed: [sbx-n9kv-ao]
PLAY RECAP *******************************************************************************************************************************************************************
sbx-n9kv-ao : ok=1 changed=1 unreachable=0 failed=0
test : ok=1 changed=1 unreachable=0 failed=0
変更後のConfig(設定変更)
Config上でも設定反映されていることが確認できました。
test#sh run interface loopback 78
Building configuration...
Current configuration : 43 bytes
!
interface Loopback78
no ip address
end
sbx-n9kv-ao# sh run interface loopback 78
!Command: show running-config interface loopback78
!Running configuration last done at: Sat Dec 15 14:44:11 2018
!Time: Sat Dec 15 14:49:41 2018
version 9.2(1) Bios:version
interface loopback78
最後に
一応、Cisco IOSとNX-OSでは問題なく動作しました。前回よりはおススメできるものになったと思います。
はい、めでたしめでたし!
~ 完 ~