Example #1
0
def save_configs(device_id):
    """
    This function will save the running config of the device and the last Cisco DNA Center saved configuration to files
    :param device_id: Cisco DNA Center {device_id}
    :return: saved files with the configs
    """

    # get the Cisco DNA Center Auth token
    dnac_auth = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)

    # get the device name for the {device_id}
    device_name = dnac_apis.get_device_info(device_id, dnac_auth)
    print('\nDevice Name: ', device_name)

    # get the running config of the device
    device_1 = dnac_apis.get_output_command_runner('show running-config', device_id, dnac_auth)
    device_config_1 = device_1.replace('show running-config', '')
    device_run_config = device_config_1.replace('\n' + device_name + '#', '\n')

    # save the running config to file

    f_temp = open(DEVICE_RUNNING_CONFIG, 'w')
    f_temp.write(device_run_config)
    f_temp.seek(0)  # reset the file pointer to 0
    f_temp.close()

    # get the last know Cisco DNA Center device config
    dnac_device_config = dnac_apis.get_device_config(device_id, dnac_auth)

    # save the Cisco DNA Center config to file

    f_temp = open(DNAC_DEVICE_CONFIG, 'w')
    f_temp.write(dnac_device_config)
    f_temp.seek(0)  # reset the file pointer to 0
    f_temp.close()
def main():
    execute('send log Application subscriber_listener.py started')
    logging.basicConfig(
        filename='application_run.log',
        level=logging.DEBUG,
        format='%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S')
    global IOS_XE_HOST_IP, DEVICE_HOSTNAME, DEVICE_LOCATION

    # retrieve the ios xe device management ip address, Gi0/0
    IOS_XE_HOST_IP = execute('sh run int gi1 | in ip address').split(' ')[3]
    print (IOS_XE_HOST_IP)
    # retrieve the device hostname using RESTCONF
    DEVICE_HOSTNAME = netconf_restconf.get_restconf_hostname(IOS_XE_HOST_IP, IOS_XE_USER, IOS_XE_PASS)
    print(str('\nThe device hostname: ' + DEVICE_HOSTNAME))


    #The following commands are if Cisco DNA Center is available

    # get DNA C AUth JWT token
    dnac_token = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)
    #print (dnac_token)
    DEVICE_HOSTNAME = DEVICE_HOSTNAME+'.ablitz.com'
    print (DEVICE_HOSTNAME)
    DEVICE_LOCATION = dnac_apis.get_device_location(DEVICE_HOSTNAME, dnac_token)
    print(str("\nDevice Location: " + DEVICE_LOCATION))


    # init the PubNub channel
    pubnub = pubnub_init(DEVICE_HOSTNAME)

    pubnub.add_listener(MySubscribeCallback())
    pubnub.subscribe().channels(CHANNEL).execute()
Example #3
0
def main():

    # the local date and time when the code will start execution
    #date_time = str(datetime.datetime.now().replace(microsecond=0))
    #print('\n\nApplication "get_sites.py" Run Started: ' + date_time)

    # get a Cisco DNA Center auth token
    dnac_auth = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)
    result = dnac_apis.get_device_config_archive(0, dnac_auth)

    for item in result:
        hostname = item['deviceName']
        #Address = item['ipAddress']
        versions = item['versions']

        for item2 in versions:
            start = item2['startupRunningStatus']
            if item2['startupRunningStatus'] == 'OUT_OF_SYNC':
                #hostname1 = hostname
                #print(hostname)
                print('Hostname : ' + hostname +
                      '    startupRunningStatus : ' + "Non-Compliant")
Example #4
0
def main():
    """
    - identify any PnP unclaimed APs
    - map to local database to identify the floor to be provisioned to
    - claim the device
    - verify PnP process workflow
    - re-sync the WLC controller
    - verify the AP on-boarded using the Cisco DNA Center Inventory
      - reachability, IP address, access switch info, WLC info
    - create, update a ServiceNow incident with the information
    - close ServiceNow incident if PnP completes successfully
    """

    # run the application on demand, scanning for a new device in the Cisco DNA Center PnP Provisioning tab

    print('\n\nApplication "dnac_pnp_ap.py" started')

    # device info and site

    pnp_device_assign = AP_ASSIGN_SITE

    site_name = pnp_device_assign['site_name']
    floor_name = pnp_device_assign['floor_name']
    pnp_device_name = pnp_device_assign['device_hostname']

    print('\nThis application will assign the device \n', pnp_device_name,
          ' to the site: ',
          pnp_device_assign['site_name'] + ' / ' + floor_name)

    # logging, debug level, to file {application_run.log}
    logging.basicConfig(
        filename='application_run.log',
        level=logging.DEBUG,
        format=
        '%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S')

    dnac_token = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)

    # check if any devices in 'Unclaimed' and 'Initialized' state, if not wait for 10 seconds and run again
    pnp_unclaimed_device_count = 0
    while pnp_unclaimed_device_count == 0:
        try:
            pnp_unclaimed_device_count = dnac_apis.pnp_get_device_count(
                'Unclaimed', dnac_token)
            if pnp_unclaimed_device_count != 0:

                # get the pnp device info
                pnp_devices_info = dnac_apis.pnp_get_device_list(dnac_token)
                device_state = pnp_devices_info[0]['deviceInfo']['state']
                device_onb_state = pnp_devices_info[0]['deviceInfo'][
                    'onbState']

                # verify if device is ready to be claimed: state = Unclaimed "and" onboard_state = Initialized
                if device_state == 'Unclaimed' and device_onb_state == 'Initialized':
                    break
                else:
                    pnp_unclaimed_device_count = 0
        except:
            pass
        time.sleep(10)

    print('\nFound Unclaimed PnP devices count: ', pnp_unclaimed_device_count)

    pnp_device_id = pnp_devices_info[0]['id']

    comment = '\nUnclaimed PnP device info:'
    comment += '\nPnP Device Hostname: ' + pnp_device_name
    comment += '\nPnP Device Id: ' + pnp_device_id

    print(comment)

    # create service now incident
    incident_number = service_now_apis.create_incident(
        'AP PnP API Provisioning: ' + pnp_device_name, comment, SNOW_DEV, 3)
    print('Created new ServiceNow Incident: ', incident_number)

    # get the floor id to assign device to using pnp

    floor_id = dnac_apis.get_floor_id(site_name, 'Floor 3', dnac_token)
    print('Floor Id: ', floor_id)

    print('\nAP PnP Provisioning Started (this may take few minutes)')

    # start the claim process of the device to site
    claim_result = dnac_apis.pnp_claim_ap_site(pnp_device_id, floor_id,
                                               'TYPICAL', dnac_token)
    comment = '\nClaim Result: ' + claim_result

    # update ServiceNow incident
    print(comment)
    service_now_apis.update_incident(incident_number, comment, SNOW_DEV)

    # check claim status every 5 seconds, build a progress status list, end when state == provisioned, exit
    status_list = []
    claim_status = dnac_apis.pnp_get_device_info(pnp_device_id,
                                                 dnac_token)['state']
    status_list.append(claim_status)

    while claim_status != 'Provisioned':
        claim_status = dnac_apis.pnp_get_device_info(pnp_device_id,
                                                     dnac_token)['state']
        if claim_status not in status_list:
            status_list.append(claim_status)
        time.sleep(5)

    comment = ''
    for status in status_list:
        comment += '\nPnP Device State: ' + status

    # update service now incident
    print(comment)
    service_now_apis.update_incident(incident_number, comment, SNOW_DEV)

    # sync the PnP WLC, wait 60 seconds to complete
    dnac_apis.sync_device(PnP_WLC_NAME, dnac_token)
    print('\nDNA Center Device Re-sync started: ', PnP_WLC_NAME)

    # wait 60 seconds and check for inventory for AP info
    time.sleep(60)

    # collect AP info
    ap_device_id = dnac_apis.get_device_id_name(pnp_device_name, dnac_token)
    ap_device_info = dnac_apis.get_device_info(ap_device_id, dnac_token)
    ap_reachability = ap_device_info['reachabilityStatus']
    ap_controller_ip = ap_device_info['associatedWlcIp']
    ap_ip_address = ap_device_info['managementIpAddress']
    ap_device_location = dnac_apis.get_device_location(pnp_device_name,
                                                       dnac_token)
    ap_access_switch_info = dnac_apis.get_physical_topology(
        ap_ip_address, dnac_token)
    ap_access_switch_hostname = ap_access_switch_info[0]
    ap_access_switch_port = ap_access_switch_info[1]

    # collect WLC info
    wlc_info = dnac_apis.get_device_info_ip(ap_controller_ip, dnac_token)
    wlc_hostname = wlc_info['hostname']

    comment = '\nProvisioned Access Point Info:\n - Reachability: ' + ap_reachability
    comment += '\n - IP Address: ' + ap_ip_address
    comment += '\n - Connected to: ' + ap_access_switch_hostname + ' , Interface: ' + ap_access_switch_port
    comment += '\n - Location: ' + ap_device_location
    comment += '\n - WLC Controller: ' + wlc_hostname + ' , IP Address: ' + ap_controller_ip

    print(comment)
    service_now_apis.update_incident(incident_number, comment, SNOW_DEV)

    print('\n\nAP PnP provisoning completed')

    service_now_apis.close_incident(incident_number, SNOW_DEV)

    print(
        '\nPnP provisioning completed successfully, ServiceNow incident closed'
    )

    print('\n\nEnd of Application "dnac_pnp_ap.py" Run')
