Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions docs/changelog/2025/december.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
December 2025
==========

December 30 - Unicon v25.11
------------------------



.. csv-table:: Module Versions
:header: "Modules", "Versions"

``unicon.plugins``, v25.11
``unicon``, v25.11




Changelogs
^^^^^^^^^^
--------------------------------------------------------------------------------
New
--------------------------------------------------------------------------------

* unicon
* adapters/topology.py
* Added support for reverse SSH connections.


--------------------------------------------------------------------------------
Fix
--------------------------------------------------------------------------------

* patterns
* Updated the regex for username prompt for the linux VMs


1 change: 1 addition & 0 deletions docs/changelog/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Changelog
.. toctree::
:maxdepth: 2

2025/december
2025/october
2025/september
2025/august
Expand Down
44 changes: 44 additions & 0 deletions docs/changelog_plugins/2025/december.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
December 2025
==========

December 30 - Unicon.Plugins v25.11
------------------------



.. csv-table:: Module Versions
:header: "Modules", "Versions"

``unicon.plugins``, v25.11
``unicon``, v25.11




Changelogs
^^^^^^^^^^
--------------------------------------------------------------------------------
Fix
--------------------------------------------------------------------------------

* iosxe
* Added cursor position handling in bash ContextMgr to prevent delays during shell initialization.

* nxos
* Updated the LC bash prompt pattern to include an anchor and improve prompt detection performance.

* generic
* Updated syslog pattern to handle insecure dynamic warning message for SSH hostkey with insufficient key length.

* linux
* Updated prompt patterns to better handle ANSI escape sequences in prompts


--------------------------------------------------------------------------------
New
--------------------------------------------------------------------------------

* generic/settings.py
* Updated the temporary enable secret to include a special character.


Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
--------------------------------------------------------------------------------
New
--------------------------------------------------------------------------------
* generic/statements.py
* Updated the password_ok_stmt to use escape_char_callback instead of sendline.
1 change: 1 addition & 0 deletions docs/changelog_plugins/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Plugins Changelog
.. toctree::
:maxdepth: 2

2025/december
2025/october
2025/september
2025/august
Expand Down
2 changes: 1 addition & 1 deletion src/unicon/plugins/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "25.10"
__version__ = "25.11"

supported_chassis = [
'single_rp',
Expand Down
2 changes: 1 addition & 1 deletion src/unicon/plugins/generic/patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def __init__(self):
r"^.*?(%\w+(-\S+)?-\d+-\w+|"
r"yang-infra:|PKI_SSL_IPC:|Guestshell destroyed successfully|"
r"%Error opening tftp:\/\/255\.255\.255\.255|Autoinstall trying|"
r"audit: kauditd hold queue overflow|SECURITY WARNING|%RSA key|"
r"audit: kauditd hold queue overflow|SECURITY WARNING|%RSA key|INSECURE DYNAMIC WARNING|"
r"(LC|RP)/\d+/\d+/CPU\d+:\w+\s+\d+\s+\d{2}:\d{2}:\d{2}|"
r"\[OK\]"
r").*\s*$"
Expand Down
2 changes: 1 addition & 1 deletion src/unicon/plugins/generic/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def __init__(self):
# Temporary enable secret used during setup
# this is used if no password is available
# and would not be saved by default
self.TEMP_ENABLE_SECRET = 'Secret12345'
self.TEMP_ENABLE_SECRET = 'Secret12345!'
# Minimum length for enable secret password:
# if the password specified is shorter,
# use the TEMP_ENABLE_SECRET instead.
Expand Down
5 changes: 3 additions & 2 deletions src/unicon/plugins/generic/statements.py
Original file line number Diff line number Diff line change
Expand Up @@ -656,10 +656,11 @@ def __init__(self):
loop_continue=True,
continue_timer=False)
self.password_ok_stmt = Statement(pattern=pat.password_ok,
action=sendline,
action=escape_char_callback,
args=None,
loop_continue=True,
continue_timer=False)
continue_timer=True,
trim_buffer=False)
self.more_prompt_stmt = Statement(pattern=pat.more_prompt,
action=more_prompt_handler,
args=None,
Expand Down
6 changes: 4 additions & 2 deletions src/unicon/plugins/iosxe/service_implementation.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

from .service_statements import execute_statement_list, configure_statement_list, confirm

from .statements import grub_prompt_stmt, boot_from_rommon_stmt
from .statements import grub_prompt_stmt, boot_from_rommon_stmt, terminal_position_stmt

from unicon.plugins.generic.utils import GenericUtils
from unicon.plugins.generic.service_implementation import BashService as GenericBashService
Expand Down Expand Up @@ -258,6 +258,7 @@ def __init__(self, connection, enable_bash=False, timeout=None, **kwargs):
timeout=timeout,
**kwargs)

