Project

General

Profile

Download (13.9 KB) Statistics
| Branch: | Tag: | Revision:
1
#!/bin/sh
2
#
3
# build_snapshots.sh
4
#
5
# Copyright (c) 2007-2015 Electric Sheep Fencing, LLC
6
# All rights reserved
7
#
8
# Redistribution and use in source and binary forms, with or without
9
# modification, are permitted provided that the following conditions
10
# are met:
11
#
12
# 1. Redistributions of source code must retain the above copyright
13
#    notice, this list of conditions and the following disclaimer.
14
#
15
# 2. Redistributions in binary form must reproduce the above copyright
16
#    notice, this list of conditions and the following disclaimer in the
17
#    documentation and/or other materials provided with the distribution.
18
#
19
# THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
20
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
23
# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30
# OF THE POSSIBILITY OF SUCH DAMAGE.
31
#
32

    
33
export BUILDER_TOOLS=$(realpath $(dirname ${0}))
34
export BUILDER_ROOT=$(realpath "${BUILDER_TOOLS}/..")
35

    
36
NO_UPLOAD=""
37
LOOPED_SNAPSHOTS=""
38

    
39
# Handle command line arguments
40
while test "$1" != "" ; do
41
	case $1 in
42
	--noupload|-u)
43
		NO_UPLOAD="-u"
44
		;;
45
	--looped)
46
		LOOPED_SNAPSHOTS="true"
47
	esac
48
	shift
49
done
50

    
51
# Source ${PRODUCT_NAME} / FreeSBIE variables
52
# *** DO NOT SOURCE BUILDER_COMMON.SH!
53
# *** IT WILL BREAK EVERYTHING FOR 
54
# *** SOME UNKNOWN LAYERING REASON.
55
# *** 04/07/2008, 11/04/2009                      
56
echo ">>> Execing build.conf"
57
. ${BUILDER_TOOLS}/builder_defaults.sh
58

    
59
if [ -z "${RSYNCIP}" -a -z "${NO_UPLOAD}" ]; then
60
	echo ">>> ERROR: RSYNCIP is not defined"
61
	exit 1
62
fi
63

    
64
if [ -z "${RSYNCUSER}" -a -z "${NO_UPLOAD}" ]; then
65
	echo ">>> ERROR: RSYNCUSER is not defined"
66
	exit 1
67
fi
68

    
69
if [ -z "${RSYNCPATH}" -a -z "${NO_UPLOAD}" ]; then
70
	echo ">>> ERROR: RSYNCPATH is not defined"
71
	exit 1
72
fi
73

    
74
if [ -z "${RSYNCLOGS}" -a -z "${NO_UPLOAD}" ]; then
75
	echo ">>> ERROR: RSYNCLOGS is not defined"
76
	exit 1
