def main():
    inputfile, config_commands = get_cmd_line()

    print("Switch configuration updater. Please provide login information.\n")
    # Get username and password information.
    username = input("Username: "******"Password: "******"Enable Secret: ")

    print("{}{:<20}{:<40}{:<20}".format(
        "\n", "IP Address", "Name", "Results"), end="")

    for switchip in inputfile:
        ciscosw = {
            "device_type": "cisco_ios",
            "ip": switchip.strip(),
            "username": username.strip(),
            "password": password.strip(),
            "secret": enasecret.strip(),
        }
        print()
        print("{:<20}".format(switchip.strip()), end="", flush=True)
        try:
            # Connect to switch and enter enable mode.
            net_connect = ConnectHandler(**ciscosw)
        except Exception:
            print("** Failed to connect.", end="", flush=True)
            continue

        prompt = net_connect.find_prompt()
        # Print out the prompt/hostname of the device
        print("{:<40}".format(prompt), end="", flush=True)
        try:
            # Ensure we are in enable mode and can make changes.
            if "#" not in prompt[-1]:
                net_connect.enable()
                print("#", end="", flush=True)
        except Exception:
            print("Unable to enter enable mode.", end="", flush=True)
            continue

        else:
            for cmd in config_commands:
                # Make requested configuration changes.
                try:
                    if cmd in ("w", "wr"):
                        output = net_connect.save_config()
                        print("w", end="", flush=True)
                    else:
                        output = net_connect.send_config_set(cmd)
                        if "Invalid input" in output:
                            # Unsupported command in this IOS version.
                            print("Invalid input: ", cmd, end="", flush=True)
                        print("*", end="", flush=True)
                except Exception:
                    # Command failed! Stop processing further commands.
                    print("!")
                    break
        net_connect.disconnect()
Exemple #2
0
    if ssh_connect:
        print("\nSSH Connection Established Successfully to host:",
              connection["host"])

    # Tell python to load all external files from the current directory
    env = Environment(loader=FileSystemLoader('.'))
    template = env.get_template("configure-interfaces-template.j2")

    interfaces = ["G1/0", "G1/1", "G1/2", "G1/3"]

    # Define which configuration you would like to use Jinja for
    for interface in interfaces:
        interface_dict = {
            "name": interface.strip(),
            "description": "Server Port",
            "vlan": "10",
        }

        # Combine between dictionary attributes with Jinja templates variables
        output = template.render(interface=interface_dict)
        # print(output)

        # Write result configuration to external file and take those configuration and send it back to the device
        with open('Host {}-config.txt'.format(connection['host']), "a") as f:
            f.write(output)

        ssh_connect.send_config_set(output, cmd_verify=False)
        ssh_connect.save_config()
    print("Finish sending configuration to", connection["host"])
    print("-----------------------------------------------------\n")
def upgrade_device(net_device):

    start_time = datetime.now()

    print()
    print("Upgrading OS on device: {}".format(net_device['host']))
    print("-" * 50)

    # Extract file and file system variables
    file_system = net_device.pop('file_system')
    source_file = net_device.pop('source_file')
    dest_file = net_device.pop('dest_file')

    # Establish SSH control channel
    print(".establishing SSH connection.")
    ssh_conn = ConnectHandler(**net_device)

    # SCP new image file
    print(".transferring image file.")
    enable_transfer = True
    if enable_transfer:
        transfer_dict = file_transfer(ssh_conn, source_file=source_file, dest_file=dest_file,
                                      file_system=file_system, direction='put',
                                      overwrite_file=False)
    else:
        transfer_dict = {}

    # Check the file exists and the MD5 matches the source file
    if not transfer_dict.get('file_exists') or not transfer_dict.get('file_verified'):
        raise ValueError("File doesn't exist or MD5 doesn't match on the remote system")

    print(".verifying new image file.")
    file_size = '42628912'
    verify_image(ssh_conn, file_system, dest_file, file_size)
    print()

    print(".checking current boot commands")
    boot_cmd = check_boot_var(ssh_conn)

    print(".constructing new boot commands")
    if boot_cmd:
        boot_commands = [
            "no {}".format(boot_cmd),
            'boot system flash {}'.format(dest_file),
            boot_cmd,
        ]
    else:
        boot_commands = [
            'boot system flash {}'.format(dest_file),
        ]

    print()
    print(">>>>>")
    print("Boot commands to send to the remote device:")
    print(boot_commands)
    print(">>>>>")
    print()
    hit_any_key()

    print()
    print(".sending new boot commands to remote device.")
    output = ssh_conn.send_config_set(boot_commands)
    print()

    print()
    print("Current boot variable: ")
    print(">>>>>")
    current_boot = ssh_conn.send_command("show run | inc boot")
    print(current_boot)
    print(">>>>>")
    print()

    # Reload the device
    print()
    try:
        response = raw_input("Do you want to reload the device(y/n): ")
    except NameError:
        response = input("Do you want to reload the device(y/n): ")

    if response.lower() != 'y':
        sys.exit("Boot commands staged, but device not reloaded!\n\n")
    else:
        print("Saving running-config to startup-config")
        ssh_conn.save_config()
        print("Reloading device with new image!")
        output = ssh_conn.send_command_timing("reload")
        print(output)
        if 'confirm' in output:
            output = ssh_conn.send_command_timing("y")

    end_time = datetime.now()
    print("File transfer time: {}".format(end_time - start_time))
Exemple #4
0
def main():
    # Collect input details
    ip_addr = input("Enter Device IP address: ")
    user = input("Enter login username: "******"Source file: ")
    md5 = input("md5: ")
    ftp = input("ftp server ip: ")
    ftp_user = input("ftp_username: "******"ftp_password: "******">>>> {}".format(start_time))

    net_device = {
        "device_type": "cisco_ios",
        "ip": ip_addr,
        "username": user,
        "password": my_pass,
        "secret": my_pass,
        "port": 22,
    }

    # Initiate Netmiko Connection
    print("\nLogging in to Device...")
    try:
        ssh_conn = ConnectHandler(**net_device)
    except (AuthenticationException):
        print('Authentication failure: ' + ip_addr)
        sys.exit(1)
    except (NetMikoTimeoutException):
        print('Timeout to device: ' + ip_addr)
        sys.exit(1)
    except (EOFError):
        print("End of file while attempting device " + ip_addr)
        sys.exit(1)
    except (SSHException):
        print('SSH Issue. Are you sure SSH is enabled? ' + ip_addr)
        sys.exit(1)
    except Exception as unknown_error:
        print('Some other error: ' + str(unknown_error))
        sys.exit(1)

    # Check current software version
    print("\nChecking the current software version...\n")
    current_version = ssh_conn.send_command("sh version | in System image")
    print(current_version)

    # Check whether software upgrade required or not
    if source_file in current_version:
        print("-" * 80)
        print("Device already running on latest version. No update required.")
        print("-" * 80)

    else:
        print("-" * 80)
        print(
            "Device not running on target software version. Starting Upgrade process."
        )
        print("-" * 80)
        print("\nInitiate file transfer...")
        output = ssh_conn.send_command("dir | in {}".format(source_file))

        # Check whether upgrade image already exists in filesystem
        if source_file in output:
            print("File already exists. No file transfer required.")
        else:
            # Identify file_system details flash or disk0 or bootflash
            dir_output = ssh_conn.send_command("dir | in Directory")
            dir_output = dir_output.strip().split()
            file_system = dir_output[2]
            file_system = file_system[:-1]
            print("Identifying file_system: {}".format(file_system))

            # Initiate file transfer via FTP
            print("Copying file via FTP...")
            cmd = "copy ftp://{}:{}@{}/{} {}".format(ftp_user, ftp_pass, ftp,
                                                     source_file, file_system)
            output = ssh_conn.send_command(
                cmd, expect_string=r'Destination filename')
            output += ssh_conn.send_command('\n',
                                            expect_string=r'#',
                                            delay_factor=2)
            print(output)

        # Verify file properly copied and MD5 hash
        print("\nCollecting flash details and Verifying MD5...")
        output = ssh_conn.send_command("dir | in {}".format(source_file))
        print(output)
        hash_output = ssh_conn.send_command("verify /md5 {}{} {}".format(
            file_system, source_file, md5),
                                            delay_factor=2)

        if source_file in output and "Verified" in hash_output:
            print("\nFile successfully copied. MD5 hash verified...")

            # Change boot statement commands
            print("\nChanging boot statements...")
            output = ssh_conn.send_command("sh run | in boot system ")
            boot_cmd = [
                'no ' + output,
                'boot system flash0:' + source_file,
            ]
            output = ssh_conn.send_config_set(boot_cmd)
            print(output)

            # Change boot statement properly configured
            print("\nVerifying boot statement...")
            output = ssh_conn.send_command("sh run | in boot system")
            print(output)

            # Save config
            ssh_conn.save_config()
            print("\nSaving config...")

            # Reload device and sleep for 7mins
            print("\nReloading Device...\n")
            request_reload = ssh_conn.send_command(
                "reload in 1\n", expect_string=r'Proceed with reload?')
            request_reload += ssh_conn.send_command('y\n', expect_string=r'#')
            print(request_reload)
            print("\nWaiting for device upgrade and reboot...\n")
            print("\n>>>> {}".format(datetime.now()))
            time.sleep(420)
            print("\n>>>> {}".format(datetime.now()))

            # Login into device again and verify current software version
            print("\nLogging in to Device...")
            ssh_conn = ConnectHandler(**net_device)
            print()
            print("\nVerifying Upgrade...")
            output = ssh_conn.send_command("sh version | in System image")
            print(output)

            # If device running on updated version, print message
            if source_file in output:
                print("-" * 80)
                print("Python sucessfully upgraded the software image.")
                print("-" * 80)

        else:
            print("Upgrade failed")

        print("\n>>>> Total time taken: {}".format(datetime.now() -
                                                   start_time))
        print()
