분류없음2015.02.15 17:42

 

Nexus Ping Drop 관련 이슈가 예전에  있어서 확인하고 조치하였다가,

네전따 카페에서 다른 분이 동일한 증상이 있어서, 알려드렸었는데 오늘 문득 또 다른 분이

쪽지로 물어오신 김에 아주 짧고 간단하게 정리하고 넘어가봅니다. (그 분도 이 증상이 맞는지 모르겠네요..)

 

Nexus 장비에서 간헐적으로 Ping Loss가 발생하는 경우가 있었습니다.

(짧게 정리할 것이기 때문에 각설하고 바로 결론..)

Nexus 7K에서는 Control Plane을 보호하기 위해서 CoPP(Control Plane Policing)이 기본적으로 활성화 되어 있습니다.

아래와 같이 내용을 확인할 수 있으며,

 

NX-OS# show run copp
<snip>
control-plane
   service-policy input copp-system-policy

 

해당 설정을 제거하고, 다시 Ping을 해보면 정상적으로 Ping이 나가는 것을 볼 수 있습니다.

 


※ 관련 링크
http://www.cisco.com/c/en/us/td/docs/switches/datacenter/sw/4_1/nx-os/security/configuration/guide/sec_nx-os-cfg/sec_cppolicing.html#wp1082584

 

 

https://supportforums.cisco.com/document/59621/icmpping-drops-when-pinging-nexus-7000?utm_source=twitterfeed&utm_medium=twitter

 

http://www.cisco.com/c/en/us/support/docs/switches/nexus-7000-series-switches/116043-copp-nexus7000-tshoot-00.html

 

http://www.cisco.com/c/en/us/support/docs/switches/nexus-7000-series-switches/116043-copp-nexus7000-tshoot-00.html#anc5

 

 

 

Posted by 네떡지기
분류없음2014.11.20 12:33

 

 

 


안녕하세요.

이번 포스팅은 기존에 한 줄 알았는 데.. 안 한(?) 정리만 해놓고... 안한 포스팅인 듯 싶습니다.

어쩌면 다른 제목으로 했을지도 모르겠지만.. 최근에 추가한 내용들도 있어서 ^^

Nexus 시리즈로 포스팅해 봅니다. ^^


 

 

VLAN

• VDC별로 4094개의 VLAN이 지원되며, 전 시스템에서는 16,384개의 VLAN이 지원이 되지만, 특정 VLANSystem-Level 의해서

 사용되거나 예약되어 있기 때문에 사용이 불가하다.  이러한 Vlan을 확인하는 명령어는 다음과 같다. [ Show vlan internal usage ]

VLAN별의 특징은 다음과 같다

     - VLAN 1  : Default VLAN으로 수정 및 삭제가 불가

     - VLAN 2-1005  : Normal VLAN으로 생성, 사용, 수정, 삭제가 가능

     - VLAN 1006-4094  : Extended VLAN으로 생성, 명명(named), 사용이 가능하며, 항상 Active 상태이며,

                                        항상 Enable 상태로 shutdown이 불가하다.

VDC간의 VLAN은 독립적으로 운용되기 때문에 VLAN번호가 VDC간에 중복되어도 상관없다

• System-Level에서 예약된 VLAN 정보는 'show vlan internal usage' 명령으로 확인이 가능하다.

• System-Level에서 예약된 VLAN은 Nexus 7K와 Nexus 5K가 서로 다르다.

        - Nexus 7K : 128개                                 - Nexus 5K : 81개

 

  

 

NX-OS_7K# show vlan internal usage

   VLAN                                 DESCRIPTION

----------------                         ----------------------------------------------------

 3968-4031                         Multicast
4032-4035,4048-4059     Online Diagnostic
4036-4039,4060-4087     ERSPAN
4042                                     Satellite
3968-4095                          Current

 

 

NX-OS_5K# show vlan internal usage

   VLAN                                 DESCRIPTION

