Автоматично Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ ΠΈ попълванС Π½Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΎΠ½Π½ΠΈ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ Π½Π° ΠΌΡ€Π΅ΠΆΠΎΠ²ΠΎ устройство с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Nornir

Автоматично Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ ΠΈ попълванС Π½Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΎΠ½Π½ΠΈ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ Π½Π° ΠΌΡ€Π΅ΠΆΠΎΠ²ΠΎ устройство с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Nornir

Π₯Π΅ΠΉ Π₯Π°Π±Ρ€!

Наскоро Ρ‚ΡƒΠΊ сС появи Π΅Π΄Π½Π° статия Mikrotik ΠΈ Linux. Π ΡƒΡ‚ΠΈΠ½Π° ΠΈ автоматизация ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ ΠΏΠΎΠ΄ΠΎΠ±Π΅Π½ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ Π΅ Ρ€Π΅ΡˆΠ΅Π½ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° ΠΈΠ·ΠΊΠΎΠΏΠ°Π΅ΠΌΠΈ срСдства. И Π²ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ Π·Π°Π΄Π°Ρ‡Π°Ρ‚Π° Π΅ напълно Ρ‚ΠΈΠΏΠΈΡ‡Π½Π°, Π½Π° Π₯Π°Π±Ρ€Π΅ няма Π½ΠΈΡ‰ΠΎ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ. ОсмСлявам сС Π΄Π° ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ° ΠΌΠΎΡ‚ΠΎΡ€Π° си Π½Π° ΡƒΠ²Π°ΠΆΠ°Π²Π°Π½Π°Ρ‚Π° IT общност.

Π’ΠΎΠ²Π° Π½Π΅ Π΅ ΠΏΡŠΡ€Π²ΠΈΡΡ‚ ΠΌΠΎΡ‚ΠΎΡ€ Π·Π° ΠΏΠΎΠ΄ΠΎΠ±Π½Π° Π·Π°Π΄Π°Ρ‡Π°. ΠŸΡŠΡ€Π²ΠΈΡΡ‚ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ бСшС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ ΠΏΡ€Π΅Π΄ΠΈ няколко Π³ΠΎΠ΄ΠΈΠ½ΠΈ Π² ansible вСрсия 1.x.x. Π’Π΅Π»ΠΎΡΠΈΠΏΠ΅Π΄ΡŠΡ‚ Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ рядко ΠΈ ΠΏΠΎΡ€Π°Π΄ΠΈ Ρ‚ΠΎΠ²Π° постоянно Ρ€ΡŠΠΆΠ΄ΡΡΠ²Π°Π». Π’ смисъл, Ρ‡Π΅ самата Π·Π°Π΄Π°Ρ‡Π° Π½Π΅ възниква Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° чСсто, ΠΊΠΎΠ»ΠΊΠΎΡ‚ΠΎ вСрсиитС сС Π°ΠΊΡ‚ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€Π°Ρ‚ ansible. И всСки ΠΏΡŠΡ‚, ΠΊΠΎΠ³Π°Ρ‚ΠΎ трябва Π΄Π° ΠΊΠ°Ρ€Π°Ρ‚Π΅, Π²Π΅Ρ€ΠΈΠ³Π°Ρ‚Π° ΠΏΠ°Π΄Π° ΠΈΠ»ΠΈ ΠΊΠΎΠ»Π΅Π»ΠΎΡ‚ΠΎ ΠΏΠ°Π΄Π°. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, ΠΏΡŠΡ€Π²Π°Ρ‚Π° част, Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Ρ‰Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ, Π²ΠΈΠ½Π°Π³ΠΈ Ρ€Π°Π±ΠΎΡ‚ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ ясно, Π·Π° щастиС Π΄ΠΆΠΈΠ½Π΄ΠΆΠ°2 ДвигатСлят Π΅ ΠΎΡ‚Π΄Π°Π²Π½Π° ΠΌΠΎΠ½Ρ‚ΠΈΡ€Π°Π½. Но Π²Ρ‚ΠΎΡ€Π°Ρ‚Π° част - пусканСто Π½Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ - ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ носСшС ΠΈΠ·Π½Π΅Π½Π°Π΄ΠΈ. И Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ трябва Π΄Π° пусна конфигурацията дистанционно Π½Π° ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½ сто устройства, някои ΠΎΡ‚ ΠΊΠΎΠΈΡ‚ΠΎ са Ρ€Π°Π·ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈ Π½Π° хиляди ΠΊΠΈΠ»ΠΎΠΌΠ΅Ρ‚Ρ€ΠΈ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Ρ‚ΠΎΠ·ΠΈ инструмСнт бСшС ΠΌΠ°Π»ΠΊΠΎ скучно.

