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
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__)
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)
+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.
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
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
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):
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):
'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 '
"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 '
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):
"""
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'],