Skip to content

Commit

Permalink
Install cloud-init configuration in the Raspi img
Browse files Browse the repository at this point in the history
  • Loading branch information
ferrarimarco committed Mar 5, 2021
1 parent 5dc3b7c commit d4ca2af
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 28 deletions.
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ spaces_around_brackets = false
[*.{dockerfilelintrc,hcl.tpl,sh,tf,tfvars,yml,yaml}]
indent_size = 2

[{Makefile,**.mk,go.mod,go.sum,*.go,.gitmodules}]
indent_size = 4
indent_style = tab

# Don't try to format binary files
[*.tfvars.enc]
charset = unset
Expand Down
4 changes: 4 additions & 0 deletions .yaml-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ rules:
max-spaces-after: 1
comments:
level: error
ignore: |
**/cloud-init/user-data.yaml
comments-indentation:
level: error
document-start:
level: error
ignore: |
**/cloud-init/user-data.yaml
empty-values: enable
line-length:
max: 250
Expand Down
2 changes: 1 addition & 1 deletion cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ steps:
- PYTHON_ISORT_CONFIG_FILE=pyproject.toml
- RUN_LOCAL=true
- VALIDATE_ALL_CODEBASE=true
- VALIIDATE_JSCPD=false
- VALIDATE_TERRAFORM_TERRASCAN=false
- id: 'clone repository'
name: gcr.io/cloud-builders/git
Expand Down Expand Up @@ -84,7 +85,6 @@ steps:
&
scripts/submit-cloud-build.sh \
--cloud-build-substitutions "COMMIT_SHA=$COMMIT_SHA" \
--commit-sha "$COMMIT_SHA" \
--destination-directory-path "provisioning/os-images/raspberry-pi/raspberry-pi-4/ubuntu" \
--failure-file-path "${_FAILURE_FILE_PATH}" \
Expand Down
2 changes: 2 additions & 0 deletions provisioning/docker/arm-image-builder/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ ENV CROSS_COMPILE_ARCHS "arm64 armhf"

# Allow us to install packages for cross-compiling architectures
SHELL ["/bin/bash", "-o", "pipefail", "-c"]

# hadolint ignore=SC2094,SC2206
RUN ARCHS=(${CROSS_COMPILE_ARCHS}) && \
ARCHS_LIST=$(IFS=,; echo "${ARCHS[*]}") && \
Expand All @@ -24,6 +25,7 @@ RUN apt-get update \
bmap-tools \
build-essential \
ca-certificates \
cloud-init \
debootstrap \
dirmngr \
dosfstools \
Expand Down
6 changes: 3 additions & 3 deletions provisioning/docker/arm-image-builder/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ while true; do
echo "Decoding parameter ${1}..."
case "${1}" in
-e | --entrypoint)
echo "Found entrypoint parameter"
echo "Found entrypoint parameter."
entrypoint="${2}"
shift 2
;;
-o | --options)
echo "Found options parameter"
echo "Found options parameter."
options="${2}"
shift 2
;;
--)
echo "No more parameters to decode"
echo "No more parameters to decode."
shift
break
;;
Expand Down
1 change: 0 additions & 1 deletion provisioning/docker/iot-core-initializer/cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,5 @@ options:
- 'DOCKER_CLI_EXPERIMENTAL=enabled'
substitutions:
_ARM_BUILDER_IMAGE_TAG: '4a17db0'
_CLOUD_SDK_IMAGE_TAG: 'alpine'
_DOCKER_BUILDX_BUILDER_NAME: 'multiarch_builder'
_DOCKER_BUILDX_PLATFORMS: 'linux/amd64,linux/arm/v7,linux/arm64'
24 changes: 24 additions & 0 deletions provisioning/os-images/raspberry-pi/raspberry-pi-4/ubuntu/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.PHONY: all
all: build-os-image-raspberry-pi-4-ubuntu ## Build OS images.

# if this session isn't interactive, then we don't want to allocate a
# TTY, which would fail, but if it is interactive, we do want to attach
# so that the user can send e.g. ^C through.
INTERACTIVE := $(shell [ -t 0 ] && echo 1 || echo 0)
ifeq ($(INTERACTIVE), 1)
DOCKER_FLAGS += -t
endif

.PHONY: build-os-image-raspberry-pi-4-ubuntu
build-os-image-raspberry-pi-4-ubuntu: ## Build the Ubuntu OS image for the Raspberry Pi 4.
docker run --rm -i $(DOCKER_FLAGS) \
--privileged \
-v "$(CURDIR)":/workspace \
-w="/workspace" \
arm-image-builder \
--entrypoint /workspace/build.sh \
--options "--build-config /workspace/config/build.conf --cloud-init-user-data /workspace/config/cloud-init/user-data.yaml"

