銀狐NetDevOps-網(wǎng)絡(luò)運(yùn)維python篇之NETCONF(一)華為ncclient指南

科技銀狐

前言

銀狐DevNet系列會(huì)持續(xù)將網(wǎng)絡(luò)運(yùn)維工作中python的應(yīng)用進(jìn)行場(chǎng)景化的分享,因?yàn)槊總€(gè)單獨(dú)的模塊網(wǎng)上都有詳細(xì)的教學(xué)煎饼,這里就不深入講解模塊基礎(chǔ)了,內(nèi)容主要以思路和示例為主,并將碰到的問(wèn)題匯總提出注意事項(xiàng)辅柴。

主要是因?yàn)榫W(wǎng)絡(luò)工程師和網(wǎng)絡(luò)運(yùn)維工作者編程基礎(chǔ)不強(qiáng),加上網(wǎng)上對(duì)于這個(gè)領(lǐng)域的python資料又少瞭吃,傳統(tǒng)的分享方式(每個(gè)章節(jié)僅單純分享一個(gè)知識(shí)點(diǎn))對(duì)于很多網(wǎng)工來(lái)說(shuō)各個(gè)知識(shí)點(diǎn)相對(duì)獨(dú)立且割裂的碌嘀,很難進(jìn)行一個(gè)知識(shí)的融合,現(xiàn)實(shí)工作中也很難直接應(yīng)用歪架,大家學(xué)習(xí)的難度就會(huì)很大股冗,也會(huì)導(dǎo)致大部分人剛?cè)腴T(mén)就放棄。所以我將這些內(nèi)容進(jìn)行場(chǎng)景化和蚪,根據(jù)特定場(chǎng)景由淺入深不斷優(yōu)化止状,從而帶出更多知識(shí)點(diǎn),希望對(duì)大家有所幫助攒霹。

這些分享都是我本人真實(shí)的學(xué)習(xí)路徑怯疤,一方面是幫助自己梳理網(wǎng)絡(luò)自動(dòng)化相關(guān)知識(shí),另一方面也希望可以通過(guò)分享我微不足道的學(xué)習(xí)過(guò)程和實(shí)戰(zhàn)經(jīng)驗(yàn)催束,幫助更多想要了解NetDevOps而苦于沒(méi)有資料和環(huán)境被勸退的人集峦,進(jìn)而找到同行之人互相交流、互相提升泣崩。

1少梁、場(chǎng)景分析:

NETCONF協(xié)議對(duì)于傳統(tǒng)網(wǎng)工來(lái)說(shuō)是噩夢(mèng),看到XML編碼就直接勸退了矫付,但對(duì)于普通網(wǎng)工來(lái)說(shuō)依然有適用的場(chǎng)景凯沪。平時(shí)我們批量操作無(wú)非就是增刪改查,針對(duì)設(shè)備增刪改买优,個(gè)人建議直接使用python的netmiko模塊妨马,非常方便挺举,也符合傳統(tǒng)網(wǎng)工輸入CLI的習(xí)慣。但對(duì)于查就需要區(qū)分場(chǎng)景了烘跺。

當(dāng)我們需要查詢?cè)O(shè)備某些配置或者狀態(tài)時(shí)湘纵,常規(guī)做法就是輸入CLI,然后在返回結(jié)果中查看想要的內(nèi)容滤淳。使用python進(jìn)行跑批操作時(shí)也是通過(guò)paramiko梧喷、netmiko這類(lèi)模塊直接SSH上設(shè)備,然后輸入CLI命令脖咐,在根據(jù)回顯內(nèi)容獲取想要的數(shù)據(jù)铺敌。這里分幾種情況,如果我們想獲取設(shè)備配置文件屁擅,直接通過(guò)netmiko傳遞show config命令偿凭,其實(shí)是沒(méi)什么問(wèn)題的,因?yàn)檫@個(gè)回顯的內(nèi)容是不需要做任何處理的派歌。

那我們換一個(gè)場(chǎng)景弯囊,1000臺(tái)網(wǎng)絡(luò)設(shè)備,需要批量獲取所有設(shè)備的設(shè)備名稱(chēng)胶果、型號(hào)匾嘱、版本號(hào)、補(bǔ)丁稽物,并將內(nèi)容存儲(chǔ)起來(lái)時(shí)該怎么辦呢奄毡?這里有3中方法折欠。

