Junos PyEZ ilə işləmək haqqında məqalə - “Junos OS ilə işləyən cihazları idarə etməyə və avtomatlaşdırmağa imkan verən Python mikroframework” avtomatlaşdırma və idarəetmə, sevdiyimiz hər şey. Bu məqalədə təsvir olunan skriptin yazılmasının bir neçə məqsədi var idi - Python öyrənmək və Junos OS ilə işləyən avadanlıqda məlumat toplamaq və ya konfiqurasiyaları dəyişdirmək üçün tapşırıqları avtomatlaşdırmaq. Python + Junos PyEZ-in bu spesifik kombinasiyasının seçimi Python proqramlaşdırma dilinə daxil olmaq üçün maneənin aşağı olması və Junos OS üzrə ekspert biliklərini tələb etməyən Junos PyEZ kitabxanasından istifadənin asanlığı səbəbindən edilib.
Tapşırıq
Şirkətə məxsus pulsuz ipv4 alt şəbəkələrinin auditi. Alt şəbəkənin pulsuz olması meyarı Junos OS ilə işləyən marşrutlaşdırıcı rolunu oynayan keçiddə marşrutlarda bu barədə qeydin olmamasıdır.
Tətbiq
Python + Junos PyEZ, paramiko və ssh.exec_command vasitəsilə bunu etmək istəyi olsa da,
Junos PyEZ-in cari versiyasını PyPI-dən quraşdırmaq aşağıdakı əmrlə həyata keçirilir:
$ pip install junos-eznc
Siz həmçinin GitHub-da layihənin əsas filialından aşağıdakı əmrlə quraşdıra bilərsiniz:
$ pip install git+https://github.com/Juniper/py-junos-eznc.git
Və daha bir seçim vasitəsilə
$ pip install -r requirements.txt
Bu əmr sistemdə olmayan və işləmək üçün zəruri olan kitabxanaları quraşdıracaq. Mənim versiyamda tələblər.txt Onlardan yalnız ikisi var, ən son versiyalar skript yazarkən göstərilir:
junos-eznc
netaddr
Varsayılan olaraq, skript sistemdəki cari istifadəçinin adını alır; show_route.py -u düyməsini istifadə edərək başqa istifadəçinin adı ilə daxil ola bilərsiniz. getpass.getpass parolu stdin-dən götürür ki, parol sistemdə qalmasın. Avadanlığa qoşulmaq üçün sizdən tələb olunduqda onun host adını və ya IP ünvanını da daxil etməlisiniz. Cihazda avtorizasiya üçün lazım olan bütün məlumatlar qəbul edilib.
Junos PyEZ ssh vasitəsilə konsol, telnet və ya netconf vasitəsilə Junos OS ilə işləyən avadanlıqlara qoşulmağı dəstəkləyir. Məqalədə sonuncu variant müzakirə olunur.
Avadanlığa qoşulmaq üçün jnpr.junos modulunun Cihaz sinifindən istifadə edin
with jnpr.junos.Device(host=router,
user=args.name,
passwd=password) as dev:
Uzaqdan prosedur çağırışı və ya uzaqdan prosedur çağırışı vasitəsilə marşrutlaşdırıcıya məlum olan bütün marşrutlar üçün sorğu verilir, hansı daha əlverişlidir.
data = dev.rpc.get_route_information()
Junos OS-də oxşar əmr
user@router> show route | display xml
Komandanın sonuna rpc əlavə etməklə biz sorğu etiketi əldə edirik və onu RPC metodunun adı ilə uyğunlaşdıra bilərik, bu yolla digər maraq doğuran adları tapa bilərik. Qeyd etmək lazımdır ki, sorğu teqini yazmaq üçün sintaksis metod adından fərqlidir, yəni defisləri alt xətt ilə əvəz etməlisiniz.
user@router> show route | display xml rpc
<rpc-reply >route_list = data.xpath("//rt-destination/text()")
Qalan hissə, marşrutlaşdırıcının artıq bildiyi başqa bir alt şəbəkədə yoxlamaq lazım gələrsə, marşrutlaşdırıcıya sorğunu təkrarlamamaq üçün bir müddət döngəsinə bükülmüşdür. Qeyd etmək lazımdır ki, sorğu göndərdiyim marşrutlaşdırıcı yalnız OSPF vasitəsilə marşrutları tanıyır, buna görə də kənar marşrutlaşdırıcı üçün skriptin işləmə müddətini azaltmaq üçün sorğunu bir az dəyişdirmək daha yaxşıdır.
data = dev.rpc.get_ospf_route_information()
İndi isə while dövrəsinin məzmununa baxaq
Başlanğıcda istifadəçidən maskalı və eyni alt şəbəkənin şəbəkəsindən üç oktetdən çox olmayan alt şəbəkəyə daxil olması tələb olunacaq, bu, axtarış diapazonunu təyin etmək üçün lazımdır. Kriteriyaların və axtarış aralığının dəqiqləşdirilməsinin bu tətbiqini həqiqətən bəyənmirəm, lakin indiyə qədər daha yaxşı bir həll tapmadım. Sonra, üç oktetdən çox olmayan dəyişəndən istifadə edərək, marşrut_list alt şəbəkələrinin nəticə siyahısından məni maraqlandıran alt şəbəkələri seçirəm.
tmp = re.search(r'^%sS*' % subnet_search, route_list[i])
IPNetwork, netaddr modulu vasitəsilə mən alt şəbəkələri ipv4 ünvanlarının siyahısı şəklində alıram.
range_subnet = netaddr.IPNetwork(tmp.group(0))
IPNetwork-dən istifadə edərək, mən maskalı istifadəçinin daxil etdiyi şəbəkədən bir sıra ünvanlar əldə edirəm və işğal olunmuş ünvanların siyahısı ilə müqayisə etmək üçün bu diapazondan bütün ünvanların siyahısını yaradıram.
for i in set(net_list).difference(set(busyip)):
freeip.append(i)
Mən nəticədə pulsuz ünvanların siyahısını alt şəbəkələr şəklində göstərirəm
print(netaddr.IPSet(freeip))
Aşağıda ex4550, ex4600 modellərində marşrutlaşdırıcı kimi istifadə edilən açarlarda sınaqdan keçirilmiş tam skript verilmişdir.
#!/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
Mənbə: www.habr.com