|
|
|
CLOUD_IMG_STR="# CLOUD_IMG: This file was created/modified by the Cloud Image build process"
|
|
|
|
IMAGE_SIZE=$((2252*1024**2)) # 2.2G (the current size we ship)
|
|
|
|
|
|
|
|
rootfs_dev_mapper=
|
|
|
|
loop_device=
|
|
|
|
loop_raw=
|
|
|
|
|
|
|
|
clean_loops() {
|
|
|
|
[ -z "${rootfs_dev_mapper}" ] || {
|
|
|
|
udevadm settle
|
|
|
|
find /dev/mapper -iname "${loop_device///dev\//}*" | \
|
|
|
|
xargs -n1 -I DEVICE dmsetup remove DEVICE ||
|
|
|
|
kpartx -d "${rootfs_dev_mapper}"
|
|
|
|
losetup -d "${loop_device}" || echo "Failed to detach disk"
|
|
|
|
unset loop_raw
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
create_empty_disk_image() {
|
|
|
|
# Prepare an empty disk image
|
|
|
|
dd if=/dev/zero of="$1" bs=1 count=0 seek="${IMAGE_SIZE}"
|
|
|
|
}
|
|
|
|
|
|
|
|
make_ext4_partition() {
|
|
|
|
device="$1"
|
|
|
|
|
|
|
|
mkfs.ext4 -F -b 4096 -i 8192 -m 0 -L cloudimg-rootfs -E resize=536870912 "$device"
|
|
|
|
}
|
|
|
|
|
|
|
|
mount_image() {
|
|
|
|
apt-get install -qqy kpartx
|
|
|
|
trap clean_loops EXIT
|
|
|
|
loop_raw="$(kpartx -s -v -a "$1" )"
|
|
|
|
loop_device="$(echo -e "${loop_raw}" | head -n1 | awk '{print($(NF-1))}')"
|
|
|
|
rootfs_dev_mapper="/dev/mapper${loop_device///dev/}p1"
|
|
|
|
[ ! -b "${rootfs_dev_mapper}" ] &&
|
|
|
|
echo "${rootfs_dev_mapper} is not a block device" && exit 1
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
mount_partition() {
|
|
|
|
partition="$1"
|
|
|
|
mountpoint="$2"
|
|
|
|
|
|
|
|
mount "$partition" "$mountpoint"
|
|
|
|
mount --bind /dev "$mountpoint/dev"
|
|
|
|
mount proc-live -t proc "$mountpoint/proc"
|
|
|
|
mount sysfs-live -t sysfs "$mountpoint/sys"
|
|
|
|
mv "$mountpoint/etc/resolv.conf" resolv.conf.tmp
|
|
|
|
cp /etc/resolv.conf "$mountpoint/etc/resolv.conf"
|
|
|
|
}
|
|
|
|
|
|
|
|
umount_partition() {
|
|
|
|
mountpoint="$1"
|
|
|
|
|
|
|
|
mv resolv.conf.tmp "$mountpoint/etc/resolv.conf"
|
|
|
|
umount "$mountpoint/proc"
|
|
|
|
umount "$mountpoint/sys"
|
|
|
|
umount "$mountpoint/dev"
|
|
|
|
umount "$mountpoint"
|
|
|
|
}
|
|
|
|
|
|
|
|
modify_vmdk_header() {
|
|
|
|
# Modify the VMDK headers so that both VirtualBox _and_ VMware can
|
|
|
|
# read the vmdk and import them. The vodoo here is _not_ documented
|
|
|
|
# anywhere....so this will have to do. This is undocumented vodoo
|
|
|
|
# that has been learned by the Cloud Image team.
|
|
|
|
|
|
|
|
vmdk_name="${1}"
|
|
|
|
descriptor=$(mktemp)
|
|
|
|
newdescriptor=$(mktemp)
|
|
|
|
|
|
|
|
# Extract the vmdk header for manipulation
|
|
|
|
dd if="${vmdk_name}" of="${descriptor}" bs=1 skip=512 count=1024
|
|
|
|
|
|
|
|
# The sed lines below is where the magic is. Specifically:
|
|
|
|
# ddb.toolsVersion: sets the open-vm-tools so that VMware shows
|
|
|
|
# the tooling as current
|
|
|
|
# ddb.virtualHWVersion: set the version to 7, which covers most
|
|
|
|
# current versions of VMware
|
|
|
|
# createType: make sure its set to stream Optimized
|
|
|
|
# remove the vmdk-stream-converter comment and replace with
|
|
|
|
# # Disk DescriptorFile. This is needed for Virtualbox
|
|
|
|
# remove the comments from vmdk-stream-converter which causes
|
|
|
|
# VirtualBox and others to fail VMDK validation
|
|
|
|
|
|
|
|
sed -e 's|ddb.comment.*|ddb.toolsVersion = "2147483647"|' \
|
|
|
|
-e 's|ddb.virtualHWVersion.*|ddb.virtualHWVersion = "7"|' \
|
|
|
|
-e 's|createType.*|createType="streamOptimized"|' \
|
|
|
|
-e 's|# Description file.*|# Disk DescriptorFile|' \
|
|
|
|
-e '/# Believe.*/d' \
|
|
|
|
-e '/# Indicates no parent/d' \
|
|
|
|
"${descriptor}" > "${new_descriptor}"
|
|
|
|
|
|
|
|
# The header is cannot be bigger than 1024
|
|
|
|
expr $(stat --format=%s ${new_descriptor}) \< 1024 || {
|
|
|
|
echo "descriptor is too large, VMDK will be invalid!"; exit 1; }
|
|
|
|
|
|
|
|
# Overwrite the vmdk header with our new, modified one
|
|
|
|
dd conv=notrunc,nocreat \
|
|
|
|
if="${new_descriptor}" of="${vmdk_name}" \
|
|
|
|
bs=1 seek=512 count=1024
|
|
|
|
|
|
|
|
rm ${descriptor} ${new_descriptor}
|
|
|
|
}
|
|
|
|
|
|
|
|
create_vmdk() {
|
|
|
|
# There is no real good way to create a _compressed_ VMDK using open source
|
|
|
|
# tooling that works across multiple VMDK-capable platforms. Thie functions
|
|
|
|
# uses vmdk-stream-converter and then call modify_vmdk_header to produce a
|
|
|
|
# compatiable VMDK.
|
|
|
|
|
|
|
|
src="$1"
|
|
|
|
destination="$2"
|
|
|
|
size="${3:-102400}"
|
|
|
|
|
|
|
|
apt-get install -qqy qemu-utils vmdk-stream-converter
|
|
|
|
streamconverter="/usr/share/pyshared/VMDKstream.py"
|
|
|
|
scratch_d=$(mktemp -d)
|
|
|
|
|
|
|
|
cp ${src} ${scratch_d}/resize.img
|
|
|
|
qemu-img resize ${scratch_d}/resize.img ${size}M
|
|
|
|
python ${streamconverter} ${scratch_d}/resize.img "${destination}"
|
|
|
|
modify_vmdk_header "${destination}"
|
|
|
|
qemu-img info "${destination}"
|
|
|
|
|
|
|
|
rm -rf ${scratch_d}
|
|
|
|
}
|
|
|
|
|
|
|
|
|