Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
04fef19
Add arg to define thread limit - to throttle concurrent API calls whe…
monrog2 Feb 27, 2026
233359a
353 the script incorrectly detects vpc and port channel interfaces as…
monrog2 Feb 27, 2026
6d7d4d4
Update aci-preupgrade-validation-script.py
monrog2 Feb 27, 2026
e4defbf
print cleanup
monrog2 Feb 27, 2026
6a2fe7f
Merge branch 'master' of github.com:datacenter/ACI-Pre-Upgrade-Valida…
takishida Mar 7, 2026
20b5eee
Check for F0467 bgpProt-policy-already-existing
dhaselva Mar 26, 2026
4e4a120
Incorporated the review comments
dhaselva Mar 27, 2026
b2dfa64
Addressed review comments
dhaselva Mar 27, 2026
d849e8e
fix: Add cversion check for post_upgrade_cb_check (#377)
takishida Apr 3, 2026
67dab4b
added validation for CFD CSCwp64296 (#307)
psureshb Apr 3, 2026
6ccd6d9
Added pre-upgrade validation for N9K-C9408 with more than 6 N9K-X9400…
Harinadh-Saladi Apr 3, 2026
ea1e0f8
New Validation for APIC Storage Inode Usage (F4388, F4389, F4390 equi…
sanjanch Apr 3, 2026
dc09913
Add validation for multipod_modular_spine_bootscript_check - CSCwr668…
asraf-khan Apr 4, 2026
d118464
Update pytest.yml to run on vX.Y.Z branches
takishida Apr 4, 2026
07ea2db
adding of cli parameters for user and password (#335)
Thatleft Apr 4, 2026
5815d26
Added version check instead of generic check
dhaselva Apr 6, 2026
b8ca9d5
Modified the target version check
dhaselva Apr 7, 2026
fdd9a28
pulled dev branch
dhaselva Apr 9, 2026
ea73e9b
Removed whitepsaces
dhaselva Apr 9, 2026
d41ad25
Modified the content in validation file
dhaselva Apr 10, 2026
6f07e2c
Updated the pytest files
dhaselva May 5, 2026
217dbcb
Added validation for CSCwd40071 (#332)
sanjanch May 8, 2026
69d6a4b
Added validation for CSCws84232 (#334)
veenaskumar-cisco May 19, 2026
a6d65c2
Merge branch 'v4.1.0-dev' into dhaselva/F0467
dhaselva May 21, 2026
1c4a1b5
modified the logic suggested by Gabe
dhaselva May 21, 2026
f6ce159
Merge branch 'dhaselva/F0467' of github.com:dhaselva/ACI-Pre-Upgrade-…
dhaselva May 21, 2026
3aaf31b
Modified the bgp proto content
dhaselva May 21, 2026
18f619e
Removed unwanted whitespace
dhaselva May 21, 2026
403e840
Removed the duplicate entry from line line 6555
dhaselva May 21, 2026
8c5487a
merged the changes from v4.2.0-dev
dhaselva May 22, 2026
714e996
Added the tversion check
dhaselva May 25, 2026
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
33 changes: 33 additions & 0 deletions aci-preupgrade-validation-script.py
Original file line number Diff line number Diff line change
Expand Up @@ -6053,6 +6053,38 @@ def auto_firmware_update_on_switch_check(cversion, tversion, **kwargs):

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


Comment thread
dhaselva marked this conversation as resolved.
@check_wrapper(check_title='BGP Policy Already Existing (F0467 bgpProt-policy-already-existing)')
def bgp_policy_already_existing_check(**kwargs):
result = PASS
headers = ['Fault', 'Tenant', 'L3Out', 'changeSet']
data = []
unformatted_headers = ['Fault', 'Affected', 'changeSet']
unformatted_data = []
recommended_action = 'Resolve duplicate BGP policy configuration on the affected L3Out.'
Comment thread
dhaselva marked this conversation as resolved.
Outdated
doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#bgp-policy-already-existing'

Comment thread
dhaselva marked this conversation as resolved.
affected_regex = r'uni/tn-(?P<tenant>[^/]+)/out-(?P<l3out>[^\]]+)'
filter = 'faultDelegate.json?query-target-filter=and(eq(faultDelegate.code,"F0467"),wcard(faultDelegate.changeSet,"bgpProt-policy-already-existing"))'
fault_delegates = icurl('class', filter)

for fault_delegate in fault_delegates:
attributes = fault_delegate['faultDelegate']['attributes']
fault_code = attributes.get('code', '')
affected = attributes.get('affected', '')
change_set = attributes.get('changeSet', '')
affected_array = re.search(affected_regex, affected)
if affected_array:
data.append([fault_code, affected_array.group('tenant'), affected_array.group('l3out'), change_set])
else:
unformatted_data.append([fault_code, affected, change_set])

if data or unformatted_data:
result = FAIL_O

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


# ---- Script Execution ----


Expand Down Expand Up @@ -6152,6 +6184,7 @@ class CheckManager:
prefix_already_in_use_check,
encap_already_in_use_check,
access_untagged_check,
bgp_policy_already_existing_check,
bd_subnet_overlap_check,
bd_duplicate_subnet_check,
vmm_controller_status_check,
Expand Down
33 changes: 33 additions & 0 deletions docs/docs/validations.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Items | Faults | This Script
[Fabric Port Status][f19] | F1394: ethpm-if-port-down-fabric | :white_check_mark: | :no_entry_sign:
[Equipment Disk Limits][f20] | F1820: 80% -minor<br>F1821: -major<br>F1822: -critical | :white_check_mark: | :no_entry_sign:
[VMM Inventory Partially Synced][f21] | F0132: comp-ctrlr-operational-issues | :white_check_mark: | :no_entry_sign:
[BGP Policy Already Existing][f22] | F0467: bgpProt-policy-already-existing | :white_check_mark: | :no_entry_sign:
Comment thread
dhaselva marked this conversation as resolved.
Outdated


[f1]: #apic-disk-space-usage
Expand All @@ -105,6 +106,7 @@ Items | Faults | This Script
[f19]: #fabric-port-status
[f20]: #equipment-disk-limits
[f21]: #vmm-inventory-partially-synced
[f22]: #bgp-policy-already-existing

### Configuration Checks

Expand Down Expand Up @@ -1551,6 +1553,37 @@ EPGs using the `pre-provision` resolution immediacy do not rely on the VMM inven

This check returns a `MANUAL` result as there are many reasons for a partial inventory sync to be reported. The goal is to ensure that the VMM inventory sync has fully completed before triggering the APIC upgrade to reduce any chance for unexpected inventory changes to occur.

### BGP Policy Already Existing

This check validates `F0467` faults where `changeSet` contains `bgpProt-policy-already-existing`.
The fault indicates conflicting BGP protocol policy configuration under an L3Out deployment path.
Comment thread
dhaselva marked this conversation as resolved.
Outdated

Resolve these faults before upgrade by reviewing the affected L3Out BGP policy and removing duplicate or inconsistent configuration.
Comment thread
dhaselva marked this conversation as resolved.
Outdated

Example:

# fault.Delegate
affected : resPolCont/rtdOutCont/rtdOutDef-[uni/tn-common/out-L3outY]/nwissues
code : F0467
ack : no
cause : configuration-failed
changeSet : configQual:bgpProt-policy-already-existing, configSt:failed-to-apply, temporaryError:no
childAction :
created : 2026-03-25T11:31:16.724+00:00
descr : Fault delegate: Configuration failed for uni/tn-common/out-L3outY due to A specific leaf node can hold only a single bgpProtP config; this fault is raised when inconsistent configuration is detected, debug message:
dn : uni/tn-common/out-L3outY/fd-[resPolCont/rtdOutCont/rtdOutDef-[uni/tn-common/out-L3outY]/nwissues]-fault-F0467
domain : tenant
highestSeverity : critical
lc : raised
occur : 1
origSeverity : critical
prevSeverity : critical
rn : fd-[resPolCont/rtdOutCont/rtdOutDef-[uni/tn-common/out-L3outY]/nwissues]-fault-F0467
rule : fv-nw-issues-config-failed
severity : critical
subject : management
type : config

## Configuration Check Details

### VPC-paired Leaf switches
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[
{
"faultDelegate": {
"attributes": {
"affected": "resPolCont/rtdOutCont/rtdOutDef-[uni/tn-common/out-L3outY]/nwissues",
"code": "F0467",
"changeSet": "configQual:bgpProt-policy-already-existing, configSt:failed-to-apply, temporaryError:no"
}
}
},
{
"faultDelegate": {
"attributes": {
"affected": "resPolCont/rtdOutCont/rtdOutDef-[uni/tn-prod/out-L3outA]/nwissues",
"code": "F0467",
"changeSet": "configQual:bgpProt-policy-already-existing, configSt:failed-to-apply, temporaryError:no"
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{
"faultDelegate": {
"attributes": {
"affected": "resPolCont/rtdOutCont/rtdOutDef-[uni/invalid]/nwissues",
"code": "F0467",
"changeSet": "configQual:bgpProt-policy-already-existing, configSt:failed-to-apply, temporaryError:no"
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
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__))
test_function = "bgp_policy_already_existing_check"
# icurl queries
faultDelegates = 'faultDelegate.json?query-target-filter=and(eq(faultDelegate.code,"F0467"),wcard(faultDelegate.changeSet,"bgpProt-policy-already-existing"))'

@pytest.mark.parametrize(
"icurl_outputs, expected_result, expected_data, expected_unformatted_data",
[
(
{faultDelegates: read_data(dir, "faultDelegate_POS.json")},
script.FAIL_O,
[
[
"F0467",
"common",
"L3outY",
"configQual:bgpProt-policy-already-existing, configSt:failed-to-apply, temporaryError:no",
],
[
"F0467",
"prod",
"L3outA",
"configQual:bgpProt-policy-already-existing, configSt:failed-to-apply, temporaryError:no",
],
],
[],
),
(
{faultDelegates: read_data(dir, "faultDelegate_UNFORMATTED.json")},
script.FAIL_O,
[],
[
[
"F0467",
"resPolCont/rtdOutCont/rtdOutDef-[uni/invalid]/nwissues",
"configQual:bgpProt-policy-already-existing, configSt:failed-to-apply, temporaryError:no",
],
],
),
(
{faultDelegates: read_data(dir, "faultDelegate_NEG.json")},
script.PASS,
[],
[],
),
],
)
def test_logic(run_check, mock_icurl, expected_result, expected_data, expected_unformatted_data):
result = run_check()
assert result.result == expected_result
assert result.data == expected_data
assert result.unformatted_data == expected_unformatted_data