----------------                         ----------------------------------------------------

3968-4031                          Multicast
4032-4035                          Online Diagnostic
4036-4039                          ERSPAN
4042                                    Satellite
3968-4047,4094               Current

 

• System-Level에서 설정된  Reserved VLAN 번호를 변경하고자 할 때에는 'system vlan Start_Vlan_Number reserve' 로 변경한다.

     변경 시에는 지정한 Reserved VLAN의  첫 번째 번호부터, N7K는 연속된 128개의 VLAN이 Reserved VLAN으로 할당되고

     N5K는 연속된 80개의 VLAN과 4094가 Reserved VLAN으로 사용할 수 있게 된다.

 

Private VLAN 개념

• Private VLAN은 하나의 VLAN을 독립된 다수의 VLAN처럼 쓸 수 있게 해준다. 

  이는 Data CenterServer Farm 안의 동일 Subnet에서 각 서버들을 분리시켜주어  보안을 강화시켜준다.

 

Private VLAN 구분

• Primary VLAN 

     - Promiscuous Port :  Secondary VLAN이 외부와 통신하기 위한 목적으로 사용된다.

                                 Community / Isolated VLAN  를 포함한 모든 Port와 통신 가능.                           

• Secondary VLAN

     - Community VLAN : 동일한 Community VLANPromiscuous  Port와 통신이 가능하지만

                                 다른 Community VLAN이나, Isolated VLAN과는 통신 불가.

    - Isolated VLAN : 각각 독립적 port로 통신.  Isolated VLAN 간은 통신 불가., Promiscuous Port와는 통신이 가능.

 

 

Private VLAN 유용

IP Address 관리 측면

        : IP Address의 사용할 수 있는 범위가 많아짐. (불필요하게 VLAN을 많이 나누게 되면 그만큼 사용 가능한  IP범위가 줄어 )

        :  IP Subnet이 많아지면, latency 가 증가함.  (성능적인 측면?)

보안 측면

        :  Community VLAN은 동일한 Community VLAN 간에서만 통신 가능하고, Isolated는 독립적으로 통신이 되기 때문에

          L2에서의 보안을 강화 시켜준다.

 

Private VLAN 특징

private-vlan : Feature 활성화 필요.

• Private Vlan 동일한 SubnetGateway를 그대로 사용.

• Isolated VLAN 간에는 unicast, multicast, broadcast 모두 통신이 불가하다.

하나의 Primary VLAN에는 하나의 Isolated VLAN만 설정이 가능하다.

하나 Primary VLAN에 포함된,  Secondary VLAN은 하나 이상의 Promiscuous Port에 연결될 수 있으며,

    이는 Load-Balancing이나  redundancy 목적으로 사용이 된다.

• Secondary VLANPromiscuous Port와 연결되지 않으면, 해당 Secondary VLAN은 외부와 통신이 불가능하다.

• Private VLAN에서 Layer3 Switch traffic이 내부 VLAN과 통신하기 위해서 Primary VLANSVISecondaryVLAN

    관계 설정이 되야 한다.

SVISecondary VLAN으로 설정이 불가하다.

Ether-Channel이나 SPAN의 목적지 PortPrivate VLAN이 될 수 없다.

 

 

 

Private VLAN 설정

1. Private VLAN feature를 활성화한다.

2. Primary VLAN을 생성 및 설정한다.

3. 필요에 따라 Community VlanIsolated Vlan 을 설정한다.

4. Primary vlanSecondary Vlan을 관계를 설정한다.

5. Layer 2 Host Port 설정

6. Promiscuous Port 설정

7. Primary  VLANSVISecondary VLAN과의 관계 설정

 

 

 

NX-OS(config)# feature private-vlan

NX-OS(config)# vlan 10   

NX-OS(config-vlan)# private-vlan primary    

  

NX-OS(config)# vlan 20-21

NX-OS(config-vlan)# private-vlan community-vlan

