Skip to content
Open
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
24 changes: 24 additions & 0 deletions aci-preupgrade-validation-script.py
Original file line number Diff line number Diff line change
Expand Up @@ -5300,6 +5300,29 @@ def apic_database_size_check(cversion, **kwargs):
result = FAIL_UF
return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url)


@check_wrapper(check_title='Auto Firmware Update on Switch Discovery')
def auto_firmware_update_ondiscovery_check(cversion, tversion, **kwargs):
result = NA
headers = ["Auto firmware Policy Dn", "Switch enforced Version"]
data = []
recommended_action = 'Disable the Auto Firmware Update on Switch Discovery policy before upgrade'
doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#auto-firmware-update-on-switch-discovery'

if not tversion or not cversion:
return Result(result=MANUAL, msg=TVER_MISSING)
if (cversion.older_than("5.2(7a)") and tversion.newer_than("6.0(3a)")) or (cversion.older_than("6.0(3a)") and tversion.newer_than("6.0(3a)")):
result = PASS
auto_firmware_update_api = 'firmwareRepoP.json'
auto_firmware_update_api += '?query-target-filter=eq(firmwareRepoP.enforceBootscriptVersionValidation,"true")'
auto_firmware_update = icurl('class', auto_firmware_update_api)
if auto_firmware_update:
data.append([auto_firmware_update[0]["firmwareRepoP"]["attributes"]["dn"], auto_firmware_update[0]["firmwareRepoP"]["attributes"]["defaultSwitchVersion"]])
if data:
result = FAIL_O

return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url)

# ---- Script Execution ----

def parse_args(args):
Expand Down Expand Up @@ -5455,6 +5478,7 @@ def get_checks(api_only, debug_function):
standby_sup_sync_check,
stale_pcons_ra_mo_check,
isis_database_byte_check,
auto_firmware_update_ondiscovery_check,

]
conn_checks = [
Expand Down
13 changes: 11 additions & 2 deletions docs/docs/validations.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ Items | Defect | This Script
[Observer Database Size][d25] | CSCvw45531 | :white_check_mark: | :no_entry_sign: |:no_entry_sign:
[Stale pconsRA Object][d26] | CSCwp22212 | :white_check_mark: | :no_entry_sign: |:no_entry_sign:
[ISIS DTEPs Byte Size][d27] | CSCwp15375 | :white_check_mark: | :no_entry_sign: |:no_entry_sign:

[Auto Firmware Update on Switch Discovery][d28] | CSCwe83941 | :white_check_mark: | :no_entry_sign: |:no_entry_sign:

[d1]: #ep-announce-compatibility
[d2]: #eventmgr-db-size-defect-susceptibility
Expand Down Expand Up @@ -217,7 +217,7 @@ Items | Defect | This Script
[d25]: #observer-database-size
[d26]: #stale-pconsra-object
[d27]: #isis-dteps-byte-size

[d28]: #auto-firmware-update-on-switch-discovery

## General Check Details

Expand Down Expand Up @@ -2588,6 +2588,14 @@ Do not upgrade to any affected ACI software release if this check fails.
!!! note
Nexus Dashboard Insights (NDI) integration can cause ACI tech support generation to happen automatically as part of the bug scan feature.

### Auto Firmware Update on Switch Discovery

Due to [CSCwe83941][59] if 'Auto Firmware Update on Switch Discovery' is enabled with the target release of 16.0(3) and later, a new switch commissioned to ACI Fabric could fail discovery.

The download of firmware image fails, causing the switch to become "soft-brick" , the switch needs to be recovered.

Do not upgrade with 'Auto Firmware Update on Switch Discovery' enabled, to avoid this escenario.


[0]: https://github.com/datacenter/ACI-Pre-Upgrade-Validation-Script
[1]: https://www.cisco.com/c/dam/en/us/td/docs/Website/datacenter/apicmatrix/index.html
Expand Down Expand Up @@ -2648,3 +2656,4 @@ Do not upgrade to any affected ACI software release if this check fails.
[56]: https://www.cisco.com/c/en/us/td/docs/dcn/whitepapers/cisco-aci-virtual-edge-migration.html
[57]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwp22212
[58]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwp15375
[59]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwe83941
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[
{
"firmwareRepoP": {
"attributes": {
"annotation": "",
"childAction": "",
"defaultSwitchVersion": "n9000-16.0(9d)",
"descr": "",
"dn": "uni/fabric/fwrepop",
"enforceBootscriptVersionValidation": "yes",
"extMngdBy": "",
"lcOwn": "local",
"modTs": "2025-08-13T17:50:54.830+00:00",
"monPolDn": "uni/fabric/monfab-default",
"name": "default",
"nameAlias": "",
"ownerKey": "",
"ownerTag": "",
"status": "",
"uid": "0",
"userdom": "all"
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import os
import pytest
import logging
import importlib
from helpers.utils import read_data

script = importlib.import_module("aci-preupgrade-validation-script")

log = logging.getLogger(__name__)
dir = os.path.dirname(os.path.abspath(__file__))

# icurl queries
auto_firmware_update_api = 'firmwareRepoP.json'
auto_firmware_update_api += '?query-target-filter=eq(firmwareRepoP.enforceBootscriptVersionValidation,"true")'

@pytest.mark.parametrize(
"icurl_outputs, cversion, tversion, expected_result",
[

# MANUAL cases
(
{auto_firmware_update_api: read_data(dir, "firmwareRepoP-pos.json")},
None, None,
script.MANUAL,
),
(
{auto_firmware_update_api: read_data(dir, "firmwareRepoP-pos.json")},
"5.2(7a)", None,
script.MANUAL,
),
(
{auto_firmware_update_api: read_data(dir, "firmwareRepoP-pos.json")},
None, "6.0(3d)",
script.MANUAL,
),
# NA cases
# firmwareRepoP cversion < 5.2(7) , tversion < 6.0(3) Result NA
(
{auto_firmware_update_api: read_data(dir, "firmwareRepoP-pos.json")},
"5.2(7a)", "6.0(2d)",
script.NA,
),
# firmwareRepoP cversion > 6.0(3) , tversion > 6.0(3) Result NA
(
{auto_firmware_update_api: read_data(dir, "firmwareRepoP-pos.json")},
"6.0(3a)", "6.0(9d)",
script.NA,
),
# Failure cases
# firmwareRepoP cversion < 5.2(7) , tversion > 6.0(3) Result FAIL_O
(
{auto_firmware_update_api: read_data(dir, "firmwareRepoP-pos.json")},
"5.2(7a)", "6.0(3d)",
script.FAIL_O,
),
# firmwareRepoP cversion is < 6.0(2) , tversion > 6.0(3) Result FAIL_O
(
{auto_firmware_update_api: read_data(dir, "firmwareRepoP-pos.json")},
"6.0(2a)", "6.0(3d)",
script.FAIL_O,
),
# Pass cases
# no firmwareRepoP cversion is < 5.2(7) , tversion > 6.0(3) Result PASS
(
{auto_firmware_update_api: []},
"5.2(7a)", "6.0(3d)",
script.PASS,
),
# no firmwareRepoP cversion is < 6.0(2) , tversion > 6.0(3) Result PASS
(
{auto_firmware_update_api: []},
"5.2(7a)", "6.0(3d)",
script.PASS,
),
]
)
def test_logic(mock_icurl, cversion, tversion, expected_result):
tversion = script.AciVersion(tversion) if tversion else None
cversion = script.AciVersion(cversion) if cversion else None

result = script.auto_firmware_update_ondiscovery_check(1, 1, cversion, tversion)
assert result == expected_result