天天看點

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

點選檢視第一章 點選檢視第三章

第2章

低級網絡裝置互動

在第1章中,我們研究了網絡通信協定背後的理論和規範,粗略介紹了Python語言。在本章中,我們将開始深入探讨如何使用Python管理網絡裝置,尤其是使用Python與傳統網絡路由器和交換機進行程式化通信的不同方式。

傳統網絡路由器和交換機是指什麼?雖然如今出現的所有的網絡裝置幾乎都配有用于程式化通信的應用程式程式設計接口(API),但衆所周知的事實是前幾年部署的許多網絡裝置都不包含API。這些裝置的預期管理方法是使用終端程式的指令行界面(CLI),這些程式最初是為人類工程師開發的。管理層依賴工程師對裝置傳回的資料進行解釋,以采取适當的措施。但随着網絡裝置數量和網絡複雜性的增加,逐個手動管理它們變得越來越困難。

Python有兩個很好的庫可以輔助完成這些任務—Pexpect庫和Paramiko庫以及從它們派生的其他庫。本章将首先介紹Pexpect庫,然後介紹Paramiko示例。一旦了解了Paramiko的基礎知識,就可以比較輕松地掌握Netmiko等擴充庫。值得一提的是,Ansible(将在第4章和第5章中介紹)在很大程度上依賴于Paramiko的網絡子產品。在本章中,我們按以下主題展開:

  • CLI面臨的挑戰。
  • 搭建虛拟實驗。
  • Python Pexpect庫。
  • Python Paramiko庫。
  • Pexpect和Paramiko的缺點。

讓我們開始吧!

2.1 CLI面臨的挑戰

在2014年拉斯維加斯的Interop展會上,BigSwitch Networks的首席執行官Douglas Murray展示了以下幻燈片,内容是1993—2013的20年間資料中心網絡(DCN)的變化:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

他的意思很明顯:我們管理網絡裝置的方式在這20年中沒有太大變化。雖然他在展示這張幻燈片時可能對現有供應商有些負面偏見,但他的觀點是有價值的。在他看來,20年來管理路由器和交換機的唯一變化是協定從安全性較低的Telnet轉變為更安全的SSH。

大概在2014年的同一時間,我們開始看到業界達成了一個共識,需要從手動的、人為驅動的CLI轉向以計算機為中心的自動化API。毫無疑問,在進行網絡設計、概念的初步驗證和首次部署拓撲時,我們仍然需要直接與裝置進行通信。但是,一旦我們經過了初始部署,就需要對全部部署進行相同的更改,以保證它們的正确性,并在工程師沒有分心或感到疲倦的情況下反複重複這些更改。這聽起來像是計算機和我們最喜歡的語言Python的理想工作。

根據幻燈片中的資訊,主要挑戰是路由器和管理者之間的互動。路由器将發送一系列資訊,并期望管理者根據工程師對輸出的解釋輸入一系列手動指令。例如,你必須輸入enable才能進入特權模式,并在收到帶#符号的傳回提示後,輸入configure terminal以進入配置模式。相同的過程可以進一步擴充到接口配置模式和路由協定配置模式。這與計算機驅動的程式化思維形成鮮明對比。當計算機想要完成一項任務(例如,在接口上放置一個IP位址)時,它期望一次性地将所有資訊提供給路由器,并且期望路由器回複單一信号yes或no以訓示任務成功與否。

由Pexpect和Paramiko實施的解決方案是将互動式流程視為子流程,并監視流程與目标裝置之間的互動。父程序根據傳回的值決定後續操作(如果有)。

2.2 搭建虛拟實驗

在深入研究庫之前,讓我們來看看為便于學習而組建實驗環境的方案。正如老話所說,熟能生巧:我們需要一個孤立的沙箱來安全地試錯,嘗試新的操作方式,并重複一些步驟來強化第一次嘗試中不明确的概念。安裝Python和管理主機所需的軟體包很容易,但我們想要模拟的那些路由器和交換機呢?

