如何使用 Python 和 Netmiko 自動創建網絡設備 VLAN,受益頗深!

2024年2月6日 25点热度 0人点赞

你好,這裡是網絡技術聯盟站,我是瑞哥。

在現代網絡中,自動化是網絡管理的重要一環。通過使用Python編程語言和Netmiko庫,我們可以簡化並提高VLAN(Virtual Local Area Network)的創建過程。VLAN允許我們將網絡設備劃分為邏輯上的獨立網絡,提高網絡的性能、安全性和管理效率。

在開始自動執行VLAN創建之前,我們需要進行一些準備工作,確保系統處於適當的狀態。

安裝 Python

在Windows上安裝Python

  1. 訪問Python官方網站

前往 Python官方網站https://www.python.org/downloads下載最新版本的Python。

  1. 下載安裝程序

在網站上選擇適用於Windows的Python版本,通常為一個exe文件。雙擊下載的安裝程序以啟動安裝。

  1. 設置安裝選項

在安裝過程中,確保勾選 "Add Python to PATH" 選項,這將使Python可在命令行中直接訪問。

  1. 完成安裝

點擊 "Install Now" 開始安裝,等待安裝程序完成。

  1. 驗證安裝

打開命令提示符(Command Prompt)或PowerShell,並輸入以下命令來驗證Python是否正確安裝:

python --version

或者,使用以下命令查看Python的交互式Shell:

python

如果成功安裝,你將看到Python版本信息。

在Mac上安裝Python

Mac通常預裝有Python,但為了確保使用最新版本或進行自定義安裝,可以按照以下步驟操作:

  1. 使用Homebrew安裝(推薦):

如果你使用了Homebrewhttps://brew.sh包管理器,可以使用以下命令安裝Python:

brew install python
  1. 手動安裝

前往Python官方網站https://www.python.org/downloads下載最新版本的Python。

  1. 安裝

雙擊下載的pkg文件,按照提示完成安裝。

  1. 驗證安裝

打開終端,並輸入以下命令驗證Python是否正確安裝:

python3 --version

或者,使用以下命令查看Python的交互式Shell:

python3

如果成功安裝,你將看到Python版本信息。

在Linux上安裝Python

大多數Linux發行版都預裝有Python,你可以通過包管理器安裝或更新。

使用包管理器

  1. Debian/Ubuntu
sudo apt-get update
sudo apt-get install python3
  1. Fedora
sudo dnf install python3
  1. openSUSE
sudo zypper install python3

通過源代碼安裝

  1. 下載源代碼

前往Python官方網站https://www.python.org/downloads/source下載Python的源代碼壓縮包。

  1. 解壓縮源代碼

在終端中進入解壓縮後的目錄,並執行以下命令:

./configure
make
sudo make install
  1. 驗證安裝

在終端中輸入以下命令驗證Python是否正確安裝:

python3 --version

或者,使用以下命令查看Python的交互式Shell:

python3

如果成功安裝,你將看到Python版本信息。

設置虛擬環境

虛擬環境可以隔離項目的依賴,防止與其他項目沖突。使用以下命令創建和激活虛擬環境:

# 安裝 virtualenv
pip install virtualenv
# 創建虛擬環境
python -m venv myenv
# 激活虛擬環境
# 在 Windows 上:
myenv\Scripts\activate
# 在 Linux 或 macOS 上:
source myenv/bin/activate

安裝 Netmiko

Netmiko是一個用於處理網絡設備的Python庫,支持多種設備類型。使用以下命令安裝Netmiko:

pip install netmiko

Netmiko基於SSH協議,因此確保你的網絡設備支持SSH,並且已經正確配置和啟用。

編寫 Python 腳本

我們將創建一個簡單的Python腳本,該腳本連接到Cisco設備並執行VLAN創建過程。

連接到設備

首先,我們需要建立與網絡設備的連接。創建一個Python腳本,命名為 create_vlan.py

from netmiko import ConnectHandler
device = {
    'device_type': 'cisco_ios',
    'ip': '設備IP地址',
    'username': '你的用戶名',
    'password': '你的密碼',
}
connection = ConnectHandler(**device)

