Volume dev upstream new options (#59660)
* Add controller ownership and cache without batteries option * Add unit test for new netapp_e_volume options * Add integration tests for netapp_e_volume module. * Changed default read_ahead_enable option to true in netapp_e_volume module. * Fix off-segment aligned volume size in netapp_e_volume module.
This commit is contained in:
parent
61a2dab2ff
commit
37dd373c6b
2 changed files with 61 additions and 26 deletions
lib/ansible/modules/storage/netapp
test/units/modules/storage/netapp
|
@ -106,6 +106,13 @@ options:
|
|||
- Values must be between or equal to 10 and 99.
|
||||
default: 95
|
||||
version_added: 2.8
|
||||
owning_controller:
|
||||
description:
|
||||
- Specifies which controller will be the primary owner of the volume
|
||||
- Not specifying will allow the controller to choose ownership.
|
||||
required: false
|
||||
choices: ["A", "B"]
|
||||
version_added: 2.9
|
||||
ssd_cache_enabled:
|
||||
description:
|
||||
- Whether an existing SSD cache should be enabled on the volume (fails if no SSD cache defined)
|
||||
|
@ -138,6 +145,13 @@ options:
|
|||
type: bool
|
||||
default: true
|
||||
version_added: 2.8
|
||||
cache_without_batteries:
|
||||
description:
|
||||
- Indicates whether caching should be used without battery backup.
|
||||
- Warning, M(cache_without_batteries==true) and the storage system looses power and there is no battery backup, data will be lost!
|
||||
type: bool
|
||||
default: false
|
||||
version_added: 2.9
|
||||
workload_name:
|
||||
description:
|
||||
- Label for the workload defined by the metadata.
|
||||
|
@ -268,6 +282,7 @@ class NetAppESeriesVolume(NetAppESeriesModule):
|
|||
type="str"),
|
||||
size=dict(type="float"),
|
||||
segment_size_kb=dict(type="int", default=128),
|
||||
owning_controller=dict(required=False, choices=['A', 'B']),
|
||||
ssd_cache_enabled=dict(type="bool", default=False),
|
||||
data_assurance_enabled=dict(type="bool", default=False),
|
||||
thin_provision=dict(type="bool", default=False),
|
||||
|
@ -278,6 +293,7 @@ class NetAppESeriesVolume(NetAppESeriesModule):
|
|||
read_cache_enable=dict(type="bool", default=True),
|
||||
read_ahead_enable=dict(type="bool", default=True),
|
||||
write_cache_enable=dict(type="bool", default=True),
|
||||
cache_without_batteries=dict(type="bool", default=False),
|
||||
workload_name=dict(type="str", required=False),
|
||||
metadata=dict(type="dict", require=False),
|
||||
wait_for_initialization=dict(type="bool", default=False),
|
||||
|
@ -300,12 +316,17 @@ class NetAppESeriesVolume(NetAppESeriesModule):
|
|||
self.size_unit = args["size_unit"]
|
||||
self.segment_size_kb = args["segment_size_kb"]
|
||||
if args["size"]:
|
||||
self.size_b = int(args["size"] * self.SIZE_UNIT_MAP[self.size_unit])
|
||||
self.size_b = self.convert_to_aligned_bytes(args["size"])
|
||||
|
||||
self.owning_controller_id = None
|
||||
if args["owning_controller"]:
|
||||
self.owning_controller_id = "070000000000000000000001" if args["owning_controller"] == "A" else "070000000000000000000002"
|
||||
|
||||
self.read_cache_enable = args["read_cache_enable"]
|
||||
self.read_ahead_enable = args["read_ahead_enable"]
|
||||
self.write_cache_enable = args["write_cache_enable"]
|
||||
self.ssd_cache_enabled = args["ssd_cache_enabled"]
|
||||
self.cache_without_batteries = args["cache_without_batteries"]
|
||||
self.data_assurance_enabled = args["data_assurance_enabled"]
|
||||
|
||||
self.thin_provision = args["thin_provision"]
|
||||
|
@ -315,10 +336,9 @@ class NetAppESeriesVolume(NetAppESeriesModule):
|
|||
self.thin_volume_max_repo_size_b = None
|
||||
|
||||
if args["thin_volume_repo_size"]:
|
||||
self.thin_volume_repo_size_b = args["thin_volume_repo_size"] * self.SIZE_UNIT_MAP[self.size_unit]
|
||||
self.thin_volume_repo_size_b = self.convert_to_aligned_bytes(args["thin_volume_repo_size"])
|
||||
if args["thin_volume_max_repo_size"]:
|
||||
self.thin_volume_max_repo_size_b = int(args["thin_volume_max_repo_size"] *
|
||||
self.SIZE_UNIT_MAP[self.size_unit])
|
||||
self.thin_volume_max_repo_size_b = self.convert_to_aligned_bytes(args["thin_volume_max_repo_size"])
|
||||
|
||||
self.workload_name = args["workload_name"]
|
||||
self.metadata = args["metadata"]
|
||||
|
@ -361,6 +381,13 @@ class NetAppESeriesVolume(NetAppESeriesModule):
|
|||
self.pool_detail = None
|
||||
self.workload_id = None
|
||||
|
||||
def convert_to_aligned_bytes(self, size):
|
||||
"""Convert size to the truncated byte size that aligns on the segment size."""
|
||||
size_bytes = int(size * self.SIZE_UNIT_MAP[self.size_unit])
|
||||
segment_size_bytes = int(self.segment_size_kb * self.SIZE_UNIT_MAP["kb"])
|
||||
segment_count = int(size_bytes / segment_size_bytes)
|
||||
return segment_count * segment_size_bytes
|
||||
|
||||
def get_volume(self):
|
||||
"""Retrieve volume details from storage array."""
|
||||
volumes = list()
|
||||
|
@ -579,6 +606,11 @@ class NetAppESeriesVolume(NetAppESeriesModule):
|
|||
self.ssd_cache_enabled != self.volume_detail["flashCached"]):
|
||||
change = True
|
||||
|
||||
# controller ownership
|
||||
if self.owning_controller_id and self.owning_controller_id != self.volume_detail["preferredManager"]:
|
||||
change = True
|
||||
request_body.update(dict(owningControllerId=self.owning_controller_id))
|
||||
|
||||
if self.workload_name:
|
||||
request_body.update(dict(metaTags=[dict(key="workloadId", value=self.workload_id),
|
||||
dict(key="volumeTypeId", value="volume")]))
|
||||
|
@ -595,9 +627,13 @@ class NetAppESeriesVolume(NetAppESeriesModule):
|
|||
if self.thin_volume_expansion_policy != self.volume_detail["expansionPolicy"]:
|
||||
change = True
|
||||
request_body.update(dict(expansionPolicy=self.thin_volume_expansion_policy))
|
||||
elif self.read_ahead_enable != (int(self.volume_detail["cacheSettings"]["readAheadMultiplier"]) > 0):
|
||||
change = True
|
||||
request_body["cacheSettings"].update(dict(readAheadEnable=self.read_ahead_enable))
|
||||
else:
|
||||
if self.read_ahead_enable != (int(self.volume_detail["cacheSettings"]["readAheadMultiplier"]) > 0):
|
||||
change = True
|
||||
request_body["cacheSettings"].update(dict(readAheadEnable=self.read_ahead_enable))
|
||||
if self.cache_without_batteries != self.volume_detail["cacheSettings"]["cwob"]:
|
||||
change = True
|
||||
request_body["cacheSettings"].update(dict(cacheWithoutBatteries=self.cache_without_batteries))
|
||||
|
||||
return request_body if change else dict()
|
||||
|
||||
|
|
|
@ -238,16 +238,14 @@ class NetAppESeriesVolumeTest(ModuleTestCase):
|
|||
self._set_args(arg_set)
|
||||
volume_object = NetAppESeriesVolume()
|
||||
|
||||
size_unit_multiplier = NetAppESeriesModule.SIZE_UNIT_MAP[arg_set["size_unit"]]
|
||||
self.assertEqual(volume_object.size_b, arg_set["size"] * size_unit_multiplier)
|
||||
self.assertEqual(volume_object.thin_volume_repo_size_b,
|
||||
arg_set["thin_volume_repo_size"] * size_unit_multiplier)
|
||||
self.assertEqual(volume_object.size_b, volume_object.convert_to_aligned_bytes(arg_set["size"]))
|
||||
self.assertEqual(volume_object.thin_volume_repo_size_b, volume_object.convert_to_aligned_bytes(arg_set["thin_volume_repo_size"]))
|
||||
self.assertEqual(volume_object.thin_volume_expansion_policy, "automatic")
|
||||
if "thin_volume_max_repo_size" not in arg_set.keys():
|
||||
self.assertEqual(volume_object.thin_volume_max_repo_size_b, arg_set["size"] * size_unit_multiplier)
|
||||
self.assertEqual(volume_object.thin_volume_max_repo_size_b, volume_object.convert_to_aligned_bytes(arg_set["size"]))
|
||||
else:
|
||||
self.assertEqual(volume_object.thin_volume_max_repo_size_b,
|
||||
arg_set["thin_volume_max_repo_size"] * size_unit_multiplier)
|
||||
volume_object.convert_to_aligned_bytes(arg_set["thin_volume_max_repo_size"]))
|
||||
|
||||
# validate metadata form
|
||||
self._set_args(
|
||||
|
@ -502,7 +500,7 @@ class NetAppESeriesVolumeTest(ModuleTestCase):
|
|||
"read_ahead_enable": True, "thin_provision": False})
|
||||
volume_object = NetAppESeriesVolume()
|
||||
volume_object.volume_detail = {"metadata": [],
|
||||
"cacheSettings": {"readCacheEnable": True, "writeCacheEnable": True,
|
||||
"cacheSettings": {"cwob": False, "readCacheEnable": True, "writeCacheEnable": True,
|
||||
"readAheadMultiplier": 1}, "flashCached": True,
|
||||
"segmentSize": str(128 * 1024)}
|
||||
self.assertEqual(volume_object.get_volume_property_changes(), dict())
|
||||
|
@ -514,7 +512,7 @@ class NetAppESeriesVolumeTest(ModuleTestCase):
|
|||
"thin_volume_max_repo_size": 1000, "thin_volume_growth_alert_threshold": 90})
|
||||
volume_object = NetAppESeriesVolume()
|
||||
volume_object.volume_detail = {"metadata": [],
|
||||
"cacheSettings": {"readCacheEnable": True, "writeCacheEnable": True,
|
||||
"cacheSettings": {"cwob": False, "readCacheEnable": True, "writeCacheEnable": True,
|
||||
"readAheadMultiplier": 1},
|
||||
"flashCached": True, "growthAlertThreshold": "90",
|
||||
"expansionPolicy": "automatic", "segmentSize": str(128 * 1024)}
|
||||
|
@ -527,7 +525,7 @@ class NetAppESeriesVolumeTest(ModuleTestCase):
|
|||
"read_ahead_enable": True, "thin_provision": False})
|
||||
volume_object = NetAppESeriesVolume()
|
||||
volume_object.volume_detail = {"metadata": [],
|
||||
"cacheSettings": {"readCacheEnable": False, "writeCacheEnable": True,
|
||||
"cacheSettings": {"cwob": False, "readCacheEnable": False, "writeCacheEnable": True,
|
||||
"readAheadMultiplier": 1}, "flashCached": True,
|
||||
"segmentSize": str(128 * 1024)}
|
||||
self.assertEqual(volume_object.get_volume_property_changes(),
|
||||
|
@ -535,11 +533,11 @@ class NetAppESeriesVolumeTest(ModuleTestCase):
|
|||
'flashCache': True})
|
||||
self._set_args(
|
||||
{"state": "present", "name": "Matthew", "storage_pool_name": "pool", "size": 100, "ssd_cache_enabled": True,
|
||||
"read_cache_enable": True, "write_cache_enable": True,
|
||||
"read_cache_enable": True, "write_cache_enable": True, "cache_without_batteries": False,
|
||||
"read_ahead_enable": True, "thin_provision": False})
|
||||
volume_object = NetAppESeriesVolume()
|
||||
volume_object.volume_detail = {"metadata": [],
|
||||
"cacheSettings": {"readCacheEnable": True, "writeCacheEnable": False,
|
||||
"cacheSettings": {"cwob": False, "readCacheEnable": True, "writeCacheEnable": False,
|
||||
"readAheadMultiplier": 1}, "flashCached": True,
|
||||
"segmentSize": str(128 * 1024)}
|
||||
self.assertEqual(volume_object.get_volume_property_changes(),
|
||||
|
@ -547,29 +545,30 @@ class NetAppESeriesVolumeTest(ModuleTestCase):
|
|||
'flashCache': True})
|
||||
self._set_args(
|
||||
{"state": "present", "name": "Matthew", "storage_pool_name": "pool", "size": 100, "ssd_cache_enabled": True,
|
||||
"read_cache_enable": True, "write_cache_enable": True,
|
||||
"read_cache_enable": True, "write_cache_enable": True, "cache_without_batteries": True,
|
||||
"read_ahead_enable": True, "thin_provision": False})
|
||||
volume_object = NetAppESeriesVolume()
|
||||
volume_object.volume_detail = {"metadata": [],
|
||||
"cacheSettings": {"readCacheEnable": True, "writeCacheEnable": True,
|
||||
"cacheSettings": {"cwob": False, "readCacheEnable": True, "writeCacheEnable": True,
|
||||
"readAheadMultiplier": 1}, "flashCached": False,
|
||||
"segmentSize": str(128 * 1024)}
|
||||
self.assertEqual(volume_object.get_volume_property_changes(),
|
||||
{"metaTags": [], 'cacheSettings': {'readCacheEnable': True, 'writeCacheEnable': True},
|
||||
{"metaTags": [], 'cacheSettings': {'readCacheEnable': True, 'writeCacheEnable': True, "cacheWithoutBatteries": True},
|
||||
'flashCache': True})
|
||||
self._set_args(
|
||||
{"state": "present", "name": "Matthew", "storage_pool_name": "pool", "size": 100, "ssd_cache_enabled": True,
|
||||
"read_cache_enable": True, "write_cache_enable": True,
|
||||
"read_cache_enable": True, "write_cache_enable": True, "cache_without_batteries": True,
|
||||
"read_ahead_enable": False, "thin_provision": False})
|
||||
volume_object = NetAppESeriesVolume()
|
||||
volume_object.volume_detail = {"metadata": [],
|
||||
"cacheSettings": {"readCacheEnable": True, "writeCacheEnable": True,
|
||||
"cacheSettings": {"cwob": False, "readCacheEnable": True, "writeCacheEnable": True,
|
||||
"readAheadMultiplier": 1}, "flashCached": False,
|
||||
"segmentSize": str(128 * 1024)}
|
||||
self.assertEqual(volume_object.get_volume_property_changes(), {"metaTags": [],
|
||||
'cacheSettings': {'readCacheEnable': True,
|
||||
'writeCacheEnable': True,
|
||||
'readAheadEnable': False},
|
||||
'readAheadEnable': False,
|
||||
"cacheWithoutBatteries": True},
|
||||
'flashCache': True})
|
||||
|
||||
self._set_args(
|
||||
|
@ -579,7 +578,7 @@ class NetAppESeriesVolumeTest(ModuleTestCase):
|
|||
"thin_volume_max_repo_size": 1000, "thin_volume_growth_alert_threshold": 90})
|
||||
volume_object = NetAppESeriesVolume()
|
||||
volume_object.volume_detail = {"metadata": [],
|
||||
"cacheSettings": {"readCacheEnable": True, "writeCacheEnable": True,
|
||||
"cacheSettings": {"cwob": True, "readCacheEnable": True, "writeCacheEnable": True,
|
||||
"readAheadMultiplier": 1},
|
||||
"flashCached": True, "growthAlertThreshold": "95",
|
||||
"expansionPolicy": "automatic", "segmentSize": str(128 * 1024)}
|
||||
|
@ -594,7 +593,7 @@ class NetAppESeriesVolumeTest(ModuleTestCase):
|
|||
"read_cache_enable": True, "write_cache_enable": True, "read_ahead_enable": True, "thin_provision": False})
|
||||
volume_object = NetAppESeriesVolume()
|
||||
volume_object.volume_detail = {
|
||||
"cacheSettings": {"readCacheEnable": True, "writeCacheEnable": True, "readAheadMultiplier": 1},
|
||||
"cacheSettings": {"cwob": False, "readCacheEnable": True, "writeCacheEnable": True, "readAheadMultiplier": 1},
|
||||
"flashCached": True, "segmentSize": str(512 * 1024)}
|
||||
with self.assertRaisesRegexp(AnsibleFailJson, "Existing volume segment size is"):
|
||||
volume_object.get_volume_property_changes()
|
||||
|
|
Loading…
Add table
Reference in a new issue