Nornir ን በመጠቀም የአውታረ መረብ መሳሪያ ውቅር ክፍሎችን በራስ ሰር ማመንጨት እና መሙላት

Nornir ን በመጠቀም የአውታረ መረብ መሳሪያ ውቅር ክፍሎችን በራስ ሰር ማመንጨት እና መሙላት

ሃይ ሀብር!

በቅርቡ እዚህ አንድ መጣጥፍ ብቅ አለ። ሚክሮቲክ እና ሊኑክስ። መደበኛ እና አውቶማቲክ ተመሳሳይ ችግር ቅሪተ አካል በመጠቀም የተፈታ ነበር የት. እና ምንም እንኳን ስራው ሙሉ በሙሉ የተለመደ ቢሆንም, በሀበሬ ላይ ምንም ተመሳሳይ ነገር የለም. ብስክሌቴን ለተከበረው የአይቲ ማህበረሰብ ለማቅረብ እደፍራለሁ።

እንዲህ ላለው ተግባር ይህ የመጀመሪያው ብስክሌት አይደለም. የመጀመሪያው አማራጭ ከብዙ አመታት በፊት ተተግብሯል ያረጀ ስሪት 1.x.x. ብስክሌቱ ብዙም ጥቅም ላይ ያልዋለ ስለሆነ ያለማቋረጥ ዝገት። ሥሪቶች ሲዘምኑ ሥራው ራሱ ብዙ ጊዜ አይነሳም በሚለው ስሜት ያረጀ. እና መንዳት በሚፈልጉበት ጊዜ ሁሉ ሰንሰለቱ ይወድቃል ወይም ተሽከርካሪው ይወድቃል። ሆኖም ግን, የመጀመሪያው ክፍል, ውቅሮችን በማፍለቅ, ሁልጊዜም በጣም ግልጽ በሆነ መልኩ ይሰራል, እንደ እድል ሆኖ ጂንጃ2 ሞተሩ ለረጅም ጊዜ ተመስርቷል. ግን ሁለተኛው ክፍል - አወቃቀሮችን መልቀቅ - ብዙውን ጊዜ አስገራሚ ነገሮችን አምጥቷል። እና አወቃቀሩን በርቀት ወደ ግማሽ መቶ መሳሪያዎች መልቀቅ ስላለብኝ ፣ አንዳንዶቹ በሺዎች የሚቆጠሩ ኪሎ ሜትሮች ርቀው ይገኛሉ ፣ ይህንን መሳሪያ መጠቀም ትንሽ አሰልቺ ነበር።

እዚህ ላይ እርግጠኛ አለመሆኔ ምናልባት ካለማወቅ ጋር የተያያዘ መሆኑን መቀበል አለብኝ ያረጀከጉድለቶቹ ይልቅ። እና ይሄ, በነገራችን ላይ, አስፈላጊ ነጥብ ነው. ያረጀ ሙሉ በሙሉ የተለየ ፣ የራሱ የእውቀት ክልል ከራሱ DSL (የጎራ ልዩ ቋንቋ) ጋር ፣ በራስ መተማመን ደረጃ መቀመጥ አለበት። ደህና ፣ ያ ቅጽበት ያረጀ በፍጥነት እያደገ ነው፣ እና ለኋላ ተኳኋኝነት ልዩ ግምት ከሌለው በራስ መተማመንን አይጨምርም።

ስለዚህ, ብዙም ሳይቆይ የብስክሌት ሁለተኛ ስሪት ተተግብሯል. በዚህ ጊዜ ጭረት፣ ወይም ይልቁንም በ ውስጥ በተፃፈ ማዕቀፍ ላይ ጭረት እና ለ ጭረት በዚህ ስም ኖርኒር

ስለዚህ - ኖርኒር ውስጥ የተጻፈ የማይክሮ ፍሬም ሥራ ነው። ጭረት እና ለ ጭረት እና ለራስ-ሰር የተነደፈ. ከጉዳዩ ጋር ተመሳሳይ ነው ያረጀ, እዚህ ችግሮችን ለመፍታት, ብቃት ያለው የውሂብ ዝግጅት ያስፈልጋል, ማለትም. የአስተናጋጆች ክምችት እና መመዘኛዎቻቸው፣ ግን ስክሪፕቶች የተፃፉት በተለየ DSL አይደለም፣ ግን በተመሳሳይ በጣም ያረጁ አይደሉም፣ ግን በጣም ጥሩ ፒ[i|i] ቶን።

