1# -*- coding: utf-8 -*-
2
3#
4# Dell EMC OpenManage Ansible Modules
5# Version 3.6.0
6# Copyright (C) 2020-2021 Dell Inc. or its subsidiaries. All Rights Reserved.
7
8# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
9#
10
11from __future__ import (absolute_import, division, print_function)
12
13__metaclass__ = type
14
15import pytest
16import json
17from ansible_collections.dellemc.openmanage.plugins.modules import ome_smart_fabric
18from ansible_collections.dellemc.openmanage.tests.unit.plugins.modules.common import FakeAnsibleModule, Constants
19from ansible.module_utils.six.moves.urllib.error import URLError, HTTPError
20from ansible.module_utils.urls import ConnectionError, SSLValidationError
21from io import StringIO
22from ansible.module_utils._text import to_text
23
24CHECK_MODE_CHANGE_FOUND_MSG = "Changes found to be applied."
25CHECK_MODE_CHANGE_NOT_FOUND_MSG = "No Changes found to be applied."
26FABRIC_NOT_FOUND_ERROR_MSG = "The smart fabric '{0}' is not present in the system."
27DOMAIN_SERVICE_TAG_ERROR_MSG = "Unable to retrieve the domain information because the" \
28                               " domain of the provided service tag {0} is not available."
29LEAD_CHASSIS_ERROR_MSG = "System should be a lead chassis if the assigned fabric topology type is {0}."
30SYSTEM_NOT_SUPPORTED_ERROR_MSG = "Fabric management is not supported on the specified system."
31DESIGN_MODEL_ERROR_MSG = "The network type of the {0} must be {1}."
32DEVICE_SERVICE_TAG_TYPE_ERROR_MSG = "The {0} type must be {1}."
33DEVICE_SERVICE_TAG_NOT_FOUND_ERROR_MSG = "Unable to retrieve the device information because the device" \
34                                         " with the provided service tag {0} is not available."
35IDEMPOTENCY_MSG = "Specified fabric details are the same as the existing settings."
36REQUIRED_FIELD = "Options 'fabric_design', 'primary_switch_service_tag' and 'secondary_switch_service_tag'" \
37                 " are required for fabric creation."
38DUPLICATE_TAGS = "The switch details of the primary switch overlaps with the secondary switch details."
39PRIMARY_SWITCH_OVERLAP_MSG = "The primary switch service tag is overlapping with existing secondary switch details."
40SECONDARY_SWITCH_OVERLAP_MSG = "The switch details of the secondary switch overlaps with the existing primary" \
41                               " switch details."
42MODULE_PATH = 'ansible_collections.dellemc.openmanage.plugins.modules.'
43device_details = {
44    "Id": Constants.device_id1,
45    "Type": 4000,
46    "Identifier": "GTCT8T2",
47    "DeviceServiceTag": "GTCT8T2",
48    "ChassisServiceTag": "FPTN6Z2",
49    "Model": "MX9116n Fabric Engine",
50    "PowerState": 17,
51    "ManagedState": 3000,
52    "Status": 1000,
53    "SystemId": 2031,
54    "DeviceName": "IOM-A2",
55    "SlotConfiguration": {
56        "ChassisName": "MX-FPTN6Z2",
57        "SlotId": "13313",
58        "DeviceType": "4000",
59        "ChassisId": "13294",
60        "SlotNumber": "2",
61        "SledBlockPowerOn": "null",
62        "SlotName": "IOM-A2",
63        "ChassisServiceTag": "FPTN6Z2",
64        "SlotType": "4000"
65    },
66    "DeviceManagement": [
67        {
68            "ManagementId": 76383,
69            "NetworkAddress": Constants.hostname1,
70            "MacAddress": "00:00:00:00:00",
71            "ManagementType": 2,
72            "InstrumentationName": "MX9116n Fabric Engine",
73            "DnsName": "",
74            "ManagementProfile": [
75                {
76                    "ManagementProfileId": 76383,
77                    "ProfileId": "FX7_BASE",
78                    "ManagementId": 76383,
79                    "AgentName": "",
80                    "Version": "",
81                    "ManagementURL": "",
82                    "HasCreds": 0,
83                    "Status": 1000,
84                    "StatusDateTime": "2020-05-07 15:00:14.718"
85                }
86            ]
87        }
88    ]
89}
90all_fabric_details = [
91    {
92        "Id": "1312cceb-c3dd-4348-95c1-d8541a17d776",
93        "Name": "Fabric_1",
94        "Description": "create new fabric1",
95        "OverrideLLDPConfiguration": "NA",
96        "ScaleVLANProfile": "NA",
97        "FabricDesignMapping": [
98            {
99                "DesignNode": "Switch-A",
100                "PhysicalNode": "2HB7NX2"
101            },
102            {
103                "DesignNode": "Switch-B",
104                "PhysicalNode": "2HBFNX2"
105            }
106        ],
107        "FabricDesign": {
108            "@odata.id": "/api/NetworkService/Fabrics('1312cceb-c3dd-4348-95c1-d8541a17d776')/FabricDesign"
109        }
110    },
111    {
112        "Id": "1312cceb-c3dd-4348-95c1-123456",
113        "Name": "Fabric_1_2",
114        "Description": "create new fabric2",
115        "OverrideLLDPConfiguration": "Enabled",
116        "ScaleVLANProfile": "NA",
117        "FabricDesignMapping": [
118            {
119                "DesignNode": "Switch-A",
120                "PhysicalNode": Constants.service_tag1
121            },
122            {
123                "DesignNode": "Switch-B",
124                "PhysicalNode": Constants.service_tag2
125            }
126        ],
127        "FabricDesign": {
128            "@odata.id": "/api/NetworkService/Fabrics('1312cceb-c3dd-4348-95c1-123456')/FabricDesign"
129        }
130    }
131]
132
133
134@pytest.fixture
135def ome_connection_mock_for_smart_fabric(mocker, ome_response_mock):
136    connection_class_mock = mocker.patch(MODULE_PATH + 'ome_smart_fabric.RestOME')
137    ome_connection_mock_obj = connection_class_mock.return_value.__enter__.return_value
138    ome_connection_mock_obj.invoke_request.return_value = ome_response_mock
139    return ome_connection_mock_obj
140
141
142class TestOmeSmartFabric(FakeAnsibleModule):
143    module = ome_smart_fabric
144
145    @pytest.mark.parametrize("exc_type",
146                             [URLError, HTTPError, SSLValidationError, ConnectionError, TypeError, ValueError])
147    def test_main_ome_smart_fabric_exception_handling_case(self, exc_type, ome_default_args,
148                                                           ome_connection_mock_for_smart_fabric,
149                                                           ome_response_mock, mocker):
150        ome_default_args.update({"name": "name", "new_name": "new_name"})
151        ome_response_mock.status_code = 400
152        ome_response_mock.success = False
153        json_str = to_text(json.dumps({"data": "out"}))
154        if exc_type == URLError:
155            mocker.patch(MODULE_PATH + 'ome_smart_fabric.fabric_actions',
156                         side_effect=exc_type("url open error"))
157            result = self._run_module(ome_default_args)
158            assert result["unreachable"] is True
159        elif exc_type not in [HTTPError, SSLValidationError]:
160            mocker.patch(MODULE_PATH + 'ome_smart_fabric.fabric_actions',
161                         side_effect=exc_type("exception message"))
162            result = self._run_module_with_fail_json(ome_default_args)
163            assert result['failed'] is True
164        else:
165            for status_code, msg in {501: SYSTEM_NOT_SUPPORTED_ERROR_MSG, 400: 'http error message'}.items():
166                mocker.patch(MODULE_PATH + 'ome_smart_fabric.fabric_actions',
167                             side_effect=exc_type('http://testhost.com', status_code, msg,
168                                                  {"accept-type": "application/json"}, StringIO(json_str)))
169                result = self._run_module_with_fail_json(ome_default_args)
170                assert result['failed'] is True
171                assert msg in result['msg']
172        assert 'msg' in result
173
174    def test_get_msm_device_details_success_case(self, ome_connection_mock_for_smart_fabric, ome_default_args, mocker):
175        """
176        success case: when provided design type and role type natches return the service tag and msm details
177        """
178        ome_default_args.update({"fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_different_chassis"})
179        f_module = self.get_module_mock(params=ome_default_args)
180        resp_data = {
181            "Id": Constants.device_id1,
182            "value": [
183                {
184                    "Id": 10086,
185                    "DeviceId": 10061,
186                    "PublicAddress": [
187                        ome_default_args["hostname"],
188                        "1000:mock_val"
189                    ],
190                    "Identifier": Constants.service_tag1,
191                    "DomainRoleTypeValue": "LEAD",
192                    "Version": "1.20.00",
193                },
194                {
195                    "Id": 13341,
196                    "DeviceId": 13294,
197                    "PublicAddress": [
198                        Constants.hostname2,
199                        "1000:mocked_val"
200                    ],
201                    "Identifier": Constants.service_tag2,
202                    "DomainTypeValue": "MSM",
203                    "DomainRoleTypeValue": "MEMBER",
204                    "Version": "1.20.00",
205                }
206            ]
207        }
208        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = resp_data
209        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_service_tag_with_fqdn',
210                     return_value=None)
211        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_ip_from_host',
212                     return_value=ome_default_args["hostname"])
213        service_tag, msm_version = self.module.get_msm_device_details(ome_connection_mock_for_smart_fabric, f_module)
214        assert service_tag == Constants.service_tag1
215        assert msm_version == "1.20.00"
216
217    def test_get_msm_device_details_fqdn_success_case1(self, ome_connection_mock_for_smart_fabric, ome_default_args,
218                                                       mocker):
219        """
220        when hostname provided is fqdn and
221        success case: when provided design type and role type matches return the service tag and msm details
222        """
223        ome_default_args.update(
224            {"hostname": "XX-XXXX.yyy.lab", "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_different_chassis"})
225        f_module = self.get_module_mock(params=ome_default_args)
226        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_ip_from_host',
227                     return_value=ome_default_args["hostname"])
228        resp_data = {
229            "Id": Constants.device_id1,
230            "value": [
231                {
232                    "Id": 10086,
233                    "DeviceId": 10061,
234                    "PublicAddress": [
235                        ome_default_args["hostname"],
236                        "1000:mock_val"
237                    ],
238                    "Identifier": Constants.service_tag1,
239                    "DomainRoleTypeValue": "LEAD",
240                    "Version": "1.20.00",
241                },
242                {
243                    "Id": 13341,
244                    "DeviceId": 13294,
245                    "PublicAddress": [
246                        Constants.hostname2,
247                        "1000:mocked_val"
248                    ],
249                    "Identifier": Constants.service_tag2,
250                    "DomainTypeValue": "MSM",
251                    "DomainRoleTypeValue": "MEMBER",
252                    "Version": "1.20.00",
253                }
254            ]
255        }
256        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = resp_data
257        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_service_tag_with_fqdn',
258                     return_value="FKMLRZ2")
259        service_tag, msm_version = self.module.get_msm_device_details(ome_connection_mock_for_smart_fabric, f_module)
260        assert service_tag == Constants.service_tag1
261        assert msm_version == "1.20.00"
262
263    def test_get_msm_device_details_fqdn_success_case2(self, ome_connection_mock_for_smart_fabric, ome_default_args,
264                                                       mocker):
265        """
266        when hostname provided is fqdn and
267        success case: when provided design type is same and fqdn is not of lead type
268        """
269        ome_default_args.update(
270            {"hostname": "XX-XXXX.yyy.lab", "fabric_design": "2xMX5108n_Ethernet_Switches_in_same_chassis"})
271        f_module = self.get_module_mock(params=ome_default_args)
272        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_ip_from_host',
273                     return_value=ome_default_args["hostname"])
274        resp_data = {
275            "Id": Constants.device_id1,
276            "value": [
277                {
278                    "Id": 10086,
279                    "DeviceId": 10061,
280                    "PublicAddress": [
281                        Constants.hostname1,
282                        "1000:mock_ipv6"
283                    ],
284                    "Identifier": Constants.service_tag1,
285                    "DomainRoleTypeValue": "LEAD",
286                    "Version": "1.20.00",
287                },
288                {
289                    "Id": 13341,
290                    "DeviceId": 13294,
291                    "PublicAddress": [
292                        Constants.hostname2,
293                        "1001:mocked_ippv6"
294                    ],
295                    "Identifier": Constants.service_tag2,
296                    "DomainTypeValue": "MSM",
297                    "DomainRoleTypeValue": "MEMBER",
298                    "Version": "1.20.10",
299                }
300            ]
301        }
302        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = resp_data
303        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_service_tag_with_fqdn',
304                     return_value=Constants.service_tag2)
305        service_tag, msm_version = self.module.get_msm_device_details(ome_connection_mock_for_smart_fabric, f_module)
306        assert service_tag == Constants.service_tag2
307        assert msm_version == "1.20.10"
308
309    def test_get_msm_device_details_fqdn_failure_case1(self, ome_connection_mock_for_smart_fabric, ome_default_args,
310                                                       mocker):
311        """
312        when hostname provided is fqdn and
313        failure case: when provided design type is 2xMX9116n_Fabric_Switching_Engines_in_different_chassis
314         but fqdn is not of lead type
315        """
316        ome_default_args.update(
317            {"hostname": "XX-XXXX.yyy.lab", "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_different_chassis"})
318        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_ip_from_host',
319                     return_value=ome_default_args["hostname"])
320        f_module = self.get_module_mock(params=ome_default_args)
321        resp_data = {
322            "Id": Constants.device_id1,
323            "value": [
324                {
325                    "Id": 10086,
326                    "DeviceId": 10061,
327                    "PublicAddress": [
328                        Constants.hostname1,
329                        "1000:mock_val"
330                    ],
331                    "Identifier": Constants.service_tag1,
332                    "DomainRoleTypeValue": "LEAD",
333                    "Version": "1.20.00",
334                },
335                {
336                    "Id": 13341,
337                    "DeviceId": 13294,
338                    "PublicAddress": [
339                        Constants.hostname2,
340                        "1000:mocked_val"
341                    ],
342                    "Identifier": Constants.service_tag2,
343                    "DomainTypeValue": "MSM",
344                    "DomainRoleTypeValue": "MEMBER",
345                    "Version": "1.20.00",
346                }
347            ]
348        }
349        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = resp_data
350        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_service_tag_with_fqdn',
351                     return_value=Constants.service_tag2)
352        with pytest.raises(Exception, match=LEAD_CHASSIS_ERROR_MSG.format(ome_default_args["fabric_design"])) as ex:
353            self.module.get_msm_device_details(ome_connection_mock_for_smart_fabric, f_module)
354
355    def test_get_msm_device_details_fqdn_failure_case2(self, ome_connection_mock_for_smart_fabric, ome_default_args,
356                                                       mocker):
357        """
358        when hostname provided is fqdn and
359        failure case: when provided fqdn not available in domain list should throw an error
360        """
361        ome_default_args.update(
362            {"hostname": "XX-XXXX.yyy.lab", "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_different_chassis"})
363        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_ip_from_host',
364                     return_value=ome_default_args["hostname"])
365        f_module = self.get_module_mock(params=ome_default_args)
366        resp_data = {
367            "value": [
368            ]
369        }
370        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = resp_data
371        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_service_tag_with_fqdn',
372                     return_value="FPTN6Z2")
373        with pytest.raises(Exception, match=SYSTEM_NOT_SUPPORTED_ERROR_MSG):
374            self.module.get_msm_device_details(ome_connection_mock_for_smart_fabric, f_module)
375
376    def test_get_msm_device_details_failure_case_01(self, ome_connection_mock_for_smart_fabric, ome_default_args,
377                                                    mocker):
378        """
379        raise exception if design type is 2xMX9116n_Fabric_Switching_Engines_in_different_chassis but domain type is not lead
380        """
381        ome_default_args.update({"fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_different_chassis"})
382        f_module = self.get_module_mock(params=ome_default_args)
383        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_ip_from_host',
384                     return_value=ome_default_args["hostname"])
385        resp_data = {"Id": Constants.device_id1, "value": [
386            {
387                "@odata.id": "/api/ManagementDomainService/Domains(25038)",
388                "Id": 25038,
389                "DeviceId": Constants.device_id1,
390                "PublicAddress": [
391                    ome_default_args["hostname"]
392                ],
393                "Name": "MX-2H5DNX2",
394                "Description": "PowerEdge MX7000",
395                "Identifier": Constants.service_tag1,
396                "DomainTypeId": 4000,
397                "DomainTypeValue": "MSM",
398                "DomainRoleTypeId": 3002,
399                "DomainRoleTypeValue": "STANDALONE",
400                "Version": "1.20.00",
401                "Local": True,
402                "GroupId": "d78ba475-f5d5-4dbb-97da-b4b1f190caa2",
403                "GroupName": None,
404                "BackupLead": False,
405                "Capabilities": [],
406                "BackupLeadHealth": 2000
407            }
408        ]}
409        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = resp_data
410        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_service_tag_with_fqdn',
411                     return_value=None)
412        with pytest.raises(Exception, match=LEAD_CHASSIS_ERROR_MSG.format(ome_default_args["fabric_design"])) as ex:
413            self.module.get_msm_device_details(ome_connection_mock_for_smart_fabric, f_module)
414
415    def test_get_msm_device_details_failure_case_02(self, ome_connection_mock_for_smart_fabric, ome_default_args,
416                                                    mocker):
417        """
418        raise exception if there is no domain values in system
419        """
420        ome_default_args.update({"fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_different_chassis"})
421        f_module = self.get_module_mock(params=ome_default_args)
422        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_ip_from_host',
423                     return_value=ome_default_args["hostname"])
424        resp_data = {"Id": None, "value": [
425        ]}
426        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = resp_data
427        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_service_tag_with_fqdn',
428                     return_value=None)
429        with pytest.raises(Exception, match=SYSTEM_NOT_SUPPORTED_ERROR_MSG):
430            self.module.get_msm_device_details(ome_connection_mock_for_smart_fabric, f_module)
431
432    @pytest.mark.parametrize("modify_payload", [
433        {"Name": "Fabric-2"},
434        {"Name": "Fabric-1", "Description": "This is a fabric1."},
435        {"FabricDesignMapping": [
436            {
437                "DesignNode": "Switch-A",
438                "PhysicalNode": Constants.service_tag1
439            },
440            {
441                "DesignNode": "Switch-B",
442                "PhysicalNode": Constants.service_tag2
443            }
444        ], },
445        {
446            "FabricDesign": {
447                "Name": "2xMX9116n_Fabric_Switching_Engines_in_different_chassis"
448            }
449        },
450        {
451            "FabricDesignMapping": [
452                {"DesignNode": "Switch-B", "PhysicalNode": Constants.service_tag2},
453                {"DesignNode": "Switch-A", "PhysicalNode": Constants.service_tag1}]
454        }
455    ])
456    def test_compare_payloads_diff_case_01(self, modify_payload):
457        current_payload = {
458            "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f",
459            "Name": "Fabric-1",
460            "Description": "This is a fabric.",
461            "FabricDesignMapping": [
462                {
463                    "DesignNode": "Switch-A",
464                    "PhysicalNode": "2HB7NX2"
465                },
466                {
467                    "DesignNode": "Switch-B",
468                    "PhysicalNode": "2HBFNX2"
469                }
470            ],
471            "FabricDesign": {
472                "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"
473            }
474        }
475        diff = self.module.compare_payloads(modify_payload, current_payload)
476        assert diff is True
477
478    @pytest.mark.parametrize("current_payload", [
479        {"Name": "Fabric-1", "Description": "This is a fabric1."},
480        {"Name": "Fabric-1", "Description": "This is a fabric.", "FabricDesignMapping": [
481            {
482                "DesignNode": "Switch-A",
483                "PhysicalNode": Constants.service_tag1
484            },
485            {
486                "DesignNode": "Switch-B",
487                "PhysicalNode": Constants.service_tag2
488            }
489        ], "FabricDesign": {
490            "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"
491        }}])
492    def test_compare_payloads_diff_case_02(self, current_payload):
493        modify_payload = {
494            "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f",
495            "Name": "Fabric-1",
496            "Description": "This is a fabric.",
497            "FabricDesignMapping": [
498                {
499                    "DesignNode": "Switch-A",
500                    "PhysicalNode": "2HB7NX2"
501                },
502                {
503                    "DesignNode": "Switch-B",
504                    "PhysicalNode": "2HBFNX2"
505                }
506            ],
507            "FabricDesign": {
508                "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"
509            }
510        }
511        diff = self.module.compare_payloads(modify_payload, current_payload)
512        assert diff is True
513
514    @pytest.mark.parametrize("modify_payload", [
515        {"Name": "Fabric-1", "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f"},
516        {"Name": "Fabric-1", "Description": "This is a fabric.", "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f", },
517        {"Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f", "Name": "Fabric-1", "FabricDesignMapping": [
518            {
519                "DesignNode": "Switch-A",
520                "PhysicalNode": Constants.service_tag1
521            },
522            {
523                "DesignNode": "Switch-B",
524                "PhysicalNode": Constants.service_tag2
525            }
526        ], },
527        {
528            "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f",
529            "Name": "Fabric-1",
530            "FabricDesign": {
531                "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"
532            }
533        },
534        {
535            "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f",
536            "Name": "Fabric-1",
537            "Description": "This is a fabric.",
538            "FabricDesignMapping": [
539                {
540                    "DesignNode": "Switch-A",
541                    "PhysicalNode": Constants.service_tag1
542                },
543                {
544                    "DesignNode": "Switch-B",
545                    "PhysicalNode": Constants.service_tag2
546                }
547            ],
548            "FabricDesign": {
549                "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"
550            }
551        }
552    ])
553    def test_compare_payloads_no_diff_case_01(self, modify_payload):
554        current_payload = {
555            "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f",
556            "Name": "Fabric-1",
557            "Description": "This is a fabric.",
558            "FabricDesignMapping": [
559                {
560                    "DesignNode": "Switch-A",
561                    "PhysicalNode": Constants.service_tag1
562                },
563                {
564                    "DesignNode": "Switch-B",
565                    "PhysicalNode": Constants.service_tag2
566                }
567            ],
568            "FabricDesign": {
569                "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"
570            }
571        }
572        val = self.module.compare_payloads(modify_payload, current_payload)
573        # print(val)
574        assert val is False
575
576    @pytest.mark.parametrize('val', [{'msg': CHECK_MODE_CHANGE_FOUND_MSG,
577                                      "current_payload": {"Name": "Fabric-1", "Description": "This is a fabric.",
578                                                          "FabricDesignMapping": [{"DesignNode": "Switch-A",
579                                                                                   "PhysicalNode": Constants.service_tag1},
580                                                                                  {"DesignNode": "Switch-B",
581                                                                                   "PhysicalNode": Constants.service_tag2}],
582                                                          "FabricDesign": {
583                                                              "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}},
584                                      "expected_payload": {"Name": "Fabric-1", "Description": "This is a fabric.",
585                                                           "FabricDesignMapping": [{"DesignNode": "Switch-A",
586                                                                                    "PhysicalNode": Constants.service_tag2},
587                                                                                   {"DesignNode": "Switch-B",
588                                                                                    "PhysicalNode": Constants.service_tag1}],
589                                                           "FabricDesign": {
590                                                               "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}}},
591                                     {'msg': CHECK_MODE_CHANGE_NOT_FOUND_MSG,
592                                      "current_payload": {"Name": "Fabric-1", "Description": "This is a fabric.",
593                                                          "FabricDesignMapping": [{"DesignNode": "Switch-A",
594                                                                                   "PhysicalNode": Constants.service_tag1},
595                                                                                  {"DesignNode": "Switch-B",
596                                                                                   "PhysicalNode": Constants.service_tag2}],
597                                                          "FabricDesign": {
598                                                              "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}},
599                                      "expected_payload": {"Name": "Fabric-1", "Description": "This is a fabric.",
600                                                           "FabricDesignMapping": [{"DesignNode": "Switch-A",
601                                                                                    "PhysicalNode": Constants.service_tag1},
602                                                                                   {"DesignNode": "Switch-B",
603                                                                                    "PhysicalNode": Constants.service_tag2}],
604                                                           "FabricDesign": {
605                                                               "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}}},
606                                     {'msg': CHECK_MODE_CHANGE_NOT_FOUND_MSG, "current_payload": {"Name": "Fabric-1",
607                                                                                                  "Description": "This is list order change case.",
608                                                                                                  "FabricDesignMapping": [
609                                                                                                      {
610                                                                                                          "DesignNode": "Switch-A",
611                                                                                                          "PhysicalNode": Constants.service_tag1},
612                                                                                                      {
613                                                                                                          "DesignNode": "Switch-B",
614                                                                                                          "PhysicalNode": Constants.service_tag2}],
615                                                                                                  "FabricDesign": {
616                                                                                                      "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}},
617                                      "expected_payload": {"Name": "Fabric-1",
618                                                           "Description": "This is list order change case.",
619                                                           "FabricDesignMapping": [{"DesignNode": "Switch-B",
620                                                                                    "PhysicalNode": Constants.service_tag2},
621                                                                                   {"DesignNode": "Switch-A",
622                                                                                    "PhysicalNode": Constants.service_tag1}],
623                                                           "FabricDesign": {
624                                                               "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}}},
625                                     {'msg': CHECK_MODE_CHANGE_NOT_FOUND_MSG,
626                                      "current_payload": {'Id': 'fa9f1b12-c003-4772-8b90-601d0bf87c69',
627                                                          'Name': 'MX9116N', 'OverrideLLDPConfiguration': 'Disabled',
628                                                          'FabricDesignMapping': [
629                                                              {'DesignNode': 'Switch-B', 'PhysicalNode': '6XLVMR2'},
630                                                              {'DesignNode': 'Switch-A', 'PhysicalNode': '6XLTMR2'}],
631                                                          'FabricDesign': {
632                                                              'Name': '2xMX9116n_Fabric_Switching_Engines_in_different_chassis'}},
633                                      "expected_payload": {'Name': 'MX9116N', 'OverrideLLDPConfiguration': 'Disabled',
634                                                           'FabricDesignMapping': [
635                                                               {'DesignNode': 'Switch-A', 'PhysicalNode': '6XLTMR2'},
636                                                               {'DesignNode': 'Switch-B', 'PhysicalNode': '6XLVMR2'}],
637                                                           'FabricDesign': {
638                                                               'Name': '2xMX9116n_Fabric_Switching_Engines_in_different_chassis'},
639                                                           'Id': 'fa9f1b12-c003-4772-8b90-601d0bf87c69'}}
640                                     ])
641    def test_idempotency_check_for_state_present_modify_check_mode_case01(self, mocker, val):
642        f_module = self.get_module_mock(params={}, check_mode=True)
643        error_message = val["msg"]
644        with pytest.raises(Exception) as err:
645            self.module.idempotency_check_for_state_present("8f25f714-9ea8-48e9-8eac-162d5d842e9f",
646                                                            val['current_payload'], val['expected_payload'],
647                                                            f_module)
648        assert err.value.args[0] == error_message
649
650    def test_idempotency_check_for_state_present_modify_non_check_mode_case01(self, mocker):
651        f_module = self.get_module_mock(params={}, check_mode=False)
652        mocker.patch(MODULE_PATH + 'ome_smart_fabric.compare_payloads',
653                     return_value=False)
654        with pytest.raises(Exception, match=IDEMPOTENCY_MSG):
655            self.module.idempotency_check_for_state_present("8f25f714-9ea8-48e9-8eac-162d5d842e9f",
656                                                            {}, {},
657                                                            f_module)
658
659    def test_idempotency_check_for_state_present_create_non_check_mode_case01(self, mocker):
660        f_module = self.get_module_mock(params={}, check_mode=True)
661        mocker.patch(MODULE_PATH + 'ome_smart_fabric.compare_payloads',
662                     return_value=False)
663        with pytest.raises(Exception, match=CHECK_MODE_CHANGE_FOUND_MSG):
664            self.module.idempotency_check_for_state_present(None,
665                                                            {}, {},
666                                                            f_module)
667
668    def test_design_node_dict_update_case_01(self):
669        design_node_map = [
670            {
671                "DesignNode": "Switch-A",
672                "PhysicalNode": Constants.service_tag1
673            },
674            {
675                "DesignNode": "Switch-B",
676                "PhysicalNode": Constants.service_tag2
677            }
678        ]
679        val = self.module.design_node_dict_update(design_node_map)
680        assert val == {
681            'PhysicalNode1': Constants.service_tag1,
682            'PhysicalNode2': Constants.service_tag2
683        }
684
685    def test_design_node_dict_update_case_02(self):
686        design_node_map = [
687            {
688                "DesignNode": "Switch-B",
689                "PhysicalNode": Constants.service_tag2
690            }
691        ]
692        val = self.module.design_node_dict_update(design_node_map)
693        assert val == {
694            'PhysicalNode2': Constants.service_tag2
695        }
696
697    def test_design_node_dict_update_case_03(self):
698        design_node_map = [
699            {
700                "DesignNode": "Switch-B",
701                "PhysicalNode": Constants.service_tag2
702            }
703        ]
704        val = self.module.design_node_dict_update(design_node_map)
705        assert val == {
706            'PhysicalNode2': Constants.service_tag2
707        }
708
709    @pytest.mark.parametrize("modify_payload", [
710        {
711            'PhysicalNode1': Constants.service_tag2,
712            'PhysicalNode2': Constants.service_tag1
713        }
714    ])
715    def test_validate_switches_overlap_case_01(self, modify_payload):
716        current_dict = {
717            'PhysicalNode1': Constants.service_tag1,
718            'PhysicalNode2': Constants.service_tag2
719        }
720        modify_dict = modify_payload
721        f_module = self.get_module_mock(params={"primary_switch_service_tag": Constants.service_tag2,
722                                                "secondary_switch_service_tag": Constants.service_tag1
723                                                })
724        with pytest.raises(Exception, match="The modify operation does not support primary_switch_service_tag update."):
725            self.module.validate_switches_overlap(current_dict, modify_dict, f_module)
726
727    @pytest.mark.parametrize("modify_payload", [
728        {
729            'PhysicalNode1': Constants.service_tag2,
730            'PhysicalNode2': Constants.service_tag1
731        }
732    ])
733    def test_validate_switches_overlap_case_02(self, modify_payload):
734        current_dict = {
735            'PhysicalNode1': Constants.service_tag2,
736            'PhysicalNode2': Constants.service_tag1
737        }
738        modify_dict = modify_payload
739        f_module = self.get_module_mock(params={"primary_switch_service_tag": Constants.service_tag2,
740                                                "secondary_switch_service_tag": Constants.service_tag1
741                                                })
742        self.module.validate_switches_overlap(current_dict, modify_dict, f_module)
743
744    def test_validate_switches_overlap_case_03(self):
745        """
746        interchanging switches should be allowed
747        """
748        current_dict = {
749            'PhysicalNode1': Constants.service_tag1,
750            'PhysicalNode2': Constants.service_tag2
751        }
752        modify_dict = {
753            'PhysicalNode1': Constants.service_tag1,
754            'PhysicalNode2': Constants.service_tag2
755        }
756        f_module = self.get_module_mock(params={"primary_switch_service_tag": Constants.service_tag1,
757                                                "secondary_switch_service_tag": Constants.service_tag2
758                                                })
759        self.module.validate_switches_overlap(current_dict, modify_dict, f_module)
760
761    def test_fabric_design_map_payload_creation_case01(self, mocker):
762        modify_payload = [
763            {
764                "DesignNode": "Switch-A",
765                "PhysicalNode": Constants.service_tag1
766            },
767            {
768                "DesignNode": "Switch-B",
769                "PhysicalNode": Constants.service_tag2
770            }
771        ]
772        current_payload = [
773            {
774                "DesignNode": "Switch-A",
775                "PhysicalNode": "xyz123"
776            },
777            {
778                "DesignNode": "Switch-B",
779                "PhysicalNode": "abc456"
780            }
781        ]
782        mocker.patch(MODULE_PATH + 'ome_smart_fabric.validate_switches_overlap', return_value=None)
783        f_module = self.get_module_mock(params={})
784        design_map = self.module.fabric_design_map_payload_creation(modify_payload, current_payload, f_module)
785        assert design_map == modify_payload
786
787    def test_fabric_design_map_payload_creation_case02(self, mocker):
788        modify_payload = [
789            {
790                "DesignNode": "Switch-A",
791                "PhysicalNode": Constants.service_tag1
792            }
793        ]
794        current_payload = [
795            {
796                "DesignNode": "Switch-A",
797                "PhysicalNode": "xyz123"
798            },
799            {
800                "DesignNode": "Switch-B",
801                "PhysicalNode": "abc456"
802            }
803        ]
804        f_module = self.get_module_mock(params={})
805        mocker.patch(MODULE_PATH + 'ome_smart_fabric.validate_switches_overlap', return_value=None)
806        design_map = self.module.fabric_design_map_payload_creation(modify_payload, current_payload, f_module)
807        assert design_map == [
808            {
809                "DesignNode": "Switch-A",
810                "PhysicalNode": Constants.service_tag1
811            },
812            {
813                "DesignNode": "Switch-B",
814                "PhysicalNode": "abc456"
815            }
816        ]
817
818    def test_fabric_design_map_payload_creation_case03(self, mocker):
819        modify_payload = [
820        ]
821        current_payload = [
822        ]
823        f_module = self.get_module_mock(params={})
824        mocker.patch(MODULE_PATH + 'ome_smart_fabric.validate_switches_overlap', return_value=None)
825        design_map = self.module.fabric_design_map_payload_creation(modify_payload, current_payload, f_module)
826        assert design_map == []
827
828    def test_merge_payload_case_01(self):
829        modify_payload = {
830            "Name": "new_name",
831            "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f",
832        }
833        current_payload = {
834            "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f",
835            "Name": "Fabric-1",
836            "Description": "This is a fabric.",
837            "FabricDesignMapping": [
838                {
839                    "DesignNode": "Switch-A",
840                    "PhysicalNode": Constants.service_tag1
841                },
842                {
843                    "DesignNode": "Switch-B",
844                    "PhysicalNode": Constants.service_tag2
845                }
846            ],
847            "FabricDesign": {
848                "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"
849            }
850        }
851        f_module = self.get_module_mock(params={})
852        payload = self.module.merge_payload(modify_payload, current_payload, f_module)
853        assert payload["Name"] == modify_payload["Name"]
854        assert payload["Id"] == modify_payload["Id"]
855        assert payload["Description"] == current_payload["Description"]
856        assert payload["FabricDesignMapping"] == current_payload["FabricDesignMapping"]
857        assert payload["FabricDesign"] == current_payload["FabricDesign"]
858
859    def test_merge_payload_case_02(self):
860        modify_payload = {
861            "Name": "new_name",
862            "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f",
863            "FabricDesignMapping": [
864                {
865                    "DesignNode": "Switch-A",
866                    "PhysicalNode": Constants.service_tag1
867                }],
868            "FabricDesign": {
869                "Name": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis"
870            }
871        }
872        current_payload = {
873            "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f",
874            "Name": "Fabric-1",
875            "Description": "This is a fabric.",
876            "FabricDesignMapping": [
877                {
878                    "DesignNode": "Switch-A",
879                    "PhysicalNode": Constants.service_tag1
880                },
881                {
882                    "DesignNode": "Switch-B",
883                    "PhysicalNode": Constants.service_tag2
884                }
885            ],
886            "FabricDesign": {
887                "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"
888            }
889        }
890        f_module = self.get_module_mock(params={})
891        payload = self.module.merge_payload(modify_payload, current_payload, f_module)
892        assert payload["Name"] == modify_payload["Name"]
893        assert payload["Id"] == modify_payload["Id"]
894        assert payload["Description"] == current_payload["Description"]
895        assert payload["FabricDesign"] == modify_payload["FabricDesign"]
896        assert payload["FabricDesignMapping"] == [
897            {
898                "DesignNode": "Switch-A",
899                "PhysicalNode": Constants.service_tag1
900            },
901            {
902                "DesignNode": "Switch-B",
903                "PhysicalNode": Constants.service_tag2
904            }
905        ]
906
907    def test_merge_payload_case_03(self):
908        modify_payload = {
909            "Name": "new_name",
910            "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f",
911            "FabricDesign": {
912                "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"
913            }
914        }
915        current_payload = {
916            "Id": "8f25f714-9ea8-48e9-8eac-162d5d842e9f",
917            "Name": "Fabric-1",
918            "FabricDesignMapping": [
919                {
920                    "DesignNode": "Switch-A",
921                    "PhysicalNode": Constants.service_tag1
922                },
923                {
924                    "DesignNode": "Switch-B",
925                    "PhysicalNode": Constants.service_tag2
926                }
927            ],
928            "Description": "This is a fabric."
929        }
930        f_module = self.get_module_mock(params={})
931        payload = self.module.merge_payload(modify_payload, current_payload, f_module)
932        assert payload["Name"] == modify_payload["Name"]
933        assert payload["Id"] == modify_payload["Id"]
934        assert payload["Description"] == current_payload["Description"]
935        assert payload["FabricDesign"] == modify_payload["FabricDesign"]
936        assert payload["FabricDesignMapping"] == current_payload["FabricDesignMapping"]
937
938    def test_get_fabric_design(self, ome_connection_mock_for_smart_fabric, ome_response_mock):
939        resp_data = {
940            "Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"
941        }
942        ome_response_mock.json_data = resp_data
943        fabric_design_uri = "/api/NetworkService/Fabrics('0bebadec-b61b-4b16-b354-5196396a4a18')/FabricDesign"
944        fabric_design = self.module.get_fabric_design(fabric_design_uri, ome_connection_mock_for_smart_fabric)
945        assert fabric_design == {"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}
946
947    def test_get_current_payload(self, mocker, ome_connection_mock_for_smart_fabric):
948        fabric_details = {
949            "Id": "1312cceb-c3dd-4348-95c1-d8541a17d776",
950            "Name": "Fabric_",
951            "Description": "create new fabric1",
952            "OverrideLLDPConfiguration": "NA",
953            "ScaleVLANProfile": "NA",
954            "FabricDesignMapping": [
955                {
956                    "DesignNode": "Switch-A",
957                    "PhysicalNode": "2HB7NX2"
958                },
959                {
960                    "DesignNode": "Switch-B",
961                    "PhysicalNode": "2HBFNX2"
962                }
963            ],
964            "FabricDesign": {
965                "@odata.id": "/api/NetworkService/Fabrics('1312cceb-c3dd-4348-95c1-d8541a17d776')/FabricDesign"
966            }
967        }
968        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_fabric_design',
969                     return_value={"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"})
970        payload = self.module.get_current_payload(fabric_details, ome_connection_mock_for_smart_fabric)
971        assert payload == {
972            "Id": "1312cceb-c3dd-4348-95c1-d8541a17d776",
973            "Name": "Fabric_",
974            "Description": "create new fabric1",
975            "FabricDesignMapping": [
976                {
977                    "DesignNode": "Switch-A",
978                    "PhysicalNode": "2HB7NX2"
979                },
980                {
981                    "DesignNode": "Switch-B",
982                    "PhysicalNode": "2HBFNX2"
983                }
984            ],
985            "FabricDesign": {"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}
986        }
987
988    def test_get_current_payload_case02(self, mocker, ome_connection_mock_for_smart_fabric):
989        fabric_details = {
990            "Id": "1312cceb-c3dd-4348-95c1-d8541a17d776",
991            "Name": "Fabric_",
992            "Description": "create new fabric1",
993            "OverrideLLDPConfiguration": "Disabled",
994            "ScaleVLANProfile": "NA",
995            "FabricDesignMapping": [
996                {
997                    "DesignNode": "Switch-A",
998                    "PhysicalNode": "2HB7NX2"
999                },
1000                {
1001                    "DesignNode": "Switch-B",
1002                    "PhysicalNode": "2HBFNX2"
1003                }
1004            ],
1005            "FabricDesign": {
1006                "@odata.id": "/api/NetworkService/Fabrics('1312cceb-c3dd-4348-95c1-d8541a17d776')/FabricDesign"
1007            }
1008        }
1009        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_fabric_design',
1010                     return_value={"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"})
1011        payload = self.module.get_current_payload(fabric_details, ome_connection_mock_for_smart_fabric)
1012        assert payload == {
1013            "Id": "1312cceb-c3dd-4348-95c1-d8541a17d776",
1014            "OverrideLLDPConfiguration": "Disabled",
1015            "Name": "Fabric_",
1016            "Description": "create new fabric1",
1017            "FabricDesignMapping": [
1018                {
1019                    "DesignNode": "Switch-A",
1020                    "PhysicalNode": "2HB7NX2"
1021                },
1022                {
1023                    "DesignNode": "Switch-B",
1024                    "PhysicalNode": "2HBFNX2"
1025                }
1026            ],
1027            "FabricDesign": {"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}
1028        }
1029
1030    @pytest.mark.parametrize("params, expected", [({"name": "fabric1"}, {"Name": "fabric1"}),
1031                                                  ({"name": "fabric1", "description": "fabric desc"},
1032                                                   {"Name": "fabric1", "Description": "fabric desc"}),
1033                                                  ({"name": "fabric1", "description": "fabric desc",
1034                                                    "override_LLDP_configuration": "Enabled"},
1035                                                   {"Name": "fabric1", "Description": "fabric desc",
1036                                                    "OverrideLLDPConfiguration": "Enabled"}
1037                                                   )])
1038    def test_create_modify_payload_case_01(self, params, expected, ome_default_args):
1039        ome_default_args.update(params)
1040        payload = self.module.create_modify_payload(ome_default_args, None, "1.1")
1041        assert payload == expected
1042
1043    def test_create_modify_payload_case_02(self, ome_default_args):
1044        params = {"name": "fabric1", "new_name": "fabric2", "primary_switch_service_tag": Constants.service_tag1,
1045                  "secondary_switch_service_tag": Constants.service_tag2,
1046                  "fabric_design": "2xMX5108n_Ethernet_Switches_in_same_chassis",
1047                  "override_LLDP_configuration": "Disabled"}
1048        ome_default_args.update(params)
1049        payload = self.module.create_modify_payload(ome_default_args, "1312cceb-c3dd-4348-95c1-d8541a17d776", "1.0")
1050        assert payload["FabricDesignMapping"] == [{"DesignNode": "Switch-A",
1051                                                   "PhysicalNode": Constants.service_tag1},
1052                                                  {"DesignNode": "Switch-B",
1053                                                   "PhysicalNode": Constants.service_tag2}
1054                                                  ]
1055        assert payload["Name"] == "fabric2"
1056        assert "OverrideLLDPConfiguration" not in payload
1057        assert payload["FabricDesign"] == {"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}
1058        assert payload["Id"] == "1312cceb-c3dd-4348-95c1-d8541a17d776"
1059
1060    def test_get_fabric_id_cse_01(self):
1061        fabric_id, fabric_id_details = self.module.get_fabric_id_details("Fabric_1", all_fabric_details)
1062        assert fabric_id == "1312cceb-c3dd-4348-95c1-d8541a17d776"
1063        assert fabric_id_details == all_fabric_details[0]
1064
1065    def test_get_fabric_id_cse_02(self):
1066        fabric_id, fabric_id_details = self.module.get_fabric_id_details("Fabric_New", all_fabric_details)
1067        assert fabric_id is None
1068        assert fabric_id_details is None
1069
1070    def test_get_fabric_id_cse_03(self):
1071        fabric_id, fabric_id_details = self.module.get_fabric_id_details("Fabric_1", [])
1072        assert fabric_id is None
1073        assert fabric_id_details is None
1074
1075    @pytest.mark.parametrize("identifier, expected_type", [("primary_switch_service_tag", "NETWORK_IOM"),
1076                                                           ("secondary_switch_service_tag", "NETWORK_IOM"),
1077                                                           ("hostname", "CHASSIS")])
1078    def test_validate_device_type_case_01(self, ome_default_args, identifier, expected_type):
1079        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag1,
1080                                 "secondary_switch_service_tag": Constants.service_tag2})
1081        f_module = self.get_module_mock(params={identifier: "val"})
1082        with pytest.raises(Exception, match=DEVICE_SERVICE_TAG_TYPE_ERROR_MSG.format(identifier, expected_type)):
1083            self.module.validate_device_type("SERVER", identifier, {}, f_module)
1084
1085    @pytest.mark.parametrize("identifier", ["primary_switch_service_tag", "secondary_switch_service_tag"])
1086    def test_validate_device_type_case_02(self, ome_default_args, identifier):
1087        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag1,
1088                                 "secondary_switch_service_tag": Constants.service_tag2,
1089                                 "fabric_design": "2xMX5108n_Ethernet_Switches_in_same_chassis"
1090                                 })
1091
1092        f_module = self.get_module_mock(params=ome_default_args)
1093        with pytest.raises(Exception, match=DESIGN_MODEL_ERROR_MSG.format(identifier, 'MX5108n')):
1094            self.module.validate_device_type("NETWORK_IOM", identifier, device_details, f_module)
1095
1096    @pytest.mark.parametrize("identifier", ["primary_switch_service_tag", "secondary_switch_service_tag"])
1097    def test_validate_device_type_case_03(self, ome_default_args, identifier):
1098        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag1,
1099                                 "secondary_switch_service_tag": Constants.service_tag2,
1100                                 "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis"
1101                                 })
1102
1103        f_module = self.get_module_mock(params=ome_default_args)
1104        self.module.validate_device_type("NETWORK_IOM", identifier, device_details, f_module)
1105
1106    def test_validate_service_tag_case_01(self, mocker, ome_connection_mock_for_smart_fabric, ome_default_args):
1107        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag1,
1108                                 "secondary_switch_service_tag": Constants.service_tag2,
1109                                 "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis"
1110                                 })
1111
1112        f_module = self.get_module_mock(params=ome_default_args)
1113        mocker.patch(MODULE_PATH + 'ome_smart_fabric.validate_device_type', return_value=None)
1114        ome_connection_mock_for_smart_fabric.get_device_id_from_service_tag.return_value = {"value": device_details,
1115                                                                                            "Id": Constants.device_id1}
1116        self.module.validate_service_tag(Constants.service_tag1, "primary_switch_service_tag",
1117                                         {2000: "CHASSIS", 4000: "NETWORK_IOM",
1118                                          1000: "SERVER",
1119                                          3000: "STORAGE"}, ome_connection_mock_for_smart_fabric, f_module)
1120
1121    def test_validate_service_tag_exception_case_01(self, mocker, ome_connection_mock_for_smart_fabric,
1122                                                    ome_default_args):
1123        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag1,
1124                                 "secondary_switch_service_tag": Constants.service_tag2,
1125                                 "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis"
1126                                 })
1127
1128        f_module = self.get_module_mock(params=ome_default_args)
1129        mocker.patch(MODULE_PATH + 'ome_smart_fabric.validate_device_type', return_value=None)
1130        ome_connection_mock_for_smart_fabric.get_device_id_from_service_tag.return_value = {"value": {}, "Id": None}
1131        with pytest.raises(Exception, match=DEVICE_SERVICE_TAG_NOT_FOUND_ERROR_MSG.format(Constants.service_tag1)):
1132            self.module.validate_service_tag(Constants.service_tag1, "primary_switch_service_tag",
1133                                             {2000: "CHASSIS", 4000: "NETWORK_IOM",
1134                                              1000: "SERVER",
1135                                              3000: "STORAGE"}, ome_connection_mock_for_smart_fabric, f_module)
1136
1137    @pytest.mark.parametrize("params", [{"primary_switch_service_tag": Constants.service_tag1,
1138                                         "secondary_switch_service_tag": Constants.service_tag2,
1139                                         "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis"
1140                                         },
1141                                        {"primary_switch_service_tag": None,
1142                                         "secondary_switch_service_tag": None,
1143                                         }
1144                                        ])
1145    def test_validate_devices_case_01(self, params, mocker, ome_connection_mock_for_smart_fabric, ome_default_args):
1146        ome_default_args.update(params)
1147
1148        f_module = self.get_module_mock(params=ome_default_args)
1149        ome_connection_mock_for_smart_fabric.get_device_type.return_value = {2000: "CHASSIS", 4000: "NETWORK_IOM",
1150                                                                             1000: "SERVER",
1151                                                                             3000: "STORAGE"}
1152        mocker.patch(MODULE_PATH + 'ome_smart_fabric.validate_service_tag', return_value=None)
1153        self.module.validate_devices(Constants.service_tag1, ome_connection_mock_for_smart_fabric, f_module)
1154
1155    def test_validate_devices_case_02(self, mocker, ome_connection_mock_for_smart_fabric, ome_default_args):
1156        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag2,
1157                                 "secondary_switch_service_tag": Constants.service_tag2,
1158                                 "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis"
1159                                 })
1160
1161        f_module = self.get_module_mock(params=ome_default_args)
1162        mocker.patch(MODULE_PATH + 'ome_smart_fabric.validate_service_tag', return_value=None)
1163        ome_connection_mock_for_smart_fabric.get_device_type.return_value = {2000: "CHASSIS",
1164                                                                             4000: "NETWORK_IOM",
1165                                                                             1000: "SERVER",
1166                                                                             3000: "STORAGE"}
1167        self.module.validate_devices(Constants.service_tag1, ome_connection_mock_for_smart_fabric, f_module)
1168
1169    def test_required_field_check_for_create_case_01(self, ome_default_args):
1170        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag1,
1171                                 "secondary_switch_service_tag": Constants.service_tag2,
1172                                 "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis",
1173                                 "state": "present"
1174                                 })
1175
1176        f_module = self.get_module_mock(params=ome_default_args)
1177        self.module.required_field_check_for_create("fabric_id", f_module)
1178
1179    def test_required_field_check_for_create_case_02(self, ome_default_args):
1180        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag1,
1181                                 "secondary_switch_service_tag": Constants.service_tag2,
1182                                 "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis",
1183                                 "state": "present"
1184                                 })
1185
1186        f_module = self.get_module_mock(params=ome_default_args)
1187        self.module.required_field_check_for_create(None, f_module)
1188
1189    @pytest.mark.parametrize("params", [{"primary_switch_service_tag": Constants.service_tag1},
1190                                        {"secondary_switch_service_tag": Constants.service_tag1},
1191                                        {"fabric_design": Constants.service_tag1},
1192                                        {"fabric_design": Constants.service_tag1,
1193                                         "primary_switch_service_tag": Constants.service_tag1},
1194                                        {"fabric_design": Constants.service_tag1,
1195                                         "secondary_switch_service_tag": Constants.service_tag1},
1196                                        {"primary_switch_service_tag": Constants.service_tag1,
1197                                         "secondary_switch_service_tag": Constants.service_tag2},
1198                                        {"primary_switch_service_tag": None,
1199                                         "secondary_switch_service_tag": None},
1200                                        {"primary_switch_service_tag": None,
1201                                         "secondary_switch_service_tag": None}
1202                                        ])
1203    def test_required_field_check_for_create_case_03(self, params, ome_default_args):
1204        ome_default_args.update(params)
1205        f_module = self.get_module_mock(params=ome_default_args)
1206        with pytest.raises(Exception, match=REQUIRED_FIELD):
1207            self.module.required_field_check_for_create(None, f_module)
1208
1209    def test_process_output_case01(self, ome_connection_mock_for_smart_fabric, ome_default_args):
1210        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag1,
1211                                 "secondary_switch_service_tag": Constants.service_tag2,
1212                                 "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis",
1213                                 "state": "present"
1214                                 })
1215        f_module = self.get_module_mock(params=ome_default_args)
1216        with pytest.raises(Exception, match="Fabric modification operation is initiated.") as err:
1217            self.module.process_output("Fabric1", True, "Fabric modification operation is initiated.", "1234",
1218                                       ome_connection_mock_for_smart_fabric, f_module)
1219        err.value.fail_kwargs['fabric_id'] == "1234"
1220
1221    def test_process_output_case02(self, mocker, ome_connection_mock_for_smart_fabric, ome_default_args):
1222        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag1,
1223                                 "secondary_switch_service_tag": Constants.service_tag2,
1224                                 "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis",
1225                                 "state": "present"
1226                                 })
1227        f_module = self.get_module_mock(params=ome_default_args)
1228        resp = {
1229            "error": {
1230                "code": "Base.1.0.GeneralError",
1231                "message": "A general error has occurred. See ExtendedInfo for more information.",
1232                "@Message.ExtendedInfo":
1233                    [
1234                        {
1235                            "MessageId": "CDEV7154",
1236                            "RelatedProperties": [],
1237                            "Message": "Fabric update is successful. The OverrideLLDPConfiguration attribute is not"
1238                                       " provided "
1239                                       " in the payload, so it preserves the previous value.",
1240                            "MessageArgs": [],
1241                            "Severity": "Informational",
1242                            "Resolution": "Please update the Fabric with the OverrideLLDPConfiguration as Disabled or"
1243                                          " Enabled "
1244                                          " if necessary. "
1245                        }
1246                    ]
1247            }
1248        }
1249        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = {"value": all_fabric_details,
1250                                                                                           "total_count": 2}
1251        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_fabric_id_details',
1252                     return_value=(all_fabric_details[0]["Id"], all_fabric_details[0]))
1253        with pytest.raises(Exception, match="Fabric creation operation is initiated.") as err:
1254            self.module.process_output("Fabric1", resp, "Fabric creation operation is initiated.", None,
1255                                       ome_connection_mock_for_smart_fabric, f_module)
1256        err.value.fail_kwargs['fabric_id'] == all_fabric_details[0]["Id"]
1257        err.value.fail_kwargs['additional_info'] == resp
1258
1259    def test_process_output_case03(self, ome_connection_mock_for_smart_fabric, ome_default_args):
1260        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag1,
1261                                 "secondary_switch_service_tag": Constants.service_tag2,
1262                                 "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis",
1263                                 "state": "present"
1264                                 })
1265        f_module = self.get_module_mock(params=ome_default_args)
1266        with pytest.raises(Exception, match="Fabric creation operation is initiated.") as err:
1267            self.module.process_output("Fabric1", "1234", "Fabric creation operation is initiated.", None,
1268                                       ome_connection_mock_for_smart_fabric, f_module)
1269        err.value.fail_kwargs['fabric_id'] == "1234"
1270
1271    def test_create_modify_fabric_modify_case_01(self, ome_connection_mock_for_smart_fabric, ome_default_args, mocker,
1272                                                 ome_response_mock):
1273        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag1,
1274                                 "secondary_switch_service_tag": Constants.service_tag2,
1275                                 "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis",
1276                                 "state": "present"
1277                                 })
1278
1279        mocker.patch(MODULE_PATH + 'ome_smart_fabric.required_field_check_for_create',
1280                     return_value=None)
1281        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_msm_device_details',
1282                     return_value=(Constants.service_tag1, "1.1"))
1283        mocker.patch(MODULE_PATH + 'ome_smart_fabric.validate_devices', return_value=None)
1284        mocker.patch(MODULE_PATH + 'ome_smart_fabric.validate_modify', return_value=None)
1285        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_fabric_id_details',
1286                     return_value=(all_fabric_details[0]["Id"], all_fabric_details[0]))
1287        mocker.patch(MODULE_PATH + 'ome_smart_fabric.create_modify_payload',
1288                     return_value={"Name": "fabric2", "Description": "fabric desc2",
1289                                   "OverrideLLDPConfiguration": "Enabled"})
1290        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_current_payload',
1291                     return_value={
1292                         "Name": "fabric1",
1293                         "Description": "fabric desc1",
1294                         "OverrideLLDPConfiguration": "Enabled",
1295                         "FabricDesignMapping": [
1296                             {
1297                                 "DesignNode": "Switch-A",
1298                                 "PhysicalNode": "3QM4WV2"
1299                             },
1300                             {
1301                                 "DesignNode": "Switch-B",
1302                                 "PhysicalNode": "GTCT8T2"
1303                             }
1304                         ],
1305                         "FabricDesign": {
1306                             "Name": "2xMX9116n_Fabric_Switching_Engines_in_different_chassis"
1307                         }
1308                     })
1309        mocker_merge_payload = mocker.patch(MODULE_PATH + 'ome_smart_fabric.merge_payload',
1310                                            return_value={
1311                                                "Name": "fabric2",
1312                                                "Description": "fabric desc2",
1313                                                "OverrideLLDPConfiguration": "Enabled",
1314                                                "FabricDesignMapping": [
1315                                                    {
1316                                                        "DesignNode": "Switch-A",
1317                                                        "PhysicalNode": "3QM4WV2"
1318                                                    },
1319                                                    {
1320                                                        "DesignNode": "Switch-B",
1321                                                        "PhysicalNode": "GTCT8T2"
1322                                                    }
1323                                                ],
1324                                                "FabricDesign": {
1325                                                    "Name": "2xMX9116n_Fabric_Switching_Engines_in_different_chassis"
1326                                                }
1327                                            })
1328        mocker.patch(MODULE_PATH + 'ome_smart_fabric.idempotency_check_for_state_present', return_value=None)
1329        mocker_process_output = mocker.patch(MODULE_PATH + 'ome_smart_fabric.process_output', return_value=None)
1330        ome_response_mock.json_data = "true"
1331        f_module = self.get_module_mock(params=ome_default_args)
1332        self.module.create_modify_fabric("Fabric1", all_fabric_details, ome_connection_mock_for_smart_fabric,
1333                                         f_module)
1334        assert mocker_process_output.called
1335        assert mocker_merge_payload.called
1336
1337    def test_create_modify_fabric_create_case_02(self, ome_connection_mock_for_smart_fabric, ome_default_args, mocker,
1338                                                 ome_response_mock):
1339        ome_default_args.update({"primary_switch_service_tag": Constants.service_tag1,
1340                                 "secondary_switch_service_tag": Constants.service_tag2,
1341                                 "fabric_design": "2xMX9116n_Fabric_Switching_Engines_in_same_chassis",
1342                                 "state": "present"
1343                                 })
1344
1345        f_module = self.get_module_mock(params=ome_default_args)
1346        mocker.patch(MODULE_PATH + 'ome_smart_fabric.required_field_check_for_create',
1347                     return_value=None)
1348        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_msm_device_details',
1349                     return_value=(Constants.service_tag1, "1.1"))
1350        mocker.patch(MODULE_PATH + 'ome_smart_fabric.validate_devices', return_value=None)
1351        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_fabric_id_details',
1352                     return_value=(None, {}))
1353        mocker_create_modify_payload = mocker.patch(MODULE_PATH + 'ome_smart_fabric.create_modify_payload',
1354                                                    return_value={"Name": "fabric2", "Description": "fabric desc2",
1355                                                                  "OverrideLLDPConfiguration": "Enabled"})
1356        mocker.patch(MODULE_PATH + 'ome_smart_fabric.idempotency_check_for_state_present', return_value=None)
1357        ome_response_mock.json_data = "123456789abcd"
1358        mocker_process_output = mocker.patch(MODULE_PATH + 'ome_smart_fabric.process_output', return_value=None)
1359        self.module.create_modify_fabric("Fabric1", all_fabric_details, ome_connection_mock_for_smart_fabric,
1360                                         f_module)
1361        assert mocker_process_output.called
1362        assert mocker_create_modify_payload.called
1363
1364    def test_check_fabric_exits_for_state_absent_non_check_mode_case01(self, mocker,
1365                                                                       ome_connection_mock_for_smart_fabric,
1366                                                                       ome_default_args):
1367        ome_default_args.update({
1368            "state": "absent",
1369            "name": "Fabric1"
1370        })
1371
1372        f_module = self.get_module_mock(params=ome_default_args, check_mode=False)
1373        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_fabric_id_details',
1374                     return_value=(None, {}))
1375        with pytest.raises(Exception, match=FABRIC_NOT_FOUND_ERROR_MSG.format("Fabric1")):
1376            self.module.check_fabric_exits_for_state_absent(all_fabric_details[0], f_module, "Fabric1")
1377
1378    def test_check_fabric_exits_for_state_absent_non_check_mode_case02(self, mocker,
1379                                                                       ome_connection_mock_for_smart_fabric,
1380                                                                       ome_default_args):
1381        ome_default_args.update({
1382            "state": "absent",
1383            "name": "Fabric1"
1384        })
1385
1386        f_module = self.get_module_mock(params=ome_default_args, check_mode=False)
1387        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_fabric_id_details',
1388                     return_value=(all_fabric_details[0]["Id"], all_fabric_details[0]))
1389        fabric_id = self.module.check_fabric_exits_for_state_absent(all_fabric_details[0], f_module, "Fabric1")
1390        assert fabric_id == all_fabric_details[0]["Id"]
1391
1392    def test_check_fabric_exits_for_state_absent_check_mode_case01(self, mocker,
1393                                                                   ome_connection_mock_for_smart_fabric,
1394                                                                   ome_default_args):
1395        ome_default_args.update({
1396            "state": "absent",
1397            "name": "Fabric1"
1398        })
1399
1400        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1401        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_fabric_id_details',
1402                     return_value=(None, {}))
1403        with pytest.raises(Exception, match=CHECK_MODE_CHANGE_NOT_FOUND_MSG):
1404            self.module.check_fabric_exits_for_state_absent(all_fabric_details[0], f_module, "Fabric1")
1405
1406    def test_check_fabric_exits_for_state_absent_check_mode_case02(self, mocker,
1407                                                                   ome_connection_mock_for_smart_fabric,
1408                                                                   ome_default_args):
1409        ome_default_args.update({
1410            "state": "absent",
1411            "name": "Fabric1"
1412        })
1413
1414        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1415        mocker.patch(MODULE_PATH + 'ome_smart_fabric.get_fabric_id_details',
1416                     return_value=(all_fabric_details[0]["Id"], all_fabric_details[0]))
1417        with pytest.raises(Exception, match=CHECK_MODE_CHANGE_FOUND_MSG):
1418            self.module.check_fabric_exits_for_state_absent(all_fabric_details[0], f_module, "Fabric1")
1419
1420    def test_delete_fabric(self, ome_connection_mock_for_smart_fabric, ome_default_args, mocker):
1421        ome_default_args.update({
1422            "state": "absent",
1423            "name": "Fabric1"
1424        })
1425
1426        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1427        mocker.patch(MODULE_PATH + 'ome_smart_fabric.check_fabric_exits_for_state_absent',
1428                     return_value=all_fabric_details[0]["Id"])
1429        with pytest.raises(Exception, match="Fabric deletion operation is initiated.") as err:
1430            self.module.delete_fabric(all_fabric_details, ome_connection_mock_for_smart_fabric, f_module, "Fabric1")
1431        err.value.fail_kwargs['fabric_id'] == all_fabric_details[0]["Id"]
1432
1433    def test_fabric_actions_case_01(self, mocker, ome_connection_mock_for_smart_fabric, ome_default_args):
1434        ome_default_args.update({
1435            "state": "absent",
1436            "name": "Fabric1"
1437        })
1438        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = {"value": all_fabric_details,
1439                                                                                           "total_count": 2}
1440        delete_fabric = mocker.patch(MODULE_PATH + 'ome_smart_fabric.delete_fabric',
1441                                     return_value=None)
1442        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1443        self.module.fabric_actions(ome_connection_mock_for_smart_fabric, f_module)
1444        assert delete_fabric.called
1445
1446    def test_fabric_actions_case_02(self, mocker, ome_connection_mock_for_smart_fabric, ome_default_args):
1447        ome_default_args.update({
1448            "state": "present",
1449            "name": "Fabric1"
1450        })
1451        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = {"value": all_fabric_details,
1452                                                                                           "total_count": 2}
1453        create_modify_fabric = mocker.patch(MODULE_PATH + 'ome_smart_fabric.create_modify_fabric',
1454                                            return_value=None)
1455        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1456        self.module.fabric_actions(ome_connection_mock_for_smart_fabric, f_module)
1457        assert create_modify_fabric.called
1458
1459    def test_get_service_tag_with_fqdn_success_case(self, ome_default_args, ome_connection_mock_for_smart_fabric):
1460        ome_default_args.update({"hostname": "M-YYYY.abcd.lab"})
1461        resp_data = {
1462            "@odata.context": "/api/$metadata#Collection(DeviceService.Device)",
1463            "@odata.count": 2,
1464            "value": [
1465                {
1466                    "@odata.type": "#DeviceService.Device",
1467                    "@odata.id": "/api/DeviceService/Devices(Constants.device_id1)",
1468                    "Id": Constants.device_id1,
1469                    "Type": 2000,
1470                    "Identifier": Constants.service_tag1,
1471                    "DeviceServiceTag": Constants.service_tag1,
1472                    "ChassisServiceTag": None,
1473                    "Model": "PowerEdge MX7000",
1474                    "PowerState": 17,
1475                    "ManagedState": 3000,
1476                    "Status": 4000,
1477                    "ConnectionState": True,
1478                    "AssetTag": None,
1479                    "SystemId": 2031,
1480                    "DeviceName": "MX-Constants.service_tag1",
1481                    "LastInventoryTime": "2020-07-11 17:00:18.925",
1482                    "LastStatusTime": "2020-07-11 09:00:07.444",
1483                    "DeviceSubscription": None,
1484                    "DeviceCapabilities": [
1485                        18,
1486                        8,
1487                        201,
1488                        202
1489                    ],
1490                    "SlotConfiguration": {
1491                        "ChassisName": None
1492                    },
1493                    "DeviceManagement": [
1494                        {
1495                            "ManagementId": 111111,
1496                            "NetworkAddress": ome_default_args["hostname"],
1497                            "MacAddress": "xx:yy:zz:x1x1",
1498                            "ManagementType": 2,
1499                            "InstrumentationName": "MX-Constants.service_tag1",
1500                            "DnsName": "M-YYYY.abcd.lab",
1501                            "ManagementProfile": [
1502                                {
1503                                    "ManagementProfileId": 111111,
1504                                    "ProfileId": "MSM_BASE",
1505                                    "ManagementId": 111111,
1506                                    "ManagementURL": "https://" + ome_default_args["hostname"] + ":443",
1507                                    "HasCreds": 0,
1508                                    "Status": 1000,
1509                                    "StatusDateTime": "2020-07-11 17:00:18.925"
1510                                }
1511                            ]
1512                        },
1513                        {
1514                            "ManagementId": 33333,
1515                            "NetworkAddress": "[1234.abcd:5678:345]",
1516                            "MacAddress": "22:xx:yy:11",
1517                            "ManagementType": 2,
1518                            "InstrumentationName": "MX-Constants.service_tag1",
1519                            "DnsName": "M-YYYY.abcd.lab",
1520                            "ManagementProfile": [
1521                                {
1522                                    "ManagementProfileId": 33333,
1523                                    "ProfileId": "MSM_BASE",
1524                                    "ManagementId": 33333,
1525                                    "ManagementURL": "https://[1234:abcd:567:xyzs]:443",
1526                                    "HasCreds": 0,
1527                                    "Status": 1000,
1528                                    "StatusDateTime": "2020-07-11 17:00:18.925"
1529                                }
1530                            ]
1531                        }
1532                    ],
1533                    "Actions": None
1534                },
1535                {
1536                    "@odata.type": "#DeviceService.Device",
1537                    "@odata.id": "/api/DeviceService/Devices(Constants.device_id1)",
1538                    "Id": Constants.device_id1,
1539                    "Type": 2000,
1540                    "Identifier": Constants.service_tag2,
1541                    "DeviceServiceTag": Constants.service_tag2,
1542                    "ChassisServiceTag": None,
1543                    "Model": "PowerEdge MX7000",
1544                    "PowerState": 17,
1545                    "ManagedState": 3000,
1546                    "Status": 4000,
1547                    "ConnectionState": True,
1548                    "AssetTag": None,
1549                    "SystemId": 2031,
1550                    "DeviceName": "MX-Constants.service_tag2",
1551                    "LastInventoryTime": "2020-07-11 17:00:18.925",
1552                    "LastStatusTime": "2020-07-11 09:00:07.444",
1553                    "DeviceSubscription": None,
1554                    "DeviceCapabilities": [
1555                        18,
1556                        8,
1557                        201,
1558                        202
1559                    ],
1560                    "SlotConfiguration": {
1561                        "ChassisName": None
1562                    },
1563                    "DeviceManagement": [
1564                        {
1565                            "ManagementId": 111111,
1566                            "NetworkAddress": ome_default_args["hostname"],
1567                            "MacAddress": "xx:yy:zz:x1x1",
1568                            "ManagementType": 2,
1569                            "InstrumentationName": "MX-Constants.service_tag2",
1570                            "DnsName": "M-XXXX.abcd.lab",
1571                            "ManagementProfile": [
1572                                {
1573                                    "ManagementProfileId": 111111,
1574                                    "ProfileId": "MSM_BASE",
1575                                    "ManagementId": 111111,
1576                                    "ManagementURL": "https://" + ome_default_args["hostname"] + ":443",
1577                                    "HasCreds": 0,
1578                                    "Status": 1000,
1579                                    "StatusDateTime": "2020-07-11 17:00:18.925"
1580                                }
1581                            ]
1582                        },
1583                        {
1584                            "ManagementId": 22222,
1585                            "NetworkAddress": "[1234.abcd:5678:345]",
1586                            "MacAddress": "22:xx:yy:11",
1587                            "ManagementType": 2,
1588                            "InstrumentationName": "MX-Constants.service_tag2",
1589                            "DnsName": "M-XXXX.abcd.lab",
1590                            "ManagementProfile": [{
1591                                "ManagementProfileId": 22222,
1592                                "ProfileId": "MSM_BASE",
1593                                "ManagementId": 22222,
1594                                "ManagementURL": "https://[1234:abcd:567:xyzs]:443",
1595                                "HasCreds": 0,
1596                                "Status": 1000,
1597                                "StatusDateTime": "2020-07-11 17:00:18.925"
1598                            }]
1599                        }
1600                    ],
1601                    "Actions": None
1602                }
1603            ]
1604        }
1605        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1606        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = resp_data
1607        service_tag = self.module.get_service_tag_with_fqdn(ome_connection_mock_for_smart_fabric, f_module)
1608        assert service_tag == Constants.service_tag1
1609
1610    def test_get_service_tag_with_fqdn_success_case2(self, ome_default_args, ome_connection_mock_for_smart_fabric):
1611        ome_default_args.update({"hostname": Constants.hostname1})
1612        resp_data = {
1613            "@odata.context": "/api/$metadata#Collection(DeviceService.Device)",
1614            "@odata.count": 2,
1615            "value": [
1616                {
1617                    "@odata.type": "#DeviceService.Device",
1618                    "@odata.id": "/api/DeviceService/Devices(Constants.device_id1)",
1619                    "Id": Constants.device_id1,
1620                    "Type": 2000,
1621                    "Identifier": Constants.service_tag1,
1622                    "DeviceServiceTag": Constants.service_tag1,
1623                    "ChassisServiceTag": None,
1624                    "Model": "PowerEdge MX7000",
1625                    "PowerState": 17,
1626                    "ManagedState": 3000,
1627                    "Status": 4000,
1628                    "ConnectionState": True,
1629                    "AssetTag": None,
1630                    "SystemId": 2031,
1631                    "DeviceName": "MX-Constants.service_tag1",
1632                    "LastInventoryTime": "2020-07-11 17:00:18.925",
1633                    "LastStatusTime": "2020-07-11 09:00:07.444",
1634                    "DeviceSubscription": None,
1635                    "DeviceCapabilities": [
1636                        18,
1637                        8,
1638                        201,
1639                        202
1640                    ],
1641                    "SlotConfiguration": {
1642                        "ChassisName": None
1643                    },
1644                    "DeviceManagement": [
1645                        {
1646                            "ManagementId": 111111,
1647                            "NetworkAddress": "192.168.1.1",
1648                            "MacAddress": "xx:yy:zz:x1x1",
1649                            "ManagementType": 2,
1650                            "InstrumentationName": "MX-Constants.service_tag1",
1651                            "DnsName": "M-YYYY.abcd.lab",
1652                            "ManagementProfile": [
1653                                {
1654                                    "ManagementProfileId": 111111,
1655                                    "ProfileId": "MSM_BASE",
1656                                    "ManagementId": 111111,
1657                                    "ManagementURL": "https://" + ome_default_args["hostname"] + ":443",
1658                                    "HasCreds": 0,
1659                                    "Status": 1000,
1660                                    "StatusDateTime": "2020-07-11 17:00:18.925"
1661                                }
1662                            ]
1663                        },
1664                        {
1665                            "ManagementId": 33333,
1666                            "NetworkAddress": "[1234.abcd:5678:345]",
1667                            "MacAddress": "22:xx:yy:11",
1668                            "ManagementType": 2,
1669                            "InstrumentationName": "MX-Constants.service_tag1",
1670                            "DnsName": "M-YYYY.abcd.lab",
1671                            "ManagementProfile": [
1672                                {
1673                                    "ManagementProfileId": 33333,
1674                                    "ProfileId": "MSM_BASE",
1675                                    "ManagementId": 33333,
1676                                    "ManagementURL": "https://[1234:abcd:567:xyzs]:443",
1677                                    "HasCreds": 0,
1678                                    "Status": 1000,
1679                                    "StatusDateTime": "2020-07-11 17:00:18.925"
1680                                }
1681                            ]
1682                        }
1683                    ],
1684                    "Actions": None
1685                },
1686                {
1687                    "@odata.type": "#DeviceService.Device",
1688                    "@odata.id": "/api/DeviceService/Devices(Constants.device_id1)",
1689                    "Id": Constants.device_id1,
1690                    "Type": 2000,
1691                    "Identifier": Constants.service_tag2,
1692                    "DeviceServiceTag": Constants.service_tag2,
1693                    "ChassisServiceTag": None,
1694                    "Model": "PowerEdge MX7000",
1695                    "PowerState": 17,
1696                    "ManagedState": 3000,
1697                    "Status": 4000,
1698                    "ConnectionState": True,
1699                    "AssetTag": None,
1700                    "SystemId": 2031,
1701                    "DeviceName": "MX-Constants.service_tag2",
1702                    "LastInventoryTime": "2020-07-11 17:00:18.925",
1703                    "LastStatusTime": "2020-07-11 09:00:07.444",
1704                    "DeviceSubscription": None,
1705                    "DeviceCapabilities": [
1706                        18,
1707                        8,
1708                        201,
1709                        202
1710                    ],
1711                    "SlotConfiguration": {
1712                        "ChassisName": None
1713                    },
1714                    "DeviceManagement": [
1715                        {
1716                            "ManagementId": 111111,
1717                            "NetworkAddress": "192.168.1.2",
1718                            "MacAddress": "xx:yy:zz:x1x1",
1719                            "ManagementType": 2,
1720                            "InstrumentationName": "MX-Constants.service_tag2",
1721                            "DnsName": "M-XXXX.abcd.lab",
1722                            "ManagementProfile": [
1723                                {
1724                                    "ManagementProfileId": 111111,
1725                                    "ProfileId": "MSM_BASE",
1726                                    "ManagementId": 111111,
1727                                    "ManagementURL": "https://" + ome_default_args["hostname"] + ":443",
1728                                    "HasCreds": 0,
1729                                    "Status": 1000,
1730                                    "StatusDateTime": "2020-07-11 17:00:18.925"
1731                                }
1732                            ]
1733                        },
1734                        {
1735                            "ManagementId": 22222,
1736                            "NetworkAddress": "[1234.abcd:5678:345]",
1737                            "MacAddress": "22:xx:yy:11",
1738                            "ManagementType": 2,
1739                            "InstrumentationName": "MX-Constants.service_tag2",
1740                            "DnsName": "M-XXXX.abcd.lab",
1741                            "ManagementProfile": [
1742                                {
1743                                    "ManagementProfileId": 22222,
1744                                    "ProfileId": "MSM_BASE",
1745                                    "ManagementId": 22222,
1746                                    "ManagementURL": "https://[1234:abcd:567:xyzs]:443",
1747                                    "HasCreds": 0,
1748                                    "Status": 1000,
1749                                    "StatusDateTime": "2020-07-11 17:00:18.925"
1750                                }
1751                            ]
1752                        }
1753                    ],
1754                    "Actions": None
1755                }
1756            ]
1757        }
1758        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1759        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = resp_data
1760        service_tag = self.module.get_service_tag_with_fqdn(ome_connection_mock_for_smart_fabric, f_module)
1761        assert service_tag is None
1762
1763    def test_get_service_tag_with_fqdn_success_case3(self, ome_default_args, ome_connection_mock_for_smart_fabric):
1764        ome_default_args.update({"hostname": Constants.hostname1})
1765        resp_data = {"value": []}
1766        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1767        ome_connection_mock_for_smart_fabric.get_all_items_with_pagination.return_value = resp_data
1768        service_tag = self.module.get_service_tag_with_fqdn(ome_connection_mock_for_smart_fabric, f_module)
1769        assert service_tag is None
1770
1771    def test_fabric_validate_modify_case01(self, ome_default_args):
1772        ome_default_args.update({"fabric_design": "2xMX5108n_Ethernet_Switches_in_same_chassis"})
1773        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1774        current_payload = {
1775            "Id": "1312cceb-c3dd-4348-95c1-d8541a17d776",
1776            "Name": "Fabric_",
1777            "Description": "create new fabric1",
1778            "FabricDesignMapping": [
1779                {
1780                    "DesignNode": "Switch-A",
1781                    "PhysicalNode": "2HB7NX2"
1782                },
1783                {
1784                    "DesignNode": "Switch-B",
1785                    "PhysicalNode": "2HBFNX2"
1786                }
1787            ],
1788            "FabricDesign": {"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}
1789        }
1790        self.module.validate_modify(f_module, current_payload)
1791
1792    def test_fabric_validate_modify_case02(self, ome_default_args):
1793        ome_default_args.update({"name": "abc"})
1794        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1795        current_payload = {
1796            "Id": "1312cceb-c3dd-4348-95c1-d8541a17d776",
1797            "Name": "Fabric_",
1798            "Description": "create new fabric1",
1799            "FabricDesignMapping": [
1800                {
1801                    "DesignNode": "Switch-A",
1802                    "PhysicalNode": "2HB7NX2"
1803                },
1804                {
1805                    "DesignNode": "Switch-B",
1806                    "PhysicalNode": "2HBFNX2"
1807                }
1808            ],
1809            "FabricDesign": {"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}
1810        }
1811        self.module.validate_modify(f_module, current_payload)
1812
1813    def test_fabric_validate_modify_case03(self, ome_default_args):
1814        ome_default_args.update({"fabric_design": "2xMX5108n_Ethernet_Switches_in_same_chassis"})
1815        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1816        current_payload = {
1817            "Id": "1312cceb-c3dd-4348-95c1-d8541a17d776",
1818            "Name": "Fabric_",
1819            "Description": "create new fabric1",
1820            "FabricDesign": {"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"},
1821            "FabricDesignMapping": [
1822                {
1823                    "DesignNode": "Switch-A",
1824                    "PhysicalNode": "2HB7NX2"
1825                },
1826                {
1827                    "DesignNode": "Switch-B",
1828                    "PhysicalNode": "2HBFNX2"
1829                }
1830            ],
1831        }
1832        self.module.validate_modify(f_module, current_payload)
1833
1834    def test_fabric_validate_modify_case05(self, ome_default_args):
1835        ome_default_args.update({"primary_switch_service_tag": "abc"})
1836        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1837        current_payload = {
1838            "Id": "1312cceb-c3dd-4348-95c1-d8541a17d776",
1839            "Name": "Fabric_",
1840            "Description": "create new fabric1",
1841            "FabricDesignMapping": [
1842                {
1843                    "DesignNode": "Switch-B",
1844                    "PhysicalNode": "2HBFNX2"
1845                }
1846            ],
1847            "FabricDesign": {"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}
1848        }
1849        self.module.validate_modify(f_module, current_payload)
1850
1851    def test_fabric_validate_modify_case07(self, ome_default_args):
1852        ome_default_args.update({"name": "abc"})
1853        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1854        current_payload = {
1855            "Id": "1312cceb-c3dd-4348-95c1-d8541a17d776",
1856            "Name": "Fabric_",
1857            "Description": "create new fabric1",
1858            "FabricDesignMapping": [
1859                {
1860                    "DesignNode": "Switch-B",
1861                    "PhysicalNode": "2HBFNX2"
1862                }
1863            ],
1864            "FabricDesign": {"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}
1865        }
1866        self.module.validate_modify(f_module, current_payload)
1867
1868    @pytest.mark.parametrize("param", [{"secondary_switch_service_tag": "abc"}, {"primary_switch_service_tag": "abc"}])
1869    def test_fabric_validate_modify_case08(self, param, ome_default_args):
1870        ome_default_args.update(param)
1871        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1872        current_payload = {
1873            "Id": "1312cceb-c3dd-4348-95c1-d8541a17d776",
1874            "Name": "Fabric_",
1875            "Description": "create new fabric1",
1876            "FabricDesignMapping": [
1877            ],
1878            "FabricDesign": {"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}
1879        }
1880        self.module.validate_modify(f_module, current_payload)
1881
1882    @pytest.mark.parametrize("param", [{"secondary_switch_service_tag": "abc"}, {"primary_switch_service_tag": "abc"}])
1883    def test_fabric_validate_modify_case09(self, param, ome_default_args):
1884        ome_default_args.update(param)
1885        f_module = self.get_module_mock(params=ome_default_args, check_mode=True)
1886        current_payload = {
1887            "Id": "1312cceb-c3dd-4348-95c1-d8541a17d776",
1888            "Name": "Fabric_",
1889            "Description": "create new fabric1",
1890            "FabricDesign": {"Name": "2xMX5108n_Ethernet_Switches_in_same_chassis"}
1891        }
1892        self.module.validate_modify(f_module, current_payload)
1893