def per_device_work(session, check_mode, enable_pass, settings_header):
    """
    This function contains the code that should be executed on each device that this script connects to.  It is called
    after establishing a connection to each device in the loop above.

    You can either put your own code here, or if there is a single-device version of a script that performs the correct
    task, it can be imported and called here, essentially making this script connect to all the devices in the chosen
    CSV file and then running a single-device script on each of them.
    """
    session.start_cisco_session(enable_pass=enable_pass)

    commands_to_add = session.script.settings.getlist(settings_header, session.os)
    logger.debug("<ADD_GLOBAL_CONFIG> Commands to send:\n{}".format(str(commands_to_add)))
    if commands_to_add:
        add_commands(session, check_mode, commands_to_add)
    else:
        raise scripts.ScriptError("There are no commands to apply for OS type: {}.".format(session.os))

    session.end_cisco_session()
Exemple #2
0
def script_main(script):
    """
    | MULTIPLE device script
    | Author: XXXXXXXX
    | Email: [email protected]

    PUT A DESCRIPTION OF THIS SCRIPT HERE.  WHAT IT DOES, ETC.
    This script checks that it will NOT be run in a connected tab.

    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """
    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_SCRIPT> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_SCRIPT> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError("This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    # Check settings if we should use a proxy/jumpbox
    use_proxy = script.settings.getboolean("Global", "use_proxy")
    default_proxy_session = script.settings.get("Global", "proxy_session")

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(script_name.split(".")[0]), include_hostname=False)

    for device in device_list:
        hostname = device['Hostname']
        protocol = device['Protocol']
        username = device['Username']
        password = device['Password']
        enable = device['Enable']
        try:
            proxy = device['Proxy Session']
        except KeyError:
            proxy = None

        if not proxy and use_proxy:
            proxy = default_proxy_session

        logger.debug("<M_SCRIPT> Connecting to {0}.".format(hostname))
        try:
            script.connect(hostname, username, password, protocol=protocol, proxy=proxy)
            session = script.get_main_session()
            per_device_work(session, enable)
            script.disconnect()
        except scripts.ConnectError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Connect to {0} failed: {1}\n".format(hostname, e.message.strip()))
                session.disconnect()
        except sessions.InteractionError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Failure on {0}: {1}\n".format(hostname, e.message.strip()))
                session.disconnect()
        except sessions.UnsupportedOSError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Unsupported OS on {0}: {1}\n".format(hostname, e.message.strip()))
                session.disconnect()
Exemple #3
0
def script_main(script):
    """
    | MULTIPLE device script
    | Author: Jamie Caesar
    | Email: [email protected]

    This script will connect to all devices in the provided CSV file and create an output report (also CSV format)
    containing inventory data about the devices, such as hostname, model number, code version, serial number,
    manufacture date, etc.

    This script checks that it will NOT be run in a connected tab.

    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """
    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_SCRIPT> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_SCRIPT> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError("This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    # Check settings if we should use a proxy/jumpbox
    use_proxy = script.settings.getboolean("Global", "use_proxy")
    default_proxy_session = script.settings.get("Global", "proxy_session")

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(script_name.split(".")[0]), include_hostname=False)

    device_data = []
    for device in device_list:
        hostname = device['Hostname']
        protocol = device['Protocol']
        username = device['Username']
        password = device['Password']
        enable = device['Enable']
        try:
            proxy = device['Proxy Session']
        except KeyError:
            proxy = None

        if not proxy and use_proxy:
            proxy = default_proxy_session

        logger.debug("<M_SCRIPT> Connecting to {0}.".format(hostname))
        try:
            script.connect(hostname, username, password, protocol=protocol, proxy=proxy)
            session = script.get_main_session()
            device_data.extend(per_device_work(session, enable))
            script.disconnect()
        except scripts.ConnectError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Connect to {0} failed: {1}\n".format(hostname, e.message.strip()))
                session.disconnect()
        except sessions.InteractionError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Failure on {0}: {1}\n".format(hostname, e.message.strip()))
                session.disconnect()
        except sessions.UnsupportedOSError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Unsupported OS on {0}: {1}\n".format(hostname, e.message.strip()))
                session.disconnect()
        except Exception as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Exception on {0}: {1} ({2})\n".format(hostname, e.message.strip(), e))
                session.disconnect()

    # #########################################  END DEVICE CONNECT LOOP  ############################################

    # Write complete output to a CSV file
    session = script.get_main_session()
    output_filename = session.create_output_filename("INVENTORY_REPORT", ext='.csv', include_hostname=False)
    header_row = ['HOSTNAME', 'MODEL', 'VERSION', 'SERIAL', 'MANUFACTURE_DATE', 'UPTIME',
                  'LAST_REBOOT_REASON', 'HARDWARE', 'IMAGE']
    utilities.list_of_dicts_to_csv(device_data, output_filename, header_row)