def main():
    """
    - This script will:
      - load a file with a configuration to be deployed to a network device
      - identify the IPv4 addresses that will be configured on interfaces
      - search in the DNA Center database if these IPV4 addresses are configured on any interfaces
      - find if any clients are using the IPv4 addresses
    - Determine if deploying the configuration file will create an IP duplicate
    """

    # configuration template file name
    config_file = 'configuration_template.txt'

    # open file with the template
    cli_file = open(config_file, 'r')

    # read the file
    cli_config = cli_file.read()
    print('\n The CLI template:\n')
    print(cli_config)

    ipv4_address_list = utils.identify_ipv4_address(cli_config)
    print('\nThese valid IPv4 addresses will be configured:\n')
    print(ipv4_address_list)

    # get the DNA Center Auth token

    dnac_token = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)
    print('\nThe DNA Center token is: ', dnac_token, '\n')

    # check each address against network devices and clients database
    # initialize duplicate_ip

    duplicate_ip = False
    for ipv4_address in ipv4_address_list:

        # check against network devices interfaces

        try:
            device_info = dnac_apis.check_ipv4_network_interface(ipv4_address, dnac_token)
            duplicate_ip = True
            if len(device_info) == 2:
                print('The IPv4 address ', ipv4_address, ' is used on this device ', device_info[0], ' interface ', device_info[1])
            else:
                print('The IPv4 address ', ipv4_address, ' is used on this device ', device_info[0])
        except:
            pass

        # check against any hosts

        try:
            client_info = dnac_apis.get_client_info(ipv4_address, dnac_token)
            if client_info is not None:
                duplicate_ip = True
                print('The IPv4 address ', ipv4_address, ' is used by a client')
        except:
            pass

    if duplicate_ip:
        print('\nDeploying the template ', config_file, ' will create IP duplicates')
    else:
        print('\nDeploying the template ', config_file, ' will not create IP duplicates')

    # end of the application run

    print('\n\nEnd of Application Run')
dnac_auth = HTTPBasicAuth(DNAC_USER, DNAC_PASS)

while True:
    interface_number = int(input('Enter the interface number (range 2-5): '))
    if 2 <= interface_number <= 5:
        disable_message = 'Interface GigabitEthernet1/0/' + str(
            interface_number) + ' disable request: '
        disable_message += netconf_restconf.netconf_oper_admin_interface(
            'GigabitEthernet1/0/' + str(interface_number), 'false', host_ip,
            830, username, password)
        print('\n', disable_message)

        # wait for event to be created
        utils.time_sleep(30)

        enable_message = 'Interface GigabitEthernet1/0/' + str(
            interface_number) + ' enable request: '
        enable_message += netconf_restconf.netconf_oper_admin_interface(
            'GigabitEthernet1/0/' + str(interface_number), 'true', host_ip,
            830, username, password)
        print('\n\n', enable_message)

        # start the Cisco DNA Center device re-sync
        dnac_token = dnac_apis.get_dnac_jwt_token(dnac_auth)

        sync_status = dnac_apis.sync_device(hostname, dnac_token)
        print('\nDevice sync started: ', sync_status)

        break
Example #7
0
def main():
    """
    This script will load the file with the name {file_info}
    The file includes the information required to deploy the template. The network device hostname, the Cisco DNA Center
    project name, the configuration template file name.
    The application will:
     - verify if the project exists and create a new project if does not
     - update or upload the configuration template
     - commit the template
     - verify the device hostname is valid
     - deploy the template
     - verify completion and status of the template deployment
    :param template_info: the CLI command
    """

    # the local date and time when the code will start execution

    date_time = str(datetime.datetime.now().replace(microsecond=0))

    print('\n\nApplication "dnacenter_config_templates.py" Run Started: ' + date_time)

    # input data validation

    # open the file with the device, project and template info
    with open('data_input.txt', 'r') as f:
        data = f.read()
    template_info = json.loads(data)

    print('\nThe Cisco DNA Center Template information is: \n', template_info)
    device_hostname = template_info['device']
    project_name = template_info['project']
    template_file_name = template_info['template']

    # get a Cisco DNA Center auth token
    dnac_auth = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)

    # check if existing project, if not create a new project
    project_id = dnac_apis.create_project(project_name, dnac_auth)
    if project_id == 'none':
        # unable to find or create the project
        print('\nUnable to create the project: ', project_name)
        return
    # continue with the project id
    print('\nThe project id for the the project with the name "' + project_name + '" is: ' + project_id)

    # create new template and commit of not existing
    # update the existing template and commit if existing

    cli_config_name = template_file_name.split('.')[0]  # select the template name from the template file

    cli_file = open(template_file_name, 'r')  # open file with the template
    cli_config_commands = cli_file.read()  # read the file

    # IPv4 conflict validation of the CLI template using the filename as input
    cli_valid = dnac_apis.check_ipv4_duplicate(template_file_name)

    # upload and commit the template
    dnac_apis.upload_template(cli_config_name, project_name, cli_config_commands, dnac_auth)

    if cli_valid is False:
        print('\n\nDeploying the CLI Template  "' + cli_config_name + '" will not create duplicated IP Addresses')
        # deploy the template
        deployment_id = dnac_apis.send_deploy_template(cli_config_name, project_name, device_hostname, dnac_auth)
        print(deployment_id)
        time.sleep(1)
        deployment_status = dnac_apis.check_template_deployment_status(deployment_id, dnac_auth)
        print(deployment_status)

    else:
        print('\n\nDeploying the CLI Template  "' + cli_config_name + '" will create duplicated IP Addresses')
        print('CLI Template not deployed')

    date_time = str(datetime.datetime.now().replace(microsecond=0))
    print('\n\nEnd of Application "dnacenter_config_templates.py" Run: ' + date_time)
    return
Example #8
0
def builder(issue_id):
    """
    This function will collect the Assurance issue details, identify the recommended actions and execute the commands (if any)
    It will create a text file with the output of all the details and commands
    :param issue_id
    :return: issue_details
    """
    # obtain the Cisco DNA Center auth
    issue_list = []

    dnac_auth = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)
    issue_complete = dnac_apis.get_issue_enrichment_details(issue_id, dnac_auth)

    # start to collect relevant information from the issue details, create a list with the output, for each suggested action

    issue_info = issue_complete['issueSummary'] + '\n\n'
    issue_info += utils.convert_html_to_text(issue_complete['issueDescription']) + '\n\n'

    issue_list.append(str(issue_info) + '\n\n')

    issue_list.append('The following troubleshooting steps have been recommended by Cisco DNA Center Assurance.\n' +
                      'The Suggested steps and CLI commands have been executed using REST APIs.\n' +
                      'For more details visit the Cisco DNA Center Issue details \n' +
                      DNAC_ISSUE + issue_id
                      )

    device_mngmnt_ip = issue_complete['issueEntityValue']
    device_info = dnac_apis.get_device_info_ip(device_mngmnt_ip, dnac_auth)
    device_id = device_info['id']

    # save the configs for the Cisco DNA Center {device_id}
    save_configs(device_id)

    # check if any device configuration changes from the last saved Cisco DNA Center configuration

    config_diff = compare_configs(DNAC_DEVICE_CONFIG, DEVICE_RUNNING_CONFIG)

    if config_diff == '':
        config_diff_comment = '\nThere are no configurations changes on the device: ' + device_info['hostname']

    else:
        config_diff_comment = '\nThe diff between the Cisco DNA Center saved config and device running config is: \n' + config_diff

    # append the config diff info
    print(config_diff_comment)
    issue_list.append('\n\n' + config_diff_comment + '\n')

    # select suggested actions

    suggested_actions = issue_complete['suggestedActions']
    for action in suggested_actions:
        action_info = 'Cisco DNA Center Suggested Action\n\n' + action['message'] + '\n\n'
        if 'steps' in action:
            steps_list = action['steps']
            action_info += 'Steps:' + '\n\n'
            for step in steps_list:
                device_hostname = dnac_apis.get_device_info(step['entityId'], dnac_auth)
                action_info += step['description'] + '\n\n'
                action_info += 'Device: ' + device_hostname + '\n'
                command_ouput = dnac_apis.get_output_command_runner(step['command'], step['entityId'], dnac_auth)
                action_info += command_ouput + '\n\n'
                print(action_info)
        issue_list.append(action_info)

    # return the list with the commands and steps
    return issue_list
