cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
613
Views
10
Helpful
3
Replies

Including NETCONF "operation" parameter in CodecService output

Jason Shoemaker
Cisco Employee
Cisco Employee

Hi folks,

 

I'm looking for a way to generate NETCONF XML payload for an edit-config operation without actually performing a CRUD execution against an actual device.  The CodecService seems to be intended for this, but I can't seem make use of YFilter settings for my entity containers when using CodecService.  For example...

 

from ydk.services import CodecService
from ydk.providers import CodecServiceProvider
from ydk.filters import YFilter
from ydk.models.cisco_ios_xe import Cisco_IOS_XE_native \
    as xe_native

provider = CodecServiceProvider(type="xml")
codec = CodecService()
native = xe_native.Native()

vlan = native.Vlan()
vlan.yfilter = YFilter.replace

vlan_list_inst = vlan.VlanList()
vlan_list_inst.id = 100
vlan_list_inst.name = "TEST_VLAN"
vlan.vlan_list.append(vlan_list_inst)

native.vlan = vlan

print(codec.encode(provider, native))

In the above Python script, I've set vlan.yfilter to "YFilter.replace" with the goal of replacing all of the configuration in the "vlan" portion of my configuration with the single VLAN that I've created.  The expectation is that this would generate the following XML...

 

<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
  <vlan operation="replace">
    <vlan-list xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-vlan">
      <id>100</id>
      <name>TEST_VLAN</name>
    </vlan-list>
  </vlan>
</native>

