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 ########################################################################
34 count=${2:-${LOGROTATE}}
35 while [ ${count} -gt 0 ]; do
37 if [ -e "${torotate}.${prev}" ]; then
38 mv "${torotate}.${prev}" "${torotate}.${count}"
42 mv "${torotate}" "${torotate}.0"
45 # log something (basically echo it together with a timestamp)
47 # Set $PROGRAM to a string to have it added to the output.
49 if [ -z "${PROGRAM}" ]; then
50 echo "$(date +"%b %d %H:%M:%S") $(hostname -s) [$$] $@"
52 echo "$(date +"%b %d %H:%M:%S") $(hostname -s) ${PROGRAM}[$$]: $@"
56 # log the message using log() but then also send a mail
57 # to the address configured in MAILTO (if non-empty)
60 if [ -z "${MAILTO}" ]; then
61 echo "$@" | mail -e -s "[$PROGRAM@$(hostname -s)] ERROR [$$]" ${MAILTO}
65 # debug log, only output when DEBUG=1
67 if [ $DEBUG -eq 1 ]; then
72 # Timestamp. Used for dinstall stat graphs
75 echo "Archive maintenance timestamp $TS ($1): $(date +%H:%M:%S)"
83 # Setup the notice file to tell bad mirrors they used the wrong time
87 Packages are currently being installed and indices rebuilt.
88 Maintenance is automatic, starting at 01|07|13|19:52 UTC,
89 and ending about an hour later. This file is then removed.
91 You should not mirror the archive during this period.
95 # ushing merkels QA user, part one
97 log "Telling merkels QA user that we start dinstall"
98 ssh -2 -i ~dak/.ssh/push_merkel_qa -o BatchMode=yes -o SetupTimeOut=90 -o ConnectTimeout=90 qa@merkel.debian.org sleep 1
101 # Create the postgres dump files
102 function pgdump_pre() {
103 log "Creating pre-daily-cron-job backup of projectb database..."
104 pg_dump projectb > $base/backup/dump_$(date +%Y.%m.%d-%H:%M:%S)
106 function pgdump_post() {
107 log "Creating post-daily-cron-job backup of projectb database..."
108 POSTDUMP=$base/backup/dump_$(date +%Y.%m.%d-%H:%M:%S)
109 pg_dump projectb > $POSTDUMP
110 (cd $base/backup; ln -sf $POSTDUMP current)
113 # Updating various files
115 log "Updating Bugs docu, Mirror list and mailing-lists.txt"
117 $scriptsdir/update-bugdoctxt
118 $scriptsdir/update-mirrorlists
119 $scriptsdir/update-mailingliststxt
120 $scriptsdir/update-pseudopackages.sh
123 # Process (oldstable)-proposed-updates "NEW" queue
124 function punew_do() {
125 cd "${queuedir}/${1}"
127 dak process-new -a -C COMMENTS >> REPORT || true
131 log "Doing automated p-u-new processing"
135 log "Doing automated o-p-u-new processing"
139 # The first i18n one, syncing new descriptions
141 log "Synchronizing i18n package descriptions"
142 # First sync their newest data
143 cd ${scriptdir}/i18nsync
144 rsync -aq --delete --delete-after ddtp-sync:/does/not/matter . || true
146 # Now check if we still know about the packages for which they created the files
147 # is the timestamp signed by us?
148 if $(gpgv --keyring /srv/ftp.debian.org/s3kr1t/dot-gnupg/pubring.gpg timestamp.gpg timestamp); then
149 # now read it. As its signed by us we are sure the content is what we expect, no need
150 # to do more here. And we only test -d a directory on it anyway.
151 TSTAMP=$(cat timestamp)
152 # do we have the dir still?
153 if [ -d ${scriptdir}/i18n/${TSTAMP} ]; then
155 if ${scriptsdir}/ddtp-i18n-check.sh . ${scriptdir}/i18n/${TSTAMP}; then
156 # Yay, worked, lets copy around
157 for dir in squeeze sid; do
158 if [ -d dists/${dir}/ ]; then
159 cd dists/${dir}/main/i18n
160 rsync -aq --delete --delete-after . ${ftpdir}/dists/${dir}/main/i18n/.
162 cd ${scriptdir}/i18nsync
165 echo "ARRRR, bad guys, wrong files, ARRR"
166 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
169 echo "ARRRR, missing the timestamp ${TSTAMP} directory, not updating i18n, ARRR"
170 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
173 echo "ARRRRRRR, could not verify our timestamp signature, ARRR. Don't mess with our files, i18n guys, ARRRRR."
174 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
178 # Process the accepted queue
179 function accepted() {
180 log "Processing queue/accepted"
183 dak process-accepted -pa *.changes | tee REPORT | \
184 mail -s "Install for $(date +"%D - %R")" ftpmaster@ftp-master.debian.org
185 chgrp debadmin REPORT
190 log "Checking for cruft in overrides"
193 log "Fixing symlinks in $ftpdir"
194 symlinks -d -r $ftpdir
198 log "Generating suite file lists for apt-ftparchive"
199 dak make-suite-file-list
202 function fingerprints() {
203 log "Updating fingerprints"
204 dak import-keyring -L /srv/keyring.debian.org/keyrings/debian-keyring.gpg
207 function overrides() {
208 log "Writing overrides into text files"
213 rm -f override.sid.all3
214 for i in main contrib non-free main.debian-installer; do cat override.sid.$i >> override.sid.all3; done
218 log "Generating package / file mapping"
219 dak make-pkg-file-mapping | bzip2 -9 > $base/ftp/indices/package-file.map.bz2
222 function packages() {
223 log "Generating Packages and Sources files"
225 apt-ftparchive generate apt.conf
229 log "Generating pdiff files"
230 dak generate-index-diffs
234 log "Generating Release files"
235 dak generate-releases
239 log "Cleanup old packages/files"
245 # Needs to be rebuilt, as files have moved. Due to unaccepts, we need to
246 # update this before wanna-build is updated.
247 log "Regenerating wanna-build/buildd information"
248 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
249 symlinks -d /srv/incoming.debian.org/buildd > /dev/null
250 apt-ftparchive generate apt.conf.buildd
254 log "Running various scripts from $scriptsdir"
264 echo "Regenerating \"public\" mirror/ hardlink fun"
266 rsync -aH --link-dest ${ftpdir} --delete --delete-after --ignore-errors ${ftpdir}/. .
270 log "Trigger daily wanna-build run"
271 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
275 log "Expiring old database dumps..."
276 (cd $base/backup; $scriptsdir/expire_dumps -d . -p -f "dump_*")
280 # Send a report on NEW/BYHAND packages
281 log "Nagging ftpteam about NEW/BYHAND packages"
282 dak queue-report | mail -e -s "NEW and BYHAND on $(date +%D)" ftpmaster@ftp-master.debian.org
283 # and one on crufty packages
284 log "Sending information about crufty packages"
285 dak cruft-report > $webdir/cruft-report-daily.txt
286 dak cruft-report -s experimental >> $webdir/cruft-report-daily.txt
287 cat $webdir/cruft-report-daily.txt | mail -e -s "Debian archive cruft report for $(date +%D)" ftpmaster@ftp-master.debian.org
291 log "Updating DM html page"
292 $scriptsdir/dm-monitor >$webdir/dm-uploaders.html
296 log "Categorizing uncategorized bugs filed against ftp.debian.org"
301 # Push katie@merkel so it syncs the projectb there. Returns immediately, the sync runs detached
302 log "Trigger merkels projectb sync"
303 ssh -2 -o BatchMode=yes -o SetupTimeOut=30 -o ConnectTimeout=30 -i ~/.ssh/push_merkel_projectb katie@merkel.debian.org sleep 1
306 function runparts() {
307 log "Using run-parts to run scripts in $base/scripts/distmnt"
308 run-parts --report $base/scripts/distmnt
312 log "Exporting package data foo for i18n project"
313 STAMP=$(date "+%Y%m%d%H%M")
314 mkdir -p ${scriptdir}/i18n/${STAMP}
315 cd ${scriptdir}/i18n/${STAMP}
316 dak control-suite -l stable > lenny
317 dak control-suite -l testing > squeeze
318 dak control-suite -l unstable > sid
319 echo "${STAMP}" > timestamp
320 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
324 ln -sfT ${scriptdir}/i18n/${STAMP} i18n
327 find ./i18n -mtime +2 -mindepth 1 -maxdepth 1 -not -name "${STAMP}" -type d -print0 | xargs --no-run-if-empty -0 rm -rf
331 log "Updating stats data"
333 $scriptsdir/update-ftpstats $base/log/* > $base/misc/ftpstats.data
334 R --slave --vanilla < $base/misc/ftpstats.R
337 function aptftpcleanup() {
338 log "Clean up apt-ftparchive's databases"
340 apt-ftparchive -q clean apt.conf
343 function compress() {
344 log "Compress old psql backups"
346 find -maxdepth 1 -mindepth 1 -type f -name 'dump_*' \! -name '*.bz2' \! -name '*.gz' -mtime +1 |
347 while read dumpname; do
348 echo "Compressing $dumpname"
349 bzip2 -9v "$dumpname"
354 function logstats() {
355 $masterdir/tools/logs.py "$LOGFILE"
358 ########################################################################
359 ########################################################################
361 # Function to save which stage we are in, so we can restart an interrupted
362 # dinstall. Or even run actions in parallel, if we dare to, by simply
363 # backgrounding the call to this function. But that should only really be
364 # done for things we dont care much about.
366 # This should be called with the first argument being an array, with the
368 # - FUNC - the function name to call
369 # - ARGS - Possible arguments to hand to the function. Can be the empty string
370 # - TS - The timestamp name. Can be the empty string
371 # - ERR - if this is the string false, then the call will be surrounded by
372 # set +e ... set -e calls, so errors in the function do not exit
373 # dinstall. Can be the empty string, meaning true.
375 # MAKE SURE TO KEEP THIS THE LAST FUNCTION, AFTER ALL THE VARIOUS ONES
376 # ADDED FOR DINSTALL FEATURES!
381 if [ -f "${stagedir}/${FUNC}" ]; then
382 stamptime=$(/usr/bin/stat -c %Z "${stagedir}/${FUNC}")
384 difference=$(( $unixtime - $stamptime ))
385 if [ ${difference} -ge 14400 ]; then
386 error "Did already run ${FUNC}, stagefile exists, but that was ${difference} seconds ago. Please check."
388 log "Did already run ${FUNC}, not calling again..."
393 debug "Now calling function ${FUNC}. Arguments: ${ARGS}. Timestamp: ${TS}"
395 if [ "${ERR}" = "false"]; then
400 # No matter what happened in the function, we make sure we have set -e default state back
403 touch "${stagedir}/${FUNC}"
405 if [ -n "${TIME}" ]; then
410 ########################################################################
413 LOGFILE="$logdir/dinstall.log"
415 exec > "$LOGFILE" 2>&1
417 # usually we are not using debug logs. Set to 1 if you want them.
423 # where do we want mails to go? For example log entries made with error()
424 if [ "x$(hostname -s)x" != "xriesx" ]; then
425 # Not our ftpmaster host
426 MAILTO=${MAILTO:-"root"}
429 MAILTO=${MAILTO:-"ftpmaster@debian.org"}
432 # How many logfiles to keep
433 LOGROTATE=${LOGROTATE:-400}
435 # Timestamps start at -1. so first gets 0
439 # Tell everyone we are doing some work
440 NOTICE="$ftpdir/Archive_Maintenance_In_Progress"
442 # lock cron.unchecked (it immediately exits when this exists)
443 LOCK_DAILY="$lockdir/daily.lock"
445 # Lock process-new and cron.unchecked from doing work
446 LOCK_ACCEPTED="$lockdir/unchecked.lock"
448 # This file is simply used to indicate to britney whether or not
449 # the Packages file updates completed sucessfully. It's not a lock
450 # from our point of view
451 LOCK_BRITNEY="$lockdir/britney.lock"
453 lockfile -l 3600 "${LOCK_DAILY}"
454 trap cleanup EXIT ERR TERM HUP INT QUIT
456 touch "${LOCK_BRITNEY}"
484 TIME="External Updates"
514 lockfile "$LOCK_ACCEPTED"
536 TIME="make-suite-file-list"
544 TIME="import-keyring"
560 TIME="pkg-file-mapping"
568 TIME="apt-ftparchive"
616 TIME="mirror hardlinks"
631 rm -f "${LOCK_DAILY}"
633 ts "locked part finished"
677 TIME="merkel projectb push"
683 ulimit -m 90000 -d 90000 -s 10000 -v 200000
713 TIME="apt-ftparchive cleanup"
727 log "Daily cron scripts successful, all done"
729 exec > /dev/null 2>&1
739 cat "$LOGFILE" | mail -s "Log for dinstall run of ${NOW}" cron@ftp-master.debian.org
741 # Now, at the very (successful) end of dinstall, make sure we remove
742 # our stage files, so the next dinstall run will do it all again.
743 rm -f "${stagedir}/*"