Exemple #5
0
device_type = 'cisco_ios'

for device in devices:
    connection = ConnectHandler(ip=device, device_type=device_type, username=username, password=password)
    interfaces = connection.send_command('show interface switchport', use_textfsm=True)
    config_commands = ['vlan '+ vlan, 'name '+ vlanname]
    output = connection.send_config_set(config_commands)
    print (output)


    for interface in interfaces:
        if interface['admin_mode'] == 'static access' and interface['access_vlan'] == 'none':
            config_commands = 'interface ' + interface['interface'] ,'switchport voice vlan ' + vlan
            output = connection.send_config_set(config_commands)
            print (output)
#the switch I have in the lab has a port channel and did not want to break it.
#I just want to add the vlan to trunks that are port channels and not the physical interfrace        
        elif interface['admin_mode'] == 'trunk' and not "trunk (member of bundle" in interface['mode']:
            config_commands = 'interface ' + interface['interface'],'switchport trunk allowed vlan add ' + vlan
            output1 = connection.send_config_set(config_commands)
            print (output1)

#Saves the config
    print('\n Saving the Switch configuration\n')
    output = connection.save_config()
    print(output)

    #print(json.dumps(interfaces, indent=2))


Exemple #6
0
class AIREOSDevice(BaseDevice):
    """Cisco AIREOS Device Implementation."""

    vendor = "cisco"

    def __init__(self, host, username, password, secret="", port=22, **kwargs):
        super().__init__(host,
                         username,
                         password,
                         device_type="cisco_aireos_ssh")
        self.native = None
        self.secret = secret
        self.port = int(port)
        self.global_delay_factor = kwargs.get("global_delay_factor", 1)
        self.delay_factor = kwargs.get("delay_factor", 1)
        self._connected = False
        self.open()

    def _ap_images_match_expected(self,
                                  image_option,
                                  image,
                                  ap_boot_options=None):
        """
        Test that all AP images have the ``image_option`` matching ``image``.

        Args:
            image_option (str): The boot_option dict key ("primary", "backup") to validate.
            image (str): The image that the ``image_option`` should match.
            ap_boot_options (dict): The results from

        Returns:
            bool: True if all APs have ``image_option`` equal to ``image``, else False.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.ap_boot_options()
            {
                'ap1': {'primary': {'8.10.105.0', 'secondary': '8.10.103.0'},
                'ap2': {'primary': {'8.10.105.0', 'secondary': '8.10.103.0'},
            }
            >>> device._ap_images_match_expected("primary", "8.10.105.0")
            True
            >>>
        """
        if ap_boot_options is None:
            ap_boot_options = self.ap_boot_options

        return all([
            boot_option[image_option] == image
            for boot_option in ap_boot_options.values()
        ])

    def _enter_config(self):
        """Enter into config mode."""
        self.enable()
        self.native.config_mode()

    def _image_booted(self, image_name, **vendor_specifics):
        """
        Check if ``image_name`` is the currently booted image.

        Args:
            image_name (str): The version to check if image is booted.

        Returns:
            bool: True if ``image_name`` is the current boot version, else False.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device._image_booted("8.10.105.0")
            True
            >>>
        """
        re_version = r"^Product\s+Version\s*\.+\s*(\S+)"
        sysinfo = self.show("show sysinfo")
        booted_image = re.search(re_version, sysinfo, re.M)
        if booted_image.group(1) == image_name:
            return True

        return False

    def _send_command(self, command, expect=False, expect_string=""):
        """
        Send single command to device.

        Args:
            command (str): The command to send to the device.
            expect (bool): Whether to send a different expect string than normal prompt.
            expect_string (str): The expected prompt after running the command.

        Returns:
            str: The response from the device after issuing the ``command``.

        Raises:
            CommandError: When the returned data indicates the command failed.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> sysinfo = device._send_command("show sysinfo")
            >>> print(sysinfo)
            Product Version.....8.2.170.0
            System Up Time......3 days 2 hrs 20 mins 30 sec
            ...
            >>>
        """
        if expect:
            if expect_string:
                response = self.native.send_command_expect(
                    command, expect_string=expect_string)
            else:
                response = self.native.send_command_expect(command)
        else:
            response = self.native.send_command_timing(command)

        if "Incorrect usage" in response or "Error:" in response:
            raise CommandError(command, response)

        return response

    def _uptime_components(self):
        """
        Retrieve days, hours, and minutes device has been up.

        Returns:
            tuple: The days, hours, and minutes device has been up as integers.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> days, hours, minutes = device._uptime_components
            >>> print(days)
            83
            >>>
        """
        sysinfo = self.show("show sysinfo")
        re_uptime = r"^System\s+Up\s+Time\.+\s*(.+?)\s*$"
        uptime = re.search(re_uptime, sysinfo, re.M)
        uptime_string = uptime.group()

        match_days = re.search(r"(\d+) days?", uptime_string)
        match_hours = re.search(r"(\d+) hrs?", uptime_string)
        match_minutes = re.search(r"(\d+) mins?", uptime_string)

        days = int(match_days.group(1)) if match_days else 0
        hours = int(match_hours.group(1)) if match_hours else 0
        minutes = int(match_minutes.group(1)) if match_minutes else 0

        return days, hours, minutes

    def _wait_for_ap_image_download(self, timeout=3600):
        """
        Wait for all APs have completed downloading the image.

        Args:
            timeout (int): The max time to wait for all APs to download the image.

        Raises:
            FileTransferError: When an AP is unable to properly retrieve the image or ``timeout`` is reached.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.ap_image_stats()
            {
                "count": 2,
                "downloaded": 0,
                "unsupported": 0,
                "failed": 0,
            }
            >>> device._wait_for_ap_image_download()
            >>> device.ap_image_stats()
            {
                "count": 2,
                "downloaded": 2,
                "unsupported": 0,
                "failed": 0,
            }
            >>>

        TODO:
            Change timeout to be a multiplier for number of APs attached to controller
        """
        start = time.time()
        ap_image_stats = self.ap_image_stats
        ap_count = ap_image_stats["count"]
        downloaded = 0
        while downloaded < ap_count:
            ap_image_stats = self.ap_image_stats
            downloaded = ap_image_stats["downloaded"]
            unsupported = ap_image_stats["unsupported"]
            failed = ap_image_stats["failed"]
            # TODO: When adding logging, send log message of current stats
            if unsupported or failed:
                raise FileTransferError("Failed transferring image to AP\n"
                                        f"Unsupported: {unsupported}\n"
                                        f"Failed: {failed}\n")
            elapsed_time = time.time() - start
            if elapsed_time > timeout:
                raise FileTransferError(
                    "Failed waiting for AP image to be transferred to all devices:\n"
                    f"Total: {ap_count}\nDownloaded: {downloaded}")

    def _wait_for_device_reboot(self, timeout=3600):
        """
        Wait for the device to finish reboot process and become accessible.

        Args:
            timeout (int): The length of time before considering the device unreachable.

        Raises:
            RebootTimeoutError: When a connection to the device is not established within the ``timeout`` period.

        Example:
            >>> device = AIREOSDevice(**connection_args):
            >>> device.reboot()
            >>> device._wait_for_device_reboot()
            >>> device.connected()
            True
            >>>
        """
        start = time.time()
        while time.time() - start < timeout:
            try:
                self.open()
                return
            except:  # noqa E722
                pass

        # TODO: Get proper hostname parameter
        raise RebootTimeoutError(hostname=self.host, wait_time=timeout)

    @property
    def ap_boot_options(self):
        """
        Boot Options for all APs associated with the controller.

        Returns:
            dict: The name of each AP are the keys, and the values are the primary and backup values.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.ap_boot_options
            {
                'ap1': {
                    'backup': '8.8.125.0',
                    'primary': '8.9.110.0',
                    'status': 'complete'
                },
                'ap2': {
                    'backup': '8.8.125.0',
                    'primary': '8.9.110.0',
                    'status': 'complete'
                },
            }
            >>>
        """
        ap_images = self.show("show ap image all")
        ap_boot_options = RE_AP_BOOT_OPTIONS.finditer(ap_images)
        boot_options_by_ap = {
            ap["name"]: {
                "primary": ap.group("primary"),
                "backup": ap.group("backup"),
                "status": ap.group("status").lower(),
            }
            for ap in ap_boot_options
        }
        return boot_options_by_ap

    @property
    def ap_image_stats(self):
        """
        The stats of downloading the the image to all APs.

        Returns:
            dict: The AP count, and the downloaded, unsupported, and failed APs.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.ap_image_stats
            {
                'count': 2,
                'downloaded': 2,
                'unsupported': 0,
                'failed': 0
            }
            >>>
        """
        ap_images = self.show("show ap image all")
        count = RE_AP_IMAGE_COUNT.search(ap_images).group(1)
        downloaded = RE_AP_IMAGE_DOWNLOADED.search(ap_images).group(1)
        unsupported = RE_AP_IMAGE_UNSUPPORTED.search(ap_images).group(1)
        failed = RE_AP_IMAGE_FAILED.search(ap_images).group(1)
        return {
            "count": int(count),
            "downloaded": int(downloaded),
            "unsupported": int(unsupported),
            "failed": int(failed),
        }

    def backup_running_config(self, filename):
        raise NotImplementedError

    @property
    def boot_options(self):
        """
        The images that are candidates for booting on reload.

        Returns:
            dict: The boot options on the device. The "sys" key is the expected image on reload.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.boot_options
            {
                'backup': '8.8.125.0',
                'primary': '8.9.110.0',
                'sys': '8.9.110.0'
            }
            >>>
        """
        show_boot_out = self.show("show boot")
        re_primary_path = r"^Primary\s+Boot\s+Image\s*\.+\s*(?P<primary>\S+)(?P<status>.*)$"
        re_backup_path = r"^Backup\s+Boot\s+Image\s*\.+\s*(?P<backup>\S+)(?P<status>.*)$"
        primary = re.search(re_primary_path, show_boot_out, re.M)
        backup = re.search(re_backup_path, show_boot_out, re.M)
        if primary:
            result = primary.groupdict()
            primary_status = result.pop("status")
            result.update(backup.groupdict())
            backup_status = result.pop("status")
            if "default" in primary_status:
                result["sys"] = result["primary"]
            elif "default" in backup_status:
                result["sys"] = result["backup"]
            else:
                result["sys"] = None
        else:
            result = {"sys": None}
        return result

    def checkpoint(self, filename):
        raise NotImplementedError

    def close(self):
        """Close the SSH connection to the device."""
        if self._connected:
            self.native.disconnect()
            self._connected = False

    def config(self, command):
        """
        Configure the device with a single command.

        Args:
            command (str): The configuration command to send to the device.
                           The command should not include the "config" keyword.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.config("boot primary")
            >>>

        Raises:
            CommandError: When the device's response indicates the command failed.
        """
        self._enter_config()
        self._send_command(command)
        self.native.exit_config_mode()

    def config_list(self, commands):
        """
        Send multiple configuration commands to the device.

        Args:
            commands (list): The list of commands to send to the device.
                             The commands should not include the "config" keyword.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.config_list(["interface hostname virtual wlc1.site.com", "config interface vlan airway 20"])
            >>>

        Raises:
            COmmandListError: When the device's response indicates an error from sending one of the commands.
        """
        self._enter_config()
        entered_commands = []
        for command in commands:
            entered_commands.append(command)
            try:
                self._send_command(command)
            except CommandError as e:
                self.native.exit_config_mode()
                raise CommandListError(entered_commands, command,
                                       e.cli_error_msg)
        self.native.exit_config_mode()

    @property
    def connected(self):
        """
        The connection status of the device.

        Returns:
            bool: True if the device is connected, else False.
        """
        return self._connected

    @connected.setter
    def connected(self, value):
        self._connected = value

    def enable(self):
        """
        Ensure device is in enable mode.

        Returns:
            None: Device prompt is set to enable mode.
        """
        # Netmiko reports enable and config mode as being enabled
        if not self.native.check_enable_mode():
            self.native.enable()
        # Ensure device is not in config mode
        if self.native.check_config_mode():
            self.native.exit_config_mode()

    @property
    def facts(self):
        raise NotImplementedError

    def file_copy(
        self,
        username,
        password,
        server,
        filepath,
        protocol="sftp",
        filetype="code",
        delay_factor=3,
    ):
        """
        Copy a file from server to Controller.

        Args:
            username (str): The username to authenticate with the ``server``.
            password (str): The password to authenticate with the ``server``.
            server (str): The address of the file server.
            filepath (str): The full path to the file on the ``server``.
            protocol (str): The transfer protocol to use to transfer the file.
            filetype (str): The type of file per aireos definitions.
            delay_factor (int): The Netmiko delay factor to wait for device to complete transfer.

        Returns:
            bool: True when the file was transferred, False when the file is deemed to already be on the device.

        Raises:
            FileTransferError: When an error is detected in transferring the file.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.boot_options
            {
                'backup': '8.8.125.0',
                'primary': '8.9.100.0',
                'sys': '8.9.100.0'
            }
            >>> device.file_copy("user", "password", "10.1.1.1", "/images/aireos/AIR-CT5500-K9-8-10-105-0.aes")
            >>> device.boot_options
            {
                'backup': '8.9.100.0',
                'primary': '8.10.105.0',
                'sys': '8.10.105.0'
            }
            >>>
        """
        self.enable()
        filedir, filename = os.path.split(filepath)
        if filetype == "code":
            version = convert_filename_to_version(filename)
            if version in self.boot_options.values():
                return False
        try:
            self.show_list([
                f"transfer download datatype {filetype}",
                f"transfer download mode {protocol}",
                f"transfer download username {username}",
                f"transfer download password {password}",
                f"transfer download serverip {server}",
                f"transfer download path {filedir}/",
                f"transfer download filename {filename}",
            ])
            response = self.native.send_command_timing(
                "transfer download start")
            if "Are you sure you want to start? (y/N)" in response:
                response = self.native.send_command(
                    "y",
                    expect_string="File transfer is successful.",
                    delay_factor=delay_factor)

        except:  # noqa E722
            raise FileTransferError

        return True

    def file_copy_remote_exists(self, src, dest=None, **kwargs):
        raise NotImplementedError

    def install_os(self,
                   image_name,
                   controller="both",
                   save_config=True,
                   **vendor_specifics):
        """
        Install an operating system on the controller.

        Args:
            image_name (str): The version to install on the device.
            controller (str): The controller(s) to reboot for install (only applies to HA device).
            save_config (bool): Whether the config should be saved to the device before reboot.

        Returns:
            bool: True when the install is successful, False when the version is deemed to already be running.

        Raises:
            OSInstallError: When the device is not booted with the specified image after reload.
            RebootTimeoutError: When the device is unreachable longer than the reboot timeout value.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.boot_options
            {
                'backup': '8.8.125.0',
                'primary': '8.9.100.0',
                'sys': '8.9.100.0'
            }
            >>> device.file_copy("user", "password", "10.1.1.1", "/images/aireos/AIR-CT5500-K9-8-10-105-0.aes")
            >>> device.boot_options
            {
                'backup': '8.9.100.0',
                'primary': '8.10.105.0',
                'sys': '8.10.105.0'
            }
            >>> device.install_os("8.10.105.0")
            >>>
        """
        timeout = vendor_specifics.get("timeout", 3600)
        if not self._image_booted(image_name):
            peer_redundancy = self.peer_redundancy_state
            self.set_boot_options(image_name, **vendor_specifics)
            self.reboot(confirm=True,
                        controller=controller,
                        save_config=save_config)
            self._wait_for_device_reboot(timeout=timeout)
            if not self._image_booted(image_name):
                raise OSInstallError(hostname=self.host,
                                     desired_boot=image_name)
            if not self.peer_redundancy_state == peer_redundancy:
                raise OSInstallError(hostname=f"{self.host}-standby",
                                     desired_boot=image_name)

            return True

        return False

    def open(self):
        """
        Open a connection to the controller.

        This method will close the connection if it is determined that it is the standby controller.
        """
        if self.connected:
            try:
                self.native.find_prompt()
            except:  # noqa E722
                self.connected = False

        if not self.connected:
            self.native = ConnectHandler(
                device_type="cisco_wlc",
                ip=self.host,
                username=self.username,
                password=self.password,
                port=self.port,
                global_delay_factor=self.global_delay_factor,
                secret=self.secret,
                verbose=False,
            )
            self.connected = True

        # This prevents open sessions from connecting to STANDBY WLC
        if not self.redundancy_state:
            self.close()

    @property
    def peer_redundancy_state(self):
        """
        Determine the state of the peer device.

        Returns:
            str: The Peer State from the local device's perspective.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.peer_redundancy_state
            'standby hot'
            >>>
        """
        ha = self.show("show redundancy summary")
        ha_peer_state = re.search(r"^\s*Peer\s+State\s*=\s*(.+?)\s*$", ha,
                                  re.M)
        return ha_peer_state.group(1).lower()

    def reboot(self,
               timer=0,
               confirm=False,
               controller="self",
               save_config=True):
        """
        Reload the controller or controller pair.

        Args:
            timer (int): The time to wait before reloading.
            confirm (bool): Whether to reboot the device or not.
            controller (str): Which controller(s) to reboot (only applies to HA pairs).
            save_config (bool): Whether the configuraion should be saved before reload.

        Raises:
            ReloadTimeoutError: When the device is still unreachable after the timeout period.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.reboot(confirm=True)
            >>>
        """
        if confirm:

            def handler(signum, frame):
                raise RebootSignal("Interrupting after reload")

            signal.signal(signal.SIGALRM, handler)

            if self.redundancy_mode != "sso disabled":
                reboot_command = f"reset system {controller}"
            else:
                reboot_command = "reset system"

            if timer:
                reboot_command += f" in {timer}"

            if save_config:
                self.save()

            signal.alarm(20)
            try:
                response = self.native.send_command_timing(reboot_command)
                if "save" in response:
                    if not save_config:
                        response = self.native.send_command_timing("n")
                    else:
                        response = self.native.send_command_timing("y")
                if "reset" in response:
                    self.native.send_command_timing("y")
            except RebootSignal:
                signal.alarm(0)

            signal.alarm(0)
        else:
            print("Need to confirm reboot with confirm=True")

    @property
    def redundancy_mode(self):
        """
        The oprating redundancy mode of the controller.

        Returns:
            str: The redundancy mode the device is operating in.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.redundancy_mode
            'sso enabled'
            >>>
        """
        ha = self.show("show redundancy summary")
        ha_mode = re.search(r"^\s*Redundancy\s+Mode\s*=\s*(.+?)\s*$", ha, re.M)
        return ha_mode.group(1).lower()

    @property
    def redundancy_state(self):
        """
        Determine if device is currently the active device.

        Returns:
            bool: True if the device is active, False if the device is standby.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.redundancy_state
            True
            >>>
        """
        ha = self.show("show redundancy summary")
        ha_state = re.search(r"^\s*Local\s+State\s*=\s*(.+?)\s*$", ha, re.M)
        if ha_state.group(1).lower() == "active":
            return True
        else:
            return False

    def rollback(self):
        raise NotImplementedError

    @property
    def running_config(self):
        raise NotImplementedError

    def save(self):
        """
        Save the configuration on the device.

        Returns:
            bool: True if the save command did not fail.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.save()
            >>>
        """
        self.native.save_config()
        return True

    def set_boot_options(self, image_name, **vendor_specifics):
        """
        Set the version to boot on the device.

        Args:
            image_name (str): The version to boot into on next reload.

        Raises:
            NTCFileNotFoundError: When the version is not listed in ``boot_options``.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.boot_options
            {
                'backup': '8.8.125.0',
                'primary': '8.9.100.0',
                'sys': '8.9.100.0'
            }
            >>> device.set_boot_options("8.8.125.0")
            >>> device.boot_options
            {
                'backup': '8.8.125.0',
                'primary': '8.9.100.0',
                'sys': '8.8.125.0'
            }
        """
        if self.boot_options["primary"] == image_name:
            boot_command = "boot primary"
        elif self.boot_options["backup"] == image_name:
            boot_command = "boot backup"
        else:
            raise NTCFileNotFoundError(image_name, "'show boot'", self.host)
        self.config(boot_command)
        self.save()
        if not self.boot_options["sys"] == image_name:
            raise CommandError(
                command=boot_command,
                message="Setting boot command did not yield expected results",
            )

    def show(self, command, expect=False, expect_string=""):
        """
        Send an operational command to the device.

        Args:
            command (str): The command to send to the device.
            expect (bool): Whether to send a different expect string than normal prompt.
            expect_string (str): The expected prompt after running the command.

        Returns:
            str: The data returned from the device

        Raises:
            CommandError: When the returned data indicates the command failed.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> sysinfo = device._send_command("show sysinfo")
            >>> print(sysinfo)
            Product Version.....8.2.170.0
            System Up Time......3 days 2 hrs 20 mins 30 sec
            ...
            >>>
        """
        self.enable()
        return self._send_command(command,
                                  expect=expect,
                                  expect_string=expect_string)

    def show_list(self, commands):
        """
        Send an operational command to the device.

        Args:
            commands (list): The list of commands to send to the device.
            expect (bool): Whether to send a different expect string than normal prompt.
            expect_string (str): The expected prompt after running the command.

        Returns:
            list: The data returned from the device for all commands.

        Raises:
            CommandListError: When the returned data indicates one of the commands failed.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> command_data = device._send_command(["show sysinfo", "show boot"])
            >>> print(command_data[0])
            Product Version.....8.2.170.0
            System Up Time......3 days 2 hrs 20 mins 30 sec
            ...
            >>> print(command_data[1])
            Primary Boot Image............................... 8.2.170.0 (default) (active)
            Backup Boot Image................................ 8.5.110.0
            >>>
        """
        self.enable()

        responses = []
        entered_commands = []
        for command in commands:
            entered_commands.append(command)
            try:
                responses.append(self._send_command(command))
            except CommandError as e:
                raise CommandListError(entered_commands, command,
                                       e.cli_error_msg)

        return responses

    @property
    def startup_config(self):
        raise NotImplementedError

    def transfer_image_to_ap(self, image, timeout=None):
        """
        Transfer ``image`` file to all APs connected to the WLC.

        Args:
            image (str): The image that should be sent to the APs.
            timeout (int): The max time to wait for all APs to download the image.

        Returns:
            bool: True if AP images are transferred or swapped, False otherwise.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.ap_boot_options
            {
                'ap1': {
                    'backup': '8.8.125.0',
                    'primary': '8.9.110.0',
                    'status': 'complete'
                },
                'ap2': {
                    'backup': '8.8.125.0',
                    'primary': '8.9.110.0',
                    'status': 'complete'
                },
            }
            >>> device.transfer_image_to_ap("8.10.1.0")
            >>> device.ap_boot_options
            {
                'ap1': {
                    'backup': '8.9.110.0',
                    'primary': '8.10.1.0',
                    'status': 'complete'
                },
                'ap2': {
                    'backup': '8.9.110.0',
                    'primary': '8.10.1.0',
                    'status': 'complete'
                },
            }
            >>>
        """
        boot_options = ["primary", "backup"]
        ap_boot_options = self.ap_boot_options
        changed = False
        if self._ap_images_match_expected("primary", image, ap_boot_options):
            return changed

        if not any(
                self._ap_images_match_expected(option, image, ap_boot_options)
                for option in boot_options):
            changed = True
            download_image = None
            for option in boot_options:
                if self.boot_options[option] == image:
                    download_image = option
                    break
            if download_image is None:
                raise FileTransferError(
                    f"Unable to find {image} on {self.host}")

            self.config(f"ap image predownload {option} all")
            self._wait_for_ap_image_download()

        if self._ap_images_match_expected("backup", image):
            changed = True
            self.config("ap image swap all")
            # testing showed delay in reflecting changes when issuing `show ap image all`
            time.sleep(1)

        if not self._ap_images_match_expected("primary", image):
            raise FileTransferError(f"Unable to set all APs to use {image}")

        return changed

    @property
    def uptime(self):
        """
        The uptime of the device in seconds.

        Returns:
            int: The number of seconds the device has been up.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.uptime
            109303
            >>>
        """
        days, hours, minutes = self._uptime_components()
        hours += days * 24
        minutes += hours * 60
        seconds = minutes * 60
        return seconds

    @property
    def uptime_string(self):
        """
        The uptime of the device as a string.
        The format is dd::hh::mm

        Returns:
            str: The uptime of the device.

        Example:
            >>> device = AIREOSDevice(**connection_args)
            >>> device.uptime_string
            22:04:39
            >>>
        """
        days, hours, minutes = self._uptime_components()
        return "%02d:%02d:%02d:00" % (days, hours, minutes)
