cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
113
Views
0
Helpful
0
Replies
Cisco Employee

Adding/removing ACEs in XR ACLs

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!