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}"
60 apt-get
install -y lxd-client
61 mkdir
-p ~
/.config
/lxc
62 cp "${LXD_CLIENT_CERT}" ~
/.config
/lxc
/client.crt
63 cp "${LXD_CLIENT_KEY}" ~
/.config
/lxc
/client.key
65 "rm -f ${HOME}/.config/lxc/client.crt"
66 "rm -f ${HOME}/.config/lxc/client.key"
68 lxc remote add ci
--accept-certificate --auth-type tls
"${LXD_HOST}"
71 # Exit gracefully if the lxc 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 [[ "$(lxc 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 LXC CI repo
102 git clone
--branch="${LXC_CI_GIT_BRANCH}" "${LXC_CI_GIT_URL}" lxc-ci
105 "${WORKSPACE}/ci/automation/images"
106 "${WORKSPACE}/lxc-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 lxd 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 `lxc 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
=$
(lxc 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="$
(lxc
-q launch
-e ${VM_ARG[@]} -p default -p "${LXD_INSTANCE_PROFILE}" "${FINGERPRINT}")" ; then
209 INSTANCE_NAME
="$(echo "${INSTANCE_NAME}" | cut -d':' -f2 | tr -d ' ')"
211 "lxc stop -f ${INSTANCE_NAME}"
214 fail
1 "Failed to launch instance using image '${FINGERPRINT}'"
216 TIME_REMAINING
="${INSTANCE_START_TIMEOUT}"
219 INSTANCE_STATUS
="$(lxc 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 'lxc exec'"
232 lxc image
alias delete
"${IMAGE_NAME}" || true
233 lxc image
alias create
"${IMAGE_NAME}" "${FINGERPRINT}"