[virt-tools-list] [virt-bootstrap] [PATCH 4/9] Add flag --use-sandbox

Radostin Stoyanov rstoyanov1 at gmail.com
Fri Jul 28 09:21:42 UTC 2017


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




More information about the virt-tools-list mailing list