ลองใช้ Nornir (Python Automation Framework) กับ Cisco IOS XR และ Nokia 7750 SR
Nornir อีกหนึ่ง Automation Tools สุดเจ๋งบน Python
— — — — — — — — — — — — — — —
สารบัญเนื้อหาทั้งหมด (My Contents)
— — — — — — — — — — — — — — —
— — — — — — — — — — — — — — — — — — — — — — — -
ฝากคอร์ส Python for Network Automation ผมด้วยครับ
— — — — — — — — — — — — — — — — — — — — — — — -
เห็นว่า Nornir ถูกปล่อยมาได้ประมาณปีนึงแล้ว(ตั้งแต่ May 2018) แต่ยังไม่มีคนไทยพูดถึงมันเลยบน internet ดังนั้นผมเลยขอชิงเปิดซิงก่อนเลยละกันครับ ฮ่า ๆ
Nornir คืออะไร?
Nornir (ชื่อเดิมคือ Brigade) คือ Python Automation Framework ซึ่งถูกออกแบบมาเป็น agentless ดังนั้นมันก็แค่ telnet หรือ SSH ตรงไปยัง remote device เพื่อจัดการได้เลย แน่นอนว่ามันก็จะคล้ายกับ Ansible นั่นแหละครับ
ความเหมือนและแตกต่างของ Nornir กับ Ansible
ในส่วนของ inventory เช่น hosts.yaml หรือ groups.yaml ของ Nornir นั้นมี concept เดียวกับ Ansible เลยโดยเขียนด้วย YAML เหมือนกัน
แต่ในส่วนจัดการ task นั้นต่างกันเพราะ Ansible จะใช้ Playbook ซึ่งต้องเขียนบน YAML ด้วย syntax ของมันเอง ในขณะที่ Nornir จะใช้การเขียนเป็น Python code เลย และนี่คือจุดเด่นของ Nornir เพราะมันมีความยืดหยุ่นกว่าเยอะ
Nornir ยืดหยุ่นกว่า Ansible ยังไง?
ปกติแล้วการใช้ Ansible อาจไม่มีปัญหาเลยถ้างาน automation ของคุณไม่ได้มีความซับซ้อนและตรงไปตรงมา เช่น หากคุณต้องการรัน show ip interface brief บน router สัก 50 ตัว จากนั้นบันทึก result ที่ได้ลง text file
แต่เมื่อใดที่คุณเริ่มมี condition ซับซ้อนมาก หรือโดยเฉพาะถ้าต้องมี condition ในการเชื่อมโยงระหว่าง task หรือโดยเฉพาะ host ขึ้นมาละก็…งานหยาบเลย (ถามว่าทำได้มั้ย ทำได้ครับ แต่บางทีมัน workaround จนน่ารำคาญและรกไป)
หรืออีกจุดด้อยเลยคือการนำ Ansible ไป integrate เข้ากับ backend ของ application ตัวอื่น ๆ เนี่ยไม่มีทาง smooth จนกลืนเป็นเนื้อเดียวกันแบบ Nornir แน่นอน
ดังนั้น Nornir ที่เกิดมาเพื่อให้เราจัดการกับ task ด้วย Python code อยู่แล้ว มันจึงยืดหยุ่นและสะดวกกว่ามากหาก coding skill ของเราอยู่ในระดับโปร
วิธีติดตั้ง Nornir และเริ่มต้นใช้งานแบบสั้น ๆ
ติดตั้ง Nornir ใน Python
pip3 install nornir
สร้าง directory ของ project นี้
ใครใช้ Windows ก็สร้างตามปกติไปนะครับ 555
mkdir hello_nornir
cd hello_nornir
mkdir inventory
สร้างไฟล์ config.yaml ใน hello_nornir/config.yaml
---
core:
num_workers: 40inventory:
plugin: nornir.plugins.inventory.simple.SimpleInventory
options:
host_file: "inventory/hosts.yaml"
group_file: "inventory/groups.yaml"
defaults_file: "inventory/defaults.yaml"
สร้างไฟล์ hosts.yaml ใน hello_nornir/inventory/hosts.yaml
จากตัวอย่างนี้ถ้าใครจะทำตามเป๊ะ ๆ (แต่คงไม่มีมั้ง) จะไป error ตรง host ที่เป็น nokia ครับ เพราะตามจริง platform ต้องเป็น alcatel_sros ครับ แถมต้องไปแก้ code บางส่วนของ netmiko ด้วยเพราะมันมี bug อยู่ ซึ่งในที่นี้ผมได้ modify เอาไว้แล้ว
---
xr1:
hostname: 192.168.100.201
platform: iosxr
groups:
- cisco
data:
loopback:
0: 1.1.1.1
1: 11.11.11.11xr2:
hostname: 192.168.100.202
platform: iosxr
groups:
- cisco
data:
loopback:
0: 2.2.2.2
1: 22.22.22.22sr1:
hostname: 192.168.100.203
platform: nokia_sros
groups:
- nokia
data:
loopback:
0: 3.3.3.3
1: 33.33.33.33sr2:
hostname: 192.168.100.204
platform: nokia_sros
groups:
- nokia
data:
loopback:
0: 4.4.4.4
1: 44.44.44.44
สร้างไฟล์ groups.yaml ใน hello_nornir/inventory/groups.yaml
---
main:
data:
domain: nopnithi.comcisco:
username: nopnithi
password: cisco1234
data:
type: network_device
groups:
- mainnokia:
username: nopnithi
password: nokia1234
data:
type: network_device
groups:
- main
สร้างไฟล์ demo1.py ใน hello_nornir/demo1.py
เริ่มต้นแบบ basic สุด ๆ ลองประมาณนี้ดูครับ อันนี้เป็นการใช้ NAPALM ในการ get interface บน Cisco IOS XR ครับ
from nornir import InitNornir
from nornir.plugins.tasks import networking
from nornir.plugins.functions.text import print_resultnr = InitNornir(config_file='config.yaml')
xr = nr.filter(platform='iosxr')
result = xr.run(task=networking.napalm_get, getters=['interfaces'])
print_result(result)
สร้างไฟล์ demo2.py ใน hello_nornir/demo1.py
from nornir import InitNornir
# from nornir.plugins.tasks import commands
from nornir.plugins.tasks import networking, text
from nornir.plugins.functions.text import print_result
from mylib.nokia_ssh import *
def run(task):
create_loopback_netmiko(task)
remove_loopback(task)
def create_loopback_netmiko(task):
r = task.run(
task=text.template_file,
name='Generate Configuration For Create Loopback Interface',
template='create_loopback.j2',
path=f'templates/{task.host.platform}'
)
task.host['config'] = r.result
task.run(
task=networking.netmiko_send_config,
name='Create Loopback Interface',
config_commands=task.host['config'].splitlines()
)
def create_loopback_mylib(task):
r = task.run(
task=text.template_file,
name='Create Loopback Interface',
template='create_loopback.j2',
path=f'templates/{task.host.platform}'
)
task.host['config'] = r.result
# Start: My SSH library for Nokia SR OS
mylib = NokiaSSH(
ip=task.host.hostname,
username=task.host.username,
password=task.host.password
)
mylib.connect()
mylib.disable_continue()
mylib.send_command_multiline(task.host['config'].splitlines())
mylib.save()
mylib.disconnect()
# End: My SSH library for Nokia SR OS
return mylib.cleaned_output
def remove_loopback(task):
r = task.run(
task=text.template_file,
name='Generate Configuration For Remove Loopback Interface',
template='remove_loopback.j2',
path=f'templates/{task.host.platform}'
)
task.host['config'] = r.result
task.run(
task=networking.netmiko_send_config,
name='Remove Loopback Interface',
config_commands=task.host['config'].splitlines()
)
def show_interfaces_napalm(task):
result = task.run(task=networking.napalm_get, getters=['interfaces'])
return result
def filter_hosts(host):
return len(host.name) >= 10 and host.name[0] == 's'
if __name__ == '__main__':
nr = InitNornir(config_file='config.yaml')
cisco = nr.filter(platform='iosxr')
nokia = nr.filter(platform='nokia_sros')
some = nr.filter(filter_func=filter_hosts).inventory.hosts.keys()
result = nr.run(task=run, num_workers=4)
print_result(result)
สำหรับตัวอย่างนี้แนะนำว่าให้ลองไปดูในวิดีโอดีกว่าครับ ผมจะลองใช้งานให้ดูว่า Nornir มันยืดหยุ่นยังไงกันแน่
ข้อมูลเพิ่มเติม:
https://nornir.readthedocs.io/en/stable/
— — — — — — — — — — — — — — —
สารบัญเนื้อหาทั้งหมด (My Contents)
— — — — — — — — — — — — — — —