Skip to content

Commit ea87320

Browse files
authored
Merge pull request #113 from CiscoTestAutomation/release_25.5
Release 25.5
2 parents b6cc3f0 + 1c487df commit ea87320

37 files changed

+1168
-177
lines changed

docs/changelog/2025/may.rst

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
May 2025
2+
==========
3+
4+
- Unicon v25.5
5+
------------------------
6+
7+
8+
9+
.. csv-table:: Module Versions
10+
:header: "Modules", "Versions"
11+
12+
``unicon.plugins``, v25.5
13+
``unicon``, v25.5
14+
15+
16+
17+
18+
Changelogs
19+
^^^^^^^^^^
20+
--------------------------------------------------------------------------------
21+
Add
22+
--------------------------------------------------------------------------------
23+
24+
* connection provider
25+
* moved the logic of boot_device to a separate function before designating handles
26+
* added the init_active to handle the learn_hostname instead of having it in designate handles
27+
* Store "current_credentials" under device.credentials when credentials are used
28+
29+
* connection
30+
* Added logging per subconnection for DualRp, Stack and Quad connection
31+
32+
33+
--------------------------------------------------------------------------------
34+
Fix
35+
--------------------------------------------------------------------------------
36+
37+
* generic
38+
* service implementation
39+
* Update the state for debug mode in attach service.
40+
41+

docs/changelog/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Changelog
44
.. toctree::
55
:maxdepth: 2
66

7+
2025/may
78
2025/april
89
2025/march
910
2025/february

docs/changelog_plugins/2025/may.rst

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
May 2025
2+
==========
3+
4+
- Unicon.Plugins v25.5
5+
------------------------
6+
7+
8+
9+
.. csv-table:: Module Versions
10+
:header: "Modules", "Versions"
11+
12+
``unicon.plugins``, v25.5
13+
``unicon``, v25.5
14+
15+
16+
17+
18+
Changelogs
19+
^^^^^^^^^^
20+
--------------------------------------------------------------------------------
21+
Add
22+
--------------------------------------------------------------------------------
23+
24+
* iosxe/cat9k/stackwise_virtual
25+
* Added support for SVL
26+
27+
* iosxe/cat9k/c9500x/stackwise_virtual
28+
* Added support for SVL
29+
30+
* generic
31+
* Add loghandler for subconnections to capture the buffer output
32+
33+
34+
--------------------------------------------------------------------------------
35+
Fix
36+
--------------------------------------------------------------------------------
37+
38+
* generic
39+
* Made it so incorrect login errors will attempt to use fallback credentials
40+
41+
* nxos
42+
* Add support for bash_console with module argument.
43+
* Make l2rib_dt_prompt pattern more strict
44+
45+
46+
--------------------------------------------------------------------------------
47+
New
48+
--------------------------------------------------------------------------------
49+
50+
* nxos
51+
* Added support for configure session
52+
* When using device.configure() you can now pass a session name with session="session_name"
53+
* IE device.configure("...", session="my_session")
54+
55+
* iosxe
56+
* IosXEPatterns
57+
* Updated the recovery-mode regex to match prompt for both mode
58+
* Added the rp-rec-mode regex to match prompt
59+
* Added acm state and transition support to IOS-XE plugin.
60+
* Enhanced Configure and HAConfigure services to support ACM CLI via acm_configlet argument using context-driven state transitions.
61+
* Added context-based transition function to enter ACM mode using acm configlet create <name>.
62+
* Added post-service transition to gracefully return to enable mode after configuration.
63+
64+

docs/changelog_plugins/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Plugins Changelog
44
.. toctree::
55
:maxdepth: 2
66

7+
2025/may
78
2025/april
89
2025/march
910
2025/february

docs/user_guide/services/nxos.rst

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,55 @@ For list of all the other service please refer this:
1313
* mandatory arguments are marked with `*`.
1414

1515

16+
bash_console
17+
------------
18+
19+
Service to execute commands in the router Bash. ``bash_console``
20+
gives you a router-like object to execute commands on using python context
21+
managers.
22+
23+
=========== ====================== ===========================================
24+
Argument Type Description
25+
=========== ====================== ===========================================
26+
timeout int (default 60 sec) timeout in sec for executing commands
27+
target str 'standby' to bring standby console to bash.
28+
enable_bash bool (default: True) enable bash service on device.
29+
module str module to connect to (optional)
30+
command str command to use with `run bash {command}`
31+
(optional)
32+
=========== ====================== ===========================================
33+
34+
Bash service will be enabled by default on devices that require the service to
35+
be configured. Bash configuration will be done on first invocation of the
36+
bash_console service.
37+
38+
You can specify the module name to use rlogin from the bash (root) shell to
39+
connect to the module shell. The command will default to `sudo su`.
40+
41+
.. code-block:: python
42+
43+
with device.bash_console() as bash:
44+
output1 = bash.execute('ls')
45+
output2 = bash.execute('pwd')
46+
47+
with device.bash_console(module='lc1') as bash:
48+
output1 = bash.execute('ls')
49+
output2 = bash.execute('pwd')
50+
51+
To run commands in the root shell, use `command="sudo su"`.
52+
53+
.. code-block:: python
54+
55+
with device.bash_console(command='sudo su') as bash:
56+
output1 = bash.execute('ls')
57+
output2 = bash.execute('pwd')
58+
59+
1660
shellexec
1761
---------
1862

