added resize function, currently under test
authorPaul Tonelli <paul.tonelli@logilab.fr>
Tue, 05 Mar 2013 18:19:24 +0100
changeset 24 5a66ef9f5377
parent 23 b6572bd0293c
child 25 18936b962551
added resize function, currently under test
_states/tmp_func.py
--- a/_states/tmp_func.py	Tue Mar 05 16:06:30 2013 +0100
+++ b/_states/tmp_func.py	Tue Mar 05 18:19:24 2013 +0100
@@ -1,5 +1,5 @@
 import salt.utils
-import os.path
+import os
 
 def local_managed(name, source):
     '''
@@ -73,27 +73,104 @@
                 ret['comment'] = output
     return ret
 
-def resize_and_check(name, new_size=0):
+def resize(name, new_size=0):
     '''
-    resize partition and filesystem whenever possible (size in Mb)
-    and check the integrity (for ext* fs)
+    Resize partition and filesystem on a file with an ext* fs whenever
+    possible (size in Mb) and check the integrity (for ext* fs)
+
+    implemented checks:
+        - check if file exists
+        - preliminary filesystem check
+        - check if there is enough space available
 
-    CLI Example::
+    ### TODO : this scripts can only be used for files containing fs and
+    not devices ###
+
+    If no size is provided, will shrink the filesystem to the minimal size
 
-        salt '*' vm_create.resize_and_check /mnt raring_image.img 4
-        salt '*' vm_create.resize_and_check /mnt raring_image.img
+    name
+        name of the filesystem to resize
+
+    new_size
+        new size, (can use suffixes like K, M...). If this size is too small,
+        the filesystem will be minimized
     '''
-    current_size = stat(path + '/' + image_name).st_size/pow(1024, 2)
-    if new_size > current_size:
-        log.info('increasing size of ' + path + '/' + image_name + ' to ' + str(new_size) + 'Gb')
-        log.debug(__salt__['cmd.run_all']('dd if=/dev/zero bs=1024k count='
-                + str(new_size - current_size) + ' >> ' + path + '/'
-                + image_name))
-        minimize = ''
+    ret = {'name': name,
+            'changes': {},
+            'result': True,
+            'comment':  ''}
+    block_size = os.statvfs(name).f_frsize
+    new_size = _convert_to_units(new_size)
+    current_size = os.stat(name).st_size / block_size
+    if __opts__['test']:
+        ret['result'] = None
+        ret['comment'] = 'if possible will resize {0} to size {1}'.format(name, new_size)
+        return ret
+    if not os.path.isfile(name):
+        ret['result'] = False
+        ret['comment'] = '{0} is not a file'.format(name, new_size)
+        return ret
+    change_value = new_size - current_size
+    additionnal_flags = ''
+    minimize = ''
+    info = __salt__['cmd.run_all']('e2fsck -n -f ' + name)
+    if info['retcode']:
+        ret['result'] = False
+        ret['comment'] = 'Error while checking fs {0}: {1}'.format(name, info['stderr'])
+        return ret
+    minimum_size = int(__salt__['cmd.run_all']('resize2fs -P -f ' + name)['stdout'].split(':')[-1])
+    if new_size == current_size or minimum_size == current_size:
+        ret['result'] = True
+        ret['comment'] = 'Filesystem {0} is already at the correct/smaller size'.format(name)
+        return ret
+    if new_size > current_size: #increase size
+        if not _has_enough_free_space(name, change_value):
+            ret['result'] = False
+            ret['comment'] = 'Not enough free space'
+            return ret
+        log.info('increasing size of ' + name + ' to ' + str(new_size) + 'Gb')
+        info = __salt__['cmd.run_all']('dd if=/dev/zero bs=1024k count='
+                + str(increase_value/pow(1024,2)) + ' >> ' + name)
+        if info['retcode']:
+            ret['result'] = False
+            ret['comment'] = 'Error while adding space to {0}: {1}'.format(name, info['stderr'])
+            return ret
     else:
-        minimize = '-M '
-    log.info(__salt__['cmd.run_all']('e2fsck -n -f ' + path + '/' + image_name))
-    log.info(__salt__['cmd.run_all']('resize2fs -f ' + minimize + path + '/'
-            + image_name))
+        if minimum_size < change_value: #decrease size to what asked
+            additionnal_flags = ' ' + str(new_size)
+        else: #minimise to min possible
+            minimize = '-M '
+    info = __salt__['cmd.run_all']('resize2fs -f ' + minimize + name + additionnal_flags)
+    if info['retcode']:
+        ret['result'] = False
+        ret['comment'] = 'Error while resizing {0}: {1}'.format(name, info['stderr'])
+        return ret
+    ret['changes']['resized'] = True
+    ret['comment'] = 'Resized filesystem {0} from {1} to {2}'.format(name, str(current_size), str(max(new_size,minimum_size)))
+    return ret
 
+def _has_enough_free_space(fs, space):
+    info = os.statvfs(fs)
+    free_space = (info.f_bavail * info.f_frsize)
+    if free_space > space:
+        return True
+    return False
 
+def _convert_to_units(value):
+    '''
+    convert value to a float in the correct unit. Accepted units are:
+        - K (kilobytes)
+        - M (megabytes)
+        - G (gigabytes)
+        - T (terabytes)
+    '''
+    conversion_factor={'K': 1, 'M': 2, 'G': 3, 'T': 4}
+    if str(value)[-1].isalpha():
+        assert str(value)[-1] in conversion_factor
+        factor = conversion_factor[str(value)[-1]]
+        value = str(value)[:-1]
+    else:
+        factor = 0
+    value=float(value)
+    return int(value * pow(1024,factor))
+