Junos PyEZ, izmantojot bezmaksas ipv4 apakštīklu meklēšanas uzdevuma piemēru

Raksts par darbu ar Junos PyEZ — “Python mikroietvars, kas ļauj pārvaldīt un automatizēt ierīces, kurās darbojas Junos OS” automatizācija un pārvaldība, viss, kas mums patīk. Rakstot šajā rakstā aprakstīto skriptu, bija vairāki mērķi — apgūt Python un automatizēt uzdevumus informācijas vākšanai vai konfigurāciju maiņai iekārtās, kurās darbojas Junos OS. Šīs īpašās Python + Junos PyEZ kombinācijas izvēle tika veikta, ņemot vērā zemo barjeru ienākšanai Python programmēšanas valodā un Junos PyEZ bibliotēkas lietošanas vienkāršību, kas neprasa ekspertu zināšanas par Junos OS.

Uzdevums

Uzņēmumam piederošo bezmaksas ipv4 apakštīklu audits. Kritērijs, lai apakštīkls būtu brīvs, ir tas, ka nav ieraksta par to slēdža maršrutos, kas darbojas kā maršrutētājs, kurā darbojas Junos OS.

Ieviešana

Python + Junos PyEZ, lai gan bija kārdinājums to izdarīt, izmantojot paramiko un ssh.exec_command, Tā rezultātā jums būs jākonfigurē netconf ierīces tīkla pārvaldības protokols iekārtā, kas tiek aptaujāta. Netconf darbojas ar aparatūru, izmantojot attālo procedūru izsaukumu RPC, un šajā piemērā izmanto XML, lai sniegtu saņemto informāciju.

Pašreizējās Junos PyEZ versijas instalēšana no PyPI tiek veikta ar šādu komandu:

$ pip install junos-eznc

Varat arī instalēt no projekta galvenās filiāles vietnē GitHub ar šādu komandu:

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

Un vēl viena iespēja, izmantojot

$ pip install -r requirements.txt 

Šī komanda instalēs bibliotēkas, kas trūkst sistēmā un ir nepieciešamas darbībai. Manā versijā prasības.txt Ir tikai divi no tiem, jaunākās versijas ir norādītas skripta rakstīšanas laikā:

junos-eznc
netaddr

Pēc noklusējuma skripts izmanto pašreizējā lietotāja vārdu sistēmā; jūs varat pieteikties ar cita lietotāja vārdu, izmantojot taustiņu show_route.py -u getpass.getpass ņem paroli no stdin, tāpēc parole nepaliks sistēmā. Lai izveidotu savienojumu ar iekārtu, jums būs jāievada arī tā resursdatora nosaukums vai IP adrese, kad tas tiek prasīts. Visi dati, kas nepieciešami ierīces autorizācijai, ir saņemti.

Junos PyEZ atbalsta savienojuma izveidi ar aprīkojumu, kurā darbojas Junos OS, izmantojot konsoli, telnet vai netconf, izmantojot ssh. Rakstā apskatīta pēdējā iespēja.

Lai izveidotu savienojumu ar aprīkojumu, izmantojiet moduļa jnpr.junos iekārtu klasi

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

Pieprasījums tiek veikts visiem maršrutētājam zināmajiem maršrutiem, izmantojot attālās procedūras zvanu vai attālās procedūras zvanu, atkarībā no tā, kurš ir ērtāk.

data = dev.rpc.get_route_information()

Līdzīga komanda operētājsistēmā Junos OS

user@router> show route | display xml

Komandas beigās pievienojot rpc, mēs iegūstam pieprasījuma tagu un varam to saskaņot ar RPC metodes nosaukumu, tādā veidā mēs varam uzzināt citus interesējošos nosaukumus. Ir vērts atzīmēt, ka pieprasījuma taga rakstīšanas sintakse atšķiras no metodes nosaukuma, proti, defises jāaizstāj ar pasvītrojumiem.

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

Pārējā daļa tika ietīta cilpā, lai neatkārtotu pieprasījumu maršrutētājam, ja bija nepieciešams pārbaudīt citu apakštīklu no tiem, par kuriem maršrutētājs jau zina. Ir vērts pieminēt, ka maršrutētājs, kuram es veicu pieprasījumu, zina maršrutus tikai caur OSPF, tāpēc malas maršrutētājam labāk ir nedaudz mainīt pieprasījumu, lai samazinātu skripta darbības laiku.

data = dev.rpc.get_ospf_route_information()

Tagad apskatīsim cilpas while saturu

Sākumā lietotājam tiks lūgts ievadīt apakštīklu ar masku un ne vairāk kā trīs oktetus no tā paša apakštīkla tīkla, tas ir nepieciešams, lai iestatītu meklēšanas diapazonu. Man ļoti nepatīk šī kritēriju un meklēšanas diapazona norādīšanas ieviešana, taču līdz šim neesmu atradis labāku risinājumu. Pēc tam no iegūtā apakštīklu saraksta route_list, izmantojot mainīgo, kas satur ne vairāk kā trīs oktetus, es atlasu apakštīklus, kas mani interesē.

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

Izmantojot IPNetwork, netaddr moduli, es saņemu apakštīklus ipv4 adrešu saraksta veidā

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

Izmantojot IPNetwork, es iegūstu adrešu diapazonu no lietotāja ievadīta tīkla ar masku un ģenerēju visu adrešu sarakstu no šī diapazona, lai tos salīdzinātu ar aizņemto adrešu sarakstu.

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

Es parādu iegūto bezmaksas adrešu sarakstu apakštīklu veidā

print(netaddr.IPSet(freeip))

Zemāk ir pilns skripts, kas pārbaudīts uz slēdžiem, ko izmanto kā maršrutētāju, modeļiem 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

Avots: www.habr.com

Pievieno komentāru