~ubuntu-on-ec2/vmbuilder/jenkins_kvm

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
#!/bin/bash

# Set default umask
umask 022

# Read in the common files
source "${kvm}/functions/common"
source "${kvm}/functions/retry"
source "${kvm}/functions/locker"
export HOME=${WORKSPACE}

# Apply the build stuff
[ -e "build_properties" ] &&
    source build_properties ||
    fail "Failed to read build_properties. I don't know what I'm doing!"

rm {failed,success} || /bin/true

# Copy the target disk image
ARCH_TYPE=${ARCH_TYPE:-$ARCH}
disk_orig="${SUITE}-server-cloudimg-${ARCH_TYPE}-disk1.img"
disk_cp="${disk_orig//$ARCH_TYPE/$ARCH_TYPE-vagrant}"
disk_root="${SRV_D:-/srv/ec2-images}/${SUITE}/${SERIAL:-current}"
disk_working="${WORKSPACE}/${disk_cp}"
final_disk="${WORKSPACE}/box-disk1.vdi"
final_location="${OUTPUT_D:-/srv/ec2-images}/vagrant/${SUITE}/${SERIAL}"
box_name="${disk_working//.img/.box}"
raw_f="${WORKSPACE}/raw_f-$(date +%s).img"

[ -e "${final_location}/${box_name}" -a "${REBUILD}" != "true" ] && exit 0

cp "${disk_root}/${disk_orig}" "${disk_working}" ||
    fail "Unable to copy ${disk_orig} from ${disk_root}"

# Resize it to 4G, but not the full 40G because we want it sparse
qemu-img resize ${disk_working} 4G

# Launch KVM to do the work
${kvm}/launch_kvm.sh \
        --id "${ARCH_TYPE}-${BUILD_ID}" \
        --user-data "${kvm}/config/cloud-vps.cfg" \
        --cloud-config "${kvm}/templates/img-vagrant.tmpl" \
        --extra-disk "${disk_working}" \
        --disk-gb 1 \
        --raw-disk "${raw_f}" \
        --raw-size 1 \
        --img-url /srv/builder/images/precise-builder-latest.img ||
            fail "KVM instance failed to build image."

# Covert to VMDK.
qemu-img convert -O raw ${disk_working} ${disk_working//.img/.raw}
truncate -s 40G ${disk_working//.img/.raw}

_vbox_cmd convertfromraw \
    --format vdi \
    ${disk_working//.img/.raw} ${final_disk}

# Create the VM
vmname="ubuntu-cloudimg-${SUITE}-vagrant-${ARCH_TYPE}"
_vbox_cmd modifyhd --compact ${final_disk}

dist_v="Ubuntu"
[ "${ARCH_TYPE}" = "amd64" ] && dist_v="Ubuntu_64"
_vbox_cmd createvm \
    --name ${vmname} \
    --ostype ${dist_v} \
    --register

_vbox_cmd modifyvm ${vmname} \
    --memory 512 \
    --boot1 disk \
    --boot2 none \
    --boot3 none \
    --boot4 none \
    --vram 12 \
    --pae off \
    --acpi on \
    --ioapic on \
    --rtcuseutc on
#    --natnet1 default \

if [ "${ARCH_TYPE}" = "i386" ]; then
    _vbox_cmd modifyvm ${vmname} \
        --ioapic off \
        --pae on
fi


_vbox_cmd modifyvm ${vmname} --natpf1 "guestssh,tcp,,2222,,22"

_vbox_cmd storagectl "${vmname}" \
    --name "SATAController" \
    --add sata \
    --controller IntelAhci \
    --sataportcount 1 \
    --hostiocache on

_vbox_cmd storageattach ${vmname} \
    --storagectl "SATAController" \
    --port 0 \
    --device 0 \
    --type hdd \
    --medium ${final_disk}

# Set extra-data
_vbox_cmd setextradata ${vmname} installdate ${serial}
_vbox_cmd setextradata ${vmname} supported false

# Set the Guest information to get rid of error message
[ -e vagrant_image.pkgs ] && {

    vbox_version=""
    while read -r line
    do
        line=( $(echo ${line}) )
        [[ ${line[0]} =~ virtualbox-guest-utils ]] && vbox_version=${line[1]}
    done < vagrant_image.pkgs
    debug "Guest Additions version is ${vbox_version}"

    # Set the revision to some arbitrary value
    _vbox_cmd guestproperty set ${vmname} \
        "/VirtualBox/GuestAdd/Revision" '8000'

    # Set the Ubuntu packaged version correctly
    _vbox_cmd guestproperty set ${vmname} \
        "/VirtualBox/GuestAdd/VersionExt" \
        "${vbox_version//-dfsg-*/_Ubuntu}"

    # Set the version string appropriately
    _vbox_cmd guestproperty set ${vmname} \
        "/VirtualBox/GuestAdd/Version" \
        "${vbox_version//-dfsg-*/}"
}

mkdir box
_vbox_cmd export ${vmname} --output box/box.ovf

# Create the Vagrant file
#macaddr="02:$(openssl rand -hex 5)"
macaddr=$(awk '-F"' '/<Adapter slot="0" enabled="true"/ {print$6}' ${WORKSPACE}/box/box.ovf)
cat << EOF > ${WORKSPACE}/box/Vagrantfile
Vagrant::Config.run do |config|
  # This Vagrantfile is auto-generated by 'vagrant package' to contain
  # the MAC address of the box. Custom configuration should be placed in
  # the actual 'Vagrantfile' in this box.
  config.vm.base_mac = "${macaddr}"
end

# Load include vagrant file if it exists after the auto-generated
# so it can override any of the settings
include_vagrantfile = File.expand_path("../include/_Vagrantfile", __FILE__)
load include_vagrantfile if File.exist?(include_vagrantfile)
EOF

# Now pack it all up....
tar -C ${WORKSPACE}/box -Scvf ${box_name} box.ovf Vagrantfile box-disk1.vmdk ||
        fail "Unable to create box file"

# Some minor cleanup
rm ${disk_working} ${disk_working//.img/.raw} || /bin/true
rm -rf ${WORKSPACE}/box *.vdi
rm "${raw_f}" || /bin/true

# Put the box in place
mkdir -p "${final_location}" ||
    fail "Unable to create the vagrant image location"

cp ${box_name} ${final_location} ||
    fail "Failed to place vagrant image in final home"

# box_d is where the boxes are stored
box_d="${OUTPUT_D:-/srv/ec2-images}/vagrant/${SUITE}"

# Only proceed if the required boxes exist
boxes=($(find ${box_d}/${SERIAL} -regextype posix-extended -regex ".*(amd64|i386)-vagrant-disk1.box"))
if [ "${#boxes[@]}" -ne 2 ]; then
    echo "Not updating current, required boxes are missing"
    [[ ! "${boxes[@]}" =~ "amd64" ]] && echo "Missing build for amd64"
    [[ ! "${boxes[@]}" =~ "i386" ]] && echo "Missing build for i386"

    # We don't want to fail here.
    exit 0
else
    echo "Updating current links; all builds are present"
fi

# Update the link to current
current_l="${box_d}/current"
[ -e "${current_l}" ] && rm "${current_l}"
( cd "${box_d}" && ln -s "${SERIAL}" current )

# Cleanup old builds
builds=($(find ${box_d} -mindepth 1 -maxdepth 1 -type d | sort -r))
build_count="${#builds[@]}"

echo "------------------------"
echo "Clean-up for prior builds"
echo "Found ${build_count} builds for consideration"

for b in ${builds[@]}
do
    echo " - found build ${b}"
done
echo ""

[ "${build_count}" -gt 4 ] && {
    for item in $(seq 4 ${build_count})
    do
        [ -e "${builds[$item]}" ] && {
            echo "Removing build ${builds[$item]} for deletion"
            rm -rf ${builds[$item]} ||
                echo "Failed to remove build ${builds[$item]}"
        }
    done

    for item in $(seq 0 3)
    do
        [ -e "${builds[$item]}" ] &&
            echo "Preserving build ${builds[$item]}"
    done

} || echo "No builds marked for removal"


# Override and set some home variables
export HOME="/srv/builder"
export CDIMAGE_BIN="${HOME}/cdimage/bin"
PUBLISH_SCRIPTS=${HOME}/ec2-publishing-scripts
export CDIMAGE_ROOT="${HOME}/cdimage"
export PATH="${PUBLISH_SCRIPTS}:${CDIMAGE_BIN}:${PATH}"
checksum-directory ${final_location}