Skip to content

Commit a3d9979

Browse files
authored
Merge pull request #117 from CiscoTestAutomation/release_25.9
Release 25.9
2 parents 882e7c6 + 38104cb commit a3d9979

23 files changed

+301
-18
lines changed

docs/changelog/2025/september.rst

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
September 2025
2+
==========
3+
4+
September 30 - Unicon v25.9
5+
------------------------
6+
7+
8+
9+
.. csv-table:: Module Versions
10+
:header: "Modules", "Versions"
11+
12+
``unicon.plugins``, v25.9
13+
``unicon``, v25.9
14+
15+
16+
17+
18+
Changelogs
19+
^^^^^^^^^^
20+
--------------------------------------------------------------------------------
21+
Fix
22+
--------------------------------------------------------------------------------
23+
24+
* backend/spawn
25+
* Modified backend spawn implementation, updated logic to optimize buffer matching
26+
27+
28+
--------------------------------------------------------------------------------
29+
Fix
30+
--------------------------------------------------------------------------------
31+
32+
* generic/service_statements
33+
* Fixed the copy_overwrite_handler prompt
34+
35+
* iosxe/stack
36+
* Added pattern for install image to match
37+
* Fixed the stack reload for the return_output true condition
38+
39+

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/september
78
2025/august
89
2025/july
910
2025/june
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
September 2025
2+
==========
3+
4+
September 30 - Unicon v25.9
5+
------------------------
6+
7+
8+
9+
.. csv-table:: Module Versions
10+
:header: "Modules", "Versions"
11+
12+
``unicon.plugins``, v25.9
13+
``unicon``, v25.9
14+
15+
16+
17+
18+
Changelogs
19+
^^^^^^^^^^
20+
--------------------------------------------------------------------------------
21+
Fix
22+
--------------------------------------------------------------------------------
23+
24+
* generic
25+
* Update config error pattern
26+
27+
* iosxe
28+
* Updated disable_prompt to ensure no false positives
29+
* Added support to syntax prompt
30+
31+
* pid tokens
32+
* Updated PID tokens to support C9500X-60L4D devices
33+
34+
35+
--------------------------------------------------------------------------------
36+
New
37+
--------------------------------------------------------------------------------
38+
39+
* iosxe/cat9k add rommon variable support in reload service
40+
41+

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/september
78
2025/august
89
2025/july
910
2025/june

src/unicon/plugins/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "25.8"
1+
__version__ = "25.9"
22

33
supported_chassis = [
44
'single_rp',

src/unicon/plugins/generic/service_statements.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,9 @@ def copy_handler_1(spawn, context, send_key):
170170

171171
def copy_overwrite_handler(spawn, context):
172172
if context['overwrite'] == 'False':
173-
spawn.sendline('n')
173+
spawn.send('n')
174174
else:
175-
spawn.sendline('y')
175+
spawn.send('y')
176176

177177
def copy_error_handler(context, retry=False):
178178
if retry:

src/unicon/plugins/generic/settings.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ def __init__(self):
149149
r'subinterface is already configured as part of an IEEE 802.10, IEEE 802.1Q, '
150150
r'or ISL vLAN.',
151151
r'% OSPF: Please enable segment-routing globally',
152-
r"% Invalid input detected at '^' marker"
152+
r"% Invalid input detected at '^' marker",
153+
r"%ERROR:"
153154
]
154155

155156
# Number of times to retry for config mode by configure service.

src/unicon/plugins/iosxe/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def __init__(self):
3030
self.rommon = svc.Rommon
3131
self.tclsh = svc.Tclsh
3232
self.maintenance_mode = svc.MaintenanceMode
33+
self.config_syntax = svc.ConfigSyntax
3334

3435

3536
class HAIosXEServiceList(HAServiceList):
@@ -48,6 +49,7 @@ def __init__(self):
4849
self.reset_standby_rp = svc.ResetStandbyRP
4950
self.rommon = svc.HARommon
5051
self.tclsh = svc.Tclsh
52+
self.config_syntax = svc.ConfigSyntax
5153

5254

5355
class IosXESingleRpConnection(BaseSingleRpConnection):