方法一:

使用paramiko或者netmiko批量登錄網(wǎng)絡(luò)設(shè)備贝或,并輸入CLI(disp ver),將如下回顯內(nèi)容自行處理锐秦。

Huawei Versatile Routing Platform Software
VRP (R) software, Version 8.180 (CE6855HI V200R005C10SPC800)
Copyright (C) 2012-2018 Huawei Technologies Co., Ltd.
HUAWEI CE6855-48S6Q-HI uptime is 421 days, 13 hours, 24 minutes 
Patch Version: V200R005SPH016

CE6855-48S6Q-HI(Master) 1 : uptime is  421 days, 13 hours, 22 minutes
        StartupTime 2020/03/24   18:35:47+08:00
Memory    Size    : 2048 M bytes
Flash     Size    : 1024 M bytes
CE6855-48S6Q-HI version information                               
1\. PCB    Version : CEM48S6QP05    VER B
2\. MAB    Version : 1
3\. Board  Type    : CE6855-48S6Q-HI
4\. CPLD1  Version : 102
5\. BIOS   Version : 433

顯然咪奖,處理以上數(shù)據(jù)會(huì)非常麻煩

方法二:

使用netmiko這類(lèi)SSH模塊配合textFSM模板(結(jié)合ntc-template)進(jìn)行操作(方法以后講解),直接回顯如下列表內(nèi)容酱床。

[{'model': 'CE6855-48S6Q-HI',
  'product_version': 'CE6855HI V200R005C10SPC800',
  'uptime': '421 days, 9 hours, 24 minutes ',
  'vrp_version': '8.180'}]

可以看到羊赵,非常方便。

但問(wèn)題就是這方面的模板cisco和juniper等國(guó)外廠商比較充足扇谣,基本涵蓋了常見(jiàn)需求昧捷,國(guó)內(nèi)華為只有4個(gè)模板,如下所示。

-rw-rw-r-- 1 yydd   yydd   483 May  8 10:21 huawei_vrp_display_interface_brief.textfsm
-rw-rw-r-- 1 yydd   yydd   1811 May  8 10:21 huawei_vrp_display_lldp_neighbor.textfsm
-rw-rw-r-- 1 yydd   yydd   390 May  8 10:21 huawei_vrp_display_temperature.textfsm
-rw-rw-r-- 1 yydd   yydd   217 May  8 10:21 huawei_vrp_display_version.textfsm

也就是只有4個(gè)命令回顯可以直接返回處理好的列表罐寨,顯然是不夠用的靡挥。(模板可自己編寫(xiě),難度比較大)

方法三:

使用NETCONF協(xié)議鸯绿,結(jié)合標(biāo)準(zhǔn)的XML編碼格式跋破,返回標(biāo)準(zhǔn)化格式的內(nèi)容簸淀。而ncclient就是一個(gè)用于NETCONF客戶端的Python庫(kù)。

2毒返、操作環(huán)境:

操作系統(tǒng):Linux CentOS 7.4

python版本:python 3.8

網(wǎng)絡(luò)設(shè)備:華為CloudEngine 6865

編輯器:vscode

安裝ncclient:

pip3 install ncclient

3租幕、代碼示例

#!/usr/bin/env python
#coding: utf-8

from pprint import pprint
import xmltodict
from ncclient import manager
from ncclient import operations
from ncclient.transport.errors import SSHError
from ncclient.transport.errors import AuthenticationError

#構(gòu)造待配置的YANG內(nèi)容,此處為系統(tǒng)信息拧簸。
#具體可參考華為官網(wǎng)二次開(kāi)發(fā)文檔《CloudEngine 8800, 7800, 6800HI, 6880EI, 6875EI, 6870EI, 6865EI, 6860EI, 6857EI, 5880EI V200R005C10 NETCONF Schema API參考》

devinfo_FILTER = '''
      <system xmlns="<http://www.huawei.com/netconf/vrp>" content-version="1.0" format-version="1.0">
      <systemInfo>
      </systemInfo>
    </system>
'''

# Fill the device information and establish a NETCONF session
def huawei_connect(host, port, user, password):
    return manager.connect(host=host,
                            port=port,
                            username=user,
                            password=password,
                            hostkey_verify = False,
                            device_params={'name': "huawei"},
                            allow_agent = False,
                            look_for_keys = False)