為了搭建網絡實驗,我們主要有兩種方案,每種方案都有其優點和缺點:

  • 實體裝置:此方案由可以檢視和觸摸的實體裝置組成。如果足夠幸運,可以搭建一個完全複制生産環境的實驗:
    • 優點:這是一個從實驗到生産的簡單過渡,更容易被管理人員以及操作裝置的工程師了解。簡而言之,由于較為熟悉,是以實體裝置的滿意度較高。
    • 缺點:用于實驗裝置的費用相對較高。裝置需要工時來搭建,并且一旦構造好了就不能靈活改變。
  • 虛拟裝置:虛拟裝置是實際網絡裝置的仿真,由供應商或開源社群提供:
    • 優點:虛拟裝置更易于設定、相對便宜,并且可以快速更改拓撲。
    • 缺點:它們通常是實體對應物的縮小版。有時虛拟裝置和實體裝置之間存在功能差距。

當然,個人可根據成本因素、是否易于實施及實驗與生産之間存在差距的風險來決定使用虛拟實驗還是實體實驗。在我所研究的一些環境中,虛拟實驗在進行初始概念驗證時使用,而當我們接近最終設計時再使用實體實驗。

在我看來,随着越來越多的供應商生産虛拟裝置,虛拟實驗也成為提供學習環境的一種方式。虛拟裝置的功能差距相對較小且有具體記錄,尤其是在供應商還提供虛拟執行個體時。與購買實體裝置相比,虛拟裝置的成本相對較低,因為它們通常隻是軟體程式,是以使用虛拟裝置搭建實驗用的時間更少。

本書将使用實體和虛拟裝置的組合來進行概念示範,但更多使用的是虛拟裝置。對于我們将看到的示例,使用哪種裝置的差異應該是透明的。如果與我們的目标有關的虛拟和實體裝置之間存在任何已知差異,本書中都會列出它們。

在虛拟實驗方面,除了來自不同供應商的圖像之外,我還使用了Cisco的一個稱為虛拟網際網路路由實驗(VIRL)的程式,位于

https://learningnetworkstore.cisco.com/virtual-internet-routing-lab-virl/cisco-personal-edition-pe-20-nodes-virl-20

警告:對于讀者來說,并不是必須使用這個程式。但強烈建議讀者使用一些實驗裝置來實踐本書中的示例。

2.2.1 Cisco VIRL

我第一次開始學習Cisco VIRL時,是為了Cisco認證網際網路專家(CCIE)實驗考試。我從eBay購買了一些二手的Cisco裝置。即使打折,每個路由器和交換機也要花費數百美元,是以為了省錢,我購買了一些過時的20世紀80年代的Cisco路由器(在你最喜歡的搜尋引擎中搜尋Cisco AGS路由器就能看到它),即使按實驗标準,這款路由器也明顯達不到需要的功能和功率。啟動時發出的聲音非常響,這件事很多次成為我們的笑料。連接配接實體裝置并不好玩,它們非常沉而且很笨重,連接配接所有電纜也很痛苦,并且很容易引起鍊路故障,每次有故障時又需要拔掉電纜。

幾年後,Dynamip出現了,建立不同的網絡場景變得非常容易。隻需要來自Cisco的IOS鏡像和一些精心建構的拓撲檔案,就可以輕松建構一個可以檢驗所學知識的虛拟網絡。如場景所要求的那樣,有一個完整的網絡拓撲檔案夾、預先儲存的配置和不同版本的圖像。GNS3前端的添加為整個設定提供了漂亮的GUI。使用GNS3,隻需點選就可以删除連結和裝置,你甚至可以直接從GNS3設計面闆中列印出管理的網絡拓撲。該工具唯一不好的地方就是沒有被供應商正式接受,并且因為這個原因被認為缺乏可信度。

2015年,Cisco社群決定通過釋出Cisco VIRL來滿足這一需求。如果伺服器滿足要求并且你願意支付所需的年度許可證費用,那麼無論對于本書還是生産用途,這是開發和嘗試大部分Python代碼的首選方法。

警告:自2017年1月1日起,隻有個人版20節點許可證可以購買,每年199.99美元。