NX-OS(config)# vlan 22

NX-OS(config-vlan)# private-vlan isolated

NX-OS(config)# vlan 10   

NX-OS(config-vlan)# private-valn association 20-21

NX-OS(config-vlan)# private-valn association add 22

NX-OS(config)# interface ethernet 5/2

NX-OS(config-if)# switchport

NX-OS(config-if)# switchport mode private-vlan host

NX-OS(config-if)# switchport private-vlan host-association 10 21

 

 

NX-OS(config)# interface ethernet 3/1

NX-OS(config-if)# switchport

NX-OS(config-if)# switchport private-vlan promiscuous

NX-OS(config-if)# switchport private-vlan mapping 10 20-22

NX-OS(config)# interface vlan 10

NX-OS(config-if)#  private-vlan mapping  20-22

 

 

 

 

Posted by 네떡지기

 

 


지난 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 네떡지기
프로그래밍/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.15 00:56

이전까지 다뤄졌던 pingrange Python 예제를 변형해봅니다.

 

코드를 모두 짤 수 없다면, 잘 짜여진 기본 에제를 바탕으로 필요한 내용을 수정/보완하는 것도 중요할 것입니다.

물론 그렇게 하기 위해서는 기존 코드를 잘 이해하는 것이 매우 중요합니다.

 

기존 예제 소스를 이해하기 위해서 이론 정리만 했다면 이번 변형 예제는 기존 예제와 달라진 점을 비교해보고

또한 변형 예제에 대해서는 나름대로.. 친절하게 주석을 달았습니다.

물론 이론적인 부분이 함께 알아두고, 코드를 잘 쪼개서 볼 수 있어야 이해가 쉬울 것입니다.

 

 기존 예제 포스팅은 아래와 같습니다.

 

Python for Networker : Part 2                  Python for Networker : Part 3                    Python for Networker : Part 4 

 

기존 예제는 아래에서 볼 수 있습니다.

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

 

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

 

※ Modified Version Code는 다음에서 받을 수 있스니다.

      - https://github.com/NetworkZIGI/Python_for_Network

 


 

 

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

 

 

기존 pingrange의 변형된 코드의 달라진 점

      IP범위를 잘못 입력했을 경우에 예외 처리를 하였다.  (옥텟별로 1~255 사이)

             : checkRagne 메서드 정의.

             : 잘못된 입력인 경우에는 오류 메시지를 출력하고 시스템을 종료(sys.exit())를 한다.

      지정된 IP범위에서 증가값을 옵션으로 임의로 지정 할 수 있게 하였다.

              : 별도의 범위를 지정하지 않으면, default 1씩 증가한다.

 

 ◇ 기타 대부분의 코드는 아래의 변형된 코드와 유사하기 때문에 변형 코드의 주석과 기존 Part 2~4에서 다루었던 코드 이해하기

     이론 내용 등을 함께 보면 기존 코드를 이해하는 데 도움이 될 수 있을 것 같습니다.

 

 

pingrange Code : Modified Version

import sys                                                             # 시스템 패키지. 시스템 종료 메서드를 호출하기 위해 사용

import re                                                              # 정규식을 쓰기 위한 패키지

import cisco                                                         # Cisco 패키지  : Cli 명령을 사용하기 위해 사용.

from argparse import ArgumentParser               # 실행시의 매개변수를 다루기 위한 패키지

 

def checkRange(checkIP):                                       # 입력받은 IP 옥텟이 IP범위에 해당하는지 확인하기 위한 메서드

    octets = checkIP.split('.')                                  # 입력받은 IP를 '.으로 나눠서 각 옥텟별로 만듬

    for octet in octets:                                            # 각 옥텟이 저장된 List의 항목(IP의 각 옥텟)을 순환

        ip = int(octet)                                              # int 형 데이터로 변경

        if (ip < 0 or ip > 255):                                 # IP의 적정 범위인지 확인하여, 그 이외의 숫자인 경우에는 에러 발생

            print "Invalid Input Value"

            print "IP value is not less than 0 or greater than 255."

            sys.exit()                                                 # 시스템 종료

    return True

 

 

