지난 OTV 7번째 포스팅과 살짝 순서가 바뀐 OTV 8번째 포스팅입니다.

앞으로 몇 번이 될지는 모르겠으나, 우선 OTV 관련 포스팅이 몇 번 더 올라갈 듯 싶습니다.

그렇다고 그 몇 번으로 OTV 완결이라는 것은 아니지만요. ^^;

그럼 한 분이라도 도움이 되시길 바라며...


 

Failure Isolation

   - 모든 LAN 확장 솔루션의 주요 요구 사항 중에 하나는 Remote Site 간의 resiliency, stability, scalability 등의 장점을 유지한 채,

     Layer 2 연결성을 Routed Transport Infrastructure을 통해서 제공하는 것이다.

   - OTV는 STP 분리 / Unknown Unicast 억제 / ARP 최적화 / Broadcast 정책 제어를 통해서 이 목표를 달성하고 있다.

 

 

STP Isolation

     -  OTV는 기본적으로 Overlay를 통해서 STP BPDU를 전송하지 않는다. 이는 별도의 BPDU Filtering과 같은 설정을 추가로 하지

       않아도 되는, 기본적인 동작 방식이다.  이를 통해 각 OTV Site는 STP Domain을 독립적으로 운용된다.

     -  STP Domain이 독립적으로 운용되기 떄문에 STP Control Plane에서 발생할 수 있는 문제점들은 Remote Site에 영향을 미치지

        못하게 된다. 하지만, 이러한 STP BPDU를 전송하지 않고 Transport Infrastructure를 통해 Layer 2를 확장함으로써 잠재적인

        end-to-end Loop 구조가 발생할 수 있게 된다. OTV에서 STP Frame을 전송하지 않으면서 이러한 end-to-end loop를 예방하기

        위한 내용은 추후에 Multi-Homing 부분에서 언급되게 된다.

                                                             ※ Multi-Homing은 다음 포스팅에서 다뤄지며, 추후 포스팅 시에 링크로 연결해 놓겠습니다.

 

Unknown Unicast Handling

     - OTV Control Protocol은 OTV edge Device들 간의 MAC-Address와 Destination의 IP Next hop에 대한 Mapping정보로

       MAC Address reachability 정보를 광고하게 된다. 결과적으로 기존에 Remote Site의 MAC Address로 통신이 가능하도록

       Mapping정보를 받게 되며, Overlay를 통한 Layer 2 Traffic은 OTV Device를 통하여 Routing을 하는 것처럼 동작한다.

     - OTV Edge device가 자신의 Mac Table에 존재하지 않는 Mac 주소를 목적지로 하는 Frame을 받으면(Unknown Unicast),

       Layer 2 Lookup을 하게 되고, Table에 없는 것을 확인하고 Layer Traffic을 Internal interface들로 Flooding하며,

       Overlay로는 전송하지 않는다.

       ※ 이는 비정상적인 Mac을 생성하여 DoS Attack을 하는 경우에 대한 문제를 예방할 수 있다.

     - Microsoft의 Network Load Balancing Services(NLBS)와 같은 Layer 2 Traffic에 대한 Flooding이 필요한 특정 Application을

       위해서 선택적으로 Flooding을 할 수 있도록 설정을 할 수 는 있다. 이러한 개별 MAC-Address를 Static하게 설정하여,

       Frame이 Drop되지 않고 모든 Remote OTV Edge Device로 Broadcast 하도록 하는 것처럼 Overlay를 통해서 Flooding 하는

      것은 매우 예외적으로 사용되는 설정이며, 기본 동작은 Unknown unicast에 대해서는 Drop된다고 보면 된다.

       ※ NX-OS Release 6.2(2)부터 이러한 선택적인 Unicast Flooding에 대한 DCI간의 Flooding을 지원한다.

 

 

ARP Optimization

     - ARP Optimization은 Transport Infrastructure를 통해서 흐르는 Traffic을 감소시키는 기능이다.

  

     - 동작 방식은 다음과 같다.

        Step 1. West Site의 Device가 IP A에 대한 Host의 Mac-Address를 확인하기 위해 ARP Request를 보낸다.

        Step 2. ARP Request는 OTV Overlay를 통해서 모든 Remote Site로 전송되어, IP A를 가지는 Host에서 ARP Reply를 보낸다.

        Step 3. West Site의 OTV Edge Device는 ARP Reply를 감지하고 이를 ARP Neighbor-Discovery(ND) Cache라고 부르는

                    Local Data Structure안에  (MAC, IP)를 Mapping한 정보를 저장한다.

        Step 4. 이후, West Site의 다른 Host가 IP A에 대한 ARP Request를 보내게 된다.

        Step 5. West Site OTV Edge Device는 IP A를 가진 Remote Host 대신에 Local에 저장해 놓은 정보를 대신 응답을 한다.

 

 

 

 

    - 하지만, 위와 같은 ARP caching 동작은 ARP와 CAM Table간의 Aging Timer의 차이로 인해서 Black-holing Traffic이

       발생할 수도 있다. 이는 위에서 다루었던 OTV에서의 Unknown Unicast를 Drop시키는 특징 때문이기도 한다.

        Step 1. West Site의 Device가 IP A에 대한 Host의 Mac-Address를 확인하기 위해 ARP Request를 보낸다.

        Step 2. ARP Request는 OTV Overlay를 통해서 모든 Remote Site로 전송되어, IP A를 가지는 Host에서 ARP Reply를 보낸다.

                    West Site의 OTV Edge Device는 ARP Reply를 감지하고 이를 ARP Neighbor-Discovery(ND) Cache라고 부르는

                    Local Data Structure안에  (MAC, IP)를 Mapping한 정보를 저장한다.

        Step 3. IP A의 Host가 East Site에서 CAM aging 만료로 인해서, East Site OTV Edge Device의 Table에서

                    IP A Host의 MAC이 사라지게 되고, 이는 OTV Update를 통해서 West Site OTV Edge Device로 전파되고,

                    마찬가지로 West Site OTV Edge Device의 CAM Table에서도 사라지게 된다.

                    하지만, ARP Cache는 이 때 영향을 받지 않기 때문에 그대로 유지되게 된다.

                    ※ 이 시나리오에서는 ARP aging Timer가 CAM aging Timer보다 크다고 가정한다.

         Step 4. West Site의 다른 Host에서 IP A로 트래픽을 전송하려고 할 때, ARP Cache를 보고 Unicast로 전송을 한다.

         Step 5. West Site OTV Edge Device에서는 해당 Unicast의 MAC이 이미 사라졌기 때문에, Unknown Unicast로 처리되어

                     전송되지 못하고 해당 Frame은 Drop되게 된다.

              

 

 

      - 따라서, OTV Edge Device의 ARP Aging Timer는 항상 CAM Table Aging Timer보다 낮게 설정해야 한다.

        N7K의 Default 값은 다음과 같다.

           ▷ OTV ARP aging-timer : 480 초                                  ▷ MAC aging-timer : 1800 초

        ※ 일반적으로 사용되는 OS 등에서도 ARP는 1800초 미만으로 설정되어 있기 때문에 사실 위와 같은 시나리오는 크게

            신경쓰지 않아도 무관하다.

       -  Host의 Default Gateway가 Nexus 7000이 아닌 경우에 ARP aging-timer를 MAC aging-timer보다 작게 하는 것은 중요하다.

 

 

Broadcast Policy Control

     - 위에서 언급된 ARP Optimization과 같이 Broadcast를 줄이기 위해서 Broadcast white-listing과 같은 추가적인 기능을 제공하여,

       Overlay를 통하여 Layer 2 Broadcast Traffic을 줄일 수 있다. 이에 대한 내용은 추후에 가용성 부분에서 다뤄질 예정이다.

     - NX-OS 6.2(2)부터 Dedicated Broadcast Group을 통해서 Broadcast Traffic에 대해서 별도의 Multicast 주소로 설정할 수 있다.

       이 기능은 Broadcast Traffic에 대한 별도의 QoS 정책을 필요로 하는 경우에 유용하다.

 

Posted by 네떡지기
분류없음2014.10.07 18:30

 

 


이번에는 OTV 7번째 정리입니다~ ^^

NX-OS로는... 34번째네요...  원래 다른 내용을 정리하려다가 어쩌다보니.. 순서가 바뀌어서.. 정리가 되었습니다. ^^;

이번에는.. OTV에서의 FHRP Isolation에 대한 내용입니다. ^^.

그럼 한 분이라도 도움이 되시길 바라며, 혹시 수정해야 하는 부분이 있으면 알려주시면 감사하겠습니다.


 

 

