рдиреЙрд░реНрдирд┐рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдиреЗрдЯрд╡рд░реНрдХ рдбрд┐рд╡рд╛рдЗрд╕ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рддрддреНрд╡реЛрдВ рдХрд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдирд┐рд░реНрдорд╛рдг рдФрд░ рднрд░рдирд╛

рдиреЙрд░реНрдирд┐рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдиреЗрдЯрд╡рд░реНрдХ рдбрд┐рд╡рд╛рдЗрд╕ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рддрддреНрд╡реЛрдВ рдХрд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдирд┐рд░реНрдорд╛рдг рдФрд░ рднрд░рдирд╛

рд╣реЗ рд╣рдмрд░!

рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдпрд╣рд╛рдВ рдПрдХ рд▓реЗрдЦ рд╕рд╛рдордиреЗ рдЖрдпрд╛ рдорд┐рдХрд░реЛрдЯрд┐рдХ рдФрд░ рд▓рд┐рдирдХреНрд╕ред рджрд┐рдирдЪрд░реНрдпрд╛ рдФрд░ рд╕реНрд╡рдЪрд╛рд▓рди рдЬрд╣рд╛рдВ рдЬреАрд╡рд╛рд╢реНрдо рд╕рд╛рдзрдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╕рдорд╛рди рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдФрд░ рдпрджреНрдпрдкрд┐ рдХрд╛рд░реНрдп рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реИ, рд╣реИрдмреЗ рдкрд░ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рднреА рд╕рдорд╛рди рдирд╣реАрдВ рд╣реИред рдореИрдВ рдкреНрд░рддрд┐рд╖реНрдард┐рдд рдЖрдИрдЯреА рд╕рдореБрджрд╛рдп рдХреЛ рдЕрдкрдиреА рд╕рд╛рдЗрдХрд┐рд▓ рдкреЗрд╢ рдХрд░рдиреЗ рдХрд╛ рд╕рд╛рд╣рд╕ рдХрд░рддрд╛ рд╣реВрдВред

рдЗрд╕ рддрд░рд╣ рдХреЗ рдХрд╛рдо рдХреЗ рд▓рд┐рдП рдпреЗ рдкрд╣рд▓реА рдмрд╛рдЗрдХ рдирд╣реАрдВ рд╣реИ. рдкрд╣рд▓рд╛ рд╡рд┐рдХрд▓реНрдк рдХрдИ рд╕рд╛рд▓ рдкрд╣рд▓реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ansible рд╕рдВрд╕реНрдХрд░рдг 1.x.x. рд╕рд╛рдЗрдХрд┐рд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдмрд╣реБрдд рдХрдо рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рдерд╛ рдФрд░ рдЗрд╕рд▓рд┐рдП рдЗрд╕рдореЗрдВ рд▓рдЧрд╛рддрд╛рд░ рдЬрдВрдЧ рд▓рдЧрддреА рд░рд╣рддреА рдереАред рдЗрд╕ рдЕрд░реНрде рдореЗрдВ рдХрд┐ рдЬрд┐рддрдиреА рдмрд╛рд░ рд╕рдВрд╕реНрдХрд░рдг рдЕрджреНрдпрддрди рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ рдЙрддрдиреА рдмрд╛рд░ рдХрд╛рд░реНрдп рд╕реНрд╡рдпрдВ рдЙрддреНрдкрдиреНрди рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ ansible. рдФрд░ рд╣рд░ рдмрд╛рд░ рдЬрдм рдЖрдкрдХреЛ рдЧрд╛рдбрд╝реА рдЪрд▓рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рдЪреЗрди рдЧрд┐рд░ рдЬрд╛рддреА рд╣реИ рдпрд╛ рдкрд╣рд┐рдпрд╛ рдЧрд┐рд░ рдЬрд╛рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╕реМрднрд╛рдЧреНрдп рд╕реЗ рдкрд╣рд▓рд╛ рднрд╛рдЧ, рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рд╡рд╛рд▓рд╛, рд╣рдореЗрд╢рд╛ рдмрд╣реБрдд рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ jinja2 рдЗрдВрдЬрди рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рд╣реИ. рд▓реЗрдХрд┐рди рджреВрд╕рд░рд╛ рднрд╛рдЧ - рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЛ рд░реЛрд▓ рдЖрдЙрдЯ рдХрд░рдирд╛ - рдЖрдорддреМрд░ рдкрд░ рдЖрд╢реНрдЪрд░реНрдп рд▓реЗрдХрд░ рдЖрдпрд╛ред рдФрд░ рдЪреВрдБрдХрд┐ рдореБрдЭреЗ рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдХреЛ рдЖрдзрд╛ рд╕реМ рдбрд┐рд╡рд╛рдЗрд╕реЛрдВ рдореЗрдВ рджреВрд░рд╕реНрде рд░реВрдк рд╕реЗ рд░реЛрд▓ рдЖрдЙрдЯ рдХрд░рдирд╛ рд╣реИ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдХреБрдЫ рд╣рдЬрд╛рд░реЛрдВ рдХрд┐рд▓реЛрдореАрдЯрд░ рджреВрд░ рд╕реНрдерд┐рдд рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЗрд╕ рдЯреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдереЛрдбрд╝рд╛ рдЙрдмрд╛рдК рдерд╛ред