Π’ΡƒΠΊ трябва Π΄Π° призная, Ρ‡Π΅ моята нСсигурност Π½Π°ΠΉ-вСроятно сС ΠΊΡ€ΠΈΠ΅ Π² липсата ΠΌΠΈ Π½Π° запознанства с ansibleΠΎΡ‚ΠΊΠΎΠ»ΠΊΠΎΡ‚ΠΎ Π² своитС Π½Π΅Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ†ΠΈ. И Ρ‚ΠΎΠ²Π°, ΠΌΠ΅ΠΆΠ΄Ρƒ Π΄Ρ€ΡƒΠ³ΠΎΡ‚ΠΎ, Π΅ Π²Π°ΠΆΠ΅Π½ ΠΌΠΎΠΌΠ΅Π½Ρ‚. ansible Π΅ напълно ΠΎΡ‚Π΄Π΅Π»Π½Π°, собствСна област Π½Π° ΠΏΠΎΠ·Π½Π°Π½ΠΈΠ΅ със собствСн DSL (спСцифичСн Π·Π° Π΄ΠΎΠΌΠ΅ΠΉΠ½ Π΅Π·ΠΈΠΊ), ΠΊΠΎΠΉΡ‚ΠΎ трябва Π΄Π° сС ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ° Π½Π° ΡƒΠ²Π΅Ρ€Π΅Π½ΠΎ Π½ΠΈΠ²ΠΎ. Π•, Ρ‚ΠΎΠ·ΠΈ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠΉΡ‚ΠΎ ansible Π Π°Π·Π²ΠΈΠ²Π° сС доста Π±ΡŠΡ€Π·ΠΎ ΠΈ Π±Π΅Π· спСциално Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° ΠΎΠ±Ρ€Π°Ρ‚Π½Π°Ρ‚Π° ΡΡŠΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌΠΎΡΡ‚ Π½Π΅ добавя увСрСност.

Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»Π½ΠΎ Π½Π΅ Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° ΠΎΡ‚Π΄Π°Π²Π½Π° бСшС Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π° Π²Ρ‚ΠΎΡ€Π° вСрсия Π½Π° вСлосипСда. Π’ΠΎΠ·ΠΈ ΠΏΡŠΡ‚ Π½Π° ΠΏΠΈΡ‚ΠΎΠ½, ΠΈΠ»ΠΈ ΠΏΠΎ-скоро Π½Π° Ρ€Π°ΠΌΠΊΠ°, написана Π² ΠΏΠΈΡ‚ΠΎΠ½ ΠΈ Π·Π° ΠΏΠΈΡ‚ΠΎΠ½ Π½Π°Ρ€ΠΈΡ‡Π° Норнир

Π’Π°ΠΊΠ° - Норнир Π΅ ΠΌΠΈΠΊΡ€ΠΎΡ€Π°ΠΌΠΊΠ°, написана Π½Π° ΠΏΠΈΡ‚ΠΎΠ½ ΠΈ Π·Π° ΠΏΠΈΡ‚ΠΎΠ½ ΠΈ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΈ Π·Π° автоматизация. Π‘ΡŠΡ‰ΠΎΡ‚ΠΎ ΠΊΠ°Ρ‚ΠΎ Π² случая с ansible, Π·Π° Ρ€Π΅ΡˆΠ°Π²Π°Π½Π΅ Π½Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΈ Ρ‚ΡƒΠΊ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ° ΠΊΠΎΠΌΠΏΠ΅Ρ‚Π΅Π½Ρ‚Π½Π° ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠ° Π½Π° Π΄Π°Π½Π½ΠΈ, Ρ‚.Π΅. опис Π½Π° хостовС ΠΈ Ρ‚Π΅Ρ…Π½ΠΈΡ‚Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ, Π½ΠΎ скриптовСтС Π½Π΅ са написани Π² ΠΎΡ‚Π΄Π΅Π»Π΅Π½ DSL, Π° Π² ΡΡŠΡ‰ΠΈΡ Π½Π΅ ΠΌΠ½ΠΎΠ³ΠΎ стар, Π½ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ Π΄ΠΎΠ±ΡŠΡ€ p[i|i]ton.

НСка Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠ°ΠΊΠ²ΠΎ прСдставлява, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ слСдния ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π½Π° ΠΆΠΈΠ²ΠΎ.

