Stages/grub2.legacy: extend default config options

Extend the stage to allow explicitly configuring more grub2 default
config options. Preserve the defaults for options which were previously
hard-coded.

Extend the stage unit test to verify setting of the new grub2 default
config options.

Related to https://issues.redhat.com/browse/RHEL-19583

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
This commit is contained in:
Tomáš Hozza 2024-02-19 17:34:12 +01:00 committed by Tomáš Hozza
parent 21ebed9305
commit 7895424b78
2 changed files with 85 additions and 13 deletions

View file

@ -174,15 +174,26 @@ SCHEMA = """
"description": "Additional kernel command line options",
"type": "string"
},
"disable_recovery": {
"type": "boolean",
"default": true
},
"disable_submenu": {
"type": "boolean",
"default": true
},
"distributor": {
"description": "Name of the distributor",
"type": "string"
},
"terminal": {
"$ref": "#/definitions/terminal"
},
"terminal_input": {
"$ref": "#/definitions/terminal"
"$ref": "#/definitions/terminal"
},
"terminal_output": {
"$ref": "#/definitions/terminal"
"$ref": "#/definitions/terminal"
},
"timeout": {
"description": "Timeout in seconds",
@ -190,6 +201,11 @@ SCHEMA = """
"minimum": 0,
"default": 0
},
"timeout_style": {
"type": "string",
"enum": ["hidden", "menu", "countdown"],
"default": "countdown"
},
"serial": {
"description": "The command to configure the serial console",
"type": "string"
@ -331,6 +347,7 @@ class GrubEntry:
return entry
# pylint: disable=too-many-instance-attributes
class GrubConfig:
def __init__(self, bios, rootfs, bootfs):
self.bios = bios
@ -338,11 +355,15 @@ class GrubConfig:
self.bootfs = bootfs
self.entries = []
self.cmdline = ""
self.disable_recovery = True
self.disable_submenu = True
self.distributor = ""
self.serial = ""
self.terminal = None
self.terminal_input = None
self.terminal_output = None
self.timeout = 0
self.timeout_style = "countdown"
@property
def grubfs(self):
@ -432,9 +453,9 @@ class GrubConfig:
data = (
f"GRUB_TIMEOUT={self.timeout}\n"
f'GRUB_CMDLINE_LINUX="{self.cmdline}"\n'
"GRUB_DISABLE_SUBMENU=true\n"
"GRUB_DISABLE_RECOVERY=true\n"
"GRUB_TIMEOUT_STYLE=countdown\n"
f"GRUB_DISABLE_SUBMENU={str(self.disable_submenu).lower()}\n"
f"GRUB_DISABLE_RECOVERY={str(self.disable_recovery).lower()}\n"
f"GRUB_TIMEOUT_STYLE={self.timeout_style}\n"
"GRUB_DEFAULT=saved\n"
)
@ -444,6 +465,10 @@ class GrubConfig:
if self.serial:
data += f'GRUB_SERIAL_COMMAND="{self.serial}"\n'
if self.terminal:
val = " ".join(self.terminal)
data += f'GRUB_TERMINAL="{val}"\n'
if self.terminal_input:
val = " ".join(self.terminal_input)
data += f'GRUB_TERMINAL_INPUT="{val}"\n'
@ -467,11 +492,15 @@ def main(tree, options):
cfg = options.get("config", {})
config = GrubConfig(bios, root_fs, boot_fs)
config.cmdline = cfg.get("cmdline", "")
config.disable_recovery = cfg.get("disable_recovery", True)
config.disable_submenu = cfg.get("disable_submenu", True)
config.distributor = cfg.get("distributor")
config.serial = cfg.get("serial")
config.terminal = cfg.get("terminal")
config.terminal_input = cfg.get("terminal_input")
config.terminal_output = cfg.get("terminal_output")
config.timeout = cfg.get("timeout", 0)
config.timeout_style = cfg.get("timeout_style", "countdown")
config.entries = [GrubEntry.from_json(e) for e in options["entries"]]
# Create the configuration file that determines how grub.cfg is generated.

View file

@ -2,11 +2,58 @@
import os.path
import pytest
STAGE_NAME = "org.osbuild.grub2.legacy"
# Test that the /etc/default/grub file is created with the correct content
def test_grub2_default_conf(tmp_path, stage_module):
@pytest.mark.parametrize("test_data,expected_conf", [
# default
({}, """GRUB_TIMEOUT=0
GRUB_CMDLINE_LINUX=""
GRUB_DISABLE_SUBMENU=true
GRUB_DISABLE_RECOVERY=true
GRUB_TIMEOUT_STYLE=countdown
GRUB_DEFAULT=saved
"""),
# custom
({
"disable_submenu": False,
"disable_recovery": False,
"timeout": 10,
"timeout_style": "hidden",
}, """GRUB_TIMEOUT=10
GRUB_CMDLINE_LINUX=""
GRUB_DISABLE_SUBMENU=false
GRUB_DISABLE_RECOVERY=false
GRUB_TIMEOUT_STYLE=hidden
GRUB_DEFAULT=saved
"""),
# custom (Azure)
({
"cmdline": "loglevel=3 crashkernel=auto console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300",
"disable_submenu": True,
"disable_recovery": True,
"distributor": "$(sed 's, release .*$,,g' /etc/system-release)",
"serial": "serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1",
"terminal": ["serial", "console"],
"terminal_output": ["console"],
"timeout": 10,
"timeout_style": "countdown",
}, """GRUB_TIMEOUT=10
GRUB_CMDLINE_LINUX="loglevel=3 crashkernel=auto console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300"
GRUB_DISABLE_SUBMENU=true
GRUB_DISABLE_RECOVERY=true
GRUB_TIMEOUT_STYLE=countdown
GRUB_DEFAULT=saved
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"
GRUB_TERMINAL="serial console"
GRUB_TERMINAL_OUTPUT="console"
"""),
])
def test_grub2_default_conf(tmp_path, stage_module, test_data, expected_conf):
treedir = tmp_path / "tree"
confpath = treedir / "etc/default/grub"
confpath.parent.mkdir(parents=True, exist_ok=True)
@ -27,12 +74,8 @@ def test_grub2_default_conf(tmp_path, stage_module):
]
}
options["config"] = test_data
stage_module.main(treedir, options)
assert os.path.exists(confpath)
assert confpath.read_text() == """GRUB_TIMEOUT=0
GRUB_CMDLINE_LINUX=""
GRUB_DISABLE_SUBMENU=true
GRUB_DISABLE_RECOVERY=true
GRUB_TIMEOUT_STYLE=countdown
GRUB_DEFAULT=saved
"""
assert confpath.read_text() == expected_conf