XML for NSO - Intermediate

XPath 표현식

  • XML 문서에서 하나 이상의 노드를 찾는데 사용되며, 패턴을 사용해 XML 요소의 범위와 다양한 속성을 정의
  • 노드 이름 선택자 
    • 주어진 컨텍스트에서 이름을 기반으로 노드 매칭
      devices 노드는 devices에 포함된 모든 요소 반환
      devices
         |
         |
      <devices>
      	<device>
      		<name> Router </name>
      		<id> 151 </id>
      	</device>
      <devices>   
      단일 노드 매칭시 해당 노드의 값을 반환
  • 절대 경로와 상대 경로
    • 컨텍스트 노드 :  기본적으로 XML 문서의 루트 요소이지만, 처리되는 XPath 표현식에 따라 변경
    • 현재 노드 :  마침표 . 기호로 현재 컨텍스트 노드를 참조
    • 부모 노드 :  도 개의 마침표 .. 로 현재 노드의 부모를 선택
    • 절대 경로 :  현재 컨텍스트 노드와 상관없이 Xpath 표현식 재사용 가능
    • 상대 경로 :  전체 구성 트리에 대한 지식이 필요하지 않고 XPah 표현식에서 작업 중인 하위 집한만 알면 사용 가능

XPath를 이용한 데이터 필터링

  • XPath는 XML 문서에서 특정 노드를 찾거나 여러 노드를 선택할 때 데이터를 필터링하는 도구
  • 이중 슬래시 // 
    • // 선택자는 문서 내 위치와 상관없이 어디에서든 노드를 선택
    • 계층적 수준이나 상위 요소가 다르더라도 일치하는 모든 노드를 찾음
    • 다른 표현식과 결합하여 검색 범위를 좁힐 수 있음
      /service/devices안에 있는 name 태그 만을 검색
      /service/devices//name
    • 용도
      • 다른 데이터 모델을 사용하는 구성에서 작업할 때 유용
      • 문서 전체에 공통으로 있는 요소 이름을 찾을 때 사용
  • 조건식과 XPath
    • 여러 노드 중 특정 노드를 필터링하는 표현식으로 대괄호 []를 사용
    • 조건식 유형
      1. 카운터 사용
        • 대괄호 안에 숫자를 넣어 해당 위치의 요소 검색
        • 인덱스 1부터 시작
        • 예시 :  /devices/device[1] → 첫 번째 device 요소 선택
      2. 속성 필터링
        • @ 기호를 사용해 속성의 노드 필터링
        • 예시 :  //device[@id="router1"] → id 속성이 "router1"인 device 요소 선택
      3. 와일드카드 연산자
        • * - 임의의 노드 매칭
        • @* - 임의의 속성 매칭
        • 예시 :  /config/* → config 하위의 모든 요소 선택 
      4. 요소 값 기반 조건
        • 요소의 실제 내용이나 값을 기준으로 노드를 찾을 때 사용
        • NSO에서는 특정 이름이나 ID 요소를 찾을 때 특히 유용
        • 예시 :  /devices/device[name="dist-rtr01"] → name이 "dist-rtr01"인 device 요소 선택
      5. XPath 함수
        • 카운터를 생성할 수도 있는 XPath 함수를 사용해 복잡한 XPath 표현식 형성
        • 논리적, 텍스트 처리 지침 등 추가 가능
        • 전체 XPath 함수 목록은 온라인 검색 가능

XPath 표현식 연습

  • NSO 접속 및 동기화
    ncs_cli -C -u developer
    devices sync-from
  • 개발자 도구 활성화 및 표현식 추가
    devtools true
    config
    xpath eval ?
  • XPath 쿼리실행
    장치 이름 반환
    xpath eval /devices/device/name
    장치 노드 반환
    xpath eval /devices/device

XPath operators

  • 수치 연산자
    연산자설명
    +덧셈
    -빼기
    *곱셈
    div분할
    =동일하다
    !=같지 않다
    <보다 작음
    >보다 크다
    >=크거나 같음
    <=보다 작거나 같음
    사용 예시(기본 언어 함수식과 유사)
    //subscription[15 > price]
    //item[(in-stock - 1) >= 0]
    /vehicles/vehicle[count(.//passenger) > 2] / name
    concat(//interface[contains(./description, "BANKI")]/type, "-", //interface[contains(./description,"BANKI")]/id)
    //service[not(state="failed")]
  • 방화벽 전체 맵 개수 세기
    xpath eval count(/devices/device[name="edge-firewall01"]/config/policy-map)
  • 방화벽 INSIDE 네트워크 객체 찾기
    xpath eval /devices/device[name='edge-firewall01']/config/object/network[contains(name, 'INSIDE')]/name
  • 활성 상태 인터페이스용 XPath 표현삭
    developer@ncs(config)# xpath eval /devices/device[name='dist-sw01']/config/ios:interface/GigabitEthernet[not(shutdown)]/name
  • 특정 범위 내의 활성 인터페이스 찾기
    developer@ncs(config)# xpath eval /devices/device[name='dist-sw01']/config/ios:interface/GigabitEthernet[not(shutdown) and substring(name, 1, 3)='1/' and number(substring(name, 4, 1)) >= 0 and number(substring(name, 4, 1)) <= 9]/name

XML templates에 변수 맵핑하기

  • XPath를 사용한 직접 맵핑
    XML templates
    <config-template xmlns="http://tail-f.com/ns/config/1.0" servicepoint="loopback">
        <devices xmlns="http://tail-f.com/ns/ncs">
            <device>
                <name>{/device}</name>
                <config>
                <interface xmlns="http://tail-f.com/ned/cisco-ios-xr">
                    <Loopback>
                    <id>{/interface-id}</id>
                    <ipv4>
                        <address>
                            <ip>{/ip-address}</ip>
                            <mask>{/network-mask}</mask>
                        </address>
                    </ipv4>
                    </Loopback>
                </interface>
                </config>
            </device>
        </devices>
    </config-template>
    YANG Model
    module loopback {
      namespace "http://com/example/loopback";
      prefix loopback;
    
      import ietf-inet-types {
        prefix inet;
      }
      import tailf-ncs {
        prefix ncs;
      }
      import tailf-common {
        prefix tailf;
      }
    
     augment /ncs:services {
      list loopback {
        key name;
    
        uses ncs:service-data;
        ncs:servicepoint "loopback";
    
        leaf name {
          type string;
        }
        leaf device {
          mandatory true;
          type leafref {
            path "/ncs:devices/ncs:device/ncs:name";
          }
        }
        leaf interface-id {
          mandatory true;
          type uint32;
        }
        leaf ip-address {
          mandatory true;
          type inet:ipv4-address;
        }
        leaf network-mask {
          mandatory true;
          type inet:ipv4-address;
        }
      }
     }
    }
    서비스 구성 값을 템플릿에 매핑
  • 코드에서 변수 매핑하기
    • $ 기호를 사용하여 서비스 코드의 매개변수 매핑
      <element>{&VALUE}</element>
    • template 해당 매개변수 위치에 XPath 변수 사용
      <config-template xmlns="http://tail-f.com/ns/config/1.0" servicepoint="loopback">
          <devices xmlns="http://tail-f.com/ns/ncs">
              <device>
                  <name>{/device}</name>
                  <config>
                  <interface xmlns="http://tail-f.com/ned/cisco-ios-xr">
                      <Loopback>
                      <id>{/interface-id}</id>
                      <ipv4>
                          <address>
                              <ip>{$IP-ADDRESS}</ip>
                              <mask>{$NETWORK-MASK}</mask>
                          </address>
                      </ipv4>
                      </Loopback>
                  </interface>
                  </config>
              </device>
          </devices>
      </config-template>
      변수로 관리하기에 더이상 YANG 모델에서는 ip-address와 entwork-mask가 필요하지 않음
      대신 Python 코드 등으로 직접 관리
      ip_address = externalApi.get_address()
      network_mask = externalApi.get_netmask()
      
      tvars = ncs.template.Variables()
      template = ncs.template.Template(service)
      tvars.add('IP-ADDRESS', ip_address)
      tvars.add('NETWORK-MASK', network_mask)
      
      template.apply('loopback', tvars)

      가능한 template에서 직접 XPath 사용해 작업
      XPath를 사용한 직접 매핑이 프로그래밍 코드보다 훨씬 빠름

NSO에서 XPath 대안

  • Python & JAVA API
    • Python API를 통해 NSO와 상호작용 가능
    • ncs 패키지
      • maggic 모듈 : 데이터 스토어에 쉽게 액세스 하는 사용
        • XPath와 maagic 모듈의 기 유사
        • get_root() 모듈을 통해서도 가능
      • namespace 처리
        NSO 내부 구성의 ncs 사용 가능
        root.namespace1__object1.namespace2__object2
        root.ncs___devices.ncs__device['dist-rtr01']