Имам ΠΊΠ»ΠΎΠ½ΠΎΠ²Π° ΠΌΡ€Π΅ΠΆΠ° ΠΎΡ‚ няколко дСсСтки офиса Π² цялата страна. ВсСки офис Ρ€Π°Π·ΠΏΠΎΠ»Π°Π³Π° с WAN Ρ€ΡƒΡ‚Π΅Ρ€, ΠΊΠΎΠΉΡ‚ΠΎ Ρ‚Π΅Ρ€ΠΌΠΈΠ½ΠΈΡ€Π° няколко ΠΊΠΎΠΌΡƒΠ½ΠΈΠΊΠ°Ρ†ΠΈΠΎΠ½Π½ΠΈ ΠΊΠ°Π½Π°Π»Π° ΠΎΡ‚ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΠΈ. ΠŸΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΡŠΡ‚ Π·Π° ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·ΠΈΡ€Π°Π½Π΅ Π΅ BGP. WAN Ρ€ΡƒΡ‚Π΅Ρ€ΠΈΡ‚Π΅ сС ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Ρ‚ Π² Π΄Π²Π° Π²ΠΈΠ΄Π°: Cisco ISG ΠΈΠ»ΠΈ Juniper SRX.

Π‘Π΅Π³Π° Π·Π°Π΄Π°Ρ‡Π°Ρ‚Π°: трябва Π΄Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Ρ‚Π΅ спСциална ΠΏΠΎΠ΄ΠΌΡ€Π΅ΠΆΠ° Π·Π° видСонаблюдСниС Π½Π° ΠΎΡ‚Π΄Π΅Π»Π΅Π½ ΠΏΠΎΡ€Ρ‚ Π½Π° всички WAN Ρ€ΡƒΡ‚Π΅Ρ€ΠΈ Π½Π° ΠΊΠ»ΠΎΠ½ΠΎΠ²Π°Ρ‚Π° ΠΌΡ€Π΅ΠΆΠ° - Ρ€Π΅ΠΊΠ»Π°ΠΌΠΈΡ€Π°ΠΉΡ‚Π΅ Ρ‚Π°Π·ΠΈ ΠΏΠΎΠ΄ΠΌΡ€Π΅ΠΆΠ° Π² BGP - ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°ΠΉΡ‚Π΅ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° скоростта Π½Π° спСциалния ΠΏΠΎΡ€Ρ‚.

ΠŸΡŠΡ€Π²ΠΎ, трябва Π΄Π° ΠΏΠΎΠ΄Π³ΠΎΡ‚Π²ΠΈΠΌ няколко шаблона, въз основа Π½Π° ΠΊΠΎΠΈΡ‚ΠΎ Ρ‰Π΅ сС Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Ρ‚ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΎΡ‚Π΄Π΅Π»Π½ΠΎ Π·Π° Cisco ΠΈ Juniper. Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° сС подготвят Π΄Π°Π½Π½ΠΈ Π·Π° всяка Ρ‚ΠΎΡ‡ΠΊΠ° ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ Π½Π° Π²Ρ€ΡŠΠ·ΠΊΠ°Ρ‚Π°, Ρ‚.Π΅. ΡΡŠΠ±Π΅Ρ€Π΅Ρ‚Π΅ ΡΡŠΡ‰ΠΈΡ ΠΈΠ½Π²Π΅Π½Ρ‚Π°Ρ€

Π“ΠΎΡ‚ΠΎΠ² шаблон Π·Π° Cisco:

$ cat templates/ios/base.j2 
class-map match-all VIDEO_SURV
 match access-group 111

policy-map VIDEO_SURV
 class VIDEO_SURV
    police 1500000 conform-action transmit  exceed-action drop

interface {{ host.task_data.ifname }}
  description VIDEOSURV
  ip address 10.10.{{ host.task_data.ipsuffix }}.254 255.255.255.0
  service-policy input VIDEO_SURV

router bgp {{ host.task_data.asn }}
  network 10.40.{{ host.task_data.ipsuffix }}.0 mask 255.255.255.0

access-list 11 permit 10.10.{{ host.task_data.ipsuffix }}.0 0.0.0.255
access-list 111 permit ip 10.10.{{ host.task_data.ipsuffix }}.0 0.0.0.255 any

Π¨Π°Π±Π»ΠΎΠ½ Π·Π° Juniper:

$ cat templates/junos/base.j2 
set interfaces {{ host.task_data.ifname }} unit 0 description "Video surveillance"
set interfaces {{ host.task_data.ifname }} unit 0 family inet filter input limit-in
set interfaces {{ host.task_data.ifname }} unit 0 family inet address 10.10.{{ host.task_data.ipsuffix }}.254/24
set policy-options policy-statement export2bgp term 1 from route-filter 10.10.{{ host.task_data.ipsuffix }}.0/24 exact
set security zones security-zone WAN interfaces {{ host.task_data.ifname }}
set firewall policer policer-1m if-exceeding bandwidth-limit 1m
set firewall policer policer-1m if-exceeding burst-size-limit 187k
set firewall policer policer-1m then discard
set firewall policer policer-1.5m if-exceeding bandwidth-limit 1500000
set firewall policer policer-1.5m if-exceeding burst-size-limit 280k
set firewall policer policer-1.5m then discard
set firewall filter limit-in term 1 then policer policer-1.5m
set firewall filter limit-in term 1 then count limiter

