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
|
When running a container from the ZFSBootMenu builder image, it is generally
|
||||||
expected that some compatible volume (generally, a local directory) will be
|
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
|
bind-mounted as a volume at the path `/build` inside the container. The volume
|
||||||
may either be empty or contain a pre-existing ZFSBootMenu source tree.
|
may either be empty or contain a custom ZFSBootMenu configuration and will
|
||||||
Specifically, if the volume is not empty, it must contain the following
|
contain build products (a UEFI bundle, separate kernel and initramfs
|
||||||
components of the ZFSBootMenu repository:
|
components, or both) in a `build` subdirectory.
|
||||||
|
|
||||||
- `dracut`, the Dracut module that populates an image with ZFSBootMenu;
|
The container entrypoint expects to run `generate-zbm` directly from a
|
||||||
|
ZFSBootMenu source repository that is available at `/zbm` within the container.
|
||||||
- `zfsbootmenu`, the core ZFSBootMenu components;
|
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,
|
||||||
- `bin/generate-zbm`, the executable script that creates ZFSBootMenu images;
|
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
|
||||||
If the build script finds the volume mounted at `/zbm` empty, it will fetch an
|
`/zbm` within the container must contain a copy of the source repository. This
|
||||||
archive of the official ZFSBootMenu repository on github.com. This makes the
|
is useful, *e.g.*, to bind-mount a local clone of the repository into the
|
||||||
image capable of producing default images without needing a local clone of the
|
container.
|
||||||
repository. The specific commit, tag or branch to fetch can be specified at
|
|
||||||
container run time.
|
|
||||||
|
|
||||||
## Command-Line Arguments and Environment Variables
|
## 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:
|
options. The options are:
|
||||||
|
|
||||||
- `$BUILDROOT` specifies a default root for image builds. The build root is
|
- `$BUILDROOT` specifies a default root for image builds. The build root is
|
||||||
expected to hold a default default configuration file and output directory,
|
expected to hold configuration files and, optionally, an output directory,
|
||||||
as well as optional hostid and pool cache files. If an output directory,
|
hostid and pool cache files. The value of `$BUILDROOT` is `/build` by
|
||||||
specific configuration and (when appropriate) hostid or pool cache are
|
default.
|
||||||
specified, then `$BUILDROOT` is not relevant.
|
|
||||||
|
|
||||||
The environment variable or default can be overridden with the `-b` option.
|
The environment variable or default can be overridden with the `-b` option.
|
||||||
|
|
||||||
- `$ZBMCONF` specifies the in-container path to a specific configuration file.
|
- `$ZBMOUTPUT` specifies an alternative output directory for ZFSBootMenu build
|
||||||
The build script will override any `ImageDir` paths and remove any
|
products. The container *always* overrides configurations to store build
|
||||||
`Global.BootMountPoint` option but otherwise uses the configuration as-is.A
|
products (UEFI bundles and kernel components, as configured) in a temporary
|
||||||
|
directory; these products will be copied to `$ZBMOUTPUT` after successful
|
||||||
The environment variable or default can be overridded with the `-c` option.
|
image creation. The value of `$ZBMOUTPUT` is `${BUILDROOT}/build` by default.
|
||||||
|
|
||||||
- `$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`.
|
|
||||||
|
|
||||||
The environment variable or default can be overridded with the `-o` option.
|
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
|
- `$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
|
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,
|
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.
|
The environment variable or default can be overridded with the `-t` option.
|
||||||
|
|
||||||
An additional command-line argument, `-e`, allows the ZFSBootMenu configuration
|
A couple of additional arguments may only be set from the command line:
|
||||||
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,
|
- `-e <statement>` provides a statement that will be evaluated via `yq-go eval`
|
||||||
what will happen!
|
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
|
## Build Examples
|
||||||
|
|
||||||
To use the previously created `zbm` image to produce ZFSBootMenu files from the
|
To use the previously created `zbm` image to produce ZFSBootMenu files from the
|
||||||
default configuration using a local ZFSBootMenu repository `/sw/zfsbootmenu`,
|
default configuration, simply run
|
||||||
simply run
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
podman run -v /sw/zfsbootmenu:/zbm zbm
|
podman run -v .:/build zbm
|
||||||
```
|
```
|
||||||
|
|
||||||
After some console output, the container should terminate and the directory
|
After some console output, the container should terminate and the directory
|
||||||
`/sw/zfsbootmenu/releng/docker/build` should contain the UEFI bundle
|
`./build` should contain the UEFI bundle `vmlinuz.EFI` as well as the
|
||||||
`vmlinuz.EFI` as well as the components `vmlinuz-bootmenu` (a stock Void Linux
|
components `vmlinuz-bootmenu` (a stock Void Linux kernel) and corresponding
|
||||||
kernel) and corresponding ZFSBootMenu initramfs `initramfs-bootmenu.img`.
|
ZFSBootMenu initramfs `initramfs-bootmenu.img`.
|
||||||
|
|
||||||
In the default configuration, the ZFSBootMenu images probably contain an
|
To provide the hostid and pool cache files to the build container and run from
|
||||||
arbitrary `/etc/hostid` that likely does not agree with the corresponding file
|
the `/etc/zfsbootmenu/build` directory, copy the desired files and run the
|
||||||
on the host. To make sure that the hostid within the images remains consistent
|
container with the appropriate volume mount:
|
||||||
with the build host, first copy the file from the host to the `releng/docker`
|
|
||||||
directory:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cp /etc/hostid /sw/zfsbootmenu/releng/docker/hostid
|
cp /etc/hostid /etc/zfs/zpool.cache /etc/zfsbootmenu/build
|
||||||
podman run -v /sw/zfsbootmenu:/zbm zbm
|
podman run -v /etc/zfsbootmenu/build:/build zbm
|
||||||
```
|
```
|
||||||
|
|
||||||
To create an image from the current `master` branch without having a local
|
To create an image from a local repository available at `/sw/zfsbootmenu` and
|
||||||
repository, store the output images in `/boot/efi/EFI/zfsbootmenu` and include
|
again use a build root of `/etc/zfsbootmenu/build`, run
|
||||||
the hostid of the current system, assuming a `zbm` builder container is tagged
|
|
||||||
locally:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mkdir -p /boot/efi/EFI/zfsbootmenu
|
podman run -v /etc/zfsbootmenu/build:/build -v /sw/zfsbootmenu:/zbm:ro zbm
|
||||||
podman run -v /boot/efi/EFI/zfsbootmenu:/output \
|
|
||||||
-v /etc/hostid:/hostid:ro zbm -o /output -H /hostid
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Using Docker Compose
|
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)
|
||||||
The file `docker-compose.yml` defines a Docker Compose service that will create
|
without consequence.
|
||||||
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.
|
|
||||||
|
|
|
@ -24,22 +24,10 @@ Usage: $0 [options]
|
||||||
Specify path for build root
|
Specify path for build root
|
||||||
(Default: /build)
|
(Default: /build)
|
||||||
|
|
||||||
-c <configuration>
|
|
||||||
Specify path to generate-zbm(5) configuration
|
|
||||||
(Default: \${BUILDROOT}/config.yaml or \${BUILDROOT}/config.yaml.default)
|
|
||||||
|
|
||||||
-o <output-directory>
|
-o <output-directory>
|
||||||
Specify path to output directory
|
Specify path to output directory
|
||||||
(Default: \${BUILDROOT}/build)
|
(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>
|
-p <package>
|
||||||
Install the named Void Linux package in the container
|
Install the named Void Linux package in the container
|
||||||
before building. May be specified more than once to
|
before building. May be specified more than once to
|
||||||
|
@ -66,23 +54,14 @@ EOF
|
||||||
PACKAGES=()
|
PACKAGES=()
|
||||||
CONFIGEVALS=()
|
CONFIGEVALS=()
|
||||||
GENARGS=()
|
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
|
case "${opt}" in
|
||||||
c)
|
|
||||||
ZBMCONF="${OPTARG}"
|
|
||||||
;;
|
|
||||||
b)
|
b)
|
||||||
BUILDROOT="${OPTARG}"
|
BUILDROOT="${OPTARG}"
|
||||||
;;
|
;;
|
||||||
o)
|
o)
|
||||||
ZBMOUTPUT="${OPTARG}"
|
ZBMOUTPUT="${OPTARG}"
|
||||||
;;
|
;;
|
||||||
H)
|
|
||||||
HOSTID="${OPTARG}"
|
|
||||||
;;
|
|
||||||
C)
|
|
||||||
POOLCACHE="${OPTARG}"
|
|
||||||
;;
|
|
||||||
t)
|
t)
|
||||||
ZBMTAG="${OPTARG}"
|
ZBMTAG="${OPTARG}"
|
||||||
;;
|
;;
|
||||||
|
@ -175,18 +154,6 @@ mkdir -p /usr/lib/dracut/modules.d
|
||||||
ln -Tsf "${dracutmod}" /usr/lib/dracut/modules.d/90zfsbootmenu \
|
ln -Tsf "${dracutmod}" /usr/lib/dracut/modules.d/90zfsbootmenu \
|
||||||
|| error "unable to link dracut module"
|
|| 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
|
# Make sure the build root exists
|
||||||
: "${BUILDROOT:=/build}"
|
: "${BUILDROOT:=/build}"
|
||||||
mkdir -p "${BUILDROOT}" || error "unable to create directory '${BUILDROOT}'"
|
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}"
|
: "${ZBMOUTPUT:=${BUILDROOT}/build}"
|
||||||
mkdir -p "${ZBMOUTPUT}" || error "unable to create directory '${ZBMOUTPUT}'"
|
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
|
# Add forced overrides to the end of CONFIGEVALS
|
||||||
CONFIGEVALS+=(
|
CONFIGEVALS+=(
|
||||||
".Global.ManageImages = true"
|
".Global.ManageImages = true"
|
||||||
".Components.ImageDir = \"${ZBMWORKDIR}/build/components\""
|
".Components.ImageDir = \"${ZBMOUTPUT}\""
|
||||||
".EFI.ImageDir = \"${ZBMWORKDIR}/build\""
|
".EFI.ImageDir = \"${ZBMOUTPUT}\""
|
||||||
"del(.Global.BootMountPoint)"
|
"del(.Global.BootMountPoint)"
|
||||||
)
|
)
|
||||||
|
|
||||||
mkdir -p "${ZBMWORKDIR}/build" || error "unable to create build directory"
|
# Use provided hostid and zpool.cache files
|
||||||
|
if [ -r "${BUILDROOT}/hostid" ]; then
|
||||||
# Apply CONFIGEVALS to override configuration
|
ln -Tsf "${BUILDROOT}/hostid" /etc/hostid \
|
||||||
for ceval in "${CONFIGEVALS[@]}"; do
|
|| error "failed to link hostid"
|
||||||
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"
|
|
||||||
else
|
else
|
||||||
rm -f /etc/hostid
|
rm -f /etc/hostid
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Copy the pool cache in place if specified, otherwise remove any cache
|
if [ -r "${BUILDROOT}/zpool.cache" ]; then
|
||||||
if [ -n "${POOLCACHE}" ]; then
|
|
||||||
mkdir -p /etc/zfs
|
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
|
else
|
||||||
rm -f /etc/zfs/zpool.cache
|
rm -f /etc/zfs/zpool.cache
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If a custom dracut.conf.d exists, link to its contents in the default location
|
# Link all configuration files in standard location;
|
||||||
if [ -d "${BUILDROOT}/dracut.conf.d" ]; then
|
# go from most generic to most specificj
|
||||||
for cfile in "${BUILDROOT}"/dracut.conf.d/*; do
|
mkdir -p /etc/zfsbootmenu
|
||||||
[ -e "${cfile}" ] || continue
|
confroots=(
|
||||||
ln -Tsf "${cfile}" "${dconfd}/${cfile##*/}" || error "unable to link ${cfile}"
|
"/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
|
done
|
||||||
fi
|
|
||||||
|
|
||||||
/zbm/bin/generate-zbm "${GENARGS[@]}" || error "failed to build images"
|
for confd in "dracut.conf.d" "mkinitcpio.conf.d"; do
|
||||||
|
mkdir -p "/etc/zfsbootmenu/${confd}"
|
||||||
for f in "${ZBMWORKDIR}"/build/*; do
|
for cfile in "${confroot}/${confd}"/*; do
|
||||||
[ "${f}" != "${ZBMWORKDIR}/build/*" ] || error "no images to copy to output"
|
[ -e "${cfile}" ] || continue
|
||||||
cp -R "${f}" "${ZBMOUTPUT}"
|
ln -Tsf "${cfile}" "/etc/zfsbootmenu/${confd}/${cfile##*/}" \
|
||||||
|
|| error "unable to link ${cfile}"
|
||||||
|
done
|
||||||
|
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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean_enabled() {
|
||||||
|
local val="${1:-}"
|
||||||
|
|
||||||
|
case "${val}" in
|
||||||
|
[Yy][Ee][Ss]|[Yy]|[Oo][Nn]|1) return 0 ;;
|
||||||
|
*) return 1 ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat << EOF
|
cat << EOF
|
||||||
Build ZFSBootMenu images in an OCI container using podman or docker.
|
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)
|
Build specific ZFSBootMenu commit or tag (e.g. v1.12.0, d5594589)
|
||||||
(Default: current upstream master)
|
(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
|
-C Do not include host /etc/zfs/zpool.cache in image
|
||||||
(If ./zpool.cache exists, this switch will be ignored)
|
(If ./zpool.cache exists, this switch will be ignored)
|
||||||
|
|
||||||
|
@ -63,6 +74,7 @@ EOF
|
||||||
|
|
||||||
SKIP_HOSTID=
|
SKIP_HOSTID=
|
||||||
SKIP_CACHE=
|
SKIP_CACHE=
|
||||||
|
REMOVE_HOST_FILES=
|
||||||
|
|
||||||
# By default, use the latest upstream build container image
|
# By default, use the latest upstream build container image
|
||||||
BUILD_IMG="ghcr.io/zbm-dev/zbm-builder:latest"
|
BUILD_IMG="ghcr.io/zbm-dev/zbm-builder:latest"
|
||||||
|
@ -80,24 +92,64 @@ BUILD_ARGS=()
|
||||||
# Volume mounts for the container manager
|
# Volume mounts for the container manager
|
||||||
VOLUME_ARGS=()
|
VOLUME_ARGS=()
|
||||||
|
|
||||||
|
# Optional configuration file
|
||||||
|
CONFIG=
|
||||||
|
|
||||||
if command -v podman >/dev/null 2>&1; then
|
if command -v podman >/dev/null 2>&1; then
|
||||||
PODMAN="podman"
|
PODMAN="podman"
|
||||||
else
|
else
|
||||||
PODMAN="docker"
|
PODMAN="docker"
|
||||||
fi
|
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
|
case "${opt}" in
|
||||||
b)
|
b)
|
||||||
BUILD_DIRECTORY="${OPTARG}"
|
BUILD_DIRECTORY="${OPTARG}"
|
||||||
;;
|
;;
|
||||||
d)
|
c)
|
||||||
PODMAN=docker
|
CONFIG="${OPTARG}"
|
||||||
;;
|
;;
|
||||||
h)
|
h)
|
||||||
usage
|
usage
|
||||||
exit 0
|
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)
|
i)
|
||||||
BUILD_IMG="${OPTARG}"
|
BUILD_IMG="${OPTARG}"
|
||||||
;;
|
;;
|
||||||
|
@ -113,6 +165,9 @@ while getopts "b:dhi:l:t:p:v:CH" opt; do
|
||||||
H)
|
H)
|
||||||
SKIP_HOSTID="yes"
|
SKIP_HOSTID="yes"
|
||||||
;;
|
;;
|
||||||
|
R)
|
||||||
|
REMOVE_HOST_FILES="yes"
|
||||||
|
;;
|
||||||
p)
|
p)
|
||||||
BUILD_ARGS+=( "-p" "${OPTARG}" )
|
BUILD_ARGS+=( "-p" "${OPTARG}" )
|
||||||
;;
|
;;
|
||||||
|
@ -132,11 +187,6 @@ if ! command -v "${PODMAN}" >/dev/null 2>&1; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Always mount a build directory at /build
|
# 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" )
|
VOLUME_ARGS+=( "-v" "${BUILD_DIRECTORY}:/build" )
|
||||||
|
|
||||||
# Only mount a local repo at /zbm if specified
|
# Only mount a local repo at /zbm if specified
|
||||||
|
@ -154,9 +204,21 @@ if [ -n "${BUILD_TAG}" ]; then
|
||||||
BUILD_ARGS+=( "-t" "${BUILD_TAG}" )
|
BUILD_ARGS+=( "-t" "${BUILD_TAG}" )
|
||||||
fi
|
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 no local hostid is available, copy the system hostid if desired
|
||||||
if ! [ -r "${BUILD_DIRECTORY}"/hostid ]; then
|
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
|
if ! cp /etc/hostid "${BUILD_DIRECTORY}"/hostid; then
|
||||||
echo "ERROR: unable to copy /etc/hostid"
|
echo "ERROR: unable to copy /etc/hostid"
|
||||||
echo "Copy a hostid file to ./hostid or use -H to disable"
|
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 no local zpool.cache is available, copy the system cache if desired
|
||||||
if ! [ -r "${BUILD_DIRECTORY}"/zpool.cache ]; then
|
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
|
if ! cp /etc/zfs/zpool.cache "${BUILD_DIRECTORY}"/zpool.cache; then
|
||||||
echo "ERROR: unable to copy /etc/zfs/zpool.cache"
|
echo "ERROR: unable to copy /etc/zfs/zpool.cache"
|
||||||
echo "Copy a zpool cache to ./zpool.cache or use -C to disable"
|
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 no config is specified, use in-tree default but force EFI and components
|
||||||
if ! [ -r "${BUILD_DIRECTORY}"/config.yaml ]; then
|
if ! [ -r "${BUILD_DIRECTORY}"/config.yaml ]; then
|
||||||
BUILD_ARGS+=( "-c" "/zbm/etc/zfsbootmenu/config.yaml" )
|
|
||||||
BUILD_ARGS+=( "-e" ".EFI.Enabled=true" )
|
BUILD_ARGS+=( "-e" ".EFI.Enabled=true" )
|
||||||
BUILD_ARGS+=( "-e" ".Components.Enabled=true" )
|
BUILD_ARGS+=( "-e" ".Components.Enabled=true" )
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in New Issue