這段代碼使用Netmiko的 ConnectHandler 類建立到Cisco設備的SSH連接。請替換 '設備IP地址''你的用戶名''你的密碼' 為實際設備的信息。

創建 VLAN

接下來,我們將編寫代碼來創建一個新的VLAN。在Cisco設備上,我們可以使用 vlan 命令來完成。

vlan_id = 100
vlan_name = 'vlan_name'
vlan_command = f"vlan {vlan_id}\nname {vlan_name}"
connection.send_config_set([vlan_command])

這段代碼定義了VLAN的ID和名稱,然後使用 send_config_set 方法將配置命令發送到設備。這裡我們使用了格式化字符串 f"vlan {vlan_id}\nname {vlan_name}" 來生成VLAN配置命令。

驗證配置

為了確保VLAN創建成功,我們可以執行 show vlan brief 命令,並輸出結果。

output = connection.send_command('show vlan brief')
print(output)

這段代碼使用 send_command 方法向設備發送命令,並將結果存儲在 output 變量中。然後通過 print(output) 打印結果。

關閉連接

最後,我們在腳本的末尾關閉與設備的連接,釋放資源。

connection.disconnect()

完整的腳本如下:

from netmiko import ConnectHandler
device = {
    'device_type': 'cisco_ios',
    'ip': '設備IP地址',
    'username': '你的用戶名',
    'password': '你的密碼',
}
connection = ConnectHandler(**device)
# 創建 VLAN
vlan_id = 100
vlan_name = 'vlan_name'
vlan_command = f"vlan {vlan_id}\nname {vlan_name}"
connection.send_config_set([vlan_command])
# 驗證配置
output = connection.send_command('show vlan brief')
print(output)
# 關閉連接
connection.disconnect()

保存並運行腳本:

python create_vlan.py

添加錯誤處理

在真實的網絡環境中,很可能會遇到各種問題,如設備不可達、認證失敗等。為了增加腳本的魯棒性,我們可以添加一些錯誤處理。

from netmiko import ConnectHandler, SSHException
device = {
    'device_type': 'cisco_ios',
    'ip': '設備IP地址',
    'username': '你的用戶名',
    'password': '你的密碼',
}
try:
    connection = ConnectHandler(**device)
    # 創建 VLAN
    vlan_id = 100
    vlan_name = 'vlan_name'
    vlan_command = f"vlan {vlan_id}\nname {vlan_name}"
    connection.send_config_set([vlan_command])
    # 驗證配置
    output = connection.send_command('show vlan brief')
    print(output)
except SSHException as e:
    print(f"SSH連接錯誤: {e}")
finally:
    # 關閉連接
    if 'connection' in locals():
        connection.disconnect()

在這個腳本中,我們使用了 tryexceptfinally 來進行錯誤處理。如果在 try 塊中發生SSHException,腳本將捕獲異常並打印錯誤消息,然後執行 finally 塊中的關閉連接操作。

從配置文件讀取設備信息

為了增加腳本的靈活性,我們可以將設備信息存儲在一個單獨的配置文件中,以便在不同場景下輕松修改。

創建一個名為 device_config.ini 的配置文件:

[device]
device_type = cisco_ios
ip = 設備IP地址
username = 你的用戶名
password = 你的密碼

修改腳本以從配置文件讀取設備信息:

from netmiko import ConnectHandler, SSHException
from configparser import ConfigParser
config = ConfigParser()
config.read('device_config.ini')
device = {
    'device_type': config['device']['device_type'],
    'ip': config['device']['ip'],
    'username': config['device']['username'],
    'password': config['device']['password'],
}
try:
    connection = ConnectHandler(**device)
    # 創建 VLAN
    vlan_id = 100
    vlan_name = 'vlan_name'
    vlan_command = f"vlan {vlan_id}\nname {vlan_name}"
    connection.send_config_set([vlan_command])
    # 驗證配置
    output = connection.send_command('show vlan brief')
    print(output)
except SSHException as e:
    print(f"SSH連接錯誤: {e}")
finally:
    # 關閉連接
    if 'connection' in locals():
        connection.disconnect()

這樣,你可以通過修改 device_config.ini 文件來輕松更改設備信息,而無需直接修改腳本。

批量創建 VLAN

