【自動化】NETCONF(ncclient)でCisco機器のコマンド実行・コンフィグ投入

DevNet

NETCONF (ncclient) サンプルコード

下記リンクのサンプルスクリプトをもとに、ncclientを利用したNETCONFによるコマンド実行・コンフィグ投入・削除のサンプルを作成して実行してみました。

【Cisco DevNet】Step 3: Walking Through Automating Your Network with NETCONF

Interface Listの取得 (get_interface_list.py)

from ncclient import manager
import xmltodict
import xml.dom.minidom


# Create an XML filter for targeted NETCONF queries
netconf_filter = """
<filter>
  <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
    <interface></interface>
  </interfaces>
</filter>"""


with manager.connect(
         host="**.**.**.**",
         port="830",
         username="*****",
         password="*****",
         hostkey_verify=False
         ) as m:

     netconf_reply = m.get_config(source = 'running', filter = netconf_filter)
     print(xml.dom.minidom.parseString(netconf_reply.xml).toprettyxml())


# Parse the returned XML to an Ordered Dictionary
netconf_data = xmltodict.parse(netconf_reply.xml)["rpc-reply"]["data"]


# Create a list of interfaces
interfaces = netconf_data["interfaces"]["interface"]


for interface in interfaces:
     print("Interface {} enabled status is {}".format(
             interface["name"],
             interface["enabled"]
             )
         )

実行結果

$ python3 get_interface_list.py
<?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:13e90453-536f-4ead-894b-f6ef40e06e7a">
    <data>
        <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
            <interface>
                <name>GigabitEthernet1</name>
                <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"/>
                <ipv6 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"/>
            </interface>
            <interface>
                <name>GigabitEthernet2</name>
                <description>to_R4</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>172.16.1.1</ip>
                        <netmask>255.255.255.0</netmask>
                    </address>
                </ipv4>
                <ipv6 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"/>
            </interface>

         --- snip ---

        </interfaces>
    </data>
</rpc-reply>


Interface GigabitEthernet1 enabled status is true
Interface GigabitEthernet2 enabled status is true
--- snip ---

Loopback IFの追加 (add_loopback.py)

from ncclient import manager
import xmltodict
import xml.dom.minidom


# Create an XML configuration template for ietf-interfaces
netconf_interface_template = """
<config>
    <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
        <interface>
            <name>{name}</name>
            <description>{desc}</description>
            <type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">
                {type}
            </type>
            <enabled>{status}</enabled>
            <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
                <address>
                    <ip>{ip_address}</ip>
                    <netmask>{mask}</netmask>
                </address>
            </ipv4>
        </interface>
    </interfaces>
</config>"""


# Ask for the Interface Details to Add
new_loopback = {}
new_loopback["name"] = "Loopback" + input("What loopback number to add? ")
new_loopback["desc"] = input("What description to use? ")
new_loopback["type"] = "ianaift:softwareLoopback"
new_loopback["status"] = "true"
new_loopback["ip_address"] = input("What IP address? ")
new_loopback["mask"] = input("What network mask? ")


# Create the NETCONF data payload for this interface
netconf_data = netconf_interface_template.format(
        name = new_loopback["name"],
        desc = new_loopback["desc"],
        type = new_loopback["type"],
        status = new_loopback["status"],
        ip_address = new_loopback["ip_address"],
        mask = new_loopback["mask"]
    )


with manager.connect(
         host="**.**.**.**",
         port="830",
         username="*****",
         password="*****",
         hostkey_verify=False
         ) as m:


    netconf_reply = m.edit_config(netconf_data, target = 'running')

実行結果

$ python3 add_loopback.py
What loopback number to add? 10
What description to use? netconf-test
What IP address? 2.2.2.2
What network mask? 255.255.255.255
$

-------
CSR1kv_1#show run int loo 10
Building configuration...


Current configuration : 90 bytes
!
interface Loopback10
 description netconf-test
 ip address 2.2.2.2 255.255.255.255
end

Loopback IFの削除 (delete_loopback.py)

from ncclient import manager
import xmltodict
import xml.dom.minidom


# Create an XML configuration template for ietf-interfaces
netconf_interface_template = """
<config>
    <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
        <interface operation="delete">
            <name>{name}</name>
        </interface>
    </interfaces>
</config>"""


# Ask for the Interface Details to Delete
new_loopback = {}
new_loopback["name"] = "Loopback" + input("What loopback number to delete?")


# Create the NETCONF data payload for this interface
netconf_data = netconf_interface_template.format(
        name = new_loopback["name"]
    )


with manager.connect(
         host="**.**.**.**",
         port="830",
         username="*****",
         password="*****",
         hostkey_verify=False
         ) as m:


    netconf_reply = m.edit_config(netconf_data, target = 'running')

実行結果

$ python3 delete_loopback.py
What loopback number to delete?10
$

XpathによるInterface Listの取得 (get_interface_list_xpath.py)

Xpath (XML Path Language)は、XMLをツリー構造としてモデル化し、パス形式でXML内の要素を指定する言語です。ncclientではXpathによる取得データのフィルタも可能です。

from ncclient import manager
import xmltodict
import xml.dom.minidom
from lxml import etree

# Create an XML filter for targeted NETCONF queries
ele_filter = etree.Element("{urn:ietf:params:xml:ns:netconf:base:1.0}filter", type="xpath", nsmap={None: 'urn:ietf:params:xml:ns:yang:ietf-interfaces'}, select="/interfaces/interface")

with manager.connect(
         host="**.**.**.**",
         port="830",
         username="*****",
         password="*****",
         hostkey_verify=False
         ) as m:

 netconf_reply = m.get_config(source = 'running', filter = ele_filter)

# Parse the returned XML to an Ordered Dictionary
netconf_data = xmltodict.parse(netconf_reply.xml)["rpc-reply"]["data"]

# Create a list of interfaces
interfaces = netconf_data["interfaces"][1]["interface"]

for interface in interfaces:
     print("Interface {}".format(
             interface["name"],
             )
         )

実行結果

$ python3 get_interface_list_xpath.py
Interface GigabitEthernet1
Interface GigabitEthernet2
Interface GigabitEthernet3

ネットワーク自動化を基礎から体系的に学びたい方は下記の本がおすすめです。

コメント

タイトルとURLをコピーしました