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 # log something (basically echo it together with a timestamp)
33 # Set $PROGRAM to a string to have it added to the output.
35 if [ -z "${PROGRAM}" ]; then
36 echo "$(date +"%b %d %H:%M:%S") $(hostname -s) [$$] $@"
38 echo "$(date +"%b %d %H:%M:%S") $(hostname -s) ${PROGRAM}[$$]: $@"
42 # log the message using log() but then also send a mail
43 # to the address configured in MAILTO (if non-empty)
44 function log_error () {
46 if [ -z "${MAILTO}" ]; then
47 echo "$@" | mail -e -s "[$PROGRAM@$(hostname -s)] ERROR [$$]" ${MAILTO}
51 # debug log, only output when DEBUG=1
53 if [ $DEBUG -eq 1 ]; then
58 # Timestamp. Used for dinstall stat graphs
61 echo "Archive maintenance timestamp $TS ($1): $(date +%H:%M:%S)"
67 rm -f ${LOCK_ACCEPTED}
70 ########################################################################
71 # the actual dinstall functions follow #
72 ########################################################################
74 # Setup the notice file to tell bad mirrors they used the wrong time
78 Packages are currently being installed and indices rebuilt.
79 Maintenance is automatic, starting at 01|07|13|19:52 UTC,
80 and ending about an hour later. This file is then removed.
82 You should not mirror the archive during this period.
86 # pushing merkels QA user, part one
88 log "Telling merkels QA user that we start dinstall"
89 ssh -2 -i ~dak/.ssh/push_merkel_qa -o BatchMode=yes -o SetupTimeOut=90 -o ConnectTimeout=90 qa@merkel.debian.org sleep 1
92 # Create the postgres dump files
93 function pgdump_pre() {
94 log "Creating pre-daily-cron-job backup of projectb database..."
95 pg_dump projectb > $base/backup/dump_$(date +%Y.%m.%d-%H:%M:%S)
98 function pgdump_post() {
99 log "Creating post-daily-cron-job backup of projectb database..."
101 POSTDUMP=$base/backup/dump_$(date +%Y.%m.%d-%H:%M:%S)
102 pg_dump projectb > $POSTDUMP
103 ln -sf $POSTDUMP current
106 # Updating various files
108 log "Updating Bugs docu, Mirror list and mailing-lists.txt"
110 $scriptsdir/update-bugdoctxt
111 $scriptsdir/update-mirrorlists
112 $scriptsdir/update-mailingliststxt
113 $scriptsdir/update-pseudopackages.sh
116 # Process (oldstable)-proposed-updates "NEW" queue
117 function punew_do() {
118 cd "${queuedir}/${1}"
120 dak process-new -a -C COMMENTS >> REPORT || true
124 log "Doing automated p-u-new processing"
128 log "Doing automated o-p-u-new processing"
132 # The first i18n one, syncing new descriptions
134 log "Synchronizing i18n package descriptions"
135 # First sync their newest data
136 cd ${scriptdir}/i18nsync
137 rsync -aq --delete --delete-after ddtp-sync:/does/not/matter . || true
139 # Now check if we still know about the packages for which they created the files
140 # is the timestamp signed by us?
141 if $(gpgv --keyring /srv/ftp.debian.org/s3kr1t/dot-gnupg/pubring.gpg timestamp.gpg timestamp); then
142 # now read it. As its signed by us we are sure the content is what we expect, no need
143 # to do more here. And we only test -d a directory on it anyway.
144 TSTAMP=$(cat timestamp)
145 # do we have the dir still?
146 if [ -d ${scriptdir}/i18n/${TSTAMP} ]; then
148 if ${scriptsdir}/ddtp-i18n-check.sh . ${scriptdir}/i18n/${TSTAMP}; then
149 # Yay, worked, lets copy around
150 for dir in squeeze sid; do
151 if [ -d dists/${dir}/ ]; then
152 cd dists/${dir}/main/i18n
153 rsync -aq --delete --delete-after . ${ftpdir}/dists/${dir}/main/i18n/.
155 cd ${scriptdir}/i18nsync
158 echo "ARRRR, bad guys, wrong files, ARRR"
159 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
162 echo "ARRRR, missing the timestamp ${TSTAMP} directory, not updating i18n, ARRR"
163 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
166 echo "ARRRRRRR, could not verify our timestamp signature, ARRR. Don't mess with our files, i18n guys, ARRRRR."
167 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
171 # Process the accepted queue
172 function accepted() {
173 log "Processing queue/accepted"
174 rm -f "$accepted/REPORT"
175 dak process-accepted -pa -d "$accepted" > "$accepted/REPORT"
176 cat "$accepted/REPORT" | mail -s "Install for $(date +"%D - %R")" ftpmaster@ftp-master.debian.org
177 chgrp debadmin "$accepted/REPORT"
178 chmod 664 "$accepted/REPORT"
182 log "Checking for cruft in overrides"
185 log "Fixing symlinks in $ftpdir"
186 symlinks -d -r $ftpdir
190 log "Generating suite file lists for apt-ftparchive"
191 dak make-suite-file-list
194 function fingerprints() {
195 log "Updating fingerprints"
196 dak import-keyring -L /srv/keyring.debian.org/keyrings/debian-keyring.gpg
199 function overrides() {
200 log "Writing overrides into text files"
205 rm -f override.sid.all3
206 for i in main contrib non-free main.debian-installer; do cat override.sid.$i >> override.sid.all3; done
210 log "Generating package / file mapping"
211 dak make-pkg-file-mapping | bzip2 -9 > $base/ftp/indices/package-file.map.bz2
214 function packages() {
215 log "Generating Packages and Sources files"
217 apt-ftparchive generate apt.conf
221 log "Generating pdiff files"
222 dak generate-index-diffs
226 log "Generating Release files"
227 dak generate-releases
230 function dakcleanup() {
231 log "Cleanup old packages/files"
237 # Needs to be rebuilt, as files have moved. Due to unaccepts, we need to
238 # update this before wanna-build is updated.
239 log "Regenerating wanna-build/buildd information"
240 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
241 symlinks -d /srv/incoming.debian.org/buildd > /dev/null
242 apt-ftparchive generate apt.conf.buildd
246 log "Running various scripts from $scriptsdir"
256 echo "Regenerating \"public\" mirror/ hardlink fun"
258 rsync -aH --link-dest ${ftpdir} --delete --delete-after --ignore-errors ${ftpdir}/. .
262 log "Trigger daily wanna-build run"
263 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
267 log "Expiring old database dumps..."
269 $scriptsdir/expire_dumps -d . -p -f "dump_*"
273 # Send a report on NEW/BYHAND packages
274 log "Nagging ftpteam about NEW/BYHAND packages"
275 dak queue-report | mail -e -s "NEW and BYHAND on $(date +%D)" ftpmaster@ftp-master.debian.org
276 # and one on crufty packages
277 log "Sending information about crufty packages"
278 dak cruft-report > $webdir/cruft-report-daily.txt
279 dak cruft-report -s experimental >> $webdir/cruft-report-daily.txt
280 cat $webdir/cruft-report-daily.txt | mail -e -s "Debian archive cruft report for $(date +%D)" ftpmaster@ftp-master.debian.org
284 log "Updating DM html page"
285 $scriptsdir/dm-monitor >$webdir/dm-uploaders.html
289 log "Categorizing uncategorized bugs filed against ftp.debian.org"
294 # Push katie@merkel so it syncs the projectb there. Returns immediately, the sync runs detached
295 log "Trigger merkels projectb sync"
296 ssh -2 -o BatchMode=yes -o SetupTimeOut=30 -o ConnectTimeout=30 -i ~/.ssh/push_merkel_projectb katie@merkel.debian.org sleep 1
299 function runparts() {
300 log "Using run-parts to run scripts in $base/scripts/distmnt"
301 run-parts --report $base/scripts/distmnt
305 log "Exporting package data foo for i18n project"
306 STAMP=$(date "+%Y%m%d%H%M")
307 mkdir -p ${scriptdir}/i18n/${STAMP}
308 cd ${scriptdir}/i18n/${STAMP}
309 dak control-suite -l stable > lenny
310 dak control-suite -l testing > squeeze
311 dak control-suite -l unstable > sid
312 echo "${STAMP}" > timestamp
313 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
317 ln -sfT ${scriptdir}/i18n/${STAMP} i18n
320 find ./i18n -mindepth 1 -maxdepth 1 -mtime +2 -not -name "${STAMP}" -type d -print0 | xargs --no-run-if-empty -0 rm -rf
324 log "Updating stats data"
326 $scriptsdir/update-ftpstats $base/log/* > $base/misc/ftpstats.data
327 R --slave --vanilla < $base/misc/ftpstats.R
330 function aptftpcleanup() {
331 log "Clean up apt-ftparchive's databases"
333 apt-ftparchive -q clean apt.conf
336 function compress() {
337 log "Compress old psql backups"
339 find -maxdepth 1 -mindepth 1 -type f -name 'dump_*' \! -name '*.bz2' \! -name '*.gz' -mtime +1 |
340 while read dumpname; do
341 echo "Compressing $dumpname"
342 bzip2 -9v "$dumpname"
346 function logstats() {
347 $masterdir/tools/logs.py "$1"
350 # save timestamp when we start
351 function savetimestamp() {
352 NOW=`date "+%Y.%m.%d-%H:%M:%S"`
353 echo ${NOW} > "${dbdir}/dinstallstart"
356 function renamelogfile() {
357 if [ -f "${dbdir}/dinstallstart" ]; then
358 RENAMETO=$(cat "${dbdir}/dinstallstart")
359 mv "$LOGFILE" "$logdir/dinstall_${RENAMETO}.log"
360 logstats "$logdir/dinstall_${RENAMETO}.log"
361 bzip2 -9 "$logdir/dinstall_${RENAMETO}.log"
363 error "Problem, I don't know when dinstall started, unable to do log statistics."
364 NOW=`date "+%Y.%m.%d-%H:%M:%S"`
365 mv "$LOGFILE" "$logdir/dinstall_${NOW}.log"
366 bzip2 -9 "$logdir/dinstall_${NOW}.log"
370 ########################################################################
371 ########################################################################
373 # Function to save which stage we are in, so we can restart an interrupted
374 # dinstall. Or even run actions in parallel, if we dare to, by simply
375 # backgrounding the call to this function. But that should only really be
376 # done for things we dont care much about.
378 # This should be called with the first argument being an array, with the
380 # - FUNC - the function name to call
381 # - ARGS - Possible arguments to hand to the function. Can be the empty string
382 # - TS - The timestamp name. Can be the empty string
383 # - ERR - if this is the string false, then the call will be surrounded by
384 # set +e ... set -e calls, so errors in the function do not exit
385 # dinstall. Can be the empty string, meaning true.
387 # MAKE SURE TO KEEP THIS THE LAST FUNCTION, AFTER ALL THE VARIOUS ONES
388 # ADDED FOR DINSTALL FEATURES!
393 if [ -f "${stagedir}/${FUNC}" ]; then
394 stamptime=$(/usr/bin/stat -c %Z "${stagedir}/${FUNC}")
396 difference=$(( $unixtime - $stamptime ))
397 if [ ${difference} -ge 14400 ]; then
398 log_error "Did already run ${FUNC}, stagefile exists, but that was ${difference} seconds ago. Please check."
400 log "Did already run ${FUNC}, not calling again..."
405 debug "Now calling function ${FUNC}. Arguments: ${ARGS}. Timestamp: ${TS}"
407 # Make sure we are always at the same place. If a function wants to be elsewhere,
408 # it has to cd first!
411 if [ -f "${LOCK_STOP}" ]; then
412 log "${LOCK_STOP} exists, exiting immediately"
416 if [ "${ERR}" = "false" ]; then
421 # No matter what happened in the function, we make sure we have set -e default state back
424 # Make sure we are always at the same place.
427 touch "${stagedir}/${FUNC}"
429 if [ -f "${LOCK_STOP}" ]; then
430 log "${LOCK_STOP} exists, exiting immediately"
434 if [ -n "${TIME}" ]; then
439 ########################################################################
442 LOGFILE="$logdir/dinstall.log"
444 exec >> "$LOGFILE" 2>&1
446 # usually we are not using debug logs. Set to 1 if you want them.
452 # where do we want mails to go? For example log entries made with error()
453 if [ "x$(hostname -s)x" != "xriesx" ]; then
454 # Not our ftpmaster host
455 MAILTO=${MAILTO:-"root"}
458 MAILTO=${MAILTO:-"ftpmaster@debian.org"}
461 # How many logfiles to keep
462 LOGROTATE=${LOGROTATE:-400}
464 # Timestamps start at -1. so first gets 0
468 # Tell everyone we are doing some work
469 NOTICE="$ftpdir/Archive_Maintenance_In_Progress"
471 # lock cron.unchecked (it immediately exits when this exists)
472 LOCK_DAILY="$lockdir/daily.lock"
474 # Lock process-new and cron.unchecked from doing work
475 LOCK_ACCEPTED="$lockdir/unchecked.lock"
477 # This file is simply used to indicate to britney whether or not
478 # the Packages file updates completed sucessfully. It's not a lock
479 # from our point of view
480 LOCK_BRITNEY="$lockdir/britney.lock"
482 # If this file exists we exit immediately after the currently running
484 LOCK_STOP="$lockdir/archive.stop"
486 lockfile -l 3600 "${LOCK_DAILY}"
487 trap cleanup EXIT ERR TERM HUP INT QUIT
489 touch "${LOCK_BRITNEY}"
525 TIME="External Updates"
555 lockfile "$LOCK_ACCEPTED"
573 rm -f "$LOCK_ACCEPTED"
577 TIME="make-suite-file-list"
585 TIME="import-keyring"
601 TIME="pkg-file-mapping"
609 TIME="apt-ftparchive"
657 TIME="mirror hardlinks"
672 rm -f "${LOCK_DAILY}"
674 ts "locked part finished"
718 TIME="merkel projectb push"
724 ulimit -m 90000 -d 90000 -s 10000 -v 200000
750 rm -f ${LOCK_BRITNEY}
754 TIME="apt-ftparchive cleanup"
768 log "Daily cron scripts successful, all done"
770 exec > /dev/null 2>&1
772 cat "$LOGFILE" | mail -s "Log for dinstall run of ${NOW}" cron@ftp-master.debian.org
783 # Now, at the very (successful) end of dinstall, make sure we remove
784 # our stage files, so the next dinstall run will do it all again.
785 rm -f "${stagedir}/*"