3 # (c) 2013-2016, Thomas Goirand <zigo@debian.org>
4 # (c) 2015-2016, Bastian Blank
5 # License: Apache 2.0, see LICENSE.txt for details.
9 if [ "$UNSHARED" != true ] ; then
10 exec env UNSHARED=true unshare --mount --pid --fork --mount-proc "$0" "$@"
16 # Parse input parameters
18 echo "Usage: $0 --release|-r <jessie|wheezy> [options]
22 --boot-manager|-bm <grub|syslinux> (default: grub)
23 --debootstrap-url|-u <debootstrap-mirror> (default: http://httpredir.debian.org/debian)
24 --sources.list-mirror|-s <source-list-mirror> (default: http://httpredir.debian.org/debian)
25 --extra-packages|-e <package>,<package>,...
26 --hook-script|-hs <hook-script>
27 --image-size|-is <image-size> (default: 2G)
28 --automatic-resize|-ar
29 --automatic-resize-space|-ars <suplementary-space> (default: 50M)
30 --login|-l <userlogin> (default: debian)
31 --password|-p <root-password> (dangerous option: avoid it if possible)
32 --boot-type|-bt <boot type> (default: mbr)
33 --architecture|-a <architecture> (default: amd64)
34 For more info: man $0"
45 "--extra-packages"|"-e")
46 if [ -z "${2}" ] ; then
47 echo "No parameter defining the extra packages"
54 "--debootstrap-url"|"-u")
55 if [ -z "${2}" ] ; then
56 echo "No parameter defining the debootstrap URL"
71 "--boot-manager"|"-bm")
72 if [ "${2}" != "grub" ] && [ "${2}" != "syslinux" ] ; then
73 echo "No recognized parameter defining the boot manager"
81 if [ "${2}" != "mbr" ] && [ "${2}" != "uefi" ] ; then
82 echo "No recognized parameter defining the boot type"
89 "--architecture"|"-a")
90 if [ "${2}" != "amd64" ] && [ "${2}" != "arm64" ] ; then
91 echo "No recognized parameter defining the architecture (currently support amd64 and arm64)"
98 "--automatic-resize"|"-ar")
102 "--automatic-resize-space"|"-ars")
103 if [ -z "${2}" ] ; then
104 echo "No parameter defining the suplementary space"
107 AUTOMATIC_RESIZE_SPACE=${2}
111 "--image-size"|"-is")
112 if [ -z "${2}" ] ; then
113 echo "No parameter defining the image size"
120 "--hook-script"|"-hs")
121 if [ -z "${2}" ] ; then
122 echo "No parameter defining the hook script"
125 if ! [ -x "${2}" ] ; then
126 echo "Hook script not executable"
132 "--sources.list-mirror"|"-s")
133 if [ -z "${2}" ] ; then
134 echo "No parameter defining the hook script"
137 SOURCE_LIST_MIRROR=${2}
142 if [ "${2}" = "wheezy" ] || [ "${2}" = "jessie" ] || [ "${2}" = "stretch" ] || [ "${2}" = "buster" ] ; then
147 echo "Release not recognized."
152 if [ -z "${2}" ] ; then
153 echo "No parameter defining the user login"
161 if [ -z "${2}" ] ; then
162 echo "No parameter defining the root password"
169 if [ -z "${2}" ] ; then
170 echo "No output file specified"
181 if [ -z "${RELEASE}" ] ; then
182 echo "Release not recognized: please specify the -r parameter."
200 if [ -z "${DEB_MIRROR}" ] ; then
201 DEB_MIRROR=http://httpredir.debian.org/debian
203 if [ -z "${EXTRA_PACKAGES}" ] ; then
204 EXTRA_PACKAGES=bash-completion,joe,most,screen,less,vim,bzip2,nano
206 if [ -z "${SOURCE_LIST_MIRROR}" ] ; then
207 SOURCE_LIST_MIRROR=http://httpredir.debian.org/debian
209 if [ -z "${IMAGE_SIZE}" ] ; then
212 if [ -z "${AUTOMATIC_RESIZE_SPACE}" ] ; then
213 AUTOMATIC_RESIZE_SPACE=50
215 if [ -z "${USER_LOGIN}" ] ; then
218 if [ -z "${OUTPUT}" ] ; then
219 OUTPUT=debian-${RELEASE}-$(TZ=UTC date '+%Y%m%d%H%M')-${ARCH}
222 if [ "${BOOTTYPE}" = "uefi" ] && [ "${BOOTMANAGER}" != "grub" ] ; then
223 echo "uefi boot type is only compatible with grub"
227 if [ "${ARCH}" = "arm64" ] ; then
228 if [ "${BOOTMANAGER}" != "grub" ] || [ "${BOOTTYPE}" != "uefi" ] ; then
229 echo "arm64 depends on using grub and uefi"
235 if [ "${ARCH}" = "arm64" ] ; then
239 if [ "${BOOTMANAGER}" = "grub" ] ; then
240 if [ "${BOOTTYPE}" = "uefi" ] ; then
241 BOOT_MGR_PKG="grub-efi-${ARCH}"
242 if [ "${ARCH}" = "arm64" ] ; then
243 GRUB_TARGET="arm64-efi"
245 GRUB_TARGET="x86_64-efi"
248 BOOT_MGR_PKG="grub-pc"
249 GRUB_TARGET="i386-pc"
252 BOOT_MGR_PKG="extlinux"
255 NEEDED_PACKAGES=sudo,adduser,locales,${BOOT_MGR_PKG},openssh-server,euca2ools,file,kbd,aptitude,file
256 if [ "${RELEASE}" = "wheezy" ] ; then
257 # These are needed by cloud-init and friends, and since we don't want backports of them,
258 # but just normal packages from Wheezy, we resolve dependencies by hand, prior to using
259 # apt-get -t wheezy-backports install cloud-init cloud-utils cloud-initramfs-growroot
260 NEEDED_PACKAGES=${NEEDED_PACKAGES},python,python-paramiko,python-argparse,python-cheetah,python-configobj,python-oauth,python-software-properties,python-yaml,python-boto,python-prettytable,initramfs-tools,python-requests,acpid,acpi-support-base,ntp,unscd
262 NEEDED_PACKAGES=${NEEDED_PACKAGES},cloud-init,cloud-utils,cloud-initramfs-growroot,dbus,ntp,unscd
265 # This is a workaround for python3-cryptography failing to install
266 if [ "${RELEASE_NUM}" -ge 9 ] ; then
267 NEEDED_PACKAGES=${NEEDED_PACKAGES},python3-cffi-backend
270 if [ ${EXTRA} = "no" ] ; then
271 PKG_LIST=${NEEDED_PACKAGES}
273 PKG_LIST=${NEEDED_PACKAGES},${EXTRA_PACKAGES}
275 if ! [ `whoami` = "root" ] ; then
276 echo "You have to be root to run this script"
279 FILE_NAME=debian-${RELEASE}-${RELEASE_NUM}.0.0-1-${ARCH}
280 RAW_NAME=${OUTPUT}.raw
281 QCOW2_NAME=${OUTPUT}.qcow2
286 ######################################
287 ### Prepare the HDD (format, ext.) ###
288 ######################################
291 qemu-img create ${RAW_NAME} ${IMAGE_SIZE}G
293 if [ "${BOOTTYPE}" = "mbr" ] ; then
294 ${PARTED} -s ${RAW_NAME} mktable msdos
295 ${PARTED} -s -a optimal ${RAW_NAME} mkpart primary ext4 1Mi 100%
296 ${PARTED} -s ${RAW_NAME} set 1 boot on
297 install-mbr --force ${RAW_NAME}
298 RESULT_KPARTX=$(kpartx -asv ${RAW_NAME} 2>&1)
299 if echo "${RESULT_KPARTX}" | grep "^add map" ; then
300 LOOP_DEVICE=$(echo ${RESULT_KPARTX} | cut -d" " -f3)
301 LOOPRAW_DEVICE=${LOOP_DEVICE%p*}
302 echo "kpartx mounted using: ${LOOP_DEVICE} via ${LOOPRAW_DEVICE}"
304 echo "It seems kpartx didn't mount the image correctly: exiting."
308 ${PARTED} -s ${RAW_NAME} mktable gpt
309 ${PARTED} -s -a optimal ${RAW_NAME} mkpart ESP fat32 1Mi 101Mi
310 ${PARTED} -s -a optimal ${RAW_NAME} -- mkpart ROOT ext4 102Mi -64s
311 ${PARTED} -s ${RAW_NAME} set 1 esp on
312 RESULT_KPARTX=$(kpartx -asv ${RAW_NAME} 2>&1 | tail -1)
313 if echo "${RESULT_KPARTX}" | grep "^add map" ; then
314 LOOP_DEVICE=$(echo ${RESULT_KPARTX} | cut -d" " -f3)
315 LOOPRAW_DEVICE=${LOOP_DEVICE%p*}
316 echo "kpartx mounted using: ${LOOP_DEVICE} via ${LOOPRAW_DEVICE}"
318 echo "It seems kpartx didn't mount the image correctly: exiting."
321 LOOP_DEVICE_ESP=$(kpartx -asv ${RAW_NAME} 2>&1 | head -1 | cut -d" " -f3)
326 [ ! -d "${MOUNT_DIR}" ] && return
327 if [ "$error" -gt 0 ]; then
337 chroot ${MOUNT_DIR} umount /proc || true
338 chroot ${MOUNT_DIR} umount /sys || true
339 chroot ${MOUNT_DIR} umount /dev || true
340 umount -l ${MOUNT_DIR}
343 kpartx -d ${RAW_NAME}
346 trap "cleanup" EXIT TERM INT
348 mkfs.ext4 /dev/mapper/${LOOP_DEVICE}
349 UUID=$(blkid -o value -s UUID /dev/mapper/${LOOP_DEVICE})
351 # No fsck because of X days without checks
352 tune2fs -i 0 /dev/mapper/${LOOP_DEVICE}
354 MOUNT_DIR=`mktemp -d -t build-debimg.XXXXXX`
356 mount /dev/mapper/${LOOP_DEVICE} ${MOUNT_DIR}
357 if [ "${BOOTTYPE}" = "uefi" ] ; then
358 mkfs.vfat /dev/mapper/${LOOP_DEVICE_ESP}
359 UUID_ESP=$(blkid -o value -s UUID /dev/mapper/${LOOP_DEVICE_ESP})
360 mkdir -p ${MOUNT_DIR}/boot/efi
361 mount /dev/mapper/${LOOP_DEVICE_ESP} ${MOUNT_DIR}/boot/efi
364 debootstrap --verbose \
365 --include=${PKG_LIST} \
366 ${RELEASE} ${MOUNT_DIR} ${DEB_MIRROR}
369 ############################
370 ### Customize the distro ###
371 ############################
372 ### Customize: access to the VM ###
373 # # # # # # # # # # # # # # # # # #
374 # Setup default root password to what has been set on the command line
375 if [ -n "${ROOT_PASSWORD}" ] ; then
376 chroot ${MOUNT_DIR} sh -c "echo root:${ROOT_PASSWORD} | chpasswd"
379 # Otherwise, we have a huge backdoor, since the root password
380 # is always the same.
381 sed -i "s/PermitRootLogin yes/PermitRootLogin without-password/" ${MOUNT_DIR}/etc/ssh/sshd_config
382 cat >>${MOUNT_DIR}/etc/ssh/sshd_config <<EOF
384 ClientAliveInterval 120
387 # Add a default user which is used by cloud-init by default
388 chroot ${MOUNT_DIR} adduser --gecos Cloud-init-user --disabled-password --quiet ${USER_LOGIN}
390 # Adds the "debian" user to sudoers, since that is the way
391 # cloud-init grant access
392 mkdir -p ${MOUNT_DIR}/etc/sudoers.d
393 echo "${USER_LOGIN} ALL = NOPASSWD: ALL" >${MOUNT_DIR}/etc/sudoers.d/debian-cloud-init
394 chmod 0440 ${MOUNT_DIR}/etc/sudoers.d/debian-cloud-init
396 ### Customize: misc stuff ###
397 # # # # # # # # # # # # # # #
399 echo "# /etc/fstab: static file system information.
400 UUID=${UUID} / ext4 errors=remount-ro 0 1
401 " > ${MOUNT_DIR}/etc/fstab
402 if [ "${BOOTTYPE}" = "uefi" ] ; then
403 echo "UUID=${UUID_ESP} /boot/efi vfat errors=remount-ro 0 0" >> ${MOUNT_DIR}/etc/fstab
405 mount -t proc proc ${MOUNT_DIR}/proc
407 echo "# disable pc speaker
408 blacklist pcspkr" >${MOUNT_DIR}/etc/modprobe.d/blacklist.conf
410 # Enable bash-completion by default
411 if [ ${EXTRA} = "yes" ] ; then
412 echo "# enable bash completion in interactive shells
413 if ! shopt -oq posix; then
414 if [ -f /usr/share/bash-completion/bash_completion ]; then
415 . /usr/share/bash-completion/bash_completion
416 elif [ -f /etc/bash_completion ]; then
417 . /etc/bash_completion
419 fi" >>${MOUNT_DIR}/etc/bash.bashrc
422 # No clear for the tty1 console
423 if [ "${RELEASE}" = "wheezy" ] ; then
424 sed -i "s#1:2345:respawn:/sbin/getty 38400 tty1#1:2345:respawn:/sbin/getty --noclear 38400 tty1#" ${MOUNT_DIR}/etc/inittab
426 # XXX: the serial port on Microsoft Azure plattform can't cope with
427 # lots of data, keep this option disabled.
428 #echo ForwardToConsole=yes >> ${MOUNT_DIR}/etc/systemd/journald.conf
432 # We do it *after* the debootstrap, as otherwise it fails with
433 # systemd-shim conflicting with systemd-sysv.
434 chroot ${MOUNT_DIR} apt-get install -y locales-all libpam-systemd
436 # Turn off console blanking which is *very* annoying
437 # and increase KEYBOARD_DELAY because it can be annoying
439 # Note: /etc/kbd/config is gone away from Stretch, but
440 # we still need to fix it for previous Debian releases.
441 # In stretch and beyond, consoleblank=0 in the kernel
442 # command line should be enough (TODO: check for that fact).
443 if [ -e ${MOUNT_DIR}/etc/kbd/config ] ; then
444 sed -i s/^BLANK_TIME=.*/BLANK_TIME=0/ ${MOUNT_DIR}/etc/kbd/config
445 sed -i s/^POWERDOWN_TIME=.*/POWERDOWN_TIME=0/ ${MOUNT_DIR}/etc/kbd/config
446 sed -i 's/^[ \t#]KEYBOARD_DELAY=.*/KEYBOARD_DELAY=1000/' ${MOUNT_DIR}/etc/kbd/config
449 rm -f ${MOUNT_DIR}/etc/ssh/ssh_host_*
450 rm -f ${MOUNT_DIR}/etc/udev/rules.d/70-persistent-net.rules
451 rm -f ${MOUNT_DIR}/lib/udev/write_net_rules
453 # Setup networking (eg: DHCP by default)
454 echo "# This file describes the network interfaces available on your system
455 # and how to activate them. For more information, see interfaces(5).
457 source /etc/network/interfaces.d/*
459 # The loopback network interface
461 iface lo inet loopback
467 # Maybe the VM has 2 NICs?
471 # Maybe the VM has 3 NICs?
474 " > ${MOUNT_DIR}/etc/network/interfaces
476 # FIXME: DHCP RFC3442 is used incorrect in Azure
477 sed -ie 's,rfc3442-classless-static-routes,disabled-\0,' $BODI_CHROOT_PATH/etc/dhcp/dhclient.conf
479 # Setup the default hostname (will be set by cloud-init
480 # at boot time anyway)
481 echo "debian.example.com" >${MOUNT_DIR}/etc/hostname
483 # This should be a correct default everywhere
484 echo "deb ${SOURCE_LIST_MIRROR} ${RELEASE} main
485 deb-src ${SOURCE_LIST_MIRROR} ${RELEASE} main" >${MOUNT_DIR}/etc/apt/sources.list
487 if [ "${RELEASE}" = "wheezy" ] || [ "${RELEASE}" = "jessie" ] ; then
488 echo "deb ${SOURCE_LIST_MIRROR} ${RELEASE}-updates main
489 deb-src ${SOURCE_LIST_MIRROR} ${RELEASE}-updates main
490 deb http://security.debian.org/ ${RELEASE}/updates main
491 deb-src http://security.debian.org/ ${RELEASE}/updates main
492 " >>${MOUNT_DIR}/etc/apt/sources.list
495 if [ "${RELEASE}" = "wheezy" ] ; then
496 echo "deb ${SOURCE_LIST_MIRROR} wheezy-backports main
497 deb-src ${SOURCE_LIST_MIRROR} wheezy-backports main
498 " >>${MOUNT_DIR}/etc/apt/sources.list
501 if [ "${RELEASE}" = "jessie" ] && [ "${AZURE}" = "yes" ] ; then
502 echo "deb ${SOURCE_LIST_MIRROR} jessie-backports main
503 deb-src ${SOURCE_LIST_MIRROR} jessie-backports main
504 deb ${SOURCE_LIST_MIRROR}-azure jessie-backports main
505 deb-src ${SOURCE_LIST_MIRROR}-azure jessie-backports main
506 " >>${MOUNT_DIR}/etc/apt/sources.list
509 if [ "${AZURE}" = "yes" ] ; then
510 chroot ${MOUNT_DIR} apt-key add - <<EOF
511 -----BEGIN PGP PUBLIC KEY BLOCK-----
514 mQENBFYWcbkBCADKvo4KT/ic3wb4AoNFtWvoS1Ae3NFcvM/6WR/n9BTsayOlnjDu
515 EFh7yH16nIhuO5pZFocY+32BWMEmiK6/0pkk1lB9+XfNB8yqDCJ/ItzADfuKQv6g
516 smfx4tLa1Vj+jUbrgiIG7MYTCPlpkSuPA+FgntlR4JBxOy2g4fqqp3of+xM8tfSN
517 4I7/g1989YU9EQN53c1HGLdsc5x5Y5Kezd46H4IK5oyri7BaG4zRzpJLYa4yxB2W
518 re+HXP0a5SN/zQq1oq8pvkPubEBPKhdypZzzoHWPkZqXh1pHsMMNRkwsLW/3iwzE
519 IjDKrbdILz3/b+iLLIvYo9RlTycRO0XeS/B3ABEBAAG0UkRlYmlhbiBmb3IgQXp1
520 cmUgQXJjaGl2ZSBBdXRvbWF0aWMgU2lnbmluZyBLZXkgKDgvamVzc2llKSA8bWlj
521 cm9zb2Z0QGNyZWRhdGl2LmNvbT6JAT4EEwECACgFAlYWcbkCGwMFCQPCZwAGCwkI
522 BwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEAbqSemobK1/2c8H/1j4HK/izt7aw7Kk
523 g+ChRDhltb4LiYTZNgHaBnLGkKewkA1vYIHQjdu/pVnJjh1JzvOBFV+rhJ4Cc60D
524 s4JDqkrl8LpA4jsLb/PW1bRtbW92mPfhWgjyWs6S2tRBsBy1m2+SLZKeaDUq/PCD
525 VnaClzDh2fQYimI8IQk5U/u8VHXtDm3qYQSq7dJMTTnDcBC1oCjEYN+uPm9M+tUI
526 ik2hIE4VmjIXYTQVTa1lD+qyJvZ9hCsBUxAGllFpcWlyexN5orer6c+30XY/0Y4i
527 Q+zzVPrp1s6MgM9F8ofgd2+MhL57fwyj2A+Tbyzm7xYhzPPMx/mopo4pi884+5lo
530 -----END PGP PUBLIC KEY BLOCK-----
534 chroot ${MOUNT_DIR} apt-get update
535 if [ "${AZURE}" = "yes" ] ; then
536 chroot ${MOUNT_DIR} apt-get install -y debian-azure-archive-keyring
537 chroot ${MOUNT_DIR} apt-get update
539 chroot ${MOUNT_DIR} apt-get upgrade -y
541 # Setup cloud-init, cloud-utils and cloud-initramfs-growroot
542 # These are only available from backports in Wheezy
543 if [ "${RELEASE}" = "wheezy" ] ; then
544 chroot ${MOUNT_DIR} apt-get -t wheezy-backports install cloud-init cloud-utils cloud-initramfs-growroot -y
545 cat > ${MOUNT_DIR}/etc/apt/preferences.d/linux.pref <<EOF
546 Package: linux-image-${ARCH} initramfs-tools
547 Pin: release n=wheezy-backports
552 chroot ${MOUNT_DIR} apt-get install -y linux-image-${ARCH}
554 if [ "${AZURE}" = "yes" ] ; then
555 echo "# to update this file, run dpkg-reconfigure cloud-init
556 datasource_list: [Azure]" >${MOUNT_DIR}/etc/cloud/cloud.cfg.d/90_dpkg.cfg
558 # For OpenStack, we would like to use Ec2 and no other API
559 echo "# to update this file, run dpkg-reconfigure cloud-init
560 datasource_list: [NoCloud, ConfigDrive, Openstack, Ec2]" >${MOUNT_DIR}/etc/cloud/cloud.cfg.d/90_dpkg.cfg
563 # Needed to have automatic mounts of /dev/vdb
564 echo "mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2']" >>${MOUNT_DIR}/etc/cloud/cloud.cfg
565 echo "manage_etc_hosts: true" >>${MOUNT_DIR}/etc/cloud/cloud.cfg
567 # Set the cloud init default user (required for the keypair to be put in the right home directory)
568 sed -i "s/name: debian/name: ${USER_LOGIN}/" ${MOUNT_DIR}/etc/cloud/cloud.cfg
570 if [ "${AZURE}" = "yes" ] ; then
571 unshare --pid --fork --mount-proc chroot ${MOUNT_DIR} apt-get install -y waagent
572 rm -f ${MOUNT_DIR}/var/log/waagent.log
575 # Setting-up initramfs
576 chroot ${MOUNT_DIR} update-initramfs -u
578 rm ${MOUNT_DIR}/var/cache/apt/archives/*.deb
580 # Set console for emergency and rescue shells
581 SYSTEMD_DIR="${MOUNT_DIR}/etc/systemd/system/"
582 for service in emergency.service rescue.service ; do
583 mkdir "${SYSTEMD_DIR}/${service}.d"
586 ExecStart=-/bin/sh -c "/sbin/sulogin /dev/tty0; /bin/systemctl --fail --no-block default"' > "${SYSTEMD_DIR}/${service}.d/console.conf"
589 ###################################
590 ### Setting-up extlinux or grub ###
591 ###################################
592 mkdir -p ${MOUNT_DIR}/boot/extlinux
593 if [ "${RELEASE}" = "wheezy" ] ; then
594 append="rootdelay=30"
596 KERNEL_PARAMS="biosdevname=0 net.ifnames=0 console=tty0 console=$CONSOLE,115200 earlyprintk=$CONSOLE,115200 consoleblank=0 systemd.show_status=true $append"
597 if [ "${BOOTMANAGER}" = "grub" ] ; then
598 sed -i -e 's|^[ #\t]*GRUB_CMDLINE_LINUX_DEFAULT[ #\t]*=.*|GRUB_CMDLINE_LINUX_DEFAULT="'"${KERNEL_PARAMS}"'"|' ${MOUNT_DIR}/etc/default/grub
600 # openstack-debian-images disables OS prober to avoid
601 # loopback detection which breaks booting
602 GRUB_DISABLE_OS_PROBER=true" >>${MOUNT_DIR}/etc/default/grub
603 # Tell grub about our loopback devices first
604 mkdir -p ${MOUNT_DIR}/boot/grub
605 mount --bind /dev ${MOUNT_DIR}/dev
606 mount --bind /proc ${MOUNT_DIR}/proc
607 mount --bind /sys ${MOUNT_DIR}/sys
608 echo "grub-efi-${ARCH} grub2/force_efi_extra_removable boolean true" | chroot ${MOUNT_DIR} debconf-set-selections
609 chroot ${MOUNT_DIR} grub-mkconfig -o /boot/grub/grub.cfg
610 # Run grub from the chroot, pointing to the bind mounted /dev device.
611 chroot ${MOUNT_DIR} grub-install --target=${GRUB_TARGET} --force-extra-removable --no-floppy --modules="part_msdos part_gpt" --grub-mkdevicemap=/boot/grub/device.map /dev/${LOOPRAW_DEVICE}
612 # Run grub from the host, pointing to the guest installation
613 #grub-install --no-floppy --modules=part_msdos --grub-mkdevicemap=${MOUNT_DIR}/boot/grub/device.map --root-directory=${MOUNT_DIR} /dev/${LOOPRAW_DEVICE}
614 umount ${MOUNT_DIR}/sys
615 umount ${MOUNT_DIR}/dev
616 umount ${MOUNT_DIR}/proc
618 KERNEL_PARAMS="initrd=/initrd.img root=UUID=${UUID} ${KERNEL_PARAMS} ro"
623 append ${KERNEL_PARAMS}" > ${MOUNT_DIR}/boot/extlinux/extlinux.conf
624 extlinux --install ${MOUNT_DIR}/boot/extlinux
630 if [ -x ${HOOK_SCRIPT} ] ; then
631 export BODI_CHROOT_PATH=${MOUNT_DIR}
632 export BODI_RELEASE=${RELEASE}
636 ##########################
637 ### Unmount everything ###
638 ##########################
641 # refine cleanup everything was ok
646 chroot ${MOUNT_DIR} umount /proc || true
647 chroot ${MOUNT_DIR} umount /sys || true
648 chroot ${MOUNT_DIR} umount /boot/efi || true
650 # Defrag the filesystem to allow for better size reduction below
651 e4defrag /dev/mapper/${LOOP_DEVICE} > /dev/null
654 # Run FSCK so that resize can work
655 fsck.ext4 -f /dev/mapper/${LOOP_DEVICE} || true
657 if [ "${AUTOMATIC_RESIZE}" = "yes" ] ; then
658 resize2fs -M /dev/mapper/${LOOP_DEVICE}
659 FS_BLOCKS=`tune2fs -l /dev/mapper/${LOOP_DEVICE} | awk '/Block count/{print $3}'`
660 WANTED_SIZE=`expr $FS_BLOCKS '*' 4 '/' 1024 + ${AUTOMATIC_RESIZE_SPACE}` # Add ${AUTOMATIC_RESIZE_SPACE}M
661 resize2fs /dev/mapper/${LOOP_DEVICE} ${WANTED_SIZE}M
662 FINAL_FS_BLOCKS=`tune2fs -l /dev/mapper/${LOOP_DEVICE} | awk '/Block count/{print $3}'`
666 kpartx -d ${RAW_NAME}
669 if [ "${AUTOMATIC_RESIZE}" = "yes" ] ; then
670 if [ "${BOOTTYPE}" = "mbr" ] ; then
671 # some blocks for mbr and multiple block size (4k)
672 FINAL_IMG_SIZE=`expr '(' $FINAL_FS_BLOCKS + 258 ')' '*' 4 '/' 1024`
673 # Rebuild a smaller partition table
674 ${PARTED} -s ${RAW_NAME} rm 1
675 ${PARTED} -s ${RAW_NAME} mkpart primary ext4 1Mi ${FINAL_IMG_SIZE}Mi
676 ${PARTED} -s ${RAW_NAME} set 1 boot on
677 # Add 2M for the 1M at the beginning of the partition and some additional space
678 truncate -s `expr 3 + ${FINAL_IMG_SIZE}`M ${RAW_NAME}
679 install-mbr ${RAW_NAME}
681 # Work out the sizes of the new image
682 # 1M for the GPT header, and alignment padding
684 # $FINAL_FS_BLOCKS for the root partition
685 FINAL_IMG_SIZE=$((1 + 100 + $((${FINAL_FS_BLOCKS} * 4 / 1024)) + 1))
686 # Rebuild a smaller partition table
687 ${PARTED} -s ${RAW_NAME} rm 2
688 ${PARTED} -s -a optimal ${RAW_NAME} -- mkpart ROOT ext4 102Mi -64s
690 truncate -s $((1 + ${FINAL_IMG_SIZE}))M ${RAW_NAME}
694 if ! [ "${AZURE}" = "yes" ] ; then
695 QEMU_VERSION=`qemu-img --help | head -n 1 | cut -d" " -f3 | cut -d"," -f1`
696 if dpkg --compare-versions ${QEMU_VERSION} gt 1.0 ; then
697 OTHER_QEMU_IMG_OPTIONS=" -o compat=0.10"
699 OTHER_QEMU_IMG_OPTIONS=""
702 qemu-img convert -c -f raw ${RAW_NAME}${OTHER_QEMU_IMG_OPTIONS} -O qcow2 ${QCOW2_NAME}