Exemple #7
0
# pip install netmiko

from netmiko import ConnectHandler
from my_devices_2 import device_list as devices

with open('config_file') as f:
    config_list = f.read().splitlines()

for a_device in devices:
    session = ConnectHandler(**a_device)
    output = session.send_config_set(config_list)
    output += session.save_config()
    print(output)
Exemple #8
0
    "username": "******",
    "password": "******",
    "device_type": "cisco_nxos",
}

nxos2 = {
    "host": "nxos2.lasthop.io",
    "username": "******",
    "password": "******",
    "device_type": "cisco_nxos",
}

nxos1_connect = ConnectHandler(**nxos1)
nxos2_connect = ConnectHandler(**nxos2)

week2_exercise5_txt = []
with open('week2_exercise5.txt') as txt:
    week2_exercise5_txt = txt.readlines()

# print(week2_exercise5_txt)

nxos1_output_1 = (nxos1_connect.send_config_from_file(
    config_file='week2_exercise5.txt'))
nxos1_output_2 = (nxos1_connect.save_config())

print(nxos1_output_1, nxos1_output_2)

nxos1_output_3 = (nxos1_connect.send_command('show vlan brief'))

print(nxos1_output_3)
from netmiko import ConnectHandler
import os

ciscoasa = {
    'device_type': 'cisco_asa',
    'ip': '192.168.1.76',
    'username': '******',
    'password': os.getenv('ciscopass'),
}