.PHONY: help
help: ## Show help
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
144 changes: 122 additions & 22 deletions provisioning/os-images/raspberry-pi/raspberry-pi-4/ubuntu/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,67 @@ set -o errexit

echo "This script has been invoked with: $0 $*"

OS_VERSION="20.04.1"
IMAGE_ARCHIVE_FILE_NAME="ubuntu-${OS_VERSION}-preinstalled-server-arm64+raspi.img.xz"
IMAGE_URL="https://cdimage.ubuntu.com/releases/${OS_VERSION}/release/${IMAGE_ARCHIVE_FILE_NAME}"
IMAGE_CHECKSUM_FILE_NAME="SHA256SUMS"
IMAGE_CHECKSUM_URL="https://cdimage.ubuntu.com/releases/${OS_VERSION}/release/${IMAGE_CHECKSUM_FILE_NAME}"
print_or_warn() {
FILE_PATH="${1}"
if [ -e "$FILE_PATH" ]; then
echo "Contents of ${FILE_PATH}:"
ls -alhR "${FILE_PATH}"
if [ -f "$FILE_PATH" ]; then
cat "${FILE_PATH}"
fi
else
echo "WARNING: ${FILE_PATH} doesn't exist"
fi
}

if ! TEMP="$(getopt -o b:u: --long build-config:,cloud-init-user-data: \
-n 'build' -- "$@")"; then
echo "Terminating..." >&2
exit 1
fi
eval set -- "$TEMP"

BUILD_ENVIRONMENT_CONFIGURATION_FILE_PATH=
CLOUD_INIT_USER_DATA_FIILE_PATH=

while true; do
echo "Decoding parameter ${1}..."
case "${1}" in
-b | --build-config)
BUILD_ENVIRONMENT_CONFIGURATION_FILE_PATH="${2}"
shift 2
;;
-u | --cloud-init-user-data)
CLOUD_INIT_USER_DATA_FIILE_PATH="${2}"
shift 2
;;
--)
echo "No more parameters to decode"
shift
break
;;
*) break ;;
esac
done

WORKSPACE_DIRECTORY="$(pwd)"
echo "Working directory: ${WORKSPACE_DIRECTORY}"

echo "Loading the build environment configuration from ${BUILD_ENVIRONMENT_CONFIGURATION_FILE_PATH}..."
# shellcheck source=/dev/null
. "${BUILD_ENVIRONMENT_CONFIGURATION_FILE_PATH}"

echo "Current environment configuration:"
env | sort

echo "Validating cloud-init configuration file..."
cloud-init devel schema --config-file "${CLOUD_INIT_USER_DATA_FIILE_PATH}"

IMAGE_ARCHIVE_FILE_PATH="${WORKSPACE_DIRECTORY}"/"${IMAGE_ARCHIVE_FILE_NAME}"

echo "Downloading the OS image from ${IMAGE_URL}..."
[ ! -f "${IMAGE_ARCHIVE_FILE_PATH}" ] && wget "${IMAGE_URL}"
[ ! -f "${IMAGE_CHECKSUM_FILE_NAME}" ] && wget -O "${IMAGE_CHECKSUM_FILE_NAME}" "${IMAGE_CHECKSUM_URL}"
[ ! -f "${IMAGE_ARCHIVE_FILE_PATH}" ] && wget -q "${IMAGE_URL}"
[ ! -f "${IMAGE_CHECKSUM_FILE_NAME}" ] && wget -q -O "${IMAGE_CHECKSUM_FILE_NAME}" "${IMAGE_CHECKSUM_URL}"

echo "Verifying the integrity of ${IMAGE_ARCHIVE_FILE_PATH}..."
sha256sum --ignore-missing -c "${IMAGE_CHECKSUM_FILE_NAME}"
Expand All @@ -33,7 +80,10 @@ echo "Getting information about the ${IMAGE_ARCHIVE_FILE_PATH} archive: $(

if [ ! -f "${IMAGE_FILE_PATH}" ]; then
echo "Extracting contents of ${IMAGE_ARCHIVE_FILE_PATH}..."
unxz "${IMAGE_ARCHIVE_FILE_PATH}"
xz -d -T0 -v "${IMAGE_ARCHIVE_FILE_PATH}"

echo "Deleting ${IMAGE_ARCHIVE_FILE_PATH} if necessary..."
[ -f "${IMAGE_ARCHIVE_FILE_PATH}" ] && rm -f "${IMAGE_ARCHIVE_FILE_PATH}"
else
echo "${IMAGE_FILE_PATH} already exists, skipping extraction..."
fi
Expand All @@ -44,29 +94,43 @@ fdisk -l "${IMAGE_FILE_PATH}"
echo "Currently used loop devices:"
losetup --all

