Junos PyEZ бо истифода аз мисоли вазифаи ҷустуҷӯи зершабакаҳои ройгони ipv4

Мақола дар бораи кор бо Junos PyEZ - "Microframework 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-ро барои таъмини иттилооти гирифтааш истифода мебарад.

Насб кардани версияи ҷории Junos PyEZ аз PyPI бо фармони зерин анҷом дода мешавад:

$ pip install junos-eznc

Шумо инчунин метавонед аз шохаи асосии лоиҳа дар GitHub бо фармони зерин насб кунед:

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

Ва як варианти дигар тавассути

$ pip install -r requirements.txt 

Ин фармон китобхонаҳоеро насб мекунад, ки дар система мавҷуд нестанд ва барои кор заруранд. Дар версияи ман Талабот.txt Танҳо дутои онҳо вуҷуд доранд, версияҳои охирин ҳангоми навиштани скрипт нишон дода шудаанд:

junos-eznc
netaddr

Скрипт ба таври пешфарз номи корбари ҷории системаро мегирад, шумо метавонед бо истифода аз калиди show_route.py -u бо номи корбари дигар ворид шавед getpass.getpass паролро аз stdin мегирад, то парол боқӣ намонад дар система. Барои пайваст шудан ба таҷҳизот, шумо инчунин бояд ҳангоми дархост номи мизбон ё суроғаи IP-и онро ворид кунед. Ҳама маълумоти зарурӣ барои иҷозатдиҳӣ дар дастгоҳ гирифта шуданд.

Junos PyEZ пайвастшавӣ ба таҷҳизоти Junos OS-ро бо истифода аз консол, telnet ё netconf тавассути ssh дастгирӣ мекунад. Дар мақола варианти охирин муҳокима карда мешавад.

Барои пайвастшавӣ ба таҷҳизот, синфи дастгоҳи модули jnpr.junos -ро истифода баред

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 назар андозем

Дар аввал аз корбар хоҳиш карда мешавад, ки ба зершабакаи ниқоб ва на бештар аз се октет аз шабакаи ҳамон зершабака ворид шавад, ин барои муқаррар кардани диапазони ҷустуҷӯ зарур аст. Ман аслан ин татбиқи муайян кардани критерияҳо ва диапазони ҷустуҷӯро дӯст намедорам, аммо то ҳол ман роҳи беҳтареро пайдо накардаам. Минбаъд, аз рӯйхати натиҷавии зершабақаҳои route_list бо истифода аз тағирёбандае, ки на бештар аз се октет дорад, ман зершабақаҳоеро интихоб мекунам, ки маро ба таваҷҷӯҳ доранд

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

Манбаъ: will.com

Илова Эзоҳ