NETCONFプロキシ

NETCONFプロキシサービスは、ネットワーク機器に対するNETCONF制御をAPI化する機能を提供しています。送信するXMLは、Jinja2テンプレート形式で記述することができます。 テンプレートへのレンダリングパラメータは、実行時に与えることができます。

NETCONFプロキシの定義項目

category: NETCONFプロキシのカテゴリを指定します。カテゴリは単なるラベルです。

name: NETCONFプロキシの名前を指定します。ユニークである必要があります。

path: NETCONFプロキシが生成するAPI待ち受けパスを指定します。ユニークである必要があります。自動生成されるAPIは全てPATCHメソッドのみを受け付けます。

async: NETCONFプロキシが生成するAPIの非同期モードを指定します。Trueの場合、APIを要求した場合は、NETCONFプロキシを起動するlambdaイベントを発行してイベントIDを応答します。Falseの場合、lambdaイベントの発行後、イベント収束まで待ち合わせて処理結果を応答します。

action: NETCONFの制御情報を指定します。action種別としてget-configedit-configをサポートしています。

action.get-config.source: コンフィグを取得する対象となるデータストアを指定します。candidate running startupのいづれかを指定します。

action.get-config.subtree: サブツリーフィルタを指定します。

action.get-config.parameter_bindings: デバイスから取得したコンフィグ情報からパラメータを導出する処理を記述する定義ブロックです。

action.get-config.parameter_bindings.name: 導出するパラメータの変数名を指定します。

action.get-config.parameter_bindings.xpath: 導出するパラメータに代入するための値としてデバイスの応答からテキストを抜き出すxpathを指定します。

action.get-config.parameter_bindings.script: 導出するパラメータに代入するための値としてデバイスの応答からテキストを抜き出すカスタムスクリプトを記述します。カスタムスクリプトの実行空間には、デバイスの応答メッセージが代入されたoutput変数が格納されています。output変数を参照してカスタムスクリプトで生成した値をv変数に代入するとaction.get-config.parameter_bindings.nameで指定したbindings辞書のパラメータに値がセットされます。

action.edit-config.template: コンフィグテンプレートを記述します。

aop: NETCONFプロキシの実行前後に実行したい同期型のカスタムスクリプトを埋め込むことができるオプションです。

aop.pre: NETCONFプロキシの実行前に実行するカスタムスクリプトを記述します。NETCONFプロキシの実行前にbindings情報を加工したり、新たなbindingsパラメータを生成することができます。カスタムスクリプトの実行空間には、開始時点のbinginsパラメータがデフォルトでセットされています。

aop.post: NETCONFプロキシの実行後に実行するカスタムスクリプトを記述します。NETCONFプロキシの実行によって確定した最終的なbindings情報を加工したり、新たなbindingsパラメータを生成することができます。カスタムスクリプトの実行空間には、bindingsパラメータがデフォルトでセットされています。


チュートリアル

はじめてのNETCONFプロキシ

Cisco CSR1000vにNETCONF接続してバージョン情報を取得するサンプルです。 parameter_bindingsでは、xpathでバージョン番号だけを抜き出してversion変数に代入しています。

- name: getVersion
  path: /getVersion
  action:
    parameter_bindings:
      - name: version
        xpath: './/{*}version/{*}Param'
    source: running
    subtree: <config-format-xml/>

Warning

Netconfの応答XMLは、名前空間が設定されています。xpathでエレメントを抽出する場合は名前空間を指定する必要があります。
Qmonus SDKでは、lxmlライブラリを使用しており、NETCONFプロキシで指定したxpathは、lxmlライブラリのfindメソッドに渡されます。
findメソッドでは、名前空間を{名前空間}で指定することができます。この例では、ワイルドカード指定で名前空間を省略していますが、.//{urn:cisco:xml-pi}version/{urn:cisco:xml-pi}Paramと記述することで厳格な指定もできます。