conn = ConnectHandler(**ciscoasa)

config_commands = ['pager 0', 'logging permit-hostdown']

output = conn.send_config_set(config_commands)
wr = conn.save_config()
conn.disconnect()

print(output)
print(wr)
Exemple #10
0
class CiscoIOSDevice:
    def __init__(self, ip, connection_parameters):
        self.ip = ip
        self.connection_parameters = connection_parameters
        self.connection_parameters.ip = self.ip
        self.hostname = None
        self.registered = False
        self.dlc = False
        self.__session = None
        self.dlc_supported = False

    def connect(self):
        try:
            self.__session = ConnectHandler(
                **self.connection_parameters.__dict__)
            self.__session.enable()
            if not self.hostname:
                self.hostname = self.__session.find_prompt().replace('#', '')
            logging.info(
                f'{self.hostname} :: {self.ip} :: Connected :: {datetime.now()}'
            )
            return self.__session
        except Exception as e:
            logging.error(f'{self.ip} :: {e} :: {datetime.now()}')

    def disconnect(self):
        self.__session.disconnect()
        logging.info(
            f'{self.hostname} :: {self.ip} :: Disconnected :: {datetime.now()}'
        )
        self.__session = None

    def show_run(self):
        return self.__session.send_command('show run').splitlines()

    def check_status(self):
        show_license = self.__session.send_command('show license status')
        status = []
        for line in show_license.splitlines():
            if 'Status:' in line:
                status.append(line.strip()[8:])
        status.pop(0)
        registration_status = status[0]
        if registration_status == 'REGISTERED':
            logging.info(
                f'{self.hostname} :: {self.ip} :: Device is registered :: {datetime.now()}'
            )
            self.registered = True
        if len(status) == 3:
            self.dlc_supported = True
            dlc_status = status[2]
            if dlc_status != 'Not started':
                logging.info(
                    f'{self.hostname} :: {self.ip} :: DLC started :: {datetime.now()}'
                )
                self.dlc = True

    def register(self, token):
        pre_check = self.show_run()
        self.__session.send_config_from_file(
            config_file='smart_license_config.txt')
        logging.info(
            f'{self.hostname} :: {self.ip} :: Configuration for Smart License is done :: {datetime.now()}'
        )
        post_check = self.show_run()
        with open(f'{self.hostname}.html', 'w') as diff_file:
            diff = difflib.HtmlDiff()
            diff_file.write(diff.make_file(pre_check, post_check))
        self.__session.save_config()
        logging.info(
            f'{self.hostname} :: {self.ip} :: Configuration is saved :: {datetime.now()}'
        )
        self.__session.send_command(f'license smart register idtoken {token}')
        logging.info(
            f'{self.hostname} :: {self.ip} :: Smart License registration has started :: {datetime.now()}'
        )

    def wait_for_registration(self, seconds):
        for i in range(int(seconds) + 1):
            time.sleep(1)
            if i % 10 == 0:
                self.check_status()
                if self.registered:
                    logging.info(
                        f'{self.hostname} :: {self.ip} :: Devices has been registered :: {datetime.now()}'
                    )
                    break
        if not self.registered:
            for line in self.__session.send_command(
                    'show license status').splitlines():
                if line.strip().startswith('Failure reason:'):
                    registration_error = line.strip()[16:]
                    logging.warning(
                        f'{self.hostname} :: {self.ip} :: {registration_error} :: {datetime.now()}'
                    )

    def run_dlc(self):
        self.__session.send_command('license smart conversion start')
        logging.info(
            f'{self.hostname} :: {self.ip} :: DLC Started :: {datetime.now()}')

    def ping(self):
        ping_result = self.__session.send_command('ping IP')
        return True if '64 bytes' in ping_result else False