Example #9
0
def main():
    """
    Vendor will join Spark Room with the name {ROOM_NAME}
    It will ask for access to an IP-enabled device - named {IPD}
    The code will map this IP-enabled device to the IP address {172.16.41.55}
    Access will be provisioned to allow connectivity from DMZ VDI to IPD
    """

    last_person_email = '*****@*****.**'
    timer = 2

    # save the initial stdout
    initial_sys = sys.stdout

    # the user will be asked if interested to run in demo mode or in
    # production (logging to files - erna_log.log, erna_err.log))

    user_input = utils.get_input_timeout(
        'If running in Demo Mode please enter y ', 10)

    if user_input != 'y':

        # open a log file 'erna.log'
        file_log = open('erna_log.log', 'w')

        # open an error log file 'erna_err.log'
        err_log = open('erna_err.log', 'w')

        # redirect the stdout to file_log and err_log
        sys.stdout = file_log
        sys.stderr = err_log

        # configure basic logging to send to stdout, level DEBUG, include timestamps
        logging.basicConfig(
            level=logging.DEBUG,
            stream=sys.stdout,
            format=('%(asctime)s - %(levelname)s - %(message)s'))

    # the local date and time when the code will start execution

    date_time = str(datetime.datetime.now().replace(microsecond=0))
    print('\nThe app started running at this time ' + date_time)

    user_input = 'y'
    user_input = utils.get_input_timeout('Enter y to skip next section : ', 10)

    if user_input != 'y':
        # verify if Spark Space exists, if not create Spark Space, and add membership (optional)

        spark_room_id = spark_apis.get_room_id(ROOM_NAME)
        if spark_room_id is None:
            spark_room_id = spark_apis.create_room(ROOM_NAME)
            print('- ', ROOM_NAME, ' -  Spark room created')

            # invite membership to the room
            spark_apis.add_room_membership(spark_room_id, APPROVER_EMAIL)

            spark_apis.post_room_message(ROOM_NAME,
                                         'To require access enter :  IPD')
            spark_apis.post_room_message(ROOM_NAME, 'Ready for input!')
            print('Instructions posted in the room')
        else:
            print('- ', ROOM_NAME, ' -  Existing Spark room found')

            spark_apis.post_room_message(ROOM_NAME,
                                         'To require access enter :  IPD')
            spark_apis.post_room_message(ROOM_NAME, 'Ready for input!')
        print('- ', ROOM_NAME, ' -  Spark room id: ', spark_room_id)

        # check for messages to identify the last message posted and the user's email who posted the message
        # check for the length of time required for access

        last_message = (spark_apis.last_user_message(ROOM_NAME))[0]

        while last_message == 'Ready for input!':
            time.sleep(5)
            last_message = (spark_apis.last_user_message(ROOM_NAME))[0]
            if last_message == 'IPD':
                last_person_email = (
                    spark_apis.last_user_message(ROOM_NAME))[1]
                spark_apis.post_room_message(
                    ROOM_NAME,
                    'How long time do you need access for? (in minutes)  : ')
                time.sleep(10)
                if (
                        spark_apis.last_user_message(ROOM_NAME)
                )[0] == 'How long time do you need access for? (in minutes)  : ':
                    timer = 30 * 60
                else:
                    timer = int(
                        spark_apis.last_user_message(ROOM_NAME)[0]) * 60
            elif last_message != 'Ready for input!':
                spark_apis.post_room_message(ROOM_NAME,
                                             'I do not understand you')
                spark_apis.post_room_message(ROOM_NAME,
                                             'To require access enter :  IPD')
                spark_apis.post_room_message(ROOM_NAME, 'Ready for input!')
                last_message = 'Ready for input!'

        print('\nThe user with this email: ', last_person_email,
              ' asked access to IPD for ', (timer / 60), ' minutes')

    # get the WJT Auth token to access DNA
    dnac_token = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)
    print('\nThe DNA Center auth token is: ', dnac_token)

    # IPD IP address - DNS lookup if available

    IPD_IP = '10.93.140.35'

    # locate IPD in the environment using DNA C
    ipd_location_info = dnac_apis.locate_client_ip(IPD_IP, dnac_token)

    remote_device_hostname = ipd_location_info[
        0]  # the network device the IPD is connected to
    vlan_number = ipd_location_info[2]  # the access VLAN number
    interface_name = ipd_location_info[
        1]  # the interface number is connected to

    device_location = dnac_apis.get_device_location(
        remote_device_hostname, dnac_token)  # network device location
    location_list_info = device_location.split('/')
    remote_device_location = location_list_info[-1]  # select the building name

    print('\nThe IPD is connected to:')
    print('this interface:', interface_name, ', access VLAN:', vlan_number)
    print('on this device:', remote_device_hostname)
    print('located:       ', remote_device_location)

    # request approval

    if user_input != 'y':
        spark_apis.post_room_message(
            ROOM_NAME,
            ('The user with this email ' + last_person_email +
             ' asked access to IPD for ' + str(timer / 60) + ' minutes'))
        spark_apis.post_room_message(
            ROOM_NAME,
            'The IPD is connected to the switch ' + remote_device_hostname +
            ' at our location ' + remote_device_location)
        spark_apis.post_room_message(ROOM_NAME, 'To approve enter: Y/N')

        # check for messages to identify the last message posted and the user's email who posted the message.
        # looking for user - Director email address, and message = 'Y'

        last_message = (spark_apis.last_user_message(ROOM_NAME))[0]

        while last_message == 'To approve enter: Y/N':
            time.sleep(5)
            last_message = (spark_apis.last_user_message(ROOM_NAME))[0]
            approver_email = (spark_apis.last_user_message(ROOM_NAME))[1]
            if last_message == 'y' or 'Y':
                if approver_email == APPROVER_EMAIL:
                    print('Access Approved')
                else:
                    last_message = 'To approve enter: Y/N'

        print('\nApproval process completed')

    # get UCSD API key
    # ucsd_key = get_ucsd_api_key()

    # execute UCSD workflow to connect VDI to VLAN, power on VDI
    # execute_ucsd_workflow(ucsd_key, UCSD_CONNECT_FLOW)

    print('UCSD connect flow executed')

    # deployment of interface configuration files to the DC router
    dc_device_hostname = 'PDX-RO'
    template_project = 'ERNA'
    print('\nThe DC device name is: ', dc_device_hostname)

    dc_int_config_file = 'DC_Interface_Config.txt'
    dc_int_templ = dc_int_config_file.split('.')[
        0]  # select the template name from the template file

    cli_file = open(dc_int_config_file, 'r')  # open file with the template
    cli_config = cli_file.read()  # read the file

    # validation of dc router cli template
    valid = dnac_apis.check_ipv4_duplicate(dc_int_config_file)
    if not valid:
        print('\nDC Router CLI Templates validated')
        dc_temp_valid = True

    dnac_apis.upload_template(dc_int_templ, template_project, cli_config,
                              dnac_token)  # upload the template to DNA C
    depl_id_dc_int = dnac_apis.deploy_template(dc_int_templ, template_project,
                                               dc_device_hostname,
                                               dnac_token)  # deploy
    time.sleep(1)

    # deployment of routing configuration files to the DC router
    dc_rout_config_file = 'DC_Routing_Config.txt'
    dc_rout_templ = dc_rout_config_file.split('.')[
        0]  # select the template name from the template file

    cli_file = open(dc_rout_config_file, 'r')  # open file with the template
    cli_config = cli_file.read()  # read the file

    dnac_apis.upload_template(dc_rout_templ, template_project, cli_config,
                              dnac_token)  # upload the template to DNA C
    depl_id_dc_routing = dnac_apis.deploy_template(dc_rout_templ,
                                                   template_project,
                                                   dc_device_hostname,
                                                   dnac_token)

    print('\nDeployment of the configurations to the DC Router, ',
          dc_device_hostname, 'started')

    time.sleep(1)

    # deployment of interface configuration files to the Remote router

    remote_int_config_file = 'Remote_Interface_Config.txt'
    remote_int_templ = remote_int_config_file.split('.')[
        0]  # select the template name from the template file

    cli_file = open(remote_int_config_file, 'r')  # open file with the template
    cli_config = cli_file.read()  # read the file

    dnac_apis.upload_template(remote_int_templ, template_project, cli_config,
                              dnac_token)  # upload the template to DNA C
    depl_id_remote_int = dnac_apis.deploy_template(remote_int_templ,
                                                   template_project,
                                                   remote_device_hostname,
                                                   dnac_token)  # deploy
    time.sleep(1)

    # deployment of routing configuration files to the Remote router

    remote_rout_config_file = 'Remote_Routing_Config.txt'
    remote_rout_templ = remote_rout_config_file.split('.')[
        0]  # select the template name from the template file

    cli_file = open(remote_rout_config_file,
                    'r')  # open file with the template
    cli_config = cli_file.read()  # read the file

    # update the template with the localized info for the IPD
    # replace the $VlanId with the localized VLAN access
    # replace the $IPD with the IPD ip address

    cli_config = cli_config.replace('$IPD', IPD_IP)
    cli_config = cli_config.replace('$VlanId', vlan_number)

    # validation of remote router cli template
    valid = dnac_apis.check_ipv4_duplicate(cli_config)
    if not valid:
        print('\nRemote Device CLI Templates validated')
        remote_templ_valid = True

    dnac_apis.upload_template(remote_rout_templ, template_project, cli_config,
                              dnac_token)  # upload the template to DNA C
    depl_id_remote_routing = dnac_apis.deploy_template(remote_rout_templ,
                                                       template_project,
                                                       remote_device_hostname,
                                                       dnac_token)  # deploy

    print('\nDeployment of the configurations to the Remote device, ',
          remote_device_hostname, ' started')

    time.sleep(1)

    # check the deployment status after waiting for all jobs to complete - 5 seconds
    print('\nWait for DNA Center to complete template deployments')
    time.sleep(10)

    dc_interface_status = dnac_apis.check_template_deployment_status(
        depl_id_dc_int, dnac_token)
    dc_routing_status = dnac_apis.check_template_deployment_status(
        depl_id_dc_routing, dnac_token)
    remote_interface_status = dnac_apis.check_template_deployment_status(
        depl_id_remote_int, dnac_token)
    remote_routing_status = dnac_apis.check_template_deployment_status(
        depl_id_remote_routing, dnac_token)

    print('Templates deployment status: ', dc_interface_status,
          dc_routing_status, remote_interface_status, remote_routing_status)
    if dc_interface_status == 'SUCCESS' and dc_routing_status == 'SUCCESS' and remote_interface_status == 'SUCCESS' and remote_routing_status == 'SUCCESS':
        print('\nAll templates deployment have been successful\n')
        templ_deploy_status = True

    # synchronization of devices configured - DC and Remote Router
    dc_sync_status = dnac_apis.sync_device(dc_device_hostname, dnac_token)[0]
    remote_sync_status = dnac_apis.sync_device(remote_device_hostname,
                                               dnac_token)[0]

    if dc_sync_status == 202:
        print('\nDNA Center started the DC Router resync')
    if remote_sync_status == 202:
        print('\nDNA Center started the Remote Router resync')

    dc_router_tunnel = netconf_restconf.get_restconf_int_oper_status(
        'Tunnel201')
    remote_router_tunnel = netconf_restconf.get_netconf_int_oper_status(
        'Tunnel201')

    print('\nThe Tunnel 201 interfaces operational state:')
    print('From ', remote_device_hostname, ' using NETCONF -',
          dc_router_tunnel)
    print('From ', dc_device_hostname, ' using RESTCONF -',
          remote_router_tunnel)

    print('\nWait for DNA Center to complete the resync of the two devices')

    time.sleep(240)

    # start a path trace to check the path segmentation
    path_trace_id = dnac_apis.create_path_trace('172.16.202.1', IPD_IP,
                                                dnac_token)

    print('\nWait for Path Trace to complete')
    time.sleep(20)

    path_trace_info = dnac_apis.get_path_trace_info(path_trace_id, dnac_token)
    print('\nPath Trace status: ', path_trace_info[0])
    print('\nPath Trace details: ', path_trace_info[1])

    # create ASAv outside interface ACL to allow traffic

    outside_acl_id = asav_apis.get_asav_access_list(OUTSIDE_INT)
    asav_status = asav_apis.create_asav_access_list(outside_acl_id,
                                                    OUTSIDE_INT, VDI_IP,
                                                    IPD_IP)
    if asav_status == 201:
        print('ASAv access list updated to allow traffic from ', VDI_IP,
              ' to ', VDI_IP, ' on the interface ', OUTSIDE_INT)
    else:
        print('Error updating the ASAv access list on the interface ',
              OUTSIDE_INT)

    # Spark notification

    spark_apis.post_room_message(
        ROOM_NAME,
        'Requested access to this device: IPD, located in our office ' +
        remote_device_location + ' by user ' + last_person_email +
        ' has been granted for ' + str(int(timer / 60)) + ' minutes')

    # Tropo notification - voice call

    voice_notification_result = spark_apis.tropo_notification()

    spark_apis.post_room_message(
        ROOM_NAME, 'Tropo Voice Notification: ' + voice_notification_result)

    # time.sleep(timer)
    input('\nInput any key to continue ! ')

    #
    #  restore configurations to initial state
    #

    #  restore DC router config

    dc_del_file = 'DC_Delete.txt'
    dc_del_templ = dc_del_file.split('.')[0]

    cli_file = open(dc_del_file, 'r')
    cli_config = cli_file.read()

    dnac_apis.upload_template(dc_del_templ, template_project, cli_config,
                              dnac_token)
    depl_id_dc_del = dnac_apis.deploy_template(dc_del_templ, template_project,
                                               dc_device_hostname, dnac_token)

    print('\nDC Router restored to the baseline configuration')

    time.sleep(1)

    #  restore Remote router config

    remote_del_file = 'Remote_Delete.txt'
    remote_del_templ = remote_del_file.split('.')[0]

    cli_file = open(remote_del_file, 'r')
    cli_config = cli_file.read()

    # update the template with the local info for the IPD
    # replace the $VlanId with the local VLAN access
    # replace the $IPD with the IPD ip address

    cli_config = cli_config.replace('$IPD', IPD_IP)
    cli_config = cli_config.replace('$VlanId', vlan_number)

    dnac_apis.upload_template(remote_del_templ, template_project, cli_config,
                              dnac_token)

    print('\nRemote Router restored to the baseline configuration')

    time.sleep(1)

    # remove the ASAv outside interface ACLE that allowed traffic between VDI and IPD

    outside_acl_id = asav_apis.get_asav_access_list(OUTSIDE_INT)
    asav_status = asav_apis.delete_asav_access_list(outside_acl_id,
                                                    OUTSIDE_INT)
    if asav_status == 204:
        print('\nASAv access list on the interface ', OUTSIDE_INT,
              ' restored to the baseline configuration')
    else:
        print('Error while restoring the ASAv access list on the interface ',
              OUTSIDE_INT)

    # execute UCSD workflow to discoconnect VDI to VLAN, power on VDI
    # execute_ucsd_workflow(ucsd_key, UCSD_DISCONNECT_FLOW)

    print('\nUCSD disconnect flow executed')

    # Spark notification

    spark_apis.post_room_message(
        ROOM_NAME, 'Access to this device: IPD has been terminated')

    # update the database with script execution

    access_log_file = open('access_logs.csv', 'a')
    data_to_append = [
        date_time, last_person_email, IPD_IP, approver_email, dc_temp_valid,
        remote_templ_valid, templ_deploy_status, dc_router_tunnel,
        remote_router_tunnel, path_trace_info
    ]
    access_log_file.write(data_to_append)
    access_log_file.close()

    print('\nRecords database updated, file saved')

    # restore the stdout to initial value
    sys.stdout = initial_sys

    # the local date and time when the code will end execution

    date_time = str(datetime.datetime.now().replace(microsecond=0))

    print('\n\nEnd of application run at this time ', date_time)
