mirror of
https://git.launchpad.net/livecd-rootfs
synced 2025-03-10 19:01:13 +00:00
* Replace "snap download" with tool that uses snap store's coherence feature This is important for parallel image builds to ensure all pre-seeded snaps have the same versions across image variants. * Inject a proxy into the build providing a snapshot view of the package repo. When the REPO_SNAPSHOT_STAMP variable is set, the auto/build script will attempt to launch a transparent HTTP proxy on port 8080, and insert an iptables rule to redirect all outgoing HTTP requests to this proxy. The proxy, contained in the `magic-proxy` Python script, examines each request and silently overrides those pointing to InRelease files or files that are listed in InRelease files. It will instead provide the contents of the requested file as it was at REPO_SNAPSHOT_STAMP, by downloading the corresponding asset "by hash". * Use series files with dependency handling to generate hook symlinks dynamically This patch currently only applies to the "ubuntu-cpc" project. More and more logic has been going into the hook scripts to decide under which conditions they should run or not. As we are moving to parallelized builds of image sets, this will get even more complicated. Base hooks will have to know which image sets they belong to and modification of the dependency chain between scripts will become more complicated and prone to errors, as the number of image sets grows. This patch introduces explicit ordering and dependency handling for scripts through the use of `series` files and an explicit syntax for dependency specification.
244 lines
7.8 KiB
Bash
Executable File
244 lines
7.8 KiB
Bash
Executable File
#!/bin/bash -ex
|
|
# vi: ts=4 noexpandtab
|
|
#
|
|
# Generate a generic Vagrant Box.
|
|
#
|
|
# Vagrant images are essentially nothing more than OVA's with extra-metadata
|
|
# and some preinstalled packages.
|
|
#
|
|
# We can't use the OVA's for Vagrant since Vagrant uses SSH to modify the
|
|
# instance. This build step creates a cloud-config ISO so that Cloud-Init
|
|
# will configure the initial user, creates meta-data that tells Vagrant how
|
|
# to interact with the cloud-init created users, and finally create the OVA.
|
|
#
|
|
# For this step, we make a deriviative of binary/boot/disk.ext4 and install
|
|
# some packages in it, convert it to a vmdk, and then assemble the vagrant
|
|
# box.
|
|
|
|
case ${SUBPROJECT:-} in
|
|
minimized)
|
|
echo "Skipping minimized $0 build as images won't boot with linux-kvm"
|
|
exit 0
|
|
;;
|
|
*)
|
|
;;
|
|
esac
|
|
|
|
cur_d=${PWD}
|
|
my_d=$(dirname $(readlink -f ${0}))
|
|
|
|
# Switch on $ARCH to determine which ID and description to use in the produced
|
|
# OVF. We have fancy Ubuntu-specific IDs in the OVF specification, we might as
|
|
# well use them.
|
|
case $ARCH in
|
|
amd64)
|
|
ovf_id=94
|
|
ovf_os_type="ubuntu64Guest"
|
|
ovf_desc_bits=64 ;;
|
|
i386)
|
|
ovf_id=93
|
|
ovf_os_type="ubuntu32Guest"
|
|
ovf_desc_bits=32 ;;
|
|
*)
|
|
echo "Vagrant images are not supported for $ARCH yet."
|
|
exit 0;;
|
|
esac
|
|
|
|
IMAGE_STR="# CLOUD_IMG: This file was created/modified by the Cloud Image build process"
|
|
|
|
. config/functions
|
|
|
|
# Lets be safe about this
|
|
box_d=$(mktemp -d)
|
|
seed_d=$(mktemp -d)
|
|
mount_d=$(mktemp -d)
|
|
|
|
create_derivative "disk" "vagrant" #sets ${derivative_img}
|
|
mount_disk_image ${derivative_img} ${mount_d}
|
|
|
|
cleanup_vagrant() {
|
|
if [ -d "$mount_d" ]; then
|
|
umount_disk_image "$mount_d"
|
|
fi
|
|
rm -rf ${box_d} ${seed_d} ${mount_d} ${derivative_img}
|
|
}
|
|
trap cleanup_vagrant EXIT
|
|
|
|
chroot ${mount_d} apt-get update
|
|
# virtualbox-guest-utils Recommends: virtualbox-guest-x11, which we want to
|
|
# avoid pulling into a cloud image.
|
|
chroot ${mount_d} apt-get install --no-install-recommends -y virtualbox-guest-utils
|
|
chroot ${mount_d} apt-get clean
|
|
|
|
# Create and setup users inside the image.
|
|
# Vagrant users expect a "vagrant" user with a "vagrant" username.
|
|
# See https://www.vagrantup.com/docs/boxes/base.html
|
|
# Note: We decided NOT to allow root login with a default password.
|
|
# --disabled-password and --gecos need to be passed to avoid adduser
|
|
# asking questions when running in an interactive shell
|
|
chroot ${mount_d} adduser vagrant --disabled-password --gecos ""
|
|
echo "vagrant:vagrant" | chroot ${mount_d} chpasswd
|
|
|
|
# The vagrant user should have passwordless sudo.
|
|
cat << EOF > ${mount_d}/etc/sudoers.d/vagrant
|
|
vagrant ALL=(ALL) NOPASSWD:ALL
|
|
EOF
|
|
|
|
# Add the insecure vagrant pubkey to the vagrant user, as is expected by the
|
|
# vagrant ecosystem (https://www.vagrantup.com/docs/boxes/base.html)
|
|
chroot ${mount_d} chmod 0440 /etc/sudoers.d/vagrant
|
|
chroot ${mount_d} mkdir -p /home/vagrant/.ssh
|
|
cat << EOF > ${mount_d}/home/vagrant/.ssh/authorized_keys
|
|
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key
|
|
EOF
|
|
chroot ${mount_d} chown -R vagrant:vagrant /home/vagrant/.ssh
|
|
chroot ${mount_d} chmod 700 /home/vagrant/.ssh
|
|
|
|
umount_disk_image "$mount_d"
|
|
rmdir "$mount_d"
|
|
|
|
# Used to identify bits
|
|
suite=$(chroot chroot lsb_release -c -s)
|
|
version=$(chroot chroot lsb_release --release --short)
|
|
distro=$(chroot chroot lsb_release --id --short | tr [:upper:] [:lower:])
|
|
|
|
# Get the VMDK in place
|
|
prefix="${distro}-${suite}-${version}-cloudimg"
|
|
vmdk_f="${box_d}/${prefix}.vmdk"
|
|
create_vmdk ${derivative_img} ${vmdk_f}
|
|
|
|
####################################
|
|
# Create the ConfigDrive
|
|
# This is a cloud-init piece that instructs cloud-init to configure
|
|
# a default user at first boot.
|
|
|
|
cdrom_vmdk_f="${box_d}/${prefix}-configdrive.vmdk"
|
|
|
|
# Create the user-data. This is totally insecure, but so is Vagrant. To
|
|
# mitigate this insecurity, the vagrant instance is not accessible
|
|
# except via local host.
|
|
cat > ${seed_d}/user-data <<END
|
|
#cloud-config
|
|
manage_etc_hosts: localhost
|
|
END
|
|
|
|
# Create the fake meta-data
|
|
cat > ${seed_d}/meta-data <<END
|
|
instance-id: iid-$(openssl rand -hex 8)
|
|
local-hostname: ubuntu-${suite}
|
|
END
|
|
|
|
# Pad the cdrom, otherwise the VMDK will be invalid
|
|
dd if=/dev/zero of=${seed_d}/bloat_file bs=1M count=10
|
|
|
|
# Create the ISO
|
|
genisoimage \
|
|
-output ${seed_d}/seed.iso \
|
|
-volid cidata \
|
|
-joliet -rock \
|
|
-input-charset utf-8 \
|
|
${seed_d}/user-data \
|
|
${seed_d}/meta-data
|
|
|
|
# Make a VMDK out of the seed file.
|
|
create_vmdk ${seed_d}/seed.iso ${cdrom_vmdk_f} 10
|
|
|
|
### END Create ConfigDrive
|
|
##########################
|
|
|
|
##########################
|
|
# VAGRANT meta-data
|
|
|
|
# Create the Vagrant file. This file is used by Vagrant to define how
|
|
# Vagrant uses Virtualbox and how Vagrant interacts with the host.
|
|
macaddr="02$(openssl rand -hex 5 | tr [:lower:] [:upper:])"
|
|
cat > ${box_d}/Vagrantfile <<EOF
|
|
# Front load the includes
|
|
include_vagrantfile = File.expand_path("../include/_Vagrantfile", __FILE__)
|
|
load include_vagrantfile if File.exist?(include_vagrantfile)
|
|
|
|
Vagrant.configure("2") do |config|
|
|
config.vm.base_mac = "${macaddr}"
|
|
|
|
config.vm.provider "virtualbox" do |vb|
|
|
vb.customize [ "modifyvm", :id, "--uart1", "0x3F8", "4" ]
|
|
vb.customize [ "modifyvm", :id, "--uartmode1", "file", File.join(Dir.pwd, "${prefix}-console.log") ]
|
|
end
|
|
end
|
|
EOF
|
|
|
|
# Tag it as a Virtualbox Vagrant
|
|
cat > ${box_d}/metadata.json <<EOF
|
|
{
|
|
"provider": "virtualbox"
|
|
}
|
|
EOF
|
|
|
|
# END
|
|
##########################
|
|
|
|
##########################
|
|
# Create the actual box
|
|
|
|
# Get information about the disks for the OVF
|
|
vmdk_size=$(du -b "${vmdk_f}" | cut -f1)
|
|
vmdk_capacity=$(qemu-img info "${vmdk_f}" | awk '-F[\( ]' '$1 ~ /virtual/ && $NF ~ /bytes.*/ {print$(NF-1)}')
|
|
vmdk_sha256=$(sha256sum ${vmdk_f} | cut -d' ' -f1)
|
|
|
|
cdrom_size=$(du -b "${cdrom_vmdk_f}" | cut -f1)
|
|
cdrom_capacity=$(qemu-img info "${cdrom_vmdk_f}" | awk '-F[\( ]' '$1 ~ /virtual/ && $NF ~ /bytes.*/ {print$(NF-1)}')
|
|
cdrom_sha256=$(sha256sum ${cdrom_vmdk_f} | cut -d' ' -f1)
|
|
|
|
# Populate the OVF template
|
|
ovf="${box_d}/box.ovf"
|
|
cp ${my_d}/ovf/ubuntu-ova-v1-cloudcfg-vmdk.tmpl ${ovf}
|
|
serial_stamp=$(date +%Y%m%d)
|
|
sed -i "${ovf}" \
|
|
-e "s/@@NAME@@/${prefix}-${serial_stamp}/g" \
|
|
-e "s/@@FILENAME1@@/${vmdk_f##*/}/g" \
|
|
-e "s/@@VMDK_FILE_SIZE@@/${vmdk_size}/g" \
|
|
-e "s/@@VMDK_CAPACITY@@/${vmdk_capacity}/g" \
|
|
-e "s/@@FILENAME2@@/${cdrom_vmdk_f##*/}/g" \
|
|
-e "s/@@VMDK_FILE_SIZE2@@/${cdrom_size}/g" \
|
|
-e "s/@@VMDK_CAPACITY2@@/${cdrom_capacity}/g" \
|
|
-e "s/@@NUM_CPUS@@/2/g" \
|
|
-e "s/@@VERSION@@/${version}/g" \
|
|
-e "s/@@DATE@@/${serial_stamp}/g" \
|
|
-e "s/@@MEM_SIZE@@/1024/g" \
|
|
-e "s/@@OVF_ID@@/${ovf_id}/g" \
|
|
-e "s/@@OVF_OS_TYPE@@/${ovf_os_type}/g" \
|
|
-e "s/@@OVF_DESC_BITS@@/${ovf_desc_bits}/g"
|
|
|
|
ovf_sha256=$(sha256sum ${ovf} | cut -d' ' -f1)
|
|
|
|
# Generate the manifest
|
|
manifest="${box_d}/${prefix}.mf"
|
|
cat > "${manifest}" <<EOF
|
|
SHA256(${vmdk_f##*/})= ${vmdk_sha256}
|
|
SHA256(${cdrom_vmdk_f##*/})= ${cdrom_sha256}
|
|
SHA256(${ovf##*/})= ${ovf_sha256}
|
|
EOF
|
|
|
|
# Now create the box
|
|
echo "Creating OVA with the following attributes:"
|
|
cat <<EOM
|
|
OVA information:
|
|
Name: ${prefix}
|
|
Size: ${vmdk_size}
|
|
VMDK Name: ${vmdk_f##*/}
|
|
VMDK Capacity: ${vmdk_capacity}
|
|
VMDK SHA256: ${vmdk_sha256}
|
|
CDROM Name: ${cdrom_vmdk_f##*/}
|
|
CDROM Capacity: ${cdrom_capacity}
|
|
CDROM SHA256: ${cdrom_sha256}
|
|
EOM
|
|
|
|
tar -C ${box_d} \
|
|
-cf ${cur_d}/livecd.ubuntu-cpc.vagrant.box \
|
|
box.ovf \
|
|
Vagrantfile \
|
|
metadata.json \
|
|
${prefix}.mf \
|
|
${vmdk_f##*/} \
|
|
${cdrom_vmdk_f##*/}
|