○ FHRP Isolation

   -  Overlay를 통한 FHRP(HSRP, VRRP 등) Filter를 제공하여, 양 Site에서 동일한 FHRP의 VIP를 사용할 수 있도록 한다.

   - 서로 다른 Site 간의 동일한 Default Gateway를 사용함으로써, Outbound Traffic Flow(Server → Client)에 대해 최적화 할 수 있다.

       * 서로 다른 Default Gateway 사용 시에는 Server의 위치가 변경됨에 따라서, Default Gateway를 변경해주어야 하거나,

          그렇지 않은 경우에는 Server에서 Client로 전송 시에, Gateway가 있는 Site로 Overlay를 통해서 전송된 후에 전송된다.

   - 동일한 VLAN, IP Subnet이 서로 다른 Site에서 사용될 때, FHRP Message는 OTV 연결을 통해서 하나의 Default gateway를

     선출한다.  이러한 경우에는 위에서 언급한 대로, 아래 그림과 같은 최적화되지 못한 경로로 트래픽이 전송될 수 있다.

 

 

   - 위와 같은 최적화되지 못한 트래픽 경로에 대한 문제점을 해결하기 위해서는 FHRP Message가 Overlay를 통해서 전송될 때,

     Filtering하여, 각 Site간의 동일한 FHRP의 Default Gateway를 가지는 것을 허용하게 된다.

     이는 각 Site에서 동일한 Virtual IP 및 Virtual Mac-address를 가지게 되는 것을 허용하게 되고, 이를 통해 각 Site별로

     Outbound Traffic의 경로 최적화를 만들 수 있다.

 

 

 


 

‡ FHRP Filtering을 위한 Config Example.

  

Step 1 : OTV VDC에 VLAN ACL 적용

   - Traffic을 식별하여 Filtering하기 위해 VLAN ACL이 필요로 하다.

   - OTV Overlay를 통하여 Remote Site로부터 GARP의 수신을 막아주며,  이는 'ip arp inspection filter' 명령을 사용한다.

   - 아래의 설정을 Agg VDC에서 OTV VDC로 가는 구간의 VLAN에 적용을 하게 되면 OTV VDC에서는 모든 HSRP Message에

     대해서 Drop 된다.

 

ip access-list ALL_IPs
   10 permit ip any any
!
mac access-list ALL_MACs
   10 permit any any
!
ip access-list HSRP_IP
   10 permit udp any 224.0.0.2/32 eq 1985                                                       // HSRPv1 Message         
   20 permit udp any 224.0.0.102/32 eq 1985                                                   // HSRPv2 Message (2029 인지 확인!)

!
mac access-list HSRP_VMAC
   10 permit 0000.0c07.ac00 0000.0000.00ff any                                            // HSRPv1 VIP Mac-Address
   20 permit 0000.0c9f.f000 0000.0000.0fff any                                              // HSRPv2 VIP Mac-Address 
!
arp access-list HSRP_VMAC_ARP
   10 deny ip any mac 0000.0c07.ac00 ffff.ffff.ff00
   20 deny ip any mac 0000.0c9f.f000 ffff.ffff.f000
   30 permit ip any mac any

 

vlan access-map HSRP_Localization 10
   match mac address HSRP_VMAC
   match ip address HSRP_IP
   action drop

 

vlan access-map HSRP_Localization 20                                           // HSRP에 해당하지 않는 모든 MAC , IP
   match mac address ALL_MACs
   match ip address ALL_IPs
   action forward
!
feature dhcp
ip arp inspection filter HSRP_VMAC_ARP <OTV_Extended_VLANs>
vlan filter HSRP_Localization vlan-list <OTV_Extended_VLANs>
 

 

 ※ FHRP Message

 - GLBP : UDP / 224.0.0.102 / 3222

 - VRRP : IP / 224.0.0.18 / 112

 - HSRPv1 : UDP / 224.0.0.2 / 1985

 - HSRPv2 : UDP / 224.0.0.102 / 1985 (IPv6는 2029)

 

Step 2 : OTV Control Protocol(IS-IS)에 Route-map 적용

  - Step 1에서 HSRP Filter를 VCAL를 통해서 적용하였지만, HSRP packet의 Source로 사용된 vMAC을 OTV VDC를 통해서 학습한다.

    따라서, 이러한 MAC 정보는 IS-IS update를 통해서 OTV 광고가 이뤄지고 이는 Remote OTV Edge Device에서 vMAC이

 

    Internal Interface와 Overlay Interface 사이에서 계속 이동하는 것을 볼 수 있게 된다.

 

  - 이러한 vMAC 이동을 예방하고, 보다 나은 Design을 위해서 아래와 같이 OTV Route-map을 적용해야 한다.

 

 

mac-list OTV_HSRP_VMAC_deny seq 10 deny 0000.0c07.ac00 ffff.ffff.ff00
mac-list OTV_HSRP_VMAC_deny seq 11 deny 0000.0c9f.f000 ffff.ffff.f000
mac-list OTV_HSRP_VMAC_deny seq 20 permit 0000.0000.0000 0000.0000.0000
!
route-map OTV_HSRP_filter permit 10
   match mac-list OTV_HSRP_VMAC_deny
!
otv-isis default
   vpn Overlay0
      redistribute filter route-map OTV_HSRP_filter

 

 

◇ 적용 전, HSRP 상태 : Center쪽이 Active 상태

CENTER_N7K-BB(config)# sh hsrp bri
*:IPv6 group   #:group belongs to a bundle
                     P indicates configured to preempt.
                     |
 Interface   Grp    Prio P State    Active addr      Standby addr     Group addr
  Vlan400     10   100    Active  local                  192.168.250.3  192.168.250.1   (conf)
  Vlan400     20   100    Active  local                  192.168.250.3 192.168.250.250 (conf)

 

DR_N7K-BB(config)# sh hsrp bri
*:IPv6 group   #:group belongs to a bundle
                     P indicates configured to preempt.
                     |
 Interface   Grp  Prio P State    Active addr      Standby addr     Group addr
  Vlan400     10   100    Standby  192.168.250.2    local            192.168.250.1   (conf)
  Vlan400     20   100    Standby  192.168.250.2    local            192.168.250.250 (conf)

 

 

◇ 적용 후, HSRP 상태 : Center와 DR 모두 각각이 Active 상태

CENTER_N7K-BB(config)# sh hsrp bri
*:IPv6 group   #:group belongs to a bundle
                     P indicates configured to preempt.
                     |
 Interface   Grp  Prio P State    Active addr      Standby addr     Group addr
  Vlan400     10   100    Active   local            unknown          192.168.250.1   (conf)
  Vlan400     20   100    Active   local            unknown          192.168.250.250 (conf)
CENTER_N7K-BB(config)#


DR_7K-BB(config)# sh hsrp bri
                     P indicates configured to preempt.
                     |
Interface   Grp Prio P State    Active addr      Standby addr     Group addr
Vlan400     10  100    Active   local            unknown          192.168.250.1   (conf)
Vlan400     20  100    Active   local            unknown          192.168.250.250 (conf)

 

 

Posted by 네떡지기
분류없음2014.09.29 21:26

 


오랜만에 포스팅하는 Nexus : NX-OS 시리즈입니다.

 

예전에 포스팅했던, OTV의 Data Plane의 Unicast/Broadcast 부분에 이어서, Multcast에 대한 Data Plane입니다.

휴가 전에 대부분의 내용을 쓰고, 휴가 직전에 포스팅하지 못해서 마지막 부분만 휴가 이후에 올리게 되네요..

무척 오랫만에 올리는 Nexus 정리 포스팅입니다.  ^^;


 

OTV Data Plane – Multicast Traffic

• 특정한 경우에 Remote Site간의 Layer 2 Multicast 통신이 필요한 경우가 있을 수 있다.

• OTV Site 간의 Layer 2 Multicast의 경우에 Multicast가 지원환경과 지원불가 환경으로 나누어서 고려되어야 한다.

 


 

 

OTV Data Plane – Multicast Traffic (Multicast 지원 환경)

• Layer 2 Multicast 트래픽은 OTV overlay를 통해서  전송되며,  Suboptimal한 Head-end 복제를 방지하기 위해

   Multicast가 가능한 Transport Infrastructure가 요구된다.