Example #10
0
def main():
    """
    This script will monitor device configuration changes. It could be executed on demand as in this lab, or periodically,
    every 60 minutes (for example). It will collect the configuration file for each device, compare with the existing cached file,
    detect if any changes.
    When changes detected, identify the last user that configured the device, and create a new ServiceNoe incident.
    """

    # get the DNA C auth token
    dnac_token = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)
    print('\nDNA C AUTH TOKEN: ', dnac_token, '\n')

    temp_run_config = 'temp_run_config.txt'

    # get the DNA C managed devices list (excluded wireless)
    all_devices_info = dnac_apis.get_all_device_info(dnac_token)
    all_devices_hostnames = []
    for device in all_devices_info:
        if device['family'] == 'Switches and Hubs' or device[
                'family'] == 'Routers':
            all_devices_hostnames.append(device['hostname'])

    # get the config files, compare with existing (if one existing). Save new config if file not existing.
    for device in all_devices_hostnames:
        device_run_config = dnac_apis.get_output_command_runner(
            'show running-config', device, dnac_token)
        filename = str(device) + '_run_config.txt'

        # save the running config to a temp file

        f_temp = open(temp_run_config, 'w')
        f_temp.write(device_run_config)
        f_temp.seek(0)  # reset the file pointer to 0
        f_temp.close

        # check if device has an existing configuration file (to account for newly discovered DNA C devices)
        # if yes, run the diff function
        # if not, save the device configuration to the local device database

        if os.path.isfile(filename):
            diff = compare_configs(filename, temp_run_config)
            if diff != '':

                # retrieve the device location using DNA C REST APIs
                location = dnac_apis.get_device_location(device, dnac_token)

                # find the users that made configuration changes
                with open(temp_run_config, 'r') as f:
                    user_info = 'User info no available'
                    for line in f:
                        if 'Last configuration change' in line:
                            user_info = line

                # get the device management IP address
                device_mngmnt_ip_address = dnac_apis.get_device_management_ip(
                    device, dnac_token)

                # define the incident description and comment
                short_description = "Configuration Change Alert"
                comment = "The device with the name: " + device + "\nhas detected a Configuration Change"
                comment += "\n\nThe device location is: " + location
                comment += "\n\nThe device management IP address is: " + device_mngmnt_ip_address
                comment += "\n\nThe configuration changes are\n" + diff + "\n\n" + user_info

                print(comment)

                # create ServiceNow incident using ServiceNow APIs
                incident = service_now_apis.create_incident(
                    short_description, comment, SNOW_DEV, 3)
            else:
                print('Device: ' + device +
                      ' - No configuration changes detected')

        else:
            f_config = open(filename, "w")
            f_config.write(device_run_config)
            f_config.seek(0)
            f_config.close
Example #11
0
def main():
    """
    This script will deploy a config file to a number of devices based on device family.
    The device family is defined by a list "DEVICE_TYPES"
    It will collect all the devices that match the device types, identify those that are reachable, and those that are
    not reachable.
    The script will deploy the configuration template to each reachable device.
    There are some optional commands included that will allow to test the template deployment to a small number of
    devices first.
    """

    # the local date and time when the code will start execution

    date_time = str(datetime.datetime.now().replace(microsecond=0))

    print('\n\nApplication "deploy_configs.py" Run Started: ' + date_time)

    # get a Cisco DNA Center auth token
    dnac_auth = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)

    # verify if existing template in the project
    template_id = dnac_apis.get_template_id(DEPLOY_TEMPLATE, DEPLOY_PROJECT,
                                            dnac_auth)

    print('\nThe template "' + DEPLOY_TEMPLATE + '" id is: ', template_id)

    # find all devices managed by Cisco DNA C, that are "switches and hubs"
    device_list = dnac_apis.get_all_device_list(500, dnac_auth)

    # create the switches list
    switch_list_reachable = []
    switch_list_unreachable = []

    # identify all devices that match the device type
    for device in device_list:
        device_type = device['type']
        if device_type in DEVICE_TYPES:
            hostname = device['hostname']
            if device['reachabilityStatus'] == 'Reachable':
                switch_list_reachable.append(hostname)
            else:
                switch_list_unreachable.append(hostname)

    print(
        '\nThe unreachable devices to which the template will not be deployed are:',
        switch_list_unreachable, '\n')
    print('\nThe devices to which the template will be deployed are:',
          switch_list_reachable)
    total_number_devices = len(switch_list_reachable)
    print('\nThe number of devices to deploy the template to is: ',
          total_number_devices)

    # we will configure a number of devices equal with "device_count" starting with the device from the list
    # identified with "first_record"

    first_record = int(
        input(
            '\nWhat is the device index you want to start with ? (integer between 0 and '
            + str(total_number_devices) + ')  '))
    device_count = int(input('How many devices do you want to configure ?  '))
    if device_count + first_record >= total_number_devices:
        device_count = total_number_devices - first_record
        print('Changed the number of the devices to maximum allowed: ',
              device_count)

    device_index = first_record

    # create a list with the structure [[device hostname, deployment status},...]
    deployment_report = []

    for switch in switch_list_reachable[first_record:first_record +
                                        device_count]:
        # deploy the template

        # get a Cisco DNA Center auth token, required for mass device configs, script running will take longer than
        # 60 min.
        dnac_auth = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)

        deployment_id = dnac_apis.send_deploy_template_no_params(
            DEPLOY_TEMPLATE, DEPLOY_PROJECT, switch, dnac_auth)

        print('\nTemplate "' + DEPLOY_TEMPLATE + '" started, task id: "' +
              deployment_id + '"')
        time.sleep(5)  # wait for the deployment task to be created

        deployment_status = dnac_apis.check_template_deployment_status(
            deployment_id, dnac_auth)
        print('Deployment task result for switch: ', switch, ' is: ',
              deployment_status, ', device index: ', device_index)
        device_index += 1

        deployment_report.append([switch, deployment_id, deployment_status])

        # optional for manual deployment to test
        # value = input('Input y/n to continue ')
        # if value == 'n':
        #    break

    print('\nThe deployment report:\n')
    for item in deployment_report:
        print(item)

    date_time = str(datetime.datetime.now().replace(microsecond=0))
    # save information to file
    file_name = 'deployment_report-' + str(date_time) + '.csv'
    file_name = file_name.replace(' ', '-')
    output_file = open(file_name, 'w', newline='')
    output_writer = csv.writer(output_file)

    # loop through all devices and deployment status to collect the information needed in the report
    for device in deployment_report:
        device_info = [device[0], device[1], device[2]]
        output_writer.writerow(device_info)
    output_file.close()
    print('\n\nFile ' + file_name + ' saved')

    date_time = str(datetime.datetime.now().replace(microsecond=0))
    print('\n\nEnd of Application "deploy_configs.py" Run: ' + date_time)
    return
    "show logging | in %PLATFORM_FEP-6-FRU_PS_OIR: Switch 1: FRU power supply A powered off"
)
syslog_lines = syslog_input.split("\n")
lines_no = len(syslog_lines) - 2
syslog_info = syslog_lines[lines_no]

# retrieve the device hostname using RESTCONF
device_name = restconf.get_restconf_hostname(DEV_IP)