የሚከተለውን የቀጥታ ምሳሌ በመጠቀም ምን እንደሆነ እንመልከት።

በመላው አገሪቱ በርካታ ደርዘን ቢሮዎች ያሉት የቅርንጫፍ ኔትወርክ አለኝ። እያንዳንዱ ቢሮ ከተለያዩ ኦፕሬተሮች ብዙ የመገናኛ መንገዶችን የሚያቋርጥ WAN ራውተር አለው። የማዞሪያው ፕሮቶኮል BGP ነው። WAN ራውተሮች በሁለት ዓይነቶች ይመጣሉ፡ Cisco ISG ወይም Juniper SRX።

አሁን ስራው: በሁሉም የቅርንጫፍ አውታር WAN ራውተሮች ላይ በተለየ ወደብ ላይ ለቪዲዮ ክትትል የተለየ ንዑስ መረብ ማዋቀር ያስፈልግዎታል - ይህንን ንዑስ መረብ በ BGP ውስጥ ያስተዋውቁ - የተመደበውን ወደብ የፍጥነት ወሰን ያዋቅሩ።

በመጀመሪያ ፣ ለ Cisco እና Juniper በተናጥል የሚፈጠሩ ውቅሮች በየትኛው መሠረት ሁለት አብነቶችን ማዘጋጀት አለብን። እንዲሁም ለእያንዳንዱ ነጥብ እና የግንኙነት መለኪያዎች ውሂብ ማዘጋጀት አስፈላጊ ነው, ማለትም. ተመሳሳይ ክምችት ይሰብስቡ

ለሲስኮ ዝግጁ አብነት፡-

$ 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 መለኪያዎች ብቻ እንፈልጋለን። እነሆ፡-

  • ስም ከሆነ
  • ipsuffix
  • አስን

አሁን እነዚህን መለኪያዎች ለእያንዳንዱ መሳሪያ ማዘጋጀት አለብን, ማለትም. ተመሳሳይ ነገር አድርግ ክምችት.

ክምችት ሰነዶቹን በጥብቅ እንከተላለን ኖርኒርን በማስጀመር ላይ

ይኸውም ተመሳሳይ የፋይል አጽም እንፍጠር፡-

.
├── 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እና ውስጥ ነባሪዎች.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

የሆነውም ይህ ነው። ክምችት ለተግባራችን። በመነሻ ጊዜ፣ ከዕቃ ዝርዝር ፋይሎች ግቤቶች ወደ ዕቃው ሞዴል ተቀርፀዋል። የእቃ ዝርዝር.

ከተበላሸው በታች የ 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"
                }
            }
        }
    }
}

ይህ ሞዴል ትንሽ ግራ የሚያጋባ ሊመስል ይችላል, በተለይም በመጀመሪያ. እሱን ለማወቅ፣ በይነተገናኝ ሁነታ ውስጥ አይፒቶን.

 $ 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.
እዚህ ጋር ተመሳሳይ ነው። ያረጀ ከራውተሩ ጋር ግንኙነት የሚፈጠርበት የሙከራ ሂደት ተተግብሯል ፣ አዲስ የተሻሻለ ውቅር ተዘጋጅቷል ፣ ከዚያም በመሣሪያው የተረጋገጠ (ነገር ግን ይህ እርግጠኛ አይደለም ፣ በመሣሪያው ድጋፍ እና በ 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 ውስጥ የይለፍ ቃሎችን በመደበቅ ላይ

በጽሁፉ መጀመሪያ ላይ ትንሽ ወደ ውስጥ ገባሁ ያረጀ, ግን ያ ሁሉ መጥፎ አይደለም. በጣም እወዳቸዋለሁ ጎጆ ሚስጥራዊነት ያለው መረጃ ከእይታ ውጭ ለመደበቅ የተነደፈ ፣ like። እና ምናልባት ብዙዎች በፋይል ውስጥ በክፍት ቅጽ ውስጥ የሚያብረቀርቁ ለሁሉም የውጊያ ራውተሮች ሁሉም መግቢያዎች / የይለፍ ቃሎች እንዳሉን አስተውለው ይሆናል። gorups.yaml. በእርግጥ ቆንጆ አይደለም. ይህን ውሂብ በ ጋር እንጠብቀው። ጎጆ.

መለኪያዎችን ከgroup.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 ለመጻፍ እቅድ አለኝ.

ምንጭ: hab.com

አስተያየት ያክሉ