การใช้ NETCONF บน Cisco Router (CSR 1000V)

Using NETCONF on Cisco Router (CSR 1000V)

Nopnithi Khaokaew (Game)
3 min readSep 13, 2020

— — — — — — — — — — — — — — —
สารบัญเนื้อหาทั้งหมด (My Contents)
— — — — — — — — — — — — — — —

สำหรับท่านที่เผลอเข้ามาแต่ยังไม่มีความรู้เกี่ยวกับ NETCONF เลย ผมแนะนำให้คลิกไปอ่านบทความ “NETCONF คืออะไร?” ของผมก่อนครับ แล้วค่อยวนกลับมาลองทำ lab ที่บทความนี้ แต่ถ้าใครมีพื้นฐานความรู้อยู่แล้วก็ตามมาเลย

อ้อ…ความรู้เรื่อง Python ก็ต้องมีด้วยนะครับ ซึ่งถ้าหากใครยังไม่มีและกำลังมองหาคอร์สสอน Python สำหรับใช้งานด้าน network โดยตรงก็ลองดูคอร์สนี้ของผมได้เลย (ขายเนียน ๆ 555)

1. เตรียม NETCONF Configuration บน Cisco CSR 1000V

1.1 Configure ข้อมูลเบื้องต้น

ทำการ configure ข้อมูลเบื้องต้นของ router รวมถึงพวก username, password และ SSH เพื่อเตรียมไว้สำหรับการใช้งาน NETCONF ให้เรียบร้อย

hostname nopnithi-r1
!
ip domain name nopnithi.lab
username nopnithi privilege 15 secret P@ssw0rd
!
crypto key generate rsa general-keys modulus 2048
!
ip ssh version 2
!
line con 0
logging synchronous
line vty 0 4
login local
transport input ssh

1.2 เปิดใช้งาน NETCONF

ทำการ configure เพื่อเปิดใช้งาน NETCONF ควบคู่กับ YANG บนอุปกรณ์

netconf ssh
netconf-yang

1.3 สร้าง Management Interface และ Loopback1

สำหรับ GigabitEthernet1 จะถูกใช้เป็น management interface ในการรับส่งข้อมูลระหว่างคอมพิวเตอร์ของเรากับ Cisco CSR 1000V ส่วน Loopback1 สร้างเอาไว้เพื่อการทดสอบเท่านั้น

interface GigabitEthernet1
description Connected-To-MGMT-Network
ip address 10.1.30.2 255.255.255.0
no shutdown
!
interface Loopback1
description Loopback1 (Created by CLI)
ip address 1.1.1.1 255.255.255.255

หลังจาก configure ทั้งหมดเรียบร้อยแล้ว ให้ทดสอบโดยการ SSH จากคอมพิวเตอร์ของเราซึ่งทำหน้าที่เป็น NETCONF Client ไปยัง router (10.1.30.2) ซึ่งทำหน้าที่เป็น NETCONF server และถ้าเราสามารถ SSH และ login เข้าสู่ router ได้ก็ถือว่าผ่านขั้นตอนนี้แล้วครับ

2. ดึงข้อมูลจาก Cisco CSR 1000V ด้วย NETCONF

2.1 ติดตั้งไลบรารี่ ncclient ใน Python

pip3 install ncclient

2.2 รัน Python Code เพื่อดึงข้อมูล Interface ทั้งหมด

สังเกตว่าผมใช้ <get> operation ร่วมกับ filter เพื่อเลือกมาเฉพาะข้อมูล interface เท่านั้น ซึ่ง YANG model ที่เลือกใช้ก็คือ ietf-interfaces ครับ (ในส่วนของ YANG model ผมจะยังไม่ได้พูดถึงในบทความนี้นะครับ)

from ncclient import manager
import xml.dom.minidom


def show_reply(response):
print(xml.dom.minidom.parseString(str(response)).toprettyxml())


def main():
device = {
'host': '10.1.30.2',
'port': '830',
'username': 'nopnithi',
'password': 'P@ssw0rd',
'hostkey_verify': False
}

netconf_filter = '''
<filter>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
</interfaces>
</filter>
'''

with manager.connect(**device) as netconf:
reply = netconf.get(netconf_filter)
show_reply(reply)


if __name__ == '__main__':
main()

ผลลัพธ์ที่ได้ก็จะประมาณนี้

<?xml version="1.0" ?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:a725aba9-38ac-4afc-b48f-cb6e5b281852">
<data>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>GigabitEthernet1</name>
<description>Connected-To-MGMT-Network</description>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
<enabled>true</enabled>
<ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
<address>
<ip>10.1.30.2</ip>
<netmask>255.255.255.0</netmask>
</address>
</ipv4>
<ipv6 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"/>
</interface>
<interface>
<name>GigabitEthernet2</name>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
<enabled>false</enabled>
<ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"/>
<ipv6 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"/>
</interface>
<interface>
<name>GigabitEthernet3</name>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
<enabled>false</enabled>
<ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"/>
<ipv6 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"/>
</interface>
<interface>
<name>GigabitEthernet4</name>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
<enabled>false</enabled>
<ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"/>
<ipv6 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"/>
</interface>
<interface>
<name>Loopback1</name>
<description>Loopback1 (Created by CLI)</description>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:softwareLoopback</type>
<enabled>true</enabled>
<ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
<address>
<ip>1.1.1.1</ip>
<netmask>255.255.255.255</netmask>
</address>
</ipv4>
<ipv6 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"/>
</interface>
</interfaces>
</data>
</rpc-reply>

