stages(kickstart): implement "reboot" option
This commit implements the `reboot` option for kickstart files.
Note that there are two ways this can be enabled via the json.
Either via a boolean or by passing a dict with options.
```
{"reboot": true}
{"reboot": {"eject": true, "kexec": true}
```
Passing the empty dict
```
{"reboot": {}}
```
is not allowed by the schema.
This commit is contained in:
parent
b9ad7dd1be
commit
cce0eeaba4
2 changed files with 56 additions and 3 deletions
|
|
@ -170,6 +170,27 @@ SCHEMA = r"""
|
|||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"reboot": {
|
||||
"description": "Reboot after the installation is successfully completed",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
}, {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"anyOf": [{"required": ["eject"]}, {"required": ["kexec"]}],
|
||||
"properties": {
|
||||
"eject": {
|
||||
"description": "Attempt to eject the installation media before rebooting",
|
||||
"type": "boolean"
|
||||
},
|
||||
"kexec": {
|
||||
"description": "Use this option to reboot into the new system using the kexec",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
|
@ -259,6 +280,19 @@ def make_clearpart(options: Dict) -> str:
|
|||
return cmd
|
||||
|
||||
|
||||
def make_reboot(options):
|
||||
reboot = options.get("reboot", None)
|
||||
if not reboot:
|
||||
return ""
|
||||
cmd = "reboot"
|
||||
if isinstance(reboot, dict):
|
||||
if reboot.get("eject"):
|
||||
cmd += " --eject"
|
||||
if reboot.get("kexec"):
|
||||
cmd += " --kexec"
|
||||
return cmd
|
||||
|
||||
|
||||
def main(tree, options):
|
||||
path = options["path"].lstrip("/")
|
||||
ostree = options.get("ostree")
|
||||
|
|
@ -302,6 +336,10 @@ def main(tree, options):
|
|||
if clearpart:
|
||||
config += [clearpart]
|
||||
|
||||
reboot = make_reboot(options)
|
||||
if reboot:
|
||||
config += [reboot]
|
||||
|
||||
target = os.path.join(tree, path)
|
||||
base = os.path.dirname(target)
|
||||
os.makedirs(base, exist_ok=True)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ from osbuild.testutil.imports import import_module_from_path
|
|||
'sshkey --username someusr "ssh-rsa not-really-a-real-key"'
|
||||
),
|
||||
({"zerombr": "true"}, "zerombr"),
|
||||
({"clearpart": {}}, "clearpart"),
|
||||
# no clearpart for an empty dict (will not do anything with options anyway)
|
||||
({"clearpart": {}}, ""),
|
||||
({"clearpart": {"all": True}}, "clearpart --all"),
|
||||
({"clearpart": {"drives": ["hda", "hdb"]}}, "clearpart --drives=hda,hdb",),
|
||||
({"clearpart": {"drives": ["hda"]}}, "clearpart --drives=hda"),
|
||||
|
|
@ -88,6 +89,13 @@ from osbuild.testutil.imports import import_module_from_path
|
|||
},
|
||||
"lang en_US.UTF-8\nkeyboard us\ntimezone UTC\nzerombr\nclearpart --all --drives=sd*|hd*|vda,/dev/vdc",
|
||||
),
|
||||
# no reboot for an empty dict
|
||||
({"reboot": True}, "reboot"),
|
||||
({"reboot": {"eject": False}}, "reboot"),
|
||||
({"reboot": {"eject": True}}, "reboot --eject"),
|
||||
({"reboot": {"kexec": False}}, "reboot"),
|
||||
({"reboot": {"kexec": True}}, "reboot --kexec"),
|
||||
({"reboot": {"eject": True, "kexec": True}}, "reboot --eject --kexec"),
|
||||
])
|
||||
def test_kickstart(tmp_path, test_input, expected):
|
||||
ks_stage_path = os.path.join(os.path.dirname(__file__), "../org.osbuild.kickstart")
|
||||
|
|
@ -105,7 +113,8 @@ def test_kickstart(tmp_path, test_input, expected):
|
|||
assert ks_content == expected + "\n"
|
||||
|
||||
# double check with pykickstart if the file looks valid
|
||||
subprocess.check_call(["ksvalidator", ks_path])
|
||||
if expected:
|
||||
subprocess.check_call(["ksvalidator", ks_path])
|
||||
|
||||
|
||||
@pytest.mark.parametrize("test_data,expected_err", [
|
||||
|
|
@ -118,10 +127,16 @@ def test_kickstart(tmp_path, test_input, expected):
|
|||
({"clearpart": {"list": ["\n%pre not allowed"]}}, "not allowed' does not match"),
|
||||
({"clearpart": {"list": ["no,comma"]}}, "no,comma' does not match"),
|
||||
({"clearpart": {"disklabel": "\n%pre not allowed"}}, "not allowed' does not match"),
|
||||
# schema ensures reboot has at least one option set
|
||||
({"reboot": {}}, "{} is not valid under any of the given schemas"),
|
||||
({"reboot": "random-string"}, "'random-string' is not valid "),
|
||||
({"reboot": {"random": "option"}}, "{'random': 'option'} is not valid "),
|
||||
# GOOD pattern we want to keep working
|
||||
({"clearpart": {"drives": ["sd*|hd*|vda", "/dev/vdc"]}}, ""),
|
||||
({"clearpart": {"drives": ["disk/by-id/scsi-58095BEC5510947BE8C0360F604351918"]}}, ""),
|
||||
({"clearpart": {"list": ["sda2", "sda3", "sdb1"]}}, ""),
|
||||
({"reboot": True}, ""),
|
||||
({"reboot": {"kexec": False}}, ""),
|
||||
])
|
||||
def test_schema_validation_smoke(test_data, expected_err):
|
||||
name = "org.osbuild.kickstart"
|
||||
|
|
@ -139,7 +154,7 @@ def test_schema_validation_smoke(test_data, expected_err):
|
|||
res = schema.validate(test_input)
|
||||
|
||||
if expected_err == "":
|
||||
assert res.valid is True
|
||||
assert res.valid is True, f"err: {[e.as_dict() for e in res.errors]}"
|
||||
else:
|
||||
assert res.valid is False
|
||||
assert len(res.errors) == 1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue