02-19-2020 05:33 PM
How would a simple YDK script would look for adding/removing ACEs in XR ACLs? Let's say we store ACEs in XML files and pass the file as an argument along with the device and the type of ACE operation (add or remove):
$ ./nc-update-xr-ipv4-acl-cfg-99-ydk.py -h usage: nc-update-xr-ipv4-acl-cfg-99-ydk.py [-h] [-o {add,remove}] [-v] FILE device positional arguments: FILE configuration file device NETCONF device (ssh://user:password@host:port) optional arguments: -h, --help show this help message and exit -o {add,remove}, --operation {add,remove} configuration operation (add or remove) -v, --verbose print debugging messages $
Let's use some ACE sample files:
$ cat ace1.xml <?xml version="1.0"?> <ipv4-acl-and-prefix-list xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-acl-cfg"> <accesses> <access> <access-list-name>ACL1</access-list-name> <access-list-entries> <access-list-entry> <sequence-number>10</sequence-number> <remark>allow multiple hosts</remark> </access-list-entry> </access-list-entries> </access> </accesses> </ipv4-acl-and-prefix-list> $
$ cat ace2.xml
<?xml version="1.0"?> <ipv4-acl-and-prefix-list xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-acl-cfg"> <accesses> <access> <access-list-name>ACL1</access-list-name> <access-list-entries> <access-list-entry> <sequence-number>20</sequence-number> <grant>permit</grant> <source-network> <source-address>172.31.255.1</source-address> <source-wild-card-bits>0.0.0.0</source-wild-card-bits> </source-network> </access-list-entry> </access-list-entries> </access> </accesses> </ipv4-acl-and-prefix-list> $
$ cat ace3.xml <?xml version="1.0"?> <ipv4-acl-and-prefix-list xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-acl-cfg"> <accesses> <access> <access-list-name>ACL1</access-list-name> <access-list-entries> <access-list-entry> <sequence-number>10</sequence-number> <remark>allow multiple hosts</remark> </access-list-entry> </access-list-entries> </access> <access> <access-list-name>ACL2</access-list-name> <access-list-entries> <access-list-entry> <sequence-number>10</sequence-number> <remark>allow multiple hosts</remark> </access-list-entry> <access-list-entry> <sequence-number>20</sequence-number> <grant>permit</grant> <source-network> <source-address>172.31.255.1</source-address> <source-wild-card-bits>0.0.0.0</source-wild-card-bits> </source-network> </access-list-entry> </access-list-entries> </access> </accesses> </ipv4-acl-and-prefix-list> $
Let's add an ACE to ACL1:
$ ./nc-update-xr-ipv4-acl-cfg-99-ydk.py --operation add ace1.xml ssh://user:password@host -v 2020-02-19 16:24:39,182 - ydk - INFO - Path where models are to be downloaded: /home/saalvare/.ydk/host 2020-02-19 16:24:39,191 - ydk - INFO - Connected to host on port 830 using ssh with timeout of -1 2020-02-19 16:24:39,233 - ydk - INFO - Executing CRUD update operation on [Cisco-IOS-XR-ipv4-acl-cfg:ipv4-acl-and-prefix-list] 2020-02-19 16:24:39,233 - ydk - INFO - Executing 'edit-config' RPC on [Cisco-IOS-XR-ipv4-acl-cfg:ipv4-acl-and-prefix-list] 2020-02-19 16:24:39,243 - ydk - INFO - ============= Sending RPC to device ============= <rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <target> <candidate/> </target> <config><ipv4-acl-and-prefix-list xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-acl-cfg" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="merge"> <accesses> <access> <access-list-name>ACL1</access-list-name> <access-list-entries> <access-list-entry> <sequence-number>10</sequence-number> <remark>allow multiple hosts</remark> </access-list-entry> </access-list-entries> </access> </accesses> </ipv4-acl-and-prefix-list> </config> </edit-config> </rpc> 2020-02-19 16:24:39,562 - ydk - INFO - ============= Received RPC from device ============= <?xml version="1.0"?> <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1"> <ok/> </rpc-reply> 2020-02-19 16:24:39,562 - ydk - INFO - Executing 'commit' RPC 2020-02-19 16:24:39,562 - ydk - INFO - ============= Sending RPC to device ============= <rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><commit xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/> </rpc> 2020-02-19 16:24:40,685 - ydk - INFO - ============= Received RPC from device ============= <?xml version="1.0"?> <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="2"> <ok/> </rpc-reply> 2020-02-19 16:24:40,685 - ydk - INFO - Operation succeeded 2020-02-19 16:24:40,700 - ydk - INFO - Disconnected from device $
Let's remove a handful of ACEs from ACL1 and ACL2:
$ ./nc-update-xr-ipv4-acl-cfg-99-ydk.py --operation remove ace3.xml ssh://user:password@host -v 2020-02-19 16:25:05,695 - ydk - INFO - Path where models are to be downloaded: /home/saalvare/.ydk/host 2020-02-19 16:25:05,708 - ydk - INFO - Connected to host on port 830 using ssh with timeout of -1 ('ACL1', 10) ('ACL2', 10) ('ACL2', 20) 2020-02-19 16:25:05,756 - ydk - INFO - Executing CRUD update operation on [Cisco-IOS-XR-ipv4-acl-cfg:ipv4-acl-and-prefix-list] 2020-02-19 16:25:05,756 - ydk - INFO - Executing 'edit-config' RPC on [Cisco-IOS-XR-ipv4-acl-cfg:ipv4-acl-and-prefix-list] 2020-02-19 16:25:05,776 - ydk - INFO - ============= Sending RPC to device ============= <rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <target> <candidate/> </target> <config><ipv4-acl-and-prefix-list xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-acl-cfg" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="merge"> <accesses> <access> <access-list-name>ACL1</access-list-name> <access-list-entries> <access-list-entry nc:operation="remove"> <sequence-number>10</sequence-number> <remark>allow multiple hosts</remark> </access-list-entry> </access-list-entries> </access> <access> <access-list-name>ACL2</access-list-name> <access-list-entries> <access-list-entry nc:operation="remove"> <sequence-number>10</sequence-number> <remark>allow multiple hosts</remark> </access-list-entry> <access-list-entry nc:operation="remove"> <sequence-number>20</sequence-number> <grant>permit</grant> <source-network> <source-address>172.31.255.1</source-address> <source-wild-card-bits>0.0.0.0</source-wild-card-bits> </source-network> </access-list-entry> </access-list-entries> </access> </accesses> </ipv4-acl-and-prefix-list> </config> </edit-config> </rpc> 2020-02-19 16:25:05,893 - ydk - INFO - ============= Received RPC from device ============= <?xml version="1.0"?> <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1"> <ok/> </rpc-reply> 2020-02-19 16:25:05,893 - ydk - INFO - Executing 'commit' RPC 2020-02-19 16:25:05,894 - ydk - INFO - ============= Sending RPC to device ============= <rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><commit xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/> </rpc> 2020-02-19 16:25:06,968 - ydk - INFO - ============= Received RPC from device ============= <?xml version="1.0"?> <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="2"> <ok/> </rpc-reply> 2020-02-19 16:25:06,968 - ydk - INFO - Operation succeeded 2020-02-19 16:25:06,973 - ydk - INFO - Disconnected from device $
The scripts handles multiple ACLs and multiple ACEs. This should be a good example of how to add/remove configuration elements to/from a list.
#!/usr/bin/env python # # Copyright 2020 Cisco Systems, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Update configuration for model Cisco-IOS-XR-ipv4-acl-cfg. usage: nc-update-xr-ipv4-acl-cfg-99-ydk.py [-h] [-o {add,remove}] [-v] FILE device positional arguments: FILE configuration file device NETCONF device (ssh://user:password@host:port) optional arguments: -h, --help show this help message and exit -o {add,remove}, --operation {add,remove} configuration operation (add or remove) -v, --verbose print debugging messages """ from argparse import ArgumentParser from urlparse import urlparse from ydk.services import CodecService from ydk.services import CRUDService from ydk.providers import CodecServiceProvider from ydk.providers import NetconfServiceProvider from ydk.models.cisco_ios_xr import Cisco_IOS_XR_ipv4_acl_cfg \ as xr_ipv4_acl_cfg from ydk.models.cisco_ios_xr import Cisco_IOS_XR_ipv4_acl_datatypes \ as xr_ipv4_acl_datatypes from ydk.filters import YFilter import logging def load_ace_config_file(ace_config_file_name): """Load ACE configuration file (XML)""" # read ACE config file with open(ace_config_file_name) as ace_config_file: encoded_config = ace_config_file.read() # create codec provider provider = CodecServiceProvider(type="xml") # create codec service codec = CodecService() ipv4_acl_and_prefix_list = xr_ipv4_acl_cfg.Ipv4AclAndPrefixList() # create object return codec.decode(provider, encoded_config) def add_ace_remove_filter(ipv4_acl_and_prefix_list): """Add remove filter to access_list_entries in ipv4_acl_and_prefix_list object.""" for access in ipv4_acl_and_prefix_list.accesses.access: for access_list_entry in access.access_list_entries.access_list_entry: access_list_entry.yfilter = YFilter.remove print(access.access_list_name, access_list_entry.sequence_number) if __name__ == "__main__": """Execute main program.""" parser = ArgumentParser() parser.add_argument("-o", "--operation", choices=['add', 'remove'], default='add', help="configuration operation (add or remove)") parser.add_argument("-v", "--verbose", help="print debugging messages", action="store_true") parser.add_argument("config_file", metavar="FILE", help="configuration file") parser.add_argument("device", help="NETCONF device (ssh://user:password@host:port)") args = parser.parse_args() device = urlparse(args.device) # log debug messages if verbose argument specified if args.verbose: 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) # print(args.operation, args.verbose, args.config_file, args.device) #print(load_ace_config_file(args.config_file)) # update NETCONF provider provider = NetconfServiceProvider(address=device.hostname, port=device.port, username=device.username, password=device.password, protocol=device.scheme) # update CRUD service crud = CRUDService() ipv4_acl_and_prefix_list = load_ace_config_file(args.config_file) if args.operation == 'remove': add_ace_remove_filter(ipv4_acl_and_prefix_list) # update configuration on NETCONF device crud.update(provider, ipv4_acl_and_prefix_list) exit() # End of script
Give it a try!
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