Π¨Π°Π±Π»ΠΎΠ½ΠΈΡ‚Π΅, Ρ€Π°Π·Π±ΠΈΡ€Π° сС, Π½Π΅ ΠΈΠ·Π»ΠΈΠ·Π°Ρ‚ ΠΎΡ‚ Π½ΠΈΡ‰ΠΎΡ‚ΠΎ. Π’ΠΎΠ²Π° са ΠΏΠΎ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΠΎ Ρ€Π°Π·Π»ΠΈΠΊΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ Ρ€Π°Π±ΠΎΡ‚Π½ΠΈΡ‚Π΅ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ бяха ΠΈ бяха слСд Ρ€Π΅ΡˆΠ°Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Π·Π°Π΄Π°Ρ‡Π°Ρ‚Π° Π½Π° Π΄Π²Π° ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΈ Ρ€ΡƒΡ‚Π΅Ρ€Π° ΠΎΡ‚ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ ΠΌΠΎΠ΄Π΅Π»ΠΈ.

ΠžΡ‚ Π½Π°ΡˆΠΈΡ‚Π΅ шаблони Π²ΠΈΠΆΠ΄Π°ΠΌΠ΅, Ρ‡Π΅ Π·Π° Π΄Π° Ρ€Π°Π·Ρ€Π΅ΡˆΠΈΠΌ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°, ΠΈΠΌΠ°ΠΌΠ΅ Π½ΡƒΠΆΠ΄Π° само ΠΎΡ‚ Π΄Π²Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚ΡŠΡ€Π° Π·Π° Juniper ΠΈ 3 ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚ΡŠΡ€Π° Π·Π° Cisco. Π•Ρ‚ΠΎ Π³ΠΈ ΠΈ тях:

  • ifname
  • ипсуфикс
  • асн

Π‘Π΅Π³Π° трябва Π΄Π° Π·Π°Π΄Π°Π΄Π΅ΠΌ Ρ‚Π΅Π·ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ Π·Π° всяко устройство, Ρ‚.Π΅. Π½Π°ΠΏΡ€Π°Π²ΠΈ ΡΡŠΡ‰ΠΎΡ‚ΠΎ опис.

Π—Π° опис Π‘Ρ‚Ρ€ΠΈΠΊΡ‚Π½ΠΎ Ρ‰Π΅ спазвамС докумСнтацията Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅ Π½Π° Nornir

тоСст, Π½Π΅ΠΊΠ° създадСм ΡΡŠΡ‰ΠΈΡ Ρ„Π°ΠΉΠ»ΠΎΠ² скСлСт:

.
β”œβ”€β”€ config.yaml
β”œβ”€β”€ inventory
β”‚   β”œβ”€β”€ defaults.yaml
β”‚   β”œβ”€β”€ groups.yaml
β”‚   └── hosts.yaml

Π€Π°ΠΉΠ»ΡŠΡ‚ config.yaml Π΅ стандартният ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΎΠ½Π΅Π½ Ρ„Π°ΠΉΠ» Π½Π° nornir

$ cat config.yaml 
---
core:
    num_workers: 10

inventory:
    plugin: nornir.plugins.inventory.simple.SimpleInventory
    options:
        host_file: "inventory/hosts.yaml"
        group_file: "inventory/groups.yaml"
        defaults_file: "inventory/defaults.yaml"

Π’ΡŠΠ² Ρ„Π°ΠΉΠ»Π° Ρ‰Π΅ посочим основнитС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ hosts.yaml, Π³Ρ€ΡƒΠΏΠ° (Π² моя случай Ρ‚ΠΎΠ²Π° са ΠΈΠΌΠ΅Π½Π°/ΠΏΠ°Ρ€ΠΎΠ»ΠΈ) Π² Π³Ρ€ΡƒΠΏΠΈ.yamlИ Π² defaults.yaml Няма Π΄Π° посочим Π½ΠΈΡ‰ΠΎ, Π½ΠΎ трябва Π΄Π° Π²ΡŠΠ²Π΅Π΄Π΅Ρ‚Π΅ Ρ‚Ρ€ΠΈ минуса Ρ‚Π°ΠΌ - ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΏΠΎΠΊΠ°Π·Π²Π°, Ρ‡Π΅ Π΅ Ρ‚Π°ΠΊΠ° ямъл Ρ„Π°ΠΉΠ»ΡŠΡ‚ ΠΎΠ±Π°Ρ‡Π΅ Π΅ ΠΏΡ€Π°Π·Π΅Π½.

Π•Ρ‚ΠΎ ΠΊΠ°ΠΊ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° hosts.yaml:

---
srx-test:
    hostname: srx-test
    groups: 
        - juniper
    data:
        task_data:
            ifname: fe-0/0/2
            ipsuffix: 111

