 590dce8dcc
			
		
	
	590dce8dcc
	
	
	
		
			
			This patch fixes the calculation of the resultant image size when building an image with diskimage-builder on ext4 a filesystem. Prior to this, using the '--image-size 2' (2GB) setting would generate an image that would not boot under a 2GB nova flavor. Change-Id: I7a753bdef84c6300ccea73ae4a92bf330dcd77cb Closes-Bug: #1513622
		
			
				
	
	
		
			331 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			331 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/bash
 | |
| #
 | |
| # Copyright 2012 Hewlett-Packard Development Company, L.P.
 | |
| #
 | |
| # 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.
 | |
| 
 | |
| set -eE
 | |
| 
 | |
| # Prevent perl from complaining a lot, but also remove any unexpected side-effects
 | |
| # of $LANG varying between build hosts
 | |
| export LANG=C
 | |
| 
 | |
| # Store our initial environment and command line args for later
 | |
| export DIB_ARGS="$@"
 | |
| export DIB_ENV=$(export | grep ' DIB_.*=')
 | |
| 
 | |
| SCRIPTNAME=$(basename $0)
 | |
| SCRIPT_HOME=$(dirname $(readlink -f $0))
 | |
| if [ -d $SCRIPT_HOME/../share/diskimage-builder ]; then
 | |
|     export _PREFIX=$SCRIPT_HOME/../share/diskimage-builder
 | |
| else
 | |
|     export _PREFIX=$SCRIPT_HOME/..
 | |
| fi
 | |
| export _LIB=$_PREFIX/lib
 | |
| source $_LIB/die
 | |
| 
 | |
| IS_RAMDISK=0
 | |
| if [ "$SCRIPTNAME" == "ramdisk-image-create" ]; then
 | |
|   IS_RAMDISK=1
 | |
| fi
 | |
| 
 | |
