packer: use latest VirtualBox Guest Additions ISO
[grml-debootstrap.git] / packer / debian64_provision.sh
1 #!/bin/bash
2
3 set -e
4 set -o pipefail
5 set -o errtrace
6 set -o functrace
7
8 # defaults
9 GRML_DEBOOTSTRAP='grml-debootstrap'
10 TARGET='/mnt'
11 INSTALL_TARGET='/dev/sda1'
12 GRUB_TARGET='/dev/sda'
13
14 ## validation / checks
15 [ -f /etc/grml_cd ] || { echo "File /etc/grml_cd doesn't exist, not executing script to avoid data loss." >&2 ; exit 1 ; }
16
17 if [ -z "$DEBIAN_VERSION" ] ; then
18   echo "* Error: DEBIAN_VERSION environment variable is undefined. Exiting." >&2
19   exit 1
20 fi
21
22 ## debugging
23 # if we notice an error then do NOT immediately return but provide
24 # user a chance to debug the VM
25 bailout() {
26   echo "* Noticed problem during execution (line ${1}, exit code ${2}), sleeping for 9999 seconds to provide debugging option"
27   sleep 9999
28   echo "* Finally exiting with return code 1"
29   exit "$2"
30 }
31 trap 'bailout ${LINENO} $?' ERR
32
33 ## helper functions
34 virtualbox_setup() {
35   case "$DEBIAN_VERSION" in
36     lenny)
37       echo "* Debian lenny doesn't support Virtualbox Guest Additions, skipping."
38       return 0
39       ;;
40   esac
41
42   if ! mountpoint "${TARGET}" &>/dev/null ; then
43     echo "* Mounting target system"
44     mount "${INSTALL_TARGET}" "${TARGET}"
45   fi
46
47   echo "* Installing packages for Virtualbox Guest Additions"
48   chroot ${TARGET} apt-get -y install make gcc dkms
49
50   echo "* Installing Virtualbox Guest Additions"
51   isofile="${HOME}/VBoxGuestAdditions.iso"
52
53   KERNELHEADERS=$(basename $(find $TARGET/usr/src/ -maxdepth 1 -name linux-headers\* ! -name \*common) | sort -u -r -V | head -1)
54   if [ -z "$KERNELHEADERS" ] ; then
55     echo "Error: no kernel headers found for building the VirtualBox Guest Additions kernel module." >&2
56     exit 1
57   fi
58
59   KERNELVERSION=${KERNELHEADERS##linux-headers-}
60   if [ -z "$KERNELVERSION" ] ; then
61     echo "Error: no kernel version could be identified." >&2
62     exit 1
63   fi
64
65   cp /tmp/fake-uname.so "${TARGET}/tmp/fake-uname.so"
66   mkdir -p "${TARGET}/media/cdrom"
67   mountpoint "${TARGET}/media/cdrom" >/dev/null && umount "${TARGET}/media/cdrom"
68   mount -t iso9660 $isofile "${TARGET}/media/cdrom/"
69   UTS_RELEASE=$KERNELVERSION LD_PRELOAD=/tmp/fake-uname.so grml-chroot "$TARGET" /media/cdrom/VBoxLinuxAdditions.run --nox11 || true
70   if grep -q "make: .*vboxguest.*Error 2" "${TARGET}/var/log/vboxadd-install.log" ; then
71     echo "Error: looks like a fatal error happened during installation of VirtualBox Guest Additions." >&2
72     exit 1
73   fi
74   [ -r "${TARGET}/var/log/VBoxGuestAdditions.log" ] && tail -10 "${TARGET}/var/log/VBoxGuestAdditions.log"
75   [ -r "${TARGET}/var/log/vboxadd-install.log" ]    && tail -10 "${TARGET}/var/log/vboxadd-install.log"
76   [ -r "${TARGET}/var/log/vboxadd-setup.log" ]      && tail -10 "${TARGET}/var/log/vboxadd-setup.log"
77   umount "${TARGET}/media/cdrom/"
78
79   # work around bug in VirtualBox 4.3.18 which leaves process behind,
80   # causing unmount of "$TARGET" to fail
81   grml-chroot "$TARGET" /etc/init.d/vboxadd-service stop || true
82   # left behind by VBoxService
83   umount "$TARGET"/dev || true
84
85   # work around regression in virtualbox-guest-additions-iso 4.3.10
86   if [ -d ${TARGET}/opt/VBoxGuestAdditions-4.3.10 ] ; then
87     ln -s /opt/VBoxGuestAdditions-4.3.10/lib/VBoxGuestAdditions ${TARGET}/usr/lib/VBoxGuestAdditions
88   fi
89
90   if mountpoint "${TARGET}" &>/dev/null ; then
91     echo "* Unmounting target system"
92     umount "${TARGET}"
93   fi
94 }
95
96 vagrant_setup() {
97   if ! mountpoint "${TARGET}" &>/dev/null ; then
98     echo "* Mounting target system"
99     mount "${INSTALL_TARGET}" "${TARGET}"
100   fi
101
102   echo "* Setting password for user root to 'vagrant'"
103   echo root:vagrant | chroot ${TARGET} chpasswd
104
105   echo "* Installing sudo package"
106   chroot ${TARGET} apt-get -y install sudo
107
108   echo "* Adding Vagrant user"
109   chroot ${TARGET} useradd -d /home/vagrant -m -u 1000 vagrant -s /bin/bash
110
111   echo "* Installing Vagrant ssh key"
112   mkdir -m 0700 -p ${TARGET}/home/vagrant/.ssh
113   echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" >> ${TARGET}/home/vagrant/.ssh/authorized_keys
114   chmod 0600 ${TARGET}/home/vagrant/.ssh/authorized_keys
115   chroot ${TARGET} chown vagrant:vagrant /home/vagrant/.ssh /home/vagrant/.ssh/authorized_keys
116
117   echo "* Setting up sudo configuration for user vagrant"
118   if ! [ -d "${TARGET}/etc/sudoers.d" ] ; then # lenny:
119     echo "vagrant ALL=(ALL) NOPASSWD: ALL" >> "${TARGET}/etc/sudoers"
120   else # wheezy and newer:
121     echo "vagrant ALL=(ALL) NOPASSWD: ALL" > "${TARGET}/etc/sudoers.d/vagrant"
122     chmod 0440 "${TARGET}/etc/sudoers.d/vagrant"
123   fi
124
125   host="$(cat ${TARGET}/etc/hostname)"
126   if ! grep -q "${host}$" "${TARGET}"/etc/hosts ; then
127     echo "* Setting up localhost entry for hostname $host in /etc/hosts"
128     cat >> "${TARGET}"/etc/hosts << EOF
129 # Added by grml-debootstrap/provision to make sure host is resolvable for sudo:
130 127.0.0.2 ${host}.local $host
131
132 EOF
133   fi
134
135   echo "* Setting up stdin/tty workaround in /root/.profile"
136   sed -i "s;^mesg n$;# modified via grml-debootstrap/provision script to work around stdin/tty issue:\ntty -s \&\& mesg n;g" "${TARGET}"/root/.profile
137
138   if [ -f ${TARGET}/etc/ssh/sshd_config ] && ! grep -q '^UseDNS' ${TARGET}/etc/ssh/sshd_config ; then
139     echo "* Disabling UseDNS in sshd config"
140     echo "UseDNS no" >> ${TARGET}/etc/ssh/sshd_config
141   fi
142
143   if mountpoint "${TARGET}" &>/dev/null ; then
144     echo "* Unmounting target system"
145     umount "${TARGET}"
146   fi
147 }
148
149 partition_setup() {
150   echo "* Executing automated partition setup"
151   cat > /tmp/partition_setup.txt << EOF
152 disk_config sda disklabel:msdos bootable:1
153 primary / 800M- ext4 rw
154 EOF
155
156   export LOGDIR='/tmp/setup-storage'
157   mkdir -p $LOGDIR
158
159   export disklist=$(/usr/lib/fai/fai-disk-info | sort)
160   PATH=/usr/lib/fai:${PATH} setup-storage -f /tmp/partition_setup.txt -X
161 }
162
163 sources_list_setup() {
164   # This is ugly because it's 'testing' no matter what ISO we're using, but otherwise we're running into
165   # W: Failed to fetch http://snapshot.debian.org/archive/debian/20141114/dists/testing/main/binary-amd64/Packages  404  Not Found [IP: 193.62.202.30 80]
166   echo "* Setting up /etc/apt/sources.list.d/debian.list to avoid snapshot.debian.org usage causing possible failures"
167   cat > /etc/apt/sources.list.d/debian.list << EOF
168 deb http://ftp.debian.org/debian testing main
169 EOF
170 }
171
172 grml_debootstrap_setup() {
173   echo "* grml-debootstrap setup"
174   if [ "$GRML_DEBOOTSTRAP_VERSION" = "latest" ] ; then
175     echo "** GRML_DEBOOTSTRAP_VERSION is set to '$GRML_DEBOOTSTRAP_VERSION'"
176     echo "** Setting up grml-debootstrap from CI repository from jenkins.grml.org"
177     cat > /etc/apt/sources.list.d/grml-debootstrap.list << EOF
178 deb     http://jenkins.grml.org/debian grml-debootstrap main
179 EOF
180     wget -O - http://jenkins.grml.org/debian/C525F56752D4A654.asc | apt-key add -
181     apt-get update
182     apt-get -y install grml-debootstrap
183   elif [ "$GRML_DEBOOTSTRAP_VERSION" = "stable" ] ; then
184     echo "** GRML_DEBOOTSTRAP_VERSION is set to '$GRML_DEBOOTSTRAP_VERSION'"
185     echo "** Using latest stable grml-debootstrap version"
186     apt-get update
187     apt-get -y install grml-debootstrap
188   elif [ "$GRML_DEBOOTSTRAP_VERSION" = "git" ] ; then
189     echo "** GRML_DEBOOTSTRAP_VERSION is set to '$GRML_DEBOOTSTRAP_VERSION'"
190     echo "** Using grml-debootstrap from Git repository"
191     git clone git://git.grml.org/grml-debootstrap.git
192     cd grml-debootstrap
193     GRML_DEBOOTSTRAP="CONFFILES=$(pwd) $(pwd)/grml-debootstrap"
194   elif [ "$GRML_DEBOOTSTRAP_VERSION" = "local" ] ; then
195     echo "** GRML_DEBOOTSTRAP_VERSION is set to '$GRML_DEBOOTSTRAP_VERSION'"
196     echo "** Using /tmp/grml-debootstrap derived from local system"
197     cd /tmp/grml-debootstrap
198     export CONFFILES=$(pwd)/etc/debootstrap
199     GRML_DEBOOTSTRAP="bash $(pwd)/usr/sbin/grml-debootstrap"
200   elif [ "$GRML_DEBOOTSTRAP_VERSION" = "iso" ] ; then
201     echo "** GRML_DEBOOTSTRAP_VERSION is set to '$GRML_DEBOOTSTRAP_VERSION'"
202     echo "** Using grml-debootstrap as provided on ISO"
203   fi
204 }
205
206 verify_debootstrap_version() {
207   local required_version=1.0.65
208   local present_version=$(dpkg-query --show --showformat='${Version}' debootstrap)
209
210   if dpkg --compare-versions $present_version lt $required_version ; then
211     echo "** debootstrap version $present_version is older than minimum required version $required_version - upgrading."
212     apt-get update
213     apt-get -y install debootstrap
214   fi
215 }
216
217 grml_debootstrap_execution() {
218   echo "* Installing Debian"
219
220   # release specific stuff
221   case "$DEBIAN_VERSION" in
222     lenny)
223       GRML_DEB_OPTIONS="--mirror http://archive.debian.org/debian/ --filesystem ext3"
224       ;;
225     stretch)
226       verify_debootstrap_version
227       ;;
228   esac
229
230   echo "** Executing: $GRML_DEBOOTSTRAP --hostname $DEBIAN_VERSION --release $DEBIAN_VERSION --target ${INSTALL_TARGET} --grub ${GRUB_TARGET} --password grml --force $GRML_DEB_OPTIONS" | tee -a /tmp/grml-debootstrap.log
231   $GRML_DEBOOTSTRAP --hostname "${DEBIAN_VERSION}" --release "${DEBIAN_VERSION}" --target "${INSTALL_TARGET}" --grub "${GRUB_TARGET}" --password grml --force $GRML_DEB_OPTIONS 2>&1 | tee -a /tmp/grml-debootstrap.log
232 }
233
234 apply_nic_workaround() {
235   # release specific stuff
236   case "$DEBIAN_VERSION" in
237     stretch|buster|bullseye|unstable|sid)
238       ;;
239     *)
240       echo "* Debian $DEBIAN_VERSION doesn't require NIC workaround"
241       return 0
242       ;;
243   esac
244
245   if ! mountpoint "${TARGET}" &>/dev/null ; then
246     echo "* Mounting target system"
247     mount "${INSTALL_TARGET}" "${TARGET}"
248   fi
249
250   echo "* Disabling predictable network interface names for Debian $DEBIAN_VERSION"
251   ln -s /dev/null "${TARGET}/etc/udev/rules.d/80-net-setup-link.rules"
252
253   echo "* Rebuilding initramfs to include udev configuration change"
254   chroot "${TARGET}" update-initramfs -u -k all
255 }
256
257 log_system_information() {
258   if ! mountpoint "${TARGET}" &>/dev/null ; then
259     echo "* Mounting target system"
260     mount "${INSTALL_TARGET}" "${TARGET}"
261   fi
262
263   local debian_version="$(cat ${TARGET}/etc/debian_version)"
264   echo "* Installed Debian version $debian_version"
265
266   echo "* Logging build information to /etc/grml_debootstrap.info"
267   echo "Debian $debian_version installed by grml-debootstrap/provision on $(date)" > ${TARGET}/etc/grml_debootstrap.info
268   $GRML_DEBOOTSTRAP --version | head -1 >> ${TARGET}/etc/grml_debootstrap.info || true
269
270   if mountpoint "${TARGET}" &>/dev/null ; then
271     echo "* Unmounting target system"
272     umount "${TARGET}"
273   fi
274 }
275
276 clean_apt_files() {
277   if ! mountpoint "${TARGET}" &>/dev/null ; then
278     echo "* Mounting target system"
279     mount "${INSTALL_TARGET}" "${TARGET}"
280   fi
281
282   echo "* Cleaning up apt stuff"
283   chroot ${TARGET} apt-get clean
284   rm -f ${TARGET}/var/lib/apt/lists/*Packages \
285     ${TARGET}/var/lib/apt/lists/*Release \
286     ${TARGET}/var/lib/apt/lists/*Sources \
287     ${TARGET}/var/lib/apt/lists/*Index* \
288     ${TARGET}/var/lib/apt/lists/*Translation* \
289     ${TARGET}/var/lib/apt/lists/*.gpg \
290     ${TARGET}/var/cache/apt-show-versions/* \
291     ${TARGET}/var/cache/debconf/*.dat-old \
292     ${TARGET}/var/cache/apt/*.bin \
293     ${TARGET}/var/lib/aptitude/pkgstates.old
294
295   if mountpoint "${TARGET}" &>/dev/null ; then
296     echo "* Unmounting target system"
297     umount "${TARGET}"
298   fi
299 }
300
301 automated_tests() {
302   echo "* Checking for bats"
303   if dpkg --list bats >/dev/null 2>&1 ; then
304     echo "* bats is already present, nothing to do."
305   else
306     echo "* Installing bats"
307     apt-get update
308     apt-get -y install bats
309   fi
310
311   echo "* Running tests to verify grml-debootstrap system"
312   bats /tmp/debian64.bats -t
313 }
314
315 ## main execution
316 sources_list_setup
317 partition_setup
318 grml_debootstrap_setup
319 grml_debootstrap_execution
320 virtualbox_setup
321 vagrant_setup
322 apply_nic_workaround
323 log_system_information
324 clean_apt_files
325 automated_tests
326
327 echo "* Finished execution of $0"