# retrieve the serial number using Python cli
device_info = cli("sh ver | in System Serial Number")
device_info_list = device_info.split(' ')
device_sn = device_info_list[-1]

# retrieve the device location using DNAC REST APIs
dnac_token = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)
location = dnac_apis.get_device_location(device_name, dnac_token)

# define the incident description and comment
short_description = "Redundant Power Supply Failure - IOS XE Automation"
comment = "The device with the name: " + device_name + "\n has detected a Redundant Power Supply failure"
comment += "\n\nThe device serial number: " + device_sn
comment += "\nThe device location is: " + location
comment += "\n\nSyslog: " + syslog_info + "\n\nSwitch Beacon LED turned ON"

# create a new ServiceNow incident using ServiceNow APIs
incident = service_now_apis.create_incident(short_description, comment,
                                            SNOW_DEV, 2)

# write the new incident name to file in /bootflash/WoS-Demo
incident_file = open("/bootflash/WoS-Demo/power_ticket.txt", "w")
Example #13
0
def main():
    """
    Vendor will join Webex Teams Room with the name {ROOM_NAME}
    It will ask for access to an IP-enabled device - named {IPD}
    The code will map this IP-enabled device to the IP address {10.93.140.35}
    Access will be provisioned to allow connectivity from DMZ VDI to IPD
    """

    # save the initial stdout
    initial_sys = sys.stdout

    # the user will be asked if interested to run in demo mode or in
    # production (logging to files - erna_log.log, erna_err.log))

    # user_input = utils.get_input_timeout('If running in Demo Mode please enter y ', 10)

    user_input = 'y'  # remove this line if you want to run in production
    if user_input != 'y':

        # open a log file 'erna.log'
        file_log = open('erna_log.log', 'w')

        # open an error log file 'erna_err.log'
        err_log = open('erna_err.log', 'w')

        # redirect the stdout to file_log and err_log
        sys.stdout = file_log
        sys.stderr = err_log

        # configure basic logging to send to stdout, level DEBUG, include timestamps
        logging.basicConfig(level=logging.DEBUG,
                            stream=sys.stdout,
                            format='%(asctime)s - %(levelname)s - %(message)s')

    # logging, debug level, to file {erna_run.log}
    logging.basicConfig(
        filename='erna_run.log',
        level=logging.DEBUG,
        format=
        '%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S')

    # the local date and time when the code will start execution

    date_time = str(datetime.datetime.now().replace(microsecond=0))
    print('\nThe Application "ERNA.py" started running at this time ' +
          date_time)

    user_input = utils.get_input_timeout('Enter y to skip next section : ', 10)

    user_input = 'y'  # remove this line if you want to follow the approval process

    if user_input != 'y':
        # verify if Webex Teams Space exists, if not create Webex Teams Space, and add membership (optional)

        webex_teams_room_id = webex_teams_apis.get_space_id(ROOM_NAME)
        if webex_teams_room_id is None:
            webex_teams_room_id = webex_teams_apis.create_space(ROOM_NAME)
            print('- ', ROOM_NAME, ' -  Webex Teams room created')

            # invite membership to the room
            webex_teams_apis.add_space_membership(ROOM_NAME, APPROVER_EMAIL)

            webex_teams_apis.post_space_message(
                ROOM_NAME, 'To require access enter :  IPD')
            webex_teams_apis.post_space_message(ROOM_NAME, 'Ready for input!')
            print('Instructions posted in the room')
        else:
            print('- ', ROOM_NAME, ' -  Existing Webex Teams room found')

            webex_teams_apis.post_space_message(
                ROOM_NAME, 'To require access enter :  IPD')
            webex_teams_apis.post_space_message(ROOM_NAME, 'Ready for input!')
        print('- ', ROOM_NAME, ' -  Webex Teams room id: ',
              webex_teams_room_id)

        # check for messages to identify the last message posted and the user's email who posted the message
        # check for the length of time required for access

        last_message = (webex_teams_apis.last_user_message(ROOM_NAME))[0]

        while last_message == 'Ready for input!':
            time.sleep(5)
            last_message = (webex_teams_apis.last_user_message(ROOM_NAME))[0]
            if last_message == 'IPD':
                last_person_email = (
                    webex_teams_apis.last_user_message(ROOM_NAME))[1]
                webex_teams_apis.post_space_message(
                    ROOM_NAME,
                    'How long time do you need access for? (in minutes)  : ')
                time.sleep(10)
                if (
                        webex_teams_apis.last_user_message(ROOM_NAME)
                )[0] == 'How long time do you need access for? (in minutes)  : ':
                    timer = 30 * 60
                else:
                    timer = int(
                        webex_teams_apis.last_user_message(ROOM_NAME)[0]) * 60
            elif last_message != 'Ready for input!':
                webex_teams_apis.post_space_message(ROOM_NAME,
                                                    'I do not understand you')
                webex_teams_apis.post_space_message(
                    ROOM_NAME, 'To require access enter :  IPD')
                webex_teams_apis.post_space_message(ROOM_NAME,
                                                    'Ready for input!')
                last_message = 'Ready for input!'

        print('\nThe user with this email: ', last_person_email,
              ' asked access to IPD for ', (timer / 60), ' minutes')

    # get the WJT Auth token to access DNA
    dnac_token = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)
    print('\nThe DNA Center auth token is: ', dnac_token)

    # IPD IP address - DNS lookup if available

    IPD_IP = '10.93.140.35'
    last_person_email = '*****@*****.**'
    approver_email = '*****@*****.**'
    timer = 3600

    # locate IPD in the environment using DNA C
    ipd_location_info = dnac_apis.locate_client_ip(IPD_IP, dnac_token)

    remote_device_hostname = ipd_location_info[
        0]  # the network device the IPD is connected to
    vlan_number = ipd_location_info[2]  # the access VLAN number
    interface_name = ipd_location_info[
        1]  # the interface number is connected to

    device_location = dnac_apis.get_device_location(
        remote_device_hostname, dnac_token)  # network device location
    location_list_info = device_location.split('/')
    remote_device_location = location_list_info[-1]  # select the building name

    log_ipd_info = '\n\nThe IPD is connected to this device: ' + remote_device_hostname
    log_ipd_info += '\n\nThis interface: ' + interface_name + ', access VLAN: ' + vlan_number
    log_ipd_info += '\n\nLocated       : ' + remote_device_location
    print(log_ipd_info)

    # request approval

    if user_input != 'y':
        webex_teams_apis.post_space_message(
            ROOM_NAME,
            ('The user with this email ' + last_person_email +
             ' asked access to IPD for ' + str(timer / 60) + ' minutes'))
        webex_teams_apis.post_space_message(
            ROOM_NAME,
            'The IPD is connected to the switch ' + remote_device_hostname +
            ' at our location ' + remote_device_location)
        webex_teams_apis.post_space_message(ROOM_NAME, 'To approve enter: Y/N')

        # check for messages to identify the last message posted and the user's email who posted the message.
        # looking for user - Director email address, and message = 'Y'

        last_message = (webex_teams_apis.last_user_message(ROOM_NAME))[0]

        while last_message == 'To approve enter: Y/N':
            time.sleep(5)
            last_message = (webex_teams_apis.last_user_message(ROOM_NAME))[0]
            approver_email = (webex_teams_apis.last_user_message(ROOM_NAME))[1]
            if last_message == 'y' or 'Y':
                if approver_email == APPROVER_EMAIL:
                    print('Access Approved')
                else:
                    last_message = 'To approve enter: Y/N'

        print('\nApproval process completed')

    # get UCSD API key
    # ucsd_key = ucsd_apis.get_ucsd_api_key()

    # execute UCSD workflow to connect VDI to VLAN, power on VDI
    # ucsd_apis.execute_ucsd_workflow(ucsd_key, UCSD_CONNECT_FLOW)

    log_ucsd_info = '\n\nUCSD connect flow executed'
    print(log_ucsd_info)

    # deployment of cli configuration files to the dc router

    dc_device_hostname = 'PDX-RO'
    template_project = 'ERNA'
    print('\nThe DC device name is: ', dc_device_hostname)

    dc_config_file = 'DC_Config.txt'
    dc_config_templ = dc_config_file.split('.')[
        0]  # select the template name from the template file

    cli_file = open(dc_config_file, 'r')  # open file with the template
    cli_config = cli_file.read()  # read the file

    # validation of dc router cli template
    dc_valid = dnac_apis.check_ipv4_duplicate(dc_config_file)
    log_dc_info = ''
    if dc_valid is False:
        print('\n\nDC Router CLI Template validated')
        log_dc_info = '\n\nDC Router CLI Templates validated'

    dnac_apis.upload_template(dc_config_templ, template_project, cli_config,
                              dnac_token)  # upload the template to DNA C
    depl_id_dc = dnac_apis.deploy_template(dc_config_templ, template_project,
                                           dc_device_hostname,
                                           dnac_token)  # deploy dc template

    log_dc_info += '\n\nDeployment of the configurations to the DC router, ' + dc_device_hostname
    log_dc_info += ' started, deployment id: ' + depl_id_dc
    log_dc_config = '\nDC Router Config \n\n' + cli_config
    print(log_dc_info)

    time.sleep(1)

    # deployment of cli configuration files to the remote router

    remote_config_file = 'Remote_Config.txt'
    remote_config_templ = remote_config_file.split('.')[
        0]  # select the template name from the template file

    cli_file = open(remote_config_file, 'r')  # open file with the template
    cli_config = cli_file.read()  # read the file

    # update the template with the localized info for the IPD
    # replace the $VlanId with the localized VLAN access
    # replace the $IPD with the IPD ip address

    cli_config = cli_config.replace('$IPD', IPD_IP)
    cli_config = cli_config.replace('$VlanId', vlan_number)

    remote_updated_config_file = 'Remote_Config_Updated.txt'
    updated_cli_file = open(remote_updated_config_file, 'w')
    updated_cli_file.write(cli_config)
    updated_cli_file.close()

    # validation of remote router cli template
    remote_valid = dnac_apis.check_ipv4_duplicate(remote_updated_config_file)
    log_remote_info = ''
    if remote_valid is False:
        log_remote_info = '\n\nRemote Device CLI Template validated'
        print(log_remote_info)

    dnac_apis.upload_template(remote_config_templ, template_project,
                              cli_config,
                              dnac_token)  # upload the template to DNA C
    depl_id_remote = dnac_apis.deploy_template(
        remote_config_templ, template_project, remote_device_hostname,
        dnac_token)  # deploy remote template
    time.sleep(1)

    log_remote_info += '\n\nDeployment of the configurations to the Remote device, ' + remote_device_hostname
    log_remote_info += ' started, deployment id: ' + depl_id_remote
    log_remote_config = '\nRemote Device Config \n\n' + cli_config
    print(log_remote_info)

    time.sleep(1)

    # check the deployment status after waiting for all jobs to complete - 10 seconds
    print('\nWait for DNA Center to complete template deployments')
    time.sleep(10)

    dc_status = dnac_apis.check_template_deployment_status(
        depl_id_dc, dnac_token)
    remote_status = dnac_apis.check_template_deployment_status(
        depl_id_remote, dnac_token)

    log_templ_depl_info = '\n\nTemplates deployment status DC: ' + dc_status + ', Remote: ' + remote_status
    print(log_templ_depl_info)

    if dc_status == 'SUCCESS' and remote_status == 'SUCCESS':
        print('\nAll templates deployment have been successful\n')
        templ_deploy_status = True

    # synchronization of devices configured - DC and Remote Router
    dc_sync_status = dnac_apis.sync_device(dc_device_hostname, dnac_token)[0]
    remote_sync_status = dnac_apis.sync_device(remote_device_hostname,
                                               dnac_token)[0]

    if dc_sync_status == 202:
        print('\nDNA Center started the DC Router resync')
    if remote_sync_status == 202:
        print('\nDNA Center started the Remote Router resync')

    dc_router_tunnel = netconf_restconf.get_restconf_int_oper_status(
        'Tunnel201')
    remote_router_tunnel = netconf_restconf.get_netconf_int_oper_status(
        'Tunnel201')

    log_tunnel_info = '\n\nThe Tunnel 201 interfaces operational state: '
    log_tunnel_info += '\n\nFrom ' + remote_device_hostname + ' using NETCONF - ' + dc_router_tunnel
    log_tunnel_info += '\n\nFrom ' + dc_device_hostname + ' using RESTCONF - ' + remote_router_tunnel

    print(log_tunnel_info)

    print('\nWait for DNA Center to complete the resync of the two devices')

    time.sleep(180)

    print('\nSync completed, Path Trace started')
    # start a path trace to check the path segmentation
    path_trace_id = dnac_apis.create_path_trace('172.16.202.1', IPD_IP,
                                                dnac_token)

    print('\nWait for Path Trace to complete')
    time.sleep(30)

    path_trace_info = dnac_apis.get_path_trace_info(path_trace_id, dnac_token)

    log_path_trace = '\n\nPath Trace status: ' + path_trace_info[0]
    log_path_trace += '\n\nPath Trace details: ' + str(path_trace_info[1])
    print(log_path_trace)

    # create ASAv outside interface ACL to allow traffic

    outside_acl_id = asav_apis.get_asav_access_list(OUTSIDE_INT)
    asav_status = asav_apis.create_asav_access_list(outside_acl_id,
                                                    OUTSIDE_INT, VDI_IP,
                                                    IPD_IP)
    if asav_status == 201:
        log_asav_info = '\n\nASAv access list updated to allow traffic from ' + VDI_IP + ' to ' + IPD_IP + ' on the interface ' + OUTSIDE_INT
    else:
        log_asav_info = '\n\nError updating the ASAv access list on the interface ' + OUTSIDE_INT
    print(log_asav_info)

    # Webex Teams notification

    webex_teams_apis.post_space_message(
        ROOM_NAME,
        'Requested access to this device: IPD, located in our office: ' +
        remote_device_location + ' by user ' + last_person_email +
        ' has been granted for ' + str(int(timer / 60)) + ' minutes')
    log_access_info = '\n\nRequested access to this device: IPD, located in our office: '
    log_access_info += remote_device_location + ' by user: '******' has been granted for ' + str(
        int(timer / 60)) + ' minutes'

    # create and update ServiceNow incident

    snow_user = '******'
    snow_description = 'ERNA Automation - Vendor Remote Access to IPD: ' + IPD_IP

    snow_incident = service_now_apis.create_incident(snow_description,
                                                     log_ipd_info, snow_user,
                                                     '2')
    comments = log_ucsd_info + log_dc_info + log_dc_config + log_remote_info + log_remote_config + log_templ_depl_info
    comments += log_tunnel_info + log_path_trace + log_asav_info + log_access_info
    service_now_apis.update_incident(snow_incident, comments, snow_user)

    date_time = str(datetime.datetime.now().replace(microsecond=0))
    print('\n\nEnd of application "ERNA.py" provisioning run at this time ',
          date_time)

    # time.sleep(timer)  # un-comment this line if time limit is required
    input('Press any key to continue de-provisioning  ')

    #
    #  restore configurations to initial state
    #

    #  restore DC router config

    dc_rem_file = 'DC_Remove.txt'
    dc_rem_templ = dc_rem_file.split('.')[0]

    cli_file = open(dc_rem_file, 'r')
    cli_config = cli_file.read()

    dnac_apis.upload_template(dc_rem_templ, template_project, cli_config,
                              dnac_token)
    depl_id_dc_rem = dnac_apis.deploy_template(dc_rem_templ, template_project,
                                               dc_device_hostname, dnac_token)

    print('\nDC Router restored to the baseline configuration')
    log_remove_info = '\n\nDC Router restored to the baseline configuration'

    time.sleep(1)

    #  restore Remote router config

    remote_rem_file = 'Remote_Remove.txt'
    remote_rem_templ = remote_rem_file.split('.')[0]

    cli_file = open(remote_rem_file, 'r')
    cli_config = cli_file.read()

    # update the template with the local info for the IPD
    # replace the $VlanId with the local VLAN access
    # replace the $IPD with the IPD ip address

    cli_config = cli_config.replace('$IPD', IPD_IP)
    cli_config = cli_config.replace('$VlanId', vlan_number)

    remote_updated_remove_file = 'Remote_Remove_Updated.txt'
    updated_cli_file = open(remote_updated_remove_file, 'w')
    updated_cli_file.write(cli_config)
    updated_cli_file.close()

    dnac_apis.upload_template(remote_rem_templ, template_project, cli_config,
                              dnac_token)
    depl_id_remote_rem = dnac_apis.deploy_template(remote_rem_templ,
                                                   template_project,
                                                   remote_device_hostname,
                                                   dnac_token)

    print('\nRemote Router restored to the baseline configuration')
    log_remove_info += '\n\nRemote Device restored to the baseline configuration'

    time.sleep(1)

    # remove the ASAv outside interface ACLE that allowed traffic between VDI and IPD

    outside_acl_id = asav_apis.get_asav_access_list(OUTSIDE_INT)
    asav_status = asav_apis.delete_asav_access_list(outside_acl_id,
                                                    OUTSIDE_INT)
    if asav_status == 204:
        log_asav_remove_info = '\n\nASAv access list on the interface ' + OUTSIDE_INT + ' restored to the baseline configuration'
    else:
        log_asav_remove_info = 'Error while restoring the ASAv access list on the interface ' + OUTSIDE_INT
    print(log_asav_remove_info)

    # execute UCSD workflow to disconnect VDI to VLAN, power on VDI
    # ucsd_apis.execute_ucsd_workflow(ucsd_key, UCSD_DISCONNECT_FLOW)

    log_ucsd_remove_info = '\n\nUCSD disconnect flow executed'
    print(log_ucsd_remove_info)

    # sync the remote and DC device
    dc_sync_status = dnac_apis.sync_device(dc_device_hostname, dnac_token)[0]
    remote_sync_status = dnac_apis.sync_device(remote_device_hostname,
                                               dnac_token)[0]

    log_sync_info = ''
    if dc_sync_status == 202:
        log_sync_info = '\n\nDNA Center started the DC Router resync'
    if remote_sync_status == 202:
        log_sync_info += '\n\nDNA Center started the Remote Router resync'

    print(log_sync_info)

    # Webex Teams notification

    webex_teams_apis.post_space_message(
        ROOM_NAME, 'Access to this device: IPD has been terminated')
    webex_teams_apis.post_space_message(
        ROOM_NAME, '----------------------------------------------')

    # update the database with script execution

    access_log_file = open('access_logs.csv', 'a')
    data_to_append = str('\n\n' + date_time) + ','
    access_log_file.write(data_to_append)
    data_to_append = last_person_email + ',' + log_ipd_info + ',' + approver_email
    data_to_append += ',' + log_dc_info + ',' + log_remote_info + ',' + log_templ_depl_info + ','
    data_to_append += log_path_trace + ',' + log_asav_info + ',\n' + snow_incident
    data_to_append_nolines = data_to_append.replace('\n\n', '\n')
    access_log_file.write(data_to_append_nolines)
    access_log_file.close()

    print('\nRecords database updated, file saved')

    comments = log_remove_info + log_asav_remove_info + log_ucsd_remove_info + log_sync_info
    service_now_apis.update_incident(snow_incident, comments, snow_user)

    # restore the stdout to initial value
    sys.stdout = initial_sys

    # the local date and time when the code will end execution

    date_time = str(datetime.datetime.now().replace(microsecond=0))
    print('\n\nEnd of application "ERNA.py" run at this time ', date_time)
