銀狐NetDevOps-網絡運維python指南之自動生成yaml文件+華爲nornir批量操作 01 前言 02 實現邏輯 03 代碼示例 04 代碼詳解

01 前言

前段時間分享了華爲NETCONF結合協程gevent,在大規模數據中心自動化批量操作的方法,不過我忽略了兩個問題,一個是協程gevent的加入會讓排錯難度大幅提升,導致很多小夥伴自己應用時無限掉坑被逼瘋,第二是gevent在windows環境下總會出現莫名其妙的問題,而很多使用者對linux又不算熟悉,最終導致很多人使用gevent並不順利。

秉着簡單易用的原則,我重新研究了下nornir這個專爲網絡而生的模塊,個人感覺3000臺以下網絡設備的簡單跑批操作使用nr就可以了。相比於ansible來說這個模塊在效率和靈活性上都有質的飛躍,相比協程+api的方式又簡單了許多,相比單獨的netmiko模塊又有更多的優化。所以中小規模企業推薦直接使用nornir。nornir的基礎知識王印老師(知乎@弈心)已經做過介紹,華爲安裝的一些坑朱嘉盛老師也介紹過,這些內容直接在知乎搜索即可,我就不重複介紹了。

雖然nr模塊確實非常好用,但從實踐的角度我發現一個問題,就是從現有的資料來看並不適合大規模跑批操作,因爲網上分享的內容(包括官方案例)都有一個問題,就是nr模塊強依賴hosts.yaml這個文件,但沒人強調如何大批量導入資產信息到這個yaml文件內,如果你有1000臺設備,按照yaml格式一個一個輸入到yaml文件裏手都要斷了,所以我手寫了一個自動生成hosts.yaml+nr跑批的py腳本,這樣在大規模場景下更加實用。

02 實現邏輯

  1. 簡化hosts.yaml內部配置,只保存設備名稱和IP地址(yaml內的hostname),用戶名、密碼、platform全放在defaults.yaml中,不使用group.yaml(想使用也可以,因爲我這個內容主要是HUAWEI,沒有第二個廠商,所以不需要)。
config.yaml

---
inventory:
    plugin: SimpleInventory
    options:
        host_file: "hosts.yaml"
        defaults_file: "defaults.yaml"
runner:
    plugin: threaded
    options:
        num_workers: 20

defaults.yaml

---
username: user
password: pass
platform: huawei_vrpv8

  1. 讀取excel內容(excel內容如下:),形成dict,在用dict專爲yaml文件,生成hosts.yaml,再使用nornir進行跑批操作。

03 代碼示例

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

import os
from pprint import pprint
from ruamel import yaml
#ruamel.yaml用來讀寫yaml文件
from openpyxl import Workbook
from openpyxl import load_workbook
from collections import defaultdict
#使用defaultdict必須導入
from nornir import InitNornir
from nornir_netmiko import netmiko_send_command
from nornir_utils.plugins.functions import print_result,print_title

def read_device_excel():
    current_path = os.path.abspath(".")
    devices_filename = current_path + "/info02.xlsx"
    wb1 = load_workbook(devices_filename)
    ws1 = wb1.get_sheet_by_name("device list")
    device_dict = defaultdict(dict)

    for cow_num in range(2,ws1.max_row+1):
        device_dict[ws1["a"+str(cow_num)].value.strip()]["hostname"]=ws1["b"+str(cow_num)].value.strip()
    return (dict(device_dict))

def dict_to_yaml(yaml_file):
    device_dict = read_device_excel()
    with open(yaml_file, 'w', encoding='utf-8') as file:
        file.write("---\\n")
        yaml.dump(device_dict, file, Dumper=yaml.RoundTripDumper)

def main():
    current_path = os.path.abspath(".")
    yaml_path = os.path.join(current_path, "hosts.yaml")
    dict_to_yaml(yaml_path)

    nr = InitNornir(config_file="config.yaml", dry_run=True)
    results = nr.run(netmiko_send_command, command_string='disp ver') 
    print_result(results)

#===========================================================
# 讀取excel內容自動生成hosts.yaml文件,再使用nr進行跑批操作
#===========================================================
if __name__ == '__main__':
    main()

執行結果(示例我就執行了1臺)

netmiko_send_command************************************************************
* SHM-RO4-POD2-1 ** changed : False ********************************************
vvvv netmiko_send_command ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
Huawei Versatile Routing Platform Software
VRP (R) software, Version 8.150 (CE6851HI V200R002C50SPC018T)
Copyright (C) 2012-2017 Huawei Technologies Co., Ltd.
HUAWEI CE6851-48S6Q-HI uptime is 1476 days, 2 hours, 26 minutes

CE6851-48S6Q-HI(Master) 1 : uptime is  1476 days, 2 hours, 25 minutes
        StartupTime 2017/06/09   14:44:20
Memory    Size    : 2048 M bytes
Flash     Size    : 1024 M bytes
CE6851-48S6Q-HI version information
1\. PCB    Version : CEM48S6QP04    VER B
2\. MAB    Version : 1
3\. Board  Type    : CE6851-48S6Q-HI
4\. CPLD1  Version : 103
5\. CPLD2  Version : 103
6\. BIOS   Version : 383
^^^^ END netmiko_send_command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

04 代碼詳解

def read_device_excel():
    current_path = os.path.abspath(".")
    devices_filename = current_path + "/info02.xlsx"
    wb1 = load_workbook(devices_filename)
    ws1 = wb1.get_sheet_by_name("device list")
    device_dict = defaultdict(dict)

    for cow_num in range(2,ws1.max_row+1):
        device_dict[ws1["a"+str(cow_num)].value.strip()]["hostname"]=ws1["b"+str(cow_num)].value.strip()
    return (dict(device_dict))

看過我分享的都比較熟悉上面的代碼了,就不做介紹了,主要說下defaultdict(dict),這個可以用作嵌套dict,比如要根據已知內容生成{'SHM-RO4-POD2-1': {'hostname': '10.13.0.224'}},那我們就用for循環遍歷excel內容,然後以A列爲key,hostname:B列內容作爲value,生成嵌套dict。

def dict_to_yaml(yaml_file):
    device_dict = read_device_excel()
    with open(yaml_file, 'w', encoding='utf-8') as file:
        file.write("---\\n")
        yaml.dump(device_dict, file, Dumper=yaml.RoundTripDumper)

使用yaml.dump()方法將dict內容以標準yaml格式寫入hosts.yaml文件,注意需要加參數Dumper=yaml.RoundTripDumper。

生成的hosts.yaml

---
SHM-RO4-POD2-1:
  hostname: 10.13.0.224
SHM-RO4-POD2-2:
  hostname: 10.13.0.225
SHM-RO4-POD2-3:
  hostname: 10.13.0.226
SHM-RO4-POD2-4:
  hostname: 10.13.0.227

def main():
    current_path = os.path.abspath(".")
    yaml_path = os.path.join(current_path, "hosts.yaml")
    dict_to_yaml(yaml_path)

    nr = InitNornir(config_file="config.yaml", dry_run=True)
    results = nr.run(netmiko_send_command, command_string='disp ver') 
    # results = nr.run(task=napalm_get, getters=["facts"])   #napalm API不好用
    print_result(results)

主函數很簡單,調用生成yaml文件的方法,然後使用Nornir進行跑批操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章