summaryrefslogtreecommitdiff
path: root/ironic
diff options
context:
space:
mode:
Diffstat (limited to 'ironic')
-rw-r--r--ironic/common/images.py45
-rw-r--r--ironic/tests/unit/common/test_images.py93
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)