Exemple #4
0
def script_main(script):
    """
    | MULTIPLE device script
    | Author: Jamie Caesar
    | Email: [email protected]

    This script will scan the running configuration of the provided list of devices, looking for instances of old IP
    helper/DHCP relay addresses (IOS/NXOS) on interfaces and if found will update the helper/relay addresses with the
    newer ones. The new and old addresses that the script looks for is saved in the settings.ini file, as documented
    below.

    Any devices that cannot be connected to will be logged in a separate file saved in the output directory.

    This script will prompt you to run in "Check Mode", where the configuration changes the script would be pushed to
    the devices are ONLY written to a file and NO CHANGES will be made to the devices.  If you select "No" when prompted
    this script will push the configuration changes to the devices. Also, when the changes are pushed to the devices
    this script will save the running config before and after the changes are made, and will also output a log of the
    configuration sessions showing all the commands pushed.

    **Script Settings** (found in settings/settings.ini):

    * | **show_instructions** - When True, displays a pop-up upon launching the script
      | explaining where to modify the list of commands sent to devices.  This window also
      | prompts the user if they want to continue seeing this message. If not, the script
      | changes this setting to False.
    * | **old_relays** - This is a comma separated list of IP addresses that the script should
      | search for as relay addresses in the device's configuration.
    * | **new_relays** - This is a comma separated list of IP addresses that are the new relay
      | addresses that should be added to any interface that has at least one of the old
      | helper/relay addresses on it.
    * | **remove_old_relays** - If True, the script will add the new relays and REMOVE the old
      | relays immediately after adding the new ones.  If False (default), the script will
      | only add the new relays to interfaces where at least one old relay is found.  This
      | is useful when you want to push out new relays as part of a migration process
      | without removing the old relays.  Since this script will not try to push new relay
      | addresses that already exist on an interface, the script can be run again with this
      | option set to True to later remove the old relays.
    
    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """

    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_SCRIPT> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_SCRIPT> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError(
            "This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    # #########################################  GET VALUES FROM SETTINGS  ###########################################
    # Display instructions message, unless settings prevent it
    show_instructions = script.settings.getboolean("update_dhcp_relay",
                                                   "show_instructions")
    if show_instructions:
        response = script.message_box(
            "The list of old and new ip-helper/dhcp relay IPs can be edited in the "
            "'settings/settings.ini' file in the main securecrt-tools directory.\nSee the "
            "documentation for this script ('docs/index.html') for more details.\n\n"
            "Do you want to stop seeing this message?", "Instructions",
            ICON_QUESTION + BUTTON_YESNO)
        if response == IDYES:
            script.settings.update("update_dhcp_relay", "show_instructions",
                                   False)

    # Collection of old helpers/relays is in a set data structure to make membership checks easier.  A list works fine
    # for new helpers/relays.
    old_helpers = set(
        build_valid_ip_list(
            script.settings.getlist("update_dhcp_relay", "old_relays")))
    new_helpers = build_valid_ip_list(
        script.settings.getlist("update_dhcp_relay", "new_relays"))
    remove_old_helpers = script.settings.getboolean("update_dhcp_relay",
                                                    "remove_old_relays")

    # #########################################  START CHECK MODE SECTION  ###########################################
    # Ask if this should be a test run (generate configs only) or full run (push updates to devices)
    # Comment out or remove the entire CHECK MODE SECTION if you don't want to prompt for check mode
    check_mode_message = "Do you want to run this script in check mode? (Only generate configs)\n" \
                         "\n" \
                         "Yes = Connect to device and write change scripts to a file ONLY\n" \
                         "No = Connect to device and PUSH configuration changes"
    message_box_design = ICON_QUESTION | BUTTON_YESNOCANCEL
    logger.debug("Prompting the user to run in check mode.")
    result = script.message_box(check_mode_message, "Run in Check Mode?",
                                message_box_design)
    if result == IDYES:
        logger.debug("<M_SCRIPT> Received 'True' for Check Mode.")
        check_mode = True
    elif result == IDNO:
        logger.debug("<M_SCRIPT> Received 'False' for Check Mode.")
        check_mode = False
    else:
        return
    # ########################################### END CHECK MODE SECTION  ############################################

    # Check settings if we should use a proxy/jumpbox
    use_proxy = script.settings.getboolean("Global", "use_proxy")
    default_proxy_session = script.settings.get("Global", "proxy_session")

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(
        script_name.split(".")[0]),
                                                include_hostname=False)

    for device in device_list:
        hostname = device['Hostname']
        protocol = device['Protocol']
        username = device['Username']
        password = device['Password']
        enable = device['Enable']
        try:
            proxy = device['Proxy Session']
        except KeyError:
            proxy = None

        if not proxy and use_proxy:
            proxy = default_proxy_session

        logger.debug("<M_SCRIPT> Connecting to {0}.".format(hostname))
        try:
            script.connect(hostname,
                           username,
                           password,
                           protocol=protocol,
                           proxy=proxy)
            session = script.get_main_session()
            per_device_work(session, check_mode, enable, old_helpers,
                            new_helpers, remove_old_helpers)
            script.disconnect()
        except scripts.ConnectError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Connect to {0} failed: {1}\n".format(
                    hostname, e.message.strip()))
                session.disconnect()
        except sessions.InteractionError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Failure on {0}: {1}\n".format(
                    hostname, e.message.strip()))
                session.disconnect()
        except sessions.UnsupportedOSError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Unsupported OS on {0}: {1}\n".format(
                    hostname, e.message.strip()))
                session.disconnect()
        except Exception as e:
            with open(failed_log, 'a') as logfile:
                logfile.write(
                    "<M_SCRIPT> Exception on {0}: {1} ({2})\n".format(
                        hostname, e.message.strip(), e))
                session.disconnect()
def script_main(script):
    """
    | MULTIPLE device script
    | Author: XXXXXXXX
    | Email: [email protected]

    PUT A DESCRIPTION OF THIS SCRIPT HERE.  WHAT IT DOES, ETC.
    This script checks that it will NOT be run in a connected tab.

    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """
    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_SCRIPT> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_SCRIPT> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError(
            "This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    check_mode = True
    # #########################################  START CHECK MODE SECTION  ###########################################
    # Ask if this should be a test run (generate configs only) or full run (push updates to devices)
    # Comment out or remove the entire CHECK MODE SECTION if you don't want to prompt for check mode
    check_mode_message = "Do you want to run this script in check mode? (Only generate configs)\n" \
                         "\n" \
                         "Yes = Connect to device and write change scripts to a file ONLY\n" \
                         "No = Connect to device and PUSH configuration changes"
    message_box_design = ICON_QUESTION | BUTTON_YESNOCANCEL
    logger.debug("Prompting the user to run in check mode.")
    result = script.message_box(check_mode_message, "Run in Check Mode?",
                                message_box_design)
    if result == IDYES:
        logger.debug("<M_SCRIPT> Received 'True' for Check Mode.")
        check_mode = True
    elif result == IDNO:
        logger.debug("<M_SCRIPT> Received 'False' for Check Mode.")
        check_mode = False
    else:
        return
    # ########################################### END CHECK MODE SECTION  ############################################

    # Check settings if we should use a proxy/jumpbox
    use_proxy = script.settings.getboolean("Global", "use_proxy")
    default_proxy_session = script.settings.get("Global", "proxy_session")

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(
        script_name.split(".")[0]),
                                                include_hostname=False)

    for device in device_list:
        hostname = device['Hostname']
        protocol = device['Protocol']
        username = device['Username']
        password = device['Password']
        enable = device['Enable']
        try:
            proxy = device['Proxy Session']
        except KeyError:
            proxy = None

        if not proxy and use_proxy:
            proxy = default_proxy_session

        logger.debug("<M_SCRIPT> Connecting to {0}.".format(hostname))
        try:
            script.connect(hostname,
                           username,
                           password,
                           protocol=protocol,
                           proxy=proxy)
            session = script.get_main_session()
            per_device_work(session, check_mode, enable)
            script.disconnect()
        except scripts.ConnectError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Connect to {0} failed: {1}\n".format(
                    hostname, e.message.strip()))
                session.disconnect()
        except sessions.InteractionError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Failure on {0}: {1}\n".format(
                    hostname, e.message.strip()))
                session.disconnect()
        except sessions.UnsupportedOSError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Unsupported OS on {0}: {1}\n".format(
                    hostname, e.message.strip()))
                session.disconnect()