def expandrange(rangefunc,stepcnt):   # 사용자가 요청한 IP 범위 / 체크할 IP띄어쓸 범위

                                                                          # 체크할 IP 범위를 별도로 지정하지 않으면 1default 값으로 함.

    hosts = []                                                      # ping을 확인할 IP를 저장하기 위한 리스트 변수

    step = str(stepcnt[0])                                   # 매개변수 두번째를 리스트 type으로 받기 때문에 문자열 처리를 위해서 변경

    octets = rangefunc.split('.')                         # IP리스트를 옥텟별로 분리하여 LIST 변수에 저장

    for i,octet in enumerate(octets):                 # 옥텍별로 확인

        if '-' in octet:                                            # 만약에 옥텟안에 '-'이 있다면 해당 옥텟은 범위를 뜻하는 것.

            octetrange = octet.split('-')                # IP 범위를 LIST로 분리 (제일 앞 대역과 제일 대역)

            sip = int(octetrange[0])                      # IP 범위의 앞 부분을 sip로 int type으로 저장

            dip = int(octetrange[1])                     # IP 범위의 뒷 부분을 dip로 int type으로 저장

            for digit in range(sip,dip+1, int(step) if i==3 else 1):     

                                                                        # 순환문을 위한 값 지정 : 범위 지정의 첫번째 IP / IP / 증가값

                                         # 증가값의 경우에는 1~3번째 옥텟에는 해당하지 않고, 마지막 옥텟에만 해당되기 떄문에

                                         # 4번째 옥텟일 경우에만(i가 3인 경우가 옥텟이 4번째인 경우임, 0,1,2,3) 증가값을 적용하고

                                         # 그 이외의 경우에는 기본 증가값인 1을 사용한다.

                ip = '.'.join(octets[:i] + [str(digit)] + octets[i+1:])   # 범위의 옥텟전 / 범위옥텟 / 범위 옥텟후를 더해서 IP로만듬

                                        # List의 경우 [] 안에 시작이나 종료점을 쓰지 않으면, 처음부터 끝까지를 나타냄.

                hosts += expandrange(ip,stepcnt)    # 옥텟에서 아직 범위가 있을 수 있기 때문에 다시 expandrage 호출

            break

    else:                                                                        # for문이 break로 종료되지 않고 정상 종료된 경우에 실행.

        if checkRange(rangefunc):                   # for문이 정상 종료된 경우 범위가 지정되지 않은 숫자로만 이뤄진 IP이나

            hosts.append(rangefunc)            # IP가 정상적인 IP범위에 해당하는지 checkRange메서드 호출해서 true인경우만

    return hosts                                          # Host에 IP를 추가하고 리턴해준다.

 

parser = ArgumentParser('AdvPing')

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

                                                                # 매개변수 관리용 : 'ip' 이름으로 매개변수 1번째를 관리

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

                                                                # 매개변수 관리용 : 'options'로 처리하며, typestr로 하고 default값은 '1' 로 한다.

args = parser.parse_args()                     # 매개변수 손쉽게 사용하기 위해서 parse_args()메서드 호출

targets = expandrange(args.ip,args.options)    # IP와 option(IP 증가값)을 가지고 호출

for ip in targets:     # Ping을 체크할 전체 IP 리스트를 순환하면서 실행

    tupleping  = cisco.cli('ping %s' % ip)       # Ping 명령을 실행하고 그에 대한 결과값을 받음.

    strping = str(tupleping) # Tuple형식의 결과값을 str type으로 변형

    m = re.search('([0-9\.]+)% packet loss',strping ) # 정규식을 활용하여 IP가 UP/Down 확인

    print('%s - %s' % (ip, 'UP' if float(m.group(1)) == 0.0 else 'DOWN')) # 해당 IP의 UP/Down 표기

 

 

 

