关于使用 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 来完成的诱惑,
使用以下命令从 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 键以其他用户的名称登录getpass.getpass 从标准输入获取密码,因此密码不会保留在系统中。 要连接到设备,您还需要在出现提示时输入其主机名或 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 >route_list = data.xpath("//rt-destination/text()")
该部分的其余部分被包装在一个 while 循环中,以便在需要从路由器已经知道的子网中签入另一个子网时不会重复向路由器发出请求。 值得一提的是,我发出请求的路由器仅通过 OSPF 知道路由,因此对于边缘路由器,最好稍微更改请求以减少脚本的运行时间
data = dev.rpc.get_ospf_route_information()
现在让我们看看 while 循环的内容
一开始,用户会被要求输入一个带有掩码的子网,并且来自同一子网的网络不超过三个八位字节,这是设置搜索范围所必需的。 我不太喜欢这种指定条件和搜索范围的实现,但到目前为止我还没有找到更好的解决方案。 接下来,从生成的子网路径列表列表中,使用包含不超过三个八位字节的变量,选择我感兴趣的子网
tmp = re.search(r'^%sS*' % subnet_search, route_list[i])
通过 IPNetwork(netaddr 模块),我以 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'^%sS*' % 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
来源: habr.com