Improve containerized builds
- "Tiered" configuration simplifies management and allows more targeted overrides, symlinking configs in `/etc/zfsbootmenu` in the container: 1. First tier comes from `etc/zfsbootmenu` (global defaults) 2. Second tier comes from `etc/zbm-builder` (container defaults) 3. Third tier comes from the build root (build specific) Configurations in later tiers override those with conflicting names in earlier tiers. - Tiered configuration now includes mkinitcpio configuration, allowing containers to build mkinitcpio images - Container configuration for mkinitcpio supports dracut-style snippets in `mkinitcpio.conf.d` - The builder now looks for an `rc.d` subdirectory in the build root and will invoke every executable file therein before generating images to provide a means to "terraform" the build container - The `zbm-builder.sh` wrapper now supports a configuration file to allow defaults to be specified; this requires a two-pass getopts to find and load the configuration file before parsing remaining options - A new option to `zbm-builder.sh`, `-R`, will remove any existing host files (`hostid` and `zpool.cache`) from the build root to make sure they are always up to date with the host versions - The container entrypoint now configures `generate-zbm` to write its output directly to the desired output directory rather than staging in a temporary output directory, allowing `generate-zbm` to manage version rollovers as it does in host installations - Remove superfluous arguments from container entrypoint to manage `hostid`, `zpool.cache` and `config.yaml`; the files either exist in the build root or the container will use defaults - Drop `docker-compose.yml` and now-obsolete `config.yaml.default` - Update documentation to better reflect current build procedure
This commit is contained in:
parent
087892c37c
commit
5427883f17
|
@ -0,0 +1,17 @@
|
|||
Global:
|
||||
# Set InitCPIO to true to use mkinitcpio for ZBM images
|
||||
#InitCPIO: true
|
||||
# The build container *forces* Global.ManageImages
|
||||
Components:
|
||||
# Enable only current kernel/initramfs components and a backup
|
||||
Enabled: true
|
||||
Versions: false
|
||||
# The ZBM build container *forces* Components.ImageDir
|
||||
EFI:
|
||||
# Enable only current EFI executable and a backup file
|
||||
Enabled: true
|
||||
Versions: false
|
||||
# The ZBM build container *forces* EFI.ImageDir
|
||||
Kernel:
|
||||
# Set ZBM command-line options for the EFI bundle here
|
||||
CommandLine: zfsbootmenu ro quiet loglevel=4 nomodeset
|
|
@ -0,0 +1,42 @@
|
|||
# This is a specialization of the ZFSBootMenu mkinitcpio.conf file for use in
|
||||
# the ghcr.io/zbm-dev/zbm-builder container. Most documentation has been
|
||||
# omitted. For a description of this file, see the manual pages
|
||||
#
|
||||
# - zfsbootmenu(7)
|
||||
# - mkinitcpio(5)
|
||||
#
|
||||
# As well as a more thoroughly commented version at the location
|
||||
# etc/zfsbootmenu/mkinitcpio.conf in the zfsbootmenu git repository.
|
||||
|
||||
# No specific customizations for container builds
|
||||
MODULES=()
|
||||
BINARIES=()
|
||||
FILES=()
|
||||
|
||||
# Because generate-zbm adds the required 'zfsbootmenu' hook, omit it here.
|
||||
HOOKS=(base udev autodetect modconf block filesystems keyboard)
|
||||
|
||||
# In containers, it is helpful to allow some dynamic configuration. In
|
||||
# particular, the zbm-builder.sh helper script that configures and runs the
|
||||
# build container will automatically create configuration entries in the
|
||||
# subdirectories
|
||||
#
|
||||
# dracut.conf.d
|
||||
# mkinitcpio.conf.d
|
||||
#
|
||||
# of the build directory for any hook found in the subdirectories
|
||||
#
|
||||
# hooks.early_setup.d
|
||||
# hooks.setup.d
|
||||
# hooks.teardown.d
|
||||
#
|
||||
# of the same build directory. Support for mkinitcpio.conf.d mimics similar
|
||||
# support for dracut.conf.d built directly into dracut.
|
||||
#
|
||||
# Note that, inside the container, the build directory will be mounted at
|
||||
# /build, so reference those paths here.
|
||||
for _zbm_hook in /build/mkinitcpio.conf.d/*; do
|
||||
[ -r "${_zbm_hook}" ] || continue
|
||||
. "${_zbm_hook}"
|
||||
done
|
||||
unset _zbm_hook
|
|
@ -63,22 +63,20 @@ specific commit based on the contents of `/etc/zbm-commit-hash`.
|
|||
|
||||
When running a container from the ZFSBootMenu builder image, it is generally
|
||||
expected that some compatible volume (generally, a local directory) will be
|
||||
bind-mounted as a volume at the path `/zbm` inside the container. This volume
|
||||
may either be empty or contain a pre-existing ZFSBootMenu source tree.
|
||||
Specifically, if the volume is not empty, it must contain the following
|
||||
components of the ZFSBootMenu repository:
|
||||
bind-mounted as a volume at the path `/build` inside the container. The volume
|
||||
may either be empty or contain a custom ZFSBootMenu configuration and will
|
||||
contain build products (a UEFI bundle, separate kernel and initramfs
|
||||
components, or both) in a `build` subdirectory.
|
||||
|
||||
- `dracut`, the Dracut module that populates an image with ZFSBootMenu;
|
||||
|
||||
- `zfsbootmenu`, the core ZFSBootMenu components;
|
||||
|
||||
- `bin/generate-zbm`, the executable script that creates ZFSBootMenu images;
|
||||
|
||||
If the build script finds the volume mounted at `/zbm` empty, it will fetch an
|
||||
archive of the official ZFSBootMenu repository on github.com. This makes the
|
||||
image capable of producing default images without needing a local clone of the
|
||||
repository. The specific commit, tag or branch to fetch can be specified at
|
||||
container run time.
|
||||
The container entrypoint expects to run `generate-zbm` directly from a
|
||||
ZFSBootMenu source repository that is available at `/zbm` within the container.
|
||||
If the entrypoint finds `/zbm` nonexistent or devoid of files, it will fetch a
|
||||
copy of the upstream source repository and unpack it where expected. (The tag,
|
||||
commit or branch to fetch can be specified at runtime or a default will be
|
||||
chosen as encoded in the container image.) Any pre-existing and non-empty
|
||||
`/zbm` within the container must contain a copy of the source repository. This
|
||||
is useful, *e.g.*, to bind-mount a local clone of the repository into the
|
||||
container.
|
||||
|
||||
## Command-Line Arguments and Environment Variables
|
||||
|
||||
|
@ -88,43 +86,20 @@ command-line argument to see a summary of build options and their default
|
|||
options. The options are:
|
||||
|
||||
- `$BUILDROOT` specifies a default root for image builds. The build root is
|
||||
expected to hold a default default configuration file and output directory,
|
||||
as well as optional hostid and pool cache files. If an output directory,
|
||||
specific configuration and (when appropriate) hostid or pool cache are
|
||||
specified, then `$BUILDROOT` is not relevant.
|
||||
expected to hold configuration files and, optionally, an output directory,
|
||||
hostid and pool cache files. The value of `$BUILDROOT` is `/build` by
|
||||
default.
|
||||
|
||||
The environment variable or default can be overridden with the `-b` option.
|
||||
|
||||
- `$ZBMCONF` specifies the in-container path to a specific configuration file.
|
||||
The build script will override any `ImageDir` paths and remove any
|
||||
`Global.BootMountPoint` option but otherwise uses the configuration as-is.A
|
||||
|
||||
The environment variable or default can be overridded with the `-c` option.
|
||||
|
||||
- `$ZBMOUTPUT` specifies the in-container path to an output directory. As noted
|
||||
above, the build script overrides any `ImageDir` path in a configuration,
|
||||
pointing it instead to a temporary output directory. After the script
|
||||
successfully runs `generate-zbm`, it will copy any artifacts from the
|
||||
temporary build directory to `$ZBMOUTPUT`.
|
||||
- `$ZBMOUTPUT` specifies an alternative output directory for ZFSBootMenu build
|
||||
products. The container *always* overrides configurations to store build
|
||||
products (UEFI bundles and kernel components, as configured) in a temporary
|
||||
directory; these products will be copied to `$ZBMOUTPUT` after successful
|
||||
image creation. The value of `$ZBMOUTPUT` is `${BUILDROOT}/build` by default.
|
||||
|
||||
The environment variable or default can be overridded with the `-o` option.
|
||||
|
||||
- `$HOSTID` specifies the in-container path to a hostid file. If this file is
|
||||
specified, it will be copied to `/etc/hostid` inside the container for
|
||||
inclusion in ZFSBootMenu images. If not, any `/etc/hostid` in the container
|
||||
will be removed. (Note: unless the `zfsbootmenu` dracut module is configured
|
||||
with `release_mode=1`, the module may still create an `/etc/hostid` with
|
||||
potentially arbitrary contents in output images.
|
||||
|
||||
The environment variable or default can be overridded with the `-H` option.
|
||||
|
||||
- `$POOLCACHE` specifies the in-container path to a ZFS pool cache file. If
|
||||
this file is specified, it will be copied to `/etc/zfs/zpool.cache` inside
|
||||
the container for inclusion in ZFSBootMenu images. If not, any
|
||||
`/etc/zfs/zpool.cache` in the container will be removed.
|
||||
|
||||
The environment variable or default can be overridded with the `-C` option.
|
||||
|
||||
- `$ZBMTAG` specifies any "commit-ish" label recognized by `git` as a pointer
|
||||
to a specific git commit. This can be a branch name (to grab the head of that
|
||||
branch), tag or commit hash. If `/zbm` in the container is not pre-populated,
|
||||
|
@ -136,56 +111,133 @@ options. The options are:
|
|||
|
||||
The environment variable or default can be overridded with the `-t` option.
|
||||
|
||||
An additional command-line argument, `-e`, allows the ZFSBootMenu configuration
|
||||
to be modified with `yq-go eval` statements at container run time. Do not use
|
||||
this unless you review the build script and understand, without documentation,
|
||||
what will happen!
|
||||
A couple of additional arguments may only be set from the command line:
|
||||
|
||||
- `-e <statement>` provides a statement that will be evaluated via `yq-go eval`
|
||||
to modify the `generate-zbm` configuration file immediately before an image
|
||||
is built. This option may be specified more than once.
|
||||
|
||||
> Do not use this unless you review the build script and understand, without
|
||||
> documentation, what will happen!
|
||||
|
||||
- `-p <package>` specifies a Void Linux package to install in the container
|
||||
before images are generated. This option may be specified more than once.
|
||||
|
||||
## ZFSBootMenu Configuration and Execution
|
||||
|
||||
After the ZFSBootMenu container entrypoint fetches (or identifies) a copy of
|
||||
the ZFSBootMenu source repository, it "installs" the copy into the container by
|
||||
symlinking key components of the source repository into the container
|
||||
filesystem:
|
||||
|
||||
- If the source repository is sufficiently new, a symbolic link
|
||||
|
||||
/usr/share/zfsbootmenu -> /zbm/zfsbootmenu
|
||||
|
||||
will point to the core ZFSBootMenu library.
|
||||
|
||||
- For newer versions of ZFSBootMenu, the symbolic link
|
||||
|
||||
/usr/lib/dracut/modules.d/90zfsbootmenu -> /zbm/dracut
|
||||
|
||||
will point to the dracut module; for older versions, the link
|
||||
|
||||
/usr/lib/dracut/modules.d/90zfsbootmenu -> /zbm/90zfsbootmenu
|
||||
|
||||
will serve the same purpose.
|
||||
|
||||
- If the ZFSBootMenu repository contains a mkinitcpio module, a family of links
|
||||
|
||||
/usr/lib/initcpio/hooks/* -> /zbm/initcpio/hooks/*
|
||||
/usr/lib/initcpio/install/* -> /zbm/initcpio/install/*
|
||||
|
||||
for each file in `/zbm/initcpio/{hooks,install}` will be made to make
|
||||
`mkinitcpio` aware of the ZFSBootMenu module.
|
||||
|
||||
Configuration files are handled in a multi-pass approach that synthesizes a
|
||||
composite configuration from increasingly specific sources. In the first pass,
|
||||
generic upstream configurations are linked *if the source exists*:
|
||||
|
||||
/etc/zfsbootmenu/config.yaml -> /zbm/etc/zfsbootmenu/config.yaml
|
||||
/etc/zfsbootmenu/mkinitcpio.conf -> /zbm/etc/zfsbootmenu/mkinitcpio.conf
|
||||
/etc/zfsbootmenu/dracut.conf.d/* -> /zbm/etc/zfsbootmenu/dracut.conf.d/*
|
||||
/etc/zfsbootmenu/mkinitcpio.conf.d/* -> /zbm/etc/zfsbootmenu/mkinitcpio.conf.d/*
|
||||
|
||||
Next, container-specific defaults are linked *if the source exists*:
|
||||
|
||||
/etc/zfsbootmenu/config.yaml -> /zbm/etc/zbm-builder/config.yaml
|
||||
/etc/zfsbootmenu/mkinitcpio.conf -> /zbm/etc/zbm-builder/mkinitcpio.conf
|
||||
/etc/zfsbootmenu/dracut.conf.d/* -> /zbm/etc/zbm-builder/dracut.conf.d/*
|
||||
/etc/zfsbootmenu/mkinitcpio.conf.d/* -> /zbm/etc/zbm-builder/mkinitcpio.conf.d/*
|
||||
|
||||
Finally, build-specific configurations are linked *if the source exists*:
|
||||
|
||||
/etc/zfsbootmenu/config.yaml -> ${BUILDROOT}/config.yaml
|
||||
/etc/zfsbootmenu/mkinitcpio.conf -> ${BUILDROOT}/mkinitcpio.conf
|
||||
/etc/zfsbootmenu/dracut.conf.d/* -> ${BUILDROOT}/dracut.conf.d/*
|
||||
/etc/zfsbootmenu/mkinitcpio.conf.d/* -> ${BUILDROOT}/mkinitcpio.conf.d/*
|
||||
|
||||
Conflicting links will *replace* any links made by earlier passes. This allows
|
||||
each level of configurations to mask or augment earlier defaults.
|
||||
|
||||
> NOTE: `mkinitcpio` does not natively support configuration snippets in
|
||||
> `/etc/zfsbootmenu/mkinitcpio.conf.d`. ZFSBootMenu includes a default
|
||||
> `mkinitcpio.conf` that manually sources these snippets to emulate the
|
||||
> standard configuration behavior of dracut.
|
||||
|
||||
In addition, host-specific files are linked if each exists:
|
||||
|
||||
/etc/hostid -> ${BUILDROOT}/hostid
|
||||
/etc/zfs/zpool.cache -> ${BUILDROOT}/zfs/zpool.cache
|
||||
|
||||
When launched, the container entrypoint will run any executable files it finds
|
||||
in `${BUILDROOT}/rc.d`. This provides a means to "terraform" the build
|
||||
container before running `generate-zbm` and can be a useful way to, *e.g.*:
|
||||
|
||||
- Modify the `FONT` variable defined in `/etc/rc.conf`, which will be parsed by
|
||||
`mkinitcpio` to set a default console font in ZFSBootMenu images.
|
||||
|
||||
- Create additional links to directories in `$BUILDROOT`, such as
|
||||
|
||||
/etc/initcpio -> ${BUILDROOT}/initcpio
|
||||
|
||||
to provide additional `mkinitcpio` modules or
|
||||
|
||||
/etc/dropbear -> ${BUILDROOT}/dropbear
|
||||
|
||||
to provide host keys and configuration for the `dropbear` `mkinitcpio`
|
||||
module.
|
||||
|
||||
## Build Examples
|
||||
|
||||
To use the previously created `zbm` image to produce ZFSBootMenu files from the
|
||||
default configuration using a local ZFSBootMenu repository `/sw/zfsbootmenu`,
|
||||
simply run
|
||||
default configuration, simply run
|
||||
|
||||
```sh
|
||||
podman run -v /sw/zfsbootmenu:/zbm zbm
|
||||
podman run -v .:/build zbm
|
||||
```
|
||||
|
||||
After some console output, the container should terminate and the directory
|
||||
`/sw/zfsbootmenu/releng/docker/build` should contain the UEFI bundle
|
||||
`vmlinuz.EFI` as well as the components `vmlinuz-bootmenu` (a stock Void Linux
|
||||
kernel) and corresponding ZFSBootMenu initramfs `initramfs-bootmenu.img`.
|
||||
`./build` should contain the UEFI bundle `vmlinuz.EFI` as well as the
|
||||
components `vmlinuz-bootmenu` (a stock Void Linux kernel) and corresponding
|
||||
ZFSBootMenu initramfs `initramfs-bootmenu.img`.
|
||||
|
||||
In the default configuration, the ZFSBootMenu images probably contain an
|
||||
arbitrary `/etc/hostid` that likely does not agree with the corresponding file
|
||||
on the host. To make sure that the hostid within the images remains consistent
|
||||
with the build host, first copy the file from the host to the `releng/docker`
|
||||
directory:
|
||||
To provide the hostid and pool cache files to the build container and run from
|
||||
the `/etc/zfsbootmenu/build` directory, copy the desired files and run the
|
||||
container with the appropriate volume mount:
|
||||
|
||||
```sh
|
||||
cp /etc/hostid /sw/zfsbootmenu/releng/docker/hostid
|
||||
podman run -v /sw/zfsbootmenu:/zbm zbm
|
||||
cp /etc/hostid /etc/zfs/zpool.cache /etc/zfsbootmenu/build
|
||||
podman run -v /etc/zfsbootmenu/build:/build zbm
|
||||
```
|
||||
|
||||
To create an image from the current `master` branch without having a local
|
||||
repository, store the output images in `/boot/efi/EFI/zfsbootmenu` and include
|
||||
the hostid of the current system, assuming a `zbm` builder container is tagged
|
||||
locally:
|
||||
To create an image from a local repository available at `/sw/zfsbootmenu` and
|
||||
again use a build root of `/etc/zfsbootmenu/build`, run
|
||||
|
||||
```sh
|
||||
mkdir -p /boot/efi/EFI/zfsbootmenu
|
||||
podman run -v /boot/efi/EFI/zfsbootmenu:/output \
|
||||
-v /etc/hostid:/hostid:ro zbm -o /output -H /hostid
|
||||
podman run -v /etc/zfsbootmenu/build:/build -v /sw/zfsbootmenu:/zbm:ro zbm
|
||||
```
|
||||
|
||||
# Using Docker Compose
|
||||
|
||||
The file `docker-compose.yml` defines a Docker Compose service that will create
|
||||
a ZFSBootMenu builder image and mount the parent repository (at path `../..`)
|
||||
at `/zbm` in the build container. To use this service, simply run
|
||||
|
||||
```sh
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
from this directory.
|
||||
Because the build container does not modify the repository found in `/zbm`, it
|
||||
is possible to mount that volume read-only (as indicated by the `:ro` suffix)
|
||||
without consequence.
|
||||
|
|
|
@ -24,22 +24,10 @@ Usage: $0 [options]
|
|||
Specify path for build root
|
||||
(Default: /build)
|
||||
|
||||
-c <configuration>
|
||||
Specify path to generate-zbm(5) configuration
|
||||
(Default: \${BUILDROOT}/config.yaml or \${BUILDROOT}/config.yaml.default)
|
||||
|
||||
-o <output-directory>
|
||||
Specify path to output directory
|
||||
(Default: \${BUILDROOT}/build)
|
||||
|
||||
-H <hostid>
|
||||
Specify path to hostid file
|
||||
(Default: \${BUILDROOT}/hostid)
|
||||
|
||||
-C <cache>
|
||||
Specify path to zpool.cache file
|
||||
(Default: \${BUILDROOT}/zpool.cache)
|
||||
|
||||
-p <package>
|
||||
Install the named Void Linux package in the container
|
||||
before building. May be specified more than once to
|
||||
|
@ -66,23 +54,14 @@ EOF
|
|||
PACKAGES=()
|
||||
CONFIGEVALS=()
|
||||
GENARGS=()
|
||||
while getopts "hc:b:o:H:C:t:e:p:" opt; do
|
||||
while getopts "hb:o:t:e:p:" opt; do
|
||||
case "${opt}" in
|
||||
c)
|
||||
ZBMCONF="${OPTARG}"
|
||||
;;
|
||||
b)
|
||||
BUILDROOT="${OPTARG}"
|
||||
;;
|
||||
o)
|
||||
ZBMOUTPUT="${OPTARG}"
|
||||
;;
|
||||
H)
|
||||
HOSTID="${OPTARG}"
|
||||
;;
|
||||
C)
|
||||
POOLCACHE="${OPTARG}"
|
||||
;;
|
||||
t)
|
||||
ZBMTAG="${OPTARG}"
|
||||
;;
|
||||
|
@ -175,18 +154,6 @@ mkdir -p /usr/lib/dracut/modules.d
|
|||
ln -Tsf "${dracutmod}" /usr/lib/dracut/modules.d/90zfsbootmenu \
|
||||
|| error "unable to link dracut module"
|
||||
|
||||
# generate-zbm configures dracut to look in /etc/zfsbootmenu/dracut.conf.d.
|
||||
# Rather than override the default, just link to the in-repo defaults
|
||||
dconfd="/etc/zfsbootmenu/dracut.conf.d"
|
||||
if [ ! -d "${dconfd}" ]; then
|
||||
mkdir -p "${dconfd}" || error "unable to create dracut configuration directory"
|
||||
|
||||
for cfile in /zbm/etc/zfsbootmenu/dracut.conf.d/*; do
|
||||
[ -e "${cfile}" ] || continue
|
||||
ln -Tsf "${cfile}" "${dconfd}/${cfile##*/}" || error "unable to link ${cfile}"
|
||||
done
|
||||
fi
|
||||
|
||||
# Make sure the build root exists
|
||||
: "${BUILDROOT:=/build}"
|
||||
mkdir -p "${BUILDROOT}" || error "unable to create directory '${BUILDROOT}'"
|
||||
|
@ -195,78 +162,72 @@ mkdir -p "${BUILDROOT}" || error "unable to create directory '${BUILDROOT}'"
|
|||
: "${ZBMOUTPUT:=${BUILDROOT}/build}"
|
||||
mkdir -p "${ZBMOUTPUT}" || error "unable to create directory '${ZBMOUTPUT}'"
|
||||
|
||||
# Pick a default configuration if one was not provided
|
||||
if [ -z "${ZBMCONF}" ]; then
|
||||
if [ -r "${BUILDROOT}/config.yaml" ]; then
|
||||
ZBMCONF="${BUILDROOT}/config.yaml"
|
||||
else
|
||||
ZBMCONF="${BUILDROOT}/config.yaml.default"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Configuration must exist
|
||||
[ -r "${ZBMCONF}" ] || error "missing configuration '${ZBMCONF}'"
|
||||
cp "${ZBMCONF}" "${ZBMWORKDIR}/config.yaml"
|
||||
|
||||
# ZBMCONF now points to local copy
|
||||
ZBMCONF="${ZBMWORKDIR}/config.yaml"
|
||||
|
||||
GENARGS+=( "--config" "${ZBMCONF}" )
|
||||
|
||||
# Add forced overrides to the end of CONFIGEVALS
|
||||
CONFIGEVALS+=(
|
||||
".Global.ManageImages = true"
|
||||
".Components.ImageDir = \"${ZBMWORKDIR}/build/components\""
|
||||
".EFI.ImageDir = \"${ZBMWORKDIR}/build\""
|
||||
".Components.ImageDir = \"${ZBMOUTPUT}\""
|
||||
".EFI.ImageDir = \"${ZBMOUTPUT}\""
|
||||
"del(.Global.BootMountPoint)"
|
||||
)
|
||||
|
||||
mkdir -p "${ZBMWORKDIR}/build" || error "unable to create build directory"
|
||||
|
||||
# Apply CONFIGEVALS to override configuration
|
||||
for ceval in "${CONFIGEVALS[@]}"; do
|
||||
yq-go eval "${ceval}" -i "${ZBMCONF}" || error "failed to apply '${ceval}' to config"
|
||||
done
|
||||
|
||||
# Make sure a hostid and cache, if provided, exist
|
||||
if [ -z "${HOSTID}" ]; then
|
||||
[ -r "${BUILDROOT}/hostid" ] && HOSTID="${BUILDROOT}/hostid"
|
||||
elif [ ! -r "${HOSTID}" ]; then
|
||||
error "missing hostid '${HOSTID}'"
|
||||
fi
|
||||
|
||||
if [ -z "${POOLCACHE}" ]; then
|
||||
[ -r "${BUILDROOT}/zpool.cache" ] && POOLCACHE="${BUILDROOT}/zpool.cache"
|
||||
elif [ ! -r "${POOLCACHE}" ]; then
|
||||
error "missing pool cache '${POOLCACHE}'"
|
||||
fi
|
||||
|
||||
# Copy the hostid in place if specified, otherwise remove any hostid
|
||||
if [ -n "${HOSTID}" ]; then
|
||||
cp "${HOSTID}" "/etc/hostid" || error "unable to copy hostid"
|
||||
# Use provided hostid and zpool.cache files
|
||||
if [ -r "${BUILDROOT}/hostid" ]; then
|
||||
ln -Tsf "${BUILDROOT}/hostid" /etc/hostid \
|
||||
|| error "failed to link hostid"
|
||||
else
|
||||
rm -f /etc/hostid
|
||||
fi
|
||||
|
||||
# Copy the pool cache in place if specified, otherwise remove any cache
|
||||
if [ -n "${POOLCACHE}" ]; then
|
||||
if [ -r "${BUILDROOT}/zpool.cache" ]; then
|
||||
mkdir -p /etc/zfs
|
||||
cp "${POOLCACHE}" /etc/zfs/zpool.cache || error "unable to copy pool cache"
|
||||
ln -Tsf "${BUILDROOT}/zpool.cache" /etc/zfs/zpool.cache \
|
||||
|| error "failed to link zpool.cache"
|
||||
else
|
||||
rm -f /etc/zfs/zpool.cache
|
||||
fi
|
||||
|
||||
# If a custom dracut.conf.d exists, link to its contents in the default location
|
||||
if [ -d "${BUILDROOT}/dracut.conf.d" ]; then
|
||||
for cfile in "${BUILDROOT}"/dracut.conf.d/*; do
|
||||
[ -e "${cfile}" ] || continue
|
||||
ln -Tsf "${cfile}" "${dconfd}/${cfile##*/}" || error "unable to link ${cfile}"
|
||||
# Link all configuration files in standard location;
|
||||
# go from most generic to most specificj
|
||||
mkdir -p /etc/zfsbootmenu
|
||||
confroots=(
|
||||
"/zbm/etc/zfsbootmenu"
|
||||
"/zbm/etc/zbm-builder"
|
||||
"${BUILDROOT}"
|
||||
)
|
||||
for confroot in "${confroots[@]}"; do
|
||||
for cfile in "config.yaml" "mkinitcpio.conf"; do
|
||||
[ -e "${confroot}/${cfile}" ] || continue
|
||||
ln -Tsf "${confroot}/${cfile}" "/etc/zfsbootmenu/${cfile}" \
|
||||
|| error "unable to link mkinitcpio.conf"
|
||||
done
|
||||
fi
|
||||
|
||||
/zbm/bin/generate-zbm "${GENARGS[@]}" || error "failed to build images"
|
||||
|
||||
for f in "${ZBMWORKDIR}"/build/*; do
|
||||
[ "${f}" != "${ZBMWORKDIR}/build/*" ] || error "no images to copy to output"
|
||||
cp -R "${f}" "${ZBMOUTPUT}"
|
||||
for confd in "dracut.conf.d" "mkinitcpio.conf.d"; do
|
||||
mkdir -p "/etc/zfsbootmenu/${confd}"
|
||||
for cfile in "${confroot}/${confd}"/*; do
|
||||
[ -e "${cfile}" ] || continue
|
||||
ln -Tsf "${cfile}" "/etc/zfsbootmenu/${confd}/${cfile##*/}" \
|
||||
|| error "unable to link ${cfile}"
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
# If a custom rc.d exists, run every executable file therein
|
||||
for rfile in "${BUILDROOT}"/rc.d/*; do
|
||||
[ -x "${rfile}" ] || continue
|
||||
"${rfile}" || error "failed to run RC script ${rfile##*/}"
|
||||
done
|
||||
|
||||
# Copy default configuration to temporary directory for modifications
|
||||
ZBMCONF="${ZBMWORKDIR}/config.yaml"
|
||||
cp "/etc/zfsbootmenu/config.yaml" "${ZBMCONF}" \
|
||||
|| error "failed to copy configuration to working directory"
|
||||
|
||||
GENARGS+=( "--config" "${ZBMCONF}" )
|
||||
|
||||
# Apply CONFIGEVALS to override configuration in working directory
|
||||
for ceval in "${CONFIGEVALS[@]}"; do
|
||||
yq-go eval "${ceval}" -i "${ZBMCONF}" \
|
||||
|| error "failed to apply '${ceval}' to config"
|
||||
done
|
||||
|
||||
exec /zbm/bin/generate-zbm "${GENARGS[@]}"
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
Global:
|
||||
# Enable image creation
|
||||
ManageImages: true
|
||||
# Make sure to look for dracut configuration in the repo
|
||||
DracutConfDir: /zbm/etc/zfsbootmenu/dracut.conf.d
|
||||
Components:
|
||||
# zbm-build.sh overwrites this anyway
|
||||
ImageDir: /zbm/releng/docker/build
|
||||
Enabled: true
|
||||
# Disable versioning, this is usually a one-off creation
|
||||
Versions: false
|
||||
syslinux:
|
||||
Enabled: false
|
||||
EFI:
|
||||
# zbm-build.sh overwrites this anyway
|
||||
ImageDir: /zbm/releng/docker/build
|
||||
Versions: false
|
||||
Enabled: true
|
||||
Kernel:
|
||||
# For the EFI bundle, turn off modesetting to avoid initializing GPUs
|
||||
# Also set loglevel=4 to provide some helpful warning output
|
||||
CommandLine: zfsbootmenu ro loglevel=4 nomodeset
|
|
@ -1,9 +0,0 @@
|
|||
# This builds the ZFSBootMenu builder and then runs it to create images
|
||||
version: "2"
|
||||
services:
|
||||
zfsbootmenu-compiler:
|
||||
build: "."
|
||||
# Mount the current repo (../..) where the builder expects it
|
||||
# Outputs will be stored in ../../releng/docker/build
|
||||
volumes:
|
||||
- "../..:/zbm"
|
|
@ -11,6 +11,15 @@ sanitise_path() {
|
|||
return 1
|
||||
}
|
||||
|
||||
boolean_enabled() {
|
||||
local val="${1:-}"
|
||||
|
||||
case "${val}" in
|
||||
[Yy][Ee][Ss]|[Yy]|[Oo][Nn]|1) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat << EOF
|
||||
Build ZFSBootMenu images in an OCI container using podman or docker.
|
||||
|
@ -39,6 +48,8 @@ OPTIONS:
|
|||
Build specific ZFSBootMenu commit or tag (e.g. v1.12.0, d5594589)
|
||||
(Default: current upstream master)
|
||||
|
||||
-R Remove any existing zpool.cache and hostid in the build directory
|
||||
|
||||
-C Do not include host /etc/zfs/zpool.cache in image
|
||||
(If ./zpool.cache exists, this switch will be ignored)
|
||||
|
||||
|
@ -63,6 +74,7 @@ EOF
|
|||
|
||||
SKIP_HOSTID=
|
||||
SKIP_CACHE=
|
||||
REMOVE_HOST_FILES=
|
||||
|
||||
# By default, use the latest upstream build container image
|
||||
BUILD_IMG="ghcr.io/zbm-dev/zbm-builder:latest"
|
||||
|
@ -80,24 +92,64 @@ BUILD_ARGS=()
|
|||
# Volume mounts for the container manager
|
||||
VOLUME_ARGS=()
|
||||
|
||||
# Optional configuration file
|
||||
CONFIG=
|
||||
|
||||
if command -v podman >/dev/null 2>&1; then
|
||||
PODMAN="podman"
|
||||
else
|
||||
PODMAN="docker"
|
||||
fi
|
||||
|
||||
while getopts "b:dhi:l:t:p:v:CH" opt; do
|
||||
CMDOPTS="b:dhi:l:t:p:v:c:CHR"
|
||||
|
||||
# First pass to get build directory and configuration file
|
||||
while getopts "${CMDOPTS}" opt; do
|
||||
case "${opt}" in
|
||||
b)
|
||||
BUILD_DIRECTORY="${OPTARG}"
|
||||
;;
|
||||
d)
|
||||
PODMAN=docker
|
||||
c)
|
||||
CONFIG="${OPTARG}"
|
||||
;;
|
||||
h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Make sure the build directory is identifiable
|
||||
if ! BUILD_DIRECTORY="$( sanitise_path "${BUILD_DIRECTORY}" )"; then
|
||||
echo "ERROR: build directory does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If a configuration wasn't specified, use a default it one exists
|
||||
if [ -z "${CONFIG}" ] && [ -r "${BUILD_DIRECTORY}/zbm-builder.conf" ]; then
|
||||
CONFIG="${BUILD_DIRECTORY}/zbm-builder.conf"
|
||||
fi
|
||||
|
||||
# Read the optional configuration
|
||||
if [ -n "${CONFIG}" ]; then
|
||||
if [ -r "${CONFIG}" ]; then
|
||||
# shellcheck disable=SC1090
|
||||
source "${CONFIG}"
|
||||
else
|
||||
echo "ERROR: non-existent configuration specified"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
OPTIND=1
|
||||
while getopts "${CMDOPTS}" opt; do
|
||||
case "${opt}" in
|
||||
# These have already been parsed in first pass
|
||||
b|c|h)
|
||||
;;
|
||||
d)
|
||||
PODMAN=docker
|
||||
;;
|
||||
i)
|
||||
BUILD_IMG="${OPTARG}"
|
||||
;;
|
||||
|
@ -113,6 +165,9 @@ while getopts "b:dhi:l:t:p:v:CH" opt; do
|
|||
H)
|
||||
SKIP_HOSTID="yes"
|
||||
;;
|
||||
R)
|
||||
REMOVE_HOST_FILES="yes"
|
||||
;;
|
||||
p)
|
||||
BUILD_ARGS+=( "-p" "${OPTARG}" )
|
||||
;;
|
||||
|
@ -132,11 +187,6 @@ if ! command -v "${PODMAN}" >/dev/null 2>&1; then
|
|||
fi
|
||||
|
||||
# Always mount a build directory at /build
|
||||
if ! BUILD_DIRECTORY="$( sanitise_path "${BUILD_DIRECTORY}" )"; then
|
||||
echo "ERROR: build directory does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VOLUME_ARGS+=( "-v" "${BUILD_DIRECTORY}:/build" )
|
||||
|
||||
# Only mount a local repo at /zbm if specified
|
||||
|
@ -154,9 +204,21 @@ if [ -n "${BUILD_TAG}" ]; then
|
|||
BUILD_ARGS+=( "-t" "${BUILD_TAG}" )
|
||||
fi
|
||||
|
||||
if boolean_enabled "${REMOVE_HOST_FILES}"; then
|
||||
# Remove existing host files
|
||||
for host_file in "hostid" "zpool.cache"; do
|
||||
[ -e "${BUILD_DIRECTORY}/${host_file}" ] || continue
|
||||
if ! rm "${BUILD_DIRECTORY}/${host_file}"; then
|
||||
echo "ERROR: failed to remove file '${host_file}' from build directory"
|
||||
exit 1
|
||||
fi
|
||||
echo "Removed file '${host_file}' by user request"
|
||||
done
|
||||
fi
|
||||
|
||||
# If no local hostid is available, copy the system hostid if desired
|
||||
if ! [ -r "${BUILD_DIRECTORY}"/hostid ]; then
|
||||
if [ "${SKIP_HOSTID}" != "yes" ] && [ -r /etc/hostid ]; then
|
||||
if ! boolean_enabled "${SKIP_HOSTID}" && [ -r /etc/hostid ]; then
|
||||
if ! cp /etc/hostid "${BUILD_DIRECTORY}"/hostid; then
|
||||
echo "ERROR: unable to copy /etc/hostid"
|
||||
echo "Copy a hostid file to ./hostid or use -H to disable"
|
||||
|
@ -167,7 +229,7 @@ fi
|
|||
|
||||
# If no local zpool.cache is available, copy the system cache if desired
|
||||
if ! [ -r "${BUILD_DIRECTORY}"/zpool.cache ]; then
|
||||
if [ "${SKIP_CACHE}" != "yes" ] && [ -r /etc/zfs/zpool.cache ]; then
|
||||
if ! boolean_enabled "${SKIP_CACHE}" && [ -r /etc/zfs/zpool.cache ]; then
|
||||
if ! cp /etc/zfs/zpool.cache "${BUILD_DIRECTORY}"/zpool.cache; then
|
||||
echo "ERROR: unable to copy /etc/zfs/zpool.cache"
|
||||
echo "Copy a zpool cache to ./zpool.cache or use -C to disable"
|
||||
|
@ -178,7 +240,6 @@ fi
|
|||
|
||||
# If no config is specified, use in-tree default but force EFI and components
|
||||
if ! [ -r "${BUILD_DIRECTORY}"/config.yaml ]; then
|
||||
BUILD_ARGS+=( "-c" "/zbm/etc/zfsbootmenu/config.yaml" )
|
||||
BUILD_ARGS+=( "-e" ".EFI.Enabled=true" )
|
||||
BUILD_ARGS+=( "-e" ".Components.Enabled=true" )
|
||||
fi
|
||||
|
|
Loading…
Reference in New Issue