mirror of https://git.48k.eu/ogclient
utils: rewrite ogReduceFs
Drop subprocess call to bash function ogReduceFs. Use a native python solution with subprocess calls to the required underlying tools. Use get_filesystem_type to get the filesystem from a partition and call the corresponding supported filesystem shrink function. Filesystem specific functions are declared "_reduce_{filesystem}" and should not be imported elsewhere. In case of NTFS filesystems, the output of 'ntfsresize' is processed directly. This is dirty, but we can expect no changes to the output strings if we read the following comment in the nftsresize.c source code: https://github.com/tuxera/ntfs-3g/blob/edge/ntfsprogs/ntfsresize.c#L12 ntfsresize requires to do previous dry-run executions to confirm that the resizing is possible. If a dry-run fails but a 10% increase in size is still smaller than original filesystem then retry the operation until dry-run reports sucess or the size increase is bigger than original. If resizing to a smaller ntfs filesystem is not possible then ogReduceFs will do nothing.more_events
parent
22dce48d3e
commit
dd999bfe34
|
@ -82,15 +82,21 @@ def get_usedperc(mountpoint):
|
|||
|
||||
def ogReduceFs(disk, part):
|
||||
"""
|
||||
Bash function 'ogReduceFs' wrapper
|
||||
Shrink filesystem of a partition. Supports ext4 and ntfs partitions.
|
||||
Unsupported filesystem or invalid paths don't raise an exception,
|
||||
instead this method logs a warning message and does nothing.
|
||||
"""
|
||||
proc = subprocess.run(f'ogReduceFs {disk} {part}',
|
||||
shell=True, stdout=PIPE,
|
||||
encoding='utf-8')
|
||||
if proc.returncode != 0:
|
||||
logging.warn(f'ogReduceFS exited with non zero code: {proc.returncode}')
|
||||
subprocess.run(f'ogUnmount {disk} {part}',
|
||||
shell=True)
|
||||
partdev = get_partition_device(disk, part)
|
||||
fstype = get_filesystem_type(partdev)
|
||||
|
||||
umount(partdev)
|
||||
if fstype == 'ext4':
|
||||
_reduce_resize2fs(partdev)
|
||||
elif fstype == 'ntfs':
|
||||
_reduce_ntfsresize(partdev)
|
||||
else:
|
||||
logging.warn(f'Unable to shrink filesystem at {partdev}. '
|
||||
f'Unsupported filesystem "{fstype}".')
|
||||
|
||||
|
||||
def ogExtendFs(disk, part):
|
||||
|
@ -177,3 +183,40 @@ def get_filesystem_type(partdev):
|
|||
if proc.returncode != 0:
|
||||
raise RuntimeError(f'Error getting filesystem from {partdev}')
|
||||
return proc.stdout.strip()
|
||||
|
||||
|
||||
def _reduce_resize2fs(partdev):
|
||||
cmd = shlex.split(f'resize2fs -fpM {partdev}')
|
||||
with open('/tmp/command.log', 'ab', 0) as logfile:
|
||||
subprocess.run(cmd, stdout=logfile, stderr=STDOUT)
|
||||
|
||||
|
||||
def _reduce_ntfsresize(partdev):
|
||||
cmd_info = shlex.split(f'ntfsresize -Pfi {partdev}')
|
||||
proc_info = subprocess.run(cmd_info, stdout=subprocess.PIPE, encoding='utf-8')
|
||||
out_info = proc_info.stdout.strip()
|
||||
|
||||
# Process ntfsresize output directly.
|
||||
# The first split operation leaves the wanted data at the second element of
|
||||
# the split ([1]). Finally do a second split with ' ' to get the data but
|
||||
# nothing else following it.
|
||||
#
|
||||
# In addition, increase by 10%+1K the reported shrink location on which the
|
||||
# filesystem can be resized according to ntfsresize.
|
||||
size = int(out_info.split('device size: ')[1].split(' ')[0])
|
||||
new_size = int(int(out_info.split('resize at ')[1].split(' ')[0])*1.1+1024)
|
||||
|
||||
# Dry-run loop to test if resizing is actually possible. This is required by ntfsresize.
|
||||
returncode = 1
|
||||
while new_size < size and returncode != 0:
|
||||
cmd_resize_dryrun = shlex.split(f'ntfsresize -Pfns {new_size:.0f} {partdev}')
|
||||
proc_resize_dryrun = subprocess.run(cmd_resize_dryrun, stdout=subprocess.PIPE, encoding='utf-8')
|
||||
returncode = proc_resize_dryrun.returncode
|
||||
out_resize_dryrun = proc_resize_dryrun.stdout.strip()
|
||||
extra_size = int(out_resize_dryrun.split('Needed relocations : ')[1].split(' ')[0])*1.1+1024
|
||||
new_size += int(extra_size)
|
||||
|
||||
if new_size < size:
|
||||
cmd_resize = shlex.split(f'ntfsresize -fs {new_size:.0f} {partdev}')
|
||||
with open('/tmp/command.log', 'ab', 0) as logfile:
|
||||
subprocess.run(cmd_resize, input='y', stderr=STDOUT, encoding='utf-8')
|
||||
|
|
Loading…
Reference in New Issue