pythontelnetnetmiko

Netmiko - How to hold or disconnect a telnet connection?


Question

How can I hold or disconnect a telnet connection without error?

Situation

I want to use Nornir to reload the router, but when it is triggered, the terminal will display the error message EOFError: telnet connection closed.

Action

I tried to use the r1.close_connections() after the reloading telnet conneciton, but it still triggered the EOFError before.

Environment

Python 3.9.6
nornir==3.1.1
nornir-jinja2==0.2.0
nornir-napalm==0.1.2
nornir-netmiko==0.1.1
nornir-rich==0.1.2
nornir-utils==0.1.2
netmiko==3.4.0
nornir-netmiko==0.1.1

Expected Result

  1. Reload the router.
    • When the reloading command is triggered, the router must restart the system, so the telnet session will be disconnected.
  2. Wait for the reloading time of router.
  3. Show the router version.

Execution Code

from time import sleep
from nornir import InitNornir
from nornir_netmiko import netmiko_send_command as send_cmd, netmiko_send_config


def reboot_device(task):
    task.run(
        task=netmiko_send_command,
        use_timing=True,
        command_string="reload",
    )
    task.run(
        task=netmiko_send_command,
        use_timing=True,
        command_string='y',
    )


def main():
    nr = InitNornir(config_file="config.yaml")
    r1 = nr.filter(device_name="R1")
    reload_time = 60

    r1.run(task=reboot_device)
    sleep(reload_time)
    r1.run(
        task=netmiko_send_command,
        use_timing=True,
        command_string="show version"
    )


if __name__ == "__main__":
    main()

Error Messages

2022-05-21 18:35:34,126 - nornir.core.task -    ERROR -      start() - Host 'R1': task 'netmiko_send_command' failed with traceback:
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/nornir/core/task.py", line 99, in start
    r = self.task(self, **self.params)
  File "/usr/local/lib/python3.9/site-packages/nornir_netmiko/tasks/netmiko_send_command.py", line 30, in netmiko_send_command
    result = net_connect.send_command_timing(command_string, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/netmiko/utilities.py", line 500, in wrapper_decorator
    return func(self, *args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/netmiko/base_connection.py", line 1303, in send_command_timing
    new_data = self.read_until_pattern(pattern=re.escape(cmd))
  File "/usr/local/lib/python3.9/site-packages/netmiko/base_connection.py", line 655, in read_until_pattern
    return self._read_channel_expect(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/netmiko/base_connection.py", line 589, in _read_channel_expect
    output += self.read_channel()
  File "/usr/local/lib/python3.9/site-packages/netmiko/base_connection.py", line 526, in read_channel
    output = self._read_channel()
  File "/usr/local/lib/python3.9/site-packages/netmiko/base_connection.py", line 508, in _read_channel
    output = self.remote_conn.read_very_eager().decode("utf-8", "ignore")
  File "/usr/local/lib/python3.9/telnetlib.py", line 368, in read_very_eager
    return self.read_very_lazy()
  File "/usr/local/lib/python3.9/telnetlib.py", line 405, in read_very_lazy
    raise EOFError('telnet connection closed')
EOFError: telnet connection closed

Solution

  • I figure out the problem, before I executed the .send_command('y') the telnet connection is disconnect, in my route, after enter the reload command if received the \n then will immediately reload the system, so it triggered the error after the send the .send_command('y')

    from nornir import InitNornir
    from nornir.core.task import Task, Result 
    from nornir_netmiko.tasks.netmiko_send_command import netmiko_send_command
    
    def main():
        
        def task_reboot(task):
    
          task.run(
              task=netmiko_send_command,
              use_timing=True,
              command_string="reload",
           )
           task.host.close_connections()
    
        nr = InitNornir(config_file="config.yaml")        
        r1 = nr.filter(device_name="R1")
    
        try:
            r = r1.run(
                task=task_reboot,
            )
        except EOFError:
            r1.close_connections()
            
    if __name__ == "__main__":
        main()