diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 78110c13..a3ca8539 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -3655,13 +3655,15 @@ def vpc_paired_switches_check(vpc_node_ids, fabric_nodes, **kwargs): @check_wrapper(check_title="APIC CIMC Compatibility") -def cimc_compatibilty_check(tversion, **kwargs): +def cimc_compatibilty_check(tversion, cversion, **kwargs): result = FAIL_UF headers = ["Node ID", "Model", "Current CIMC version", "Catalog Recommended CIMC Version", "Warning"] data = [] recommended_action = 'Check Release note of APIC Model/version for latest recommendations.' doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#compatibility-cimc-version' + m4l4_model_affected_version_found = False + apic_obj = icurl('class', 'eqptCh.json?query-target-filter=wcard(eqptCh.descr,"APIC")') if apic_obj and tversion: try: @@ -3670,6 +3672,21 @@ def cimc_compatibilty_check(tversion, **kwargs): apic_model = eqptCh['eqptCh']['attributes']['descr'] model = "apic" + apic_model.split('-')[2].lower() current_cimc = eqptCh['eqptCh']['attributes']['cimcVersion'] + + #defect CSCwo74485 cimc compatibility check for M4/L4 model. + if model in ("apicm4", "apicl4") and cversion: + is_affected_apic_version = ( + (cversion.major1 == "5" and cversion.major2 == "3") + or (cversion.major1 == "6" and cversion.major2 == "0" and cversion.older_than("6.0(9e)")) + or (cversion.major1 == "6" and cversion.major2 == "1" and cversion.older_than("6.1(4h)")) + ) + if is_affected_apic_version: + if not is_firstver_gt_secondver(current_cimc, "4.3(5)"): + m4l4_model_affected_version_found = True + nodeid = eqptCh['eqptCh']['attributes']['dn'].split('/')[2] + data.append([nodeid, apic_model, current_cimc, "-", "-"]) + continue + compat_lookup_dn = "uni/fabric/compcat-default/ctlrfw-apic-" + tversion.simple_version + \ "/rssuppHw-[uni/fabric/compcat-default/ctlrhw-" + model + "].json" compatMo = icurl('mo', compat_lookup_dn) @@ -3688,6 +3705,9 @@ def cimc_compatibilty_check(tversion, **kwargs): if not data: result = PASS + if m4l4_model_affected_version_found: + recommended_action = 'Intentionally Upgrade your APICs to a fixed target version [6.0(9e)+ or (6.1(4h)+] BEFORE upgrading CIMC to avoid hitting CSCwo74485.' + except KeyError: return Result(result=MANUAL, msg="eqptCh does not have cimcVersion parameter on this version", headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) else: diff --git a/docs/docs/validations.md b/docs/docs/validations.md index bd0de6d7..76e9c140 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -257,6 +257,8 @@ The script checks the minimum recommended CIMC version for the given APIC model As the `compatRsSuppHw` object recommendation is strictly tied to the target software image, it is possible that the [Release Note Documentation][4] for your model/target version has a different recommendation than what the software recommends. Always check the release note of your Target version and APIC model to ensure you are getting the latest recommendations. +Due to the defect CSCwo74485, APIC-SERVER-M4/L4 systems will fail to boot correctly after upgrading CIMC firmware to version 4.3.5 or later while on Non-fixed APIC releases 5.3.x/6.0.9d/6.1(3g) and below. Upgrade the APIC software first, then proceed with the CIMC upgrade for the releases 6.0.9e/ 6.1.4h and above, will avoid this issue. Follow the software advisory for this defect [CSCwo74485][73]. + !!! note Older versions of CIMC may required multi-step CIMC upgrades to get to the identified target version. Refer to the [Cisco UCS Rack Server Upgrade Matrix][22] for the latest documentation on which steps are required and support given your current and target CIMC versions. @@ -2890,3 +2892,4 @@ This bug [CSCwt78235][71] validates `F0467` faults where `changeSet` contains 'b [70]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCvo27498 [71]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwt78235 [72]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwt50713 +[73]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwo74485 \ No newline at end of file diff --git a/tests/checks/cimc_compatibilty_check/compatRsSuppHw_605_M4L4.json b/tests/checks/cimc_compatibilty_check/compatRsSuppHw_605_M4L4.json new file mode 100644 index 00000000..a05bdec7 --- /dev/null +++ b/tests/checks/cimc_compatibilty_check/compatRsSuppHw_605_M4L4.json @@ -0,0 +1,18 @@ +[ + { + "compatRsSuppHw": { + "attributes": { + "cimcVersion": "4.0(2g)", + "dn": "uni/fabric/compcat-default/ctlrfw-apic-6.0(5)/rssuppHw-[uni/fabric/compcat-default/ctlrhw-apicl4]" + } + } + }, + { + "compatRsSuppHw": { + "attributes": { + "cimcVersion": "4.0(2g)", + "dn": "uni/fabric/compcat-default/ctlrfw-apic-6.0(5)/rssuppHw-[uni/fabric/compcat-default/ctlrhw-apicm4]" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/cimc_compatibilty_check/compatRsSuppHw_615_M4L4.json b/tests/checks/cimc_compatibilty_check/compatRsSuppHw_615_M4L4.json new file mode 100644 index 00000000..d8c7b772 --- /dev/null +++ b/tests/checks/cimc_compatibilty_check/compatRsSuppHw_615_M4L4.json @@ -0,0 +1,18 @@ +[ + { + "compatRsSuppHw": { + "attributes": { + "cimcVersion": "4.0(2g)", + "dn": "uni/fabric/compcat-default/ctlrfw-apic-6.1(5)/rssuppHw-[uni/fabric/compcat-default/ctlrhw-apicl4]" + } + } + }, + { + "compatRsSuppHw": { + "attributes": { + "cimcVersion": "4.0(2g)", + "dn": "uni/fabric/compcat-default/ctlrfw-apic-6.1(5)/rssuppHw-[uni/fabric/compcat-default/ctlrhw-apicm4]" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/cimc_compatibilty_check/eqptCh_m4l4_mixed_models.json b/tests/checks/cimc_compatibilty_check/eqptCh_m4l4_mixed_models.json new file mode 100644 index 00000000..24345c60 --- /dev/null +++ b/tests/checks/cimc_compatibilty_check/eqptCh_m4l4_mixed_models.json @@ -0,0 +1,55 @@ +[ + + { + "eqptCh": { + "attributes": { + "bootSource": "bootflash", + "cimcVersion": "4.0(2f)", + "configRole": "unspecified", + "descr": "APIC-SERVER-M4", + "dn": "topology/pod-2/node-3/sys/ch", + "hybridMode": "no", + "model": "APIC-SERVER-M4" + } + } + }, + { + "eqptCh": { + "attributes": { + "bootSource": "bootflash", + "cimcVersion": "4.0(2f)", + "configRole": "unspecified", + "descr": "APIC-SERVER-L4", + "dn": "topology/pod-2/node-4/sys/ch", + "hybridMode": "no", + "model": "APIC-SERVER-L4" + } + } + }, + { + "eqptCh": { + "attributes": { + "bootSource": "bootflash", + "cimcVersion": "3.0(4l)", + "configRole": "unspecified", + "descr": "APIC-SERVER-L2", + "dn": "topology/pod-1/node-1/sys/ch", + "hybridMode": "no", + "model": "APIC-SERVER-L2" + } + } + }, + { + "eqptCh": { + "attributes": { + "bootSource": "bootflash", + "cimcVersion": "3.0(4l)", + "configRole": "unspecified", + "descr": "APIC-SERVER-M1", + "dn": "topology/pod-2/node-5/sys/ch", + "hybridMode": "no", + "model": "APIC-SERVER-M1" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/cimc_compatibilty_check/eqptCh_m4l4_model_new_cimc.json b/tests/checks/cimc_compatibilty_check/eqptCh_m4l4_model_new_cimc.json new file mode 100644 index 00000000..708b47e5 --- /dev/null +++ b/tests/checks/cimc_compatibilty_check/eqptCh_m4l4_model_new_cimc.json @@ -0,0 +1,29 @@ +[ + + { + "eqptCh": { + "attributes": { + "bootSource": "bootflash", + "cimcVersion": "4.5(2f)", + "configRole": "unspecified", + "descr": "APIC-SERVER-M4", + "dn": "topology/pod-2/node-3/sys/ch", + "hybridMode": "no", + "model": "APIC-SERVER-M4" + } + } + }, + { + "eqptCh": { + "attributes": { + "bootSource": "bootflash", + "cimcVersion": "4.5(2f)", + "configRole": "unspecified", + "descr": "APIC-SERVER-L4", + "dn": "topology/pod-2/node-4/sys/ch", + "hybridMode": "no", + "model": "APIC-SERVER-L4" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/cimc_compatibilty_check/eqptCh_m4l4_model_old_cimc.json b/tests/checks/cimc_compatibilty_check/eqptCh_m4l4_model_old_cimc.json new file mode 100644 index 00000000..05396766 --- /dev/null +++ b/tests/checks/cimc_compatibilty_check/eqptCh_m4l4_model_old_cimc.json @@ -0,0 +1,29 @@ +[ + + { + "eqptCh": { + "attributes": { + "bootSource": "bootflash", + "cimcVersion": "4.0(2f)", + "configRole": "unspecified", + "descr": "APIC-SERVER-M4", + "dn": "topology/pod-2/node-3/sys/ch", + "hybridMode": "no", + "model": "APIC-SERVER-M4" + } + } + }, + { + "eqptCh": { + "attributes": { + "bootSource": "bootflash", + "cimcVersion": "4.0(2f)", + "configRole": "unspecified", + "descr": "APIC-SERVER-L4", + "dn": "topology/pod-2/node-4/sys/ch", + "hybridMode": "no", + "model": "APIC-SERVER-L4" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/cimc_compatibilty_check/test_cimc_compatibilty_check.py b/tests/checks/cimc_compatibilty_check/test_cimc_compatibilty_check.py index cb587fb3..4db1b7ea 100644 --- a/tests/checks/cimc_compatibilty_check/test_cimc_compatibilty_check.py +++ b/tests/checks/cimc_compatibilty_check/test_cimc_compatibilty_check.py @@ -17,15 +17,59 @@ compatRsSuppHwL2_api = 'uni/fabric/compcat-default/ctlrfw-apic-6.0(5)/rssuppHw-[uni/fabric/compcat-default/ctlrhw-apicl2].json' compatRsSuppHwM1_api = 'uni/fabric/compcat-default/ctlrfw-apic-6.0(5)/rssuppHw-[uni/fabric/compcat-default/ctlrhw-apicm1].json' +compatRsSuppHwL4_605_api = 'uni/fabric/compcat-default/ctlrfw-apic-6.0(5)/rssuppHw-[uni/fabric/compcat-default/ctlrhw-apicl4].json' +compatRsSuppHwM4_605_api = 'uni/fabric/compcat-default/ctlrfw-apic-6.0(5)/rssuppHw-[uni/fabric/compcat-default/ctlrhw-apicm4].json' +compatRsSuppHwL4_api = 'uni/fabric/compcat-default/ctlrfw-apic-6.1(5)/rssuppHw-[uni/fabric/compcat-default/ctlrhw-apicl4].json' +compatRsSuppHwM4_api = 'uni/fabric/compcat-default/ctlrfw-apic-6.1(5)/rssuppHw-[uni/fabric/compcat-default/ctlrhw-apicm4].json' @pytest.mark.parametrize( - "icurl_outputs, tversion, expected_result", + "icurl_outputs, tversion, cversion, expected_result", [ + #m4/l4 model check and targeting affected version and cversion affected and cimc < 4.3.5 + ( + {eqptCh_api: read_data(dir, "eqptCh_m4l4_model_old_cimc.json"), + compatRsSuppHwL4_605_api: read_data(dir, "compatRsSuppHw_605_M4L4.json"), + compatRsSuppHwM4_605_api: read_data(dir, "compatRsSuppHw_605_M4L4.json")}, + "6.0(5h)", + "5.3(1d)", + script.FAIL_UF, + ), + #m4/l4 with other apic server model and check targeting affect version and cversion affected and cimc < 4.3.5 + ( + { + eqptCh_api: read_data(dir, "eqptCh_m4l4_mixed_models.json"), + compatRsSuppHwL4_605_api: read_data(dir, "compatRsSuppHw_605_M4L4.json"), + compatRsSuppHwM4_605_api: read_data(dir, "compatRsSuppHw_605_M4L4.json"), + compatRsSuppHwL2_api: read_data(dir, "compatRsSuppHw_605_L2.json"), + compatRsSuppHwM1_api: read_data(dir, "compatRsSuppHw_605_M1.json")}, + "6.0(5h)", + "5.3(1d)", + script.FAIL_UF, + ), + # current cimc > 3.4.5 (known issue) but APIC current version is not affected + ( + {eqptCh_api: read_data(dir, "eqptCh_m4l4_model_new_cimc.json"), + compatRsSuppHwL4_api: read_data(dir, "compatRsSuppHw_615_M4L4.json"), + compatRsSuppHwM4_api: read_data(dir, "compatRsSuppHw_615_M4L4.json")}, + "6.1(5e)", + "6.1(4h)", + script.PASS, + ), + #version affected and cimc version > 4.3.5 + ( + {eqptCh_api: read_data(dir, "eqptCh_m4l4_model_new_cimc.json"), + compatRsSuppHwL4_605_api: read_data(dir, "compatRsSuppHw_605_M4L4.json"), + compatRsSuppHwM4_605_api: read_data(dir, "compatRsSuppHw_605_M4L4.json")}, + "6.0(5h)", + "5.3(1d)", + script.PASS, + ), ( {eqptCh_api: read_data(dir, "eqptCh_reallyoldver.json"), compatRsSuppHwL2_api: read_data(dir, "compatRsSuppHw_605_L2.json"), compatRsSuppHwM1_api: read_data(dir, "compatRsSuppHw_605_M1.json")}, "6.0(5a)", + None, script.FAIL_UF, ), ( @@ -33,6 +77,7 @@ compatRsSuppHwL2_api: read_data(dir, "compatRsSuppHw_605_L2.json"), compatRsSuppHwM1_api: read_data(dir, "compatRsSuppHw_605_M1.json")}, "6.0(5a)", + None, script.FAIL_UF, ), ( @@ -40,6 +85,7 @@ compatRsSuppHwL2_api: read_data(dir, "compatRsSuppHw_605_L2.json"), compatRsSuppHwM1_api: read_data(dir, "compatRsSuppHw_605_M1.json")}, "6.0(5a)", + None, script.PASS, ), # Seen in QA testing where version + model does not have catalog entry @@ -48,10 +94,11 @@ compatRsSuppHwL2_api: read_data(dir, "compatRsSuppHw_605_L2.json"), compatRsSuppHwM1_api: read_data(dir, "compatRsSuppHw_empty.json")}, "6.0(5a)", + None, script.MANUAL, ), ], ) -def test_logic(run_check, mock_icurl, tversion, expected_result): - result = run_check(tversion=script.AciVersion(tversion)) +def test_logic(run_check, mock_icurl, tversion, cversion, expected_result): + result = run_check(tversion=script.AciVersion(tversion), cversion=script.AciVersion(cversion) if cversion is not None else None) assert result.result == expected_result