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

Članak o radu sa Junos PyEZ - „Python mikroframework koji vam omogućava da upravljate i automatizujete uređaje koji koriste Junos OS“ automatizaciju i upravljanje, sve što volimo. Pisanje skripte opisane u ovom članku imalo je nekoliko ciljeva - učenje Pythona i automatizaciju zadataka za prikupljanje informacija ili promjenu konfiguracija na opremi koja radi Junos OS. Izbor ove specifične kombinacije Python + Junos PyEZ napravljen je zbog niske barijere za ulazak u programski jezik Python i lakoće upotrebe Junos PyEZ biblioteke, koja ne zahtijeva stručno poznavanje Junos OS-a.

Cilj

Revizija besplatnih ipv4 podmreža koje pripadaju kompaniji. Kriterijum da je podmreža slobodna je odsustvo unosa o njoj u rutama na komutatoru koji se ponaša kao ruter koji pokreće Junos OS.

Реализация

Python + Junos PyEZ, iako je postojalo iskušenje da se to uradi kroz paramiko i ssh.exec_command, Kao rezultat toga, morat ćete konfigurirati protokol za upravljanje mrežom netconf uređaja na opremi koja se proziva. Netconf radi s hardverom putem udaljenog poziva procedure RPC i koristi XML, u ovom primjeru, da pruži informacije 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 GitHub-u pomoću sljedeće naredbe:

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

I još jedna opcija preko

$ pip install -r requirements.txt 

Ova komanda će instalirati biblioteke koje nedostaju u sistemu i koje su neophodne za rad. U mojoj verziji Zahtevi.txt Postoje samo dva od njih, najnovije verzije su naznačene u trenutku pisanja skripte:

junos-eznc
netaddr

Podrazumevano, skripta uzima ime trenutnog korisnika u sistemu; možete se prijaviti pod imenom drugog korisnika koristeći show_route.py -u ključ getpass.getpass preuzima lozinku sa stdin tako da lozinka neće ostati u sistemu. Da biste se povezali s opremom, također ćete morati unijeti njeno ime hosta 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 sa opremom koja koristi Junos OS koristeći konzolu, telnet ili netconf putem ssh-a. Članak govori o potonjoj opciji.

Za povezivanje na opremu 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 ruteru putem udaljenog poziva procedure ili poziva udaljene procedure, što god je zgodnije.

data = dev.rpc.get_route_information()

Slična komanda na Junos OS-u

user@router> show route | display xml

Dodavanjem rpc na kraj naredbe dobijamo oznaku zahtjeva i možemo je upariti sa imenom RPC metode, na taj način možemo saznati druga imena koja nas zanimaju. Vrijedi napomenuti da se sintaksa za pisanje oznake zahtjeva razlikuje od naziva metode, naime, crtice biste trebali zamijeniti podvlakama.

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

Ostatak dijela je umotan u while petlju, kako se ne bi ponavljao zahtjev ruteru ako je bilo potrebno provjeriti drugu podmrežu od onih za koje ruter već zna. Vrijedi napomenuti da ruter na kojem postavljam zahtjev poznaje rute samo preko OSPF-a, tako da je za rubni ruter bolje malo promijeniti zahtjev kako bi se smanjilo vrijeme izvođenja skripte

data = dev.rpc.get_ospf_route_information()

Pogledajmo sad sadržaj while petlje

Na početku će od korisnika biti zatraženo da unese podmrežu sa 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 specificiranja kriterija i raspona pretraživanja, ali do sada nisam našao bolje rješenje. Zatim, sa rezultirajuće liste podmreža route_list, koristeći varijablu koja ne sadrži više od tri okteta, biram podmreže koje me zanimaju

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

Preko IPNetwork-a, netaddr modula, primam podmreže u obliku liste ipv4 adresa

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

Koristeći IPNetwork, dobijam opseg adresa iz mreže koju je uneo korisnik sa maskom i generišem listu svih adresa iz ovog opsega za poređenje sa listom zauzetih adresa.

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

Prikazujem rezultujuću listu slobodnih adresa u obliku podmreža

print(netaddr.IPSet(freeip))

Ispod je kompletna skripta, testirana na prekidačima koji se koriste kao ruter, 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