Artikkel Junos PyEZ-ist — "Pythoni mikrokeskkond, mis võimaldab hallata ja automatiseerida seadmeid, mis töötavad Junos OS-il" automatiseerimise ja haldamise kohta, nagu me armastame. Selle artikli kaudu välja kirjutatud skripti eesmärgiks oli õppida Pythonit ja automatiseerida ülesandeid, mis on seotud teabe kogumise või konfiguratsiooni muutmisega seadmetes, mis töötavad Junos OS-il. Python + Junos PyEZ kombinatsiooni valik tehti madala sissejuhatuse tõttu Pythonisse ja Junos PyEZ teeki lihtsuse tõttu, mis ei nõua ekspertteadmisi Junos OS-ist.
Ülesanne
IPv4 alavõrkude auditeerimine, mis kuuluvad ettevõttele. Kriteeriumiks, et alavõrk on vaba — on selle puudumine marsruutides lülitil, mis täidab ruutimise rolli Junos OS-i all.
Rakendus
Python + Junos PyEZ, kuigi oli kiusatus kasutada paramiko ja ssh.exec_command, sellega seoses tuleb küsitaval seadmel seadistada seadme haldamise protokoll netconf. Netconf töötab seadmetega kaugkutsumise (remote procedure call RPC) kaudu ning kasutab XML-i, antud näites, et edastada saadud teavet.
Praeguse versiooni Junos PyEZ installimine PyPI-st toimub järgmise käsu abil:
$ pip install junos-ezncSamuti võib installida projekti põhivärvist GitHubist järgmise käsu abil:
$ pip install git+https://github.com/Juniper/py-junos-eznc.gitJa veel üks variant läbi
$ pip install -r requirements.txt see käsk installib puuduvad teegid, mis on vajalikud tööks. Minu versioonis requirements.txt on neid kokku kaks, versioonid on viimased skripti kirjutamise hetkel:
junos-eznc
netaddrSkript võtab vaikimisi praeguse kasutajanime süsteemis, siseneda teise kasutajana saab, kasutades võtit show_route.py -u . getpass.getpass võtab parooli stdin-ist, nii et parool ei jää süsteemi. Seadmest ühendamiseks peab samuti sisestama selle pärimise ajal hostname või IP-aadressi. Kõik vajalikud autentsuse andmed seadmes on saadud.
Junos PyEZ toetab ühendust seadmetega, mis töötavad Junos OS-il, kasutades konsooli, telneti või netconf'i through ssh. Artiklis on arvestatud viimase variandiga.
Seadmest ühendamiseks kasutatakse jnpr.junos mooduli Device klassi
with jnpr.junos.Device(host=router,
user=args.name,
passwd=password) as dev:Küsite kõiki ruuterile teadaolevaid marsroute kaugkutsumise abil, või kaugkutsumise käitamise kaudu, nagu kellele see meeldib.
data = dev.rpc.get_route_information()Junos OS-i analoogne käsk
user@router> show route | display xmlLisades käskude rpc lõppu, saame päringu sildi ja saame vastavusse viia selle RPC meetodi nimega, nii et on võimalik teada saada ka teisi huvitavaid nimesid. Tuleb märkida, et päringu sildi kirjutamise süntaks erineb meetodi nimest, nimelt tuleb asendada hüülsid allajoonisega.
user@router> show route | display xml rpc
route_list = data.xpath("//rt-destination/text()")Ülejäänud osa panin tsüklisse while, et mitte teha ruuteri suhtes uuesti päringut, kui on vaja kontrollida teistest alavõrkudest, millest ruuter juba teab. Tuleb mainida, et ruuter, millest pärin, teab marsroute ainult OSPF kaudu, seega on parema ruuteri puhul parem pisut muutuda päringut, et vähendada skripti tööaega.
data = dev.rpc.get_ospf_route_information()Nüüd vaatame while-tsükli sisu
Alustuseks palutakse kasutajal sisestada alavõrk koos maskiga ja mitte rohkem kui kolme oktetiga sama alavõrgu sees, see on vajalik otsingupiiri määramiseks. Ei meeldi selline rakendus kriteeriumi ja otsingupiiri määramiseks, kuid paremat lahendust pole leidnud. Edasi, saadud alavõrkude loendist route_list Kasutades muutujat, mis sisaldab mitte rohkem kui kolme okteti, valin huvitavad alavõrgud.
tmp = re.search(r'^%sS*' % subnet_search, route_list[i])IPNetwork mooduli kaudu netaddr, saan alavõrkude loendi IPv4 aadressidest.
range_subnet = netaddr.IPNetwork(tmp.group(0))Kasutades IPNetwork'i, mille kasutaja sisestab koos maskiga, saan aadresside vahemiku ja koostan loendi kõigist selle vahemiku aadressidest, et võrrelda hõivatud aadresside nimekirjaga.
for i in set(net_list).difference(set(busyip)):
freeip.append(i)Saadud vabad aadresside loendi edastan alavõrkudena.
print(netaddr.IPSet(freeip))Allpool on skript täielikult, testitud lülitites, mis töötavad marsruutimise rollis, mudelid ex4550 ja 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
Allikas: habr.com