NETCONFプロキシを実行するためには、Deviceオブジェクトが必要です。Docs » Lambda » CLIプロキシでも解説していますので参考にしてください。ここではDeviceオブジェクトが既に存在することを前提に説明しています。実行する方法は、NetconfProxy組込みオブジェクトを利用する方法と生成されたAPIをリクエストする方法の2種類が提供されます。 まずは、NetconfProxy組込みオブジェクトを利用して実行してみましょう。NetconfProxy組込みオブジェクトの使用方法は、Docs » リファレンス » ビルトインオブジェクトにも記載していますので参考にしてください。

>>> p = await NetconfProxy.load("getVersion")↵
... r = await p.run("csr1000v")↵
... print(r.bindings.version)↵
... ↵
↵
15.5
>>> print(r.yaml_format)↵
... ↵
↵
bindings:
  version: '15.5'
log: null
message: null
responses:
- |-
  <?xml version="1.0" encoding="UTF-8"?><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><xml-config-data><Device-Configuration xmlns="urn:cisco:xml-pi">
  <version><Param>15.5</Param></version>
  <service><timestamps><debug><datetime><msec/></datetime></debug></timestamps></service>
  <service><timestamps><log><datetime><msec/></datetime></log></timestamps></service>
  <platform operation="delete"><punt-keepalive><disable-kernel-core/></punt-keepalive></platform>
  <platform><console><auto/></console></platform>
  <hostname><SystemNetworkName>csr1000v</SystemNetworkName></hostname>
  <boot-start-marker/>
  <boot-end-marker/>
  <enable><secret><_5><EncryptedEnableSecretString>$1$mRd1$j3Bahth4A41LK4AZkbbuL.</EncryptedEnableSecretString></_5></secret></enable>
  <aaa operation="delete"><new-model/></aaa>
  <ip><domain><name><DefaultDomainName>ftth.ucom.ne.jp</DefaultDomainName></name></domain></ip>
  <subscriber><templating/></subscriber>
  <multilink><bundle-name><authenticated/></bundle-name></multilink>
  <license><udi><pid><PidString>CSR1000V</PidString><sn><SnString>9MO3W5YB3YU</SnString></sn></pid></udi></license>
  <license><boot><level><ax/></level></boot></license>
  <spanning-tree><extend><system-id/></extend></spanning-tree>
  <username><UserName>qmonus</UserName><privilege><UserPrivilegeLevel>15</UserPrivilegeLevel><secret><_5><HiddenUserSecretString>$1$WYlL$Acuu1HOExDC2nNG8LSpHT1</HiddenUserSecretString></_5></secret></privilege></username>
  <username><UserName>ncclient</UserName><privilege><UserPrivilegeLevel>15</UserPrivilegeLevel><password><_0><UnencryptedUserPassword>ncclient</UnencryptedUserPassword></_0></password></privilege></username>
  <redundancy>
  <ConfigRed-Configuration>
  </ConfigRed-Configuration>
  </redundancy>
  <interface><Param>GigabitEthernet1</Param>
  <ConfigIf-Configuration>
  <ip><address><IPAddress>192.168.2.200</IPAddress><IPSubnetMask>255.255.255.0</IPSubnetMask></address></ip>
  <negotiation><auto/></negotiation>
  </ConfigIf-Configuration>
  </interface>
  <interface><Param>GigabitEthernet2</Param>
  <ConfigIf-Configuration>
  <ip operation="delete"><address/></ip>
  <shutdown/>
  <negotiation><auto/></negotiation>
  </ConfigIf-Configuration>
  </interface>
  <interface><Param>GigabitEthernet3</Param>
  <ConfigIf-Configuration>
  <ip><address><IPAddress>172.16.100.1</IPAddress><IPSubnetMask>255.255.255.0</IPSubnetMask></address></ip>
  <negotiation><auto/></negotiation>
  </ConfigIf-Configuration>
  </interface>
  <interface><Param>GigabitEthernet3.23</Param>
  <ConfigSubif-Configuration>
  <encapsulation><dot1Q><IEEEVLANIDRequired>23</IEEEVLANIDRequired></dot1Q></encapsulation>
  <ip><address><IPAddress>172.16.23.1</IPAddress><IPSubnetMask>255.255.255.0</IPSubnetMask></address></ip>
  </ConfigSubif-Configuration>
  </interface>
  <interface><Param>GigabitEthernet3.24</Param>
  <ConfigSubif-Configuration>
  <encapsulation><dot1Q><IEEEVLANIDRequired>24</IEEEVLANIDRequired></dot1Q></encapsulation>
  <ip><address><IPAddress>172.16.24.1</IPAddress><IPSubnetMask>255.255.255.0</IPSubnetMask></address></ip>
  </ConfigSubif-Configuration>
  </interface>
  <interface><Param>GigabitEthernet3.30</Param>
  <ConfigSubif-Configuration>
  <encapsulation><dot1Q><IEEEVLANIDRequired>30</IEEEVLANIDRequired></dot1Q></encapsulation>
  <ip><address><IPAddress>172.16.30.1</IPAddress><IPSubnetMask>255.255.255.0</IPSubnetMask></address></ip>
  </ConfigSubif-Configuration>
  </interface>
  <virtual-service><VirtualServiceNameUpTo63Characters>csr_mgmt</VirtualServiceNameUpTo63Characters>
  <ConfigVirtServ-Configuration>
  </ConfigVirtServ-Configuration>
  </virtual-service>
  <ip><forward-protocol><nd/></forward-protocol></ip>
  <ip operation="delete"><http><server/></http></ip>
  <ip><http><secure-server/></http></ip>
  <snmp-server><community><SNMPCommunityString>public</SNMPCommunityString><ro/></community></snmp-server>
  <control-plane/>
  <line><LineNumber>con 0</LineNumber>
  <ConfigLine-Configuration>
  <X-Interface> login local</X-Interface>
  </ConfigLine-Configuration>
  </line>
  <line><LineNumber>vty 0 4</LineNumber>
  <ConfigLine-Configuration>
  <X-Interface> login local</X-Interface>
  </ConfigLine-Configuration>
  </line>
  <netconf><ssh/></netconf>
  <end/>
  </Device-Configuration></xml-config-data></data>
