Project

General

Profile

Download (13.8 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}-${DATESTRING}.img.gz"
169
			FILENAMEUPGRADE="${PRODUCT_NAME}-${PRODUCT_VERSION}-${FILESIZE}-${TARGET}-${NANOTYPE}-upgrade-${DATESTRING}.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
	cp $BUILTDATESTRINGFILE $STAGINGAREA/version 2>/dev/null
222
}
223

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

    
230
	rm -f $SCRATCHDIR/ssh-snapshots*
231

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

    
259
	# Rather than copy these twice, use ln to link to the latest one.
260

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

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

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

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

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

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

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

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

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

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

    
341
		export minsleepvalue=28800
342
		export maxsleepvalue=86400
343

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

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

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

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

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