self.terminal_position_dialog = Dialog([terminal_position_stmt])
def __enter__(self):

if self.conn.context.get('_disable_selinux'):
Expand All @@ -272,7 +273,8 @@ def __enter__(self):
'shell',
self.conn.spawn,
timeout=self.timeout,
context=self.conn.context)
context=self.conn.context,
dialog=self.terminal_position_dialog,)

for cmd in self.conn.settings.BASH_INIT_COMMANDS:
self.conn.execute(
Expand Down
14 changes: 12 additions & 2 deletions src/unicon/plugins/iosxe/statements.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
from unicon.plugins.generic.service_statements import\
admin_password as admin_password_stmt
from unicon.plugins.generic.statements import (
connection_statement_list, boot_timeout_stmt)
connection_statement_list,
boot_timeout_stmt,
terminal_position_handler,
)

from .patterns import IosXEReloadPatterns, IosXEPatterns

Expand Down Expand Up @@ -183,6 +186,13 @@ def boot_image(spawn, context, session):
loop_continue=True,
continue_timer=False)

terminal_position_stmt = Statement(
pattern=patterns.get_cursor_position,
action=terminal_position_handler,
args=None,
loop_continue=True,
continue_timer=False,
)

# Statement covering when a device asks us to reset it.
please_reset_stmt = \
Expand Down Expand Up @@ -245,4 +255,4 @@ def wrapper(spawn, session, context, **kwargs):
boot_from_rommon_statement_list += connection_statement_list.copy()
for stmt in boot_from_rommon_statement_list:
if stmt.pattern in [reload_patterns.press_return] or stmt.loop_continue is False:
stmt.action = boot_finished_deco(stmt.action)
stmt.action = boot_finished_deco(stmt.action)
6 changes: 3 additions & 3 deletions src/unicon/plugins/linux/patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ def __init__(self):
# The reason for using the learn_hostname pattern instead of the shell_prompt pattern
# to learn the hostname, is that the regex in the router implementation matches \S
# which is not exact enough for the known linux prompts.
self.learn_hostname = r'^.*?({a})?(?P<hostname>[-\w]+)\s?([-\w\]/~:\.\d ]+)?([>\$~%#\]])\s*(\x1b\S+)?$'.format(a=ANSI_REGEX)
self.learn_hostname = r'^.*?({a})?(?P<hostname>[-\w]+)\s?([-\w\]/~:\.\d ]+)?([>\$~%#\]])\s*(\x1b\S+\s?)*$'.format(a=ANSI_REGEX)

# shell_prompt pattern will be used by the 'shell' state after lean_hostname matches
# a known hostname pattern this pattern is set for the shell state at transition
# from learn_hostname to shell, see statemachine for more details.
self.shell_prompt = r'^(.*?(?P<prompt>((\([-\w]+\) |\x1b(?!\[\?2004).*?)?\S+)?%N\s?([-\w\]/~\s:\.\d]+)?[>\$~%#\]]\s?(\x1b\S+)?))$'
self.shell_prompt = r'^(.*?(?P<prompt>((\([-\w]+\) |\x1b(?!\[\?2004).*?)?\S+)?%N\s?([-\w\]/~\s:\.\d]+)?[>\$~%#\]]\s?(\x1b\S+\s?)*))$'