def script_main(script):
    """
    | MULTIPLE device script
    | Author: Jamie Caesar
    | Email: [email protected]

    This script will add global configuration commands to the provided list of devices.  The commands sent will depend
    on the operating system of each connected device.  For example, IOS devices get the commands listed in the 'ios'
    section of the settings for this script.   If the device is running NX-OS, it will get the commands from the 'nxos'
    section of the settings, etc.

    Any devices that cannot be connected to will be logged in a separate file saved in the output directory.

    This script will prompt you to run in "Check Mode", where the configuration changes the script would be pushed to
    the devices are ONLY written to a file and NO CHANGES will be made to the devices.  If you select "No" when prompted
    this script will push the configuration changes to the devices. Also, when the changes are pushed to the devices
    this script will save the running config before and after the changes are made, and will also output a log of the
    configuration sessions showing all the commands pushed.

    **Script Settings** (found in settings/settings.ini):

    * | **show_instructions** - When True, displays a pop-up upon launching the script
      | explaining where to modify the list of commands sent to devices.  This window also
      | prompts the user if they want to continue seeing this message. If not, the script
      | changes this setting to False.
    * | **ios** - A comma separated list of commands that will be sent to IOS devices.
    * | **ios-xr** - A comma separated list of commands that will be sent to IOS-XR devices.
    * | **nxos** - A comma separated list of commands that will be sent to NX-OS devices.
    * | **asa** - A comma separated list of commands that will be sent to ASA devices.
    
    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """

    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_SCRIPT> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_SCRIPT> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError("This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    # #########################################  GET VALUES FROM SETTINGS  ###########################################
    # Display instructions message, unless settings prevent it
    settings_header = "add_global_config"
    show_instructions = script.settings.getboolean(settings_header, "show_instructions")
    if show_instructions:
        response = script.message_box("The list of old and new ip-helper/dhcp relay IPs can be edited in the "
                                      "'settings/settings.ini' file in the main securecrt-tools directory.\nSee the "
                                      "documentation for this script ('docs/index.html') for more details.\n\n"
                                      "Do you want to stop seeing this message?",
                                      "Instructions", ICON_QUESTION + BUTTON_YESNO)
        if response == IDYES:
            script.settings.update(settings_header, "show_instructions", False)

    # Get setting that decides if we need to give a warning that we will be pushing configuration to devices.
    # Not currently used in this script.
    # prompt_before_write = script.settings.getboolean(settings_header, "prompt_before_write")

    # #########################################  START CHECK MODE SECTION  ###########################################
    # Ask if this should be a test run (generate configs only) or full run (push updates to devices)
    # Comment out or remove the entire CHECK MODE SECTION if you don't want to prompt for check mode
    check_mode_message = "THIS SCRIPT WILL MAKE CONFIG CHANGES ON THE REMOTE DEVICES!!!!!\n\n"\
                         "Do you want to run this script in check mode instead? (Only generate configs)\n" \
                         "\n" \
                         "Yes = Connect to device and write change scripts to a file only. NO CHANGES.\n" \
                         "No = Connect to device and PUSH CONFIGURATION CHANGES TO ALL DEVICES"
    message_box_design = ICON_QUESTION | BUTTON_YESNOCANCEL
    logger.debug("Prompting the user to run in check mode.")
    result = script.message_box(check_mode_message, "Run in Check Mode?", message_box_design)
    if result == IDYES:
        logger.debug("<M_SCRIPT> Received 'True' for Check Mode.")
        check_mode = True
    elif result == IDNO:
        logger.debug("<M_SCRIPT> Received 'False' for Check Mode.")
        check_mode = False
    else:
        return
    # ########################################### END CHECK MODE SECTION  ############################################

    # Check settings if we should use a proxy/jumpbox
    use_proxy = script.settings.getboolean("Global", "use_proxy")
    default_proxy_session = script.settings.get("Global", "proxy_session")

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(script_name.split(".")[0]), include_hostname=False)

    for device in device_list:
        hostname = device['Hostname']
        protocol = device['Protocol']
        username = device['Username']
        password = device['Password']
        enable = device['Enable']
        try:
            proxy = device['Proxy Session']
        except KeyError:
            proxy = None

        if not proxy and use_proxy:
            proxy = default_proxy_session

        logger.debug("<M_SCRIPT> Connecting to {0}.".format(hostname))
        try:
            script.connect(hostname, username, password, protocol=protocol, proxy=proxy)
            session = script.get_main_session()
            per_device_work(session, check_mode, enable, settings_header)
            script.disconnect()
        except scripts.ConnectError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Connect to {0} failed: {1}\n".format(hostname, e.message.strip()))
                session.disconnect()
        except sessions.InteractionError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Failure on {0}: {1}\n".format(hostname, e.message.strip()))
                session.disconnect()
        except sessions.UnsupportedOSError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Unsupported OS on {0}: {1}\n".format(hostname, e.message.strip()))
                session.disconnect()
        except Exception as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Exception on {0}: {1} ({2})\n".format(hostname, e.message.strip(), e))
                session.disconnect()
