Článek o práci s Junos PyEZ – „Mikrorámec Pythonu, který vám umožňuje spravovat a automatizovat zařízení se systémem Junos OS“, automatizace a správa, vše, co máme rádi. Psaní skriptu popsaného v tomto článku mělo několik cílů – naučit se Python a automatizovat úlohy pro shromažďování informací nebo změnu konfigurací na zařízení s Junos OS. Volba této specifické kombinace Python + Junos PyEZ byla provedena z důvodu nízké bariéry vstupu do programovacího jazyka Python a snadného použití knihovny Junos PyEZ, která nevyžaduje odborné znalosti Junos OS.
Úkol
Audit bezplatných podsítí ipv4 patřících společnosti. Kritériem, že podsíť je volná, je absence záznamu o ní v trasách na přepínači fungujícím jako router s Junos OS.
uskutečnění
Python + Junos PyEZ, i když bylo pokušení to udělat přes paramiko a ssh.exec_command,
Instalace aktuální verze Junos PyEZ z PyPI se provádí pomocí následujícího příkazu:
$ pip install junos-eznc
Můžete také nainstalovat z hlavní větve projektu na GitHubu pomocí následujícího příkazu:
$ pip install git+https://github.com/Juniper/py-junos-eznc.git
A ještě jedna možnost přes
$ pip install -r requirements.txt
Tento příkaz nainstaluje knihovny, které v systému chybí a jsou nezbytné pro provoz. V mé verzi požadavky.txt Existují pouze dvě z nich, nejnovější verze jsou uvedeny v době psaní skriptu:
junos-eznc
netaddr
Ve výchozím nastavení skript přebírá jméno aktuálního uživatele v systému, můžete se přihlásit pod jménem jiného uživatele pomocí klíče show_route.py -u getpass.getpass přebírá heslo ze stdin, takže heslo nezůstane v systému. Chcete-li se připojit k zařízení, budete také muset na výzvu zadat název hostitele nebo adresu IP. Všechna data potřebná pro autorizaci na zařízení byla přijata.
Junos PyEZ podporuje připojení k zařízení se systémem Junos OS pomocí konzole, telnetu nebo netconf přes ssh. Článek pojednává o poslední možnosti.
Pro připojení k zařízení použijte třídu Device modulu jnpr.junos
with jnpr.junos.Device(host=router,
user=args.name,
passwd=password) as dev:
Požadavek je proveden pro všechny cesty známé routeru prostřednictvím vzdáleného volání procedury nebo vzdáleného volání procedury, podle toho, co je pohodlnější.
data = dev.rpc.get_route_information()
Podobný příkaz na Junos OS
user@router> show route | display xml
Přidáním rpc na konec příkazu získáme značku požadavku a můžeme ji porovnat s názvem metody RPC, tímto způsobem můžeme zjistit další zajímavá jména. Stojí za zmínku, že syntaxe pro zápis tagu požadavku se liší od názvu metody, konkrétně byste měli nahradit pomlčky podtržítky.
user@router> show route | display xml rpc
<rpc-reply >route_list = data.xpath("//rt-destination/text()")
Zbytek části byl zabalen do while smyčky, aby se neopakoval požadavek na router, pokud by bylo potřeba odbavit jinou podsíť z těch, o kterých router už ví. Za zmínku stojí, že router, na kterém zadávám požadavek, zná trasy pouze přes OSPF, takže u okrajového routeru je lepší požadavek trochu změnit, aby se zkrátila doba běhu skriptu
data = dev.rpc.get_ospf_route_information()
Nyní se podíváme na obsah cyklu while
Na začátku bude uživatel požádán o zadání podsítě s maskou a maximálně třemi oktety ze sítě stejné podsítě, to je nutné pro nastavení rozsahu vyhledávání. Tato implementace specifikace kritérií a rozsahu vyhledávání se mi moc nelíbí, ale zatím jsem nenašel lepší řešení. Dále z výsledného seznamu podsítí route_list pomocí proměnné obsahující ne více než tři oktety vyberu podsítě, které mě zajímají
tmp = re.search(r'^%sS*' % subnet_search, route_list[i])
Prostřednictvím IPNetwork, modulu netaddr, dostávám podsítě ve formě seznamu adres ipv4
range_subnet = netaddr.IPNetwork(tmp.group(0))
Pomocí IPNetwork získám rozsah adres z uživatelem zadané sítě s maskou a vygeneruji seznam všech adres z tohoto rozsahu pro porovnání se seznamem obsazených adres.
for i in set(net_list).difference(set(busyip)):
freeip.append(i)
Výsledný seznam volných adres zobrazím ve formě podsítí
print(netaddr.IPSet(freeip))
Níže je kompletní skript, testovaný na přepínačích používaných jako router, modely 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
Zdroj: www.habr.com