cisco-test:
    hostname: cisco-test
    groups: 
        - cisco
    data:
        task_data:
            ifname: GigabitEthernet0/1/1
            ipsuffix: 222
            asn: 65111

А Π΅Ρ‚ΠΎ ΠΈ groups.yaml:

---
cisco:
    platform: ios
    username: admin1
    password: cisco1

juniper:
    platform: junos
    username: admin2
    password: juniper2

Π•Ρ‚ΠΎ ΠΊΠ°ΠΊΠ²ΠΎ сС случи опис Π·Π° Π½Π°ΡˆΠ°Ρ‚Π° Π·Π°Π΄Π°Ρ‡Π°. По Π²Ρ€Π΅ΠΌΠ΅ Π½Π° инициализацията ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈΡ‚Π΅ ΠΎΡ‚ ΠΈΠ½Π²Π΅Π½Ρ‚Π°Ρ€Π½ΠΈΡ‚Π΅ Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ сС нанасят Π²ΡŠΡ€Ρ…Ρƒ обСктния ΠΌΠΎΠ΄Π΅Π» InventoryElement.

Под спойлСра ΠΈΠΌΠ° Π΄ΠΈΠ°Π³Ρ€Π°ΠΌΠ° Π½Π° ΠΌΠΎΠ΄Π΅Π»Π° InventoryElement

print(json.dumps(InventoryElement.schema(), indent=4))
{
    "title": "InventoryElement",
    "type": "object",
    "properties": {
        "hostname": {
            "title": "Hostname",
            "type": "string"
        },
        "port": {
            "title": "Port",
            "type": "integer"
        },
        "username": {
            "title": "Username",
            "type": "string"
        },
        "password": {
            "title": "Password",
            "type": "string"
        },
        "platform": {
            "title": "Platform",
            "type": "string"
        },
        "groups": {
            "title": "Groups",
            "default": [],
            "type": "array",
            "items": {
                "type": "string"
            }
        },
        "data": {
            "title": "Data",
            "default": {},
            "type": "object"
        },
        "connection_options": {
            "title": "Connection_Options",
            "default": {},
            "type": "object",
            "additionalProperties": {
                "$ref": "#/definitions/ConnectionOptions"
            }
        }
    },
    "definitions": {
        "ConnectionOptions": {
            "title": "ConnectionOptions",
            "type": "object",
            "properties": {
                "hostname": {
                    "title": "Hostname",
                    "type": "string"
                },
                "port": {
                    "title": "Port",
                    "type": "integer"
                },
                "username": {
                    "title": "Username",
                    "type": "string"
                },
                "password": {
                    "title": "Password",
                    "type": "string"
                },
                "platform": {
                    "title": "Platform",
                    "type": "string"
                },
                "extras": {
                    "title": "Extras",
                    "type": "object"
                }
            }
        }
    }
}

Π’ΠΎΠ·ΠΈ ΠΌΠΎΠ΄Π΅Π» ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΠΌΠ°Π»ΠΊΠΎ ΠΎΠ±ΡŠΡ€ΠΊΠ²Π°Ρ‰ΠΎ, особСно Π² Π½Π°Ρ‡Π°Π»ΠΎΡ‚ΠΎ. Π—Π° Π΄Π° Π³ΠΎ Ρ€Π°Π·Π±Π΅Ρ€Π΅Ρ‚Π΅, интСрактивният Ρ€Π΅ΠΆΠΈΠΌ Π² ipython.

 $ ipython3
Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.1.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from nornir import InitNornir                                                                           

In [2]: nr = InitNornir(config_file="config.yaml", dry_run=True)                                                

In [3]: nr.inventory.hosts                                                                                      
Out[3]: 
{'srx-test': Host: srx-test, 'cisco-test': Host: cisco-test}

In [4]: nr.inventory.hosts['srx-test'].data                                                                                    
Out[4]: {'task_data': {'ifname': 'fe-0/0/2', 'ipsuffix': 111}}

In [5]: nr.inventory.hosts['srx-test']['task_data']                                                     
Out[5]: {'ifname': 'fe-0/0/2', 'ipsuffix': 111}

In [6]: nr.inventory.hosts['srx-test'].platform                                                                                
Out[6]: 'junos'

И накрая, Π½Π΅ΠΊΠ° Π΄Π° ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅ΠΌ към самия сцСнарий. Π’ΡƒΠΊ няма с ΠΊΠ°ΠΊΠ²ΠΎ особСно Π΄Π° сС гордСя. ΠŸΡ€ΠΎΡΡ‚ΠΎ Π²Π·Π΅Ρ… Π³ΠΎΡ‚ΠΎΠ² ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΎΡ‚ ΡƒΡ€ΠΎΠΊ ΠΈ Π³ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΏΠΎΡ‡Ρ‚ΠΈ Π½Π΅ΠΏΡ€ΠΎΠΌΠ΅Π½Π΅Π½. Π•Ρ‚ΠΎ ΠΊΠ°ΠΊ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° готовият Ρ€Π°Π±ΠΎΡ‚Π΅Ρ‰ скрипт:

