diff options
Diffstat (limited to 'ironic')
-rw-r--r-- | ironic/common/images.py | 45 | ||||
-rw-r--r-- | ironic/tests/unit/common/test_images.py | 93 |
2 files changed, 71 insertions, 67 deletions
diff --git a/ironic/common/images.py b/ironic/common/images.py index 9f771ca29..8652ba1fb 100644 --- a/ironic/common/images.py +++ b/ironic/common/images.py @@ -27,6 +27,7 @@ from ironic_lib import disk_utils from oslo_concurrency import processutils from oslo_log import log as logging from oslo_utils import fileutils +import pycdlib from ironic.common import exception from ironic.common.glance_service import service_utils as glance_utils @@ -72,14 +73,6 @@ def _create_root_fs(root_directory, files_info): shutil.copyfile(src_file, target_file) -def _umount_without_raise(mount_dir): - """Helper method to umount without raise.""" - try: - utils.umount(mount_dir) - except processutils.ProcessExecutionError: - pass - - def create_vfat_image(output_file, files_info=None, parameters=None, parameters_file='parameters.txt', fs_size_kib=100): """Creates the fat fs image on the desired file. @@ -299,7 +292,7 @@ def create_esp_image_for_uefi( # directory. if deploy_iso and not esp_image: uefi_path_info, e_img_rel_path, grub_rel_path = ( - _mount_deploy_iso(deploy_iso, mountdir)) + _get_deploy_iso_files(deploy_iso, mountdir)) grub_cfg = os.path.join(tmpdir, grub_rel_path) @@ -336,7 +329,7 @@ def create_esp_image_for_uefi( finally: if deploy_iso: - _umount_without_raise(mountdir) + shutil.rmtree(mountdir) # Generate and copy grub config file. grub_conf = _generate_cfg(kernel_params, @@ -622,7 +615,27 @@ def is_whole_disk_image(ctx, instance_info): return is_whole_disk_image -def _mount_deploy_iso(deploy_iso, mountdir): +def _extract_iso(extract_iso, extract_dir): + # NOTE(rpittau): we could probably just extract the files we need + # if we find them. Also we probably need to detect the correct iso + # type (UDF, RR, JOLIET). + iso = pycdlib.PyCdlib() + iso.open(extract_iso) + + for dirname, dirlist, filelist in iso.walk(iso_path='/'): + dir_path = dirname.lstrip('/') + for dir_iso in dirlist: + os.makedirs(os.path.join(extract_dir, dir_path, dir_iso)) + for file in filelist: + file_path = os.path.join(extract_dir, dirname, file) + iso.get_file_from_iso( + os.path.join(extract_dir, dir_path, file), + iso_path=file_path) + + iso.close() + + +def _get_deploy_iso_files(deploy_iso, mountdir): """This function opens up the deploy iso used for deploy. :param deploy_iso: path to the deploy iso where its @@ -641,9 +654,9 @@ def _mount_deploy_iso(deploy_iso, mountdir): grub_path = None try: - utils.mount(deploy_iso, mountdir, '-o', 'loop') - except processutils.ProcessExecutionError as e: - LOG.exception("mounting the deploy iso failed.") + _extract_iso(deploy_iso, mountdir) + except Exception as e: + LOG.exception("extracting the deploy iso failed.") raise exception.ImageCreationFailed(image_type='iso', error=e) try: @@ -658,14 +671,14 @@ def _mount_deploy_iso(deploy_iso, mountdir): mountdir) except (OSError, IOError) as e: LOG.exception("examining the deploy iso failed.") - _umount_without_raise(mountdir) + shutil.rmtree(mountdir) raise exception.ImageCreationFailed(image_type='iso', error=e) # check if the variables are assigned some values or not during # walk of the mountdir. if not (e_img_path and e_img_rel_path and grub_path and grub_rel_path): error = (_("Deploy iso didn't contain efiboot.img or grub.cfg")) - _umount_without_raise(mountdir) + shutil.rmtree(mountdir) raise exception.ImageCreationFailed(image_type='iso', error=error) uefi_path_info = {e_img_path: e_img_rel_path, diff --git a/ironic/tests/unit/common/test_images.py b/ironic/tests/unit/common/test_images.py index fe6b67ad3..e705373f2 100644 --- a/ironic/tests/unit/common/test_images.py +++ b/ironic/tests/unit/common/test_images.py @@ -374,13 +374,6 @@ class FsImageTestCase(base.TestCase): self.assertRaises(exception.ImageCreationFailed, images.create_vfat_image, 'tgt_file') - @mock.patch.object(utils, 'umount', autospec=True) - def test__umount_without_raise(self, umount_mock): - - umount_mock.side_effect = processutils.ProcessExecutionError - images._umount_without_raise('mountdir') - umount_mock.assert_called_once_with('mountdir') - def test__generate_isolinux_cfg(self): kernel_params = ['key1=value1', 'key2'] @@ -414,9 +407,9 @@ class FsImageTestCase(base.TestCase): @mock.patch.object(os.path, 'relpath', autospec=True) @mock.patch.object(os, 'walk', autospec=True) - @mock.patch.object(utils, 'mount', autospec=True) - def test__mount_deploy_iso(self, mount_mock, - walk_mock, relpath_mock): + @mock.patch.object(images, '_extract_iso', autospec=True) + def test__get_deploy_iso_files(self, extract_mock, + walk_mock, relpath_mock): walk_mock.return_value = [('/tmpdir1/EFI/ubuntu', [], ['grub.cfg']), ('/tmpdir1/isolinux', [], ['efiboot.img', 'isolinux.bin', @@ -424,38 +417,34 @@ class FsImageTestCase(base.TestCase): relpath_mock.side_effect = ['EFI/ubuntu/grub.cfg', 'isolinux/efiboot.img'] - images._mount_deploy_iso('path/to/deployiso', 'tmpdir1') - mount_mock.assert_called_once_with('path/to/deployiso', - 'tmpdir1', '-o', 'loop') + images._get_deploy_iso_files('path/to/deployiso', 'tmpdir1') + extract_mock.assert_called_once_with('path/to/deployiso', 'tmpdir1') walk_mock.assert_called_once_with('tmpdir1') - @mock.patch.object(images, '_umount_without_raise', autospec=True) + @mock.patch.object(shutil, 'rmtree', autospec=True) @mock.patch.object(os.path, 'relpath', autospec=True) @mock.patch.object(os, 'walk', autospec=True) - @mock.patch.object(utils, 'mount', autospec=True) - def test__mount_deploy_iso_fail_no_esp_imageimg(self, mount_mock, - walk_mock, relpath_mock, - umount_mock): + @mock.patch.object(images, '_extract_iso', autospec=True) + def test__get_deploy_iso_files_fail_no_esp_imageimg( + self, extract_mock, walk_mock, relpath_mock, rmtree_mock): walk_mock.return_value = [('/tmpdir1/EFI/ubuntu', [], ['grub.cfg']), ('/tmpdir1/isolinux', [], ['isolinux.bin', 'isolinux.cfg'])] relpath_mock.side_effect = 'EFI/ubuntu/grub.cfg' self.assertRaises(exception.ImageCreationFailed, - images._mount_deploy_iso, + images._get_deploy_iso_files, 'path/to/deployiso', 'tmpdir1') - mount_mock.assert_called_once_with('path/to/deployiso', - 'tmpdir1', '-o', 'loop') + extract_mock.assert_called_once_with('path/to/deployiso', 'tmpdir1') walk_mock.assert_called_once_with('tmpdir1') - umount_mock.assert_called_once_with('tmpdir1') + rmtree_mock.assert_called_once_with('tmpdir1') - @mock.patch.object(images, '_umount_without_raise', autospec=True) + @mock.patch.object(shutil, 'rmtree', autospec=True) @mock.patch.object(os.path, 'relpath', autospec=True) @mock.patch.object(os, 'walk', autospec=True) - @mock.patch.object(utils, 'mount', autospec=True) - def test__mount_deploy_iso_fails_no_grub_cfg(self, mount_mock, - walk_mock, relpath_mock, - umount_mock): + @mock.patch.object(images, '_extract_iso', autospec=True) + def test__get_deploy_iso_files_fails_no_grub_cfg( + self, extract_mock, walk_mock, relpath_mock, rmtree_mock): walk_mock.return_value = [('/tmpdir1/EFI/ubuntu', '', []), ('/tmpdir1/isolinux', '', ['efiboot.img', 'isolinux.bin', @@ -463,30 +452,30 @@ class FsImageTestCase(base.TestCase): relpath_mock.side_effect = 'isolinux/efiboot.img' self.assertRaises(exception.ImageCreationFailed, - images._mount_deploy_iso, + images._get_deploy_iso_files, 'path/to/deployiso', 'tmpdir1') - mount_mock.assert_called_once_with('path/to/deployiso', - 'tmpdir1', '-o', 'loop') + extract_mock.assert_called_once_with('path/to/deployiso', 'tmpdir1') walk_mock.assert_called_once_with('tmpdir1') - umount_mock.assert_called_once_with('tmpdir1') + rmtree_mock.assert_called_once_with('tmpdir1') @mock.patch.object(utils, 'mount', autospec=True) - def test__mount_deploy_iso_fail_with_ExecutionError(self, mount_mock): - mount_mock.side_effect = processutils.ProcessExecutionError + def test__get_deploy_iso_files_fail_with_ExecutionError( + self, get_iso_files_mock): + get_iso_files_mock.side_effect = processutils.ProcessExecutionError self.assertRaises(exception.ImageCreationFailed, - images._mount_deploy_iso, + images._get_deploy_iso_files, 'path/to/deployiso', 'tmpdir1') - @mock.patch.object(images, '_umount_without_raise', autospec=True) + @mock.patch.object(shutil, 'rmtree', autospec=True) @mock.patch.object(images, '_create_root_fs', autospec=True) @mock.patch.object(utils, 'write_to_file', autospec=True) @mock.patch.object(utils, 'execute', autospec=True) - @mock.patch.object(images, '_mount_deploy_iso', autospec=True) + @mock.patch.object(images, '_get_deploy_iso_files', autospec=True) @mock.patch.object(utils, 'tempdir', autospec=True) @mock.patch.object(images, '_generate_cfg', autospec=True) def test_create_esp_image_for_uefi_with_deploy_iso( - self, gen_cfg_mock, tempdir_mock, mount_mock, execute_mock, - write_to_file_mock, create_root_fs_mock, umount_mock): + self, gen_cfg_mock, tempdir_mock, get_iso_files_mock, execute_mock, + write_to_file_mock, create_root_fs_mock, rmtree_mock): files_info = { 'path/to/kernel': 'vmlinuz', @@ -513,15 +502,16 @@ class FsImageTestCase(base.TestCase): mock_file_handle1 = mock.MagicMock(spec=io.BytesIO) mock_file_handle1.__enter__.return_value = 'mountdir' tempdir_mock.side_effect = mock_file_handle, mock_file_handle1 - mount_mock.return_value = (uefi_path_info, - e_img_rel_path, grub_rel_path) + get_iso_files_mock.return_value = (uefi_path_info, + e_img_rel_path, grub_rel_path) images.create_esp_image_for_uefi('tgt_file', 'path/to/kernel', 'path/to/ramdisk', deploy_iso='path/to/deploy_iso', kernel_params=params) - mount_mock.assert_called_once_with('path/to/deploy_iso', 'mountdir') + get_iso_files_mock.assert_called_once_with('path/to/deploy_iso', + 'mountdir') create_root_fs_mock.assert_called_once_with('tmpdir', files_info) gen_cfg_mock.assert_any_call(params, CONF.grub_config_template, grub_options) @@ -529,7 +519,7 @@ class FsImageTestCase(base.TestCase): execute_mock.assert_called_once_with( 'mkisofs', '-r', '-V', 'VMEDIA_BOOT_ISO', '-l', '-e', 'path/to/efiboot.img', '-no-emul-boot', '-o', 'tgt_file', 'tmpdir') - umount_mock.assert_called_once_with('mountdir') + rmtree_mock.assert_called_once_with('mountdir') @mock.patch.object(utils, 'write_to_file', autospec=True) @mock.patch.object(images, '_create_root_fs', autospec=True) @@ -647,14 +637,15 @@ class FsImageTestCase(base.TestCase): self._test_create_isolinux_image_for_bios( inject_files={'/source': 'target'}) - @mock.patch.object(images, '_umount_without_raise', autospec=True) + @mock.patch.object(images, '_extract_iso', autospec=True) + @mock.patch.object(shutil, 'rmtree', autospec=True) @mock.patch.object(images, '_create_root_fs', autospec=True) @mock.patch.object(utils, 'tempdir', autospec=True) @mock.patch.object(utils, 'execute', autospec=True) @mock.patch.object(os, 'walk', autospec=True) def test_create_esp_image_uefi_rootfs_fails( self, walk_mock, utils_mock, tempdir_mock, - create_root_fs_mock, umount_mock): + create_root_fs_mock, rmtree_mock, extract_mock): mock_file_handle = mock.MagicMock(spec=io.BytesIO) mock_file_handle.__enter__.return_value = 'tmpdir' @@ -669,7 +660,7 @@ class FsImageTestCase(base.TestCase): 'path/to/kernel', 'path/to/ramdisk', deploy_iso='path/to/deployiso') - umount_mock.assert_called_once_with('mountdir') + rmtree_mock.assert_called_once_with('mountdir') @mock.patch.object(images, '_create_root_fs', autospec=True) @mock.patch.object(utils, 'tempdir', autospec=True) @@ -686,22 +677,22 @@ class FsImageTestCase(base.TestCase): 'tgt_file', 'path/to/kernel', 'path/to/ramdisk') - @mock.patch.object(images, '_umount_without_raise', autospec=True) + @mock.patch.object(shutil, 'rmtree', autospec=True) @mock.patch.object(images, '_create_root_fs', autospec=True) @mock.patch.object(utils, 'write_to_file', autospec=True) @mock.patch.object(utils, 'tempdir', autospec=True) @mock.patch.object(utils, 'execute', autospec=True) - @mock.patch.object(images, '_mount_deploy_iso', autospec=True) + @mock.patch.object(images, '_get_deploy_iso_files', autospec=True) @mock.patch.object(images, '_generate_cfg', autospec=True) def test_create_esp_image_mkisofs_fails( - self, gen_cfg_mock, mount_mock, utils_mock, tempdir_mock, - write_to_file_mock, create_root_fs_mock, umount_mock): + self, gen_cfg_mock, get_iso_files_mock, utils_mock, tempdir_mock, + write_to_file_mock, create_root_fs_mock, rmtree_mock): mock_file_handle = mock.MagicMock(spec=io.BytesIO) mock_file_handle.__enter__.return_value = 'tmpdir' mock_file_handle1 = mock.MagicMock(spec=io.BytesIO) mock_file_handle1.__enter__.return_value = 'mountdir' tempdir_mock.side_effect = mock_file_handle, mock_file_handle1 - mount_mock.return_value = ({'a': 'a'}, 'b', 'c') + get_iso_files_mock.return_value = ({'a': 'a'}, 'b', 'c') utils_mock.side_effect = processutils.ProcessExecutionError self.assertRaises(exception.ImageCreationFailed, @@ -710,7 +701,7 @@ class FsImageTestCase(base.TestCase): 'path/to/kernel', 'path/to/ramdisk', deploy_iso='path/to/deployiso') - umount_mock.assert_called_once_with('mountdir') + rmtree_mock.assert_called_once_with('mountdir') @mock.patch.object(images, '_create_root_fs', autospec=True) @mock.patch.object(utils, 'write_to_file', autospec=True) |