Exemple #7
0
def script_main(script):
    """
    | MULTIPLE device script
    | Author: Jamie Caesar
    | Email: [email protected]

    This script will provide a list of all the switches that have locally connected MAC addresses in their mac address
    table for a range of VLANs.

    After launching the script, it will prompt for a CSV file with all of the devices the script should connect to.
    It will also prompt for a range of VLANs that it should look for MAC addresses
    This script checks that it will NOT be run in a connected tab.

    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """
    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_SCRIPT> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_SCRIPT> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError(
            "This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    # Check settings if we should use a proxy/jumpbox
    use_proxy = script.settings.getboolean("Global", "use_proxy")
    default_proxy_session = script.settings.get("Global", "proxy_session")

    num_string = script.prompt_window(
        "Provide a list of VLANs to search the devices for (e.g. 1,2,5-7,9)",
        "Input range")
    if not num_string:
        return

    vlan_set = set(utilities.expand_number_range(num_string))

    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(
        script_name.split(".")[0]),
                                                include_hostname=False)

    output_filename = session.create_output_filename("mac-search-by-vlan",
                                                     include_hostname=False,
                                                     ext=".txt")
    with open(output_filename, 'w') as output_file:
        output_file.write(
            "MAC ADDRESS SEARCH IN VLANS: {0}\n\n".format(num_string))
        # ########################################  START DEVICE CONNECT LOOP  ###########################################
        for device in device_list:
            hostname = device['hostname']
            protocol = device['protocol']
            username = device['username']
            password = device['password']
            enable = device['enable']
            proxy = device['proxy']

            if not proxy and use_proxy:
                proxy = default_proxy_session

            logger.debug("<M_SCRIPT> Connecting to {0}.".format(hostname))
            try:
                session.connect(hostname,
                                username,
                                password,
                                protocol=protocol,
                                proxy=proxy)
                hostname, matched_macs = per_device_work(
                    session, enable, vlan_set)
                session.disconnect()
                if matched_macs:
                    output_file.write("### Device: {0} ###\n".format(hostname))
                    output_file.write("VLAN    MAC                  PORT\n")
                    for line in matched_macs:
                        output_line = line[0]
                        output_line += ' ' * (8 - len(line[0]))
                        output_line += line[1]
                        output_line += ' ' * (20 - len(line[1]))
                        output_line += line[2]
                        output_file.write("{}\n".format(output_line))
                    output_file.write("\n\n")
                    output_file.flush()
            except sessions.ConnectError as e:
                with open(failed_log, 'a') as logfile:
                    logfile.write("Connect to {0} failed: {1}\n".format(
                        hostname, e.message.strip()))
            except sessions.InteractionError as e:
                with open(failed_log, 'a') as logfile:
                    logfile.write("Failure on {0}: {1}\n".format(
                        hostname, e.message.strip()))
Exemple #8
0
def script_main(script):
    """
    | MULTIPLE device script
    | Author: Jamie Caesar
    | Email: [email protected]

    This script will pull the ARP tables from multiple devices and combine their data into a single ARP CSV file.

    The main intention for this script is to be used with the 's_switchport_mapping' script, which will prompt for an
    ARP table CSV file to list IPs connected to switch ports.  This script is intended to speed up the collection of
    ARP data in cases such as:

    1) There are 2 core switches running a first hop redundancy protocol (HSRP, GLBP, etc) and both devices are
    actively passing traffic so we need both ARP tables

    2) The switch has VLANs that are being used in multiple upstream VRFs (not all with SVIs on the same devices) so
    the ARP tables from many devices may be needed to fully map the switch.

    NOTE: Since this script merges the ARP tables of multiple devices which may have duplicate entries, the interface
          is NOT written to the output file like it is with the single device version of this script.

    This script checks that it will NOT be run in a connected tab.  This script initiates the connection to all devices
    based on the input of the device CSV file that the script requests.

    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """
    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_SCRIPT> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_SCRIPT> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError(
            "This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    # Prompt for the VRF
    selected_vrf = script.prompt_window(
        "Enter the VRF name.\n(Leave blank for default VRF)")
    if selected_vrf == "":
        selected_vrf = None
    logger.debug("Set VRF to '{0}'".format(selected_vrf))

    # Check settings if we should use a proxy/jumpbox
    use_proxy = script.settings.getboolean("Global", "use_proxy")
    default_proxy_session = script.settings.get("Global", "proxy_session")

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(
        script_name.split(".")[0]),
                                                include_hostname=False)

    arp_collection = []

    for device in device_list:
        hostname = device['hostname']
        protocol = device['protocol']
        username = device['username']
        password = device['password']
        enable = device['enable']
        proxy = device['proxy']

        if not proxy and use_proxy:
            proxy = default_proxy_session

        logger.debug("<M_SCRIPT> Connecting to {0}.".format(hostname))
        try:
            session.connect(hostname,
                            username,
                            password,
                            protocol=protocol,
                            proxy=proxy)
            arp_collection.extend(
                per_device_work(session, selected_vrf, add_header=False))
            session.disconnect()
        except sessions.ConnectError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("Connect to {0} failed: {1}\n".format(
                    hostname, e.message.strip()))
        except sessions.InteractionError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("Failure on {0}: {1}\n".format(
                    hostname, e.message.strip()))

    # #########################################  END DEVICE CONNECT LOOP  ############################################

    # #########################################  PROCESS COLLECTED DATA  #############################################

    # Build a combined table without duplicate values from the data retrieved from all devices.
    combined_table = []
    seen = set()
    for entry in arp_collection:
        if entry[2] not in seen:
            combined_table.append([entry[0], "", entry[2], entry[3], ""])
            seen.add(entry[2])
    combined_table.sort(key=lambda x: utilities.human_sort_key(x[0]))
    combined_table.insert(0, ["IP ADDRESS", "", "MAC ADDRESS", "VLAN", ""])

    # Generate filename and output data as CSV
    output_filename = session.create_output_filename("merged-arp",
                                                     include_hostname=False,
                                                     ext=".csv")
    utilities.list_of_lists_to_csv(combined_table, output_filename)
