Junos PyEZ na primjeru zadatka traženja slobodnih ipv4 podmreža

Članak o radu s Junos PyEZ - “Python microframework koji vam omogućuje upravljanje i automatizaciju uređaja koji pokreću Junos OS” automatizacija i upravljanje, sve što volimo. Pisanje skripte opisane u ovom članku imalo je nekoliko ciljeva - učenje Pythona i automatiziranje zadataka za prikupljanje informacija ili mijenjanje konfiguracija na opremi koja pokreće Junos OS. Odabir ove specifične kombinacije Python + Junos PyEZ napravljen je zbog niske barijere za ulazak u programski jezik Python i jednostavnosti korištenja Junos PyEZ biblioteke, koja ne zahtijeva stručno poznavanje Junos OS-a.

Zadatak

Revizija besplatnih ipv4 podmreža koje pripadaju tvrtki. Kriterij da je podmreža slobodna je nepostojanje unosa o njoj u rutama na preklopniku koji djeluje kao usmjerivač koji pokreće Junos OS.

Provedba

Python + Junos PyEZ, iako je bilo iskušenja da se to učini kroz paramiko i ssh.exec_command, Kao rezultat toga, morat ćete konfigurirati protokol upravljanja mrežom uređaja netconf na opremi koja se ispituje. Netconf radi s hardverom preko udaljenog poziva procedure RPC i koristi XML, u ovom primjeru, za pružanje informacija koje prima.

Instaliranje trenutne verzije Junos PyEZ-a iz PyPI-ja vrši se sljedećom naredbom:

$ pip install junos-eznc

Također možete instalirati iz glavne grane projekta na GitHubu sljedećom naredbom:

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

I još jedna opcija putem

$ pip install -r requirements.txt 

Ova naredba će instalirati biblioteke koje nedostaju sustavu, a potrebne su za rad. U mojoj verziji zahtjevi.txt Postoje samo dvije od njih, najnovije verzije su naznačene u vrijeme pisanja skripte:

junos-eznc
netaddr

Skripta prema zadanim postavkama uzima ime trenutnog korisnika u sustavu, možete se prijaviti pod imenom drugog korisnika pomoću ključa show_route.py -u getpass.getpass uzima lozinku iz stdin-a tako da lozinka neće ostati u sustavu. Za povezivanje s opremom također ćete morati unijeti naziv glavnog računala ili IP adresu kada se to od vas zatraži. Svi podaci potrebni za autorizaciju na uređaju su primljeni.

Junos PyEZ podržava povezivanje s opremom koja pokreće Junos OS koristeći konzolu, telnet ili netconf putem ssh-a. U članku se govori o potonjoj opciji.

Za povezivanje s opremom koristite klasu uređaja modula jnpr.junos

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

Zahtjev se postavlja za sve rute poznate usmjerivaču putem poziva udaljene procedure ili poziva udaljene procedure, ovisno o tome što je prikladnije.

data = dev.rpc.get_route_information()

Slična naredba na Junos OS-u

user@router> show route | display xml

Dodavanjem rpc na kraj naredbe dobivamo oznaku zahtjeva i možemo je spojiti s nazivom RPC metode, na taj način možemo saznati druga imena od interesa. Vrijedno je napomenuti da se sintaksa za pisanje oznake zahtjeva razlikuje od naziva metode, naime crtice trebate zamijeniti podvlakama.

user@router> show route | display xml rpc
<rpc-reply >route_list = data.xpath("//rt-destination/text()")

Ostatak dijela bio je umotan u while petlju, kako se ne bi ponavljao zahtjev usmjerivaču ako je potrebno provjeriti drugu podmrežu od onih za koje usmjerivač već zna. Vrijedno je spomenuti da usmjerivač na kojem postavljam zahtjev poznaje rute samo kroz OSPF, tako da je za rubni usmjerivač bolje malo promijeniti zahtjev kako bi se smanjilo vrijeme izvođenja skripte

data = dev.rpc.get_ospf_route_information()

Sada pogledajmo sadržaj while petlje

Na početku će se od korisnika tražiti da unese podmrežu s maskom i ne više od tri okteta iz mreže iste podmreže, što je potrebno za postavljanje raspona pretraživanja. Ne sviđa mi se baš ova implementacija određivanja kriterija i raspona pretraživanja, ali do sada nisam našao bolje rješenje. Zatim, s rezultirajućeg popisa podmreža route_list, koristeći varijablu koja ne sadrži više od tri okteta, odabirem podmreže koje me zanimaju

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

Kroz IPNetwork, modul netaddr, primam podmreže u obliku popisa ipv4 adresa

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

Koristeći IPNetwork, dobivam niz adresa iz mreže koju je unio korisnik s maskom i generiram popis svih adresa iz tog raspona za usporedbu s popisom zauzetih adresa.

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

Prikazujem rezultirajući popis slobodnih adresa u obliku podmreža

print(netaddr.IPSet(freeip))

Ispod je kompletna skripta, testirana na preklopnicima koji se koriste kao usmjerivač, modeli 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

Izvor: www.habr.com

Dodajte komentar