diff --git a/plugins/module_utils/fabric/create.py b/plugins/module_utils/fabric/create.py index ee763434b..c6a540dd9 100644 --- a/plugins/module_utils/fabric/create.py +++ b/plugins/module_utils/fabric/create.py @@ -110,6 +110,38 @@ def _set_fabric_create_endpoint(self, payload): self.path = self.ep_fabric_create.path self.verb = self.ep_fabric_create.verb + def _add_ext_fabric_type_to_payload(self, payload: dict) -> dict: + """ + # Summary + + If the payload contains an external fabric type (e.g ISN) + and does not contain the EXT_FABRIC_TYPE key, add this + key with the default value that NDFC GUI uses for displaying + the fabric type. + + # Raises + + None + """ + method_name = inspect.stack()[0][3] + + fabric_type = payload.get("FABRIC_TYPE") + if fabric_type not in self.fabric_types.external_fabric_types: + return payload + if "EXT_FABRIC_TYPE" in payload: + return payload + value = self.fabric_types.fabric_type_to_ext_fabric_type_map.get(fabric_type) + if value is None: + return payload + payload["EXT_FABRIC_TYPE"] = value + + msg = f"{self.class_name}.{method_name}: " + msg += "Added EXT_FABRIC_TYPE to payload. " + msg += f"fabric_type: {fabric_type}, " + msg += f"value: {value}" + self.log.debug(msg) + return payload + def _send_payloads(self): """ - If ``check_mode`` is ``False``, send the payloads @@ -123,6 +155,8 @@ def _send_payloads(self): - This overrides the parent class method. """ for payload in self._payloads_to_commit: + payload = self._add_ext_fabric_type_to_payload(payload) + try: self._set_fabric_create_endpoint(payload) except ValueError as error: diff --git a/plugins/module_utils/fabric/fabric_types.py b/plugins/module_utils/fabric/fabric_types.py index f96dc41ce..cb737b53a 100644 --- a/plugins/module_utils/fabric/fabric_types.py +++ b/plugins/module_utils/fabric/fabric_types.py @@ -88,8 +88,28 @@ def _init_fabric_types(self) -> None: self._fabric_type_to_feature_name_map["VXLAN_EVPN"] = "vxlan" self._fabric_type_to_feature_name_map["VXLAN_EVPN_MSD"] = "vxlan" + # Map fabric type to the value that the controller GUI displays + # in the Fabric Type column at NDFC -> Manage -> Fabrics + # This is needed only for fabrics that use the External_Fabric + # template, e.g. ISN, and will be inserted into the POST request + # payload for external fabrics as (in the case of ISN fabric type): + # "EXT_FABRIC_TYPE": "Multi-Site External Network" + # + # Exposed via property fabric_type_to_ext_fabric_type_map + self._fabric_type_to_ext_fabric_type_map = {} + self._fabric_type_to_ext_fabric_type_map["ISN"] = "Multi-Site External Network" + self._valid_fabric_types = sorted(self._fabric_type_to_template_name_map.keys()) + # self._external_fabric_types is used in conjunction with + # self._fabric_type_to_ext_fabric_type_map. This is used in (at least) + # FabricCreateCommon() to determine if EXT_FABRIC_TYPE key needs to be + # added to a payload. + # + # Exposed via property external_fabric_types + self._external_fabric_types = set() + self._external_fabric_types.add("ISN") + self._mandatory_parameters_all_fabrics = [] self._mandatory_parameters_all_fabrics.append("FABRIC_NAME") self._mandatory_parameters_all_fabrics.append("FABRIC_TYPE") @@ -128,6 +148,19 @@ def _init_properties(self) -> None: self._properties["template_name"] = None self._properties["valid_fabric_types"] = self._valid_fabric_types + @property + def external_fabric_types(self): + """ + # Summary + + set() containing all external fabric types e.g. ISN. + + # Raises + + None + """ + return self._external_fabric_types + @property def fabric_type(self): """ @@ -150,6 +183,19 @@ def fabric_type(self, value): raise ValueError(msg) self._properties["fabric_type"] = value + @property + def fabric_type_to_ext_fabric_type_map(self): + """ + # Summary + + Returns a dictionary, keyed on fabric_type (e.g. "ISN"), + whose value is a string that the NDFC GUI uses to describe the + external fabric type. See the Fabric Type column at + NDFC -> Manage -> Fabrics for an example of how this is used + by the NDFC GUI. + """ + return self._fabric_type_to_ext_fabric_type_map + @property def feature_name(self): """ 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")) )