今回は 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 変換でした。