| function show_options () {
 | |
|     echo "Usage: ${SCRIPTNAME} [OPTION]... [ELEMENT]..."
 | |
|     echo
 | |
|     echo "Options:"
 | |
|     echo "    -a i386|amd64|armhf -- set the architecture of the image(default amd64)"
 | |
|     echo "    -o imagename -- set the imagename of the output image file(default image)"
 | |
|     echo "    -t qcow2,tar,vhd,docker,raw -- set the image types of the output image files (default qcow2)"
 | |
|     echo "       File types should be comma separated. VHD outputting requires the vhd-util"
 | |
|     echo "       executable be in your PATH."
 | |
|     echo "    -x -- turn on tracing"
 | |
|     echo "    -u -- uncompressed; do not compress the image - larger but faster"
 | |
|     echo "    -c -- clear environment before starting work"
 | |
|     echo "    --image-size size -- image size in GB for the created image"
 | |
|     echo "    --image-cache directory -- location for cached images(default ~/.cache/image-create)"
 | |
|     echo "    --max-online-resize size -- max number of filesystem blocks to support when resizing."
 | |
|     echo "       Useful if you want a really large root partition when the image is deployed."
 | |
|     echo "       Using a very large value may run into a known bug in resize2fs."
 | |
|     echo "       Setting the value to 274877906944 will get you a 1PB root file system."
 | |
|     echo "       Making this value unnecessarily large will consume extra disk space "
 | |
|     echo "       on the root partition with extra file system inodes."
 | |
|     echo "    --min-tmpfs size -- minimum size in GB needed in tmpfs to build the image"
 | |
|     echo "    --mkfs-options -- option flags to be passed directly to mkfs."
 | |
|     echo "       Options should be passed as a single string value."
 | |
|     echo "    --no-tmpfs -- do not use tmpfs to speed image build"
 | |
|     echo "    --offline -- do not update cached resources"
 | |
|     echo "    --qemu-img-options -- option flags to be passed directly to qemu-img."
 | |
|     echo "       Options need to be comma separated, and follow the key=value pattern."
 | |
|     echo "    --root-label label -- label for the root filesystem.  Defaults to 'cloudimg-rootfs'."
 | |
|     echo "    --ramdisk-element -- specify the main element to be used for building ramdisks."
 | |
|     echo "       Defaults to 'ramdisk'.  Should be set to 'dracut-ramdisk' for platforms such"
 | |
|     echo "       as RHEL and CentOS that do not package busybox."
 | |
|     echo "    --install-type -- specify the default installation type. Defaults to 'source'. Set to 'package' to use package based installations by default."
 | |
|     echo "    --docker-target -- specify the repo and tag to use if the output type is docker. Defaults to the value of output imagename"
 | |
|     if [ "$IS_RAMDISK" == "0" ]; then
 | |
|         echo "    -n skip the default inclusion of the 'base' element"
 | |
|         echo "    -p package[,package,package] -- list of packages to install in the image"
 | |
|     fi
 | |
|     echo "    -h|--help -- display this help and exit"
 | |
|     echo
 | |
|     echo "ELEMENTS_PATH will allow you to specify multiple locations for the elements."
 | |
|     echo
 | |
|     echo "NOTE: At least one distribution root element must be specified."
 | |
|     echo
 | |
|     echo "NOTE: If using the VHD output format you need to have a patched version of vhd-util installed for the image"
 | |
|     echo "      to be bootable. The patch is available here: https://github.com/emonty/vhd-util/blob/master/debian/patches/citrix"
 | |
|     echo "      and a PPA with the patched tool is available here: https://launchpad.net/~openstack-ci-core/+archive/ubuntu/vhd-util"
 | |
|     echo
 | |
|     echo "Examples:"
 | |
|     if [ "$IS_RAMDISK" == "0" ]; then
 | |
|         echo "    ${SCRIPTNAME} -a amd64 -o ubuntu-amd64 vm ubuntu"
 | |
|         echo "    export ELEMENTS_PATH=~/source/tripleo-image-elements/elements"
 | |
|         echo "    ${SCRIPTNAME} -a amd64 -o fedora-amd64-heat-cfntools vm fedora heat-cfntools"
 | |
|     else
 | |
|         echo "    ${SCRIPTNAME} -a amd64 -o fedora-deploy deploy fedora"
 | |
|         echo "    ${SCRIPTNAME} -a amd64 -o ubuntu-ramdisk ramdisk ubuntu"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| INSTALL_PACKAGES=""
 | |
| IMAGE_TYPES=("qcow2")
 | |
| COMPRESS_IMAGE="true"
 | |
| export DIB_ROOT_LABEL=""
 | |
| DIB_DEFAULT_INSTALLTYPE=${DIB_DEFAULT_INSTALLTYPE:-"source"}
 | |
| MKFS_OPTS=""
 | |
| DOCKER_TARGET=""
 | |
| TEMP=`getopt -o a:ho:t:xucnp: -l no-tmpfs,offline,help,min-tmpfs:,image-size:,image-cache:,max-online-resize:,mkfs-options:,qemu-img-options:,ramdisk-element:,root-label:,install-type:,docker-target: -n $SCRIPTNAME -- "$@"`
 | |
| if [ $? -ne 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
 | |
| 
 | |
| # Note the quotes around `$TEMP': they are essential!
 | |
| eval set -- "$TEMP"
 | |
| 
 | |
| while true ; do
 | |
|     case "$1" in
 | |
|         -a) export ARCH=$2; shift 2 ;;
 | |
|         -o) export IMAGE_NAME=$2; shift 2 ;;
 | |
|         -t) IFS="," read -a IMAGE_TYPES <<< "$2"; export IMAGE_TYPES ; shift 2 ;;
 | |
|         -h|--help) show_options; exit 0;;
 | |
|         -x) shift; export DIB_DEBUG_TRACE=$(( $DIB_DEBUG_TRACE + 1 )); set -x;;
 | |
|         -u) shift; export COMPRESS_IMAGE="";;
 | |
|         -c) shift ; export CLEAR_ENV=1;;
 | |
|         -n) shift; export SKIP_BASE="1";;
 | |
|         -p) IFS="," read -a INSTALL_PACKAGES <<< "$2"; export INSTALL_PACKAGES ; shift 2 ;;
 | |
