-
Notifications
You must be signed in to change notification settings - Fork 148
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Previosly detection of Azure hybrid image was tightly coupled with process of converting grubenv symlink to a regular file. Since there exists other issues relating to hybrid images it is worth to separate these two concepts. This commit modifies the CheckHybridImage actor so that it produces a message whel WALinuxAgent is detected or we are booted in bios and ESP partition is mounted (sign of a hybrid image). New CheckGrubenvToFile actor is responsible for detection of grubenv symlink on hybrid images and tasks ConvertGrubenvToFile that is later responsible for the actual conversion.
- Loading branch information
Showing
13 changed files
with
278 additions
and
161 deletions.
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
repos/system_upgrade/common/actors/cloud/checkgrubenvtofile/actor.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from leapp.actors import Actor | ||
from leapp.libraries.actor import checkgrubenvtofile | ||
from leapp.models import HybridImage, ConvertGrubenvTask, FirmwareFacts | ||
from leapp.reporting import Report | ||
from leapp.tags import FinalizationPhaseTag, IPUWorkflowTag | ||
|
||
|
||
class CheckGrubenvToFile(Actor): | ||
""" | ||
Check whether grubenv is a symlink on Azure hybrid images using BIOS. | ||
Azure images provided by Red Hat aim for hybrid (BIOS/EFI) functionality, | ||
however, currently GRUB is not able to see the "grubenv" file if it is a | ||
symlink to a different partition (default on EFI with grub2-efi pkg | ||
installed) and fails on BIOS systems. | ||
These images have a default relative symlink to EFI partition even when | ||
booted using BIOS and in such cases GRUB is not able to find "grubenv" and | ||
fails to get the kernel cmdline options resulting in system failing to boot | ||
after upgrade. | ||
The symlink needs to be converted to a normal file with the content of | ||
grubenv on the EFI partition in case the system is using BIOS and running | ||
on the Azure cloud. This action is reported in the preupgrade phase. | ||
""" | ||
|
||
name = 'check_grubenv_to_file' | ||
consumes = (FirmwareFacts, HybridImage,) | ||
produces = (ConvertGrubenvTask, Report) | ||
tags = (FinalizationPhaseTag, IPUWorkflowTag) | ||
|
||
def process(self): | ||
checkgrubenvtofile.process() |
50 changes: 50 additions & 0 deletions
50
repos/system_upgrade/common/actors/cloud/checkgrubenvtofile/libraries/checkgrubenvtofile.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import os | ||
|
||
from leapp import reporting | ||
from leapp.libraries.stdlib import api | ||
from leapp.models import FirmwareFacts, HybridImage, ConvertGrubenvTask | ||
|
||
GRUBENV_BIOS_PATH = '/boot/grub2/grubenv' | ||
GRUBENV_EFI_PATH = '/boot/efi/EFI/redhat/grubenv' | ||
|
||
|
||
def process(): | ||
hybrid_image = next(api.consume(HybridImage), None) | ||
|
||
if hybrid_image and is_bios() and is_grubenv_symlink_to_efi(): | ||
reporting.create_report([ | ||
reporting.Title( | ||
'Azure hybrid (BIOS/EFI) image detected. "grubenv" symlink will be converted to a regular file' | ||
), | ||
reporting.Summary( | ||
'Leapp detected the system is running on Azure cloud, booted using BIOS and ' | ||
'the "/boot/grub2/grubenv" file is a symlink to "../efi/EFI/redhat/grubenv". In case of such a ' | ||
'hybrid image scenario GRUB is not able to locate "grubenv" as it is a symlink to different ' | ||
'partition and fails to boot. If the system needs to be run in EFI mode later, please re-create ' | ||
'the relative symlink again.' | ||
), | ||
reporting.Severity(reporting.Severity.HIGH), | ||
reporting.Groups([reporting.Groups.PUBLIC_CLOUD]), | ||
]) | ||
|
||
api.produce(ConvertGrubenvTask()) | ||
|
||
|
||
def is_bios(): | ||
""" | ||
Check whether system is booted into BIOS | ||
""" | ||
|
||
ff = next(api.consume(FirmwareFacts), None) | ||
return ff and ff.firmware == 'bios' | ||
|
||
|
||
def is_grubenv_symlink_to_efi(): | ||
""" | ||
Check whether '/boot/grub2/grubenv' is a relative symlink to '/boot/efi/EFI/redhat/grubenv'. | ||
""" | ||
|
||
is_symlink = os.path.islink(GRUBENV_BIOS_PATH) | ||
realpaths_match = os.path.realpath(GRUBENV_BIOS_PATH) == os.path.realpath(GRUBENV_EFI_PATH) | ||
|
||
return is_symlink and realpaths_match |
59 changes: 59 additions & 0 deletions
59
repos/system_upgrade/common/actors/cloud/checkgrubenvtofile/tests/test_checkgrubenvtofile.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import pytest | ||
|
||
from leapp import reporting | ||
from leapp.libraries.actor import checkgrubenvtofile | ||
from leapp.libraries.stdlib import api | ||
from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked, produce_mocked | ||
from leapp.models import HybridImage, FirmwareFacts | ||
|
||
|
||
BIOS_FIRMWARE = FirmwareFacts(firmware='bios') | ||
EFI_FIRMWARE = FirmwareFacts(firmware='efi') | ||
|
||
|
||
@pytest.mark.parametrize('is_symlink', [True, False]) | ||
@pytest.mark.parametrize('realpath_match', [True, False]) | ||
def test_is_grubenv_symlink_to_efi(monkeypatch, tmpdir, is_symlink, realpath_match): | ||
grubenv_efi = tmpdir.join('grubenv_efi') | ||
grubenv_efi.write('grubenv') | ||
grubenv_efi.write('nope') | ||
grubenv_boot = tmpdir.join('grubenv_boot') | ||
|
||
grubenv_efi_false = tmpdir.join('grubenv_efi_false') | ||
|
||
monkeypatch.setattr(checkgrubenvtofile, 'GRUBENV_BIOS_PATH', grubenv_boot.strpath) | ||
monkeypatch.setattr(checkgrubenvtofile, 'GRUBENV_EFI_PATH', grubenv_efi.strpath) | ||
|
||
grubenv_target = grubenv_efi if realpath_match else grubenv_efi_false | ||
if is_symlink: | ||
grubenv_boot.mksymlinkto(grubenv_target) | ||
|
||
ans = checkgrubenvtofile.is_grubenv_symlink_to_efi() | ||
|
||
assert ans == (is_symlink and realpath_match) | ||
|
||
|
||
@pytest.mark.parametrize('is_hybrid', [True, False]) | ||
@pytest.mark.parametrize('is_bios', [True, False]) | ||
@pytest.mark.parametrize('is_symlink', [True, False]) | ||
def test_check_grubenv_to_file(monkeypatch, tmpdir, is_hybrid, is_bios, is_symlink): | ||
|
||
should_report = all([is_hybrid, is_bios, is_symlink]) | ||
|
||
monkeypatch.setattr(reporting, 'create_report', create_report_mocked()) | ||
|
||
firmware = BIOS_FIRMWARE if is_bios else EFI_FIRMWARE | ||
msgs = [firmware] + ([HybridImage()] if is_hybrid else []) | ||
monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(arch='x86_64', msgs=msgs)) | ||
monkeypatch.setattr(api, "produce", produce_mocked()) | ||
monkeypatch.setattr(checkgrubenvtofile, "is_grubenv_symlink_to_efi", lambda: is_symlink) | ||
|
||
checkgrubenvtofile.process() | ||
|
||
if should_report: | ||
assert reporting.create_report.called == 1 | ||
assert 'hybrid' in reporting.create_report.report_fields['title'] | ||
assert api.produce.called == 1 | ||
else: | ||
assert reporting.create_report.called == 0 | ||
assert api.produce.called == 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
repos/system_upgrade/common/actors/cloud/convertgrubenvtofile/actor.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from leapp.actors import Actor | ||
from leapp.libraries.actor import convertgrubenvtofile | ||
from leapp.models import ConvertGrubenvTask | ||
from leapp.tags import FinalizationPhaseTag, IPUWorkflowTag | ||
|
||
|
||
class ConvertGrubenvToFile(Actor): | ||
""" | ||
Convert "grubenv" symlink to a regular file on Azure hybrid images using BIOS. | ||
For more information see CheckGrubenvToFile actor. | ||
""" | ||
|
||
name = 'convert_grubenv_to_file' | ||
consumes = (ConvertGrubenvTask,) | ||
produces = () | ||
tags = (FinalizationPhaseTag, IPUWorkflowTag) | ||
|
||
def process(self): | ||
convertgrubenvtofile.process() |
8 changes: 8 additions & 0 deletions
8
.../grubenvtofile/libraries/grubenvtofile.py → ...vtofile/libraries/convertgrubenvtofile.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.