nixos/lib/make-disk-image.nix: support content mode and ownership

This commit is contained in:
Francesco Gazzetta 2020-11-19 17:18:02 +01:00
parent 1e5a7a9135
commit 6f21ae7a62

View file

@ -18,9 +18,13 @@
bootSize ? "256M" bootSize ? "256M"
, # The files and directories to be placed in the target file system. , # The files and directories to be placed in the target file system.
# This is a list of attribute sets {source, target} where `source' # This is a list of attribute sets {source, target, mode, user, group} where
# is the file system object (regular file or directory) to be # `source' is the file system object (regular file or directory) to be
# grafted in the file system at path `target'. # grafted in the file system at path `target', `mode' is a string containing
# the permissions that will be set (ex. "755"), `user' and `group' are the
# user and group name that will be set as owner of the files.
# `mode', `user', and `group' are optional.
# When setting one of `user' or `group', the other needs to be set too.
contents ? [] contents ? []
, # Type of partition table to use; either "legacy", "efi", or "none". , # Type of partition table to use; either "legacy", "efi", or "none".
@ -60,6 +64,11 @@
assert partitionTableType == "legacy" || partitionTableType == "legacy+gpt" || partitionTableType == "efi" || partitionTableType == "hybrid" || partitionTableType == "none"; assert partitionTableType == "legacy" || partitionTableType == "legacy+gpt" || partitionTableType == "efi" || partitionTableType == "hybrid" || partitionTableType == "none";
# We use -E offset=X below, which is only supported by e2fsprogs # We use -E offset=X below, which is only supported by e2fsprogs
assert partitionTableType != "none" -> fsType == "ext4"; assert partitionTableType != "none" -> fsType == "ext4";
# Either both or none of {user,group} need to be set
assert lib.all
(attrs: ((attrs.user or null) == null)
== ((attrs.group or null) == null))
contents;
with lib; with lib;
@ -148,6 +157,9 @@ let format' = format; in let
# !!! should use XML. # !!! should use XML.
sources = map (x: x.source) contents; sources = map (x: x.source) contents;
targets = map (x: x.target) contents; targets = map (x: x.target) contents;
modes = map (x: x.mode or "''") contents;
users = map (x: x.user or "''") contents;
groups = map (x: x.group or "''") contents;
closureInfo = pkgs.closureInfo { rootPaths = [ config.system.build.toplevel channelSources ]; }; closureInfo = pkgs.closureInfo { rootPaths = [ config.system.build.toplevel channelSources ]; };
@ -174,22 +186,33 @@ let format' = format; in let
set -f set -f
sources_=(${concatStringsSep " " sources}) sources_=(${concatStringsSep " " sources})
targets_=(${concatStringsSep " " targets}) targets_=(${concatStringsSep " " targets})
modes_=(${concatStringsSep " " modes})
set +f set +f
for ((i = 0; i < ''${#targets_[@]}; i++)); do for ((i = 0; i < ''${#targets_[@]}; i++)); do
source="''${sources_[$i]}" source="''${sources_[$i]}"
target="''${targets_[$i]}" target="''${targets_[$i]}"
mode="''${modes_[$i]}"
if [ -n "$mode" ]; then
rsync_chmod_flags="--chmod=$mode"
else
rsync_chmod_flags=""
fi
# Unfortunately cptofs only supports modes, not ownership, so we can't use
# rsync's --chown option. Instead, we change the ownerships in the
# VM script with chown.
rsync_flags="-a --no-o --no-g $rsync_chmod_flags"
if [[ "$source" =~ '*' ]]; then if [[ "$source" =~ '*' ]]; then
# If the source name contains '*', perform globbing. # If the source name contains '*', perform globbing.
mkdir -p $root/$target mkdir -p $root/$target
for fn in $source; do for fn in $source; do
rsync -a --no-o --no-g "$fn" $root/$target/ rsync $rsync_flags "$fn" $root/$target/
done done
else else
mkdir -p $root/$(dirname $target) mkdir -p $root/$(dirname $target)
if ! [ -e $root/$target ]; then if ! [ -e $root/$target ]; then
rsync -a --no-o --no-g $source $root/$target rsync $rsync_flags $source $root/$target
else else
echo "duplicate entry $target -> $source" echo "duplicate entry $target -> $source"
exit 1 exit 1
@ -284,6 +307,21 @@ in pkgs.vmTools.runInLinuxVM (
# The above scripts will generate a random machine-id and we don't want to bake a single ID into all our images # The above scripts will generate a random machine-id and we don't want to bake a single ID into all our images
rm -f $mountPoint/etc/machine-id rm -f $mountPoint/etc/machine-id
# Set the ownerships of the contents. The modes are set in preVM.
# No globbing on targets, so no need to set -f
targets_=(${concatStringsSep " " targets})
users_=(${concatStringsSep " " users})
groups_=(${concatStringsSep " " groups})
for ((i = 0; i < ''${#targets_[@]}; i++)); do
target="''${targets_[$i]}"
user="''${users_[$i]}"
group="''${groups_[$i]}"
if [ -n "$user$group" ]; then
# We have to nixos-enter since we need to use the user and group of the VM
nixos-enter --root $mountPoint -- chown -R "$user:$group" "$target"
fi
done
umount -R /mnt umount -R /mnt
# Make sure resize2fs works. Note that resize2fs has stricter criteria for resizing than a normal # Make sure resize2fs works. Note that resize2fs has stricter criteria for resizing than a normal