рдпрд╣рд╛рдВ рдореБрдЭреЗ рдпрд╣ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдореЗрд░реА рдЕрдирд┐рд╢реНрдЪрд┐рддрддрд╛ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рдореЗрд░реА рдкрд░рд┐рдЪрд┐рддрддрд╛ рдХреА рдХрдореА рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИ ansibleрдЗрд╕рдХреА рдХрдорд┐рдпреЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВред рдФрд░ рд╡реИрд╕реЗ, рдпрд╣ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдВрджреБ рд╣реИред ansible рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ, рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдбреАрдПрд╕рдПрд▓ (рдбреЛрдореЗрди рд╡рд┐рд╢рд┐рд╖реНрдЯ рднрд╛рд╖рд╛) рдХреЗ рд╕рд╛рде рдЬреНрдЮрд╛рди рдХрд╛ рдЕрдкрдирд╛ рдХреНрд╖реЗрддреНрд░ рд╣реИ, рдЬрд┐рд╕реЗ рдЖрддреНрдорд╡рд┐рд╢реНрд╡рд╛рд╕ рдХреЗ рд╕реНрддрд░ рдкрд░ рдмрдирд╛рдП рд░рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЦреИрд░, рд╡рд╣ рдХреНрд╖рдг рд╡рд╣ ansible рдпрд╣ рдХрд╛рдлреА рддреЗрдЬрд╝реА рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдФрд░ рдкрд┐рдЫрдбрд╝реА рдЕрдиреБрдХреВрд▓рддрд╛ рдкрд░ рд╡рд┐рд╢реЗрд╖ рдзреНрдпрд╛рди рджрд┐рдП рдмрд┐рдирд╛, рдпрд╣ рдЖрддреНрдорд╡рд┐рд╢реНрд╡рд╛рд╕ рдирд╣реАрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИред

рдЗрд╕рд▓рд┐рдП, рдмрд╣реБрдд рд╕рдордп рдкрд╣рд▓реЗ рд╕рд╛рдЗрдХрд┐рд▓ рдХрд╛ рджреВрд╕рд░рд╛ рд╕рдВрд╕реНрдХрд░рдг рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЗрд╕ рдмрд╛рд░ рдЕрдЬрдЧрд░, рдпрд╛ рдпреВрдБ рдХрд╣реЗрдВ рдХрд┐ рдХрд┐рд╕реА рдврд╛рдБрдЪреЗ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ рдЕрдЬрдЧрд░ рдФрд░ рдХреЗ рд▓рд┐рдП рдЕрдЬрдЧрд░ рд╣рдХрджрд╛рд░ рдиреЛрд░реНрдирд┐рд░

рдЗрд╕рд▓рд┐рдП - рдиреЛрд░реНрдирд┐рд░ рдПрдХ рдорд╛рдЗрдХреНрд░реЛрдлреНрд░реЗрдорд╡рд░реНрдХ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ рдЕрдЬрдЧрд░ рдФрд░ рдХреЗ рд▓рд┐рдП рдЕрдЬрдЧрд░ рдФрд░ рд╕реНрд╡рдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ред рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рднреА рд╡реИрд╕рд╛ рд╣реА ansible, рдпрд╣рд╛рдВ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕рдХреНрд╖рдо рдбреЗрдЯрд╛ рддреИрдпрд╛рд░реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рддред рдореЗрдЬрдмрд╛рдиреЛрдВ рдХреА рд╕реВрдЪреА рдФрд░ рдЙрдирдХреЗ рдкреИрд░рд╛рдореАрдЯрд░, рд▓реЗрдХрд┐рди рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдПрдХ рдЕрд▓рдЧ рдбреАрдПрд╕рдПрд▓ рдореЗрдВ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рдмрд╣реБрдд рдкреБрд░рд╛рдиреЗ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рдмрд╣реБрдд рдЕрдЪреНрдЫреЗ рдкреА[рдЖрдИ|рдЖрдИ]рдЯрди рдореЗрдВ рд▓рд┐рдЦреА рдЬрд╛рддреА рд╣реИрдВред

рдЖрдЗрдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓рд╛рдЗрд╡ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рдХреНрдпрд╛ рд╣реИред

рдкреВрд░реЗ рджреЗрд╢ рдореЗрдВ рдХрдИ рджрд░реНрдЬрди рдХрд╛рд░реНрдпрд╛рд▓рдпреЛрдВ рдХреЗ рд╕рд╛рде рдореЗрд░рд╛ рдПрдХ рд╢рд╛рдЦрд╛ рдиреЗрдЯрд╡рд░реНрдХ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдпрд╛рд▓рдп рдореЗрдВ рдПрдХ WAN рд░рд╛рдЙрдЯрд░ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рд╡рд┐рднрд┐рдиреНрди рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреЗ рдХрдИ рд╕рдВрдЪрд╛рд░ рдЪреИрдирд▓реЛрдВ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рд░реВрдЯрд┐рдВрдЧ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдмреАрдЬреАрдкреА рд╣реИред WAN рд░рд╛рдЙрдЯрд░ рджреЛ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рдЖрддреЗ рд╣реИрдВ: рд╕рд┐рд╕реНрдХреЛ ISG рдпрд╛ рдЬреБрдирд┐рдкрд░ SRXред

рдЕрдм рдХрд╛рд░реНрдп: рдЖрдкрдХреЛ рд╢рд╛рдЦрд╛ рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рд╕рднреА WAN рд░рд╛рдЙрдЯрд░ рдкрд░ рдПрдХ рдЕрд▓рдЧ рдкреЛрд░реНрдЯ рдкрд░ рд╡реАрдбрд┐рдпреЛ рдирд┐рдЧрд░рд╛рдиреА рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдорд░реНрдкрд┐рдд рд╕рдмрдиреЗрдЯ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рдЗрд╕ рд╕рдмрдиреЗрдЯ рдХреЛ рдмреАрдЬреАрдкреА рдореЗрдВ рд╡рд┐рдЬреНрдЮрд╛рдкрд┐рдд рдХрд░реЗрдВ - рд╕рдорд░реНрдкрд┐рдд рдкреЛрд░реНрдЯ рдХреА рдЧрддрд┐ рд╕реАрдорд╛ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдХреБрдЫ рдЯреЗрдореНрдкрд▓реЗрдЯ рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╕рд┐рд╕реНрдХреЛ рдФрд░ рдЬреБрдирд┐рдкрд░ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рддреИрдпрд╛рд░ рдХрд┐рдП рдЬрд╛рдПрдВрдЧреЗред рдкреНрд░рддреНрдпреЗрдХ рдмрд┐рдВрджреБ рдФрд░ рдХрдиреЗрдХреНрд╢рди рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рддреИрдпрд╛рд░ рдХрд░рдирд╛ рднреА рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЕрд░реНрдерд╛рддред рд╕рдорд╛рди рд╕реВрдЪреА рдПрдХрддреНрд░рд┐рдд рдХрд░реЗрдВ

рд╕рд┐рд╕реНрдХреЛ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рдЯреЗрдореНрдкрд▓реЗрдЯ:

$ 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

рдЬреБрдирд┐рдкрд░ рдХреЗ рд▓рд┐рдП рдЯреЗрдореНрдкрд▓реЗрдЯ:

$ 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

рдмреЗрд╢рдХ, рдЯреЗрдореНрдкреНрд▓реЗрдЯ рд╣рд╡рд╛ рд╕реЗ рдирд╣реАрдВ рдЖрддреЗред рдпреЗ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдХрд╛рд░реНрдпрд╢реАрд▓ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рдмреАрдЪ рдЕрдВрддрд░ рд╣реИрдВ рдЬреЛ рд╡рд┐рднрд┐рдиреНрди рдореЙрдбрд▓реЛрдВ рдХреЗ рджреЛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд░рд╛рдЙрдЯрд░ рдкрд░ рдХрд╛рд░реНрдп рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдереЗ рдФрд░ рдереЗред

