Skip to content

Commit bd6d1b4

Browse files
authored
Merge pull request #2778 from OSInside/efifatfileimage-filter
Add support for filtering out files from the ESP image for GRUB
2 parents aa0adc7 + 22190cf commit bd6d1b4

File tree

7 files changed

+104
-8
lines changed

7 files changed

+104
-8
lines changed

build-tests/x86/fedora/test-image-live-disk/appliance.kiwi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
<source path="obsrepositories:/"/>
6262
</repository>
6363
<packages type="image">
64+
<!-- Filter out unwanted EFI files from the embedded ESP -->
65+
<file name="iso-esp-excludes.yaml" target="image/exclude_files_efifatimage.yaml"/>
6466
<package name="grub2"/>
6567
<package name="grubby"/>
6668
<package name="kernel"/>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
exclude:
2+
- BOOT/fb*.efi
3+
- fedora

kiwi/bootloader/config/grub2.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from kiwi.system.identifier import SystemIdentifier
3636
from kiwi.utils.sync import DataSync
3737
from kiwi.utils.sysconfig import SysConfig
38+
from kiwi.utils.temporary import Temporary
3839

3940
from kiwi.exceptions import (
4041
KiwiTemplateError,
@@ -1032,6 +1033,12 @@ def _create_embedded_fat_efi_image(self, path):
10321033
self.xml_state.build_type
10331034
.get_efifatimagesize() or defaults.EFI_FAT_IMAGE_SIZE
10341035
)
1036+
efi_folder = Temporary(prefix='efi_folder').new_dir()
1037+
efi_data = DataSync(self.boot_dir + '/EFI/', efi_folder.name)
1038+
efi_data.sync_data(
1039+
options=Defaults.get_sync_options(),
1040+
exclude=Defaults.get_exclude_list_from_custom_exclude_files_for_efifatimage(self.root_dir)
1041+
)
10351042
Command.run(
10361043
['qemu-img', 'create', path, f'{fat_image_mbsize}M']
10371044
)
@@ -1041,7 +1048,7 @@ def _create_embedded_fat_efi_image(self, path):
10411048
Command.run(
10421049
[
10431050
'mcopy', '-Do', '-s', '-i', path,
1044-
self.boot_dir + '/EFI', '::'
1051+
efi_folder.name, '::EFI'
10451052
]
10461053
)
10471054

kiwi/defaults.py

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -443,19 +443,30 @@ def get_runtime_checker_metadata() -> Dict:
443443
return yaml.safe_load(meta)
444444

445445
@staticmethod
446-
def get_exclude_list_from_custom_exclude_files(root_dir: str) -> List:
446+
def _parse_exclude_file(root_dir: str, exclude_filename: str) -> List:
447447
"""
448-
Provides the list of folders that are excluded by the
449-
optional metadata file image/exclude_files.yaml
448+
Retrieves an exclusion list from the provided metadata file
450449
451-
:return: list of file and directory names
450+
The file should contain a YAML dictionary with a top-level key
451+
named 'exclude' and the list of exclusions as its value.
452+
453+
The list of exclusions may include:
454+
* file paths
455+
* folder paths
456+
* glob patterns
457+
458+
Paths and patterns should be relative to the filesystem or
459+
directory that they're being excluded from.
460+
461+
:return: list of paths and glob patterns
452462
453463
:param string root_dir: image root directory
464+
:param string exclude_filename: file exclusion YAML metadata file
454465
455466
:rtype: list
456467
"""
457468
exclude_file = os.sep.join(
458-
[root_dir, 'image', 'exclude_files.yaml']
469+
[root_dir, 'image', exclude_filename]
459470
)
460471
exclude_list = []
461472
if os.path.isfile(exclude_file):
@@ -473,6 +484,36 @@ def get_exclude_list_from_custom_exclude_files(root_dir: str) -> List:
473484
)
474485
return exclude_list
475486

