except cephfs.Error as e:
raise VolumeException(-e.args[0], e.args[1])
+ def resize_subvolume(self, subvolpath, newsize, noshrink):
+ """
+ :param subvolpath: subvolume path
+ :param newsize: new size In bytes
+ :return: new quota size and used bytes as a tuple
+ """
+ if newsize <= 0:
+ raise VolumeException(-errno.EINVAL, "Provide a valid size")
+
+ try:
+ maxbytes = int(self.fs.getxattr(subvolpath, 'ceph.quota.max_bytes').decode('utf-8'))
+ except cephfs.NoData:
+ maxbytes = 0
+
+ subvolstat = self.fs.stat(subvolpath)
+ if newsize > 0 and newsize < subvolstat.st_size:
+ if noshrink:
+ raise VolumeException(-errno.EINVAL, "Can't resize the subvolume. The new size '{0}' would be lesser than the current "
+ "used size '{1}'".format(newsize, subvolstat.st_size))
+
+ if newsize == maxbytes:
+ return newsize, subvolstat.st_size
+
+ try:
+ self.fs.setxattr(subvolpath, 'ceph.quota.max_bytes', str(newsize).encode('utf-8'), 0)
+ except Exception as e:
+ raise VolumeException(-e.args[0], "Cannot set new size for the subvolume. '{0}'".format(e.args[1]))
+ return newsize, subvolstat.st_size
+
def purge_subvolume(self, spec, should_cancel):
"""
Finish clearing up a subvolume from the trash directory.
ret = self.volume_exception_to_retval(ve)
return ret
+ @connection_pool_wrap
+ def resize_subvolume(self, fs_handle, **kwargs):
+ ret = 0, "", ""
+ subvolname = kwargs['sub_name']
+ newsize = kwargs['new_size']
+ groupname = kwargs['group_name']
+ noshrink = kwargs['no_shrink']
+
+ try:
+ with SubVolume(self.mgr, fs_handle) as sv:
+ spec = SubvolumeSpec(subvolname, groupname)
+ if not self.group_exists(sv, spec):
+ raise VolumeException(
+ -errno.ENOENT, "Subvolume group '{0}' not found, create it with " \
+ "'ceph fs subvolumegroup create' before creating or resizing subvolumes".format(groupname))
+ subvolpath = sv.get_subvolume_path(spec)
+ if not subvolpath:
+ raise VolumeException(
+ -errno.ENOENT, "Subvolume '{0}' not found, create it with " \
+ "'ceph fs subvolume create' before resizing subvolumes".format(subvolname))
+ nsize, usedbytes = sv.resize_subvolume(subvolpath, newsize, noshrink)
+ ret = 0, json.dumps([{'bytes_used': usedbytes},{'bytes_quota': nsize},
+ {'bytes_pcent': '{0:.2f}'.format((float(usedbytes) / nsize) * 100.0)}], indent=2), ""
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
@connection_pool_wrap
def subvolume_getpath(self, fs_handle, **kwargs):
ret = None
"and optionally, in a specific subvolume group",
'perm': 'rw'
},
+ {
+ 'cmd': 'fs subvolume resize '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=new_size,type=CephInt,req=true '
+ 'name=group_name,type=CephString,req=false '
+ 'name=no_shrink,type=CephBool,req=false ',
+ 'desc': "Resize a CephFS subvolume",
+ 'perm': 'rw'
+ },
# volume ls [recursive]
# subvolume ls <volume>
return self.vc.list_subvolume_snapshots(None, vol_name=cmd['vol_name'],
sub_name=cmd['sub_name'],
group_name=cmd.get('group_name', None))
+
+ def _cmd_fs_subvolume_resize(self, inbuf, cmd):
+ return self.vc.resize_subvolume(None, vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ new_size=cmd['new_size'],
+ group_name=cmd.get('group_name', None),
+ no_shrink=cmd.get('no_shrink', False))