# default linux prompt with loose matching of the prompt
# this can result in false prompt matching when output has
# one of the prompt characters at the end of the line,
# e.g. XML output or a banner
self.prompt = r'^(.*?([>\$~%\]]|\] # |[^#\s]#|~ #|~/|^admin:|^#|~\s?#\s?)\s?(\x1b\S+)?)$'
self.prompt = r'^(.*?([>\$~%\]]|\] # |[^#\s]#|~ #|~/|^admin:|^#|~\s?#\s?)\s?(\x1b\S+\s?)*)$'

self.trex_console = r'^(.*?)(?P<prompt>trex>\s*)$'
2 changes: 1 addition & 1 deletion src/unicon/plugins/nxos/patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ def __init__(self):
self.commit_changes_prompt = r'Uncommitted changes found, commit them before exiting \(yes/no/cancel\)\? \[cancel\]\s*$'
self.nxos_module_reload = r'This command will reload module \S+ Proceed\[y\/n]\?'
self.l2rib_pycl_prompt = r'^(.*?)L2RIBCLIENT-.+>\s*?'
self.lc_bash_prompt = r'(.*?)root@lc\d+:\S+#\s*?$'
self.lc_bash_prompt = r'^(.*?)root@lc\d+:\S+#\s*?$'
92 changes: 92 additions & 0 deletions src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_cat9k.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,7 @@ c9k_exec:
"term length 0": ""
"term width 0": ""
"show version | include operating mode" : ""
"show install summary": ""
"show version": |2
Cisco IOS XE Software, Version 16.09.02
Cisco IOS Software [Fuji], Catalyst L3 Switch Software (c9k_IOSXE), Version 16.9.2, RELEASE SOFTWARE (fc4)
Expand Down Expand Up @@ -805,6 +806,7 @@ enable_c9k:
"term length 0": ""
"term width 0": ""
"show version | include operating mode" : ""
"show install summary": ""
"show version": |2
Cisco IOS XE Software, Version 16.09.02
Cisco IOS Software [Fuji], Catalyst L3 Switch Software (c9k_IOSXE), Version 16.9.2, RELEASE SOFTWARE (fc4)
Expand Down Expand Up @@ -1113,3 +1115,93 @@ grub_execute:
MANUAL_BOOT=yes
"boot":
new_state: cat9k_rommon_boot


# ================================
# Login sequence for login_creds

c9k_login7:
prompt: "Username: "
commands:
"ts_user": # First credential from login_creds: [ts, default] - terminal server auth
new_state: c9k_password7_ts

c9k_password7_ts:
prompt: "Password: "
commands:
"ts_pass":
response: |

Password OK

new_state: c9k_password7_ok # Intermediate state after Password OK

c9k_password7_ok:
prompt: "" # Empty prompt - requires 'enter' to proceed
commands:
"":
new_state: c9k_login7_device # Now go to device login

c9k_login7_device:
prompt: "Username: "
commands:
"admin": # Second credential from login_creds: [ts, default] - device credential
new_state: c9k_password7_device

c9k_password7_device:
prompt: "Password: "
commands:
"cisco":
new_state: c9k_exec

# ================================
# Login sequence for login_creds with fallback testing
c9k_login8:
prompt: "Username: "
commands:
"ts_user": # First credential from login_creds: [ts, default] - terminal server auth
new_state: c9k_password8_ts

c9k_password8_ts:
prompt: "Password: "
commands:
"ts_pass":
response: |

Password OK

new_state: c9k_password8_ok # Intermediate state after Password OK

c9k_password8_ok:
prompt: "" # Empty prompt - requires 'enter' to proceed
commands:
"":
new_state: c9k_login8_device # Now go to device login

c9k_login8_device:
prompt: "Username: "
commands:
"admin": # Second credential from login_creds: [ts, default] - device credential (will fail)
new_state: c9k_password8_device_fail

c9k_password8_device_fail:
prompt: "Password: "
commands:
"wrong_password":
response: |
% Login invalid

new_state: c9k_login8_fallback # Default fails, go to fallback

c9k_login8_fallback:
prompt: "Username: "
commands:
"fallback_user": # Fallback credential - this will succeed
new_state: c9k_password8_fallback

c9k_password8_fallback:
prompt: "Password: "
commands:
"fallback_pass":
new_state: c9k_exec

Loading
Loading