diff options
-rw-r--r-- | src/utils/fs.py | 61 |
1 files changed, 52 insertions, 9 deletions
diff --git a/src/utils/fs.py b/src/utils/fs.py index a7058a7..bffdb8c 100644 --- a/src/utils/fs.py +++ b/src/utils/fs.py @@ -82,15 +82,21 @@ def get_usedperc(mountpoint): def ogReduceFs(disk, part): """ - Bash function 'ogReduceFs' wrapper - """ - 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) + 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. + """ + 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') |