10-07-2025 01:06 PM
Using EOS unicon plugin to connect to Arista switch.
During device.connect(), password is sent and unicon logs: %UNICON-INFO: +++ connection to spawn: ssh ....
Then it times out with TimeoutError error.
One specific fact for this Arista switch is that when you login through SSH, once password is entered and user gets authenticated successfully, it will show a message: " Last login: #date# from IP address" before showing the hostname# prompt.
So I am assuming the login handler expects to see hostname in case of successful authentication or some error but not the "Last login" message through its predefined pattern matching logic.
How can that "last login" pattern be added for proper handling in this case?
10-07-2025 01:46 PM - edited 10-07-2025 01:49 PM
You can do this by adding a custom statement to the connection dialog. Be something like (excuse the formatting on my phone!)
last_login_stmt = Statement( pattern=r'.*Last login:.*', action=None, loop_continue=True, continue_timer=True )
then .append(last_login_stmt) that to your device connection.
10-07-2025 06:37 PM
Thanks for the reply. Trying to figure out how to append the Statement to my device connection.
Usually I use pyATS testbed to connect:
from pyats.topology import loader
testbed = loader.load(test_bed_file.yaml)
device = testbed.devices[device_name]
device.connect()
I get that I can define the new statement like this:
from unicon.eal.dialogs import Statement
last_login_stmt = Statement( pattern=r'.*Last login:.*', action=None, loop_continue=True, continue_timer=True )
But it seems I need to use native Python Unicon APIs to connect instead:
from unicon import Connection
dev = Connection(hostname=xxx, ....)
dev.connect()
How do I append the statement above? Am I on the right track?
10-08-2025 01:23 AM
You would not need to switch away from PyATS testbed and you can still use your testbed YAML and append the statement before connecting.
10-08-2025 07:51 AM
Ok no idea how to do that. pyATS / Unicon are not open source so not able to look further.
10-08-2025 08:00 AM
Please test this, its been a minute since i did this. Try
from pyats.topology import loader
from unicon.eal.dialogs import Statement
testbed = loader.load('test_bed_file.yaml')
device = testbed.devices['device_name']
last_login_stmt = Statement(
pattern=r'.*Last login:.*',
action=None,
loop_continue=True,
continue_timer=True
)
device.connectionmgr.connections['default'].connection_provider.get_connection_dialog().append(last_login_stmt)
device.connect()
10-08-2025 09:14 AM
Thanks @bigevilbeard
device.connectionmgr.connections['default'].connection_provider.get_connection_dialog().append(last_login_stmt)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[9], line 1
----> 1 device.connectionmgr.connections['default'].connection_provider.get_connection_dialog().append(last_login_stmt)
AttributeError: 'NoneType' object has no attribute 'connection_provider'
Where is this 'default' coming from? I guess that should be defined inside the testbed and I do not have it.
10-08-2025 09:48 AM
Thanks, told you was rusty! Soo...... i think if you update device.connect with these three lines.
device.instantiate()
device.connectionmgr.connections['default'].connection_provider.get_connection_dialog().append(last_login_stmt)
device.connect()
10-08-2025 11:30 AM
Ok, so the first one works:
device1.instantiate()
2025-10-08 17:00:03,196: %UNICON-INFO: +++ device_name logfile device_name-cli-123423.log +++
2025-10-08 17:00:03,200: %UNICON-INFO: +++ Unicon plugin eos (unicon.plugins.eos) +++
Out[12]: <unicon.plugins.eos.EOSSingleRPConnection at 0x7f7e51953c20>
But the second errors out as before:
In [25]: device1.connectionmgr.connections['default'].connection_provider.get_connection_dialog().append(last_login_stmt)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[25], line 1
----> 1 device1.connectionmgr.connections['default'].connection_provider.get_connection_dialog().append(last_login_stmt)
AttributeError: 'NoneType' object has no attribute 'get_connection_dialog'
Seems get_connection_dialog() is not a method of device1.connectionmgr.connections['default'].connection_provider:
In [27]: dir(device1.connectionmgr.connections['default'].connection_provider)
Out[27]:
['__bool__',
'__class__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getstate__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__']
10-08-2025 12:33 PM
Hmm so the connection type is none. Try
device.instantiate()
device.connectionmgr.connections['default'].dialogs.append(last_login_stmt)
device.connect()
10-08-2025 12:58 PM
In [28]: device1.connectionmgr.connections['default'].dialogs.append(last_login_stmt)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[28], line 1
----> 1 device1.connectionmgr.connections['default'].dialogs.append(last_login_stmt)
AttributeError: 'EOSSingleRPConnection' object has no attribute 'dialogs'
In [29]: dir(device1.connectionmgr.connections['default'])
Out[29]:
['__class__',
'__delattr__',
'__device__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getstate__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lock__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'_connection_type',
'_get_learned_hostname',
'_hostname',
'_is_ha',
'_learned_hostname',
'_log_buffer',
'_logfile',
'_service_init',
'acquire',
'add_service',
'alias',
'attach',
'chassis_type',
'config',
'configure',
'configure_logging',
'connect',
'connect_reply',
'connected',
'connection_provider',
'connection_provider_class',
'connection_timeout',
'connection_type',
'context',
'copy',
'debug',
'device',
'disable',
'disconnect',
'enable',
'enable_password',
'execute',
'execute_proxy_commands',
'expect',
'expect_log',
'get_services',
'goto_enable',
'guestshell',
'hostname',
'init_config_commands',
'init_context',
'init_exec_commands',
'init_service',
'init_state_machine',
'is_connected',
'is_ha',
'learn_hostname',
'learn_os',
'learn_os_version',
'learn_tokens',
'learned_hostname',
'line_password',
'locked',
'log',
'log_buffer',
'log_file',
'log_propagate',
'log_stdout',
'log_user',
'logfile',
'logout',
'mit',
'mode',
'model',
'no_pyats_tasklog',
'operating_mode',
'os',
'os_flavor',
'overwrite_testbed_tokens',
'parent',
'parse_spawn_command',
'patch_service_attributes',
'ping',
'platform',
'playback_idx',
'playback_record',
'playback_replay',
'playback_speed',
'previous_hostname',
'prompt_recovery',
'proxy_connect',
'proxy_connections',
'receive',
'receive_buffer',
'reconnect',
'release',
'reload',
'role',
'rommon',
'send',
'sendline',
'service_attributes_patch',
'service_init',
'session',
'settings',
'setup_connection',
'shellexec',
'spawn',
'standby_goto_enable',
'start',
'state_machine',
'state_machine_class',
'subcommand_list',
'switchto',
'system_text',
'tacacs_password',
'traceroute',
'transmit',
'trim_line',
'username',
'via']
In [30]:
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide