Add flag --use-sandbox which indicates wheter the extraction of container root file system to be performed within VM/Container using virt-sandbox or not. If virt-sandbox is not installed this flag is ignored. --- src/virtBootstrap/sources.py | 9 +++++++-- src/virtBootstrap/utils.py | 40 ++++++++++++++++++++++++++++--------- src/virtBootstrap/virt_bootstrap.py | 12 ++++++++--- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/virtBootstrap/sources.py b/src/virtBootstrap/sources.py index f4bae72..673e68c 100644 --- a/src/virtBootstrap/sources.py +++ b/src/virtBootstrap/sources.py @@ -45,10 +45,12 @@ class FileSource(object): @param uri: Path to tar archive file. @param fmt: Format used to store image [dir, qcow2] + @param use_sandbox: Run the untar within VM/container @param progress: Instance of the progress module """ self.path = kwargs['uri'].path self.output_format = kwargs.get('fmt', utils.DEFAULT_OUTPUT_FORMAT) + self.use_sandbox = kwargs.get('use_sandbox', False) self.progress = kwargs['progress'].update_progress def unpack(self, dest): @@ -64,7 +66,7 @@ class FileSource(object): if self.output_format == 'dir': self.progress("Extracting files into destination directory", value=0, logger=logger) - utils.safe_untar(self.path, dest) + utils.untar(self.path, dest, self.use_sandbox) elif self.output_format == 'qcow2': # Remove the old path @@ -98,6 +100,7 @@ class DockerSource(object): @param password: Password to access source registry @param fmt: Format used to store image [dir, qcow2] @param not_secure: Do not require HTTPS and certificate verification + @param use_sandbox: Run the untar within VM/container @param no_cache: Whether to store downloaded images or not @param progress: Instance of the progress module """ @@ -108,6 +111,7 @@ class DockerSource(object): self.output_format = kwargs.get('fmt', utils.DEFAULT_OUTPUT_FORMAT) self.insecure = kwargs.get('not_secure', False) self.no_cache = kwargs.get('no_cache', False) + self.use_sandbox = kwargs.get('use_sandbox', False) self.progress = kwargs['progress'].update_progress self.images_dir = utils.get_image_dir(self.no_cache) self.manifest = None @@ -303,7 +307,8 @@ class DockerSource(object): if self.output_format == 'dir': self.progress("Extracting container layers", value=50, logger=logger) - utils.untar_layers(self.layers, dest, self.progress) + utils.untar_layers(self.layers, dest, self.progress, + self.use_sandbox) elif self.output_format == 'qcow2': self.progress("Extracting container layers into qcow2 images", value=50, logger=logger) diff --git a/src/virtBootstrap/utils.py b/src/virtBootstrap/utils.py index dbe4677..aadc393 100644 --- a/src/virtBootstrap/utils.py +++ b/src/virtBootstrap/utils.py @@ -33,6 +33,7 @@ import logging import re from subprocess import CalledProcessError, PIPE, Popen +import distutils.spawn import passlib.hosts # pylint: disable=invalid-name @@ -92,18 +93,30 @@ def execute(cmd): raise CalledProcessError(proc.returncode, cmd_str) -def safe_untar(src, dest): +def untar(src, dest, use_sandbox=False): """ - Extract tarball within LXC container for safety. + Extract tarball to destination path. + + @param use_sandbox: If True run tar command in VM or LXC container + using virt-sandbox. """ - virt_sandbox = ['virt-sandbox', - '-c', LIBVIRT_CONN, - '-m', 'host-bind:/mnt=' + dest] # Bind destination folder # Compression type is auto detected from tar # Exclude files under /dev to avoid "Cannot mknod: Operation not permitted" - params = ['--', '/bin/tar', 'xf', src, '-C', '/mnt', '--exclude', 'dev/*'] - execute(virt_sandbox + params) + cmd = ['/bin/tar', + 'xf', src, + '-C', '/mnt' if use_sandbox else dest, + '--exclude', 'dev/*'] + + if use_sandbox: + cmd = ['virt-sandbox', + # Set connection + '-c', LIBVIRT_CONN, + # Bind destination folder + '-m', 'host-bind:/mnt=' + dest, + '--'] + cmd + + execute(cmd) def bytes_to_size(number): @@ -150,17 +163,26 @@ def log_layer_extract(layer, current, total, progress): logger.debug('Untar layer: (%s:%s) %s', sum_type, sum_value, layer_file) -def untar_layers(layers_list, dest_dir, progress): +def is_installed(program): + """ + Return True/False is executable is found the in the PATH env variable + """ + return bool(distutils.spawn.find_executable(program)) + + +def untar_layers(layers_list, dest_dir, progress, use_sandbox=False): """ Untar each of layers from container image. """ nlayers = len(layers_list) + use_sandbox = use_sandbox and is_installed('virt-sandbox') + for index, layer in enumerate(layers_list): log_layer_extract(layer, index + 1, nlayers, progress) layer_file = layer[2] # Extract layer tarball into destination directory - safe_untar(layer_file, dest_dir) + untar(layer_file, dest_dir, use_sandbox) # Update progress value progress(value=(float(index + 1) / nlayers * 50) + 50) diff --git a/src/virtBootstrap/virt_bootstrap.py b/src/virtBootstrap/virt_bootstrap.py index ddc5456..029cee2 100755 --- a/src/virtBootstrap/virt_bootstrap.py +++ b/src/virtBootstrap/virt_bootstrap.py @@ -173,7 +173,8 @@ def bootstrap(uri, dest, gid_map=None, not_secure=False, no_cache=False, - progress_cb=None): + progress_cb=None, + use_sandbox=None): """ Get source object and call unpack method """ @@ -198,7 +199,8 @@ def bootstrap(uri, dest, password=password, not_secure=not_secure, no_cache=no_cache, - progress=prog).unpack(dest) + progress=prog, + use_sandbox=use_sandbox).unpack(dest) if root_password is not None: logger.info("Setting password of the root account") @@ -278,6 +280,9 @@ def main(): parser.add_argument("--status-only", action="store_const", const=utils.write_progress, help=_("Show only progress information")) + parser.add_argument("--use-sandbox", action="store_true", + help=_("Run the untar command within VM/container " + "for extra security (requires virt-sandbox)")) try: args = parser.parse_args() @@ -304,7 +309,8 @@ def main(): gid_map=gid_map, not_secure=args.not_secure, no_cache=args.no_cache, - progress_cb=args.status_only) + progress_cb=args.status_only, + use_sandbox=args.use_sandbox) sys.exit(0) except KeyboardInterrupt: -- 2.9.4 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list