mirror of
https://github.com/ceph/ceph
synced 2026-08-01 22:45:39 +00:00
Merge pull request #62342 from dparmar18/i62673
mgr/volumes: accept unit with subvolume resize Reviewed-by: Rishabh Dave <ridave@redhat.com> Reviewed-by: Neeraj Pratap Singh <neesingh@redhat.com> Reviewed-by: Christopher Hoffman <choffman@redhat.com>
This commit is contained in:
commit
0efbe10e14
@ -476,6 +476,15 @@ This command resizes the subvolume quota, using the size specified by
|
||||
``new_size``. The ``--no_shrink`` flag prevents the subvolume from shrinking
|
||||
below the current "used size" of the subvolume.
|
||||
|
||||
Resizing can also be done using human-friendly units::
|
||||
|
||||
ceph fs subvolume resize foo subvol1 100KiB
|
||||
ceph fs subvolume resize foo subvol1 200.45KiB
|
||||
ceph fs subvolume resize foo subvol1 300KB
|
||||
|
||||
.. note:: Values will be strictly cast to IEC units even when SI units
|
||||
are input, i.e. 1{K|KB|Ki|KiB} all translate to 1024 bytes.
|
||||
|
||||
The subvolume can be resized to an unlimited (but sparse) logical size by
|
||||
passing ``inf`` or ``infinite`` as ``<new_size>``.
|
||||
|
||||
|
||||
@ -4431,6 +4431,51 @@ class TestSubvolumes(TestVolumesHelper):
|
||||
# verify trash dir is clean
|
||||
self._wait_for_trash_empty()
|
||||
|
||||
def test_subvolume_resize_valid_unit(self):
|
||||
"""
|
||||
That a subvolume can be resized when provided with valid value
|
||||
(both int and float accepted) and unit.
|
||||
"""
|
||||
readable_values = {"10B": 10, "10K": 10240, "200KB": 204800,
|
||||
"300Ki": 307200, "300KiB": 307200,
|
||||
"300.67KiB": 307886, "10M": 10485760,
|
||||
"100MB": 104857600, "100Mi": 104857600,
|
||||
"100MiB": 104857600, "100.123MiB": 104986574,
|
||||
"2G": 2147483648, "2GB": 2147483648,
|
||||
"4Gi": 4294967296, "4GiB": 4294967296,
|
||||
"4.2GiB": 4509715660, "1T": 1099511627776,
|
||||
"2TB": 2199023255552, "2Ti": 2199023255552,
|
||||
"2TiB": 2199023255552, "2.2TiB": 2418925581107}
|
||||
subvolume = self._gen_subvol_name()
|
||||
self._fs_cmd("subvolume", "create", self.volname, subvolume)
|
||||
for readable_value in readable_values:
|
||||
self._fs_cmd("subvolume", "resize", self.volname, subvolume,
|
||||
readable_value)
|
||||
subvol_info = json.loads(self._get_subvolume_info(self.volname, subvolume))
|
||||
self.assertEqual(subvol_info["bytes_quota"], readable_values.get(readable_value))
|
||||
|
||||
self._fs_cmd("subvolume", "rm", self.volname, subvolume)
|
||||
self._wait_for_trash_empty()
|
||||
|
||||
def test_subvolume_resize_invalid_unit(self):
|
||||
"""
|
||||
That a subvolume resize fails when provided with invalid value
|
||||
and/or unit.
|
||||
"""
|
||||
invalid_values = ("10A", "1y00Ki", "af00", "G", "", " ", "-1t", "-1",
|
||||
"1GT", "2MM", "5Di", "8Bi", "i", "7iB", "1.K", ".MB",
|
||||
".10.G", "10Ki.B", "1.0.3TiB", "20G/.", "Gi32Ki",
|
||||
"10.64B", "1.B", ".B", "B.1", "KB1", "GB.1", "TB1.1")
|
||||
subvolume = self._gen_subvol_name()
|
||||
self._fs_cmd("subvolume", "create", self.volname, subvolume)
|
||||
for invalid_value in invalid_values:
|
||||
with self.assertRaises(CommandFailedError):
|
||||
self._fs_cmd("subvolume", "resize", self.volname, subvolume,
|
||||
invalid_value)
|
||||
|
||||
self._fs_cmd("subvolume", "rm", self.volname, subvolume)
|
||||
self._wait_for_trash_empty()
|
||||
|
||||
def test_subvolume_rm_force(self):
|
||||
# test removing non-existing subvolume with --force
|
||||
subvolume = self._gen_subvol_name()
|
||||
|
||||
@ -371,7 +371,37 @@ class SubvolumeBase(object):
|
||||
raise VolumeException(-errno.EINVAL,
|
||||
"invalid fscrypt_file specified: '{0}'".format(fscrypt_file))
|
||||
|
||||
def convert_to_bytes(self, subvol_size):
|
||||
import re
|
||||
unit_map = {"B": 1,
|
||||
"K": pow(1024, 1),
|
||||
"M": pow(1024, 2),
|
||||
"G": pow(1024, 3),
|
||||
"T": pow(1024, 4),
|
||||
"P": pow(1024, 5),
|
||||
"E": pow(1024, 6)}
|
||||
pattern = r'^(\d+\.\d+|\d+)([KMGTPE]i?B?|B)$'
|
||||
match = re.match(pattern, subvol_size)
|
||||
if match:
|
||||
value = match.group(1)
|
||||
unit = match.group(2)
|
||||
if unit[0] == "B" and "." in value:
|
||||
raise VolumeException(-errno.EINVAL,
|
||||
f"Invalid byte value: {value}")
|
||||
multiplier = unit_map.get(unit[0])
|
||||
if multiplier is None:
|
||||
raise VolumeException(-errno.EINVAL,
|
||||
f"Invalid subvolume unit: {unit}")
|
||||
else:
|
||||
return float(value) * multiplier
|
||||
else:
|
||||
return None
|
||||
|
||||
def _resize(self, path, newsize, noshrink):
|
||||
num = self.convert_to_bytes(newsize)
|
||||
if num is not None:
|
||||
newsize = num
|
||||
|
||||
try:
|
||||
newsize = int(newsize)
|
||||
if newsize <= 0:
|
||||
@ -396,7 +426,7 @@ class SubvolumeBase(object):
|
||||
raise VolumeException(-e.args[0], e.args[1])
|
||||
|
||||
subvolstat = self.fs.stat(path)
|
||||
if newsize > 0 and newsize < subvolstat.st_size:
|
||||
if 0 < newsize < subvolstat.st_size:
|
||||
if noshrink:
|
||||
raise VolumeException(-errno.EINVAL,
|
||||
"Can't resize the subvolume. "
|
||||
|
||||
Loading…
Reference in New Issue
Block a user