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:
Nathan Swartz 2019-08-27 08:04:02 -05:00 committed by Jake Jackson
parent 61a2dab2ff
commit 37dd373c6b
2 changed files with 61 additions and 26 deletions

View file

@ -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()

View file

@ -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()