19-
Service to execute commands on the Bourne-Again SHell (Bash).
20-
63+
Service to execute commands on the Bourne-Again SHell (Bash). Similar to
64+
``bash_console``.
2165

2266
========== ====================== ========================================
2367
Argument Type Description

docs/user_guide/supported_platforms.rst

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ the iosxe table, it will fallback to use the generic ``iosxe`` plugin. If
1414

1515
.. tip::
1616

17-
The priority to pick up which plugin is: chassis_type > os > platform > model.
17+
The priority to pick up which plugin is: chassis_type > os > platform > model > submodel.
1818

1919

2020
.. important::
@@ -30,8 +30,8 @@ the iosxe table, it will fallback to use the generic ``iosxe`` plugin. If
3030

3131
.. csv-table:: Unicon Supported Platforms
3232
:align: center
33-
:widths: 20, 20, 20, 40
34-
:header: "os", "platform", "model", "Comments"
33+
:widths: 20, 20, 20, 20, 40
34+
:header: "os", "platform", "model", "submodel", "Comments"
3535

3636
``apic``
3737
``aireos``
@@ -46,21 +46,22 @@ the iosxe table, it will fallback to use the generic ``iosxe`` plugin. If
4646
``confd``, ``nfvis``
4747
``dnos6``
4848
``dnos10``
49-
``fxos``,,,"Tested with FP2K."
49+
``fxos``,,,,"Tested with FP2K."
5050
``fxos``, ``fp4k``
5151
``fxos``, ``fp9k``
52-
``fxos``, ``ftd``,,"Deprecated, please use one of the other fxos plugins."
53-
``gaia``, , , "Check Point Gaia OS"
52+
``fxos``, ``ftd``,,,"Deprecated, please use one of the other fxos plugins."
53+
``gaia``, , , , "Check Point Gaia OS"
5454
``hvrp``
5555
``ios``, ``ap``
5656
``ios``, ``iol``
5757
``ios``, ``iosv``
58-
``ios``, ``pagent``,,"See example below."
58+
``ios``, ``pagent``,,,"See example below."
5959
``iosxe``
6060
``iosxe``, ``cat3k``
6161
``iosxe``, ``cat3k``, ``ewlc``
6262
``iosxe``, ``cat8k``
63-
``iosxe``, ``cat9k``
63+
``iosxe``, ``cat9k``,
64+
``iosxe``, ``cat9k``, ``c9500``, ``c9500x``, "See example below."
6465
``iosxe``, ``c9800``
6566
``iosxe``, ``c9800``, ``ewc_ap``
6667
``iosxe``, ``csr1000v``
@@ -76,26 +77,26 @@ the iosxe table, it will fallback to use the generic ``iosxe`` plugin. If
7677
``iosxr``, ``spitfire``
7778
``ironware``
7879
``ise``
79-
``linux``, , , "Generic Linux server with bash prompts"
80-
``nd``, , , "Nexus Dashboard (ND) Linux server. identical to os: linux"
80+
``linux``, , , , "Generic Linux server with bash prompts"
81+
``nd``, , , , "Nexus Dashboard (ND) Linux server. identical to os: linux"
8182
``nxos``
8283
``nxos``, ``mds``
8384
``nxos``, ``n5k``
8485
``nxos``, ``n7k``
8586
``nxos``, ``n9k``
8687
``nxos``, ``nxosv``
8788
``nxos``, ``aci``
88-
``nso``,,, "Network Service Orchestrator"
89-
``ons``,,, "Optical Networking System"
90-
``sdwan``, ``viptela``,,"Identical to os=viptela."
89+
``nso``,,,, "Network Service Orchestrator"
90+
``ons``,,,, "Optical Networking System"
91+
``sdwan``, ``viptela``,,,"Identical to os=viptela."
9192
``sros``
9293
``staros``
9394
``vos``
9495
``junos``
9596
``eos``
9697
``sros``
97-
``viptela``,,,"Identical to os=sdwan, platform=viptela."
98-
``windows``,,,"Only command shell (cmd) is supported. Powershell is not supported"
98+
``viptela``,,,,"Identical to os=sdwan, platform=viptela."
99+
``windows``,,,,"Only command shell (cmd) is supported. Powershell is not supported"
99100

