06-26-2019 11:45 AM - edited 06-26-2019 11:46 AM
Hello Community,
I brought the last set of ACL sample apps for basic level ydk-py.
You can encode OpenConfig ACL configurations with this set of sample applications.
cd-encode-oc-acl-10-ydk.py - encode boilerplate cd-encode-oc-acl-30-ydk.py - allow one host cd-encode-oc-acl-32-ydk.py - allow multiple hosts cd-encode-oc-acl-34-ydk.py - multiple hosts w/ codepoint
Using the following link, you can also get into the parent directory of the provided sample applications:
In order to run any encoding sample applications, you don't need to access to server, but you can simply run the application in Terminal as follows:
./cd-encode-oc-acl-30-ydk.py
Now, we have three sets of OpenConfig ACL sample applications.
If you did not check out the previous ACL sample app posts yet, please visit the following links to get more information:
ACL Sample apps with OpenConfig/NETCONF
ACL Sample apps with OpenConfig/gNMI
Cheers!
10-18-2019 03:27 AM
Hello.
I've tried to generate XML config using examples provided but it failes with the following exception:
python3 acl2.py 2019-10-18 13:22:47,441 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Value "173.31.1.0/24" does not satisfy the constraint "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))$" (range, length, or pattern). Path: '/openconfig-acl:acl/acl-sets/acl-set[name='ACL3'][type='openconfig-acl:ACL_IPV4']/acl-entries/acl-entry[sequence-id='20']/ipv4/config/source-address' Traceback (most recent call last): File "acl2.py", line 92, in <module> main() File "acl2.py", line 84, in main print(codec.encode(provider, acl)) File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 112, in helper return func(self, provider, entity, *args, **kwargs) File "/usr/local/lib/python3.6/dist-packages/ydk/services/codec_service.py", line 78, in encode return self._encode(provider, entity_holder, pretty, subtree) File "/usr/local/lib/python3.6/dist-packages/ydk/services/codec_service.py", line 110, in _encode return result File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__ self.gen.throw(type, value, traceback) File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 82, in handle_runtime_error _raise(_exc) File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 54, in _raise exec("raise exc from None") File "<string>", line 1, in <module> ydk.errors.YModelError: Value "173.31.1.0/24" does not satisfy the constraint "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))$" (range, length, or pattern). Path: /openconfig-acl:acl/acl-sets/acl-set[name='ACL3'][type='openconfig-acl:ACL_IPV4']/acl-entries/acl-entry[sequence-id='20']/ipv4/config/source-address
The script is:
import logging from ydk.services import CodecService, CRUDService from ydk.providers import CodecServiceProvider, NetconfServiceProvider from ydk.models.openconfig import openconfig_acl as oc_acl DEVICES = ['10.10.40.4', '10.10.30.5', '10.10.30.6'] def config_acl(acl): """Add config data to acl object.""" # acl-set configuration acl_set = acl.AclSets.AclSet() acl_set.name = "ACL3" acl_set.type = oc_acl.ACLIPV4() acl_set.config.name = "ACL3" acl_set.config.type = oc_acl.ACLIPV4() acl_set.acl_entries = acl_set.AclEntries() # acl-entry with sequence number 10 acl_entry = acl_set.acl_entries.AclEntry() acl_entry.sequence_id = 10 acl_entry.config.sequence_id = 10 acl_set.acl_entries.acl_entry.append(acl_entry) # acl-entry with sequence number 20 acl_entry = acl_set.acl_entries.AclEntry() acl_entry.sequence_id = 20 acl_entry.config.sequence_id = 20 acl_entry.actions.config.forwarding_action = oc_acl.REJECT() acl_entry.ipv4.config.source_address = "173.31.1.0/24" acl_entry.ipv4.config.destination_address = "172.16.0.0/16" acl_set.acl_entries.acl_entry.append(acl_entry) # acl-entry with sequence number 30 acl_entry = acl_set.acl_entries.AclEntry() acl_entry.sequence_id = 30 acl_entry.config.sequence_id = 30 acl_entry.actions.config.forwarding_action = oc_acl.REJECT() acl_entry.ipv4.config.source_address = "172.31.2.0/24" acl_entry.ipv4.config.destination_address = "172.16.0.0/16" acl_entry.ipv4.config.dscp = 46 acl_set.acl_entries.acl_entry.append(acl_entry) # acl-entry with sequence number 40 acl_entry = acl_set.acl_entries.AclEntry() acl_entry.sequence_id = 40 acl_entry.config.sequence_id = 40 acl_entry.actions.config.forwarding_action = oc_acl.REJECT() acl_entry.ipv4.config.source_address = "172.31.3.0/24" acl_entry.ipv4.config.destination_address = "172.16.0.0/16" acl_set.acl_entries.acl_entry.append(acl_entry) # acl-entry with sequence number 50 acl_entry = acl_set.acl_entries.AclEntry() acl_entry.sequence_id = 50 acl_entry.config.sequence_id = 50 acl_entry.actions.config.forwarding_action = oc_acl.ACCEPT() acl_set.acl_entries.acl_entry.append(acl_entry) acl.acl_sets.acl_set.append(acl_set) def get_netconf_provider(ip): provider = NetconfServiceProvider( address=ip, port=22, username='admin', password='admin', protocol='ssh' ) return provider def main(): logger = logging.getLogger('ydk') logger.setLevel(logging.INFO) handler = logging.StreamHandler() formatter = logging.Formatter(("%(asctime)s - %(name)s - " "%(levelname)s - %(message)s")) handler.setFormatter(formatter) logger.addHandler(handler) provider = CodecServiceProvider(type='xml') codec = CodecService() acl = oc_acl.Acl() config_acl(acl) print(codec.encode(provider, acl)) # crud = CRUDService() # provider = get_netconf_provider(DEVICES[2]) # crud.create(provider, acl) if __name__ == '__main__': main()
And I have the following versions of ydk packets
pip freeze | grep ydk ydk==0.8.4 ydk-models-cisco-ios-xe==16.9.3 ydk-models-cisco-ios-xr==6.5.1 ydk-models-ietf==0.1.5.post2 ydk-models-openconfig==0.1.6.post1
Could you please help tme to find the answer?
10-18-2019 10:48 AM
Hello
You are facing well known issue, which is specific to openconfig YANG models. It is well documented issue, see discussion here. I have opened YDK enhancement to overcome this issue in YDK as recommended.
In the meanwhile I can recommend a workaround, which depends on how you are going to use YDK. If this is just for converting data model API to XML payload as it is described bellow, I would recommend to use XmlSubtreeCodec instead of CodecService. Note that in this case the converted data will not be validated. The XmlSubtreeCodec API is described here.
Please let me know if this workaround is not sufficient for your project.
Regards,
Yan
10-21-2019 01:51 AM
Thank you for quick response.
I'm just starting my YDK journey and don't know what it is capable of. Need to spend some time to be able to apply it in my current infrastructure.
10-24-2019 09:27 PM
I am happy to report that the issue has been fixed. See details on the GitHub.
In order to apply the fix you need to recompile and reinstall YDK-0.8.4 core library and Python core package. Here is the procedure:
Please let me know if you have any installation issue.
Good luck!
10-28-2019 04:04 AM - edited 10-28-2019 05:54 AM
Did this but nothing changed.
I do not understand anything in C++ so I must ask: how pip install -U connected with what I've done before?
It is don't do anything:
pip install -U ydk WARNING: The directory '/home/horseinthesky/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag. WARNING: The directory '/home/horseinthesky/.cache/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag. Requirement already up-to-date: ydk in /usr/local/lib/python3.6/dist-packages (0.8.4) Requirement already satisfied, skipping upgrade: pybind11>=2.1.1 in /usr/local/lib/python3.6/dist-packages (from ydk) (2.2.4)
So the result is the same:
python3 openconfig_acl.py Traceback (most recent call last): File "openconfig_acl.py", line 49, in <module> print(codec.encode(provider, acl)) File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 112, in helper return func(self, provider, entity, *args, **kwargs) File "/usr/local/lib/python3.6/dist-packages/ydk/services/codec_service.py", line 78, in encode return self._encode(provider, entity_holder, pretty, subtree) File "/usr/local/lib/python3.6/dist-packages/ydk/services/codec_service.py", line 110, in _encode return result File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__ self.gen.throw(type, value, traceback) File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 82, in handle_runtime_error _raise(_exc) File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 54, in _raise exec("raise exc from None") File "<string>", line 1, in <module> ydk.errors.YModelError: Value "172.31.255.1/32" does not satisfy the constraint "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))$" (range, length, or pattern). Path: /openconfig-acl:acl/acl-sets/acl-set[name='ACL1'][type='openconfig-acl:ACL_IPV4']/acl-entries/acl-entry[sequence-id='20']/ipv4/config/source-address
12-03-2019 12:32 AM
Needed to recompile the libydk from source and install it https://github.com/CiscoDevNet/ydk-gen#build-from-source
And then reinstall ydk python core package after libydk got changed:
python3 generate.py --core -is
Alternatively you can install YDK from PyPi:
pip3 install -U ydk
12-03-2019 12:34 AM
Now it fails validation against device models I guess:
2019-12-03 11:26:45,055 - ydk - INFO - Path where models are to be downloaded: /home/horseinthesky/.ydk/10.10.30.6 2019-12-03 11:26:45,064 - ydk - INFO - Connected to 10.10.30.6 on port 22 using ssh with timeout of -1 2019-12-03 11:26:45,064 - ydk - INFO - Executing CRUD create operation on [openconfig-acl:acl] 2019-12-03 11:26:45,064 - ydk - INFO - Executing 'edit-config' RPC on [openconfig-acl:acl] 2019-12-03 11:26:47,884 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Internal error (/home/horseinthesky/ydk-gen/gen-api/cpp/ydk/build/project_libyang/src/project_libyang/src/parser_yang.c:4466). 2019-12-03 11:26:47,884 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Module "cisco-xe-openconfig-acl-deviation" parsing failed. 2019-12-03 11:26:47,885 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Internal error (/home/horseinthesky/ydk-gen/gen-api/cpp/ydk/build/project_libyang/src/project_libyang/src/parser_yang.c:4466). 2019-12-03 11:26:47,885 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Module "cisco-xe-openconfig-acl-deviation" parsing failed. 2019-12-03 11:26:47,887 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Internal error (/home/horseinthesky/ydk-gen/gen-api/cpp/ydk/build/project_libyang/src/project_libyang/src/parser_yang.c:4466). 2019-12-03 11:26:47,887 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Module "cisco-xe-openconfig-acl-deviation" parsing failed. 2019-12-03 11:26:47,888 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Internal error (/home/horseinthesky/ydk-gen/gen-api/cpp/ydk/build/project_libyang/src/project_libyang/src/parser_yang.c:4466). 2019-12-03 11:26:47,888 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Module "cisco-xe-openconfig-acl-deviation" parsing failed. 2019-12-03 11:26:47,888 - ydk - ERROR - Could not fetch schema node 'name' Traceback (most recent call last): File "openconfig_acl.py", line 67, in <module> crud.create(provider, acl) File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 112, in helper return func(self, provider, entity, *args, **kwargs) File "/usr/local/lib/python3.6/dist-packages/ydk/services/crud_service.py", line 49, in create return _crud_update(provider, entity, self._crud.create) File "/usr/local/lib/python3.6/dist-packages/ydk/services/crud_service.py", line 70, in _crud_update return crud_call(provider, entity) File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__ self.gen.throw(type, value, traceback) File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 82, in handle_runtime_error _raise(_exc) File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 54, in _raise exec("raise exc from None") File "<string>", line 1, in <module> ydk.errors.YCoreError: Could not fetch schema node: name 2019-12-03 11:26:47,956 - ydk - INFO - Disconnected from device
12-03-2019 12:44 PM - edited 12-03-2019 03:15 PM
I tested the script on sandboxes for IOS-XR-6.5.3 and IOS-XE-16.9.3. It works perfectly well on IOS-XR including parsing of deviation file cisco-xr-openconfig-acl-deviations.yang received from the device. But the script fails on IOS-XE while parsing deviation file cisco-xe-openconfig-acl-deviation.yang (same internal error). Then I removed all 'deviation' statements in the failed file located in repository under $HOME/.ydk/<device-IP> and repeated the test. This time it all worked fine. I am guessing that something is wrong with the deviation file for IOS-XE-16.9.3.
Note. When YANG file in default repository is changed, it is not get overwritten by YDK when synchronizing repository with YANG models on device.
I used Libyang utility yanglint to analyze cisco-xe-openconfig-acl-deviation.yang parsing. From your ydk-gen location run:
cd sdk/cpp/core/build/project_libyang/src/project_libyang-build
./yanglint -p /Users/ygorelik/.ydk/ios-xe-mgmt.cisco.com /Users/ygorelik/.ydk/ios-xe-mgmt.cisco.com/cisco-xe-openconfig-acl-deviation.yang
I found that some of the deviation statements are incorrect. Here is the module content with my comments:
module cisco-xe-openconfig-acl-deviation {
namespace "http://cisco.com/ns/cisco-xe-openconfig-acl-deviation";
prefix acl-devs;
import openconfig-acl {
prefix oc-acl;
}
import tailf-common { prefix tailf; }
organization
"Cisco Systems, Inc.";
contact
"Cisco Systems, Inc.
Customer Service
Postal: 170 W Tasman Drive
San Jose, CA 95134
Tel: +1 1800 553-NETS
E-mail: cs-yang@cisco.com";
description
"This module defines deviation statements for openconfig-acl module.";
revision 2017-08-25 {
description
"Added deviation to remove leafref from ingress/egress acls because of IOS allowing
access-groups on interfaces when the access-group doesn't exit";
}
revision 2017-08-22 {
description
"Remove deviation to require at least one ingress or egress acl on interface";
}
revision 2017-05-04 {
description
"Add";
}
deviation "/oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set" {
deviate add {
unique "oc-acl:name";
}
}
deviation "/oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry" {
deviate add {
unique "oc-acl:actions/oc-acl:config/oc-acl:forwarding-action "
+ "oc-acl:l2/oc-acl:config/oc-acl:source-mac "
+ "oc-acl:l2/oc-acl:config/oc-acl:destination-mac "
+ "oc-acl:l2/oc-acl:config/oc-acl:ethertype";
}
}
deviation "/oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry"
+ "/oc-acl:l2/oc-acl:config/oc-acl:source-mac" {
deviate add {
default 00:00:00:00:00:00;
}
}
deviation "/oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry"
+ "/oc-acl:l2/oc-acl:config/oc-acl:source-mac-mask" {
deviate add {
must "../oc-acl:source-mac" {
error-message "When source-mac-mask is set, source-mac must be set too";
}
}
}
deviation "/oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry"
+ "/oc-acl:l2/oc-acl:config/oc-acl:destination-mac" {
deviate add {
default 00:00:00:00:00:00;
}
}
deviation "/oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry"
+ "/oc-acl:l2/oc-acl:config/oc-acl:destination-mac-mask" {
deviate add {
must "../oc-acl:destination-mac" {
error-message "When destination-mac-mask is set, destination-mac must be set too";
}
}
}
/* WRONG STATEMENTS BELOW THIS LINE
deviation "/oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry"
+ "/oc-acl:actions/oc-acl:config/oc-acl:log-action" {
deviate add {
must ". = 'oc-acl:LOG_NONE' or ../../../../../type != 'oc-acl:ACL_L2'" {
error-message "Log action not supported for L2 ACL sets";
}
}
}
deviation "/oc-acl:acl/oc-acl:interfaces/oc-acl:interface/oc-acl:ingress-acl-sets/oc-acl:ingress-acl-set"
+ "/oc-acl:config/oc-acl:set-name" {
deviate replace {
type leafref {
tailf:no-leafref-check;
path "../../../../../../acl-sets/acl-set/config/name";
}
}
}
deviation "/oc-acl:acl/oc-acl:interfaces/oc-acl:interface/oc-acl:ingress-acl-sets/oc-acl:ingress-acl-set"
+ "/oc-acl:config/oc-acl:type" {
deviate replace {
type leafref {
tailf:no-leafref-check;
path "../../../../../../acl-sets/acl-set[name=current()/../set-name]" +
"/config/type";
}
}
}
deviation "/oc-acl:acl/oc-acl:interfaces/oc-acl:interface/oc-acl:egress-acl-sets/oc-acl:egress-acl-set"
+ "/oc-acl:config/oc-acl:set-name" {
deviate replace {
type leafref {
tailf:no-leafref-check;
path "../../../../../../acl-sets/acl-set/config/name";
}
}
}
deviation "/oc-acl:acl/oc-acl:interfaces/oc-acl:interface/oc-acl:egress-acl-sets/oc-acl:egress-acl-set"
+ "/oc-acl:config/oc-acl:type" {
deviate replace {
type leafref {
tailf:no-leafref-check;
path "../../../../../../acl-sets/acl-set[name=current()/../set-name]" +
"/config/type";
}
}
}
*/
}
You might consider opening a bug for this IOS-XE YANG model issue.
12-04-2019 12:13 AM
Yanglint
Could you please explain in more detail how to build yanglint binary(?) because I don't have build directory inside ydk-gen/sdk/cpp/core/ and how to use it to verify if models are correct?
Device models
This is another thing I am a little bit confused regarding YDK internal work: is it correct that YDK downloads YANG models from the device to validate the configuration against it? If so does it download only the models used for the particular configuration and not the whole models that are supported on the device?
12-04-2019 10:17 AM
yanglint
The yanglint is command line utility of Libyang. Please refer to Libyang documentation for details. The Libyang is a third party software, which is used by YDK to parse YANG models, load and output data, which are organized accordingly to the YANG models. The core YDK library - libydk - incorporates the Libyang library, which is compiled during libydk build. Therefore, in order to get yanglint utility you need compile the core YDK library from source. Please note that YDK uses private fork of libyang; its code is adjusted to YDK needs. The YDK code currently is not compatible with master branch due to recent significant change in API by Libyang developers.
Device models
In order to load YANG models to libyang we need create repository (directory) of *.yang files. It can be a limited set of files, which is needed to resolve all the dependencies. By default the repository is organized in directory $HOME/.ydk/<device-IP>. The Netconf protocol has capability to retrieve YANG models from device. When there is a need to load a module to libyang, the YDK looks for that module in repository. If not found, it attempts to retrieve the module from device and puts it to repository. This algorithm allows to have in repository only those models that are needed for particular task, and significantly save time on repeated runs of user application.
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