Ejemplo n.º 1
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')
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
Ejemplo n.º 3
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)
Ejemplo n.º 4
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)
Ejemplo n.º 5
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')