minimize_size: New option for qemu-img-based shrinking

This commit is contained in:
Tomasz Melcer 2017-07-09 23:34:58 +02:00
parent 6a96a2b5b1
commit 75e0ce86f0
4 changed files with 70 additions and 16 deletions

View file

@ -15,17 +15,21 @@ footprint:
deallocate unused sectors on the volume. On an unpartitioned volume deallocate unused sectors on the volume. On an unpartitioned volume
this will be done for the entire volume, while it will only happen on this will be done for the entire volume, while it will only happen on
the root partition for partitioned volumes. the root partition for partitioned volumes.
- Use - Shrink the real volume size. Supported tools are:
`vmware-vdiskmanager <https://www.vmware.com/support/ws45/doc/disks_vdiskmanager_eg_ws.html>`__
to shrink the real volume size (only applicable when using vmdk - `vmware-vdiskmanager <https://www.vmware.com/support/ws45/doc/disks_vdiskmanager_eg_ws.html>`__
backing). The tool is part of the `VMWare (only applicable when using vmdk backing). The tool is part of the
Workstation <https://my.vmware.com/web/vmware/info/slug/desktop_end_user_computing/vmware_workstation/10_0>`__ `VMWare Workstation <https://my.vmware.com/web/vmware/info/slug/desktop_end_user_computing/vmware_workstation/10_0>`__
package. package.
- `qemu-img` (only applicaple when using vmdk or vdi backing). This
tool is part of the `QEMU emulator <https://www.qemu.org/>`__.
- Tell apt to only download specific language files. See the - Tell apt to only download specific language files. See the
`apt.conf manpage <http://manpages.debian.org/cgi-bin/man.cgi?query=apt.conf>`__ `apt.conf manpage <http://manpages.debian.org/cgi-bin/man.cgi?query=apt.conf>`__
for more details ("Languages" in the "Acquire group" section). for more details ("Languages" in the "Acquire group" section).
- Configure debootstrap and dpkg to filter out specific paths when installing packages - Configure debootstrap and dpkg to filter out specific paths when installing packages
Settings Settings
~~~~~~~~ ~~~~~~~~
@ -35,8 +39,13 @@ Settings
Default: false Default: false
``optional`` ``optional``
- ``shrink``: Whether the volume should be shrunk. This setting works - ``shrink``: Whether the volume should be shrunk. This setting works
best in conjunction with the zerofree tool. best in conjunction with the zerofree tool. Valid values:
Valid values: true, false
- false: Do not shrink.
- ``vmware-vdiskmanager`` or true: Shrink using the `vmware-vdiskmanager`
utility.
- ``qemu-img``: Shrink using the `qemu-img` utility.
Default: false Default: false
``optional`` ``optional``
- ``apt``: Apt specific configurations. ``optional`` - ``apt``: Apt specific configurations. ``optional``

View file

@ -5,12 +5,29 @@ import tasks.dpkg
from bootstrapvz.common.tasks import locale from bootstrapvz.common.tasks import locale
def get_shrink_type(plugins):
"""Gets the type of shrinking process requested by the user, taking into account backward compatibility
values
:param dict plugins: the part of the manifest related to plugins
:return: None (if none selected), "vmware-vdiskmanager" or "qemu-img" (tool to be used)"""
shrink_type = plugins['minimize_size'].get('shrink')
if shrink_type is True:
shrink_type = 'vmware-vdiskmanager'
elif shrink_type is False:
shrink_type = None
return shrink_type
def validate_manifest(data, validator, error): def validate_manifest(data, validator, error):
from bootstrapvz.common.tools import rel_path from bootstrapvz.common.tools import rel_path
validator(data, rel_path(__file__, 'manifest-schema.yml')) validator(data, rel_path(__file__, 'manifest-schema.yml'))
if data['plugins']['minimize_size'].get('shrink', False) and data['volume']['backing'] != 'vmdk': shrink_type = get_shrink_type(data['plugins'])
error('Can only shrink vmdk images', ['plugins', 'minimize_size', 'shrink']) if shrink_type == 'vmware-vdiskmanager' and data['volume']['backing'] != 'vmdk':
error('Can only shrink vmdk images with vmware-vdiskmanager', ['plugins', 'minimize_size', 'shrink'])
if shrink_type == 'qemu-img' and data['volume']['backing'] not in ('vmdk', 'vdi'):
error('Can only shrink vmdk and vdi images with qemu-img', ['plugins', 'minimize_size', 'shrink'])
def resolve_tasks(taskset, manifest): def resolve_tasks(taskset, manifest):
@ -20,9 +37,12 @@ def resolve_tasks(taskset, manifest):
if manifest.plugins['minimize_size'].get('zerofree', False): if manifest.plugins['minimize_size'].get('zerofree', False):
taskset.add(tasks.shrink.AddRequiredZeroFreeCommand) taskset.add(tasks.shrink.AddRequiredZeroFreeCommand)
taskset.add(tasks.shrink.Zerofree) taskset.add(tasks.shrink.Zerofree)
if manifest.plugins['minimize_size'].get('shrink', False): if get_shrink_type(manifest.plugins) == 'vmware-vdiskmanager':
taskset.add(tasks.shrink.AddRequiredVDiskManagerCommand) taskset.add(tasks.shrink.AddRequiredVDiskManagerCommand)
taskset.add(tasks.shrink.ShrinkVolume) taskset.add(tasks.shrink.ShrinkVolumeWithVDiskManager)
if get_shrink_type(manifest.plugins) == 'qemu-img':
taskset.add(tasks.shrink.AddRequiredQemuImgCommand)
taskset.add(tasks.shrink.ShrinkVolumeWithQemuImg)
if 'apt' in manifest.plugins['minimize_size']: if 'apt' in manifest.plugins['minimize_size']:
apt = manifest.plugins['minimize_size']['apt'] apt = manifest.plugins['minimize_size']['apt']
if apt.get('autoclean', False): if apt.get('autoclean', False):

