carlmontanari / scrapli

Fast, flexible, sync/async, Python 3.7+ screen scraping client specifically for network devices
https://carlmontanari.github.io/scrapli/
MIT License
588 stars 63 forks source link

"Timed out sending input to device" if I try remove all usernames "no username test" #73

Closed L0llipop closed 3 years ago

L0llipop commented 3 years ago

Describe the bug After send a command to delete username, on this ios need press enter button to confirm.

To Reproduce Steps to reproduce the behavior:

  1. Your script
    result = task.run(name="show all usernames", task=send_command, command="show run | i username")
        if result[0].result:
            users = re.findall(r"username\s+(.+)\s+privi", result[0].result)
            commands = ["no username {}".format(x) for x in users]
            result = task.run(name="delete all usernames", task=send_configs(task=task, configs=commands, strip_prompt=False, timeout_ops=5))
  2. What you're connecting to (vendor, platform, version) cisco 2951, ios 15.0

Stack Trace Copy of your stack trace here, please format it properly using triple back ticks (top left key on US keyboards!)

Screenshots Screenshot from 2021-01-21 15-59-26

OS (please complete the following information):

Additional context I know that i can use send_interactive, but there are devices in my file that do not require confirm.

carlmontanari commented 3 years ago

Hey @L0llipop thanks for opening this!

I don't know if I think this is a scrapli issue really, or that there is anything I would change here.

I imagine you could add a bit of logic that fetches the current version (I'm assuming that some versions require the extra return whereas others do not?) and then decide if you need to use send_interactive or just "normal" send_command right?

Alternatively, you could also use the send_input_and_read method here -- basically send some stuff and read until you see a pattern (or the normal prompt) or things timeout, then based on whatever you read you can proceed with a return or just moving on to normal operations.

Lastly, you could just send the command and an additional return "manually" by reaching down to the channel/transport, something like: `conn.transport.write("blah\n".encode()) followed by another new line just to handle that second prompt if needed -- worst case the second return will just do nothing for the devices that dont need it.

Note that if you are going to do the latter -- things will change slightly when the current overhaul branch gets merged -- you will be able to use the channel instead of the transport: conn.channel.write("stuff") and conn.channel.send_return() -- little nicer, no need for bytes, no need to manually write the new line character, etc.. This is in the overhaul branch right now, you can read more about some of the backstory for this big overhaul here

In any case, I'm not sure there is a scrapli issue here -- I think the tools are available to handle this situation!

Carl