### basic subvolume operations
- def create_subvolume(self, spec, size=None, namespace_isolated=True, mode=0o755, pool=None):
+ def create_subvolume(self, spec, size=None, pool=None, namespace_isolated=True,
+ uid=None, gid=None, mode=0o755):
"""
Set up metadata, pools and auth for a subvolume.
:param spec: subvolume path specification
:param size: In bytes, or None for no size limit
- :param namespace_isolated: If true, use separate RADOS namespace for this subvolume
:param pool: the RADOS pool where the data objects of the subvolumes will be stored
+ :param namespace_isolated: If true, use separate RADOS namespace for this subvolume
+ :param uid: the user identifier
+ :param gid: the group identifier
+ :mode: the user permissions
:return: None
"""
subvolpath = spec.subvolume_path
xattr_val = self._get_ancestor_xattr(subvolpath, "ceph.dir.layout.pool")
# TODO: handle error...
self.fs.setxattr(subvolpath, xattr_key, xattr_val.encode('utf-8'), 0)
+
+ groupstat = self.fs.stat(spec.group_path)
+ if uid is None:
+ uid = int(groupstat.st_uid)
+ elif uid < 0:
+ raise VolumeException(-errno.EINVAL, "Provide a valid uid")
+
+ if gid is None:
+ gid = int(groupstat.st_gid)
+ elif gid < 0:
+ raise VolumeException(-errno.EINVAL, "Provide a valid gid")
+
+ try:
+ self.fs.chown(subvolpath, uid, gid)
+ except cephfs.InvalidValue:
+ raise VolumeException(-e.args[0], e.args[1])
+
except Exception as e:
try:
# cleanup subvol path on best effort basis
### group operations
- def create_group(self, spec, mode=0o755, pool=None):
+ def create_group(self, spec, pool=None, uid=None, gid=None, mode=0o755):
+ """
+ Create a subvolume group.
+
+ :param spec: subvolume path specification
+ :param pool: the RADOS pool where the data objects of the subvolumes will be stored
+ :param uid: the user identifier
+ :param gid: the group identifier
+ :mode: the user permissions
+ :return: None
+ """
path = spec.group_path
self.fs.mkdirs(path, mode)
try:
except cephfs.InvalidValue:
raise VolumeException(-errno.EINVAL,
"Invalid pool layout '{0}'. It must be a valid data pool".format(pool))
+
+ if uid is None:
+ uid = 0
+ elif uid < 0:
+ raise VolumeException(-errno.EINVAL, "Provide a valid uid")
+
+ if gid is None:
+ gid = 0
+ elif gid < 0:
+ raise VolumeException(-errno.EINVAL, "Provide a valid gid")
+
+ try:
+ self.fs.chown(path, uid, gid)
+ except cephfs.InvalidValue:
+ raise VolumeException(-e.args[0], e.args[1])
+
except Exception as e:
try:
# cleanup group path on best effort basis
groupname = kwargs['group_name']
size = kwargs['size']
pool = kwargs['pool_layout']
+ uid = kwargs['uid']
+ gid = kwargs['gid']
mode = kwargs['mode']
try:
raise VolumeException(
-errno.ENOENT, "Subvolume group '{0}' not found, create it with " \
"`ceph fs subvolumegroup create` before creating subvolumes".format(groupname))
- sv.create_subvolume(spec, size, pool=pool, mode=self.octal_str_to_decimal_int(mode))
+ sv.create_subvolume(spec, size, pool=pool, uid=uid, gid=gid, mode=self.octal_str_to_decimal_int(mode))
except VolumeException as ve:
ret = self.volume_exception_to_retval(ve)
return ret
volname = kwargs['vol_name']
groupname = kwargs['group_name']
pool = kwargs['pool_layout']
+ uid = kwargs['uid']
+ gid = kwargs['gid']
mode = kwargs['mode']
try:
# TODO: validate that subvol size fits in volume size
with SubVolume(self.mgr, fs_handle) as sv:
spec = SubvolumeSpec("", groupname)
- sv.create_group(spec, pool=pool, mode=self.octal_str_to_decimal_int(mode))
+ sv.create_group(spec, pool=pool, uid=uid, gid=gid, mode=self.octal_str_to_decimal_int(mode))
except VolumeException as ve:
ret = self.volume_exception_to_retval(ve)
return ret
'name=vol_name,type=CephString '
'name=group_name,type=CephString '
'name=pool_layout,type=CephString,req=false '
+ 'name=uid,type=CephInt,req=false '
+ 'name=gid,type=CephInt,req=false '
'name=mode,type=CephString,req=false ',
'desc': "Create a CephFS subvolume group in a volume, and optionally, "
"with a specific data pool layout, and a specific numeric mode",
'name=size,type=CephInt,req=false '
'name=group_name,type=CephString,req=false '
'name=pool_layout,type=CephString,req=false '
+ 'name=uid,type=CephInt,req=false '
+ 'name=gid,type=CephInt,req=false '
'name=mode,type=CephString,req=false ',
'desc': "Create a CephFS subvolume in a volume, and optionally, "
"with a specific size (in bytes), a specific data pool layout, "
"""
return self.vc.create_subvolume_group(
None, vol_name=cmd['vol_name'], group_name=cmd['group_name'],
- pool_layout=cmd.get('pool_layout', None), mode=cmd.get('mode', '755'))
+ pool_layout=cmd.get('pool_layout', None), uid=cmd.get('uid', None),
+ gid=cmd.get('gid', None), mode=cmd.get('mode', '755'))
def _cmd_fs_subvolumegroup_rm(self, inbuf, cmd):
"""
group_name=cmd.get('group_name', None),
size=cmd.get('size', None),
pool_layout=cmd.get('pool_layout', None),
+ uid=cmd.get('uid', None),
+ gid=cmd.get('gid', None),
mode=cmd.get('mode', '755'))
def _cmd_fs_subvolume_rm(self, inbuf, cmd):