opencas-test-framework/storage_devices/raid.py
Katarzyna Treder 5bd6a656c5 Fix imports
Signed-off-by: Katarzyna Treder <katarzyna.treder@h-partners.com>
2024-12-31 11:51:05 +01:00

184 lines
5.2 KiB
Python

#
# Copyright(c) 2020-2021 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
#
import threading
from enum import IntEnum, Enum
from core.test_run import TestRun
from storage_devices.device import Device
from storage_devices.disk import Disk
from test_tools.fs_tools import readlink
from test_tools.mdadm import Mdadm
from test_tools.disk_finder import resolve_to_by_id_link
from type_def.size import Size, Unit
def get_devices_paths_string(devices: [Device]):
return " ".join([d.path for d in devices])
class Level(IntEnum):
Raid0 = 0
Raid1 = 1
Raid4 = 4
Raid5 = 5
Raid6 = 6
Raid10 = 10
class StripSize(IntEnum):
Strip4K = 4
Strip8K = 8
Strip16K = 16
Strip32K = 32
Strip64K = 64
Strip128K = 128
Strip256K = 256
Strip1M = 1024
class MetadataVariant(Enum):
Legacy = "legacy"
Imsm = "imsm"
class RaidConfiguration:
def __init__(
self,
level: Level = None,
metadata: MetadataVariant = MetadataVariant.Imsm,
number_of_devices: int = 0,
size: Size = None,
strip_size: StripSize = None,
name: str = None,
):
self.level = level
self.metadata = metadata
self.number_of_devices = number_of_devices
self.size = size
self.strip_size = strip_size
self.name = name
class Raid(Disk):
__unique_id = 0
__lock = threading.Lock()
def __init__(
self,
path: str,
level: Level,
uuid: str,
container_uuid: str = None,
container_path: str = None,
metadata: MetadataVariant = MetadataVariant.Imsm,
array_devices: [Device] = [],
volume_devices: [Device] = [],
):
Device.__init__(self, resolve_to_by_id_link(path.replace("/dev/", "")))
self.device_name = path.split('/')[-1]
self.level = level
self.uuid = uuid
self.container_uuid = container_uuid
self.container_path = container_path
self.metadata = metadata
self.array_devices = array_devices if array_devices else volume_devices.copy()
self.volume_devices = volume_devices
self.partitions = []
self.__block_size = None
def __eq__(self, other):
try:
return self.uuid == other.uuid
except AttributeError:
return False
@property
def block_size(self):
if not self.__block_size:
self.__block_size = Unit(int(self.get_sysfs_property("logical_block_size")))
return self.__block_size
def stop(self):
Mdadm.stop(self.path)
if self.container_path:
Mdadm.stop(self.container_path)
@classmethod
def discover(cls):
TestRun.LOGGER.info("Discover RAIDs in system...")
raids = []
for raid in Mdadm.examine_result():
raids.append(
cls(
raid["path"],
Level[raid["level"]],
raid["uuid"],
raid["container"]["uuid"] if "container" in raid else None,
raid["container"]["path"] if "container" in raid else None,
MetadataVariant(raid["metadata"]),
[Device(d) for d in raid["array_devices"]],
[Device(d) for d in raid["devices"]]
)
)
return raids
@classmethod
def create(
cls,
raid_configuration: RaidConfiguration,
devices: [Device]
):
import copy
raid_conf = copy.deepcopy(raid_configuration)
if not raid_conf.number_of_devices:
raid_conf.number_of_devices = len(devices)
elif len(devices) < raid_conf.number_of_devices:
raise ValueError("RAID configuration requires at least "
f"{raid_conf.number_of_devices} devices")
md_dir_path = "/dev/md/"
array_devices = devices
volume_devices = devices[:raid_conf.number_of_devices]
if raid_conf.metadata != MetadataVariant.Legacy:
container_conf = RaidConfiguration(
name=cls.__get_unique_name(raid_conf.metadata.value),
metadata=raid_conf.metadata,
number_of_devices=len(array_devices)
)
Mdadm.create(container_conf, get_devices_paths_string(array_devices))
if not raid_conf.name:
raid_conf.name = cls.__get_unique_name()
Mdadm.create(raid_conf, get_devices_paths_string(volume_devices))
raid_link = md_dir_path + raid_conf.name
raid = [r for r in Mdadm.examine_result() if readlink(r["path"]) == readlink(raid_link)][0]
return cls(
raid["path"],
raid_conf.level,
raid["uuid"],
raid["container"]["uuid"] if "container" in raid else None,
raid["container"]["path"] if "container" in raid else None,
raid_conf.metadata,
array_devices,
volume_devices
)
@staticmethod
def remove_all():
Mdadm.stop()
@classmethod
def __get_unique_name(cls, prefix: str = "Raid"):
with cls.__lock:
cls.__unique_id += 1
return f"{prefix}{cls.__unique_id}"