iso-wrapper: Add utility for mounting images
This patch refactors logic for creating a temporary mount point, mounting an image, running arbitrary code on it, unmounting the image and removing the mount point. It immediately uses it in the buildinstall phase. Similar mounting is present in product_img phase as well, but due to different usage pattern it's not changed yet. Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
This commit is contained in:
parent
05a666fb3b
commit
306f7e69b0
@ -27,7 +27,7 @@ from productmd.images import Image
|
||||
|
||||
from pungi.arch import get_valid_arches
|
||||
from pungi.util import get_buildroot_rpms, get_volid, get_arch_variant_data
|
||||
from pungi.util import get_file_size, get_mtime, failable, makedirs, fusermount
|
||||
from pungi.util import get_file_size, get_mtime, failable, makedirs
|
||||
from pungi.wrappers.lorax import LoraxWrapper
|
||||
from pungi.wrappers.kojiwrapper import KojiWrapper
|
||||
from pungi.wrappers import iso
|
||||
@ -267,22 +267,15 @@ def tweak_buildinstall(compose, src, dst, arch, variant, label, volid, kickstart
|
||||
for image in images:
|
||||
if not os.path.isfile(image):
|
||||
continue
|
||||
mount_tmp_dir = compose.mkdtemp(prefix="tweak_buildinstall")
|
||||
# use guestmount to mount the image, which doesn't require root privileges
|
||||
# LIBGUESTFS_BACKEND=direct: running qemu directly without libvirt
|
||||
cmd = ["LIBGUESTFS_BACKEND=direct", "guestmount", "-a", image, "-m", "/dev/sda", mount_tmp_dir]
|
||||
run(cmd)
|
||||
|
||||
for config in BOOT_CONFIGS:
|
||||
config_path = os.path.join(tmp_dir, config)
|
||||
config_in_image = os.path.join(mount_tmp_dir, config)
|
||||
with iso.mount(image, logger=compose._logger) as mount_tmp_dir:
|
||||
for config in BOOT_CONFIGS:
|
||||
config_path = os.path.join(tmp_dir, config)
|
||||
config_in_image = os.path.join(mount_tmp_dir, config)
|
||||
|
||||
if os.path.isfile(config_in_image):
|
||||
cmd = ["cp", "-v", "--remove-destination", config_path, config_in_image]
|
||||
run(cmd)
|
||||
|
||||
fusermount(mount_tmp_dir)
|
||||
shutil.rmtree(mount_tmp_dir)
|
||||
if os.path.isfile(config_in_image):
|
||||
cmd = ["cp", "-v", "--remove-destination", config_path, config_in_image]
|
||||
run(cmd)
|
||||
|
||||
# HACK: make buildinstall files world readable
|
||||
run("chmod -R a+rX %s" % pipes.quote(tmp_dir))
|
||||
|
@ -18,8 +18,10 @@ import os
|
||||
import sys
|
||||
import pipes
|
||||
from fnmatch import fnmatch
|
||||
import contextlib
|
||||
|
||||
from kobo.shortcuts import force_list, relative_path, run
|
||||
from pungi import util
|
||||
|
||||
|
||||
# HACK: define cmp in python3
|
||||
@ -392,3 +394,20 @@ def cmp_graft_points(x, y):
|
||||
return 1
|
||||
|
||||
return cmp(x, y)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def mount(image, logger=None):
|
||||
"""Mount an image and make sure it's unmounted.
|
||||
|
||||
The yielded path will only be valid in the with block and is removed once
|
||||
the image is unmounted.
|
||||
"""
|
||||
# use guestmount to mount the image, which doesn't require root privileges
|
||||
# LIBGUESTFS_BACKEND=direct: running qemu directly without libvirt
|
||||
with util.temp_dir(prefix='iso-mount-') as mount_dir:
|
||||
run(["LIBGUESTFS_BACKEND=direct", "guestmount", "-a", image, "-m", "/dev/sda", mount_dir])
|
||||
try:
|
||||
yield mount_dir
|
||||
finally:
|
||||
util.fusermount(mount_dir, logger=logger)
|
||||
|
@ -37,3 +37,25 @@ class TestIsoUtils(unittest.TestCase):
|
||||
self.assertEqual(mock_run.call_args_list,
|
||||
[mock.call(['/usr/bin/checkisomd5', '--md5sumonly', 'dummy.iso'])])
|
||||
self.assertGreater(len(logger.mock_calls), 0)
|
||||
|
||||
@mock.patch('pungi.util.run_unmount_cmd')
|
||||
@mock.patch('pungi.wrappers.iso.run')
|
||||
def test_mount_iso(self, mock_run, mock_unmount):
|
||||
with iso.mount('dummy') as temp_dir:
|
||||
self.assertTrue(os.path.isdir(temp_dir))
|
||||
self.assertEqual(len(mock_run.call_args_list), 1)
|
||||
self.assertEqual(len(mock_unmount.call_args_list), 1)
|
||||
self.assertFalse(os.path.isdir(temp_dir))
|
||||
|
||||
@mock.patch('pungi.util.run_unmount_cmd')
|
||||
@mock.patch('pungi.wrappers.iso.run')
|
||||
def test_mount_iso_always_unmounts(self, mock_run, mock_unmount):
|
||||
try:
|
||||
with iso.mount('dummy') as temp_dir:
|
||||
self.assertTrue(os.path.isdir(temp_dir))
|
||||
raise RuntimeError()
|
||||
except RuntimeError:
|
||||
pass
|
||||
self.assertEqual(len(mock_run.call_args_list), 1)
|
||||
self.assertEqual(len(mock_unmount.call_args_list), 1)
|
||||
self.assertFalse(os.path.isdir(temp_dir))
|
||||
|
Loading…
Reference in New Issue
Block a user