2 # No way I try to deal with a crippled sh just for POSIX foo.
4 # Copyright (C) 2009 Joerg Jaspert <joerg@debian.org>
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License as
8 # published by the Free Software Foundation; version 2.
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 # make sure to only use defined variables
24 # import the general variable set.
25 export SCRIPTVARS=/srv/ftp.debian.org/dak/config/debian/vars
28 ########################################################################
30 ########################################################################
31 # common functions are "outsourced"
32 . "${configdir}/common"
34 # Timestamp. Used for dinstall stat graphs
37 echo "Archive maintenance timestamp $TS ($1): $(date +%H:%M:%S)"
43 rm -f ${LOCK_ACCEPTED}
46 ########################################################################
47 # the actual dinstall functions follow #
48 ########################################################################
50 # Setup the notice file to tell bad mirrors they used the wrong time
54 Packages are currently being installed and indices rebuilt.
55 Maintenance is automatic, starting at 01|07|13|19:52 UTC,
56 and ending about an hour later. This file is then removed.
58 You should not mirror the archive during this period.
62 # pushing merkels QA user, part one
64 log "Telling merkels QA user that we start dinstall"
65 ssh -2 -i ~dak/.ssh/push_merkel_qa -o BatchMode=yes -o SetupTimeOut=90 -o ConnectTimeout=90 qa@merkel.debian.org sleep 1
68 # Create the postgres dump files
69 function pgdump_pre() {
70 log "Creating pre-daily-cron-job backup of projectb database..."
71 pg_dump projectb > $base/backup/dump_$(date +%Y.%m.%d-%H:%M:%S)
74 function pgdump_post() {
75 log "Creating post-daily-cron-job backup of projectb database..."
77 POSTDUMP=$(date +%Y.%m.%d-%H:%M:%S)
78 pg_dump projectb > $base/backup/dump_$POSTDUMP
79 pg_dumpall --globals-only > $base/backup/dumpall_$POSTDUMP
80 ln -sf $base/backup/dump_$POSTDUMP current
81 ln -sf $base/backup/dumpall_$POSTDUMP currentall
84 # Load the dak-dev projectb
87 echo "drop database projectb" | psql -p 5433 template1
88 cat currentall | psql -p 5433 template1
89 createdb -p 5433 -T template0 projectb
90 fgrep -v '\connect' current | psql -p 5433 projectb
93 # Updating various files
95 log "Updating Bugs docu, Mirror list and mailing-lists.txt"
97 $scriptsdir/update-bugdoctxt
98 $scriptsdir/update-mirrorlists
99 $scriptsdir/update-mailingliststxt
100 $scriptsdir/update-pseudopackages.sh
103 # Process (oldstable)-proposed-updates "NEW" queue
104 function punew_do() {
105 cd "${queuedir}/${1}"
107 dak process-new -a -C COMMENTS >> REPORT || true
111 log "Doing automated p-u-new processing"
115 log "Doing automated o-p-u-new processing"
119 # The first i18n one, syncing new descriptions
121 log "Synchronizing i18n package descriptions"
122 # First sync their newest data
123 cd ${scriptdir}/i18nsync
124 rsync -aq --delete --delete-after ddtp-sync:/does/not/matter . || true
126 # Now check if we still know about the packages for which they created the files
127 # is the timestamp signed by us?
128 if $(gpgv --keyring /srv/ftp.debian.org/s3kr1t/dot-gnupg/pubring.gpg timestamp.gpg timestamp); then
129 # now read it. As its signed by us we are sure the content is what we expect, no need
130 # to do more here. And we only test -d a directory on it anyway.
131 TSTAMP=$(cat timestamp)
132 # do we have the dir still?
133 if [ -d ${scriptdir}/i18n/${TSTAMP} ]; then
135 if ${scriptsdir}/ddtp-i18n-check.sh . ${scriptdir}/i18n/${TSTAMP}; then
136 # Yay, worked, lets copy around
137 for dir in squeeze sid; do
138 if [ -d dists/${dir}/ ]; then
139 cd dists/${dir}/main/i18n
140 rsync -aq --delete --delete-after . ${ftpdir}/dists/${dir}/main/i18n/.
142 cd ${scriptdir}/i18nsync
145 echo "ARRRR, bad guys, wrong files, ARRR"
146 echo "Arf, Arf, Arf, bad guys, wrong files, arf, arf, arf" | mail -s "Don't you kids take anything. I'm watching you. I've got eye implants in the back of my head." debian-l10n-devel@lists.alioth.debian.org
149 echo "ARRRR, missing the timestamp ${TSTAMP} directory, not updating i18n, ARRR"
150 echo "Arf, Arf, Arf, missing the timestamp ${TSTAMP} directory, not updating i18n, arf, arf, arf" | mail -s "Lisa, if you don't like your job you don't strike. You just go in every day and do it really half-assed. That's the American way." debian-l10n-devel@lists.alioth.debian.org
153 echo "ARRRRRRR, could not verify our timestamp signature, ARRR. Don't mess with our files, i18n guys, ARRRRR."
154 echo "Arf, Arf, Arf, could not verify our timestamp signature, arf. Don't mess with our files, i18n guys, arf, arf, arf" | mail -s "You can't keep blaming yourself. Just blame yourself once, and move on." debian-l10n-devel@lists.alioth.debian.org
158 # Process the accepted queue
159 function accepted() {
160 log "Processing queue/accepted"
161 rm -f "$accepted/REPORT"
162 dak process-accepted -pa -d "$accepted" > "$accepted/REPORT"
163 cat "$accepted/REPORT" | mail -s "Install for $(date +"%D - %R")" ftpmaster@ftp-master.debian.org
164 chgrp debadmin "$accepted/REPORT"
165 chmod 664 "$accepted/REPORT"
169 log "Checking for cruft in overrides"
172 log "Fixing symlinks in $ftpdir"
173 symlinks -d -r $ftpdir
177 log "Generating suite file lists for apt-ftparchive"
178 dak make-suite-file-list
181 function fingerprints() {
182 log "Updating fingerprints"
183 dak import-keyring -L /srv/keyring.debian.org/keyrings/debian-keyring.gpg
186 function overrides() {
187 log "Writing overrides into text files"
192 rm -f override.sid.all3
193 for i in main contrib non-free main.debian-installer; do cat override.sid.$i >> override.sid.all3; done
197 log "Generating package / file mapping"
198 dak make-pkg-file-mapping | bzip2 -9 > $base/ftp/indices/package-file.map.bz2
201 function packages() {
202 log "Generating Packages and Sources files"
204 apt-ftparchive generate apt.conf
208 log "Generating pdiff files"
209 dak generate-index-diffs
213 log "Generating Release files"
214 dak generate-releases
217 function dakcleanup() {
218 log "Cleanup old packages/files"
224 # Needs to be rebuilt, as files have moved. Due to unaccepts, we need to
225 # update this before wanna-build is updated.
226 log "Regenerating wanna-build/buildd information"
227 psql projectb -A -t -q -c "SELECT filename FROM queue_build WHERE suite = 5 AND queue = 0 AND in_queue = true AND filename ~ 'd(sc|eb)$'" > $dbdir/dists/unstable_accepted.list
228 symlinks -d /srv/incoming.debian.org/buildd > /dev/null
229 apt-ftparchive generate apt.conf.buildd
233 log "Running various scripts from $scriptsdir"
243 echo "Regenerating \"public\" mirror/ hardlink fun"
245 rsync -aH --link-dest ${ftpdir} --delete --delete-after --ignore-errors ${ftpdir}/. .
249 log "Trigger daily wanna-build run"
250 ssh -o BatchMode=yes -o SetupTimeOut=90 -o ConnectTimeout=90 wbadm@buildd /org/wanna-build/trigger.daily || echo "W-B trigger.daily failed" | mail -s "W-B Daily trigger failed" ftpmaster@ftp-master.debian.org
254 log "Expiring old database dumps..."
256 $scriptsdir/expire_dumps -d . -p -f "dump_*"
260 # Send a report on NEW/BYHAND packages
261 log "Nagging ftpteam about NEW/BYHAND packages"
262 dak queue-report | mail -e -s "NEW and BYHAND on $(date +%D)" ftpmaster@ftp-master.debian.org
263 # and one on crufty packages
264 log "Sending information about crufty packages"
265 dak cruft-report > $webdir/cruft-report-daily.txt
266 dak cruft-report -s experimental >> $webdir/cruft-report-daily.txt
267 cat $webdir/cruft-report-daily.txt | mail -e -s "Debian archive cruft report for $(date +%D)" ftpmaster@ftp-master.debian.org
271 log "Updating DM html page"
272 $scriptsdir/dm-monitor >$webdir/dm-uploaders.html
276 log "Categorizing uncategorized bugs filed against ftp.debian.org"
281 # Push katie@merkel so it syncs the projectb there. Returns immediately, the sync runs detached
282 log "Trigger merkels projectb sync"
283 ssh -2 -o BatchMode=yes -o SetupTimeOut=30 -o ConnectTimeout=30 -i ~/.ssh/push_merkel_projectb katie@merkel.debian.org sleep 1
286 function runparts() {
287 log "Using run-parts to run scripts in $base/scripts/distmnt"
288 run-parts --report $base/scripts/distmnt
292 log "Exporting package data foo for i18n project"
293 STAMP=$(date "+%Y%m%d%H%M")
294 mkdir -p ${scriptdir}/i18n/${STAMP}
295 cd ${scriptdir}/i18n/${STAMP}
296 dak control-suite -l stable > lenny
297 dak control-suite -l testing > squeeze
298 dak control-suite -l unstable > sid
299 echo "${STAMP}" > timestamp
300 gpg --secret-keyring /srv/ftp.debian.org/s3kr1t/dot-gnupg/secring.gpg --keyring /srv/ftp.debian.org/s3kr1t/dot-gnupg/pubring.gpg --no-options --batch --no-tty --armour --default-key 6070D3A1 --detach-sign -o timestamp.gpg timestamp
304 ln -sfT ${scriptdir}/i18n/${STAMP} i18n
307 find ./i18n -mindepth 1 -maxdepth 1 -mtime +2 -not -name "${STAMP}" -type d -print0 | xargs --no-run-if-empty -0 rm -rf
311 log "Updating stats data"
313 $scriptsdir/update-ftpstats $base/log/* > $base/misc/ftpstats.data
314 R --slave --vanilla < $base/misc/ftpstats.R
317 function aptftpcleanup() {
318 log "Clean up apt-ftparchive's databases"
320 apt-ftparchive -q clean apt.conf
323 function compress() {
324 log "Compress old psql backups"
326 find -maxdepth 1 -mindepth 1 -type f -name 'dump_*' \! -name '*.bz2' \! -name '*.gz' -mtime +1 |
327 while read dumpname; do
328 echo "Compressing $dumpname"
329 bzip2 -9v "$dumpname"
333 function logstats() {
334 $masterdir/tools/logs.py "$1"
337 # save timestamp when we start
338 function savetimestamp() {
339 NOW=`date "+%Y.%m.%d-%H:%M:%S"`
340 echo ${NOW} > "${dbdir}/dinstallstart"
343 function renamelogfile() {
344 if [ -f "${dbdir}/dinstallstart" ]; then
345 RENAMETO=$(cat "${dbdir}/dinstallstart")
346 mv "$LOGFILE" "$logdir/dinstall_${RENAMETO}.log"
347 logstats "$logdir/dinstall_${RENAMETO}.log"
348 bzip2 -9 "$logdir/dinstall_${RENAMETO}.log"
350 error "Problem, I don't know when dinstall started, unable to do log statistics."
351 NOW=`date "+%Y.%m.%d-%H:%M:%S"`
352 mv "$LOGFILE" "$logdir/dinstall_${NOW}.log"
353 bzip2 -9 "$logdir/dinstall_${NOW}.log"
357 ########################################################################
358 ########################################################################
360 # Function to save which stage we are in, so we can restart an interrupted
361 # dinstall. Or even run actions in parallel, if we dare to, by simply
362 # backgrounding the call to this function. But that should only really be
363 # done for things we dont care much about.
365 # This should be called with the first argument being an array, with the
367 # - FUNC - the function name to call
368 # - ARGS - Possible arguments to hand to the function. Can be the empty string
369 # - TS - The timestamp name. Can be the empty string
370 # - ERR - if this is the string false, then the call will be surrounded by
371 # set +e ... set -e calls, so errors in the function do not exit
372 # dinstall. Can be the empty string, meaning true.
374 # MAKE SURE TO KEEP THIS THE LAST FUNCTION, AFTER ALL THE VARIOUS ONES
375 # ADDED FOR DINSTALL FEATURES!
380 if [ -f "${stagedir}/${FUNC}" ]; then
381 stamptime=$(/usr/bin/stat -c %Z "${stagedir}/${FUNC}")
383 difference=$(( $unixtime - $stamptime ))
384 if [ ${difference} -ge 14400 ]; then
385 log_error "Did already run ${FUNC}, stagefile exists, but that was ${difference} seconds ago. Please check."
387 log "Did already run ${FUNC}, not calling again..."
392 debug "Now calling function ${FUNC}. Arguments: ${ARGS}. Timestamp: ${TS}"
394 # Make sure we are always at the same place. If a function wants to be elsewhere,
395 # it has to cd first!
398 if [ -f "${LOCK_STOP}" ]; then
399 log "${LOCK_STOP} exists, exiting immediately"
403 if [ "${ERR}" = "false" ]; then
408 # No matter what happened in the function, we make sure we have set -e default state back
411 # Make sure we are always at the same place.
414 touch "${stagedir}/${FUNC}"
416 if [ -n "${TIME}" ]; then
420 if [ -f "${LOCK_STOP}" ]; then
421 log "${LOCK_STOP} exists, exiting immediately"
426 ########################################################################
429 LOGFILE="$logdir/dinstall.log"
431 exec >> "$LOGFILE" 2>&1
433 # usually we are not using debug logs. Set to 1 if you want them.
439 # where do we want mails to go? For example log entries made with error()
440 if [ "x$(hostname -s)x" != "xriesx" ]; then
441 # Not our ftpmaster host
442 MAILTO=${MAILTO:-"root"}
445 MAILTO=${MAILTO:-"ftpmaster@debian.org"}
448 # How many logfiles to keep
449 LOGROTATE=${LOGROTATE:-400}
451 # Marker for dinstall start
452 DINSTALLSTART="${lockdir}/dinstallstart"
453 # Marker for dinstall end
454 DINSTALLEND="${lockdir}/dinstallend"
456 # Timestamps start at -1. so first gets 0
458 touch "${DINSTALLSTART}"
461 # Tell everyone we are doing some work
462 NOTICE="$ftpdir/Archive_Maintenance_In_Progress"
464 # lock cron.unchecked (it immediately exits when this exists)
465 LOCK_DAILY="$lockdir/daily.lock"
467 # Lock process-new and cron.unchecked from doing work
468 LOCK_ACCEPTED="$lockdir/unchecked.lock"
470 # This file is simply used to indicate to britney whether or not
471 # the Packages file updates completed sucessfully. It's not a lock
472 # from our point of view
473 LOCK_BRITNEY="$lockdir/britney.lock"
475 # If this file exists we exit immediately after the currently running
477 LOCK_STOP="$lockdir/archive.stop"
479 lockfile -l 3600 "${LOCK_DAILY}"
480 trap cleanup EXIT ERR TERM HUP INT QUIT
482 touch "${LOCK_BRITNEY}"
518 TIME="External Updates"
548 lockfile "$LOCK_ACCEPTED"
566 rm -f "$LOCK_ACCEPTED"
570 TIME="make-suite-file-list"
578 TIME="import-keyring"
594 TIME="pkg-file-mapping"
602 TIME="apt-ftparchive"
650 TIME="mirror hardlinks"
665 rm -f "${LOCK_DAILY}"
667 ts "locked part finished"
719 TIME="merkel projectb push"
725 ulimit -m 90000 -d 90000 -s 10000 -v 200000
751 rm -f ${LOCK_BRITNEY}
755 TIME="apt-ftparchive cleanup"
769 log "Daily cron scripts successful, all done"
771 exec > "$logdir/afterdinstall.log" 2>&1
773 cat "$LOGFILE" | mail -s "Log for dinstall run of ${NOW}" cron@ftp-master.debian.org
784 # Now, at the very (successful) end of dinstall, make sure we remove
785 # our stage files, so the next dinstall run will do it all again.
787 touch "${DINSTALLEND}"