7 DEF_SIZE=${DEF_SIZE:-24M}
9 DEF_MODULES="acpiphp e1000 ne2k-pci 8139cp pcnet32 ip_tables"
11 error() { echo "$@" 1>&2; }
13 [ "${DEBUG}" -ge "${1}" ] || return 0;
17 fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
20 Usage: ${0##*/} rootfs.tar kpkg.deb output_dir
21 [re]Bundle a buildroot rootfs into a mini-cloud image
24 -s | --size S resize image to size (default: ${DEF_SIZE})
25 --arch A prepare for arch A
28 ${0##*/} rootfs.tar linux-image-*-virtuaal*.deb build-output/
31 bad_Usage() { Usage 1>&2; fail "$@"; }
33 [ -z "${UMOUNT}" ] || umount "${UMOUNT}"
34 [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
37 rsync --archive --xattrs --hard-links --acls --sparse "$@"
41 long_opts="arch:,initrd-busybox:,help,size:,verbose"
42 getopt_out=$(getopt --name "${0##*/}" \
43 --options "${short_opts}" --long "${long_opts}" -- "$@") &&
44 eval set -- "${getopt_out}" ||
47 topdir=$(cd "${0%/*}/.." && pwd)
49 FS_LABEL="cirros-rootfs"
53 while [ $# -ne 0 ]; do
56 -h|--help) Usage; exit 0;;
57 -s|--size) size=${next}; shift;;
58 --arch) arch=${next}; shift;;
59 -v|--verbose) DEBUG=$((${DEBUG}+1));;
65 [ $# -eq 3 ] || bad_Usage "must give rootfs.tar, kernel pkg, out_dir"
70 PATH="$topdir/bin:$PATH"
71 src_dir="${topdir}/src"
72 src_symlinks="${topdir}/symlinks.list"
73 makedevs_list="${topdir}/makedevs.list"
74 fixup_fs="${topdir}/fixup-fs"
75 xgrubd="$topdir/grubd"
77 [ "$(id -u)" = "0" ] || fail "sorry... must be root"
79 [ -d "${src_dir}" ] || fail "no source dir ${src_d}"
81 TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/.${0##*/}.XXXXXX") ||
82 fail "failed to make tempd"
85 mkdir -p "${out_d_in}" && out_d=$(readlink -f "${out_d_in}") &&
86 rootfs=$(readlink -f "${rootfs_in}") &&
87 kpkg=$(readlink -f "${kpkg_in}") ||
88 fail "failed to get full path for input"
90 out_partimg="${out_d}/part.img"
91 out_diskimg="${out_d}/disk.img"
92 out_kernel="${out_d}/kernel"
93 out_initramfs="${out_d}/initramfs"
94 out_diskimg="${out_d}/disk.img"
95 out_blankimg="${out_d}/blank.img"
96 out_filesys_lxc="${out_d}/filesys.tar.gz"
97 inter_d="$out_d/intermediate"
100 kernel_d="${TEMP_D}/kernel"
101 kern_list_full="${TEMP_D}/kernel.files.full"
102 kern_files="${TEMP_D}/kernel.files"
103 kern_modules="${TEMP_D}/kernel.files.modules"
104 overlay_d="${TEMP_D}/overlay"
105 initramfs_d="${TEMP_D}/initramfs"
106 initramfs="${TEMP_D}/initramfs.img"
107 stage_d="$TEMP_D/staging"
109 kernel_tar="$inter_d/kernel.tar"
110 overlay_tar="$inter_d/overlay.tar"
111 filesys_tar="$inter_d/filesys.tar"
113 modfile="$src_dir/etc/modules"
114 if [ -f "$modfile" ]; then
115 MODULES=$("$src_dir/etc/init.d/load-modules" parse_modules \
116 "$modfile" "$arch") ||
117 fail "failed to read modules"
118 MODULES=$(echo "$MODULES" | sed 's, .*,,' | tr '\n' ' ')
120 MODULES=${DEF_MODULES}
122 debug 1 "modules: $MODULES"
124 prepare-grub "$xgrubd" ||
125 fail "failed to get grub binary"
127 mkdir -p "${mp}" "${kernel_d}" "${overlay_d}" \
128 "${initramfs_d}" "$inter_d" "$stage_d" ||
129 fail "failed to make temp dirs"
131 debug 1 "creating filesystem in ${out_partimg}"
133 truncate "--size=${size}" "${out_partimg}" ||
134 fail "failed to create ${out_partimg} of size ${size}"
136 out=$("mkfs.${fs_type}" -F "${out_partimg}" -L "${FS_LABEL}" 2>&1) ||
137 fail "failed to make filesystem of type ${fs_type}: ${out}"
139 cp "$out_partimg" "$out_blankimg" ||
140 fail "failed to to copy blank partition image"
142 debug 1 "preparing kernel overlay"
143 # creating kernel tarball
144 dpkg -x "${kpkg_in}" "${kernel_d}" &&
145 ( cd "${kernel_d}" && find * -type f ) > "${kern_list_full}" ||
146 fail "failed to extract kernel to ${kernel_d}"
149 for x in "$kernel_d/lib/modules"/*; do
150 [ -d "$x/kernel" ] || continue
152 fail "2 or more things looked like kernels in lib/modules of $kpkg_in"
156 fail "failed to find kernel version. no lib/modules/* ?"
158 depmod -a --basedir "${kernel_d}" "${kver}" ||
159 fail "failed to run depmod"
161 mdep="${kernel_d}/lib/modules/${kver}/modules.dep"
162 for x in ${MODULES}; do
163 grep -q "/${x}.ko" "${mdep}" ||
164 { error "WARNING: no ${x} in kernel package!"; continue; }
167 printf("%s/%s\n",p,$1)
168 leng=split($0,deps," ")
169 x=2 # strange, but 0 contains nothing, 1 contains first field (with :)
171 printf("%s/%s\n", p, deps[x]);
174 }' mat="/${x}.ko$" p="lib/modules/${kver}" "${mdep}"
175 done > "${kern_modules}"
176 sort -u "${kern_modules}" > "${kern_files}"
177 vmlinuz=$( cd "${kernel_d}" && [ -f boot/vmlinu?-* ] &&
178 echo boot/vmlinu?-* ) && echo "${vmlinuz}" >> "${kern_files}" &&
179 ln -sf "$vmlinuz" "$kernel_d/vmlinuz" && echo "vmlinuz" >> "$kern_files" ||
180 fail "no kernel (boot/vmlinuz-*) found in ${kpkg_in}"
181 echo "boot/config-$kver" >> "$kern_files"
183 tar -C "${kernel_d}" -cpf - \
184 --files-from "${kern_files}" > "${kernel_tar}" ||
185 fail "failed to collect kernel files"
187 debug 1 "preparing source overlay from ${src_dir}"
188 xrsync "${src_dir}/" "${overlay_d}" ||
189 fail "failed to copy source dir"
191 chown -R 0:0 "${overlay_d}" || fail "failed to chown files in overlay"
193 if [ -f "${src_symlinks}" ]; then
194 ( cd "${overlay_d}" &&
195 while read src target; do
196 { [ -d "${target%/*}" ] || mkdir -p "${target%/*}"; } ||
197 { error "could not create ${target%/*}"; exit 1; }
198 ln -sf "${src}" "${target}" || exit 1
199 done < "${src_symlinks}"
200 ) || fail "failed to create symlinks"
202 if [ -f "${makedevs_list}" ]; then
203 xmakedevs "$makedevs_list" "$overlay_d" ||
204 fail "failed to makedevs on overlay"
207 ( cd "$overlay_d" && tar -cpf - * ) > "$overlay_tar" ||
208 fail "failed to make overlay_tar"
210 debug 1 "populating staging directory"
211 tar -C "$stage_d" -xpf - < "$rootfs_in" ||
212 fail "failed to extract rootfs_tar"
213 tar -C "$stage_d" -xpf - < "$overlay_tar" ||
214 fail "failed to extract overlay_tar"
216 if [ -x "${fixup_fs}" ]; then
217 "${fixup_fs}" "${stage_d}" ||
218 fail "failed to fixup filesystem"
221 ( cd "$stage_d" && tar -Scpzf - -- * ) > "$out_filesys_lxc" ||
222 fail "failed to create filesys tarball"
224 tar -C "$stage_d" -xpf - < "$kernel_tar" ||
225 fail "failed to extract kernel_tar"
226 tar -C "$stage_d" -xpf - < "$xgrubd/bootgrub.tar" ||
227 fail "failed to extract bootgrub"
229 depmod -a --basedir "$stage_d" "${kver}" ||
230 fail "failed to run depmod for kver ${kver} in output"
232 debug 1 "creating initramfs"
233 xrsync "$stage_d/" "$initramfs_d" ||
234 fail "failed to copy to initramfs_d"
235 rm -Rf "$initramfs_d/vmlinuz" "$initramfs_d/boot" ||
236 fail "failed to remove files in initramfs staging dir"
238 ( cd "$initramfs_d" && find . | cpio --quiet -o -H newc |
239 gzip -9 ) > "$initramfs"
241 rm -Rf "$initramfs_d/lib/modules/$kver" ||
242 fail "failed to remove lib/modules for mini initramfs"
244 ( cd "$initramfs_d" && find . | cpio --quiet -o -H newc |
245 gzip -9 ) > "${initramfs}.smaller"
247 cp "${initramfs}.smaller" "$stage_d/boot/initrd.img-${kver}" &&
248 ln -s "boot/initrd.img-${kver}" "${stage_d}/initrd.img" ||
249 fail "failed to copy initramfs to stage dir"
251 debug 1 "packing clean kernel_tar"
252 tar -C "$stage_d" -cpf - \
253 vmlinuz initrd.img boot/ lib/modules/ > "$kernel_tar" ||
254 fail "failed to create clean kerne_tar"
256 ( cd "$stage_d" && tar -cpf - * ) > "$filesys_tar" ||
257 fail "failed to create filesys_tar"
259 debug 1 "populating image"
260 mount -o loop "${out_partimg}" "${mp}" && UMOUNT=${mp} ||
261 fail "failed to mount ${out_partimg} loopback"
263 tar -C "$mp" -xpf - < "$filesys_tar" ||
264 fail "failed to populate mount point"
266 umount "${mp}" && UMOUNT="" ||
267 fail "failed to unmount ${out_partimg}"
269 cp "${kernel_d}/${vmlinuz}" "${out_kernel}" ||
270 fail "failed to copy kernel to ${out_kernel}"
272 { [ -z "${out_initramfs}" ] || cp "${initramfs}" "${out_initramfs}"; } ||
273 fail "failed to copy initramfs to ${out_initramfs}"
275 debug 1 "fixing grub entry in partimg"
276 tmp_part="$TEMP_D/part.img.disk"
277 cp "$out_partimg" "$tmp_part" &&
278 mount -o loop "$tmp_part" "$mp" && UMOUNT="$mp" ||
279 fail "failed to mount $tmp_part"
280 sed -i 's/(hd0)/(hd0,0)/' "$mp/boot/grub/menu.lst" ||
281 fail "failed to edit /boot/grub/menu.lst in image"
282 umount "$mp" && UMOUNT="" ||
283 fail "failed to unmount partimg"
285 debug 1 "creating disk image"
286 out=$(PATH=$xgrubd:$PATH part2disk --grub1 "$tmp_part" "$out_diskimg.raw" 2>&1) ||
287 fail "failed to create disk image: $out"
288 qemu-img convert -O qcow2 -c "$out_diskimg.raw" "$out_diskimg" ||
289 fail "failed to convert disk image"
290 rm -f "$out_diskimg.raw" "$tmp_part"
292 if [ -n "${SUDO_USER}" ]; then
294 g=$(id -g "${u}") || g=${u}
295 chown "${u}:${g}" -R "$out_d" ||
296 fail "failed to grant ownership of ${u}:${g} to ${u}:${g}"
299 echo "wrote ${out_partimg}"
300 echo "wrote ${out_diskimg}"
301 echo "wrote ${out_kernel}"
302 echo "wrote ${out_initramfs}"
303 echo "wrote ${out_blankimg}"
304 echo "wrote ${out_filesys_lxc}"