En artikel om at arbejde med Junos PyEZ - "Python microframework, der gør det muligt for dig at administrere og automatisere enheder, der kører Junos OS" automatisering og administration, alt hvad vi elsker. At skrive scriptet beskrevet i denne artikel havde flere mål - at lære Python og automatisere opgaver til at indsamle information eller ændre konfigurationer på udstyr, der kører Junos OS. Valget af denne specifikke kombination af Python + Junos PyEZ blev truffet på grund af den lave adgangsbarriere til Python-programmeringssproget og den nemme brug af Junos PyEZ-biblioteket, som ikke kræver ekspertviden om Junos OS.
Opgave
Revision af gratis ipv4 undernet tilhørende virksomheden. Kriteriet for, at et undernet er gratis, er fraværet af en post om det i ruterne på switchen, der fungerer som en router, der kører Junos OS.
implementering
Python + Junos PyEZ, selvom der var en fristelse til at gøre det gennem paramiko og ssh.exec_command,
Installation af den aktuelle version af Junos PyEZ fra PyPI udføres med følgende kommando:
$ pip install junos-eznc
Du kan også installere fra projektets hovedgren på GitHub med følgende kommando:
$ pip install git+https://github.com/Juniper/py-junos-eznc.git
Og endnu en mulighed via
$ pip install -r requirements.txt
Denne kommando vil installere biblioteker, der mangler i systemet og er nødvendige for driften. I min version krav.txt Der er kun to af dem, de seneste versioner er angivet på tidspunktet for skrivning af scriptet:
junos-eznc
netaddr
Som standard tager scriptet navnet på den aktuelle bruger i systemet; du kan logge ind under navnet på en anden bruger ved hjælp af show_route.py -u-tasten getpass.getpass tager adgangskoden fra stdin, så adgangskoden forbliver ikke i systemet. For at oprette forbindelse til udstyret skal du også indtaste dets værtsnavn eller IP-adresse, når du bliver bedt om det. Alle data, der er nødvendige for godkendelse på enheden, er modtaget.
Junos PyEZ understøtter tilslutning til udstyr, der kører Junos OS ved hjælp af konsollen, telnet eller netconf via ssh. Artiklen diskuterer sidstnævnte mulighed.
For at oprette forbindelse til udstyr skal du bruge enhedsklassen i jnpr.junos-modulet
with jnpr.junos.Device(host=router,
user=args.name,
passwd=password) as dev:
Der foretages en anmodning om alle ruter, som routeren kender via fjernprocedurekald eller fjernprocedurekald, alt efter hvad der er mest bekvemt.
data = dev.rpc.get_route_information()
Lignende kommando på Junos OS
user@router> show route | display xml
Ved at tilføje rpc til slutningen af kommandoen får vi et request tag og kan matche det med navnet på RPC metoden, på denne måde kan vi finde ud af andre navne af interesse. Det er værd at bemærke, at syntaksen for at skrive anmodnings-tagget er forskellig fra metodenavnet, nemlig at du skal erstatte bindestreger med understregninger.
user@router> show route | display xml rpc
<rpc-reply >route_list = data.xpath("//rt-destination/text()")
Resten af delen blev pakket ind i en while-løkke, for ikke at gentage anmodningen til routeren, hvis det var nødvendigt at tjekke et andet undernet ind fra dem, som routeren allerede kender til. Det er værd at nævne, at den router, som jeg laver anmodningen på, kun kender ruter gennem OSPF, så for en edge-router er det bedre at ændre anmodningen lidt for at reducere scriptets køretid
data = dev.rpc.get_ospf_route_information()
Lad os nu se på indholdet af while-løkken
I begyndelsen vil brugeren blive bedt om at indtaste et undernet med en maske og ikke mere end tre oktetter fra netværket i det samme undernet, dette er nødvendigt for at indstille søgeområdet. Jeg kan ikke rigtig lide denne implementering af at specificere kriterierne og søgeområdet, men indtil videre har jeg ikke fundet en bedre løsning. Dernæst, fra den resulterende liste over undernet rute_liste, ved hjælp af en variabel, der ikke indeholder mere end tre oktetter, vælger jeg de undernet, der interesserer mig
tmp = re.search(r'^%sS*' % subnet_search, route_list[i])
Gennem IPNetwork, netaddr-modulet, modtager jeg undernet i form af en liste over ipv4-adresser
range_subnet = netaddr.IPNetwork(tmp.group(0))
Ved hjælp af IPNetwork henter jeg en række adresser fra et brugerindtastet netværk med en maske og genererer en liste over alle adresser fra dette område til sammenligning med listen over besatte adresser.
for i in set(net_list).difference(set(busyip)):
freeip.append(i)
Jeg viser den resulterende liste over gratis adresser i form af undernet
print(netaddr.IPSet(freeip))
Nedenfor er det komplette script, testet på switches brugt som router, modeller 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
Kilde: www.habr.com