3. เปลี่ยน Configuration ของ Cisco CSR 1000V ด้วย NETCONF

3.1 รัน Python Code เพื่อสร้าง Loopback2 ถึง 5

ผมจะใช้ NETCONF ในการสร้าง Loopback2 ถึง 5 ขึ้นมา โดยคราวนี้ผมเปลี่ยนจากการใช้ <get> เป็น <edit-config> แทน ซึ่งเป็น operation ที่ใช้สำหรับการเปลี่ยนแปลงแก้ไข configuration

สังเกตว่าใน code ผมระบุ datastore เป็น running นะครับ

from ncclient import manager


def main():
device = {
'host': '10.1.30.2',
'port': '830',
'username': 'nopnithi',
'password': 'P@ssw0rd',
'hostkey_verify': False
}
config_template = '''
<interface>
<name>{name}</name>
<description>{desc}</description>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:softwareLoopback</type>
<enabled>true</enabled>
<ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
<address>
<ip>{ip}</ip>
<netmask>{mask}</netmask>
</address>
</ipv4>
</interface>
'''
loopbacks = [
{'name': 'Loopback2', 'desc': 'Loopback2 (Created by NETCONF)', 'ip': '2.2.2.2', 'mask': '255.255.255.255'},
{'name': 'Loopback3', 'desc': 'Loopback3 (Created by NETCONF)', 'ip': '3.3.3.3', 'mask': '255.255.255.255'},
{'name': 'Loopback4', 'desc': 'Loopback4 (Created by NETCONF)', 'ip': '4.4.4.4', 'mask': '255.255.255.255'},
{'name': 'Loopback5', 'desc': 'Loopback5 (Created by NETCONF)', 'ip': '5.5.5.5', 'mask': '255.255.255.255'}
]
netconf_config = '<config><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">'
for loopback in loopbacks:
netconf_config += config_template.format(**loopback)
netconf_config += '</interfaces></config>'

with manager.connect(**device) as netconf:
reply = netconf.edit_config(netconf_config, target='running')
print(reply)


if __name__ == '__main__':
main()

ผลลัพธ์ที่ได้ก็คือมี Loopback2 ถึง 5 ถูกสร้างขึ้นมาบนอุปกรณ์แบบนี้

interface Loopback2
description Loopback2 (Created by NETCONF)
ip address 2.2.2.2 255.255.255.255
!
interface Loopback3
description Loopback3 (Created by NETCONF)
ip address 3.3.3.3 255.255.255.255
!
interface Loopback4
description Loopback4 (Created by NETCONF)
ip address 4.4.4.4 255.255.255.255
!
interface Loopback5
description Loopback5 (Created by NETCONF)
ip address 5.5.5.5 255.255.255.255

สรุปส่งท้าย

ทั้งหมดนี้ก็เป็นตัวอย่างง่าย ๆ ในการเริ่มใช้งาน NETCONF บนอุปกรณ์ network

และสำหรับท่านที่สงสัยว่าผมรู้ได้ยังไงว่า filter ต้องเขียนแบบไหน หรือตอนจะ configure ต้องมี payload อะไรบ้าง คำตอบก็คือเราต้องดูจาก YANG model ของอุปกรณ์รุ่นนั้น ๆ ครับ โดยจากตัวอย่างผมใช้ Cisco CSR 1000V ซึ่งเป็น IOS XE เวอร์ชั่น 16.11.01b ผมก็ต้องมาดูที่นี่

แต่เนื่องด้วยบทความนี้ผมจะยังไม่ได้ลงรายละเอียดเกี่ยวกับ YANG หรือวิธีการใช้งานนะครับ เพราะใจความหลักของบทความนี้คือการแสดงตัวอย่างวิธีการใช้งาน NETCONF บนอุปกรณ์ Cisco ไว้ถ้ามีเวลาผมจะเขียนรายละเอียดเกี่ยวกับ YANG อีกครั้งในบทความต่อ ๆ ไป

— — — — — — — — — — — — — — —
สารบัญเนื้อหาทั้งหมด (My Contents)
— — — — — — — — — — — — — — —

--

--

Nopnithi Khaokaew (Game)
Nopnithi Khaokaew (Game)

Written by Nopnithi Khaokaew (Game)

Cloud Solutions Architect & Hobbyist Developer | 6x AWS Certified, CKA, CKAD, 2x HashiCorp Certified (Terraform, Vault), etc.

No responses yet