1# -*- coding: utf-8 -*-
2
3#
4# Dell EMC OpenManage Ansible Modules
5# Version 3.0.0
6# Copyright (C) 2018-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 idrac_network
18from ansible_collections.dellemc.openmanage.tests.unit.plugins.modules.common import FakeAnsibleModule, Constants
19from ansible_collections.dellemc.openmanage.tests.unit.compat.mock import MagicMock, patch, Mock
20from io import StringIO
21from ansible.module_utils._text import to_text
22from ansible.module_utils.six.moves.urllib.error import HTTPError, URLError
23from ansible.module_utils.urls import ConnectionError, SSLValidationError
24from pytest import importorskip
25
26importorskip("omsdk.sdkfile")
27importorskip("omsdk.sdkcreds")
28
29MODULE_PATH = 'ansible_collections.dellemc.openmanage.plugins.modules.'
30
31
32class TestConfigNetwork(FakeAnsibleModule):
33    module = idrac_network
34
35    @pytest.fixture
36    def idrac_configure_network_mock(self):
37        omsdk_mock = MagicMock()
38        idrac_obj = MagicMock()
39        omsdk_mock.file_share_manager = idrac_obj
40        omsdk_mock.config_mgr = idrac_obj
41        type(idrac_obj).create_share_obj = Mock(return_value="networkstatus")
42        type(idrac_obj).set_liason_share = Mock(return_value="networkstatus")
43        return idrac_obj
44
45    @pytest.fixture
46    def idrac_file_manager_config_networking_mock(self, mocker):
47        try:
48            file_manager_obj = mocker.patch(
49                MODULE_PATH + 'idrac_network.file_share_manager')
50        except AttributeError:
51            file_manager_obj = MagicMock()
52        obj = MagicMock()
53        file_manager_obj.create_share_obj.return_value = obj
54        return file_manager_obj
55
56    @pytest.fixture
57    def idrac_connection_configure_network_mock(self, mocker, idrac_configure_network_mock):
58        idrac_conn_class_mock = mocker.patch(MODULE_PATH +
59                                             'idrac_network.iDRACConnection',
60                                             return_value=idrac_configure_network_mock)
61        idrac_conn_class_mock.return_value.__enter__.return_value = idrac_configure_network_mock
62        return idrac_configure_network_mock
63
64    def test_main_idrac_configure_network_success_case(self, idrac_connection_configure_network_mock, mocker,
65                                                       idrac_default_args, idrac_file_manager_config_networking_mock):
66        idrac_default_args.update({"share_name": "sharename"})
67        message = {'changed': False, 'msg': {'Status': "Success", "message": "No changes found to commit!"}}
68        mocker.patch(MODULE_PATH +
69                     'idrac_network.run_idrac_network_config', return_value=message)
70        result = self._run_module(idrac_default_args)
71        assert result == {'msg': 'Successfully configured the idrac network settings.',
72                          'network_status': {
73                              'changed': False,
74                              'msg': {'Status': 'Success', 'message': 'No changes found to commit!'}},
75                          'changed': False, 'failed': False}
76
77    def test_run_idrac_network_config_success_case01(self, idrac_connection_configure_network_mock, idrac_default_args,
78                                                     idrac_file_manager_config_networking_mock):
79        idrac_default_args.update({"share_name": "sharename", "share_mnt": "mountname", "share_user": "shareuser",
80                                   "share_password": "sharepassword", "register_idrac_on_dns": "Enabled",
81                                   "dns_idrac_name": "testname", "auto_config": "Disabled", "static_dns": "staticdns",
82                                   "setup_idrac_nic_vlan": "Enabled", "vlan_id": 4, "vlan_priority": "Enabled",
83                                   "enable_nic": "Enabled", "nic_selection": "Dedicated",
84                                   "failover_network": "ALL", "auto_detect": "Enabled", "auto_negotiation": "Enabled",
85                                   "network_speed": "T_10", "duplex_mode": "Full", "nic_mtu": "nicmtu",
86                                   "enable_dhcp": "Enabled", "ip_address": "100.100.102.114", "enable_ipv4": "Enabled",
87                                   "dns_from_dhcp": "Enabled", "static_dns_1": "staticdns1",
88                                   "static_dns_2": "staticdns2", "static_gateway": "staticgateway",
89                                   "static_net_mask": "staticnetmask"})
90        message = {"changes_applicable": True, "message": "changes are applicable"}
91        idrac_connection_configure_network_mock.config_mgr.is_change_applicable.return_value = message
92        f_module = self.get_module_mock(params=idrac_default_args, check_mode=True)
93        msg = self.module.run_idrac_network_config(idrac_connection_configure_network_mock, f_module)
94        assert msg == {'changes_applicable': True, 'message': 'changes are applicable'}
95
96    def test_run_idrac_network_config_success_case02(self, idrac_connection_configure_network_mock, idrac_default_args,
97                                                     idrac_file_manager_config_networking_mock):
98        idrac_default_args.update({"share_name": "sharename", "share_mnt": "mountname", "share_user": "shareuser",
99                                   "share_password": "sharepassword", "register_idrac_on_dns": "Enabled",
100                                   "dns_idrac_name": "testname", "auto_config": "Disabled", "static_dns": "staticdns",
101                                   "setup_idrac_nic_vlan": "Enabled", "vlan_id": 4, "vlan_priority": "Enabled",
102                                   "enable_nic": "Enabled", "nic_selection": "Dedicated",
103                                   "failover_network": "ALL", "auto_detect": "Enabled", "auto_negotiation": "Enabled",
104                                   "network_speed": "T_10", "duplex_mode": "Full", "nic_mtu": "nicmtu",
105                                   "enable_dhcp": "Enabled", "ip_address": "100.100.102.114", "enable_ipv4": "Enabled",
106                                   "dns_from_dhcp": "Enabled", "static_dns_1": "staticdns1",
107                                   "static_dns_2": "staticdns2", "static_gateway": "staticgateway",
108                                   "static_net_mask": "staticnetmask"})
109        message = {"changes_applicable": True, "message": "changes found to commit!", "changed": True,
110                   "Status": "Success"}
111        idrac_connection_configure_network_mock.config_mgr.apply_changes.return_value = message
112        f_module = self.get_module_mock(params=idrac_default_args)
113        f_module.check_mode = False
114        msg = self.module.run_idrac_network_config(idrac_connection_configure_network_mock, f_module)
115        assert msg == {'Status': 'Success',
116                       'changed': True,
117                       'changes_applicable': True,
118                       'message': 'changes found to commit!'}
119
120    def test_run_idrac_network_config_success_case03(self, idrac_connection_configure_network_mock, idrac_default_args,
121                                                     idrac_file_manager_config_networking_mock):
122        idrac_default_args.update({"share_name": "sharename", "share_mnt": "mountname", "share_user": "shareuser",
123                                   "share_password": "sharepassword", "register_idrac_on_dns": "Enabled",
124                                   "dns_idrac_name": "testname", "auto_config": "Disabled", "static_dns": "staticdns",
125                                   "setup_idrac_nic_vlan": "Enabled", "vlan_id": 4, "vlan_priority": "Enabled",
126                                   "enable_nic": "Enabled", "nic_selection": "Dedicated",
127                                   "failover_network": "ALL", "auto_detect": "Enabled", "auto_negotiation": "Enabled",
128                                   "network_speed": "T_10", "duplex_mode": "Full", "nic_mtu": "nicmtu",
129                                   "enable_dhcp": "Enabled", "ip_address": "100.100.102.114", "enable_ipv4": "Enabled",
130                                   "dns_from_dhcp": "Enabled", "static_dns_1": "staticdns1",
131                                   "static_dns_2": "staticdns2", "static_gateway": "staticgateway",
132                                   "static_net_mask": "staticnetmask"})
133        message = {"changes_applicable": False, "Message": "No changes found to commit!", "changed": False,
134                   "Status": "Success"}
135        idrac_connection_configure_network_mock.config_mgr.apply_changes.return_value = message
136        f_module = self.get_module_mock(params=idrac_default_args)
137        f_module.check_mode = False
138        msg = self.module.run_idrac_network_config(idrac_connection_configure_network_mock, f_module)
139        assert msg == {'Message': 'No changes found to commit!',
140                       'Status': 'Success',
141                       'changed': False,
142                       'changes_applicable': False}
143
144    def test_run_idrac_network_config_success_case04(self, idrac_connection_configure_network_mock,
145                                                     idrac_default_args, idrac_file_manager_config_networking_mock):
146        idrac_default_args.update({"share_name": "sharename", "share_mnt": "mountname", "share_user": "shareuser",
147                                   "share_password": "sharepassword", "register_idrac_on_dns": "Enabled",
148                                   "dns_idrac_name": "testname", "auto_config": "Disabled", "static_dns": "staticdns",
149                                   "setup_idrac_nic_vlan": "Enabled", "vlan_id": 4, "vlan_priority": "Enabled",
150                                   "enable_nic": "Enabled", "nic_selection": "Dedicated",
151                                   "failover_network": "ALL", "auto_detect": "Enabled", "auto_negotiation": "Enabled",
152                                   "network_speed": "T_10", "duplex_mode": "Full", "nic_mtu": "nicmtu",
153                                   "enable_dhcp": "Enabled", "ip_address": "100.100.102.114", "enable_ipv4": "Enabled",
154                                   "dns_from_dhcp": "Enabled", "static_dns_1": "staticdns1",
155                                   "static_dns_2": "staticdns2", "static_gateway": "staticgateway",
156                                   "static_net_mask": "staticnetmask"})
157        message = {"changes_applicable": False, "Message": "No changes were applied", "changed": False,
158                   "Status": "Success"}
159        idrac_connection_configure_network_mock.config_mgr.apply_changes.return_value = message
160        f_module = self.get_module_mock(params=idrac_default_args)
161        f_module.check_mode = False
162        msg = self.module.run_idrac_network_config(idrac_connection_configure_network_mock, f_module)
163        assert msg == {'Message': 'No changes were applied',
164                       'Status': 'Success',
165                       'changed': False,
166                       'changes_applicable': False}
167
168    def test_run_idrac_network_config_success_case05(self, idrac_connection_configure_network_mock, idrac_default_args,
169                                                     idrac_file_manager_config_networking_mock):
170        idrac_default_args.update({"share_name": "sharename", "share_mnt": "mountname", "share_user": "shareuser",
171                                   "share_password": "sharepassword", "register_idrac_on_dns": None,
172                                   "dns_idrac_name": None, "auto_config": None, "static_dns": None,
173                                   "setup_idrac_nic_vlan": None, "vlan_id": None, "vlan_priority": None,
174                                   "enable_nic": None, "nic_selection": None,
175                                   "failover_network": None, "auto_detect": None, "auto_negotiation": None,
176                                   "network_speed": None, "duplex_mode": None, "nic_mtu": None,
177                                   "enable_dhcp": None, "ip_address": None, "enable_ipv4": None,
178                                   "dns_from_dhcp": None, "static_dns_1": None, "static_dns_2": None,
179                                   "static_gateway": None, "static_net_mask": None})
180        message = {"changes_applicable": False, "Message": "No changes were applied", "changed": False,
181                   "Status": "Success"}
182        idrac_connection_configure_network_mock.config_mgr.configure_dns.return_value = message
183        idrac_connection_configure_network_mock.config_mgr.configure_nic_vlan.return_value = message
184        idrac_connection_configure_network_mock.config_mgr.configure_network_settings.return_value = message
185        idrac_connection_configure_network_mock.config_mgr.configure_ipv4.return_value = message
186        idrac_connection_configure_network_mock.config_mgr.configure_static_ipv4.return_value = message
187        idrac_connection_configure_network_mock.config_mgr.apply_changes.return_value = message
188        f_module = self.get_module_mock(params=idrac_default_args)
189        f_module.check_mode = False
190        msg = self.module.run_idrac_network_config(idrac_connection_configure_network_mock, f_module)
191        assert msg == {'Message': 'No changes were applied',
192                       'Status': 'Success',
193                       'changed': False,
194                       'changes_applicable': False}
195
196    def test_run_idrac_network_config_failed_case01(self, idrac_connection_configure_network_mock, idrac_default_args,
197                                                    idrac_file_manager_config_networking_mock):
198        idrac_default_args.update({"share_name": "sharename", "share_mnt": "mountname", "share_user": "shareuser",
199                                   "share_password": "sharepassword", "register_idrac_on_dns": "Enabled",
200                                   "dns_idrac_name": "testname", "auto_config": "Disabled", "static_dns": "staticdns",
201                                   "setup_idrac_nic_vlan": "Enabled", "vlan_id": 4, "vlan_priority": "Enabled",
202                                   "enable_nic": "Enabled", "nic_selection": "Dedicated",
203                                   "failover_network": "ALL", "auto_detect": "Enabled", "auto_negotiation": "Enabled",
204                                   "network_speed": "T_10", "duplex_mode": "Full", "nic_mtu": "nicmtu",
205                                   "enable_dhcp": "Enabled", "ip_address": "100.100.102.114", "enable_ipv4": "Enabled",
206                                   "dns_from_dhcp": "Enabled", "static_dns_1": "staticdns1",
207                                   "static_dns_2": "staticdns2", "static_gateway": "staticgateway",
208                                   "static_net_mask": "staticnetmask"})
209        message = {'Status': 'Failed', "Data": {'Message': 'status failed in checking Data'}}
210        idrac_connection_configure_network_mock.file_share_manager.create_share_obj.return_value = "mnt/iso"
211        idrac_connection_configure_network_mock.config_mgr.set_liason_share.return_value = message
212        f_module = self.get_module_mock(params=idrac_default_args, check_mode=True)
213        result = self.module.run_idrac_network_config(idrac_connection_configure_network_mock, f_module)
214        assert result == idrac_connection_configure_network_mock.config_mgr.is_change_applicable()
215
216    def test_run_idrac_network_config_failed_case02(self, idrac_connection_configure_network_mock,
217                                                    idrac_default_args, idrac_file_manager_config_networking_mock):
218        idrac_default_args.update({"share_name": "sharename", "share_mnt": "mountname", "share_user": "shareuser",
219                                   "share_password": "sharepassword", "register_idrac_on_dns": "Enabled",
220                                   "dns_idrac_name": "testname", "auto_config": "Disabled", "static_dns": "staticdns",
221                                   "setup_idrac_nic_vlan": "Enabled", "vlan_id": 4, "vlan_priority": "Enabled",
222                                   "enable_nic": "Enabled", "nic_selection": "Dedicated",
223                                   "failover_network": "ALL", "auto_detect": "Enabled", "auto_negotiation": "Enabled",
224                                   "network_speed": "T_10", "duplex_mode": "Full", "nic_mtu": "nicmtu",
225                                   "enable_dhcp": "Enabled", "ip_address": "100.100.102.114", "enable_ipv4": "Enabled",
226                                   "dns_from_dhcp": "Enabled", "static_dns_1": "staticdns1",
227                                   "static_dns_2": "staticdns2", "static_gateway": "staticgateway",
228                                   "static_net_mask": "staticnetmask"})
229        message = {"changes_applicable": False, "Message": "No changes were applied", "changed": False,
230                   "Status": "failed"}
231        idrac_connection_configure_network_mock.config_mgr.apply_changes.return_value = message
232        f_module = self.get_module_mock(params=idrac_default_args)
233        f_module.check_mode = False
234        msg = self.module.run_idrac_network_config(idrac_connection_configure_network_mock, f_module)
235        assert msg == {'Message': 'No changes were applied',
236                       'Status': 'failed',
237                       'changed': False,
238                       'changes_applicable': False}
239
240    def test_run_idrac_network_config_failed_case03(self, idrac_connection_configure_network_mock,
241                                                    idrac_default_args, idrac_file_manager_config_networking_mock):
242        idrac_default_args.update({"share_name": "sharename", "share_mnt": "mountname", "share_user": "shareuser",
243                                   "share_password": "sharepassword", "register_idrac_on_dns": "Enabled",
244                                   "dns_idrac_name": "testname", "auto_config": "Disabled", "static_dns": "staticdns",
245                                   "setup_idrac_nic_vlan": "Enabled", "vlan_id": 4, "vlan_priority": "Enabled",
246                                   "enable_nic": "Enabled", "nic_selection": "Dedicated",
247                                   "failover_network": "ALL", "auto_detect": "Enabled", "auto_negotiation": "Enabled",
248                                   "network_speed": "T_10", "duplex_mode": "Full", "nic_mtu": "nicmtu",
249                                   "enable_dhcp": "Enabled", "ip_address": "100.100.102.114", "enable_ipv4": "Enabled",
250                                   "dns_from_dhcp": "Enabled", "static_dns_1": "staticdns1",
251                                   "static_dns_2": "staticdns2", "static_gateway": "staticgateway",
252                                   "static_net_mask": "staticnetmask"})
253        message = {'Status': 'Failed', "Data": {'Message': "Failed to found changes"}}
254        idrac_connection_configure_network_mock.file_share_manager.create_share_obj.return_value = "mnt/iso"
255        idrac_connection_configure_network_mock.config_mgr.set_liason_share.return_value = message
256        f_module = self.get_module_mock(params=idrac_default_args, check_mode=True)
257        msg = self.module.run_idrac_network_config(idrac_connection_configure_network_mock, f_module)
258        assert msg == idrac_connection_configure_network_mock.config_mgr.is_change_applicable()
259
260    @pytest.mark.parametrize("exc_type", [RuntimeError, SSLValidationError, ConnectionError, KeyError,
261                                          ImportError, ValueError, TypeError, HTTPError, URLError])
262    def test_main_idrac_configure_network_exception_handling_case(self, exc_type, mocker, idrac_default_args,
263                                                                  idrac_connection_configure_network_mock,
264                                                                  idrac_file_manager_config_networking_mock):
265        idrac_default_args.update({"share_name": "sharename"})
266        json_str = to_text(json.dumps({"data": "out"}))
267        if exc_type not in [HTTPError, SSLValidationError]:
268            mocker.patch(
269                MODULE_PATH + 'idrac_network.run_idrac_network_config',
270                side_effect=exc_type('test'))
271        else:
272            mocker.patch(
273                MODULE_PATH + 'idrac_network.run_idrac_network_config',
274                side_effect=exc_type('http://testhost.com', 400, 'http error message',
275                                     {"accept-type": "application/json"}, StringIO(json_str)))
276        if not exc_type == URLError:
277            result = self._run_module_with_fail_json(idrac_default_args)
278            assert result['failed'] is True
279        else:
280            result = self._run_module(idrac_default_args)
281        assert 'msg' in result
282