Python: Yang Model を XML / JSON 形式へ変換

今回は Yang Model を Python で XML / JSON へ変換する方法を紹介したいと思います。Yang Model を使って Netconf 等でネットワーク機器を操作したり、情報を取ったりというのが流行りですが、Python のスクリプト内でも Yang Model のデータを扱うために XML や JSON へ変換したい場合があったので、試してみました。

Yang Model を Git でゲットする

まずは Linux 上で Git を使って Yang Model のレポジトリをクローンして Yang Model をゲットします。

virl@virl:~$ mkdir yang
virl@virl:~$ cd yang
virl@virl:~/yang$ git clone https://github.com/YangModels/yang.git
Cloning into 'yang'...
remote: Counting objects: 7043, done.
remote: Compressing objects: 100% (20/20), done.
remote: Total 7043 (delta 4), reused 9 (delta 3), pack-reused 7020
Receiving objects: 100% (7043/7043), 14.24 MiB | 4.76 MiB/s, done.
Resolving deltas: 100% (4213/4213), done.
Checking connectivity... done.
Checking out files: 100% (5945/5945), done.
virl@virl:~/yang$ 

すると yang ディレクトリが作成され、その配下にファイルができたことが確認できます。

virl@virl:~/yang$ cd yang
virl@virl:~/yang/yang$ ls
experimental  README.md  standard  tools  vendor

まずは Yang Model を XML へ変換する

今回はまだドラフトですが、日本では人気のない IS-IS の Yang Model を変換してみたいと思います。まずはファイルがある場所へ移動します。

(test_3.6.1) virl@virl:~/yang/yang$ cd standard/ietf/DRAFT/

pyang を使って XML へ変換します。pyang をまだインストールしていない場合は、pip でインストールします。

(test_3.6.1) virl@virl:~/yang/yang/standard/ietf/DRAFT$ pip install pyang
Collecting pyang
  Downloading pyang-1.7.2-py2.py3-none-any.whl (322kB)
    100% |████████████████████████████████| 327kB 2.6MB/s
Installing collected packages: pyang
Successfully installed pyang-1.7.2

pyang の -f yin オプションを使って XML 変換します。warning や error も出てますが、とりあえず無視します。

(test_3.6.1) virl@virl:~/yang/yang/standard/ietf/DRAFT$ pyang -f yin ietf-isis.yang                               ietf-isis.yang:97: error: ietf-routing:routing-instance in the path for routing-protocol-instance-name at ietf-isiang:1551 is not found
ietf-isis.yang:97: error: ietf-routing:routing-instance in the path for routing-protocol-instance-name at ietf-isiang:1614 is not found
ietf-isis.yang:97: error: ietf-routing:routing-instance in the path for isis-instance-state-ref at ietf-isis.yang:is not found
ietf-isis.yang:129: warning: the escape sequence "\." is unsafe in double quoted strings - pass the flag --lax-quochecks to avoid this warning
ietf-isis.yang:138: warning: the escape sequence "\." is unsafe in double quoted strings - pass the flag --lax-quochecks to avoid this warning
ietf-isis.yang:139: warning: the escape sequence "\." is unsafe in double quoted strings - pass the flag --lax-quochecks to avoid this warning
ietf-isis.yang:150: warning: the escape sequence "\." is unsafe in double quoted strings - pass the flag --lax-quochecks to avoid this warning
ietf-isis.yang:241: error: node ietf-routing::active-route is not found
ietf-isis.yang:1037: error: node ietf-routing::routing-instance is not found
ietf-isis.yang:1148: error: ietf-routing:routing-instance in the path for name at ietf-isis.yang:1145 is not found
ietf-isis.yang:1255: error: node ietf-routing::routing-instance is not found
ietf-isis.yang:1538: error: type "routing-instance-state-ref" not found in module ietf-routing
ietf-isis.yang:1601: error: type "routing-instance-state-ref" not found in module ietf-routing
<?xml version="1.0" encoding="UTF-8"?>
<module name="ietf-isis"
        xmlns="urn:ietf:params:xml:ns:yang:yin:1"
        xmlns:isis="urn:ietf:params:xml:ns:yang:ietf-isis"
        xmlns:rt="urn:ietf:params:xml:ns:yang:ietf-routing"
        xmlns:inet="urn:ietf:params:xml:ns:yang:ietf-inet-types"
        xmlns:yang="urn:ietf:params:xml:ns:yang:ietf-yang-types">
  <namespace uri="urn:ietf:params:xml:ns:yang:ietf-isis"/>
  <prefix value="isis"/>
  <import module="ietf-routing">
    <prefix value="rt"/>
  </import>
  <import module="ietf-inet-types">