from nornir import InitNornir
from nornir.plugins.tasks import networking, text
from nornir.plugins.functions.text import print_title, print_result

def config_and_deploy(task):
    # Transform inventory data to configuration via a template file
    r = task.run(task=text.template_file,
                 name="Base Configuration",
                 template="base.j2",
                 path=f"templates/{task.host.platform}")

    # Save the compiled configuration into a host variable
    task.host["config"] = r.result

    # Save the compiled configuration into a file
    with open(f"configs/{task.host.hostname}", "w") as f:
        f.write(r.result)

    # Deploy that configuration to the device using NAPALM
    task.run(task=networking.napalm_configure,
             name="Loading Configuration on the device",
             replace=False,
             configuration=task.host["config"])

nr = InitNornir(config_file="config.yaml", dry_run=True) # set dry_run=False, cross your fingers and run again

# run tasks
result = nr.run(task=config_and_deploy)
print_result(result)

ΠžΠ±ΡŠΡ€Π½Π΅Ρ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚ΡŠΡ€Π° dry_run=Вярно инициализация Π½Π° Π»ΠΈΠ½Π΅ΠΉΠ½ΠΈ ΠΎΠ±Π΅ΠΊΡ‚ΠΈ nr.
Π’ΡƒΠΊ ΡΡŠΡ‰ΠΎΡ‚ΠΎ ΠΊΠ°Ρ‚ΠΎ Π² ansible Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½ΠΎ Π΅ тСстово изпълнСниС, ΠΏΡ€ΠΈ ΠΊΠΎΠ΅Ρ‚ΠΎ сС ΠΎΡΡŠΡ‰Π΅ΡΡ‚Π²ΡΠ²Π° Π²Ρ€ΡŠΠ·ΠΊΠ° с Ρ€ΡƒΡ‚Π΅Ρ€Π°, подготвя сС Π½ΠΎΠ²Π° ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€Π°Π½Π° конфигурация, която слСд Ρ‚ΠΎΠ²Π° сС Π²Π°Π»ΠΈΠ΄ΠΈΡ€Π° ΠΎΡ‚ устройството (Π½ΠΎ Ρ‚ΠΎΠ²Π° Π½Π΅ Π΅ сигурно; зависи ΠΎΡ‚ ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ°Ρ‚Π° Π½Π° устройството ΠΈ внСдряванСто Π½Π° Π΄Ρ€Π°ΠΉΠ²Π΅Ρ€Π° Π² NAPALM) , Π½ΠΎ Π½ΠΎΠ²Π°Ρ‚Π° конфигурация Π½Π΅ сС ΠΏΡ€ΠΈΠ»Π°Π³Π° Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ. Π—Π° Π±ΠΎΠΉΠ½Π° ΡƒΠΏΠΎΡ‚Ρ€Π΅Π±Π° трябва Π΄Π° ΠΏΡ€Π΅ΠΌΠ°Ρ…Π½Π΅Ρ‚Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚ΡŠΡ€Π° суха Ρ‚Ρ€Π΅Π½ΠΈΡ€ΠΎΠ²ΠΊΠ° ΠΈΠ»ΠΈ ΠΏΡ€ΠΎΠΌΠ΅Π½Π΅Ρ‚Π΅ стойността ΠΌΡƒ Π½Π° Ѐалшив.

ΠšΠΎΠ³Π°Ρ‚ΠΎ ΡΠΊΡ€ΠΈΠΏΡ‚ΡŠΡ‚ сС изпълни, Nornir ΠΈΠ·Π²Π΅ΠΆΠ΄Π° ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΈ рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ към ΠΊΠΎΠ½Π·ΠΎΠ»Π°Ρ‚Π°.

Под спойлСра Π΅ ΠΈΠ·Ρ…ΠΎΠ΄ΡŠΡ‚ ΠΎΡ‚ Π±ΠΎΠΉΠ½ΠΎ изпълнСниС Π½Π° Π΄Π²Π° тСстови Ρ€ΡƒΡ‚Π΅Ρ€Π°:

config_and_deploy***************************************************************
* cisco-test ** changed : True *******************************************
vvvv config_and_deploy ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- Base Configuration ** changed : True ------------------------------------- INFO
class-map match-all VIDEO_SURV
 match access-group 111

policy-map VIDEO_SURV
 class VIDEO_SURV
    police 1500000 conform-action transmit  exceed-action drop

