question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Linux SSH / OpenGear read_until_prompt fails to detect enable mode when prompt is only single character

See original GitHub issue

Steps to reproduce:

  1. Initialise a connection with an OpenGear device, using the Linux SSH driver:
>>> from netmiko import ConnectHandler
>>> device = ConnectHandler(device_type="linux", host="some-opengear", username="root", password="pass", secret="pass", fast_cli=False)
  1. Attempt to enter in enable mode:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/site-packages/netmiko/linux/linux_ssh.py", line 150, in enable
    raise ValueError(msg)
ValueError: 

Netmiko failed to elevate privileges.

Please ensure you pass the sudo password into ConnectHandler
using the 'secret' argument and that the user has sudo
permissions.

The previous command does send the sudo -s command as it should, the device returns a line containing the # as expected, but it fails on check_enable_mode.

After digging deeper, it seems like the issue is caused by the read_until_prompt method that is misbehaving. To reproduce, use the device defined previously:

>>> device.write_channel(device.RETURN)
>>> output = device.read_channel()
>>> results = re.split("(.*)", output, maxsplit=1, flags=re.I)
>>> output, match_str, buffer = results
>>> output
''
>>> match_str
''
>>> output + match_str
''
>>> buffer
'\n# \n# \n# '
>>> 

Can notice that it sends the return, it reads the prompt correctly, but the regular expression split renders output + match_str to be an empty string. As a result, check_enable_mode will never find the # prompt in the empty string, and therefore check_enable_mode will always return False in https://github.com/ktbyers/netmiko/blob/v4.1.1/netmiko/base_connection.py#L1861.

The above is a simplified version of https://github.com/ktbyers/netmiko/blob/v4.1.1/netmiko/base_connection.py#L614-L640 to reproduce it step-by-step. The pattern .* comes from https://github.com/ktbyers/netmiko/blob/v4.1.1/netmiko/base_connection.py#L731-L733 as self.base_prompt is empty string. So everything seems to be caused by the incorrectly detected prompt.

TL;DR: self.base_prompt should be # but it’s ''.

If I change the line https://github.com/ktbyers/netmiko/blob/v4.1.1/netmiko/base_connection.py#L1289 to

self.base_prompt = prompt

Everything seems to work fine, but might break other things? If so, perhaps something like the following would be more appropriate?

if len(prompt.strip()) == 1:
    self.base_prompt = prompt
else:
    self.base_prompt = prompt[:-1]

In fact, I can’t think of a case where we need to strip the last character of a prompt, but perhaps there’s more background to this than I’m aware of.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
ktbyerscommented, Jul 21, 2022
 Regardless, I'm curious what's the reasoning for having self.base_prompt = prompt[:-1] 
(instead of just self.base_prompt = prompt) if you recall?

For self.base_prompt, I want something that is enduring (not likely to change).

For example, in the below:

cisco3>enable
Password: 
cisco3#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
cisco3(config)#

I want to be able to go through the state changes and still have the netmiko read succeed. So I want the part of the prompt that is common to all of these cases i.e. cisco3. So that is what is meant by the base in self.base_prompt.

Obviously, that doesn’t always work, but that is why the last character is dropped (to try to make Netmiko output reading more reliable).

Linux behavior can already be problematic here (relative to platforms that are very Cisco IOS like).

For example:

(yang_test) [ktbyers@pydev2 ~]$ sudo -s
(yang_test) [root@pydev2 ktbyers]# 

i.e. the prompt here is changing on more things than just the last character.

0reactions
ktbyerscommented, Aug 8, 2022
Read more comments on GitHub >

github_iconTop Results From Across the Web

Unauthenticated SSH to Console Ports - Opengear
Configure > Services > SSH. The Unauthenticated SSH Access feature provides the option to access console ports (using TCP high ports) by establishing ......
Read more >
Connecting to consoles and CLI using an SSH client
SSH provides a convenient and secure means to access the command line of the Opengear device itself, and its connected serial console ports....
Read more >
Open Gear : Basic Commands - The Packet Wizard
is there a command to exit out of pmshell (other than Ctrl+C or Ctrl+Z)?. Connect to port > exit. ERROR: Not a valid...
Read more >
Review of the Opengear CM4116 - PacketLife.net
Anyone who has used HyperTerminal or a similar terminal emulator before will find console port configuration very familiar.
Read more >
Opengear Advanced Console Management Demo - YouTube
Jared Mallett demonstrates Opengear's console management capabilities.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found