Exemple #11
0
connect = ConnectHandler(**device_information)
connect.enable()

# Creating a list of all Vlan's
vlan_names = [
    'Management', 'Staff', 'Guest', 'HR-Office', 'Administation', 'Finance'
]

a = 10
while a <= 60:

    for i in vlan_names:
        print("         *** Creating Vlan " + str(a) + " ***  ")
        vlan_num = ['Vlan ' + str(a), 'name ' + str(i)]
        a += 10
        send_conf = connect.send_config_set(vlan_num, cmd_verify=False)
        if vlan_names == 'Finance':
            break
        print(send_conf)

print("\n  ##### Saving the configuration #####   ")
save = connect.save_config()
print(save)

print("#" * 80, "\n   *** show vlan brief ***    ")
sh_vlan = connect.send_command('show vlan brief')
print(sh_vlan)

print("\n   *   *   *    Closing connection   *   *   *   ")
connect.disconnect()
Exemple #12
0
def connect_to_device(remote_device, interface, ip_name):
    if remote_device['device_type'] == 'arista_eos':
        netconnect = ConnectHandler(**remote_device)
        cname = netconnect.find_prompt()
        device_name = cname.replace('>', ' ')
        print('')
        cprint('Connected to {}'.format(device_name), 'yellow', 'on_red')
        cprint('...Performing PRE-CHECK...', 'yellow', 'on_red')
        print('')
        shint = netconnect.send_command(
            'show interface {} | in ip|Desc|Et'.format(interface))
        rprint(shint)
        netconnect.enable()
        # print(netconnect.find_prompt())
        time.sleep(5)
        print(
            colored('Checking interface description if port is a TAP',
                    'white',
                    'on_red',
                    attrs=['reverse', 'blink']))
        print('')
        x = []
        intf_conf = netconnect.send_command(
            'show run int {} | in desc'.format(interface))
        x = intf_conf.strip()
        result = x.find('TAP')
        if result != -1:
            print(
                colored('PORT IS A TAP',
                        'white',
                        'on_red',
                        attrs=['reverse', 'blink']))

        else:
            print(
                colored('PORT IS NOT A TAP',
                        'white',
                        'on_red',
                        attrs=['reverse', 'blink']))
            rprint('[red]...Disconnecting[red]')
            netconnect.disconnect()

        # matching = [s for s in tap if "TAP" in s]
        # print(matching)
        print('')
        shrun = netconnect.send_command(
            'show run interface {}'.format(interface))
        rprint(shrun)
        print('')
        print(
            colored('##########################################',
                    'white',
                    'on_red',
                    attrs=['reverse', 'blink']))
        print('ARE YOU SURE YOU WANT TO BOUNCE THIS PORT?')
        print(
            colored('##########################################',
                    'white',
                    'on_red',
                    attrs=['reverse', 'blink']))
        rprint('')
        user_input = input('ENTER [Y]es or [N]o: ')
        select = user_input.lower().strip()

        if select == 'y' and select:
            commands = [
                'int {}'.format(interface), 'shutdown', 'do show run diff',
                'no shut', 'do show run int {}'.format(interface),
                'do show run diff'
            ]
            print('')
            output = netconnect.send_config_set(commands)
            output += netconnect.save_config()
            rprint(output)
            print('')
            time.sleep(10)
            netconnect.disconnect()
            rprint('[red]..Disconnecting to {} [red]'.format(device_name))

        elif select == 'n' and select:
            print('..Try again..')
            netconnect.disconnect()

        else:
            rprint('.Try Again..')

    else:
        print(
            colored('This script is only for Arista AGG device',
                    'white',
                    'on_red',
                    attrs=['reverse', 'blink']))
Exemple #13
0
from netmiko import ConnectHandler
from getpass import getpass

