stages: externalize schemas
Copy all schemas into the relevant `.meta.json` files instead of having them contained inside the stages.
This commit is contained in:
parent
02b6d696ef
commit
bb58892571
296 changed files with 10435 additions and 9394 deletions
|
|
@ -1,56 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Configure basic aspects of the anaconda installer
|
|
||||||
|
|
||||||
Create an anaconda configuration file `90-osbuild.conf` in
|
|
||||||
the folder `/etc/anaconda/conf.d` to configure anaconda.
|
|
||||||
|
|
||||||
Currently only the list of enabled kickstart modules is
|
|
||||||
configurable via the `kickstart-modules` option.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": true,
|
|
||||||
"properties": {
|
|
||||||
"kickstart-modules": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Kick start modules to enable",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"minItems": 1
|
|
||||||
},
|
|
||||||
"activatable-modules": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Kick start modules to activate",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"minItems": 1
|
|
||||||
},
|
|
||||||
"forbidden-modules": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Kick start modules to forbid",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"minItems": 1
|
|
||||||
},
|
|
||||||
"optional-modules": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Kick start modules to activate but are allowed to fail",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"minItems": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONFIG = """
|
CONFIG = """
|
||||||
# osbuild customizations
|
# osbuild customizations
|
||||||
|
|
|
||||||
46
stages/org.osbuild.anaconda.meta.json
Normal file
46
stages/org.osbuild.anaconda.meta.json
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"summary": "Configure basic aspects of the anaconda installer",
|
||||||
|
"description": [
|
||||||
|
"Create an anaconda configuration file `90-osbuild.conf` in",
|
||||||
|
"the folder `/etc/anaconda/conf.d` to configure anaconda.",
|
||||||
|
"Currently only the list of enabled kickstart modules is",
|
||||||
|
"configurable via the `kickstart-modules` option."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": true,
|
||||||
|
"properties": {
|
||||||
|
"kickstart-modules": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Kick start modules to enable",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"minItems": 1
|
||||||
|
},
|
||||||
|
"activatable-modules": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Kick start modules to activate",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"minItems": 1
|
||||||
|
},
|
||||||
|
"forbidden-modules": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Kick start modules to forbid",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"minItems": 1
|
||||||
|
},
|
||||||
|
"optional-modules": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Kick start modules to activate but are allowed to fail",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"minItems": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,26 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Configure authentication sources using authconfig.
|
|
||||||
|
|
||||||
Applies the default settings. Backups are cleared.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
- Requires 'chroot' in the buildroot.
|
|
||||||
- Runs the 'authconfig' binary from the image in the chroot.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "Configure authentication sources."
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree):
|
def main(tree):
|
||||||
cmd = [
|
cmd = [
|
||||||
|
|
|
||||||
13
stages/org.osbuild.authconfig.meta.json
Normal file
13
stages/org.osbuild.authconfig.meta.json
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"summary": "Configure authentication sources using authconfig.",
|
||||||
|
"description": [
|
||||||
|
"Applies the default settings. Backups are cleared.",
|
||||||
|
"Notes:",
|
||||||
|
" - Requires 'chroot' in the buildroot.",
|
||||||
|
" - Runs the 'authconfig' binary from the image in the chroot."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Configure authentication sources."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,45 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Select system identity and authentication sources with authselect.
|
|
||||||
|
|
||||||
Sets system identity and authentication sources.
|
|
||||||
|
|
||||||
The stage calls `authselect select` to set authselect profile to 'profile'.
|
|
||||||
Optionally a list of profile features to enable may be provided using 'features'
|
|
||||||
option. The list of available profile features can be obtained by running
|
|
||||||
`authselect list-features <profile>`.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
- Requires 'chroot' in the buildroot.
|
|
||||||
- Runs the 'authselect' binary from the image in the chroot.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["profile"],
|
|
||||||
"description": "Select system identity and authentication sources.",
|
|
||||||
"properties": {
|
|
||||||
"profile": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Desired authselect profile to activate."
|
|
||||||
},
|
|
||||||
"features": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Features of the selected profile to activate.",
|
|
||||||
"minItems": 1,
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
profile = options["profile"]
|
profile = options["profile"]
|
||||||
|
|
|
||||||
34
stages/org.osbuild.authselect.meta.json
Normal file
34
stages/org.osbuild.authselect.meta.json
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"summary": "Select system identity and authentication sources with authselect.",
|
||||||
|
"description": [
|
||||||
|
"Sets system identity and authentication sources.",
|
||||||
|
"The stage calls `authselect select` to set authselect profile to 'profile'.",
|
||||||
|
"Optionally a list of profile features to enable may be provided using 'features'",
|
||||||
|
"option. The list of available profile features can be obtained by running",
|
||||||
|
"`authselect list-features <profile>`.",
|
||||||
|
"Notes:",
|
||||||
|
" - Requires 'chroot' in the buildroot.",
|
||||||
|
" - Runs the 'authselect' binary from the image in the chroot."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"profile"
|
||||||
|
],
|
||||||
|
"description": "Select system identity and authentication sources.",
|
||||||
|
"properties": {
|
||||||
|
"profile": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Desired authselect profile to activate."
|
||||||
|
},
|
||||||
|
"features": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Features of the selected profile to activate.",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,15 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Run bootc install to-filesystem
|
|
||||||
|
|
||||||
Note that this needs the disk.img in the inputs as one continous
|
|
||||||
devices so that bootupd can install grub to the mbr. It also needs
|
|
||||||
all relevant mount points for booting (e.g. /boot, /boot/efi) in
|
|
||||||
mounted in the "mounts" path.
|
|
||||||
|
|
||||||
Buildhost commands used: bootc
|
|
||||||
"""
|
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
@ -17,48 +6,6 @@ import tempfile
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
from osbuild.util import containers
|
from osbuild.util import containers
|
||||||
|
|
||||||
CAPABILITIES = ["CAP_MAC_ADMIN"]
|
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"inputs": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["images"],
|
|
||||||
"properties": {
|
|
||||||
"images": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"root-ssh-authorized-keys": {
|
|
||||||
"description": "array of SSH Public Keys to add to roots authorized_keys",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kernel-args": {
|
|
||||||
"description": "array of additional kernel arguments",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"devices": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
},
|
|
||||||
"mounts": {
|
|
||||||
"type": "array"
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(options, inputs, paths):
|
def main(options, inputs, paths):
|
||||||
images = containers.parse_containers_input(inputs)
|
images = containers.parse_containers_input(inputs)
|
||||||
|
|
|
||||||
54
stages/org.osbuild.bootc.install-to-filesystem.meta.json
Normal file
54
stages/org.osbuild.bootc.install-to-filesystem.meta.json
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
"summary": "Run bootc install to-filesystem",
|
||||||
|
"description": [
|
||||||
|
"Note that this needs the disk.img in the inputs as one continous",
|
||||||
|
"devices so that bootupd can install grub to the mbr. It also needs",
|
||||||
|
"all relevant mount points for booting (e.g. /boot, /boot/efi) in",
|
||||||
|
"mounted in the \"mounts\" path.",
|
||||||
|
"Buildhost commands used: bootc"
|
||||||
|
],
|
||||||
|
"capabilities": [
|
||||||
|
"CAP_MAC_ADMIN"
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"inputs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"images"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"images": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"root-ssh-authorized-keys": {
|
||||||
|
"description": "array of SSH Public Keys to add to roots authorized_keys",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"kernel-args": {
|
||||||
|
"description": "array of additional kernel arguments",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"devices": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
"mounts": {
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,28 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Assemble a file system tree for a bootable iso
|
|
||||||
|
|
||||||
This stage prepares a file system tree for a bootable ISO, like the
|
|
||||||
Anaconda installer. It follows the convention used by Lorax to
|
|
||||||
create the boot isos: It takes an input `rootfs`, which will serve
|
|
||||||
as the root file system. This is copied into a file with a `ext4`
|
|
||||||
file system which in turn will be made into a squashfs file system.
|
|
||||||
Options for controlling the root file-system creation can be given
|
|
||||||
via `rootfs`, like it size and the compression to be used.
|
|
||||||
|
|
||||||
The boot loader is configured via the `isolinux` and `efi` options.
|
|
||||||
Which combination makes sense depends on the targeted platform and
|
|
||||||
architecture.
|
|
||||||
The kernel and initrd are taken from the tree given via the `kernel`
|
|
||||||
input, or if that was not specified, from `rootfs`. In either case
|
|
||||||
it will look for the specified kernel in the `/boot` directory.
|
|
||||||
Additionally kernel command line flags can passed via `kernel_opts`.
|
|
||||||
|
|
||||||
This stage has the `.mono` suffix to indicate that is a monolithic
|
|
||||||
stage that could, and in the future will be, broken up into smaller
|
|
||||||
pieces.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
@ -34,119 +10,6 @@ import tempfile
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
import osbuild.remoteloop as remoteloop
|
import osbuild.remoteloop as remoteloop
|
||||||
|
|
||||||
SCHEMA_2 = """
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["product", "kernel", "isolabel"],
|
|
||||||
"properties": {
|
|
||||||
"product": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["name", "version"],
|
|
||||||
"properties": {
|
|
||||||
"name": {"type": "string"},
|
|
||||||
"version": {"type": "string"}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kernel": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"isolabel": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"efi": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["architectures", "vendor"],
|
|
||||||
"properties": {
|
|
||||||
"architectures": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vendor": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"isolinux": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["enabled"],
|
|
||||||
"properties": {
|
|
||||||
"enabled": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"debug": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kernel_opts": {
|
|
||||||
"description": "Additional kernel boot options",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"templates": {
|
|
||||||
"type": "string",
|
|
||||||
"default": "99-generic"
|
|
||||||
},
|
|
||||||
"rootfs": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"compression": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["method"],
|
|
||||||
"properties": {
|
|
||||||
"method": {
|
|
||||||
"enum": ["gzip", "xz", "lz4"]
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"bcj": {
|
|
||||||
"enum": [
|
|
||||||
"x86",
|
|
||||||
"arm",
|
|
||||||
"armthumb",
|
|
||||||
"powerpc",
|
|
||||||
"sparc",
|
|
||||||
"ia64"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "size in MB",
|
|
||||||
"default": 3072
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inputs": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["rootfs"],
|
|
||||||
"properties": {
|
|
||||||
"rootfs": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
},
|
|
||||||
"kernel": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
LORAX_TEMPLATES = "/usr/share/lorax/templates.d"
|
LORAX_TEMPLATES = "/usr/share/lorax/templates.d"
|
||||||
|
|
||||||
|
|
|
||||||
158
stages/org.osbuild.bootiso.mono.meta.json
Normal file
158
stages/org.osbuild.bootiso.mono.meta.json
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
{
|
||||||
|
"summary": "Assemble a file system tree for a bootable iso",
|
||||||
|
"description": [
|
||||||
|
"This stage prepares a file system tree for a bootable ISO, like the",
|
||||||
|
"Anaconda installer. It follows the convention used by Lorax to",
|
||||||
|
"create the boot isos: It takes an input `rootfs`, which will serve",
|
||||||
|
"as the root file system. This is copied into a file with a `ext4`",
|
||||||
|
"file system which in turn will be made into a squashfs file system.",
|
||||||
|
"Options for controlling the root file-system creation can be given",
|
||||||
|
"via `rootfs`, like it size and the compression to be used.",
|
||||||
|
"The boot loader is configured via the `isolinux` and `efi` options.",
|
||||||
|
"Which combination makes sense depends on the targeted platform and",
|
||||||
|
"architecture.",
|
||||||
|
"The kernel and initrd are taken from the tree given via the `kernel`",
|
||||||
|
"input, or if that was not specified, from `rootfs`. In either case",
|
||||||
|
"it will look for the specified kernel in the `/boot` directory.",
|
||||||
|
"Additionally kernel command line flags can passed via `kernel_opts`.",
|
||||||
|
"This stage has the `.mono` suffix to indicate that is a monolithic",
|
||||||
|
"stage that could, and in the future will be, broken up into smaller",
|
||||||
|
"pieces."
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"product",
|
||||||
|
"kernel",
|
||||||
|
"isolabel"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"product": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"version"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"kernel": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"isolabel": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"efi": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"architectures",
|
||||||
|
"vendor"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"architectures": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"vendor": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isolinux": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"enabled"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"kernel_opts": {
|
||||||
|
"description": "Additional kernel boot options",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"templates": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "99-generic"
|
||||||
|
},
|
||||||
|
"rootfs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"compression": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"method"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"method": {
|
||||||
|
"enum": [
|
||||||
|
"gzip",
|
||||||
|
"xz",
|
||||||
|
"lz4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"bcj": {
|
||||||
|
"enum": [
|
||||||
|
"x86",
|
||||||
|
"arm",
|
||||||
|
"armthumb",
|
||||||
|
"powerpc",
|
||||||
|
"sparc",
|
||||||
|
"ia64"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "size in MB",
|
||||||
|
"default": 3072
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inputs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"rootfs"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"rootfs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
"kernel": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Install GRUB on both BIOS and UEFI systems,
|
|
||||||
ensuring that your bootloader stays up-to-date.
|
|
||||||
|
|
||||||
Bootupd supports updating GRUB and shim for
|
|
||||||
UEFI firmware on x86_64 and aarch64,
|
|
||||||
and GRUB for BIOS firmware on x86_64.
|
|
||||||
The project is deployed in Fedora CoreOS and derivatives
|
|
||||||
"""
|
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
@ -18,84 +8,6 @@ import sys
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
from osbuild.util import ostree
|
from osbuild.util import ostree
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"devices": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
},
|
|
||||||
"mounts": {
|
|
||||||
"type": "array"
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"deployment": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"properties": {
|
|
||||||
"default": {"enum": [false]}
|
|
||||||
},
|
|
||||||
"required": ["osname", "ref"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"properties": {
|
|
||||||
"default": {"enum": [true]}
|
|
||||||
},
|
|
||||||
"not": {
|
|
||||||
"anyOf": [
|
|
||||||
{"required": ["osname"]},
|
|
||||||
{"required": ["ref"]},
|
|
||||||
{"required": ["serial"]}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"osname": {
|
|
||||||
"description": "Name of the stateroot to be used in the deployment",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"ref": {
|
|
||||||
"description": "OStree ref to create and use for deployment",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"serial": {
|
|
||||||
"description": "The deployment serial (usually '0')",
|
|
||||||
"type": "number",
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"description": "Find and use the default ostree deployment",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"static-configs": {
|
|
||||||
"description": "Install the grub configs defined for Fedora CoreOS",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"bios": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"type": "object",
|
|
||||||
"required": ["device"],
|
|
||||||
"properties": {
|
|
||||||
"device": {
|
|
||||||
"description": "Name of stage device to install GRUB for BIOS-based systems.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"partition": {
|
|
||||||
"description": "The partition on the stage device to install to, if installing to a partition",
|
|
||||||
"type": "number"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def bind_mounts(sources, dest_root):
|
def bind_mounts(sources, dest_root):
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Transforms /usr/lib/ostree-boot into a bootupd-compatible update payload.
|
|
||||||
|
|
||||||
Scrapes metadata (e.g. RPM versions) about shim/grub and puts them along with their component files in
|
|
||||||
`/usr/lib/bootupd/updates/`.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
- Requires 'chroot' in the buildroot.
|
|
||||||
- Runs the 'bootupctl' binary from the image in the chroot.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -17,12 +6,6 @@ import sys
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
from osbuild.util.mnt import MountGuard, MountPermissions
|
from osbuild.util.mnt import MountGuard, MountPermissions
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree):
|
def main(tree):
|
||||||
with MountGuard() as mounter:
|
with MountGuard() as mounter:
|
||||||
|
|
|
||||||
15
stages/org.osbuild.bootupd.gen-metadata.meta.json
Normal file
15
stages/org.osbuild.bootupd.gen-metadata.meta.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"summary": "Transforms /usr/lib/ostree-boot into a bootupd-compatible update payload.",
|
||||||
|
"description": [
|
||||||
|
"Scrapes metadata (e.g. RPM versions) about shim/grub and puts them along with their component files in",
|
||||||
|
"`/usr/lib/bootupd/updates/`.",
|
||||||
|
"Notes:",
|
||||||
|
" - Requires 'chroot' in the buildroot.",
|
||||||
|
" - Runs the 'bootupctl' binary from the image in the chroot."
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
111
stages/org.osbuild.bootupd.meta.json
Normal file
111
stages/org.osbuild.bootupd.meta.json
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
{
|
||||||
|
"summary": "Install GRUB on both BIOS and UEFI systems,\nensuring that your bootloader stays up-to-date.",
|
||||||
|
"description": [
|
||||||
|
"Bootupd supports updating GRUB and shim for",
|
||||||
|
"UEFI firmware on x86_64 and aarch64,",
|
||||||
|
"and GRUB for BIOS firmware on x86_64.",
|
||||||
|
"The project is deployed in Fedora CoreOS and derivatives"
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"devices": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
"mounts": {
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"deployment": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"default": {
|
||||||
|
"enum": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"osname",
|
||||||
|
"ref"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"default": {
|
||||||
|
"enum": [
|
||||||
|
true
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"not": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"osname"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"ref"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"serial"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"osname": {
|
||||||
|
"description": "Name of the stateroot to be used in the deployment",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ref": {
|
||||||
|
"description": "OStree ref to create and use for deployment",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"serial": {
|
||||||
|
"description": "The deployment serial (usually '0')",
|
||||||
|
"type": "number",
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"description": "Find and use the default ostree deployment",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"static-configs": {
|
||||||
|
"description": "Install the grub configs defined for Fedora CoreOS",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"bios": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"device"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"device": {
|
||||||
|
"description": "Name of stage device to install GRUB for BIOS-based systems.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"partition": {
|
||||||
|
"description": "The partition on the stage device to install to, if installing to a partition",
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,46 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Create subvolumes on a mounted btrfs partition.
|
|
||||||
|
|
||||||
See `btrfs`(8).
|
|
||||||
|
|
||||||
Buildhost commands used: `btrfs`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"subvolumes": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["name"],
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"devices": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
},
|
|
||||||
"mounts": {
|
|
||||||
"type": "array"
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(paths, options):
|
def main(paths, options):
|
||||||
volume = paths["mounts"]
|
volume = paths["mounts"]
|
||||||
|
|
|
||||||
36
stages/org.osbuild.btrfs.subvol.meta.json
Normal file
36
stages/org.osbuild.btrfs.subvol.meta.json
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"summary": "Create subvolumes on a mounted btrfs partition.",
|
||||||
|
"description": [
|
||||||
|
"See `btrfs`(8).",
|
||||||
|
"Buildhost commands used: `btrfs`."
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"subvolumes": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"devices": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
"mounts": {
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,47 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Create a /.buildstamp file describing the system
|
|
||||||
|
|
||||||
This will create a './buildstamp' with the specified parameters.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import configparser
|
import configparser
|
||||||
import datetime
|
import datetime
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": true,
|
|
||||||
"required": ["arch", "product", "version", "final"],
|
|
||||||
"properties": {
|
|
||||||
"arch": {
|
|
||||||
"description": "Build architecture.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"product": {
|
|
||||||
"description": "The product name.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"description": "The version .",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"final": {
|
|
||||||
"description": "The product.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"variant": {
|
|
||||||
"description": "The variant of the product.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"bugurl": {
|
|
||||||
"description": "The bugurl of the product.",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
buildarch = options["arch"]
|
buildarch = options["arch"]
|
||||||
|
|
|
||||||
41
stages/org.osbuild.buildstamp.meta.json
Normal file
41
stages/org.osbuild.buildstamp.meta.json
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"summary": "Create a /.buildstamp file describing the system",
|
||||||
|
"description": [
|
||||||
|
"This will create a './buildstamp' with the specified parameters."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": true,
|
||||||
|
"required": [
|
||||||
|
"arch",
|
||||||
|
"product",
|
||||||
|
"version",
|
||||||
|
"final"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"arch": {
|
||||||
|
"description": "Build architecture.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"description": "The product name.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"description": "The version .",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"final": {
|
||||||
|
"description": "The product.",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"variant": {
|
||||||
|
"description": "The variant of the product.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"bugurl": {
|
||||||
|
"description": "The bugurl of the product.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Runs `chattr` to set file/directory attributes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -11,38 +7,6 @@ from urllib.parse import ParseResult, urlparse
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"patternProperties": {
|
|
||||||
"^mount:\/\/[^\/]+\/|^tree:\/\/\/": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["immutable"],
|
|
||||||
"properties": {
|
|
||||||
"immutable": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Make the file/directory immutable",
|
|
||||||
"default": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"devices": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
},
|
|
||||||
"mounts": {
|
|
||||||
"type": "array"
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def parse_mount(url: ParseResult, args: Dict):
|
def parse_mount(url: ParseResult, args: Dict):
|
||||||
name = url.netloc
|
name = url.netloc
|
||||||
|
|
|
||||||
37
stages/org.osbuild.chattr.meta.json
Normal file
37
stages/org.osbuild.chattr.meta.json
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"summary": "Runs `chattr` to set file/directory attributes.",
|
||||||
|
"description": [],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"patternProperties": {
|
||||||
|
"^mount://[^/]+/|^tree:///": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"immutable"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"immutable": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Make the file/directory immutable",
|
||||||
|
"default": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"devices": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
"mounts": {
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Change file mode bits
|
|
||||||
|
|
||||||
Change the file mode bits of one or more files or directories inside the tree.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -12,35 +6,6 @@ import sys
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
from osbuild.util.path import in_tree
|
from osbuild.util.path import in_tree
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"patternProperties": {
|
|
||||||
"^\\/(?!\\.\\.)((?!\\/\\.\\.\\/).)+$": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["mode"],
|
|
||||||
"properties": {
|
|
||||||
"mode": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Symbolic or numeric octal mode"
|
|
||||||
},
|
|
||||||
"recursive": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Change modes recursively",
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def chmod(path: str, mode: str, recursive: bool):
|
def chmod(path: str, mode: str, recursive: bool):
|
||||||
arguments = [mode]
|
arguments = [mode]
|
||||||
|
|
|
||||||
36
stages/org.osbuild.chmod.meta.json
Normal file
36
stages/org.osbuild.chmod.meta.json
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"summary": "Change file mode bits",
|
||||||
|
"description": [
|
||||||
|
"Change the file mode bits of one or more files or directories inside the tree."
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"patternProperties": {
|
||||||
|
"^\\/(?!\\.\\.)((?!\\/\\.\\.\\/).)+$": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"mode"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"mode": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Symbolic or numeric octal mode"
|
||||||
|
},
|
||||||
|
"recursive": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Change modes recursively",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,73 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Change file owner and group
|
|
||||||
|
|
||||||
Change the file user and/or group ownership of one or more files or directories inside the tree.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
- Requires 'chroot' in the buildroot.
|
|
||||||
- Runs the 'chown' binary from the image in the chroot.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"patternProperties": {
|
|
||||||
"^\\/(?!\\.\\.)((?!\\/\\.\\.\\/).)+$": {
|
|
||||||
"type": "object",
|
|
||||||
"anyOf": [
|
|
||||||
{"required" : ["user"]},
|
|
||||||
{"required" : ["group"]}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"user": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[A-Za-z0-9_.][A-Za-z0-9_.-]{0,31}$"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "number",
|
|
||||||
"minimum": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "User name or UID"
|
|
||||||
},
|
|
||||||
"group": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[A-Za-z0-9_][A-Za-z0-9_-]{0,31}$"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "number",
|
|
||||||
"minimum": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Group name or GID"
|
|
||||||
},
|
|
||||||
"recursive": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"description": "Change ownership recursively"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
for path, cmdargs in options["items"].items():
|
for path, cmdargs in options["items"].items():
|
||||||
|
|
|
||||||
70
stages/org.osbuild.chown.meta.json
Normal file
70
stages/org.osbuild.chown.meta.json
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
"summary": "Change file owner and group",
|
||||||
|
"description": [
|
||||||
|
"Change the file user and/or group ownership of one or more files or directories inside the tree.",
|
||||||
|
"Notes:",
|
||||||
|
" - Requires 'chroot' in the buildroot.",
|
||||||
|
" - Runs the 'chown' binary from the image in the chroot."
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"patternProperties": {
|
||||||
|
"^\\/(?!\\.\\.)((?!\\/\\.\\.\\/).)+$": {
|
||||||
|
"type": "object",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"user"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"group"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"user": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[A-Za-z0-9_.][A-Za-z0-9_.-]{0,31}$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "User name or UID"
|
||||||
|
},
|
||||||
|
"group": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[A-Za-z0-9_][A-Za-z0-9_-]{0,31}$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Group name or GID"
|
||||||
|
},
|
||||||
|
"recursive": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "Change ownership recursively"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,100 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Configure chrony to set system time from the network.
|
|
||||||
|
|
||||||
Configures `chrony` by modifying `/etc/chrony.conf`.
|
|
||||||
|
|
||||||
Before new values are added to the chrony configuration, all lines starting with
|
|
||||||
"server", "pool" or "peer" are removed.
|
|
||||||
|
|
||||||
The 'timeservers' option provides a very high-level way of configuring chronyd
|
|
||||||
with specific timeservers. Its value is a list of strings representing the
|
|
||||||
hostname or IP address of the timeserver. For each list item, the following
|
|
||||||
line will be added to the configuration:
|
|
||||||
`server <HOSTNAME/IP> iburst`
|
|
||||||
|
|
||||||
The 'servers' option provides a direct mapping to the `server` directive from
|
|
||||||
chrony configuration. Its value is a list of dictionaries representing each
|
|
||||||
timeserver which should be added to the configuration. For each list item,
|
|
||||||
a `server` directive will be added the configuration. Currently supported
|
|
||||||
subset of options which can be specified for each timeserver item:
|
|
||||||
- 'hostname' (REQUIRED)
|
|
||||||
- 'minpoll'
|
|
||||||
- 'maxpoll'
|
|
||||||
- 'iburst' (defaults to true)
|
|
||||||
- 'prefer' (defaults to false)
|
|
||||||
|
|
||||||
The 'leapsectz' option configures chrony behavior related to automatic checking
|
|
||||||
of the next occurrence of the leap second, using the provided timezone. Its
|
|
||||||
value is a string representing a timezone from the system tz database (e.g.
|
|
||||||
'right/UTC'). If an empty string is provided, then all occurrences of
|
|
||||||
'leapsectz' directive are removed from the configuration.
|
|
||||||
|
|
||||||
Constraints:
|
|
||||||
- Exactly one of 'timeservers' or 'servers' options must be provided.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"oneOf": [
|
|
||||||
{"required": ["timeservers"]},
|
|
||||||
{"required": ["servers"]}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"timeservers": {
|
|
||||||
"type": "array",
|
|
||||||
"items": { "type": "string" },
|
|
||||||
"description": "Array of NTP server addresses."
|
|
||||||
},
|
|
||||||
"servers": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"type": "object",
|
|
||||||
"required": ["hostname"],
|
|
||||||
"properties": {
|
|
||||||
"hostname": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Hostname or IP address of a NTP server."
|
|
||||||
},
|
|
||||||
"minpoll": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "Specifies the minimum interval between requests sent to the server as a power of 2 in seconds.",
|
|
||||||
"minimum": -6,
|
|
||||||
"maximum": 24
|
|
||||||
},
|
|
||||||
"maxpoll": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "Specifies the maximum interval between requests sent to the server as a power of 2 in seconds.",
|
|
||||||
"minimum": -6,
|
|
||||||
"maximum": 24
|
|
||||||
},
|
|
||||||
"iburst": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true,
|
|
||||||
"description": "Configures chronyd behavior related to burst requests on startup."
|
|
||||||
},
|
|
||||||
"prefer": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"description": "Prefer this source over sources without the prefer option."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"leapsectz": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Timezone used by chronyd to determine when will the next leap second occur. Empty value will remove the option."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
DELETE_TIME_SOURCE_LINE_REGEX = re.compile(r"(server|pool|peer) ")
|
DELETE_TIME_SOURCE_LINE_REGEX = re.compile(r"(server|pool|peer) ")
|
||||||
DELETE_LEAPSECTZ_LINE_REGEX = re.compile(r"leapsectz ")
|
DELETE_LEAPSECTZ_LINE_REGEX = re.compile(r"leapsectz ")
|
||||||
|
|
|
||||||
96
stages/org.osbuild.chrony.meta.json
Normal file
96
stages/org.osbuild.chrony.meta.json
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
{
|
||||||
|
"summary": "Configure chrony to set system time from the network.",
|
||||||
|
"description": [
|
||||||
|
"Configures `chrony` by modifying `/etc/chrony.conf`.",
|
||||||
|
"Before new values are added to the chrony configuration, all lines starting with",
|
||||||
|
"\"server\", \"pool\" or \"peer\" are removed.",
|
||||||
|
"The 'timeservers' option provides a very high-level way of configuring chronyd",
|
||||||
|
"with specific timeservers. Its value is a list of strings representing the",
|
||||||
|
"hostname or IP address of the timeserver. For each list item, the following",
|
||||||
|
"line will be added to the configuration:",
|
||||||
|
"`server <HOSTNAME/IP> iburst`",
|
||||||
|
"The 'servers' option provides a direct mapping to the `server` directive from",
|
||||||
|
"chrony configuration. Its value is a list of dictionaries representing each",
|
||||||
|
"timeserver which should be added to the configuration. For each list item,",
|
||||||
|
"a `server` directive will be added the configuration. Currently supported",
|
||||||
|
"subset of options which can be specified for each timeserver item:",
|
||||||
|
" - 'hostname' (REQUIRED)",
|
||||||
|
" - 'minpoll'",
|
||||||
|
" - 'maxpoll'",
|
||||||
|
" - 'iburst' (defaults to true)",
|
||||||
|
" - 'prefer' (defaults to false)",
|
||||||
|
"The 'leapsectz' option configures chrony behavior related to automatic checking",
|
||||||
|
"of the next occurrence of the leap second, using the provided timezone. Its",
|
||||||
|
"value is a string representing a timezone from the system tz database (e.g.",
|
||||||
|
"'right/UTC'). If an empty string is provided, then all occurrences of",
|
||||||
|
"'leapsectz' directive are removed from the configuration.",
|
||||||
|
"Constraints:",
|
||||||
|
" - Exactly one of 'timeservers' or 'servers' options must be provided."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"timeservers"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"servers"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"timeservers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "Array of NTP server addresses."
|
||||||
|
},
|
||||||
|
"servers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"hostname"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"hostname": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Hostname or IP address of a NTP server."
|
||||||
|
},
|
||||||
|
"minpoll": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Specifies the minimum interval between requests sent to the server as a power of 2 in seconds.",
|
||||||
|
"minimum": -6,
|
||||||
|
"maximum": 24
|
||||||
|
},
|
||||||
|
"maxpoll": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Specifies the maximum interval between requests sent to the server as a power of 2 in seconds.",
|
||||||
|
"minimum": -6,
|
||||||
|
"maximum": 24
|
||||||
|
},
|
||||||
|
"iburst": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Configures chronyd behavior related to burst requests on startup."
|
||||||
|
},
|
||||||
|
"prefer": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "Prefer this source over sources without the prefer option."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"leapsectz": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Timezone used by chronyd to determine when will the next leap second occur. Empty value will remove the option."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,49 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Bind a LUKS device using the specified policy.
|
|
||||||
|
|
||||||
Buildhost commands used: `clevis`, `clevis-luks`, `clevis-pin-*`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"devices": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true,
|
|
||||||
"required": ["device"],
|
|
||||||
"properties": {
|
|
||||||
"device": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["passphrase", "pin", "policy"],
|
|
||||||
"properties": {
|
|
||||||
"passphrase": {
|
|
||||||
"description": "Passphrase to unlock the container",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"pin": {
|
|
||||||
"description": "The pin to use",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"policy": {
|
|
||||||
"description": "Policy to use with the given pin",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(devices, options):
|
def main(devices, options):
|
||||||
device = devices["device"]
|
device = devices["device"]
|
||||||
|
|
|
||||||
43
stages/org.osbuild.clevis.luks-bind.meta.json
Normal file
43
stages/org.osbuild.clevis.luks-bind.meta.json
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
{
|
||||||
|
"summary": "Bind a LUKS device using the specified policy.",
|
||||||
|
"description": [
|
||||||
|
"Buildhost commands used: `clevis`, `clevis-luks`, `clevis-pin-*`."
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"devices": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true,
|
||||||
|
"required": [
|
||||||
|
"device"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"device": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"passphrase",
|
||||||
|
"pin",
|
||||||
|
"policy"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"passphrase": {
|
||||||
|
"description": "Passphrase to unlock the container",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"pin": {
|
||||||
|
"description": "The pin to use",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"policy": {
|
||||||
|
"description": "Policy to use with the given pin",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,146 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Configure cloud-init
|
|
||||||
|
|
||||||
The 'config' option allows to configure cloud-init by creating a
|
|
||||||
configuration file under `/etc/cloud/cloud.cfg.d` with the name
|
|
||||||
specified by `filename`.
|
|
||||||
|
|
||||||
Constrains:
|
|
||||||
- Each configuration file definition must contain at least one configuration
|
|
||||||
|
|
||||||
Currently supported subset of cloud-init configuration:
|
|
||||||
- 'system_info' section
|
|
||||||
- 'default_user' section
|
|
||||||
- 'name' option
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = r"""
|
|
||||||
"definitions": {
|
|
||||||
"reporting_handlers": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["log", "print", "webhook", "hyperv"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["config", "filename"],
|
|
||||||
"properties": {
|
|
||||||
"filename": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Name of the cloud-init configuration file.",
|
|
||||||
"pattern": "^[\\w.-]{1,251}\\.cfg$"
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"type": "object",
|
|
||||||
"description": "cloud-init configuration",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"system_info": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"type": "object",
|
|
||||||
"description": "'system_info' configuration section.",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"default_user": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"type": "object",
|
|
||||||
"description": "Configuration of the 'default' user created by cloud-init.",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "username of the 'default' user."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"reporting": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "Define reporting endpoints.",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"logging": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"$ref": "#/definitions/reporting_handlers"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"telemetry": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"$ref": "#/definitions/reporting_handlers"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"datasource_list": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["Azure"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"datasource": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Sources of configuration data for cloud-init.",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"Azure": {
|
|
||||||
"type": "object",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"apply_network_config": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Whether to use network configuration described by Azure’s IMDS endpoint",
|
|
||||||
"default": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"type": "object",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"init": {
|
|
||||||
"description": "Redirect the output of the init stage",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"description": "Redirect the output of the config stage",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"final": {
|
|
||||||
"description": "Redirect the output of the final stage",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"all": {
|
|
||||||
"description": "Redirect the output of all stages",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
# Class representing the 'datasource_list' configuration option,
|
# Class representing the 'datasource_list' configuration option,
|
||||||
# allowing to define a custom YAML dumper for it.
|
# allowing to define a custom YAML dumper for it.
|
||||||
|
|
|
||||||
142
stages/org.osbuild.cloud-init.meta.json
Normal file
142
stages/org.osbuild.cloud-init.meta.json
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
{
|
||||||
|
"summary": "Configure cloud-init",
|
||||||
|
"description": [
|
||||||
|
"The 'config' option allows to configure cloud-init by creating a",
|
||||||
|
"configuration file under `/etc/cloud/cloud.cfg.d` with the name",
|
||||||
|
"specified by `filename`.",
|
||||||
|
"Constrains:",
|
||||||
|
" - Each configuration file definition must contain at least one configuration",
|
||||||
|
"Currently supported subset of cloud-init configuration:",
|
||||||
|
" - 'system_info' section",
|
||||||
|
" - 'default_user' section",
|
||||||
|
" - 'name' option"
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"definitions": {
|
||||||
|
"reporting_handlers": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"log",
|
||||||
|
"print",
|
||||||
|
"webhook",
|
||||||
|
"hyperv"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"config",
|
||||||
|
"filename"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"filename": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Name of the cloud-init configuration file.",
|
||||||
|
"pattern": "^[\\w.-]{1,251}\\.cfg$"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"type": "object",
|
||||||
|
"description": "cloud-init configuration",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"system_info": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"type": "object",
|
||||||
|
"description": "'system_info' configuration section.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"default_user": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"type": "object",
|
||||||
|
"description": "Configuration of the 'default' user created by cloud-init.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "username of the 'default' user."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reporting": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Define reporting endpoints.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"logging": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/definitions/reporting_handlers"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"telemetry": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/definitions/reporting_handlers"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"datasource_list": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Azure"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"datasource": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Sources of configuration data for cloud-init.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"Azure": {
|
||||||
|
"type": "object",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"apply_network_config": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to use network configuration described by Azure\u2019s IMDS endpoint",
|
||||||
|
"default": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "object",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"init": {
|
||||||
|
"description": "Redirect the output of the init stage",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"description": "Redirect the output of the config stage",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"final": {
|
||||||
|
"description": "Redirect the output of the final stage",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"all": {
|
||||||
|
"description": "Redirect the output of all stages",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Deploy a container.
|
|
||||||
|
|
||||||
Buildhost commands used: podman skopeo
|
|
||||||
"""
|
|
||||||
import contextlib
|
import contextlib
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
|
|
@ -14,33 +9,6 @@ import sys
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
from osbuild.util import containers
|
from osbuild.util import containers
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"inputs": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["images"],
|
|
||||||
"properties": {
|
|
||||||
"images": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"exclude": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Exclude paths from the deployment",
|
|
||||||
"minItems": 1,
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def mount_container(image_tag):
|
def mount_container(image_tag):
|
||||||
|
|
|
||||||
34
stages/org.osbuild.container-deploy.meta.json
Normal file
34
stages/org.osbuild.container-deploy.meta.json
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"summary": "Deploy a container.",
|
||||||
|
"description": [
|
||||||
|
"Buildhost commands used: podman skopeo"
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"inputs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"images"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"images": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"exclude": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Exclude paths from the deployment",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Edit containers-storage.conf(5) files.
|
|
||||||
|
|
||||||
This stage can be used to create or modify `containers-storage.conf`
|
|
||||||
configuration files. The default strategy is to merge the specified
|
|
||||||
options with the existing options.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -19,126 +11,6 @@ except ModuleNotFoundError:
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = r"""
|
|
||||||
"definitions": {
|
|
||||||
"storage": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"driver": {
|
|
||||||
"description": "container storage driver.",
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"overlay",
|
|
||||||
"vfs",
|
|
||||||
"devmapper",
|
|
||||||
"aufs",
|
|
||||||
"btrfs",
|
|
||||||
"zfs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"graphroot": {
|
|
||||||
"description": "container storage graph directory.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"runroot": {
|
|
||||||
"description": "container storage run directory.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"transient_store": {
|
|
||||||
"description": "Make the container store not persist across reboot.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"$ref": "#/definitions/storage-options"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"storage-options": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"additionalimagestores": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pull_options": {
|
|
||||||
"$ref": "#/definitions/storage-options-pulloptions"
|
|
||||||
},
|
|
||||||
"overlay": {
|
|
||||||
"$ref": "#/definitions/storage-options-overlay"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"storage-options-pulloptions": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"enable_partial_images": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["true", "false"]
|
|
||||||
},
|
|
||||||
"use_hard_links": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["true", "false"]
|
|
||||||
},
|
|
||||||
"convert_images": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["true", "false"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"storage-options-overlay": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"mountopt": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["config"],
|
|
||||||
"properties": {
|
|
||||||
"filename": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "location of the configuration file.",
|
|
||||||
"default": "/etc/containers/storage.conf",
|
|
||||||
"enum": [
|
|
||||||
"/etc/containers/storage.conf",
|
|
||||||
"/usr/share/containers/storage.conf"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"filebase": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Read the base configuration from this file."
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"type": "object",
|
|
||||||
"description": "storage configuration",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"storage": {
|
|
||||||
"$ref": "#/definitions/storage"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
DEFAULT_LOCATION = "/etc/containers/storage.conf"
|
DEFAULT_LOCATION = "/etc/containers/storage.conf"
|
||||||
|
|
||||||
|
|
|
||||||
139
stages/org.osbuild.containers.storage.conf.meta.json
Normal file
139
stages/org.osbuild.containers.storage.conf.meta.json
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
{
|
||||||
|
"summary": "Edit containers-storage.conf(5) files.",
|
||||||
|
"description": [
|
||||||
|
"This stage can be used to create or modify `containers-storage.conf`",
|
||||||
|
"configuration files. The default strategy is to merge the specified",
|
||||||
|
"options with the existing options."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"definitions": {
|
||||||
|
"storage": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"driver": {
|
||||||
|
"description": "container storage driver.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"overlay",
|
||||||
|
"vfs",
|
||||||
|
"devmapper",
|
||||||
|
"aufs",
|
||||||
|
"btrfs",
|
||||||
|
"zfs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"graphroot": {
|
||||||
|
"description": "container storage graph directory.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"runroot": {
|
||||||
|
"description": "container storage run directory.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"transient_store": {
|
||||||
|
"description": "Make the container store not persist across reboot.",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"$ref": "#/definitions/storage-options"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"storage-options": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"additionalimagestores": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pull_options": {
|
||||||
|
"$ref": "#/definitions/storage-options-pulloptions"
|
||||||
|
},
|
||||||
|
"overlay": {
|
||||||
|
"$ref": "#/definitions/storage-options-overlay"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"storage-options-pulloptions": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"enable_partial_images": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"true",
|
||||||
|
"false"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"use_hard_links": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"true",
|
||||||
|
"false"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"convert_images": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"true",
|
||||||
|
"false"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"storage-options-overlay": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"mountopt": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"config"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"filename": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "location of the configuration file.",
|
||||||
|
"default": "/etc/containers/storage.conf",
|
||||||
|
"enum": [
|
||||||
|
"/etc/containers/storage.conf",
|
||||||
|
"/usr/share/containers/storage.conf"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"filebase": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Read the base configuration from this file."
|
||||||
|
},
|
||||||
|
"comment": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"type": "object",
|
||||||
|
"description": "storage configuration",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"storage": {
|
||||||
|
"$ref": "#/definitions/storage"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,24 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Copy items
|
|
||||||
|
|
||||||
Stage to copy items, that is files or trees, from inputs to mount
|
|
||||||
points or the tree. Multiple items can be copied. The source and
|
|
||||||
destination is an url. Supported locations ('schemes') are `tree`,
|
|
||||||
`mount` and `input`.
|
|
||||||
The path format follows the rsync convention that if the paths
|
|
||||||
ends with a slash `/` the content of that directory is copied not
|
|
||||||
the directory itself.
|
|
||||||
|
|
||||||
Note that the stage by default does not remove the destination
|
|
||||||
before copying. As a result, if the destination is an existing
|
|
||||||
symlink to a file, then this file will be overwritten, instead of
|
|
||||||
the symlink being replaced. If you want to replace the symlink
|
|
||||||
with a file, you need to set the `remove_destination` option to
|
|
||||||
`true`. This option works only for files, not directories or
|
|
||||||
symlinks to directories.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -27,79 +7,6 @@ from urllib.parse import ParseResult, urlparse
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
CAPABILITIES = ["CAP_MAC_ADMIN"]
|
|
||||||
|
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["paths"],
|
|
||||||
"properties": {
|
|
||||||
"paths": {
|
|
||||||
"description": "Array of items to copy",
|
|
||||||
"type": "array",
|
|
||||||
"minItems": 1,
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["from", "to"],
|
|
||||||
"properties": {
|
|
||||||
"from": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "The source, if an input",
|
|
||||||
"pattern": "^input:\/\/[^\/]+\/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "The source, if a mount",
|
|
||||||
"pattern": "^mount:\/\/[^\/]+\/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "The source, if the tree",
|
|
||||||
"pattern": "^tree:\/\/\/"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"to": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "The destination, if a mount",
|
|
||||||
"pattern": "^mount:\/\/[^\/]+\/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "The destination, if the tree",
|
|
||||||
"pattern": "^tree:\/\/\/"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"remove_destination": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Remove the destination before copying. Works only for files, not directories.",
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"devices": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
},
|
|
||||||
"mounts": {
|
|
||||||
"type": "array"
|
|
||||||
},
|
|
||||||
"inputs": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def parse_mount(url: ParseResult, args: Dict):
|
def parse_mount(url: ParseResult, args: Dict):
|
||||||
name = url.netloc
|
name = url.netloc
|
||||||
|
|
|
||||||
96
stages/org.osbuild.copy.meta.json
Normal file
96
stages/org.osbuild.copy.meta.json
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
{
|
||||||
|
"summary": "Copy items",
|
||||||
|
"description": [
|
||||||
|
"Stage to copy items, that is files or trees, from inputs to mount",
|
||||||
|
"points or the tree. Multiple items can be copied. The source and",
|
||||||
|
"destination is an url. Supported locations ('schemes') are `tree`,",
|
||||||
|
"`mount` and `input`.",
|
||||||
|
"The path format follows the rsync convention that if the paths",
|
||||||
|
"ends with a slash `/` the content of that directory is copied not",
|
||||||
|
"the directory itself.",
|
||||||
|
"Note that the stage by default does not remove the destination",
|
||||||
|
"before copying. As a result, if the destination is an existing",
|
||||||
|
"symlink to a file, then this file will be overwritten, instead of",
|
||||||
|
"the symlink being replaced. If you want to replace the symlink",
|
||||||
|
"with a file, you need to set the `remove_destination` option to",
|
||||||
|
"`true`. This option works only for files, not directories or",
|
||||||
|
"symlinks to directories."
|
||||||
|
],
|
||||||
|
"capabilities": [
|
||||||
|
"CAP_MAC_ADMIN"
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"paths"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"paths": {
|
||||||
|
"description": "Array of items to copy",
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"from",
|
||||||
|
"to"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"from": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "The source, if an input",
|
||||||
|
"pattern": "^input://[^/]+/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "The source, if a mount",
|
||||||
|
"pattern": "^mount://[^/]+/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "The source, if the tree",
|
||||||
|
"pattern": "^tree:///"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"to": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "The destination, if a mount",
|
||||||
|
"pattern": "^mount://[^/]+/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "The destination, if the tree",
|
||||||
|
"pattern": "^tree:///"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"remove_destination": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Remove the destination before copying. Works only for files, not directories.",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"devices": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
"mounts": {
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"inputs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,27 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Setup a CoreOS platform
|
|
||||||
|
|
||||||
In CoreOS we have the concept of a platform (i.e. AWS, GCP, Metal, QEMU)
|
|
||||||
where each platform has its own provided disk image with slightly
|
|
||||||
differing settings/behavior. This stage will perform the necessary
|
|
||||||
configuration for the given platform. This configuration boils down to
|
|
||||||
a few steps:
|
|
||||||
1. Locate the source of platform specific information that is provided
|
|
||||||
in the CoreOS filesystem tree already (the platforms.json).
|
|
||||||
2. Copy the platforms.json file into the /boot/ partition, which is
|
|
||||||
sometimes used by coreos-installer.
|
|
||||||
3. Read the platforms.json to fetch and platform specific kernel
|
|
||||||
arguments or grub configuration to set. These arguments/config
|
|
||||||
are primarily console settings.
|
|
||||||
4. Apply any platform specific kernel arguments along with the
|
|
||||||
`ignition.platform.id={platform-name}` kernel argument.
|
|
||||||
5. Create the grub console.cfg file and apply any platform
|
|
||||||
specific grub console configuration.
|
|
||||||
This stage is highly CoreOS specific and subject to change in the
|
|
||||||
future if/when we change the way platform specific information is
|
|
||||||
defined in our broader efforts to share more defaults with OSBuild.
|
|
||||||
"""
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
|
@ -30,24 +7,6 @@ import sys
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
from osbuild.util import bls
|
from osbuild.util import bls
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"platform": {
|
|
||||||
"description": "The target platform name/ID",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"devices": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
},
|
|
||||||
"mounts": {
|
|
||||||
"type": "array"
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
# For console.cfg see https://github.com/coreos/bootupd/pull/620
|
# For console.cfg see https://github.com/coreos/bootupd/pull/620
|
||||||
|
|
|
||||||
42
stages/org.osbuild.coreos.platform.meta.json
Normal file
42
stages/org.osbuild.coreos.platform.meta.json
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
"summary": "Setup a CoreOS platform",
|
||||||
|
"description": [
|
||||||
|
"In CoreOS we have the concept of a platform (i.e. AWS, GCP, Metal, QEMU)",
|
||||||
|
"where each platform has its own provided disk image with slightly",
|
||||||
|
"differing settings/behavior. This stage will perform the necessary",
|
||||||
|
"configuration for the given platform. This configuration boils down to",
|
||||||
|
"a few steps:",
|
||||||
|
"1. Locate the source of platform specific information that is provided",
|
||||||
|
" in the CoreOS filesystem tree already (the platforms.json).",
|
||||||
|
"2. Copy the platforms.json file into the /boot/ partition, which is",
|
||||||
|
" sometimes used by coreos-installer.",
|
||||||
|
"3. Read the platforms.json to fetch and platform specific kernel",
|
||||||
|
" arguments or grub configuration to set. These arguments/config",
|
||||||
|
" are primarily console settings.",
|
||||||
|
"4. Apply any platform specific kernel arguments along with the",
|
||||||
|
" `ignition.platform.id={platform-name}` kernel argument.",
|
||||||
|
"5. Create the grub console.cfg file and apply any platform",
|
||||||
|
" specific grub console configuration.",
|
||||||
|
"This stage is highly CoreOS specific and subject to change in the",
|
||||||
|
"future if/when we change the way platform specific information is",
|
||||||
|
"defined in our broader efforts to share more defaults with OSBuild."
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"platform": {
|
||||||
|
"description": "The target platform name/ID",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"devices": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
"mounts": {
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,80 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Assembles the tree into a CPIO archive.
|
|
||||||
|
|
||||||
Uses the buildhost's `cpio` command, to create an archive
|
|
||||||
at `filename` with the contents of the input `tree`. If
|
|
||||||
`append` is `true`, its files will be added to an existing
|
|
||||||
archive. The default format is `newc` , the "new (SVR4)
|
|
||||||
portable format", which is also used by `dracut`(8).
|
|
||||||
|
|
||||||
Buildhost commands used: `cpio`
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA_2 = """
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["filename"],
|
|
||||||
"properties": {
|
|
||||||
"filename": {
|
|
||||||
"description": "Filename for tar archive",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"append": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Append to an existing archive.",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"format": {
|
|
||||||
"description": "Archive format to use",
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["bin", "odc", "newc", "crc", "tar", "ustar"],
|
|
||||||
"default": "newc"
|
|
||||||
},
|
|
||||||
"root-node": {
|
|
||||||
"description": "How to handle the root node: include or omit",
|
|
||||||
"enum": ["include", "omit"],
|
|
||||||
"default": "include"
|
|
||||||
},
|
|
||||||
"reproducible": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Produce device-independent, reproducible archives.",
|
|
||||||
"default": true
|
|
||||||
},
|
|
||||||
"owner": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["user"],
|
|
||||||
"properties": {
|
|
||||||
"user": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"group": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inputs": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["tree"],
|
|
||||||
"properties": {
|
|
||||||
"tree": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def iter_files(tree, include):
|
def iter_files(tree, include):
|
||||||
for root, _, files in os.walk(tree, topdown=True):
|
for root, _, files in os.walk(tree, topdown=True):
|
||||||
|
|
|
||||||
84
stages/org.osbuild.cpio.out.meta.json
Normal file
84
stages/org.osbuild.cpio.out.meta.json
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
{
|
||||||
|
"summary": "Assembles the tree into a CPIO archive.",
|
||||||
|
"description": [
|
||||||
|
"Uses the buildhost's `cpio` command, to create an archive",
|
||||||
|
"at `filename` with the contents of the input `tree`. If",
|
||||||
|
"`append` is `true`, its files will be added to an existing",
|
||||||
|
"archive. The default format is `newc` , the \"new (SVR4)",
|
||||||
|
"portable format\", which is also used by `dracut`(8).",
|
||||||
|
"Buildhost commands used: `cpio`"
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"filename"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"filename": {
|
||||||
|
"description": "Filename for tar archive",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"append": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Append to an existing archive.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"format": {
|
||||||
|
"description": "Archive format to use",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"bin",
|
||||||
|
"odc",
|
||||||
|
"newc",
|
||||||
|
"crc",
|
||||||
|
"tar",
|
||||||
|
"ustar"
|
||||||
|
],
|
||||||
|
"default": "newc"
|
||||||
|
},
|
||||||
|
"root-node": {
|
||||||
|
"description": "How to handle the root node: include or omit",
|
||||||
|
"enum": [
|
||||||
|
"include",
|
||||||
|
"omit"
|
||||||
|
],
|
||||||
|
"default": "include"
|
||||||
|
},
|
||||||
|
"reproducible": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Produce device-independent, reproducible archives.",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"user": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"group": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inputs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"tree"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"tree": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,59 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Run a script at regular intervals.
|
|
||||||
|
|
||||||
Execute a script at regular intervals. This uses the cron drop-in
|
|
||||||
directories in etc, which correspond to the supported intervals:
|
|
||||||
`cron.hourly/`, `cron.daily/`, `cron.weekly/`, `cron.monthly/`
|
|
||||||
|
|
||||||
NB: Does itself not create the directories so they must be created
|
|
||||||
via the package that provides the facility, like `cronie` or on
|
|
||||||
older systems `crontabs`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["interval", "filename"],
|
|
||||||
"oneOf": [
|
|
||||||
{"required": ["simple"]}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"interval": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["hourly", "daily", "weekly", "monthly"]
|
|
||||||
},
|
|
||||||
"filename": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Name of the cron script",
|
|
||||||
"pattern": "^[\\w.-]{1,255}$"
|
|
||||||
},
|
|
||||||
"simple": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "A simple command to run.",
|
|
||||||
"required": ["command"],
|
|
||||||
"properties": {
|
|
||||||
"comment": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"command": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def format_comment(comment):
|
def format_comment(comment):
|
||||||
lines = comment.split("\n")
|
lines = comment.split("\n")
|
||||||
|
|
|
||||||
61
stages/org.osbuild.cron.script.meta.json
Normal file
61
stages/org.osbuild.cron.script.meta.json
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
{
|
||||||
|
"summary": "Run a script at regular intervals.",
|
||||||
|
"description": [
|
||||||
|
"Execute a script at regular intervals. This uses the cron drop-in",
|
||||||
|
"directories in etc, which correspond to the supported intervals:",
|
||||||
|
" `cron.hourly/`, `cron.daily/`, `cron.weekly/`, `cron.monthly/`",
|
||||||
|
"NB: Does itself not create the directories so they must be created",
|
||||||
|
"via the package that provides the facility, like `cronie` or on",
|
||||||
|
"older systems `crontabs`."
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"interval",
|
||||||
|
"filename"
|
||||||
|
],
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"simple"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"interval": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"hourly",
|
||||||
|
"daily",
|
||||||
|
"weekly",
|
||||||
|
"monthly"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"filename": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Name of the cron script",
|
||||||
|
"pattern": "^[\\w.-]{1,255}$"
|
||||||
|
},
|
||||||
|
"simple": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "A simple command to run.",
|
||||||
|
"required": [
|
||||||
|
"command"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"comment": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"command": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,66 +1,8 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Create /etc/crypttab entries for encrypted block devices
|
|
||||||
|
|
||||||
See crypttab(5) for a detailed description of the format but in brief:
|
|
||||||
each item in the list of `volumes` describes an encrypted block device
|
|
||||||
and how it should it should be setup. The block device is identified
|
|
||||||
either by `uuid` or by `path` (device node path). The volume will be
|
|
||||||
named as `volume`, i.e. made available as `/dev/mapper/$volume`.
|
|
||||||
Additionally, a keyfile can (optionally) be specified via `keyfile`.
|
|
||||||
Specific device options can be specified via `options`.
|
|
||||||
|
|
||||||
This stage replaces /etc/crypttab, removing any existing entries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["volumes"],
|
|
||||||
"properties": {
|
|
||||||
"volumes": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "array of volume objects",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"oneOf": [{
|
|
||||||
"required": ["uuid", "volume"]
|
|
||||||
}, {
|
|
||||||
"required": ["path", "volume"]
|
|
||||||
}],
|
|
||||||
"properties": {
|
|
||||||
"volume": {
|
|
||||||
"description": "volume mountpoint",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"uuid": {
|
|
||||||
"description": "device UUID",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"path": {
|
|
||||||
"description": "device path",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"keyfile": {
|
|
||||||
"description": "",
|
|
||||||
"type": "string",
|
|
||||||
"default": "none"
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"description": "options (comma-separated)",
|
|
||||||
"type": "string",
|
|
||||||
"default": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
volumes = options["volumes"]
|
volumes = options["volumes"]
|
||||||
|
|
|
||||||
66
stages/org.osbuild.crypttab.meta.json
Normal file
66
stages/org.osbuild.crypttab.meta.json
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
{
|
||||||
|
"summary": "Create /etc/crypttab entries for encrypted block devices",
|
||||||
|
"description": [
|
||||||
|
"See crypttab(5) for a detailed description of the format but in brief:",
|
||||||
|
"each item in the list of `volumes` describes an encrypted block device",
|
||||||
|
"and how it should it should be setup. The block device is identified",
|
||||||
|
"either by `uuid` or by `path` (device node path). The volume will be",
|
||||||
|
"named as `volume`, i.e. made available as `/dev/mapper/$volume`.",
|
||||||
|
"Additionally, a keyfile can (optionally) be specified via `keyfile`.",
|
||||||
|
"Specific device options can be specified via `options`.",
|
||||||
|
"This stage replaces /etc/crypttab, removing any existing entries."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"volumes"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"volumes": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "array of volume objects",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"uuid",
|
||||||
|
"volume"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"path",
|
||||||
|
"volume"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"volume": {
|
||||||
|
"description": "volume mountpoint",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"description": "device UUID",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"description": "device path",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"keyfile": {
|
||||||
|
"description": "",
|
||||||
|
"type": "string",
|
||||||
|
"default": "none"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"description": "options (comma-separated)",
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,30 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Set up an early root shell on a certain tty
|
|
||||||
|
|
||||||
Creates a systemd unit file at /etc/systemd/system/osbuild-debug-shell.service
|
|
||||||
which starts an early-boot root shell on the given `tty`.
|
|
||||||
|
|
||||||
Also symlinks the service file into /etc/systemd/system/sysinit.target.wants/.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["tty"],
|
|
||||||
"properties": {
|
|
||||||
"tty": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Absolute path of the tty device to start a root shell on."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
tty = options["tty"]
|
tty = options["tty"]
|
||||||
|
|
|
||||||
20
stages/org.osbuild.debug-shell.meta.json
Normal file
20
stages/org.osbuild.debug-shell.meta.json
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"summary": "Set up an early root shell on a certain tty",
|
||||||
|
"description": [
|
||||||
|
"Creates a systemd unit file at /etc/systemd/system/osbuild-debug-shell.service",
|
||||||
|
"which starts an early-boot root shell on the given `tty`.",
|
||||||
|
"Also symlinks the service file into /etc/systemd/system/sysinit.target.wants/."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"tty"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"tty": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Absolute path of the tty device to start a root shell on."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,31 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Create a `.discinfo` file describing disk
|
|
||||||
|
|
||||||
This will create a `.discinfo` file with the specified parameters.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": true,
|
|
||||||
"required": ["basearch", "release"],
|
|
||||||
"properties": {
|
|
||||||
"basearch": {
|
|
||||||
"description": "Build architecture.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"release": {
|
|
||||||
"description": "The product name.",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
basearch = options["basearch"]
|
basearch = options["basearch"]
|
||||||
|
|
|
||||||
23
stages/org.osbuild.discinfo.meta.json
Normal file
23
stages/org.osbuild.discinfo.meta.json
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"summary": "Create a `.discinfo` file describing disk",
|
||||||
|
"description": [
|
||||||
|
"This will create a `.discinfo` file with the specified parameters."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": true,
|
||||||
|
"required": [
|
||||||
|
"basearch",
|
||||||
|
"release"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"basearch": {
|
||||||
|
"description": "Build architecture.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"release": {
|
||||||
|
"description": "The product name.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,56 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Change DNF Automatic configuration.
|
|
||||||
|
|
||||||
The stage changes persistent DNF Automatic configuration. Currently, only
|
|
||||||
a subset of options can be set:
|
|
||||||
- 'commands' section
|
|
||||||
- apply_updates
|
|
||||||
- upgrade_type
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import iniparse
|
import iniparse
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = r"""
|
|
||||||
"definitions": {
|
|
||||||
"commands": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "'commands' configuration section.",
|
|
||||||
"properties": {
|
|
||||||
"apply_updates": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Whether packages comprising the available updates should be installed."
|
|
||||||
},
|
|
||||||
"upgrade_type": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "What kind of upgrades to look at.",
|
|
||||||
"enum": ["default", "security"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "DNF Automatic configuration.",
|
|
||||||
"properties": {
|
|
||||||
"config": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "configuration definition.",
|
|
||||||
"properties": {
|
|
||||||
"commands": {
|
|
||||||
"$ref": "#/definitions/commands"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def bool_to_yes_no(b):
|
def bool_to_yes_no(b):
|
||||||
if b:
|
if b:
|
||||||
|
|
|
||||||
47
stages/org.osbuild.dnf-automatic.config.meta.json
Normal file
47
stages/org.osbuild.dnf-automatic.config.meta.json
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"summary": "Change DNF Automatic configuration.",
|
||||||
|
"description": [
|
||||||
|
"The stage changes persistent DNF Automatic configuration. Currently, only",
|
||||||
|
"a subset of options can be set:",
|
||||||
|
" - 'commands' section",
|
||||||
|
" - apply_updates",
|
||||||
|
" - upgrade_type"
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"definitions": {
|
||||||
|
"commands": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "'commands' configuration section.",
|
||||||
|
"properties": {
|
||||||
|
"apply_updates": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether packages comprising the available updates should be installed."
|
||||||
|
},
|
||||||
|
"upgrade_type": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "What kind of upgrades to look at.",
|
||||||
|
"enum": [
|
||||||
|
"default",
|
||||||
|
"security"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "DNF Automatic configuration.",
|
||||||
|
"properties": {
|
||||||
|
"config": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "configuration definition.",
|
||||||
|
"properties": {
|
||||||
|
"commands": {
|
||||||
|
"$ref": "#/definitions/commands"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,15 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Change DNF configuration.
|
|
||||||
|
|
||||||
The stage changes persistent DNF configuration on the filesystem.
|
|
||||||
|
|
||||||
Allows defining dnf variables via the `variables` option and
|
|
||||||
specific configuration options via the `config` option. The
|
|
||||||
latter will be saved in `/etc/dnf/dnf.conf`. See `dnf.conf(5)`
|
|
||||||
for details about the configuration options.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
@ -17,79 +6,6 @@ import iniparse
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = r"""
|
|
||||||
"definitions": {
|
|
||||||
"variable": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["name", "value"],
|
|
||||||
"description": "DNF variable to configure persistently.",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[a-z0-9_]+$",
|
|
||||||
"description": "Name of the variable."
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Value of the variable."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"config_main": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"ip_resolve": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["4", "IPv4", "6", "IPv6"],
|
|
||||||
"description": "Determines how DNF resolves host names."
|
|
||||||
},
|
|
||||||
"tsflags": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Extra flags for the RPM transaction.",
|
|
||||||
"minItems": 1,
|
|
||||||
"uniqueItems": true,
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"noscripts",
|
|
||||||
"test",
|
|
||||||
"notriggers",
|
|
||||||
"nodocs",
|
|
||||||
"justdb",
|
|
||||||
"nocontexts",
|
|
||||||
"nocaps",
|
|
||||||
"nocrypto"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "DNF configuration.",
|
|
||||||
"properties": {
|
|
||||||
"variables": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "DNF variables to configure persistently.",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/variable"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"type": "object",
|
|
||||||
"description": "DNF global configuration.",
|
|
||||||
"properties": {
|
|
||||||
"main": {
|
|
||||||
"$ref": "#/definitions/config_main"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def configure_variable(tree, name, value):
|
def configure_variable(tree, name, value):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
90
stages/org.osbuild.dnf.config.meta.json
Normal file
90
stages/org.osbuild.dnf.config.meta.json
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
{
|
||||||
|
"summary": "Change DNF configuration.",
|
||||||
|
"description": [
|
||||||
|
"The stage changes persistent DNF configuration on the filesystem.",
|
||||||
|
"Allows defining dnf variables via the `variables` option and",
|
||||||
|
"specific configuration options via the `config` option. The",
|
||||||
|
"latter will be saved in `/etc/dnf/dnf.conf`. See `dnf.conf(5)`",
|
||||||
|
"for details about the configuration options."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"definitions": {
|
||||||
|
"variable": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"description": "DNF variable to configure persistently.",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[a-z0-9_]+$",
|
||||||
|
"description": "Name of the variable."
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Value of the variable."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config_main": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"ip_resolve": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"4",
|
||||||
|
"IPv4",
|
||||||
|
"6",
|
||||||
|
"IPv6"
|
||||||
|
],
|
||||||
|
"description": "Determines how DNF resolves host names."
|
||||||
|
},
|
||||||
|
"tsflags": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Extra flags for the RPM transaction.",
|
||||||
|
"minItems": 1,
|
||||||
|
"uniqueItems": true,
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"noscripts",
|
||||||
|
"test",
|
||||||
|
"notriggers",
|
||||||
|
"nodocs",
|
||||||
|
"justdb",
|
||||||
|
"nocontexts",
|
||||||
|
"nocaps",
|
||||||
|
"nocrypto"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "DNF configuration.",
|
||||||
|
"properties": {
|
||||||
|
"variables": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "DNF variables to configure persistently.",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/variable"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"type": "object",
|
||||||
|
"description": "DNF global configuration.",
|
||||||
|
"properties": {
|
||||||
|
"main": {
|
||||||
|
"$ref": "#/definitions/config_main"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,43 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Mark packages in the DNF state database.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from osbuild import api
|
from osbuild import api
|
||||||
|
|
||||||
SCHEMA_2 = """
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"packages": {
|
|
||||||
"type": "array",
|
|
||||||
"minItems": 1,
|
|
||||||
"description": "Packages and their marks.",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["name", "mark"],
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Package name."
|
|
||||||
},
|
|
||||||
"mark": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["install", "group"],
|
|
||||||
"description": "Package mark."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def mark(tree, packages):
|
def mark(tree, packages):
|
||||||
dnf_bin = shutil.which("dnf-3")
|
dnf_bin = shutil.which("dnf-3")
|
||||||
|
|
|
||||||
38
stages/org.osbuild.dnf4.mark.meta.json
Normal file
38
stages/org.osbuild.dnf4.mark.meta.json
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"summary": "Mark packages in the DNF state database.",
|
||||||
|
"description": [],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"packages": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"description": "Packages and their marks.",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"mark"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Package name."
|
||||||
|
},
|
||||||
|
"mark": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"install",
|
||||||
|
"group"
|
||||||
|
],
|
||||||
|
"description": "Package mark."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,141 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Create (re-create) the initial RAM file-system
|
|
||||||
|
|
||||||
Uses `dracut` to re-create the initial RAM filesystem, see man dracut(8).
|
|
||||||
The kernels for which the initramfs should be generated need to be provided
|
|
||||||
via `kernel` matching their name on the disk, like "5.6.6-300.fc32.x86_64".
|
|
||||||
|
|
||||||
Supports most options also found in `dracut`(8). See the respective man
|
|
||||||
page and schema for this stage.
|
|
||||||
|
|
||||||
NB: needs chroot for now as well as `strip` for stripping the initrfams.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"required": ["kernel"],
|
|
||||||
"properties": {
|
|
||||||
"kernel": {
|
|
||||||
"description": "List of target kernel versions",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A kernel version"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compress": {
|
|
||||||
"description": "Compress the initramfs, passed via `--compress`",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"modules": {
|
|
||||||
"description": "Exact list of dracut modules to use.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A dracut module, e.g. base, nfs, network ..."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"add_modules": {
|
|
||||||
"description": "Additional dracut modules to include.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A dracut module, e.g. base, nfs, network ..."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"omit_modules": {
|
|
||||||
"description": "Dracut modules to not include.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A dracut module, e.g. base, nfs, network ..."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"drivers": {
|
|
||||||
"description": "Kernel modules to exclusively include.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A kernel module without the .ko extension"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"add_drivers": {
|
|
||||||
"description": "Add a specific kernel modules.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A kernel module without the .ko extension"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"omit_drivers": {
|
|
||||||
"description": "Omit specific kernel modules.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A kernel module without the .ko extension."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"force_drivers": {
|
|
||||||
"description": "Add driver and ensure that they are tried to be loaded.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A kernel module without the .ko extension"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"filesystems": {
|
|
||||||
"description": "Kernel filesystem modules to exclusively include.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A kernel module without the .ko extension"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"include": {
|
|
||||||
"description": "Add custom files to the initramfs.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "What (keys) to include where (values)"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"install": {
|
|
||||||
"description": "Install the specified files.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"early_microcode": {
|
|
||||||
"description": "Combine early microcode with the initramfs.",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"reproducible": {
|
|
||||||
"description": "Create reproducible images.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"initoverlayfs": {
|
|
||||||
"description": "Use initoverlayfs rather than initramfs, requires initoverlayfs rpm to be installed",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"extra": {
|
|
||||||
"description": "Extra arguments to directly pass to dracut",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Individual extra arguments"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def yesno(name: str, value: bool) -> str:
|
def yesno(name: str, value: bool) -> str:
|
||||||
prefix = "" if value else "no-"
|
prefix = "" if value else "no-"
|
||||||
|
|
|
||||||
|
|
@ -1,138 +1,8 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Configure dracut.
|
|
||||||
|
|
||||||
The 'config' option allows to create a dracut configuration file under
|
|
||||||
`/usr/lib/dracut/dracut.conf.d/` with the name `filename`. Only a subset
|
|
||||||
of configuration options is supported, with the intention to provide
|
|
||||||
functional parity with `org.osbuild.dracut` stage.
|
|
||||||
|
|
||||||
Constrains:
|
|
||||||
- At least one configuration option must be specified for each configuration
|
|
||||||
|
|
||||||
Supported configuration options:
|
|
||||||
- compress
|
|
||||||
- dracutmodules
|
|
||||||
- add_dracutmodules
|
|
||||||
- omit_dracutmodules
|
|
||||||
- drivers
|
|
||||||
- add_drivers
|
|
||||||
- omit_drivers
|
|
||||||
- force_drivers
|
|
||||||
- filesystems
|
|
||||||
- install_items
|
|
||||||
- early_microcode
|
|
||||||
- reproducible
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = r"""
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["config", "filename"],
|
|
||||||
"properties": {
|
|
||||||
"filename": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Name of the dracut configuration file.",
|
|
||||||
"pattern": "^[\\w.-]{1,250}\\.conf$"
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"type": "object",
|
|
||||||
"description": "dracut configuration.",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"compress": {
|
|
||||||
"description": "Compress the generated initramfs using the passed compression program.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"dracutmodules": {
|
|
||||||
"description": "Exact list of dracut modules to use.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A dracut module, e.g. base, nfs, network ..."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"add_dracutmodules": {
|
|
||||||
"description": "Additional dracut modules to include.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A dracut module, e.g. base, nfs, network ..."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"omit_dracutmodules": {
|
|
||||||
"description": "Dracut modules to not include.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A dracut module, e.g. base, nfs, network ..."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"drivers": {
|
|
||||||
"description": "Kernel modules to exclusively include.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A kernel module without the .ko extension."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"add_drivers": {
|
|
||||||
"description": "Add a specific kernel modules.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A kernel module without the .ko extension."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"omit_drivers": {
|
|
||||||
"description": "Omit specific kernel modules.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A kernel module without the .ko extension."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"force_drivers": {
|
|
||||||
"description": "Add driver and ensure that they are tried to be loaded.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A kernel module without the .ko extension."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"filesystems": {
|
|
||||||
"description": "Kernel filesystem modules to exclusively include.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A kernel module without the .ko extension."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"install_items": {
|
|
||||||
"description": "Install the specified files.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Specify additional files to include in the initramfs."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"early_microcode": {
|
|
||||||
"description": "Combine early microcode with the initramfs.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"reproducible": {
|
|
||||||
"description": "Create reproducible images.",
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def bool_to_string(value):
|
def bool_to_string(value):
|
||||||
return "yes" if value else "no"
|
return "yes" if value else "no"
|
||||||
|
|
|
||||||
130
stages/org.osbuild.dracut.conf.meta.json
Normal file
130
stages/org.osbuild.dracut.conf.meta.json
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
{
|
||||||
|
"summary": "Configure dracut.",
|
||||||
|
"description": [
|
||||||
|
"The 'config' option allows to create a dracut configuration file under",
|
||||||
|
"`/usr/lib/dracut/dracut.conf.d/` with the name `filename`. Only a subset",
|
||||||
|
"of configuration options is supported, with the intention to provide",
|
||||||
|
"functional parity with `org.osbuild.dracut` stage.",
|
||||||
|
"Constrains:",
|
||||||
|
" - At least one configuration option must be specified for each configuration",
|
||||||
|
"Supported configuration options:",
|
||||||
|
" - compress",
|
||||||
|
" - dracutmodules",
|
||||||
|
" - add_dracutmodules",
|
||||||
|
" - omit_dracutmodules",
|
||||||
|
" - drivers",
|
||||||
|
" - add_drivers",
|
||||||
|
" - omit_drivers",
|
||||||
|
" - force_drivers",
|
||||||
|
" - filesystems",
|
||||||
|
" - install_items",
|
||||||
|
" - early_microcode",
|
||||||
|
" - reproducible"
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"config",
|
||||||
|
"filename"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"filename": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Name of the dracut configuration file.",
|
||||||
|
"pattern": "^[\\w.-]{1,250}\\.conf$"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"type": "object",
|
||||||
|
"description": "dracut configuration.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"compress": {
|
||||||
|
"description": "Compress the generated initramfs using the passed compression program.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"dracutmodules": {
|
||||||
|
"description": "Exact list of dracut modules to use.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A dracut module, e.g. base, nfs, network ..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"add_dracutmodules": {
|
||||||
|
"description": "Additional dracut modules to include.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A dracut module, e.g. base, nfs, network ..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"omit_dracutmodules": {
|
||||||
|
"description": "Dracut modules to not include.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A dracut module, e.g. base, nfs, network ..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"drivers": {
|
||||||
|
"description": "Kernel modules to exclusively include.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A kernel module without the .ko extension."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"add_drivers": {
|
||||||
|
"description": "Add a specific kernel modules.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A kernel module without the .ko extension."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"omit_drivers": {
|
||||||
|
"description": "Omit specific kernel modules.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A kernel module without the .ko extension."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"force_drivers": {
|
||||||
|
"description": "Add driver and ensure that they are tried to be loaded.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A kernel module without the .ko extension."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filesystems": {
|
||||||
|
"description": "Kernel filesystem modules to exclusively include.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A kernel module without the .ko extension."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"install_items": {
|
||||||
|
"description": "Install the specified files.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Specify additional files to include in the initramfs."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"early_microcode": {
|
||||||
|
"description": "Combine early microcode with the initramfs.",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"reproducible": {
|
||||||
|
"description": "Create reproducible images.",
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
131
stages/org.osbuild.dracut.meta.json
Normal file
131
stages/org.osbuild.dracut.meta.json
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
{
|
||||||
|
"summary": "Create (re-create) the initial RAM file-system",
|
||||||
|
"description": [
|
||||||
|
"Uses `dracut` to re-create the initial RAM filesystem, see man dracut(8).",
|
||||||
|
"The kernels for which the initramfs should be generated need to be provided",
|
||||||
|
"via `kernel` matching their name on the disk, like \"5.6.6-300.fc32.x86_64\".",
|
||||||
|
"Supports most options also found in `dracut`(8). See the respective man",
|
||||||
|
"page and schema for this stage.",
|
||||||
|
"NB: needs chroot for now as well as `strip` for stripping the initrfams."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"required": [
|
||||||
|
"kernel"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"kernel": {
|
||||||
|
"description": "List of target kernel versions",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A kernel version"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compress": {
|
||||||
|
"description": "Compress the initramfs, passed via `--compress`",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"modules": {
|
||||||
|
"description": "Exact list of dracut modules to use.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A dracut module, e.g. base, nfs, network ..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"add_modules": {
|
||||||
|
"description": "Additional dracut modules to include.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A dracut module, e.g. base, nfs, network ..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"omit_modules": {
|
||||||
|
"description": "Dracut modules to not include.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A dracut module, e.g. base, nfs, network ..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"drivers": {
|
||||||
|
"description": "Kernel modules to exclusively include.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A kernel module without the .ko extension"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"add_drivers": {
|
||||||
|
"description": "Add a specific kernel modules.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A kernel module without the .ko extension"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"omit_drivers": {
|
||||||
|
"description": "Omit specific kernel modules.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A kernel module without the .ko extension."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"force_drivers": {
|
||||||
|
"description": "Add driver and ensure that they are tried to be loaded.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A kernel module without the .ko extension"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filesystems": {
|
||||||
|
"description": "Kernel filesystem modules to exclusively include.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A kernel module without the .ko extension"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": {
|
||||||
|
"description": "Add custom files to the initramfs.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "What (keys) to include where (values)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"install": {
|
||||||
|
"description": "Install the specified files.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"early_microcode": {
|
||||||
|
"description": "Combine early microcode with the initramfs.",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"reproducible": {
|
||||||
|
"description": "Create reproducible images.",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"initoverlayfs": {
|
||||||
|
"description": "Use initoverlayfs rather than initramfs, requires initoverlayfs rpm to be installed",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"description": "Extra arguments to directly pass to dracut",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Individual extra arguments"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,76 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Create a file containing an erofs filesystem named `filename`.
|
|
||||||
|
|
||||||
See https://en.wikipedia.org/wiki/EROFS for details about the
|
|
||||||
filesystem.
|
|
||||||
|
|
||||||
Buildhost commands used: `mkfs.erofs`
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA_2 = """
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["filename"],
|
|
||||||
"properties": {
|
|
||||||
"filename": {
|
|
||||||
"description": "Filename for the output",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"compression": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["method"],
|
|
||||||
"properties": {
|
|
||||||
"method": {
|
|
||||||
"description": "Compression method",
|
|
||||||
"enum": ["lz4", "lz4hc", "lzma"]
|
|
||||||
},
|
|
||||||
"level": {
|
|
||||||
"description": "Compression level. Note that different methods support different levels. See mkfs.erofs(1) for more details",
|
|
||||||
"type": "number"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"description": "Extended options for the filesystem, see mkfs.erofs(1)",
|
|
||||||
"type": "array",
|
|
||||||
"minItems": 1,
|
|
||||||
"items:": {
|
|
||||||
"enum": [
|
|
||||||
"all-fragments",
|
|
||||||
"dedupe",
|
|
||||||
"force-inode-compact",
|
|
||||||
"force-inode-extended",
|
|
||||||
"force-inode-blockmap",
|
|
||||||
"force-chunk-indexes",
|
|
||||||
"fragments",
|
|
||||||
"noinline_data",
|
|
||||||
"ztailpacking"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inputs": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["tree"],
|
|
||||||
"properties": {
|
|
||||||
"tree": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(inputs, output_dir, options):
|
def main(inputs, output_dir, options):
|
||||||
source = inputs["tree"]["path"]
|
source = inputs["tree"]["path"]
|
||||||
|
|
|
||||||
74
stages/org.osbuild.erofs.meta.json
Normal file
74
stages/org.osbuild.erofs.meta.json
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
{
|
||||||
|
"summary": "Create a file containing an erofs filesystem named `filename`.",
|
||||||
|
"description": [
|
||||||
|
"See https://en.wikipedia.org/wiki/EROFS for details about the",
|
||||||
|
"filesystem.",
|
||||||
|
"Buildhost commands used: `mkfs.erofs`"
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"filename"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"filename": {
|
||||||
|
"description": "Filename for the output",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"compression": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"method"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"method": {
|
||||||
|
"description": "Compression method",
|
||||||
|
"enum": [
|
||||||
|
"lz4",
|
||||||
|
"lz4hc",
|
||||||
|
"lzma"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"level": {
|
||||||
|
"description": "Compression level. Note that different methods support different levels. See mkfs.erofs(1) for more details",
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"description": "Extended options for the filesystem, see mkfs.erofs(1)",
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items:": {
|
||||||
|
"enum": [
|
||||||
|
"all-fragments",
|
||||||
|
"dedupe",
|
||||||
|
"force-inode-compact",
|
||||||
|
"force-inode-extended",
|
||||||
|
"force-inode-blockmap",
|
||||||
|
"force-chunk-indexes",
|
||||||
|
"fragments",
|
||||||
|
"noinline_data",
|
||||||
|
"ztailpacking"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inputs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"tree"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"tree": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,27 +1,8 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Return an error
|
|
||||||
|
|
||||||
Error stage. Return the given error. Useful for testing, debugging, and
|
|
||||||
wasting time.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"returncode": {
|
|
||||||
"description": "What to return code to use",
|
|
||||||
"type": "number",
|
|
||||||
"default": 255
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(_tree, options):
|
def main(_tree, options):
|
||||||
errno = options.get("returncode", 255)
|
errno = options.get("returncode", 255)
|
||||||
|
|
|
||||||
17
stages/org.osbuild.error.meta.json
Normal file
17
stages/org.osbuild.error.meta.json
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"summary": "Return an error",
|
||||||
|
"description": [
|
||||||
|
"Error stage. Return the given error. Useful for testing, debugging, and",
|
||||||
|
"wasting time."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"returncode": {
|
||||||
|
"description": "What to return code to use",
|
||||||
|
"type": "number",
|
||||||
|
"default": 255
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,52 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Change OSTree configuration experimental options
|
|
||||||
|
|
||||||
NOTE: This stage is experimental and subject to changes
|
|
||||||
|
|
||||||
Change the configuration for an OSTree repository.
|
|
||||||
Currently only the following values are supported:
|
|
||||||
- `integrity.composefs`
|
|
||||||
|
|
||||||
See `ostree.repo-config(5)` for more information.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
from osbuild.util import ostree
|
from osbuild.util import ostree
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["repo"],
|
|
||||||
"properties": {
|
|
||||||
"repo": {
|
|
||||||
"description": "Location of the OSTree repo.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "OSTree configuration groups",
|
|
||||||
"properties": {
|
|
||||||
"integrity": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "Options concerning the sysroot",
|
|
||||||
"properties": {
|
|
||||||
"composefs": {
|
|
||||||
"description": "Enable composefs image generation on deploy.",
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["true", "false", "maybe"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
repo = os.path.join(tree, options["repo"].lstrip("/"))
|
repo = os.path.join(tree, options["repo"].lstrip("/"))
|
||||||
|
|
|
||||||
45
stages/org.osbuild.experimental.ostree.config.meta.json
Normal file
45
stages/org.osbuild.experimental.ostree.config.meta.json
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"summary": "Change OSTree configuration experimental options",
|
||||||
|
"description": [
|
||||||
|
"NOTE: This stage is experimental and subject to changes",
|
||||||
|
"Change the configuration for an OSTree repository.",
|
||||||
|
"Currently only the following values are supported:",
|
||||||
|
" - `integrity.composefs`",
|
||||||
|
"See `ostree.repo-config(5)` for more information."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"repo"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"repo": {
|
||||||
|
"description": "Location of the OSTree repo.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "OSTree configuration groups",
|
||||||
|
"properties": {
|
||||||
|
"integrity": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Options concerning the sysroot",
|
||||||
|
"properties": {
|
||||||
|
"composefs": {
|
||||||
|
"description": "Enable composefs image generation on deploy.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"true",
|
||||||
|
"false",
|
||||||
|
"maybe"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,37 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
FDO initial DIUN certificates
|
|
||||||
|
|
||||||
FDO stage to write down the initial DIUN pub key root certificates
|
|
||||||
to be read by the manufacturer client
|
|
||||||
|
|
||||||
This will create a '/fdo_diun_root_certs.pem' with content
|
|
||||||
specified via the `rootcerts` input.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"inputs": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["rootcerts"],
|
|
||||||
"properties": {
|
|
||||||
"rootcerts": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def parse_input(inputs):
|
def parse_input(inputs):
|
||||||
image = inputs["rootcerts"]
|
image = inputs["rootcerts"]
|
||||||
|
|
|
||||||
27
stages/org.osbuild.fdo.meta.json
Normal file
27
stages/org.osbuild.fdo.meta.json
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"summary": "FDO initial DIUN certificates",
|
||||||
|
"description": [
|
||||||
|
"FDO stage to write down the initial DIUN pub key root certificates",
|
||||||
|
"to be read by the manufacturer client",
|
||||||
|
"This will create a '/fdo_diun_root_certs.pem' with content",
|
||||||
|
"specified via the `rootcerts` input."
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"inputs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"rootcerts"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"rootcerts": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,98 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Configure firewall
|
|
||||||
|
|
||||||
Configure firewalld using the `firewall-offline-cmd` from inside the target.
|
|
||||||
|
|
||||||
This stage adds each of the given `ports` and `enabled_services` to the default
|
|
||||||
firewall zone using the `--port` and `--service` options, then removes the
|
|
||||||
services listed in `disabled_services` with `--remove-service`.
|
|
||||||
|
|
||||||
Ports should be specified as "portid:protocol" or "portid-portid:protocol",
|
|
||||||
where "portid" is a number (or a port name from `/etc/services`, like "ssh" or
|
|
||||||
"echo") and "protocol" is one of "tcp", "udp", "sctp", or "dccp".
|
|
||||||
|
|
||||||
Enabling or disabling a service that is already enabled or disabled will not
|
|
||||||
cause an error.
|
|
||||||
|
|
||||||
Attempting to enable/disable an unknown service name will cause this stage to
|
|
||||||
fail. Known service names are determined by the contents of firewalld's
|
|
||||||
configuration directories, usually `/{lib,etc}/firewalld/services/*.xml`, and
|
|
||||||
may vary from release to release.
|
|
||||||
|
|
||||||
WARNING: this stage uses `chroot` to run `firewall-offline-cmd` inside the
|
|
||||||
target tree, which means it may fail unexpectedly when the buildhost and target
|
|
||||||
are different arches or OSes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"ports": {
|
|
||||||
"description": "Ports (or port ranges) to open",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A port or port range: 'portid[-portid]:protocol'",
|
|
||||||
"pattern": ".:(tcp|udp|sctp|dccp)$"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"enabled_services": {
|
|
||||||
"description": "Network services to allow in the default firewall zone",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Service name (from /{lib,etc}/firewalld/services/*.xml)"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"disabled_services": {
|
|
||||||
"description": "Network services to remove from the default firewall zone",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Service name (from /{lib,etc}/firewalld/services/*.xml)"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"default_zone": {
|
|
||||||
"description": "Set default zone for connections and interfaces where no zone has been selected.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"zones": {
|
|
||||||
"description": "Bind a list of network sources to a zone to restrict traffic from those sources based on the settings of the zone.",
|
|
||||||
"type": "array",
|
|
||||||
"minItems": 1,
|
|
||||||
"items": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"type": "object",
|
|
||||||
"description": "configuration for each zone",
|
|
||||||
"required": ["name", "sources"],
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "name of the zone, if left empty the sources will apply to the default zone.",
|
|
||||||
"pattern": "^[a-zA-Z0-9_-]+$"
|
|
||||||
},
|
|
||||||
"sources": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "list of sources for the zone",
|
|
||||||
"items": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"type": "string",
|
|
||||||
"description": "A source: <source>[/<mask>]|<MAC>|ipset:<ipset>"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
# Takes a list of <port|application protocol>:<transport protocol> pairs
|
# Takes a list of <port|application protocol>:<transport protocol> pairs
|
||||||
|
|
|
||||||
85
stages/org.osbuild.firewall.meta.json
Normal file
85
stages/org.osbuild.firewall.meta.json
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
{
|
||||||
|
"summary": "Configure firewall",
|
||||||
|
"description": [
|
||||||
|
"Configure firewalld using the `firewall-offline-cmd` from inside the target.",
|
||||||
|
"This stage adds each of the given `ports` and `enabled_services` to the default",
|
||||||
|
"firewall zone using the `--port` and `--service` options, then removes the",
|
||||||
|
"services listed in `disabled_services` with `--remove-service`.",
|
||||||
|
"Ports should be specified as \"portid:protocol\" or \"portid-portid:protocol\",",
|
||||||
|
"where \"portid\" is a number (or a port name from `/etc/services`, like \"ssh\" or",
|
||||||
|
"\"echo\") and \"protocol\" is one of \"tcp\", \"udp\", \"sctp\", or \"dccp\".",
|
||||||
|
"Enabling or disabling a service that is already enabled or disabled will not",
|
||||||
|
"cause an error.",
|
||||||
|
"Attempting to enable/disable an unknown service name will cause this stage to",
|
||||||
|
"fail. Known service names are determined by the contents of firewalld's",
|
||||||
|
"configuration directories, usually `/{lib,etc}/firewalld/services/*.xml`, and",
|
||||||
|
"may vary from release to release.",
|
||||||
|
"WARNING: this stage uses `chroot` to run `firewall-offline-cmd` inside the",
|
||||||
|
"target tree, which means it may fail unexpectedly when the buildhost and target",
|
||||||
|
"are different arches or OSes."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"ports": {
|
||||||
|
"description": "Ports (or port ranges) to open",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A port or port range: 'portid[-portid]:protocol'",
|
||||||
|
"pattern": ".:(tcp|udp|sctp|dccp)$"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enabled_services": {
|
||||||
|
"description": "Network services to allow in the default firewall zone",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Service name (from /{lib,etc}/firewalld/services/*.xml)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"disabled_services": {
|
||||||
|
"description": "Network services to remove from the default firewall zone",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Service name (from /{lib,etc}/firewalld/services/*.xml)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default_zone": {
|
||||||
|
"description": "Set default zone for connections and interfaces where no zone has been selected.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"zones": {
|
||||||
|
"description": "Bind a list of network sources to a zone to restrict traffic from those sources based on the settings of the zone.",
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"type": "object",
|
||||||
|
"description": "configuration for each zone",
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"sources"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the zone, if left empty the sources will apply to the default zone.",
|
||||||
|
"pattern": "^[a-zA-Z0-9_-]+$"
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "list of sources for the zone",
|
||||||
|
"items": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"type": "string",
|
||||||
|
"description": "A source: <source>[/<mask>]|<MAC>|ipset:<ipset>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,45 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Execute commands on first-boot
|
|
||||||
|
|
||||||
Sequentially execute a list of commands on first-boot / instantiation.
|
|
||||||
|
|
||||||
This stage uses a logic similar to systemd's first-boot to execute a given
|
|
||||||
script only the first time the image is booted.
|
|
||||||
|
|
||||||
An empty flag file /etc/osbuild-first-boot is written to /etc and a systemd
|
|
||||||
service is enabled that is only run when the file exits, and will remove it
|
|
||||||
before executing the given commands.
|
|
||||||
|
|
||||||
If the flag-file cannot be removed, the service fails without executing
|
|
||||||
any further first-boot commands.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["commands"],
|
|
||||||
"properties": {
|
|
||||||
"commands": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "The command lines to execute",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wait_for_network": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Wait for the network to be up before executing",
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def add_first_boot(tree, commands, wait_for_network):
|
def add_first_boot(tree, commands, wait_for_network):
|
||||||
if wait_for_network:
|
if wait_for_network:
|
||||||
|
|
|
||||||
33
stages/org.osbuild.first-boot.meta.json
Normal file
33
stages/org.osbuild.first-boot.meta.json
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"summary": "Execute commands on first-boot",
|
||||||
|
"description": [
|
||||||
|
"Sequentially execute a list of commands on first-boot / instantiation.",
|
||||||
|
"This stage uses a logic similar to systemd's first-boot to execute a given",
|
||||||
|
"script only the first time the image is booted.",
|
||||||
|
"An empty flag file /etc/osbuild-first-boot is written to /etc and a systemd",
|
||||||
|
"service is enabled that is only run when the file exits, and will remove it",
|
||||||
|
"before executing the given commands.",
|
||||||
|
"If the flag-file cannot be removed, the service fails without executing",
|
||||||
|
"any further first-boot commands."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"commands"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"commands": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "The command lines to execute",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wait_for_network": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Wait for the network to be up before executing",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,40 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Fix paths in /boot/loader/entries
|
|
||||||
|
|
||||||
Fixes paths in /boot/loader/entries that have incorrect paths for /boot.
|
|
||||||
|
|
||||||
This happens because some boot loader config tools (e.g. grub2-mkrelpath)
|
|
||||||
examine /proc/self/mountinfo to find the "real" path to /boot, and find the
|
|
||||||
path to the osbuild tree - which won't be valid at boot time for this image.
|
|
||||||
|
|
||||||
The paths in the Bootloader Specification are relative to the partition
|
|
||||||
they are located on, i.e. `/boot/loader/...` if `/boot` is on the root
|
|
||||||
file-system partition. If `/boot` is on a separate partition, the correct
|
|
||||||
path would be `/loader/.../` The `prefix` can be used to adjust for that.
|
|
||||||
By default it is `/boot`, i.e. assumes `/boot` is on the root file-system.
|
|
||||||
|
|
||||||
This stage reads and (re)writes all .conf files in /boot/loader/entries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import glob
|
import glob
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"prefix": {
|
|
||||||
"description": "Prefix to use, normally `/boot`",
|
|
||||||
"type": "string",
|
|
||||||
"default": "/boot"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
"""Fix broken paths in /boot/loader/entries.
|
"""Fix broken paths in /boot/loader/entries.
|
||||||
|
|
|
||||||
25
stages/org.osbuild.fix-bls.meta.json
Normal file
25
stages/org.osbuild.fix-bls.meta.json
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"summary": "Fix paths in /boot/loader/entries",
|
||||||
|
"description": [
|
||||||
|
"Fixes paths in /boot/loader/entries that have incorrect paths for /boot.",
|
||||||
|
"This happens because some boot loader config tools (e.g. grub2-mkrelpath)",
|
||||||
|
"examine /proc/self/mountinfo to find the \"real\" path to /boot, and find the",
|
||||||
|
"path to the osbuild tree - which won't be valid at boot time for this image.",
|
||||||
|
"The paths in the Bootloader Specification are relative to the partition",
|
||||||
|
"they are located on, i.e. `/boot/loader/...` if `/boot` is on the root",
|
||||||
|
"file-system partition. If `/boot` is on a separate partition, the correct",
|
||||||
|
"path would be `/loader/.../` The `prefix` can be used to adjust for that.",
|
||||||
|
"By default it is `/boot`, i.e. assumes `/boot` is on the root file-system.",
|
||||||
|
"This stage reads and (re)writes all .conf files in /boot/loader/entries."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"prefix": {
|
||||||
|
"description": "Prefix to use, normally `/boot`",
|
||||||
|
"type": "string",
|
||||||
|
"default": "/boot"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,138 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Create /etc/fstab entries for filesystems
|
|
||||||
|
|
||||||
Each filesystem item must have at least the fs_spec, i.e `uuid`,
|
|
||||||
`label`, `partlabel` or `device` and a `path` (mount point).
|
|
||||||
|
|
||||||
This stage replaces /etc/fstab, removing any existing entries.
|
|
||||||
|
|
||||||
NB: The ostree configuration options are experimental and might
|
|
||||||
be replaced with a different mechanism in the near future.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
from osbuild.util import ostree
|
from osbuild.util import ostree
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["filesystems"],
|
|
||||||
"properties": {
|
|
||||||
"ostree": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["deployment"],
|
|
||||||
"properties": {
|
|
||||||
"deployment": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"properties": {
|
|
||||||
"default": {"enum": [false]}
|
|
||||||
},
|
|
||||||
"required": ["osname", "ref"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"properties": {
|
|
||||||
"default": {"enum": [true]}
|
|
||||||
},
|
|
||||||
"not": {
|
|
||||||
"anyOf": [
|
|
||||||
{"required": ["osname"]},
|
|
||||||
{"required": ["ref"]},
|
|
||||||
{"required": ["serial"]}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"osname": {
|
|
||||||
"description": "Name of the stateroot to be used in the deployment",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"ref": {
|
|
||||||
"description": "OStree ref to create and use for deployment",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"serial": {
|
|
||||||
"description": "The deployment serial (usually '0')",
|
|
||||||
"type": "number",
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"description": "Find and use the default ostree deployment",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"filesystems": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "array of filesystem objects",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"oneOf": [{
|
|
||||||
"required": ["device", "path"]
|
|
||||||
}, {
|
|
||||||
"required": ["uuid", "path"]
|
|
||||||
}, {
|
|
||||||
"required": ["label", "path"]
|
|
||||||
}, {
|
|
||||||
"required": ["partlabel", "path"]
|
|
||||||
}],
|
|
||||||
"properties": {
|
|
||||||
"device": {
|
|
||||||
"description": "Device node",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"uuid": {
|
|
||||||
"description": "Filesystem UUID",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"label": {
|
|
||||||
"description": "Filesystem label",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"partlabel": {
|
|
||||||
"description": "Partition label.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"path": {
|
|
||||||
"description": "Filesystem mountpoint",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"vfs_type": {
|
|
||||||
"description": "Filesystem type",
|
|
||||||
"type": "string",
|
|
||||||
"default": "none"
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"description": "Filesystem options (comma-separated)",
|
|
||||||
"type": "string",
|
|
||||||
"default": "defaults"
|
|
||||||
},
|
|
||||||
"freq": {
|
|
||||||
"description": "dump(8) period in days",
|
|
||||||
"type": "number",
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"passno": {
|
|
||||||
"description": "pass number on parallel fsck(8)",
|
|
||||||
"type": "number",
|
|
||||||
"default": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
filesystems = options["filesystems"]
|
filesystems = options["filesystems"]
|
||||||
|
|
|
||||||
169
stages/org.osbuild.fstab.meta.json
Normal file
169
stages/org.osbuild.fstab.meta.json
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
{
|
||||||
|
"summary": "Create /etc/fstab entries for filesystems",
|
||||||
|
"description": [
|
||||||
|
"Each filesystem item must have at least the fs_spec, i.e `uuid`,",
|
||||||
|
"`label`, `partlabel` or `device` and a `path` (mount point).",
|
||||||
|
"This stage replaces /etc/fstab, removing any existing entries.",
|
||||||
|
"NB: The ostree configuration options are experimental and might",
|
||||||
|
"be replaced with a different mechanism in the near future."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"filesystems"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"ostree": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"deployment"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"deployment": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"default": {
|
||||||
|
"enum": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"osname",
|
||||||
|
"ref"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"default": {
|
||||||
|
"enum": [
|
||||||
|
true
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"not": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"osname"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"ref"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"serial"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"osname": {
|
||||||
|
"description": "Name of the stateroot to be used in the deployment",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ref": {
|
||||||
|
"description": "OStree ref to create and use for deployment",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"serial": {
|
||||||
|
"description": "The deployment serial (usually '0')",
|
||||||
|
"type": "number",
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"description": "Find and use the default ostree deployment",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filesystems": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "array of filesystem objects",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"device",
|
||||||
|
"path"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"uuid",
|
||||||
|
"path"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"label",
|
||||||
|
"path"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"partlabel",
|
||||||
|
"path"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"device": {
|
||||||
|
"description": "Device node",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"description": "Filesystem UUID",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"description": "Filesystem label",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"partlabel": {
|
||||||
|
"description": "Partition label.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"description": "Filesystem mountpoint",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"vfs_type": {
|
||||||
|
"description": "Filesystem type",
|
||||||
|
"type": "string",
|
||||||
|
"default": "none"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"description": "Filesystem options (comma-separated)",
|
||||||
|
"type": "string",
|
||||||
|
"default": "defaults"
|
||||||
|
},
|
||||||
|
"freq": {
|
||||||
|
"description": "dump(8) period in days",
|
||||||
|
"type": "number",
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"passno": {
|
||||||
|
"description": "pass number on parallel fsck(8)",
|
||||||
|
"type": "number",
|
||||||
|
"default": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,16 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Create or modify the GCP guest-agent config
|
|
||||||
|
|
||||||
Create or modify the GCP guest-agent config, depending on the
|
|
||||||
scope either at:
|
|
||||||
/etc/default/instance_configs.cfg.distro or
|
|
||||||
/etc/default/instance_configs.cfg
|
|
||||||
|
|
||||||
Configuration sections and options may contain any of these values:
|
|
||||||
https://github.com/GoogleCloudPlatform/guest-agent#configuration
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
@ -18,204 +6,6 @@ import iniparse
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = r"""
|
|
||||||
"definitions": {
|
|
||||||
"Accounts": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "Accounts section.",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"deprovision_remove": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Makes deprovisioning a user destructive."
|
|
||||||
},
|
|
||||||
"groups": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "List of groups for newly provisioned users."
|
|
||||||
},
|
|
||||||
"useradd_cmd": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Command string to create a new user."
|
|
||||||
},
|
|
||||||
"userdel_cmd": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Command string to delete a user."
|
|
||||||
},
|
|
||||||
"usermod_cmd": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Command string to modify a user's groups."
|
|
||||||
},
|
|
||||||
"gpasswd_add_cmd": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Command string to add a user to a group."
|
|
||||||
},
|
|
||||||
"gpasswd_remove_cmd": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Command string to remove a user from a group."
|
|
||||||
},
|
|
||||||
"groupadd_cmd": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Command string to create a new group."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Daemons": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "Daemons section.",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"accounts_daemon": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Disables the accounts daemon."
|
|
||||||
},
|
|
||||||
"clock_skew_daemon": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Disables the clock skew daemon."
|
|
||||||
},
|
|
||||||
"network_daemon": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Disables the network daemon."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"InstanceSetup": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "InstanceSetup section.",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"host_key_types": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "List of host key types to generate."
|
|
||||||
},
|
|
||||||
"optimize_local_ssd": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Prevents optimizing for local SSD."
|
|
||||||
},
|
|
||||||
"network_enabled": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Skips instance setup functions that require metadata."
|
|
||||||
},
|
|
||||||
"set_boto_config": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Skip setting up a boto config."
|
|
||||||
},
|
|
||||||
"set_host_keys": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Skips generating host keys on first boot."
|
|
||||||
},
|
|
||||||
"set_multiqueue": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Skips multiqueue driver support."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"IpForwarding": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "IpForwarding section.",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"ethernet_proto_id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Protocol ID string for daemon added routes."
|
|
||||||
},
|
|
||||||
"ip_aliases": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Disables setting up alias IP routes."
|
|
||||||
},
|
|
||||||
"target_instance_ips": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Disables internal IP address load balancing."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"MetadataScripts": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "MetadataScripts section.",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"default_shell": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "String with the default shell to execute scripts."
|
|
||||||
},
|
|
||||||
"run_dir": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "String base directory where metadata scripts are executed."
|
|
||||||
},
|
|
||||||
"startup": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Disables startup script execution."
|
|
||||||
},
|
|
||||||
"shutdown": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Disables shutdown script execution."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"NetworkInterfaces": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "NetworkInterfaces section.",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"setup": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Skips network interface setup."
|
|
||||||
},
|
|
||||||
"ip_forwarding": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Skips IP forwarding."
|
|
||||||
},
|
|
||||||
"dhcp_command": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Path for alternate dhcp executable used to enable network interfaces."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["config"],
|
|
||||||
"description": "Configure GCP guest-agent.",
|
|
||||||
"properties": {
|
|
||||||
"config_scope": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Create distro-wide or instance-specific configuration.",
|
|
||||||
"enum": ["distro", "instance"],
|
|
||||||
"default": "distro"
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "GCP guest-agent configuration.",
|
|
||||||
"minProperties": 1,
|
|
||||||
"properties": {
|
|
||||||
"Accounts": {
|
|
||||||
"$ref": "#/definitions/Accounts"
|
|
||||||
},
|
|
||||||
"Daemons": {
|
|
||||||
"$ref": "#/definitions/Daemons"
|
|
||||||
},
|
|
||||||
"InstanceSetup": {
|
|
||||||
"$ref": "#/definitions/InstanceSetup"
|
|
||||||
},
|
|
||||||
"IpForwarding": {
|
|
||||||
"$ref": "#/definitions/IpForwarding"
|
|
||||||
},
|
|
||||||
"MetadataScripts": {
|
|
||||||
"$ref": "#/definitions/MetadataScripts"
|
|
||||||
},
|
|
||||||
"NetworkInterfaces": {
|
|
||||||
"$ref": "#/definitions/NetworkInterfaces"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def option_value_to_str(value):
|
def option_value_to_str(value):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
213
stages/org.osbuild.gcp.guest-agent.conf.meta.json
Normal file
213
stages/org.osbuild.gcp.guest-agent.conf.meta.json
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
{
|
||||||
|
"summary": "Create or modify the GCP guest-agent config",
|
||||||
|
"description": [
|
||||||
|
"Create or modify the GCP guest-agent config, depending on the",
|
||||||
|
"scope either at:",
|
||||||
|
" /etc/default/instance_configs.cfg.distro or",
|
||||||
|
" /etc/default/instance_configs.cfg",
|
||||||
|
"Configuration sections and options may contain any of these values:",
|
||||||
|
"https://github.com/GoogleCloudPlatform/guest-agent#configuration"
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"definitions": {
|
||||||
|
"Accounts": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Accounts section.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"deprovision_remove": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Makes deprovisioning a user destructive."
|
||||||
|
},
|
||||||
|
"groups": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "List of groups for newly provisioned users."
|
||||||
|
},
|
||||||
|
"useradd_cmd": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Command string to create a new user."
|
||||||
|
},
|
||||||
|
"userdel_cmd": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Command string to delete a user."
|
||||||
|
},
|
||||||
|
"usermod_cmd": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Command string to modify a user's groups."
|
||||||
|
},
|
||||||
|
"gpasswd_add_cmd": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Command string to add a user to a group."
|
||||||
|
},
|
||||||
|
"gpasswd_remove_cmd": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Command string to remove a user from a group."
|
||||||
|
},
|
||||||
|
"groupadd_cmd": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Command string to create a new group."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Daemons": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Daemons section.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"accounts_daemon": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Disables the accounts daemon."
|
||||||
|
},
|
||||||
|
"clock_skew_daemon": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Disables the clock skew daemon."
|
||||||
|
},
|
||||||
|
"network_daemon": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Disables the network daemon."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"InstanceSetup": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "InstanceSetup section.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"host_key_types": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "List of host key types to generate."
|
||||||
|
},
|
||||||
|
"optimize_local_ssd": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Prevents optimizing for local SSD."
|
||||||
|
},
|
||||||
|
"network_enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Skips instance setup functions that require metadata."
|
||||||
|
},
|
||||||
|
"set_boto_config": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Skip setting up a boto config."
|
||||||
|
},
|
||||||
|
"set_host_keys": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Skips generating host keys on first boot."
|
||||||
|
},
|
||||||
|
"set_multiqueue": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Skips multiqueue driver support."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IpForwarding": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "IpForwarding section.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"ethernet_proto_id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Protocol ID string for daemon added routes."
|
||||||
|
},
|
||||||
|
"ip_aliases": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Disables setting up alias IP routes."
|
||||||
|
},
|
||||||
|
"target_instance_ips": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Disables internal IP address load balancing."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MetadataScripts": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "MetadataScripts section.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"default_shell": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "String with the default shell to execute scripts."
|
||||||
|
},
|
||||||
|
"run_dir": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "String base directory where metadata scripts are executed."
|
||||||
|
},
|
||||||
|
"startup": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Disables startup script execution."
|
||||||
|
},
|
||||||
|
"shutdown": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Disables shutdown script execution."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NetworkInterfaces": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "NetworkInterfaces section.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"setup": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Skips network interface setup."
|
||||||
|
},
|
||||||
|
"ip_forwarding": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Skips IP forwarding."
|
||||||
|
},
|
||||||
|
"dhcp_command": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path for alternate dhcp executable used to enable network interfaces."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"config"
|
||||||
|
],
|
||||||
|
"description": "Configure GCP guest-agent.",
|
||||||
|
"properties": {
|
||||||
|
"config_scope": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Create distro-wide or instance-specific configuration.",
|
||||||
|
"enum": [
|
||||||
|
"distro",
|
||||||
|
"instance"
|
||||||
|
],
|
||||||
|
"default": "distro"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "GCP guest-agent configuration.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"Accounts": {
|
||||||
|
"$ref": "#/definitions/Accounts"
|
||||||
|
},
|
||||||
|
"Daemons": {
|
||||||
|
"$ref": "#/definitions/Daemons"
|
||||||
|
},
|
||||||
|
"InstanceSetup": {
|
||||||
|
"$ref": "#/definitions/InstanceSetup"
|
||||||
|
},
|
||||||
|
"IpForwarding": {
|
||||||
|
"$ref": "#/definitions/IpForwarding"
|
||||||
|
},
|
||||||
|
"MetadataScripts": {
|
||||||
|
"$ref": "#/definitions/MetadataScripts"
|
||||||
|
},
|
||||||
|
"NetworkInterfaces": {
|
||||||
|
"$ref": "#/definitions/NetworkInterfaces"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,35 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Configure greenboot
|
|
||||||
|
|
||||||
Update configuration of greenboot in /etc/greenboot/greenbot.conf.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import fileinput
|
import fileinput
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["config"],
|
|
||||||
"properties": {
|
|
||||||
"config": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "greenboot config options",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"monitor_services": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
greenboot_conf = options.get("config", {})
|
greenboot_conf = options.get("config", {})
|
||||||
|
|
|
||||||
27
stages/org.osbuild.greenboot.meta.json
Normal file
27
stages/org.osbuild.greenboot.meta.json
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"summary": "Configure greenboot",
|
||||||
|
"description": [
|
||||||
|
"Update configuration of greenboot in /etc/greenboot/greenbot.conf."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"config"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"config": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "greenboot config options",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"monitor_services": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,43 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Create group accounts
|
|
||||||
|
|
||||||
Create group accounts, optionally assigning them static GIDs.
|
|
||||||
|
|
||||||
Runs `groupadd` from the buildhost to create the groups listed in `groups`.
|
|
||||||
If no `gid` is given, `groupadd` will choose one.
|
|
||||||
|
|
||||||
If the specified group name or GID is already in use, this stage will fail.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"groups": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "Keys are group names, values are objects with group info",
|
|
||||||
"patternProperties": {
|
|
||||||
"^[A-Za-z0-9_][A-Za-z0-9_-]{0,31}$": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"gid": {
|
|
||||||
"type": "number",
|
|
||||||
"description": "GID for this group"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def groupadd(root, name, gid=None):
|
def groupadd(root, name, gid=None):
|
||||||
arguments = []
|
arguments = []
|
||||||
|
|
|
||||||
30
stages/org.osbuild.groups.meta.json
Normal file
30
stages/org.osbuild.groups.meta.json
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"summary": "Create group accounts",
|
||||||
|
"description": [
|
||||||
|
"Create group accounts, optionally assigning them static GIDs.",
|
||||||
|
"Runs `groupadd` from the buildhost to create the groups listed in `groups`.",
|
||||||
|
"If no `gid` is given, `groupadd` will choose one.",
|
||||||
|
"If the specified group name or GID is already in use, this stage will fail."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"groups": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Keys are group names, values are objects with group info",
|
||||||
|
"patternProperties": {
|
||||||
|
"^[A-Za-z0-9_][A-Za-z0-9_-]{0,31}$": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"gid": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "GID for this group"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,80 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Configure GRUB2 bootloader and set boot options
|
|
||||||
|
|
||||||
Configure the system to use GRUB2 as the bootloader, and set boot options.
|
|
||||||
|
|
||||||
Sets the GRUB2 boot/root filesystem to `rootfs`. If a separated boot
|
|
||||||
partition is used it can be specified via `bootfs`. The file-systems
|
|
||||||
can be identified either via uuid (`{"uuid": "<uuid>"}`) or label
|
|
||||||
(`{"label": "<label>"}`). The kernel boot argument will be composed
|
|
||||||
of the root file system id and additional options specified in
|
|
||||||
`{kernel_opts}`, if any.
|
|
||||||
|
|
||||||
Configures GRUB2 to boot via the Boot Loader Specification
|
|
||||||
(https://systemd.io/BOOT_LOADER_SPECIFICATION), which is the default
|
|
||||||
behavior in Fedora 30 and later.
|
|
||||||
|
|
||||||
This stage will overwrite `/etc/default/grub`, `/boot/grub2/grubenv`, and
|
|
||||||
`/boot/grub2/grub.cfg`. (Leading directories will be created if not present.)
|
|
||||||
|
|
||||||
If Legacy boot support is requested via `legacy` this stage will also
|
|
||||||
overwrite `/boot/grub2/grub.cfg` and will copy the GRUB2 files from the
|
|
||||||
buildhost into the target tree:
|
|
||||||
* `/usr/share/grub/unicode.pf2` -> `/boot/grub2/fonts/`
|
|
||||||
* `/usr/lib/grub/$platform/*.{mod,lst}` -> `/boot/grub2/$platform/`
|
|
||||||
* NOTE: skips `fdt.lst`, which is an empty file
|
|
||||||
The $platform variable (default: i386-pc) refers to target platform
|
|
||||||
that grub2 is mean to ran on (see grub-install(1)'s `--target`)
|
|
||||||
|
|
||||||
NB: with legacy support enabled, this stage will fail if the buildhost
|
|
||||||
doesn't have `/usr/lib/grub/$platform/` and `/usr/share/grub/unicode.pf2`.
|
|
||||||
|
|
||||||
If UEFI support is enabled via `uefi: {"vendor": "<vendor>"}` this stage will
|
|
||||||
also write the `grub.cfg` to `boot/efi/EFI/<vendor>/grub.cfg`. EFI binaries
|
|
||||||
and accompanying data can be installed from the built root via `uefi.install`.
|
|
||||||
|
|
||||||
Both UEFI and Legacy can be specified at the same time (hybrid boot).
|
|
||||||
|
|
||||||
If `uefi.unified` is specified or hybrid boot is enabled, the main grub config
|
|
||||||
will be written to `boot/grub2/grub.cfg` and a redirect config will be placed
|
|
||||||
in the EFI directory.
|
|
||||||
|
|
||||||
If the `saved_entry` option is present it will result in an entry in the
|
|
||||||
`grubenv` file of the same name. The grub config file contains logic so
|
|
||||||
that this variable will be used to select the next boot entry. This will
|
|
||||||
also make grub2-reboot and grub2-set-default tools work. It will also
|
|
||||||
prevent newly installed non-default kernels (like e.g. the debug kernel)
|
|
||||||
to be selected as default. The contents of variable needs to match the
|
|
||||||
corresponding loader entry, which currently is a combination of the
|
|
||||||
machine id and kernel NVRA, like e.g.:
|
|
||||||
`ffffffffffffffffffffffffffffffff-5.6.6-300.fc32.x86_64`
|
|
||||||
If `saved_entry` is set it is advisable to set `config.default` to
|
|
||||||
`saved` so that any re-creation of the grub configuration by the
|
|
||||||
user will preserve that functionality.
|
|
||||||
|
|
||||||
Support for "greenboot" can be turned on via the `greenboot` option.
|
|
||||||
Greenboot is the idea of automatically rolling back bad updates,
|
|
||||||
i.e. updates that do not boot successfully. The implementation
|
|
||||||
is split between the boot loader and a user space component.
|
|
||||||
The latter sets two variables `boot_counter`, which indicates
|
|
||||||
the maximum number of boot attempts and `boot_success` which
|
|
||||||
tells the boot laoder if a previous boot was successful. The
|
|
||||||
bootloader on the other hand will decrement the counter variable
|
|
||||||
and reset the success indicator one.
|
|
||||||
An implementation of the user space component for rpm-ostree is
|
|
||||||
called `greenboot`.
|
|
||||||
|
|
||||||
Support for ignition (https://github.com/coreos/ignition) can be turned
|
|
||||||
on via the `ignition` option. If enabled, a 'ignition_firstboot' variable
|
|
||||||
will be created, which is meant to be included in the kernel command line.
|
|
||||||
The grub.cfg will then contain the necessary code to detect and source
|
|
||||||
the '/boot/ignition.firstboot' file and configure said 'ignition_firstboot'
|
|
||||||
variable appropriately. See the 'org.osbuild.ignition' stage for more
|
|
||||||
information on that file.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import string
|
import string
|
||||||
|
|
@ -82,164 +6,6 @@ import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"oneOf": [{
|
|
||||||
"required": ["root_fs_uuid"]
|
|
||||||
}, {
|
|
||||||
"required": ["rootfs"]
|
|
||||||
}],
|
|
||||||
"definitions": {
|
|
||||||
"uuid": {
|
|
||||||
"description": "Identify the file system by UUID",
|
|
||||||
"type": "string",
|
|
||||||
"oneOf": [
|
|
||||||
{ "pattern": "^[0-9A-Za-z]{8}(-[0-9A-Za-z]{4}){3}-[0-9A-Za-z]{12}$",
|
|
||||||
"examples": ["9c6ae55b-cf88-45b8-84e8-64990759f39d"] },
|
|
||||||
{ "pattern": "^[0-9A-Za-z]{4}-[0-9A-Za-z]{4}$",
|
|
||||||
"examples": ["6699-AFB5"] }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"filesystem": {
|
|
||||||
"description": "Description of how to locate a file system",
|
|
||||||
"type": "object",
|
|
||||||
"oneOf": [{
|
|
||||||
"required": ["uuid"]
|
|
||||||
}, {
|
|
||||||
"required": ["label"]
|
|
||||||
}],
|
|
||||||
"properties": {
|
|
||||||
"label": {
|
|
||||||
"description": "Identify the file system by label",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"uuid": { "$ref": "#/definitions/uuid" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"terminal": {
|
|
||||||
"description": "Terminal device",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"properties": {
|
|
||||||
"rootfs": { "$ref": "#/definitions/filesystem" },
|
|
||||||
"bootfs": { "$ref": "#/definitions/filesystem" },
|
|
||||||
"root_fs_uuid": { "$ref": "#/definitions/uuid" },
|
|
||||||
"boot_fs_uuid": { "$ref": "#/definitions/uuid" },
|
|
||||||
"kernel_opts": {
|
|
||||||
"description": "Additional kernel boot options",
|
|
||||||
"type": "string",
|
|
||||||
"default": ""
|
|
||||||
},
|
|
||||||
"legacy": {
|
|
||||||
"description": "Include legacy boot support",
|
|
||||||
"oneOf": [
|
|
||||||
{"type": "boolean", "default": false},
|
|
||||||
{"type": "string"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uefi": {
|
|
||||||
"description": "Include UEFI boot support",
|
|
||||||
"type": "object",
|
|
||||||
"required": ["vendor"],
|
|
||||||
"properties": {
|
|
||||||
"vendor": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The vendor of the UEFI binaries (this is us)",
|
|
||||||
"examples": ["fedora"],
|
|
||||||
"pattern": "^(.+)$"
|
|
||||||
},
|
|
||||||
"efi_src_dir": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The source path to use for the EFI/ binaries when installing is set to True",
|
|
||||||
"default": "/boot/efi/EFI"
|
|
||||||
},
|
|
||||||
"install": {
|
|
||||||
"description": "Install EFI binaries and data from the build root",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"unified": {
|
|
||||||
"description": "Main grub config in 'boot/grub2/grub.cfg'",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"saved_entry": {
|
|
||||||
"description": "Set the variable of the same name in `grubenv`.",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"write_defaults": {
|
|
||||||
"description": "Whether to write /etc/defaults/grub",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true
|
|
||||||
},
|
|
||||||
"write_cmdline": {
|
|
||||||
"description": "Include the kernel command line in `grubenv`",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true
|
|
||||||
},
|
|
||||||
"ignition": {
|
|
||||||
"description": "Include ignition support in the grub.cfg",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"greenboot": {
|
|
||||||
"description": "Include support for fallback counting",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"description": "Configuration options for grub itself",
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"default": {
|
|
||||||
"description": "Default boot entry",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"disable_recovery": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"disable_submenu": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"distributor": {
|
|
||||||
"description": "Name of the distributor",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"terminal": {
|
|
||||||
"$ref": "#/definitions/terminal"
|
|
||||||
},
|
|
||||||
"terminal_input": {
|
|
||||||
"$ref": "#/definitions/terminal"
|
|
||||||
},
|
|
||||||
"terminal_output": {
|
|
||||||
"$ref": "#/definitions/terminal"
|
|
||||||
},
|
|
||||||
"timeout": {
|
|
||||||
"description": "Timeout in seconds",
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"timeout_style": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["hidden", "menu", "countdown"]
|
|
||||||
},
|
|
||||||
"serial": {
|
|
||||||
"description": "The command to configure the serial console",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
# The main grub2 configuration file template. Used for UEFI and legacy
|
# The main grub2 configuration file template. Used for UEFI and legacy
|
||||||
# boot. The parameters are currently:
|
# boot. The parameters are currently:
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Install the grub2 boot loader for non-UEFI systems or hybrid boot
|
|
||||||
|
|
||||||
This stage can be used to generate a grub2 core image and install
|
|
||||||
it to the correct location to enable booting of non-UEFI systems,
|
|
||||||
i.e. x86 legacy and PPC64LE (Open Firmware).
|
|
||||||
|
|
||||||
On x86, the core image can be installed into the MBR gap or to a
|
|
||||||
dedicated BIOS boot partition when the partition label is GTP. On
|
|
||||||
ppc64le with Open Firmware a dedicated 'PrEP partition' is used.
|
|
||||||
|
|
||||||
x86 / MBR gap:
|
|
||||||
For historic and performance reasons the first partition
|
|
||||||
is aligned to a specific sector number (used to be 64,
|
|
||||||
now it is 2048), which leaves a gap between it and the MBR,
|
|
||||||
where the core image can be embedded in
|
|
||||||
|
|
||||||
x86 / BIOS boot:
|
|
||||||
A dedicated partition with a specific GUID[1] is used.
|
|
||||||
|
|
||||||
ppc64le / Open Firmware:
|
|
||||||
A dedicated partition with a specified GUID[2] is used.
|
|
||||||
|
|
||||||
On ppc64le with Open Firmware a special partition called
|
|
||||||
'PrEP partition' is used the store the grub2 core; the
|
|
||||||
firmware looks for this partition and directly loads and
|
|
||||||
executes the core form it.
|
|
||||||
|
|
||||||
On x86, a "boot image", aka grub stage 1, is installed into the
|
|
||||||
master boot record (MBR) of the partition (even in the case the
|
|
||||||
partition layout is GPT). It main purpose is to load the second
|
|
||||||
stage (core image). Therefore the location of the core image is
|
|
||||||
patched into the boot image.
|
|
||||||
|
|
||||||
On ppc64le, the firmware itself directly loads the complete core
|
|
||||||
image and transfers control to it.
|
|
||||||
|
|
||||||
[1] 21686148-6449-6E6F-744E-656564454649
|
|
||||||
[2] 9E1A2D38-C612-4316-AA26-8B49521E5A8B
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import struct
|
import struct
|
||||||
|
|
@ -50,92 +8,6 @@ from typing import BinaryIO, Dict
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = r"""
|
|
||||||
"definitions": {
|
|
||||||
"core-mkimage": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Generate the core image via grub-mkimage",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["type", "partlabel", "filesystem"],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"enum": ["mkimage"]
|
|
||||||
},
|
|
||||||
"partlabel": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["gpt", "dos"]
|
|
||||||
},
|
|
||||||
"filesystem": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["ext4", "xfs", "btrfs"]
|
|
||||||
},
|
|
||||||
"binary": {
|
|
||||||
"description": "grub-mkimage binary name",
|
|
||||||
"type": "string",
|
|
||||||
"default": "grub2-mkimage"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"prefix-partition": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Grub2 config on a specific partition, e.g. (,gpt3)/boot",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["type", "partlabel", "number", "path"],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"enum": ["partition"]
|
|
||||||
},
|
|
||||||
"partlabel": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["gpt", "dos"]
|
|
||||||
},
|
|
||||||
"number": {
|
|
||||||
"description": "The partition number, starting at zero",
|
|
||||||
"type": "number"
|
|
||||||
},
|
|
||||||
"path": {
|
|
||||||
"description": "location of grub config inside the partition",
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "\/.*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["filename", "platform", "location", "core", "prefix"],
|
|
||||||
"properties": {
|
|
||||||
"filename": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "filename of the disk image"
|
|
||||||
},
|
|
||||||
"platform": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Platform of the target system"
|
|
||||||
},
|
|
||||||
"location": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "Location of the stage 2 (in sectors)"
|
|
||||||
},
|
|
||||||
"core": {
|
|
||||||
"description": "How to obtain the GRUB core image",
|
|
||||||
"oneOf": [
|
|
||||||
{"$ref": "#/definitions/core-mkimage"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"prefix": {
|
|
||||||
"description": "location of grub config",
|
|
||||||
"oneOf": [
|
|
||||||
{"$ref": "#/definitions/prefix-partition"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"sector-size": {
|
|
||||||
"type": "number",
|
|
||||||
"description": "Sector size (in bytes)",
|
|
||||||
"default": 512
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def grub2_partition_id(label):
|
def grub2_partition_id(label):
|
||||||
"""grub2 partition identifier for the partition table"""
|
"""grub2 partition identifier for the partition table"""
|
||||||
|
|
|
||||||
151
stages/org.osbuild.grub2.inst.meta.json
Normal file
151
stages/org.osbuild.grub2.inst.meta.json
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
{
|
||||||
|
"summary": "Install the grub2 boot loader for non-UEFI systems or hybrid boot",
|
||||||
|
"description": [
|
||||||
|
"This stage can be used to generate a grub2 core image and install",
|
||||||
|
"it to the correct location to enable booting of non-UEFI systems,",
|
||||||
|
"i.e. x86 legacy and PPC64LE (Open Firmware).",
|
||||||
|
"On x86, the core image can be installed into the MBR gap or to a",
|
||||||
|
"dedicated BIOS boot partition when the partition label is GTP. On",
|
||||||
|
"ppc64le with Open Firmware a dedicated 'PrEP partition' is used.",
|
||||||
|
"x86 / MBR gap:",
|
||||||
|
" For historic and performance reasons the first partition",
|
||||||
|
" is aligned to a specific sector number (used to be 64,",
|
||||||
|
" now it is 2048), which leaves a gap between it and the MBR,",
|
||||||
|
" where the core image can be embedded in",
|
||||||
|
"x86 / BIOS boot:",
|
||||||
|
" A dedicated partition with a specific GUID[1] is used.",
|
||||||
|
"ppc64le / Open Firmware:",
|
||||||
|
" A dedicated partition with a specified GUID[2] is used.",
|
||||||
|
" On ppc64le with Open Firmware a special partition called",
|
||||||
|
" 'PrEP partition' is used the store the grub2 core; the",
|
||||||
|
" firmware looks for this partition and directly loads and",
|
||||||
|
" executes the core form it.",
|
||||||
|
"On x86, a \"boot image\", aka grub stage 1, is installed into the",
|
||||||
|
"master boot record (MBR) of the partition (even in the case the",
|
||||||
|
"partition layout is GPT). It main purpose is to load the second",
|
||||||
|
"stage (core image). Therefore the location of the core image is",
|
||||||
|
"patched into the boot image.",
|
||||||
|
"On ppc64le, the firmware itself directly loads the complete core",
|
||||||
|
"image and transfers control to it.",
|
||||||
|
"[1] 21686148-6449-6E6F-744E-656564454649",
|
||||||
|
"[2] 9E1A2D38-C612-4316-AA26-8B49521E5A8B"
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"definitions": {
|
||||||
|
"core-mkimage": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Generate the core image via grub-mkimage",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"partlabel",
|
||||||
|
"filesystem"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"mkimage"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"partlabel": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"gpt",
|
||||||
|
"dos"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"filesystem": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"ext4",
|
||||||
|
"xfs",
|
||||||
|
"btrfs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"binary": {
|
||||||
|
"description": "grub-mkimage binary name",
|
||||||
|
"type": "string",
|
||||||
|
"default": "grub2-mkimage"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prefix-partition": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Grub2 config on a specific partition, e.g. (,gpt3)/boot",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"partlabel",
|
||||||
|
"number",
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"partition"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"partlabel": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"gpt",
|
||||||
|
"dos"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"number": {
|
||||||
|
"description": "The partition number, starting at zero",
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"description": "location of grub config inside the partition",
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "/.*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"filename",
|
||||||
|
"platform",
|
||||||
|
"location",
|
||||||
|
"core",
|
||||||
|
"prefix"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"filename": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "filename of the disk image"
|
||||||
|
},
|
||||||
|
"platform": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Platform of the target system"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Location of the stage 2 (in sectors)"
|
||||||
|
},
|
||||||
|
"core": {
|
||||||
|
"description": "How to obtain the GRUB core image",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/core-mkimage"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"prefix": {
|
||||||
|
"description": "location of grub config",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/prefix-partition"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sector-size": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Sector size (in bytes)",
|
||||||
|
"default": 512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Create a boot filesystem tree, can be consumed to create
|
|
||||||
an efiboot.img.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import string
|
import string
|
||||||
|
|
@ -11,65 +6,6 @@ import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA_2 = """
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["product", "kernel", "isolabel"],
|
|
||||||
"properties": {
|
|
||||||
"product": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["name", "version"],
|
|
||||||
"properties": {
|
|
||||||
"name": {"type": "string"},
|
|
||||||
"version": {"type": "string"}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kernel": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["dir"],
|
|
||||||
"properties": {
|
|
||||||
"dir": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"opts": {
|
|
||||||
"description": "Array of group names for this user",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"isolabel": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"architectures": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vendor": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"description": "Configuration options for grub itself",
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"timeout": {
|
|
||||||
"description": "Timeout in seconds",
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0,
|
|
||||||
"default": 60
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
# The main grub2 configuration file template. Used for UEFI.
|
# The main grub2 configuration file template. Used for UEFI.
|
||||||
GRUB2_EFI_CFG_TEMPLATE = """
|
GRUB2_EFI_CFG_TEMPLATE = """
|
||||||
|
|
|
||||||
75
stages/org.osbuild.grub2.iso.meta.json
Normal file
75
stages/org.osbuild.grub2.iso.meta.json
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
{
|
||||||
|
"summary": "Create a boot filesystem tree, can be consumed to create\nan efiboot.img.",
|
||||||
|
"description": [],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"product",
|
||||||
|
"kernel",
|
||||||
|
"isolabel"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"product": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"version"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"kernel": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"dir"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"dir": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"opts": {
|
||||||
|
"description": "Array of group names for this user",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isolabel": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"architectures": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"vendor": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"description": "Configuration options for grub itself",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"timeout": {
|
||||||
|
"description": "Timeout in seconds",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"default": 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,43 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Configure GRUB2 bootloader and set boot options (legacy, i.e. non-BLS)
|
|
||||||
|
|
||||||
This stage creates traditional menu entries for systems that are not
|
|
||||||
capable of using the Booloader Specific (BLS).
|
|
||||||
|
|
||||||
Sets the GRUB2 boot/root filesystem to `rootfs`. If a separated boot
|
|
||||||
partition is used it can be specified via `bootfs`. The file-systems
|
|
||||||
can be identified either via
|
|
||||||
- uuid (`{"uuid": "<uuid>"}`)
|
|
||||||
- label (`{"label": "<label>"}`)
|
|
||||||
- device (`{"device": "<device>"}`, only for the root file system)
|
|
||||||
|
|
||||||
The kernel boot argument will be composed of the root file system id
|
|
||||||
and additional options specified in `config.cmdline`, if any.
|
|
||||||
|
|
||||||
This stage will overwrite `/etc/default/grub`, `/boot/grub2/grubenv`;
|
|
||||||
leading directories will be created if not present.
|
|
||||||
|
|
||||||
The stage supports configuring grub for BIOS boot and UEFI systems:
|
|
||||||
|
|
||||||
If BIOS boot support is requested via `bios` this stage will also
|
|
||||||
overwrite `/boot/grub2/grub.cfg` and will copy the GRUB2 files from the
|
|
||||||
buildhost into the target tree:
|
|
||||||
* `/usr/share/grub/unicode.pf2` -> `/boot/grub2/fonts/`
|
|
||||||
* `/usr/lib/grub/$platform/*.{mod,lst}` -> `/boot/grub2/$platform/`
|
|
||||||
* NOTE: skips `fdt.lst`, which is an empty file
|
|
||||||
|
|
||||||
NB: with bios support enabled, this stage will fail if the buildhost
|
|
||||||
doesn't have `/usr/lib/grub/$platform/` and `/usr/share/grub/unicode.pf2`.
|
|
||||||
|
|
||||||
If UEFI support is enabled via `uefi: {"vendor": "<vendor>"}` this stage will
|
|
||||||
also write the `grub.cfg` to `boot/efi/EFI/<vendor>/grub.cfg`. EFI binaries
|
|
||||||
and accompanying data can be installed from the built root via `uefi.install`.
|
|
||||||
|
|
||||||
Both UEFI and Legacy can be specified at the same time (hybrid boot).
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import string
|
import string
|
||||||
|
|
@ -45,181 +6,6 @@ import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
|
|
||||||
"definitions": {
|
|
||||||
"filesystem": {
|
|
||||||
"description": "Description of how to locate a file system",
|
|
||||||
"type": "object",
|
|
||||||
"oneOf": [{
|
|
||||||
"required": ["uuid"]
|
|
||||||
}, {
|
|
||||||
"required": ["label"]
|
|
||||||
}, {
|
|
||||||
"required": ["device"]
|
|
||||||
}],
|
|
||||||
"properties": {
|
|
||||||
"device": {
|
|
||||||
"description": "Identify the file system by device node",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"label": {
|
|
||||||
"description": "Identify the file system by label",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"uuid": {
|
|
||||||
"description": "Identify the file system by UUID",
|
|
||||||
"type": "string",
|
|
||||||
"oneOf": [
|
|
||||||
{ "pattern": "^[0-9A-Za-z]{8}(-[0-9A-Za-z]{4}){3}-[0-9A-Za-z]{12}$",
|
|
||||||
"examples": ["9c6ae55b-cf88-45b8-84e8-64990759f39d"] },
|
|
||||||
{ "pattern": "^[0-9A-Za-z]{4}-[0-9A-Za-z]{4}$",
|
|
||||||
"examples": ["6699-AFB5"] }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"terminal": {
|
|
||||||
"description": "Terminal device",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["rootfs", "entries"],
|
|
||||||
"anyOf": [{
|
|
||||||
"required": ["bios"]
|
|
||||||
}, {
|
|
||||||
"required": ["uefi"]
|
|
||||||
}],
|
|
||||||
"properties": {
|
|
||||||
"rootfs": { "$ref": "#/definitions/filesystem" },
|
|
||||||
"bootfs": { "$ref": "#/definitions/filesystem" },
|
|
||||||
"bios": {
|
|
||||||
"description": "Include bios boot support",
|
|
||||||
"type": "object",
|
|
||||||
"required": ["platform"],
|
|
||||||
"properties": {
|
|
||||||
"platform": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["i386-pc", "powerpc-ieee1275"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uefi": {
|
|
||||||
"description": "Include UEFI boot support",
|
|
||||||
"type": "object",
|
|
||||||
"required": ["vendor"],
|
|
||||||
"properties": {
|
|
||||||
"vendor": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The vendor of the UEFI binaries (this is us)",
|
|
||||||
"examples": ["fedora"],
|
|
||||||
"pattern": "^(.+)$"
|
|
||||||
},
|
|
||||||
"install": {
|
|
||||||
"description": "Install EFI binaries and data from the build root",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"write_defaults": {
|
|
||||||
"description": "Whether to write /etc/defaults/grub",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true
|
|
||||||
},
|
|
||||||
"entries": {
|
|
||||||
"description": "List of entries to add to the boot menu",
|
|
||||||
"type": "array",
|
|
||||||
"minItems": 1,
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["id", "product", "kernel"],
|
|
||||||
"properties": {
|
|
||||||
"default": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Make this entry the default entry"
|
|
||||||
},
|
|
||||||
"id": {
|
|
||||||
"description": "UUID for the entry (grub uses the root fs uuid)",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"product": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["name", "version"],
|
|
||||||
"properties": {
|
|
||||||
"name": {"type": "string"},
|
|
||||||
"nick": {"type": "string"},
|
|
||||||
"version": {"type": "string"}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kernel": {
|
|
||||||
"description": "The kernel (EVRA)",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"description": "Configuration options for grub itself",
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"cmdline": {
|
|
||||||
"description": "Additional kernel command line options",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"description": "Default boot entry",
|
|
||||||
"type": "string",
|
|
||||||
"default": "saved"
|
|
||||||
},
|
|
||||||
"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"
|
|
||||||
},
|
|
||||||
"terminal_output": {
|
|
||||||
"$ref": "#/definitions/terminal"
|
|
||||||
},
|
|
||||||
"timeout": {
|
|
||||||
"description": "Timeout in seconds",
|
|
||||||
"type": "integer",
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
# The main grub2 configuration file template. Used for UEFI and legacy
|
# The main grub2 configuration file template. Used for UEFI and legacy
|
||||||
GRUB_CFG_TEMPLATE = """
|
GRUB_CFG_TEMPLATE = """
|
||||||
|
|
|
||||||
261
stages/org.osbuild.grub2.legacy.meta.json
Normal file
261
stages/org.osbuild.grub2.legacy.meta.json
Normal file
|
|
@ -0,0 +1,261 @@
|
||||||
|
{
|
||||||
|
"summary": "Configure GRUB2 bootloader and set boot options (legacy, i.e. non-BLS)",
|
||||||
|
"description": [
|
||||||
|
"This stage creates traditional menu entries for systems that are not",
|
||||||
|
"capable of using the Booloader Specific (BLS).",
|
||||||
|
"Sets the GRUB2 boot/root filesystem to `rootfs`. If a separated boot",
|
||||||
|
"partition is used it can be specified via `bootfs`. The file-systems",
|
||||||
|
"can be identified either via",
|
||||||
|
" - uuid (`{\"uuid\": \"<uuid>\"}`)",
|
||||||
|
" - label (`{\"label\": \"<label>\"}`)",
|
||||||
|
" - device (`{\"device\": \"<device>\"}`, only for the root file system)",
|
||||||
|
"The kernel boot argument will be composed of the root file system id",
|
||||||
|
"and additional options specified in `config.cmdline`, if any.",
|
||||||
|
"This stage will overwrite `/etc/default/grub`, `/boot/grub2/grubenv`;",
|
||||||
|
"leading directories will be created if not present.",
|
||||||
|
"The stage supports configuring grub for BIOS boot and UEFI systems:",
|
||||||
|
"If BIOS boot support is requested via `bios` this stage will also",
|
||||||
|
"overwrite `/boot/grub2/grub.cfg` and will copy the GRUB2 files from the",
|
||||||
|
"buildhost into the target tree:",
|
||||||
|
"* `/usr/share/grub/unicode.pf2` -> `/boot/grub2/fonts/`",
|
||||||
|
"* `/usr/lib/grub/$platform/*.{mod,lst}` -> `/boot/grub2/$platform/`",
|
||||||
|
" * NOTE: skips `fdt.lst`, which is an empty file",
|
||||||
|
"NB: with bios support enabled, this stage will fail if the buildhost",
|
||||||
|
"doesn't have `/usr/lib/grub/$platform/` and `/usr/share/grub/unicode.pf2`.",
|
||||||
|
"If UEFI support is enabled via `uefi: {\"vendor\": \"<vendor>\"}` this stage will",
|
||||||
|
"also write the `grub.cfg` to `boot/efi/EFI/<vendor>/grub.cfg`. EFI binaries",
|
||||||
|
"and accompanying data can be installed from the built root via `uefi.install`.",
|
||||||
|
"Both UEFI and Legacy can be specified at the same time (hybrid boot)."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"definitions": {
|
||||||
|
"filesystem": {
|
||||||
|
"description": "Description of how to locate a file system",
|
||||||
|
"type": "object",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"label"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"device"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"device": {
|
||||||
|
"description": "Identify the file system by device node",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"description": "Identify the file system by label",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"description": "Identify the file system by UUID",
|
||||||
|
"type": "string",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"pattern": "^[0-9A-Za-z]{8}(-[0-9A-Za-z]{4}){3}-[0-9A-Za-z]{12}$",
|
||||||
|
"examples": [
|
||||||
|
"9c6ae55b-cf88-45b8-84e8-64990759f39d"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "^[0-9A-Za-z]{4}-[0-9A-Za-z]{4}$",
|
||||||
|
"examples": [
|
||||||
|
"6699-AFB5"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"terminal": {
|
||||||
|
"description": "Terminal device",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"rootfs",
|
||||||
|
"entries"
|
||||||
|
],
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"bios"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"uefi"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"rootfs": {
|
||||||
|
"$ref": "#/definitions/filesystem"
|
||||||
|
},
|
||||||
|
"bootfs": {
|
||||||
|
"$ref": "#/definitions/filesystem"
|
||||||
|
},
|
||||||
|
"bios": {
|
||||||
|
"description": "Include bios boot support",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"platform"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"platform": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"i386-pc",
|
||||||
|
"powerpc-ieee1275"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uefi": {
|
||||||
|
"description": "Include UEFI boot support",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"vendor"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"vendor": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The vendor of the UEFI binaries (this is us)",
|
||||||
|
"examples": [
|
||||||
|
"fedora"
|
||||||
|
],
|
||||||
|
"pattern": "^(.+)$"
|
||||||
|
},
|
||||||
|
"install": {
|
||||||
|
"description": "Install EFI binaries and data from the build root",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"write_defaults": {
|
||||||
|
"description": "Whether to write /etc/defaults/grub",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"entries": {
|
||||||
|
"description": "List of entries to add to the boot menu",
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"product",
|
||||||
|
"kernel"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"default": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Make this entry the default entry"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"description": "UUID for the entry (grub uses the root fs uuid)",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"version"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"nick": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"kernel": {
|
||||||
|
"description": "The kernel (EVRA)",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"description": "Configuration options for grub itself",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"cmdline": {
|
||||||
|
"description": "Additional kernel command line options",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"description": "Default boot entry",
|
||||||
|
"type": "string",
|
||||||
|
"default": "saved"
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"terminal_output": {
|
||||||
|
"$ref": "#/definitions/terminal"
|
||||||
|
},
|
||||||
|
"timeout": {
|
||||||
|
"description": "Timeout in seconds",
|
||||||
|
"type": "integer",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
266
stages/org.osbuild.grub2.meta.json
Normal file
266
stages/org.osbuild.grub2.meta.json
Normal file
|
|
@ -0,0 +1,266 @@
|
||||||
|
{
|
||||||
|
"summary": "Configure GRUB2 bootloader and set boot options",
|
||||||
|
"description": [
|
||||||
|
"Configure the system to use GRUB2 as the bootloader, and set boot options.",
|
||||||
|
"Sets the GRUB2 boot/root filesystem to `rootfs`. If a separated boot",
|
||||||
|
"partition is used it can be specified via `bootfs`. The file-systems",
|
||||||
|
"can be identified either via uuid (`{\"uuid\": \"<uuid>\"}`) or label",
|
||||||
|
"(`{\"label\": \"<label>\"}`). The kernel boot argument will be composed",
|
||||||
|
"of the root file system id and additional options specified in",
|
||||||
|
"`{kernel_opts}`, if any.",
|
||||||
|
"Configures GRUB2 to boot via the Boot Loader Specification",
|
||||||
|
"(https://systemd.io/BOOT_LOADER_SPECIFICATION), which is the default",
|
||||||
|
"behavior in Fedora 30 and later.",
|
||||||
|
"This stage will overwrite `/etc/default/grub`, `/boot/grub2/grubenv`, and",
|
||||||
|
"`/boot/grub2/grub.cfg`. (Leading directories will be created if not present.)",
|
||||||
|
"If Legacy boot support is requested via `legacy` this stage will also",
|
||||||
|
"overwrite `/boot/grub2/grub.cfg` and will copy the GRUB2 files from the",
|
||||||
|
"buildhost into the target tree:",
|
||||||
|
"* `/usr/share/grub/unicode.pf2` -> `/boot/grub2/fonts/`",
|
||||||
|
"* `/usr/lib/grub/$platform/*.{mod,lst}` -> `/boot/grub2/$platform/`",
|
||||||
|
" * NOTE: skips `fdt.lst`, which is an empty file",
|
||||||
|
"The $platform variable (default: i386-pc) refers to target platform",
|
||||||
|
"that grub2 is mean to ran on (see grub-install(1)'s `--target`)",
|
||||||
|
"NB: with legacy support enabled, this stage will fail if the buildhost",
|
||||||
|
"doesn't have `/usr/lib/grub/$platform/` and `/usr/share/grub/unicode.pf2`.",
|
||||||
|
"If UEFI support is enabled via `uefi: {\"vendor\": \"<vendor>\"}` this stage will",
|
||||||
|
"also write the `grub.cfg` to `boot/efi/EFI/<vendor>/grub.cfg`. EFI binaries",
|
||||||
|
"and accompanying data can be installed from the built root via `uefi.install`.",
|
||||||
|
"Both UEFI and Legacy can be specified at the same time (hybrid boot).",
|
||||||
|
"If `uefi.unified` is specified or hybrid boot is enabled, the main grub config",
|
||||||
|
"will be written to `boot/grub2/grub.cfg` and a redirect config will be placed",
|
||||||
|
"in the EFI directory.",
|
||||||
|
"If the `saved_entry` option is present it will result in an entry in the",
|
||||||
|
"`grubenv` file of the same name. The grub config file contains logic so",
|
||||||
|
"that this variable will be used to select the next boot entry. This will",
|
||||||
|
"also make grub2-reboot and grub2-set-default tools work. It will also",
|
||||||
|
"prevent newly installed non-default kernels (like e.g. the debug kernel)",
|
||||||
|
"to be selected as default. The contents of variable needs to match the",
|
||||||
|
"corresponding loader entry, which currently is a combination of the",
|
||||||
|
"machine id and kernel NVRA, like e.g.:",
|
||||||
|
" `ffffffffffffffffffffffffffffffff-5.6.6-300.fc32.x86_64`",
|
||||||
|
"If `saved_entry` is set it is advisable to set `config.default` to",
|
||||||
|
"`saved` so that any re-creation of the grub configuration by the",
|
||||||
|
"user will preserve that functionality.",
|
||||||
|
"Support for \"greenboot\" can be turned on via the `greenboot` option.",
|
||||||
|
"Greenboot is the idea of automatically rolling back bad updates,",
|
||||||
|
"i.e. updates that do not boot successfully. The implementation",
|
||||||
|
"is split between the boot loader and a user space component.",
|
||||||
|
"The latter sets two variables `boot_counter`, which indicates",
|
||||||
|
"the maximum number of boot attempts and `boot_success` which",
|
||||||
|
"tells the boot laoder if a previous boot was successful. The",
|
||||||
|
"bootloader on the other hand will decrement the counter variable",
|
||||||
|
"and reset the success indicator one.",
|
||||||
|
"An implementation of the user space component for rpm-ostree is",
|
||||||
|
"called `greenboot`.",
|
||||||
|
"Support for ignition (https://github.com/coreos/ignition) can be turned",
|
||||||
|
"on via the `ignition` option. If enabled, a 'ignition_firstboot' variable",
|
||||||
|
"will be created, which is meant to be included in the kernel command line.",
|
||||||
|
"The grub.cfg will then contain the necessary code to detect and source",
|
||||||
|
"the '/boot/ignition.firstboot' file and configure said 'ignition_firstboot'",
|
||||||
|
"variable appropriately. See the 'org.osbuild.ignition' stage for more",
|
||||||
|
"information on that file."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"root_fs_uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"rootfs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"definitions": {
|
||||||
|
"uuid": {
|
||||||
|
"description": "Identify the file system by UUID",
|
||||||
|
"type": "string",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"pattern": "^[0-9A-Za-z]{8}(-[0-9A-Za-z]{4}){3}-[0-9A-Za-z]{12}$",
|
||||||
|
"examples": [
|
||||||
|
"9c6ae55b-cf88-45b8-84e8-64990759f39d"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "^[0-9A-Za-z]{4}-[0-9A-Za-z]{4}$",
|
||||||
|
"examples": [
|
||||||
|
"6699-AFB5"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"filesystem": {
|
||||||
|
"description": "Description of how to locate a file system",
|
||||||
|
"type": "object",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"label"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"label": {
|
||||||
|
"description": "Identify the file system by label",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"$ref": "#/definitions/uuid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"terminal": {
|
||||||
|
"description": "Terminal device",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"rootfs": {
|
||||||
|
"$ref": "#/definitions/filesystem"
|
||||||
|
},
|
||||||
|
"bootfs": {
|
||||||
|
"$ref": "#/definitions/filesystem"
|
||||||
|
},
|
||||||
|
"root_fs_uuid": {
|
||||||
|
"$ref": "#/definitions/uuid"
|
||||||
|
},
|
||||||
|
"boot_fs_uuid": {
|
||||||
|
"$ref": "#/definitions/uuid"
|
||||||
|
},
|
||||||
|
"kernel_opts": {
|
||||||
|
"description": "Additional kernel boot options",
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"legacy": {
|
||||||
|
"description": "Include legacy boot support",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"uefi": {
|
||||||
|
"description": "Include UEFI boot support",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"vendor"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"vendor": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The vendor of the UEFI binaries (this is us)",
|
||||||
|
"examples": [
|
||||||
|
"fedora"
|
||||||
|
],
|
||||||
|
"pattern": "^(.+)$"
|
||||||
|
},
|
||||||
|
"efi_src_dir": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The source path to use for the EFI/ binaries when installing is set to True",
|
||||||
|
"default": "/boot/efi/EFI"
|
||||||
|
},
|
||||||
|
"install": {
|
||||||
|
"description": "Install EFI binaries and data from the build root",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"unified": {
|
||||||
|
"description": "Main grub config in 'boot/grub2/grub.cfg'",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"saved_entry": {
|
||||||
|
"description": "Set the variable of the same name in `grubenv`.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"write_defaults": {
|
||||||
|
"description": "Whether to write /etc/defaults/grub",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"write_cmdline": {
|
||||||
|
"description": "Include the kernel command line in `grubenv`",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"ignition": {
|
||||||
|
"description": "Include ignition support in the grub.cfg",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"greenboot": {
|
||||||
|
"description": "Include support for fallback counting",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"description": "Configuration options for grub itself",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"default": {
|
||||||
|
"description": "Default boot entry",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"disable_recovery": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"disable_submenu": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"distributor": {
|
||||||
|
"description": "Name of the distributor",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"terminal": {
|
||||||
|
"$ref": "#/definitions/terminal"
|
||||||
|
},
|
||||||
|
"terminal_input": {
|
||||||
|
"$ref": "#/definitions/terminal"
|
||||||
|
},
|
||||||
|
"terminal_output": {
|
||||||
|
"$ref": "#/definitions/terminal"
|
||||||
|
},
|
||||||
|
"timeout": {
|
||||||
|
"description": "Timeout in seconds",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"timeout_style": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"hidden",
|
||||||
|
"menu",
|
||||||
|
"countdown"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"serial": {
|
||||||
|
"description": "The command to configure the serial console",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,40 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Extract a gzipped file
|
|
||||||
|
|
||||||
Buildhost commands used: `gunzip`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"inputs": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["file"],
|
|
||||||
"properties": {
|
|
||||||
"file": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["path"],
|
|
||||||
"properties": {
|
|
||||||
"path": {
|
|
||||||
"description": "Unzip here.",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def parse_input(inputs):
|
def parse_input(inputs):
|
||||||
image = inputs["file"]
|
image = inputs["file"]
|
||||||
|
|
|
||||||
33
stages/org.osbuild.gunzip.meta.json
Normal file
33
stages/org.osbuild.gunzip.meta.json
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"summary": "Extract a gzipped file",
|
||||||
|
"description": [
|
||||||
|
"Buildhost commands used: `gunzip`."
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"inputs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"file"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"file": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"description": "Unzip here.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,47 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Compress a file using gzip
|
|
||||||
|
|
||||||
Buildhost commands used: `gzip`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA_2 = r"""
|
|
||||||
"inputs": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["file"],
|
|
||||||
"properties": {
|
|
||||||
"file": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["filename"],
|
|
||||||
"properties": {
|
|
||||||
"filename": {
|
|
||||||
"description": "Filename to use for the compressed file",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"level": {
|
|
||||||
"description": "Compression level",
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 1,
|
|
||||||
"maximum": 9,
|
|
||||||
"default": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def parse_input(inputs):
|
def parse_input(inputs):
|
||||||
image = inputs["file"]
|
image = inputs["file"]
|
||||||
|
|
|
||||||
40
stages/org.osbuild.gzip.meta.json
Normal file
40
stages/org.osbuild.gzip.meta.json
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"summary": "Compress a file using gzip",
|
||||||
|
"description": [
|
||||||
|
"Buildhost commands used: `gzip`."
|
||||||
|
],
|
||||||
|
"schema_2": {
|
||||||
|
"inputs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"file"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"file": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"filename"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"filename": {
|
||||||
|
"description": "Filename to use for the compressed file",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"level": {
|
||||||
|
"description": "Compression level",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 9,
|
||||||
|
"default": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,32 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Set system hostname
|
|
||||||
|
|
||||||
Sets system hostname.
|
|
||||||
|
|
||||||
Deletes /etc/hostname if present, then runs `systemd-firstboot` from the
|
|
||||||
buildhost with `--hostname={hostname}`, which checks the validity of the
|
|
||||||
hostname and writes it to /etc/hostname.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["hostname"],
|
|
||||||
"properties": {
|
|
||||||
"hostname": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "hostname for the target system"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
hostname = options["hostname"]
|
hostname = options["hostname"]
|
||||||
|
|
|
||||||
21
stages/org.osbuild.hostname.meta.json
Normal file
21
stages/org.osbuild.hostname.meta.json
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"summary": "Set system hostname",
|
||||||
|
"description": [
|
||||||
|
"Sets system hostname.",
|
||||||
|
"Deletes /etc/hostname if present, then runs `systemd-firstboot` from the",
|
||||||
|
"buildhost with `--hostname={hostname}`, which checks the validity of the",
|
||||||
|
"hostname and writes it to /etc/hostname."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"hostname"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"hostname": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "hostname for the target system"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,39 +1,8 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Setup ignition so it will be triggered on first boot.
|
|
||||||
|
|
||||||
Create the file '/boot/ignition.firstboot' that will be used by grub,
|
|
||||||
if the necessary ignition support is enabled, to create a variable to
|
|
||||||
be used in the kernel command line ('ignition_firstboot'). Via this
|
|
||||||
variable, if included in the actual kernel command line, the run of
|
|
||||||
ignition during early boot can be controlled: if grub detects the
|
|
||||||
aforementioned file to be present it will set 'ignition_firstboot'
|
|
||||||
to "ignition.firstboot" which is the trigger for ignition to run.
|
|
||||||
The "ignition-firstboot-complete.service" will remove said file and
|
|
||||||
thus preventing ignition to be run on the next boot.
|
|
||||||
|
|
||||||
The `network` option can be used to overwrite the default network
|
|
||||||
configuration, in case that ignition is run.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"network": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Overwrite default network connection",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
network = options.get("network", [])
|
network = options.get("network", [])
|
||||||
|
|
|
||||||
28
stages/org.osbuild.ignition.meta.json
Normal file
28
stages/org.osbuild.ignition.meta.json
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"summary": "Setup ignition so it will be triggered on first boot.",
|
||||||
|
"description": [
|
||||||
|
"Create the file '/boot/ignition.firstboot' that will be used by grub,",
|
||||||
|
"if the necessary ignition support is enabled, to create a variable to",
|
||||||
|
"be used in the kernel command line ('ignition_firstboot'). Via this",
|
||||||
|
"variable, if included in the actual kernel command line, the run of",
|
||||||
|
"ignition during early boot can be controlled: if grub detects the",
|
||||||
|
"aforementioned file to be present it will set 'ignition_firstboot'",
|
||||||
|
"to \"ignition.firstboot\" which is the trigger for ignition to run.",
|
||||||
|
"The \"ignition-firstboot-complete.service\" will remove said file and",
|
||||||
|
"thus preventing ignition to be run on the next boot.",
|
||||||
|
"The `network` option can be used to overwrite the default network",
|
||||||
|
"configuration, in case that ignition is run."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"network": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Overwrite default network connection",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,28 +1,10 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Implant an MD5 checksum in an ISO9660 image
|
|
||||||
|
|
||||||
This stage is using implantisomd5(1) to implant MD5 checksums into an iso
|
|
||||||
image. This is needed for the check media feature used in the installer.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA = """
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["filename"],
|
|
||||||
"properties": {
|
|
||||||
"filename": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Path to where the iso to implant md5s is located."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main(tree, options):
|
def main(tree, options):
|
||||||
filename = options["filename"].lstrip("/")
|
filename = options["filename"].lstrip("/")
|
||||||
|
|
|
||||||
19
stages/org.osbuild.implantisomd5.meta.json
Normal file
19
stages/org.osbuild.implantisomd5.meta.json
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"summary": "Implant an MD5 checksum in an ISO9660 image",
|
||||||
|
"description": [
|
||||||
|
"This stage is using implantisomd5(1) to implant MD5 checksums into an iso",
|
||||||
|
"image. This is needed for the check media feature used in the installer."
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"filename"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"filename": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path to where the iso to implant md5s is located."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
"""
|
|
||||||
Create an isolinux bootloader
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import string
|
import string
|
||||||
|
|
@ -10,51 +6,6 @@ import sys
|
||||||
|
|
||||||
import osbuild.api
|
import osbuild.api
|
||||||
|
|
||||||
SCHEMA_2 = """
|
|
||||||
"options": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["product", "kernel"],
|
|
||||||
"properties": {
|
|
||||||
"product": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["name", "version"],
|
|
||||||
"properties": {
|
|
||||||
"name": {"type": "string"},
|
|
||||||
"version": {"type": "string"}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kernel": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["dir"],
|
|
||||||
"properties": {
|
|
||||||
"dir": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"opts": {
|
|
||||||
"description": "Array of group names for this user",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inputs": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["data"],
|
|
||||||
"properties": {
|
|
||||||
"data": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
# The isolinux configuration template
|
# The isolinux configuration template
|
||||||
ISOLINUX_CFG_TEMPLATE = """
|
ISOLINUX_CFG_TEMPLATE = """
|
||||||
|
|
|
||||||
62
stages/org.osbuild.isolinux.meta.json
Normal file
62
stages/org.osbuild.isolinux.meta.json
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
{
|
||||||
|
"summary": "Create an isolinux bootloader",
|
||||||
|
"description": [],
|
||||||
|
"schema_2": {
|
||||||
|
"options": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"product",
|
||||||
|
"kernel"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"product": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"version"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"kernel": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"dir"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"dir": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"opts": {
|
||||||
|
"description": "Array of group names for this user",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inputs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"data"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue