XML for NSO - Advanced

XPath 표현식

  • XML 문서에서 하나 이상의 노드를 찾는데 사용되며, 패턴을 사용해 XML 요소의 범위와 다양한 속성을 정의
  • 노드 이름 선택자 
    • 주어진 컨텍스트에서 이름을 기반으로 노드 매칭
      devices 노드는 devices에 포함된 모든 요소 반환

NSO templates 과 NSO services

  • NSO 서비스는 서비스 입력과 서비스 또는 네트워크 구성 출력을 매핑하며, 매핑은 XML 템플릿 내에서 이루어짐
  • 여러 장치가 있는 namespaces
    • namespaces는 전체 환경의 맥락에서 모델의 고유성을 보장
    • 하나의 XML 템플릿을 두 장치에 모두 사용 가능
      각각의 xmlns 태그에 다른 정의로 구
      <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>
      <!-- IOS-XE -->
                  <interface xmlns="urn:ios">
                      <Loopback>
                      <id>{$INTERFACE}</id>
                      <ip>
                          <address>
                            <primary>
                              <ip>{$ADDRESS}</ip>
                              <mask>{$MASK}</mask>
                            </primary>
                          </address>
                      </ipv4>
                      </Loopback>
                  </interface>
      <!-- IOS-XR -->
                  <interface xmlns="http://tail-f.com/ned/cisco-ios-xr">
                      <Loopback>
                      <id>{$INTERFACE}</id>
                      <ipv4>
                          <address>
                              <ip>{$ADDRESS}</ip>
                              <mask>{$MASK}</mask>
                          </address>
                      </ipv4>
                      </Loopback>
                  </interface>
                  </config>
              </device>
          </devices>
      </config-template>

templates에서 XPath context 설명하기

  • XPath 축(axis)
    • :: 이중 콜론을 사용해 축 지정자와 노드 테스트 구 
    • XPath 표준 기능으로 축은 conext node와의 관계를 말하며 노드를 찾는데 사용 가능
      NameAction
      ancestorcontext node의 조상을 식별(루트 노드와, 부모노드도 포함)
      ancestor-or-selfcontext node와 그 조상을 식별
      attributecontext node의 속성을 식별
      childcontext node의 자식 식별
      descendantcontext node의 자식을 식별하며, context node의 자식부터 말단 노드까지 나타냄
      descendant-or-selfcurrent node와 그 자식을 식별
      followingcontext node 이후의 모든 노드를 식별
      following-sibling동일한 수준에서 현재 노드 이후의 모든 형제 노드를 식별
      namespacecontext node의 namespace 식별
      parentcurrent node의 부모를 식별
      preceding-siblingcurrent node 이전의 모든 형제 노드 식별
      precedingcurrent node 이전에 오는 모든 노드 식별
      selfcontext node 식별
  • NSO 고유 기능
    • NSO CDB는 YANG 모델로 정의
    • copy-tree
      • XPath 표현식 매개변수는 복사할 소스 경로를 보여줌
    • save-context
      • 현재 context와 XPath 사용 가능 트리의 루트 노드를 저장
      • 이름이 동일할 때 저장하면 덮어씀
    • set-root-node
      • XPath 사용 가능 트리의 루트 노드를 조작
      • 전체 데이터 저장소를 취하는 XPath 컨텍스트로 평가
    • switch-context
      • 저장된 context 이름을 가져와 XPath 사용 가능 트리의 현재 및 루트 노드 변경
      • 저장소에서 context를 제거하지 않으면 여러 번 사용 가능

NSO templates에서 XPath 조건 사용

  • Yang에서의 XPath 조건
    • 데이터 검증에서 사용하는 YANG 문
      • When
        • XML 템플릿에서 사용하는 if 문과 유사
      • must
        • 항상 참으로 평가
        • 결함이 있는 서비스 입력의 서비스 적용 방지
      • 예시
        Switch Virtual Interface(SVI)서비스가 있고 장치 선택을 스위치로만 제한
        ...
        type leafref {
          path "/ncs:devices/ncs:device/ncs:name";
          }
          must "starts-with(current(),'SW')" {
          error-message "Only SW devices can be selected.";
        }
        ....
  • NSO template tag
    • XML template은 template 구현시 여러 동작 제공
    • 속성으로 태그 정의
      • merge
        • 노드가 존재하면 병합하거나 존재하지 않으면 생성
          <config tags="merge">
              <interface xmlns="urn:ios">
      • replace
        • 노드가 존재하면 교체하거나, 이미 존재하지 않으면 노드 생성
          <GigabitEthernet tags="replace">
              <name>{link/interface-number}</name>
              <description tags="merge">Link to PE</description>
      • create
        • 새 노드를 생성합니다. 이미 존재하면 오류가 발생
          <GigabitEthernet tags="create">
              <name>{link/interface-number}</name>
              <description tags="merge">Link to PE</description>
      • nocreate
        • 노드가 존재하면 병합하고, 그렇지 않으면 아무 작업도 수행하지 않음.
          <GigabitEthernet tags="nocreate">
              <name>{link/interface-number}</name>
              <description tags="merge">Link to PE</description>
      • delete
        • 원하는 노드를 삭제
          <GigabitEthernet tags="delete">
              <name>{link/interface-number}</name>
              <description tags="merge">Link to PE</description>