pingrange Code : Modified Version : 결과값

NX-OS# python pingrange2.py 10.9.8.1-200 32

10.9.8.1 - UP

10.9.8.33 - DOWN

10.9.8.65 - UP

10.9.8.97 - UP

10.9.8.129 - DOWN

10.9.8.161 - DOWN

10.9.8.193 - DOWN

 

Posted by 네떡지기
프로그래밍/Python2014.07.08 02:49

 


 

이번 포스팅은 지난 포스팅에 이어서 실제 Python 예제를 통해서 보려고 합니다.

기본 내용은 지난 포스팅과 이어지게 됩니다.  예제 소스는 기존 포스팅과 함께 왔다리 갔다리

하기 힘드실 듯하여... 해당 예제 포스팅이 끝날 때까지 계속 포함할 예정입니다. 

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

 

Python for Networker : Part 2

 

을 보고 오셔야 합니다.

 

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

[ 예제 링크 ] 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 코드 실행 순서

  -  Active한 대화명 프롬프트 모드에서의 Python 실행이 아닌, Python 스크립트 코드를 보면서 어떻게 실행이 되는지

    혹시라도 헛갈리실 수 있을 듯 싶어서, 간단하게 위의 코드를 보면서 어떤 순서로 실행되는 보려고 합니다.

  - 우선 모든 코드는 제일 위에서부터 차례대로 진행이 되기 때문에 지난 Part 2에서 얘기된 필요한 Python 모듈을 먼저 Import

    하는 것으로 코드가 시작이 됩니다. 실제 아래 정의되는 실행부분에서 해당 모듈의 내용을 사용해야 하기 때문에 Python 모듈을

    Import하는 것이 당연히 제일 먼저 선언되어야 할 것입니다.

  - 그리고나서는 순서대로 실행이 되어야 하나, 위에서 보면 def 키워드로 expandrange() 함수가 선언되어 있습니다.

    함수는 바로 실행되지는 않기 때문에 expandrange() 함수 영역까지 (상단에서 보면 return host 부분)는 실제 바로 실행되지는

    않습니다.

  - 함수 선언부가 지난 이후에 일반 실행 코드가 순서대로 실행이 되게 됩니다.

  - 그리고 targets = expandrange(args.ip)에서 상단에 선언한 함수를 호출을 하게 됩니다. 그러면 당연히 Def로 선언한 함수

    선언부의 첫 줄부터 실행을 하게 되고, return host 부분까지 실행 후에는 해당 함수를 호출했던 라인으로 복귀를 하게 됩니다.

  - 그 다음에는 for문을 순환한 이후에 프로그램이 종료하게 됩니다.

  - 별다른 내용은 아니긴 하지만, 코드를 보면서 def나 class로(앞으로 다뤄질) 지정된 부분은 그 해당 라인에서 바로 실행이 아니라

    해당 내용을 사용하기 위한 선언부이기 때문에 실행 해당 내용이 실행되는 시점은 아래 실행 코드에서 해당 선언부를 호출하는

    경우가 되게 됩니다. 

 

 


 

 

 

python 문자열 다루기

      - Network 장비에서의 Python 사용에 있어서 가장 많이 활용하기 위해서 사용하는 부분이 문자열을 어떻게 다루느냐가 아닐 듯

       싶습니다.  물론 만약에 장비에서 얼마나 많은 종류의 자체 Python 모듈을 제공하느냐에 따라서 이 부분이 달라질 수 있을 듯

       싶지만, 그렇다고 하더라도 문자열을 가지고 활용할 수 있는 방법은 많을 것 같습니다. 이번 포스팅에서는 이런 문자열 다루기에

       대해서 다뤄봅니다. 아래 내용은 위의 코드를 이해하는 데 가장 많이 사용되는 부분이니, 꼭! 중요하게 읽어보셔야 할 것이라~

       생각해봅니다.

  

