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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
48 changes: 48 additions & 0 deletions pkgs/clean-pkg/changelog/2026/january.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
--------------------------------------------------------------------------------
New
--------------------------------------------------------------------------------

* clean/stages/deletefiles
* Added timeout parameter to delete_files method to specify timeout for delete operation.

* iosxe
* RommonBoot Stage
* Added retry functionality for TFTP boot with configurable tftp_boot_max_attempts and tftp_boot_sleep_interval parameters
* Default 3 attempts with 30 second intervals between retries
* Applies to iosxe, cat9k, and ie3k platforms

* iosxe/cat9k/stackwise_virtual
* New stage for StackWise Virtual configuration

* clean-pkg
* Added image handler for RommonBoot stage to set image in rommon_boot section
* iosxe/cat9k
* updated the schema to make image as Optional parameter in RommonBoot stage


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

* clean-pkg
* Added support for new flag overwrite_if_size_different to allow conditional overwriting only when the existing file’s size differs.

* iosxe
* RommonBoot Stage
* Improved ROMMON TFTP logging to report each ROMMON variable as it is set, making ROMMON boot failures easier to debug.

* clean/iosxe/test_connect_device_rommon
* Removed the extra comma in the FIND_BOOT_IMAGE setting to fix the UT.

* installimage stage
* N9k
* Added check_reload logic to detect if device auto reloads after image install and wait for device to reload.

* clean
* IOSXE - ResetConfiguration
* Re-initialize init commands after rollback in case they were removed

* clean/recovery/recovery
* Added a check to verify the boot manual recovery process.


1,340 changes: 0 additions & 1,340 deletions pkgs/clean-pkg/sdk_generator/output/github_clean.json

This file was deleted.

2 changes: 1 addition & 1 deletion pkgs/clean-pkg/src/genie/libs/clean/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
'''

# metadata
__version__ = "25.11"
__version__ = "26.1"
__author__ = 'Cisco Systems Inc.'
__contact__ = ['asg-genie-support@cisco.com', 'pyats-support-ext@cisco.com']
__copyright__ = 'Copyright (c) 2019, Cisco Systems Inc.'
Expand Down
6 changes: 6 additions & 0 deletions pkgs/clean-pkg/src/genie/libs/clean/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ class StackMemberConfigException(CleanException):
Exception for when all the member of stack device is configured
"""
pass

class FailedToBootException(CleanException):
"""
Exception raised when device fails to boot from rommon
"""
pass
31 changes: 30 additions & 1 deletion pkgs/clean-pkg/src/genie/libs/clean/recovery/iosxe/recovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
from unicon.eal.dialogs import Dialog, Statement
from unicon.plugins.iosxe.statements import grub_prompt_handler

# Genie
from genie.libs.clean.exception import FailedToBootException

# Logger
log = logging.getLogger(__name__)

Expand Down Expand Up @@ -67,7 +70,33 @@ def recovery_worker(device, console_activity_pattern=None,
))
wait_futures(futures, timeout=timeout, return_when=ALL_COMPLETED)
elif kwargs.get('tftp_boot'):
device.api.device_rommon_boot(tftp_boot=kwargs.get('tftp_boot'))
tftp_boot = kwargs.get('tftp_boot')

# Retry for TFTP rommon boot if clean stage provides retry parameters
max_attempts = kwargs.get('tftp_boot_max_attempts', 1)
sleep_interval = kwargs.get('tftp_boot_sleep_interval', 30)

retry_count = 0
while retry_count < max_attempts:
try:
log.info(f"TFTP rommon boot attempt {retry_count + 1}/{max_attempts}")
device.api.device_rommon_boot(tftp_boot=tftp_boot)
log.info(f"TFTP rommon boot successful on attempt {retry_count + 1}")
break
except FailedToBootException as e:
retry_count += 1
if retry_count < max_attempts:
log.warning(
f"TFTP rommon boot failed on attempt {retry_count}/{max_attempts}. "
f"Error: {str(e)}. Retrying in {sleep_interval} seconds..."
)
time.sleep(sleep_interval)
else:
log.error(
f"TFTP rommon boot failed after {max_attempts} attempts. "
f"Last error: {str(e)}"
)
raise


def device_recovery(con, timeout, golden_image, grub_activity_pattern):
Expand Down
4 changes: 4 additions & 0 deletions pkgs/clean-pkg/src/genie/libs/clean/recovery/recovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ def _recovery_steps(device, clear_line=True, powercycler=True,
device.destroy()
device.api.configure_management_console()
log.info(f"Successfully configured management console speed on device '{device.name}'")

log.info(banner(f"Verify if manual boot is configured on device '{device.name}'"))
device.api.verify_no_boot_manual()

device.disconnect()
continue
else:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from genie import abstract
abstract.declare_token(chassis_type='stackwise_virtual')
Loading
Loading