•Multicast가 가능한 Transport Infrastructure를 통해 Layer 2 Multicast를 전송하는 데 하나의 SSM

  (Source Specific Multicast) Group를 이용한다.

   이 Group은 Site간의 OTV Control Protocol을 전송하기 위한 ASM group과는 독립적으로 사용된다

 

 

 

 Multicast Source 최초 활성화 시

  1. West Side에서 활성화된 Multicast Source가 Group Gs로 Traffic을 전송한다.


   2. Local의 OTV Edge Device는 첫 번째 Multicast Frame을 수신하고, Group Gs와 Transport  Infrastructure에서 사용될 특정
       SSM Gd Group간의 Mapping을 생성한다.


       Layer 2 Multicast Data Stream을 전송하는 데 사용되는 SSM Group의 범위는 Overlay Interface의 설정에 들어가게 된다.

       Ex>  NX-OS(config-if-overlay)# otv data-group 232.1.1.0/28

 

  3. OTV Control Protocol은 모든 Remote OTV Edge Device들의 Gs와 Gd 간의 Mapping을 전달하기 위해 사용된다.
      Mapping 정보는 Multicast Source가 속한 VLAN과 Mapping이 만들어진 OTV Edge Device의 IP address간의 정보로 구성된다.

                                 

 

 

 

 Multicast Source와 동일한 VLAN에 Deploy된 Receiver가 Group Gs에 Join하는 과정

  1.East Side Client가 GS group에 Join 할 수 있도록 IGMP Report를 전송

 

  2.OTV edge device가 IGMP Message를 snoop하고, VLAN A에 속한 Gs Group의 Active receiver이 있음을 확인한다.


  3.OTV Device는 OTV Control Protocol Message를 모든 Remote Edge Device로 전송한다.


  4.West Side의 Remote OTV Edge Device는 GM-Update를 수신하여, OTV Overlay를 통해서 전달될 group Gs에 대한
     OIL(Outgoing Interface List) 를 업데이트 한다.

 

  5.East Side의 OTV Edge Device는 이전에 IP A에 의해서 확인한 West side의 OTV Edge Device로부터 받은 Mapping정보를 찾는다.
      East Edge Device는  (IP A, Gd) SSM Group에 Join하기 위한 IGMPv3 report를 전송한다.

     이를 통해 Transport Infrastructure를 통해서 Multicast Gs를 전송하는데 사용될 수 있는 SSM tree(group Gd)를 만든다.

 

 

 

 

 

 OTV를 통한 Multicast 전송 과정

  1.OTV Edge Device가 Gs Stream를 수신하고, Overlay를 통하여 Gs Group을 수신하고자 하는 Receiver에게 전송하기 위해

    OIL를 확인 후에, Interface를 결정한다.

 

2. Edge device에서 Original Multicast frame을 Encapsulation 한다.  Outer IP header의 Source는 자신의 IP A로 설정되고,

     Destination은 Multicast data를 전송하기 위해 할당된 Gd SSM Group으로 설정된다.

 

3. Multicast Stream Gd는 기존의 Transport Infrastructure를 통해 만들어진 SSM Tree를 통해서, Gs Stream을 수신하고자 하는

     Receiver들이 있는 OTV Remote Site로 전송된다.

 

4. Remote OTV edge Deivce들은 해당 Packet을 수신한다.

 

5. Packet은 De-capsulation 되어서, 각 Site 내의 Receiver들에게 전송된다.

 

 

 

 



OTV Data Plane – Multicast Traffic (Unicast only Transport Infrastructure 환경)

  • Layer 2 Multicast 트래픽은 OTV overlay를 통해서  전송되며,  Suboptimal한 Head-end 복제를 방지하기 위해

      

Unicast Core망을 통한 Multicast Group Gs에 Receiver Join 시

  1. East Site에 있는 Client가 Gs group에 Join하기 위해 IGMP report를 보낸다.

 

  2. OTV Edge Device는 IGMP Message를 확인하여, VLAN 100에서 group Gs에 Active Receiver가 있다는 것을 알게 된다.

 

  3. OTV Edge Device는 OTV control protocol message(GM-Update)를  각 Unicast List에 속해 있는 remote Edge Device로

     전송하여 2번에서 확인된 정보를 전달한다.

 

   4. Remote Edge Device들은 GM-Update Message를 수신하게  되고,  multicast group Gs1의  receiver가  IP B Address로

    확인되는 OTV Device를 통해서 연결되어 있다는 정보와 "Data Group Mapping Table"을 함께 Update 한다.

 

 

 

 

 

 

 Unicast Core망을 통한 Layer 2 Multicast Stream Gs 전송 시

  1. Gs1을 목적지로 하는 Multicast TrafficWest Site의 내부에서 만들어지게 되고, OTV Edge Device“Data Group Mapping Table’에서

      OIFLookup한다. 아래 예시의 ‘Data Group Mapping Table’에서는 해당 Multicast Traffic EastSouthOverlay를 연결된 것을 확인한다.

  2. West SiteOTV Edge Devicehead-end replication을 통해 원래  Layer 2 Multicast Frame을 캡슐화한 2개의 Unicast IP Packet를 생성한다.

      이 때, Outer IP header IPWest SiteIP A로 설정이 되고, Destination IPSouth/EastIPIPB/C로 설정된다.

  3.  Unicast FrameRouting을 통해 Transport Infrastructure를 거쳐서 Remote OTV Device로 전송되게 되어, De-capsulation이 되어

       SiteReceiver들에게 전송된다.  이 때, North Site에는 해당 Multicast TrafficReceiver가 없기 때문에 Data Group Mapping TableNorth Site가 존재하지 않고,  따라서 Frame이 전송되지 않는다.

 

 

 

 

Posted by 네떡지기
프로그래밍/Python2014.08.24 17:15

 

Last Updated 2014.08.26


Python for Networker의 이번 포스팅은 Cisco dCloud 의  Nexus 9000 : NX-OS Programmability v1에 있는 Python Script 예제 중의 하나를 다뤄봅니다.

 

이 Python Script는 Nexus에서 현재 원하는 정보를 Text 형태의 첨부파일로 만들어서, 메일로 전송을 하는 예제 Script 입니다.

 

다음과 같이 bootflash://script 디렉토리에서 예제 Script를 실행합니다.

 

 

dcloud-n9k#  python ./n9k_serviceability.py 수신메일주소

 

 

 

 

Script를 실행하게 되면, 어떤 종류의 정보를 수집할 것인지에 대해서 물어보게 됩니다.

 

여기서 원하는 정보의 종류를 선택하면, Nexus에서 해당 정보를 수집하여, 수신하고자 하는 Email 주소로 발송을 하게 됩니다.

 

실제 메일이 제대로 발송이 되었는지 확인을 해보면, 아래와 같이 제 메일 계정으로  메일이 수신되었음을 확인할 수 있습니다.

 

Cisco dCloud의 Nexus 9000에서의 예제 Script이기는 하지만,

어차피 기존 포스팅에서도 다뤘듯이 Nexus에서만 가능한 부분은 아닙니다.

 

그럼 유사한 기능을 기존 포스팅에서 언급했던, Arista vEOS에서 유사한 Script로 만들어서 테스트 해보겠습니다.

 

Arista VM을 실행하여, vEOS에서 mail.py 이라는 예제 Script를 만들었습니다.

 

그리고 아래와 같이 해당 Script를 실행해봅니다.

 

 

이 예제에서는 특정 정보를 가공해서 메일을 발송할 수 있다는 점에 대해서 보여주는 것이기 때문에

복잡하게 구현하지는 않았고, 단순하게 현재 vEOS의 version 정보를 확인하여, 첨부파일로 전송을 하는 역할을 합니다.

 

위와 같이 해당 Script를 실행하게 되면, vEOS의 version 정보를 Text 형태의 첨부 파일로 가공을 하게 되고, 메일을 보내게 됩니다.

(참고로 Arista VM에서 bash shell mode에서 python script를 실행 중인 모습입니다.)

 

자 이제, 메일이 잘 도착했는지 메일함을 확인해보겠습니다.

(위의 예제에서는 별도로 뒤에 수신자 email 주소를 쓰지 않았지만 Nexus에서와 마찬가지로 실행 시 수신하고자 하는 email주소를 쓰게 되면,  해당 email로 전송도 물론 가능합니다.)

 

 

 메일함을 보면,  정상적으로 메일이 잘 수신된 것을 확인할 수 있습니다.

 첨부파일을 열어보게 되면, show version으로 확인된 정보를 볼 수 있습니다.

 

 이번 포스팅에서는 별도의 기술적인 내용은 배제하였습니다.

 

  다만, Python을 이용하여 어떤 것들이 가능한지에 대해서 Cisco dCloud에서의 보여주는 예제를 확인해보고

 또한 그러한 예제들이 단순히 특정 벤더에서만 실행되는 것이 아니라 Python을 지원하는 어떤 장비에서도 유연하게 사용할 수 있다는 것을

 확인해보는 것이 이번 포스팅에서 말하고자 하는 부분입니다.

 

  물론 Script 상에 들어가는 각 벤더에서 제공하는 모듈들은 유사한 기능을 하는 각 벤더의 모듈을 가져다 쓰기는 해야겠지만,

 기본적인 프로그램 상의 로직이나 코드는 모두 재활용이 가능합니다. 

 

  또한 기존에 있는 코드에서 추가적인 기능들을 얼마든지 필요에 의해서 추가도 가능하게 될 것입니다. 

 

 그럼 다음 포스팅에서 다시 찾아뵙겠습니다.

 

 