Exemple #9
0
def script_main(script):
    """
    | MULTIPLE device script
    | Author: Jamie Caesar
    | Email: [email protected]

    This script will grab the output for a list of commands from the provided list of devices.  The list of commands is
    taken from the 'settings/settings.ini' file.  There is a separate list for each supported network operating system
    (IOS, NXOS and ASA) and by default the list that matches the network operating system of the connected device will
    be used.

    Custom lists of commands are supported.  These lists can be added manually to the [document_device] section of the
    'settings/settings.ini' file.  To be able to choose one of these lists when running the script, the
    'prompt_for_custom_lists' setting needs to be changed to 'True' in the settings.ini file.  Once this option is
    enabled, the script will prompt for the name of the list that you want to use.  If the input is left blank then
    the default behavior (based on network OS) will choose the list.

    NOTE:
    The Custom list can be set on a PER DEVICE basis if a column names "Command List" (case sensitive) is added to the
    device list CSV file that is selected when running this script.  If the "Command List" column is missing or the
    field is left blank for a device then the list will be chosen using the default behavior (i.e. use the list
    specified when running the script, or based on the network OS of each device).

    **Script Settings** (found in settings/settings.ini):

    * | **show_instructions** - When True, displays a pop-up upon launching the script
      | explaining where to modify the list of commands sent to devices.  This window also
      | prompts the user if they want to continue seeing this message.  If not, the script
      | changes this setting to False.
    * | **folder_per_device** - If True, Creates a folder for each device, based on the
      | hostname, and saves all files inside that folder WITHOUT the hostname in the output
      | file names.  If False, it saves all the files directly into the output folder from
      | the global settings and includes the hostname in each individual filename.
    * | **prompt_for_custom_lists** - When set to True, the script will prompt the user to
      | type the name of a list of commands to use with the connected device.  This list
      | name must be found as an option in the [document_device] section of the
      | settings.ini file.  The format is the same as the default network OS lists, 'ios',
      | 'nxos', etc.
    * | **ios** - The list of commands that will be run on IOS devices
    * | **nxos** - The list of commands that will be run on NXOS devices
    * | **asa** - The list of commands that will be run on ASA devices

    **Any additional options found in this section would be custom added by the user and are expected to be lists of
    commands for use with the 'prompt_for_custom_lists' setting.**

    By default, The outputs will be saved in a folder named after the hostname of the device, with each output file
    being saved inside that directory.  This behavior can be changed in the settings above.

    :param session: A subclass of the sessions.Session object that represents this particular script session (either
                SecureCRTSession or DirectSession)
    :type session: sessions.Session
    """
    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_SCRIPT> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_SCRIPT> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError(
            "This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    # Check settings if we should use a proxy/jumpbox
    use_proxy = script.settings.getboolean("Global", "use_proxy")
    default_proxy_session = script.settings.get("Global", "proxy_session")

    # Display instructions message, unless settings prevent it
    show_instructions = script.settings.getboolean("document_device",
                                                   "show_instructions")
    if show_instructions:
        response = script.message_box(
            "The list of commands sent to the device can be edited in the 'settings/settings."
            "ini' file in the main securecrt-tools directory.\nSee the documentation for this"
            " script for more details.\n\nDo you want to stop seeing this message?",
            "Instructions", ICON_QUESTION + BUTTON_YESNO)
        if response == IDYES:
            script.settings.update("document_device", "show_instructions",
                                   False)

    # Check if settings allow for custom lists, and if so prompt for the list to use -- if not, just use the list for
    # the OS of the device connected
    custom_allowed = script.settings.getboolean("document_device",
                                                "prompt_for_custom_lists")
    if custom_allowed:
        default_command_list = script.prompt_window(
            "Enter the name of the command list you want to use.\n\nThese lists are found "
            "in the [document_device] section of your settings.ini file\n",
            "Enter command list")
    else:
        default_command_list = None

    folder_per_device = script.settings.getboolean("document_device",
                                                   "folder_per_device")

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(
        script_name.split(".")[0]),
                                                include_hostname=False)

    for device in device_list:
        hostname = device['Hostname']
        protocol = device['Protocol']
        username = device['Username']
        password = device['Password']
        enable = device['Enable']
        try:
            proxy = device['Proxy Session']
        except KeyError:
            proxy = None
        try:
            if device['Command List']:
                command_list = device['Command List']
            else:
                command_list = default_command_list
        except KeyError:
            command_list = default_command_list

        if not proxy and use_proxy:
            proxy = default_proxy_session

        logger.debug("<M_SCRIPT> Connecting to {0}.".format(hostname))
        try:
            script.connect(hostname,
                           username,
                           password,
                           protocol=protocol,
                           proxy=proxy)
            session = script.get_main_session()
            per_device_work(session, command_list, folder_per_device)
            script.disconnect()
        except scripts.ConnectError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Connect to {0} failed: {1}\n".format(
                    hostname, e.message.strip()))
                session.disconnect()
        except sessions.InteractionError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Failure on {0}: {1}\n".format(
                    hostname, e.message.strip()))
                session.disconnect()
        except sessions.UnsupportedOSError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Unsupported OS on {0}: {1}\n".format(
                    hostname, e.message.strip()))
                session.disconnect()
def script_main(script):
    """
    | MULTIPLE device script
    | Author: Jamie Caesar
    | Email: [email protected]

    This script will prompt for a CSV list of devices, then will prompt for a command to run on each device in the list.
    The output from each device will be saved to a file.  The path where the file is saved is specified in the
    settings.ini file.

    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """
    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_SCRIPT> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_SCRIPT> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError("This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    send_cmd = script.prompt_window("Enter the command to capture on each device.")
    logger.debug("Received command: '{0}'".format(send_cmd))

    if send_cmd == "":
        return

    # ##########################################  START JUMP BOX SECTION  ############################################
    # Check settings if we should use a jumpbox.  If so, prompt for password (and possibly missing values)
    use_jumpbox = script.settings.getboolean("Global", "use_jumpbox")

    if use_jumpbox:
        jumpbox = script.settings.get("Global", "jumpbox_host")
        j_username = script.settings.get("Global", "jumpbox_user")
        j_ending = script.settings.get("Global", "jumpbox_prompt_end")

        if not jumpbox:
            jumpbox = script.prompt_window("Enter the HOSTNAME or IP for the jumpbox".format(jumpbox))
            script.settings.update("Global", "jumpbox_host", jumpbox)

        if not j_username:
            j_username = script.prompt_window("JUMPBOX: Enter the USERNAME for {0}".format(jumpbox))
            script.settings.update("Global", "jumpbox_user", j_username)

        j_password = script.prompt_window("JUMPBOX: Enter the PASSWORD for {0}".format(j_username), hide_input=True)

        if not j_ending:
            j_ending = script.prompt_window("Enter the last character of the jumpbox CLI prompt")
            script.settings.update("Global", "jumpbox_prompt_end", j_ending)

    # ############################################  END JUMP BOX SECTION  ############################################

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    # We are not yet connected to a jump box.  This will be updated later in the code if needed.
    jump_connected = False
    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(script_name.split(".")[0]), include_hostname=False)

    for device in device_list:
        hostname = device['hostname']
        protocol = device['protocol']
        username = device['username']
        password = device['password']
        enable = device['enable']

        if use_jumpbox:
            logger.debug("<M_SCRIPT> Connecting to {0} via jumpbox.".format(hostname))
            if "ssh" in protocol.lower():
                try:
                    if not jump_connected:
                        session.connect_ssh(jumpbox, j_username, j_password, prompt_endings=[j_ending])
                        jump_connected = True
                    session.ssh_via_jump(hostname, username, password)
                    per_device_work(session, enable, send_cmd)
                    session.disconnect_via_jump()
                except (sessions.ConnectError, sessions.InteractionError) as e:
                    with open(failed_log, 'a') as logfile:
                        logfile.write("Connect to {0} failed: {1}\n".format(hostname, e.message.strip()))
                    session.disconnect()
                    jump_connected = False
            elif protocol.lower() == "telnet":
                try:
                    if not jump_connected:
                        session.connect_ssh(jumpbox, j_username, j_password, prompt_endings=[j_ending])
                        jump_connected = True
                    session.telnet_via_jump(hostname, username, password)
                    per_device_work(session, enable, send_cmd)
                    session.disconnect_via_jump()
                except (sessions.ConnectError, sessions.InteractionError) as e:
                    with open(failed_log, 'a') as logfile:
                        logfile.write("Connect to {0} failed: {1}\n".format(hostname, e.message.strip()))
                    session.disconnect()
                    jump_connected = False
        else:
            logger.debug("<M_SCRIPT> Connecting to {0}.".format(hostname))
            try:
                session.connect(hostname, username, password, protocol=protocol)
                per_device_work(session, enable, send_cmd)
                session.disconnect()
            except sessions.ConnectError as e:
                with open(failed_log, 'a') as logfile:
                    logfile.write("Connect to {0} failed: {1}\n".format(hostname, e.message.strip()))
            except sessions.InteractionError as e:
                with open(failed_log, 'a') as logfile:
                    logfile.write("Failure on {0}: {1}\n".format(hostname, e.message.strip()))

    # If we are still connected to our jump box, disconnect.
    if jump_connected:
        session.disconnect()
