在平时的网络运维工作中,网工少不了要给新设备做批量配置。其中一些配置比如line vty下的transport input ssh以及AAA、SNMP之类的属于共有配置,所有此类命令在所有设备上是统一没有差异的,写一个Python脚本用Paramiko、Netmiko或者pexpect等SSH模块就能轻松搞定。但是针对那些有差异化的配置,比如每个端口下的description(比如用来描述每个端口下面所连接的服务器的名称,服务器的物理端口(网卡)号,以及服务器的用途等等),每个端口的功能(access port还是trunk port?如果是access port,access哪个VLAN?因为存在差异,你不能简单的用一个interface range来一次性统一完成所有端口的配置)以及在不同交换机上划分和创建不同的VLAN id等等,光靠上述SSH模块是很难搞定的,就算能搞定,写出来的脚本的代码量也是相当庞大,不便于维护的。这时就有必要用到Jinja2这个模板引擎来帮助我们完成这些量大又有差异化的配置。
本文将以一台华为思科设备为例,讲解如何使用Jinja2来完成对该交换机多个端口的配置
华为篇:
ensp拓扑:
switch ports2.csv文件内容如下:
interface-template2.j2文件内容如下:
interface {{ interface }} description Link to {{ server }} port {{ port }} for {{ purpose }} {% if vlan == "Trunk" -%} port link-type trunk {% else -%} port link-type access port default vlan {{ vlan }} {% endif -%} undo shutdown
jinja2_peizhiSW.py文件内容如下:
from jinja2 import Template import csv from netmiko import ConnectHandler csv_file = open('switch ports2.csv') template_file = open('interface-template2.j2') reader = csv.DictReader(csv_file) interface_template = Template(template_file.read(), keep_trailing_newline=True) interface_configs = '' for row in reader: interface_config = interface_template.render( interface = row['Interface'], vlan = row['VLAN'], server = row['Server'], link = row['Port'], purpose = row['Purpose'] ) interface_configs += interface_config config_set = interface_configs.split('\n') SW = { 'device_type': 'huawei', 'ip': '192.168.88.1', 'username': 'admin', 'password': 'admin123', } connect = ConnectHandler(**SW) print ('Connected to switch') output = connect.send_config_set(config_set) #output = connect.send_config_set(config_set, cmd_verify=False) 注释这个是Netmiko 3需要的自身的一个"bug",我查看了我的netmiko是2所以不需要这个参数 print(output)
执行结果:
执行成功 cmd打印的 PS D:\Python_Files\python2020item\CSV_Jinja2> python .\jinja2_peizhiSW.py Connected to switch Traceback (most recent call last): File ".\jinja2_peizhiSW.py", line 35, inoutput = connect.send_config_set(config_set, cmd_verify=False) TypeError: send_config_set() got an unexpected keyword argument 'cmd_verify' PS D:\Python_Files\python2020item\CSV_Jinja2> PS D:\Python_Files\python2020item\CSV_Jinja2> PS D:\Python_Files\python2020item\CSV_Jinja2> python .\jinja2_peizhiSW.py Connected to switch system-view Enter system view, return user view with Ctrl+Z. [RR]interface Ethernet0/0/0 [RR-Ethernet0/0/0] description Link to esxi-01 port for VM Host [RR-Ethernet0/0/0] port link-type trunk [RR-Ethernet0/0/0] undo shutdown Info: Interface Ethernet0/0/0 is not shutdown. [RR-Ethernet0/0/0] [RR-Ethernet0/0/0]interface Ethernet0/0/1 [RR-Ethernet0/0/1] description Link to esxi-01 port for VM Host [RR-Ethernet0/0/1] port link-type trunk [RR-Ethernet0/0/1] undo shutdown Info: Interface Ethernet0/0/1 is not shutdown. [RR-Ethernet0/0/1] [RR-Ethernet0/0/1]interface Ethernet0/0/2 [RR-Ethernet0/0/2] description Link to esxi-02 port for VM Host [RR-Ethernet0/0/2] port link-type trunk [RR-Ethernet0/0/2] undo shutdown Info: Interface Ethernet0/0/2 is not shutdown. [RR-Ethernet0/0/2] [RR-Ethernet0/0/2]interface Ethernet0/0/3 [RR-Ethernet0/0/3] description Link to esxi-02 port for VM Host [RR-Ethernet0/0/3] port link-type trunk [RR-Ethernet0/0/3] undo shutdown Info: Interface Ethernet0/0/3 is not shutdown. [RR-Ethernet0/0/3] [RR-Ethernet0/0/3]interface Ethernet0/0/4 [RR-Ethernet0/0/4] description Link to db-01 port for Database Server [RR-Ethernet0/0/4] port link-type access [RR-Ethernet0/0/4] port default vlan 80 [RR-Ethernet0/0/4] undo shutdown Info: Interface Ethernet0/0/4 is not shutdown. [RR-Ethernet0/0/4] [RR-Ethernet0/0/4]interface Ethernet0/0/5 [RR-Ethernet0/0/5] description Link to db-02 port for Database Server [RR-Ethernet0/0/5] port link-type access [RR-Ethernet0/0/5] port default vlan 80 [RR-Ethernet0/0/5] undo shutdown Info: Interface Ethernet0/0/5 is not shutdown. [RR-Ethernet0/0/5] [RR-Ethernet0/0/5]interface Ethernet0/0/6 [RR-Ethernet0/0/6] description Link to app-01 port for App Server [RR-Ethernet0/0/6] port link-type access [RR-Ethernet0/0/6] port default vlan 80 [RR-Ethernet0/0/6] undo shutdown Info: Interface Ethernet0/0/6 is not shutdown. [RR-Ethernet0/0/6] [RR-Ethernet0/0/6]interface Ethernet0/0/7 [RR-Ethernet0/0/7] description Link to app-02 port for App Server [RR-Ethernet0/0/7] port link-type access [RR-Ethernet0/0/7] port default vlan 80 [RR-Ethernet0/0/7] undo shutdown Info: Interface Ethernet0/0/7 is not shutdown. [RR-Ethernet0/0/7] [RR-Ethernet0/0/7] [RR-Ethernet0/0/7]return PS D:\Python_Files\python2020item\CSV_Jinja2> ======================================================================================= 交换机配置也对应上了 [RR]dis cur [V200R003C00] # sysname RR # snmp-agent local-engineid 800007DB03000000000000 snmp-agent sys-info version v3 snmp-agent group v3 MyGroup privacy read-view View_ALL write-view View_ALL notify-view View_ALL snmp-agent target-host trap-hostname V3HOST address 192.168.88.3 udp-port 162 trap-paramsname V3TRAP snmp-agent target-host trap-paramsname V3TRAP v3 securityname MyUser privacy snmp-agent mib-view View_ALL include iso snmp-agent usm-user v3 MyUser MyGroup authentication-mode sha 4705BD8CE37634ECB4D7DE1D59E200E00DFF5B06 privacy-mode aes128 4705BD8CE37634ECB4D7DE1D59E200E00DFF5B06 snmp-agent trap source GigabitEthernet0/0/0 snmp-agent trap enable snmp-agent # clock timezone China-Standard-Time minus 08:00:00 # portal local-server load flash:/portalpage.zip # drop illegal-mac alarm # vlan batch 80 # wlan ac-global carrier id other ac id 0 # set cpu-usage threshold 80 restore 75 # aaa authentication-scheme default authorization-scheme default accounting-scheme default domain default domain default_admin local-user admin password cipher %$%$b^!*~`,kEQm{^F(k8;_ Please press ENTER to execute command [RR]dis int brie [RR]dis int brief PHY: Physical *down: administratively down (l): loopback (s): spoofing (b): BFD down ^down: standby (e): ETHOAM down (d): Dampening Suppressed InUti/OutUti: input utility/output utility Interface PHY Protocol InUti OutUti inErrors outErrors Ethernet0/0/0 down down 0% 0% 0 0 Ethernet0/0/1 down down 0% 0% 0 0 Ethernet0/0/2 down down 0% 0% 0 0 Ethernet0/0/3 down down 0% 0% 0 0 Ethernet0/0/4 down down 0% 0% 0 0 Ethernet0/0/5 down down 0% 0% 0 0 Ethernet0/0/6 down down 0% 0% 0 0 Ethernet0/0/7 down down 0% 0% 0 0 GigabitEthernet0/0/0 up up 0% 0% 0 0 GigabitEthernet0/0/1 down down 0% 0% 0 0 LoopBack3 up up(s) 0% 0% 0 0 LoopBack4 up up(s) 0% 0% 0 0 LoopBack6 up up(s) 0% 0% 0 0 LoopBack8 up up(s) 0% 0% 0 0 LoopBack9 up up(s) 0% 0% 0 0 LoopBack66 up up(s) 0% 0% 0 0 LoopBack88 up up(s) 0% 0% 0 0 NULL0 up up(s) 0% 0% 0 0 [RR] [RR] [RR]dis int des [RR]dis int description brei [RR]dis int description brie [RR]dis int description brie ^ Error: Wrong parameter found at '^' position. [RR]dis int description ? Ethernet Ethernet interface GigabitEthernet GigabitEthernet interface LoopBack LoopBack interface NULL NULL interface | Matching output Please press ENTER to execute command [RR]dis int description PHY: Physical *down: administratively down (l): loopback (s): spoofing (b): BFD down ^down: standby (e): ETHOAM down (d): Dampening Suppressed Interface PHY Protocol Description Eth0/0/0 down down Link to esxi-01 port for VM Host Eth0/0/1 down down Link to esxi-01 port for VM Host Eth0/0/2 down down Link to esxi-02 port for VM Host Eth0/0/3 down down Link to esxi-02 port for VM Host Eth0/0/4 down down Link to db-01 port for Database Server Eth0/0/5 down down Link to db-02 port for Database Server Eth0/0/6 down down Link to app-01 port for App Serv er Eth0/0/7 down down Link to app-02 port for App Serv er GE0/0/0 up up HUAWEI, AR Series, GigabitEtherne t0/0/0 Interface GE0/0/1 down down HUAWEI, AR Series, GigabitEtherne t0/0/1 Interface Loop3 up up(s) HUAWEI, AR Series, LoopBack3 Inte rface Loop4 up up(s) HUAWEI, AR Series, LoopBack4 Inte rface Loop6 up up(s) HUAWEI, AR Series, LoopBack6 Inte rface Loop8 up up(s) HUAWEI, AR Series, LoopBack8 Inte rface Loop9 up up(s) HUAWEI, AR Series, LoopBack9 Inte rface Loop66 up up(s) HUAWEI, AR Series, LoopBack66 Int erface Loop88 up up(s) HUAWEI, AR Series, LoopBack88 Int erface NULL0 up up(s) HUAWEI, AR Series, NULL0 Interfac e [RR]
思科篇:
实验拓扑:
switch ports-gns3.csv文件内容:
interface-template-gns3.j2文件内容:
interface {{ interface }} description Link to {{ server }} port {{ port }} for {{ purpose }} switchport {% if vlan == "Trunk" -%} switchport mode trunk {% else -%} switchport mode access switchport access vlan {{ vlan }} spanning-tree portfast {% endif -%} no shutdown
jinja2_peizhiSW-gns3.py
from jinja2 import Template import csv from netmiko import ConnectHandler csv_file = open('switch ports-gns3.csv') template_file = open('interface-template-gns3.j2') reader = csv.DictReader(csv_file) interface_template = Template(template_file.read(), keep_trailing_newline=True) interface_configs = '' for row in reader: interface_config = interface_template.render( interface = row['Interface'], vlan = row['VLAN'], server = row['Server'], link = row['Port'], purpose = row['Purpose'] ) interface_configs += interface_config config_set = interface_configs.split('\n') SW = { 'device_type': 'cisco_ios', 'ip': '192.168.88.1', 'username': 'admin', 'password': 'admin123', } connect = ConnectHandler(**SW) print ('Connected to switch') output = connect.send_config_set(config_set) #output = connect.send_config_set(config_set, cmd_verify=False) 注释这个是Netmiko 3需要的自身的一个"bug",我查看了我的netmiko是2所以不需要这个参数 print(output) 执行结果: ! interface FastEthernet3/0 description Link to esxi-01 port for VM Host switchport mode trunk ! interface FastEthernet3/1 description Link to esxi-01 port for VM Host switchport mode trunk ! interface FastEthernet3/2 description Link to esxi-02 port for VM Host switchport mode trunk ! interface FastEthernet3/3 description Link to esxi-02 port for VM Host switchport mode trunk ! interface FastEthernet3/4 description Link to db-01 port for Database Server switchport access vlan 80 ! interface FastEthernet3/5 description Link to db-02 port for Database Server switchport access vlan 80 ! interface FastEthernet3/6 description Link to app-01 port for App Server switchport access vlan 80 ! interface FastEthernet3/7 description Link to app-02 port for App Server switchport access vlan 80 ! interface FastEthernet3/8 ================================ PS D:\Python_Files\python2020item\CSV_Jinja2> python .\jinja2_peizhiSW-gns3.py Connected to switch config term Enter configuration commands, one per line. End with CNTL/Z. R1(config)#interface FastEthernet3/0 R1(config-if)# description Link to esxi-01 port for VM Host R1(config-if)# switchport R1(config-if)# switchport mode trunk R1(config-if)# no shutdown R1(config-if)# R1(config-if)#interface FastEthernet3/1 R1(config-if)# description Link to esxi-01 port for VM Host R1(config-if)# switchport R1(config-if)# switchport mode trunk R1(config-if)# no shutdown R1(config-if)# R1(config-if)#interface FastEthernet3/2 R1(config-if)# description Link to esxi-02 port for VM Host R1(config-if)# switchport R1(config-if)# switchport mode trunk R1(config-if)# no shutdown R1(config-if)# R1(config-if)#interface FastEthernet3/3 R1(config-if)# description Link to esxi-02 port for VM Host R1(config-if)# switchport R1(config-if)# switchport mode trunk R1(config-if)# no shutdown R1(config-if)# R1(config-if)#interface FastEthernet3/4 R1(config-if)# description Link to db-01 port for Database Server R1(config-if)# switchport R1(config-if)# switchport mode access R1(config-if)# switchport access vlan 80 %Access VLAN 80 does not exist. Please add it to vlan database R1(config-if)# spanning-tree port type edge ^ % Invalid input detected at '^' marker. R1(config-if)# no shutdown R1(config-if)# R1(config-if)#interface FastEthernet3/5 R1(config-if)# description Link to db-02 port for Database Server R1(config-if)# switchport R1(config-if)# switchport mode access R1(config-if)# switchport access vlan 80 %Access VLAN 80 does not exist. Please add it to vlan database R1(config-if)# spanning-tree port type edge ^ % Invalid input detected at '^' marker. R1(config-if)# no shutdown R1(config-if)# R1(config-if)#interface FastEthernet3/6 R1(config-if)# description Link to app-01 port for App Server R1(config-if)# switchport R1(config-if)# switchport mode access R1(config-if)# switchport access vlan 80 %Access VLAN 80 does not exist. Please add it to vlan database R1(config-if)# spanning-tree port type edge ^ % Invalid input detected at '^' marker. R1(config-if)# no shutdown R1(config-if)# R1(config-if)#interface FastEthernet3/7 R1(config-if)# description Link to app-02 port for App Server R1(config-if)# switchport R1(config-if)# switchport mode access R1(config-if)# switchport access vlan 80 %Access VLAN 80 does not exist. Please add it to vlan database R1(config-if)# spanning-tree port type edge ^ % Invalid input detected at '^' marker. R1(config-if)# no shutdown R1(config-if)# R1(config-if)# R1(config-if)#end R1# PS D:\Python_Files\python2020item\CSV_Jinja2> ================================================= 思科配置ssh 配置ssh如下: R1(config)#line vty 0 4 R1(config-line)#transport input all 【可以选ssh telnet 我都选了,all】 R1(config-line)#login local 【使用本地定义的用户名密码登录】 R1(config-line)# R1(config-line)#exi R1(config)#username admin privilege 15 password cisco 【定义本地定义的用户名密码】 R1(config)#crypto key generate rsa % Please define a domain-name first. 【务必先定义domain-name】 R1(config)# R1(config)#ip domain-name xxh.com R1(config)# R1(config)#crypto key generate rsa 【发现配置了ip domain-name xxh.com和crypto key generate rsa 之后,22端口能测试通了!crypto key generate rsa在路由器上产生一对RSA密钥就会自动启用SSH.如果你删除这对RSA密钥,就会自动禁用该SSH服务器】 之后配置ip,我之后再用CRT测试,发现ssh2不行,ssh1倒是可以登录。 R1#show ip ssh SSH Enabled - version 1.99 Authentication timeout: 120 secs; Authentication retries: 3 R1# R1#conf t R1(config)#ip ssh version 2 R1(config)#exi R1#show ip ssh SSH Enabled - version 2.0 Authentication timeout: 120 secs; Authentication retries: 3 R1# R1# R1# 注意:重启路由器之后,gns模拟器需要crypto key generate rsa重新生成key才能恢复ssh功能,不然又不能ssh了 R1#conf Configuring from terminal, memory, or network [terminal]? Enter configuration commands, one per line. End with CNTL/Z. R1(config)#crypto key generate rsa The name for the keys will be: R1.xxh.com Choose the size of the key modulus in the range of 360 to 2048 for your General Purpose Keys. Choosing a key modulus greater than 512 may take a few minutes. How many bits in the modulus [512]: % Generating 512 bit RSA keys, keys will be non-exportable...[OK] R1(config)# R1(config)# R1(config)# R1(config)# R1(config)# *Mar 1 00:00:54.711: %SSH-5-ENABLED: SSH 2.0 has been enabled R1(config)# *Mar 1 00:01:15.199: %SYS-5-CONFIG_I: Configured from console by admin on vty0 (192.168.88.3) R1(config)#