def nc_get(host, port, user, password):
    with huawei_connect(host, port=port, user=user, password=password) as m:

        return m.get(("subtree", devinfo_FILTER))

def main():
    nc_res = nc_get("172.26.32.7",22,"user","pass")
    xml_rep = nc_res.data_xml
    print(xml_rep)

if __name__ == '__main__':
    main()

執(zhí)行結(jié)果

<?xml version="1.0" encoding="UTF-8"?><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <system xmlns="<http://www.huawei.com/netconf/vrp>" format-version="1.0" content-version="1.0">
      <systemInfo>
        <sysName>SZTL-POD2-Leaf-H6865-1</sysName>
        <sysContact>R&amp;D Beijing, Huawei Technologies co.,Ltd.</sysContact>
        <sysLocation>Beijing China</sysLocation>
        <sysDesc>Huawei Versatile Routing Platform Software &#13;
VRP (R) software, Version 8.191 (CE6865EI V200R019C10SPC800) &#13;
Copyright (C) 2012-2020 Huawei Technologies Co., Ltd. &#13;
HUAWEI CE6865-48S8CQ-EI &#13;</sysDesc>
        <sysObjectId>1.3.6.1.4.1.2011.2.239.49</sysObjectId>
        <sysGmtTime>1621568735</sysGmtTime>
        <sysUpTime>4125375</sysUpTime>
        <sysService>78</sysService>
        <platformName>VRP</platformName>
        <platformVer>V800R019C16SPC599</platformVer>
        <productName>CE6865EI</productName>
        <productVer>V200R019C10SPC800</productVer>
        <patchVer>V200R019SPH007</patchVer>
        <esn>2102351RFD10MC111521</esn>
        <mac>9017-3FF0-1CB1</mac>
        <lsRole>admin</lsRole>
        <authenFlag>false</authenFlag>
        <softwareName/>
      </systemInfo>
    </system>
  </data>

可以看到回顯內(nèi)容結(jié)構(gòu)非常清晰劲绪,需要什么數(shù)據(jù)直接從XML中獲取即可。后面就以示例為基礎(chǔ)盆赤,完成開(kāi)頭提到的需求珠叔。

4、ncclient實(shí)驗(yàn)

4.1 需求

獲取設(shè)備的設(shè)備名稱(chēng)弟劲、型號(hào)祷安、版本號(hào)、補(bǔ)丁兔乞、SN

4.2 代碼

#!/usr/bin/env python
#coding: utf-8

from pprint import pprint
import xmltodict
from ncclient import manager
from ncclient import operations
from ncclient.transport.errors import SSHError
from ncclient.transport.errors import AuthenticationError

#構(gòu)造YANG
devinfo_FILTER = '''
      <system xmlns="<http://www.huawei.com/netconf/vrp>" content-version="1.0" format-version="1.0">
      <systemInfo>
        <sysName></sysName>
        <productName></productName>
        <productVer></productVer>
        <patchVer></patchVer>
        <esn></esn>
      </systemInfo>
    </system>
'''

#建立NETCONF會(huì)話
def huawei_connect(host, port, user, password):
    return manager.connect(host=host,
                            port=port,
                            username=user,
                            password=password,
                            hostkey_verify = False,
                            device_params={'name': "huawei"},
                            allow_agent = False,
                            look_for_keys = False)

#構(gòu)造<get>報(bào)文
def nc_get(host, port, user, password):
    with huawei_connect(host, port=port, user=user, password=password) as m:

        return m.get(("subtree", devinfo_FILTER))

#主函數(shù)
def main():
    nc_res = nc_get("172.26.32.7",22,"user","pass")
    xml_rep = nc_res.data_xml
    print(xml_rep)

    xml_dict = xmltodict.parse(xml_rep)
    for k,y in xml_dict.items():
        print(k,y)
    print("="*70)

        for k,y in xml_dict['data']['system']['systemInfo'].items():
            print(k,":",y)

if __name__ == '__main__':
    main()

執(zhí)行結(jié)果

