The cirros image was rebuilt against the 3.13.0-83 kernel, drivers e1000e, igbvf...
[packages/trusty/cirros-testvm.git] / cirros-testvm / src-cirros / bin / bundle
diff --git a/cirros-testvm/src-cirros/bin/bundle b/cirros-testvm/src-cirros/bin/bundle
new file mode 100755 (executable)
index 0000000..cf7fb2b
--- /dev/null
@@ -0,0 +1,306 @@
+#!/bin/bash
+# vi: ts=4 noexpandtab
+#
+
+TEMP_D=""
+UMOUNT=""
+DEF_SIZE=${DEF_SIZE:-24M}
+DEBUG=0
+DEF_MODULES="acpiphp e1000 ne2k-pci 8139cp pcnet32 ip_tables"
+
+error() { echo "$@" 1>&2; }
+debug() {
+       [ "${DEBUG}" -ge "${1}" ] || return 0;
+       shift;
+       error "$@"
+}
+fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
+Usage() {
+       cat <<EOF
+Usage: ${0##*/} rootfs.tar kpkg.deb output_dir
+   [re]Bundle a buildroot rootfs into a mini-cloud image
+
+   options:
+     -s | --size S            resize image to size (default: ${DEF_SIZE})
+          --arch A            prepare for arch A
+
+   Example:
+    ${0##*/} rootfs.tar linux-image-*-virtuaal*.deb build-output/
+EOF
+}
+bad_Usage() { Usage 1>&2; fail "$@"; }
+cleanup() {
+       [ -z "${UMOUNT}" ] || umount "${UMOUNT}"
+       [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
+}
+xrsync() {
+       rsync --archive --xattrs --hard-links --acls --sparse "$@"
+}
+
+short_opts="hs:v"
+long_opts="arch:,initrd-busybox:,help,size:,verbose"
+getopt_out=$(getopt --name "${0##*/}" \
+       --options "${short_opts}" --long "${long_opts}" -- "$@") &&
+       eval set -- "${getopt_out}" ||
+       bad_Usage
+
+topdir=$(cd "${0%/*}/.." && pwd)
+size=${DEF_SIZE}
+FS_LABEL="cirros-rootfs"
+fs_type="ext3"
+arch=""
+
+while [ $# -ne 0 ]; do
+       cur=${1}; next=${2};
+       case "$cur" in
+               -h|--help) Usage; exit 0;;
+               -s|--size) size=${next}; shift;;
+                  --arch) arch=${next}; shift;;
+               -v|--verbose) DEBUG=$((${DEBUG}+1));;
+               --) shift; break;;
+       esac
+       shift;
+done
+
+[ $# -eq 3 ] || bad_Usage "must give rootfs.tar, kernel pkg, out_dir"
+rootfs_in=${1}
+kpkg_in=${2}
+out_d_in=${3}
+
+PATH="$topdir/bin:$PATH"
+src_dir="${topdir}/src"
+src_symlinks="${topdir}/symlinks.list"
+makedevs_list="${topdir}/makedevs.list"
+fixup_fs="${topdir}/fixup-fs"
+xgrubd="$topdir/grubd"
+
+[ "$(id -u)" = "0" ] || fail "sorry... must be root"
+
+[ -d "${src_dir}" ] || fail "no source dir ${src_d}"
+
+TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/.${0##*/}.XXXXXX") ||
+       fail "failed to make tempd"
+trap cleanup EXIT
+
+mkdir -p "${out_d_in}" && out_d=$(readlink -f "${out_d_in}") &&
+       rootfs=$(readlink -f "${rootfs_in}") &&
+       kpkg=$(readlink -f "${kpkg_in}") ||
+       fail "failed to get full path for input"
+
+out_partimg="${out_d}/part.img"
+out_diskimg="${out_d}/disk.img"
+out_kernel="${out_d}/kernel"
+out_initramfs="${out_d}/initramfs"
+out_diskimg="${out_d}/disk.img"
+out_blankimg="${out_d}/blank.img"
+out_filesys_lxc="${out_d}/filesys.tar.gz"
+inter_d="$out_d/intermediate"
+
+mp="${TEMP_D}/mnt"
+kernel_d="${TEMP_D}/kernel"
+kern_list_full="${TEMP_D}/kernel.files.full"
+kern_files="${TEMP_D}/kernel.files"
+kern_modules="${TEMP_D}/kernel.files.modules"
+overlay_d="${TEMP_D}/overlay"
+initramfs_d="${TEMP_D}/initramfs"
+initramfs="${TEMP_D}/initramfs.img"
+stage_d="$TEMP_D/staging"
+
+kernel_tar="$inter_d/kernel.tar"
+overlay_tar="$inter_d/overlay.tar"
+filesys_tar="$inter_d/filesys.tar"
+
+modfile="$src_dir/etc/modules"
+if [ -f "$modfile" ]; then
+       MODULES=$("$src_dir/etc/init.d/load-modules" parse_modules \
+        "$modfile" "$arch") ||
+               fail "failed to read modules"
+       MODULES=$(echo "$MODULES" | sed 's, .*,,' | tr '\n' ' ')
+else
+       MODULES=${DEF_MODULES}
+fi
+debug 1 "modules: $MODULES"
+
+prepare-grub "$xgrubd" ||
+       fail "failed to get grub binary"
+
+mkdir -p "${mp}" "${kernel_d}" "${overlay_d}" \
+       "${initramfs_d}" "$inter_d" "$stage_d" ||
+       fail "failed to make temp dirs"
+
+debug 1 "creating filesystem in ${out_partimg}"
+rm -f "$out_partimg"
+truncate "--size=${size}" "${out_partimg}" ||
+       fail "failed to create ${out_partimg} of size ${size}"
+
+out=$("mkfs.${fs_type}" -F "${out_partimg}" -L "${FS_LABEL}" 2>&1) ||
+       fail "failed to make filesystem of type ${fs_type}: ${out}" 
+
+cp "$out_partimg" "$out_blankimg" ||
+       fail "failed to to copy blank partition image"
+
+debug 1 "preparing kernel overlay"
+# creating kernel tarball
+dpkg -x "${kpkg_in}" "${kernel_d}" &&
+       ( cd "${kernel_d}" && find * -type f ) > "${kern_list_full}" ||
+       fail "failed to extract kernel to ${kernel_d}"
+
+kver=""
+for x in "$kernel_d/lib/modules"/*; do
+       [ -d "$x/kernel" ] || continue
+       [ -z "$kver" ] ||
+               fail "2 or more things looked like kernels in lib/modules of $kpkg_in"
+       kver="${x##*/}"
+done
+[ -n "$kver" ] ||
+       fail "failed to find kernel version. no lib/modules/* ?"
+
+depmod -a --basedir "${kernel_d}" "${kver}" ||
+       fail "failed to run depmod"
+
+mdep="${kernel_d}/lib/modules/${kver}/modules.dep"
+for x in ${MODULES}; do
+       grep -q "/${x}.ko" "${mdep}" ||
+               { error "WARNING: no ${x} in kernel package!"; continue; }
+       awk -F: '$1 ~ mat {
+               sub(":","",$1)
+               printf("%s/%s\n",p,$1)
+               leng=split($0,deps," ")
+               x=2 # strange, but 0 contains nothing, 1 contains first field (with :)
+               while ( x<=leng ) {
+                       printf("%s/%s\n", p, deps[x]);
+                       x++
+               }
+       }' mat="/${x}.ko$" p="lib/modules/${kver}" "${mdep}"
+done > "${kern_modules}"
+sort -u "${kern_modules}" > "${kern_files}"
+vmlinuz=$( cd "${kernel_d}" && [ -f boot/vmlinu?-* ] &&
+       echo boot/vmlinu?-* ) && echo "${vmlinuz}" >> "${kern_files}" &&
+       ln -sf "$vmlinuz" "$kernel_d/vmlinuz" && echo "vmlinuz" >> "$kern_files" ||
+       fail "no kernel (boot/vmlinuz-*) found in ${kpkg_in}"
+echo "boot/config-$kver" >> "$kern_files"
+
+tar -C "${kernel_d}" -cpf - \
+       --files-from "${kern_files}" > "${kernel_tar}" ||
+       fail "failed to collect kernel files"
+
+debug 1 "preparing source overlay from ${src_dir}"
+xrsync "${src_dir}/" "${overlay_d}" ||
+       fail "failed to copy source dir"
+
+chown -R 0:0 "${overlay_d}" || fail "failed to chown files in overlay"
+       
+if [ -f "${src_symlinks}" ]; then
+       ( cd "${overlay_d}" &&
+               while read src target; do
+                       { [ -d "${target%/*}" ] || mkdir -p "${target%/*}"; } ||
+                               { error "could not create ${target%/*}"; exit 1; }
+                       ln -sf "${src}" "${target}" || exit 1
+               done < "${src_symlinks}"
+       ) || fail "failed to create symlinks"
+fi
+if [ -f "${makedevs_list}" ]; then
+       xmakedevs "$makedevs_list" "$overlay_d" ||
+               fail "failed to makedevs on overlay"
+fi
+
+( cd "$overlay_d" && tar -cpf - * ) > "$overlay_tar" ||
+       fail "failed to make overlay_tar"
+
+debug 1 "populating staging directory"
+tar -C "$stage_d" -xpf - < "$rootfs_in" ||
+       fail "failed to extract rootfs_tar"
+tar -C "$stage_d" -xpf - < "$overlay_tar" ||
+       fail "failed to extract overlay_tar"
+
+if [ -x "${fixup_fs}" ]; then
+       "${fixup_fs}" "${stage_d}" ||
+               fail "failed to fixup filesystem"
+fi
+
+( cd "$stage_d" && tar -Scpzf - -- * ) > "$out_filesys_lxc" ||
+       fail "failed to create filesys tarball"
+
+tar -C "$stage_d" -xpf - < "$kernel_tar" ||
+       fail "failed to extract kernel_tar"
+tar -C "$stage_d" -xpf - < "$xgrubd/bootgrub.tar" ||
+       fail "failed to extract bootgrub"
+
+depmod -a --basedir "$stage_d" "${kver}" ||
+       fail "failed to run depmod for kver ${kver} in output"
+
+debug 1 "creating initramfs"
+xrsync "$stage_d/" "$initramfs_d" ||
+       fail "failed to copy to initramfs_d"
+rm -Rf "$initramfs_d/vmlinuz" "$initramfs_d/boot" ||
+       fail "failed to remove files in initramfs staging dir"
+
+( cd "$initramfs_d" && find . | cpio --quiet -o -H newc |
+       gzip -9 ) > "$initramfs"
+
+rm -Rf "$initramfs_d/lib/modules/$kver" ||
+       fail "failed to remove lib/modules for mini initramfs"
+
+( cd "$initramfs_d" && find . | cpio --quiet -o -H newc |
+       gzip -9 ) > "${initramfs}.smaller"
+
+cp "${initramfs}.smaller" "$stage_d/boot/initrd.img-${kver}" &&
+       ln -s "boot/initrd.img-${kver}" "${stage_d}/initrd.img" ||
+       fail "failed to copy initramfs to stage dir"
+
+debug 1 "packing clean kernel_tar"
+tar -C "$stage_d" -cpf - \
+       vmlinuz initrd.img boot/ lib/modules/ > "$kernel_tar" ||
+       fail "failed to create clean kerne_tar"
+
+( cd "$stage_d" && tar -cpf - * ) > "$filesys_tar" ||
+       fail "failed to create filesys_tar"
+
+debug 1 "populating image"
+mount -o loop "${out_partimg}" "${mp}" && UMOUNT=${mp} ||
+       fail "failed to mount ${out_partimg} loopback"
+
+tar -C "$mp" -xpf - < "$filesys_tar" ||
+       fail "failed to populate mount point"
+
+umount "${mp}" && UMOUNT="" ||
+       fail "failed to unmount ${out_partimg}"
+
+cp "${kernel_d}/${vmlinuz}" "${out_kernel}" ||
+       fail "failed to copy kernel to ${out_kernel}"
+
+{ [ -z "${out_initramfs}" ] || cp "${initramfs}" "${out_initramfs}"; }  ||
+       fail "failed to copy initramfs to ${out_initramfs}"
+
+debug 1 "fixing grub entry in partimg"
+tmp_part="$TEMP_D/part.img.disk"
+cp "$out_partimg" "$tmp_part" &&
+       mount -o loop "$tmp_part" "$mp" && UMOUNT="$mp" ||
+       fail "failed to mount $tmp_part"
+sed -i 's/(hd0)/(hd0,0)/' "$mp/boot/grub/menu.lst" ||
+       fail "failed to edit /boot/grub/menu.lst in image"
+umount "$mp" && UMOUNT="" ||
+       fail "failed to unmount partimg"
+
+debug 1 "creating disk image"
+out=$(PATH=$xgrubd:$PATH part2disk --grub1 "$tmp_part" "$out_diskimg.raw" 2>&1) ||
+       fail "failed to create disk image: $out"
+qemu-img convert -O qcow2 -c "$out_diskimg.raw" "$out_diskimg" ||
+       fail "failed to convert disk image"
+rm -f "$out_diskimg.raw" "$tmp_part"
+
+if [ -n "${SUDO_USER}" ]; then
+       u=${SUDO_USER}
+       g=$(id -g "${u}") || g=${u}
+       chown "${u}:${g}" -R "$out_d" ||
+               fail "failed to grant ownership of ${u}:${g} to ${u}:${g}"
+fi
+
+echo "wrote ${out_partimg}"
+echo "wrote ${out_diskimg}"
+echo "wrote ${out_kernel}"
+echo "wrote ${out_initramfs}"
+echo "wrote ${out_blankimg}"
+echo "wrote ${out_filesys_lxc}"
+
+exit 0