Merge pull request #702 from robertbaldyga/v22.6-composite-volume

Introduce composite volume
This commit is contained in:
Adam Rutkowski
2022-06-02 13:36:21 +02:00
committed by GitHub
20 changed files with 1079 additions and 148 deletions

View File

@@ -63,8 +63,7 @@ class CacheConfig(Structure):
class CacheDeviceConfig(Structure):
_fields_ = [
("_uuid", Uuid),
("_volume_type", c_uint8),
("_volume", c_void_p),
("_perform_test", c_bool),
("_volume_params", c_void_p),
]
@@ -257,7 +256,7 @@ class Cache:
raise OcfError("Failed to detach failover cache device", c.results["error"])
def standby_activate(self, device, open_cores=True):
device_cfg = Cache.generate_device_config(device)
device_cfg = self.generate_device_config(device)
activate_cfg = CacheStandbyActivateConfig(_device=device_cfg, _open_cores=open_cores,)
@@ -457,14 +456,24 @@ class Cache:
if status:
raise OcfError("Error adding partition to cache", status)
@staticmethod
def generate_device_config(device, perform_test=True):
def generate_device_config(self, device, perform_test=True):
uuid = Uuid(
_data=cast(create_string_buffer(device.uuid.encode("ascii")), c_char_p),
_size=len(device.uuid) + 1,
)
volume = c_void_p()
lib = OcfLib.getInstance()
result = lib.ocf_volume_create(
byref(volume),
self.owner.ocf_volume_type[type(device)],
byref(uuid)
)
if result != 0:
raise OcfError("Cache volume initialization failed", result)
device_config = CacheDeviceConfig(
_uuid=Uuid(
_data=cast(create_string_buffer(device.uuid.encode("ascii")), c_char_p),
_size=len(device.uuid) + 1,
),
_volume_type=device.type_id,
_volume=volume,
_perform_test=perform_test,
_volume_params=None,
)
@@ -477,7 +486,7 @@ class Cache:
self.device = device
self.device_name = device.uuid
device_config = Cache.generate_device_config(device, perform_test=perform_test)
device_config = self.generate_device_config(device, perform_test=perform_test)
attach_cfg = CacheAttachConfig(
_device=device_config,
@@ -505,7 +514,7 @@ class Cache:
self.device = device
self.device_name = device.uuid
device_config = Cache.generate_device_config(device, perform_test=False)
device_config = self.generate_device_config(device, perform_test=False)
attach_cfg = CacheAttachConfig(
_device=device_config,
@@ -533,7 +542,7 @@ class Cache:
self.device = device
self.device_name = device.uuid
device_config = Cache.generate_device_config(device, perform_test=perform_test)
device_config = self.generate_device_config(device, perform_test=perform_test)
attach_cfg = CacheAttachConfig(
_device=device_config,
@@ -570,7 +579,7 @@ class Cache:
self.device = device
self.device_name = device.uuid
device_config = Cache.generate_device_config(device)
device_config = self.generate_device_config(device)
attach_cfg = CacheAttachConfig(
_device=device_config,
@@ -917,3 +926,5 @@ lib.ocf_mngt_add_partition_to_cache.argtypes = [
]
lib.ocf_mngt_cache_io_classes_configure.restype = c_int
lib.ocf_mngt_cache_io_classes_configure.argtypes = [c_void_p, c_void_p]
lib.ocf_volume_create.restype = c_int
lib.ocf_volume_create.argtypes = [c_void_p, c_void_p, c_void_p]

View File

@@ -3,7 +3,7 @@
# SPDX-License-Identifier: BSD-3-Clause
#
from ctypes import c_void_p, Structure, c_char_p, cast, pointer, byref, c_int
from ctypes import c_void_p, Structure, c_char_p, cast, pointer, byref, c_int, c_uint8
import weakref
from .logger import LoggerOps, Logger
@@ -37,6 +37,7 @@ class OcfCtx:
self.lib = lib
self.volume_types_count = 1
self.volume_types = {}
self.ocf_volume_type = {}
self.caches = []
self.cfg = OcfCtxCfg(
@@ -77,6 +78,11 @@ class OcfCtx:
if result != 0:
raise OcfError("Volume type registration failed", result)
self.ocf_volume_type[volume_type] = self.lib.ocf_ctx_get_volume_type(
self.ctx_handle,
volume_type.type_id
)
self.volume_types_count += 1
def unregister_volume_type(self, vol_type):
@@ -86,6 +92,7 @@ class OcfCtx:
self.lib.ocf_ctx_unregister_volume_type(self.ctx_handle, vol_type.type_id)
del self.volume_types[vol_type.type_id]
del self.ocf_volume_type[vol_type]
def cleanup_volume_types(self):
for k, vol_type in list(self.volume_types.items()):
@@ -108,3 +115,5 @@ class OcfCtx:
lib = OcfLib.getInstance()
lib.ocf_mngt_cache_get_by_name.argtypes = [c_void_p, c_void_p, c_void_p]
lib.ocf_mngt_cache_get_by_name.restype = c_int
lib.ocf_ctx_get_volume_type.argtypes = [c_void_p, c_uint8]
lib.ocf_ctx_get_volume_type.restype = c_void_p

View File

@@ -47,7 +47,9 @@ class VolumeOps(Structure):
SUBMIT_METADATA = CFUNCTYPE(None, c_void_p)
SUBMIT_DISCARD = CFUNCTYPE(None, c_void_p)
SUBMIT_WRITE_ZEROES = CFUNCTYPE(None, c_void_p)
OPEN = CFUNCTYPE(c_int, c_void_p)
ON_INIT = CFUNCTYPE(c_int, c_void_p)
ON_DEINIT = CFUNCTYPE(None, c_void_p)
OPEN = CFUNCTYPE(c_int, c_void_p, c_void_p)
CLOSE = CFUNCTYPE(None, c_void_p)
GET_MAX_IO_SIZE = CFUNCTYPE(c_uint, c_void_p)
GET_LENGTH = CFUNCTYPE(c_uint64, c_void_p)
@@ -58,6 +60,8 @@ class VolumeOps(Structure):
("_submit_metadata", SUBMIT_METADATA),
("_submit_discard", SUBMIT_DISCARD),
("_submit_write_zeroes", SUBMIT_WRITE_ZEROES),
("_on_init", ON_INIT),
("_on_deinit", ON_DEINIT),
("_open", OPEN),
("_close", CLOSE),
("_get_length", GET_LENGTH),
@@ -124,8 +128,16 @@ class Volume:
def _submit_write_zeroes(write_zeroes):
raise NotImplementedError
@VolumeOps.ON_INIT
def _on_init(ref):
return 0
@VolumeOps.ON_DEINIT
def _on_deinit(ref):
return
@VolumeOps.OPEN
def _open(ref):
def _open(ref, params):
uuid_ptr = cast(OcfLib.getInstance().ocf_volume_get_uuid(ref), POINTER(Uuid))
uuid = str(uuid_ptr.contents._data, encoding="ascii")
try:
@@ -161,6 +173,8 @@ class Volume:
_close=_close,
_get_max_io_size=_get_max_io_size,
_get_length=_get_length,
_on_init=_on_init,
_on_deinit=_on_deinit,
)
return Volume._ops_[cls]

View File

@@ -74,6 +74,8 @@ def test_io_flags(pyocf_ctx, cache_mode):
data = bytes(block_size)
pyocf_ctx.register_volume_type(FlagsValVolume)
cache_device = FlagsValVolume(Size.from_MiB(50), flags)
core_device = FlagsValVolume(Size.from_MiB(50), flags)

View File

@@ -63,6 +63,8 @@ def test_flush_after_mngmt(pyocf_ctx):
data = bytes(block_size)
pyocf_ctx.register_volume_type(FlushValVolume)
cache_device = FlushValVolume(Size.from_MiB(50))
core_device = FlushValVolume(Size.from_MiB(50))

View File

@@ -0,0 +1,276 @@
#
# Copyright(c) 2022 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
#
import pytest
@pytest.mark.skip(reason="not implemented")
def test_create_composite_volume(pyocf_ctx):
"""
title: Create composite volume.
description: |
Check that it is possible to create and destroy composite volume
object.
pass_criteria:
- Composite volume is created without an error.
- Subvolume is added without an error.
steps:
- Create composite volume
- Verify that no error occured
- Add RamVolume as a subvolume
- Verify that no error occured
- Destroy composite volume
requirements:
- composite_volume::creation
- composite_volume::adding_component_volume
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_add_subvolumes_of_different_types(pyocf_ctx):
"""
title: Add subvolumes of different types.
description: |
Check that it is possible to add two subvolumes of different types to
composite volume.
pass_criteria:
- Composite volume is created without an error.
- Subvolumes are added without an error.
steps:
- Create composite volume
- Add RamVolume as a subvolume
- Verify that no error occured
- Add ErrorDevice as a subvolume
- Verify that no error occured
- Destroy composite volume
requirements:
- composite_volume::component_volume_types
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_add_max_subvolumes(pyocf_ctx):
"""
title: Add maximum number of subvolumes.
description: |
Check that it is possible to add 16 subvolumes to composite volume.
pass_criteria:
- Composite volume is created without an error.
- Subvolumes are added without an error.
steps:
- Create composite volume
- Add 16 RamVolume instances as subvolumes
- Verify that no error occured
- Destroy composite volume
requirements:
- composite_volume::max_composite_volumes
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_basic_volume_operations(pyocf_ctx):
"""
title: Perform basic volume operations.
description: |
Check that basic volume operations work on composite volume.
pass_criteria:
- Composite volume is created without an error.
- Subvolume is added without an error.
- Submit io, submit flush and submit discard operations work properly.
steps:
- Create composite volume
- Add mock volume as a subvolume
- Submit io to composite volume and check if it was propagated
- Submit flush to composite volume and check if it was propagated
- Submit discard to composite volume and check if it was propagated
- Destroy composite volume
requirements:
- composite_volume::volume_api
- composite_volume::io_request_passing
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_io_propagation_basic(pyocf_ctx):
"""
title: Perform volume operations with multiple subvolumes.
description: |
Check that io operations are propagated properly to subvolumes.
pass_criteria:
- Composite volume is created without an error.
- Subvolumes are added without an error.
- Operations are propagated properly.
steps:
- Create composite volume
- Add 16 mock volumes as subvolumes
- Submit io to each subvolume address range
- Check if requests were propagated properly
- Submit flush to each subvolume address range
- Check if requests were propagated properly
- Submit discard to each subvolume address range
- Check if requests were propagated properly
- Destroy composite volume
requirements:
- composite_volume::volume_api
- composite_volume::io_request_passing
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_io_propagation_cross_boundary(pyocf_ctx):
"""
title: Perform cross-subvolume operations.
description: |
Check that cross-subvolume operations are propagated properly.
pass_criteria:
- Composite volume is created without an error.
- Subvolumes are added without an error.
- Operations are propagated properly.
steps:
- Create composite volume
- Add 16 mock volumes as subvolumes
- Submit io that cross address range boundary between each subvolume
- Check if requests were propagated properly
- Submit flush that cross address range boundary between each subvolume
- Check if requests were propagated properly
- Submit discard that cross address range boundary between each subvolume
- Check if requests were propagated properly
- Destroy composite volume
requirements:
- composite_volume::io_request_passing
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_io_propagation_multiple_subvolumes(pyocf_ctx):
"""
title: Perform multi-subvolume operations.
description: |
Check that multi-subvolume operations are propagated properly.
pass_criteria:
- Composite volume is created without an error.
- Subvolumes are added without an error.
- Operations are propagated properly.
steps:
- Create composite volume
- Add 16 mock volumes as subvolumes
- Submit series of ios that touch from 2 to 16 subvolumes
- Check if requests were propated properly
- Submit series of flushes that touch from 2 to 16 subvolumes
- Check if requests were propagated properly
- Submit series of discardss that touch from 2 to 16 subvolumes
- Check if requests were propagated properly
- Destroy composite volume
requirements:
- composite_volume::io_request_passing
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_io_completion(pyocf_ctx):
"""
title: Composite volume completion order.
description: |
Check that composite volume waits for completions from all subvolumes.
pass_criteria:
- Composite volume is created without an error.
- Subvolumes are added without an error.
- Operations are completed only after all subvolumes operations complete.
steps:
- Create composite volume
- Add 16 mock volumes as subvolumes
- Submit series of ios that touch from 2 to 16 subvolumes
- Check if completions are called only after all subvolumes completed
- Submit series of flushes that touch from 2 to 16 subvolumes
- Check if completions are called only after all subvolumes completed
- Submit series of discardss that touch from 2 to 16 subvolumes
- Check if completions are called only after all subvolumes completed
- Destroy composite volume
requirements:
- composite_volume::io_request_completion
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_io_completion(pyocf_ctx):
"""
title: Composite volume error propagation.
description: |
Check that composite volume propagates errors from subvolumes.
pass_criteria:
- Composite volume is created without an error.
- Subvolumes are added without an error.
- Errors from subvolumes are propagated to composite volume.
steps:
- Create composite volume
- Add 16 ErrorDevice instances as subvolumes
- Before each request arm one of ErrorDevices touched by this request
- Submit series of ios that touch from 2 to 16 subvolumes
- Check if errors were propagated properly
- Submit series of flushes that touch from 2 to 16 subvolumes
- Check if errors were propagated properly
- Submit series of discardss that touch from 2 to 16 subvolumes
- Check if errors were propagated properly
- Destroy composite volume
requirements:
- composite_volume::io_error_handling
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_attach(pyocf_ctx):
"""
title: Attach composite volume.
description: |
Check that it is possible to attach composite volume
pass_criteria:
- Composite volume is created without an error.
- Subvolumes are added without an error.
- Cache attach succeeds.
steps:
- Create composite volume
- Add 16 RamVolume instances as subvolumes.
- Start cache and attach it using composite volume instance.
- Verify that cache was attached properly.
- Stop the cache.
- Verify that cache was stopped.
requirements:
- composite_volume::cache_attach_load
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_load(pyocf_ctx):
"""
title: Load composite volume.
description: |
Check that it is possible to attach composite volume
pass_criteria:
- Composite volume is created without an error.
- Subvolumes are added without an error.
- Cache load succeeds.
steps:
- Create composite volume
- Add 16 RamVolume instances as subvolumes.
- Start cache and attach it using composite volume instance.
- Stop the cache.
- Start cache and load it using composite volume instance.
- Verify that cache was loaded properly.
- Stop the cache.
- Verify that cache was stopped.
requirements:
- composite_volume::cache_attach_load
"""
pass