From 7e10ee327df4088f80d2b8b635e5bfc5b9314cad Mon Sep 17 00:00:00 2001 From: Antoine Bartuccio Date: Fri, 14 Nov 2025 14:17:36 +0100 Subject: [PATCH 1/2] fix(linstorvolumemanager): fix typo (#106) Fix some typo in docstring Signed-off-by: Antoine Bartuccio --- drivers/linstorvolumemanager.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/linstorvolumemanager.py b/drivers/linstorvolumemanager.py index 49d67d708..249ebf584 100755 --- a/drivers/linstorvolumemanager.py +++ b/drivers/linstorvolumemanager.py @@ -1176,7 +1176,7 @@ def get_usage_states(self, volume_uuid): """ Check if a volume is currently used. :param str volume_uuid: The volume uuid to check. - :return: A dictionnary that contains states. + :return: A dictionary that contains states. :rtype: dict(str, bool or None) """ @@ -1194,14 +1194,14 @@ def get_volume_openers(self, volume_uuid): """ Get openers of a volume. :param str volume_uuid: The volume uuid to monitor. - :return: A dictionnary that contains openers. + :return: A dictionary that contains openers. :rtype: dict(str, obj) """ return get_all_volume_openers(self.get_volume_name(volume_uuid), '0') def get_volumes_with_name(self): """ - Give a volume dictionnary that contains names actually owned. + Give a volume dictionary that contains names actually owned. :return: A volume/name dict. :rtype: dict(str, str) """ @@ -1209,7 +1209,7 @@ def get_volumes_with_name(self): def get_volumes_with_info(self): """ - Give a volume dictionnary that contains VolumeInfos. + Give a volume dictionary that contains VolumeInfos. :return: A volume/VolumeInfo dict. :rtype: dict(str, VolumeInfo) """ @@ -1233,7 +1233,7 @@ def get_volumes_with_info(self): def get_volumes_with_metadata(self): """ - Give a volume dictionnary that contains metadata. + Give a volume dictionary that contains metadata. :return: A volume/metadata dict. :rtype: dict(str, dict) """ From 6817eee427cabebf21be959f34b1f4ad12f9cc01 Mon Sep 17 00:00:00 2001 From: Antoine Bartuccio Date: Fri, 31 Oct 2025 13:00:42 +0100 Subject: [PATCH 2/2] fix(linstorvolumemanager): don't allow InUse volumes to be deleted (#106) Check for usage status before deleting a linstor volume and raise an appropriate error if this happens Signed-off-by: Antoine Bartuccio --- drivers/linstorvolumemanager.py | 37 +++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/linstorvolumemanager.py b/drivers/linstorvolumemanager.py index 249ebf584..ebaf6baf5 100755 --- a/drivers/linstorvolumemanager.py +++ b/drivers/linstorvolumemanager.py @@ -15,7 +15,7 @@ # along with this program. If not, see . # -from sm_typing import override +from sm_typing import Any, Dict, override import errno import json @@ -273,7 +273,8 @@ class LinstorVolumeManagerError(Exception): ERR_VOLUME_EXISTS = 1, ERR_VOLUME_NOT_EXISTS = 2, ERR_VOLUME_DESTROY = 3, - ERR_GROUP_NOT_EXISTS = 4 + ERR_GROUP_NOT_EXISTS = 4, + ERR_VOLUME_IN_USE = 5 def __init__(self, message, code=ERR_GENERIC): super(LinstorVolumeManagerError, self).__init__(message) @@ -302,7 +303,8 @@ class LinstorVolumeManager(object): '_base_group_name', '_group_name', '_ha_group_name', '_volumes', '_storage_pools', '_storage_pools_time', '_kv_cache', '_resource_cache', '_volume_info_cache', - '_kv_cache_dirty', '_resource_cache_dirty', '_volume_info_cache_dirty' + '_kv_cache_dirty', '_resource_cache_dirty', '_volume_info_cache_dirty', + '_resources_info_cache', ) DEV_ROOT_PATH = DRBD_BY_RES_PATH @@ -439,6 +441,7 @@ def __init__( self._resource_cache_dirty = True self._volume_info_cache = None self._volume_info_cache_dirty = True + self._resources_info_cache = None self._build_volumes(repair=repair) @property @@ -698,6 +701,13 @@ def destroy_volume(self, volume_uuid): self._ensure_volume_exists(volume_uuid) self.ensure_volume_is_not_locked(volume_uuid) + is_volume_in_use = any(node["in-use"] for node in self.get_resource_info(volume_uuid)["nodes"].values()) + if is_volume_in_use: + raise LinstorVolumeManagerError( + f"Could not destroy volume `{volume_uuid}` as it is currently in use", + LinstorVolumeManagerError.ERR_VOLUME_IN_USE + ) + # Mark volume as destroyed. volume_properties = self._get_volume_properties(volume_uuid) volume_properties[self.PROP_NOT_EXISTS] = self.STATE_NOT_EXISTS @@ -1701,6 +1711,9 @@ def get_resources_info(self): Give all resources of current group name. :rtype: dict(str, list) """ + if self._resources_info_cache and not self._resource_cache_dirty: + return self._resources_info_cache + resources = {} resource_list = self._get_resource_cache() volume_names = self.get_volumes_with_name() @@ -1757,7 +1770,23 @@ def get_resources_info(self): if resource: resource['uuid'] = volume_uuid - return resources + self._resources_info_cache = resources + return self._resources_info_cache + + def get_resource_info(self, volume_uuid: str) -> Dict[str, Any]: + """ + Give a resource info based on its UUID. + :param volume_uuid str: volume uuid to search for + :rtype: dict(str, any) + """ + for volume in self.get_resources_info().values(): + if volume["uuid"] == volume_uuid: + return volume + + raise LinstorVolumeManagerError( + f"Could not find info about volume `{volume_uuid}`", + LinstorVolumeManagerError.ERR_VOLUME_NOT_EXISTS + ) def get_database_path(self): """