interface GigabitEthernet0/1/1
  description VIDEOSURV
  ip address 10.10.222.254 255.255.255.0
  service-policy input VIDEO_SURV

router bgp 65001
  network 10.10.222.0 mask 255.255.255.0

access-list 11 permit 10.10.222.0 0.0.0.255
access-list 111 permit ip 10.10.222.0 0.0.0.255 any
---- Loading Configuration on the device ** changed : True --------------------- INFO
+class-map match-all VIDEO_SURV
+ match access-group 111
+policy-map VIDEO_SURV
+ class VIDEO_SURV
+interface GigabitEthernet0/1/1
+  description VIDEOSURV
+  ip address 10.10.222.254 255.255.255.0
+  service-policy input VIDEO_SURV
+router bgp 65001
+  network 10.10.222.0 mask 255.255.255.0
+access-list 11 permit 10.10.222.0 0.0.0.255
+access-list 111 permit ip 10.10.222.0 0.0.0.255 any
^^^^ END config_and_deploy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* srx-test ** changed : True *******************************************
vvvv config_and_deploy ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- Base Configuration ** changed : True ------------------------------------- INFO
set interfaces fe-0/0/2 unit 0 description "Video surveillance"
set interfaces fe-0/0/2 unit 0 family inet filter input limit-in
set interfaces fe-0/0/2 unit 0 family inet address 10.10.111.254/24
set policy-options policy-statement export2bgp term 1 from route-filter 10.10.111.0/24 exact
set security zones security-zone WAN interfaces fe-0/0/2
set firewall policer policer-1m if-exceeding bandwidth-limit 1m
set firewall policer policer-1m if-exceeding burst-size-limit 187k
set firewall policer policer-1m then discard
set firewall policer policer-1.5m if-exceeding bandwidth-limit 1500000
set firewall policer policer-1.5m if-exceeding burst-size-limit 280k
set firewall policer policer-1.5m then discard
set firewall filter limit-in term 1 then policer policer-1.5m
set firewall filter limit-in term 1 then count limiter
---- Loading Configuration on the device ** changed : True --------------------- INFO
[edit interfaces]
+   fe-0/0/2 {
+       unit 0 {
+           description "Video surveillance";
+           family inet {
+               filter {
+                   input limit-in;
+               }
+               address 10.10.111.254/24;
+           }
+       }
+   }
[edit]
+  policy-options {
+      policy-statement export2bgp {
+          term 1 {
+              from {
+                  route-filter 10.10.111.0/24 exact;
+              }
+          }
+      }
+  }
[edit security zones]
     security-zone test-vpn { ... }
+    security-zone WAN {
+        interfaces {
+            fe-0/0/2.0;
+        }
+    }
[edit]
+  firewall {
+      policer policer-1m {
+          if-exceeding {
+              bandwidth-limit 1m;
+              burst-size-limit 187k;
+          }
+          then discard;
+      }
+      policer policer-1.5m {
+          if-exceeding {
+              bandwidth-limit 1500000;
+              burst-size-limit 280k;
+          }
+          then discard;
+      }
+      filter limit-in {
+          term 1 {
+              then {
+                  policer policer-1.5m;
+                  count limiter;
+              }
+          }
+      }
+  }
^^^^ END config_and_deploy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Π‘ΠΊΡ€ΠΈΠ²Π°Π½Π΅ Π½Π° ΠΏΠ°Ρ€ΠΎΠ»ΠΈ Π² ansible_vault

Π’ Π½Π°Ρ‡Π°Π»ΠΎΡ‚ΠΎ Π½Π° статията ΠΌΠ°Π»ΠΊΠΎ ΠΏΡ€Π΅ΠΊΠ°Π»ΠΈΡ… ansible, Π½ΠΎ Π½Π΅ всичко Π΅ Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° лошо. Много Π³ΠΈ харСсвам свод like, ΠΊΠΎΠΉΡ‚ΠΎ Π΅ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ Π΄Π° скриС чувствитСлна информация извън ΠΏΠΎΠ»Π΅Π·Ρ€Π΅Π½ΠΈΠ΅Ρ‚ΠΎ. И вСроятно ΠΌΠ½ΠΎΠ·ΠΈΠ½Π° са забСлязали, Ρ‡Π΅ ΠΈΠΌΠ°ΠΌΠ΅ всички Π΄Π°Π½Π½ΠΈ Π·Π° Π²Π»ΠΈΠ·Π°Π½Π΅/ΠΏΠ°Ρ€ΠΎΠ»ΠΈ Π·Π° всички Π±ΠΎΠΉΠ½ΠΈ Ρ€ΡƒΡ‚Π΅Ρ€ΠΈ, искрящи Π² ΠΎΡ‚Π²ΠΎΡ€Π΅Π½Π° Ρ„ΠΎΡ€ΠΌΠ° във Ρ„Π°ΠΉΠ» gorups.yaml. НС Π΅ красиво, Ρ€Π°Π·Π±ΠΈΡ€Π° сС. НСка Π·Π°Ρ‰ΠΈΡ‚ΠΈΠΌ Ρ‚Π΅Π·ΠΈ Π΄Π°Π½Π½ΠΈ с свод.

