Junos PyEZ gebruikt het voorbeeld van de taak van het zoeken naar gratis IPv4-subnetten

Een artikel over het werken met Junos PyEZ - “Python-microframework waarmee u apparaten met Junos OS kunt beheren en automatiseren” automatisering en beheer, alles waar we van houden. Het schrijven van het script dat in dit artikel wordt beschreven had verschillende doelen: het leren van Python en het automatiseren van taken voor het verzamelen van informatie of het wijzigen van configuraties op apparatuur waarop Junos OS draait. De keuze voor deze specifieke combinatie van Python + Junos PyEZ is gemaakt vanwege de lage drempel voor toegang tot de programmeertaal Python en het gebruiksgemak van de Junos PyEZ-bibliotheek, waarvoor geen specialistische kennis van Junos OS vereist is.

Taak

Controle van gratis IPv4-subnetten van het bedrijf. Het criterium dat een subnet vrij is, is de afwezigheid van een vermelding erover in de routes op de switch die fungeert als router met Junos OS.

uitvoering

Python + Junos PyEZ, hoewel de verleiding bestond om het via paramiko en ssh.exec_command te doen, Als gevolg hiervan moet u het netconf-apparaatnetwerkbeheerprotocol configureren op de apparatuur die wordt ondervraagd. Netconf werkt met hardware via remote procedure call RPC en gebruikt in dit voorbeeld XML om de ontvangen informatie te verstrekken.

Het installeren van de huidige versie van Junos PyEZ vanuit PyPI doe je met het volgende commando:

$ pip install junos-eznc

Je kunt ook vanuit de hoofdtak van het project op GitHub installeren met de volgende opdracht:

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

En nog een optie via

$ pip install -r requirements.txt 

Met deze opdracht worden bibliotheken geïnstalleerd die ontbreken in het systeem en die nodig zijn voor de werking. In mijn versie requirements.txt Er zijn er maar twee, de nieuwste versies worden aangegeven op het moment dat het script wordt geschreven:

junos-eznc
netaddr

Standaard neemt het script de naam aan van de huidige gebruiker in het systeem; u kunt inloggen onder de naam van een andere gebruiker met behulp van de show_route.py -u sleutel getpass.getpass haalt het wachtwoord van stdin, zodat het wachtwoord niet in het systeem achterblijft. Om verbinding te maken met de apparatuur moet u ook de hostnaam of het IP-adres invoeren wanneer daarom wordt gevraagd. Alle gegevens die nodig zijn voor autorisatie op het apparaat zijn ontvangen.

Junos PyEZ ondersteunt verbinding met apparatuur waarop Junos OS draait met behulp van de console, telnet of netconf via ssh. Het artikel bespreekt de laatste optie.

Om verbinding te maken met apparatuur, gebruikt u de Device-klasse van de jnpr.junos-module

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

Er wordt een verzoek ingediend voor alle routes die bij de router bekend zijn via een externe procedureaanroep of een externe procedureaanroep, afhankelijk van wat het handigst is.

data = dev.rpc.get_route_information()

Soortgelijke opdracht op Junos OS

user@router> show route | display xml

Door rpc aan het einde van de opdracht toe te voegen, krijgen we een verzoektag en kunnen deze matchen met de naam van de RPC-methode, op deze manier kunnen we andere interessante namen achterhalen. Het is vermeldenswaard dat de syntaxis voor het schrijven van de request-tag anders is dan de naam van de methode, namelijk dat u de koppeltekens moet vervangen door onderstrepingstekens.

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

De rest van het onderdeel was in een while-lus gewikkeld, om het verzoek aan de router niet te herhalen als het nodig was om een ​​ander subnet in te checken dan de subnetten waarvan de router al op de hoogte is. Het is de moeite waard te vermelden dat de router waarop ik het verzoek doe alleen routes kent via OSPF, dus voor een edge-router is het beter om het verzoek een beetje te wijzigen om de looptijd van het script te verkorten

data = dev.rpc.get_ospf_route_information()

Laten we nu eens kijken naar de inhoud van de while-lus

In het begin wordt de gebruiker gevraagd een subnet in te voeren met een masker en niet meer dan drie octetten uit het netwerk van hetzelfde subnet, dit is nodig om het zoekbereik in te stellen. Ik vind deze implementatie van het specificeren van de criteria en het zoekbereik niet echt leuk, maar tot nu toe heb ik geen betere oplossing gevonden. Vervolgens selecteer ik uit de resulterende lijst met subnetten route_list, met behulp van een variabele die niet meer dan drie octetten bevat, de subnetten die mij interesseren

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

Via IPNetwork, de netaddr-module, ontvang ik subnetten in de vorm van een lijst met ipv4-adressen

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

Met behulp van IPNetwork verkrijg ik met een masker een reeks adressen van een door de gebruiker ingevoerd netwerk en genereer ik een lijst met alle adressen uit dit bereik ter vergelijking met de lijst met bezette adressen.

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

Ik geef de resulterende lijst met vrije adressen weer in de vorm van subnetten

print(netaddr.IPSet(freeip))

Hieronder vindt u het volledige script, getest op switches die als router worden gebruikt, modellen 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

Bron: www.habr.com

Voeg een reactie