03-17-2022 07:48 AM - edited 03-17-2022 07:49 AM
Hello everyone,
I'm trying to convert a Juniper vendor-specific XML configuration using CodecService encode and decode API. Juniper yang models have been generated and installed however the code is failing with an error:
Traceback (most recent call last): File "convert.py", line 69, in <module> print(yang_xml_to_json(ARGS['xml_file'])) File "convert.py", line 58, in yang_xml_to_json decoded_xml_yang = CODEC.decode(XML_PROVIDER, config_xml_yang) File "/opt/neteng/lib/python3.6/site-packages/ydk/errors/error_handler.py", line 112, in helper return func(self, provider, entity, *args, **kwargs) File "/opt/neteng/lib/python3.6/site-packages/ydk/services/codec_service.py", line 130, in decode entity = self.decode(provider, payload_holder[key], subtree) File "/opt/neteng/lib/python3.6/site-packages/ydk/errors/error_handler.py", line 112, in helper return func(self, provider, entity, *args, **kwargs) File "/opt/neteng/lib/python3.6/site-packages/ydk/services/codec_service.py", line 130, in decode entity = self.decode(provider, payload_holder[key], subtree) File "/opt/neteng/lib/python3.6/site-packages/ydk/errors/error_handler.py", line 112, in helper return func(self, provider, entity, *args, **kwargs) File "/opt/neteng/lib/python3.6/site-packages/ydk/services/codec_service.py", line 140, in decode return self._decode(provider, payload_holder, subtree) File "/opt/neteng/lib/python3.6/site-packages/ydk/services/codec_service.py", line 158, in _decode entity = _payload_to_top_entity(payload, provider.encoding) File "/opt/neteng/lib/python3.6/site-packages/ydk/entity_utils/entity_utils.py", line 117, in _payload_to_top_entity raise YModelError("Could not retrieve namespace and container name") ydk.errors.YModelError: Could not retrieve namespace and container name
pip freeze | grep ydk ydk==0.8.4 ydk-models-ietf==0.1.5.post2 ydk-models-junos-18-4==18.4.post3 ydk-models-openconfig==0.1.8
Code is the following:
import argparse import json import yaml import xmltodict from ydk.providers import CodecServiceProvider from ydk.services import CodecService codec = CodecService() JSON_PROVIDER = CodecServiceProvider(type='json') XML_PROVIDER = CodecServiceProvider(type='xml') def yang_xml_to_json (xml_file): with open(xml_file, "rb") as f: config_xml_yang = xmltodict.parse(f, xml_attribs=True) decoded_xml_yang = codec.decode(XML_PROVIDER, config_xml_yang) yang_json = code.encode(JSON_PROVIDER, decoded_xml_yang) return yang_json
I am using the XML output from the YDK conversion: (YAML) -> JSON -> XML -> JSON -> (YAML)
Thanks in advance for any suggestion or input,
Luca
Solved! Go to Solution.
03-18-2022 08:25 AM
Hi Luka
I am happy to hear that it worked for your purposes. To use the Juniper bundle in import statements I suggest you to run command 'pip list | grep ydk' and check how the bundle package is referred to. What is related to the codec operations, you do not need to have a model referral although model bundle installation is needed. The codec is smart enough to search for the bundle in the YDK installation directories. You just have to include the top level container/list into your XML/JSON string.
03-17-2022 08:43 AM
Hi Luca
I do not understand, why do you need convert XML to a dictionary, especially since the YDK does not support conversion from/to a dictionary?
with open(xml_file, "rb") as f: config_xml_yang = xmltodict.parse(f, xml_attribs=True)
You need simply read XML file to a string and give it to the codec:
with open(xml_file, "rb") as f: config_xml = f(read)
decoded_entity = codec.decode(XML_PROVIDER, config_xml)
config_json = codec.encode(JSON_PROVIDER, decoded_entity)
Yan Gorelik
03-17-2022 09:01 AM
Thank you for detailed informations. This code below was solved my problem too.
with open(xml_file, "rb") as f: config_xml = f(read)
decoded_entity = codec.decode(XML_PROVIDER, config_xml)
config_json = codec.encode(JSON_PROVIDER, decoded_entity)
03-17-2022 06:36 PM
Hi Yan,
Thank you, this worked for the openconfig models. I am getting "ydk.errors.YModelError: No YDK bundle installed for node path 'http://yang.juniper.net/junos/conf/interfaces:interfaces'" when decoding a simple interfaces section Juniper specific. I have generated the bundle via ydg-gen command "./generate.py --python --bundle profiles/bundles/juniper-junos_18_4_R3.json" which included all the modules under 18.4R4 and installed (see my previous notes - bundle name ydk-models-junos-18-4==18.4.post3). Is there any specific way to refer to it?
Thank you,
Luca
{ "name": "junos-18_4", "version": "18.4R3", "core_version": "0.8.4", "author": "", "copyright": "", "description": "JunOS 18.4 Yang Model", "long_description": "JunOS 18.4 Yang Model", "models": { "description": "JunOS 18.4 Yang Model", "git": [ { "url": "https://github.com/Juniper/yang.git", "commits": [ { "dir": [ "18.4/18.4R3/common", "18.4/18.4R3/junos/conf", "18.4/18.4R3/junos/conf-with-extensions" ] } ] } ] } }
<interfaces xmlns="http://yang.juniper.net/junos/conf/interfaces"> <interface> <name>xe-2/0/0</name> <description>Test</description> <unit> <name>0</name> <family> <inet> <address> <name>1.1.1.1/30</name> </address> </inet> </family> </unit> </interface> </interfaces>
03-18-2022 08:25 AM
Hi Luka
I am happy to hear that it worked for your purposes. To use the Juniper bundle in import statements I suggest you to run command 'pip list | grep ydk' and check how the bundle package is referred to. What is related to the codec operations, you do not need to have a model referral although model bundle installation is needed. The codec is smart enough to search for the bundle in the YDK installation directories. You just have to include the top level container/list into your XML/JSON string.
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide