~ubuntu-core-dev/livecd-rootfs/trunk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#!/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 $IMAGE_TARGETS in
	""|*vagrant*)
		;;
	*)
		echo "Skipping Vagrant image build"
		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

. 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.
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##*/}