summaryrefslogtreecommitdiffstats
path: root/ansible_collections/dellemc/powerflex/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:22 +0000
commit38b7c80217c4e72b1d8988eb1e60bb6e77334114 (patch)
tree356e9fd3762877d07cde52d21e77070aeff7e789 /ansible_collections/dellemc/powerflex/tests
parentAdding upstream version 7.7.0+dfsg. (diff)
downloadansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.tar.xz
ansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.zip
Adding upstream version 9.4.0+dfsg.upstream/9.4.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/dellemc/powerflex/tests')
-rw-r--r--ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.13.txt11
-rw-r--r--ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.14.txt31
-rw-r--r--ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.15.txt42
-rw-r--r--ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.16.txt28
-rw-r--r--ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.17.txt (renamed from ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.12.txt)2
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/__init__.py0
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/fail_json.py21
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/initial_mock.py17
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/powerflex_unit_base.py40
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_device_api.py146
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_fail_json.py21
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_fault_set_api.py69
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_info_api.py105
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_protection_domain_api.py124
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_replication_consistency_group_api.py1
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_replication_pair_api.py11
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_sdc_api.py64
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_sds_api.py147
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_snapshot_policy_api.py186
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_storagepool_api.py166
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_volume_api.py64
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_device.py471
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_fault_set.py215
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_info.py475
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_protection_domain.py542
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_replication_consistency_group.py125
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_replication_pair.py132
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_sdc.py192
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_sds.py630
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_snapshot_policy.py502
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_storagepool.py355
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_volume.py664
-rw-r--r--ansible_collections/dellemc/powerflex/tests/unit/requirements.txt (renamed from ansible_collections/dellemc/powerflex/tests/requirements.txt)0
33 files changed, 5253 insertions, 346 deletions
diff --git a/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.13.txt b/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.13.txt
deleted file mode 100644
index c78903cdf..000000000
--- a/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.13.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-plugins/modules/device.py validate-modules:missing-gplv3-license
-plugins/modules/sdc.py validate-modules:missing-gplv3-license
-plugins/modules/sds.py validate-modules:missing-gplv3-license
-plugins/modules/snapshot.py validate-modules:missing-gplv3-license
-plugins/modules/storagepool.py validate-modules:missing-gplv3-license
-plugins/modules/volume.py validate-modules:missing-gplv3-license
-plugins/modules/info.py validate-modules:missing-gplv3-license
-plugins/modules/protection_domain.py validate-modules:missing-gplv3-license
-plugins/modules/mdm_cluster.py validate-modules:missing-gplv3-license
-plugins/modules/replication_consistency_group.py validate-modules:missing-gplv3-license
-plugins/modules/replication_pair.py validate-modules:missing-gplv3-license
diff --git a/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.14.txt b/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.14.txt
index c78903cdf..cb6ef4675 100644
--- a/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.14.txt
+++ b/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.14.txt
@@ -1,3 +1,18 @@
+plugins/modules/sds.py import-2.7
+plugins/modules/sds.py import-3.5
+plugins/modules/sds.py compile-2.7
+plugins/modules/sds.py compile-3.5
+plugins/modules/info.py import-2.7
+plugins/modules/info.py import-3.5
+plugins/modules/info.py compile-2.7
+plugins/modules/fault_set.py import-2.7
+plugins/modules/fault_set.py import-3.5
+plugins/modules/fault_set.py compile-2.7
+plugins/modules/fault_set.py compile-3.5
+plugins/module_utils/storage/dell/libraries/configuration.py import-2.7
+plugins/module_utils/storage/dell/libraries/configuration.py import-3.5
+plugins/module_utils/storage/dell/libraries/configuration.py compile-2.7
+plugins/module_utils/storage/dell/libraries/configuration.py compile-3.5
plugins/modules/device.py validate-modules:missing-gplv3-license
plugins/modules/sdc.py validate-modules:missing-gplv3-license
plugins/modules/sds.py validate-modules:missing-gplv3-license
@@ -9,3 +24,19 @@ plugins/modules/protection_domain.py validate-modules:missing-gplv3-license
plugins/modules/mdm_cluster.py validate-modules:missing-gplv3-license
plugins/modules/replication_consistency_group.py validate-modules:missing-gplv3-license
plugins/modules/replication_pair.py validate-modules:missing-gplv3-license
+plugins/modules/snapshot_policy.py validate-modules:missing-gplv3-license
+plugins/modules/fault_set.py validate-modules:missing-gplv3-license
+plugins/modules/snapshot_policy.py compile-2.7
+plugins/modules/snapshot_policy.py compile-3.5
+plugins/modules/snapshot_policy.py import-2.7
+plugins/modules/snapshot_policy.py import-3.5
+plugins/modules/sdc.py import-2.7
+plugins/modules/sdc.py import-3.5
+plugins/modules/sdc.py compile-2.7
+plugins/modules/sdc.py compile-3.5
+tests/unit/plugins/module_utils/mock_device_api.py compile-2.7
+tests/unit/plugins/module_utils/mock_device_api.py compile-3.5
+plugins/modules/replication_consistency_group.py import-2.7
+plugins/modules/replication_consistency_group.py import-3.5
+plugins/modules/replication_consistency_group.py compile-2.7
+plugins/modules/replication_consistency_group.py compile-3.5
diff --git a/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.15.txt b/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.15.txt
new file mode 100644
index 000000000..cb6ef4675
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.15.txt
@@ -0,0 +1,42 @@
+plugins/modules/sds.py import-2.7
+plugins/modules/sds.py import-3.5
+plugins/modules/sds.py compile-2.7
+plugins/modules/sds.py compile-3.5
+plugins/modules/info.py import-2.7
+plugins/modules/info.py import-3.5
+plugins/modules/info.py compile-2.7
+plugins/modules/fault_set.py import-2.7
+plugins/modules/fault_set.py import-3.5
+plugins/modules/fault_set.py compile-2.7
+plugins/modules/fault_set.py compile-3.5
+plugins/module_utils/storage/dell/libraries/configuration.py import-2.7
+plugins/module_utils/storage/dell/libraries/configuration.py import-3.5
+plugins/module_utils/storage/dell/libraries/configuration.py compile-2.7
+plugins/module_utils/storage/dell/libraries/configuration.py compile-3.5
+plugins/modules/device.py validate-modules:missing-gplv3-license
+plugins/modules/sdc.py validate-modules:missing-gplv3-license
+plugins/modules/sds.py validate-modules:missing-gplv3-license
+plugins/modules/snapshot.py validate-modules:missing-gplv3-license
+plugins/modules/storagepool.py validate-modules:missing-gplv3-license
+plugins/modules/volume.py validate-modules:missing-gplv3-license
+plugins/modules/info.py validate-modules:missing-gplv3-license
+plugins/modules/protection_domain.py validate-modules:missing-gplv3-license
+plugins/modules/mdm_cluster.py validate-modules:missing-gplv3-license
+plugins/modules/replication_consistency_group.py validate-modules:missing-gplv3-license
+plugins/modules/replication_pair.py validate-modules:missing-gplv3-license
+plugins/modules/snapshot_policy.py validate-modules:missing-gplv3-license
+plugins/modules/fault_set.py validate-modules:missing-gplv3-license
+plugins/modules/snapshot_policy.py compile-2.7
+plugins/modules/snapshot_policy.py compile-3.5
+plugins/modules/snapshot_policy.py import-2.7
+plugins/modules/snapshot_policy.py import-3.5
+plugins/modules/sdc.py import-2.7
+plugins/modules/sdc.py import-3.5
+plugins/modules/sdc.py compile-2.7
+plugins/modules/sdc.py compile-3.5
+tests/unit/plugins/module_utils/mock_device_api.py compile-2.7
+tests/unit/plugins/module_utils/mock_device_api.py compile-3.5
+plugins/modules/replication_consistency_group.py import-2.7
+plugins/modules/replication_consistency_group.py import-3.5
+plugins/modules/replication_consistency_group.py compile-2.7
+plugins/modules/replication_consistency_group.py compile-3.5
diff --git a/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.16.txt b/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.16.txt
new file mode 100644
index 000000000..531796f6c
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.16.txt
@@ -0,0 +1,28 @@
+plugins/modules/sds.py import-2.7
+plugins/modules/sds.py compile-2.7
+plugins/module_utils/storage/dell/libraries/configuration.py import-2.7
+plugins/module_utils/storage/dell/libraries/configuration.py compile-2.7
+plugins/modules/device.py validate-modules:missing-gplv3-license
+plugins/modules/sdc.py validate-modules:missing-gplv3-license
+plugins/modules/sds.py validate-modules:missing-gplv3-license
+plugins/modules/snapshot.py validate-modules:missing-gplv3-license
+plugins/modules/storagepool.py validate-modules:missing-gplv3-license
+plugins/modules/volume.py validate-modules:missing-gplv3-license
+plugins/modules/info.py validate-modules:missing-gplv3-license
+plugins/modules/protection_domain.py validate-modules:missing-gplv3-license
+plugins/modules/mdm_cluster.py validate-modules:missing-gplv3-license
+plugins/modules/replication_consistency_group.py validate-modules:missing-gplv3-license
+plugins/modules/replication_pair.py validate-modules:missing-gplv3-license
+plugins/modules/snapshot_policy.py validate-modules:missing-gplv3-license
+plugins/modules/fault_set.py validate-modules:missing-gplv3-license
+plugins/modules/snapshot_policy.py compile-2.7
+plugins/modules/snapshot_policy.py import-2.7
+plugins/modules/sdc.py import-2.7
+plugins/modules/sdc.py compile-2.7
+plugins/modules/fault_set.py import-2.7
+plugins/modules/fault_set.py compile-2.7
+tests/unit/plugins/module_utils/mock_device_api.py compile-2.7
+plugins/modules/replication_consistency_group.py import-2.7
+plugins/modules/replication_consistency_group.py compile-2.7
+plugins/modules/info.py compile-2.7
+plugins/modules/info.py import-2.7
diff --git a/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.12.txt b/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.17.txt
index c78903cdf..54067647b 100644
--- a/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.12.txt
+++ b/ansible_collections/dellemc/powerflex/tests/sanity/ignore-2.17.txt
@@ -9,3 +9,5 @@ plugins/modules/protection_domain.py validate-modules:missing-gplv3-license
plugins/modules/mdm_cluster.py validate-modules:missing-gplv3-license
plugins/modules/replication_consistency_group.py validate-modules:missing-gplv3-license
plugins/modules/replication_pair.py validate-modules:missing-gplv3-license
+plugins/modules/snapshot_policy.py validate-modules:missing-gplv3-license
+plugins/modules/fault_set.py validate-modules:missing-gplv3-license
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/__init__.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/__init__.py
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/fail_json.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/fail_json.py
new file mode 100644
index 000000000..d270326b9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/fail_json.py
@@ -0,0 +1,21 @@
+# Copyright: (c) 2024, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""Mock fail json for PowerFlex Test modules"""
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+
+class FailJsonException(Exception):
+ def __init__(self, *args):
+ if args:
+ self.message = args[0]
+ else:
+ self.message = None
+
+
+def fail_json(msg, **kwargs):
+ raise FailJsonException(msg)
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/initial_mock.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/initial_mock.py
new file mode 100644
index 000000000..7409ab4c2
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/initial_mock.py
@@ -0,0 +1,17 @@
+# Copyright: (c) 2024, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+from ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell \
+ import utils
+from mock.mock import MagicMock
+
+utils.get_logger = MagicMock()
+utils.get_powerflex_gateway_host_connection = MagicMock()
+utils.PowerFlexClient = MagicMock()
+
+from ansible.module_utils import basic
+basic.AnsibleModule = MagicMock()
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/powerflex_unit_base.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/powerflex_unit_base.py
new file mode 100644
index 000000000..0c06b0cd5
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/libraries/powerflex_unit_base.py
@@ -0,0 +1,40 @@
+# Copyright: (c) 2024, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+import pytest
+# pylint: disable=unused-import
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.libraries import initial_mock
+from mock.mock import MagicMock
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.libraries. \
+ fail_json import FailJsonException, fail_json
+
+
+class PowerFlexUnitBase:
+
+ '''Powerflex Unit Test Base Class'''
+
+ @pytest.fixture
+ def powerflex_module_mock(self, mocker, module_object):
+ powerflex_module_mock = module_object()
+ powerflex_module_mock.module = MagicMock()
+ powerflex_module_mock.module.fail_json = fail_json
+ powerflex_module_mock.module.check_mode = False
+ return powerflex_module_mock
+
+ def capture_fail_json_call(self, error_msg, module_mock, module_handler=None, invoke_perform_module=False):
+ try:
+ if not invoke_perform_module:
+ module_handler().handle(module_mock, module_mock.module.params)
+ else:
+ module_mock.perform_module_operation()
+ except FailJsonException as fj_object:
+ if error_msg not in fj_object.message:
+ raise AssertionError(fj_object.message)
+
+ def set_module_params(self, module_mock, get_module_args, params):
+ get_module_args.update(params)
+ module_mock.module.params = get_module_args
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_device_api.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_device_api.py
new file mode 100644
index 000000000..2a2cf8756
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_device_api.py
@@ -0,0 +1,146 @@
+# Copyright: (c) 2023, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""
+Mock Api response for Unit tests of Device module on Dell Technologies (Dell) PowerFlex
+"""
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+
+class MockDeviceApi:
+ MODULE_UTILS_PATH = "ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell.utils"
+
+ DEVICE_NAME_1 = "ansible_device_1"
+ DEVICE_ID_1 = "3fef781c00080000"
+ PD_ID_1 = "4eeb305100000001"
+ PD_NAME_1 = "domain1"
+ SDS_ID_1 = "6af03fc500000008"
+ SDS_NAME_1 = "ansible_sds_1"
+ SP_ID_1 = "7644c68600000008"
+ SP_NAME_1 = "ansible_sp_1"
+ PATH_1 = "/dev/sdb"
+
+ DEVICE_COMMON_ARGS = {
+ "hostname": "**.***.**.***",
+ "current_pathname": None,
+ "device_id": None,
+ "device_name": None,
+ "sds_name": None,
+ "sds_id": None,
+ "storage_pool_name": None,
+ "storage_pool_id": None,
+ "acceleration_pool_name": None,
+ "acceleration_pool_id": None,
+ "protection_domain_name": None,
+ "protection_domain_id": None,
+ "external_acceleration_type": None,
+ "media_type": None,
+ "state": None
+ }
+
+ DEVICE_GET_LIST = [
+ {
+ "accelerationPoolId": SP_ID_1,
+ "accelerationPoolName": SP_NAME_1,
+ "autoDetectMediaType": "Unknown",
+ "capacityLimitInKb": 124718080,
+ "deviceCurrentPathName": PATH_1,
+ "deviceOriginalPathName": PATH_1,
+ "externalAccelerationType": "ReadAndWrite",
+ "fglNvdimmWriteCacheSize": 16,
+ "id": DEVICE_ID_1,
+ "mediaType": "HDD",
+ "name": DEVICE_NAME_1,
+ "protectionDomainId": PD_ID_1,
+ "protectionDomainName": PD_NAME_1,
+ "sdsId": SDS_ID_1,
+ "sdsName": SDS_NAME_1,
+ "spSdsId": "bfe791ff00080000",
+ "storagePoolId": SP_ID_1,
+ "storagePoolName": SP_NAME_1
+ }
+ ]
+ SDS_DETAILS_1 = [
+ {
+ "name": SDS_NAME_1,
+ "id": SDS_ID_1
+ }
+ ]
+ PD_DETAILS_1 = [
+ {
+ "name": PD_NAME_1,
+ "id": PD_ID_1
+ }
+ ]
+ SP_DETAILS_1 = [
+ {
+ "name": SP_NAME_1,
+ "protectionDomainId": PD_ID_1,
+ "id": SP_ID_1
+ }
+ ]
+ AP_DETAILS_1 = [
+ {
+ "name": SP_NAME_1,
+ "protectionDomainId": PD_ID_1,
+ "id": SP_ID_1
+ }
+ ]
+
+ @staticmethod
+ def get_device_exception_response(response_type):
+ if response_type == 'get_dev_without_SDS':
+ return "sds_name or sds_id is mandatory along with device_name. Please enter a valid value"
+ elif response_type == 'get_device_details_without_path':
+ return "sds_name or sds_id is mandatory along with current_pathname. Please enter a valid value"
+ elif response_type == 'get_device_exception':
+ return "Failed to get the device with error"
+ elif response_type == 'create_id_exception':
+ return "Addition of device is allowed using device_name only, device_id given."
+ elif response_type == 'empty_path':
+ return "Please enter a valid value for current_pathname"
+ elif response_type == 'empty_device_name':
+ return "Please enter a valid value for device_name."
+ elif response_type == 'empty_sds':
+ return "Please enter a valid value for "
+ elif response_type == 'empty_dev_id':
+ return "Please provide valid device_id value to identify a device"
+ elif response_type == 'space_in_name':
+ return "current_pathname or device_name is mandatory along with sds"
+ elif response_type == 'with_required_params':
+ return "Please specify a valid parameter combination to identify a device"
+
+ @staticmethod
+ def get_device_exception_response1(response_type):
+ if response_type == 'modify_exception':
+ return "Modification of device attributes is currently not supported by Ansible modules."
+ elif response_type == 'delete_exception':
+ return f"Remove device '{MockDeviceApi.DEVICE_ID_1}' operation failed with error"
+ elif response_type == 'sds_exception':
+ return f"Unable to find the SDS with '{MockDeviceApi.SDS_NAME_1}'. Please enter a valid SDS name/id."
+ elif response_type == 'pd_exception':
+ return f"Unable to find the protection domain with " \
+ f"'{MockDeviceApi.PD_NAME_1}'. Please enter a valid " \
+ f"protection domain name/id"
+ elif response_type == 'sp_exception':
+ return f"Unable to find the storage pool with " \
+ f"'{MockDeviceApi.SP_NAME_1}'. Please enter a valid " \
+ f"storage pool name/id."
+ elif response_type == 'ap_exception':
+ return f"Unable to find the acceleration pool with " \
+ f"'{MockDeviceApi.SP_NAME_1}'. Please enter a valid " \
+ f"acceleration pool name/id."
+ elif response_type == 'add_exception':
+ return "Adding device ansible_device_1 operation failed with error"
+ elif response_type == 'add_dev_name_exception':
+ return "Please provide valid device_name value for adding a device"
+ elif response_type == 'add_dev_path_exception':
+ return "Current pathname of device is a mandatory parameter for adding a device. Please enter a valid value"
+ elif response_type == 'ext_type_exception':
+ return "Storage Pool ID/name or Acceleration Pool ID/name is mandatory along with external_acceleration_type."
+ elif response_type == 'add_without_pd':
+ return "Protection domain name/id is required to uniquely identify"
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_fail_json.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_fail_json.py
new file mode 100644
index 000000000..8e20402c0
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_fail_json.py
@@ -0,0 +1,21 @@
+# Copyright: (c) 2023, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""Mock fail json for PowerFlex Test modules"""
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+
+class FailJsonException(Exception):
+ def __init__(self, *args):
+ if args:
+ self.message = args[0]
+ else:
+ self.message = None
+
+
+def fail_json(msg):
+ raise FailJsonException(msg)
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_fault_set_api.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_fault_set_api.py
new file mode 100644
index 000000000..1072888a2
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_fault_set_api.py
@@ -0,0 +1,69 @@
+# Copyright: (c) 2024, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""
+Mock Api response for Unit tests of fault set module on Dell Technologies (Dell) PowerFlex
+"""
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+
+class MockFaultSetApi:
+ FAULT_SET_COMMON_ARGS = {
+ "hostname": "**.***.**.***",
+ "protection_domain_name": None,
+ "protection_domain_id": None,
+ "fault_set_name": None,
+ "fault_set_id": None,
+ "fault_set_new_name": None,
+ "state": None
+ }
+
+ FAULT_SET_GET_LIST = [
+ {
+ "protectionDomainId": "7bd6457000000000",
+ "name": "fault_set_name_1",
+ "id": "fault_set_id_1",
+ "links": []
+ }
+ ]
+
+ PROTECTION_DOMAIN = {
+ "protectiondomain": [
+ {
+ "id": "7bd6457000000000",
+ "name": "test_pd_1",
+ "protectionDomainState": "Active",
+ "overallIoNetworkThrottlingInKbps": 20480,
+ "rebalanceNetworkThrottlingInKbps": 10240,
+ "rebuildNetworkThrottlingInKbps": 10240,
+ "vtreeMigrationNetworkThrottlingInKbps": 10240,
+ "rfcacheEnabled": "false",
+ "rfcacheMaxIoSizeKb": 128,
+ "rfcacheOpertionalMode": "None",
+ "rfcachePageSizeKb": 64,
+ "storagePools": [
+ {
+ "id": "8d1cba1700000000",
+ "name": "pool1"
+ }
+ ]
+ }
+ ]
+ }
+
+ RESPONSE_EXEC_DICT = {
+ 'delete_fault_set_exception': "Removing Fault Set fault_set_id_1 failed with error",
+ 'rename_fault_set_exception': "Failed to rename the fault set instance",
+ 'create_fault_set_exception': "Create fault set test_fs_1 operation failed",
+ 'get_fault_set_exception': "Failed to get the Fault Set",
+ 'create_fault_set_wo_pd_exception': "Provide protection_domain_id/protection_domain_name with fault_set_name.",
+ 'create_fault_set_empty_name_exception': "Provide valid value for name for the creation/modification of the fault set."
+ }
+
+ @staticmethod
+ def get_fault_set_exception_response(response_type):
+ return MockFaultSetApi.RESPONSE_EXEC_DICT.get(response_type, "")
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_info_api.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_info_api.py
index e2ef01fe7..20de1c1c9 100644
--- a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_info_api.py
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_info_api.py
@@ -1,4 +1,4 @@
-# Copyright: (c) 2022, Dell Technologies
+# Copyright: (c) 2024, Dell Technologies
# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -13,12 +13,16 @@ from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_
import MockReplicationConsistencyGroupApi
from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_replication_pair_api \
import MockReplicationPairApi
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_snapshot_policy_api \
+ import MockSnapshotPolicyApi
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_fault_set_api import MockFaultSetApi
__metaclass__ = type
class MockInfoApi:
+ MODULE_UTILS_PATH = "ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell.utils"
INFO_COMMON_ARGS = {
"hostname": "**.***.**.***",
"gather_subset": [],
@@ -219,6 +223,12 @@ class MockInfoApi:
'test_vol_id_1': MockVolumeApi.VOLUME_STATISTICS
}
+ INFO_SNAPSHOT_POLICY_GET_LIST = MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+
+ INFO_SNAPSHOT_POLICY_STATISTICS = {
+ 'test_snap_pol_id_1': MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ }
+
INFO_STORAGE_POOL_GET_LIST = MockStoragePoolApi.STORAGE_POOL_GET_LIST
INFO_STORAGE_POOL_STATISTICS = {
@@ -228,13 +238,90 @@ class MockInfoApi:
RCG_LIST = MockReplicationConsistencyGroupApi.get_rcg_details()
PAIR_LIST = MockReplicationPairApi.get_pair_details()
+ INFO_GET_FAULT_SET_LIST = MockFaultSetApi.FAULT_SET_GET_LIST
+
+ INFO_SDC_GET_LIST = [
+ {
+ "id": "07335d3d00000006",
+ "name": "sdc_1"
+ },
+ {
+ "id": "07335d3c00000005",
+ "name": "sdc_2"
+ },
+ {
+ "id": "0733844a00000003",
+ "name": "sdc_3"
+ }
+ ]
+
+ INFO_SDC_FILTER_LIST = [
+ {
+ "id": "07335d3d00000006",
+ "name": "sdc_1"
+ }
+ ]
+
+ INFO_SDS_GET_LIST = [
+ {
+ "id": "8f3bb0cc00000002",
+ "name": "node0"
+ },
+ {
+ "id": "8f3bb0ce00000000",
+ "name": "node1"
+ },
+ {
+ "id": "8f3bb15300000001",
+ "name": "node22"
+ }
+ ]
+ INFO_GET_PD_LIST = [
+ {
+ "id": "9300e90900000001",
+ "name": "domain2"
+ },
+ {
+ "id": "9300c1f900000000",
+ "name": "domain1"
+ }
+ ]
+ INFO_GET_DEVICE_LIST = [
+ {
+ "id": "b6efa59900000000",
+ "name": "device230"
+ },
+ {
+ "id": "b6efa5fa00020000",
+ "name": "device_node0"
+ },
+ {
+ "id": "b7f3a60900010000",
+ "name": "device22"
+ }
+ ]
+
+ RESPONSE_EXEC_DICT = {
+ 'volume_get_details': "Get volumes list from powerflex array failed with error",
+ 'snapshot_policy_get_details': "Get snapshot policies list from powerflex array failed with error ",
+ 'sp_get_details': "Get storage pool list from powerflex array failed with error ",
+ 'rcg_get_details': "Get replication consistency group list from powerflex array failed with error ",
+ 'replication_pair_get_details': "Get replication pair list from powerflex array failed with error ",
+ 'fault_set_get_details': "Get fault set list from powerflex array failed with error",
+ 'sdc_get_details': "Get SDC list from powerflex array failed with error",
+ 'sds_get_details': "Get SDS list from powerflex array failed with error",
+ 'pd_get_details': "Get protection domain list from powerflex array failed with error",
+ 'device_get_details': "Get device list from powerflex array failed with error",
+ 'get_sds_details_filter_invalid': "Filter should have all keys: 'filter_key, filter_operator, filter_value'",
+ 'get_sds_details_filter_empty': "Filter keys: '['filter_key', 'filter_operator', 'filter_value']' cannot be None",
+ 'invalid_filter_operator_exception': "Given filter operator 'does_not_contain' is not supported.",
+ 'api_exception': "Get API details from Powerflex array failed with error",
+ 'system_exception': "Get array details from Powerflex array failed with error",
+ 'managed_device_get_error': "Get managed devices from PowerFlex Manager failed with error",
+ 'service_template_get_error': "Get service templates from PowerFlex Manager failed with error",
+ 'deployment_get_error': "Get deployments from PowerFlex Manager failed with error"
+ }
+
@staticmethod
def get_exception_response(response_type):
- if response_type == 'volume_get_details':
- return "Get volumes list from powerflex array failed with error "
- elif response_type == 'sp_get_details':
- return "Get storage pool list from powerflex array failed with error "
- elif response_type == 'rcg_get_details':
- return "Get replication consistency group list from powerflex array failed with error "
- elif response_type == 'replication_pair_get_details':
- return "Get replication pair list from powerflex array failed with error "
+ return MockInfoApi.RESPONSE_EXEC_DICT.get(response_type, "")
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_protection_domain_api.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_protection_domain_api.py
index 60452ecda..bab9a832c 100644
--- a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_protection_domain_api.py
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_protection_domain_api.py
@@ -1,4 +1,4 @@
-# Copyright: (c) 2022, Dell Technologies
+# Copyright: (c) 2024, Dell Technologies
# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -15,54 +15,86 @@ class MockProtectionDomainApi:
MODULE_PATH = 'ansible_collections.dellemc.powerflex.plugins.modules.protection_domain.PowerFlexProtectionDomain'
MODULE_UTILS_PATH = 'ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell.utils'
- PROTECTION_DOMAIN = {
- "protectiondomain": [
- {
- "id": "7bd6457000000000",
- "name": "test_domain",
- "protectionDomainState": "Active",
- "overallIoNetworkThrottlingInKbps": 20480,
- "rebalanceNetworkThrottlingInKbps": 10240,
- "rebuildNetworkThrottlingInKbps": 10240,
- "vtreeMigrationNetworkThrottlingInKbps": 10240,
- "rfcacheEnabled": "false",
- "rfcacheMaxIoSizeKb": 128,
- "rfcacheOpertionalMode": "None",
- "rfcachePageSizeKb": 64,
- "storagePools": [
- {
- "id": "8d1cba1700000000",
- "name": "pool1"
- }
- ]
- }
- ]
- }
- STORAGE_POOL = {
- "storagepool": [
- {
- "protectionDomainId": "7bd6457000000000",
- "rebuildEnabled": True,
- "mediaType": "HDD",
- "name": "pool1",
- "id": "8d1cba1700000000"
- }
- ]
+ PD_COMMON_ARGS = {
+ 'hostname': '**.***.**.***',
+ 'protection_domain_id': None,
+ 'protection_domain_name': None,
+ 'protection_domain_new_name': None,
+ 'is_active': None,
+ 'network_limits': None,
+ 'rf_cache_limits': None,
+ 'state': 'present'
}
+ PD_NAME = 'test_domain'
+ PD_NEW_NAME = 'test_domain_new'
+ PD_ID = '7bd6457000000000'
- @staticmethod
- def modify_pd_with_failed_msg(protection_domain_name):
- return "Failed to update the rf cache limits of protection domain " + protection_domain_name + " with error "
+ PROTECTION_DOMAIN = [
+ {
+ "id": "7bd6457000000000",
+ "name": "test_domain",
+ "protectionDomainState": "Active",
+ "overallIoNetworkThrottlingInKbps": 20480,
+ "rebalanceNetworkThrottlingInKbps": 10240,
+ "rebuildNetworkThrottlingInKbps": 10240,
+ "vtreeMigrationNetworkThrottlingInKbps": 10240,
+ "rfcacheEnabled": "false",
+ "rfcacheMaxIoSizeKb": 128,
+ "rfcacheOpertionalMode": "None",
+ "rfcachePageSizeKb": 64,
+ "storagePools": [
+ {
+ "id": "8d1cba1700000000",
+ "name": "pool1"
+ }
+ ]
+ }
+ ]
- @staticmethod
- def delete_pd_failed_msg(protection_domain_id):
- return "Delete protection domain '" + protection_domain_id + "' operation failed with error ''"
+ PROTECTION_DOMAIN_1 = [
+ {
+ "id": "7bd6457000000000",
+ "name": "test_domain",
+ "protectionDomainState": "Inactive",
+ "overallIoNetworkThrottlingInKbps": 20480,
+ "rebalanceNetworkThrottlingInKbps": 10240,
+ "rebuildNetworkThrottlingInKbps": 10240,
+ "vtreeMigrationNetworkThrottlingInKbps": 10240,
+ "rfcacheEnabled": "false",
+ "rfcacheMaxIoSizeKb": 128,
+ "rfcacheOpertionalMode": "None",
+ "rfcachePageSizeKb": 64,
+ "storagePools": [
+ {
+ "id": "8d1cba1700000000",
+ "name": "pool1"
+ }
+ ]
+ }
+ ]
- @staticmethod
- def rename_pd_failed_msg(protection_domain_name):
- return "Failed to update the protection domain " + protection_domain_name + " with error "
+ STORAGE_POOL = [
+ {
+ "protectionDomainId": "7bd6457000000000",
+ "rebuildEnabled": True,
+ "mediaType": "HDD",
+ "name": "pool1",
+ "id": "8d1cba1700000000"
+ }
+ ]
@staticmethod
- def version_pd_failed_msg():
- return "Getting PyPowerFlex SDK version, failed with Error The 'PyPowerFlex' distribution was " \
- "not found and is required by the application"
+ def get_failed_msgs(response_type):
+ error_msg = {
+ 'get_pd_failed_msg': "Failed to get the protection domain ",
+ 'empty_pd_msg': "Please provide the valid protection_domain_name",
+ 'overall_limit_msg': "Overall limit cannot be negative. Provide a valid value",
+ 'new_name_in_create': "protection_domain_new_name/protection_domain_id are not supported during creation of protection domain",
+ 'create_pd_exception': "operation failed with error",
+ 'rename_pd_exception': "Failed to update the protection domain 7bd6457000000000 with error",
+ 'modify_network_limits_exception': "Failed to update the network limits of protection domain",
+ 'rf_cache_limits_exception': "Failed to update the rf cache limits of protection domain",
+ 'delete_pd_exception': "Delete protection domain '7bd6457000000000' operation failed with error ''",
+ 'get_sp_exception': "Failed to get the storage pools present in protection domain",
+ }
+ return error_msg.get(response_type)
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_replication_consistency_group_api.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_replication_consistency_group_api.py
index 6671fd875..0867024f5 100644
--- a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_replication_consistency_group_api.py
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_replication_consistency_group_api.py
@@ -23,6 +23,7 @@ class MockReplicationConsistencyGroupApi:
"verifycert": None, "port": None, "protection_domain_name": None,
"protection_domain_id": None},
"target_volume_access_mode": None, "is_consistent": None,
+ "rcg_state": None, "force": None,
"state": None
}
RCG_ID = "aadc17d500000000"
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_replication_pair_api.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_replication_pair_api.py
index f621db47e..5ac7010cf 100644
--- a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_replication_pair_api.py
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_replication_pair_api.py
@@ -1,4 +1,4 @@
-# Copyright: (c) 2023, Dell Technologies
+# Copyright: (c) 2024, Dell Technologies
# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -48,3 +48,12 @@ class MockReplicationPairApi:
def get_volume_details():
return [{"id": "0001",
"name": "volume1"}]
+
+ @staticmethod
+ def get_error_message(response_type):
+ error_msg = {"get_rcg_exception": "Failed to get the replication consistency group 12 with error ",
+ "get_rcg_id_name_error": "Specify either rcg_id or rcg_name to create replication pair",
+ "get_pause_error": "Specify either pair_id or pair_name to perform pause or resume of initial copy",
+ "get_pause_or_resume_error": "Specify a valid pair_name or pair_id to perform pause or resume",
+ "get_volume_exception": "Failed to retrieve volume"}
+ return error_msg[response_type]
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_sdc_api.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_sdc_api.py
new file mode 100644
index 000000000..ba65bc67f
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_sdc_api.py
@@ -0,0 +1,64 @@
+# Copyright: (c) 2024, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""
+Mock Api response for Unit tests of SDC module on Dell Technologies (Dell) PowerFlex
+"""
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+
+class MockSdcApi:
+ MODULE_UTILS_PATH = "ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell.utils"
+ COMMON_ARGS = {
+ "sdc_id": None,
+ "sdc_ip": None,
+ "sdc_name": None, "sdc_new_name": None,
+ "performance_profile": None,
+ "state": None
+ }
+ SDC_ID = "07335d3d00000006"
+
+ @staticmethod
+ def get_sdc_details():
+ return [{
+ "id": "07335d3d00000006",
+ "installedSoftwareVersionInfo": "R3_6.0.0",
+ "kernelBuildNumber": None,
+ "kernelVersion": "3.10.0",
+ "mapped_volumes": [],
+ "mdmConnectionState": "Disconnected",
+ "memoryAllocationFailure": None,
+ "name": "LGLAP203",
+ "osType": "Linux",
+ "peerMdmId": None,
+ "perfProfile": "HighPerformance",
+ "sdcApproved": True,
+ "sdcApprovedIps": None,
+ "sdcGuid": "F8ECB844-23B8-4629-92BB-B6E49A1744CB",
+ "sdcIp": "N/A",
+ "sdcIps": None,
+ "sdcType": "AppSdc",
+ "sdrId": None,
+ "socketAllocationFailure": None,
+ "softwareVersionInfo": "R3_6.0.0",
+ "systemId": "4a54a8ba6df0690f",
+ "versionInfo": "R3_6.0.0"
+ }]
+
+ RESPONSE_EXEC_DICT = {
+ 'get_sdc_details_empty_sdc_id_exception': "Please provide valid sdc_id",
+ 'get_sdc_details_with_exception': "Failed to get the SDC 07335d3d00000006 with error",
+ 'get_sdc_details_mapped_volumes_with_exception': "Failed to get the volumes mapped to SDC",
+ 'modify_sdc_throws_exception': "Modifying performance profile of SDC 07335d3d00000006 failed with error",
+ 'rename_sdc_empty_new_name_exception': "Provide valid SDC name to rename to.",
+ 'rename_sdc_throws_exception': "Failed to rename SDC",
+ 'remove_sdc_throws_exception': "Removing SDC 07335d3d00000006 failed with error"
+ }
+
+ @staticmethod
+ def get_sdc_exception_response(response_type):
+ return MockSdcApi.RESPONSE_EXEC_DICT.get(response_type, "")
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_sds_api.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_sds_api.py
new file mode 100644
index 000000000..60b5f95e9
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_sds_api.py
@@ -0,0 +1,147 @@
+# Copyright: (c) 2024, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""
+Mock Api response for Unit tests of SDS module on Dell Technologies (Dell) PowerFlex
+"""
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+
+class MockSDSApi:
+ SDS_COMMON_ARGS = {
+ "hostname": "**.***.**.***",
+ "sds_name": "test_node0",
+ "sds_id": None,
+ "sds_new_name": None,
+ "sds_ip_list": None,
+ "sds_ip_state": None,
+ "rfcache_enabled": None,
+ "rmcache_enabled": None,
+ "rmcache_size": None,
+ "performance_profile": None,
+ "protection_domain_name": None,
+ "protection_domain_id": None,
+ "fault_set_name": None,
+ "fault_set_id": None,
+ "fault_set_new_name": None,
+ "state": None
+ }
+
+ SDS_GET_LIST = [
+ {
+ "authenticationError": "None",
+ "certificateInfo": None,
+ "configuredDrlMode": "Volatile",
+ "drlMode": "Volatile",
+ "faultSetId": "test_id_1",
+ "fglMetadataCacheSize": 0,
+ "fglMetadataCacheState": "Disabled",
+ "fglNumConcurrentWrites": 1000,
+ "id": "8f3bb0cc00000002",
+ "ipList": [
+ {
+ "ip": "10.47.xxx.xxx",
+ "role": "all"
+ },
+ {
+ "ip": "10.46.xxx.xxx",
+ "role": "sdcOnly"
+ }
+ ],
+ "lastUpgradeTime": 0,
+ "links": [],
+ "maintenanceState": "NoMaintenance",
+ "maintenanceType": "NoMaintenance",
+ "mdmConnectionState": "Connected",
+ "membershipState": "Joined",
+ "name": "test_node0",
+ "numOfIoBuffers": None,
+ "numRestarts": 2,
+ "onVmWare": True,
+ "perfProfile": "HighPerformance",
+ "port": 7072,
+ "protectionDomainId": "9300c1f900000000",
+ "protectionDomainName": "test_domain",
+ "raidControllers": None,
+ "rfcacheEnabled": True,
+ "rfcacheErrorApiVersionMismatch": False,
+ "rfcacheErrorDeviceDoesNotExist": False,
+ "rfcacheErrorInconsistentCacheConfiguration": False,
+ "rfcacheErrorInconsistentSourceConfiguration": False,
+ "rfcacheErrorInvalidDriverPath": False,
+ "rfcacheErrorLowResources": False,
+ "rmcacheEnabled": True,
+ "rmcacheFrozen": False,
+ "rmcacheMemoryAllocationState": "AllocationPending",
+ "rmcacheSizeInKb": 131072,
+ "rmcacheSizeInMb": 128,
+ "sdsConfigurationFailure": None,
+ "sdsDecoupled": None,
+ "sdsReceiveBufferAllocationFailures": None,
+ "sdsState": "Normal",
+ "softwareVersionInfo": "R3_6.0.0"
+ }
+ ]
+
+ PROTECTION_DOMAIN = {
+ "protectiondomain": [
+ {
+ "id": "7bd6457000000000",
+ "name": "test_domain",
+ "protectionDomainState": "Active",
+ "overallIoNetworkThrottlingInKbps": 20480,
+ "rebalanceNetworkThrottlingInKbps": 10240,
+ "rebuildNetworkThrottlingInKbps": 10240,
+ "vtreeMigrationNetworkThrottlingInKbps": 10240,
+ "rfcacheEnabled": "false",
+ "rfcacheMaxIoSizeKb": 128,
+ "rfcacheOpertionalMode": "None",
+ "rfcachePageSizeKb": 64,
+ "storagePools": [
+ {
+ "id": "8d1cba1700000000",
+ "name": "pool1"
+ }
+ ]
+ }
+ ]
+ }
+
+ FAULT_SET_GET_LIST = [
+ {
+ "protectionDomainId": "test_domain",
+ "name": "fault_set_name",
+ "id": "fault_set_id",
+ "links": []
+ }
+ ]
+
+ RESPONSE_EXEC_DICT = {
+ "delete_sds_exception": "Delete SDS '8f3bb0cc00000002' operation failed with error",
+ "rename_sds_exception": "Failed to update the SDS",
+ "create_sds_exception": "Create SDS test_node0 operation failed with error",
+ "get_sds_exception": "Failed to get the SDS",
+ "rmcache_size_exception": "RM cache size can be set only when RM cache is enabled",
+ "create_sds_wo_sds_name": "Please provide valid sds_name value for creation of SDS.",
+ "create_sds_wo_pd": "Protection Domain is a mandatory parameter",
+ "create_sds_wo_sds_ip_list": "Please provide valid sds_ip_list values for " +
+ "creation of SDS.",
+ "create_sds_incorrect_sds_ip_state": "Incorrect IP state given for creation of SDS.",
+ "create_sds_sds_id": "Creation of SDS is allowed using sds_name " +
+ "only, sds_id given.",
+ "create_sds_sds_new_name": "sds_new_name parameter is not supported " +
+ "during creation of a SDS. Try renaming the " +
+ "SDS after the creation.",
+ "rename_sds_empty_exception": "Provide valid value for name for the creation/modification of the SDS.",
+ "add_ip_exception": "Add IP to SDS '8f3bb0cc00000002' operation failed with error ",
+ "remove_ip_exception": "Remove IP from SDS '8f3bb0cc00000002' operation failed with error ",
+ "set_ip_role_exception": "Update role of IP for SDS '8f3bb0cc00000002' operation failed"
+ }
+
+ @staticmethod
+ def get_sds_exception_response(response_type):
+ return MockSDSApi.RESPONSE_EXEC_DICT.get(response_type, "")
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_snapshot_policy_api.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_snapshot_policy_api.py
new file mode 100644
index 000000000..35dabb9fd
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_snapshot_policy_api.py
@@ -0,0 +1,186 @@
+# Copyright: (c) 2023, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""
+Mock Api response for Unit tests of snapshot policy module on Dell Technologies (Dell) PowerFlex
+"""
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+
+class MockSnapshotPolicyApi:
+ SNAPSHOT_POLICY_COMMON_ARGS = {
+ "hostname": "**.***.**.***",
+ "snapshot_policy_name": None,
+ "snapshot_policy_id": None,
+ "new_name": None,
+ "access_mode": None,
+ "secure_snapshots": None,
+ "auto_snapshot_creation_cadence": {
+ "time": None,
+ "unit": "Minute"},
+ "num_of_retained_snapshots_per_level": None,
+ "source_volume": None,
+ "source_volume_state": None,
+ "pause": None,
+ "state": None
+ }
+
+ SNAPSHOT_POLICY_GET_LIST = [
+ {
+ "autoSnapshotCreationCadenceInMin": 120,
+ "id": "15ae842500000004",
+ "lastAutoSnapshotCreationFailureReason": "NR",
+ "lastAutoSnapshotFailureInFirstLevel": False,
+ "maxVTreeAutoSnapshots": 40,
+ "name": "Ansible_snap_policy_1",
+ "nextAutoSnapshotCreationTime": 1683617581,
+ "numOfAutoSnapshots": 0,
+ "numOfCreationFailures": 0,
+ "numOfExpiredButLockedSnapshots": 0,
+ "numOfLockedSnapshots": 0,
+ "numOfRetainedSnapshotsPerLevel": [
+ 40
+ ],
+ "numOfSourceVolumes": 0,
+ "secureSnapshots": False,
+ "snapshotAccessMode": "ReadWrite",
+ "snapshotPolicyState": "Active",
+ "systemId": "0e7a082862fedf0f",
+ "timeOfLastAutoSnapshot": 0,
+ "timeOfLastAutoSnapshotCreationFailure": 0
+ }
+ ]
+
+ SNAPSHOT_POLICY_2_GET_LIST = [
+ {
+ "autoSnapshotCreationCadenceInMin": 120,
+ "id": "15ae842500000005",
+ "lastAutoSnapshotCreationFailureReason": "NR",
+ "lastAutoSnapshotFailureInFirstLevel": False,
+ "maxVTreeAutoSnapshots": 40,
+ "name": "testing_2",
+ "nextAutoSnapshotCreationTime": 1683617581,
+ "numOfAutoSnapshots": 0,
+ "numOfCreationFailures": 0,
+ "numOfExpiredButLockedSnapshots": 0,
+ "numOfLockedSnapshots": 0,
+ "numOfRetainedSnapshotsPerLevel": [
+ 40
+ ],
+ "numOfSourceVolumes": 1,
+ "secureSnapshots": False,
+ "snapshotAccessMode": "ReadWrite",
+ "snapshotPolicyState": "Paused",
+ "systemId": "0e7a082862fedf0f",
+ "timeOfLastAutoSnapshot": 0,
+ "timeOfLastAutoSnapshotCreationFailure": 0
+ }
+ ]
+
+ VOLUME_GET_LIST = [
+ {
+ 'storagePoolId': 'test_pool_id_1',
+ 'dataLayout': 'MediumGranularity',
+ 'vtreeId': 'vtree_id_1',
+ 'sizeInKb': 8388608,
+ 'snplIdOfAutoSnapshot': None,
+ 'volumeType': 'ThinProvisioned',
+ 'consistencyGroupId': None,
+ 'ancestorVolumeId': None,
+ 'notGenuineSnapshot': False,
+ 'accessModeLimit': 'ReadWrite',
+ 'secureSnapshotExpTime': 0,
+ 'useRmcache': False,
+ 'managedBy': 'ScaleIO',
+ 'lockedAutoSnapshot': False,
+ 'lockedAutoSnapshotMarkedForRemoval': False,
+ 'autoSnapshotGroupId': None,
+ 'compressionMethod': 'Invalid',
+ 'pairIds': None,
+ 'timeStampIsAccurate': False,
+ 'mappedSdcInfo': None,
+ 'originalExpiryTime': 0,
+ 'retentionLevels': [
+ ],
+ 'snplIdOfSourceVolume': None,
+ 'volumeReplicationState': 'UnmarkedForReplication',
+ 'replicationJournalVolume': False,
+ 'replicationTimeStamp': 0,
+ 'creationTime': 1655878090,
+ 'name': 'source_volume_name',
+ 'id': 'source_volume_id'
+ }
+ ]
+
+ VOLUME_2_GET_LIST = [
+ {
+ 'storagePoolId': 'test_pool_id_1',
+ 'dataLayout': 'MediumGranularity',
+ 'vtreeId': 'vtree_id_1',
+ 'sizeInKb': 8388608,
+ 'snplIdOfAutoSnapshot': None,
+ 'volumeType': 'ThinProvisioned',
+ 'consistencyGroupId': None,
+ 'ancestorVolumeId': None,
+ 'notGenuineSnapshot': False,
+ 'accessModeLimit': 'ReadWrite',
+ 'secureSnapshotExpTime': 0,
+ 'useRmcache': False,
+ 'managedBy': 'ScaleIO',
+ 'lockedAutoSnapshot': False,
+ 'lockedAutoSnapshotMarkedForRemoval': False,
+ 'autoSnapshotGroupId': None,
+ 'compressionMethod': 'Invalid',
+ 'pairIds': None,
+ 'timeStampIsAccurate': False,
+ 'mappedSdcInfo': None,
+ 'originalExpiryTime': 0,
+ 'retentionLevels': [
+ ],
+ 'snplIdOfSourceVolume': "15ae842500000005",
+ 'volumeReplicationState': 'UnmarkedForReplication',
+ 'replicationJournalVolume': False,
+ 'replicationTimeStamp': 0,
+ 'creationTime': 1655878090,
+ 'name': 'source_volume_name_2',
+ 'id': 'source_volume_id_2'
+ }
+ ]
+
+ SNAPSHOT_POLICY_STATISTICS = {
+ "autoSnapshotVolIds": [],
+ "expiredButLockedSnapshotsIds": [],
+ "numOfAutoSnapshots": 0,
+ "numOfExpiredButLockedSnapshots": 0,
+ "numOfSrcVols": 0,
+ "srcVolIds": []
+ }
+
+ @staticmethod
+ def get_snapshot_policy_exception_response(response_type):
+ if response_type == 'get_vol_details_exception':
+ return "Failed to get the volume source_volume_id_2 with error "
+ elif response_type == 'get_snapshot_policy_details_exception':
+ return "Failed to get the snapshot policy with error "
+ elif response_type == 'create_exception':
+ return "Creation of snapshot policy failed with error "
+ elif response_type == 'create_id_exception':
+ return "Creation of snapshot policy is allowed using snapshot_policy_name only, snapshot_policy_id given."
+ elif response_type == 'delete_exception':
+ return "Deletion of snapshot policy 15ae842500000004 failed with error "
+ elif response_type == 'modify_exception':
+ return "Failed to update the snapshot policy 15ae842500000004 with error "
+ elif response_type == 'source_volume_exception':
+ return "Failed to manage the source volume source_volume_id with error "
+ elif response_type == 'add_source_volume_wo_vol':
+ return "Either id or name of source volume needs to be passed with state of source volume"
+ elif response_type == 'add_source_volume_vol_id_name':
+ return "id and name of source volume are mutually exclusive"
+ elif response_type == 'add_non_existing_source_volume':
+ return "Failed to get the volume non_existing_source_volume_name with error Volume with identifier non_existing_source_volume_name not found"
+ elif response_type == 'pause_exception':
+ return "Failed to pause/resume 15ae842500000004 with error"
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_storagepool_api.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_storagepool_api.py
index 0246b9dd4..87af1d6eb 100644
--- a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_storagepool_api.py
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_storagepool_api.py
@@ -1,4 +1,4 @@
-# Copyright: (c) 2022, Dell Technologies
+# Copyright: (c) 2024, Dell Technologies
# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -28,6 +28,7 @@ class MockStoragePoolApi:
STORAGE_POOL_GET_LIST = [
{
'protectionDomainId': '4eeb304600000000',
+ 'protectionDomainName': 'test_pd',
'rebuildEnabled': True,
'dataLayout': 'MediumGranularity',
'persistentChecksumState': 'Protected',
@@ -95,6 +96,149 @@ class MockStoragePoolApi:
}
]
+ STORAGE_POOL_GET_MULTI_LIST = [
+ {
+ 'protectionDomainId': '4eeb304600000000',
+ 'protectionDomainName': 'test_pd',
+ 'rebuildEnabled': True,
+ 'dataLayout': 'MediumGranularity',
+ 'persistentChecksumState': 'Protected',
+ 'addressSpaceUsage': 'Normal',
+ 'externalAccelerationType': 'None',
+ 'rebalanceEnabled': True,
+ 'sparePercentage': 10,
+ 'rmcacheWriteHandlingMode': 'Cached',
+ 'checksumEnabled': False,
+ 'useRfcache': False,
+ 'compressionMethod': 'Invalid',
+ 'fragmentationEnabled': True,
+ 'numOfParallelRebuildRebalanceJobsPerDevice': 2,
+ 'capacityAlertHighThreshold': 80,
+ 'capacityAlertCriticalThreshold': 90,
+ 'capacityUsageState': 'Normal',
+ 'capacityUsageType': 'NetCapacity',
+ 'addressSpaceUsageType': 'DeviceCapacityLimit',
+ 'bgScannerCompareErrorAction': 'ReportAndFix',
+ 'bgScannerReadErrorAction': 'ReportAndFix',
+ 'fglExtraCapacity': None,
+ 'fglOverProvisioningFactor': None,
+ 'fglWriteAtomicitySize': None,
+ 'fglMaxCompressionRatio': None,
+ 'fglPerfProfile': None,
+ 'replicationCapacityMaxRatio': 0,
+ 'persistentChecksumEnabled': True,
+ 'persistentChecksumBuilderLimitKb': 3072,
+ 'persistentChecksumValidateOnRead': False,
+ 'useRmcache': False,
+ 'fglAccpId': None,
+ 'rebuildIoPriorityPolicy': 'limitNumOfConcurrentIos',
+ 'rebalanceIoPriorityPolicy': 'favorAppIos',
+ 'vtreeMigrationIoPriorityPolicy': 'favorAppIos',
+ 'protectedMaintenanceModeIoPriorityPolicy': 'limitNumOfConcurrentIos',
+ 'rebuildIoPriorityNumOfConcurrentIosPerDevice': 1,
+ 'rebalanceIoPriorityNumOfConcurrentIosPerDevice': 1,
+ 'vtreeMigrationIoPriorityNumOfConcurrentIosPerDevice': 1,
+ 'protectedMaintenanceModeIoPriorityNumOfConcurrentIosPerDevice': 1,
+ 'rebuildIoPriorityBwLimitPerDeviceInKbps': 10240,
+ 'rebalanceIoPriorityBwLimitPerDeviceInKbps': 10240,
+ 'vtreeMigrationIoPriorityBwLimitPerDeviceInKbps': 10240,
+ 'protectedMaintenanceModeIoPriorityBwLimitPerDeviceInKbps': 10240,
+ 'rebuildIoPriorityAppIopsPerDeviceThreshold': None,
+ 'rebalanceIoPriorityAppIopsPerDeviceThreshold': None,
+ 'vtreeMigrationIoPriorityAppIopsPerDeviceThreshold': None,
+ 'protectedMaintenanceModeIoPriorityAppIopsPerDeviceThreshold': None,
+ 'rebuildIoPriorityAppBwPerDeviceThresholdInKbps': None,
+ 'rebalanceIoPriorityAppBwPerDeviceThresholdInKbps': None,
+ 'vtreeMigrationIoPriorityAppBwPerDeviceThresholdInKbps': None,
+ 'protectedMaintenanceModeIoPriorityAppBwPerDeviceThresholdInKbps': None,
+ 'rebuildIoPriorityQuietPeriodInMsec': None,
+ 'rebalanceIoPriorityQuietPeriodInMsec': None,
+ 'vtreeMigrationIoPriorityQuietPeriodInMsec': None,
+ 'protectedMaintenanceModeIoPriorityQuietPeriodInMsec': None,
+ 'zeroPaddingEnabled': True,
+ 'backgroundScannerMode': 'DataComparison',
+ 'backgroundScannerBWLimitKBps': 3072,
+ 'fglMetadataSizeXx100': None,
+ 'fglNvdimmWriteCacheSizeInMb': None,
+ 'fglNvdimmMetadataAmortizationX100': None,
+ 'mediaType': 'HDD',
+ 'name': 'test_pool',
+ 'id': 'test_pool_id_1'
+ },
+ {
+ 'protectionDomainId': '4eeb304600000002',
+ 'protectionDomainName': 'test_pd_1',
+ 'rebuildEnabled': True,
+ 'dataLayout': 'MediumGranularity',
+ 'persistentChecksumState': 'Protected',
+ 'addressSpaceUsage': 'Normal',
+ 'externalAccelerationType': 'None',
+ 'rebalanceEnabled': True,
+ 'sparePercentage': 10,
+ 'rmcacheWriteHandlingMode': 'Cached',
+ 'checksumEnabled': False,
+ 'useRfcache': False,
+ 'compressionMethod': 'Invalid',
+ 'fragmentationEnabled': True,
+ 'numOfParallelRebuildRebalanceJobsPerDevice': 2,
+ 'capacityAlertHighThreshold': 80,
+ 'capacityAlertCriticalThreshold': 90,
+ 'capacityUsageState': 'Normal',
+ 'capacityUsageType': 'NetCapacity',
+ 'addressSpaceUsageType': 'DeviceCapacityLimit',
+ 'bgScannerCompareErrorAction': 'ReportAndFix',
+ 'bgScannerReadErrorAction': 'ReportAndFix',
+ 'fglExtraCapacity': None,
+ 'fglOverProvisioningFactor': None,
+ 'fglWriteAtomicitySize': None,
+ 'fglMaxCompressionRatio': None,
+ 'fglPerfProfile': None,
+ 'replicationCapacityMaxRatio': 0,
+ 'persistentChecksumEnabled': True,
+ 'persistentChecksumBuilderLimitKb': 3072,
+ 'persistentChecksumValidateOnRead': False,
+ 'useRmcache': False,
+ 'fglAccpId': None,
+ 'rebuildIoPriorityPolicy': 'limitNumOfConcurrentIos',
+ 'rebalanceIoPriorityPolicy': 'favorAppIos',
+ 'vtreeMigrationIoPriorityPolicy': 'favorAppIos',
+ 'protectedMaintenanceModeIoPriorityPolicy': 'limitNumOfConcurrentIos',
+ 'rebuildIoPriorityNumOfConcurrentIosPerDevice': 1,
+ 'rebalanceIoPriorityNumOfConcurrentIosPerDevice': 1,
+ 'vtreeMigrationIoPriorityNumOfConcurrentIosPerDevice': 1,
+ 'protectedMaintenanceModeIoPriorityNumOfConcurrentIosPerDevice': 1,
+ 'rebuildIoPriorityBwLimitPerDeviceInKbps': 10240,
+ 'rebalanceIoPriorityBwLimitPerDeviceInKbps': 10240,
+ 'vtreeMigrationIoPriorityBwLimitPerDeviceInKbps': 10240,
+ 'protectedMaintenanceModeIoPriorityBwLimitPerDeviceInKbps': 10240,
+ 'rebuildIoPriorityAppIopsPerDeviceThreshold': None,
+ 'rebalanceIoPriorityAppIopsPerDeviceThreshold': None,
+ 'vtreeMigrationIoPriorityAppIopsPerDeviceThreshold': None,
+ 'protectedMaintenanceModeIoPriorityAppIopsPerDeviceThreshold': None,
+ 'rebuildIoPriorityAppBwPerDeviceThresholdInKbps': None,
+ 'rebalanceIoPriorityAppBwPerDeviceThresholdInKbps': None,
+ 'vtreeMigrationIoPriorityAppBwPerDeviceThresholdInKbps': None,
+ 'protectedMaintenanceModeIoPriorityAppBwPerDeviceThresholdInKbps': None,
+ 'rebuildIoPriorityQuietPeriodInMsec': None,
+ 'rebalanceIoPriorityQuietPeriodInMsec': None,
+ 'vtreeMigrationIoPriorityQuietPeriodInMsec': None,
+ 'protectedMaintenanceModeIoPriorityQuietPeriodInMsec': None,
+ 'zeroPaddingEnabled': True,
+ 'backgroundScannerMode': 'DataComparison',
+ 'backgroundScannerBWLimitKBps': 3072,
+ 'fglMetadataSizeXx100': None,
+ 'fglNvdimmWriteCacheSizeInMb': None,
+ 'fglNvdimmMetadataAmortizationX100': None,
+ 'mediaType': 'HDD',
+ 'name': 'test_pool',
+ 'id': 'test_pool_id_2'
+ }
+ ]
+
+ PROTECTION_DETAILS = [{"pd_id": "4eeb304600000000", "pd_name": "test_pd"}]
+
+ PROTECTION_DETAILS_1 = [{"id": "4eeb304600000001", "name": "test_pd_name"}]
+
STORAGE_POOL_STATISTICS = {
'backgroundScanFixedReadErrorCount': 0,
'pendingMovingOutBckRebuildJobs': 0,
@@ -461,7 +605,23 @@ class MockStoragePoolApi:
'numOfIncomingVtreeMigrations': 1
}
+ RESPONSE_EXEC_DICT = {
+ "get_details": "Failed to get the storage pool test_pool with error ",
+ "invalid_pd_id": "Entered protection domain id does not match with the storage pool's protection domain id.",
+ "get_pd_exception": "Failed to get the protection domain 4eeb304600000001 with error",
+ "create_storage_pool": "Failed to create the storage pool",
+ "rename_storage_pool": "Failed to update the storage pool",
+ "create_pool_id": "storage_pool_name is missing & name required to create a storage pool",
+ "get_pd_non_exist": "Unable to find the protection domain",
+ "get_multi_details": "More than one storage pool found",
+ "create_wo_pd": "Please provide protection domain details",
+ "create_transitional": "TRANSITIONAL media type is not supported during creation.",
+ "create_pool_name_empty": "Empty or white spaced string provided in storage_pool_name.",
+ "create_pool_new_name": "storage_pool_new_name is passed during creation.",
+ "rename_storage_pool_empty": "Empty/White spaced name is not allowed during renaming of a storage pool.",
+ "delete_storage_pool": "Deleting storage pool is not supported through ansible module."
+ }
+
@staticmethod
def get_exception_response(response_type):
- if response_type == 'get_details':
- return "Failed to get the storage pool test_pool with error "
+ return MockStoragePoolApi.RESPONSE_EXEC_DICT.get(response_type, "")
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_volume_api.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_volume_api.py
index b05cc84d3..8c264940f 100644
--- a/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_volume_api.py
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/module_utils/mock_volume_api.py
@@ -1,4 +1,4 @@
-# Copyright: (c) 2022, Dell Technologies
+# Copyright: (c) 2024, Dell Technologies
# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -61,7 +61,9 @@ class MockVolumeApi:
'originalExpiryTime': 0,
'retentionLevels': [
],
- 'snplIdOfSourceVolume': None,
+ 'snplIdOfSourceVolume': "snplIdOfSourceVolume",
+ 'snapshotPolicyId': 'snapshotPolicyId',
+ 'snapshotPolicyName': 'snapshotPolicyName',
'volumeReplicationState': 'UnmarkedForReplication',
'replicationJournalVolume': False,
'replicationTimeStamp': 0,
@@ -542,7 +544,61 @@ class MockVolumeApi:
'numOfIncomingVtreeMigrations': 0
}
+ SDC_RESPONSE = [
+ {
+ 'id': 'abdfe71b00030001',
+ }
+ ]
+
+ SDC_RESPONSE_EMPTY = []
+
+ GET_STORAGE_POOL = {
+ 'dataLayout': 'MediumGranularity'
+ }
+
+ GET_STORAGE_POOL_FINE = {
+ 'dataLayout': 'FineGranularity',
+ }
+
+ PROTECTION_DETAILS = [{"pd_id": "pd_id", "pd_name": "pd_name"}]
+
+ GET_ID = {"id": "e0d8f6c900000000"}
+ PROTECTION_DETAILS_MULTI = [
+ {"pd_id": "pd_id", "pd_name": "pd_name"},
+ {"pd_id": "pd_id", "pd_name": "pd_name"},
+ ]
+
+ RESPONSE_EXEC_DICT = {
+ 'get_details': "Failed to get the volume test_id_1 with error ",
+ 'get_sds': "Failed to get the SDC sdc_name with error ",
+ 'create_vol_name': "Please provide valid volume name.",
+ 'create_vol_size': "Size is a mandatory parameter",
+ 'create_vol_ctype': "compression_type for volume can only be",
+ 'create_vol_exc': "Create volume vol_name operation failed with error",
+ 'modify_access': "Modify access mode of SDC operation failed",
+ 'modify_limits': "Modify bandwidth/iops limits of SDC",
+ 'delete_volume': "Delete volume vol_id operation failed with",
+ 'val_params_err1': "sdc_id, sdc_ip and sdc_name are mutually exclusive",
+ 'val_params_err2': "cap_unit can be specified along with size only",
+ 'val_params_err3': "To remove/detach snapshot policy, please provide",
+ 'val_params_err4': "delete_snapshots can be specified only when the state",
+ 'modify_volume_exp': "Failed to update the volume",
+ 'to_modify_err1': "To remove/detach a snapshot policy, provide the ",
+ 'snap_pol_id_err': "Entered snapshot policy id does not ",
+ 'snap_pol_name_err': "Entered snapshot policy name does not ",
+ 'pd_id_err': "Entered protection domain id does not ",
+ 'pool_id_err': "Entered storage pool id does ",
+ 'pd_name_err': "Entered protection domain name does ",
+ 'pool_name_err': "Entered storage pool name does ",
+ 'get_pd_exception': "Failed to get the protection domain ",
+ 'get_sp_exception': "Failed to get the snapshot policy ",
+ 'get_spool_error1': "More than one storage pool found with",
+ 'get_spool_error2': "Failed to get the storage pool",
+ 'map_vol_exception': "Mapping volume name to SDC sdc_id1 failed with error",
+ 'unmap': "Unmap SDC sdc_id from volume vol_id failed with error",
+ 'perform_error1': "vol_new_name parameter is not supported during creation of a volume"
+ }
+
@staticmethod
def get_exception_response(response_type):
- if response_type == 'get_details':
- return "Failed to get the volume test_id_1 with error "
+ return MockVolumeApi.RESPONSE_EXEC_DICT.get(response_type, "")
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_device.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_device.py
new file mode 100644
index 000000000..c18204339
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_device.py
@@ -0,0 +1,471 @@
+# Copyright: (c) 2023, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""Unit Tests for Device module on PowerFlex"""
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+import pytest
+from mock.mock import MagicMock
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_device_api import MockDeviceApi
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_api_exception \
+ import MockApiException
+from ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell \
+ import utils
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_fail_json \
+ import FailJsonException, fail_json
+
+utils.get_logger = MagicMock()
+utils.get_powerflex_gateway_host_connection = MagicMock()
+utils.PowerFlexClient = MagicMock()
+
+from ansible.module_utils import basic
+basic.AnsibleModule = MagicMock()
+from ansible_collections.dellemc.powerflex.plugins.modules.device import PowerFlexDevice
+
+
+class TestPowerflexDevice():
+
+ get_module_args = MockDeviceApi.DEVICE_COMMON_ARGS
+
+ @pytest.fixture
+ def device_module_mock(self, mocker):
+ mocker.patch(
+ MockDeviceApi.MODULE_UTILS_PATH + '.PowerFlexClient',
+ new=MockApiException)
+ device_module_mock = PowerFlexDevice()
+ device_module_mock.module.fail_json = fail_json
+ return device_module_mock
+
+ def capture_fail_json_call(self, error_msg, device_module_mock):
+ try:
+ device_module_mock.perform_module_operation()
+ except FailJsonException as fj_object:
+ assert error_msg in fj_object.message
+
+ def test_get_device_detail_using_dev_name_sds_id(self, device_module_mock):
+ self.get_module_args.update({
+ "device_name": MockDeviceApi.DEVICE_NAME_1,
+ "sds_id": MockDeviceApi.SDS_ID_1,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=MockDeviceApi.DEVICE_GET_LIST)
+ device_module_mock.perform_module_operation()
+ device_module_mock.powerflex_conn.device.get.assert_called()
+
+ def test_get_device_detail_using_path_sds_name(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=MockDeviceApi.DEVICE_GET_LIST)
+ device_module_mock.perform_module_operation()
+ device_module_mock.powerflex_conn.device.get.assert_called()
+
+ def test_get_device_detail_using_dev_id(self, device_module_mock):
+ self.get_module_args.update({
+ "device_id": MockDeviceApi.DEVICE_ID_1,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=MockDeviceApi.DEVICE_GET_LIST)
+ device_module_mock.perform_module_operation()
+ device_module_mock.powerflex_conn.device.get.assert_called()
+
+ def test_get_device_without_sds(self, device_module_mock):
+ self.get_module_args.update({
+ "device_name": MockDeviceApi.DEVICE_NAME_1,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=None)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response(
+ 'get_dev_without_SDS'), device_module_mock)
+
+ def test_get_device_without_sds_with_path(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=None)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response(
+ 'get_device_details_without_path'), device_module_mock)
+
+ def test_get_device_exception(self, device_module_mock):
+ self.get_module_args.update({
+ "device_id": MockDeviceApi.DEVICE_ID_1,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response(
+ 'get_device_exception'), device_module_mock)
+
+ def test_create_device_with_id(self, device_module_mock):
+ self.get_module_args.update({
+ "device_id": MockDeviceApi.DEVICE_ID_1,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=[])
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response(
+ 'create_id_exception'), device_module_mock)
+
+ def test_get_device_with_empty_path(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": "",
+ "sds_id": MockDeviceApi.SDS_ID_1,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response(
+ 'empty_path'), device_module_mock)
+
+ def test_get_device_with_empty_name(self, device_module_mock):
+ self.get_module_args.update({
+ "device_name": "",
+ "sds_id": MockDeviceApi.SDS_ID_1,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response(
+ 'empty_device_name'), device_module_mock)
+
+ def test_get_device_with_empty_sds_id(self, device_module_mock):
+ self.get_module_args.update({
+ "device_id": MockDeviceApi.DEVICE_ID_1,
+ "sds_id": "",
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response(
+ 'empty_sds'), device_module_mock)
+
+ def test_get_device_with_empty_sds_name(self, device_module_mock):
+ self.get_module_args.update({
+ "device_id": MockDeviceApi.DEVICE_ID_1,
+ "sds_name": "",
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response(
+ 'empty_sds'), device_module_mock)
+
+ def test_get_device_with_empty_dev_id(self, device_module_mock):
+ self.get_module_args.update({
+ "device_id": "",
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response(
+ 'empty_dev_id'), device_module_mock)
+
+ def test_get_device_with_space_in_name(self, device_module_mock):
+ self.get_module_args.update({
+ "device_name": " ",
+ "sds_id": MockDeviceApi.SDS_ID_1,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response(
+ 'space_in_name'), device_module_mock)
+
+ def test_get_device_with_space_in_name_with_sds_name(self, device_module_mock):
+ self.get_module_args.update({
+ "device_name": " ",
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response(
+ 'space_in_name'), device_module_mock)
+
+ def test_get_device_without_required_params(self, device_module_mock):
+ self.get_module_args.update({
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response(
+ 'with_required_params'), device_module_mock)
+
+ def test_modify_device_exception(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "media_type": "SSD",
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=MockDeviceApi.DEVICE_GET_LIST)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response1(
+ 'modify_exception'), device_module_mock)
+
+ def test_delete_device(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "state": "absent"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=MockDeviceApi.DEVICE_GET_LIST)
+ device_module_mock.perform_module_operation()
+ device_module_mock.powerflex_conn.device.delete.assert_called()
+
+ def test_delete_device_exception(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "state": "absent"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=MockDeviceApi.DEVICE_GET_LIST)
+ device_module_mock.powerflex_conn.device.delete = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response1(
+ 'delete_exception'), device_module_mock)
+ device_module_mock.powerflex_conn.device.delete.assert_called()
+
+ def test_get_sds_exception(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "state": "absent"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=False)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response1(
+ 'sds_exception'), device_module_mock)
+
+ def test_get_pd_exception(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "device_name": MockDeviceApi.DEVICE_NAME_1,
+ "protection_domain_name": MockDeviceApi.PD_NAME_1,
+ "media_type": "HDD",
+ "external_acceleration_type": "ReadAndWrite",
+ "storage_pool_name": MockDeviceApi.SP_NAME_1,
+ "force": False,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=[])
+ device_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=False)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response1(
+ 'pd_exception'), device_module_mock)
+
+ def test_get_sp_exception(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "device_name": MockDeviceApi.DEVICE_NAME_1,
+ "protection_domain_name": MockDeviceApi.PD_NAME_1,
+ "media_type": "HDD",
+ "external_acceleration_type": "ReadAndWrite",
+ "storage_pool_name": MockDeviceApi.SP_NAME_1,
+ "force": False,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=[])
+ device_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockDeviceApi.PD_DETAILS_1)
+ device_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=False)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response1(
+ 'sp_exception'), device_module_mock)
+
+ def test_get_acc_pool_exception(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "device_name": MockDeviceApi.DEVICE_NAME_1,
+ "protection_domain_name": MockDeviceApi.PD_NAME_1,
+ "media_type": "HDD",
+ "external_acceleration_type": "ReadAndWrite",
+ "acceleration_pool_name": MockDeviceApi.SP_NAME_1,
+ "force": False,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=[])
+ device_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockDeviceApi.PD_DETAILS_1)
+ device_module_mock.powerflex_conn.acceleration_pool.get = MagicMock(
+ return_value=False)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response1(
+ 'ap_exception'), device_module_mock)
+
+ def test_add_device_exception(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "device_name": MockDeviceApi.DEVICE_NAME_1,
+ "protection_domain_name": MockDeviceApi.PD_NAME_1,
+ "media_type": "HDD",
+ "external_acceleration_type": "ReadAndWrite",
+ "storage_pool_name": MockDeviceApi.SP_NAME_1,
+ "force": False,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=[])
+ device_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockDeviceApi.PD_DETAILS_1)
+ device_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=MockDeviceApi.SP_DETAILS_1)
+ device_module_mock.powerflex_conn.device.create = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response1(
+ 'add_exception'), device_module_mock)
+ device_module_mock.powerflex_conn.device.create.assert_called()
+
+ def test_add_device_name_exception(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "device_name": " ",
+ "protection_domain_name": MockDeviceApi.PD_NAME_1,
+ "media_type": "HDD",
+ "external_acceleration_type": "ReadAndWrite",
+ "storage_pool_name": MockDeviceApi.SP_NAME_1,
+ "force": False,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=[])
+ device_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockDeviceApi.PD_DETAILS_1)
+ device_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=MockDeviceApi.SP_DETAILS_1)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response1(
+ 'add_dev_name_exception'), device_module_mock)
+
+ def test_add_device_path_exception(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": " ",
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "device_name": MockDeviceApi.DEVICE_NAME_1,
+ "protection_domain_name": MockDeviceApi.PD_NAME_1,
+ "media_type": "HDD",
+ "external_acceleration_type": "ReadAndWrite",
+ "storage_pool_name": MockDeviceApi.SP_NAME_1,
+ "force": False,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=[])
+ device_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockDeviceApi.PD_DETAILS_1)
+ device_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=MockDeviceApi.SP_DETAILS_1)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response1(
+ 'add_dev_path_exception'), device_module_mock)
+
+ def test_add_device_ext_acc_type_exception(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": " ",
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "device_name": MockDeviceApi.DEVICE_NAME_1,
+ "protection_domain_name": MockDeviceApi.PD_NAME_1,
+ "media_type": "HDD",
+ "external_acceleration_type": "ReadAndWrite",
+ "force": False,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=[])
+ device_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockDeviceApi.PD_DETAILS_1)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response1(
+ 'ext_type_exception'), device_module_mock)
+
+ def test_add_device_without_pd_exception(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "device_name": MockDeviceApi.DEVICE_NAME_1,
+ "media_type": "HDD",
+ "external_acceleration_type": "ReadAndWrite",
+ "storage_pool_name": MockDeviceApi.SP_NAME_1,
+ "force": False,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=[])
+ device_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=MockDeviceApi.SP_DETAILS_1)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response1(
+ 'add_without_pd'), device_module_mock)
+
+ def test_add_device_without_pd_exception_for_acc_pool(self, device_module_mock):
+ self.get_module_args.update({
+ "current_pathname": MockDeviceApi.PATH_1,
+ "sds_name": MockDeviceApi.SDS_NAME_1,
+ "device_name": MockDeviceApi.DEVICE_NAME_1,
+ "media_type": "HDD",
+ "external_acceleration_type": "ReadAndWrite",
+ "acceleration_pool_name": MockDeviceApi.SP_NAME_1,
+ "force": False,
+ "state": "present"
+ })
+ device_module_mock.module.params = self.get_module_args
+ device_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockDeviceApi.SDS_DETAILS_1)
+ device_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=[])
+ device_module_mock.powerflex_conn.acceleration_pool.get = MagicMock(
+ return_value=MockDeviceApi.SP_DETAILS_1)
+ self.capture_fail_json_call(MockDeviceApi.get_device_exception_response1(
+ 'add_without_pd'), device_module_mock)
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_fault_set.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_fault_set.py
new file mode 100644
index 000000000..ea2aa1104
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_fault_set.py
@@ -0,0 +1,215 @@
+# Copyright: (c) 2024, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""Unit Tests for fault set module on PowerFlex"""
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+import pytest
+# pylint: disable=unused-import
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.libraries import initial_mock
+from mock.mock import MagicMock
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_fault_set_api import MockFaultSetApi
+from ansible_collections.dellemc.powerflex.plugins.modules.fault_set import \
+ FaultSetHandler
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_api_exception \
+ import MockApiException
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.libraries.powerflex_unit_base \
+ import PowerFlexUnitBase
+
+from ansible_collections.dellemc.powerflex.plugins.modules.fault_set import PowerFlexFaultSet
+
+
+class TestPowerflexFaultSet(PowerFlexUnitBase):
+
+ get_module_args = MockFaultSetApi.FAULT_SET_COMMON_ARGS
+
+ @pytest.fixture
+ def module_object(self):
+ return PowerFlexFaultSet
+
+ def test_get_fault_set_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'fault_set_id': 'fault_set_id_1',
+ 'state': "present"
+ })
+ powerflex_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=MockFaultSetApi.FAULT_SET_GET_LIST)
+ pd_resp = MockFaultSetApi.PROTECTION_DOMAIN
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp['protectiondomain'])
+ FaultSetHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.fault_set.get.assert_called()
+
+ def test_get_fault_set_name_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'fault_set_name': 'fault_set_name_1',
+ 'protection_domain_id': 'test_pd_id_1',
+ 'state': "present"
+ })
+ pd_resp = MockFaultSetApi.PROTECTION_DOMAIN
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp['protectiondomain'])
+ powerflex_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=MockFaultSetApi.FAULT_SET_GET_LIST)
+ FaultSetHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.fault_set.get.assert_called()
+
+ def test_create_fault_set_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "fault_set_name": "test_fs_1",
+ "protection_domain_name": "test_pd_1",
+ "state": "present"
+ })
+ pd_resp = MockFaultSetApi.PROTECTION_DOMAIN
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp['protectiondomain'])
+ powerflex_module_mock.get_fault_set = MagicMock(
+ return_value=None)
+ FaultSetHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.fault_set.create.assert_called()
+
+ def test_create_fault_set_wo_pd_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "fault_set_name": "test_fs_1",
+ "state": "present"
+ })
+ powerflex_module_mock.get_fault_set = MagicMock(
+ return_value=None)
+ self.capture_fail_json_call(
+ MockFaultSetApi.get_fault_set_exception_response(
+ 'create_fault_set_wo_pd_exception'), powerflex_module_mock, FaultSetHandler)
+
+ def test_create_fault_set_empty_name_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "fault_set_name": " ",
+ "protection_domain_name": "test_pd_1",
+ "state": "present"
+ })
+ pd_resp = MockFaultSetApi.PROTECTION_DOMAIN
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp['protectiondomain'])
+ powerflex_module_mock.get_fault_set = MagicMock(
+ return_value=None)
+ self.capture_fail_json_call(
+ MockFaultSetApi.get_fault_set_exception_response(
+ 'create_fault_set_empty_name_exception'), powerflex_module_mock, FaultSetHandler)
+
+ def test_create_fault_set_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "fault_set_name": "test_fs_1",
+ "protection_domain_name": "test_pd_1",
+ "state": "present"
+ })
+ pd_resp = MockFaultSetApi.PROTECTION_DOMAIN
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp['protectiondomain'])
+ powerflex_module_mock.get_fault_set = MagicMock(
+ return_value=None)
+ powerflex_module_mock.powerflex_conn.fault_set.create = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(
+ MockFaultSetApi.get_fault_set_exception_response(
+ 'create_fault_set_exception'), powerflex_module_mock, FaultSetHandler)
+
+ def test_rename_fault_set_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "fault_set_name": 'fault_set_name_1',
+ "protection_domain_name": "test_pd_1",
+ "fault_set_new_name": "fs_new_name",
+ "state": "present"
+ })
+ pd_resp = MockFaultSetApi.PROTECTION_DOMAIN
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp['protectiondomain'])
+ powerflex_module_mock.get_fault_set = MagicMock(
+ return_value=MockFaultSetApi.FAULT_SET_GET_LIST[0])
+ FaultSetHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.fault_set.rename.assert_called()
+
+ def test_rename_fault_set_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "fault_set_name": 'fault_set_name_1',
+ "protection_domain_name": "test_pd_1",
+ "fault_set_new_name": "fs_new_name",
+ "state": "present"
+ })
+ pd_resp = MockFaultSetApi.PROTECTION_DOMAIN
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp['protectiondomain'])
+ powerflex_module_mock.get_fault_set = MagicMock(
+ return_value=MockFaultSetApi.FAULT_SET_GET_LIST[0])
+ powerflex_module_mock.powerflex_conn.fault_set.rename = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(
+ MockFaultSetApi.get_fault_set_exception_response(
+ 'rename_fault_set_exception'), powerflex_module_mock, FaultSetHandler)
+
+ def test_delete_fault_set_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "fault_set_name": 'test_fs_1',
+ "protection_domain_name": "test_pd_1",
+ "state": "absent"
+ })
+ pd_resp = MockFaultSetApi.PROTECTION_DOMAIN
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp['protectiondomain'])
+ powerflex_module_mock.get_fault_set = MagicMock(
+ return_value=MockFaultSetApi.FAULT_SET_GET_LIST[0])
+ FaultSetHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.fault_set.delete.assert_called()
+
+ def test_delete_fault_set_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "fault_set_name": 'test_fs_1',
+ "protection_domain_name": "test_pd_1",
+ "state": "absent"
+ })
+ pd_resp = MockFaultSetApi.PROTECTION_DOMAIN
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp['protectiondomain'])
+ powerflex_module_mock.get_fault_set = MagicMock(
+ return_value=MockFaultSetApi.FAULT_SET_GET_LIST[0])
+ powerflex_module_mock.powerflex_conn.fault_set.delete = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(
+ MockFaultSetApi.get_fault_set_exception_response(
+ 'delete_fault_set_exception'), powerflex_module_mock, FaultSetHandler)
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_info.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_info.py
index 2bd0ff158..ce5091212 100644
--- a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_info.py
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_info.py
@@ -1,4 +1,4 @@
-# Copyright: (c) 2022, Dell Technologies
+# Copyright: (c) 2024, Dell Technologies
# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -9,14 +9,17 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import pytest
+# pylint: disable=unused-import
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.libraries import initial_mock
from mock.mock import MagicMock
from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_info_api import MockInfoApi
-from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_sdk_response \
- import MockSDKResponse
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_fault_set_api import MockFaultSetApi
from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_api_exception \
import MockApiException
from ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell \
import utils
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_fail_json \
+ import FailJsonException, fail_json
utils.get_logger = MagicMock()
utils.get_powerflex_gateway_host_connection = MagicMock()
@@ -25,6 +28,7 @@ utils.PowerFlexClient = MagicMock()
from ansible.module_utils import basic
basic.AnsibleModule = MagicMock()
from ansible_collections.dellemc.powerflex.plugins.modules.info import PowerFlexInfo
+INVALID_SORT_MSG = 'messageCode=PARSE002 displayMessage=An invalid column name: invalid is entered in the sort list'
class TestPowerflexInfo():
@@ -33,6 +37,9 @@ class TestPowerflexInfo():
@pytest.fixture
def info_module_mock(self, mocker):
+ mocker.patch(
+ MockInfoApi.MODULE_UTILS_PATH + '.PowerFlexClient',
+ new=MockApiException)
info_module_mock = PowerFlexInfo()
info_module_mock.module.check_mode = False
info_module_mock.powerflex_conn.system.api_version = MagicMock(
@@ -41,8 +48,15 @@ class TestPowerflexInfo():
info_module_mock.powerflex_conn.system.get = MagicMock(
return_value=MockInfoApi.INFO_ARRAY_DETAILS
)
+ info_module_mock.module.fail_json = fail_json
return info_module_mock
+ def capture_fail_json_call(self, error_msg, info_module_mock):
+ try:
+ info_module_mock.perform_module_operation()
+ except FailJsonException as fj_object:
+ assert error_msg in fj_object.message
+
def test_get_volume_details(self, info_module_mock):
self.get_module_args.update({
"gather_subset": ['vol']
@@ -60,6 +74,23 @@ class TestPowerflexInfo():
info_module_mock.powerflex_conn.volume.get.assert_called()
info_module_mock.powerflex_conn.utility.get_statistics_for_all_volumes.assert_called()
+ def test_get_volume_details_filter(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['vol'],
+ "filters": [{
+ "filter_key": "storagePoolId",
+ "filter_operator": "equal",
+ "filter_value": "test_pool_id_1"
+ }]
+ })
+ info_module_mock.module.params = self.get_module_args
+ vol_resp = MockInfoApi.INFO_VOLUME_GET_LIST
+ info_module_mock.powerflex_conn.volume.get = MagicMock(
+ return_value=vol_resp
+ )
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.volume.get.assert_called()
+
def test_get_volume_details_with_exception(self, info_module_mock):
self.get_module_args.update({
"gather_subset": ['vol']
@@ -72,8 +103,8 @@ class TestPowerflexInfo():
info_module_mock.powerflex_conn.utility.get_statistics_for_all_volumes = MagicMock(
side_effect=MockApiException
)
- info_module_mock.perform_module_operation()
- assert MockInfoApi.get_exception_response('volume_get_details') in info_module_mock.module.fail_json.call_args[1]['msg']
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'volume_get_details'), info_module_mock)
def test_get_sp_details(self, info_module_mock):
self.get_module_args.update({
@@ -92,6 +123,23 @@ class TestPowerflexInfo():
info_module_mock.powerflex_conn.storage_pool.get.assert_called()
info_module_mock.powerflex_conn.utility.get_statistics_for_all_storagepools.assert_called()
+ def test_get_sp_details_filter(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['storage_pool'],
+ "filters": [{
+ "filter_key": "id",
+ "filter_operator": "equal",
+ "filter_value": "test_pool_id_1"
+ }]
+ })
+ info_module_mock.module.params = self.get_module_args
+ storage_pool_resp = MockInfoApi.INFO_STORAGE_POOL_GET_LIST
+ info_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=storage_pool_resp
+ )
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.storage_pool.get.assert_called()
+
def test_get_sp_details_with_exception(self, info_module_mock):
self.get_module_args.update({
"gather_subset": ['storage_pool']
@@ -104,8 +152,8 @@ class TestPowerflexInfo():
info_module_mock.powerflex_conn.utility.get_statistics_for_all_storagepools = MagicMock(
side_effect=MockApiException
)
- info_module_mock.perform_module_operation()
- assert MockInfoApi.get_exception_response('sp_get_details') in info_module_mock.module.fail_json.call_args[1]['msg']
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'sp_get_details'), info_module_mock)
def test_get_rcg_details(self, info_module_mock):
self.get_module_args.update({
@@ -118,6 +166,22 @@ class TestPowerflexInfo():
info_module_mock.perform_module_operation()
info_module_mock.powerflex_conn.replication_consistency_group.get.assert_called()
+ def test_get_rcg_filter_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['rcg'],
+ "filters": [{
+ "filter_key": "id",
+ "filter_operator": "equal",
+ "filter_value": "aadc17d500000000"
+ }]
+ })
+ info_module_mock.module.params = self.get_module_args
+ rcg_resp = MockInfoApi.RCG_LIST
+ info_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
+ return_value=rcg_resp)
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.replication_consistency_group.get.assert_called()
+
def test_get_rcg_details_throws_exception(self, info_module_mock):
self.get_module_args.update({
"gather_subset": ['rcg']
@@ -126,8 +190,8 @@ class TestPowerflexInfo():
info_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
side_effect=MockApiException
)
- info_module_mock.perform_module_operation()
- assert MockInfoApi.get_exception_response('rcg_get_details') in info_module_mock.module.fail_json.call_args[1]['msg']
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'rcg_get_details'), info_module_mock)
def test_get_replication_pair_details(self, info_module_mock):
self.get_module_args.update({
@@ -147,5 +211,396 @@ class TestPowerflexInfo():
info_module_mock.powerflex_conn.replication_pair.get = MagicMock(
side_effect=MockApiException
)
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'replication_pair_get_details'), info_module_mock)
+
+ def test_get_snapshot_policy_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['snapshot_policy']
+ })
+ info_module_mock.module.params = self.get_module_args
+ snapshot_policy_resp = MockInfoApi.INFO_SNAPSHOT_POLICY_GET_LIST
+ info_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=snapshot_policy_resp
+ )
+ snapshot_policy_stat_resp = MockInfoApi.INFO_SNAPSHOT_POLICY_STATISTICS
+ info_module_mock.powerflex_conn.utility.get_statistics_for_all_snapshot_policies = MagicMock(
+ return_value=snapshot_policy_stat_resp
+ )
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.snapshot_policy.get.assert_called()
+ info_module_mock.powerflex_conn.utility.get_statistics_for_all_snapshot_policies.assert_called()
+
+ def test_get_snapshot_policy_details_with_exception(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['snapshot_policy']
+ })
+ info_module_mock.module.params = self.get_module_args
+ snapshot_policy_resp = MockInfoApi.INFO_SNAPSHOT_POLICY_GET_LIST
+ info_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=snapshot_policy_resp
+ )
+ info_module_mock.powerflex_conn.utility.get_statistics_for_all_snapshot_policies = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'snapshot_policy_get_details'), info_module_mock)
+
+ def test_get_sdc_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['sdc']
+ })
+ info_module_mock.module.params = self.get_module_args
+ sdc_resp = MockInfoApi.INFO_SDC_FILTER_LIST
+ info_module_mock.powerflex_conn.sdc.get = MagicMock(
+ return_value=sdc_resp
+ )
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.sdc.get.assert_called()
+
+ def test_get_sdc_details_filter(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['sdc'],
+ "filters": [{
+ "filter_key": "name",
+ "filter_operator": "equal",
+ "filter_value": "sdc_1"
+ }]
+ })
+ info_module_mock.module.params = self.get_module_args
+ sdc_resp = MockInfoApi.INFO_SDC_FILTER_LIST
+ info_module_mock.powerflex_conn.sdc.create = MagicMock(
+ return_value=sdc_resp
+ )
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.sdc.get.assert_called()
+
+ def test_get_sdc_details_exception(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['sdc']
+ })
+ info_module_mock.module.params = self.get_module_args
+ info_module_mock.powerflex_conn.sdc.get = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'sdc_get_details'), info_module_mock)
+
+ def test_get_sds_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['sds']
+ })
+ info_module_mock.module.params = self.get_module_args
+ sds_resp = MockInfoApi.INFO_SDS_GET_LIST
+ info_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=sds_resp
+ )
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.sds.get.assert_called()
+
+ def test_get_sds_filter_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['sds'],
+ "filters": [
+ {
+ "filter_key": "name",
+ "filter_operator": "equal",
+ "filter_value": "node0",
+ },
+ {
+ "filter_key": "name",
+ "filter_operator": "equal",
+ "filter_value": "node1",
+ },
+ {
+ "filter_key": "id",
+ "filter_operator": "equal",
+ "filter_value": "8f3bb15300000001",
+ }
+ ]
+ })
+ info_module_mock.module.params = self.get_module_args
+ sds_resp = MockInfoApi.INFO_SDS_GET_LIST
+ info_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=sds_resp
+ )
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.sds.get.assert_called()
+
+ def test_get_sds_details_filter_invalid(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['sds'],
+ "filters": [{
+ "filter_key": "name",
+ "filter_op": "equal",
+ "filter_value": "LGLAP203",
+ }]
+ })
+ info_module_mock.module.params = self.get_module_args
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'get_sds_details_filter_invalid'), info_module_mock)
+
+ def test_get_sds_details_filter_empty(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['sds'],
+ "filters": [{
+ "filter_key": "name",
+ "filter_operator": None,
+ "filter_value": "LGLAP203",
+ }]
+ })
+ info_module_mock.module.params = self.get_module_args
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'get_sds_details_filter_empty'), info_module_mock)
+
+ def test_get_sds_details_exception(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['sds']
+ })
+ info_module_mock.module.params = self.get_module_args
+ sds_resp = MockInfoApi.INFO_SDS_GET_LIST
+ info_module_mock.powerflex_conn.sds.get = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'sds_get_details'), info_module_mock)
+
+ def test_get_pd_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['protection_domain']
+ })
+ info_module_mock.module.params = self.get_module_args
+ pd_resp = MockInfoApi.INFO_GET_PD_LIST
+ info_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp
+ )
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.protection_domain.get.assert_called()
+
+ def test_get_pd_filter_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['protection_domain'],
+ "filters": [{
+ "filter_key": "name",
+ "filter_operator": "equal",
+ "filter_value": "domain1",
+ }]
+ })
+ info_module_mock.module.params = self.get_module_args
+ pd_resp = MockInfoApi.INFO_GET_PD_LIST
+ info_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp
+ )
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.protection_domain.get.assert_called()
+
+ def test_get_pd_details_exception(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['protection_domain']
+ })
+ info_module_mock.module.params = self.get_module_args
+ pd_resp = MockInfoApi.INFO_GET_PD_LIST
+ info_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'pd_get_details'), info_module_mock)
+
+ def test_get_device_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['device']
+ })
+ info_module_mock.module.params = self.get_module_args
+ device_resp = MockInfoApi.INFO_GET_DEVICE_LIST
+ info_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=device_resp
+ )
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.device.get.assert_called()
+
+ def test_get_device_filter_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['device'],
+ "filters": [{
+ "filter_key": "name",
+ "filter_operator": "equal",
+ "filter_value": "device230",
+ }]
+ })
+ info_module_mock.module.params = self.get_module_args
+ device_resp = MockInfoApi.INFO_GET_DEVICE_LIST
+ info_module_mock.powerflex_conn.device.get = MagicMock(
+ return_value=device_resp
+ )
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.device.get.assert_called()
+
+ def test_get_device_details_exception(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['device']
+ })
+ info_module_mock.module.params = self.get_module_args
+ device_resp = MockInfoApi.INFO_GET_DEVICE_LIST
+ info_module_mock.powerflex_conn.device.get = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'device_get_details'), info_module_mock)
+
+ def test_get_fault_set_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['fault_set']
+ })
+ info_module_mock.module.params = self.get_module_args
+ pd_resp = MockFaultSetApi.PROTECTION_DOMAIN
+ info_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp['protectiondomain'])
+ fault_set_resp = MockInfoApi.INFO_GET_FAULT_SET_LIST
+ info_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=fault_set_resp
+ )
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.fault_set.get.assert_called()
+
+ def test_get_fault_set_details_exception(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['fault_set']
+ })
+ info_module_mock.module.params = self.get_module_args
+ fault_set_resp = MockInfoApi.INFO_GET_FAULT_SET_LIST
+ info_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'fault_set_get_details'), info_module_mock)
+
+ def test_get_fault_set_details_invalid_filter_operator_exception(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['fault_set'],
+ "filters": [{
+ "filter_key": "name",
+ "filter_operator": "does_not_contain",
+ "filter_value": "LGLAP203",
+ }]
+ })
+ info_module_mock.module.params = self.get_module_args
+ fault_set_resp = MockInfoApi.INFO_GET_FAULT_SET_LIST
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'invalid_filter_operator_exception'), info_module_mock)
+
+ def test_get_fault_set_details_api_exception(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['fault_set']
+ })
+ info_module_mock.module.params = self.get_module_args
+ fault_set_resp = MockInfoApi.INFO_GET_FAULT_SET_LIST
+ info_module_mock.powerflex_conn.system.api_version = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'api_exception'), info_module_mock)
+
+ def test_get_fault_set_details_system_exception(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['fault_set']
+ })
+ info_module_mock.module.params = self.get_module_args
+ fault_set_resp = MockInfoApi.INFO_GET_FAULT_SET_LIST
+ info_module_mock.powerflex_conn.system.get = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'system_exception'), info_module_mock)
+
+ def test_get_managed_device_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['managed_device']
+ })
+ info_module_mock.module.params = self.get_module_args
+ info_module_mock.powerflex_conn.managed_device.get = MagicMock()
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.managed_device.get.assert_called()
+
+ def test_get_managed_device_details_throws_exception(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['managed_device']
+ })
+ info_module_mock.module.params = self.get_module_args
+ info_module_mock.powerflex_conn.managed_device.get = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'managed_device_get_error'), info_module_mock)
+
+ def test_get_service_template_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['service_template']
+ })
+ info_module_mock.module.params = self.get_module_args
+ info_module_mock.powerflex_conn.service_template.get = MagicMock()
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.service_template.get.assert_called()
+
+ def test_get_service_template_details_throws_exception(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['service_template']
+ })
+ info_module_mock.module.params = self.get_module_args
+ info_module_mock.powerflex_conn.service_template.get = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'service_template_get_error'), info_module_mock)
+
+ def test_get_deployment_details(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['deployment'],
+ "limit": 20
+ })
+ info_module_mock.module.params = self.get_module_args
+ info_module_mock.powerflex_conn.deployment.get = MagicMock()
+ info_module_mock.perform_module_operation()
+ info_module_mock.powerflex_conn.deployment.get.assert_called()
+
+ def test_get_deployment_details_throws_exception(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['deployment']
+ })
+ info_module_mock.module.params = self.get_module_args
+ info_module_mock.powerflex_conn.deployment.get = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockInfoApi.get_exception_response(
+ 'deployment_get_error'), info_module_mock)
+
+ def test_get_deployment_details_throws_exception_invalid_sort(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['deployment'],
+ "sort": 'invalid'
+ })
+ info_module_mock.module.params = self.get_module_args
+ info_module_mock.powerflex_conn.deployment.get = MagicMock(
+ side_effect=MockApiException(INVALID_SORT_MSG)
+ )
+ info_module_mock.perform_module_operation()
+ assert info_module_mock.get_deployments_list() == []
+
+ def test_get_with_multiple_gather_subset(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['deployment', 'service_template'],
+ "sort": 'name', "filters": [{"filter_key": "name", "filter_operator": "equal", "filter_value": "rack"}],
+ })
+ info_module_mock.module.params = self.get_module_args
+ info_module_mock.perform_module_operation()
+ assert info_module_mock.populate_filter_list() == []
+ assert info_module_mock.get_param_value('sort') is None
+
+ def test_get_with_invalid_offset_and_limit_for_subset(self, info_module_mock):
+ self.get_module_args.update({
+ "gather_subset": ['deployment'],
+ "limit": -1, "offset": -1
+ })
+ info_module_mock.module.params = self.get_module_args
info_module_mock.perform_module_operation()
- assert MockInfoApi.get_exception_response('replication_pair_get_details') in info_module_mock.module.fail_json.call_args[1]['msg']
+ assert info_module_mock.get_param_value('limit') is None
+ assert info_module_mock.get_param_value('offset') is None
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_protection_domain.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_protection_domain.py
index ced9fc7f7..fa1dfe641 100644
--- a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_protection_domain.py
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_protection_domain.py
@@ -1,4 +1,4 @@
-# Copyright: (c) 2022, Dell Technologies
+# Copyright: (c) 2024, Dell Technologies
# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -8,229 +8,327 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import pytest
+# pylint: disable=unused-import
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.libraries import initial_mock
from mock.mock import MagicMock
-from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_protection_domain_api import MockProtectionDomainApi
-from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_sdk_response \
- import MockSDKResponse
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_protection_domain_api \
+ import MockProtectionDomainApi
from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_api_exception \
import MockApiException
-from ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell \
- import utils
-
-utils.get_logger = MagicMock()
-utils.get_powerflex_gateway_host_connection = MagicMock()
-utils.PowerFlexClient = MagicMock()
-from ansible.module_utils import basic
-basic.AnsibleModule = MagicMock()
-from ansible_collections.dellemc.powerflex.plugins.modules.protection_domain import PowerFlexProtectionDomain
-
-
-class TestPowerflexProtectionDomain():
-
- get_module_args = {
- 'hostname': '**.***.**.***',
- 'protection_domain_id': '7bd6457000000000',
- 'protection_domain_name': None,
- 'protection_domain_new_name': None,
- 'is_active': True,
- 'network_limits': {
- 'rebuild_limit': 10240,
- 'rebalance_limit': 10240,
- 'vtree_migration_limit': 10240,
- 'overall_limit': 20480,
- 'bandwidth_unit': 'KBps',
- },
- 'rf_cache_limits': {
- 'is_enabled': None,
- 'page_size': 4,
- 'max_io_limit': 16,
- 'pass_through_mode': 'None'
- },
- 'state': 'present'
- }
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.libraries.powerflex_unit_base \
+ import PowerFlexUnitBase
+from ansible_collections.dellemc.powerflex.plugins.modules.protection_domain \
+ import PowerFlexProtectionDomain
+
+
+class TestPowerflexProtectionDomain(PowerFlexUnitBase):
+
+ get_module_args = MockProtectionDomainApi.PD_COMMON_ARGS
@pytest.fixture
- def protection_domain_module_mock(self, mocker):
- mocker.patch(MockProtectionDomainApi.MODULE_UTILS_PATH + '.PowerFlexClient', new=MockApiException)
- protection_domain_module_mock = PowerFlexProtectionDomain()
- return protection_domain_module_mock
-
- def test_get_protection_domain_response(self, protection_domain_module_mock):
- protection_domain_module_mock.module.params = self.get_module_args
- pd_resp = MockSDKResponse(MockProtectionDomainApi.PROTECTION_DOMAIN)
- protection_domain_module_mock.powerflex_conn.protection_domain.get = MagicMock(
- return_value=pd_resp.__dict__['data']['protectiondomain']
- )
- protection_domain_module_mock.perform_module_operation()
- protection_domain_module_mock.powerflex_conn.protection_domain.get.assert_called()
-
- def test_create_protection_domain(self, protection_domain_module_mock):
- self.get_module_args.update({
- "protection_domain_name": "test_domain",
- "state": "present"
- })
- protection_domain_module_mock.module.params = self.get_module_args
- pd_resp = MockSDKResponse(MockProtectionDomainApi.PROTECTION_DOMAIN)
- protection_domain_module_mock.get_protection_domain = MagicMock(
- return_value=pd_resp.__dict__['data']['protectiondomain'][0]
- )
- protection_domain_module_mock.powerflex_conn.protection_domain.create = MagicMock(return_values=None)
- protection_domain_module_mock.perform_module_operation()
- assert (self.get_module_args['protection_domain_name'] ==
- protection_domain_module_mock.module.exit_json.call_args[1]["protection_domain_details"]['name'])
- assert protection_domain_module_mock.module.exit_json.call_args[1]['changed'] is True
-
- def test_modify_protection_domain(self, protection_domain_module_mock):
- self.get_module_args.update({
- 'network_limits': {
- 'rebuild_limit': 10,
- 'rebalance_limit': 10,
- 'vtree_migration_limit': 11,
- 'overall_limit': 21,
- 'bandwidth_unit': 'GBps',
- }
- })
- protection_domain_module_mock.module.params = self.get_module_args
- pd_resp = MockSDKResponse(MockProtectionDomainApi.PROTECTION_DOMAIN)
- sp_resp = MockSDKResponse(MockProtectionDomainApi.STORAGE_POOL)
- protection_domain_module_mock.powerflex_conn.protection_domain.get = MagicMock(
- return_value=pd_resp.__dict__['data']['protectiondomain']
- )
- protection_domain_module_mock.powerflex_conn.protection_domain.get_storage_pools = MagicMock(
- return_value=sp_resp.__dict__['data']['storagepool']
- )
- protection_domain_module_mock.perform_module_operation()
- protection_domain_module_mock.powerflex_conn.protection_domain.network_limits.assert_called()
-
- def test_rename_protection_domain(self, protection_domain_module_mock):
- self.get_module_args.update({
- 'protection_domain_new_name': 'new_test_domain'
- })
- protection_domain_module_mock.module.params = self.get_module_args
- pd_resp = MockSDKResponse(MockProtectionDomainApi.PROTECTION_DOMAIN)
- protection_domain_module_mock.powerflex_conn.protection_domain.get = MagicMock(
- return_value=pd_resp.__dict__['data']['protectiondomain']
- )
- protection_domain_module_mock.perform_module_operation()
- protection_domain_module_mock.powerflex_conn.protection_domain.rename.assert_called()
-
- def test_inactivate_protection_domain(self, protection_domain_module_mock):
- self.get_module_args.update({
- 'is_active': False
- })
- protection_domain_module_mock.module.params = self.get_module_args
- pd_resp = MockSDKResponse(MockProtectionDomainApi.PROTECTION_DOMAIN)
- protection_domain_module_mock.powerflex_conn.protection_domain.get = MagicMock(
- return_value=pd_resp.__dict__['data']['protectiondomain']
- )
- protection_domain_module_mock.perform_module_operation()
- protection_domain_module_mock.powerflex_conn.protection_domain. \
- inactivate.assert_called()
-
- def test_activate_protection_domain(self, protection_domain_module_mock):
- self.get_module_args.update({
- 'is_active': True
- })
- protection_domain_module_mock.module.params = self.get_module_args
- pd_resp = MockSDKResponse(MockProtectionDomainApi.PROTECTION_DOMAIN)
- protection_domain_module_mock.powerflex_conn.protection_domain.get = MagicMock(
- return_value=pd_resp.__dict__['data']['protectiondomain']
- )
- protection_domain_module_mock.powerflex_conn.protection_domain.activate = MagicMock(return_value=None)
- protection_domain_module_mock.perform_module_operation()
- assert protection_domain_module_mock.module.exit_json.call_args[1]['changed'] is True
-
- def test_delete_protection_domain(self, protection_domain_module_mock):
- self.get_module_args.update({
- 'protection_domain_name': 'new_test_domain',
- 'state': 'absent'
- })
- protection_domain_module_mock.module.params = self.get_module_args
- protection_domain_module_mock.get_protection_domain = MagicMock(return_values=None)
- protection_domain_module_mock.perform_module_operation()
- assert protection_domain_module_mock.module.exit_json.call_args[1]['changed'] is True
-
- def test_delete_protection_domain_throws_exception(self, protection_domain_module_mock):
- self.get_module_args.update({
- 'protection_domain_id': '7bd6457000000000',
- 'state': 'absent'
- })
- protection_domain_module_mock.module.params = self.get_module_args
- pd_resp = MockSDKResponse(MockProtectionDomainApi.PROTECTION_DOMAIN)
- protection_domain_module_mock.powerflex_conn.protection_domain.get = MagicMock(
- return_value=pd_resp.__dict__['data']['protectiondomain']
- )
- protection_domain_module_mock.powerflex_conn.protection_domain.delete = MagicMock(
- side_effect=utils.PowerFlexClient)
- protection_domain_module_mock.perform_module_operation()
- assert MockProtectionDomainApi.delete_pd_failed_msg(self.get_module_args['protection_domain_id']) in \
- protection_domain_module_mock.module.fail_json.call_args[1]['msg']
-
- def test_get_with_404_exception(self, protection_domain_module_mock):
- MockProtectionDomainApi.status = 404
- self.get_module_args.update({
- "protection_domain_name": "test_domain1"
- })
- protection_domain_module_mock.module.params = self.get_module_args
- pd_resp = MockSDKResponse(MockProtectionDomainApi.PROTECTION_DOMAIN)
- protection_domain_module_mock.powerflex_conn.protection_domain.get = MagicMock(
- return_value=pd_resp.__dict__['data']['protectiondomain']
- )
- protection_domain_module_mock.powerflex_conn.protection_domain.create = MagicMock(
- side_effect=utils.PowerFlexClient)
- protection_domain_module_mock.perform_module_operation()
- assert protection_domain_module_mock.module.exit_json.call_args[1]['changed'] is True
-
- def test_modify_protection_domain_throws_exception(self, protection_domain_module_mock):
- self.get_module_args.update({
- "protection_domain_id": "7bd6457000000000",
- 'rf_cache_limits': {
- 'is_enabled': True,
- 'page_size': 64,
- 'max_io_limit': 128,
- 'pass_through_mode': 'invalid_Read'
- }
- })
- protection_domain_module_mock.module.params = self.get_module_args
- pd_resp = MockSDKResponse(MockProtectionDomainApi.PROTECTION_DOMAIN)
- protection_domain_module_mock.powerflex_conn.protection_domain.get = MagicMock(
- return_value=pd_resp.__dict__['data']['protectiondomain']
- )
- protection_domain_module_mock.powerflex_conn.protection_domain.set_rfcache_enabled = MagicMock(
- side_effect=utils.PowerFlexClient)
- protection_domain_module_mock.perform_module_operation()
- assert MockProtectionDomainApi.modify_pd_with_failed_msg(self.get_module_args['protection_domain_id']) in \
- protection_domain_module_mock.module.fail_json.call_args[1]['msg']
-
- def test_rename_protection_domain_invalid_value(self, protection_domain_module_mock):
- self.get_module_args.update({
- "protection_domain_name": "test_domain",
- "protection_domain_new_name": " test domain",
- })
- protection_domain_module_mock.module.params = self.get_module_args
- pd_resp = MockSDKResponse(MockProtectionDomainApi.PROTECTION_DOMAIN)
- protection_domain_module_mock.powerflex_conn.protection_domain.get = MagicMock(
- return_value=pd_resp.__dict__['data']['protectiondomain']
- )
- protection_domain_module_mock.powerflex_conn.protection_domain.rename = MagicMock(
- side_effect=utils.PowerFlexClient)
- protection_domain_module_mock.perform_module_operation()
- assert MockProtectionDomainApi.rename_pd_failed_msg(self.get_module_args['protection_domain_id']) in \
- protection_domain_module_mock.module.fail_json.call_args[1]['msg']
-
- def test_create_protection_domain_invalid_param(self, protection_domain_module_mock):
- self.get_module_args.update({
- "protection_domain_name": "test_domain1",
- "protection_domain_new_name": "new_domain",
- "state": "present"
- })
- protection_domain_module_mock.module.params = self.get_module_args
- pd_resp = MockSDKResponse(MockProtectionDomainApi.PROTECTION_DOMAIN)
- protection_domain_module_mock.powerflex_conn.protection_domain.get = MagicMock(
- return_value=pd_resp.__dict__['data']['protectiondomain']
- )
- protection_domain_module_mock.powerflex_conn.protection_domain.create = MagicMock(
- side_effect=utils.PowerFlexClient)
- protection_domain_module_mock.perform_module_operation()
- assert MockProtectionDomainApi.version_pd_failed_msg() in \
- protection_domain_module_mock.module.fail_json.call_args[1]['msg']
+ def module_object(self):
+ return PowerFlexProtectionDomain
+
+ @pytest.mark.parametrize("params", [
+ {'protection_domain_id': MockProtectionDomainApi.PD_ID},
+ {"protection_domain_name": MockProtectionDomainApi.PD_NAME},
+ ])
+ def test_get_protection_domain_response(self, powerflex_module_mock, params):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_id': params.get('protection_domain_id', None),
+ 'protection_domain_name': params.get('protection_domain_name', None)
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN
+ )
+ powerflex_module_mock.perform_module_operation()
+ powerflex_module_mock.powerflex_conn.protection_domain.get.assert_called()
+
+ def test_get_pd_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_id': MockProtectionDomainApi.PD_ID,
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockApiException())
+ self.capture_fail_json_call(
+ MockProtectionDomainApi.get_failed_msgs('get_pd_failed_msg'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_validate_input_empty_params(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': ''
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN
+ )
+ self.capture_fail_json_call(
+ MockProtectionDomainApi.get_failed_msgs('empty_pd_msg'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_validate_network_limits_params(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': MockProtectionDomainApi.PD_NAME,
+ 'network_limits': {'overall_limit': -199,
+ 'bandwidth_unit': 'MBps'}
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN
+ )
+ self.capture_fail_json_call(
+ MockProtectionDomainApi.get_failed_msgs('overall_limit_msg'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_create_pd_new_name_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': MockProtectionDomainApi.PD_NAME,
+ 'protection_domain_new_name': MockProtectionDomainApi.PD_NAME
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=[]
+ )
+ self.capture_fail_json_call(
+ MockProtectionDomainApi.get_failed_msgs('new_name_in_create'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_create_pd_(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': MockProtectionDomainApi.PD_NAME
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=[]
+ )
+ powerflex_module_mock.powerflex_conn.protection_domain.create = MagicMock(
+ return_value=None
+ )
+ resp = powerflex_module_mock.create_protection_domain("protection_domain_name")
+ assert resp is True
+ powerflex_module_mock.powerflex_conn.protection_domain.create.assert_called()
+
+ def test_rename_pd(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': MockProtectionDomainApi.PD_NAME,
+ 'protection_domain_new_name': MockProtectionDomainApi.PD_NEW_NAME,
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.perform_module_operation()
+ powerflex_module_mock.powerflex_conn.protection_domain.rename.assert_called()
+
+ def test_rename_pd_execption(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': MockProtectionDomainApi.PD_NAME,
+ 'protection_domain_new_name': MockProtectionDomainApi.PD_NEW_NAME,
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.rename = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(
+ MockProtectionDomainApi.get_failed_msgs('rename_pd_exception'),
+ powerflex_module_mock, invoke_perform_module=True
+ )
+
+ def test_inactivate_pd(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': MockProtectionDomainApi.PD_NAME,
+ 'is_active': False
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.perform_module_operation()
+ powerflex_module_mock.powerflex_conn.protection_domain.inactivate.assert_called()
+
+ def test_activate_pd(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_id': MockProtectionDomainApi.PD_ID,
+ 'is_active': True
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN_1)
+ powerflex_module_mock.perform_module_operation()
+ powerflex_module_mock.powerflex_conn.protection_domain.activate.assert_called()
+
+ def test_create_pd_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': MockProtectionDomainApi.PD_NAME,
+ 'is_active': False
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=[]
+ )
+ powerflex_module_mock.powerflex_conn.protection_domain.create = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(
+ MockProtectionDomainApi.get_failed_msgs('create_pd_exception'),
+ powerflex_module_mock, invoke_perform_module=True
+ )
+
+ def test_modify_network_limits(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': MockProtectionDomainApi.PD_NAME,
+ 'network_limits': {'overall_limit': 15,
+ 'bandwidth_unit': 'GBps',
+ 'rebalance_limit': 10,
+ 'rebuild_limit': 10,
+ 'vtree_migration_limit': 10}
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.perform_module_operation()
+ powerflex_module_mock.powerflex_conn.protection_domain.network_limits.assert_called()
+
+ def test_modify_network_limits_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_id': MockProtectionDomainApi.PD_ID,
+ 'network_limits': {'overall_limit': 15,
+ 'bandwidth_unit': 'GBps',
+ 'rebalance_limit': 10,
+ 'rebuild_limit': 10,
+ 'vtree_migration_limit': 10}
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.network_limits = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(
+ MockProtectionDomainApi.get_failed_msgs('modify_network_limits_exception'),
+ powerflex_module_mock, invoke_perform_module=True
+ )
+
+ def test_enable_rf_cache(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': MockProtectionDomainApi.PD_NAME,
+ 'rf_cache_limits': {'is_enabled': True,
+ 'page_size': 10,
+ 'max_io_limit': 10,
+ 'pass_through_mode': 'Read'}
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.perform_module_operation()
+ powerflex_module_mock.powerflex_conn.protection_domain.set_rfcache_enabled.assert_called()
+ powerflex_module_mock.powerflex_conn.protection_domain.rfcache_parameters.assert_called()
+
+ def test_modify_rf_cache_params_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': MockProtectionDomainApi.PD_NAME,
+ 'rf_cache_limits': {'is_enabled': True, 'page_size': 10,
+ 'max_io_limit': 10, 'pass_through_mode': 'Read'}
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.set_rfcache_enabled = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(
+ MockProtectionDomainApi.get_failed_msgs('rf_cache_limits_exception'),
+ powerflex_module_mock, invoke_perform_module=True
+ )
+
+ def test_delete_pd(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': MockProtectionDomainApi.PD_NAME,
+ 'state': 'absent'
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.perform_module_operation()
+ powerflex_module_mock.powerflex_conn.protection_domain.delete.assert_called()
+
+ def test_delete_pd_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_id': MockProtectionDomainApi.PD_ID,
+ 'state': 'absent'
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.delete = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(
+ MockProtectionDomainApi.get_failed_msgs('delete_pd_exception'),
+ powerflex_module_mock, invoke_perform_module=True
+ )
+
+ def test_get_sp(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': MockProtectionDomainApi.PD_NAME
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.get_storage_pools = MagicMock(
+ return_value=MockProtectionDomainApi.STORAGE_POOL)
+ powerflex_module_mock.perform_module_operation()
+ powerflex_module_mock.powerflex_conn.protection_domain.get_storage_pools.assert_called()
+
+ def test_get_sp_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_id': MockProtectionDomainApi.PD_ID
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockProtectionDomainApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.get_storage_pools = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(
+ MockProtectionDomainApi.get_failed_msgs('get_sp_exception'),
+ powerflex_module_mock, invoke_perform_module=True)
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_replication_consistency_group.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_replication_consistency_group.py
index 334de8942..e1074f282 100644
--- a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_replication_consistency_group.py
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_replication_consistency_group.py
@@ -5,7 +5,6 @@
"""Unit Tests for replication consistency group module on PowerFlex"""
from __future__ import (absolute_import, division, print_function)
-from unittest.mock import Mock
__metaclass__ = type
@@ -170,7 +169,7 @@ class TestPowerflexReplicationConsistencyGroup():
replication_consistency_group_module_mock.module.fail_json.call_args[1]['msg']
def test_pause_rcg(self, replication_consistency_group_module_mock):
- self.get_module_args.update({"rcg_name": "test_rcg", "pause": True,
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": 'pause',
"pause_mode": "StopDataTransfer", "state": "present"})
replication_consistency_group_module_mock.module.params = self.get_module_args
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
@@ -180,7 +179,7 @@ class TestPowerflexReplicationConsistencyGroup():
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.pause.assert_called()
def test_pause_rcg_throws_exception(self, replication_consistency_group_module_mock):
- self.get_module_args.update({"rcg_name": "test_rcg", "pause": True,
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": 'pause',
"pause_mode": "StopDataTransfer", "state": "present"})
replication_consistency_group_module_mock.module.params = self.get_module_args
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
@@ -193,7 +192,7 @@ class TestPowerflexReplicationConsistencyGroup():
replication_consistency_group_module_mock.module.fail_json.call_args[1]['msg']
def test_resume_rcg(self, replication_consistency_group_module_mock):
- self.get_module_args.update({"rcg_name": "test_rcg", "pause": False, "state": "present"})
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": 'resume', "state": "present"})
replication_consistency_group_module_mock.module.params = self.get_module_args
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
return_value=MockReplicationConsistencyGroupApi.get_rcg_details(pause_mode="StopDataTransfer"))
@@ -201,7 +200,7 @@ class TestPowerflexReplicationConsistencyGroup():
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.resume.assert_called()
def test_resume_rcg_throws_exception(self, replication_consistency_group_module_mock):
- self.get_module_args.update({"rcg_name": "test_rcg", "pause": False, "state": "present"})
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": 'resume', "state": "present"})
replication_consistency_group_module_mock.module.params = self.get_module_args
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
return_value=MockReplicationConsistencyGroupApi.get_rcg_details(pause_mode="StopDataTransfer"))
@@ -213,7 +212,7 @@ class TestPowerflexReplicationConsistencyGroup():
replication_consistency_group_module_mock.module.fail_json.call_args[1]['msg']
def test_freeze_rcg(self, replication_consistency_group_module_mock):
- self.get_module_args.update({"rcg_name": "test_rcg", "freeze": True, "state": "present"})
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": 'freeze', "state": "present"})
replication_consistency_group_module_mock.module.params = self.get_module_args
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
return_value=MockReplicationConsistencyGroupApi.get_rcg_details())
@@ -221,7 +220,7 @@ class TestPowerflexReplicationConsistencyGroup():
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.freeze.assert_called()
def test_freeze_rcg_throws_exception(self, replication_consistency_group_module_mock):
- self.get_module_args.update({"rcg_name": "test_rcg", "freeze": True, "state": "present"})
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": 'freeze', "state": "present"})
replication_consistency_group_module_mock.module.params = self.get_module_args
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
return_value=MockReplicationConsistencyGroupApi.get_rcg_details())
@@ -233,7 +232,7 @@ class TestPowerflexReplicationConsistencyGroup():
replication_consistency_group_module_mock.module.fail_json.call_args[1]['msg']
def test_unfreeze_rcg(self, replication_consistency_group_module_mock):
- self.get_module_args.update({"rcg_name": "test_rcg", "freeze": False, "state": "present"})
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": 'unfreeze', "state": "present"})
replication_consistency_group_module_mock.module.params = self.get_module_args
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
return_value=MockReplicationConsistencyGroupApi.get_rcg_details(freeze_state="Frozen")
@@ -242,7 +241,7 @@ class TestPowerflexReplicationConsistencyGroup():
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.unfreeze.assert_called()
def test_unfreeze_rcg_throws_exception(self, replication_consistency_group_module_mock):
- self.get_module_args.update({"rcg_name": "test_rcg", "freeze": False, "state": "present"})
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": 'unfreeze', "state": "present"})
replication_consistency_group_module_mock.module.params = self.get_module_args
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
return_value=MockReplicationConsistencyGroupApi.get_rcg_details(freeze_state="Frozen"))
@@ -311,7 +310,7 @@ class TestPowerflexReplicationConsistencyGroup():
replication_consistency_group_module_mock.module.fail_json.call_args[1]['msg']
def test_pause_rcg_without_pause_mode(self, replication_consistency_group_module_mock):
- self.get_module_args.update({"rcg_name": "test_rcg", "pause": True, "state": "present"})
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": 'pause', "state": "present"})
replication_consistency_group_module_mock.module.params = self.get_module_args
replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
return_value=MockReplicationConsistencyGroupApi.get_rcg_details())
@@ -340,5 +339,109 @@ class TestPowerflexReplicationConsistencyGroup():
return_value=MockReplicationConsistencyGroupApi.get_rcg_details())
replication_consistency_group_module_mock.powerflex_conn.protection_domain.get = MagicMock(return_value=[{"name": "pd_id"}])
replication_consistency_group_module_mock.perform_module_operation()
- assert "Specify pause as True to pause replication consistency group" in \
+ assert "Specify rcg_state as 'pause' to pause replication consistency group" in \
+ replication_consistency_group_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_failover_rcg(self, replication_consistency_group_module_mock):
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": "failover", "state": "present"})
+ replication_consistency_group_module_mock.module.params = self.get_module_args
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
+ return_value=MockReplicationConsistencyGroupApi.get_rcg_details())
+ replication_consistency_group_module_mock.perform_module_operation()
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.failover.assert_called()
+
+ def test_failover_rcg_throws_exception(self, replication_consistency_group_module_mock):
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": "failover", "state": "present"})
+ replication_consistency_group_module_mock.module.params = self.get_module_args
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
+ return_value=MockReplicationConsistencyGroupApi.get_rcg_details())
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.failover = \
+ MagicMock(side_effect=MockApiException)
+ replication_consistency_group_module_mock.perform_module_operation()
+ assert "Failover replication consistency group " + MockReplicationConsistencyGroupApi.RCG_ID \
+ + MockReplicationConsistencyGroupApi.FAIL_MSG in \
+ replication_consistency_group_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_restore_rcg(self, replication_consistency_group_module_mock):
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": "restore", "state": "present"})
+ replication_consistency_group_module_mock.module.params = self.get_module_args
+ rcg_details = MockReplicationConsistencyGroupApi.get_rcg_details()
+ rcg_details[0]['failoverType'] = 'Failover'
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(return_value=rcg_details)
+ replication_consistency_group_module_mock.perform_module_operation()
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.restore.assert_called()
+
+ def test_restore_rcg_throws_exception(self, replication_consistency_group_module_mock):
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": "restore", "state": "present"})
+ replication_consistency_group_module_mock.module.params = self.get_module_args
+ rcg_details = MockReplicationConsistencyGroupApi.get_rcg_details()
+ rcg_details[0]['failoverType'] = 'Failover'
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(return_value=rcg_details)
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.restore = \
+ MagicMock(side_effect=MockApiException)
+ replication_consistency_group_module_mock.perform_module_operation()
+ assert "Restore replication consistency group " + MockReplicationConsistencyGroupApi.RCG_ID \
+ + MockReplicationConsistencyGroupApi.FAIL_MSG in \
+ replication_consistency_group_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_reverse_rcg(self, replication_consistency_group_module_mock):
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": "reverse", "state": "present"})
+ replication_consistency_group_module_mock.module.params = self.get_module_args
+ rcg_details = MockReplicationConsistencyGroupApi.get_rcg_details()
+ rcg_details[0]['failoverType'] = 'Failover'
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(return_value=rcg_details)
+ replication_consistency_group_module_mock.perform_module_operation()
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.reverse.assert_called()
+
+ def test_reverse_rcg_throws_exception(self, replication_consistency_group_module_mock):
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": "reverse", "state": "present"})
+ replication_consistency_group_module_mock.module.params = self.get_module_args
+ rcg_details = MockReplicationConsistencyGroupApi.get_rcg_details()
+ rcg_details[0]['failoverType'] = 'Failover'
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(return_value=rcg_details)
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.reverse = \
+ MagicMock(side_effect=MockApiException)
+ replication_consistency_group_module_mock.perform_module_operation()
+ assert "Reverse replication consistency group " + MockReplicationConsistencyGroupApi.RCG_ID \
+ + MockReplicationConsistencyGroupApi.FAIL_MSG in \
+ replication_consistency_group_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_switchover_rcg(self, replication_consistency_group_module_mock):
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": "switchover", "state": "present"})
+ replication_consistency_group_module_mock.module.params = self.get_module_args
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
+ return_value=MockReplicationConsistencyGroupApi.get_rcg_details())
+ replication_consistency_group_module_mock.perform_module_operation()
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.switchover.assert_called()
+
+ def test_switchover_rcg_throws_exception(self, replication_consistency_group_module_mock):
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": "switchover", "state": "present"})
+ replication_consistency_group_module_mock.module.params = self.get_module_args
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
+ return_value=MockReplicationConsistencyGroupApi.get_rcg_details())
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.switchover = \
+ MagicMock(side_effect=MockApiException)
+ replication_consistency_group_module_mock.perform_module_operation()
+ assert "Switchover replication consistency group " + MockReplicationConsistencyGroupApi.RCG_ID \
+ + MockReplicationConsistencyGroupApi.FAIL_MSG in \
+ replication_consistency_group_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_sync_rcg(self, replication_consistency_group_module_mock):
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": 'sync', "state": "present"})
+ replication_consistency_group_module_mock.module.params = self.get_module_args
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
+ return_value=MockReplicationConsistencyGroupApi.get_rcg_details())
+ replication_consistency_group_module_mock.perform_module_operation()
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.sync.assert_called()
+
+ def test_sync_rcg_throws_exception(self, replication_consistency_group_module_mock):
+ self.get_module_args.update({"rcg_name": "test_rcg", "rcg_state": 'sync', "state": "present"})
+ replication_consistency_group_module_mock.module.params = self.get_module_args
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.get = MagicMock(
+ return_value=MockReplicationConsistencyGroupApi.get_rcg_details())
+ replication_consistency_group_module_mock.powerflex_conn.replication_consistency_group.sync = \
+ MagicMock(side_effect=MockApiException)
+ replication_consistency_group_module_mock.perform_module_operation()
+ assert "Synchronization of replication consistency group " + MockReplicationConsistencyGroupApi.RCG_ID \
+ + MockReplicationConsistencyGroupApi.FAIL_MSG in \
replication_consistency_group_module_mock.module.fail_json.call_args[1]['msg']
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_replication_pair.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_replication_pair.py
index 81787de8f..e3c9cf18d 100644
--- a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_replication_pair.py
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_replication_pair.py
@@ -1,11 +1,10 @@
-# Copyright: (c) 2023, Dell Technologies
+# Copyright: (c) 2024, Dell Technologies
# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
"""Unit Tests for replication pair module on PowerFlex"""
from __future__ import (absolute_import, division, print_function)
-from unittest.mock import Mock
__metaclass__ = type
@@ -16,6 +15,8 @@ from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_
import MockApiException
from ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell \
import utils
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_fail_json \
+ import FailJsonException, fail_json
utils.get_logger = MagicMock()
utils.get_powerflex_gateway_host_connection = MagicMock()
@@ -26,7 +27,7 @@ basic.AnsibleModule = MagicMock()
from ansible_collections.dellemc.powerflex.plugins.modules.replication_pair import PowerFlexReplicationPair
-class TestPowerflexReplicationPair():
+class TestPowerflexReplicationPair:
get_module_args = MockReplicationPairApi.REPLICATION_PAIR_COMMON_ARGS
@@ -37,6 +38,19 @@ class TestPowerflexReplicationPair():
replication_pair_module_mock.module.check_mode = False
return replication_pair_module_mock
+ @pytest.fixture
+ def replication_pair_mock(self):
+ replication_pair_mock = PowerFlexReplicationPair()
+ replication_pair_mock.module.check_mode = False
+ replication_pair_mock.module.fail_json = fail_json
+ return replication_pair_mock
+
+ def capture_fail_json_call(self, error_msg, device_module_mock):
+ try:
+ device_module_mock.perform_module_operation()
+ except FailJsonException as fj_object:
+ assert error_msg in fj_object.message
+
def test_get_pair_details(self, replication_pair_module_mock):
self.get_module_args.update({
"pair_name": "test_pair",
@@ -235,3 +249,115 @@ class TestPowerflexReplicationPair():
replication_pair_module_mock.perform_module_operation()
assert "Failed to get the replication pairs for replication consistency group" in \
replication_pair_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_rcg_application_pairs(self, replication_pair_module_mock):
+ self.get_module_args.update({
+ "rcg_name": "test_rcg",
+ "pairs": [{"source_volume_name": "src_vol", "target_volume_name": "dest_vol", "source_volume_id": None,
+ "target_volume_id": None, "copy_type": "OnlineCopy", "name": "test_pair"}],
+ "state": "present"
+ })
+ replication_pair_module_mock.module.params = self.get_module_args
+ replication_pair_module_mock.powerflex_conn.volume.get = MagicMock(
+ return_value=MockReplicationPairApi.get_volume_details()
+ )
+ replication_pair_module_mock.get_rcg = MagicMock(return_value={"id": 123, "name": "test_rcg"})
+ replication_pair_module_mock.powerflex_conn.replication_consistency_group.get_replication_pairs = MagicMock(
+ return_value=MockReplicationPairApi.get_pair_details())
+ replication_pair_module_mock.perform_module_operation()
+ replication_pair_module_mock.powerflex_conn.replication_pair.add.assert_called()
+
+ def test_get_rcg_name(self, replication_pair_mock):
+ self.get_module_args.update({
+ "rcg_name": "test_rcg",
+ "pairs": [{"source_volume_name": "src_vol", "target_volume_name": "dest_vol", "source_volume_id": None,
+ "target_volume_id": None, "copy_type": "OnlineCopy", "name": "test_pair"}],
+ "state": "present"
+ })
+ replication_pair_mock.module.params = self.get_module_args
+ replication_pair_mock.powerflex_conn.replication_consistency_group = MagicMock(
+ return_value=[{"name": "test_rcg", "id": 12}]
+ )
+ replication_pair_mock.powerflex_conn.replication_consistency_group.get_replication_pairs = MagicMock(
+ return_value=MockReplicationPairApi.get_pair_details())
+ replication_pair_mock.create_replication_pairs = MagicMock(return_value=True)
+ replication_pair_mock.get_rcg_replication_pairs = MagicMock(return_value={})
+ replication_pair_mock.get_replication_pair = MagicMock(return_value=None)
+ replication_pair_mock.validate_pause_or_resume = MagicMock(return_value=True)
+ replication_pair_mock.perform_module_operation()
+ assert replication_pair_mock.module.exit_json.call_args[1]['changed'] is True
+
+ def test_get_rcg_id(self, replication_pair_mock):
+ self.get_module_args.update({
+ "rcg_id": 12,
+ "pairs": [{"source_volume_name": "src_vol", "target_volume_name": "dest_vol", "source_volume_id": None,
+ "target_volume_id": None, "copy_type": "OnlineCopy", "name": "test_pair"}],
+ "state": "present"
+ })
+ replication_pair_mock.module.params = self.get_module_args
+ replication_pair_mock.powerflex_conn.replication_consistency_group = MagicMock(
+ return_value=[{"name": "test_rcg", "id": 12}]
+ )
+ replication_pair_mock.powerflex_conn.replication_consistency_group.get_replication_pairs = MagicMock(
+ return_value=MockReplicationPairApi.get_pair_details())
+ replication_pair_mock.create_replication_pairs = MagicMock(return_value=True)
+ replication_pair_mock.get_rcg_replication_pairs = MagicMock(return_value={})
+ replication_pair_mock.get_replication_pair = MagicMock(return_value=None)
+ replication_pair_mock.validate_pause_or_resume = MagicMock(return_value=True)
+ replication_pair_mock.perform_module_operation()
+ assert replication_pair_mock.module.exit_json.call_args[1]['changed'] is True
+
+ def test_get_rcg_exception(self, replication_pair_mock):
+ self.get_module_args.update({
+ "rcg_id": 12,
+ "pairs": [{"source_volume_name": "src_vol", "target_volume_name": "dest_vol", "source_volume_id": None,
+ "target_volume_id": None, "copy_type": "OnlineCopy", "name": "test_pair"}],
+ "state": "present"
+ })
+ replication_pair_mock.module.params = self.get_module_args
+ replication_pair_mock.powerflex_conn.replication_consistency_group.get = MagicMock(side_effect=MockApiException)
+ replication_pair_mock.create_replication_pairs = MagicMock(return_value=None)
+ self.capture_fail_json_call(MockReplicationPairApi.get_error_message('get_rcg_exception'),
+ replication_pair_mock)
+
+ def test_input_validation(self, replication_pair_mock):
+ self.get_module_args.update({
+ "rcg_id": None, "rcg_name": None,
+ "pairs": [{"source_volume_name": "src_vol", "target_volume_name": "dest_vol", "source_volume_id": None,
+ "target_volume_id": None, "copy_type": "OnlineCopy", "name": "test_pair"}],
+ "state": "present"
+ })
+ replication_pair_mock.module.params = self.get_module_args
+ replication_pair_mock.validate_pairs = MagicMock(return_value=None)
+ self.capture_fail_json_call(MockReplicationPairApi.get_error_message('get_rcg_id_name_error'),
+ replication_pair_mock)
+ self.get_module_args.update({
+ "rcg_name": "test_rcg", "pairs": None, "state": "present", "pause": False,
+ "pair_id": None, "pair_name": None
+ })
+ replication_pair_mock.module.params = self.get_module_args
+ self.capture_fail_json_call(MockReplicationPairApi.get_error_message('get_pause_error'),
+ replication_pair_mock)
+ self.get_module_args.update({
+ "rcg_name": "test_rcg", "pairs": None, "state": "present", "pause": False,
+ "pair_id": None, "pair_name": None
+ })
+ replication_pair_mock.module.params = self.get_module_args
+ replication_pair_mock.validate_input = MagicMock(return_value=None)
+ self.capture_fail_json_call(MockReplicationPairApi.get_error_message('get_pause_or_resume_error'),
+ replication_pair_mock)
+
+ def test_get_volume_exception(self, replication_pair_mock):
+ self.get_module_args.update({
+ "rcg_name": "test_rcg", "pairs": None, "state": "present", "pause": False,
+ "pair_id": None, "pair_name": "test_pair"
+ })
+ replication_pair_mock.module.params = self.get_module_args
+ replication_pair_mock.validate_input = MagicMock(return_value=None)
+ replication_pair_mock.powerflex_conn.replication_consistency_group.get_replication_pairs = MagicMock(
+ return_value=MockReplicationPairApi.get_pair_details())
+ replication_pair_mock.powerflex_conn.volume.get = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockReplicationPairApi.get_error_message('get_volume_exception'),
+ replication_pair_mock)
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_sdc.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_sdc.py
new file mode 100644
index 000000000..dbf9ac1e0
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_sdc.py
@@ -0,0 +1,192 @@
+# Copyright: (c) 2024, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""Unit Tests for SDC module on PowerFlex"""
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+import pytest
+# pylint: disable=unused-import
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.libraries import initial_mock
+from mock.mock import MagicMock
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_sdc_api import MockSdcApi
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_api_exception \
+ import MockApiException
+from ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell \
+ import utils
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_fail_json \
+ import FailJsonException, fail_json
+
+utils.get_logger = MagicMock()
+utils.get_powerflex_gateway_host_connection = MagicMock()
+utils.PowerFlexClient = MagicMock()
+
+from ansible.module_utils import basic
+basic.AnsibleModule = MagicMock()
+from ansible_collections.dellemc.powerflex.plugins.modules.sdc import PowerFlexSdc
+
+
+class TestPowerflexSdc():
+
+ get_module_args = MockSdcApi.COMMON_ARGS
+
+ @pytest.fixture
+ def sdc_module_mock(self, mocker):
+ mocker.patch(
+ MockSdcApi.MODULE_UTILS_PATH + '.PowerFlexClient',
+ new=MockApiException)
+ sdc_module_mock = PowerFlexSdc()
+ sdc_module_mock.module.check_mode = False
+ sdc_module_mock.module.fail_json = fail_json
+ return sdc_module_mock
+
+ def capture_fail_json_call(self, error_msg, sdc_module_mock):
+ try:
+ sdc_module_mock.perform_module_operation()
+ except FailJsonException as fj_object:
+ assert error_msg in fj_object.message
+
+ def test_get_sdc_details(self, sdc_module_mock):
+ self.get_module_args.update({
+ "sdc_name": "test_sdc",
+ "state": "present"
+ })
+ sdc_module_mock.module.params = self.get_module_args
+ sdc_module_mock.powerflex_conn.sdc.get = MagicMock(
+ return_value=MockSdcApi.get_sdc_details()
+ )
+ sdc_module_mock.perform_module_operation()
+ sdc_module_mock.powerflex_conn.sdc.get.assert_called()
+
+ def test_get_sdc_details_empty_sdc_id_exception(self, sdc_module_mock):
+ self.get_module_args.update({
+ "sdc_id": " ",
+ "state": "present"
+ })
+ sdc_module_mock.module.params = self.get_module_args
+ self.capture_fail_json_call(MockSdcApi.get_sdc_exception_response(
+ 'get_sdc_details_empty_sdc_id_exception'), sdc_module_mock)
+
+ def test_get_sdc_details_with_exception(self, sdc_module_mock):
+ self.get_module_args.update({
+ "sdc_id": MockSdcApi.SDC_ID,
+ "state": "present"
+ })
+ sdc_module_mock.module.params = self.get_module_args
+ sdc_module_mock.powerflex_conn.sdc.get = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(MockSdcApi.get_sdc_exception_response(
+ 'get_sdc_details_with_exception'), sdc_module_mock)
+
+ def test_get_sdc_details_mapped_volumes_with_exception(self, sdc_module_mock):
+ self.get_module_args.update({
+ "sdc_id": MockSdcApi.SDC_ID,
+ "state": "present"
+ })
+ sdc_module_mock.module.params = self.get_module_args
+ sdc_module_mock.powerflex_conn.sdc.get = MagicMock(
+ return_value=MockSdcApi.get_sdc_details()
+ )
+ sdc_module_mock.powerflex_conn.sdc.get_mapped_volumes = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(MockSdcApi.get_sdc_exception_response(
+ 'get_sdc_details_mapped_volumes_with_exception'), sdc_module_mock)
+
+ def test_modify_sdc(self, sdc_module_mock):
+ self.get_module_args.update({
+ "sdc_name": "test_sdc",
+ "performance_profile": "Compact",
+ "state": "present"
+ })
+ sdc_module_mock.module.params = self.get_module_args
+ sdc_module_mock.powerflex_conn.sdc.get = MagicMock(
+ return_value=MockSdcApi.get_sdc_details()
+ )
+ sdc_module_mock.powerflex_conn.sdc.set_performance_profile = MagicMock(return_value=True)
+ sdc_module_mock.perform_module_operation()
+ sdc_module_mock.powerflex_conn.sdc.set_performance_profile.assert_called()
+
+ def test_modify_sdc_throws_exception(self, sdc_module_mock):
+ self.get_module_args.update({
+ "sdc_name": "test_sdc",
+ "performance_profile": "Compact",
+ "state": "present"
+ })
+ sdc_module_mock.module.params = self.get_module_args
+ sdc_module_mock.powerflex_conn.sdc.get = MagicMock(
+ return_value=MockSdcApi.get_sdc_details()
+ )
+ sdc_module_mock.powerflex_conn.sdc.set_performance_profile = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(MockSdcApi.get_sdc_exception_response(
+ 'modify_sdc_throws_exception'), sdc_module_mock)
+
+ def test_rename_sdc(self, sdc_module_mock):
+ self.get_module_args.update({
+ "sdc_name": "test_sdc",
+ "sdc_new_name": "test_sdc_renamed",
+ "state": "present"
+ })
+ sdc_module_mock.module.params = self.get_module_args
+ sdc_module_mock.powerflex_conn.sdc.get = MagicMock(
+ return_value=MockSdcApi.get_sdc_details()
+ )
+ sdc_module_mock.powerflex_conn.sdc.rename = MagicMock(return_value=True)
+ sdc_module_mock.perform_module_operation()
+ sdc_module_mock.powerflex_conn.sdc.rename.assert_called()
+
+ def test_rename_sdc_empty_new_name_exception(self, sdc_module_mock):
+ self.get_module_args.update({
+ "sdc_name": "test_sdc",
+ "sdc_new_name": " ",
+ "state": "present"
+ })
+ sdc_module_mock.module.params = self.get_module_args
+ sdc_module_mock.powerflex_conn.sdc.get = MagicMock(
+ return_value=MockSdcApi.get_sdc_details()
+ )
+ self.capture_fail_json_call(MockSdcApi.get_sdc_exception_response(
+ 'rename_sdc_empty_new_name_exception'), sdc_module_mock)
+
+ def test_rename_sdc_throws_exception(self, sdc_module_mock):
+ self.get_module_args.update({
+ "sdc_name": "test_sdc",
+ "sdc_new_name": "test_sdc_renamed",
+ "state": "present"
+ })
+ sdc_module_mock.module.params = self.get_module_args
+ sdc_module_mock.powerflex_conn.sdc.get = MagicMock(
+ return_value=MockSdcApi.get_sdc_details()
+ )
+ sdc_module_mock.powerflex_conn.sdc.rename = MagicMock(side_effect=MockApiException)
+ self.capture_fail_json_call(MockSdcApi.get_sdc_exception_response(
+ 'rename_sdc_throws_exception'), sdc_module_mock)
+
+ def test_remove_sdc(self, sdc_module_mock):
+ self.get_module_args.update({
+ "sdc_name": "test_sdc",
+ "state": "absent"
+ })
+ sdc_module_mock.module.params = self.get_module_args
+ sdc_module_mock.powerflex_conn.sdc.get = MagicMock(
+ return_value=MockSdcApi.get_sdc_details()
+ )
+ sdc_module_mock.powerflex_conn.sdc.delete = MagicMock(return_value=True)
+ sdc_module_mock.perform_module_operation()
+ sdc_module_mock.powerflex_conn.sdc.delete.assert_called()
+
+ def test_remove_sdc_throws_exception(self, sdc_module_mock):
+ self.get_module_args.update({
+ "sdc_ip": "1.1.1.1",
+ "state": "absent"
+ })
+ sdc_module_mock.module.params = self.get_module_args
+ sdc_module_mock.powerflex_conn.sdc.get = MagicMock(
+ return_value=MockSdcApi.get_sdc_details()
+ )
+ sdc_module_mock.powerflex_conn.sdc.delete = MagicMock(side_effect=MockApiException)
+ self.capture_fail_json_call(MockSdcApi.get_sdc_exception_response(
+ 'remove_sdc_throws_exception'), sdc_module_mock)
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_sds.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_sds.py
new file mode 100644
index 000000000..30e9a589f
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_sds.py
@@ -0,0 +1,630 @@
+# Copyright: (c) 2024, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""Unit Tests for SDS module on PowerFlex"""
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+import pytest
+# pylint: disable=unused-import
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.libraries import initial_mock
+from mock.mock import MagicMock
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_sds_api import MockSDSApi
+from ansible_collections.dellemc.powerflex.plugins.modules.sds import \
+ SDSHandler
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_sdk_response \
+ import MockSDKResponse
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_api_exception \
+ import MockApiException
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.libraries.powerflex_unit_base \
+ import PowerFlexUnitBase
+
+from ansible_collections.dellemc.powerflex.plugins.modules.sds import PowerFlexSDS
+
+
+class TestPowerflexSDS(PowerFlexUnitBase):
+
+ get_module_args = MockSDSApi.SDS_COMMON_ARGS
+ ip1 = "10.47.xxx.xxx"
+ ip2 = "10.46.xxx.xxx"
+
+ @pytest.fixture
+ def module_object(self):
+ return PowerFlexSDS
+
+ def test_get_sds_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'sds_id': '8f3bb0cc00000002',
+ 'state': 'present'
+ })
+ powerflex_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST)
+ pd_resp = MockSDKResponse(MockSDSApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp.__dict__['data']['protectiondomain'])
+ fs_resp = MockSDSApi.FAULT_SET_GET_LIST
+ powerflex_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=fs_resp)
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.get.assert_called()
+
+ def test_get_sds_name_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'state': "present"
+ })
+ powerflex_module_mock.powerflex_conn.sds.get = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST)
+ pd_resp = MockSDKResponse(MockSDSApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp.__dict__['data']['protectiondomain'])
+ fs_resp = MockSDSApi.FAULT_SET_GET_LIST
+ powerflex_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=fs_resp)
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.get.assert_called()
+
+ def test_get_sds_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'state': "present"
+ })
+ powerflex_module_mock.powerflex_conn.sds.get = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'get_sds_exception'), powerflex_module_mock, SDSHandler)
+
+ def test_create_sds_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': 'test_domain',
+ 'fault_set_name': 'fault_set_name',
+ 'sds_ip_list':
+ [
+ {
+ 'ip': self.ip1,
+ 'role': "all"
+ }
+ ],
+ 'sds_ip_state': 'present-in-sds',
+ 'rmcache_enabled': True,
+ 'rmcache_size': 128,
+ 'performance_profile': "HighPerformance",
+ 'state': "present"
+ })
+ pd_resp = MockSDKResponse(MockSDSApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp.__dict__['data']['protectiondomain'])
+ fs_resp = MockSDSApi.FAULT_SET_GET_LIST
+ powerflex_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=fs_resp)
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=None)
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.create.assert_called()
+
+ def test_create_sds_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': 'test_domain',
+ 'fault_set_name': 'fault_set_name',
+ 'sds_ip_list':
+ [
+ {
+ 'ip': self.ip1,
+ 'role': "all"
+ }
+ ],
+ 'sds_ip_state': 'present-in-sds',
+ 'rmcache_enabled': True,
+ 'rmcache_size': 128,
+ 'performance_profile': "HighPerformance",
+ 'state': "present"
+ })
+ pd_resp = MockSDKResponse(MockSDSApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp.__dict__['data']['protectiondomain'])
+ powerflex_module_mock.get_fault_set = MagicMock(
+ return_value=MockSDSApi.FAULT_SET_GET_LIST[0])
+ powerflex_module_mock.powerflex_conn.sds.create = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'create_sds_exception'), powerflex_module_mock, SDSHandler)
+
+ def test_rename_sds_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "sds_new_name": "node0_new",
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.rename.assert_called()
+
+ def test_modify_rfcache_enabled_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "rfcache_enabled": False,
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.set_rfcache_enabled.assert_called()
+
+ def test_modify_rmcache_enabled_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "rmcache_enabled": False,
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.set_rmcache_enabled.assert_called()
+
+ def test_modify_rmcache_size_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "rmcache_size": 256,
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.set_rmcache_size.assert_called()
+
+ def test_rmcache_size_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': 'test_domain',
+ 'fault_set_name': 'fault_set_name',
+ 'sds_ip_list':
+ [
+ {
+ 'ip': self.ip1,
+ 'role': "all"
+ }
+ ],
+ 'sds_ip_state': 'present-in-sds',
+ 'rmcache_enabled': False,
+ 'rmcache_size': 128,
+ 'state': "present"
+ })
+ pd_resp = MockSDKResponse(MockSDSApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp.__dict__['data']['protectiondomain'])
+ fs_resp = MockSDSApi.FAULT_SET_GET_LIST
+ powerflex_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=fs_resp)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'rmcache_size_exception'), powerflex_module_mock, SDSHandler)
+
+ def test_create_sds_wo_sds_name_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'sds_name': None,
+ 'protection_domain_name': 'test_domain',
+ 'fault_set_name': 'fault_set_name',
+ 'sds_ip_list':
+ [
+ {
+ 'ip': self.ip1,
+ 'role': "all"
+ }
+ ],
+ 'sds_ip_state': 'present-in-sds',
+ 'rmcache_enabled': True,
+ 'rmcache_size': 128,
+ 'state': "present"
+ })
+ pd_resp = MockSDKResponse(MockSDSApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp.__dict__['data']['protectiondomain'])
+ fs_resp = MockSDSApi.FAULT_SET_GET_LIST
+ powerflex_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=fs_resp)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'create_sds_wo_sds_name'), powerflex_module_mock, SDSHandler)
+
+ def test_create_sds_wo_pd_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'fault_set_name': 'fault_set_name',
+ 'sds_ip_list':
+ [
+ {
+ 'ip': self.ip1,
+ 'role': "all"
+ }
+ ],
+ 'sds_ip_state': 'present-in-sds',
+ 'rmcache_enabled': True,
+ 'rmcache_size': 128,
+ 'state': "present"
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=None)
+ fs_resp = MockSDSApi.FAULT_SET_GET_LIST
+ powerflex_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=fs_resp)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'create_sds_wo_pd'), powerflex_module_mock, SDSHandler)
+
+ def test_create_sds_wo_sds_ip_list_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': 'test_domain',
+ 'fault_set_name': 'fault_set_name',
+ 'sds_ip_list': [],
+ 'sds_ip_state': 'present-in-sds',
+ 'rmcache_enabled': True,
+ 'rmcache_size': 128,
+ 'state': "present"
+ })
+ pd_resp = MockSDKResponse(MockSDSApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp.__dict__['data']['protectiondomain'])
+ fs_resp = MockSDSApi.FAULT_SET_GET_LIST
+ powerflex_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=fs_resp)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'create_sds_wo_sds_ip_list'), powerflex_module_mock, SDSHandler)
+
+ def test_create_sds_incorrect_sds_ip_state_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'protection_domain_name': 'test_domain',
+ 'fault_set_name': 'fault_set_name',
+ 'sds_ip_list':
+ [
+ {
+ 'ip': self.ip1,
+ 'role': "all"
+ }
+ ],
+ 'sds_ip_state': 'absent-in-sds',
+ 'rmcache_enabled': True,
+ 'rmcache_size': 128,
+ 'state': "present"
+ })
+ pd_resp = MockSDKResponse(MockSDSApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp.__dict__['data']['protectiondomain'])
+ fs_resp = MockSDSApi.FAULT_SET_GET_LIST
+ powerflex_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=fs_resp)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'create_sds_incorrect_sds_ip_state'), powerflex_module_mock, SDSHandler)
+
+ def test_create_sds_sds_id_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'sds_id': "sds_id_1",
+ 'protection_domain_name': 'test_domain',
+ 'fault_set_name': 'fault_set_name',
+ 'sds_ip_list':
+ [
+ {
+ 'ip': self.ip1,
+ 'role': "all"
+ }
+ ],
+ 'sds_ip_state': 'present-in-sds',
+ 'rmcache_enabled': True,
+ 'rmcache_size': 128,
+ 'state': "present"
+ })
+ pd_resp = MockSDKResponse(MockSDSApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp.__dict__['data']['protectiondomain'])
+ fs_resp = MockSDSApi.FAULT_SET_GET_LIST
+ powerflex_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=fs_resp)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'create_sds_sds_id'), powerflex_module_mock, SDSHandler)
+
+ def test_create_sds_sds_new_name_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'sds_new_name': "sds_new_name",
+ 'protection_domain_name': 'test_domain',
+ 'fault_set_name': 'fault_set_name',
+ 'sds_ip_list':
+ [
+ {
+ 'ip': self.ip1,
+ 'role': "all"
+ }
+ ],
+ 'sds_ip_state': 'present-in-sds',
+ 'rmcache_enabled': True,
+ 'rmcache_size': 128,
+ 'state': "present"
+ })
+ pd_resp = MockSDKResponse(MockSDSApi.PROTECTION_DOMAIN)
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=pd_resp.__dict__['data']['protectiondomain'])
+ fs_resp = MockSDSApi.FAULT_SET_GET_LIST
+ powerflex_module_mock.powerflex_conn.fault_set.get = MagicMock(
+ return_value=fs_resp)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'create_sds_sds_new_name'), powerflex_module_mock, SDSHandler)
+
+ def test_modify_performance_profile_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "performance_profile": "Compact",
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.set_performance_parameters.assert_called()
+
+ def test_rename_sds_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "sds_new_name": "node0_new",
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ powerflex_module_mock.powerflex_conn.sds.rename = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'rename_sds_exception'), powerflex_module_mock, SDSHandler)
+
+ def test_rename_sds_empty_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "sds_new_name": "",
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'rename_sds_empty_exception'), powerflex_module_mock, SDSHandler)
+
+ def test_update_role_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "sds_ip_list":
+ [
+ {
+ "ip": self.ip2,
+ "role": "all"
+ }
+ ],
+ "sds_ip_state": "present-in-sds",
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.set_ip_role.assert_called()
+
+ def test_update_role_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "sds_ip_list":
+ [
+ {
+ "ip": self.ip2,
+ "role": "all"
+ }
+ ],
+ "sds_ip_state": "present-in-sds",
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ powerflex_module_mock.powerflex_conn.sds.set_ip_role = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'set_ip_role_exception'), powerflex_module_mock, SDSHandler)
+
+ def test_add_ip_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "sds_ip_list":
+ [
+ {
+ "ip": "10.xx.xx.xx",
+ "role": "all"
+ }
+ ],
+ "sds_ip_state": "present-in-sds",
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.add_ip.assert_called()
+
+ def test_add_ip_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "sds_ip_list":
+ [
+ {
+ "ip": "10.xx.xx.xx",
+ "role": "all"
+ }
+ ],
+ "sds_ip_state": "present-in-sds",
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ powerflex_module_mock.powerflex_conn.sds.add_ip = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'add_ip_exception'), powerflex_module_mock, SDSHandler)
+
+ def test_remove_ip_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "sds_ip_list":
+ [
+ {
+ "ip": self.ip2,
+ "role": "sdcOnly"
+ }
+ ],
+ "sds_ip_state": "absent-in-sds",
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.remove_ip.assert_called()
+
+ def test_remove_ip_idempotent(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "sds_ip_list":
+ [
+ {
+ "ip": "10.45.xxx.xxx",
+ "role": "sdcOnly"
+ }
+ ],
+ "sds_ip_state": "absent-in-sds",
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.get.assert_called()
+
+ def test_remove_ip_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "sds_ip_list":
+ [
+ {
+ "ip": self.ip2,
+ "role": "sdcOnly"
+ }
+ ],
+ "sds_ip_state": "absent-in-sds",
+ "state": "present"
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ powerflex_module_mock.powerflex_conn.sds.remove_ip = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'remove_ip_exception'), powerflex_module_mock, SDSHandler)
+
+ def test_delete_sds_response(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'state': 'absent'
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ SDSHandler().handle(
+ powerflex_module_mock, powerflex_module_mock.module.params)
+ powerflex_module_mock.powerflex_conn.sds.delete.assert_called()
+
+ def test_delete_fault_set_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ 'state': 'absent'
+ })
+ powerflex_module_mock.get_sds_details = MagicMock(
+ return_value=MockSDSApi.SDS_GET_LIST[0])
+ powerflex_module_mock.powerflex_conn.sds.delete = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(
+ MockSDSApi.get_sds_exception_response(
+ 'delete_sds_exception'), powerflex_module_mock, SDSHandler)
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_snapshot_policy.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_snapshot_policy.py
new file mode 100644
index 000000000..275b7b007
--- /dev/null
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_snapshot_policy.py
@@ -0,0 +1,502 @@
+# Copyright: (c) 2023, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""Unit Tests for snapshot policy module on PowerFlex"""
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+import pytest
+from mock.mock import MagicMock
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_snapshot_policy_api import MockSnapshotPolicyApi
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_api_exception \
+ import MockApiException
+from ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell \
+ import utils
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_fail_json \
+ import FailJsonException, fail_json
+
+utils.get_logger = MagicMock()
+utils.get_powerflex_gateway_host_connection = MagicMock()
+utils.PowerFlexClient = MagicMock()
+
+from ansible.module_utils import basic
+basic.AnsibleModule = MagicMock()
+from ansible_collections.dellemc.powerflex.plugins.modules.snapshot_policy import PowerFlexSnapshotPolicy, SnapshotPolicyHandler
+
+
+class TestPowerflexSnapshotPolicy():
+
+ get_module_args = MockSnapshotPolicyApi.SNAPSHOT_POLICY_COMMON_ARGS
+
+ @pytest.fixture
+ def snapshot_policy_module_mock(self, mocker):
+ snapshot_policy_module_mock = PowerFlexSnapshotPolicy()
+ snapshot_policy_module_mock.module.check_mode = False
+ snapshot_policy_module_mock.module.fail_json = fail_json
+ return snapshot_policy_module_mock
+
+ def capture_fail_json_call(self, error_msg, snapshot_policy_module_mock):
+ try:
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ except FailJsonException as fj_object:
+ assert error_msg == fj_object.message
+
+ def test_get_snapshot_policy_detail_using_name(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get.assert_called()
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics.assert_called()
+
+ def test_get_snapshot_policy_detail_using_id(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_id": "testing",
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get.assert_called()
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics.assert_called()
+
+ def test_get_snapshot_policy_details_with_exception(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockSnapshotPolicyApi.get_snapshot_policy_exception_response('get_snapshot_policy_details_exception'),
+ snapshot_policy_module_mock)
+
+ def test_create_snapshot_policy_using_name(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "access_mode": "ReadOnly",
+ "secure_snapshots": True,
+ "auto_snapshot_creation_cadence": {
+ "time": 1,
+ "unit": "Hour"},
+ "num_of_retained_snapshots_per_level": [20],
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=None
+ )
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.create.assert_called()
+
+ def test_create_snapshot_policy_exception(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "access_mode": "ReadOnly",
+ "secure_snapshots": True,
+ "auto_snapshot_creation_cadence": {
+ "time": 1,
+ "unit": "Hour"},
+ "num_of_retained_snapshots_per_level": [20],
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=None
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.create = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockSnapshotPolicyApi.get_snapshot_policy_exception_response('create_exception'),
+ snapshot_policy_module_mock)
+
+ def test_create_snapshot_policy_with_id_exception(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_id": "testing",
+ "access_mode": "ReadOnly",
+ "secure_snapshots": True,
+ "auto_snapshot_creation_cadence": {
+ "time": 1,
+ "unit": "Hour"},
+ "num_of_retained_snapshots_per_level": [20],
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=None
+ )
+ self.capture_fail_json_call(MockSnapshotPolicyApi.get_snapshot_policy_exception_response('create_id_exception'),
+ snapshot_policy_module_mock)
+
+ def test_delete_snapshot_policy(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "state": "absent"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.delete.assert_called()
+
+ def test_delete_snapshot_policy_exception(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "state": "absent"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.delete = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockSnapshotPolicyApi.get_snapshot_policy_exception_response('delete_exception'),
+ snapshot_policy_module_mock)
+
+ def test_modify_snapshot_policy(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "auto_snapshot_creation_cadence": {
+ "time": 20,
+ "unit": "Minute"},
+ "num_of_retained_snapshots_per_level": [30],
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.modify.assert_called()
+
+ def test_modify_snapshot_policy_wo_snapshot_rule(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "num_of_retained_snapshots_per_level": [30],
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.modify.assert_called()
+
+ def test_modify_snapshot_policy_wo_retention_rule(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "auto_snapshot_creation_cadence": {
+ "time": 20,
+ "unit": "Minute"},
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.modify.assert_called()
+
+ def test_modify_snapshot_policy_exception(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "auto_snapshot_creation_cadence": {
+ "time": 20,
+ "unit": "Minute"},
+ "num_of_retained_snapshots_per_level": [30],
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.modify = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockSnapshotPolicyApi.get_snapshot_policy_exception_response('modify_exception'),
+ snapshot_policy_module_mock)
+
+ def test_rename_snapshot_policy(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "new_name": "testing_new",
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.rename.assert_called()
+
+ def test_rename_snapshot_policy_exception(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "new_name": "testing_new",
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.rename = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockSnapshotPolicyApi.get_snapshot_policy_exception_response('modify_exception'),
+ snapshot_policy_module_mock)
+
+ def test_add_source_volume(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "source_volume": [{
+ "name": "source_volume_name",
+ "id": None,
+ "auto_snap_removal_action": None,
+ "detach_locked_auto_snapshots": None,
+ "state": "present"}],
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ snapshot_policy_module_mock.powerflex_conn.volume.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.VOLUME_GET_LIST
+ )
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.add_source_volume.assert_called()
+
+ def test_add_non_existing_volume_exception(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "source_volume": [{
+ "name": "non_existing_source_volume_name",
+ "id": None,
+ "auto_snap_removal_action": None,
+ "detach_locked_auto_snapshots": None}],
+ "source_volume_state": "present",
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ snapshot_policy_module_mock.powerflex_conn.volume.get = MagicMock(
+ return_value=[]
+ )
+ self.capture_fail_json_call(MockSnapshotPolicyApi.get_snapshot_policy_exception_response('add_non_existing_source_volume'),
+ snapshot_policy_module_mock)
+
+ def test_add_source_volume_wo_id_or_name_exception(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "source_volume": [{
+ "name": None,
+ "id": None,
+ "auto_snap_removal_action": None,
+ "detach_locked_auto_snapshots": None,
+ "state": "present"}],
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ self.capture_fail_json_call(MockSnapshotPolicyApi.get_snapshot_policy_exception_response('add_source_volume_wo_vol'),
+ snapshot_policy_module_mock)
+
+ def test_add_source_volume_wo_id_and_name_exception(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "source_volume": [{
+ "name": "source_volume_name",
+ "id": "source_volume_id",
+ "auto_snap_removal_action": None,
+ "detach_locked_auto_snapshots": None,
+ "state": "present"}],
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ self.capture_fail_json_call(MockSnapshotPolicyApi.get_snapshot_policy_exception_response('add_source_volume_vol_id_name'),
+ snapshot_policy_module_mock)
+
+ def test_add_source_volume_exception(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing",
+ "source_volume": [{
+ "name": "source_volume_name",
+ "id": None,
+ "auto_snap_removal_action": None,
+ "detach_locked_auto_snapshots": None,
+ "state": "present"}],
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ snapshot_policy_module_mock.powerflex_conn.volume.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.VOLUME_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.add_source_volume = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockSnapshotPolicyApi.get_snapshot_policy_exception_response('source_volume_exception'),
+ snapshot_policy_module_mock)
+
+ def test_remove_source_volume(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing_2",
+ "source_volume": [{
+ "id": "source_volume_id_2",
+ "name": None,
+ "auto_snap_removal_action": 'Remove',
+ "detach_locked_auto_snapshots": None,
+ "state": "absent"}],
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_2_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ snapshot_policy_module_mock.powerflex_conn.volume.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.VOLUME_2_GET_LIST
+ )
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.remove_source_volume.assert_called()
+
+ def test_pause_snapshot_policy(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing_2",
+ "pause": True,
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.pause.assert_called()
+
+ def test_resume_snapshot_policy(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing_2",
+ "pause": False,
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_2_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ SnapshotPolicyHandler().handle(snapshot_policy_module_mock, snapshot_policy_module_mock.module.params)
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.resume.assert_called()
+
+ def test_pause_snapshot_policy_exception(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing_2",
+ "pause": True,
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_2_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ snapshot_policy_module_mock.powerflex_conn.volume.pause = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockSnapshotPolicyApi.get_snapshot_policy_exception_response('pause_exception'),
+ snapshot_policy_module_mock)
+
+ def test_remove_source_volume_exception(self, snapshot_policy_module_mock):
+ self.get_module_args.update({
+ "snapshot_policy_name": "testing_2",
+ "source_volume": [{
+ "id": "source_volume_id_2",
+ "name": None,
+ "auto_snap_removal_action": 'Remove',
+ "detach_locked_auto_snapshots": None,
+ "state": "absent"}],
+ "state": "present"
+ })
+ snapshot_policy_module_mock.module.params = self.get_module_args
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_2_GET_LIST
+ )
+ snapshot_policy_module_mock.powerflex_conn.snapshot_policy.get_statistics = MagicMock(
+ return_value=MockSnapshotPolicyApi.SNAPSHOT_POLICY_STATISTICS
+ )
+ snapshot_policy_module_mock.powerflex_conn.volume.get = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(MockSnapshotPolicyApi.get_snapshot_policy_exception_response('get_vol_details_exception'),
+ snapshot_policy_module_mock)
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_storagepool.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_storagepool.py
index a2c463f66..6780ed7ad 100644
--- a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_storagepool.py
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_storagepool.py
@@ -1,4 +1,4 @@
-# Copyright: (c) 2022, Dell Technologies
+# Copyright: (c) 2024, Dell Technologies
# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -10,13 +10,15 @@ __metaclass__ = type
import pytest
from mock.mock import MagicMock
+# pylint: disable=unused-import
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.libraries import initial_mock
from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_storagepool_api import MockStoragePoolApi
-from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_sdk_response \
- import MockSDKResponse
from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_api_exception \
import MockApiException
from ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell \
import utils
+from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.libraries.powerflex_unit_base \
+ import PowerFlexUnitBase
utils.get_logger = MagicMock()
utils.get_powerflex_gateway_host_connection = MagicMock()
@@ -27,46 +29,355 @@ basic.AnsibleModule = MagicMock()
from ansible_collections.dellemc.powerflex.plugins.modules.storagepool import PowerFlexStoragePool
-class TestPowerflexStoragePool():
+class TestPowerflexStoragePool(PowerFlexUnitBase):
get_module_args = MockStoragePoolApi.STORAGE_POOL_COMMON_ARGS
@pytest.fixture
- def storagepool_module_mock(self, mocker):
- storagepool_module_mock = PowerFlexStoragePool()
- storagepool_module_mock.module.check_mode = False
- return storagepool_module_mock
+ def module_object(self):
+ return PowerFlexStoragePool
- def test_get_storagepool_details(self, storagepool_module_mock):
+ def test_get_storagepool_details(self, powerflex_module_mock):
self.get_module_args.update({
"storage_pool_name": "test_pool",
"state": "present"
})
- storagepool_module_mock.module.params = self.get_module_args
+ powerflex_module_mock.module.params = self.get_module_args
storagepool_resp = MockStoragePoolApi.STORAGE_POOL_GET_LIST
- storagepool_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
return_value=storagepool_resp
)
storagepool_statistics_resp = MockStoragePoolApi.STORAGE_POOL_STATISTICS
- storagepool_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
return_value=storagepool_statistics_resp
)
- storagepool_module_mock.perform_module_operation()
- storagepool_module_mock.powerflex_conn.storage_pool.get.assert_called()
- storagepool_module_mock.powerflex_conn.storage_pool.get_statistics.assert_called()
+ powerflex_module_mock.perform_module_operation()
+ powerflex_module_mock.powerflex_conn.storage_pool.get.assert_called()
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics.assert_called()
- def test_get_storagepool_details_with_exception(self, storagepool_module_mock):
+ def test_get_storagepool_details_multi(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_name": "test_pool",
+ "state": "present"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ storagepool_resp = MockStoragePoolApi.STORAGE_POOL_GET_MULTI_LIST
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=storagepool_resp
+ )
+ storagepool_statistics_resp = MockStoragePoolApi.STORAGE_POOL_STATISTICS
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ return_value=storagepool_statistics_resp
+ )
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('get_multi_details'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_get_storagepool_details_with_exception(self, powerflex_module_mock):
self.get_module_args.update({
"storage_pool_name": "test_pool"
})
- storagepool_module_mock.module.params = self.get_module_args
+ powerflex_module_mock.module.params = self.get_module_args
storagepool_resp = MockStoragePoolApi.STORAGE_POOL_GET_LIST
- storagepool_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
return_value=storagepool_resp
)
- storagepool_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
side_effect=MockApiException
)
- storagepool_module_mock.create_storage_pool = MagicMock(return_value=None)
- storagepool_module_mock.perform_module_operation()
- assert MockStoragePoolApi.get_exception_response('get_details') in storagepool_module_mock.module.fail_json.call_args[1]['msg']
+ powerflex_module_mock.create_storage_pool = MagicMock(return_value=None)
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('get_details'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ @pytest.mark.parametrize("params", [
+ {"pd_id": "4eeb304600000000"},
+ {"pd_name": "test"},
+ ])
+ def test_get_protection_domain(self, powerflex_module_mock, params):
+ pd_id = params.get("pd_id", None)
+ pd_name = params.get("pd_name", None)
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockStoragePoolApi.PROTECTION_DETAILS
+ )
+ pd_details = powerflex_module_mock.get_protection_domain(pd_name, pd_id)
+ assert MockStoragePoolApi.PROTECTION_DETAILS[0] == pd_details
+
+ def test_get_protection_domain_exception(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "storage_pool_name": "test_pool",
+ "protection_domain_id": "4eeb304600000001",
+ "state": "present"
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ side_effect=MockApiException)
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('get_pd_exception'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_get_protection_domain_non_exist(self, powerflex_module_mock):
+ self.set_module_params(
+ powerflex_module_mock,
+ self.get_module_args,
+ {
+ "storage_pool_name": "test_pool",
+ "protection_domain_id": "4eeb304600000001",
+ "state": "present"
+ })
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=None)
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('get_pd_non_exist'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_get_storagepool_details_with_invalid_pd_id(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_name": "test_pool",
+ "protection_domain_id": "4eeb304600000001"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ storagepool_resp = MockStoragePoolApi.STORAGE_POOL_GET_LIST
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=storagepool_resp
+ )
+ storagepool_statistics_resp = MockStoragePoolApi.STORAGE_POOL_STATISTICS
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ return_value=storagepool_statistics_resp
+ )
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockStoragePoolApi.PROTECTION_DETAILS_1
+ )
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('invalid_pd_id'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_create_storagepool_response(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_name": "test_pool",
+ "protection_domain_name": "test_pd_name",
+ "media_type": "HDD",
+ "state": "present"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockStoragePoolApi.PROTECTION_DETAILS_1)
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=[]
+ )
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ return_value=[]
+ )
+ powerflex_module_mock.powerflex_conn.storage_pool.create = MagicMock(
+ return_value=None
+ )
+ resp = powerflex_module_mock.create_storage_pool(pool_name="test_pool",
+ pd_id=MockStoragePoolApi.PROTECTION_DETAILS_1[0]['id'],
+ media_type="HDD")
+ assert resp is True
+ powerflex_module_mock.powerflex_conn.storage_pool.create.assert_called()
+
+ def test_create_storagepool_only_pool_id(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_id": "test_pool_id",
+ "protection_domain_name": "test_pd_name",
+ "media_type": "HDD",
+ "state": "present"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockStoragePoolApi.PROTECTION_DETAILS_1)
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=[]
+ )
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ return_value=[]
+ )
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('create_pool_id'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_create_storagepool_new_name(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_name": "test_pool",
+ "storage_pool_new_name": "pool_new_name",
+ "protection_domain_name": "test_pd_name",
+ "media_type": "HDD",
+ "state": "present"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockStoragePoolApi.PROTECTION_DETAILS_1)
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=[]
+ )
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ return_value=[]
+ )
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('create_pool_new_name'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_create_storagepool_empty_name(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_name": " ",
+ "protection_domain_name": "test_pd_name",
+ "media_type": "HDD",
+ "state": "present"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockStoragePoolApi.PROTECTION_DETAILS_1)
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('create_pool_name_empty'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_create_storagepool_wo_pd(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_name": "test_pool",
+ "media_type": "HDD",
+ "state": "present"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=None)
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=[]
+ )
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ return_value=[]
+ )
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('create_wo_pd'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_create_storagepool_transitional_exception(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_name": "test_pool",
+ "protection_domain_name": "test_pd_name",
+ "media_type": "TRANSITIONAL",
+ "state": "present"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockStoragePoolApi.PROTECTION_DETAILS_1)
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=[]
+ )
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ return_value=[]
+ )
+ powerflex_module_mock.powerflex_conn.storage_pool.create = MagicMock(
+ return_value=None
+ )
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('create_transitional'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_create_storagepool_exception(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_name": "test_pool",
+ "protection_domain_name": "test_pd_name",
+ "media_type": "HDD",
+ "state": "present"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ powerflex_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockStoragePoolApi.PROTECTION_DETAILS_1)
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=[]
+ )
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ return_value=[]
+ )
+ powerflex_module_mock.powerflex_conn.storage_pool.create = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('create_storage_pool'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_modify_storagepool_details(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_name": "test_pool",
+ "storage_pool_new_name": "new_ansible_pool",
+ "use_rfcache": True,
+ "use_rmcache": True,
+ "media_type": "TRANSITIONAL",
+ "state": "present"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ storagepool_resp = MockStoragePoolApi.STORAGE_POOL_GET_LIST
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=storagepool_resp
+ )
+ storagepool_statistics_resp = MockStoragePoolApi.STORAGE_POOL_STATISTICS
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ return_value=storagepool_statistics_resp
+ )
+ powerflex_module_mock.perform_module_operation()
+ powerflex_module_mock.powerflex_conn.storage_pool.rename.assert_called()
+ powerflex_module_mock.powerflex_conn.storage_pool.set_use_rmcache.assert_called()
+ powerflex_module_mock.powerflex_conn.storage_pool.set_use_rfcache.assert_called()
+ powerflex_module_mock.powerflex_conn.storage_pool.set_media_type.assert_called()
+
+ def test_rename_storagepool_exception(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_name": "test_pool",
+ "storage_pool_new_name": "new_ansible_pool",
+ "state": "present"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ storagepool_resp = MockStoragePoolApi.STORAGE_POOL_GET_LIST
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=storagepool_resp
+ )
+ storagepool_statistics_resp = MockStoragePoolApi.STORAGE_POOL_STATISTICS
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ return_value=storagepool_statistics_resp
+ )
+ powerflex_module_mock.powerflex_conn.storage_pool.rename = MagicMock(
+ side_effect=MockApiException
+ )
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('rename_storage_pool'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_rename_storagepool_empty_exception(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_name": "test_pool",
+ "storage_pool_new_name": " ",
+ "state": "present"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ storagepool_resp = MockStoragePoolApi.STORAGE_POOL_GET_LIST
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=storagepool_resp
+ )
+ storagepool_statistics_resp = MockStoragePoolApi.STORAGE_POOL_STATISTICS
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ return_value=storagepool_statistics_resp
+ )
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('rename_storage_pool_empty'),
+ powerflex_module_mock, invoke_perform_module=True)
+
+ def test_delete_storagepool_exception(self, powerflex_module_mock):
+ self.get_module_args.update({
+ "storage_pool_name": "test_pool",
+ "state": "absent"
+ })
+ powerflex_module_mock.module.params = self.get_module_args
+ storagepool_resp = MockStoragePoolApi.STORAGE_POOL_GET_LIST
+ powerflex_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ return_value=storagepool_resp
+ )
+ storagepool_statistics_resp = MockStoragePoolApi.STORAGE_POOL_STATISTICS
+ powerflex_module_mock.powerflex_conn.storage_pool.get_statistics = MagicMock(
+ return_value=storagepool_statistics_resp
+ )
+ self.capture_fail_json_call(
+ MockStoragePoolApi.get_exception_response('delete_storage_pool'),
+ powerflex_module_mock, invoke_perform_module=True)
diff --git a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_volume.py b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_volume.py
index 53cdcfc0d..e36c13695 100644
--- a/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_volume.py
+++ b/ansible_collections/dellemc/powerflex/tests/unit/plugins/modules/test_volume.py
@@ -1,4 +1,4 @@
-# Copyright: (c) 2022, Dell Technologies
+# Copyright: (c) 2024, Dell Technologies
# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -11,8 +11,6 @@ __metaclass__ = type
import pytest
from mock.mock import MagicMock
from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_volume_api import MockVolumeApi
-from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_sdk_response \
- import MockSDKResponse
from ansible_collections.dellemc.powerflex.tests.unit.plugins.module_utils.mock_api_exception \
import MockApiException
from ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell \
@@ -78,4 +76,662 @@ class TestPowerflexVolume():
)
volume_module_mock.create_volume = MagicMock(return_value=None)
volume_module_mock.perform_module_operation()
- assert MockVolumeApi.get_exception_response('get_details') in volume_module_mock.module.fail_json.call_args[1]['msg']
+ assert MockVolumeApi.get_exception_response(
+ 'get_details') in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ @pytest.mark.parametrize("params", [
+ {"pd_id": "123"},
+ {"pd_name": "test"},
+ ])
+ def test_get_protection_domain(self, volume_module_mock, params):
+ pd_id = params.get("pd_id", None)
+ pd_name = params.get("pd_name", None)
+ volume_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=MockVolumeApi.PROTECTION_DETAILS
+ )
+ pd_details = volume_module_mock.get_protection_domain(pd_name, pd_id)
+ assert MockVolumeApi.PROTECTION_DETAILS[0] == pd_details
+
+ def test_get_protection_domain_exeception(self, volume_module_mock):
+ pd_id = "pd_id"
+ pd_name = "pd_name"
+ volume_module_mock.powerflex_conn.protection_domain.get = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.get_protection_domain(pd_name, pd_id)
+ assert MockVolumeApi.get_exception_response(
+ 'get_pd_exception') in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ @pytest.mark.parametrize("params", [
+ {"pol_id": "123"},
+ {"pol_name": "test"},
+ ])
+ def test_get_snapshot_policy(self, volume_module_mock, params):
+ pol_id = params.get("pol_id", None)
+ pol_name = params.get("pol_name", None)
+ volume_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=MockVolumeApi.PROTECTION_DETAILS
+ )
+ snap_pol_details = volume_module_mock.get_snapshot_policy(
+ pol_id, pol_name)
+ assert MockVolumeApi.PROTECTION_DETAILS[0] == snap_pol_details
+
+ def test_get_snapshot_policy_exception(self, volume_module_mock):
+ pol_id = "pol_id"
+ pol_name = "pol_name"
+ volume_module_mock.powerflex_conn.snapshot_policy.get = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.get_snapshot_policy(pol_id, pol_name)
+ assert MockVolumeApi.get_exception_response(
+ 'get_sp_exception') in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ @pytest.mark.parametrize("params", [
+ {"pol_id": "123", "prot_id": "123"},
+ ])
+ def test_get_storage_pool(self, volume_module_mock, params):
+ pol_id = params.get("pol_id", None)
+ pol_name = params.get("pol_name", None)
+ prot_id = params.get("prot_id", None)
+
+ def mock_get(filter_fields):
+ if filter_fields.get("protectionDomainId", None):
+ return MockVolumeApi.PROTECTION_DETAILS
+ else:
+ return MockVolumeApi.PROTECTION_DETAILS_MULTI
+
+ volume_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ side_effect=mock_get
+ )
+ sp_details = volume_module_mock.get_storage_pool(
+ pol_id, pol_name, prot_id)
+ assert MockVolumeApi.PROTECTION_DETAILS[0] == sp_details
+
+ @pytest.mark.parametrize("params", [
+ {"pol_id": "123", "assert_msg": "get_spool_error1"},
+ {"pol_name": "123", "prot_id": "123", "assert_msg": "get_spool_error2"},
+ ])
+ def test_get_storage_pool_error(self, volume_module_mock, params):
+ pol_id = params.get("pol_id", None)
+ pol_name = params.get("pol_name", None)
+ prot_id = params.get("prot_id", None)
+
+ def mock_get(filter_fields):
+ if filter_fields.get("protectionDomainId", None):
+ return None
+ else:
+ return MockVolumeApi.PROTECTION_DETAILS_MULTI
+
+ volume_module_mock.powerflex_conn.storage_pool.get = MagicMock(
+ side_effect=mock_get
+ )
+ volume_module_mock.get_storage_pool(pol_id, pol_name, prot_id)
+ assert MockVolumeApi.get_exception_response(params.get(
+ "assert_msg")) in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ @pytest.mark.parametrize("params", [
+ {"vol_name": "123", "assert_msg": "get_spool_error1"}
+ ])
+ def test_get_volume(self, volume_module_mock, params):
+ vol_name = params.get("vol_name", None)
+ vol_id = params.get("vol_id", None)
+ volume_module_mock.powerflex_conn.volume.get = MagicMock(
+ return_value=MockVolumeApi.VOLUME_GET_LIST
+ )
+ volume_module_mock.get_snapshot_policy = MagicMock(
+ return_value={"name": "snapshotPolicyName"}
+ )
+ volume_details = volume_module_mock.get_volume(vol_name, vol_id)
+ assert volume_details["snapshotPolicyId"] == MockVolumeApi.VOLUME_GET_LIST[0]["snapshotPolicyId"]
+ assert volume_details["snapshotPolicyName"] == MockVolumeApi.VOLUME_GET_LIST[0]["snapshotPolicyName"]
+
+ def test_get_volume_exeception(self, volume_module_mock):
+ volume_module_mock.powerflex_conn.volume.get = MagicMock(
+ side_effect=MockApiException
+ )
+ volume_module_mock.get_snapshot_policy = MagicMock(
+ return_value={"name": "snapshotPolicyName"}
+ )
+ volume_module_mock.get_volume("test_id_1", "test_id_1")
+ assert MockVolumeApi.get_exception_response(
+ "get_details") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ @pytest.mark.parametrize("params", [
+ {"sdc_id": "sdc_id"},
+ {"sdc_ip": "sdc_ip"},
+ ])
+ def test_get_sdc_id(self, volume_module_mock, params):
+ sdc_name = params.get("sdc_name", None)
+ sdc_ip = params.get("sdc_ip", None)
+ sdc_id = params.get("sdc_id", None)
+ volume_module_mock.powerflex_conn.sdc.get = MagicMock(
+ return_value=MockVolumeApi.SDC_RESPONSE
+ )
+ sdc_details = volume_module_mock.get_sdc_id(sdc_name, sdc_ip, sdc_id)
+ assert MockVolumeApi.SDC_RESPONSE[0]['id'] == sdc_details
+
+ def test_get_sdc_id_error(self, volume_module_mock):
+ sdc_name = "sdc_name"
+ sdc_ip = "sdc_ip"
+ sdc_id = "sdc_id"
+ volume_module_mock.powerflex_conn.sdc.get = MagicMock(
+ return_value=[]
+ )
+ volume_module_mock.get_sdc_id(sdc_name, sdc_ip, sdc_id)
+ assert MockVolumeApi.get_exception_response(
+ "get_sds") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_create_volume_error_vol_name(self, volume_module_mock):
+ volume_module_mock.create_volume("", "pool_id", 1024)
+ assert MockVolumeApi.get_exception_response(
+ "create_vol_name") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_create_volume_error_comp_type(self, volume_module_mock):
+ volume_module_mock.get_storage_pool = MagicMock(
+ return_value=MockVolumeApi.GET_STORAGE_POOL
+ )
+ volume_module_mock.create_volume(
+ "vol_name", "pool_id", 1024, comp_type="comp_type")
+ assert MockVolumeApi.get_exception_response(
+ "create_vol_ctype") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_create_volume_error_size(self, volume_module_mock):
+ volume_module_mock.get_storage_pool = MagicMock(
+ return_value=MockVolumeApi.GET_STORAGE_POOL
+ )
+ volume_module_mock.create_volume("vol_name", "pool_id", None)
+ assert MockVolumeApi.get_exception_response(
+ "create_vol_size") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_create_volume_exception(self, volume_module_mock):
+ volume_module_mock.powerflex_conn.volume.create = MagicMock(
+ side_effect=MockApiException
+ )
+ volume_module_mock.create_volume("vol_name", None, 1024)
+ assert MockVolumeApi.get_exception_response(
+ "create_vol_exc") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_create_volume(self, volume_module_mock):
+ volume_module_mock.powerflex_conn.volume.create = MagicMock(
+ return_value=None
+ )
+ ret = volume_module_mock.create_volume("vol_name", None, 1024)
+ assert ret is True
+
+ def test_modify_access_mode_true(self, volume_module_mock):
+ access_mode_list = [{"accessMode": "READ_ONLY", "sdc_id": "sdc_id"}]
+ volume_module_mock.powerflex_conn.volume.set_access_mode_for_sdc = MagicMock(
+ return_value=None
+ )
+ ret = volume_module_mock.modify_access_mode(
+ "vol_name", access_mode_list)
+ assert ret is True
+
+ def test_modify_access_mode_false(self, volume_module_mock):
+ access_mode_list = [{"accessMode": None, "sdc_id": "sdc_id"}]
+ volume_module_mock.powerflex_conn.volume.set_access_mode_for_sdc = MagicMock(
+ return_value=None
+ )
+ ret = volume_module_mock.modify_access_mode(
+ "vol_name", access_mode_list)
+ assert ret is False
+
+ def test_modify_access_mode_exception(self, volume_module_mock):
+ access_mode_list = [{"accessMode": "READ_ONLY", "sdc_id": "sdc_id"}]
+ volume_module_mock.powerflex_conn.volume.set_access_mode_for_sdc = MagicMock(
+ side_effect=MockApiException
+ )
+ volume_module_mock.modify_access_mode("vol_name", access_mode_list)
+ assert MockVolumeApi.get_exception_response(
+ "modify_access") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_modify_limits_true(self, volume_module_mock):
+ payload = {"sdc_id": "sdc_id",
+ "bandwidth_limit": 1024, "iops_limit": 1024}
+ volume_module_mock.powerflex_conn.volume.set_mapped_sdc_limits = MagicMock(
+ return_value=None
+ )
+ ret = volume_module_mock.modify_limits(payload)
+ assert ret is True
+
+ def test_modify_limits_false(self, volume_module_mock):
+ payload = {"sdc_id": "sdc_id",
+ "bandwidth_limit": None, "iops_limit": None}
+ volume_module_mock.powerflex_conn.volume.set_mapped_sdc_limits = MagicMock(
+ return_value=None
+ )
+ ret = volume_module_mock.modify_limits(payload)
+ assert ret is False
+
+ def test_modify_limits_exception(self, volume_module_mock):
+ payload = {"sdc_id": "sdc_id",
+ "bandwidth_limit": 1024, "iops_limit": 1024}
+ volume_module_mock.powerflex_conn.volume.set_mapped_sdc_limits = MagicMock(
+ side_effect=MockApiException
+ )
+ volume_module_mock.modify_limits(payload)
+ assert MockVolumeApi.get_exception_response(
+ "modify_limits") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_delete_volume_true(self, volume_module_mock):
+ volume_module_mock.powerflex_conn.volume.delete = MagicMock(
+ side_effect=None
+ )
+ ret = volume_module_mock.delete_volume("vol_id", "remove_mode")
+ assert ret is True
+
+ def test_delete_volume_exception(self, volume_module_mock):
+ volume_module_mock.powerflex_conn.volume.delete = MagicMock(
+ side_effect=MockApiException
+ )
+ volume_module_mock.delete_volume("vol_id", "remove_mode")
+ assert MockVolumeApi.get_exception_response(
+ "delete_volume") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_unmap_volume_from_sdc_true(self, volume_module_mock):
+ volume = {"mappedSdcInfo": [{"sdcId": "sdc_id"}], "id": "vol_id"}
+ sdc = [{"sdc_name": "sdc_name"}]
+ volume_module_mock.get_sdc_id = MagicMock(
+ return_value="sdc_id"
+ )
+ volume_module_mock.powerflex_conn.volume.remove_mapped_sdc = MagicMock(
+ return_value=None
+ )
+ ret = volume_module_mock.unmap_volume_from_sdc(volume, sdc)
+ assert ret is True
+
+ def test_unmap_volume_from_sdc_false(self, volume_module_mock):
+ volume = {"mappedSdcInfo": [{"sdcId": "sdc_id"}], "id": "vol_id"}
+ sdc = [{"sdc_ip": "sdc_ip"}]
+ volume_module_mock.get_sdc_id = MagicMock(
+ return_value="sdc_id1"
+ )
+ volume_module_mock.powerflex_conn.volume.remove_mapped_sdc = MagicMock(
+ return_value=None
+ )
+ ret = volume_module_mock.unmap_volume_from_sdc(volume, sdc)
+ assert ret is False
+
+ def test_unmap_volume_from_sdc_exception(self, volume_module_mock):
+ volume = {"mappedSdcInfo": [{"sdcId": "sdc_id"}], "id": "vol_id"}
+ sdc = [{"sdc_id": "sdc_id"}]
+ volume_module_mock.get_sdc_id = MagicMock(
+ return_value="sdc_id"
+ )
+ volume_module_mock.powerflex_conn.volume.remove_mapped_sdc = MagicMock(
+ side_effect=MockApiException
+ )
+ volume_module_mock.unmap_volume_from_sdc(volume, sdc)
+ assert MockVolumeApi.get_exception_response(
+ "unmap") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_map_volume_to_sdc_name(self, volume_module_mock):
+ volume = {
+ "mappedSdcInfo": [
+ {"sdcId": "sdc_id", "accessMode": "READ_WRITE",
+ "limitIops": 1024, "limitBwInMbps": 1024}],
+ "id": "vol_id",
+ }
+ sdc = [{"sdc_name": "sdc_name", "access_mode": "READ_ONLY",
+ "iops_limit": 2048, "bandwidth_limit": 2048}]
+ volume_module_mock.get_sdc_id = MagicMock(
+ return_value="sdc_id"
+ )
+ ret, sdc_modify_list1, sdc_modify_list2 = volume_module_mock.map_volume_to_sdc(
+ volume, sdc)
+ assert ret is False
+ assert sdc_modify_list1[0]["sdc_id"] == "sdc_id"
+ assert sdc_modify_list2[0]["sdc_id"] == "sdc_id"
+
+ def test_map_volume_to_sdc_ip(self, volume_module_mock):
+ volume = {
+ "mappedSdcInfo": [
+ {"sdcId": "sdc_id", "accessMode": "READ_WRITE",
+ "limitIops": 1024, "limitBwInMbps": 1024}],
+ "id": "vol_id",
+ }
+ sdc = [{"sdc_ip": "sdc_ip", "access_mode": "READ_ONLY",
+ "iops_limit": 2048, "bandwidth_limit": 2048}]
+ volume_module_mock.get_sdc_id = MagicMock(
+ return_value="sdc_id1"
+ )
+ volume_module_mock.powerflex_conn.volume.add_mapped_sdc = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.powerflex_conn.volume.set_mapped_sdc_limits = MagicMock(
+ return_value=None
+ )
+ ret, sdc_modify_list1, sdc_modify_list2 = volume_module_mock.map_volume_to_sdc(
+ volume, sdc)
+ assert ret is True
+ assert sdc_modify_list1 == []
+ assert sdc_modify_list2 == []
+
+ def test_map_volume_to_sdc_id(self, volume_module_mock):
+ volume = {
+ "mappedSdcInfo": [
+ {"sdcId": "sdc_id", "accessMode": "READ_WRITE",
+ "limitIops": 1024, "limitBwInMbps": 1024}],
+ "id": "vol_id",
+ }
+ sdc = [{"sdc_id": "sdc_id", "access_mode": "READ_ONLY"}]
+ volume_module_mock.get_sdc_id = MagicMock(
+ return_value="sdc_id1"
+ )
+ volume_module_mock.powerflex_conn.volume.add_mapped_sdc = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.powerflex_conn.volume.set_mapped_sdc_limits = MagicMock(
+ return_value=None
+ )
+ ret, sdc_modify_list1, sdc_modify_list2 = volume_module_mock.map_volume_to_sdc(
+ volume, sdc)
+ assert ret is True
+ assert sdc_modify_list1 == []
+ assert sdc_modify_list2 == []
+
+ def test_map_volume_to_sdc_exception(self, volume_module_mock):
+ volume = {
+ "mappedSdcInfo": [
+ {"sdcId": "sdc_id", "accessMode": "READ_WRITE",
+ "limitIops": 1024, "limitBwInMbps": 1024}],
+ "id": "vol_id",
+ "name": "name"
+ }
+ sdc = [{"sdc_id": "sdc_id", "access_mode": "READ_ONLY",
+ "iops_limit": 2048, "bandwidth_limit": 2048}]
+ volume_module_mock.get_sdc_id = MagicMock(
+ return_value="sdc_id1"
+ )
+ volume_module_mock.powerflex_conn.volume.add_mapped_sdc = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.powerflex_conn.volume.set_mapped_sdc_limits = MagicMock(
+ side_effect=MockApiException
+ )
+ volume_module_mock.map_volume_to_sdc(volume, sdc)
+ assert MockVolumeApi.get_exception_response(
+ "map_vol_exception") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ @pytest.mark.parametrize('params', [
+ {"sdc": [{"sdc_id": "sdc_id", "sdc_name": "sdc_name", "sdc_ip": "sdc_ip"}],
+ "assert_msg": "val_params_err1"},
+ {"cap_unit": "GB", "size": None, "assert_msg": "val_params_err2"},
+ {"asrt": "asrt", "assert_msg": "val_params_err3"},
+ {"state": "present", "del_snaps": "del_snaps",
+ "assert_msg": "val_params_err4"},
+ ])
+ def test_validate_parameters(self, volume_module_mock, params):
+ self.get_module_args.update({
+ "sdc": params.get("sdc", None),
+ "cap_unit": params.get("cap_unit", None),
+ "size": params.get("size", None),
+ })
+ volume_module_mock.module.params = self.get_module_args
+ asrt = params.get("asrt", None)
+ pol_id = params.get("pol_id", None)
+ pol_name = params.get("pol_name", None)
+ del_snaps = params.get("del_snaps", None)
+ state = params.get("state", None)
+ assert_msg = params.get("assert_msg", None)
+ volume_module_mock.validate_parameters(
+ asrt, pol_id, pol_name, del_snaps, state)
+ assert MockVolumeApi.get_exception_response(
+ assert_msg) in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ @pytest.mark.parametrize('params', [
+ {"modify_dict": {
+ "auto_snap_remove_type": "remove",
+ "snap_pol_id": "vol_id",
+ "new_name": "new_name",
+ "new_size": "new_size",
+ "use_rmcache": "use_rmcache",
+ "comp_type": "comp_type"
+ }, "vol_id": "vol_id"},
+ {"modify_dict": {
+ "snap_pol_id": "vol_id"
+ }, "vol_id": "vol_id"},
+ ])
+ def test_modify_volume(self, volume_module_mock, params):
+ vol_id = params.get("vol_id", None)
+ modify_dict = params.get("modify_dict", None)
+ volume_module_mock.get_sdc_id = MagicMock(
+ return_value="sdc_id1"
+ )
+ volume_module_mock.powerflex_conn.snapshot_policy.remove_source_volume = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.powerflex_conn.snapshot_policy.add_source_volume = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.powerflex_conn.snapshot_policy.rename = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.powerflex_conn.snapshot_policy.extend = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.powerflex_conn.snapshot_policy.set_use_rmcache = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.powerflex_conn.snapshot_policy.set_compression_method = MagicMock(
+ return_value=None
+ )
+ ret = volume_module_mock.modify_volume(vol_id, modify_dict)
+ assert ret is True
+
+ def test_modify_volume_execption(self, volume_module_mock):
+ vol_id = "vol_id"
+ modify_dict = {"snap_pol_id": "vol_id"}
+ volume_module_mock.powerflex_conn.snapshot_policy.add_source_volume = MagicMock(
+ side_effect=MockApiException
+ )
+ volume_module_mock.modify_volume(vol_id, modify_dict)
+ assert MockVolumeApi.get_exception_response(
+ "modify_volume_exp") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_to_modify(self, volume_module_mock):
+ vol_details = {
+ "storagePoolId": "sdc_id",
+ "compressionMethod": "tar",
+ "useRmcache": True,
+ "sizeInKb": 2048,
+ "name": "name",
+ "snplIdOfSourceVolume": "snplIdOfSourceVolume"
+ }
+ new_size = 1024
+ use_rmcache = False
+ comp_type = "zip"
+ new_name = "new_name"
+ snap_pol_id = ""
+ asrt = "asrt"
+ volume_module_mock.get_storage_pool = MagicMock(
+ return_value=MockVolumeApi.GET_STORAGE_POOL_FINE
+ )
+ modify_dict = volume_module_mock.to_modify(vol_details, new_size, use_rmcache, comp_type,
+ new_name, snap_pol_id,
+ asrt)
+ assert modify_dict["snap_pol_id"] == "snplIdOfSourceVolume"
+
+ def test_to_modify_comp_type_error(self, volume_module_mock):
+ vol_details = {
+ "storagePoolId": "sdc_id",
+ "compressionMethod": "tar",
+ "useRmcache": True,
+ "sizeInKb": 2048,
+ "name": "name",
+ "snplIdOfSourceVolume": None
+ }
+ new_size = 1024
+ use_rmcache = False
+ comp_type = "zip"
+ new_name = "new_name"
+ snap_pol_id = "snap_pol_id"
+ asrt = None
+ volume_module_mock.get_storage_pool = MagicMock(
+ return_value=MockVolumeApi.GET_STORAGE_POOL
+ )
+ volume_module_mock.to_modify(vol_details, new_size, use_rmcache, comp_type,
+ new_name, snap_pol_id,
+ asrt)
+ assert MockVolumeApi.get_exception_response(
+ "create_vol_ctype") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_to_modify_new_name_error(self, volume_module_mock):
+ vol_details = {
+ "storagePoolId": "sdc_id",
+ "compressionMethod": "tar",
+ "useRmcache": True,
+ "sizeInKb": 2048,
+ "name": "name",
+ "snplIdOfSourceVolume": "snplIdOfSourceVolume"
+ }
+ new_size = None
+ use_rmcache = None
+ comp_type = None
+ new_name = ""
+ snap_pol_id = "snap_pol_id"
+ asrt = None
+ volume_module_mock.get_storage_pool = MagicMock(
+ return_value=MockVolumeApi.GET_STORAGE_POOL_FINE
+ )
+ volume_module_mock.to_modify(vol_details, new_size, use_rmcache, comp_type,
+ new_name, snap_pol_id,
+ asrt)
+ assert MockVolumeApi.get_exception_response(
+ "create_vol_name") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_to_modify_remove_error(self, volume_module_mock):
+ vol_details = {
+ "storagePoolId": "sdc_id",
+ "compressionMethod": "tar",
+ "useRmcache": True,
+ "sizeInKb": 2048,
+ "name": "name",
+ "snplIdOfSourceVolume": "snplIdOfSourceVolume"
+ }
+ new_size = None
+ use_rmcache = None
+ comp_type = None
+ new_name = None
+ snap_pol_id = "snap_pol_id"
+ asrt = "asrt"
+ volume_module_mock.get_storage_pool = MagicMock(
+ return_value=MockVolumeApi.GET_STORAGE_POOL_FINE
+ )
+ volume_module_mock.to_modify(vol_details, new_size, use_rmcache, comp_type,
+ new_name, snap_pol_id,
+ asrt)
+ assert MockVolumeApi.get_exception_response(
+ "to_modify_err1") in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ @pytest.mark.parametrize('params', [
+ {"snap_pol_id": "snap_pol_id", "assert_msg": "snap_pol_id_err"},
+ {"snap_pol_name": "snap_pol_id", "assert_msg": "snap_pol_name_err"},
+ {"pd_id": "pd_id", "assert_msg": "pd_id_err"},
+ {"pool_id": "pool_id", "assert_msg": "pool_id_err"},
+ {"pd_name": "pd_name", "assert_msg": "pd_name_err"},
+ {"pool_name": "pool_name", "assert_msg": "pool_name_err"}
+ ])
+ def test_verify_params(self, volume_module_mock, params):
+ vol_details = {
+ "snapshotPolicyId": "snapshotPolicyId",
+ "snapshotPolicyName": "snapshotPolicyName",
+ "protectionDomainId": "protectionDomainId",
+ "storagePoolId": "storagePoolId",
+ "protectionDomainName": "protectionDomainName",
+ "storagePoolName": "storagePoolName",
+ }
+ snap_pol_name = params.get("snap_pol_name", None)
+ snap_pol_id = params.get("snap_pol_id", None)
+ pd_name = params.get("pd_name", None)
+ pd_id = params.get("pd_id", None)
+ pool_name = params.get("pool_name", None)
+ pool_id = params.get("pool_id", None)
+ assert_msg = params.get("assert_msg", None)
+ volume_module_mock.verify_params(vol_details, snap_pol_name, snap_pol_id, pd_name,
+ pd_id, pool_name, pool_id)
+ assert MockVolumeApi.get_exception_response(
+ assert_msg) in volume_module_mock.module.fail_json.call_args[1]['msg']
+
+ def test_perform_module_operation_delete(self, volume_module_mock):
+ self.get_module_args.update({
+ "compression_type": "tar",
+ "vol_type": "vol_type",
+ "auto_snap_remove_type": "asrt",
+ "size": 20,
+ "protection_domain_name": "protection_domain_name",
+ "storage_pool_name": "storage_pool_name",
+ "snapshot_policy_name": "snapshot_policy_name",
+ "vol_name": "vol_name",
+ "state": "absent",
+ "delete_snapshots": True
+ })
+ volume_module_mock.module.params = self.get_module_args
+ volume_module_mock.validate_parameters = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.get_protection_domain = MagicMock(
+ return_value=MockVolumeApi.GET_ID
+ )
+ volume_module_mock.get_storage_pool = MagicMock(
+ return_value=MockVolumeApi.GET_ID
+ )
+ volume_module_mock.get_snapshot_policy = MagicMock(
+ return_value=MockVolumeApi.GET_ID
+ )
+ volume_module_mock.get_volume = MagicMock(
+ return_value=MockVolumeApi.GET_ID
+ )
+ volume_module_mock.delete_volume = MagicMock(
+ return_value=True
+ )
+ volume_module_mock.verify_params = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.perform_module_operation()
+ assert volume_module_mock.module.exit_json.call_args[1]['changed'] is True
+ assert volume_module_mock.module.exit_json.call_args[1]['volume_details'] == {
+ }
+
+ def test_perform_module_operation_create_fail(self, volume_module_mock):
+ self.get_module_args.update({
+ "compression_type": "tar",
+ "vol_type": "vol_type",
+ "auto_snap_remove_type": "asrt",
+ "size": 1,
+ "protection_domain_name": "protection_domain_name",
+ "storage_pool_name": "storage_pool_name",
+ "snapshot_policy_name": "",
+ "snapshot_policy_id": "",
+ "vol_name": "vol_name",
+ "state": "present",
+ "delete_snapshots": True,
+ "cap_unit": "TB",
+ "vol_id": "vol_id",
+ "vol_new_name": "vol_new_name",
+ })
+ volume_module_mock.module.params = self.get_module_args
+ volume_module_mock.validate_parameters = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.get_protection_domain = MagicMock(
+ return_value=MockVolumeApi.GET_ID
+ )
+ volume_module_mock.get_storage_pool = MagicMock(
+ return_value=MockVolumeApi.GET_ID
+ )
+ volume_module_mock.get_snapshot_policy = MagicMock(
+ return_value=MockVolumeApi.GET_ID
+ )
+ volume_module_mock.get_volume = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.verify_params = MagicMock(
+ return_value=None
+ )
+ volume_module_mock.create_volume = MagicMock(
+ return_value=False
+ )
+ volume_module_mock.perform_module_operation()
+ assert MockVolumeApi.get_exception_response(
+ "perform_error1") in volume_module_mock.module.fail_json.call_args[1]['msg']
diff --git a/ansible_collections/dellemc/powerflex/tests/requirements.txt b/ansible_collections/dellemc/powerflex/tests/unit/requirements.txt
index 3541acd15..3541acd15 100644
--- a/ansible_collections/dellemc/powerflex/tests/requirements.txt
+++ b/ansible_collections/dellemc/powerflex/tests/unit/requirements.txt