在Junos PyEZ上找到免费的ipv4子网的任务示例

有关与Junos PyEZ一起使用的文章-“ Python微框架,使您可以管理和自动化运行Junos OS的设备”自动化和控制,这是我们所喜欢的一切。 编写本文中描述的脚本可实现多个目标-学习Python并自动化在运行Junos OS的设备上收集信息或更改配置的任务。 之所以选择该特定的Python + Junos PyEZ软件包,是因为进入Python编程语言的门槛低,而且Junos PyEZ库的易用性不需要Junos OS专业知识。

挑战赛


审核公司拥有的ipv4免费子网。 子网空闲的标准是在充当运行Junos OS的路由器的交换机上的路由中没有关于子网的记录。

实作


Python + Junos PyEZ,尽管通过paramiko和ssh.exec_command有诱惑力​​, 结果,有必要在被调查设备上为netconf设备配置网络管理协议。 在此示例中,Netconf通过远程过程调用(RPC)与设备配合使用,并使用XML提供接收的信息。

使用以下命令从PyPI安装当前版本的Junos PyEZ:

$ pip install junos-eznc 

您还可以使用以下命令从GitHub上的项目的主要分支中进行安装:

 $ pip install git+https://github.com/Juniper/py-junos-eznc.git 

还有一个选择

 $ pip install -r requirements.txt 

此命令将安装系统中缺少的工作所需的库。 在我的requirements.txt版本中,只有两个,在编写脚本时指出了最新版本:

 junos-eznc netaddr 

默认脚本使用系统中当前用户的名称,您可以使用密钥show_route.py -u <user_name> getpass.getpass以另一个用户的名称登录。getpass接受来自stdin的密码,因此该密码将不会保留在系统中。 要连接到设备,您还需要根据要求输入其主机名或ip地址。 已收到设备授权所需的所有数据。

Junos PyEZ支持通过ssh使用控制台,telnet或netconf连接到运行Junos OS的设备。 本文考虑了最后一个选择。

要连接到设备,使用jnpr.junos模块的Device类。

 with jnpr.junos.Device(host=router, user=args.name, passwd=password) as dev: 

通过远程过程调用或对远程过程的调用,发出有关路由器已知的所有路由的请求,对此更为方便。

 data = dev.rpc.get_route_information() 

Junos OS上的类似命令

 user@router> show route | display xml 

将rpc命令添加到命令的末尾,我们将获得请求标签,并将其与RPC方法的名称进行匹配,这样您就可以找到其他感兴趣的名称。 值得注意的是,编写请求标签的语法与方法名称不同,即用下划线替换连字符。

 user@router> show route | display xml rpc <rpc-reply xmlns:junos="http://xml.juniper.net/junos/15.1R1/junos"> <rpc> <get-route-information> </get-route-information> </rpc> </rpc-reply> 

我收到了xml格式的路由数据,我只通过标签<rt-destination> xxx.xxx.xxx.xxx/yy </ rt-destination>选择了我感兴趣的路由数据,并将其以字符串格式作为列表写入了变量,从而获得了一个列表繁忙的子网。

 route_list = data.xpath("//rt-destination/text()") 

我将其余部分包装在while循环中,以便在需要检查与路由器已知的子网不同的子网时,不重新执行对路由器的请求。 值得一提的是,我请求的路由器仅通过OSPF知道路由,因此,对于边界路由器,最好对请求进行一些更改以减少脚本时间

 data = dev.rpc.get_ospf_route_information() 

现在让我们看看while循环的内容


开始时,将提示用户输入一个带掩码的子网,并且该子网距同一子网的网络不得超过三个八位位组,这是设置搜索范围所必需的。 我不太喜欢这种设置条件和搜索范围的方法,但是到目前为止,我还没有找到更好的解决方案。 接下来,从所获得的route_list子网列表中,使用包含不超过三个八位位组的变量,选择我感兴趣的子网

 tmp = re.search(r'^%s\S*' % subnet_search, route_list[i]) 

通过netaddr模块IPNetwork,我将子网作为ipv4地址列表

 range_subnet = netaddr.IPNetwork(tmp.group(0)) 

使用用户通过掩码输入的网络中的IPNetwork,我得到了一个地址范围,并形成了该范围内所有地址的列表,以便与繁忙地址列表进行比较。

 for i in set(net_list).difference(set(busyip)): freeip.append(i) 

我得到了子网形式的免费地址列表

 print(netaddr.IPSet(freeip)) 

以下是完整的脚本,已在ex4550,ex4600型号的路由器上测试过

 #!/usr/bin/env python3 # -*- coding: utf-8 -*- import argparse import getpass import netaddr import re import sys import jnpr.junos parser = argparse.ArgumentParser() parser.add_argument('-u', '--user', action='store', dest='name', help='Enter login from tacacs if it differs from the ' 'username in the system.') args = parser.parse_args() if not args.name: args.name = getpass.getuser() # Return the “login name” of the user. router = input("Full routers name: ") password = getpass.getpass("Password: ") try: # Authenticates to a device running Junos, for get information about routs # into xml format and selects by tag. route_list = [] with jnpr.junos.Device(host=router, user=args.name, passwd=password) as dev: data = dev.rpc.get_route_information() route_list = data.xpath("//rt-destination/text()") except (jnpr.junos.exception.ConnectRefusedError, jnpr.junos.exception.ConnectUnknownHostError) as err: print("Equipment name or password wrong.") sys.exit(1) while True: subnet = input("Net with mask: ") subnet_search = input("Input no more three octet: ") # Gets a list of busy IP addresses from the received subnets. busyip = [] for i in range(len(route_list)): tmp = re.search(r'^%s\S*' % subnet_search, route_list[i]) if tmp: range_subnet = netaddr.IPNetwork(tmp.group(0)) for ip in range_subnet: busyip.append("%s" % ip) range_subnet = netaddr.IPNetwork(subnet) # Gets list ip adresses from subnetworks lists. net_list = [] for ip in range_subnet: net_list.append("%s" % ip) # omparing lists. freeip = [] for i in set(net_list).difference(set(busyip)): freeip.append(i) print(netaddr.IPSet(freeip)) request = input("To run request again enter yes or y, " "press 'enter', complete request: ") if request in ("yes", "y"): continue else: print('Bye') break 

Source: https://habr.com/ru/post/zh-CN481648/


All Articles