Instead, I get an error generated, which I assume is the result of CodeService not supporting certain yfilter values...

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/ydk/errors/error_handler.py", line 112, in helper
    return func(self, provider, entity, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/ydk/services/codec_service.py", line 78, in encode
    return self._encode(provider, entity_holder, pretty, subtree)
  File "/usr/local/lib/python2.7/dist-packages/ydk/services/codec_service.py", line 110, in _encode
    return result
  File "/usr/lib/python2.7/contextlib.py", line 35, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/local/lib/python2.7/dist-packages/ydk/errors/error_handler.py", line 82, in handle_runtime_error
    _raise(_exc)
  File "/usr/local/lib/python2.7/dist-packages/ydk/errors/error_handler.py", line 56, in _raise
    raise exc
ydk.errors.YInvalidArgumentError:  Cannot find module with given namespace.

Is there any way to generate the above XML as desired?  If CodecService can't do it, I'd be happy to entertain using CRUDService assuming there's a way I can setup a dummy device and capture the XML output that would have been sent to it.

 

If you're curious about the use case, we're generating NETCONF XML output for planned config changes so that it can be posted to a Git repository for peer review before implementing the actual changes.

 

Thanks for your help!

1 Accepted Solution

Accepted Solutions

yangorelik
Spotlight
Spotlight

Hello Jason

There are two issues:

1. Your vlan model is incorrect. Here is how it should be:

from ydk.models.cisco_ios_xe import Cisco_IOS_XE_native as xe_native

native = xe_native.Native()
vlan = native.vlan # vlan instance is already present in native

vlan_list_inst = vlan.VlanList()
vlan_list_inst.id = 100
vlan_list_inst.name = "TEST_VLAN"
vlan.vlan_list.append(vlan_list_inst)

2. The CodecService is not suitable for building XML payload with defined filters. The CradService adInstead you can use XmlSubtreeCodec from ydk.entity_utils package:

from ydk.entity_utils import XmlSubtreeCodec
from ydk.providers import CodecServiceProvider, NetconfServiceProvider
from ydk.filters import YFilter
from ydk.models.cisco_ios_xe import Cisco_IOS_XE_native as xe_native

provider = CodecServiceProvider(type='xml')
provider.initialize('cisco_ios_xe', '/Users/ygorelik/ydk-gen/venv/lib/python3.7/site-packages/ydk/models/cisco_ios_xe/_yang')
root_schema = provider.get_root_schema('cisco_ios_xe')

xml_codec = XmlSubtreeCodec()

native = xe_native.Native()
vlan = native.vlan
vlan_list_inst = vlan.VlanList()
vlan_list_inst.id = 100
vlan_list_inst.name = "TEST_VLAN"
vlan.vlan_list.append(vlan_list_inst)

vlan.yfilter = YFilter.replace

xml = xml_codec.encode(native, root_schema)
print(xml)

The result of this script seems what you are looking for:

<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
  <vlan operation="replace">
    <vlan-list xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-vlan">
      <id>100</id>
      <name>TEST_VLAN</name>
    </vlan-list>
  </vlan>
</native>

Please note that XmlSubtreeCodec does not validate the entity against YANG models and it requires to provide root schema (extra step in provider initialization).

Yan Gorelik
YDK Solutions

View solution in original post

3 Replies 3

yangorelik
Spotlight
Spotlight

Hello Jason

There are two issues:

1. Your vlan model is incorrect. Here is how it should be:

from ydk.models.cisco_ios_xe import Cisco_IOS_XE_native as xe_native

native = xe_native.Native()
vlan = native.vlan # vlan instance is already present in native

vlan_list_inst = vlan.VlanList()
vlan_list_inst.id = 100
vlan_list_inst.name = "TEST_VLAN"
vlan.vlan_list.append(vlan_list_inst)

2. The CodecService is not suitable for building XML payload with defined filters. The CradService adInstead you can use XmlSubtreeCodec from ydk.entity_utils package:

from ydk.entity_utils import XmlSubtreeCodec
from ydk.providers import CodecServiceProvider, NetconfServiceProvider
from ydk.filters import YFilter
from ydk.models.cisco_ios_xe import Cisco_IOS_XE_native as xe_native

provider = CodecServiceProvider(type='xml')
provider.initialize('cisco_ios_xe', '/Users/ygorelik/ydk-gen/venv/lib/python3.7/site-packages/ydk/models/cisco_ios_xe/_yang')
root_schema = provider.get_root_schema('cisco_ios_xe')

xml_codec = XmlSubtreeCodec()

native = xe_native.Native()
vlan = native.vlan
vlan_list_inst = vlan.VlanList()
vlan_list_inst.id = 100
vlan_list_inst.name = "TEST_VLAN"
vlan.vlan_list.append(vlan_list_inst)

vlan.yfilter = YFilter.replace

xml = xml_codec.encode(native, root_schema)
print(xml)

The result of this script seems what you are looking for:

<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
  <vlan operation="replace">
    <vlan-list xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-vlan">
      <id>100</id>
      <name>TEST_VLAN</name>
    </vlan-list>
  </vlan>
</native>

Please note that XmlSubtreeCodec does not validate the entity against YANG models and it requires to provide root schema (extra step in provider initialization).

Yan Gorelik
YDK Solutions

Hey Yan - thanks for the quick reply!  I followed the steps you shared and was able to generate the desired configuration.

A few follow-up questions and comments...

In your code, you referenced the absolute directory of your cisco_ios_xe package in provider.initialize().  I wanted to be able to retrieve the relative directory of the cisco_ios_xe package for portability of this code, so I did the following:

import ydk.models.cisco_ios_xe as xe
<code removed for brevity> provider.initialize('cisco_ios_xe', xe.__path__[0] + '/_yang')

This seems to work for me.  However, if there's an better way to capture this path that you're aware of (e.g. a solution that doesn't require actually importing the full cisco_ios_xe package), please let me know.

You commented that one of the key limitations here is that XMLSubtreeCodec does not validate the entity against YANG models.  I was under the impression that this validation was implicit when modifying properties of the entity (e.g. if I try to assign an invalid data type to a leaf of an entity, an error would be generated during the assignment action).  Is there an additional level of validation that typically occurs during the XML generation?

Depending upon the answer to the above question, I also wanted to get your thoughts on how I might be able to validate the entity against YANG models outside of the XML generation.  e.g. Is there a validation method that I could run against my entity prior to calling the XMLSubtreeCodec for XML generation such that I could still have the benefit of YANG model verification?

Thanks for all of your help,

Jason

 

Hi Jason

Your improvement of the script to find path to repository is definitely better than specifying absolute path. But more accurate solution, which works in Python 2 and 3, would be:

from ydk.models.cisco_ios_xe import Cisco_IOS_XE_native as xe_native
import os

provider = CodecServiceProvider(type='xml')
provider.initialize('cisco_ios_xe',
os.path.join(os.path.dirname(xe_native.__file__), '_yang'))

Regarding validation. If this is critical, then I would suggest first to use CodecService on entity without setting operation filters (that will validate the entity structure and leaves' values), then add filters and repeat encoding with XmlSubtreeCodec.

Yan Gorelik
YDK Solutions