рд╣рдорд╛рд░реЗ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рд╕реЗ рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЬреБрдирд┐рдкрд░ рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рджреЛ рдкреИрд░рд╛рдореАрдЯрд░ рдФрд░ рд╕рд┐рд╕реНрдХреЛ рдХреЗ рд▓рд┐рдП 3 рдкреИрд░рд╛рдореАрдЯрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╡реЗ рдпрд╣рд╛рдБ рд╣реИрдВ:

  • ifname
  • ipsuffix
  • ASN

рдЕрдм рд╣рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдбрд┐рд╡рд╛рдЗрд╕ рдХреЗ рд▓рд┐рдП рдпреЗ рдкреИрд░рд╛рдореАрдЯрд░ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рддред рд╡рд╣реАрдВ рдХрд╛рдо рдХрд░реЗрдВ рд╕реВрдЪреА.

рдХреЗ рд▓рд┐рдП рд╕реВрдЪреА рд╣рдо рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдХрд╛ рд╕рдЦреНрддреА рд╕реЗ рдкрд╛рд▓рди рдХрд░реЗрдВрдЧреЗ рдиреЙрд░реНрдирд┐рд░ рдХреА рд╢реБрд░реБрдЖрдд

рдпрд╛рдиреА, рдЖрдЗрдП рд╡рд╣реА рдлрд╝рд╛рдЗрд▓ рд╕реНрдХреЗрд▓реЗрдЯрди рдмрдирд╛рдПрдВ:

.
тФЬтФАтФА config.yaml
тФЬтФАтФА inventory
тФВ   тФЬтФАтФА defaults.yaml
тФВ   тФЬтФАтФА groups.yaml
тФВ   тФФтФАтФА hosts.yaml

config.yaml рдлрд╝рд╛рдЗрд▓ рдорд╛рдирдХ рдиреЙрд░реНрдирд┐рд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рд╣реИ

$ 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"

рд╣рдо рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдореБрдЦреНрдп рдкреИрд░рд╛рдореАрдЯрд░ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВрдЧреЗ рдореЗрдЬрд╝рдмрд╛рди.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

рдФрд░ рдпрд╣рд╛рдБ рд╕рдореВрд╣ рд╣реИрдВ.yaml:

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

juniper:
    platform: junos
    username: admin2
    password: juniper2

рдпрд╣ рд╣реБрдЖ рдерд╛ рд╕реВрдЪреА рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП. рдЖрд░рдВрднреАрдХрд░рдг рдХреЗ рджреМрд░рд╛рди, рдЗрдиреНрд╡реЗрдВрдЯреНрд░реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЙрдбрд▓ рдкрд░ рдореИрдк рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЗрдиреНрд╡реЗрдВрдЯрд░реА рддрддреНрд╡.

рд╕реНрдкреЙрдЗрд▓рд░ рдХреЗ рдиреАрдЪреЗ рдЗрдиреНрд╡реЗрдВрдЯрд░реАрдПрд▓рд┐рдореЗрдВрдЯ рдореЙрдбрд▓ рдХрд╛ рдПрдХ рдЖрд░реЗрдЦ рд╣реИ

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"
                }
            }
        }
    }
}

рдпрд╣ рдореЙрдбрд▓ рдереЛрдбрд╝рд╛ рднреНрд░рдорд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ, рдЦрд╛рд╕рдХрд░ рд╢реБрд░реБрдЖрдд рдореЗрдВред рдЗрд╕рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрдВрдЯрд░реИрдХреНрдЯрд┐рд╡ рдореЛрдб рдореЗрдВ рдЖрдИрдкреАрдереЙрди.

 $ 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)

рдкреИрд░рд╛рдореАрдЯрд░ рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ рдбреНрд░рд╛рдИ_рд░рди = рд╕рддреНрдп рд▓рд╛рдЗрди рдСрдмреНрдЬреЗрдХреНрдЯ рдЖрд░рдВрднреАрдХрд░рдг рдореЗрдВ nr.
рдпрд╣рд╛рдБ рднреА рд╡реИрд╕рд╛ рд╣реА рд╣реИ рдЬреИрд╕рд╛ рдЕрдВрджрд░ рд╣реИ ansible рдПрдХ рдкрд░реАрдХреНрд╖рдг рд░рди рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд░рд╛рдЙрдЯрд░ рд╕реЗ рдХрдиреЗрдХреНрд╢рди рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдПрдХ рдирдпрд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рддрдм рдбрд┐рд╡рд╛рдЗрд╕ рджреНрд╡рд╛рд░рд╛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рд▓реЗрдХрд┐рди рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ; рдпрд╣ рдбрд┐рд╡рд╛рдЗрд╕ рд╕рдорд░реНрдерди рдФрд░ NAPALM рдореЗрдВ рдбреНрд░рд╛рдЗрд╡рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ) , рд▓реЗрдХрд┐рди рдирдпрд╛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╕реАрдзреЗ рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рд▓рдбрд╝рд╛рдХреВ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рд╣рдЯрд╛рдирд╛ рд╣реЛрдЧрд╛ рдкреВрд░реНрд╡рд╛рднреНрдпрд╛рд╕ рдпрд╛ рдЗрд╕рдХрд╛ рдорд╛рди рдмрджрд▓реЗрдВ рдЭреВрдард╛.

