#!/usr/bin/env python3 # # Copyright (c) 2018, Cisco and/or its affiliates # All rights reserved. #__maintainer__ = 'Siddharth Krishna' #__email__ = 'sidkrish@cisco.com' #__date__ = 'February 2019' #__version__ = 1.0 # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # This script automates streaming telemetry grpc (dial-out) based subscription on the Catalyst 9K. # It uses Jinja Templates for dynamic redering of XML payloads to netconf requests. import sys from argparse import ArgumentParser from ncclient import manager import xml.dom.minidom import re import logging #import checkversion from xml.etree.ElementTree import XML from jinja2 import Environment , FileSystemLoader def configure_grpc_subscription(netconf_handler, proc_subid, proc_triggertype, proc_period, proc_xpath, proc_dstaddr, proc_dstport, proc_srcaddr, proc_srcvrf): file_loader = FileSystemLoader('templates') env = Environment(loader=file_loader) template = env.get_template('grpc_template.j2') flow_record_payload = template.render(grpc_subid=proc_subid, grpc_trigger_type= proc_triggertype, grpc_period=proc_period, grpc_xpath=proc_xpath, grpc_dstaddr=proc_dstaddr, grpc_dstport=proc_dstport, grpc_srcaddr=proc_srcaddr, grpc_srcvrf=proc_srcvrf) netconf_reply = xml.dom.minidom.parseString(str(netconf_handler.edit_config(flow_record_payload, target='running'))) print (netconf_reply.toprettyxml( indent = " " )) if "<ok/>" in (netconf_reply.toprettyxml(indent = " ")): return_val = True else: return_val = False return return_val if __name__ == '__main__': parser = ArgumentParser(description='Select options.') # Input parameters parser.add_argument('--host', type=str, required=True, help="The device IP or DN") parser.add_argument('-u', '--username', type=str, default='cisco', help="Go on, guess!") parser.add_argument('-p', '--password', type=str, default='cisco', help="Yep, this one too! ;-)") parser.add_argument('--port', type=int, default=830, help="Specify this if you want a non-default port") parser.add_argument('--subscription_id', type=str, required=True, help="Specify the id for gRPC subscription") parser.add_argument('--trigger_type', type=str, required=True, help="Specify the trigger type for gRPC subscription - must be either 'onchange' or 'periodic'") parser.add_argument('--period', type=str, help="Specify the period for gRPC subscription - must for trigger type 'periodic'") parser.add_argument('--dst_ipaddr', type=str, required=True, help="Specify the destinaton address for gRPC subscription") parser.add_argument('--dst_port', type=str, required=True, help="Specify the destination port for gRPC subscription") parser.add_argument('--xpath', type=str, required=True, help="Specify the XPATH for gRPC subscription") parser.add_argument('--src_ipaddr', type=str, help="Optional,Specify the switch source address for gRPC subscription") parser.add_argument('--src_vrf', type=str, help="Optional, Specify the switch source VRF for gRPC subscription") args = parser.parse_args() if args.trigger_type != 'periodic' and args.trigger_type != 'onchange': parser.error("--trigger_type must be either 'onchnage' or 'periodic'") if args.trigger_type == 'periodic' and args.period is None: parser.error("'--trigger_type periodic needs a valid period value'") m = manager.connect(host=args.host, port=args.port, username=args.username, password=args.password, device_params={'name':"iosxe"}) if configure_grpc_subscription(m, args.subscription_id, args.trigger_type, args.period, args.xpath, args.dst_ipaddr, args.dst_port, args.src_ipaddr, args.src_vrf): print("HURRAAY!! Telemetry subscription has beeen configured.") else: print("AAARGHH!! Something wrong with configuring the telemetry subscription.") exit()