Image building tools for OpenStack
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.

637 lines
24KB

  1. #!/bin/bash
  2. #
  3. # Copyright 2012 Hewlett-Packard Development Company, L.P.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  6. # not use this file except in compliance with the License. You may obtain
  7. # a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14. # License for the specific language governing permissions and limitations
  15. # under the License.
  16. set -eE
  17. # Set/override locale. This ensures consistency in sorting etc. We
  18. # need to choose a lowest-common denominator locale, as this is
  19. # applied when running in the building chroot too (maybe a bug and we
  20. # should prune this?). Thus "C" --centOS 7 doesn't include C.utf-8
  21. # (fedora does, centos 8 probably will). Note: LC_ALL to really
  22. # override this; it overrides LANG and all other LC_ vars
  23. export LC_ALL=C
  24. # Store our initial environment and command line args for later
  25. export DIB_ARGS="$@"
  26. export DIB_ENV=$(export | grep ' DIB_.*=')
  27. SCRIPTNAME=$(basename $0)
  28. if [ -z "$_LIB" ]; then
  29. echo "_LIB not set!"
  30. exit 1
  31. fi
  32. _BASE_ELEMENT_DIR=$(${DIB_PYTHON_EXEC:-python} -c '
  33. import diskimage_builder.paths
  34. diskimage_builder.paths.show_path("elements")')
  35. source $_LIB/die
  36. IS_RAMDISK=0
  37. if [ "$SCRIPTNAME" == "ramdisk-image-create" ]; then
  38. IS_RAMDISK=1
  39. fi
  40. function show_options () {
  41. echo "Usage: ${SCRIPTNAME} [OPTION]... [ELEMENT]..."
  42. echo
  43. echo "Options:"
  44. echo " -a i386|amd64|armhf|arm64 -- set the architecture of the image(default amd64)"
  45. echo " -o imagename -- set the imagename of the output image file(default image)"
  46. echo " -t qcow2,tar,tgz,squashfs,vhd,docker,aci,raw -- set the image types of the output image files (default qcow2)"
  47. echo " File types should be comma separated. VHD outputting requires the vhd-util"
  48. echo " executable be in your PATH. ACI outputting requires the ACI_MANIFEST "
  49. echo " environment variable be a path to a manifest file."
  50. echo " -x -- turn on tracing (use -x -x for very detailed tracing)."
  51. echo " -u -- uncompressed; do not compress the image - larger but faster"
  52. echo " -c -- clear environment before starting work"
  53. echo " --logfile -- save run output to given logfile (implies DIB_QUIET=1)"
  54. echo " --checksum -- generate MD5 and SHA256 checksum files for the created image"
  55. echo " --image-size size -- image size in GB for the created image"
  56. echo " --image-extra-size size -- extra image size in GB for the created image"
  57. echo " --image-cache directory -- location for cached images(default ~/.cache/image-create)"
  58. echo " --max-online-resize size -- max number of filesystem blocks to support when resizing."
  59. echo " Useful if you want a really large root partition when the image is deployed."
  60. echo " Using a very large value may run into a known bug in resize2fs."
  61. echo " Setting the value to 274877906944 will get you a 1PB root file system."
  62. echo " Making this value unnecessarily large will consume extra disk space "
  63. echo " on the root partition with extra file system inodes."
  64. echo " --min-tmpfs size -- minimum size in GB needed in tmpfs to build the image"
  65. echo " --mkfs-journal-size -- filesystem journal size in MB to pass to mkfs."
  66. echo " --mkfs-options -- option flags to be passed directly to mkfs."
  67. echo " Options should be passed as a single string value."
  68. echo " --no-tmpfs -- do not use tmpfs to speed image build"
  69. echo " --offline -- do not update cached resources"
  70. echo " --qemu-img-options -- option flags to be passed directly to qemu-img."
  71. echo " Options need to be comma separated, and follow the key=value pattern."
  72. echo " --root-label label -- label for the root filesystem. Defaults to 'cloudimg-rootfs'."
  73. echo " --ramdisk-element -- specify the main element to be used for building ramdisks."
  74. echo " Defaults to 'ramdisk'. Should be set to 'dracut-ramdisk' for platforms such"
  75. echo " as RHEL and CentOS that do not package busybox."
  76. echo " --install-type -- specify the default installation type. Defaults to 'source'. Set to 'package' to use package based installations by default."
  77. echo " --docker-target -- specify the repo and tag to use if the output type is docker. Defaults to the value of output imagename"
  78. if [ "$IS_RAMDISK" == "0" ]; then
  79. echo " -n skip the default inclusion of the 'base' element"
  80. echo " -p package[,p2...] [-p p3] -- extra packages to install in the image. Runs once, after 'install.d' phase. Can be specified multiple times"
  81. fi
  82. echo " -h|--help -- display this help and exit"
  83. echo " --version -- display version and exit"
  84. echo
  85. echo "Environment Variables:"
  86. echo " (this is not a complete list)"
  87. echo
  88. echo " * ELEMENTS_PATH: specify external locations for the elements. As for \$PATH"
  89. echo " * DIB_NO_TIMESTAMP: no timestamp prefix on output. Useful if capturing output"
  90. echo " * DIB_QUIET: 1=do not output log output to stdout; 0=always ouptut to stdout. See --logfile"
  91. echo
  92. echo "NOTE: At least one distribution root element must be specified."
  93. echo
  94. echo "NOTE: If using the VHD output format you need to have a patched version of vhd-util installed for the image"
  95. echo " to be bootable. The patch is available here: https://github.com/emonty/vhd-util/blob/master/debian/patches/citrix"
  96. echo " and a PPA with the patched tool is available here: https://launchpad.net/~openstack-ci-core/+archive/ubuntu/vhd-util"
  97. echo
  98. echo "Examples:"
  99. if [ "$IS_RAMDISK" == "0" ]; then
  100. echo " ${SCRIPTNAME} -a amd64 -o ubuntu-amd64 vm ubuntu"
  101. echo " export ELEMENTS_PATH=~/source/tripleo-image-elements/elements"
  102. echo " ${SCRIPTNAME} -a amd64 -o fedora-amd64-heat-cfntools vm fedora heat-cfntools"
  103. else
  104. echo " ${SCRIPTNAME} -a amd64 -o fedora-deploy deploy fedora"
  105. echo " ${SCRIPTNAME} -a amd64 -o ubuntu-ramdisk ramdisk ubuntu"
  106. fi
  107. }
  108. function show_version() {
  109. ${DIB_PYTHON_EXEC:-python} -c "from diskimage_builder import version; print(version.version_info.version_string())"
  110. }
  111. DIB_DEBUG_TRACE=${DIB_DEBUG_TRACE:-0}
  112. INSTALL_PACKAGES=""
  113. IMAGE_TYPES=("qcow2")
  114. COMPRESS_IMAGE="true"
  115. DIB_GZIP_BIN=${DIB_GZIP_BIN:-"gzip"}
  116. ROOT_LABEL=""
  117. DIB_DEFAULT_INSTALLTYPE=${DIB_DEFAULT_INSTALLTYPE:-"source"}
  118. MKFS_OPTS=""
  119. ACI_MANIFEST=${ACI_MANIFEST:-}
  120. DOCKER_TARGET=""
  121. LOGFILE=""
  122. TEMP=`getopt -o a:ho:t:xucnp: -l checksum,no-tmpfs,offline,help,version,min-tmpfs:,image-size:,image-cache:,max-online-resize:,mkfs-options:,qemu-img-options:,ramdisk-element:,root-label:,install-type:,docker-target:,logfile: -n $SCRIPTNAME -- "$@"`
  123. if [ $? -ne 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
  124. # Note the quotes around `$TEMP': they are essential!
  125. eval set -- "$TEMP"
  126. while true ; do
  127. case "$1" in
  128. -a) export ARCH=$2; shift 2 ;;
  129. -o) export IMAGE_NAME=$2; shift 2 ;;
  130. -t) IFS="," read -a IMAGE_TYPES <<< "$2"; export IMAGE_TYPES ; shift 2 ;;
  131. -h|--help) show_options; exit 0;;
  132. --version) show_version; exit 0;;
  133. -x) shift; DIB_DEBUG_TRACE=$(( $DIB_DEBUG_TRACE + 1 ));;
  134. -u) shift; export COMPRESS_IMAGE="";;
  135. -c) shift ; export CLEAR_ENV=1;;
  136. -n) shift; export SKIP_BASE="1";;
  137. -p) IFS="," read -a _INSTALL_PACKAGES <<< "$2"; export INSTALL_PACKAGES=( ${INSTALL_PACKAGES[@]} ${_INSTALL_PACKAGES[@]} ) ; shift 2 ;;
  138. --checksum) shift; export DIB_CHECKSUM=1;;
  139. --image-size) export DIB_IMAGE_SIZE=$2; shift 2;;
  140. --image-extra-size) export DIB_IMAGE_EXTRA_SIZE=$2; shift 2;;
  141. --image-cache) export DIB_IMAGE_CACHE=$2; shift 2;;
  142. --max-online-resize) export MAX_ONLINE_RESIZE=$2; shift 2;;
  143. --mkfs-journal-size) export DIB_JOURNAL_SIZE=$2; shift 2;;
  144. --mkfs-options) MKFS_OPTS=$2; shift 2;;
  145. --min-tmpfs) export DIB_MIN_TMPFS=$2; shift 2;;
  146. --no-tmpfs) shift; export DIB_NO_TMPFS=1;;
  147. --offline) shift; export DIB_OFFLINE=1;;
  148. --qemu-img-options) QEMU_IMG_OPTIONS=$2; shift 2;;
  149. --root-label) ROOT_LABEL=$2; shift 2;;
  150. --ramdisk-element) RAMDISK_ELEMENT=$2; shift 2;;
  151. --install-type) DIB_DEFAULT_INSTALLTYPE=$2; shift 2;;
  152. --docker-target) export DOCKER_TARGET=$2; shift 2 ;;
  153. --logfile) export LOGFILE=$2; shift 2 ;;
  154. --) shift ; break ;;
  155. *) echo "Internal error!" ; exit 1 ;;
  156. esac
  157. done
  158. export DIB_DEBUG_TRACE
  159. # TODO: namespace this under ~/.cache/dib/ for consistency
  160. export DIB_IMAGE_CACHE=${DIB_IMAGE_CACHE:-~/.cache/image-create}
  161. mkdir -p $DIB_IMAGE_CACHE
  162. # Setup a symbolic link to the correct python exec so that element
  163. # scripts running outside the chroot using "#!/usr/bin/env python" get
  164. # the right python version.
  165. export DIB_ORIGINAL_PATH=$PATH
  166. export DIB_PYTHON_EXEC_TMP=$(mktemp -d -t --tmpdir=$HOME .DIB_PYTHON_TMP.XXXXXXXX)
  167. ln -s "$DIB_PYTHON_EXEC" "$DIB_PYTHON_EXEC_TMP/python"
  168. export PATH=$DIB_PYTHON_EXEC_TMP:$DIB_ORIGINAL_PATH
  169. # We have a couple of critical sections (touching parts of the host
  170. # system or download images to common cache) that we use flock around.
  171. # Use this directory for lockfiles.
  172. export DIB_LOCKFILES=${DIB_LOCKFILES:-~/.cache/dib/lockfiles}
  173. mkdir -p $DIB_LOCKFILES
  174. if [ "$CLEAR_ENV" = "1" -a "$HOME" != "" ]; then
  175. echo "Re-execing to clear environment."
  176. echo "(note this will prevent much of the local_config element from working)"
  177. exec -c $0 "$@"
  178. fi
  179. # We send stdout & stderr through "outfilter" which does timestamping,
  180. # basic filtering and log file output.
  181. _TS_FLAG=""
  182. if [[ "${DIB_NO_TIMESTAMP:-0}" -eq 1 ]]; then
  183. _TS_FLAG="--no-timestamp"
  184. fi
  185. # A logfile with *no* DIB_QUIET specified implies we just want output
  186. # to the logfile. Explicitly setting DIB_QUIET=0 will overide this
  187. # and log both.
  188. if [[ -n "${LOGFILE}" && -z "${DIB_QUIET}" ]]; then
  189. DIB_QUIET=1
  190. fi
  191. _QUIET_FLAG="-v"
  192. if [[ "${DIB_QUIET:-0}" -eq 1 ]]; then
  193. _QUIET_FLAG=""
  194. fi
  195. _LOGFILE_FLAG=""
  196. if [[ -n "${LOGFILE}" ]]; then
  197. echo "Output logs going to: ${LOGFILE}"
  198. _LOGFILE_FLAG="-o ${LOGFILE}"
  199. fi
  200. # Save the existing stdout to fd3
  201. exec 3>&1
  202. exec 1> >( ${DIB_PYTHON_EXEC:-python} $_LIB/outfilter.py ${_TS_FLAG} ${_QUIET_FLAG} ${_LOGFILE_FLAG} ) 2>&1
  203. # Display the current file/function/line in the debug output
  204. function _ps4 {
  205. IFS=" " called=($(caller 0))
  206. local f=$(readlink -f ${called[2]})
  207. # As we're being run out of the python package's lib/ dir (either
  208. # virtualenv or system), we can strip everything before
  209. # "site-packages" to significantly shorten the line without really
  210. f=${f##*site-packages/}
  211. printf "%-80s " "$f:${called[1]}:${called[0]}"
  212. }
  213. export -f _ps4
  214. export PS4='+ $(_ps4): '
  215. source $_LIB/img-defaults
  216. source $_LIB/common-functions
  217. source $_LIB/img-functions
  218. if [ "$IS_RAMDISK" == "1" ]; then
  219. source $_LIB/ramdisk-defaults
  220. source $_LIB/ramdisk-functions
  221. fi
  222. echo "diskimage-builder version $(show_version)"
  223. # If no elements are specified theres no way we can succeed
  224. if [ -z "$*" ]; then
  225. echo "ERROR: At least one distribution root element must be specified"
  226. exit 1
  227. fi
  228. arg_to_elements "$@"
  229. # start tracing after most boilerplate
  230. if [ ${DIB_DEBUG_TRACE} -gt 0 ]; then
  231. set -x
  232. fi
  233. if [ "${#IMAGE_TYPES[@]}" = "1" ]; then
  234. export IMAGE_NAME=${IMAGE_NAME%%\.${IMAGE_TYPES[0]}}
  235. fi
  236. # Check for required tools early on
  237. for X in ${!IMAGE_TYPES[@]}; do
  238. case "${IMAGE_TYPES[$X]}" in
  239. qcow2)
  240. if ! type qemu-img > /dev/null 2>&1; then
  241. echo "qcow2 output format specified but qemu-img executable not found."
  242. exit 1
  243. fi
  244. ;;
  245. tgz)
  246. # Force tar to be created.
  247. IMAGE_TYPES+=('tar')
  248. ;;
  249. vhd)
  250. if ! type vhd-util > /dev/null 2>&1; then
  251. echo "vhd output format specified but no vhd-util executable found."
  252. exit 1
  253. fi
  254. ;;
  255. squashfs)
  256. if ! type mksquashfs > /dev/null 2>&1; then
  257. echo "squashfs output format specified but no mksquashfs executable found."
  258. exit 1
  259. fi
  260. ;;
  261. docker)
  262. if ! type docker > /dev/null 2>&1; then
  263. echo "docker output format specified but no docker executable found."
  264. exit 1
  265. fi
  266. if [ -z "$DOCKER_TARGET" ]; then
  267. echo "Please set --docker-target."
  268. exit 1
  269. fi
  270. ;;
  271. esac
  272. done
  273. # NOTE: fstrim is on most all recent systems. It is provided by the util-linux
  274. # package.
  275. if ! type fstrim > /dev/null 2>&1; then
  276. echo "fstrim utility is not found. This is provided by util-linux package"
  277. echo "Please check your PATH variable is set correctly"
  278. exit 1
  279. fi
  280. # xattr support cannot be relied upon with tmpfs builds
  281. # some kernels supoprt it, some don't
  282. if [[ -n "${GENTOO_PROFILE}" ]]; then
  283. if [[ "${GENTOO_PROFILE}" =~ "hardened" ]]; then
  284. echo 'disabling tmpfs for gentoo hardened build'
  285. export DIB_NO_TMPFS=1
  286. fi
  287. fi
  288. mk_build_dir
  289. # Create the YAML file with the final and raw configuration for
  290. # the block device layer.
  291. mkdir -p ${TMP_BUILD_DIR}/block-device
  292. BLOCK_DEVICE_CONFIG_YAML=${TMP_BUILD_DIR}/block-device/config.yaml
  293. block_device_create_config_file "${BLOCK_DEVICE_CONFIG_YAML}"
  294. # Write out the parameter file
  295. DIB_BLOCK_DEVICE_PARAMS_YAML=${TMP_BUILD_DIR}/block-device/params.yaml
  296. export DIB_BLOCK_DEVICE_PARAMS_YAML
  297. cat >${DIB_BLOCK_DEVICE_PARAMS_YAML} <<EOF
  298. config: ${BLOCK_DEVICE_CONFIG_YAML}
  299. image-dir: ${TMP_IMAGE_DIR}
  300. root-fs-type: ${FS_TYPE}
  301. root-label: ${ROOT_LABEL}
  302. mount-base: ${TMP_BUILD_DIR}/mnt
  303. build-dir: ${TMP_BUILD_DIR}
  304. EOF
  305. dib-block-device init
  306. # Need to get the real root label because it can be overwritten
  307. # by the BLOCK_DEVICE_CONFIG.
  308. DIB_ROOT_LABEL=$(dib-block-device getval root-label)
  309. export DIB_ROOT_LABEL
  310. # Need to get the real fs type for the root filesystem
  311. DIB_ROOT_FSTYPE=$(dib-block-device getval root-fstype)
  312. export DIB_ROOT_FSTYPE
  313. # retrieve mount points so we can reuse in elements
  314. DIB_MOUNTPOINTS=$(dib-block-device getval mount-points)
  315. export DIB_MOUNTPOINTS
  316. create_base
  317. # This variable needs to be propagated into the chroot
  318. mkdir -p $TMP_HOOKS_PATH/environment.d
  319. echo "export DIB_DEFAULT_INSTALLTYPE=\${DIB_DEFAULT_INSTALLTYPE:-\"${DIB_DEFAULT_INSTALLTYPE}\"}" > $TMP_HOOKS_PATH/environment.d/11-dib-install-type.bash
  320. run_d extra-data
  321. # Run pre-install scripts. These do things that prepare the chroot for package installs
  322. run_d_in_target pre-install
  323. # Call install scripts to pull in the software users want.
  324. run_d_in_target install
  325. do_extra_package_install
  326. run_d_in_target post-install
  327. run_d post-root
  328. # ensure we do not have a lost+found directory in the root folder
  329. # that could cause copy to fail (it will be created again later
  330. # when creating the file system, if it needs such directory)
  331. if [ -e "$TMP_BUILD_DIR/mnt/lost+found" ]; then
  332. sudo rm -rf "$TMP_BUILD_DIR/mnt/lost+found"
  333. fi
  334. # Free up /mnt
  335. unmount_image
  336. mv $TMP_BUILD_DIR/mnt $TMP_BUILD_DIR/built
  337. # save xtrace state, as we always want to turn it off to avoid
  338. # spamming the logs with du output below.
  339. xtrace=$(set +o | grep xtrace)
  340. # temp file for holding du output
  341. du_output=${TMP_BUILD_DIR}/du_output.tmp
  342. if [ -n "$DIB_IMAGE_SIZE" ]; then
  343. du_size=$(echo "$DIB_IMAGE_SIZE" | awk '{printf("%d\n",$1 * 1024 *1024)}')
  344. else
  345. set +o xtrace
  346. echo "Calculating image size (this may take a minute)..."
  347. sudo du -a -c -x ${TMP_BUILD_DIR}/built > ${du_output}
  348. # the last line is the total size from "-c".
  349. if [ -n "$DIB_IMAGE_EXTRA_SIZE" ]; then
  350. # add DIB_IMAGE_EXTRA_SIZE megabytes to create a bigger image as requested
  351. du_extra_size=$(echo "$DIB_IMAGE_EXTRA_SIZE" | awk '{printf("%d\n",$1 * 1024)}')
  352. du_size_tmp=$(tail -n1 ${du_output} | cut -f1)
  353. du_size=$(echo "$du_size_tmp $du_extra_size" | awk '{print int($1 + $2)}')
  354. else
  355. # scale this by 0.6 to create a slightly bigger image
  356. du_size=$(tail -n1 ${du_output} | cut -f1 | awk '{print int($1 / 0.6)}')
  357. fi
  358. $xtrace
  359. fi
  360. if [[ "${DIB_SHOW_IMAGE_USAGE:-0}" != 0 ]]; then
  361. set +o xtrace
  362. if [ ! -f "$du_output" ]; then
  363. sudo du -a -c -x ${TMP_BUILD_DIR}/built > ${du_output}
  364. fi
  365. du_output_show="sort -nr ${du_output} |
  366. numfmt --to=iec-i --padding=7
  367. --suffix=B --field=1 --from-unit=1024"
  368. # by default show the 10MiB and greater files & directories -- a
  369. # dir with lots of little files will still show up, but this helps
  370. # signal:noise ratio
  371. if [[ ${DIB_SHOW_IMAGE_USAGE_FULL:-0} == 0 ]]; then
  372. # numfmt will start giving a decimal place when < 10MiB
  373. du_output_show+="| egrep 'MiB|GiB|TiB|PiB' | grep -v '\..MiB'"
  374. echo "================================="
  375. echo "Image size report (files > 10MiB)"
  376. echo "================================="
  377. else
  378. echo "================="
  379. echo "Image size report"
  380. echo "================="
  381. fi
  382. eval ${du_output_show}
  383. echo
  384. echo "===== end image size report ====="
  385. echo
  386. $xtrace
  387. fi
  388. rm -f ${du_output}
  389. if [ -n "$DIB_JOURNAL_SIZE" ]; then
  390. journal_size="$DIB_JOURNAL_SIZE"
  391. else
  392. journal_size=64
  393. fi
  394. if [ "$DIB_ROOT_FSTYPE" = "ext4" ] ; then
  395. # Very conservative to handle images being resized a lot
  396. # We set journal size to 64M so our journal is large enough when we
  397. # perform an FS resize.
  398. MKFS_OPTS="-i 4096 -J size=$journal_size $MKFS_OPTS"
  399. # NOTE(ianw) 2019-12-11 : this is a terrible hack ... if building on
  400. # >=Bionic hosts, mkfs sets "metadata_csum" for ext4 filesystems,
  401. # which makes broken Trusty images as that era fsck doesn't
  402. # understand this flag. The image will stop in early boot
  403. # complaining:
  404. #
  405. # Serious errors were found while checking the disk drive for /.
  406. #
  407. # We do not really have any suitable hook points where one of the
  408. # ubuntu elements or block-device-* could set this override flag for
  409. # just Trusty. We probably should, but desire to implement more
  410. # code to support the out-of-date trusty at this point is
  411. # non-existant. So hack in disabling this here.
  412. if [[ ${DIB_RELEASE} == "trusty" ]]; then
  413. MKFS_OPTS="-O ^metadata_csum $MKFS_OPTS"
  414. fi
  415. # Grow the image size to account for the journal, only if the user
  416. # has not asked for a specific size.
  417. if [ -z "$DIB_IMAGE_SIZE" ]; then
  418. du_size=$(( $du_size + ($journal_size * 1024) ))
  419. fi
  420. fi
  421. # EFI system partitions default to be quite large at 512mb for maximum
  422. # compatability (see notes in
  423. # 7fd52ba84180b4e749ccf4c9db8c49eafff46ea8) . We need to increase the
  424. # total size to account for this, or we run out of space creating the
  425. # final image. See if we have included the block-device-efi element,
  426. # which implies we have a large EFI partition, and then pad the final
  427. # image size.
  428. if [[ ${IMAGE_ELEMENT} =~ "block-device-efi" ]]; then
  429. echo "Expanding disk for EFI partition"
  430. du_size=$(( $du_size + (525 * 1024) ))
  431. fi
  432. # Rounding down size so that is is a multiple of 64, works around a bug in
  433. # qemu-img that may occur when compressing raw images that aren't a multiple
  434. # of 64k. https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1180021
  435. export DIB_IMAGE_SIZE=$(echo "$du_size" | awk ' { if ($1 % 64 != 0) print $1 + 64 - ( $1 % 64); else print $1; } ')
  436. if [ -n "$MAX_ONLINE_RESIZE" ]; then
  437. MKFS_OPTS="-E resize=$MAX_ONLINE_RESIZE $MKFS_OPTS"
  438. fi
  439. export TMP_IMAGE_DIR
  440. # Try the 'old fashioned' way calling the block device
  441. # phase. If this gives no result, use the configuration based approach:
  442. eval_run_d block-device "IMAGE_BLOCK_DEVICE="
  443. if [ -z ${IMAGE_BLOCK_DEVICE} ] ; then
  444. # For compatibily reasons in addition to the YAML configuration
  445. # there is the need to handle the old environment variables.
  446. echo "image-size: ${DIB_IMAGE_SIZE}KiB" >> ${DIB_BLOCK_DEVICE_PARAMS_YAML}
  447. if [ -n "${MKFS_OPTS}" ] ; then
  448. echo "root-fs-opts: '${MKFS_OPTS}'" >> ${DIB_BLOCK_DEVICE_PARAMS_YAML}
  449. fi
  450. # After changeing the parameters, there is the need to
  451. # re-run dib-block-device init because some value might
  452. # change based on the new set parameters.
  453. dib-block-device init
  454. # values to dib-block-device: using the YAML config and
  455. dib-block-device create
  456. # This is the device (/dev/loopX). It's where to install the
  457. # bootloader.
  458. IMAGE_BLOCK_DEVICE=$(dib-block-device getval image-block-device)
  459. export IMAGE_BLOCK_DEVICE
  460. # Similar to above, but all mounted devices. This is handy for
  461. # some bootloaders that have multi-partition layouts and want to
  462. # copy things to different places other than just
  463. # IMAGE_BLOCK_DEVICE. "eval" this into an array as needed
  464. IMAGE_BLOCK_DEVICES=$(dib-block-device getval image-block-devices)
  465. export IMAGE_BLOCK_DEVICES
  466. # Write the fstab
  467. dib-block-device writefstab
  468. fi
  469. # XXX: needed?
  470. LOOPDEV=${IMAGE_BLOCK_DEVICE}
  471. # At this point, dib-block-device has created the raw image file
  472. # (IMAGE_BLOCK_DEVICE) and mounted all the partitions under
  473. # $TMP_BUILD_DIR/mnt for us. We can now copy into the final image.
  474. # 'mv' is not usable here - especially when a top level directory
  475. # has the same name as a mount point of a partition. If so, 'mv'
  476. # will complain:
  477. # mv: inter-device move failed: '...' to '...'; \
  478. # unable to remove target: Device or resource busy
  479. # therefore a 'cp' and 'rm' approach is used.
  480. sudo cp -ra ${TMP_BUILD_DIR}/built/* $TMP_BUILD_DIR/mnt
  481. sudo rm -fr ${TMP_BUILD_DIR}/built/*
  482. mount_proc_dev_sys
  483. run_d pre-finalise
  484. run_d_in_target finalise
  485. finalise_base
  486. for X in ${!IMAGE_TYPES[@]} ; do
  487. if [[ " tar aci " =~ "${IMAGE_TYPES[$X]}" ]]; then
  488. if [ "${IMAGE_TYPES[$X]}" = "aci" ]; then
  489. sudo tar -C ${TMP_BUILD_DIR}/mnt -cf $IMAGE_NAME.aci --exclude ./sys \
  490. --exclude ./proc --xattrs --xattrs-include=\* \
  491. --transform 's,^.,rootfs,S' .
  492. if [ -n "$ACI_MANIFEST" ]; then
  493. cp $ACI_MANIFEST ${TMP_BUILD_DIR}/manifest
  494. sudo tar -C ${TMP_BUILD_DIR} --append -f $IMAGE_NAME.aci manifest
  495. else
  496. echo "No ACI_MANIFEST specified. An ACI_MANIFEST must be specified for"
  497. echo " this image to be usable."
  498. fi
  499. else
  500. sudo tar -C ${TMP_BUILD_DIR}/mnt -cf $IMAGE_NAME.tar --exclude ./sys \
  501. --exclude ./proc --xattrs --xattrs-include=\* .
  502. fi
  503. sudo chown $USER: $IMAGE_NAME.${IMAGE_TYPES[$X]}
  504. unset IMAGE_TYPES[$X]
  505. elif [ "${IMAGE_TYPES[$x]}" == "squashfs" ]; then
  506. sudo mksquashfs ${TMP_BUILD_DIR}/mnt $IMAGE_NAME.squash -comp xz \
  507. -noappend -root-becomes ${TMP_BUILD_DIR}/mnt \
  508. -wildcards -e "proc/*" -e "sys/*" -no-recovery
  509. elif [ "${IMAGE_TYPES[$X]}" == "docker" ]; then
  510. sudo tar -C ${TMP_BUILD_DIR}/mnt -cf - --exclude ./sys \
  511. --exclude ./proc --xattrs --xattrs-include=\* . \
  512. | sudo docker import - $DOCKER_TARGET
  513. unset IMAGE_TYPES[$X]
  514. fi
  515. done
  516. # Unmount and cleanup the /mnt and /build subdirectories, to save
  517. # space before converting the image to some other format.
  518. # XXX ? needed?
  519. export EXTRA_UNMOUNT=""
  520. unmount_image
  521. TMP_IMAGE_PATH=$(dib-block-device getval image-path)
  522. export TMP_IMAGE_PATH
  523. # remove all mounts
  524. dib-block-device umount
  525. dib-block-device cleanup
  526. cleanup_build_dir
  527. if [[ (! $IMAGE_ELEMENT =~ no-final-image) && "$IS_RAMDISK" == "0" ]]; then
  528. has_raw_type=
  529. for IMAGE_TYPE in ${IMAGE_TYPES[@]} ; do
  530. # We have to do raw last because it is destructive
  531. if [ "$IMAGE_TYPE" = "raw" ]; then
  532. has_raw_type=1
  533. elif [ "$IMAGE_TYPE" != "squashfs" ]; then
  534. compress_and_save_image $IMAGE_NAME.$IMAGE_TYPE
  535. fi
  536. done
  537. if [ -n "$has_raw_type" ]; then
  538. IMAGE_TYPE="raw"
  539. compress_and_save_image $IMAGE_NAME.$IMAGE_TYPE
  540. fi
  541. fi
  542. # Remove the leftovers, i.e. the temporary image directory.
  543. cleanup_image_dir
  544. cleanup_temp_python_exec
  545. # Restore fd 1&2 from the outfilter.py redirect back to the original
  546. # saved fd. Note small hack that we can't really wait properly for
  547. # outfilter.py so put in a sleep (might be possible to use coproc for
  548. # this...?)
  549. #
  550. # TODO(ianw): probably better to cleanup the exit handler a bit for
  551. # this? We really want some helper functions that append to the exit
  552. # handler so we can register multiple things.
  553. set +o xtrace
  554. echo "Build completed successfully"
  555. exec 1>&3 2>&3
  556. sleep 1
  557. # All done!
  558. trap EXIT