雖然有一定的成本,但在我看來VIRL平台提供了一些超過其他選擇的優勢:

  • 便于使用:IOSv、IOS-XRv、CSR100v、NX-OSv和ASAv的所有映像都包含在一次下載下傳中。
  • 官方:雖然由社群提供支援,但它是Cisco内部廣泛使用的工具。鑒于其受歡迎程度,錯誤能得到快速修複,新功能會被仔細記錄,并且有用的知識在其使用者之間廣泛共享。
  • 雲遷移路徑:當仿真功能超出硬體功能時,該項目提供了一個邏輯遷移路徑,例如Cisco dCloud( https://dcloud.cisco.com/ )、包上的VIRL( http://virl.cisco.com/cloud/ )和Cisco DevNet( https://developer.cisco.com/ )。這是一個有時被忽視的重要特點。
  • 鍊路和控制平面模拟:該工具可以基于每個鍊路模拟實際鍊路特性的延遲、波資料包丢失。還有一個用于外部路由注入的控制平面流量發生器。
  • 其他:該工具提供了一些不錯的功能,例如VM Maestro拓撲設計和模拟控制、用于生成自動配置的AutoNetkit以及使用者工作區管理(如果伺服器是共享的)。還有開源項目,如virlutils( https://github.com/CiscoDevNet/virlutils ),這個項目的社群積極緻力于提高工具的可用性。

在本書中沒有使用VIRL中的所有功能。但由于這是一個值得考慮的相對較新的工具,如果你想要使用該工具,我可以提供一些我使用的設定。

警告:同樣,我想強調實驗的重要性,但并不一定是Cisco VIRL實驗。本書中提供的代碼示例應該适用于任何實驗裝置,隻要它們運作相同的軟體類型和版本即可。

VIRL的建議

VIRL網站(

http://virl.cisco.com/

)提供了大量的指南、準備和文檔。我還發現VIRL使用者社群通常提供快速準确的幫助。我不會重複這兩個地方已經提供的資訊,但是,這裡有一些我在本書中用于實驗的設定:

  1. VIRL使用兩個虛拟以太網接口進行連接配接。第一個接口設定為主機連接配接的NAT,第二個接口用于本地管理接口連接配接(以下示例中為VMnet2)。我使用具有類似網絡設定的單獨虛拟機來運作Python代碼,第一個主以太網用于網際網路連接配接,第二個以太網連接配接到VMnet2用于實驗裝置管理網絡:
    帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章
  1. VMnet2是為了将Ubuntu主機與VIRL虛拟機連接配接而建立的自定義網絡:
    帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章
  1. 在Topology Design選項中,我将Management Network選項設定為Shared flat network,以便将VMnet2用作虛拟路由器上的管理網絡:
    帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章
  1. 在節點配置下,可以選擇靜态配置管理IP。我用的是靜态設定管理IP位址,而不是讓它們由軟體動态配置設定。這會有更确定的可通路性:
    帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

2.2.2 Cisco DevNet和Cisco dCloud

在撰寫本書時,Cisco免費提供了另外兩個非常好的網絡自動化的工具。這兩個工具都需要Cisco Connection Online(CCO)登入。

第一個工具是Cisco DevNet(

)沙箱,其中包括指導學習的教程、完整文檔和沙箱遠端實驗等。有些實驗室一直處于打開狀态,而其他實驗室則需要預定。實驗室的可用性取決于使用情況。如果你還沒有自己的實驗室,這是一個很好的選擇。根據我使用DevNet的經驗,一些文檔和連結已經過時,但可以輕松檢索它們以獲得最新版本。在軟體開發等快速變化的領域,這是可以預料到的。無論是否擁有本地運作的VIRL主機,DevNet無疑是應該充分利用的工具:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

Cisco的另一個線上實驗是

。你可以将dCloud視為在其他人的伺服器上運作VIRL,而無須管理或支付這些資源。似乎Cisco将dCloud視為獨立産品以及VIRL的擴充。例如,當遇到無法在本地運作多個IOX-XR或NX-OS執行個體的情況時,可以使用dCloud擴充本地實驗。這是一個相對較新的工具,但絕對值得一看:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

2.2.3 GNS3

在本書中我還會使用其他一些虛拟實驗工具。GNS3工具就是其中之一:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

正如本章前面提到的,很多人使用CNS3來認證測試和進行實踐。這個工具已經從早期的Dynamips前端發展成為一個可行的商業産品。Cisco制造的工具,如VIRL、DevNet和dCloud,隻包含Cisco技術。盡管它們為虛拟實驗裝置提供了與外部世界通信的方式,但它們并不像直接在模拟環境中使用多供應商虛拟化裝置那麼容易。但GNS3與供應商無關,可以直接在實驗中包含多供應商虛拟化平台。這通常通過制作圖像的克隆(例如Arista vEOS)或通過其他管理程式(例如Juniper Olive仿真)直接啟動網絡裝置映像來完成。有些人可能認為GNS3沒有Cisco VIRL項目的廣度和深度,但因為它們可以運作不同的Cisco技術,是以我經常在需要将其他供應商技術融入實驗時使用它。

另一個獲得了大量好評的多供應商網絡仿真環境是下一代仿真虛拟環境(EVE-NG),位于

http://www.eve-ng.net/

還有其他虛拟化平台,如Arista vEOS(

https://eos.arista.com/tag/veos/

)、Juniper vMX(

http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/

)和vSRX(

http://www.juniper.net/us/en/products-services/security

/srx-series/vsrx/ ),你可以在測試期間将其用作獨立的虛拟裝置。它們是用于測試特定于平台的功能(例如平台上API版本之間的差異)的強大補充工具。其中許多是在公共雲提供商市場上作為付費産品提供的。為了便于通路,它們通常具有與其實體對應物相同的特征。

2.3 Python Pexpect庫

Pexpect是一個純Python子產品,用于生成子應用程式,控制它們并響應其輸出中的預期模式。Pexpect就像Don Libe的Expect一樣。Pexpect允許你的腳本生成子應用程式并控制它,就像人類正在鍵入指令一樣。Pexpect文檔位于https://pexpect.readthedocs.io/en/stable/index.html 。

現在我們來看看Python Pexpect庫。與Don Libe的原始Tcl Expect子產品類似,Pexpect啟動或生成另一個流程并監視它以控制互動。Expect工具最初是為了自動化FTP、Telnet和rlogin等互動式流程而開發的,後來擴充到網絡自動化。與最初的Expect不同,Pexpect完全用Python編寫,不需要編譯TCL或C擴充。這允許我們在代碼中使用熟悉的Python文法及其豐富的标準庫。

2.3.1 Pexpect安裝

由于這是我們安裝的第一個軟體包,我們将安裝pip工具和pexpect軟體包。這個過程非常簡單:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

警告:我使用pip3安裝Python 3軟體包,同時使用pip在Python 2環境中安裝軟體包。

快速測試以確定包可用:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

2.3.2 Pexpect概述

對于第一個實驗,我們将建構一個簡單的網絡,其中兩個IOSv裝置直接連接配接:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

每個裝置都具有192.16.0.x/24範圍内的環回位址,管理IP将在172.16.1.x/24範圍内。VIRL拓撲檔案包含在可下載下傳檔案中。你可以将拓撲導入自己的VIRL軟體中。如果你沒有VIRL,還可以通過使用文本編輯器打開拓撲檔案來檢視必要的資訊。該檔案隻是一個XML檔案,node元素下包含每個節點的資訊:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

準備好裝置後,讓我們來看看如果要遠端登入到裝置中如何與路由器進行互動:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

我使用VIRL AutoNetkit自動生成路由器的初始配置,生成預設使用者名cisco和密碼cisco。請注意,由于配置中配置設定了特權,使用者已處于特權模式:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

auto-config還為Telnet和SSH生成了vty通路:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

讓我們看一下使用Python互動式shell的Pexpect示例:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

警告:從Pexpect 4.0版本開始,你可以在Windows平台上運作Pexpect。但是,正如Pexpect文檔中所述,在Windows上運作Pexpect應該被認為是實驗性的。

在之前的互動式示例中,Pexpect生成了一個子程序,并以互動方式監視它。示例中展示了兩個重要的方法expect()和sendline()。expect()行訓示Pexpect程序查找的字元串,這些字元串被視為“已完成”的訓示符。這是預期的模式。在示例中,我們知道路由器在傳回主機名提示符(iosv-1#)時向我們發送了所有資訊。sendline()方法訓示應将哪些單詞作為指令發送到遠端裝置。還有一個名為send()的方法,但不同的是sendline()包含換行符,類似于在前一個telnet會話中發送的單詞末尾按Enter鍵。從路由器的角度來看,就好像有人從終端輸入了文本。換句話說,當路由器實際上與計算機通信時,我們“欺騙”路由器讓它們以為正在與人類連接配接。

before和after屬性将設定為子應用程式列印的文本。before屬性将設定為子應用程式列印的文本,直到達到預期的模式。after字元串将包含與預期模式比對的文本。在我們的例子中,before文本将被設定為兩個預期比對(iosv-1#)之間的輸出,包括show version指令。after文本是路由器主機名提示符:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

當出現錯誤時會發生什麼?例如,如果在生成子應用程式後鍵入username而不是Username,則Pexpect程序将從子程序中查找username字元串。在這種情況下,Pexpect程序隻會挂起,因為路由器永遠不會傳回username單詞。會話最終會逾時,或者你通過Ctrl + C手動退出。

expect()方法需等待子應用程式傳回給定的字元串,是以在前面的示例中,如果要同時容納小寫和大寫u,則可以使用以下指令:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

方括号用作or操作,告訴子應用程式期望小寫或大寫u後跟sername作為字元串。我們告訴流程的是将接受Username或username作為預期字元串。

警告:有關Python正規表達式的更多資訊,請參考:

https: //docs.python.org/3.5/library/re.html 。

expect()方法還可以包含選項清單,而不是僅包含單個字元串,這些選項還可以是正規表達式。回到上一個示例,你可以使用以下選項清單來容納兩個不同的字元串:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

一般來說,當要在正規表達式中使用不同的主機名時,将正規表達式用于單個expect字元串,而如果需要從路由器捕獲完全不同的響應(例如密碼拒絕),請加入相應的選項。例如,如果登入時使用多個不同的密碼,則需要捕獲% Login invalid以及裝置提示。

Pexpect正規表達式和Python正規表達式之間的一個重要差別是:Pexpect是非貪婪比對模式,這意味着在使用特殊字元時将盡可能少比對。因為Pexpect在一個流上實施正規表達式比對時,生成這個流的子程序可能還沒有結束,是以在流中很難預測。這意味着通常與行尾比對的特殊美元符号$是無效的,因為字元.+将始終不傳回任何字元,而字元.*模式又是盡可能少比對。請記住,一般情況下expect比對字元串越具體越好。

我們考慮以下場景:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章
帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

這裡不太對勁。将它與之前的終端輸出進行比較,你期望的輸出将是hostname iosv-1:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

仔細看看預期的字元串就可發現錯誤。在這種情況下,我們漏掉了iosv-1主機名後面的哈希(#)符号。是以,子應用程式将傳回字元串的第二部分視為預期的字元串:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

在幾個例子之後,你可以看到使用Pexpect時出現的模式。使用者映射Pexpect程序和子應用程式之間的互動順序。通過一些Python變量和循環,我們可以開始建構一個有用的程式,幫助我們收集資訊并對網絡裝置進行更改。

2.3.3 第一個Pexpect程式

第一個程式chapter2_1.py通過一些額外的代碼擴充了我們在上一節中所做的工作:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

在第5行使用嵌套字典:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

嵌套字典允許我們使用适當的IP位址和提示符号來引用同一裝置(例如iosv-1)。然後我們可以在循環中将這些值用于expect()方法。

将show version | i V輸出列印到每個裝置的螢幕上:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

2.3.4 Pexpect的更多功能

在本小節中,我們将介紹更多Pexpect功能,這些功能在某些情況下可能會派上用場。

如果你的遠端裝置有慢速或快速連結,則expect()方法預設的逾時為30秒,可以通過設定timeout參數增加或減少逾時時間:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

你可以選擇使用interact()方法将指令傳回使用者。當隻想自動執行初始任務的某些部分時,這非常有用:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

可以以字元串的格式列印有關child.spawn對象的大量資訊:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章
帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

Pexpect最有用的調試工具是将輸出記錄在一個檔案中:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

警告:對Python 2使用child.logfile = open('debug','w')。預設情況下,Python 3使用位元組字元串。有關Pexpect功能的更多資訊,請檢視:

https://pexpect.readthedocs.io/en/stable/api/index.

html 。

2.3.5 Pexpect和SSH

如果你嘗試使用以前的Telnet示例并将其插入SSH會話中,可能會發現自己對這種體驗感到非常沮喪。你總是必須在會話中包含使用者名,回答ssh新鍵問題等。幸運的是,有許多方法可以進行SSH會話工作,Pexpect有一個名為pxssh的子類,它專門用于建立SSH連接配接。該類添加了登入、登出和各種複雜的方法來處理ssh登入過程中的不同情況。除了login()和logout()之外,其餘方法大緻相同:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

請注意login()方法中的auto_prompt_reset = False參數。預設情況下,pxssh使用Shell提示符同步輸出。但由于它在大多數bash或CSH中使用PS1選項,是以在Cisco或其他網絡裝置上會出錯。

2.3.6 将Pexpect的所有内容都放到腳本中

最後一步,我們将迄今為止學到的關于Pexpect的所有内容都放到腳本中。将代碼放入腳本可以更輕松地在開發環境中使用,也可以更輕松地與同僚共享。我們将編寫第二個腳本chapter2_2.py。

警告:你可以從GitHub倉庫

https://github.com/PacktPublishing/Mastering-Python-Networking-

second-edition 下載下傳該腳本,并檢視指令行輸出。

請參閱以下代碼:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

該腳本進一步擴充了第一個Pexpect程式,具有以下附加功能:

  • 使用SSH代替Telnet。
  • 通過将指令放入清單(第8行)并循環執行指令(從第20行開始)來達到支援多個指令而不是僅支援一個指令的目的。
  • 提示使用者輸入使用者名和密碼,而不是在腳本中對其進行寫死。
  • 将輸出寫入兩個檔案iosv-1_output.txt和ios-2_output.txt中進行進一步分析。

提示:對于Python 2,使用raw_input()而不是input()作為使用者名提示。另外,使用w而不是wb作為檔案模式。

2.4 Python Paramiko庫

Paramiko是SSHv2協定的Python實作。就像Pexpect的pxssh子類一樣,Paramiko簡化了主機和遠端裝置之間的SSHv2互動。與pxssh不同,Paramiko隻關注沒有Telnet支援的SSHv2。它還提供用戶端和伺服器操作。

Paramiko是其網絡子產品的進階自動化架構Ansible背後的低級SSH用戶端。我們将在後面的章節中介紹Ansible。下面我們來看看Paramiko庫。

2.4.1 Paramiko安裝

使用Python pip安裝Paramiko非常簡單。但是,密碼庫存在嚴重依賴性。該庫為SSH協定提供了基于C的低級加密算法。

有關Windows、Mac和其他Linux版本的安裝說明,請通路:

https://cryptography.io/en/latest/installation/ 。

我們将在以下輸出中說明Ubuntu 16.04虛拟機中的Paramiko安裝。以下輸出說明了安裝步驟以及在Python互動式環境中導入Paramiko的步驟。

如果使用的是Python 2,請按照以下步驟操作。我們将嘗試在互動式提示中導入庫以確定可以使用庫:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

如果使用的是Python 3,請參閱以下指令行安裝依賴項。安裝後,我們将導入庫以確定它已正确安裝:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

2.4.2 Paramiko概述

讓我們看一下使用Python 3互動式shell的Paramiko例子:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章
帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

提示:time.sleep()函數插入時間延遲以確定捕獲所有輸出。這在較慢的網絡連接配接或繁忙的裝置上特别有用。此指令不是必需的,建議根據具體情況而定。

即使你是第一次看到Paramiko操作,Python美妙清晰的文法也可以使你直覺地推斷出程式的功能:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

前4行建立了Paramiko的SSHClient類的執行個體。下一行設定用SSH伺服器的主機名連接配接時用戶端應使用的政策,在這種情況下,iosv-1不出現在系統主機密鑰或應用程式密鑰中。在我們的場景中,會自動将密鑰添加到應用程式的HostKeys對象。此時,如果你登入路由器,将看到Paramiko的其他登入會話:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

接下來的幾行從連接配接中調用一個新的互動式shell,以及一個發送指令和檢索輸出的可重複模式。最後,我們關閉連接配接。

一些之前使用過Paramiko的讀者可能會使用exec_command()方法而不是調用shell。為什麼我們需要調用互動式shell而不是直接使用exec_command()呢?因為不幸的是,Cisco IOS上的exec_command()隻允許一個指令。考慮以下帶有exec_command()的連接配接示例:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

一切都很好,但是,如果檢視Cisco裝置上的會話數,你會注意到Cisco裝置在沒有關閉連接配接的情況下斷開連接配接:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

由于SSH會話不再處于活動狀态,是以如果要向遠端裝置發送更多指令,exec_command()将傳回錯誤:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

提示:Kirk Byers的Netmiko庫是一個開源Python庫,簡化了對網絡裝置的SSH管理。要閱讀它,請檢視位于

https://pynet.twb-tech.com/blog/automation/

netmiko.html 的文章和位于

https://github.com/ktbyers/netmiko

的源代碼。

如果你沒有清除接收的緩沖區會發生什麼?輸出将繼續填充緩沖區并覆寫它:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章
帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

為了确定輸出的一緻性,我們将在每次執行指令時從緩沖區中檢索輸出。

2.4.3 第一個Paramiko程式

第一個程式将使用與之前整理的Pexpect程式相同的通用結構。我們将使用Paramiko而不是Pexpect循環周遊裝置和指令清單。這裡可以很好地将Paramiko和Pexpect進行對比。

如果你還沒有這樣做,可以從本書的GitHub倉庫下載下傳代碼chapter2_3.py,位于

https://github.com/PacktPublishing/Mastering-Python-

Networking-second-edition。我将列出這裡的明顯差異:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

我們不再需要使用Paramiko來比對裝置提示,是以,裝置字典可以簡化:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

Paramiko沒有與sendline相似的指令,相反,在每個指令中需要手動輸入newline:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

因為不需要這些指令的輸出,我們提供了一種新方法來清除緩沖區以發送指令(例如terminal length 0或enable)。我們隻想清除緩沖區并進入執行提示。稍後将在循環中使用此函數,例如腳本的第25行:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

程式的其餘部分應該是非常清晰的,類似于我們在本章中已看到的。我要指出的最後一件事是,由于這是一個互動式程式,需放置一些緩沖區并等待指令在遠端裝置上完成,然後再檢索輸出:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

清除緩沖區後,在執行指令之間的時間内,我們将等待兩秒。如果裝置繁忙,這将為裝置提供足夠的響應時間。

2.4.4 Paramiko的更多功能

讨論Ansible時,一般會同時讨論Paramiko,因為Paramiko是許多網絡子產品的基礎傳輸。在本節中,我們将介紹Paramiko的一些其他功能。

Paramiko伺服器

Paramiko也可通過SSHv2管理伺服器。我們看一下如何使用Paramiko來管理伺服器。我們将對SSHv2會話使用基于密鑰的身份驗證。

提示:在此示例中,我在與目标伺服器相同的虛拟機管理程式上使用了另一個Ubuntu虛拟機。你還可以使用VIRL模拟器上的伺服器或其中一個公共雲提供程式(例如Amazon AWS EC2)中的執行個體。

我們将為Paramiko主機生成公鑰–私鑰對:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

預設情況下,此指令将生成名為id_rsa.pub的公鑰以及名為id_rsa的私鑰放在使用者主目錄~/.ssh下。可以将私鑰看作不想與其他人共享的私人密碼,将公鑰視為可識别身份的名片。使用私鑰和公鑰,郵件将在本地由你的私鑰加密,并由遠端主機使用公鑰解密。我們應該将公鑰複制到遠端主機。在實際應用中,可以通過使用一個外置的USB驅動器來實作;在我們的實驗中,可以簡單地将公鑰複制到遠端主機的~/.ssh/authorized_keys檔案中。但需要打開遠端伺服器的終端視窗,以便粘貼公鑰。

使用Paramiko複制管理主機上~/.ssh/id_rsa的内容:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

然後,将其粘貼到使用者目錄下的遠端主機上,這種情況下,雙方應使用echou:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

現在可以使用Paramiko來管理遠端主機。請注意,在此示例中,我們将使用私鑰進行身份驗證,并使用exec_command()方法發送指令:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章
帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

請注意,在伺服器示例中,不需要建立互動式會話來執行多個指令。現在可以在遠端主機的SSHv2配置中關閉基于密碼的身份驗證,以便在啟用自動化的情況下實作更安全的基于密鑰的身份驗證。某些網絡裝置(如Cumulus和Vyatta交換機)也支援基于密鑰的身份驗證。

2.4.5 Paramiko可重用性

在本章的最後,讓Paramiko程式更具可重用性。現在的腳本有一個缺點:每次我們想要添加/删除主機或者更改想要在遠端主機上執行的指令時,都需要打開腳本。這是因為主機和指令資訊都是靜态輸入到腳本中的。寫死主機和指令有更高的錯誤率。此外,如果要将腳本傳給同僚,他們可能會覺得在Python、Paramiko或Linux中工作不舒服。

通過将主機和指令檔案作為腳本的參數讀入,可以消除其中的一些問題。當需要進行主機或指令更改時,使用者可以簡單地修改這些文本檔案。

我們已将更改合并到名為chapter2_4.py的腳本中。

我們将指令分解為單獨的commands.txt檔案,而不是對指令進行寫死。到目前為止,我們一直在使用show指令,在這個例子中,我們将更改配置。特别是,将日志記錄緩沖區大小更改為30000位元組:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

裝置的資訊将寫入devices.json檔案。我們選擇JSON格式來記錄裝置的資訊,因為JSON資料類型可以很容易地轉換為Python字典資料類型:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

在腳本中,我們進行了以下更改:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

這是腳本執行的縮略輸出:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章
帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

快速檢查以確定在running-config和startup-config中都有更改:

帶你讀《Python網絡程式設計(原書第2版)》之二:低級網絡裝置互動第2章

2.5 展望

就使用Python來自動化網絡而言,我們在本章中有了相當大的飛躍。但是,我們使用的方法感覺有點像自動化的變通方案。我們試圖欺騙遠端裝置使其認為正在與另一端的人進行互動。

與其他工具相比Pexpect和Paramiko的缺點

到目前為止,我們的方法的最大缺點是遠端裝置不傳回結構化資料,它們傳回的資料非常适合在終端上由人類而不是計算機程式來解釋。人類可以輕松地解釋空間,而計算機隻能看到傳回的字元。

我們将在接下來的章節中看到更好的方法。作為第3章的前奏,讓我們先來讨論幂等性的概念。

幂等網絡裝置互動

幂等性一詞具有不同的含義,取決于其背景。但在本書的上下文中,該術語意味着當用戶端對遠端裝置進行相同的調用時,結果應始終相同。我相信我們都同意這是必要的。想象一下每次執行相同的腳本時得到不同的結果,這種情況是多麼可怕。如果是這樣的話,你怎麼能相信你的腳本?它會使自動化工作變得無用,因為我們需要準備好處理不同的回調結果。

由于Pexpect和Paramiko以互動方式拼出一系列指令,是以進行非幂等互動的可能性更大。對有用元素進行螢幕截取才能傳回結果這一事實使得産生差異的風險要高很多。遠端端的某些内容可能在我們編寫腳本和腳本第100次執行之間發生了變化。例如,如果供應商在不更新腳本的情況下在版本之間更改螢幕輸出,則腳本可能會中斷。

如果我們需要依賴腳本進行實驗,則需要腳本盡可能具有幂等性。

糟糕的自動化使錯誤加劇

糟糕的自動化會使你大跌眼鏡。計算機執行任務的速度比人類工程師快得多。如果我們使人類與腳本執行相同的操作程式集,則腳本将比人類快很多,有時甚至沒有在程式之間建立可靠的回報循環。當有人按下Enter鍵并立即後悔時,網際網路上就會充滿恐怖的事情。

我們需要確定自動化腳本錯誤的可能性盡量小。我們都會犯錯,在任何實驗工作開始之前仔細測試你的腳本和确定錯誤範圍是確定你在錯誤發生之前發現錯誤的關鍵。

2.6 小結

在本章中,我們介紹了與網絡裝置直接通信的低級方法。如果沒有辦法以程式設計方式進行通信并對網絡裝置進行更改,則無法實作自動化。我們介紹了Python中的兩個庫,它們允許我們管理要由CLI管理的裝置。雖然很有用,但很容易看出這個過程有多麼脆弱。這主要是因為有問題的網絡裝置是由人類而不是計算機管理的。

在第3章中,我們将介紹支援API和意圖驅動網絡的網絡裝置。