Nexus 5000에서도 테스팅 추가 완료하였습니다.

 

아래와 같이 Nexus 5000에서 mail.py 이라는 Script를 만들었습니다.

기본적인 코드는 위에서 사용했던 코드와 거의 유사하며, 실제 장비에 Cli 모드의 명령하는 부분과 결과값을 가공하는 부분만

다르게 되어 있습니다. Script의 내용은 기존과 마찬가지로 show version으로 나오는 결과값을 메일로 발송하도록 되어 있습니다.

 

 

위와 같이 정상적으로 코드가 실행된 것을 확인할 수 있습니다.

 

 

 Nexus에서 메일을 발송한 이후에, 메일함을 살펴보면

정상적으로 메일과 첨부파일이 도착한 것을 볼 수 있습니다.

 

이것으로 Nexus 9000 / 5000 , Arista vEOS에서 모두 메일 발송하는 Python Script를 살펴보았습니다.

전체적으로 변경된 부분은 단지 장비에 대한 상태를 확인하기 위한 명령어를 입력하고, 해당 결과값을 가공하는 부분만 다르고

나머지 부분은 모두 동일하다고 보시면 됩니다.

 

앞으로는 정말 코드를 처음부터 짤 수는 없더라고, 기존 코드를 이해하고 수정할 수 있을정도로 알아두어야만(?) 할 것 같습니다.

 

 

 

Posted by 네떡지기
프로그래밍/Python2014.08.18 17:42

 


10번째 Python for Networker 포스팅입니다.

이번 포스팅에서 Cisco Nexus의 7000과 5000에서 공통으로 사용이 가능하도록 기존에 만들었던 ipinfo.py 모듈을 변경해봅니다.

장비별로 개개의 코드를 작성해서 수행하는 것보다는 장비에서 공통으로 호환성있게 사용 가능한 코드를 만드는 것이 향후 코드에 대한

유지보수 측면에서 더욱 유리할 것 이기 때문에 유심있게 봐두면 좋을 듯 싶습니다.

 

Git에서 Code 보기

  - einfo.py : https://github.com/NetworkZIGI/Python_for_Network/blob/master/eipinfo.py

  - vCheck.py : https://github.com/NetworkZIGI/Python_for_Network/blob/master/vCheck.py

 


 

 

Nexus 7000와 Nexus 5000에서 지원하는 Python의 경우에는 각각 지원되는 방식이 다르다.

 

실제 Cisco에서 제공되는 Python의 Cisco Module을 확인해 보면 아래와 같이 내장된 Member가 서로 다른 것을 확인할 수 있다.

 

◇ Nexus 7K Cisco Module

 

__doc__

__name__

__package__

cli

cli_execution_error

clil_syntax_error

clid

clip

set_vrf

 

 

◇ Nexus 5K Cisco Module

 

BGPSession

Routes

check_port_discards

line_parser

show_run

BufferDepthMonitor

SectionParser

cisco_secret

mac_address_table

ssh

CLI

VRF

cisco_socket

md5sum

tacacs

CheckPortDiscards

Vlan

cli

msdp

telnet

CiscoSecret

__all__

dhcp

ospf

transfer

CiscoSocket

__builtins__

eigrp

ospfv3

udld

Feature

__doc__

feature

pim

vlan

History

__file__

get_global_vrf

private-vlan

vpc

IPv4ACL

__name__

get_valid_port

ptp

vrf

IPv6ACL

__package__

history

rip

vrrp

Interface

__path__

hsrp

routes

vtp

Key

acl

interface

scheduler

 

LineParser

bfd

interface-vlan

section_parser

 

MacAddressTable

bgp

key

set_global_vrf

 

OSPFSession

buffer_depth_monitor

lacp

show_queues

 

 

 

서로 지원되는 Cisco Module이 다르기 때문에, 관리자가 Module을 새롭게 만들 경우에는 이러한 점이 고려되어야 합니다.

물론 Cisco Module을 사용하지 않고 만든 Python Module은 상관이 없겠지만, Cisco Module을 Import하여 만든 Python Module은

각 Nexus 별로 지원되는 내용과 결과값이 다르기 때문에 별개의 코드로 만들어야 하는 경우가 발생하게 됩니다.

 

기존 Python for Networker : Part 6 에서 다뤄졌던, IP를 가지고 해당 IP의 정보(IP / Mac  / VLAN / Interface / Description)를 보는

ipinfo.py의 경우에도 대부분의 코드가 비슷하지만, Cisco Module이 사용된 부분에 대해서는 내용이 달라지게 됩니다.

 

가령 Nexus 7K의 경우에는 Cisco Cli 명령을 수행하기 위해서 cisco.cli 메서드를 사용하여 결과를 수행하면 str(문자열) 값으로

결과값을 가져옵니다. 반면에 Nexus 5K의 경우에는 cisco.CLI 메서드르 사용하고 이러한 결과값은 tuple 형태로 결과를 가져옵니다.

 

이처럼 cisco에서 제공하는 Module이 서로 다르게 처리되다 보니, 각 Module을 만들고자 할 때에는 각각의 Module에서 사용되는

cisco Module을 고려하여 만들어야 합니다.

 

그렇다면, Nexus 7K와 Nexus 5K에서 공통으로 사용할 수 있는 코드를 만들 수는 없을까요?.... 물론 가능합니다.

 

먼저 아래의 예제 코드를 살펴보면..

 

 

vCheck.py : Nexus 7000/5000 구분하는 예제 코드

import sys
N7K = 'Nexus7000'
N5K = 'Nexus5000'
#N3K = 'Nexus3000'     : Constant for Extension.

NexusVersion = ''

def NexusVersionCheck():
    global NexusVersion
    sysPathList = sys.path
    for pathItem in sysPathList:
        if(pathItem=='/bootflash/scripts'):
            NexusVersion = N7K
            break
    else:
        NexusVersion = N5K

 

위의 예제 코드는 코드가 실행되는 장비가 Nexus 7000인지, 5000인지 확인하는 코드입니다.

원리는 무척이나 단순합니다.

 

각 장비의 path 정보값을 가져와서 확인을 하는 데, Nexus 7000에서는 기존 포스팅에서 다뤘던 것처럼

bootflash/scripts 에 Python Module이 들어가게 됩니다. 그리고 이 Path 정보는 Nexus 7000에만 있습니다.

(물론 제가 Testing이 가능한 장비가 Nexus 7000과 5000밖에 없기 때문에, 다른 장비에서는 어떻게 달라질지 그리고 그경우에는

 어떠한 방법으로 다시 구분을 할지는 달라지게 됩니다. 단지 장비별로 이렇게 특정값을 확인하여 어떤 장비인지 확인할 수 있는지에

 대한 부분을 확인하는 Module을 만든다면, 현재 해당 Module이 실행되는 장비가 어떤 장비인지 확인 할 수 있습니다.)

 

이러한 구분 정보를 통하여 현재 동작하고 있는 Module의 장비 값을 Global 변수에 저장할 수 있습니다.

그러면, 실제 특정 기능을 수행하는 Module에서는 위의 정보를 바탕으로 필요한 Cisco Module을 사용하여 처리할 수 있습니다.

 

위의 Nexus Version을 체크하는 Module을 바탕으로, 기존에 작성하였던 ipinfo.py를 Nexus 7000과 5000에서 모두 동작하게 하는

공통 Module로 아래와 같이 작성할 수 있습니다.

 

 

eipinfo.py

#!/bin/env python
import argparse
import sys
import cisco
import vCheck
from vCheck import NexusVersionCheck


IP = 'IP-Address'
MAC = 'Mac-Address'
Vlan = 'Vlan'
Intf = 'Interface'
Desc = 'Description'


IP_info = {IP:'None', MAC:'None', Vlan:'None', Intf:'None', Desc:'None'}

 

def get_ARP_Table(ipaddr):
    arpCmd = 'sh ip arp ' + ipaddr
    arpCmdResultList = [] 
    if(vCheck.NexusVersion==vCheck.N7K):
        arpCmdResult = cisco.cli(arpCmd)
        arpCmdResultList = arpCmdResult.split('\n')
    elif(vCheck.NexusVersion==vCheck.N5K):
        arpCmdResult = cisco.CLI(arpCmd, False)
        arpCmdResultList = arpCmdResult.get_output()

    for arp in arpCmdResultList:
        if (-1<arp.find(args.ip)):
            return arp
    else:
        print ' %s : Not found IP Address Infomation' % args.ip
        sys.exit()

 