<?xml version="1.0" encoding="UTF-8"?><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <system xmlns="<http://www.huawei.com/netconf/vrp>" format-version="1.0" content-version="1.0">
      <systemInfo>
        <sysName>SZTL-POD2-Leaf-H6865-1</sysName>
        <productName>CE6865EI</productName>
        <productVer>V200R019C10SPC800</productVer>
        <patchVer>V200R019SPH007</patchVer>
        <esn>2102351RFD10MC111521</esn>
      </systemInfo>
    </system>
  </data>

data OrderedDict([('@xmlns', 'urn:ietf:params:xml:ns:netconf:base:1.0'), ('system', OrderedDict([('@xmlns', '<http://www.huawei.com/netconf/vrp>'), ('@format-version', '1.0'), ('@content-version', '1.0'), ('systemInfo', OrderedDict([('sysName', 'SZTL-POD2-Leaf-H6865-1'), ('productName', 'CE6865EI'), ('productVer', 'V200R019C10SPC800'), ('patchVer', 'V200R019SPH007'), ('esn', '2102351RFD10MC111521')]))]))])
======================================================================
sysName : SZTL-POD2-Leaf-H6865-1
productName : CE6865EI
productVer : V200R019C10SPC800
patchVer : V200R019SPH007
esn : 2102351RFD10MC111521

4.3 詳解

from pprint import pprint                 
#有縮進(jìn)的打印汇鞭,回顯更直觀,建議使用

import xmltodict                          
#用于xml轉(zhuǎn)換為dict

#導(dǎo)入ncclient常用模塊
from ncclient import manager
from ncclient import operations
from ncclient.transport.errors import SSHError
from ncclient.transport.errors import AuthenticationError

devinfo_FILTER = '''
      <system xmlns="<http://www.huawei.com/netconf/vrp>" content-version="1.0" format-version="1.0">
      <systemInfo>
        <sysName></sysName>
        <productName></productName>
        <productVer></productVer>
        <patchVer></patchVer>
        <esn></esn>
      </systemInfo>
    </system>
'''

構(gòu)造待配置的YANG內(nèi)容,此處為系統(tǒng)信息庸追。 具體可參考華為官網(wǎng)二次開(kāi)發(fā)文檔《CloudEngine 8800, 7800, 6800HI, 6880EI, 6875EI, 6870EI, 6865EI, 6860EI, 6857EI, 5880EI V200R005C10 NETCONF Schema API參考》霍骄。

如果我們只需要systemInfo下的部分信息,直接在<systemInfo></systemInfo>中間加入明細(xì)內(nèi)容即可淡溯,可參考官方文檔读整。

關(guān)于XML基礎(chǔ)知識(shí),可以訪問(wèn)https://www.w3school.com.cn/xml/xml_intro.asp查看咱娶。


def huawei_connect(host, port, user, password):
    return manager.connect(host=host,
                            port=port,
                            username=user,
                            password=password,
                            hostkey_verify = False,
                            device_params={'name': "huawei"},
                            allow_agent = False,
                            look_for_keys = False)

定義NETCONF session的函數(shù)米间,調(diào)用manager.connect建立連接。

def nc_get(host, port, user, password):
    with huawei_connect(host, port=port, user=user, password=password) as m:

        return m.get(("subtree", devinfo_FILTER))

定義get函數(shù)膘侮,構(gòu)造<get>報(bào)文屈糊,并返回rpc-reply的結(jié)果。

因?yàn)槲覀儾幌M鹓et過(guò)多內(nèi)容琼了,所以要加入filter功能逻锐,devinfo_FILTER就是我們自己構(gòu)建的XML,<filter>元素可以包含“type”屬性雕薪,NETCONF中的默認(rèn)過(guò)濾機(jī)制被稱(chēng)為子樹(shù)過(guò)濾(“type”屬性值為“subtree”)昧诱。

打印結(jié)果一:

#主函數(shù)
def main():
    nc_res = nc_get("172.26.32.7",22,"user","pass")
    xml_rep = nc_res.data_xml   #返回XML標(biāo)準(zhǔn)格式的字符串
    print(xml_rep)

#執(zhí)行結(jié)果
<?xml version="1.0" encoding="UTF-8"?><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <system xmlns="<http://www.huawei.com/netconf/vrp>" format-version="1.0" content-version="1.0">
      <systemInfo>
        <sysName>SZTL-POD2-Leaf-H6865-1</sysName>
        <productName>CE6865EI</productName>
        <productVer>V200R019C10SPC800</productVer>
        <patchVer>V200R019SPH007</patchVer>
        <esn>2102351RFD10MC111521</esn>
      </systemInfo>
    </system>
  </data>