在實際網絡中,可能需要一次性在多個設備上創建相同的VLAN。為了實現這一點,我們可以將設備信息存儲在一個列表中,並使用循環在每個設備上執行相同的操作。

from netmiko import ConnectHandler, SSHException
from configparser import ConfigParser
config = ConfigParser()
config.read('device_config.ini')
devices = [
    {
        'device_type': config['device']['device_type'],
        'ip': '設備1的IP地址',
        'username': config['device']['username'],
        'password': config['device']['password'],
    },
    {
        'device_type': config['device']['device_type'],
        'ip': '設備2的IP地址',
        'username': config['device']['username'],
        'password': config['device']['password'],
    },
    # 添加更多設備
]
for device in devices:
    try:
        connection = ConnectHandler(**device)
        # 創建 VLAN
        vlan_id = 100
        vlan_name = 'vlan_name'
        vlan_command = f"vlan {vlan_id}\nname {vlan_name}"
        connection.send_config_set([vlan_command])
        # 驗證配置
        output = connection.send_command('show vlan brief')
        print(output)
    except SSHException as e:
        print(f"SSH連接錯誤({device['ip']}): {e}")
    finally:
        # 關閉連接
        if 'connection' in locals():
            connection.disconnect()

通過在 devices 列表中添加更多設備,可以在一次運行中批量創建相同的VLAN。

使用函數進行模塊化

為了提高腳本的可讀性和維護性,我們可以將不同的功能模塊化,將其放入函數中。

from netmiko import ConnectHandler, SSHException
from configparser import ConfigParser
def connect_to_device(device):
    try:
        connection = ConnectHandler(**device)
        return connection
    except SSHException as e:
        print(f"SSH連接錯誤({device['ip']}): {e}")
        return None
def create_vlan(connection, vlan_id, vlan_name):
    vlan_command = f"vlan {vlan_id}\nname {vlan_name}"
    connection.send_config_set([vlan_command])
def verify_vlan(connection):
    output = connection.send_command('show vlan brief')
    print(output)
def disconnect_from_device(connection):
    connection.disconnect()
def main():
    config = ConfigParser()
    config.read('device_config.ini')
    devices = [
        {
            'device_type': config['device']['device_type'],
            'ip': '設備1的IP地址',
            'username': config['device']['username'],
            'password': config['device']['password'],
        },
        {
            'device_type': config['device']['device_type'],
            'ip': '設備2的IP地址',
            'username': config['device']['username'],
            'password': config['device']['password'],
        },
        # 添加更多設備
    ]
    for device in devices:
        connection = connect_to_device(device)
        if connection:
            create_vlan(connection, vlan_id=100, vlan_name='vlan_name')
            verify_vlan(connection)
            disconnect_from_device(connection)
if __name__ == "__main__":
    main()

通過將連接設備、創建VLAN、驗證配置和斷開連接等操作封裝成函數,我們可以更清晰地組織腳本,並使其更易於維護。

使用 Jinja2 模板生成配置

在實際網絡環境中,可能會有大量相似的配置任務,例如在多個設備上創建相同的VLAN。為了更靈活地生成配置,我們可以使用 Jinja2 模板引擎。

首先,安裝 Jinja2:

pip install jinja2

然後,創建一個 Jinja2 模板文件,命名為 vlan_template.j2

vlan {{ vlan_id }}
 name {{ vlan_name }}

修改腳本,使用 Jinja2 模板引擎加載模板並生成配置:

from netmiko import ConnectHandler, SSHException
from configparser import ConfigParser
from jinja2 import Environment, FileSystemLoader
def render_template(template_path, **kwargs):
    env = Environment(loader=FileSystemLoader('.'))
    template = env.get_template(template_path)
    return template.render(kwargs)
def connect_to_device(device):
    try:
        connection = ConnectHandler(**device)
        return connection
    except SSHException as e:
        print(f"SSH連接錯誤({device['ip']}): {e}")
        return None
def create_vlan(connection, vlan_id, vlan_name):
    vlan_template = render_template('vlan_template.j2', vlan_id=vlan_id, vlan_name=vlan_name)
    connection.send_config_set([vlan_template])
def verify_vlan(connection):
    output = connection.send_command('show vlan brief')
    print(output)
