ktbyers / netmiko

Multi-vendor library to simplify Paramiko SSH connections to network devices
MIT License
3.49k stars 1.26k forks source link

Added MOTD Wake Up #3425

Open FriendlyGecko opened 2 months ago

FriendlyGecko commented 2 months ago

This may not be the best way to solve the issue, but it is a way.

Issue we are trying to solve

When attempting to log into a device that uses a MOTD, the login fails. This is because the MOTD requires the user to first send a return character to wake it up. If I use putty to first console in and press enter, I can swap back to my netmiko script and log into the device without issue.

To solve the issue, I added a check (checks if the login process is already started) that will send a return character to the device to first wake it up before going to into the login process. If the user is already logged in, then all this will do is return a blank line (unless there is text in the prompt somehow).

This may be better, but taking critiques on it:

                try:
                    output = self.read_channel()
                    return_msg += output

                    # Search for username pattern / send username
                    if re.search(username_pattern, output, flags=re.I):
                        # Sometimes username/password must be terminated with "\r" and not "\r\n"
                        self.write_channel(self.username + "\r")
                        time.sleep(1 * delay_factor)
                        output = self.read_channel()
                        return_msg += output

                    # Search for password pattern / send password
                    if re.search(pwd_pattern, output, flags=re.I):
                        # Sometimes username/password must be terminated with "\r" and not "\r\n"
                        assert isinstance(self.password, str)
                        self.write_channel(self.password + "\r")
                        time.sleep(0.5 * delay_factor)
                        output = self.read_channel()
                        return_msg += output
                        if re.search(
                            pri_prompt_terminator, output, flags=re.M
                        ) or re.search(alt_prompt_terminator, output, flags=re.M):
                            return return_msg

                    # Support direct telnet through terminal server
                    if re.search(
                        r"initial configuration dialog\? \[yes/no\]: ", output
                    ):
                        self.write_channel("no" + self.TELNET_RETURN)
                        time.sleep(0.5 * delay_factor)
                        count = 0
                        while count < 15:
                            output = self.read_channel()
                            return_msg += output
                            if re.search(r"ress RETURN to get started", output):
                                output = ""
                                break
                            time.sleep(2 * delay_factor)
                            count += 1

                    # Check for device with no password configured
                    if re.search(r"assword required, but none set", output):
                        assert self.remote_conn is not None
                        self.remote_conn.close()
                        msg = (
                            "Login failed - Password required, but none set: {}".format(
                                self.host
                            )
                        )
                        raise NetmikoAuthenticationException(msg)

                    # Check if proper data received
                    if re.search(
                        pri_prompt_terminator, output, flags=re.M
                    ) or re.search(alt_prompt_terminator, output, flags=re.M):
                        return return_msg

                    # MOTD Wake Up
                    self.write_channel("\r")
                    time.sleep(1 * delay_factor)
                    output = self.read_channel()
                    return_msg += output

                    i += 1
FriendlyGecko commented 2 months ago

This resolves #3424

FriendlyGecko commented 2 months ago

I moved this to a draft, because it warrants a conversation on if this is the best way to resolve the issue or if it should be moved/tweaked