487+
@staticmethod
488+
def get_exclude_list_from_custom_exclude_files(root_dir: str) -> List:
489+
"""
490+
Gets the list of excluded items for the root filesystem from
491+
the optional metadata file image/exclude_files.yaml
492+
493+
:return: list of paths and glob patterns
494+
495+
:param string root_dir: image root directory
496+
497+
:rtype: list
498+
"""
499+
return Defaults._parse_exclude_file(root_dir, 'exclude_files.yaml')
500+
501+
@staticmethod
502+
def get_exclude_list_from_custom_exclude_files_for_efifatimage(root_dir: str) -> List:
503+
"""
504+
Gets the list of excluded items for the ESP's EFI folder from
505+
the optional metadata file image/exclude_files_efifatimage.yaml
506+
507+
Excluded items must be relative to the ESP's /EFI directory.
508+
509+
:return: list of paths and glob patterns
510+
511+
:param string root_dir: EFI root directory
512+
513+
:rtype: list
514+
"""
515+
return Defaults._parse_exclude_file(root_dir, 'exclude_files_efifatimage.yaml')
516+
476517
@staticmethod
477518
def get_exclude_list_for_non_physical_devices():
478519
"""
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
exclude:
2+
- BOOT/fbia32.efi
3+
- BOOT/fbx64.efi

test/unit/bootloader/config/grub2_test.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,13 @@ def test_write(
326326
'some-data'
327327
)
328328

329+
@patch('kiwi.bootloader.config.grub2.DataSync.sync_data')
330+
@patch('kiwi.bootloader.config.grub2.Temporary.new_dir')
329331
@patch('kiwi.bootloader.config.grub2.Command.run')
330-
def test_create_embedded_fat_efi_image(self, mock_command):
332+
def test_create_embedded_fat_efi_image(self, mock_command, mock_tmpdir, mock_syncdata):
333+
tmpdir = Mock()
334+
tmpdir.name = 'tmpdir'
335+
mock_tmpdir.return_value = tmpdir
331336
self.bootloader._create_embedded_fat_efi_image('tmp-esp-image')
332337
assert mock_command.call_args_list == [
333338
call(
@@ -343,7 +348,7 @@ def test_create_embedded_fat_efi_image(self, mock_command):
343348
call(
344349
[
345350
'mcopy', '-Do', '-s', '-i', 'tmp-esp-image',
346-
'root_dir/EFI', '::'
351+
'tmpdir', '::EFI'
347352
]
348353
)
349354
]

test/unit/defaults_test.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,23 @@ def test_get_vendor_grubenv(self, mock_path_exists):
107107
assert Defaults.get_vendor_grubenv('boot/efi') == \
108108
'boot/efi/EFI/fedora/grubenv'
109109

110+
def test_parse_exclude_file_is_valid(self):
111+
assert Defaults._parse_exclude_file(
112+
'../data/root-dir', 'exclude_files.yaml'
113+
) == [
114+
'usr/bin/qemu-binfmt',
115+
'usr/bin/qemu-x86_64-binfmt',
116+
'usr/bin/qemu-x86_64'
117+
]
118+
119+
@patch('yaml.safe_load')
120+
def test_parse_exclude_file_is_invalid(self, mock_yaml_safe_load):
121+
mock_yaml_safe_load.return_value = {'invalid': 'artificial'}
122+
with self._caplog.at_level(logging.WARNING):
123+
assert Defaults._parse_exclude_file(
124+
'../data/root-dir', 'exclude_files.yaml'
125+
) == []
126+
110127
def test_get_exclude_list_from_custom_exclude_files(self):
111128
assert Defaults.get_exclude_list_from_custom_exclude_files(
112129
'../data/root-dir'
@@ -126,6 +143,24 @@ def test_get_exclude_list_from_custom_exclude_files_is_invalid(
126143
'../data/root-dir'
127144
) == []
128145

146+
def test_get_exclude_list_from_custom_exclude_files_for_efifatimage(self):
147+
assert Defaults.get_exclude_list_from_custom_exclude_files_for_efifatimage(
148+
'../data/root-dir'
149+
) == [
150+
'BOOT/fbia32.efi',
151+
'BOOT/fbx64.efi',
152+
]
153+
154+
@patch('yaml.safe_load')
155+
def test_get_exclude_list_from_custom_exclude_files_for_efifatimage_is_invalid(
156+
self, mock_yaml_safe_load
157+
):
158+
mock_yaml_safe_load.return_value = {'invalid': 'artificial'}
159+
with self._caplog.at_level(logging.WARNING):
160+
assert Defaults.get_exclude_list_from_custom_exclude_files_for_efifatimage(
161+
'../data/root-dir'
162+
) == []
163+
129164
def test_get_exclude_list_for_root_data_sync(self):
130165
assert Defaults.get_exclude_list_for_root_data_sync() == [
131166
'image', '.kconfig',

0 commit comments

Comments
 (0)