Template 분할하기

  • template의 재사용성을 높이기 위해 여러 template으로 나눈 뒤 Python 코드를 사용해 변수를 XML template에 매핑 가능
  • 하나로 구성된 firewall 서비스 XML template
    <config-template xmlns="http://tail-f.com/ns/config/1.0" servicepoint="firewall">
       <devices xmlns="http://tail-f.com/ns/ncs">
           <device>
               <name>{$DEVICE}</name>
               <config>
                   <logging xmlns="http://cisco.com/ned/asa">
                       <host>
                           <interface>{$LOG-INTERFACE}</interface>
                           <host>{$HOST}/host>
                       </host>
                   </logging>
                   <interface xmlns="http://cisco.com/ned/asa">
                       <allocated>
                           <name>{$INTERFACE}</name>
                           <description>{$DESCRIPTION}</description>
                           <ip>
                               <address>
                                   <ip>
                                       <host-ip>{$HOST-IP}</host-ip>
                                   </ip>
                               </address>
                           </ip>
                       </allocated>
                   </interface>
                   <ntp xmlns="http://cisco.com/ned/asa">
                       <authentication-key>
                           <id>{$ID}</id>
                           <md5>
                               <secret>{$SECRET}</secret>
                           </md5>
                       </authentication-key>
                   </ntp>
               </config>
           </device>
       </devices>
    </config-template>
    python 적용
    tvars = ncs.template.Variables()
    template = ncs.template.Template(service)
    tvars.add('DEVICE', device)
    tvars.add('LOG-INTERFACE', log_interface)
    tvars.add('HOST', host)
    ...
    template.apply('firewall', tvars)
  • template 분할 및 python 사용 예제
    • firewall-logging
      <config-template xmlns="http://tail-f.com/ns/config/1.0" servicepoint="firewall">
         <devices xmlns="http://tail-f.com/ns/ncs">
             <device>
                 <name>{$DEVICE}</name>
                 <config>
                     <logging xmlns="http://cisco.com/ned/asa">
                         <host>
                             <interface>{$LOG-INTERFACE}</interface>
                             <host>{$HOST}</host>
                         </host>
                     </logging>
                 </config>
             </device>
         </devices>
      </config-template>
    • firewall-interface
      <config-template xmlns="http://tail-f.com/ns/config/1.0" servicepoint="firewall">
          <devices xmlns="http://tail-f.com/ns/ncs">
              <device>
                  <name>{$DEVICE}</name>
                  <config>
                      <interface xmlns="http://cisco.com/ned/asa">
                          <allocated>
                              <name>{$INTERFACE}</name>
                              <description>{$DESCRIPTION}</description>
                              <ip>
                                  <address>
                                      <ip>
                                          <host-ip>{$HOST-IP}</host-ip>
                                      </ip>
                                  </address>
                              </ip>
                          </allocated>
                      </interface>
                  </config>
              </device>
          </devices>
      </config-template>
    • firewall-ntp
      <config-template xmlns="http://tail-f.com/ns/config/1.0" servicepoint="firewall">
          <devices xmlns="http://tail-f.com/ns/ncs">
              <device>
                  <name>{$DEVICE}</name>
                  <config>
                      <interface xmlns="http://cisco.com/ned/asa">
                          <allocated>
                              <name>{$INTERFACE}</name>
                              <description>{$DESCRIPTION}</description>
                              <ip>
                                  <address>
                                      <ip>
                                          <host-ip>{$HOST-IP}</host-ip>
                                      </ip>
                                  </address>
                              </ip>
                          </allocated>
                      </interface>
                  </config>
              </device>
          </devices>
      </config-template>
    • python
      tvars = ncs.template.Variables()
      template = ncs.template.Template(service)
      tvars.add('DEVICE', device)
      tvars.add('LOG-INTERFACE', log_interface)
      tvars.add('HOST', host)
      
      ...
      template.apply('firewall-logging', tvars)
      template.apply('firewall-interface', tvars)
      template.apply('firewall-ntp', tvars)