def disconnect_from_device(connection):
    connection.disconnect()
def main():
    config = ConfigParser()
    config.read('device_config.ini')
    devices = [
        {
            'device_type': config['device']['device_type'],
            'ip': '設備1的IP地址',
            'username': config['device']['username'],
            'password': config['device']['password'],
        },
        {
            'device_type': config['device']['device_type'],
            'ip': '設備2的IP地址',
            'username': config['device']['username'],
            'password': config['device']['password'],
        },
        # 添加更多設備
    ]
    for device in devices:
        connection = connect_to_device(device)
        if connection:
            create_vlan(connection, vlan_id=100, vlan_name='vlan_name')
            verify_vlan(connection)
            disconnect_from_device(connection)
if __name__ == "__main__":
    main()

這樣,我們可以使用 Jinja2 模板生成更復雜的配置,並輕松地在不同的設備上執行相同的配置任務。

使用異常處理改進腳本穩定性

在網絡自動化中,異常處理是至關重要的。當我們嘗試連接設備、發送配置或執行其他操作時,可能會遇到各種錯誤。通過適當的異常處理,我們可以使腳本更加穩定和可靠。

from netmiko import ConnectHandler, SSHException
from configparser import ConfigParser
def connect_to_device(device):
    try:
        connection = ConnectHandler(**device)
        return connection
    except SSHException as e:
        print(f"SSH連接錯誤({device['ip']}): {e}")
        return None
    except Exception as e:
        print(f"連接設備({device['ip']})時出現錯誤: {e}")
        return None
def create_vlan(connection, vlan_id, vlan_name):
    try:
        vlan_command = f"vlan {vlan_id}\nname {vlan_name}"
        connection.send_config_set([vlan_command])
    except Exception as e:
        print(f"創建VLAN({vlan_id})時出現錯誤: {e}")
def verify_vlan(connection):
    try:
        output = connection.send_command('show vlan brief')
        print(output)
    except Exception as e:
        print(f"驗證VLAN時出現錯誤: {e}")
def disconnect_from_device(connection):
    try:
        connection.disconnect()
    except Exception as e:
        print(f"斷開連接時出現錯誤: {e}")
def main():
    config = ConfigParser()
    config.read('device_config.ini')
    devices = [
        {
            'device_type': config['device']['device_type'],
            'ip': '設備1的IP地址',
            'username': config['device']['username'],
            'password': config['device']['password'],
        },
        {
            'device_type': config['device']['device_type'],
            'ip': '設備2的IP地址',
            'username': config['device']['username'],
            'password': config['device']['password'],
        },
        # 添加更多設備
    ]
    for device in devices:
        connection = connect_to_device(device)
        if connection:
            create_vlan(connection, vlan_id=100, vlan_name='vlan_name')
            verify_vlan(connection)
            disconnect_from_device(connection)
if __name__ == "__main__":
    main()

通過在關鍵部分添加適當的異常處理,我們可以提高腳本的魯棒性,並更好地處理可能出現的問題。

使用日志記錄

在復雜的自動化腳本中,輸出到控制臺的信息可能不足以進行詳細的故障排查。使用日志記錄可以幫助我們跟蹤腳本的執行過程,記錄關鍵事件和錯誤。

import logging
logging.basicConfig(filename='automation.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def connect_to_device(device):
    try:
        connection = ConnectHandler(**device)
        logging.info(f"連接到設備({device['ip']})成功")
        return connection
    except SSHException as e:
        logging.error(f"SSH連接錯誤({device['ip']}): {e}")
        return None
    except Exception as e:
        logging.error(f"連接設備({device['ip']})時出現錯誤: {e}")
        return None
# 在其他關鍵部分添加日志記錄

通過配置日志記錄,我們可以在執行過程中捕獲關鍵事件,並在需要時檢查日志文件以了解腳本的行為。

使用版本控制

版本控制是軟件開發中的重要實踐之一,它允許我們跟蹤代碼的變化並協作開發。將腳本存儲在版本控制系統(如Git)中可以使我們更好地管理代碼,並跟蹤變更歷史。

通過將腳本存儲在Git倉庫中,並定期提交和推送變更,我們可以確保腳本的安全和可追溯性。