You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

296 lines
10 KiB

#! /usr/bin/env bash
#
# Copyright 2021 Northern.tech AS
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Default that can be overridden by providing this method in a
# configuration file passed with '--config'
function platform_modify() {
true
}
PLATFORM_MODIFY_HOOKS=(platform_modify)
function user_local_modify() {
true
}
USER_LOCAL_MODIFY_HOOKS=(user_local_modify)
function overlay_modify() {
true
}
OVERLAY_MODIFY_HOOKS=(overlay_modify)
function trap_exit() {
echo "mender-convert-modify has finished. Cleaning up..."
sudo umount -f work/boot
sudo umount -f work/rootfs
}
function trap_term() {
true
}
trap trap_term INT TERM
trap trap_exit EXIT
echo "Running $(basename $0): $@"
source modules/bootstrap.sh
source modules/disk.sh
source modules/probe.sh
source modules/deb.sh
source modules/testscfg.sh
source modules/grub.sh
# The mender_convert_config is always used and provides all the defaults
declare -a configs=("configs/mender_convert_config")
while (("$#")); do
case "$1" in
-o | --overlay)
overlays+=("${2}")
shift 2
;;
-c | --config)
configs+=("${2}")
shift 2
;;
-d | --disk-image)
disk_image="${2}"
shift 2
;;
*)
log_fatal "Sorry, but the provided option is not supported: $1"
;;
esac
done
# Note the use of %q formatting here. This is a bash feature to add
# proper quoting to the strings so that spaces and special characters
# will be treated properly. Primarily for supporting spaces in
# pathnames and avoid splitting those into multiple parameters.
source modules/config.sh $(printf "%q " "${configs[@]}")
boot_part=$(disk_boot_part)
root_part=$(disk_root_part)
# Sysfs device paths
boot_part_device=$(disk_boot_part_device)
data_part_device=$(disk_data_part_device)
root_part_a_device=$(disk_root_part_a_device)
root_part_b_device=$(disk_root_part_b_device)
# Create mount points
mkdir -p work/boot
mkdir -p work/rootfs
sudo mount ${boot_part} work/boot
sudo mount ${root_part} work/rootfs
log_info "Installing Mender client and related files"
if [ "${MENDER_CLIENT_INSTALL}" = "y" ]; then
log_info "Installing Mender client version ${MENDER_CLIENT_VERSION}"
deb_get_and_install_pacakge mender-client "${MENDER_CLIENT_VERSION}"
# Save installed client version for tests in Yocto variable format
testscfg_add "PREFERRED_VERSION_mender-client" "$(echo ${DEB_NAME} | sed -r 's/.*_([0-9]+\.[0-9]+\.[0-9]+).*/\1/')"
fi
if [ "${MENDER_ENABLE_SYSTEMD}" == "y" ]; then
run_and_log_cmd "sudo ln -sf /lib/systemd/system/mender-client.service \
work/rootfs/etc/systemd/system/multi-user.target.wants/mender-client.service"
fi
if [ "${MENDER_ADDON_CONNECT_INSTALL}" = "y" ]; then
log_info "Installing Mender Connect addon"
deb_get_and_install_pacakge mender-connect "${MENDER_ADDON_CONNECT_VERSION}"
run_and_log_cmd "sudo ln -sf /lib/systemd/system/mender-connect.service \
work/rootfs/etc/systemd/system/multi-user.target.wants/mender-connect.service"
fi
if [ "${MENDER_ADDON_CONFIGURE_INSTALL}" = "y" ]; then
log_info "Installing Mender Configure addon"
deb_get_and_install_pacakge mender-configure "${MENDER_ADDON_CONFIGURE_VERSION}" "true"
fi
# Do this unconditionally even if not installing add-ons. The reason is that if
# the Debian package is installed later, this folder has to preexist. It is part
# of the rootfs setup, independently of the software.
log_info "Creating state folder in the data partition for Mender add-ons"
run_and_log_cmd "sudo mkdir -p work/rootfs/var/lib"
run_and_log_cmd "sudo mkdir -p work/rootfs/data/mender-configure"
run_and_log_cmd "sudo ln -sf /data/mender-configure work/rootfs/var/lib"
run_and_log_cmd "sudo mkdir -p work/rootfs/data/mender-monitor"
run_and_log_cmd "sudo ln -sf /data/mender-monitor work/rootfs/var/lib"
if [ "${MENDER_GRUB_EFI_INTEGRATION}" == "y" ]; then
# Check for known U-Boot problems in all files on the boot partition.
check_for_broken_uboot_uefi_support work/boot
if [ "$MENDER_GRUB_D_INTEGRATION" = y ] || ( [ "$MENDER_GRUB_D_INTEGRATION" = auto ] \
&& supports_grub_d_and_efi "work/boot" "work/rootfs" ); then
# No need to install Grub, use the one already present, and only install
# our tools.
log_info "Not installing GRUB EFI bootloader, relying on platform provided one."
log_info "Installing Mender GRUB tools..."
grub_install_grub_editenv_binary
log_info "Generating grub config using update-grub..."
grub_create_grub_config
grub_install_grub_d_config
else
log_info "Installing GRUB EFI bootloader..."
grub_install_mender_grub
log_info "Generating the mender-grub config..."
grub_create_grub_config
grub_install_standalone_grub_config
fi
fi
MENDER_CLIENT_DATA_DIR_SERVICE_URL="https://raw.githubusercontent.com/mendersoftware/\
meta-mender/e05cde10fde3646a78081709e717fb42a6c5ba44/meta-mender-core/recipes-mender/mender-client/files/mender-client-data-dir.service"
run_and_log_cmd "wget --quiet -O work/mender-client-data-dir.service $MENDER_CLIENT_DATA_DIR_SERVICE_URL"
run_and_log_cmd "sudo install -m 644 work/mender-client-data-dir.service work/rootfs/lib/systemd/system/mender-client-data-dir.service"
run_and_log_cmd "sudo mkdir -p work/rootfs/lib/systemd/system/mender-client.service.wants"
run_and_log_cmd "sudo ln -sf /lib/systemd/system/mender-client-data-dir.service \
work/rootfs/lib/systemd/system/mender-client.service.wants/mender-client-data-dir.service"
run_and_log_cmd "sudo mkdir -p work/rootfs/data/mender"
run_and_log_cmd "sudo mkdir -p work/rootfs/var/lib"
run_and_log_cmd "sudo ln -sf /data/mender work/rootfs/var/lib"
log_info "Using root device A in mender.conf: $root_part_a_device"
log_info "Using root device B in mender.conf: $root_part_b_device"
cat <<- EOF > work/mender.conf.data
{
"RootfsPartA": "${root_part_a_device}",
"RootfsPartB": "${root_part_b_device}"
}
EOF
run_and_log_cmd "sudo cp work/mender.conf.data work/rootfs/data/mender/mender.conf"
run_and_log_cmd "sudo chmod 600 work/rootfs/data/mender/mender.conf"
if [ -f input/resources/mender.conf ]; then
log_info "Installing the local mender.conf file"
run_and_log_cmd "mkdir -p work/rootfs/etc/mender"
run_and_log_cmd "cp input/resources/mender.conf work/rootfs/etc/mender"
run_and_log_cmd "sudo chmod 600 work/rootfs/etc/mender/mender.conf"
else
log_warn "No mender.conf file found in input/resources. Have you remembered to run the bootstrap script?"
fi
if [ -z "${MENDER_DEVICE_TYPE}" ]; then
# Observed systems who do not have this file, e.g images generated with mkosi
if [ -f work/rootfs/etc/hostname ]; then
device_type=$(cat work/rootfs/etc/hostname)
else
device_type="default"
fi
else
device_type="${MENDER_DEVICE_TYPE}"
fi
run_and_log_cmd "echo 'device_type=${device_type}' > work/device_type"
run_and_log_cmd "sudo install -m 0444 work/device_type work/rootfs/data/mender/"
log_info "Creating state scripts version file."
case "${MENDER_CLIENT_VERSION}" in
1*) VERSION_STRING='2' ;;
*) VERSION_STRING='3' ;;
esac
run_and_log_cmd "sudo mkdir -p work/rootfs/etc/mender/scripts/"
run_and_log_cmd "echo -n ${VERSION_STRING} | sudo tee work/rootfs/etc/mender/scripts/version"
log_info "Installing a custom /etc/fstab (see ${MENDER_CONVERT_LOG_FILE} for more info)"
if [ "${MENDER_GRUB_EFI_INTEGRATION}" == "y" ]; then
boot_part_mountpoint="/boot/efi"
else
boot_part_mountpoint="/uboot"
fi
run_and_log_cmd "sudo mkdir -p work/rootfs/${boot_part_mountpoint}"
if [ "${MENDER_DATA_PART_GROWFS}" == "y" ]; then
MENDER_DATA_PART_FSTAB_OPTS="${MENDER_DATA_PART_FSTAB_OPTS},x-systemd.growfs"
fi
if echo ${MENDER_ROOT_PART_FSTAB_OPTS} | tr ',' '\n' | egrep -q "^ro$"; then
if ! echo "${MENDER_ROOT_PART_MKFS_OPTS}" | fgrep -q -- "^64bit"; then
log_warn "EXT4 64bits feature is known to create unstable checksums on read-only file systems, add \"-O ^64bit\" to MENDER_ROOT_PART_MKFS_OPTS to remove it"
fi
if ! echo "${MENDER_ROOT_PART_MKFS_OPTS}" | fgrep -q -- "^has_journal"; then
log_warn "EXT4 journal feature is known to create unstable checksums on read-only file systems, add \"-O ^has_journal\" to MENDER_ROOT_PART_MKFS_OPTS to remove it"
fi
fi
log_info "Using boot partition device in fstab: $boot_part_device"
log_info "Using data partition device in fstab: $data_part_device"
fstab=$(sed '/\/boot/d' work/rootfs/etc/fstab)
fstab=$(sed '/.*\s\/\s.*/d' <<< "$fstab")
cat <<- EOF > work/rootfs/etc/fstab
${boot_part_device} ${boot_part_mountpoint} auto ${MENDER_BOOT_PART_FSTAB_OPTS} 0 0
/dev/root / auto ${MENDER_ROOT_PART_FSTAB_OPTS} 1 ${MENDER_ROOT_PART_FS_PASSNO}
${data_part_device} /data auto ${MENDER_DATA_PART_FSTAB_OPTS} 0 0
# entries kept from original fstab
$fstab
EOF
#
# Make sure to re-label rootfs when selinux is in enforcing mode
# e.g. CentOS8 after conversion cannot start login shell due selinux
# inspired by: https://forums.centos.org/viewtopic.php?t=48714
#
if [ -f work/rootfs/etc/selinux/config ]; then
grep -r 'SELINUX=Enforcing' work/rootfs/etc/selinux/config || true
if [ $? -eq 0 ]; then
log_info "Selinux is in enforcing mode. Enable autorelabel"
touch work/rootfs/.autorelabel
fi
fi
log_info "Performing platform specific modifications (if any)"
for hook in "${PLATFORM_MODIFY_HOOKS[@]}"; do
log_info "Running hook: $hook"
eval $hook
done
log_info "Performing user/local specific modifications (if any)"
for hook in "${USER_LOCAL_MODIFY_HOOKS[@]}"; do
log_info "Running hook: $hook"
eval $hook
done
for overlay in "${overlays[@]}"; do
log_info "Applying rootfs overlay: ${overlay}"
run_and_log_cmd "sudo rsync --archive --keep-dirlinks --verbose ${overlay}/ work/rootfs/"
done
log_info "Performing overlay specific modifications (if any)"
for hook in "${OVERLAY_MODIFY_HOOKS[@]}"; do
log_info "Running hook: $hook"
eval $hook
done