Source code for COT.helpers.vmdktool
#!/usr/bin/env python
#
# vmdktool.py - Helper for 'vmdktool'
#
# February 2015, Glenn F. Matthews
# Copyright (c) 2013-2015 the COT project developers.
# See the COPYRIGHT.txt file at the top-level directory of this distribution
# and at https://github.com/glennmatthews/cot/blob/master/COPYRIGHT.txt.
#
# This file is part of the Common OVF Tool (COT) project.
# It is subject to the license terms in the LICENSE.txt file found in the
# top-level directory of this distribution and at
# https://github.com/glennmatthews/cot/blob/master/LICENSE.txt. No part
# of COT, including this file, may be copied, modified, propagated, or
# distributed except according to the terms contained in the LICENSE.txt file.
"""Give COT access to ``vmdktool`` for manipulating compressed VMDK files.
http://www.freshports.org/sysutils/vmdktool/
"""
import logging
import os.path
import platform
from .helper import Helper
logger = logging.getLogger(__name__)
[docs]class VmdkTool(Helper):
"""Helper provider for ``vmdktool``.
http://www.freshports.org/sysutils/vmdktool/
**Methods**
.. autosummary::
:nosignatures:
install_helper
convert_disk_image
"""
def __init__(self):
"""Initializer."""
super(VmdkTool, self).__init__(
"vmdktool",
version_args=['-V'],
version_regexp="vmdktool version ([0-9.]+)")
[docs] def install_helper(self):
"""Install ``vmdktool``."""
if self.path:
logger.warning("Tried to install {0} -- "
"but it's already available at {1}!"
.format(self.name, self.path))
return
logger.info("Installing 'vmdktool'...")
if Helper.port_install('vmdktool'):
pass
elif platform.system() == 'Linux':
# We don't have vmdktool in apt or yum yet,
# but we can build it manually:
# vmdktool requires make and zlib
if not self.find_executable('make'):
logger.info("vmdktool requires 'make'... installing 'make'")
if not (Helper.apt_install('make') or
Helper.yum_install('make')):
raise NotImplementedError("Not sure how to install 'make'")
logger.info("vmdktool requires 'zlib'... installing 'zlib'")
if not (Helper.apt_install('zlib1g-dev') or
Helper.yum_install('zlib-devel')):
raise NotImplementedError("Not sure how to install 'zlib'")
with self.download_and_expand('http://people.freebsd.org/~brian/'
'vmdktool/vmdktool-1.4.tar.gz') as d:
new_d = os.path.join(d, "vmdktool-1.4")
logger.info("Compiling 'vmdktool'")
# vmdktool is originally a BSD tool so it has some build
# assumptions that aren't necessarily correct under Linux.
# The easiest workaround is to override the CFLAGS to:
# 1) add -D_GNU_SOURCE
# 2) not treat all warnings as errors
self._check_call(['make',
'CFLAGS="-D_GNU_SOURCE -g -O -pipe"'],
cwd=new_d)
logger.info("Compilation complete, installing now.")
# Make sure the relevant man directory exists
self._check_call(['sudo', 'mkdir', '-p', '--mode=755',
'/usr/local/man/man8'])
self._check_call(['sudo', 'make', 'install'],
cwd=new_d)
else:
raise NotImplementedError(
"Unsure how to install vmdktool.\n"
"See http://www.freshports.org/sysutils/vmdktool/")
logger.info("Successfully installed 'vmdktool'")
[docs] def convert_disk_image(self, file_path, output_dir,
new_format, new_subformat=None):
"""Convert the given disk image to the requested format/subformat.
If the disk is already in this format then it is unchanged;
otherwise, will convert to a new disk in the specified output_dir
and return its path.
Current supported conversions:
* .vmdk (any format) to .vmdk (streamOptimized)
* .img to .vmdk (streamOptimized)
:param str file_path: Disk image file to inspect/convert
:param str output_dir: Directory to place converted image into, if
needed
:param str new_format: Desired final format
:param str new_subformat: Desired final subformat
:return:
* :attr:`file_path`, if no conversion was required
* or a file path in :attr:`output_dir` containing the converted image
:raise NotImplementedError: if the :attr:`new_format` and/or
:attr:`new_subformat` are not supported conversion targets.
"""
file_name = os.path.basename(file_path)
(file_string, file_extension) = os.path.splitext(file_name)
new_file_path = None
if new_format == 'vmdk' and new_subformat == 'streamOptimized':
new_file_path = os.path.join(output_dir, file_string + '.vmdk')
logger.info("Invoking vmdktool to convert {0} to "
"stream-optimized VMDK {1}"
.format(file_path, new_file_path))
# Note that vmdktool takes its arguments in unusual order -
# output file comes before input file
self.call_helper(['-z9', '-v', new_file_path, file_path])
else:
raise NotImplementedError("No support for converting disk image "
"to format {0} / subformat {1}"
.format(new_format, new_subformat))
return new_file_path