diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 1cb18e5..edc9c86 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -5300,6 +5300,39 @@ 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='Host Interface Policy policy Set') +def host_interface_policy_set_speed_check( tversion, **kwargs): + result = PASS + headers = ["Host Interface Policy", "Set Speed", "Policy Groups associated"] + data = [] + recommended_action = 'Change the speed to "inherit" to avoid issues with interfaces upon stateless reboot' + doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#host-interface-policy-set-to-auto' + if not tversion: + return Result(result=MANUAL, msg=TVER_MISSING) + + policy_group_regex = r'uni/infra/funcprof/accportgrp-(?P.+)' + host_interface_policy_api = 'fabricHIfPol.json' + host_interface_policy_api += '?query-target-filter=and(eq(fabricHIfPol.speed,"auto"))' + host_interface_policy_api += '&rsp-subtree=children&rsp-subtree-class=fabricRtHIfPol' + host_interface_policies = icurl('class', host_interface_policy_api) + if host_interface_policies: + for host_interface_policy in host_interface_policies: + if "children" in host_interface_policy["fabricHIfPol"]: + for policy_group in host_interface_policy["fabricHIfPol"]["children"]: + pg_match = re.match(policy_group_regex, + policy_group["fabricRtHIfPol"]["attributes"]["tDn"]) + if pg_match: + policy_group_name = pg_match.group("policyGroup") + else: + policy_group_name = "N/A" + fabricHIfPol = host_interface_policy["fabricHIfPol"]["attributes"]["dn"] + speed = host_interface_policy["fabricHIfPol"]["attributes"]["speed"] + data.append([fabricHIfPol, speed, policy_group_name]) + 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): @@ -5428,6 +5461,7 @@ def get_checks(api_only, debug_function): aes_encryption_check, service_bd_forceful_routing_check, ave_eol_check, + host_interface_policy_set_speed_check, # Bugs ep_announce_check, @@ -5455,7 +5489,6 @@ def get_checks(api_only, debug_function): standby_sup_sync_check, stale_pcons_ra_mo_check, isis_database_byte_check, - ] conn_checks = [ # General diff --git a/docs/docs/validations.md b/docs/docs/validations.md index e46a881..f20bf81 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -131,6 +131,7 @@ Items | Faults | This Script [Global AES Encryption][c21] | :white_check_mark: | :white_check_mark: 6.1(2) | :no_entry_sign: [Service Graph BD Forceful Routing][c22] | :white_check_mark: | :no_entry_sign: | :no_entry_sign: [AVE End-of-life][c23] | :white_check_mark: | :no_entry_sign: | :no_entry_sign: +[Host interface policy set to auto][c24] | :white_check_mark: | :no_entry_sign: | :no_entry_sign: [c1]: #vpc-paired-leaf-switches @@ -156,6 +157,7 @@ Items | Faults | This Script [c21]: #global-aes-encryption [c22]: #service-graph-bd-forceful-routing [c23]: #ave-end-of-life +[c24]: #host-interface-policy-set-to-auto ### Defect Condition Checks @@ -2222,6 +2224,13 @@ As outlined in the [End-of-Sale and End-of-Life Announcement for Cisco Applicati If planning an upgrade to 6.0+, review the [Cisco ACI Virtual Edge Migration Guide][56] and complete a domain migration prior to performing the upgrade. +### Host interface policy set to auto +As detailed in the [Cisco Apic Basic Configuration guide][59] a Link level Policy is recommended to have the speed set to "inherit". +With this value, Cisco Apic determines the speed based on the transceiver inserted. + +In case the link speed is set to "auto" , interfaces may not come up after an upgrade (stateless reboot). +Changing the speed to "inherit" resolves this situation, which is also a best practice. + ## Defect Check Details ### EP Announce Compatibility @@ -2648,3 +2657,5 @@ 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://www.cisco.com/c/en/us/td/docs/dcn/aci/apic/5x/basic-configuration/cisco-apic-basic-configuration-guide-52x/m_provisioning.html#Cisco_Task_in_List_GUI.dita_45856d2e-8ddd-41bd-93f7-91207aea2061 + diff --git a/tests/host_interface_policy_set_speed_check/fabricHIfPol-pos.json b/tests/host_interface_policy_set_speed_check/fabricHIfPol-pos.json new file mode 100644 index 0000000..c63f074 --- /dev/null +++ b/tests/host_interface_policy_set_speed_check/fabricHIfPol-pos.json @@ -0,0 +1,103 @@ +[ + { + "fabricHIfPol": { + "attributes": { + "annotation": "orchestrator:msc", + "autoNeg": "on", + "childAction": "", + "creator": "USER", + "descr": "", + "dfeDelayMs": "0", + "dn": "uni/infra/hintfpol-fernandh_interface", + "emiRetrain": "disable", + "extMngdBy": "", + "fecMode": "inherit", + "lcOwn": "local", + "linkDebounce": "100", + "modTs": "2025-05-07T23:54:47.082+00:00", + "monPolDn": "uni/fabric/monfab-default", + "name": "fernandh_interface", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "", + "portPhyMediaType": "auto", + "speed": "auto", + "status": "", + "uid": "0", + "userdom": ":all:" + }, + "children": [ + { + "fabricRtHIfPol": { + "attributes": { + "childAction": "", + "lcOwn": "local", + "modTs": "2025-05-07T23:54:47.082+00:00", + "rn": "rtinfraHIfPol-[uni/infra/funcprof/accportgrp-fernandh_interface]", + "status": "", + "tCl": "infraAccPortGrp", + "tDn": "uni/infra/funcprof/accportgrp-fernandh_interface" + } + } + } + ] + } + }, + { + "fabricHIfPol": { + "attributes": { + "annotation": "", + "autoNeg": "on", + "childAction": "", + "creator": "USER", + "descr": "", + "dfeDelayMs": "0", + "dn": "uni/infra/hintfpol-AUTO", + "emiRetrain": "disable", + "extMngdBy": "", + "fecMode": "inherit", + "lcOwn": "local", + "linkDebounce": "100", + "modTs": "2025-06-03T23:21:03.594+00:00", + "monPolDn": "uni/fabric/monfab-default", + "name": "AUTO", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "", + "portPhyMediaType": "auto", + "speed": "auto", + "status": "", + "uid": "15374", + "userdom": ":all:" + }, + "children": [ + { + "fabricRtHIfPol": { + "attributes": { + "childAction": "", + "lcOwn": "local", + "modTs": "2025-06-03T23:21:07.485+00:00", + "rn": "rtinfraHIfPol-[uni/infra/funcprof/accportgrp-av_accessB]", + "status": "", + "tCl": "infraAccPortGrp", + "tDn": "uni/infra/funcprof/accportgrp-av_accessB" + } + } + }, + { + "fabricRtHIfPol": { + "attributes": { + "childAction": "", + "lcOwn": "local", + "modTs": "2025-06-05T04:53:53.112+00:00", + "rn": "rtinfraHIfPol-[uni/infra/funcprof/accportgrp-av-access]", + "status": "", + "tCl": "infraAccPortGrp", + "tDn": "uni/infra/funcprof/accportgrp-av-access" + } + } + } + ] + } + } +] \ No newline at end of file diff --git a/tests/host_interface_policy_set_speed_check/test_host_interface_policy_set_speed_check.py b/tests/host_interface_policy_set_speed_check/test_host_interface_policy_set_speed_check.py new file mode 100644 index 0000000..42bf4c4 --- /dev/null +++ b/tests/host_interface_policy_set_speed_check/test_host_interface_policy_set_speed_check.py @@ -0,0 +1,48 @@ +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 +host_interface_policy_api = 'fabricHIfPol.json' +host_interface_policy_api += '?query-target-filter=and(eq(fabricHIfPol.speed,"auto"))' +host_interface_policy_api += '&rsp-subtree=children&rsp-subtree-class=fabricRtHIfPol' + +@pytest.mark.parametrize( "icurl_outputs, tversion, expected_result", + [ + # MANUAL Cases + # No tversion given + ( + {host_interface_policy_api: read_data(dir, "fabricHIfPol-pos.json")}, + None, + script.MANUAL, + ), + # FAIL_O Cases + # fabricHIfPol with 'auto' speed found + ( + {host_interface_policy_api: read_data(dir, "fabricHIfPol-pos.json")}, + "6.0(9d)", + script.FAIL_O, + ), + # PASS Cases + # No fabricHIfPol with 'auto' speed found + ( + {host_interface_policy_api: []}, + "6.0(1g)", + script.PASS, + ), + ], +) +def test_logic(mock_icurl, tversion, expected_result): + tversion = script.AciVersion(tversion) if tversion else None + result = script.host_interface_policy_set_speed_check( + 1, 1, tversion + ) + assert result == expected_result \ No newline at end of file