return []
raise
+def set_group_attrs(fs, path, attrs):
+ # set subvolume group attrs
+ # set size
+ quota = attrs.get("quota")
+ if quota is not None:
+ try:
+ fs.setxattr(path, 'ceph.quota.max_bytes', str(quota).encode('utf-8'), 0)
+ except cephfs.InvalidValue:
+ raise VolumeException(-errno.EINVAL, "invalid size specified: '{0}'".format(quota))
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
-def create_group(fs, vol_spec, groupname, pool, mode, uid, gid):
+ # set pool layout
+ pool = attrs.get("data_pool")
+ if not pool:
+ pool = get_ancestor_xattr(fs, path, "ceph.dir.layout.pool")
+ try:
+ fs.setxattr(path, 'ceph.dir.layout.pool', pool.encode('utf-8'), 0)
+ except cephfs.InvalidValue:
+ raise VolumeException(-errno.EINVAL,
+ "Invalid pool layout '{0}'. It must be a valid data pool".format(pool))
+
+ # set uid/gid
+ uid = attrs.get("uid")
+ if uid is None:
+ uid = 0
+ else:
+ try:
+ uid = int(uid)
+ if uid < 0:
+ raise ValueError
+ except ValueError:
+ raise VolumeException(-errno.EINVAL, "invalid UID")
+
+ gid = attrs.get("gid")
+ if gid is None:
+ gid = 0
+ else:
+ try:
+ gid = int(gid)
+ if gid < 0:
+ raise ValueError
+ except ValueError:
+ raise VolumeException(-errno.EINVAL, "invalid GID")
+ fs.chown(path, uid, gid)
+
+ # set mode
+ mode = attrs.get("mode", None)
+ if mode is not None:
+ fs.lchmod(path, mode)
+
+def create_group(fs, vol_spec, groupname, size, pool, mode, uid, gid):
"""
create a subvolume group.
:param fs: ceph filesystem handle
:param vol_spec: volume specification
:param groupname: subvolume group name
+ :param size: In bytes, or None for no size limit
:param pool: the RADOS pool where the data objects of the subvolumes will be stored
:param mode: the user permissions
:param uid: the user identifier
create_base_dir(fs, vol_spec_base_dir, vol_spec.DEFAULT_MODE)
fs.mkdir(path, mode)
try:
- if not pool:
- pool = get_ancestor_xattr(fs, path, "ceph.dir.layout.pool")
- try:
- fs.setxattr(path, 'ceph.dir.layout.pool', pool.encode('utf-8'), 0)
- 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
- else:
- try:
- uid = int(uid)
- if uid < 0:
- raise ValueError
- except ValueError:
- raise VolumeException(-errno.EINVAL, "invalid UID")
- if gid is None:
- gid = 0
- else:
- try:
- gid = int(gid)
- if gid < 0:
- raise ValueError
- except ValueError:
- raise VolumeException(-errno.EINVAL, "invalid GID")
- fs.chown(path, uid, gid)
+ attrs = {
+ 'uid': uid,
+ 'gid': gid,
+ 'data_pool': pool,
+ 'quota': size
+ }
+ set_group_attrs(fs, path, attrs)
except (cephfs.Error, VolumeException) as e:
try:
# cleanup group path on best effort basis
from .operations.volume import create_volume, \
delete_volume, rename_volume, list_volumes, open_volume, get_pool_names
-from .operations.group import open_group, create_group, remove_group, open_group_unique
+from .operations.group import open_group, create_group, remove_group, \
+ open_group_unique, set_group_attrs
from .operations.subvolume import open_subvol, create_subvol, remove_subvol, \
create_clone
from .operations.trash import Trash
ret = 0, "", ""
volname = kwargs['vol_name']
groupname = kwargs['group_name']
+ size = kwargs['size']
pool = kwargs['pool_layout']
uid = kwargs['uid']
gid = kwargs['gid']
try:
with open_volume(self, volname) as fs_handle:
try:
- with open_group(fs_handle, self.volspec, groupname):
+ with open_group(fs_handle, self.volspec, groupname) as group:
# idempotent creation -- valid.
- pass
+ attrs = {
+ 'uid': uid,
+ 'gid': gid,
+ 'mode': octal_str_to_decimal_int(mode),
+ 'data_pool': pool,
+ 'quota': size
+ }
+ set_group_attrs(fs_handle, group.path, attrs)
except VolumeException as ve:
if ve.errno == -errno.ENOENT:
oct_mode = octal_str_to_decimal_int(mode)
- create_group(fs_handle, self.volspec, groupname, pool, oct_mode, uid, gid)
+ create_group(fs_handle, self.volspec, groupname, size, pool, oct_mode, uid, gid)
else:
raise
except VolumeException as ve:
'cmd': 'fs subvolumegroup create '
'name=vol_name,type=CephString '
f'name=group_name,type=CephString,goodchars={goodchars} '
+ 'name=size,type=CephInt,req=false '
'name=pool_layout,type=CephString,req=false '
'name=uid,type=CephInt,req=false '
'name=gid,type=CephInt,req=false '
:return: a 3-tuple of return code(int), empty string(str), error message (str)
"""
return self.vc.create_subvolume_group(
- vol_name=cmd['vol_name'], group_name=cmd['group_name'],
+ vol_name=cmd['vol_name'], group_name=cmd['group_name'], size=cmd.get('size', None),
pool_layout=cmd.get('pool_layout', None), mode=cmd.get('mode', '755'),
uid=cmd.get('uid', None), gid=cmd.get('gid', None))