100101
To use this table - locate your device's os/platform/model information, and fill
101102
your pyATS testbed YAML with it:
@@ -222,6 +223,35 @@ Example: Stack router
222223
port: 2003
223224
member: 3 <<< peer rp id
224225
226+
Example: Stackwise Virtual Router
227+
---------------------------------
228+
229+
.. code-block:: yaml
230+
231+
devices:
232+
router_hostname:
233+
os: iosxe
234+
platform: cat9k
235+
model: c9500
236+
submodel: c9500x
237+
chassis_type: stackwise_virtual <<< define the chassis_type as 'stackwise_virtual'
238+
credentials:
239+
default:
240+
username: xxx
241+
password: yyy
242+
enable:
243+
password: zzz
244+
connections:
245+
defaults:
246+
class: unicon.Unicon
247+
a:
248+
protocol: telnet
249+
ip: 1.1.1.1
250+
port: 2001
251+
b:
252+
protocol: telnet
253+
ip: 1.1.1.1
254+
port: 2002
225255
226256
Example: Quad Sup router
227257
------------------------

src/unicon/plugins/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
__version__ = '25.4'
1+
__version__ = "25.5"
22

33
supported_chassis = [
44
'single_rp',
55
'dual_rp',
66
'stack',
77
'quad',
8+
'stackwise_virtual'
89
]
910

1011
supported_os = [

src/unicon/plugins/apic/patterns.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
__author__ = "dwapstra"
22

3+
from unicon.utils import ANSI_REGEX
34
from unicon.plugins.generic.patterns import GenericPatterns
45

56

67
class ApicPatterns(GenericPatterns):
78
def __init__(self):
89
super().__init__()
10+
self.learn_hostname = r'^.*?({a})?(?P<hostname>[-\w]+)\s?([-\w\]/~:\.\d ]+)?([>\$~%#\]])\s*(\x1b\S+)?$'.format(a=ANSI_REGEX)
911
self.enable_prompt = r'^(.*?)((\x1b\S+)?\x00)*(%N)#\s*(\x1b\S+)?$'
1012
self.config_prompt = r'^(.*?)((\x1b\S+)?\x00)*(%N)\(config.*\)#\s*(\x1b\S+)?$'
1113
self.shell_prompt = r'^(.*?)((\x1b\S+)?\x00)*\[[-\.\w]+@((%N)\s+.*?\]#)\s*(\x1b\S+)?$'

src/unicon/plugins/apic/statemachine.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ def create(self):
2222
enable = State('enable', patterns.enable_prompt)
2323
config = State('config', patterns.config_prompt)
2424
shell = State('shell', patterns.shell_prompt)
25+
learn_hostname = State('learn_hostname', patterns.learn_hostname)
2526
setup = State('setup', list(setup_patterns.__dict__.values()))
2627

2728
self.add_state(enable)
2829
self.add_state(config)
30+
self.add_state(learn_hostname)
2931
self.add_state(setup)
3032
self.add_state(shell)
3133

34+
self.add_path(Path(learn_hostname, enable, None, None))
3235
enable_to_config = Path(enable, config, 'configure', None)
3336
config_to_enable = Path(config, enable, 'end', None)
3437

src/unicon/plugins/generic/service_implementation.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,6 +2093,10 @@ def call_service(self, # noqa: C901
20932093
lb.setFormatter(logging.Formatter(fmt=UNICON_LOG_FORMAT))
20942094
self.connection.log.addHandler(lb)
20952095

2096+
# logging the output to subconnections
2097+
for subcon in con.subconnections:
2098+
subcon.log.addHandler(lb)
2099+
20962100
# Clear log buffer
20972101
self.log_buffer.seek(0)
20982102
self.log_buffer.truncate()
@@ -2250,6 +2254,8 @@ def call_service(self, # noqa: C901
22502254
self.log_buffer.truncate()
22512255

22522256
self.connection.log.removeHandler(lb)
2257+
for subcon in con.subconnections:
2258+
subcon.log.removeHandler(lb)
22532259

22542260
self.result = True
22552261
if return_output:
@@ -2681,7 +2687,7 @@ class AttachModuleService(BaseService):
26812687
with rtr.attach(1) as m:
26822688
m.execute('show interface')
26832689
m.execute(['show interface 1', 'show interface 2'])
2684-
# if we want to go to module_debug state
2690+
# if we want to go to lc_shell state
26852691
with rtr.attach(1, debug=True) as m:
26862692
m.execute('show interface')
26872693
m.execute(['show interface 1', 'show interface 2'])
@@ -2742,7 +2748,7 @@ def __enter__(self):
27422748
raise NotImplementedError('Attach module state not implemented')
27432749

27442750
self.conn.log.debug('+++ attaching module +++')
2745-
conn.state_machine.go_to('module_debug' if self.debug else 'module',
2751+
conn.state_machine.go_to('lc_shell' if self.debug else 'module',
27462752
conn.spawn,
27472753
context=self.context,
27482754
timeout=self.timeout)

src/unicon/plugins/generic/statements.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,11 @@ def incorrect_login_handler(spawn, context, session):
451451
# If credentials have been supplied, there are no login retries.
452452
# The user must supply appropriate credentials to ensure login
453453
# does not fail. Skip it for the first attempt
454+
455+
# Attempt fallback credentials if available
456+
if session['current_credential']:
457+
return
458+
454459
raise UniconAuthenticationError(
455460
'Login failure, either wrong username or password')
456461
if 'incorrect_login_attempts' not in session:

src/unicon/plugins/iosxe/cat9k/c9500x/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)