From 8d7b1b0bd6be864ef56da80b3c4bd6174c52bb54 Mon Sep 17 00:00:00 2001 From: Alexander Gubin Date: Fri, 15 Jan 2016 18:35:45 +0100 Subject: [PATCH] Make fileystem module idemponent. Compare devicesize and filesystemsize. --- system/filesystem.py | 73 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/system/filesystem.py b/system/filesystem.py index b44168a0e06..d31d6ebec5c 100644 --- a/system/filesystem.py +++ b/system/filesystem.py @@ -63,6 +63,50 @@ EXAMPLES = ''' - filesystem: fstype=ext4 dev=/dev/sdb1 opts="-cc" ''' +def _get_dev_size(dev, module): + """ Return size in bytes of device. Returns int """ + blockdev_cmd = module.get_bin_path("blockdev", required=True) + rc, devsize_in_bytes, err = module.run_command("%s %s %s" % (blockdev_cmd, "--getsize64", dev)) + return int(devsize_in_bytes) + + +def _get_fs_size(fssize_cmd, dev, module): + """ Return size in bytes of filesystem on device. Returns int """ + cmd = module.get_bin_path(fssize_cmd, required=True) + if 'tune2fs' == fssize_cmd: + # Get Block count and Block size + rc, size, err = module.run_command("%s %s %s" % (cmd, '-l', dev)) + if rc == 0: + for line in size.splitlines(): + if 'Block count:' in line: + block_count = int(line.split(':')[1].strip()) + elif 'Block size:' in line: + block_size = int(line.split(':')[1].strip()) + break + else: + module.fail_json(msg="Failed to get block count and block size of %s with %s" % (dev, cmd), rc=rc, err=err ) + elif 'xfs_info' == fssize_cmd: + # Get Block count and Block size + rc, size, err = module.run_command("%s %s" % (cmd, dev)) + if rc == 0: + for line in size.splitlines(): + #if 'data' in line: + if 'data ' in line: + block_size = int(line.split('=')[2].split()[0]) + block_count = int(line.split('=')[3].split(',')[0]) + break + else: + module.fail_json(msg="Failed to get block count and block size of %s with %s" % (dev, cmd), rc=rc, err=err ) + elif 'btrfs' == fssize_cmd: + #ToDo + # There is no way to get the blocksize and blockcount for btrfs filesystems + block_size = 1 + block_count = 1 + + + return block_size*block_count + + def main(): module = AnsibleModule( argument_spec = dict( @@ -82,36 +126,42 @@ def main(): 'grow' : 'resize2fs', 'grow_flag' : None, 'force_flag' : '-F', + 'fsinfo': 'tune2fs', }, 'ext3' : { 'mkfs' : 'mkfs.ext3', 'grow' : 'resize2fs', 'grow_flag' : None, 'force_flag' : '-F', + 'fsinfo': 'tune2fs', }, 'ext4' : { 'mkfs' : 'mkfs.ext4', 'grow' : 'resize2fs', 'grow_flag' : None, 'force_flag' : '-F', + 'fsinfo': 'tune2fs', }, 'ext4dev' : { 'mkfs' : 'mkfs.ext4', 'grow' : 'resize2fs', 'grow_flag' : None, 'force_flag' : '-F', + 'fsinfo': 'tune2fs', }, 'xfs' : { 'mkfs' : 'mkfs.xfs', 'grow' : 'xfs_growfs', 'grow_flag' : None, 'force_flag' : '-f', + 'fsinfo': 'xfs_info', }, 'btrfs' : { 'mkfs' : 'mkfs.btrfs', 'grow' : 'btrfs', 'grow_flag' : 'filesystem resize', 'force_flag' : '-f', + 'fsinfo': 'btrfs', } } @@ -131,6 +181,7 @@ def main(): mkfscmd = fs_cmd_map[fstype]['mkfs'] force_flag = fs_cmd_map[fstype]['force_flag'] growcmd = fs_cmd_map[fstype]['grow'] + fssize_cmd = fs_cmd_map[fstype]['fsinfo'] if not os.path.exists(dev): module.fail_json(msg="Device %s not found."%dev) @@ -143,10 +194,21 @@ def main(): if fs == fstype and resizefs == False: module.exit_json(changed=False) elif fs == fstype and resizefs == True: - cmd = module.get_bin_path(growcmd, required=True) - if module.check_mode: - module.exit_json(changed=True, msg="May resize filesystem") + # Get dev and fs size and compare + devsize_in_bytes = _get_dev_size(dev, module) + fssize_in_bytes = _get_fs_size(fssize_cmd, dev, module) + if fssize_in_bytes < devsize_in_bytes: + fs_smaller = True else: + fs_smaller = False + + + if module.check_mode and fs_smaller: + module.exit_json(changed=True, msg="Resizing filesystem %s on device %s" % (fstype,dev)) + elif module.check_mode and not fs_smaller: + module.exit_json(changed=False, msg="%s filesystem is using the whole device %s" % (fstype, dev)) + elif fs_smaller: + cmd = module.get_bin_path(growcmd, required=True) rc,out,err = module.run_command("%s %s" % (cmd, dev)) # Sadly there is no easy way to determine if this has changed. For now, just say "true" and move on. # in the future, you would have to parse the output to determine this. @@ -155,6 +217,8 @@ def main(): module.exit_json(changed=True, msg=out) else: module.fail_json(msg="Resizing filesystem %s on device '%s' failed"%(fstype,dev), rc=rc, err=err) + else: + module.exit_json(changed=False, msg="%s filesystem is using the whole device %s" % (fstype, dev)) elif fs and not force: module.fail_json(msg="'%s' is already used as %s, use force=yes to overwrite"%(dev,fs), rc=rc, err=err) @@ -180,4 +244,5 @@ def main(): # import module snippets from ansible.module_utils.basic import * -main() +if __name__ == '__main__': + main()