77
fi
78

    
79
# Keeps track of how many time builder has looped
80
BUILDCOUNTER=0
81

    
82
# Local variables that are used by builder scripts
83
STAGINGAREA=${SCRATCHDIR}/staging
84
RSYNCKBYTELIMIT="248000"
85

    
86
export SNAPSHOTSLOGFILE=${SNAPSHOTSLOGFILE:-"$SCRATCHDIR/snapshots-build.log"}
87
export SNAPSHOTSLASTUPDATE=${SNAPSHOTSLASTUPDATE:-"$SCRATCHDIR/snapshots-lastupdate.log"}
88

    
89
# Ensure directories exist
90
mkdir -p $STAGINGAREA
91

    
92
echo "" > $SNAPSHOTSLOGFILE
93
echo "" > $SNAPSHOTSLASTUPDATE
94

    
95
git_last_commit() {
96
	if [ -d "${1}/.git" ]; then
97
		git -C "${1}" pull -q
98
		git -C "${1}" log -1 --format='%H'
99
	fi
100
}
101

    
102
# This routine is called in between runs. We
103
# will sleep for a bit and check for new commits
104
# in between sleeping for short durations.
105
sleep_between_runs() {
106
	COUNTER=0
107
	while [ $COUNTER -lt $maxsleepvalue ]; do
108
		sleep 60
109
		CURRENT_COMMIT=$(git_last_commit "${BUILDER_ROOT}")
110
		if [ "${LAST_COMMIT}" != "${CURRENT_COMMIT}" ]; then
111
			update_status ">>> New commit: $CURRENT_AUTHOR - $CURRENT_COMMIT .. No longer sleepy."
112
			COUNTER=$(($maxsleepvalue + 60))
113
			export LAST_COMMIT="${CURRENT_COMMIT}"
114
		fi
115
		COUNTER=$(($COUNTER + 60))
116
	done
117
	if [ $COUNTER -ge $maxsleepvalue ]; then
118
		update_status ">>> Sleep timer expired. Restarting build."
119
		maxsleepvalue=0
120
		COUNTER=0
121
	fi
122
}
123

    
124
# This routine is called to write out to stdout
125
# a string. The string is appended to $SNAPSHOTSLOGFILE
126
# and we scp the log file to the builder host if
127
# needed for the real time logging functions.
128
update_status() {
129
	if [ "$1" = "" ]; then
130
		return
131
	fi
132
	echo $1
133
	echo "`date` -|- $1" >> $SNAPSHOTSLOGFILE
134
	if [ -z "${NO_UPLOAD}" ]; then
135
		LU=`cat $SNAPSHOTSLASTUPDATE`
136
		CT=`date "+%H%M%S"`
137
		# Only update every minute
138
		if [ "$LU" != "$CT" ]; then 
139
			ssh ${RSYNCUSER}@${RSYNCIP} "mkdir -p ${RSYNCLOGS}"
140
			scp -q $SNAPSHOTSLOGFILE ${RSYNCUSER}@${RSYNCIP}:${RSYNC_LOGS}/build.log
141
			date "+%H%M%S" > $SNAPSHOTSLASTUPDATE
142
		fi
143
	fi
144
}
145

    
146
# Copy the current log file to $filename.old on
147
# the snapshot www server (real time logs)
148
rotate_logfile() {
149
	if [ -n "$MASTER_BUILDER_SSH_LOG_DEST" -a -z "${NO_UPLOAD}" ]; then
150
		scp -q $SNAPSHOTSLOGFILE ${RSYNCUSER}@${RSYNCIP}:${RSYNC_LOGS}/build.log.old
151
	fi
152

    
153
	# Cleanup log file
154
	echo "" > $SNAPSHOTSLOGFILE
155
}
156

    
157
dobuilds() {
158
	# Build images
159
	(cd ${BUILDER_ROOT} && ./build.sh --flash-size '1g 2g 4g' "iso memstick memstickserial memstickadi fullupdate nanobsd nanobsd-vga")
160
	# Copy files
161
	copy_to_staging_iso_updates
162
	copy_to_staging_nanobsd '1g 2g 4g'
163
}
164

    
165
copy_to_staging_nanobsd() {
166
	for NANOTYPE in nanobsd nanobsd-vga; do
167
		for FILESIZE in ${1}; do
168
			FILENAMEFULL="${PRODUCT_NAME}-${PRODUCT_VERSION}-${FILESIZE}-${TARGET}-${NANOTYPE}${TIMESTAMP_SUFFIX}.img.gz"
169
			FILENAMEUPGRADE="${PRODUCT_NAME}-${PRODUCT_VERSION}-${FILESIZE}-${TARGET}-${NANOTYPE}-upgrade${TIMESTAMP_SUFFIX}.img.gz"
170
			mkdir -p $STAGINGAREA/nanobsd
171
			mkdir -p $STAGINGAREA/nanobsdupdates
172

    
173
			cp $IMAGES_FINAL_DIR/$FILENAMEFULL $STAGINGAREA/nanobsd/ 2>/dev/null
174
			cp $IMAGES_FINAL_DIR/$FILENAMEUPGRADE $STAGINGAREA/nanobsdupdates 2>/dev/null
175

    
176
			if [ -f $STAGINGAREA/nanobsd/$FILENAMEFULL ]; then
177
				md5 $STAGINGAREA/nanobsd/$FILENAMEFULL > $STAGINGAREA/nanobsd/$FILENAMEFULL.md5 2>/dev/null
178
				sha256 $STAGINGAREA/nanobsd/$FILENAMEFULL > $STAGINGAREA/nanobsd/$FILENAMEFULL.sha256 2>/dev/null
179
			fi
180
			if [ -f $STAGINGAREA/nanobsdupdates/$FILENAMEUPGRADE ]; then
181
				md5 $STAGINGAREA/nanobsdupdates/$FILENAMEUPGRADE > $STAGINGAREA/nanobsdupdates/$FILENAMEUPGRADE.md5 2>/dev/null
182
				sha256 $STAGINGAREA/nanobsdupdates/$FILENAMEUPGRADE > $STAGINGAREA/nanobsdupdates/$FILENAMEUPGRADE.sha256 2>/dev/null
183
			fi
184

    
185
			# Copy NanoBSD auto update:
186
			if [ -f $STAGINGAREA/nanobsdupdates/$FILENAMEUPGRADE ]; then
187
				cp $STAGINGAREA/nanobsdupdates/$FILENAMEUPGRADE $STAGINGAREA/latest-${NANOTYPE}-$FILESIZE.img.gz 2>/dev/null
188
				sha256 $STAGINGAREA/latest-${NANOTYPE}-$FILESIZE.img.gz > $STAGINGAREA/latest-${NANOTYPE}-$FILESIZE.img.gz.sha256 2>/dev/null
189
				# NOTE: Updates need a file with output similar to date output
190
				# Use the file generated at start of dobuilds() to be consistent on times
191
				cp $BUILTDATESTRINGFILE $STAGINGAREA/version-${NANOTYPE}-$FILESIZE
192
			fi
193
		done
194
	done
195
}
196

    
197
copy_to_staging_iso_updates() {
198
	# Copy ISOs
199
	md5 ${ISOPATH}.gz > ${ISOPATH}.md5
200
	sha256 ${ISOPATH}.gz > ${ISOPATH}.sha256
201
	cp ${ISOPATH}* $STAGINGAREA/ 2>/dev/null
202

    
203
	# Copy memstick items
204
	md5 ${MEMSTICKPATH}.gz > ${MEMSTICKPATH}.md5
205
	sha256 ${MEMSTICKPATH}.gz > ${MEMSTICKPATH}.sha256
206
	cp ${MEMSTICKPATH}* $STAGINGAREA/ 2>/dev/null
207

    
208
	md5 ${MEMSTICKSERIALPATH}.gz > ${MEMSTICKSERIALPATH}.md5
209
	sha256 ${MEMSTICKSERIALPATH}.gz > ${MEMSTICKSERIALPATH}.sha256
210
	cp ${MEMSTICKSERIALPATH}* $STAGINGAREA/ 2>/dev/null
211

    
212
	md5 ${MEMSTICKADIPATH}.gz > ${MEMSTICKADIPATH}.md5
213
	sha256 ${MEMSTICKADIPATH}.gz > ${MEMSTICKADIPATH}.sha256
214
	cp ${MEMSTICKADIPATH}* $STAGINGAREA/ 2>/dev/null
215

    
216
	md5 ${UPDATES_TARBALL_FILENAME} > ${UPDATES_TARBALL_FILENAME}.md5
217
	sha256 ${UPDATES_TARBALL_FILENAME} > ${UPDATES_TARBALL_FILENAME}.sha256
218
	cp ${UPDATES_TARBALL_FILENAME}* $STAGINGAREA/ 2>/dev/null
219
	# NOTE: Updates need a file with output similar to date output
220
	# Use the file generated at start of dobuilds() to be consistent on times
221
	if [ -z "${_IS_RELEASE}" ]; then
222
		cp $BUILTDATESTRINGFILE $STAGINGAREA/version 2>/dev/null
223
	fi
224
}
225

    
226
scp_files() {
227
	if [ -z "${RSYNC_COPY_ARGUMENTS:-}" ]; then
228
		RSYNC_COPY_ARGUMENTS="-ave ssh --timeout=60 --bwlimit=${RSYNCKBYTELIMIT}" #--bwlimit=50
229
	fi
230
	update_status ">>> Copying files to ${RSYNCIP}"
231

    
232
	rm -f $SCRATCHDIR/ssh-snapshots*
233

    
234
	# Ensure directory(s) are available
235
	ssh ${RSYNCUSER}@${RSYNCIP} "mkdir -p ${RSYNCPATH}/livecd_installer"
236
	ssh ${RSYNCUSER}@${RSYNCIP} "mkdir -p ${RSYNCPATH}/updates"
237
	ssh ${RSYNCUSER}@${RSYNCIP} "mkdir -p ${RSYNCPATH}/nanobsd"
238
	if [ -d $STAGINGAREA/virtualization ]; then
239
		ssh ${RSYNCUSER}@${RSYNCIP} "mkdir -p ${RSYNCPATH}/virtualization"
240
	fi
241
	ssh ${RSYNCUSER}@${RSYNCIP} "mkdir -p ${RSYNCPATH}/.updaters"
242
	# ensure permissions are correct for r+w
243
	ssh ${RSYNCUSER}@${RSYNCIP} "chmod -R ug+rw /usr/local/www/snapshots/FreeBSD_${FREEBSD_PARENT_BRANCH}/${TARGET}/."
244
	ssh ${RSYNCUSER}@${RSYNCIP} "chmod -R ug+rw ${RSYNCPATH}/."
245
	ssh ${RSYNCUSER}@${RSYNCIP} "chmod -R ug+rw ${RSYNCPATH}/*/."
246
	rsync $RSYNC_COPY_ARGUMENTS $STAGINGAREA/${PRODUCT_NAME}-*iso* \
247
		${RSYNCUSER}@${RSYNCIP}:${RSYNCPATH}/livecd_installer/
248
	rsync $RSYNC_COPY_ARGUMENTS $STAGINGAREA/${PRODUCT_NAME}-memstick* \
249
		${RSYNCUSER}@${RSYNCIP}:${RSYNCPATH}/livecd_installer/
250
	rsync $RSYNC_COPY_ARGUMENTS $STAGINGAREA/${PRODUCT_NAME}-*Update* \
251
		${RSYNCUSER}@${RSYNCIP}:${RSYNCPATH}/updates/
252
	rsync $RSYNC_COPY_ARGUMENTS $STAGINGAREA/nanobsd/* \
253
		${RSYNCUSER}@${RSYNCIP}:${RSYNCPATH}/nanobsd/
254
	rsync $RSYNC_COPY_ARGUMENTS $STAGINGAREA/nanobsdupdates/* \
255
		${RSYNCUSER}@${RSYNCIP}:${RSYNCPATH}/updates/
256
	if [ -d $STAGINGAREA/virtualization ]; then
257
		rsync $RSYNC_COPY_ARGUMENTS $STAGINGAREA/virtualization/* \
258
			${RSYNCUSER}@${RSYNCIP}:${RSYNCPATH}/virtualization/
259
	fi
260

    
261
	# Rather than copy these twice, use ln to link to the latest one.
262

    
263
	ssh ${RSYNCUSER}@${RSYNCIP} "rm -f ${RSYNCPATH}/.updaters/latest.tgz"
264
	ssh ${RSYNCUSER}@${RSYNCIP} "rm -f ${RSYNCPATH}/.updaters/latest.tgz.sha256"
265

    
266
	LATESTFILENAME="`ls $UPDATESDIR/*.tgz | grep Full | grep -v md5 | grep -v sha256 | tail -n1`"
267
	LATESTFILENAME=`basename ${LATESTFILENAME}`
268
	ssh ${RSYNCUSER}@${RSYNCIP} "ln -s ${RSYNCPATH}/updates/${LATESTFILENAME} \
269
		${RSYNCPATH}/.updaters/latest.tgz"
270
	ssh ${RSYNCUSER}@${RSYNCIP} "ln -s ${RSYNCPATH}/updates/${LATESTFILENAME}.sha256 \
271
		${RSYNCPATH}/.updaters/latest.tgz.sha256"
272

    
273
	for i in 1g 2g 4g
274
	do
275
		ssh ${RSYNCUSER}@${RSYNCIP} "rm -f ${RSYNCPATH}/.updaters/latest-nanobsd-${i}.img.gz"
276
		ssh ${RSYNCUSER}@${RSYNCIP} "rm -f ${RSYNCPATH}/.updaters/latest-nanobsd-${i}.img.gz.sha256"
277
		ssh ${RSYNCUSER}@${RSYNCIP} "rm -f ${RSYNCPATH}/.updaters/latest-nanobsd-vga-${i}.img.gz"
278
		ssh ${RSYNCUSER}@${RSYNCIP} "rm -f ${RSYNCPATH}/.updaters/latest-nanobsd-vga-${i}.img.gz.sha256"
279

    
280
		FILENAMEUPGRADE="${PRODUCT_NAME}-${PRODUCT_VERSION}-${i}-${TARGET}-nanobsd-upgrade${TIMESTAMP_SUFFIX}.img.gz"
281
		ssh ${RSYNCUSER}@${RSYNCIP} "ln -s ${RSYNCPATH}/updates/${FILENAMEUPGRADE} \
282
			${RSYNCPATH}/.updaters/latest-nanobsd-${i}.img.gz"
283
		ssh ${RSYNCUSER}@${RSYNCIP} "ln -s ${RSYNCPATH}/updates/${FILENAMEUPGRADE}.sha256 \
284
			${RSYNCPATH}/.updaters/latest-nanobsd-${i}.img.gz.sha256"
285

    
286
		FILENAMEUPGRADE="${PRODUCT_NAME}-${PRODUCT_VERSION}-${i}-${TARGET}-nanobsd-vga-upgrade${TIMESTAMP_SUFFIX}.img.gz"
287
		ssh ${RSYNCUSER}@${RSYNCIP} "ln -s ${RSYNCPATH}/updates/${FILENAMEUPGRADE} \
288
			${RSYNCPATH}/.updaters/latest-nanobsd-vga-${i}.img.gz"
289
		ssh ${RSYNCUSER}@${RSYNCIP} "ln -s ${RSYNCPATH}/updates/${FILENAMEUPGRADE}.sha256 \
290
			${RSYNCPATH}/.updaters/latest-nanobsd-vga-${i}.img.gz.sha256"
291
	done
292

    
293
	rsync $RSYNC_COPY_ARGUMENTS $STAGINGAREA/version* \
294
		${RSYNCUSER}@${RSYNCIP}:${RSYNCPATH}/.updaters
295
	update_status ">>> Finished copying files."
296
}
297

    
298
cleanup_builds() {
299
	# Remove prior builds
300
	update_status ">>> Cleaning up after prior builds..."
301
	rm -rf $STAGINGAREA/*
302
	rm -rf $IMAGES_FINAL_DIR/*
303
	(cd ${BUILDER_ROOT} && ./build.sh --clean-builder)
304
}
305

    
306
build_loop_operations() {
307
	update_status ">>> Starting build loop operations"
308
	# --- Items we need to run for a complete build run ---
309
	# Cleanup prior builds
310
	cleanup_builds
311
	# Update pkgs if necessary
312
	if pkg update -r ${PRODUCT_NAME} >/dev/null 2>&1; then
313
		update_status ">>> Updating builder packages... "
314
		pkg upgrade -r ${PRODUCT_NAME} -y -q >/dev/null 2>&1
315
	fi
316
	# Do the builds
317
	dobuilds
318
	# SCP files to snapshot web hosting area
319
	if [ -z "${NO_UPLOAD}" ]; then
320
		scp_files
321
	fi
322
	# Alert the world that we have some snapshots ready.
323
	update_status ">>> Builder run is complete."
324
}
325

    
326
if [ -z "${LOOPED_SNAPSHOTS}" ]; then
327
	build_loop_operations
328
else
329
	# Main builder loop
330
	while [ /bin/true ]; do
331
		BUILDCOUNTER=`expr $BUILDCOUNTER + 1`
332
		update_status ">>> Starting builder run #${BUILDCOUNTER}..."
333

    
334
		# Launch the snapshots builder script and pipe its
335
		# contents to the while loop so we can record the 
336
		# script progress in real time to the public facing
337
		# snapshot server (${RSYNCIP}).
338
		( build_loop_operations ) | while read LINE
339
		do
340
			update_status "$LINE"
341
		done
342

    
343
		export minsleepvalue=28800
344
		export maxsleepvalue=86400
345

    
346
		# Initialize variables that keep track of last commit
347
		[ -z "${LAST_COMMIT}" ] \
348
			&& export LAST_COMMIT="$(git -C ${BUILDER_ROOT} log | head -n1 | cut -d' ' -f2)"
349

    
350
		update_status ">>> Sleeping for at least $minsleepvalue, at most $maxsleepvalue in between snapshot builder runs.  Last known commit ${LAST_COMMIT}"
351
		update_status ">>> Freezing build process at `date`."
352
		sleep $minsleepvalue
353
		update_status ">>> Thawing build process and resuming checks for pending commits at `date`."
354

    
355
		# Count some sheep or wait until a new commit turns up 
356
		# for one days time.  We will wake up if a new commit
357
		# is detected during sleepy time.
358
		sleep_between_runs $maxsleepvalue
359

    
360
		# If REBOOT_AFTER_SNAPSHOT_RUN is defined reboot
361
		# the box after the run. 
362
		if [ ! -z "${REBOOT_AFTER_SNAPSHOT_RUN:-}" ]; then
363
			update_status ">>> Rebooting `hostname` due to \$REBOOT_AFTER_SNAPSHOT_RUN"
364
			shutdown -r now
365
			kill $$
366
		fi
367
		# Rotate log file (.old)
368
		rotate_logfile
369

    
370
		# Set a common DATESTRING for the build if not set from builder_defaults.sh.
371
		# Rely on builder_defaults.sh doing the right job the first time included from this script.
372
		# NOTE: This is needed to have autoupdate detect a new version.
373
		# Override it here to have continuous builds with proper labels
374
		rm -f $DATESTRINGFILE
375
		rm -f $BUILTDATESTRINGFILE
376
		unset TIMESTAMP_SUFFIX
377
		unset DATESTRING
378
		unset BUILTDATESTRING
379
		unset ISOPATH
380
		unset MEMSTICKPATH
381
		unset MEMSTICKSERIALPATH
382
		unset MEMSTICKADIPATH
383
		unset UPDATES_TARBALL_FILENAME
384
		# builder_defaults.sh will set variables with correct timestamp
385
		. ${BUILDER_TOOLS}/builder_defaults.sh
386
	done
387
fi
(1-1/3)