mgr/volumes: add interface to check the presence of subvolumegroups/subvolumes

Fixes: https://tracker.ceph.com/issues/55821
Signed-off-by: Neeraj Pratap Singh <neesingh@redhat.com>
This commit is contained in:
Neeraj Pratap Singh 2022-06-24 11:52:38 +05:30
parent 869c716e9c
commit 4eff1bb534
5 changed files with 108 additions and 2 deletions

View File

@ -88,6 +88,28 @@ def listdir(fs, dirpath, filter_entries=None):
raise VolumeException(-e.args[0], e.args[1])
return dirs
def has_subdir(fs, dirpath, filter_entries=None):
"""
Check the presence of directory (only dirs) for a given path
"""
res = False
if filter_entries is None:
filter_entries = [b".", b".."]
else:
filter_entries.extend([b".", b".."])
try:
with fs.opendir(dirpath) as dir_handle:
d = fs.readdir(dir_handle)
while d:
if (d.d_name not in filter_entries) and d.is_dir():
res = True
break
d = fs.readdir(dir_handle)
except cephfs.Error as e:
raise VolumeException(-e.args[0], e.args[1])
return res
def is_inherited_snap(snapname):
"""
Returns True if the snapname is inherited else False

View File

@ -8,7 +8,7 @@ import cephfs
from .snapshot_util import mksnap, rmsnap
from .pin_util import pin
from .template import GroupTemplate
from ..fs_util import listdir, listsnaps, get_ancestor_xattr, create_base_dir
from ..fs_util import listdir, listsnaps, get_ancestor_xattr, create_base_dir, has_subdir
from ..exception import VolumeException
log = logging.getLogger(__name__)
@ -64,6 +64,15 @@ class Group(GroupTemplate):
return []
raise
def has_subvolumes(self):
try:
return has_subdir(self.fs, self.path)
except VolumeException as ve:
# listing a default group when it's not yet created
if ve.errno == -errno.ENOENT and self.is_default_group():
return False
raise
def pin(self, pin_type, pin_setting):
return pin(self.fs, self.path, pin_type, pin_setting)

View File

@ -1,3 +1,9 @@
from .operations.index import Index
from .operations.group import Group
from .operations.trash import Trash
from .operations.versions.subvolume_base import SubvolumeBase
class VolSpec(object):
"""
specification of a "volume" -- base directory and various prefixes.
@ -9,6 +15,8 @@ class VolSpec(object):
DEFAULT_NS_PREFIX = "fsvolumens_"
# default mode for subvol prefix and group
DEFAULT_MODE = 0o755
# internal directories
INTERNAL_DIRS = [Group.NO_GROUP_NAME, Index.GROUP_NAME, Trash.GROUP_NAME, SubvolumeBase.LEGACY_CONF_DIR]
def __init__(self, snapshot_prefix, subvolume_prefix=None, pool_ns_prefix=None):
self.snapshot_prefix = snapshot_prefix

View File

@ -1,13 +1,14 @@
import json
import errno
import logging
import os
from typing import TYPE_CHECKING
import cephfs
from mgr_util import CephfsClient
from .fs_util import listdir
from .fs_util import listdir, has_subdir
from .operations.volume import create_volume, \
delete_volume, rename_volume, list_volumes, open_volume, get_pool_names
@ -466,6 +467,28 @@ class VolumeClient(CephfsClient["Module"]):
ret = self.volume_exception_to_retval(ve)
return ret
def subvolume_exists(self, **kwargs):
volname = kwargs['vol_name']
groupname = kwargs['group_name']
ret = 0, "", ""
volume_exists = False
try:
with open_volume(self, volname) as fs_handle:
volume_exists = True
with open_group(fs_handle, self.volspec, groupname) as group:
res = group.has_subvolumes()
if res:
ret = 0, "subvolume exists", ""
else:
ret = 0, "no subvolume exists", ""
except VolumeException as ve:
if volume_exists and ve.errno == -errno.ENOENT:
ret = 0, "no subvolume exists", ""
else:
ret = self.volume_exception_to_retval(ve)
return ret
### subvolume snapshot
def create_subvolume_snapshot(self, **kwargs):
@ -864,6 +887,27 @@ class VolumeClient(CephfsClient["Module"]):
ret = self.volume_exception_to_retval(ve)
return ret
def subvolume_group_exists(self, **kwargs):
volname = kwargs['vol_name']
ret = 0, "", ""
volume_exists = False
try:
with open_volume(self, volname) as fs_handle:
volume_exists = True
res = has_subdir(fs_handle, self.volspec.base_dir, filter_entries=[
dir.encode('utf-8') for dir in self.volspec.INTERNAL_DIRS])
if res:
ret = 0, "subvolumegroup exists", ""
else:
ret = 0, "no subvolumegroup exists", ""
except VolumeException as ve:
if volume_exists and ve.errno == -errno.ENOENT:
ret = 0, "no subvolumegroup exists", ""
else:
ret = self.volume_exception_to_retval(ve)
return ret
### group snapshot
def create_subvolume_group_snapshot(self, **kwargs):

View File

@ -111,6 +111,12 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
'desc': "Resize a CephFS subvolume group",
'perm': 'rw'
},
{
'cmd': 'fs subvolumegroup exist '
'name=vol_name,type=CephString ',
'desc': "Check a volume for the existence of subvolumegroup",
'perm': 'r'
},
{
'cmd': 'fs subvolume ls '
'name=vol_name,type=CephString '
@ -210,6 +216,14 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
"and optionally, in a specific subvolume group",
'perm': 'r'
},
{
'cmd': 'fs subvolume exist '
'name=vol_name,type=CephString '
'name=group_name,type=CephString,req=false ',
'desc': "Check a volume for the existence of a subvolume, "
"optionally in a specified subvolume group",
'perm': 'r'
},
{
'cmd': 'fs subvolume metadata set '
'name=vol_name,type=CephString '
@ -567,6 +581,10 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
def _cmd_fs_subvolumegroup_ls(self, inbuf, cmd):
return self.vc.list_subvolume_groups(vol_name=cmd['vol_name'])
@mgr_cmd_wrap
def _cmd_fs_subvolumegroup_exist(self, inbuf, cmd):
return self.vc.subvolume_group_exists(vol_name=cmd['vol_name'])
@mgr_cmd_wrap
def _cmd_fs_subvolume_create(self, inbuf, cmd):
"""
@ -657,6 +675,11 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
sub_name=cmd['sub_name'],
group_name=cmd.get('group_name', None))
@mgr_cmd_wrap
def _cmd_fs_subvolume_exist(self, inbuf, cmd):
return self.vc.subvolume_exists(vol_name=cmd['vol_name'],
group_name=cmd.get('group_name', None))
@mgr_cmd_wrap
def _cmd_fs_subvolume_metadata_set(self, inbuf, cmd):
return self.vc.set_user_metadata(vol_name=cmd['vol_name'],