password = getpass(prompt="Bitte Passwort eingeben : ")
cisco_nxos1 = {"host": "nxos1.lasthop.io",
               "username": "******",
               "password": password,
               "device_type": "cisco_nxos",
               "session_log": "my_session1.txt"}

cisco_nxos2 = {"host": "nxos2.lasthop.io",
               "username": "******",
               "password": password,
               "device_type": "cisco_nxos",
               "session_log": "my_session2.txt"}


device_list = [cisco_nxos1, cisco_nxos2]

for device in device_list:
    nxos_connect = ConnectHandler(**device)
    print(nxos_connect.find_prompt())
    output = nxos_connect.send_config_from_file("vlan.txt")
    output += nxos_connect.save_config()
    #print(output)
    nxos_connect.disconnect()



Exemple #14
0
    'password': '******',
    'secret': 'cisco'

}

try:
    ssh_connection = ConnectHandler(**ios_l2_accesslayer1)
    print("connection success\n")
    ssh_connection.enable()
    print(ssh_connection.find_prompt())
    ports = ["gig 0/0", "gig 0/1 ", "gig1/0"]
    for com in ports:
        commands = ['int' + " " + str(com), 'switchport trunk encapsulation dot1q', 'switchport mode trunk', 'exit']
        out = ssh_connection.send_config_set(commands)
        time.sleep(5)
        ssh_connection.save_config(self, 'write mem', False, '')
        print(out)



except:

    print("login failure\n")
    sys.exit()

try:
    ssh_connection = ConnectHandler(**ios_l2_distlayer1)
    print("connection success\n")
    ssh_connection.enable()
    print(ssh_connection.find_prompt())
    ports = ["gig 0/0", "gig 0/1 ", "gig 0/2", "gig 2/1", "gig 2/0", "gig 1/0", "gig 1/1"]
def configuration():
    start_time = datetime.now()

    #Ouverture du fichier de configuration et du fichier contenant les IP des commutateurs.
    with open('CONFIGURATION_L2') as f:
        lines_l2 = f.read().splitlines()
    with open('switch.list') as f:
        ip_sw = f.read().splitlines()

    #Boucle autant de fois qu'il y a de ligne dans le fichier 'switch.list'.
    for ip in ip_sw:
        device = {
            'device_type': 'cisco_ios',
            'ip': ip,
            'username': username,
            'password': password,
        }
        net_connect = ConnectHandler(**device)
        #Vérifie la présence d'une ligne de configuration issu du fichier 'CONFIGURATION_L2', si résultat positif: n'envoie rien.
        #Sauvegarde la 'running-config' dans la 'startup-config' dans les 2 cas.
        try:
            result = net_connect.send_command(
                "show running-config | inc ip access-list standard SSH")
        except (NetMikoTimeoutException):
            print("Délai d'attente dépassé.  " + ip)
        if "ip access-list standard SSH" in result:
            net_connect.save_config()
            time.sleep(0.5)
            net_connect.disconnect()

        #Envoie l'intégralité du contenu du fichier de configuration.
        else:
            output = net_connect.send_config_set(lines_l2)
            time.sleep(1)
            net_connect.save_config()
            time.sleep(0.5)
            net_connect.disconnect()
            print(output)

    #Ouverture du fichier de configuration et du fichier contenant les IP des routeurs.
    with open('CONFIGURATION_L3') as f:
        lines = f.read().splitlines()
    with open('router.list') as f:
        ip_rtr = f.read().splitlines()

    #Boucle autant de fois qu'il y a de ligne dans 'router.list'.
    for ip in ip_rtr:
        device = {
            'device_type': 'cisco_ios',
            'ip': ip,
            'username': username,
            'password': password,
        }

        net_connect = ConnectHandler(**device)
        #Vérifie la présence d'une ligne de configuration issue de 'CONFIGURATION_L3', si résultat positif; n'envoie rien.
        #Sauvegarde la 'running-config' dans la 'startup-config' dans les 2 cas.
        try:
            result = net_connect.send_command(
                "show running-config | inc ip access-list standard SSH")
        except (NetMikoTimeoutException):
            print("Délai d'attente dépassé. " + ip)
        if "ip access-list standard SSH" in result:
            net_connect.save_config()
            time.sleep(0.5)
            net_connect.disconnect()

        #Envoie l'intégralité du contenu du fichier de configuration

        else:
            output = net_connect.send_config_set(lines)
            time.sleep(1)
            net_connect.save_config()
            time.sleep(0.5)
            net_connect.disconnect()
            print(output)

    end_time = datetime.now()
    total_time = end_time - start_time
    print("Durée de la configuration: " + str(total_time) + "\n")
Exemple #16
0
'''On both the NXOS1 and NXOS2 switches configure five VLANs including VLAN names (just pick 5 VLAN numbers between 100 - 999).
Use Netmiko's send_config_from_file() method to accomplish this.
Also use Netmiko's save_config() method to save the changes to the startup-config.'''

from netmiko import ConnectHandler
from getpass import getpass
password = getpass()

nxos1_dict = {
    "host": "nxos1.lasthop.io",
    "username": "******",
    "password": password,
    "device_type": "cisco_nxos"
}
nxos2_dict = {
    "host": "nxos2.lasthop.io",
    "username": "******",
    "password": password,
    "device_type": "cisco_nxos"
}

for dev in (nxos1_dict, nxos2_dict):
    dev_conn = ConnectHandler(**dev)
    op = dev_conn.find_prompt()
    op += dev_conn.send_config_from_file("vlans.txt")
    dev_conn.save_config()
    print(op)
    print("*" * 60)
    dev_conn.disconnect()