|         --image-size) export DIB_IMAGE_SIZE=$2; shift 2;;
 | |
|         --image-cache) export DIB_IMAGE_CACHE=$2; shift 2;;
 | |
|         --max-online-resize) export MAX_ONLINE_RESIZE=$2; shift 2;;
 | |
|         --mkfs-options) MKFS_OPTS=$2; shift 2;;
 | |
|         --min-tmpfs) export DIB_MIN_TMPFS=$2; shift 2;;
 | |
|         --no-tmpfs) shift; export DIB_NO_TMPFS=1;;
 | |
|         --offline) shift; export DIB_OFFLINE=1;;
 | |
|         --qemu-img-options) QEMU_IMG_OPTIONS=$2; shift 2;;
 | |
|         --root-label) export DIB_ROOT_LABEL=$2; shift 2;;
 | |
|         --ramdisk-element) RAMDISK_ELEMENT=$2; shift 2;;
 | |
|         --install-type) DIB_DEFAULT_INSTALLTYPE=$2; shift 2;;
 | |
|         --docker-target) export DOCKER_TARGET=$2; shift 2 ;;
 | |
|         --) shift ; break ;;
 | |
|         *) echo "Internal error!" ; exit 1 ;;
 | |
|     esac
 | |
| done
 | |
| 
 | |
| export DIB_IMAGE_CACHE=${DIB_IMAGE_CACHE:-~/.cache/image-create}
 | |
| mkdir -p $DIB_IMAGE_CACHE
 | |
| 
 | |
| if [ "$CLEAR_ENV" = "1" -a "$HOME" != "" ]; then
 | |
|   echo "Re-execing to clear environment."
 | |
|   echo "(note this will prevent much of the local_config element from working)"
 | |
|   exec -c $0 "$@"
 | |
| fi
 | |
| 
 | |
| source $_LIB/img-defaults
 | |
| source $_LIB/common-functions
 | |
| source $_LIB/img-functions
 | |
| 
 | |
| if [ "$IS_RAMDISK" == "1" ]; then
 | |
|   source $_LIB/ramdisk-defaults
 | |
|   source $_LIB/ramdisk-functions
 | |
| fi
 | |
| 
 | |
| # If no elements are specified theres no way we can succeed
 | |
| if [ -z "$*" ]; then
 | |
|     echo "ERROR: At least one distribution root element must be specified"
 | |
|     exit 1
 | |
| fi
 | |
| arg_to_elements "$@"
 | |
| 
 | |
| if [ "${#IMAGE_TYPES[@]}" = "1" ]; then
 | |
|   export IMAGE_NAME=${IMAGE_NAME%%\.${IMAGE_TYPES[0]}}
 | |
| fi
 | |
| 
 | |
| # Check for required tools early on
 | |
| for X in ${!IMAGE_TYPES[@]}; do
 | |
|     case "${IMAGE_TYPES[$X]}" in
 | |
|         qcow2)
 | |
|             if [ -z "$(which qemu-img)" ]; then
 | |
|                 echo "qcow2 output format specified but qemu-img executable not found."
 | |
|                 exit 1
 | |
|             fi
 | |
|             ;;
 | |
|         vhd)
 | |
|             if [ -z "$(which vhd-util)" ]; then
 | |
|                 echo "vhd output format specified but no vhd-util executable found."
 | |
|                 exit 1
 | |
|             fi
 | |
|             ;;
 | |
|         docker)
 | |
|             if [ -z "$(which docker)" ]; then
 | |
|                 echo "docker output format specified but no docker executable found."
 | |
|                 exit 1
 | |
|             fi
 | |
|             if [ -z "$DOCKER_TARGET" ]; then
 | |
|                 echo "Please set --docker-target."
 | |
|                 exit 1
 | |
|             fi
 | |
|             ;;
 | |
|     esac
 | |
| done
 | |
| 
 | |
| # NOTE: Tuning the rootfs uuid works only for ext filesystems.
 | |
| # Rely on the below environment variable only for ext filesystems.
 | |