LOOP_DEVICE_PATH="$(losetup -f)"
echo "First available loop device: ${LOOP_DEVICE_PATH}"
echo "Checking if there are stale mounts to clean (mounting ${IMAGE_FILE_PATH})..."
if losetup -O NAME,BACK-FILE | grep "${IMAGE_FILE_PATH}"; then
echo "Cleaning stale mounts..."
losetup -O NAME,BACK-FILE | grep "${IMAGE_FILE_PATH}" | awk '{ print $1 }' | xargs -l1 losetup -d
else
echo "There are no stale mounts to clean."
fi

echo "Mounting loop devices from ${IMAGE_FILE_PATH}..."
kpartx -asv "${IMAGE_FILE_PATH}"

mkdir -p /mnt/raspi-1
mkdir -p /mnt/raspi-2
echo "Currently used loop devices (after mounting the image):"
losetup --all

BOOT_DIRECTORY_PATH="/mnt/raspi-1"
ROOTFS_DIRECTORY_PATH="/mnt/raspi-2"

echo "Creating directories to mount loop devices (${BOOT_DIRECTORY_PATH}, ${ROOTFS_DIRECTORY_PATH})..."
mkdir -p "${BOOT_DIRECTORY_PATH}"
mkdir -p "${ROOTFS_DIRECTORY_PATH}"

LOOP_DEVICE_PATH="$(losetup -O NAME,BACK-FILE | grep "${IMAGE_FILE_PATH}" | awk '{ print $1 }')"
LOOP_DEVICE_NAME="$(basename "${LOOP_DEVICE_PATH}")"
LOOP_DEVICE_PARTITION_PREFIX=/dev/mapper/"${LOOP_DEVICE_NAME}"
ROOTFS_DIRECTORY_PATH="/mnt/raspi-2"

echo "Gathering information about the partitions to mount..."
blkid "${LOOP_DEVICE_PATH}" "${LOOP_DEVICE_PARTITION_PREFIX}"p*

echo "Mounting partitions from ${LOOP_DEVICE_PATH} (prefix: ${LOOP_DEVICE_PARTITION_PREFIX})"
mount -v "${LOOP_DEVICE_PARTITION_PREFIX}"p1 /mnt/raspi-1
mount -v "${LOOP_DEVICE_PARTITION_PREFIX}"p1 "${BOOT_DIRECTORY_PATH}"
mount -v "${LOOP_DEVICE_PARTITION_PREFIX}"p2 "${ROOTFS_DIRECTORY_PATH}"

echo "Current disk space usage:"
df -h

for d in /mnt/raspi-*/; do
echo "$d contents:"
ls -ahl "$d"
done
print_or_warn "${BOOT_DIRECTORY_PATH}"
print_or_warn "${ROOTFS_DIRECTORY_PATH}/var/lib/cloud"

