7 for (( index
=${#CLEANUP[@]}-1 ; index
>= 0 ; index--
)) ;do
16 REASON
="${2:-Unknown reason}"
22 trap cleanup EXIT TERM INT
38 DISTROBUILDER_GIT_BRANCH
44 for var
in "${REQUIRED_VARIABLES[@]}" ; do
45 if [ ! -v "$var" ] ; then
47 echo "Missing required variable: '${var}'" >&2
50 if [[ ! "${MISSING_VARS}" == "0" ]] ; then
51 fail
1 "Missing required variables"
55 INSTANCE_START_TIMEOUT
="${INSTANCE_START_TIMEOUT:-120}"
58 # Install incus-client
60 apt-get
install -y incus-client
61 mkdir
-p ~
/.config
/incus
62 cp "${INCUS_CLIENT_CERT}" ~
/.config
/incus
/client.crt
63 cp "${INCUS_CLIENT_KEY}" ~
/.config
/incus
/client.key
65 "rm -f ${HOME}/.config/incus/client.crt"
66 "rm -f ${HOME}/.config/incus/client.key"
68 incus remote add ci
--accept-certificate --auth-type tls
"${INCUS_HOST}"
69 incus remote switch ci
71 # Exit gracefully if the incus images: provides the base image
72 IMAGE_NAME
="${OS}/${RELEASE}/${VARIANT}/${ARCH}"
73 TYPE_FILTER
='type=container'
74 if [[ "${IMAGE_TYPE}" == "vm" ]] ; then
75 TYPE_FILTER
='type=virtual-machine'
77 if [[ "$(incus image list -f csv images:"${IMAGE_NAME}" -- "${TYPE_FILTER}" | wc -l)" != "0" ]] ; then
78 echo "Image '${IMAGE_NAME}' provided by 'images:' remote"
83 apt-get
install -y wget
84 wget
-q "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" -O - |
tar -C /usr
/local -xzf -
85 export PATH
="${PATH}:/usr/local/go/bin"
87 # Install distrobuilder
88 apt-get
install -y debootstrap rsync gpg squashfs-tools git \
89 btrfs-progs dosfstools qemu-utils gdisk
91 git clone
--branch="${DISTROBUILDER_GIT_BRANCH}" "${DISTROBUILDER_GIT_URL}" distrobuilder
94 PATH
="${PATH}:${HOME}/go/bin"
98 git clone
--branch="${GIT_BRANCH}" "${GIT_URL}" ci
100 # Get the INCUS CI repo
102 git clone
--branch="${INCUS_CI_GIT_BRANCH}" "${INCUS_CI_GIT_URL}" incus-ci
105 "${WORKSPACE}/ci/automation/images"
106 "${WORKSPACE}/incus-ci/images"
113 for IMAGE_DIR
in "${IMAGE_DIRS[@]}" ; do
114 for EXTENSION
in "${EXTENSIONS[@]}" ; do
115 if [ -f "${IMAGE_DIR}/${OS}-${RELEASE}.${EXTENSION}" ] ; then
116 IMAGE_FILE
="${IMAGE_DIR}/${OS}-${RELEASE}.${EXTENSION}"
120 for EXTENSION
in "${EXTENSIONS[@]}" ; do
121 if [ -f "${IMAGE_DIR}/${OS}.${EXTENSION}" ] ; then
122 IMAGE_FILE
="${IMAGE_DIR}/${OS}.${EXTENSION}"
128 if [[ "${IMAGE_FILE}" == "" ]] ; then
129 fail
1 "Unable to find image file for '${OS}' in ${IMAGE_DIRS[@]}"
132 if grep -q -E 'XX[A-Za-z0-9_]+XX' "${IMAGE_FILE}" ; then
133 while read -r VAR
; do
135 SHELLVAR
=$
(echo "${VAR}" |
sed 's/^XX//g' |
sed 's/XX$//g')
137 sed -i "s/${VAR}/${!SHELLVAR:-VARIABLENOTFOUND}/g" "${IMAGE_FILE}"
139 done < <(grep -E -o 'XX[A-Za-z0-9_]+XX' "${IMAGE_FILE}")
146 if [[ "${IMAGE_TYPE}" == "vm" ]] ; then
147 DISTROBUILDER_ARGS
+=('--vm')
151 # This could be quite large, and /tmp may be a tmpfs backed
152 # by memory, so instead make it relative to the workspace directory
153 BUILD_DIR
=$
(mktemp
-d -p "${WORKSPACE}")
155 "rm -rf ${BUILD_DIR}"
157 DISTROBUILDER_ARGS
+=(
161 "image.architecture=${ARCH}"
163 "image.variant=${VARIANT}"
165 "image.release=${RELEASE}"
167 "image.serial=$(date -u +%Y%m%dT%H:%M:%S%z)"
171 ${DISTROBUILDER_ARGS[@]}
174 # As 'distrobuilder --import-into-incus=alias' doesn't work since it only
175 # connects to the local unix socket, and the remote instance cannot be specified
177 ROOTFS
="${BUILD_DIR}/rootfs.squashfs"
178 if [[ "${IMAGE_TYPE}" == "vm" ]] ; then
179 ROOTFS
="${BUILD_DIR}/disk.qcow2"
182 # Work-around for incus not using qemu-system-i386: set the architecture to x86_64
183 # which will use qemu-system-x86_64 and still run 32bit userspace/kernels fine.
184 if [[ "${ARCH}" == "i386" ]] ; then
187 tar -xf "${BUILD_DIR}/incus.tar.xz"
188 sed -i 's/architecture: i386/architecture: x86_64/' metadata.yaml
189 tar -cf "${BUILD_DIR}/incus.tar.xz" .
/*
194 # When using `incus image import` two images cannot have the same alias -
195 # only the last image imported will keep the alias. Therefore, the
196 # image type is appended as part of the alias.
197 IMAGE_NAME
="${IMAGE_NAME}/${IMAGE_TYPE}"
199 if FINGERPRINT
=$
(incus image import
"${BUILD_DIR}/incus.tar.xz" "${ROOTFS}" 2>&1 | grep -E -o '[A-Fa-f0-9]{64}') ; then
200 echo "Image imported with fingerprint
'${FINGERPRINT}'"
202 fail 1 "No fingerprint
for imported image
"
205 if [[ "${TEST}" == "true
" ]] ; then
208 if INSTANCE_NAME="$
(incus
-q launch
-e ${VM_ARG[@]} -p default -p "${INCUS_INSTANCE_PROFILE}" "${FINGERPRINT}")" ; then
209 INSTANCE_NAME
="$(echo "${INSTANCE_NAME}" | cut -d':' -f2 | tr -d ' ')"
211 "incus stop -f ${INSTANCE_NAME}"
214 fail
1 "Failed to launch instance using image '${FINGERPRINT}'"
216 TIME_REMAINING
="${INSTANCE_START_TIMEOUT}"
219 INSTANCE_STATUS
="$(incus exec "${INSTANCE_NAME}" hostname)"
220 if [[ "${INSTANCE_STATUS}" == "${INSTANCE_NAME}" ]] ; then
224 TIME_REMAINING
=$
((TIME_REMAINING
- 1))
225 if [ "${TIME_REMAINING}" -lt "0" ] ; then
226 fail
1 "Timed out waiting for instance to become available via 'incus exec'"
232 incus image
alias delete
"${IMAGE_NAME}" || true
233 incus image
alias create
"${IMAGE_NAME}" "${FINGERPRINT}"