打印結(jié)果二:

    xml_dict = xmltodict.parse(xml_rep)   
    #此方法會(huì)將xml_rep解析為orderdict,和傳統(tǒng)dict區(qū)別就是orderdict是有順序的
        for k,y in xml_dict.items():
        #遍歷字典所袁,items() 方法讓字典以列表形式返回可遍歷的(鍵, 值) 元組數(shù)組
       print(k,y)

#執(zhí)行結(jié)果
data OrderedDict([('@xmlns', 'urn:ietf:params:xml:ns:netconf:base:1.0'), ('system', OrderedDict([('@xmlns', '<http://www.huawei.com/netconf/vrp>'), ('@format-version', '1.0'), ('@content-version', '1.0'), ('systemInfo', OrderedDict([('sysName', 'SZTL-POD2-Leaf-H6865-1'), ('productName', 'CE6865EI'), ('productVer', 'V200R019C10SPC800'), ('patchVer', 'V200R019SPH007'), ('esn', '2102351RFD10MC111521')]))]))])

打印結(jié)果三:

#訪問(wèn)xml_dict['data']['system']['systemInfo']的value
#OrderedDict([('sysName', 'SZTL-POD2-Leaf-H6865-1'),
# ('productName', 'CE6865EI'),
# ('productVer', 'V200R019C10SPC800'), 
# ('patchVer', 'V200R019SPH007'),
# ('esn', '2102351RFD10MC111521')])
#在進(jìn)行遍歷操作

for k,y in xml_dict['data']['system']['systemInfo'].items():
    print(k,":",y)

#打印結(jié)果
sysName : SZTL-POD2-Leaf-H6865-1
productName : CE6865EI
productVer : V200R019C10SPC800
patchVer : V200R019SPH007
esn : 2102351RFD10MC111521

上面的逐步打印盏档,是為了讓大家更清晰的看到每一步數(shù)據(jù)處理的區(qū)別。

核心還是提供思路纲熏,詳細(xì)的基礎(chǔ)知識(shí)如果有不懂的妆丘,直接在Google或者baidu搜索锄俄,有很多資料。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末勺拣,一起剝皮案震驚了整個(gè)濱河市奶赠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌药有,老刑警劉巖毅戈,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異愤惰,居然都是意外死亡苇经,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)宦言,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)扇单,“玉大人,你說(shuō)我怎么就攤上這事奠旺≈├剑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵响疚,是天一觀的道長(zhǎng)鄙信。 經(jīng)常有香客問(wèn)我,道長(zhǎng)忿晕,這世上最難降的妖魔是什么装诡? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮践盼,結(jié)果婚禮上鸦采,老公的妹妹穿的比我還像新娘。我一直安慰自己宏侍,他們只是感情好赖淤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布蜀漆。 她就那樣靜靜地躺著谅河,像睡著了一般。 火紅的嫁衣襯著肌膚如雪确丢。 梳的紋絲不亂的頭發(fā)上绷耍,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音鲜侥,去河邊找鬼褂始。 笑死,一個(gè)胖子當(dāng)著我的面吹牛描函,可吹牛的內(nèi)容都是我干的崎苗。 我是一名探鬼主播狐粱,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼胆数!你這毒婦竟也來(lái)了肌蜻?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤必尼,失蹤者是張志新(化名)和其女友劉穎蒋搜,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體判莉,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡豆挽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了券盅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帮哈。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖锰镀,靈堂內(nèi)的尸體忽然破棺而出但汞,到底是詐尸還是另有隱情,我是刑警寧澤互站,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布私蕾,位于F島的核電站,受9級(jí)特大地震影響胡桃,放射性物質(zhì)發(fā)生泄漏踩叭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一翠胰、第九天 我趴在偏房一處隱蔽的房頂上張望容贝。 院中可真熱鬧,春花似錦之景、人聲如沸斤富。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)满力。三九已至,卻和暖如春轻纪,著一層夾襖步出監(jiān)牢的瞬間油额,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工刻帚, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留潦嘶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓崇众,卻偏偏與公主長(zhǎng)得像掂僵,于是被迫代替她去往敵國(guó)和親航厚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容