Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 38 additions & 9 deletions drivers/linstorvolumemanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#

from sm_typing import override
from sm_typing import Any, Dict, override

import errno
import json
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1176,7 +1186,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)
"""

Expand All @@ -1194,22 +1204,22 @@ 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)
"""
return self._get_volumes_by_property(self.REG_VOLUME_NAME)

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)
"""
Expand All @@ -1233,7 +1243,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)
"""
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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):
"""
Expand Down