def script_main(script):
    """
    | MULTIPLE device script
    | Author: Jamie Caesar
    | Email: [email protected]

    This script will prompt for a CSV list of devices, then will prompt for a command to run on each device in the list.
    The output from each device will be saved to a file.  The path where the file is saved is specified in the
    settings.ini file.

    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """
    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_SCRIPT> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_SCRIPT> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError(
            "This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    send_cmd = script.prompt_window(
        "Enter the command to capture on each device.")
    logger.debug("Received command: '{0}'".format(send_cmd))

    if send_cmd == "":
        return

    # Check settings if we should use a proxy/jumpbox
    use_proxy = script.settings.getboolean("Global", "use_proxy")
    default_proxy_session = script.settings.get("Global", "proxy_session")

    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(
        script_name.split(".")[0]),
                                                include_hostname=False)

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    for device in device_list:
        hostname = device['Hostname']
        protocol = device['Protocol']
        username = device['Username']
        password = device['Password']
        enable = device['Enable']
        try:
            proxy = device['Proxy Session']
        except KeyError:
            proxy = None

        if not proxy and use_proxy:
            proxy = default_proxy_session

        logger.debug("<M_SCRIPT> Connecting to {0}.".format(hostname))
        try:
            script.connect(hostname,
                           username,
                           password,
                           protocol=protocol,
                           proxy=proxy)
            session = script.get_main_session()
            per_device_work(session, enable, send_cmd)
            script.disconnect()
        except scripts.ConnectError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Connect to {0} failed: {1}\n".format(
                    hostname, e.message.strip()))
                session.disconnect()
        except sessions.InteractionError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Failure on {0}: {1}\n".format(
                    hostname, e.message.strip()))
                session.disconnect()
        except sessions.UnsupportedOSError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_SCRIPT> Unsupported OS on {0}: {1}\n".format(
                    hostname, e.message.strip()))
                session.disconnect()
def script_main(script):
    """
    | MULTIPLE device script
    | Author: Jamie Caesar
    | Email: [email protected]

    This script will grab the detailed CDP information from each Cisco IOS or NX-OS device in the provided device list
    CSV file and export each to a CSV file containing the important information, such as Remote Device hostname, model
    and IP information, in addition to the local and remote interfaces that connect the devices.

    **Script Settings** (found in settings/settings.ini):

    * | **strip_domains** -  A list of domain names that will be stripped away if found in the CDP remote device name.


    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """
    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_CDP_TO_CSV> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_CDP_TO_CSV> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError("This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    # Check settings if we should use a proxy/jumpbox
    use_proxy = script.settings.getboolean("Global", "use_proxy")
    default_proxy_session = script.settings.get("Global", "proxy_session")

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(script_name.split(".")[0]), include_hostname=False)

    for device in device_list:
        hostname = device['Hostname']
        protocol = device['Protocol']
        username = device['Username']
        password = device['Password']
        enable = device['Enable']
        try:
            proxy = device['Proxy Session']
        except KeyError:
            proxy = None

        if not proxy and use_proxy:
            proxy = default_proxy_session

        logger.debug("<M_CDP_TO_CSV> Connecting to {0}".format(hostname))
        try:
            script.connect(hostname, username, password, protocol=protocol)
            session = script.get_main_session()
            per_device_work(session, enable)
            script.disconnect()
        except scripts.ConnectError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_CDP_TO_CSV> Connect to {0} failed: {1}\n".format(hostname, e.message))
                session.disconnect()
        except sessions.InteractionError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_CDP_TO_CSV> Failure on {0}: {1}\n".format(hostname, e.message))
                session.disconnect()
        except sessions.UnsupportedOSError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("<M_CDP_TO_CSV> Unsupported OS on {0}: {1}\n".format(hostname, e.message.strip()))
                session.disconnect()