def get_IP_MAC_info(info):
    info_list = info.split()
    IP_info[IP] = info_list[0]
    IP_info[MAC] = info_list[2]
    IP_info[Vlan] = info_list[3][4:]

 

def get_Interface_info():
    macCmd = 'sh mac address-table addr ' + IP_info[MAC]
    macCmdResultList = [] 

    if(vCheck.NexusVersion==vCheck.N7K):
        macCmdResult = cisco.cli(macCmd)
        macCmdResultList = macCmdResult.split('\n')
    elif(vCheck.NexusVersion==vCheck.N5K):
        macCmdResult = cisco.CLI(macCmd, False)
        macCmdResultList = macCmdResult.get_output()

 

    for infInfo in macCmdResultList:
        idx = infInfo.find(IP_info[MAC])
        if(-1<idx):
            IP_info[Intf] = infInfo[58:]
            get_Description_info(IP_info[Intf])
            break


def get_Description_info(iInfo):
    if(iInfo.find('Eth') == 0 or iInfo.find('Po')==0):
        intCmd = 'sh int desc | inc ' + iInfo
        if(vCheck.NexusVersion==vCheck.N7K):
            intCmdResult = cisco.cli(intCmd)
            intCmdResultList = intCmdResult.split('\n')
            if(intCmdResult != ''):
                IP_info[Desc] = intCmdResultList[0][25:].strip()
        elif(vCheck.NexusVersion==vCheck.N5K):
            intCmdResult = cisco.CLI(intCmd, False)
            intCmdResultList = intCmdResult.get_output()
            if(intCmdResult != ''):
                IP_info[Desc] = intCmdResultList[0][25:].strip()

 

def show_IP_info():
    print '==================================='
    print '      enhanced IP Info : NetworkZIGI                 '
    print '==================================='
    print '%-15s : %s' % (IP,IP_info[IP])
    print '%-15s : %s' % (MAC,IP_info[MAC])
    print '%-15s : %s' % (Vlan, IP_info[Vlan])
    print '%-15s : %s' % (Intf, IP_info[Intf])
    print '%-15s : %s' % (Desc,IP_info[Desc])

 

NexusVersionCheck()
parser = argparse.ArgumentParser('Args',description='Args Desc')
parser.add_argument('ip')
args = parser.parse_args()
iparp = get_ARP_Table(args.ip)
get_IP_MAC_info(iparp)
get_Interface_info()
show_IP_info()

 

 

위의 Code 중에서 파란색으로 표기된 부분이 Nexus 7K와 5K를 구분하기 위한 부분입니다.

 

 그럼 이제 위의 1개의 코드로 Nexus 7000과 Nexus 5000에서 별도의 코드를 각각 사용하는 것이 아닌, 하나의 동일한 코드로

원하는 결과값을 같이 얻을 수 있게 되었습니다.

 

 이번 Part에서 다뤄진 부분은 제가 Test가 가능한 장비를 기준으로 두 장비에 대해서 단순한 방법으로 구분을 지었습니다.

하지만, Nexus 의 다른 시리즈의 경우에는 또 지원되는 부분이 다르기 때문에 그러한 부분까지 수용하기 위해서는 장비를 구분하는

vCheck 모듈의 수정이 필요하게 될 것입니다.

 

 여기서 세부적인 장비 구분을 체크하는 실제적인 내용보다는, 그러한 장비 구분을 통해서 실제 수행을 원하는 내용의 코드를 장비 개별

코드가 아니라, 하나의 공통 코드로 만들어서 사용할 수 있다는 것이 다루고자 하는 내용이었습니다.  

 

 그러한 부분을 잘 활용하게 된다면, 하나의 코드로 다른 버전의 장비에서도 호환이 되는 코드를 작성할 수 있을 것입니다.

 

물론 아예 처음부터 지원되는 cisco module이 동일하다면, 이러한 부분을 별도로 고려하지 않을 수 있겠지만

그러한 부분도 고려한 코드를 작성하는 것도 현재 시점에서는 또 하나의 몫이 아닐까 생각을 해봅니다.

Posted by 네떡지기
프로그래밍/Python2014.08.13 12:20

이번 포스팅은 별도의 Part은 아니고~ 추가 포스팅입니다.

지난 Part 6에서 다뤄진 내용에 대해서 Nexus 7K용으로 변경한 코드입니다.

꼭 바꿔야하는 부분을 제외하고.. 약간 추가적으로 내용 업데이트도 함께 했습니다. (그 부분은 5K도 공통사항이긴합니다..)

Nexus 7K로 변경해야 할 때, 어디를 바꿔야 하는지 문의하시는 분이 계셔서 수정해서 올려드립니다.
지난 번에 생각했던 것보다 조금 더 수정해야 하는 부분이 있어서. ^^;

포스팅으로 대체했습니다.

 

Python for Networker : Part 6 보기

 

Github에서 보기 

 


 

 

 

 ○ IP Info - Nexus 7000

 __author__ = 'Network ZIGI - Ko Jae Sung'

 #!/bin/env python
import argparse
import sys 
import cisco 
IP = 'IP-Address' 
MAC = 'Mac-Address' 
Vlan = 'Vlan' 
Intf = 'Interface' 
Desc = 'Description' 
IP_info = {IP:'None', MAC:'None', Vlan:'None', Intf:'None', Desc:'None'} 

def get_ARP_Table(ipaddr): 
    arpCmd = 'sh ip arp ' + ipaddr 
    arpCmdResult = cisco.cli(arpCmd) 
    arpCmdResultList = arpCmdResult.split('\n') 
    for arp in arpCmdResultList: 
        if (-1<arp.find(args.ip)):   
            return arp           
    else: 
        print ' %s : Not found IP Address Infomation' % args.ip  
        sys.exit() 

def get_IP_MAC_info(info): 
    info_list = info.split()          
    IP_info[IP] = info_list[0]        
    IP_info[MAC] = info_list[2]          
    IP_info[Vlan] = info_list[3][4:]    
                                     
def get_Interface_info(): 
    macCmd = 'sh mac address-table addr ' + IP_info[MAC] 
    macCmdResult = cisco.cli(macCmd) 
    macCmdResultList = macCmdResult.split('\n') 
 
    for infInfo in macCmdResultList: 
        idx = infInfo.find(IP_info[MAC]) 
        if(-1<idx): 
            IP_info[Intf] = infInfo[58:] 
            get_Description_info(IP_info[Intf]) 
            break 


def get_Description_info(iInfo): 
    if(iInfo.find('Eth') == 0 or iInfo.find('Po')==0):  
        intCmd = 'sh int desc | inc ' + iInfo 
        intCmdResult = cisco.cli(intCmd) 
        if(intCmdResult != ''): 
            intCmdResultList = intCmdResult.split('\n') 
            IP_info[Desc] = intCmdResultList[0][25:].strip() 

def show_IP_info(): 
    print '================================================' 
    print '             IP Info : NetworkZIGI              ' 
    print '================================================' 
    print '%-15s : %s' % (IP,IP_info[IP]) 
    print '%-15s : %s' % (MAC,IP_info[MAC]) 
    print '%-15s : %s' % (Vlan, IP_info[Vlan]) 
    print '%-15s : %s' % (Intf, IP_info[Intf]) 
    print '%-15s : %s' % (Desc,IP_info[Desc]) 

parser = argparse.ArgumentParser('Args',description='Args Desc') 
parser.add_argument('ip') 
args = parser.parse_args() 

iparp = get_ARP_Table(args.ip) 
get_IP_MAC_info(iparp) 
get_Interface_info() 
show_IP_info() 

 

 

Posted by 네떡지기
프로그래밍/Python2014.07.24 21:30

이번 포스팅도 Python으로 만들어 보는 예제입니다.  마찬가지로 Cisco Nexus 5548 기준입니다.   

 

하지만, 현재 만드는 예제가 모두 기본 CLI명령을 입력하는 부분에서만 Cisco 패키지를 사용하기 때문에

 

간단한(?) 변형을 통해 다른 곳에도 활용이 가능합니다.

 

(물론 출력된 문자열이 Nexus 기준에서 가공하여 만든 예제라 문자열 가공을 각 상황에 맞게 일부 변형이 필요합니다)

 

이번 예제는 특정 interface의 사용량을 원하는 횟수만큼,  원하는 시간 간격으로 화면에 출력해주는 예제입니다.

 

