Praktični primeri – Modul 24 – Automatizacija mreža
Primeri 1, 2 i 5 rade bez ijednog mrežnog uređaja — dovoljni su Python i tekstualni editor. Primeri 3 i 4 prikazuju Cisco IOS varijantu, onako kako bi izgledala u stvarnoj firmi; laboratorijska vežba iste postupke radi sa VyOS ruterima.
Svi primeri su namenjeni isključivo sopstvenoj ili ovlašćenoj infrastrukturi.
Primer 1 – Generisanje konfiguracija iz CSV tabele
Situacija: Stiže 5 novih svičeva. Iz tabele sa podacima treba napraviti početne konfiguracije bez grešaka u kucanju.
Fajl svicevi.csv:
hostname,ip,gateway,lokacija
NS-HQ-SW-01,10.10.99.2,10.10.99.1,Novi Sad server sala
NS-HQ-SW-02,10.10.99.3,10.10.99.1,Novi Sad sprat 1
NS-HQ-SW-03,10.10.99.4,10.10.99.1,Novi Sad sprat 2
Skripta generisi.py:
import csv
from pathlib import Path
SABLON = """hostname {hostname}
interface vlan 99
ip address {ip} 255.255.255.0
no shutdown
ip default-gateway {gateway}
snmp-server location {lokacija}
"""
folder = Path("konfiguracije")
folder.mkdir(exist_ok=True)
with open("svicevi.csv", encoding="utf-8", newline="") as f:
for red in csv.DictReader(f):
tekst = SABLON.format(**red)
(folder / f"{red['hostname']}.cfg").write_text(tekst, encoding="utf-8")
print("Napravljeno:", red["hostname"])
Rezultat: fajl konfiguracije/NS-HQ-SW-02.cfg:
hostname NS-HQ-SW-02
interface vlan 99
ip address 10.10.99.3 255.255.255.0
no shutdown
ip default-gateway 10.10.99.1
snmp-server location Novi Sad sprat 1
Zaključak: csv.DictReader pretvara svaki red u rečnik, a format(**red) ubacuje vrednosti u šablon. Za složenije šablone (petlje, uslovi) koristi se biblioteka Jinja2, koju koristi i Ansible.
Primer 2 – Izvlačenje podataka iz izlaza show version
Situacija: Za evidenciju opreme (Modul 23) treba iz izlaza show version izvući hostname, verziju, uptime i serijski broj.
import json
import re
izlaz = """Cisco IOS Software, C2960 Software (C2960-LANBASEK9-M), Version 15.0(2)SE4, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
NS-HQ-SW-01 uptime is 12 weeks, 3 days, 4 hours, 10 minutes
System image file is "flash:c2960-lanbasek9-mz.150-2.SE4.bin"
Processor board ID FOC1234X0YZ
"""
podaci = {
"hostname": re.search(r"^(\S+) uptime is", izlaz, re.MULTILINE).group(1),
"verzija": re.search(r"Version ([^,]+),", izlaz).group(1),
"uptime": re.search(r"uptime is (.+)", izlaz).group(1),
"serijski_broj": re.search(r"Processor board ID (\S+)", izlaz).group(1),
}
print(json.dumps(podaci, indent=2, ensure_ascii=False))
Rezultat:
{
"hostname": "NS-HQ-SW-01",
"verzija": "15.0(2)SE4",
"uptime": "12 weeks, 3 days, 4 hours, 10 minutes",
"serijski_broj": "FOC1234X0YZ"
}
Objašnjenje izraza: ([^,]+) hvata sve znakove do prvog zareza; (\S+) hvata niz znakova bez razmaka; re.MULTILINE omogućava da ^ označava početak svakog reda.
Zaključak: Ako neki uređaj ima drugačiji format izlaza, re.search vraća None i .group(1) izaziva grešku. U stvarnoj skripti rezultat se prvo proverava (if pogodak:), ili se koristi gotov TextFSM šablon (Tema 9).
Primer 3 – Prikupljanje show komandi sa više Cisco uređaja
Situacija: Tokom incidenta treba za minut prikupiti tri show komande sa svih svičeva u upravljačkom VLAN-u.
import os
from datetime import datetime
from pathlib import Path
from netmiko import ConnectHandler
from netmiko.exceptions import NetmikoAuthenticationException, NetmikoTimeoutException
KOMANDE = ["show version", "show ip interface brief", "show cdp neighbors"]
ADRESE = ["10.10.99.2", "10.10.99.3", "10.10.99.4"]
folder = Path("izlazi") / datetime.now().strftime("%Y-%m-%d_%H%M")
folder.mkdir(parents=True, exist_ok=True)
for adresa in ADRESE:
uredjaj = {
"device_type": "cisco_ios",
"host": adresa,
"username": os.environ["NET_USER"],
"password": os.environ["NET_PASS"],
}
try:
with ConnectHandler(**uredjaj) as veza:
ime = veza.find_prompt().rstrip("#>")
for komanda in KOMANDE:
izlaz = veza.send_command(komanda)
fajl = folder / f"{ime}_{komanda.replace(' ', '_')}.txt"
fajl.write_text(izlaz, encoding="utf-8")
print(f"{adresa} ({ime}): sačuvano {len(KOMANDE)} komande")
except NetmikoTimeoutException:
print(f"{adresa}: GREŠKA — uređaj ne odgovara na SSH (timeout)")
except NetmikoAuthenticationException:
print(f"{adresa}: GREŠKA — pogrešni kredencijali")
Pokretanje (kredencijali se ne upisuju u kod):
$ export NET_USER=netauto
$ read -s NET_PASS && export NET_PASS
$ python prikupi.py
10.10.99.2 (NS-HQ-SW-01): sačuvano 3 komande
10.10.99.3: GREŠKA — uređaj ne odgovara na SSH (timeout)
10.10.99.4 (NS-HQ-SW-03): sačuvano 3 komande
Zaključak: Zahvaljujući try/except, nedostupan svič ne prekida prikupljanje sa ostalih. find_prompt() daje hostname za naziv fajla, a folder sa datumom i vremenom čuva rezultate svakog pokretanja odvojeno.
Primer 4 – Ansible: NTP i Syslog standard na Cisco svičevima
Situacija: Na svim svičevima treba uvesti isti NTP i Syslog server (Modul 23), a prvo videti šta bi se promenilo.
inventory.ini:
[svicevi]
ns-hq-sw-01 ansible_host=10.10.99.2
ns-hq-sw-02 ansible_host=10.10.99.3
[svicevi:vars]
ansible_connection=ansible.netcommon.network_cli
ansible_network_os=cisco.ios.ios
ansible_user=netauto
ansible_become=true
ansible_become_method=enable
nadzor.yml:
---
- name: NTP i Syslog standard
hosts: svicevi
gather_facts: false
tasks:
- name: NTP i Syslog server
cisco.ios.ios_config:
lines:
- ntp server 10.10.99.10
- logging host 10.10.99.10
- logging trap notifications
save_when: modified
Suvi rad, pa stvarno pokretanje:
$ ansible-playbook -i inventory.ini nadzor.yml --ask-pass --check --diff
TASK [NTP i Syslog server] *****************************************
changed: [ns-hq-sw-01]
ok: [ns-hq-sw-02]
$ ansible-playbook -i inventory.ini nadzor.yml --ask-pass
PLAY RECAP *********************************************************
ns-hq-sw-01 : ok=1 changed=1 unreachable=0 failed=0 skipped=0
ns-hq-sw-02 : ok=1 changed=0 unreachable=0 failed=0 skipped=0
Tumačenje: ns-hq-sw-02 je već imao ispravna podešavanja (changed=0), pa na njemu ništa nije menjano — idempotentnost. save_when: modified čuva konfiguraciju samo ako je nešto izmenjeno.
Zamka idempotentnosti: da je u listi bilo logging trap informational, Ansible bi svaki put prijavljivao izmenu. informational je podrazumevana vrednost, pa je Cisco IOS ne prikazuje u running-config, a modul ne pronalazi tu liniju. Linije u lines moraju izgledati tačno onako kako ih uređaj prikazuje u konfiguraciji.
Primer 5 – Obrada JSON odgovora API-ja
Situacija: VyOS HTTP API (koji koristite u laboratoriji) na upit za konfiguraciju interfejsa vraća JSON. Treba napraviti pregled adresa i opisa.
Odgovor API-ja (skraćeno):
{
"success": true,
"data": {
"ethernet": {
"eth0": {"address": "192.168.56.11/24", "description": "MGMT-HOSTONLY"},
"eth1": {"address": ["10.0.12.1/30", "10.0.12.5/30"]}
}
},
"error": null
}
import json
odgovor = json.loads(open("odgovor.json", encoding="utf-8").read())
if not odgovor["success"]:
raise SystemExit(f"API greška: {odgovor['error']}")
for ime, podesavanja in odgovor["data"]["ethernet"].items():
adrese = podesavanja.get("address", [])
if isinstance(adrese, str):
adrese = [adrese]
opis = podesavanja.get("description", "(bez opisa)")
print(f"{ime:6} {', '.join(adrese):30} {opis}")
Rezultat:
eth0 192.168.56.11/24 MGMT-HOSTONLY
eth1 10.0.12.1/30, 10.0.12.5/30 (bez opisa)
Zaključak: API vraća jednu adresu kao tekst, a više adresa kao listu. Skripta zato obe varijante svodi na listu. .get(ključ, podrazumevano) sprečava grešku kada polje ne postoji (eth1 nema opis). Uvek se prvo proverava polje success, odnosno HTTP statusni kod.
Poslovni scenario – Uvođenje automatizacije u firmu „Sirius Logistika"
Situacija: Firma ima 60 mrežnih uređaja na tri lokacije. Backup-i se rade ručno „kad se stigne", konfiguracije svičeva se razlikuju, a svaka standardna izmena traje danima. Dva administratora nemaju iskustva sa programiranjem.
Faza 1 — Temelji (1. mesec)
- Kontrolni računar: Ubuntu Server VM u upravljačkom VLAN-u; pristup samo za dva administratora preko SSH ključeva.
- Git repozitorijum (interni GitLab) za skripte, inventar i backup-e;
.gitignoreza fajlove sa tajnama. - Poseban nalog
netautona svim uređajima preko TACACS+ (Modul 16): za prvu fazu samo prava čitanja. - Inventar uređaja u YAML-u, prenet iz evidencije opreme (Modul 23).
Faza 2 — Samo čitanje, bez rizika (2. mesec)
- Noćni Netmiko backup svih konfiguracija u Git (cron u 2:00), sa e-poštom o neuspešnim uređajima.
- Skripta za proveru dostupnosti (ping + SSH) pre svakog pokretanja.
- Skripta za prikupljanje
showkomandi, za incidente. - Nedeljni izveštaj o odstupanjima od standarda (npr. uređaji bez NTP-a), bez automatske ispravke.
Faza 3 — Kontrolisane izmene (3.–4. mesec)
- Ansible playbook-ovi za standard: NTP, Syslog, SNMPv3, banner, opisi uplink portova.
- Pravila: svaka izmena kroz Git uz pregled drugog administratora; prvo
--check --diff; zatim jedan uređaj u laboratoriji (GNS3, Modul 22); zatim--limitna jednu lokaciju; zatim sve. - Kredencijali za pisanje samo u Ansible Vault-u; lozinka za Vault kod dva administratora.
Faza 4 — Integracija (6. mesec)
- Inventar prelazi u NetBox; Ansible dinamički čita uređaje preko NetBox REST API-ja.
- Monitoring sistem (Modul 23) prima obaveštenja o neuspelim backup-ima.
Rezultat posle šest meseci: backup-i su svakodnevni i kompletni. Standardna izmena na svih 60 uređaja traje sat vremena umesto tri dana, uključujući proveru. Dva incidenta izazvana ručnom izmenom pronađena su za nekoliko minuta preko git diff između noćnih backup-a.