Exemple #13
0
def script_main(script):
    """
    | MULTIPLE device script
    | Author: XXXXXXXX
    | Email: [email protected]

    PUT A DESCRIPTION OF THIS SCRIPT HERE.  WHAT IT DOES, ETC.
    This script checks that it will NOT be run in a connected tab.

    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """
    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_SCRIPT> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_SCRIPT> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError(
            "This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    check_mode = True
    # #########################################  START CHECK MODE SECTION  ###########################################
    # Ask if this should be a test run (generate configs only) or full run (push updates to devices)
    # Comment out or remove the entire CHECK MODE SECTION if you don't want to prompt for check mode
    check_mode_message = "Do you want to run this script in check mode? (Only generate configs)\n" \
                         "\n" \
                         "Yes = Connect to device and write change scripts to a file ONLY\n" \
                         "No = Connect to device and PUSH configuration changes"
    message_box_design = ICON_QUESTION | BUTTON_YESNOCANCEL
    logger.debug("Prompting the user to run in check mode.")
    result = script.message_box(check_mode_message, "Run in Check Mode?",
                                message_box_design)
    if result == IDYES:
        logger.debug("<M_SCRIPT> Received 'True' for Check Mode.")
        check_mode = True
    elif result == IDNO:
        logger.debug("<M_SCRIPT> Received 'False' for Check Mode.")
        check_mode = False
    else:
        return
    # ########################################### END CHECK MODE SECTION  ############################################

    # ##########################################  START JUMP BOX SECTION  ############################################
    # Check settings if we should use a jumpbox.  If so, prompt for password (and possibly missing values)
    use_jumpbox = script.settings.getboolean("Global", "use_jumpbox")

    if use_jumpbox:
        jumpbox = script.settings.get("Global", "jumpbox_host")
        j_username = script.settings.get("Global", "jumpbox_user")
        j_ending = script.settings.get("Global", "jumpbox_prompt_end")

        if not jumpbox:
            jumpbox = script.prompt_window(
                "Enter the HOSTNAME or IP for the jumpbox".format(jumpbox))
            script.settings.update("Global", "jumpbox_host", jumpbox)

        if not j_username:
            j_username = script.prompt_window(
                "JUMPBOX: Enter the USERNAME for {0}".format(jumpbox))
            script.settings.update("Global", "jumpbox_user", j_username)

        j_password = script.prompt_window(
            "JUMPBOX: Enter the PASSWORD for {0}".format(j_username),
            hide_input=True)

        if not j_ending:
            j_ending = script.prompt_window(
                "Enter the last character of the jumpbox CLI prompt")
            script.settings.update("Global", "jumpbox_prompt_end", j_ending)

    # ############################################  END JUMP BOX SECTION  ############################################

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    # We are not yet connected to a jump box.  This will be updated later in the code if needed.
    jump_connected = False
    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(
        script_name.split(".")[0]),
                                                include_hostname=False)

    for device in device_list:
        hostname = device['hostname']
        protocol = device['protocol']
        username = device['username']
        password = device['password']
        enable = device['enable']

        if use_jumpbox:
            logger.debug(
                "<M_SCRIPT> Connecting to {0} via jumpbox.".format(hostname))
            if "ssh" in protocol.lower():
                try:
                    if not jump_connected:
                        session.connect_ssh(jumpbox,
                                            j_username,
                                            j_password,
                                            prompt_endings=[j_ending])
                        jump_connected = True
                    session.ssh_via_jump(hostname, username, password)
                    per_device_work(session, check_mode, enable)
                    session.disconnect_via_jump()
                except (sessions.ConnectError, sessions.InteractionError) as e:
                    with open(failed_log, 'a') as logfile:
                        logfile.write("Connect to {0} failed: {1}\n".format(
                            hostname, e.message.strip()))
                    session.disconnect()
                    jump_connected = False
            elif protocol.lower() == "telnet":
                try:
                    if not jump_connected:
                        session.connect_ssh(jumpbox,
                                            j_username,
                                            j_password,
                                            prompt_endings=[j_ending])
                        jump_connected = True
                    session.telnet_via_jump(hostname, username, password)
                    per_device_work(session, check_mode, enable)
                    session.disconnect_via_jump()
                except (sessions.ConnectError, sessions.InteractionError) as e:
                    with open(failed_log, 'a') as logfile:
                        logfile.write("Connect to {0} failed: {1}\n".format(
                            hostname, e.message.strip()))
                    session.disconnect()
                    jump_connected = False
        else:
            logger.debug("<M_SCRIPT> Connecting to {0}.".format(hostname))
            try:
                session.connect(hostname,
                                username,
                                password,
                                protocol=protocol)
                per_device_work(session, check_mode, enable)
                session.disconnect()
            except sessions.ConnectError as e:
                with open(failed_log, 'a') as logfile:
                    logfile.write("Connect to {0} failed: {1}\n".format(
                        hostname, e.message.strip()))
            except sessions.InteractionError as e:
                with open(failed_log, 'a') as logfile:
                    logfile.write("Failure on {0}: {1}\n".format(
                        hostname, e.message.strip()))

    # If we are still connected to our jump box, disconnect.
    if jump_connected:
        session.disconnect()
Exemple #14
0
def script_main(script):
    """
    | MULTIPLE device script
    | Author: Jamie Caesar
    | Email: [email protected]

    This script will grab the detailed CDP information from a Cisco IOS or NX-OS device and port-channel information and
    generate the commands to update interface descriptions.  The user will be prompted to run in "Check Mode" which will
    write the configuration changes to a file (for verification or later manual application).  If not, then the script
    will push the configuration commands to the device and save the configuration.

    IMPORTANT:  This script imports the script_main() function from the s_update_interface_desc.py to run a majority
    of the script logic.  Much of this script is only handling multiple logins and calling the single-device version of
    this script.

    | Local Settings:
    | "strip_domains" -  A list of domain names that will be stripped away if found in the CDP remote device name.
    | "take_backups" - If True, the script will save a copy of the running config before and after making changes.
    | "rollback_file" - If True, the script will generate a rollback configuration script and save it to a file.

    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """
    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_SCRIPT> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug("<M_SCRIPT> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError("This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    check_mode = True
    # #########################################  START CHECK MODE SECTION  ###########################################
    # Ask if this should be a test run (generate configs only) or full run (push updates to devices)
    # Comment out or remove the entire CHECK MODE SECTION if you don't want to prompt for check mode
    check_mode_message = "Do you want to run this script in check mode? (Only generate configs)\n" \
                         "\n" \
                         "Yes = Connect to device and write change scripts to a file ONLY\n" \
                         "No = Connect to device and PUSH configuration changes"
    message_box_design = ICON_QUESTION | BUTTON_YESNOCANCEL
    logger.debug("Prompting the user to run in check mode.")
    result = script.message_box(check_mode_message, "Run in Check Mode?", message_box_design)
    if result == IDYES:
        logger.debug("<M_SCRIPT> Received 'True' for Check Mode.")
        check_mode = True
    elif result == IDNO:
        logger.debug("<M_SCRIPT> Received 'False' for Check Mode.")
        check_mode = False
    else:
        return
    # ########################################### END CHECK MODE SECTION  ############################################

    # Check settings if we should use a proxy/jumpbox
    use_proxy = script.settings.getboolean("Global", "use_proxy")
    default_proxy_session = script.settings.get("Global", "proxy_session")

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(script_name.split(".")[0]), include_hostname=False)

    for device in device_list:
        hostname = device['hostname']
        protocol = device['protocol']
        username = device['username']
        password = device['password']
        enable = device['enable']
        proxy = device['proxy']

        if not proxy and use_proxy:
            proxy = default_proxy_session

        logger.debug("<M_SCRIPT> Connecting to {0}.".format(hostname))
        try:
            session.connect(hostname, username, password, protocol=protocol, proxy=proxy)
            per_device_work(session, check_mode, enable)
            session.disconnect()
        except sessions.ConnectError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("Connect to {0} failed: {1}\n".format(hostname, e.message.strip()))
        except sessions.InteractionError as e:
            with open(failed_log, 'a') as logfile:
                logfile.write("Failure on {0}: {1}\n".format(hostname, e.message.strip()))