Example #14
0
def main():
    """
    This script will monitor device configuration changes. It could be executed on demand,
    periodically (every 60 minutes, for example) or continuously.
    It will collect the configuration file for each DNA Center managed device, compare with the existing cached file,
    and detect if any changes.
    When changes detected, identify the last user that configured the device, and create a new ServiceNow incident.
    Automatically roll back all non-compliant configurations, or save new configurations if approved in ServiceNow.
    Device configuration files managemnt using RESTCONF and NETCONF
    Compliance checks at this time:
    - no Access Control Lists changes
    - no logging changes
    - no duplicated IPv4 addresses
    """

    # run the demo continuously, looping

    print('Application config_mon.py started')
    # create a local directory for all the configuration files
    # check if 'Config_Files' folder exists and create one if it does not

    if not os.path.exists('Config_Files'):
        os.makedirs('Config_Files')

    os.chdir('Config_Files')

    # logging, debug level, to file {application_run.log}
    logging.basicConfig(
        filename='application_run.log',
        level=logging.DEBUG,
        format=
        '%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S')

    while True:

        # get the DNA C auth token
        dnac_token = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)
        print('\nDNA C AUTH TOKEN: ', dnac_token, '\n')

        temp_run_config = 'temp_run_config.txt'

        # get the DNA C managed devices list (excluded wireless, for one location)
        all_devices_info = dnac_apis.get_all_device_info(dnac_token)
        all_devices_hostnames = []
        for device in all_devices_info:
            if device['family'] == 'Switches and Hubs' or device[
                    'family'] == 'Routers':
                if IOS_XE_HOSTNAME in device['hostname']:
                    all_devices_hostnames.append(device['hostname'])

        # get the config files, compare with existing (if one existing). Save new config if file not existing.
        for device in all_devices_hostnames:
            device_run_config = dnac_apis.get_output_command_runner(
                'show running-config', device, dnac_token)
            filename = str(device) + '_run_config.txt'

            # save the running config to a temp file

            f_temp = open(temp_run_config, 'w')
            f_temp.write(device_run_config)
            f_temp.seek(0)  # reset the file pointer to 0
            f_temp.close()

            # check if device has an existing configuration file (to account for newly discovered DNA C devices)
            # if yes, run the diff function
            # if not, save the device configuration to the local device database
            # this will create the local "database" of configs, one file/device

            if os.path.isfile(filename):
                diff = compare_configs(filename, temp_run_config)

                if diff != '':

                    # retrieve the device location using DNA C REST APIs
                    location = dnac_apis.get_device_location(
                        device, dnac_token)

                    # find the users that made configuration changes
                    with open(temp_run_config, 'r') as f:
                        user_info = 'User info no available'
                        for line in f:
                            if 'Last configuration change' in line:
                                user_info = line

                    # define the incident description and comment
                    short_description = 'Configuration Change Alert - ' + device
                    comment = 'The device with the name: ' + device + '\nhas detected a Configuration Change'

                    print(comment)

                    # create ServiceNow incident using ServiceNow APIs
                    incident = service_now_apis.create_incident(
                        short_description, comment, SNOW_DEV, 3)

                    # get the device health from DNA Center
                    current_time_epoch = utils.get_epoch_current_time()
                    device_details = dnac_apis.get_device_health(
                        device, current_time_epoch, dnac_token)

                    device_sn = device_details['serialNumber']
                    private_mngmnt_ip_address = device_details[
                        'managementIpAddr']
                    device_mngmnt_ip_address = NAT[private_mngmnt_ip_address]
                    device_family = device_details['platformId']
                    device_os_info = device_details[
                        'osType'] + ',  ' + device_details['softwareVersion']
                    device_health = device_details['overallHealth']

                    updated_comment = '\nDevice location: ' + location
                    updated_comment += '\nDevice family: ' + device_family
                    updated_comment += '\nDevice OS info: ' + device_os_info
                    updated_comment += '\nDevice S/N: ' + device_sn
                    updated_comment += '\nDevice Health: ' + str(
                        device_health) + '/10'
                    updated_comment += '\nDevice management IP address: ' + device_mngmnt_ip_address

                    print(updated_comment)

                    # update ServiceNow incident
                    service_now_apis.update_incident(incident, updated_comment,
                                                     SNOW_DEV)

                    updated_comment = '\nThe configuration changes are\n' + diff + '\n\n' + user_info

                    print(updated_comment)

                    # update ServiceNow incident
                    service_now_apis.update_incident(incident, updated_comment,
                                                     SNOW_DEV)

                    # start the compliance validation
                    # ACL changes
                    validation_result = 'Pass'
                    validation_comment = ''
                    if ('+access-list' in diff) or ('-access-list' in diff):
                        updated_comment = '\nValidation against ACL changes failed'
                        service_now_apis.update_incident(
                            incident, updated_comment, SNOW_DEV)
                        validation_result = 'Failed'
                    else:
                        validation_comment = '\nPassed ACL Policy'

                    # logging changes
                    if ('+logging' in diff) or ('-logging' in diff):
                        updated_comment = '\nValidation against logging changes failed'
                        service_now_apis.update_incident(
                            incident, updated_comment, SNOW_DEV)
                        validation_result = 'Failed'
                    else:
                        validation_comment += '\nPassed Logging Policy'

                    # IPv4 duplicates
                    diff_list = diff.split('\n')
                    diff_config = '!\n'
                    for command in diff_list:
                        if 'ip address' in command:
                            diff_config += command.replace('+', '') + '\n!'

                    # save the diff config that include only IP addresses in a file
                    f_diff = open('temp_config_file.txt', 'w')
                    f_diff.write(diff_config)
                    f_diff.seek(0)  # reset the file pointer to 0
                    f_diff.close()

                    duplicate_ip_result = dnac_apis.check_ipv4_duplicate(
                        'temp_config_file.txt')
                    if duplicate_ip_result:
                        updated_comment = '\nValidation against duplicated IPv4 addresses failed'
                        service_now_apis.update_incident(
                            incident, updated_comment, SNOW_DEV)
                        validation_result = 'Failed'
                    else:
                        validation_comment += '\nPassed Duplicate IPv4 Prevention'

                    print(updated_comment)

                    # procedure to restore configurations as policy validations failed
                    if validation_result == 'Failed':
                        updated_comment = '\nConfiguration changes do not pass validation,\nConfiguration roll back initiated'
                        service_now_apis.update_incident(
                            incident, updated_comment, SNOW_DEV)

                        print(updated_comment)

                        # start the config roll back
                        baseline_config = 'flash:/config_mon_baseline'
                        netconf_restconf.restconf_rollback_to_saved_config(
                            baseline_config, device_mngmnt_ip_address,
                            IOS_XE_USER, IOS_XE_PASS)

                        # check if rollback is successful after 5 seconds
                        time.sleep(5)
                        device_run_config = dnac_apis.get_output_command_runner(
                            'show running-config', device, dnac_token)
                        filename = str(device) + '_run_config.txt'

                        # save the running config to a temp file
                        f_temp = open(temp_run_config, 'w')
                        f_temp.write(device_run_config)
                        f_temp.seek(0)  # reset the file pointer to 0
                        f_temp.close()

                        diff = compare_configs(filename, temp_run_config)
                        if diff != ' ':
                            updated_comment = '\nConfiguration rolled back successfully'
                            service_now_apis.update_incident(
                                incident, updated_comment, SNOW_DEV)
                            # close ServiceNow incident
                            service_now_apis.close_incident(incident, SNOW_DEV)
                        else:
                            updated_comment = '\nConfiguration rolled back not successful'
                            service_now_apis.update_incident(
                                incident, updated_comment, SNOW_DEV)

                    # start procedure to ask for approval as validation passed
                    else:
                        service_now_apis.update_incident(
                            incident, 'Approve these changes (YES/NO)?\n' +
                            validation_comment, SNOW_DEV)
                        service_now_apis.update_incident(
                            incident, 'Waiting for Management Approval',
                            SNOW_DEV)

                        print(
                            '\nConfiguration changes pass compliance checks, approval waiting'
                        )

                        # start the approval YES/NO procedure
                        # start a loop to check for 2 min if approved of not
                        approval = 'NO'
                        timer_count = 0
                        while timer_count <= 5:
                            if service_now_apis.find_comment(incident, 'YES'):

                                # start the save of running config to new baseline on device
                                # flash:/config_mon_baseline

                                netconf_restconf.netconf_save_running_config_to_file(
                                    'flash:/config_mon_baseline',
                                    device_mngmnt_ip_address, IOS_XE_PORT,
                                    IOS_XE_USER, IOS_XE_PASS)

                                print(
                                    'New baseline configuration saved on network device: '
                                    + device)

                                # establish new baseline config on server
                                time.sleep(5)
                                device_run_config = dnac_apis.get_output_command_runner(
                                    'show running-config', device, dnac_token)
                                filename = str(device) + '_run_config.txt'

                                # save the running config to the device config file
                                f_temp = open(filename, 'w')
                                f_temp.write(device_run_config)
                                f_temp.seek(0)  # reset the file pointer to 0
                                f_temp.close()

                                approval = 'YES'

                                # update ServiceNow incident
                                updated_comment = '\nApproval received, saved device configuration, established new baseline configuration'
                                print(updated_comment)

                                service_now_apis.update_incident(
                                    incident, updated_comment, SNOW_DEV)
                                service_now_apis.close_incident(
                                    incident, SNOW_DEV)
                                break
                            elif service_now_apis.find_comment(incident, 'NO'):
                                break
                            else:
                                timer_count += 1
                                time.sleep(10)
                                if timer_count == 5:
                                    service_now_apis.update_incident(
                                        incident, 'Approval Timeout', SNOW_DEV)

                        # check if Approval is 'NO' at the end of the timer
                        if approval == 'NO':

                            # start the config roll back
                            baseline_config = 'flash:/config_mon_baseline'
                            netconf_restconf.restconf_rollback_to_saved_config(
                                baseline_config, device_mngmnt_ip_address,
                                IOS_XE_USER, IOS_XE_PASS)

                            # check if rollback is successful after 3 seconds
                            time.sleep(5)
                            device_run_config = dnac_apis.get_output_command_runner(
                                'show running-config', device, dnac_token)
                            # save the running config to a temp file
                            f_temp = open(temp_run_config, 'w')
                            f_temp.write(device_run_config)
                            f_temp.seek(0)  # reset the file pointer to 0
                            f_temp.close()

                            filename = str(device) + '_run_config.txt'

                            diff = compare_configs(filename, temp_run_config)
                            if diff != ' ':
                                updated_comment = '\nConfiguration changes not approved,\nConfiguration rolled back successfully'
                                print(updated_comment)

                                service_now_apis.update_incident(
                                    incident, updated_comment, SNOW_DEV)
                                service_now_apis.close_incident(
                                    incident, SNOW_DEV)
                            else:
                                updated_comment = '\nConfiguration changes not approved,\nConfiguration rolled back not successful'
                                service_now_apis.update_incident(
                                    incident, updated_comment, SNOW_DEV)

                else:
                    print('Device: ' + device +
                          ' - No configuration changes detected')

            else:
                # new device discovered, save the running configuration to a file in the folder with the name
                # {Config_Files}

                f_config = open(filename, 'w')
                f_config.write(device_run_config)
                f_config.seek(0)
                f_config.close()

                # retrieve the device management IP address

                private_mngmnt_ip_address = dnac_apis.get_device_management_ip(
                    device, dnac_token)
                device_mngmnt_ip_address = NAT[private_mngmnt_ip_address]

                # Save the running configuration as a baseline configuration local on each device
                # flash:/config_mon_baseline

                netconf_restconf.netconf_save_running_config_to_file(
                    'flash:/config_mon_baseline', device_mngmnt_ip_address,
                    IOS_XE_PORT, IOS_XE_USER, IOS_XE_PASS)

                print('Device: ' + device + ' - New device discovered')

        print('Wait for 10 seconds and start again')
        time.sleep(10)

    print('\n\nEnd of Application Run')
