diff --git a/plugins/module_utils/network/dcnm/dcnm_vpc_pair_utils.py b/plugins/module_utils/network/dcnm/dcnm_vpc_pair_utils.py index f3f243901..06d509054 100644 --- a/plugins/module_utils/network/dcnm/dcnm_vpc_pair_utils.py +++ b/plugins/module_utils/network/dcnm/dcnm_vpc_pair_utils.py @@ -22,6 +22,7 @@ "VPC_PAIR_DELETE_PATH": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/vpcpair?serialNumber={}", "VPC_PAIR_DEPLOY_PATH": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{}/config-deploy/{}?forceShowRun=false", "VPC_PAIR_CFG_SAVE_PATH": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{}/config-save", + "VPC_PEER_LINK_GET_PATH": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/vpcpair/recommendation?serialNumber={}&useVirtualPeerlink=true", "FABRIC_ACCESS_MODE": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{}/accessmode", }, } @@ -209,6 +210,22 @@ def dcnm_vpc_pair_utils_get_vpc_pair_info_from_dcnm(self, swid): else: return [] + # Get useVirtualPeerlink information + path = self.paths["VPC_PEER_LINK_GET_PATH"] + path = path.format(peerOneId) + + resp = dcnm_send(self.module, "GET", path) + + if ( + resp + and (resp["RETURN_CODE"] == 200) + and (resp["MESSAGE"] == "OK") + and resp["DATA"] + ): + useVirtualPeerlink = resp["DATA"][0].get("useVirtualPeerlink", None) + else: + return [] + # Get the Profile information now and combine both the first response data and the current one to # form the 'have' object. There is no direct call to get this combined information. path = self.paths["VPC_PAIR_GET_POLICY_PATH"] @@ -226,6 +243,7 @@ def dcnm_vpc_pair_utils_get_vpc_pair_info_from_dcnm(self, swid): resp["DATA"]["peerTwoId"] = peerTwoId resp["DATA"]["peerOneDbId"] = peerOneDbId resp["DATA"]["peerTwoDbId"] = peerTwoDbId + resp["DATA"]["useVirtualPeerlink"] = useVirtualPeerlink # Some of the fields in 'have' may be different than what is sent in CREATE/UPDATE/DELETE payloads to DCNM. Update these # fields,if any, so that all keys are consistent between 'want' and 'have'. This will be necessary for compare function to @@ -634,6 +652,9 @@ def dcnm_vpc_pair_utils_process_modify_payloads(self): path = self.paths["VPC_PAIR_UPDATE_PATH"] json_payload = json.dumps(elem) + # Sample json_payload + # '{"useVirtualPeerlink":true,"peerOneId":"FDO24020JMB","peerTwoId":"FDO24020JMT"}' + resp = dcnm_send(self.module, "PUT", path, json_payload) if resp != []: diff --git a/plugins/modules/dcnm_vpc_pair.py b/plugins/modules/dcnm_vpc_pair.py index 4376a0937..0130db341 100644 --- a/plugins/modules/dcnm_vpc_pair.py +++ b/plugins/modules/dcnm_vpc_pair.py @@ -909,7 +909,7 @@ def dcnm_vpc_pair_validate_input(self, cfg): "peerOneId": {"required": "True", "type": "ipv4"}, "peerTwoId": {"required": "True", "type": "ipv4"}, "templateName": {"type": "str"}, - "useVirtualPeerLink": {"type": "bool"}, + "useVirtualPeerlink": {"type": "bool"}, "profile": {"type": "dict"}, } diff --git a/tests/unit/modules/dcnm/fixtures/dcnm_vpc_pair/dcnm_vpc_pair_response.json b/tests/unit/modules/dcnm/fixtures/dcnm_vpc_pair/dcnm_vpc_pair_response.json index 48a8de170..dfeeb9d20 100644 --- a/tests/unit/modules/dcnm/fixtures/dcnm_vpc_pair/dcnm_vpc_pair_response.json +++ b/tests/unit/modules/dcnm/fixtures/dcnm_vpc_pair/dcnm_vpc_pair_response.json @@ -1193,6 +1193,32 @@ } }, + "vpc_pair_info_virtual_peer_link_resp": + { + "DATA": [{ + "blockSelection": "False", + "currentPeer": "True", + "ethSwitchId": 178800, + "fabricName": "None", + "ipAddress": "172.31.217.103", + "lanId": 0, + "logicalName": "93180YC-FX3S-L1-S1", + "nxosVersion": "10.4(3)", + "platformType": "None", + "recommendationReason": "Switches have same role and support Virtual Fabric Peering", + "recommended": "True", + "serialNumber": "FDO24020JMT", + "useVirtualPeerlink": "False", + "uuid": "None", + "vdcId": 0, + "vdcName": "None" + }], + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://10.78.210.227:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/vpcpair/recommendation?serialNumber=FDO24020JMB&useVirtualPeerlink=true", + "RETURN_CODE": 200 + }, + "vpc_pair_policy_resp_84": { "RETURN_CODE": 200, diff --git a/tests/unit/modules/dcnm/test_dcnm_vpc_pair.py b/tests/unit/modules/dcnm/test_dcnm_vpc_pair.py index 12796cfaa..ddb8dd6c7 100644 --- a/tests/unit/modules/dcnm/test_dcnm_vpc_pair.py +++ b/tests/unit/modules/dcnm/test_dcnm_vpc_pair.py @@ -185,8 +185,10 @@ def test_dcnm_vpc_pair_00003( if tc_id < 7: dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_00003")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_00003")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_00003")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_00003")) ) @@ -250,22 +252,28 @@ def test_dcnm_vpc_pair_00004( resp = load_data("dcnm_vpc_pair_response") dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_1")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_1")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_1")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_1")) ) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_2")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_2")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_2")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_2")) ) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_3")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_3")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_3")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_3")) ) @@ -341,12 +349,15 @@ def test_dcnm_vpc_pair_00005( if tc_id < 3: dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_1")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_1")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_2")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_2")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_3")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_3")) elif tc_id == 3: dcnm_send_side_effect.append([]) @@ -356,23 +367,29 @@ def test_dcnm_vpc_pair_00005( vpc_pair.vpc_pair_info[0]["peerOneId"] = "10.122.84.190" dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_1")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_1")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_2")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_2")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_3")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_3")) elif tc_id == 5: vpc_pair.vpc_pair_info[0]["peerTwoId"] = "10.122.84.190" dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_1")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_1")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_2")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_2")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_3")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_3")) update_delete_payloads_side_effect.append( @@ -722,14 +739,18 @@ def test_dcnm_vpc_pair_00010( resp = load_data("dcnm_vpc_pair_response") dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_1")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_1")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_1")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_1")) ) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_2")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_2")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_3")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_3")) mock_dcnm_send = Mock(side_effect=dcnm_send_side_effect) @@ -778,6 +799,7 @@ def test_dcnm_vpc_pair_00010_2( resp = load_data("dcnm_vpc_pair_response") dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_1")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_1")) mock_dcnm_send = Mock(side_effect=dcnm_send_side_effect) @@ -823,6 +845,7 @@ def test_dcnm_vpc_pair_00010_3( resp = load_data("dcnm_vpc_pair_response") dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_1")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_1")) mock_dcnm_send = Mock(side_effect=dcnm_send_side_effect) @@ -1912,10 +1935,13 @@ def test_dcnm_vpc_pair_merged_existing(self): # dcnm_send() invoked from module_utils/dcnm_vpc_pair_utils.py dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_84")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_84")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_85")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_85")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_86")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_86")) dcnm_send_side_effect.append(resp.get("vpc_pair_sync_status_in_sync")) dcnm_send_side_effect.append(resp.get("vpc_pair_sync_status_in_sync")) @@ -2042,10 +2068,13 @@ def test_dcnm_vpc_pair_delete_existing(self): # dcnm_send() invoked from module_utils/dcnm_vpc_pair_utils.py dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_84")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_84")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_85")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_85")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_86")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_86")) dcnm_send_side_effect.append(resp.get("vpc_pair_delete_succ_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_delete_succ_resp")) @@ -2260,17 +2289,21 @@ def test_dcnm_vpc_pair_override_existing_cfg(self): # dcnm_send() invoked from module_utils/dcnm_vpc_pair_utils.py dcnm_send_side_effect.append(resp.get("vpc_pair_null_have")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_85")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_85")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_86")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_86")) dcnm_send_side_effect.append(resp.get("vpc_pair_null_have")) dcnm_send_side_effect.append(resp.get("vpc_pair_null_have")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_85")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_85")) ) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_86")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_86")) ) @@ -2389,21 +2422,27 @@ def test_dcnm_vpc_pair_override_existing_no_new_cfg(self): # dcnm_send() invoked from module_utils/dcnm_vpc_pair_utils.py dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_84")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_84")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_85")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_85")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_86")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_86")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_84")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_84")) ) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_85")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_85")) ) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_86")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_86")) ) @@ -2507,21 +2546,27 @@ def test_dcnm_vpc_pair_query(self): # dcnm_send() invoked from module_utils/dcnm_vpc_pair_utils.py dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_84")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_84")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_85")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_85")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_86")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append(resp.get("vpc_pair_policy_resp_86")) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_84")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_84")) ) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_85")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_85")) ) dcnm_send_side_effect.append(resp.get("vpc_pair_info_resp_86")) + dcnm_send_side_effect.append(resp.get("vpc_pair_info_virtual_peer_link_resp")) dcnm_send_side_effect.append( copy.deepcopy(resp.get("vpc_pair_policy_resp_86")) )