| export DIB_IMAGE_ROOT_FS_UUID=$(uuidgen -r)
 | |
| if echo "$FS_TYPE" | grep -q "^ext" && [ -z "${DIB_IMAGE_ROOT_FS_UUID}" ]; then
 | |
|     echo "ext filesystem detected but no DIB_IMAGE_ROOT_FS_UUID found."
 | |
|     echo "Is the uuidgen utility installed on your system?"
 | |
|     exit 1
 | |
| fi
 | |
| 
 | |
| # FS_TYPE isn't available until after we source img-defaults
 | |
| if [ -z "$DIB_ROOT_LABEL" ]; then
 | |
|     # NOTE(bnemec): XFS has a limit of 12 characters for filesystem labels
 | |
|     # Not changing the default for other filesystems to maintain backwards compatibility
 | |
|     if [ "$FS_TYPE" = "xfs" ]; then
 | |
|         DIB_ROOT_LABEL="img-rootfs"
 | |
|     else
 | |
|         DIB_ROOT_LABEL="cloudimg-rootfs"
 | |
|     fi
 | |
| fi
 | |
| 
 | |
| mk_build_dir
 | |
| create_base
 | |
| # This variable needs to be propagated into the chroot
 | |
| mkdir -p $TMP_HOOKS_PATH/environment.d
 | |
| echo "export DIB_DEFAULT_INSTALLTYPE=\${DIB_DEFAULT_INSTALLTYPE:-\"${DIB_DEFAULT_INSTALLTYPE}\"}" > $TMP_HOOKS_PATH/environment.d/11-dib-install-type.bash
 | |
| run_d extra-data
 | |
| # Run pre-install scripts. These do things that prepare the chroot for package installs
 | |
| run_d_in_target pre-install
 | |
| do_extra_package_install
 | |
| # Call install scripts to pull in the software users want.
 | |
| run_d_in_target install
 | |
| run_d_in_target post-install
 | |
| # ensure we do not have a lost+found directory in the root folder
 | |
| # that could cause copy to fail (it will be created again later
 | |
| # when creating the file system, if it needs such directory)
 | |
| if [ -e "$TMP_BUILD_DIR/mnt/lost+found" ]; then
 | |
|     sudo rm -rf "$TMP_BUILD_DIR/mnt/lost+found"
 | |
| fi
 | |
| # Free up /mnt
 | |
| unmount_image
 | |
| mv $TMP_BUILD_DIR/mnt $TMP_BUILD_DIR/built
 | |
| 
 | |
| if [ -n "$DIB_IMAGE_SIZE" ]; then
 | |
|   du_size=$(echo "$DIB_IMAGE_SIZE" | awk '{printf("%d\n",$1 * 1024 *1024)}')
 | |
| else
 | |
|   # in kb*0.60 - underreport to get a slightly bigger device
 | |
|   du_size=$(sudo du --block-size=600 -x -s ${TMP_BUILD_DIR}/built |\
 | |
|             awk ' { print $1 }')
 | |
| fi
 | |
| if [ "$FS_TYPE" = "ext4" ] ; then
 | |
|   # Very conservative to handle images being resized a lot
 | |
|   # We set journal size to 64M so our journal is large enough when we
 | |
|   # perform an FS resize.
 | |
|   MKFS_OPTS="-i 4096 -J size=64 $MKFS_OPTS"
 | |
|   # Grow the image size to account for the journal, only if the user
 | |
|   # has not asked for a specific size.
 | |
|   if [ -z "$DIB_IMAGE_SIZE" ]; then
 | |
|     du_size=$(( $du_size + 65536 ))
 | |
|   fi
 | |
| fi
 | |
| 
 | |
| # Rounding down size so that is is a multiple of 64, works around a bug in
 | |
| # qemu-img that may occur when compressing raw images that aren't a multiple
 | |
| # of 64k. https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1180021
 | |
| du_size=$(echo "$du_size" | awk ' { if ($1 % 64 != 0) print $1 + 64 - ( $1 % 64); else print $1; } ')
 | |