class ConnectToDevice(object):
    """
    This class pretend to establish a connection to a network device.

    It has 4 functions (static methods):
        - configure_add_raw_commands : send a cisco command to a device. it not run on privileged mode
        - configure_add_raw_commands_not_privileged:  send a cisco command to a device on privileged mode.
        - configures_add_commands_list: send a list of cisco commands to device: it runs on privileged mode.
            (it puts the CLI prompt on: device_name<config>    )
        - save_running_config - save running configurations on cisco network devices

    We could build this code as functions because we don't change anything in the instance object properties of the
    class

    This clas dont validate any data passed to the class. we are assuming that the data is ok.


    :param data: <dict> keys: "ip" - device ip to establish a connection
    :param connection_type <string> WE are expecting "SSH" or "TELNET" as strings for this parameter
                                            ** THIS OPTIONAL PARAMETER

    :param port <int> a port to connect    ** THIS PARAMETER IS OPTIONAL
    :return , check each method, since each one can export different types of data

    ====================================================================================================================

    ## NETMIKO SUPPORTS THIS CISCO DEVICES: (in 2019 Was different)
    ## CISCO DEVICES DRIVERS SUPORTED BY NETMIKO in 2020:
    ## ["cisco_asa", "cisco_ios", "cisco_nxos", "cisco_s300", "cisco_tp", "cisco_wlc", "cisco_xe", "cisco_xr"]


    ## WE suppose, (but not confirmed) that NETMIKO 2020 uses Cisco pyATS and Cisco Gennie 'capabilities' to connect to
    the new Cisco operating systems running on new devices. (e.g. nexos)
    ** We may want to automate configurations on network devices directly through Python pyATS and gennie or Ansible
        source: https://developer.cisco.com/docs/pyats/#!introduction/cisco-pyats-network-test--automation-solution

    # NETMIKO SOURCE LINKS:
        - source: https://ktbyers.github.io/netmiko/docs/netmiko/cisco_base_connection.html
        - source: https://ktbyers.github.io/netmiko/docs/netmiko/index.html
        - source: https://pynet.twb-tech.com/blog/automation/netmiko.html
        - source: https://github.com/ktbyers/netmiko

    ## DEVELOPMENT ENVIRONMENT
    In 2019, we were using 'cisco_ios' driver for ssh connections. and "cisco_ios_telnet" for telnet connections
    It proved to work properly on the devices that we test.
    We have implemented netmiko new feature SSHdiscover that tries to guess which operating system is running on device
    and choose for us the the correspondent device_driver for better interaction.
    We don't know which NETWORK device, CLIENTS WANT TO CONNECT, JUST THE IP.
    NOTE:
    May consider to be mandatory in future requests, that clients send us the OS Device Type instead of just telnet or
    ssh. Or have access to a database table or a file with a mapping between "ip">> "OS type".

    We have tested on these 2 Cisco devices:
        Cisco device 1:
            - Model:  WS-C3560-48PS
            - IOS VERSION: 12.2(53)SE2
        Cisco device 2:
            - Model:  WS-C2950T-24
            - IOS VERSION: 12.1(22)EA14
    --------------------------------------------------------------------------------------------------------------------
        NOTE: if we run problems when connecting to devices(slow networks, slow equipment , etc.) we may consider in
        adjusting and override global_delay_factor for connections.) We can pass as« a key,value pair when we call the
        ConnectHandler method.

        Rationale: netmiko  send_command << will wait 100 seconds by default, which corresponds to default, global_delay_factor=1,
                    if set to:
                        gobal_delay_factor=2  it will duplicate the amount of time
                        goblal_delay_factor=3 will triplicate
                        and so on ...
    --------------------------------------------------------------------------------------------------------------------
    Methods  in MODULE netmiko.cisco_base_connection. THEY ARE USEFUL IF WE NEED TO BUILD MORE functionalities
        - check_config_mode--> Checks if the device is in configuration mode or not.
        - check_enable_mode--> Check if in enable mode. Return boolean.
        - cleanup: Gracefully--> exit the SSH session.
        - config_mode--> Enter into configuration mode on remote device.
        - enable--> Enter enable mode.
        - exit_config_mode--> Exit from configuration mode.
        - exit_enable_mode--> Exits enable (privileged exec) mode.
        - save_config--> Saves Config.
        - serial_login
        - telnet_login

    ###
    ### LAST NOTE:
    Since one of the goals of the development of this application was to present me (the processes of
    writing an app) And i had no knowledge of the oop programming paradigm, I think this class could be better
    constructed using python class inheritance.
        e.g.    class ConnectToDevice(Netmiko):



    """

    # init method
    def __init__(self, data, connection_type, port=None):
        # class attributes

        # TODO: # WE SHOULD CONSIDER TO USE THIS credenctiasl as an(APLICATION  ENV) decrypted
        #  from disk WHENEVER OUR APP STARTS
        self.device_credentials = {
            "device_username": current_app.config["DEVICE_USERNAME"],
            "device_password": current_app.config["DEVICE_PASSWORD"],
            "device_secret": current_app.config["DEVICE_SECRET"]
        }
        self.data = data
        self.connection_type = connection_type
        self.port = port
        print("=" * 79)
        print("OUTPUT - port: ", port)
        print("OUTPUT - connection_type: ", connection_type)
        print("=" * 79)
        if self.connection_type == "TELNET":
            self.connection_type = "cisco_ios_telnet"
            if port is None:
                self.port = 23

        if self.connection_type == "SSH":
            # FOR SSH  WE WILL TRY TO GUESS FIRST THE BEST MATCH
            if port is None:
                self.port = 22

            # INSERT TEST GUESS HERE
            ssh_device_driver = guess_device(ip=self.data["ip"],
                                             port=self.port)
            print(
                "OUTPUT - -----------------------------------------------------------------"
            )
            print("OUTPUT - GUESSING THE SSH DEVICE DRIVER")
            print("OUTPUT - ssh device driver best match is :",
                  ssh_device_driver)
            if isinstance(ssh_device_driver, dict):
                if "STATUS" in ssh_device_driver:
                    if ssh_device_driver["STATUS"] == "Failure":
                        print(" WE COULDNT GUESS THE DEVICE DRIVER FOR SSH")
                        # LETS USE DEFAULT DEVICE DRIVER
                        self.connection_type = "cisco_ios"
            else:
                self.connection_type = ssh_device_driver

        print("OUTPUT - ---------------------")
        print("OUPTUT - INSTANCE OBJECT- ConnectToDevice - __INIT__ METHOD")
        print("OUTPUT - Preparing to connect to device with this setup:")
        print("OUTPUT - device ip: ", self.data["ip"])
        print("OUTPUT - connection_type: ", self.connection_type)
        print("OUTPUT - port: ", self.port)

        # (STANDARD FAILURE DICTIONARY) AND SET VALUES FOR THIS OPERATION ERROR
        self.error_dictionary = {
            "STATUS": "Failure",
            "ERROR": "4",
            "TYPE": {},
            "MESSAGE": {}
        }

    def configure_add_raw_commands(self, command_to_send):
        """
        THIS FUNCTION send  a command to a cisco network device in privileged mode
        :param command_to_send: <string>
        :return: <tupple> a tuple with 2 items. one item is a structured result if netmiko could parse the data
        The second item will be unparsed data, result of the command output in the network device CLI
        """

        print(
            "OUTPUT - Entering...  configure_add_raw_commands --> METHOD           "
        )
        try:
            # ESTABLISH A  CONNECTION TO DEVICE USING NETMIKO
            self.net_connect = ConnectHandler(
                device_type=self.connection_type,
                ip=self.data["ip"],
                username=self.device_credentials["device_username"],
                password=self.device_credentials["device_password"],
                secret=self.device_credentials["device_secret"],
                port=self.port)

            # ENTER PRIVILEGED MODE -- like we put enable in the cisco console.
            self.net_connect.enable()

            # ELIMINATES DE "MORE" WORD ON CISCO TERMINAL - USER DOESN'T HAVE TO PRESS A KEY TO CONTINUE
            self.net_connect.send_command('terminal length 0')

            # WE want to try to get structured data from the cli output but it is only possible
            # TEXTFSM - ntc templates were installed
            try:
                output_structured = self.net_connect.send_command(
                    command_to_send, use_textfsm=True)
            # DESEINTALAR O PATH OU ALTERAR PARA OUTRA LOCALIZACAO NAO EXISTENTE E VER O TIPO DE ERRO QUE DA_
            # Esta excepcao não é a melhor forma de apanhar errors
            except Exception:
                output_structured = None
            output_unstructured = self.net_connect.send_command(
                command_to_send, use_textfsm=False)
            self.net_connect.send_command('terminal length 24')
            # disconnect from device
            self.net_connect.disconnect()
            return output_structured, output_unstructured

        # CATCH ERRORS AND RETURN THEM
        except AuthenticationException as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "AuthenticationException"
            self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except NetMikoTimeoutException as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "NetMikoTimeoutException"
            self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except SSHException as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "SSH_exception"
            if "Error reading SSH protocol banner" in str(e):
                self.error_dictionary[
                    "MESSAGE"] = "Error while connecting to device. Check port and connection type."
            else:
                self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except EOFError as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "EOFError"
            self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except Exception as unknown_error:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "unknown error"
            self.error_dictionary["MESSAGE"] = str(unknown_error)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary

    def configure_add_raw_commands_not_privileged(self, command_to_send):
        """
        THIS FUNCTION send  a command to a cisco network device not in privileged mode.
        :param command_to_send: <string>
        :return: <tupple> a tuple with 2 items. one item is a structured result if netmiko could parse the data
        The second item will be unparsed data, result of the command output in the network device CLI
        """

        print(
            "OUTPUT - Entering...  configure_add_raw_commands_not_privileged --> METHOD           "
        )
        try:
            # ESTABLISH A  CONNECTION TO DEVICE USING NETMIKO
            self.net_connect = ConnectHandler(
                device_type=self.connection_type,
                ip=self.data["ip"],
                username=self.device_credentials["device_username"],
                password=self.device_credentials["device_password"],
                secret=self.device_credentials["device_secret"],
                port=self.port)
            # ENTER PRIVILEGED MODE -- like we put enable in the cisco console.
            # self.net_connect.enable()

            # WE CAN RUN COMMANDS not in privileged mode on the cisco cli:
            # EXAMPLE : WE can run --> show version and it will output the result
            # But, if we run a show run :
            # switchTelnet > show run
            #                     ^
            # % Invalid input detected at '^' marker.
            # because we are not in privileged mode

            # ELIMINATES DE "MORE" WORD ON CISCO TERMINAL - USER DOESN'T HAVE TO PRESS A KEY TO CONTINUE
            self.net_connect.send_command('terminal length 0')

            # WE want to try to get structured data from the cli output but it is only possible
            # TEXTFSM - ntc templates were installed
            try:
                output_structured = self.net_connect.send_command(
                    command_to_send, use_textfsm=True)
            # DESEINTALAR O PATH OU ALTERAR PARA OUTRA LOCALIZACAO NAO EXISTENTE E VER O TIPO DE ERRO QUE DA_
            # Esta excepcao não é a melhor forma de apanhar errors
            except Exception:
                output_structured = None
            output_unstructured = self.net_connect.send_command(
                command_to_send, use_textfsm=False)
            self.net_connect.send_command('terminal length 24')
            # disconnect from device
            self.net_connect.disconnect()
            return output_structured, output_unstructured

        # CATCH ERRORS AND RETURN THEM
        except AuthenticationException as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "AuthenticationException"
            self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except NetMikoTimeoutException as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "NetMikoTimeoutException"
            self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except SSHException as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "SSH_exception"
            if "Error reading SSH protocol banner" in str(e):
                self.error_dictionary[
                    "MESSAGE"] = "Error while connecting to device. Check port and connection type."
            else:
                self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except EOFError as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "EOFError"
            self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except Exception as unknown_error:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "unknown error"
            self.error_dictionary["MESSAGE"] = str(unknown_error)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary

    def configure_add_commands_list(self, commands_list):
        """
        THIS FUNCTION RECEIVE A LIST WITH CISCO CLI COMMNANDS , AND SEND ThEM TO A NETWORK DEVICE

        :param commands_list: list of command to sento to device NOTE. EACH ITEM SHOUD BE A STRING
        :return: <string> with all the cli device captured by netmiko
        """
        print(
            "OUTPUT - HERE--------------------configure_add_commands_list method----------------"
        )
        try:
            # ESTABLISH A  CONNECTION TO DEVICE USING NETMIKO
            self.net_connect = ConnectHandler(
                device_type=self.connection_type,
                ip=self.data["ip"],
                username=self.device_credentials["device_username"],
                password=self.device_credentials["device_password"],
                secret=self.device_credentials["device_secret"],
                port=self.port)

            # enter user exec mode
            self.net_connect.enable()

            # ELIMINATES DE "MORE" WORD ON CISCO TERMINAL - USER DOESN'T HAVE TO PRESS A KEY TO CONTINUE
            self.net_connect.send_command('terminal length 0')

            #output_list= []
            #for command in commands_list:
            #    output = self.net_connect.send_command(command, use_textfsm=True)
            #    output_list.append(output)

            # WE COULD SEND ALL THE COMMANDS ONE ONE TIME.
            output = self.net_connect.send_config_set(commands_list)

            # SET CONSOLE TO DEFAULTS 24 LINES - IT WILL SHOW AGAIN "MORE" WHEN USER RUN COMMANDS LIKE "SHOW VLAN"
            self.net_connect.send_command('terminal length 24')
            # DISCONNECT FROM DEVICE
            self.net_connect.disconnect()
            return output

        # CATCH ERRORS AND RETURN THEM
        except AuthenticationException as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "AuthenticationException"
            self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except NetMikoTimeoutException as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "NetMikoTimeoutException"
            self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except SSHException as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "SSH_exception"
            if "Error reading SSH protocol banner" in str(e):
                self.error_dictionary[
                    "MESSAGE"] = "Error while connecting to device. Check port and connection type."
            else:
                self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except EOFError as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "EOFError"
            self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except Exception as unknown_error:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "unknown error"
            self.error_dictionary["MESSAGE"] = str(unknown_error)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary

    def save_running_config(self):
        """
        THIS FUNCTION save the running configurations in the start up configuration file
        :return: <string> with all the cli device captured by netmiko

        rationale:
        They essentially achieve the same things by saving the running configuration to the memory so that after a
        reload it retains the same configuration. Write memory is the "ancient" way, and
        copy running-config startup-config is the "newer way".
        Some newer platforms do not accept write memory, the Nexus platforms for instance.

        The workaround is to create an alias using cli alias name wr copy run start in global configuration mode.

        The "copy run start" command is just a variation of the "copy" command. The copy command can be used to copy any
        files in or out of the flash etc. - as opposed to just saving the configuration. Just remember though, if you
        are in the wrong configuration register "wr" will lose your configuration after a reload/when you change
        the configuration register whereas "copy run start" will just copy the contents of the running
        configuration to the start-up configuration.
        When doing CCNA exams, the command "write" is not allowed.
        It has to be the official "copy running-config startup-config".
        The reason why the "wr" or "write" command is very popular are:
            - A minimum of two characters to save a config;
            - It is easy to confuse "copy start run" with "copy run start".

        # SOURCE: https://ktbyers.github.io/netmiko/docs/netmiko/cisco_base_connection.html#netmiko.cisco_base_connection.CiscoBaseConnection.save_config

        """
        print(
            "OUTPUT - HERE--------------------save_running_config method----------------"
        )
        try:
            # ESTABLISH A  CONNECTION TO DEVICE USING NETMIKO
            self.net_connect = ConnectHandler(
                device_type=self.connection_type,
                ip=self.data["ip"],
                username=self.device_credentials["device_username"],
                password=self.device_credentials["device_password"],
                secret=self.device_credentials["device_secret"],
                port=self.port)

            #SOURCE: https://github.com/ktbyers/netmiko/blob/develop/examples/enable/enable.py
            # Enter enable mode
            self.net_connect.enable()
            #print(self.net_connect.find_prompt())

            # SEND SAVE COMMAND TO DEVICE
            output = self.net_connect.save_config(
                cmd="copy running-config startup-config",
                confirm=True,
                confirm_response="")

            # DISCONNECT FROM DEVICE
            self.net_connect.disconnect()
            # RETURN THE OUTPUT OF THE CONSOLE OUT
            return output

        # CATCH ERRORS AND RETURN THEM
        except AuthenticationException as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "AuthenticationException"
            self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except NetMikoTimeoutException as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "NetMikoTimeoutException"
            self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except SSHException as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "SSH_exception"
            if "Error reading SSH protocol banner" in str(e):
                self.error_dictionary[
                    "MESSAGE"] = "Error while connecting to device. Check port and connection type."
            else:
                self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except EOFError as e:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "EOFError"
            self.error_dictionary["MESSAGE"] = str(e)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
        except Exception as unknown_error:
            self.error_dictionary["STATUS"] = "Failure"
            self.error_dictionary["TYPE"] = "unknown error"
            self.error_dictionary["MESSAGE"] = str(unknown_error)
            # SEND ERROR MESSAGE TO CLIENT
            return self.error_dictionary