(snip)

実際には下記のようにリダイレクトしてファイルへ保存します。

(test_3.6.1) virl@virl:~/yang/yang/standard/ietf/DRAFT$ pyang -f yin ietf-isis.yang > ietf-isis.xml

以上で Yang Model -> XML への変換は完了です。

次は XML -> JSON 変換

先ほど保存した XML 形式のファイルを使って JSON 形式へ変換します。xmltodict と json というライブラリを使って、下記のような簡単なスクリプトで JSON 形式へ変換が可能です。

> cat xmltojson.py 
import json
import xmltodict

with open('ietf-isis.xml') as f:
	a = xmltodict.parse(f.read())
	print(json.dumps(a,indent=2))

実行した結果は下記のようになり、JSON 形式になっていることが確認できます。

> python xmltojson.py 
{
  "module": {
    "@name": "ietf-isis",
    "@xmlns": "urn:ietf:params:xml:ns:yang:yin:1",
    "@xmlns:isis": "urn:ietf:params:xml:ns:yang:ietf-isis",
    "@xmlns:inet": "urn:ietf:params:xml:ns:yang:ietf-inet-types",
    "@xmlns:yang": "urn:ietf:params:xml:ns:yang:ietf-yang-types",
    "namespace": {
      "@uri": "urn:ietf:params:xml:ns:yang:ietf-isis"
    },
    "prefix": {
      "@value": "isis"
    },
    "import": [
      {
        "@module": "ietf-routing",
        "prefix": {
          "@value": "rt"
        }
      },
      {
        "@module": "ietf-inet-types",
        "prefix": {
          "@value": "inet"
        }
      },
      {
        "@module": "ietf-yang-types",
        "prefix": {
          "@value": "yang"
        }
      }
    ],
    "organization": {
      "text": "IETF ISIS Working Group"
    },
    "contact": {
      "text": "WG List:   <mailto:isis-wg@ietf.org>\n\nEditor:     Stephane Litkowski\n           <mailto:stephane.litkowski@orange.com>"
    },
    "description": {
      "text": "The YANG module defines a generic configuration model for ISIS\ncommon across all of the vendor implementations."
    },
    "revision": [
      {
        "@date": "2014-06-20",
        "description": {
          "text": "* isis-op renamed to isis-state.\n* Multiple instances under isis are removed.\n* interface-cfg grouping removed and content\nis directly included in container isis.\n* TLVxx renamed with human-readable name in isis-database.\nTLV reference are putted in description.\n* Reference to core routing module were fixed.\n* Namespace fixed.\n* Add simple-iso-address type.\n* area-id and system-id in isis container are merged to\nnsap-address.\n* Add isis-system-id type.\n* Add isis-lsp-id type.\n* Add remaining-lifetime leaf in isis-database.\n* Add TLV2 (is-neighbor) in isis-database.\n* Renamed some container name for consistency\nreason ('isis-' prefixed).\n* Add new identities isis-cfg and isis-state.\n* Add descriptions.\n* Add notification isis-adjacency-updown.\n* Add RPC clear-isis-adjacency and clear-isis-database."
        },
        "reference": {
          "text": "draft-litkowski-isis-yang-isis-00"
        }
      },
(snip)

以上が Yang Model -> XML -> JSON 変換でした。

スポンサーリンク