문자열 선언

   문자열을 선언하는 방법에는

       문자열’ , “문자열” , ‘’’다중라인 문자열‘’’, “””다중 라인 문자열“””

   •’, “ 모두 표기 가능하게 하여, 문자열 안에 를 넣으려고 할 때에는 문자열 안에 기호와 반대로 문자열을 묶어주면 안의

      기호는 문자열 기호가 아니라 단순히 ‘, “ 의 역할만 하게 된다.

       , “Network” ZIGI를 표현하고 싶을 경우에는 로 묶어서 ‘ “Network” ZIGI ‘ 쓰면 된다.

 

문자열 슬라이싱

   문자열[시작Idx:종료Idx-1]   : 문자열을 시작 Index 지점부터, 종료 Index – 1까지 의 문자열을 잘라낸다.

   시작 Index와 종료 Index를 각각 생략하게 되면, 각각 최초 시작 지점/종료 지점을 가리키게 된다.

 

❖ 문자열 연산

   문자열을 ‘+’로 합치는 경우에는 두 문자열 사이에 공백이 없이 합쳐지고, ‘,’로 합치는 경우에는 두 문자열 사이에 공백이

     들어가면서 합쳐지게 된다.

 

❖ 문자열 Formatting

   •print 시에 %s, %c, %d 등으로 지정하여 원하는 데이터 값을 출력 할 수 있다.

   Formatting 코드에 맞춰서 값을 넣어야 하지만, %s로 지정할 경우에는 자동 변환이 되서 들어가게 된다.

   문자열 내에 %를 사용하여 Formatting 시에는 %를 일반 문자로 출력하려면 %%로 써야 출력이 된다.

      하지만, 문자열 내에 % 사용한 Formatting이 없으면 그냥 %만 써도 된다.

   •%숫자s 과 같이 %Formatting 코드 사이에 숫자를 넣으면 해당 크기만큼 공간을 할당해서 출력하게 된다.

       이 때에 숫자를 로 입력하면 해당 공간만큼 할당하여 문자열을 왼쪽 정열하여 출력하게 된다.

  

%s 문자열 (String)

%c 문자 한개(character)

%d 정수 (Integer)

%f 부동소수 (floating-point)

%o 8진수

%x 16진수

%% Literal % (문자 '%s' 자체) 

 

Formatting Example Code

Example Code Result

print "I warn %d won." % 100

print "Americano %d won. Latte %d won" % (3900,4600)

print "My Name is %s" % ("Network ZIGI")

I warn 100 won.

Americano 3900 won. Latte 4600 won

My Name is Network ZIGI

print "%15s %s" % ("Network", "ZIGI")

print "%-15s %s" % ("Network", "ZIGI")

        Network ZIGI

Network         ZIGI

 

문자열 Method

•find(keyword, [start, [end]])   / rfind(keyword, [start, [end]])

     - 문자열에서 Keyword가 위치한 첫 번째(rfind는 뒤에서부터 첫 번째) Index리턴하고, 해당 Keyword가 존재하지 않으면

       ‘-1’을 리턴

•index(keyword, [start, [end]])

     - find() 와 동일한 동작을 하지만, Keyword가 존재하지 않을 경우에 ‘-1’이 아닌 ValueError 예외를 발생.

•join(sequence)

      - sequence 형변수를, Join을 호출한 문자열로 연결해서 리턴하는 메서드이며, split()와 반대의 역할을 하게 됨.

•partition(separator)

      - 문자열을 separator을 나누게 되는 데, separator , separator , separator 뒤의 3개의 Tuple로 리턴.

lstrip([chars])

      - 문자열의 왼쪽을 제거.chars을 지정하지 않으면 공백 문자를 제거.

 

 

Join / Partition / lstrip Example Code

 Join / Partition / lstrip Example Code Result

str1 = '-'

joinstr = str1.join("abc")

print(joinstr)

 a-b-c

