Issue
So, I'm trying to push some configuration to my switches automatically but those commands typically return a (y/n) prompt in the switch. As a result, the send_command function will not work as it looks for the prompt, so I'm using the write_channel() function which works perfectly. However, for some reason, neither the read_channel nor the clear_buffer() functions print more than 1 or 2 lines of output after I send a command.
Things I've tried:
Putting the read_channel/buffer in a slow loop.
read_until_prompt/pattern
send_command with cmd_verify=False and auto_find_prompt=False
printing read_channel
and more. . .
send_command can display output no problem and its source code uses read_channel() to push output, so I'm not sure what else to try.
Goal: I need to get the output from a command in a cisco switch (reload in 001:00), so that I can then tell the program how to react to the prompt if there is one.
Here is some basic code I wrote to troubleshoot the problem in my main project:
from netmiko import ConnectHandler
import time
Network_Device = {
"ip": "10.251.11.38",
"username": "user",
"password": "pass",
"secret": "secretpass",
"device_type": "cisco_ios",
"fast_cli": False
}
#Connect = ConnectHandler(**Network_Device)
with ConnectHandler(**Network_Device) as ssh:
ssh.enable()
while True:
x = input(ssh.find_prompt())
if x == '':
pass
elif x == 'exit' or x == 'Exit':
ssh.disconnect()
else:
ssh.write_channel(x) # Writes command to cli
#Problem lies on the two functions below: Neither will print out a show command fully.
ssh.clear_buffer(backoff=True)
ssh.read_channel()
Solution
Yes, I want to reload dozen's of switches at approximately the same time for a dhcp update.
It's obvious now you want to reload a bunch of switches. The reload
prompts you with Proceed with reload? [confirm]
. So you can you use expect_sting
argument to either confirm or deny the reload. To do so, it's better to save the configuration first before the reload to avoid any config loss.
A quick brief of how
send_command
works.send_command
is pattern-based where it checks for the device prompt to know that the command output is done. On the other handsend_command_timing
is delay-based meaning it waits for some time and doesn't check for anything to know if the command is done running or not.
from netmiko import ConnectHandler
device = {
"device_type": "",
"ip": "",
"username": "",
"password": "",
"secret": "",
"conn_timeout": 12,
"fast_cli": False,
}
conn = ConnectHandler(**device)
# Check if not logged into enable mode directly
# and enter enable mode if logged into user mode
if not conn.check_enable_mode():
conn.enable()
conn.save_config() # save configuration first
conn.send_command(command_string="reload", expect_string=r"confirm")
Notice here the expect_string
which informs the send_command
I am done.
Now you have one of two options:
- send
y
to confirm the reload (Discouraged) - call
conn.disconnect()
to both confirm the reload and exit (Preferred)
Option 1 is discouraged because you will not be able to disconnect after confirming the reload and eventually an
OSError
orEOFError
exception is raised that you will have to handle.
conn.disconnect()
The above line sends a \n
first, then disconnects from the device. This lets you handle other devices reload immediately and you don't have to handle any raised OSError
or EOFError
excpetions.
Full example
from netmiko import ConnectHandler
device = {
"device_type": "",
"ip": "",
"username": "",
"password": "",
"secret": "",
"conn_timeout": 12,
"fast_cli": False,
}
conn = ConnectHandler(**device)
if not conn.check_enable_mode():
conn.enable()
conn.save_config()
# Notice here the `expect_string` which informs
# the `send_command` I am done.
# I am telling `send_command` function don't look at
# the device prompt but look for `"confirm"` to proceed
# with the next command.
conn.send_command(command_string="reload", expect_string=r"confirm")
conn.disconnect()
print(f'Reloading {device["ip"]}... Please wait for some time for {device["ip"]} to boot up again')
I didn't use the context manager method on purpose to make use of
conn.disconnect()
function.
UPDATE
As recommended by Kirk Byers (the author of netmiko) in the comments, it's recommended to just add r"confirm"
in the expect_string
and omit the square brackets.
Answered By - Tes3awy