def script_main(script):
    """
    | MULTIPLE device script
    | Author: Jamie Caesar
    | Email: [email protected]

    This script will grab the detailed CDP information from a Cisco IOS or NX-OS device and port-channel information and
    generate the commands to update interface descriptions.  The user will be prompted to run in "Check Mode" which will
    write the configuration changes to a file (for verification or later manual application).  If not, then the script
    will push the configuration commands to the device and save the configuration.

    IMPORTANT:  This script imports the script_main() function from the s_update_interface_desc.py to run a majority
    of the script logic.  Much of this script is only handling multiple logins and calling the single-device version of
    this script.

    | Local Settings:
    | "strip_domains" -  A list of domain names that will be stripped away if found in the CDP remote device name.
    | "take_backups" - If True, the script will save a copy of the running config before and after making changes.
    | "rollback_file" - If True, the script will generate a rollback configuration script and save it to a file.

    :param script: A subclass of the scripts.Script object that represents the execution of this particular script
                   (either CRTScript or DirectScript)
    :type script: scripts.Script
    """
    session = script.get_main_session()

    # If this is launched on an active tab, disconnect before continuing.
    logger.debug("<M_INTF_DESC> Checking if current tab is connected.")
    if session.is_connected():
        logger.debug(
            "<M_INTF_DESC> Existing tab connected.  Stopping execution.")
        raise scripts.ScriptError(
            "This script must be launched in a not-connected tab.")

    # Load a device list
    device_list = script.import_device_list()
    if not device_list:
        return

    check_mode = True
    # #########################################  START CHECK MODE SECTION  ###########################################
    # Ask if this should be a test run (generate configs only) or full run (push updates to devices)
    # Comment out or remove the entire CHECK MODE SECTION if you don't want to prompt for check mode
    check_mode_message = "Do you want to run this script in check mode? (Only generate configs)\n" \
                         "\n" \
                         "Yes = Connect to device and write change scripts to a file ONLY\n" \
                         "No = Connect to device and PUSH configuration changes"
    message_box_design = ICON_QUESTION | BUTTON_YESNOCANCEL
    logger.debug("Prompting the user to run in check mode.")
    result = script.message_box(check_mode_message, "Run in Check Mode?",
                                message_box_design)
    if result == IDYES:
        logger.debug("<M_SCRIPT> Received 'True' for Check Mode.")
        check_mode = True
    elif result == IDNO:
        logger.debug("<M_SCRIPT> Received 'False' for Check Mode.")
        check_mode = False
    else:
        return
    # ########################################### END CHECK MODE SECTION  ############################################

    # ##########################################  START JUMP BOX SECTION  ############################################
    # Check settings if we should use a jumpbox.  If so, prompt for password (and possibly missing values)
    use_jumpbox = script.settings.getboolean("Global", "use_jumpbox")

    if use_jumpbox:
        jumpbox = script.settings.get("Global", "jumpbox_host")
        j_username = script.settings.get("Global", "jumpbox_user")
        j_ending = script.settings.get("Global", "jumpbox_prompt_end")

        if not jumpbox:
            jumpbox = script.prompt_window(
                "Enter the HOSTNAME or IP for the jumpbox".format(jumpbox))
            script.settings.update("Global", "jumpbox_host", jumpbox)

        if not j_username:
            j_username = script.prompt_window(
                "JUMPBOX: Enter the USERNAME for {0}".format(jumpbox))
            script.settings.update("Global", "jumpbox_user", j_username)

        j_password = script.prompt_window(
            "JUMPBOX: Enter the PASSWORD for {0}".format(j_username),
            hide_input=True)

        if not j_ending:
            j_ending = script.prompt_window(
                "Enter the last character of the jumpbox CLI prompt")
            script.settings.update("Global", "jumpbox_prompt_end", j_ending)

    # ############################################  END JUMP BOX SECTION  ############################################

    # ########################################  START DEVICE CONNECT LOOP  ###########################################

    # We are not yet connected to a jump box.  This will be updated later in the code if needed.
    jump_connected = False
    # Create a filename to keep track of our connection logs, if we have failures.  Use script name without extension
    failed_log = session.create_output_filename("{0}-LOG".format(
        script_name.split(".")[0]),
                                                include_hostname=False)

    for device in device_list:
        hostname = device['hostname']
        protocol = device['protocol']
        username = device['username']
        password = device['password']
        enable = device['enable']

        if use_jumpbox:
            logger.debug("<M_INTF_DESC> Connecting to {0} via jumpbox.".format(
                hostname))
            if "ssh" in protocol.lower():
                try:
                    if not jump_connected:
                        session.connect_ssh(jumpbox,
                                            j_username,
                                            j_password,
                                            prompt_endings=[j_ending])
                        jump_connected = True
                    session.ssh_via_jump(hostname, username, password)
                    per_device_work(session, check_mode, enable)
                    session.disconnect_via_jump()
                except (sessions.ConnectError, sessions.InteractionError) as e:
                    error_msg = e.message
                    with open(failed_log, 'a') as logfile:
                        logfile.write("Connect to {0} failed: {1}\n".format(
                            hostname, error_msg))
                    session.disconnect()
                    jump_connected = False
            elif protocol.lower() == "telnet":
                try:
                    if not jump_connected:
                        session.connect_ssh(jumpbox,
                                            j_username,
                                            j_password,
                                            prompt_endings=[j_ending])
                        jump_connected = True
                    session.telnet_via_jump(hostname, username, password)
                    per_device_work(session, check_mode, enable)
                    session.disconnect_via_jump()
                except (sessions.ConnectError, sessions.InteractionError) as e:
                    with open(failed_log, 'a') as logfile:
                        logfile.write("Connect to {0} failed: {1}\n".format(
                            hostname, e.message))
                    session.disconnect()
                    jump_connected = False
        else:
            logger.debug("<M_INTF_DESC> Connecting to {0}".format(hostname))
            try:
                session.connect(hostname,
                                username,
                                password,
                                protocol=protocol)
                per_device_work(session, check_mode, enable)
                session.disconnect()
            except sessions.ConnectError as e:
                with open(failed_log, 'a') as logfile:
                    logfile.write("Connect to {0} failed: {1}\n".format(
                        hostname, e.message))
            except sessions.InteractionError as e:
                with open(failed_log, 'a') as logfile:
                    logfile.write("Failure on {0}: {1}\n".format(
                        hostname, e.message))

    # If we are still connected to our jump box, disconnect.
    if jump_connected:
        session.disconnect()