str1 = "Network ZIGI Good"

partStr = str1.partition("ZIGI")

print(partStr)

part1 = partStr.__getitem__(2)

print(part1)

part1 = part1.lstrip()

print(part1)

 

('Network ', 'ZIGI', ' Good')

 Good

Good

 

•Split([separator, [maxsplit]])

      - separator로 문자열을 분리하는 것은 Partition과 동일하나, Partition의 경우에는 separator도 함께 리턴되지만,

        split는 해당 separator 기준으로 분리가 되면서 포함되지 않는다.

      - 뒤에 Maxsplit의 값을 주게되면, 앞에서부터 분리되는 개수의 max 값을 지정할 수 있다

Strip([chars])

      - 문자열 양쪽 끝을 잘라내는 데, 별도의 chars를 지정하지 않으면 공백을 제거하고 chars 지정 시에는 해당 문자가 포함된

        모든 내용이 삭제 된다

 

 

Split Example Code

Split Example Code

str1 = "Network ZIGI Good Split Test"

partStr = str1.partition("ZIGI")

print(partStr)

str2 = str1.split()

print(str2)

str3 = str1.split("ZIGI")

print(str3)

str4 = str1.split(' ',2)

print(str4)

 

('Network ', 'ZIGI', ' Good Split Test')

['Network', 'ZIGI', 'Good', 'Split', 'Test']

['Network ', ' Good Split Test']

['Network', 'ZIGI', 'Good Split Test']

 

 

 

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

 

 


 

이번 포스팅은 실제 Python 예제를 통해서 보려고 합니다.

코드에 대한 상세 내용은 내용은 추가적인  포스팅으로 예제들과 함께 다뤄질 예정입니다.

이번 포스팅은 '이런 것도 할 수 있구나?'

 정도의 느낌의 포스팅이라고 보시면 좋을 듯 싶습니다.

이번 포스팅에 사용된 예제는 github.com에서 보실 수 있습니다.

 

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

 

우선 예제를 보기 전에 몇 가지 정리를 해봅니다.

 

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

 

 

 


 

Python Script

    •Python ScriptNX-OS의 기본적으로 bootflash://’ 에서 실행된다.

 

   NX-OS# dir

    …

        Mar 10 07:38:37 2009  pingrange.py

    ...

   NS-OS#

 

    기본 CLI Mode에서의 Python Script 실행 시에는 python 키워드를 사용하여 아래와 같이 실행 할 수 있다.

                 NX-OS# python pythonFileName.py { args,.. }

 


 

 

pingragne.

 

    •pIng을 확인할 때, '-'를 사용하여 range를 주어서 확인이 필요한 IP대역에 대해서 확인을 할 수 있다.

    •range는 각 옥텟별로 구성이 가능하다.

             Ex) 1.1.1-2.3-4       : 3번째 옥텍에서 1과 2에 대해서 각각 4번째 옥텟의 3,4번 IP에 대해서 Ping Check.

                                               즉, 1.1.1.3 / 1.1.1.4 / 1.1.2.3 / 1.1.2.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'))

 

 

pingrange.py 실행결과

NX-OS# python pingrange.py 10.1.1-2.1-3

   10.1.1.1 – UP

   10.1.1.2 – UP

   10.1.1.3 – DOWN

   10.1.2.1 – UP

   10.1.2.2 – UP

   10.1.2.3 – DOWN
NX-OS#

 

 


 

pingrange 이해하기 위한 기반 내용들을 하나씩 볼 예정이며, 이번 내용에서 몇 가지만 살펴보게 됩니다.

    Data type과 제어문에 반복문에 대한 부분은 기존 제 포스팅을 참조하셔도 됩니다.


 

 

○ 패키지 Import

     import 패키지명

         - 모듈 이름으로 Import하며, 사용 시에는 패키지명.멤버메서드명 으로 사용한다.

     from 패키지명 import 멤버

         - 실제 사용하고자 하는 멤버를