def main():
    """
    This sample script will:
     - validate the CLI template file name exists
     - open the file
     - select the IPv4 addresses to be configured on interfaces
     - validate if the selected IPv4 addresses are valid IPv4 addresses
     - verify if the IPv4 addresses are in use by a network device
     - verify if the IPv4 addresses are in use by a client
     - verify if the IPv4 addresses are reachable
     - deploying the configuration file will create an IPv4 address conflict if any of the above steps fail for one IPv4 address
    """

    print('\n\nStart of Application "ip_conflict_prevention.py" Run')

    # define the template config file name
    config_file = 'configuration_template.txt'

    # enter and validate the file exists
    if not os.path.isfile(config_file):
        print('File not found')

    # open file with the template
    cli_file = open(config_file, 'r')

    # read the file
    cli_config = cli_file.read()
    print('\nThe CLI template:\n')
    print(cli_config)

    ipv4_address_list = utils.identify_ipv4_address(cli_config)
    print('\nThe CLI template will configure these valid IPv4 addresses:')
    print(ipv4_address_list)

    # get the DNA Center Auth token

    dnac_token = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)

    # check each address against network devices and clients database

    duplicate_ip = False
    for ipv4_address in ipv4_address_list:

        # check against network devices interfaces

        device_info = dnac_apis.check_ipv4_network_interface(
            ipv4_address, dnac_token)
        if device_info[0] == 'Found':
            duplicate_ip = True
            print('\nThe IPv4 address ', ipv4_address,
                  ' is used by this device ', device_info[1], ', ',
                  device_info[2])
        else:
            print('\nThe IPv4 address ', ipv4_address,
                  ' is not used by any network devices')

            # if IP address no used by network devices continue to check against any hosts

            try:
                client_info = dnac_apis.get_client_info(
                    ipv4_address, dnac_token)
                if client_info:
                    duplicate_ip = True
                    print('The IPv4 address ', ipv4_address,
                          ' is used by a client')
                else:
                    print('The IPv4 address ', ipv4_address,
                          ' is not used by a client')

                    # if IP address not used by a client, continue with the reachability test

                    reachable = utils.ping_return(ipv4_address)
                    if reachable == 'Success':
                        duplicate_ip = True
                        print('The IPv4 address ', ipv4_address,
                              ' is reachable')
                    else:
                        print('The IPv4 address ', ipv4_address,
                              ' is not reachable')
            except:
                pass

    if duplicate_ip:
        print('\nDeploying the template ', config_file,
              ' will create an IP address conflict')
    else:
        print('\nDeploying the template ', config_file,
              ' will not create an IP address conflict')

    # end of the application run
    print('\n\nEnd of Application "ip_conflict_prevention.py" Run')