НСка ΠΏΡ€Π΅Ρ…Π²ΡŠΡ€Π»ΠΈΠΌ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈΡ‚Π΅ ΠΎΡ‚ groups.yaml към creds.yaml ΠΈ Π΄Π° Π³ΠΎ ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°ΠΌΠ΅ с AES256 с 20-Ρ†ΠΈΡ„Ρ€Π΅Π½Π° ΠΏΠ°Ρ€ΠΎΠ»Π°:

$ cd inventory
$ cat creds.yaml
---
cisco:
    username: admin1
    password: cisco1

juniper:
    username: admin2
    password: juniper2

$ pwgen 20 -N 1 > vault.passwd
ansible-vault encrypt creds.yaml --vault-password-file vault.passwd  
Encryption successful
$ cat creds.yaml 
$ANSIBLE_VAULT;1.1;AES256
39656463353437333337356361633737383464383231366233386636333965306662323534626131
3964396534396333363939373539393662623164373539620a346565373439646436356438653965
39643266333639356564663961303535353364383163633232366138643132313530346661316533
6236306435613132610a656163653065633866626639613537326233653765353661613337393839
62376662303061353963383330323164633162386336643832376263343634356230613562643533
30363436343465306638653932366166306562393061323636636163373164613630643965636361
34343936323066393763323633336366366566393236613737326530346234393735306261363239
35663430623934323632616161636330353134393435396632663530373932383532316161353963
31393434653165613432326636616636383665316465623036376631313162646435

Π’ΠΎΠ»ΠΊΠΎΠ²Π° Π΅ просто. ΠžΡΡ‚Π°Π²Π° Π΄Π° Π½Π°ΡƒΡ‡ΠΈΠΌ Π½Π°ΡˆΠΈΡ‚Π΅ Норнир-скрипт Π·Π° ΠΈΠ·Π²Π»ΠΈΡ‡Π°Π½Π΅ ΠΈ ΠΏΡ€ΠΈΠ»Π°Π³Π°Π½Π΅ Π½Π° Ρ‚Π΅Π·ΠΈ Π΄Π°Π½Π½ΠΈ.
Π—Π° Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ Ρ‚ΠΎΠ²Π°, Π² нашия скрипт слСд Ρ€Π΅Π΄Π° Π·Π° инициализация nr = InitNornir(config_file=… Π΄ΠΎΠ±Π°Π²Π΅Ρ‚Π΅ слСдния ΠΊΠΎΠ΄:

...
nr = InitNornir(config_file="config.yaml", dry_run=True) # set dry_run=False, cross your fingers and run again

# enrich Inventory with the encrypted vault data
from ansible_vault import Vault
vault_password_file="inventory/vault.passwd"
vault_file="inventory/creds.yaml"
with open(vault_password_file, "r") as fp:
    password = fp.readline().strip()   
    vault = Vault(password)
    vaultdata = vault.load(open(vault_file).read())

for a in nr.inventory.hosts.keys():
    item = nr.inventory.hosts[a]
    item.username = vaultdata[item.groups[0]]['username']
    item.password = vaultdata[item.groups[0]]['password']
    #print("hostname={}, username={}, password={}n".format(item.hostname, item.username, item.password))

# run tasks
...

Π Π°Π·Π±ΠΈΡ€Π° сС, vault.passwd Π½Π΅ трябва Π΄Π° сС Π½Π°ΠΌΠΈΡ€Π° Π΄ΠΎ creds.yaml, ΠΊΠ°ΠΊΡ‚ΠΎ Π² моя ΠΏΡ€ΠΈΠΌΠ΅Ρ€. Но Π΅ Π΄ΠΎΠ±Ρ€Π΅ Π·Π° ΠΈΠ³Ρ€Π°.

Π’ΠΎΠ²Π° Π΅ всичко Π·Π° сСга. Има ΠΎΡ‰Π΅ няколко статии Π·Π° Cisco + Zabbix, Π½ΠΎ Ρ‚ΠΎΠ²Π° Π½Π΅ Π΅ ΠΌΠ°Π»ΠΊΠΎ Π·Π° автоматизацията. И Π² Π±Π»ΠΈΠ·ΠΊΠΎ Π±ΡŠΠ΄Π΅Ρ‰Π΅ смятам Π΄Π° пиша Π·Π° RESTCONF Π² Cisco.

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: www.habr.com

ДобавянС Π½Π° Π½ΠΎΠ² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€