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=$base/backup/dump_$(date +%Y.%m.%d-%H:%M:%S)
78 pg_dump projectb > $POSTDUMP
79 ln -sf $POSTDUMP current
82 # Updating various files
84 log "Updating Bugs docu, Mirror list and mailing-lists.txt"
86 $scriptsdir/update-bugdoctxt
87 $scriptsdir/update-mirrorlists
88 $scriptsdir/update-mailingliststxt
89 $scriptsdir/update-pseudopackages.sh
92 # Process (oldstable)-proposed-updates "NEW" queue
96 dak process-new -a -C COMMENTS >> REPORT || true
100 log "Doing automated p-u-new processing"
104 log "Doing automated o-p-u-new processing"
108 # The first i18n one, syncing new descriptions
110 log "Synchronizing i18n package descriptions"
111 # First sync their newest data
112 cd ${scriptdir}/i18nsync
113 rsync -aq --delete --delete-after ddtp-sync:/does/not/matter . || true
115 # Now check if we still know about the packages for which they created the files
116 # is the timestamp signed by us?
117 if $(gpgv --keyring /srv/ftp.debian.org/s3kr1t/dot-gnupg/pubring.gpg timestamp.gpg timestamp); then
118 # now read it. As its signed by us we are sure the content is what we expect, no need
119 # to do more here. And we only test -d a directory on it anyway.
120 TSTAMP=$(cat timestamp)
121 # do we have the dir still?
122 if [ -d ${scriptdir}/i18n/${TSTAMP} ]; then
124 if ${scriptsdir}/ddtp-i18n-check.sh . ${scriptdir}/i18n/${TSTAMP}; then
125 # Yay, worked, lets copy around
126 for dir in squeeze sid; do
127 if [ -d dists/${dir}/ ]; then
128 cd dists/${dir}/main/i18n
129 rsync -aq --delete --delete-after . ${ftpdir}/dists/${dir}/main/i18n/.
131 cd ${scriptdir}/i18nsync
134 echo "ARRRR, bad guys, wrong files, ARRR"
135 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
138 echo "ARRRR, missing the timestamp ${TSTAMP} directory, not updating i18n, ARRR"
139 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
142 echo "ARRRRRRR, could not verify our timestamp signature, ARRR. Don't mess with our files, i18n guys, ARRRRR."
143 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
147 # Process the accepted queue
148 function accepted() {
149 log "Processing queue/accepted"
150 rm -f "$accepted/REPORT"
151 dak process-accepted -pa -d "$accepted" > "$accepted/REPORT"
152 cat "$accepted/REPORT" | mail -s "Install for $(date +"%D - %R")" ftpmaster@ftp-master.debian.org
153 chgrp debadmin "$accepted/REPORT"
154 chmod 664 "$accepted/REPORT"
158 log "Checking for cruft in overrides"
161 log "Fixing symlinks in $ftpdir"
162 symlinks -d -r $ftpdir
166 log "Generating suite file lists for apt-ftparchive"
167 dak make-suite-file-list
170 function fingerprints() {
171 log "Updating fingerprints"
172 dak import-keyring -L /srv/keyring.debian.org/keyrings/debian-keyring.gpg
175 function overrides() {
176 log "Writing overrides into text files"
181 rm -f override.sid.all3
182 for i in main contrib non-free main.debian-installer; do cat override.sid.$i >> override.sid.all3; done
186 log "Generating package / file mapping"
187 dak make-pkg-file-mapping | bzip2 -9 > $base/ftp/indices/package-file.map.bz2
190 function packages() {
191 log "Generating Packages and Sources files"
193 apt-ftparchive generate apt.conf
197 log "Generating pdiff files"
198 dak generate-index-diffs
202 log "Generating Release files"
203 dak generate-releases
206 function dakcleanup() {
207 log "Cleanup old packages/files"
213 # Needs to be rebuilt, as files have moved. Due to unaccepts, we need to
214 # update this before wanna-build is updated.
215 log "Regenerating wanna-build/buildd information"
216 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
217 symlinks -d /srv/incoming.debian.org/buildd > /dev/null
218 apt-ftparchive generate apt.conf.buildd
222 log "Running various scripts from $scriptsdir"
232 echo "Regenerating \"public\" mirror/ hardlink fun"
234 rsync -aH --link-dest ${ftpdir} --delete --delete-after --ignore-errors ${ftpdir}/. .
238 log "Trigger daily wanna-build run"
239 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
243 log "Expiring old database dumps..."
245 $scriptsdir/expire_dumps -d . -p -f "dump_*"
249 # Send a report on NEW/BYHAND packages
250 log "Nagging ftpteam about NEW/BYHAND packages"
251 dak queue-report | mail -e -s "NEW and BYHAND on $(date +%D)" ftpmaster@ftp-master.debian.org
252 # and one on crufty packages
253 log "Sending information about crufty packages"
254 dak cruft-report > $webdir/cruft-report-daily.txt
255 dak cruft-report -s experimental >> $webdir/cruft-report-daily.txt
256 cat $webdir/cruft-report-daily.txt | mail -e -s "Debian archive cruft report for $(date +%D)" ftpmaster@ftp-master.debian.org
260 log "Updating DM html page"
261 $scriptsdir/dm-monitor >$webdir/dm-uploaders.html
265 log "Categorizing uncategorized bugs filed against ftp.debian.org"
270 # Push katie@merkel so it syncs the projectb there. Returns immediately, the sync runs detached
271 log "Trigger merkels projectb sync"
272 ssh -2 -o BatchMode=yes -o SetupTimeOut=30 -o ConnectTimeout=30 -i ~/.ssh/push_merkel_projectb katie@merkel.debian.org sleep 1
275 function runparts() {
276 log "Using run-parts to run scripts in $base/scripts/distmnt"
277 run-parts --report $base/scripts/distmnt
281 log "Exporting package data foo for i18n project"
282 STAMP=$(date "+%Y%m%d%H%M")
283 mkdir -p ${scriptdir}/i18n/${STAMP}
284 cd ${scriptdir}/i18n/${STAMP}
285 dak control-suite -l stable > lenny
286 dak control-suite -l testing > squeeze
287 dak control-suite -l unstable > sid
288 echo "${STAMP}" > timestamp
289 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
293 ln -sfT ${scriptdir}/i18n/${STAMP} i18n
296 find ./i18n -mindepth 1 -maxdepth 1 -mtime +2 -not -name "${STAMP}" -type d -print0 | xargs --no-run-if-empty -0 rm -rf
300 log "Updating stats data"
302 $scriptsdir/update-ftpstats $base/log/* > $base/misc/ftpstats.data
303 R --slave --vanilla < $base/misc/ftpstats.R
306 function aptftpcleanup() {
307 log "Clean up apt-ftparchive's databases"
309 apt-ftparchive -q clean apt.conf
312 function compress() {
313 log "Compress old psql backups"
315 find -maxdepth 1 -mindepth 1 -type f -name 'dump_*' \! -name '*.bz2' \! -name '*.gz' -mtime +1 |
316 while read dumpname; do
317 echo "Compressing $dumpname"
318 bzip2 -9v "$dumpname"
322 function logstats() {
323 $masterdir/tools/logs.py "$1"
326 # save timestamp when we start
327 function savetimestamp() {
328 NOW=`date "+%Y.%m.%d-%H:%M:%S"`
329 echo ${NOW} > "${dbdir}/dinstallstart"
332 function renamelogfile() {
333 if [ -f "${dbdir}/dinstallstart" ]; then
334 RENAMETO=$(cat "${dbdir}/dinstallstart")
335 mv "$LOGFILE" "$logdir/dinstall_${RENAMETO}.log"
336 logstats "$logdir/dinstall_${RENAMETO}.log"
337 bzip2 -9 "$logdir/dinstall_${RENAMETO}.log"
339 error "Problem, I don't know when dinstall started, unable to do log statistics."
340 NOW=`date "+%Y.%m.%d-%H:%M:%S"`
341 mv "$LOGFILE" "$logdir/dinstall_${NOW}.log"
342 bzip2 -9 "$logdir/dinstall_${NOW}.log"
346 ########################################################################
347 ########################################################################
349 # Function to save which stage we are in, so we can restart an interrupted
350 # dinstall. Or even run actions in parallel, if we dare to, by simply
351 # backgrounding the call to this function. But that should only really be
352 # done for things we dont care much about.
354 # This should be called with the first argument being an array, with the
356 # - FUNC - the function name to call
357 # - ARGS - Possible arguments to hand to the function. Can be the empty string
358 # - TS - The timestamp name. Can be the empty string
359 # - ERR - if this is the string false, then the call will be surrounded by
360 # set +e ... set -e calls, so errors in the function do not exit
361 # dinstall. Can be the empty string, meaning true.
363 # MAKE SURE TO KEEP THIS THE LAST FUNCTION, AFTER ALL THE VARIOUS ONES
364 # ADDED FOR DINSTALL FEATURES!
369 if [ -f "${stagedir}/${FUNC}" ]; then
370 stamptime=$(/usr/bin/stat -c %Z "${stagedir}/${FUNC}")
372 difference=$(( $unixtime - $stamptime ))
373 if [ ${difference} -ge 14400 ]; then
374 log_error "Did already run ${FUNC}, stagefile exists, but that was ${difference} seconds ago. Please check."
376 log "Did already run ${FUNC}, not calling again..."
381 debug "Now calling function ${FUNC}. Arguments: ${ARGS}. Timestamp: ${TS}"
383 # Make sure we are always at the same place. If a function wants to be elsewhere,
384 # it has to cd first!
387 if [ -f "${LOCK_STOP}" ]; then
388 log "${LOCK_STOP} exists, exiting immediately"
392 if [ "${ERR}" = "false" ]; then
397 # No matter what happened in the function, we make sure we have set -e default state back
400 # Make sure we are always at the same place.
403 touch "${stagedir}/${FUNC}"
405 if [ -n "${TIME}" ]; then
409 if [ -f "${LOCK_STOP}" ]; then
410 log "${LOCK_STOP} exists, exiting immediately"
415 ########################################################################
418 LOGFILE="$logdir/dinstall.log"
420 exec >> "$LOGFILE" 2>&1
422 # usually we are not using debug logs. Set to 1 if you want them.
428 # where do we want mails to go? For example log entries made with error()
429 if [ "x$(hostname -s)x" != "xriesx" ]; then
430 # Not our ftpmaster host
431 MAILTO=${MAILTO:-"root"}
434 MAILTO=${MAILTO:-"ftpmaster@debian.org"}
437 # How many logfiles to keep
438 LOGROTATE=${LOGROTATE:-400}
440 # Marker for dinstall start
441 DINSTALLSTART="${lockdir}/dinstallstart"
442 # Marker for dinstall end
443 DINSTALLEND="${lockdir}/dinstallend"
445 # Timestamps start at -1. so first gets 0
447 touch "${DINSTALLSTART}"
450 # Tell everyone we are doing some work
451 NOTICE="$ftpdir/Archive_Maintenance_In_Progress"
453 # lock cron.unchecked (it immediately exits when this exists)
454 LOCK_DAILY="$lockdir/daily.lock"
456 # Lock process-new and cron.unchecked from doing work
457 LOCK_ACCEPTED="$lockdir/unchecked.lock"
459 # This file is simply used to indicate to britney whether or not
460 # the Packages file updates completed sucessfully. It's not a lock
461 # from our point of view
462 LOCK_BRITNEY="$lockdir/britney.lock"
464 # If this file exists we exit immediately after the currently running
466 LOCK_STOP="$lockdir/archive.stop"
468 lockfile -l 3600 "${LOCK_DAILY}"
469 trap cleanup EXIT ERR TERM HUP INT QUIT
471 touch "${LOCK_BRITNEY}"
507 TIME="External Updates"
537 lockfile "$LOCK_ACCEPTED"
555 rm -f "$LOCK_ACCEPTED"
559 TIME="make-suite-file-list"
567 TIME="import-keyring"
583 TIME="pkg-file-mapping"
591 TIME="apt-ftparchive"
639 TIME="mirror hardlinks"
654 rm -f "${LOCK_DAILY}"
656 ts "locked part finished"
700 TIME="merkel projectb push"
706 ulimit -m 90000 -d 90000 -s 10000 -v 200000
732 rm -f ${LOCK_BRITNEY}
736 TIME="apt-ftparchive cleanup"
750 log "Daily cron scripts successful, all done"
752 exec > "$logdir/afterdinstall.log" 2>&1
754 cat "$LOGFILE" | mail -s "Log for dinstall run of ${NOW}" cron@ftp-master.debian.org
765 # Now, at the very (successful) end of dinstall, make sure we remove
766 # our stage files, so the next dinstall run will do it all again.
768 touch "${DINSTALLEND}"