View file

@ -6,7 +6,9 @@ properties:
minimize_size: minimize_size:
properties: properties:
shrink: shrink:
type: boolean anyOf:
- type: boolean
- enum: [vmware-vdiskmanager, qemu-img]
zerofree: zerofree:
type: boolean type: boolean
apt: apt:

View file

@ -19,7 +19,7 @@ class AddRequiredZeroFreeCommand(Task):
class AddRequiredVDiskManagerCommand(Task): class AddRequiredVDiskManagerCommand(Task):
description = 'Adding command required for reducing volume size' description = 'Adding vmware-vdiskmanager command required for reducing volume size'
phase = phases.validation phase = phases.validation
successors = [host.CheckExternalCommands] successors = [host.CheckExternalCommands]
@ -29,6 +29,16 @@ class AddRequiredVDiskManagerCommand(Task):
info.host_dependencies['vmware-vdiskmanager'] = link info.host_dependencies['vmware-vdiskmanager'] = link
class AddRequiredQemuImgCommand(Task):
description = 'Adding qemu-img command required for reducing volume size'
phase = phases.validation
successors = [host.CheckExternalCommands]
@classmethod
def run(cls, info):
info.host_dependencies['qemu-img'] = 'qemu-img'
class Zerofree(Task): class Zerofree(Task):
description = 'Zeroing unused blocks on the root partition' description = 'Zeroing unused blocks on the root partition'
phase = phases.volume_unmounting phase = phases.volume_unmounting
@ -40,8 +50,8 @@ class Zerofree(Task):
log_check_call(['zerofree', info.volume.partition_map.root.device_path]) log_check_call(['zerofree', info.volume.partition_map.root.device_path])
class ShrinkVolume(Task): class ShrinkVolumeWithVDiskManager(Task):
description = 'Shrinking the volume' description = 'Shrinking the volume with vmware-vdiskmanager'
phase = phases.volume_unmounting phase = phases.volume_unmounting
predecessors = [volume.Detach] predecessors = [volume.Detach]
@ -50,3 +60,16 @@ class ShrinkVolume(Task):
perm = os.stat(info.volume.image_path).st_mode & 0777 perm = os.stat(info.volume.image_path).st_mode & 0777
log_check_call(['/usr/bin/vmware-vdiskmanager', '-k', info.volume.image_path]) log_check_call(['/usr/bin/vmware-vdiskmanager', '-k', info.volume.image_path])
os.chmod(info.volume.image_path, perm) os.chmod(info.volume.image_path, perm)
class ShrinkVolumeWithQemuImg(Task):
description = 'Shrinking the volume with qemu-img'
phase = phases.volume_unmounting
predecessors = [volume.Detach]
@classmethod
def run(cls, info):
tmp_name = os.path.join(info.workspace, 'shrinked.' + info.volume.extension)
log_check_call(
['qemu-img', 'convert', '-O', info.volume.extension, info.volume.image_path, tmp_name])
os.rename(tmp_name, info.volume.image_path)