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
30 changes: 30 additions & 0 deletions aci-preupgrade-validation-script.py
Original file line number Diff line number Diff line change
Expand Up @@ -6007,6 +6007,35 @@ def apic_vmm_inventory_sync_faults_check(**kwargs):
recommended_action=recommended_action,
doc_url=doc_url)


@check_wrapper(check_title='Pending Contract Check')
def pending_contract_check(tversion, **kwargs):
result = PASS
headers = ["Pending Contract Count"]
data = []
recommended_action = 'Pending contracts detected. Contact TAC to resolve stuck contract deployments before upgrade to prevent outage.'
doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#pending-contract-check'

if not tversion:
return Result(result=MANUAL, msg=TVER_MISSING)

if tversion.older_than('6.1(4h)'):
# Query fvPndgCtrct with count
fvPndgCtrct_count = icurl('class', 'fvPndgCtrct.json?rsp-subtree-include=count')

if fvPndgCtrct_count:
count = int(fvPndgCtrct_count[0]['moCount']['attributes']['count'])

if count > 0:
result = FAIL_O
data.append([str(count)])

else:
return Result(result=NA, msg=VER_NOT_AFFECTED)

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


# ---- Script Execution ----


Expand Down Expand Up @@ -6168,6 +6197,7 @@ class CheckManager:
standby_sup_sync_check,
isis_database_byte_check,
configpush_shard_check,
pending_contract_check,

]
ssh_checks = [
Expand Down
11 changes: 11 additions & 0 deletions docs/docs/validations.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ Items | Defect | This Script
[Stale pconsRA Object][d26] | CSCwp22212 | :warning:{title="Deprecated"} | :no_entry_sign:
[ISIS DTEPs Byte Size][d27] | CSCwp15375 | :white_check_mark: | :no_entry_sign:
[Policydist configpushShardCont Crash][d28] | CSCwp95515 | :white_check_mark: |
[Pending Contract Check][d29] | CSCwp99433 | :white_check_mark: | :no_entry_sign:

[d1]: #ep-announce-compatibility
[d2]: #eventmgr-db-size-defect-susceptibility
Expand Down Expand Up @@ -220,6 +221,7 @@ Items | Defect | This Script
[d26]: #stale-pconsra-object
[d27]: #isis-dteps-byte-size
[d28]: #policydist-configpushshardcont-crash
[d29]: #pending-contract-check


## General Check Details
Expand Down Expand Up @@ -2613,6 +2615,14 @@ Due to [CSCwp95515][59], upgrading to an affected version while having any `conf

If any instances of `configpushShardCont` are flagged by this script, Cisco TAC must be contacted to identify and resolve the underlying issue before performing the upgrade.

### Pending Contract Check

Due to [CSCwp99433][62], failed transactions during high-scale contract processing can cause pending contracts (`fvPndgCtrct`) to get permanently stuck in memory, preventing contract policies from being deployed to leaf switches. The issue occurs when performing operations that require significant contract reprocessing, such as changing VRF enforcement mode (enforced ↔ unenforced) for VRFs containing hundreds or thousands of contracts, bulk contract configuration changes, or large-scale tenant migrations. When triggered, the `policyelement` service fails multiple transactions but continues processing, leaving `fvPndgCtrct` objects stuck in the system.

This script checks for the presence of pending contracts by querying `fvPndgCtrct` objects with a count in the affected version.

If any instances of `fvPndgCtrct` are flagged by this script, Cisco TAC must be contacted to identify and resolve the stuck contracts.


[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 @@ -2676,3 +2686,4 @@ If any instances of `configpushShardCont` are flagged by this script, Cisco TAC
[59]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwp95515
[60]: https://www.cisco.com/c/en/us/solutions/collateral/data-center-virtualization/application-centric-infrastructure/white-paper-c11-743951.html#Inter
[61]: https://www.cisco.com/c/en/us/solutions/collateral/data-center-virtualization/application-centric-infrastructure/white-paper-c11-743951.html#EnablePolicyCompression
[62]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwp99433
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"moCount": {
"attributes": {
"childAction": "",
"count": "10",
"dn": "",
"status": ""
}
}
}
]
12 changes: 12 additions & 0 deletions tests/checks/pending_contract_check/fvPndgCtrct_count_zero.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"moCount": {
"attributes": {
"childAction": "",
"count": "0",
"dn": "",
"status": ""
}
}
}
]
57 changes: 57 additions & 0 deletions tests/checks/pending_contract_check/test_pending_contract_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
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 = "pending_contract_check"

# icurl queries
pending_contract_api = 'fvPndgCtrct.json'
pending_contract_api += '?rsp-subtree-include=count'


@pytest.mark.parametrize(
"icurl_outputs, tversion, expected_result",
[
# NO TVERSION PROVIDED - MANUAL CHECK
(
{pending_contract_api: read_data(dir, "fvPndgCtrct_count_zero.json")},
None,
script.MANUAL,
),
# TVERSION > 6.1(3g) and no pending contracts - NA
(
{pending_contract_api: read_data(dir, "fvPndgCtrct_count_zero.json")},
"6.1(5a)",
script.NA,
),
# TVERSION > 6.1(3g) and pending contracts exist - NA
(
{pending_contract_api: read_data(dir, "fvPndgCtrct_count_not_zero.json")},
"6.1(5a)",
script.NA,
),
# TVERSION < 6.1(3g) and no pending contracts - PASS
(
{pending_contract_api: read_data(dir, "fvPndgCtrct_count_zero.json")},
"5.2(1a)",
script.PASS,
),
# TVERSION < 6.1(3g) and pending contracts exist - FAIL_O
(
{pending_contract_api: read_data(dir, "fvPndgCtrct_count_not_zero.json")},
"5.2(1a)",
script.FAIL_O,
),

],
)
def test_logic(run_check, mock_icurl, icurl_outputs, tversion, expected_result):
result = run_check(tversion=script.AciVersion(tversion) if tversion else None)
assert result.result == expected_result