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