src/unicon/plugins/iosxe/cat9k/c9500x/stackwise_virtual/service_implementation.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
""" Stack based IOS-XE/cat9k/c9500X service implementations. """
2+
import io
3+
import logging
24
from time import sleep
35
from collections import namedtuple
46
from datetime import timedelta
@@ -7,6 +9,7 @@
79
from unicon.eal.dialogs import Dialog
810
from unicon.core.errors import SubCommandFailure
911
from unicon.bases.routers.services import BaseService
12+
from unicon.logs import UniconStreamHandler, UNICON_LOG_FORMAT
1013

1114
from unicon.plugins.iosxe.stack.utils import StackUtils
1215
from unicon.plugins.generic.statements import custom_auth_statements
@@ -44,6 +47,7 @@ def __init__(self, connection, context, *args, **kwargs):
4447
self.end_state = 'enable'
4548
self.timeout = connection.settings.STACK_RELOAD_TIMEOUT
4649
self.reload_command = "redundancy reload shelf"
50+
self.log_buffer = io.StringIO()
4751
self.dialog = Dialog(stack_reload_stmt_list)
4852

4953
def call_service(self,
@@ -82,6 +86,20 @@ def call_service(self,
8286
if not isinstance(append_error_pattern, list):
8387
raise ValueError('append_error_pattern should be a list')
8488
self.error_pattern += append_error_pattern
89+
90+
# Connecting to the log handler to capture the buffer output
91+
lb = UniconStreamHandler(self.log_buffer)
92+
lb.setFormatter(logging.Formatter(fmt=UNICON_LOG_FORMAT))
93+
self.connection.log.addHandler(lb)
94+
95+
# logging the output to subconnections
96+
for subcon in self.connection.subconnections:
97+
subcon.log.addHandler(lb)
98+
99+
# Clear log buffer
100+
self.log_buffer.seek(0)
101+
self.log_buffer.truncate()
102+
85103
# update all subconnection context with image_to_boot
86104
if image_to_boot:
87105
for subconn in self.connection.subconnections:
@@ -243,12 +261,23 @@ def boot(con):
243261
self.connection.connection_provider.init_connection()
244262

245263
self.connection.log.info("+++ Reload Completed Successfully +++")
264+
265+
# Read the log buffer
266+
self.log_buffer.seek(0)
267+
reload_output = self.log_buffer.read()
268+
# clear buffer
269+
self.log_buffer.truncate()
270+
271+
# Remove the handler
272+
self.connection.log.removeHandler(lb)
273+
for subcon in self.connection.subconnections:
274+
subcon.log.removeHandler(lb)
275+
246276
self.result = True
247277

248278
if return_output:
249279
Result = namedtuple('Result', ['result', 'output'])
250-
self.result = Result(self.result, reload_cmd_output.match_output.replace(reload_cmd, '', 1))
251-
280+
self.result = Result(self.result, reload_output.replace(reload_cmd, '', 1))
252281

253282
class SVLStackSwitchover(BaseService):
254283
""" Get Rp state
@@ -355,3 +384,4 @@ def call_service(self, command=None,
355384
else:
356385
self.connection.log.info('Switchover failed')
357386
self.result = False
387+

src/unicon/plugins/iosxe/cat9k/service_implementation.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ def call_service(self, *args, **kwargs):
4141
# assume the device is in rommon if image_to_boot is passed
4242
# update reload command to use rommon boot syntax
4343
if "image_to_boot" in kwargs:
44+
if 'rommon_vars' in kwargs and self.connection.state_machine.current_state == 'rommon':
45+
self.connection.execute([f'set {k}={v}' for k, v in kwargs['rommon_vars'].items()])
4446
self.context["image_to_boot"] = kwargs["image_to_boot"]
4547
reload_command = "boot {}".format(
4648
self.context['image_to_boot']).strip()
@@ -63,6 +65,9 @@ def __init__(self, connection, context, **kwargs):
6365

6466
def pre_service(self, *args, **kwargs):
6567
if "image_to_boot" in kwargs:
68+
if 'rommon_vars' in kwargs and all(con.state_machine.current_state == 'rommon' for con in self.connection._subconnections):
69+
for con in self.connection._subconnections:
70+
con.execute([f'set {k}={v}' for k, v in kwargs['rommon_vars'].items()])
6671
self.start_state = 'rommon'
6772
if 'image_to_boot' in self.context:
6873
self.context['orig_image_to_boot'] = self.context['image_to_boot']

0 commit comments

Comments
 (0)