from netmiko import ConnectHandler
from netmiko.ssh_exception import NetMikoAuthenticationException

#router = {
    "host":"192.168.0.7",
    "port":22,
    "username":"******",
    "password":"******",
    "device_type":"cisco_ios"
}

configurar = ["no interface loopback 11"]

try:
    A = ConnectHandler(**router)
    A.enable()
    A.send_config_set(configurar)
    respuesta = A.send_command("show ip int brief")
    save = A.save_config()
    print("saving running config......")
    A.disconnect()
    print("user has exited tty session...")
except Exception as ex:
    print(ex)
else:
    print(respuesta)
Exemple #19
0
from netmiko import ConnectHandler
from getpass import getpass

'''
5. On both the NXOS1 and NXOS2 switches configure five VLANs including VLAN
names (just pick 5 VLAN numbers between 100 - 999). Use Netmiko's send_config_from_file()
method to accomplish this. Also use Netmiko's save_config() method to save the
changes to the startup-config.
'''

password = getpass()

routers = ["nxos1.lasthop.io", "nxos2.lasthop.io"]
for router in routers:
    device = {
        "device_type": "cisco_nxos",
        "host": router,
        "username": "******",
        "password": password,
        "fast_cli": True,
        }
    net_connect = ConnectHandler(**device)
    output = net_connect.send_config_from_file("config_set2.txt")
    net_connect.save_config()
    print(output)
    print("*" * 40)

net_connect.disconnect()
Exemple #20
0
from netmiko import ConnectHandler
import getpass
import os

username = input('Username: '******'Switch_ips.txt') as file:
    devices_list = file.read().splitlines()

#connecting to Switchs
for devices in devices_list:
    print('Connecting to device: ' + devices)
    ip_address_of_device = devices
    iosv_l2 = {
        'device_type': 'cisco_ios',
        'ip': ip_address_of_device,
        'username': username,
        'password': password,
    }
    # Add account with priv 15
    net_connect = ConnectHandler(**iosv_l2)
    output = net_connect.send_config_set(
        'username USERNAME privilege 15 secret 0 PASSWORD')
    output += net_connect.save_config()
    print(output)
    print()
Exemple #21
0
from netmiko import ConnectHandler
from getpass import getpass

device1 = {
    "host": 'cisco3.lasthop.io', 
    "username": '******', 
    "password": getpass(), 
    "device_type": 'cisco_ios',
 }

net_connect = ConnectHandler(**device1)
print(net_connect.find_prompt())

output = net_connect.send_config_from_file(config_file="my_changes.txt")
print(output)

save_out = net_connect.save_config()
print(save_out)

Exemple #22
0
    "fast_cli": True
}

nxos2 = {
    "host": "nxos2",
    'username': '******',
    'password': getpass(),
    'device_type': 'cisco_nxos',
    'session_log': 'nxos2_5.txt',
    'fast_cli': True
}

device = [nxos1, nxos2]

t0 = datetime.now()

for d in device:
    t1 = datetime.now()
    ssh_con = ConnectHandler(**d)
    ssh_con.send_config_from_file('ex5_commands.txt')
    ssh_con.save_config()
    ssh_con.disconnect()
    t2 = datetime.now()
    t3 = t2 - t1
    print("\nINICIO: ", t1)
    print('\nFIN: ', t2)
    print('\nDuracion ejecucion comando: ', t3)

tf = datetime.now()
print('\nDuracion configuracion equipos: ', tf - t0)