| truncate -s${du_size}K $TMP_IMAGE_PATH
 | |
| 
 | |
| if [ -n "$MAX_ONLINE_RESIZE" ]; then
 | |
|     MKFS_OPTS="-E resize=$MAX_ONLINE_RESIZE $MKFS_OPTS"
 | |
| fi
 | |
| 
 | |
| LOOPDEV=$(sudo losetup --show -f $TMP_IMAGE_PATH)
 | |
| export EXTRA_UNMOUNT="detach_loopback $LOOPDEV"
 | |
| export IMAGE_BLOCK_DEVICE=$LOOPDEV
 | |
| eval_run_d block-device "IMAGE_BLOCK_DEVICE="
 | |
| sudo mkfs $MKFS_OPTS -t $FS_TYPE -L ${DIB_ROOT_LABEL} ${IMAGE_BLOCK_DEVICE}
 | |
| # Tuning the rootfs uuid works only for ext filesystems.
 | |
| if echo "$FS_TYPE" | grep -q "^ext"; then
 | |
|     sudo tune2fs ${IMAGE_BLOCK_DEVICE} -U ${DIB_IMAGE_ROOT_FS_UUID}
 | |
| fi
 | |
| mkdir $TMP_BUILD_DIR/mnt
 | |
| sudo mount ${IMAGE_BLOCK_DEVICE} $TMP_BUILD_DIR/mnt
 | |
| sudo mv -t $TMP_BUILD_DIR/mnt ${TMP_BUILD_DIR}/built/*
 | |
| mount_proc_dev_sys
 | |
| run_d_in_target finalise
 | |
| finalise_base
 | |
| 
 | |
| for X in ${!IMAGE_TYPES[@]} ; do
 | |
|   if [ "${IMAGE_TYPES[$X]}" == "tar" ]; then
 | |
|     sudo tar -C ${TMP_BUILD_DIR}/mnt -cf $IMAGE_NAME.tar --exclude ./sys \
 | |
|              --exclude ./proc --xattrs --xattrs-include=\* .
 | |
|     sudo chown $USER: $IMAGE_NAME.tar
 | |
|     unset IMAGE_TYPES[$X]
 | |
|   elif [ "${IMAGE_TYPES[$X]}" == "docker" ]; then
 | |
|     sudo tar -C ${TMP_BUILD_DIR}/mnt -cf - --exclude ./sys \
 | |
|              --exclude ./proc --xattrs --xattrs-include=\* . \
 | |
|         | docker import - $DOCKER_TARGET
 | |
|     unset IMAGE_TYPES[$X]
 | |
|   fi
 | |
| done
 | |
| 
 | |
| # Unmount and cleanup the /mnt and /build subdirectories, to save
 | |
| # space before converting the image to some other format.
 | |
| unmount_image
 | |
| cleanup_build_dir
 | |
| 
 | |
| has_raw_type=
 | |
| if [ "$IS_RAMDISK" == "0" ]; then
 | |
|   for IMAGE_TYPE in ${IMAGE_TYPES[@]} ; do
 | |
|     # We have to do raw last because it is destructive
 | |
|     if [ "$IMAGE_TYPE" = "raw" ]; then
 | |
|       has_raw_type=1
 | |
|     else
 | |
|       compress_and_save_image $IMAGE_NAME.$IMAGE_TYPE
 | |
|     fi
 | |
|   done
 | |
| fi
 | |
| if [ -n "$has_raw_type" ]; then
 | |
|   IMAGE_TYPE="raw"
 | |
|   compress_and_save_image $IMAGE_NAME.$IMAGE_TYPE
 | |
| fi
 | |
| 
 | |
| # Remove the leftovers, i.e. the temporary image directory.
 | |
| cleanup_image_dir
 | |
| 
 | |
| case "$IMAGE_ELEMENT" in
 | |
|   *ironic-agent*)
 | |
|     rm $IMAGE_NAME.$IMAGE_TYPE
 | |
|     ;;
 | |
| esac
 | |
| 
 | |
| # All done!
 | |
| trap EXIT
 |