* Github에서 보기

    uInt.py : https://github.com/NetworkZIGI/Python_for_Network/blob/master/uInt.py

    uIntmod : https://github.com/NetworkZIGI/Python_for_Network/blob/master/uIntmod.py

 


 

 

uInt.py

__author__ = 'Network ZIGI'

import cisco
import time
from argparse import ArgumentParser


def CheckInterfaceRate():
    inPacketList = []
    inBitList =[]
    outPacketList=[]
    outBitList=[]
 

    for cnt in range(1,int(args.repeat)+1):
        result = getInterfacerRate()
        print '%8d >>  [ Input ]  %13s bps -  %6s pps   :   [ Ouput ]  %13s bps  -  %6s pps    [ %s %s]' % \
        (cnt,result[0][4], result[0][6],result[1][4],result[1][6],result[0][0],result[0][1])
        inBitList.append(int(result[0][4]))
        inPacketList.append(int(result[0][6]))
        outBitList.append(int(result[1][4]))
        outPacketList.append(int(result[1][6]))
        time.sleep(int(args.interval[0]))

    print '==========================================================================='
    print 'Max  >>   [ Input ]  %13d bps -  %6d pps   :   [ Ouput ]  %13d bps  -  %6d pps ' % \
    (max(inBitList), max(inPacketList),max(outBitList), max(outPacketList))

 

def getInterfacerRate():
     intRateCmdResult = cisco.CLI('sh int '+args.Intinfo, False)
    intRateCmdResultList =intRateCmdResult.get_output()
    for rate in intRateCmdResultList:
        if(-1<rate.find('input rate')):
            inputList = rate.split()
        elif ( -1<rate.find('output rate')):
            outputList = rate.split()
            return inputList, outputList

 

parser = ArgumentParser('usingInt')
parser.add_argument('Intinfo',  help='Interface')
parser.add_argument('repeat', help='repeat Interface Input/Output rate')
parser.add_argument('interval', type=str, default=['1'],nargs='*',  help='Interval time (Second) - [default : 1 Second]')
args = parser.parse_args()
CheckInterfaceRate()

 

그리고 위의 코드를 아래와 같이 실행해봅니다.

 

필요한 매개변수는

 

1. 사용량을 확인할 인터페이스               2. 반복할 횟수               3. 체크할 시간 간격

 

uInt.py - Cli 모드 실행 결과

4F_DMZ_NEXUS_A_1# python uInt.py po1 5 2
  1 >> [ Input ]          9592 bps -       9 pps : [ Ouput ]        126888 bps  -     173 pps  [ 30 seconds]
  2 >> [ Input ]          9264 bps -       9 pps : [ Ouput ]        125600 bps  -     170 pps  [ 30 seconds]
  3 >> [ Input ]          9264 bps -       9 pps : [ Ouput ]        125600 bps  -     170 pps  [ 30 seconds]
  4 >> [ Input ]          9264 bps -       9 pps : [ Ouput ]        125600 bps  -     170 pps  [ 30 seconds]
  5 >> [ Input ]          9328 bps -       9 pps : [ Ouput ]        124000 bps  -     166 pps  [ 30 seconds]
===========================================================================
Max  >> [ Input ]          9592 bps -       9 pps : [ Ouput ]        126888 bps  -     173 pps

 

원하는 대로 결과값이 나온 것 같습니다!!

하지만... 절망.. Cli모드에서 실행을 하게되면 모든 코드가 종료된 이후에 결과가 나오게 됩니다.

이 부분을 실시간으로 나오게 하는게 있는지 확인을 오늘 이래저래.. 구글링을 해 보았으나..

없는 듯 싶습니다. (만약 있다면 알려주세요!!!)

 

그래서 어찌할까.. 하다가... Python Shell 모드에서 실행하도록 변형해봅니다.

 

위에서 만든 코드를 거의 그대로 가져다 쓸 수 있도록 메인 실행 부분을 함수로 변형하고 실행 시의 매개변수를

해당 함수를 호출 할 때의 매개변수로 대체하는 것 이외에는 달라지는 부분은 없습니다.

 

 

uIntmod.py

 # -*- coding: utf-8 -*-
__author__ = 'Network ZIGI'

import cisco 
import time

def CheckInterfaceRate(args):
    inPacketList = []
    inBitList =[]
    outPacketList=[]
    outBitList=[]
    inPacketavg=0
    inBitavg=0
    outPacketavg=0
    outBitavg=0

    for cnt in range(1,args['repeat']+1):
        result = getInterfaceRate(args['intInfo'])
        print '%8d  >>  [ Input ]  %13s bps -  %6s pps   :   [ Ouput ]  %13s bps  -  %6s pps    [ %s %s]' % \

       (cnt,result[0][4], result[0][6],result[1][4],result[1][6],result[0][0],result[0][1])
        inBitList.append(int(result[0][4]))
        inPacketList.append(int(result[0][6]))
        outBitList.append(int(result[1][4]))
        outPacketList.append(int(result[1][6]))
        time.sleep((args['interval']))

    print '==========================================================================='
    print 'Max  >>   [ Input ]  %13d bps -  %6d pps   :   [ Ouput ]  %13d bps  -  %6d pps ' % \

    (max(inBitList), max(inPacketList),max(outBitList), max(outPacketList))

 

def getInterfaceRate(Intinfo):
    intRateCmdResult =cisco.CLI('sh int '+Intinfo,False)
    intRateCmdResultList =intRateCmdResult.get_output()
    for rate in intRateCmdResultList:
        if(-1<rate.find('input rate')):
            inputList = rate.split()
        elif ( -1<rate.find('output rate')):
            outputList = rate.split()
            return inputList, outputList
 
def rate(info,r,step=1):
    args = {'intInfo':info,'repeat': r, 'interval':step}
    CheckInterfaceRate(args)

 

모듈로 만들었으니.. 이제 위의 모듈을 Shell모드에서 import하여 실행해봅니다.

 

 

 uIntmod : Python Shell Mode에서 실행하기