status: Complete
>>>


NETCONFプロキシによるコンフィグ例

VLAN設定のサンプルです。VLAN番号は引数で指定できるようにします。

- name: setVlan
  path: /setVlan
  action:
    template: |-
      <config>
        <cli-config-data>
          <cmd>interface gigabitEthernet 3.{{ vlan }}</cmd>
          <cmd>encapsulation dot1Q {{ vlan }}</cmd>
          <cmd>ip address 172.16.{{ vlan }}.1 255.255.255.0</cmd>
          <cmd>no shutdown</cmd>
        </cli-config-data>
      </config>


実行時にVLAN番号をparams引数で渡すことができます。

>>> p = await NetconfProxy.load("setVlan")↵
... r = await p.run("csr1000v", params={"vlan": 30})↵
... print(r.yaml_format)↵
... ↵
↵
bindings:
  vlan: 30
log: |-
  <config>
    <cli-config-data>
      <cmd>interface gigabitEthernet 3.30</cmd>
      <cmd>encapsulation dot1Q 30</cmd>
      <cmd>ip address 172.16.30.1 255.255.255.0</cmd>
      <cmd>no shutdown</cmd>
    </cli-config-data>
  </config>
message: null
responses:
- <?xml version="1.0" encoding="UTF-8"?><rpc-reply message-id="urn:uuid:6e4cfa90-d794-4db4-af0a-fb82c7088a5d"
  xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><ok /></rpc-reply>
status: Complete
>>>


Warning

NETCONFプロキシでedit-configを実行する場合、対象機器のcapabilitiesによって動作が異なる点に注意してください。
candidateがサポートされている場合は以下のシーケンスが実行されます。
1. discard-changes
2. lock(target=candidate)
3. edit-config(target=candidate): エラー受信時はdiscard-changesを送信して終了
4. commit(confirmed=False): エラー受信時はdiscard-changesを送信して終了
6. unlock(target=candidate)
candidateがサポートされていない場合は以下のシーケンスが実行されます。
1. lock(target=running)
2. edit-config(target=running)
3. copy-config(source=running, target=startup)
4. unlock(target=candidate)