def main():
    """
    This script will load the file with the name {file_info}
    The file includes the information required to deploy the template. The network device hostname, the Cisco DNA Center
    project name, the configuration template file name.
    The application will:
     - verify if the project exists and create a new project if does not
     - update or upload the configuration template
     - commit the template
     - verify the device hostname is valid
     - deploy the template
     - verify completion and status of the template deployment
    """

    # the local date and time when the code will start execution

    date_time = str(datetime.datetime.now().replace(microsecond=0))

    print('\n\nApplication "dnacenter_jinja2_templates.py" Run Started: ' + date_time)

    # get a Cisco DNA Center auth token
    dnac_auth = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)

    # check if existing project, if not create a new project
    project_id = dnac_apis.create_project(PROJECT_J2, dnac_auth)
    if project_id == 'none':
        # unable to find or create the project
        print('\nUnable to create the project: ', PROJECT_J2)
        return

    # continue with the project id
    print('The project "' + PROJECT_J2 + '" id is: ' + project_id)

    input('\nEnter any key to continue ')

    # Management IP address configuration
    # create new template and commit if not existing
    # update the existing template and commit if existing

    template_name = MANAGEMENT_INT_J2.split('.')[0]  # select the template name from the template file

    cli_file = open(MANAGEMENT_INT_J2, 'r')  # open file with the template
    cli_config_commands = cli_file.read()  # read the file

    template_param = [
        {
            "parameterName": "interface_number",
            "dataType": "STRING",
            "required": True,
            "order": 1
        },
        {
            "parameterName": "ip_address",
            "dataType": "STRING",
            "required": True,
            "order": 2
        }
    ]

    # verify if existing template in the project
    template_id = dnac_apis.get_template_id(template_name, PROJECT_J2, dnac_auth)

    if template_id == '':
        print('\nThe template with the name "' + template_name + '" not found, create and commit the template')
        template_id = dnac_apis.create_commit_template(template_name, PROJECT_J2, cli_config_commands, template_param,
                                              dnac_auth)

    else:
        print('\nThe template with the name "' + template_name + '" found, update and commit template')
        dnac_apis.update_commit_template(template_name, PROJECT_J2, cli_config_commands,
                                                       template_param, dnac_auth)

    print('The template "' + template_name + '" id is: ', template_id)
    input('\nEnter any key to continue \n')

    # deploy the template
    deployment_id = dnac_apis.send_deploy_template(template_name, PROJECT_J2, DEVICE_NAME, PARAMS, dnac_auth)

    print('\nTemplate "' + template_name + '" started, task id: "' + deployment_id)
    time.sleep(10)

    deployment_status = dnac_apis.check_template_deployment_status(deployment_id, dnac_auth)
    print('Deployment task result :', deployment_status)

    # optional, delete the project and template
    input('\nEnter any key to delete the template and project \n')
    dnac_apis.delete_template(template_name, PROJECT_J2, dnac_auth)
    dnac_apis.delete_project(PROJECT_J2, dnac_auth)

    date_time = str(datetime.datetime.now().replace(microsecond=0))
    print('\n\nEnd of Application "dnacenter_jinja2_templates.py" Run: ' + date_time)
    return
Example #17
0
def main():
    """
    This application will:
    - clear the capwap ap config from C9800-CL
    - delete the AP from the PnP database
    - re-sync the WLC controller
    - delete the AP from the DNAC inventory
    """

    # run the application on demand to reset the AP PnP demo

    print('\n\nApplication "dnac_pnp_ap_reset.py" started')

    # device info and site

    pnp_device_assign = {
        'device_hostname': 'APB026.80DF.6E18',
        'site_name': 'PDX',
        'floor_name': 'Floor 3'
    }

    site_name = pnp_device_assign['site_name']
    floor_name = pnp_device_assign['floor_name']
    pnp_device_name = pnp_device_assign['device_hostname']

    print('\nThis application will reset the DNA Center PnP AP demo')

    # logging, debug level, to file {application_run.log}
    logging.basicConfig(
        filename='application_run.log',
        level=logging.DEBUG,
        format=
        '%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S')

    dnac_token = dnac_apis.get_dnac_jwt_token(DNAC_AUTH)

    # find if the AP is in provisioned state and delete from the PnP database

    pnp_devices_info = dnac_apis.pnp_get_device_list(dnac_token)
    device_state = pnp_devices_info[0]['deviceInfo']['state']
    pnp_device_id = pnp_devices_info[0]['id']
    pnp_device_ip = pnp_devices_info[0]['deviceInfo']['httpHeaders'][0][
        'value']

    print('\nPnP device state: ' + device_state)
    if device_state != 'Unclaimed':
        # if AP is unclaimed, go through the process to delete all configs

        # connect to C9800-CL using ssh/netmiko
        net_connect = ConnectHandler(**DEVICE_INFO)
        command_output = net_connect.find_prompt()
        print('\nPrompt of the connected device: ', command_output)

        # send the command to clear the PnP AP capwap config
        command = 'clear ap config ' + pnp_device_name
        command_output = net_connect.send_command(command)
        print(command_output)

        # disconnect from the C9800-CL
        net_connect.disconnect()

        # check if error during CLI command and delete config manually

        if '% Error' in command_output:
            print(
                '\n\nClear AP Config All from C9800-CL>Configuration>Wireless>AP>Advanced'
            )
            input('\nPress any key to continue')

        print('\nDemo reset started')

        # wait for the AP to delete the config and reboot
        time.sleep(30)

        print('\n\n\nPnP database device id: ' + pnp_device_id)
        print('PnP device IP Address: ', pnp_device_ip)

        # delete the device from the PnP database
        delete_result = dnac_apis.pnp_delete_provisioned_device(
            pnp_device_id, dnac_token)
        print('PnP database delete result: ',
              delete_result['deviceInfo']['state'])

        # get the Provisioned AP device id
        ap_device_id = dnac_apis.get_device_id_name(pnp_device_name,
                                                    dnac_token)

        # sync the PnP WLC, wait 60 seconds to complete, delete the PnP device from the DNAC inventory
        dnac_apis.sync_device(PnP_WLC_NAME, dnac_token)
        print('\nDNA Center Device Re-sync started: ', PnP_WLC_NAME)
        time.sleep(60)

        delete_task_id = dnac_apis.delete_device(ap_device_id,
                                                 dnac_token)['taskId']
        print('Device deleted from DNA Center inventory started')

        time.sleep(30)

        delete_status = dnac_apis.check_task_id_status(delete_task_id,
                                                       dnac_token)
        print('\nDelete task status: ', delete_status)

    print(
        '\nYou may start the demo again when the AP is available in the Cisco DNA Center PnP tab'
    )
    print('\n\nEnd of Application "dnac_pnp_ap_reset.py" Run')