рдЬрдм рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрддреА рд╣реИ, рддреЛ рдиреЙрд░реНрдирд┐рд░ рдХрдВрд╕реЛрд▓ рдкрд░ рд╡рд┐рд╕реНрддреГрдд рд▓реЙрдЧ рдЖрдЙрдЯрдкреБрдЯ рдХрд░рддрд╛ рд╣реИред

рд╕реНрдкреЙрдЗрд▓рд░ рдХреЗ рдиреАрдЪреЗ рджреЛ рдЯреЗрд╕реНрдЯ рд░рд╛рдЙрдЯрд░реНрд╕ рдкрд░ рдХреЙрдореНрдмреИрдЯ рд░рди рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ рд╣реИ:

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, рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдм рдЙрддрдирд╛ рдмреБрд░рд╛ рдирд╣реАрдВ рд╣реИред рдореБрдЭреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╡реЗ рдкрд╕рдВрдж рд╣реИрдВ рдореЗрд╣рд░рд╛рдм рдЬреИрд╕реЗ, рдЬреЛ рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдирдЬрд╝рд░реЛрдВ рд╕реЗ рдЫрд┐рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдФрд░ рд╢рд╛рдпрдж рдХрдИ рд▓реЛрдЧреЛрдВ рдиреЗ рджреЗрдЦрд╛ рд╣реЛрдЧрд╛ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╕рднреА рдХреЙрдореНрдмреИрдЯ рд░рд╛рдЙрдЯрд░реНрд╕ рдХреЗ рд▓рд┐рдП рд╕рднреА рд▓реЙрдЧрд┐рди/рдкрд╛рд╕рд╡рд░реНрдб рдПрдХ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЦреБрд▓реЗ рд░реВрдк рдореЗрдВ рдЪрдордХ рд░рд╣реЗ рд╣реИрдВ gorups.yaml. рдирд┐рдГрд╕рдВрджреЗрд╣, рдпрд╣ рд╕реБрдВрджрд░ рдирд╣реАрдВ рд╣реИред рдЖрдЗрдП рдЗрд╕ рдбреЗрдЯрд╛ рдХреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░рдЦреЗрдВ рдореЗрд╣рд░рд╛рдм.

рдЖрдЗрдП рдкреИрд░рд╛рдореАрдЯрд░реНрд╕ рдХреЛ Groups.yaml рд╕реЗ creds.yaml рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВ, рдФрд░ рдЗрд╕реЗ 256 рдЕрдВрдХреЛрдВ рдХреЗ рдкрд╛рд╕рд╡рд░реНрдб рдХреЗ рд╕рд╛рде AES20 рдХреЗ рд╕рд╛рде рдПрдиреНрдХреНрд░рд┐рдкреНрдЯ рдХрд░реЗрдВ:

$ 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 рдХреЗ рдмрдЧрд▓ рдореЗрдВ рд╕реНрдерд┐рдд рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд▓реЗрдХрд┐рди рдпрд╣ рдЦреЗрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдареАрдХ рд╣реИ.

рдЕрднреА рдХреЗ рд▓рд┐рдП рдЗрддрдирд╛ рд╣реАред рд╕рд┐рд╕реНрдХреЛ + рдЬрд╝реИрдмрд┐рдХреНрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рдФрд░ рд▓реЗрдЦ рдЖрдиреЗ рд╡рд╛рд▓реЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕реНрд╡рдЪрд╛рд▓рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИред рдФрд░ рдирд┐рдХрдЯ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдореЗрд░реА рд╕рд┐рд╕реНрдХреЛ рдореЗрдВ RESTCONF рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓рд┐рдЦрдиреЗ рдХреА рдпреЛрдЬрдирд╛ рд╣реИред

рд╕реНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╝реЗрдВ