echo "Mounting /sys..."
if [ "$(mount | grep "${ROOTFS_DIRECTORY_PATH}"/sys | awk '{print $3}')" != "${ROOTFS_DIRECTORY_PATH}/sys" ]; then
Expand All @@ -88,7 +152,7 @@ if [ "$(mount | grep "${ROOTFS_DIRECTORY_PATH}"/dev/pts | awk '{print $3}')" !=
mount -t devpts devpts "${ROOTFS_DIRECTORY_PATH}/dev/pts"
fi

echo "Customizing ${ROOTFS_DIRECTORY_PATH} via chroot..."
echo "Customizing ${ROOTFS_DIRECTORY_PATH}..."

CHROOT_RESOLV_CONF_PATH="${ROOTFS_DIRECTORY_PATH}"/run/systemd/resolve/stub-resolv.conf
CHROOT_RESOLV_CONF_DIRECTORY_PATH="$(dirname "${CHROOT_RESOLV_CONF_PATH}")"
Expand All @@ -99,15 +163,44 @@ if [ ! -f "${CHROOT_RESOLV_CONF_PATH}" ]; then
CUSTOMIZED_RESOLV_CONF="true"
fi

echo "Contents of ${CHROOT_RESOLV_CONF_PATH}:"
cat "${CHROOT_RESOLV_CONF_PATH}"
print_or_warn "${CHROOT_RESOLV_CONF_PATH}"

echo "Pinging an external domain..."
chroot "${ROOTFS_DIRECTORY_PATH}" ping -c 3 google.com

print_or_warn "${BOOT_DIRECTORY_PATH}/cmdline.txt"

print_or_warn "${BOOT_DIRECTORY_PATH}/config.txt"
print_or_warn "${BOOT_DIRECTORY_PATH}/syscfg.txt"
print_or_warn "${BOOT_DIRECTORY_PATH}/usercfg.txt"

CLOUD_INIT_CONFIGURATION_PATH="${ROOTFS_DIRECTORY_PATH}/etc/cloud"
print_or_warn "${CLOUD_INIT_CONFIGURATION_PATH}"
print_or_warn "${CLOUD_INIT_CONFIGURATION_PATH}/cloud.cfg"

echo "Getting contents of the cloud-init configuration files..."
find "${CLOUD_INIT_CONFIGURATION_PATH}/cloud.cfg.d" -type f -print -exec echo \; -exec cat {} \; -exec echo \;

CHROOT_CLOUD_INIT_USER_DATA_FILE_PATH="${BOOT_DIRECTORY_PATH}/user-data"
print_or_warn "${CHROOT_CLOUD_INIT_USER_DATA_FILE_PATH}"

print_or_warn "${BOOT_DIRECTORY_PATH}/meta-data"
print_or_warn "${BOOT_DIRECTORY_PATH}/network-config"

echo "Copying the user-data configuration file (${CLOUD_INIT_USER_DATA_FIILE_PATH}) to ${CHROOT_CLOUD_INIT_USER_DATA_FILE_PATH}..."
cp -f "${CLOUD_INIT_USER_DATA_FIILE_PATH}" "${CHROOT_CLOUD_INIT_USER_DATA_FILE_PATH}"

print_or_warn "${CHROOT_CLOUD_INIT_USER_DATA_FILE_PATH}"

print_or_warn "${ROOTFS_DIRECTORY_PATH}/etc/fstab"

echo "Updating the APT index and upgrading the system..."
chroot "${ROOTFS_DIRECTORY_PATH}" apt-get update
chroot "${ROOTFS_DIRECTORY_PATH}" apt-get -y upgrade

echo "Installed APT packages:"
chroot "${ROOTFS_DIRECTORY_PATH}" dpkg -l | sort

if [ "${CUSTOMIZED_RESOLV_CONF}" = "true" ]; then
rm -rf "${CHROOT_RESOLV_CONF_DIRECTORY_PATH}"
fi
Expand All @@ -125,11 +218,18 @@ echo "Unmounting /sys..."
umount -fl "${ROOTFS_DIRECTORY_PATH}/sys"

echo "Unmounting Raspberry Pi file system..."
umount -v /mnt/raspi-1
umount -v "${BOOT_DIRECTORY_PATH}"
umount -v "${ROOTFS_DIRECTORY_PATH}"

echo "Unmounting loop devices..."
kpartx -vd "${IMAGE_FILE_PATH}"

echo "Ensuring that the loop device is not present anymore..."
rm -f "${LOOP_DEVICE_PATH}"

IMAGE_ARCHIVE_FILE_PATH="${IMAGE_FILE_PATH}".xz
echo "Removing image archive path leftovers..."
rm -f "${IMAGE_ARCHIVE_FILE_PATH}"

echo "Compressing ${IMAGE_FILE_PATH} to ${IMAGE_ARCHIVE_FILE_PATH}..."
xz -9 -T6 -v -z "${IMAGE_FILE_PATH}"
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
---
artifacts:
objects:
location: 'gs://${PROJECT_ID}-os-images'
paths:
- './*.xz'
options:
machineType: 'N1_HIGHCPU_8'
steps:
- id: 'Build the customized OS image'
name: 'gcr.io/$PROJECT_ID/arm-image-builder:$_ARM_BUILDER_IMAGE_TAG'
args:
- "--entrypoint"
- "$$(pwd)/build.sh"
- "--options"
- "--build-config $$(pwd)/config/build.conf --cloud-init-user-data $$(pwd)/config/cloud-init/user-data.yaml"
substitutions:
_ARM_BUILDER_IMAGE_TAG: 'b7673dc'
_ARM_BUILDER_IMAGE_TAG: 'ec9be07'
timeout: 37000s
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
OS_VERSION="20.04.2"
IMAGE_ARCHIVE_FILE_NAME="ubuntu-${OS_VERSION}-preinstalled-server-arm64+raspi.img.xz"
IMAGE_URL="https://cdimage.ubuntu.com/releases/${OS_VERSION}/release/${IMAGE_ARCHIVE_FILE_NAME}"
IMAGE_CHECKSUM_FILE_NAME="SHA256SUMS"
IMAGE_CHECKSUM_URL="https://cdimage.ubuntu.com/releases/${OS_VERSION}/release/${IMAGE_CHECKSUM_FILE_NAME}"
Loading

0 comments on commit d4ca2af

Please sign in to comment.