NX-OS# python
Python 2.7.2 (default, Nov 27 2012, 17:50:33)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Loaded cisco NxOS lib!
>>> import uIntmod
>>> uIntmod.rate('po1',5,2)
       1  >>  [ Input ]           8968 bps -       9 pps   :   [ Ouput ]         122544 bps  -     164 pps    [ 30 secon
       2  >>  [ Input ]           9216 bps -       9 pps   :   [ Ouput ]         123296 bps  -     165 pps    [ 30 secon
       3  >>  [ Input ]           9216 bps -       9 pps   :   [ Ouput ]         123296 bps  -     165 pps    [ 30 secon
       4  >>  [ Input ]           8592 bps -       8 pps   :   [ Ouput ]         122856 bps  -     165 pps    [ 30 secon
       5  >>  [ Input ]           8592 bps -       8 pps   :   [ Ouput ]         122856 bps  -     165 pps    [ 30 secon
===========================================================================
Max  >>   [ Input ]           9216 bps -       9 pps   :   [ Ouput ]         123296 bps  -     165 pps
>>> exit()
NX-OS#

 

Shell 모드에서는 실행할 때, 만든 모듈을 Import하고 메서드를 이용해서 모듈의 기능을 사용합니다.

 

자 이제 실시간으로 한 줄씩.. 원하는 시간간격으로 Interface의 사용량을 확인할 수 있게 되었습니다.

 

Posted by 네떡지기
프로그래밍/Python2014.07.19 13:38

 


이번 포스팅은  Python으로 만들어 보는 예제입니다.

 

제가 Test 가능한 환경이 Cisco Nexus이기 때문에  Cisco Nexus 5548 기준으로 작성된 예제입니다만,

 

기본 CLI명령을 입력하는 부분에서만 Cisco 패키지의 명령을 사용하였기 때문에 변형을 한다면,

 

다른 곳에서 충분히 활용이 가능한(?) 예제가 될 수 있을 듯 싶습니다. 

 

(물론 출력된 문자열이 Nexus 기준에서 가공하여 만든 예제라 문자열 가공을 각 상황에 맞게 일부 변형이 필요합니다)

 

IP를 입력하면, 해당 IP의 MAC주소와 VLAN, Interface, Description 정보를 한 번에 확인할 수 있는 내용입니다.

 

추후에 아래 코드는 조금씩 변형되서 업데이트 버전이 만들 계획이지만, 언제 어떻게 될지는 아직은 알 수 없습니다! ^^;

 

아래 코드는 Github에서도 함께 볼 수 있습니다. 

 

Github 에서 보기 


 

 

 ○ IP Info

 __author__ = 'Network ZIGI - Ko Jae Sung'

  # 2014.07.19. First Version
  #
  # ================================================
  #      IP Info : NetworkZIGI   2014.07.19
  #================================================
  #IP-Address      : 10.0.0.1
  #Mac-Address     : 0012.3456.abcd
  #Vlan            : 11
  #Interface       : Eth14/2
  #Description     : NetworkZIGI Blog Server
  #
  # Blog : http://ThePlmingspace.tistory.com
  #
  # Tested : Cisco Nexus 5548  : 6.0(2)N2(4)

 

  import argparse
  import sys
  import cisco

  IP = 'IP-Address'
  MAC = 'Mac-Address'
  Vlan = 'Vlan'
  Int = 'Interface'
  Desc = 'Description'

  
  IP_info = {IP:'None', MAC:'None', Vlan:'None', Int:'None', Desc:'None'}    # IP정보를 저장할 Dict type 변수

 

  # ARP 정보를 가져오는 메서드

  def get_ARP_Table(ipaddr):
      arpCmd = 'sh ip arp ' + ipaddr
      arpCmdResult = cisco.CLI(arpCmd, False)
      arpCmdResultList = arpCmdResult.get_output()
      for arp in arpCmdResultList:
          if (-1<arp.find(args.ip)):
              return arp
      else:
          print ' %s : Not found IP Address Infomation' % args.ip
          sys.exit()

 

  # IP와 MAC, VLAN 정보를 가져오는 메서드

  def get_IP_MAC_info(info):
      info_list = info.split()
      IP_info[IP] = info_list[0]
      IP_info[MAC] = info_list[2]
      IP_info[Vlan] = info_list[3][4:]

 

  # Interface 정보를 가져오는 메서드

  def get_Interface_info():
      macCmd = 'sh mac address-table addr ' + IP_info[MAC]
      macCmdResult = cisco.CLI(macCmd, False)
      macCmdResultList = macCmdResult.get_output()
      if (len(macCmdResultList) > 6):                                                
          IP_info[Int] = macCmdResultList[5][58:]
          get_Description_info(IP_info[Int])

 

  # Description 정보를 가져오는 메서드

  def get_Description_info(iInfo):
      if(iInfo.find('Eth') == 0 or iInfo.find('Po')==0): 

          intCmd = 'sh int desc | inc ' + iInfo
          intCmdResult = cisco.CLI(intCmd, False)
          intCmdResultList = intCmdResult.get_output()
          IP_info[Desc] = intCmdResultList[0][25:]

 

  # IP 정보 출력

  def show_IP_info():
      print '================================================'
      print '             IP Info : NetworkZIGI              '
      print '================================================'
      print '%-15s : %s' % (IP,IP_info[IP])
      print '%-15s : %s' % (MAC,IP_info[MAC])
      print '%-15s : %s' % (Vlan, IP_info[Vlan])
      print '%-15s : %s' % (Int, IP_info[Int])
      print '%-15s : %s' % (Desc,IP_info[Desc])

 

  # 프로그램 시작 지점

  parser = argparse.ArgumentParser('Args',description='Args Desc')
  parser.add_argument('ip')
  args = parser.parse_args()

  iparp = get_ARP_Table(args.ip)
  get_IP_MAC_info(iparp)
  get_Interface_info()
  show_IP_info()

 

 

 ○ IP Info : 결과

NX-OS# python ipinfo.py 10.10.10.11
================================================
      IP Info : NetworkZIGI   2014.07.19       
================================================
IP-Address                                : 10.10.10.11
Mac-Address                           : 0012.3456.789A
Vlan                                           : 20
Interface                                  : E12/3
Description                              : NetworkZIGI Blog Web Server

 

Posted by 네떡지기
프로그래밍/Python2014.07.13 01:50

 


pingrange Python 예제로 살펴보는 포스팅의 3번째 편이자, 해당 예제의 마지막 편입니다.

물론 다음 편에서 다시 비슷하게 다뤄질 예정이긴 합니다.

 

기본 내용은 지난 포스팅과 이어지게 되며, 예제 소스는 이번 포스팅에도 동일하게 포함하여 보시기 쉽게 하였습니다.

 

혹시 기존 포스팅을 보지 못하신 분은 반드시!

 

Programmability for Networker : Part 2            Programmability for Networker : Part 3

 

을 보고 오셔야 합니다.

 

본 내용에 사용된 에제는 아래에서 볼 수 있습니다.

[ 예제 링크 ] https://github.com/datacenter/who-moved-my-cli

 

※ 본 내용의 진행은 Nexus 5548 6.0(2)N2(4) 기준입니다.

 

 


 

 

pingrange.py

import re

from cisco import cli

from argparse import ArgumentParser

def expandrange(rangefunc):

    hosts = []

    octets = rangefunc.split('.')

    for i,octet in enumerate(octets):

        if '-' in octet:

            octetrange = octet.split('-')

            for digit in range(int(octetrange[0]), int(octetrange[1])+1):

                ip = '.'.join(octets[:i] + [str(digit)] + octets[i+1:])

                hosts += expandrange(ip)

            break

    else:

        hosts.append(rangefunc)

    return hosts

 

parser = ArgumentParser('pingrange')

parser.add_argument('ip', help='IP range to ping, e.g., 10.1.0-1.0-255 will expand to 10.1.0.0/23')

parser.add_argument('options', nargs='*', help='Options to pass to ping', default=['count 1'])

args = parser.parse_args()

targets = expandrange(args.ip)

for ip in targets:

    tupleping  = cli('ping %s %s' % (ip, ' '.join(args.options)))

    strping = str(tupleping)

    m = re.search('([0-9\.]+)% packet loss',strping )

    print('%s - %s' % (ip, 'UP' if float(m.group(1)) == 0.0 else 'DOWN'))

 

 


 

 

[ 매개변수 ]

 

명령줄 매개변수

     •Python Script 실행 시에, 사용되는 매개변수는 sys.argv에 리스트 형태로 전달된다.

     리스트의 첫 번째 값은 해당 Script의 이름이고, 그 이후의 값이 실제 매개변수가 된다.

        따라서, sys.argv[1:] 으로 하면 실제 매개변수의 값만 리스트로 뽑을 수 있다.

     argparse 모듈을 사용 할 경우에는 매개변수에 대한 작업을 좀 더 편하게 할 수 있다.

 

argparse

     •class argparse.ArgumentParser(prog=None, usage=None, description=None, epilog=None, parents=[],

                                           formatter_class=argparse.HelpFormatter, prefix_chars='-', fromfile_prefix_chars=None,

                                           argument_default=None, conflict_handler='error', add_help=True)

     ArgumentParser 클래스는 실행 시의 매개변수에 대한 값을 손쉽게 처리하도록 매개변수의 값을 argparse 객체로 만들어 준다 .

     add_argument 메서드는 매개변수를 어떻게 분석하여 처리할지에 대한 부분 지정한다.

 

 

Args1.py : Code

import sys

argvList = sys.argv

for ar in argvList:

    print 'argv : %s' % ar

 

Args.py : 실행

>>> python  Args1.py 2014 ZIGI JaeSung

argv : I:/Network/Nexus/py/Args1.py

argv : 2014

argv : ZIGI

argv : JaeSung

 

Args2.py : Code

import argparse

parser = argparse.ArgumentParser('Args',description='Args Desc')

parser.add_argument('year', type = int)

parser.add_argument('nick', type = str)

parser.add_argument('name')                               # Type 미지정 시에는 Default로 Str Tytpe

args = parser.parse_args()

print "2014=%d , nick=%s , name=%s" % (args.year, args.nick, args.name)

 

Args.py : 실행

>>> python  Args.py 2014 ZIGI JaeSung

year=2014 , nick=ZIGI , name=JaeSung

 


 

 

[ 정규식 ]

 

❖ 정규식

     - 복잡한 문자열 패턴을 검색/추출/대치하는 규칙

 

re 모듈

     - Python에서 정규식을 사용하기 위해 제공하는 모듈

  

meta 문자

     - 문자나 문자 패턴을 반복의 표현을 나타나는 문자

 

     ▷ 메타 문자 [반복]

 

 Meta 문자

 내용

 예제

*

  문자를 0회 이상 반복

 Zi*Gi : ZGI, ZiGi, ZiiiiiiiiGi

+

 앞 문자를 1회 이상 반복

 Zi+Gi : ZiGi, ZiiiiiGi

?

 앞 문자를 0 or 1회 반복

 Zi?Gi : ZGi, ZiGi

{m}

 앞 문자를 m회 반복

 Zi{3} : Ziii

{m,n}

 앞 문자를 m~n 회까지 반복

 Zi{2,3} : Zii, Ziii

 

     ▷ 메타 문자 [매칭]

 

 Meta 문자

 내용

 예제

.

 개행문자를 제외한 모든 문자와 매칭

re.DOTALL 모드 시에는 개행문자 포함하여 매칭

 Z.Gi : ZiGi ZzGi, Z1Gi

^

1. 문자열의 시작과 매칭

   re.MULTILINE 모드에서는 각 줄의 시작과 매칭

2. 메타 문자 [ ]안에서는 해당 문자 예외

^ZiGi : ZiGi of Network (O) , Network ZiGi(X)

 

Z[^i]Gi : ZkGi, ZlGi (O) , ZiGi (X)

$

문자열의 마지막과 매칭

메타 문자 [ ] 내부에서는 순수한 $의 의미로 사용

$ZiGi : Network ZiGi (O), Network ZiGis (X

[ ]

 문자 집합 안에 속한 한 문자를 의미

‘-’로 범위지정 가능

 Z[hij]]Gi : ZhGi, ZiGi, ZjGi

 Z[a-z]Gi

|

 Or

 Zi|oGi : ZiGi, ZoGi

( )

정규식을 그룹으로 지정

정규식 내부에서 그룹을 만들고,

각 그룹을 Index에 따라서 가져올 수도 있다.

, Index를 벗어나게 될 경우에는 예외처리된다

 m = re.match('\s*([0-9]+) ([0-9]+)', ' 123 12')

print m.group(0)                 : ‘ 123 12’

print m.group(1)                 : ‘123’

print m.group(2)                 : ‘12’

 

 

      ▷ 메타 문자 [특수문자]

 

 Meta 문자

 내용

 예제

\\

‘\’ 자체를 문자로 인식

 Z.Gi : ZiGi ZzGi, Z1Gi

\d

 모든 숫자와 매칭

[0-9]

\D

 숫자가 아닌 모든 문자와 매칭

 [^0-9]

\s

공백이나 탭등의 문자와 매칭

[\t\n\r\f\v]

\S

공백이나 탭등이 아닌 문자와 매칭

[^ \t\n\r\f\v]

\w)

숫자 혹은 문자와 매칭

[a-zA-Z0-9]

 

 

match() vs search()

     •match

         - 문자열의 시작지점에서부터 일치하는지 확인

     •search

         - 문자열 내부에 부분적으로 일치하는 것이 존재하는지 확인

Ex)

     >>> re.match("c", "abcdef")  # No match

     >>> re.search("c", "abcdef") # Match

 

 


 

 이번 포스팅으로, git에 올라와 있는 Nexus pingrange 예제를 알아보기 위한 Python 내용을 살펴보았습니다.

각 항목별로 물론 더 많은 이론 내용이 있겠지만, 이번 포스팅의 중점은 코드를 이해하기 위한 기술 수준에서만 정리를 했습니다.

물론 조금 더 이해하기 쉽게(?)하기 위해 비교를 위해서 딱 코드에 있는 내용만 있지는 않고 +a의 내용이 있습니다.

각 코드별로 좀 더 이해를 돕기 위한 내용은 이번 pingrange에서는 하지 않았습니다.

물론 정리해놓은 기술 내용을 기반으로 보실 수 있기는 합니다만, 그래도 좀 더 각 줄 별로 주석을 달아드리겠지만

이번 코드가 아닌 다음 포스팅에서 다뤄질  pingrange의 변형 코드에서 할 예정입니다.

그 전까지는 코드를 먼저 나눠서 기술 내용을 바탕으로 이해해 보시면 좋을 듯 싶습니다.

 

아래는 pingrange를 이해하기 쉽게 하기 위한 각 실행 범위별 구간이니(Part 3에서 다뤄지기도 했습니다.),

참고하시면 좋을 것 같습니다.

 


 

 

Posted by 네떡지기

Last Updated : 2014.07.02

 


 

Network 장비에서 Python을 활용한 부분에 간단히 정리를 해보려고 합니다.

우선 처음 진행 부분은 현재 실제 테스트가 가능한 Nexus 7000 / 5000으로 먼저 간단히 시작합니다.

물론 완전 초기 부분이라서, 아마도 잘못된 부분 등에 대해서는 업데이트가 지속적으로 필요할 것 같습니다.

그리고 Nexus에서는 9000 / 3000 시리즈 기반으

Python 활용도가 더 높은 것으로 알고 있지만..(잘못 알고 있을수도? ^^)

현재 테스트가 가능한 부분이 Nexus 7000과 5000이라 이것으로 시작하며, 추후에 다른 테스트 장비(VM포함)로..

추가적인 포스팅을 진행할까합니다.

 

 


 

Cisco Nexus 7000  Python 특징

 Nexus 7K에서는 Python 2.7.2Interactive / noninteractive(script)에 대한 모드를 모두 지원합니다.

 NX-OS 6.2(8) 부터는 JavaScript Object Notation(JSON)logging module을 지원합니다.

 

 

Cisco Nexus 5000  Python 특징

 Nexus 5K에서는 Python 2.7.2모든 Feature를 사용할 수 있다.

 • Python Script를 이용하여 다음과 같은 기능을 구현할 수 있다.

       -  Swtich Bootup 시에 Configuration을 확인하는 Script 실행

       - Configuration 백업

       - Monitoring Buffer 이용량에 따라서, 사전에 혼잡 관리가 가능

       - 일정 시간 간격으로 작업을 수행

       - 프로그래밍 방식으로 SwitchCLI 명령을 수행하고 다양한 업무에 활용 가능

 

 

Third Party Pure Python Packages

 •Nexus에서 Third Party Python Package를 다음과 같은 방법으로 설치하고 사용할 수 있다.  

    ) ZIGI.tgz 를 서버로부터 복사하여 설치하는 경우.

     Step 1. 다음의 명령으로 tar fileSecure Copy 한다.

                      copy scp://user@server/path/to/ZIGI.tgz bootflash:ZIGI.tgz vrf management

     Step 2. Packge의 압축을 해제

                      tar extract bootflash:ZIGI.tgz

     Step 3. 압축이 풀린 Packgebootflash로 옮긴다

                      move bootflash:ZIGI/* bootflash:          

     Step 4. PackgeInstall 한다.

                      python setup.py install

     Step 5. bootflash에 복사된 파일을 제거한다.

     Step 6. Python Mode에서 해당 Packge를 사용한다.

                      NX-OS# python

                      >>> import ZIGI

 

 

 

Python Mode 접근

 

NX-OS# python

Python 2.7.2 (default, Nov 27 2012, 17:50:33)

[GCC 4.3.2] on linux2

Type "help", "copyright", "credits" or "license" for more  information.

Loaded cisco NxOS lib!

 >>> exit()

NX-OS#

 

 

 

 

Python 모드에서 Cli  명령 

 

 API

내  용 

1.  NX-OS# >>> cli("명령어")
    string = cli(“
명령어”)

 Python Mode에서 NexusCLI 명령어를 실행하고 Raw 결과를 리턴받게.

‘;’ 이용하여 다수의 명령어를 한 줄에 실행 가능

제어/특수 문자도 함께 출력. 이는 ‘\n’과 값도 함께 출력된다는 것을 의미하며,

    이는 가독성을 떨어지므로, clip() 명령을 사용하는 것이 보다 가독성에 좋다

2. NX-OS# >>> clid(“명령어”)

    dictionary= cli(“명령어”)

XML을 지원하는 CLI 명령어로 결과를 Dictionary 형식으로 리턴 받게 됨.

3. NX-OS#>>> Clip(“명령어”)

CLI 명령어에 대한 결과를 표준 Output으로 출력을 하며, 별도의 리턴 값은 없다.

 clip(“명령어”) r = cli(“명령어”) , print r  은 동일한 역할을 한다.

※ Nexus 7000 기준이며, Nexus 5000에서는 cli만 지원이 됩니다.

 

 Python Mode / CLI Mode 관련

 •Python Mode에서 Cli 명령을 사용하여 Switch Mode를 변경하는 경우에, Python Mode를 벗어나게 되면 변경된 Switch
   
Mode  유지되지는 않고, Python Mode 들어올 때의 기존 Mode로 가게 된다.

 •Python Mode에서 선언된 Data는 해당 Python Shell에서만 유효하며, Shell을 나간 후에 다시 들어오게 되면 사용 할 수 없게 된다. 

 

EX-1

EX - 2

NX-OS# python

NX-OS# >>> cli("conf t")

NX-OS(config)# >>> cli(“int e1/1”)

NX-OS(config-if)# >>> exit

NX-OS# 

NX-OS# python

NX-OS# >>> ZIGI = “JaeSung

NX-OS# >>> print ZIGI

JaeSung

NX-OS# >>> exit

NX-OS# python

NX-OS>>> pint ZIGI

Error:variable ‘ZIGI’ undefined

 

 

Posted by 네떡지기

티스토리 툴바