Force EFI grub installation on amd64 with uefi
[openstack-debian-images.git] / build-openstack-debian-image
1 #!/bin/sh
2 # Copyright:
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.
6
7 set -e
8
9 if [ "$UNSHARED" != true ] ; then
10         exec env UNSHARED=true unshare --mount --pid --fork --mount-proc "$0" "$@"
11 fi
12
13 LC_ALL=C
14 export LC_ALL
15
16 # Parse input parameters
17 usage() {
18         echo "Usage: $0 --release|-r <jessie|wheezy> [options]
19 Options are:
20  --minimal|-m
21  --azure|-az
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"
35         exit 1
36 }
37
38 EXTRA=yes
39 AZURE=no
40 BOOTMANAGER=grub
41 BOOTTYPE=mbr
42 ARCH=amd64
43 for i in $@ ; do
44         case "${1}" in
45         "--extra-packages"|"-e")
46                 if [ -z "${2}" ] ; then
47                         echo "No parameter defining the extra packages"
48                         usage
49                 fi
50                 EXTRA_PACKAGES=${2}
51                 shift
52                 shift
53         ;;
54         "--debootstrap-url"|"-u")
55                 if [ -z "${2}" ] ; then
56                         echo "No parameter defining the debootstrap URL"
57                         usage
58                 fi
59                 DEB_MIRROR=${2}
60                 shift
61                 shift
62         ;;
63         "--minimal"|"-m")
64                 EXTRA=no
65                 shift
66         ;;
67         "--azure"|"-az")
68                 AZURE=yes
69                 shift
70         ;;
71         "--boot-manager"|"-bm")
72                 if [ "${2}" != "grub" ] && [ "${2}" != "syslinux" ] ; then
73                         echo "No recognized parameter defining the boot manager"
74                         usage
75                 fi
76                 BOOTMANAGER=${2}
77                 shift
78                 shift
79         ;;
80         "--boot-type"|"-bt")
81                 if [ "${2}" != "mbr" ] && [ "${2}" != "uefi" ] ; then
82                         echo "No recognized parameter defining the boot type"
83                         usage
84                 fi
85                 BOOTTYPE=${2}
86                 shift
87                 shift
88         ;;
89         "--architecture"|"-a")
90                 if [ "${2}" != "amd64" ] && [ "${2}" != "arm64" ] ; then
91                         echo "No recognized parameter defining the architecture (currently support amd64 and arm64)"
92                         usage
93                 fi
94                 ARCH=${2}
95                 shift
96                 shift
97         ;;
98         "--automatic-resize"|"-ar")
99                 AUTOMATIC_RESIZE=yes
100                 shift
101         ;;
102         "--automatic-resize-space"|"-ars")
103                 if [ -z "${2}" ] ; then
104                         echo "No parameter defining the suplementary space"
105                         usage
106                 fi
107                 AUTOMATIC_RESIZE_SPACE=${2}
108                 shift
109                 shift
110         ;;
111         "--image-size"|"-is")
112                 if [ -z "${2}" ] ; then
113                         echo "No parameter defining the image size"
114                         usage
115                 fi
116                 IMAGE_SIZE=${2}
117                 shift
118                 shift
119         ;;
120         "--hook-script"|"-hs")
121                 if [ -z "${2}" ] ; then
122                         echo "No parameter defining the hook script"
123                         usage
124                 fi
125                 if ! [ -x "${2}" ] ; then
126                         echo "Hook script not executable"
127                 fi
128                 HOOK_SCRIPT=${2}
129                 shift
130                 shift
131         ;;
132         "--sources.list-mirror"|"-s")
133                 if [ -z "${2}" ] ; then
134                         echo "No parameter defining the hook script"
135                         usage
136                 fi
137                 SOURCE_LIST_MIRROR=${2}
138                 shift
139                 shift
140         ;;
141         "--release"|"-r")
142                 if [ "${2}" = "wheezy" ] || [ "${2}" = "jessie" ] || [ "${2}" = "stretch" ] || [ "${2}" = "buster" ] ; then
143                         RELEASE=${2}
144                         shift
145                         shift
146                 else
147                         echo "Release not recognized."
148                         usage
149                 fi
150         ;;
151         "--login"|"-l")
152                 if [ -z "${2}" ] ; then
153                         echo "No parameter defining the user login"
154                         usage
155                 fi
156                 USER_LOGIN=${2}
157                 shift
158                 shift
159         ;;
160         "--password"|"-p")
161                 if [ -z "${2}" ] ; then
162                         echo "No parameter defining the root password"
163                 fi
164                 ROOT_PASSWORD=${2}
165                 shift
166                 shift
167         ;;
168         "--output"|"-o")
169                 if [ -z "${2}" ] ; then
170                         echo "No output file specified"
171                 fi
172                 OUTPUT=${2}
173                 shift
174                 shift
175         ;;
176         *)
177         ;;
178         esac
179 done
180
181 if [ -z "${RELEASE}" ] ; then
182         echo "Release not recognized: please specify the -r parameter."
183         usage
184 fi
185 case "${RELEASE}" in
186         "wheezy")
187                 RELEASE_NUM=7
188         ;;
189         "jessie")
190                 RELEASE_NUM=8
191         ;;
192         "stretch")
193                 RELEASE_NUM=9
194         ;;
195         "buster")
196                 RELEASE_NUM=10
197         ;;
198 esac
199
200 if [ -z "${DEB_MIRROR}" ] ; then
201         DEB_MIRROR=http://httpredir.debian.org/debian
202 fi
203 if [ -z "${EXTRA_PACKAGES}" ] ; then
204         EXTRA_PACKAGES=bash-completion,joe,most,screen,less,vim,bzip2,nano
205 fi
206 if [ -z "${SOURCE_LIST_MIRROR}" ] ; then
207         SOURCE_LIST_MIRROR=http://httpredir.debian.org/debian
208 fi
209 if [ -z "${IMAGE_SIZE}" ] ; then
210         IMAGE_SIZE=2
211 fi
212 if [ -z "${AUTOMATIC_RESIZE_SPACE}" ] ; then
213         AUTOMATIC_RESIZE_SPACE=50
214 fi
215 if [ -z "${USER_LOGIN}" ] ; then
216         USER_LOGIN=debian
217 fi
218 if [ -z "${OUTPUT}" ] ; then
219         OUTPUT=debian-${RELEASE}-$(TZ=UTC date '+%Y%m%d%H%M')-${ARCH}
220 fi
221
222 if [ "${BOOTTYPE}" = "uefi" ] && [ "${BOOTMANAGER}" != "grub" ] ; then
223         echo "uefi boot type is only compatible with grub"
224         usage
225 fi
226
227 if [ "${ARCH}" = "arm64" ] ; then
228         if [ "${BOOTMANAGER}" != "grub" ] || [ "${BOOTTYPE}" != "uefi" ] ; then
229                 echo "arm64 depends on using grub and uefi"
230                 usage
231         fi
232 fi
233
234 CONSOLE=ttyS0
235 if [ "${ARCH}" = "arm64" ] ; then
236         CONSOLE=ttyAMA0
237 fi
238
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"
244                 else
245                         GRUB_TARGET="x86_64-efi"
246                 fi
247         else
248                 BOOT_MGR_PKG="grub-pc"
249                 GRUB_TARGET="i386-pc"
250         fi
251 else
252         BOOT_MGR_PKG="extlinux"
253 fi
254
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
261 else
262         NEEDED_PACKAGES=${NEEDED_PACKAGES},cloud-init,cloud-utils,cloud-initramfs-growroot,dbus,ntp,unscd
263 fi
264
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
268 fi
269
270 if [ ${EXTRA} = "no" ] ; then
271         PKG_LIST=${NEEDED_PACKAGES}
272 else
273         PKG_LIST=${NEEDED_PACKAGES},${EXTRA_PACKAGES}
274 fi
275 if ! [ `whoami` = "root" ] ; then
276         echo "You have to be root to run this script"
277         exit 1
278 fi
279 FILE_NAME=debian-${RELEASE}-${RELEASE_NUM}.0.0-1-${ARCH}
280 RAW_NAME=${OUTPUT}.raw
281 QCOW2_NAME=${OUTPUT}.qcow2
282 rm -f ${RAW_NAME}
283
284 set -x
285
286 ######################################
287 ### Prepare the HDD (format, ext.) ###
288 ######################################
289 PARTED=/sbin/parted
290 rm -f $RAW_NAME
291 qemu-img create ${RAW_NAME} ${IMAGE_SIZE}G
292
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}"
303         else
304                 echo "It seems kpartx didn't mount the image correctly: exiting."
305                 exit 1
306         fi
307 else # uefi
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}"
317         else
318                 echo "It seems kpartx didn't mount the image correctly: exiting."
319                 exit 1
320         fi
321         LOOP_DEVICE_ESP=$(kpartx -asv ${RAW_NAME} 2>&1 | head -1 | cut -d" " -f3)
322 fi
323
324 cleanup(){
325         error=$?
326         [ ! -d "${MOUNT_DIR}" ] && return
327         if [ "$error" -gt 0 ]; then
328                 echo
329                 echo "Error $error"
330         else
331                 echo "Finished."
332         fi
333
334         set +e
335
336         sync
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}
341         rmdir ${MOUNT_DIR}
342
343         kpartx -d ${RAW_NAME}
344         exit $error
345 }
346 trap "cleanup" EXIT TERM INT
347
348 mkfs.ext4 /dev/mapper/${LOOP_DEVICE}
349 UUID=$(blkid -o value -s UUID /dev/mapper/${LOOP_DEVICE})
350
351 # No fsck because of X days without checks
352 tune2fs -i 0 /dev/mapper/${LOOP_DEVICE}
353
354 MOUNT_DIR=`mktemp -d -t build-debimg.XXXXXX`
355
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
362 fi
363
364 debootstrap --verbose \
365         --include=${PKG_LIST} \
366         ${RELEASE} ${MOUNT_DIR} ${DEB_MIRROR}
367
368
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"
377 fi
378
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
383
384 ClientAliveInterval 120
385 EOF
386
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}
389
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
395
396 ### Customize: misc stuff ###
397 # # # # # # # # # # # # # # #
398 # Setup fstab
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
404 fi
405 mount -t proc proc ${MOUNT_DIR}/proc
406
407 echo "# disable pc speaker
408 blacklist pcspkr" >${MOUNT_DIR}/etc/modprobe.d/blacklist.conf
409
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
418   fi
419 fi" >>${MOUNT_DIR}/etc/bash.bashrc
420 fi
421
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
425 else
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
429         :
430 fi
431
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
435
436 # Turn off console blanking which is *very* annoying
437 # and increase KEYBOARD_DELAY because it can be annoying
438 # over network.
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
447 fi
448
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
452
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).
456
457 source /etc/network/interfaces.d/*
458
459 # The loopback network interface
460 auto lo
461 iface lo inet loopback
462
463 # The normal eth0
464 auto eth0
465 iface eth0 inet dhcp
466
467 # Maybe the VM has 2 NICs?
468 allow-hotplug eth1
469 iface eth1 inet dhcp
470
471 # Maybe the VM has 3 NICs?
472 allow-hotplug eth2
473 iface eth2 inet dhcp
474 " > ${MOUNT_DIR}/etc/network/interfaces
475
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
478
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
482
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
486
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
493 fi
494
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
499 fi
500
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
507 fi
508
509 if [ "${AZURE}" = "yes" ] ; then
510         chroot ${MOUNT_DIR} apt-key add - <<EOF
511 -----BEGIN PGP PUBLIC KEY BLOCK-----
512 Version: GnuPG v1
513
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
528 FY6A20E=
529 =X0jG
530 -----END PGP PUBLIC KEY BLOCK-----
531 EOF
532 fi
533
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
538 fi
539 chroot ${MOUNT_DIR} apt-get upgrade -y
540
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
548 Pin-Priority: 500
549 EOF
550 fi
551
552 chroot ${MOUNT_DIR} apt-get install -y linux-image-${ARCH}
553
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
557 else
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
561 fi
562
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
566
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
569
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
573 fi
574
575 # Setting-up initramfs
576 chroot ${MOUNT_DIR} update-initramfs -u
577
578 rm ${MOUNT_DIR}/var/cache/apt/archives/*.deb
579
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"
584         echo '[Service]
585 ExecStart=
586 ExecStart=-/bin/sh -c "/sbin/sulogin /dev/tty0; /bin/systemctl --fail --no-block default"' > "${SYSTEMD_DIR}/${service}.d/console.conf"
587 done
588
589 ###################################
590 ### Setting-up extlinux or grub ###
591 ###################################
592 mkdir -p ${MOUNT_DIR}/boot/extlinux 
593 if [ "${RELEASE}" = "wheezy" ] ; then
594         append="rootdelay=30"
595 fi
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
599         echo "
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
617 else
618         KERNEL_PARAMS="initrd=/initrd.img root=UUID=${UUID} ${KERNEL_PARAMS} ro"
619         echo "default linux
620 timeout 1
621 label linux
622 kernel /vmlinuz
623 append ${KERNEL_PARAMS}" > ${MOUNT_DIR}/boot/extlinux/extlinux.conf
624         extlinux --install ${MOUNT_DIR}/boot/extlinux
625 fi
626
627 ###################
628 ### HOOK SCRIPT ###
629 ###################
630 if [ -x ${HOOK_SCRIPT} ] ; then
631         export BODI_CHROOT_PATH=${MOUNT_DIR}
632         export BODI_RELEASE=${RELEASE}
633         ${HOOK_SCRIPT}
634 fi
635
636 ##########################
637 ### Unmount everything ###
638 ##########################
639
640 cleanup(){
641         # refine cleanup everything was ok
642         echo "Finished."
643
644
645 sync
646 chroot ${MOUNT_DIR} umount /proc || true
647 chroot ${MOUNT_DIR} umount /sys || true
648 chroot ${MOUNT_DIR} umount /boot/efi || true
649
650 # Defrag the filesystem to allow for better size reduction below
651 e4defrag /dev/mapper/${LOOP_DEVICE} > /dev/null
652 umount ${MOUNT_DIR}
653
654 # Run FSCK so that resize can work
655 fsck.ext4 -f /dev/mapper/${LOOP_DEVICE} || true
656
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}'` 
663 fi
664
665 sync
666 kpartx -d ${RAW_NAME}
667 rmdir ${MOUNT_DIR}
668
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}
680         else # uefi
681                 # Work out the sizes of the new image
682                 # 1M for the GPT header, and alignment padding
683                 # 100M for the ESP
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
689                 # Add 1M padding
690                 truncate -s $((1 + ${FINAL_IMG_SIZE}))M ${RAW_NAME}
691         fi
692 fi
693
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"
698         else
699                 OTHER_QEMU_IMG_OPTIONS=""
700         fi
701
702         qemu-img convert -c -f raw ${RAW_NAME}${OTHER_QEMU_IMG_OPTIONS} -O qcow2 ${QCOW2_NAME}
703 fi