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
23 # ERR traps should be inherited from functions too. (And command
24 # substitutions and subshells and whatnot, but for us the functions is
25 # the important part here)
28 # import the general variable set.
29 export SCRIPTVARS=/srv/ftp.debian.org/dak/config/debian/vars
32 ########################################################################
34 ########################################################################
35 # common functions are "outsourced"
36 . "${configdir}/common"
38 # Timestamp. Used for dinstall stat graphs
41 echo "Archive maintenance timestamp $TS ($1): $(date +%H:%M:%S)"
47 rm -f ${LOCK_ACCEPTED}
50 # If we error out this one is called, *FOLLOWED* by cleanup above
52 ERRDATE=$(date "+%Y.%m.%d-%H:%M:%S")
53 cat "$LOGFILE" | mail -s "ATTENTION ATTENTION! dinstall error at ${ERRDATE} (Be quiet, Brain, or I'll stab you with a Q-tip)" cron@ftp-master.debian.org
56 ########################################################################
57 # the actual dinstall functions follow #
58 ########################################################################
60 # Setup the notice file to tell bad mirrors they used the wrong time
64 Packages are currently being installed and indices rebuilt.
65 Maintenance is automatic, starting at 01|07|13|19:52 UTC,
66 and ending about an hour later. This file is then removed.
68 You should not mirror the archive during this period.
72 # pushing merkels QA user, part one
74 log "Telling merkels QA user that we start dinstall"
75 ssh -2 -i ~dak/.ssh/push_merkel_qa -o BatchMode=yes -o SetupTimeOut=90 -o ConnectTimeout=90 qa@merkel.debian.org sleep 1
78 # Create the postgres dump files
79 function pgdump_pre() {
80 log "Creating pre-daily-cron-job backup of projectb database..."
81 pg_dump projectb > $base/backup/dump_pre_$(date +%Y.%m.%d-%H:%M:%S)
84 function pgdump_post() {
85 log "Creating post-daily-cron-job backup of projectb database..."
87 POSTDUMP=$(date +%Y.%m.%d-%H:%M:%S)
88 pg_dump projectb > $base/backup/dump_$POSTDUMP
89 pg_dumpall --globals-only > $base/backup/dumpall_$POSTDUMP
90 ln -sf $base/backup/dump_$POSTDUMP current
91 ln -sf $base/backup/dumpall_$POSTDUMP currentall
94 # Load the dak-dev projectb
97 echo "drop database projectb" | psql -p 5433 template1
98 cat currentall | psql -p 5433 template1
99 createdb -p 5433 -T template0 projectb
100 fgrep -v '\connect' current | psql -p 5433 projectb
103 # Updating various files
105 log "Updating Bugs docu, Mirror list and mailing-lists.txt"
107 $scriptsdir/update-bugdoctxt
108 $scriptsdir/update-mirrorlists
109 $scriptsdir/update-mailingliststxt
110 $scriptsdir/update-pseudopackages.sh
113 # Process (oldstable)-proposed-updates "NEW" queue
114 function punew_do() {
115 cd "${queuedir}/${1}"
117 dak process-new -a -C COMMENTS >> REPORT || true
121 log "Doing automated p-u-new processing"
125 log "Doing automated o-p-u-new processing"
129 # The first i18n one, syncing new descriptions
131 log "Synchronizing i18n package descriptions"
132 # First sync their newest data
133 cd ${scriptdir}/i18nsync
134 rsync -aq --delete --delete-after ddtp-sync:/does/not/matter . || true
136 # Now check if we still know about the packages for which they created the files
137 # is the timestamp signed by us?
138 if $(gpgv --keyring /srv/ftp.debian.org/s3kr1t/dot-gnupg/pubring.gpg timestamp.gpg timestamp); then
139 # now read it. As its signed by us we are sure the content is what we expect, no need
140 # to do more here. And we only test -d a directory on it anyway.
141 TSTAMP=$(cat timestamp)
142 # do we have the dir still?
143 if [ -d ${scriptdir}/i18n/${TSTAMP} ]; then
145 if ${scriptsdir}/ddtp-i18n-check.sh . ${scriptdir}/i18n/${TSTAMP}; then
146 # Yay, worked, lets copy around
147 for dir in squeeze sid; do
148 if [ -d dists/${dir}/ ]; then
149 cd dists/${dir}/main/i18n
150 rsync -aq --delete --delete-after . ${ftpdir}/dists/${dir}/main/i18n/.
152 cd ${scriptdir}/i18nsync
155 echo "ARRRR, bad guys, wrong files, ARRR"
156 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
159 echo "ARRRR, missing the timestamp ${TSTAMP} directory, not updating i18n, ARRR"
160 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
163 echo "ARRRRRRR, could not verify our timestamp signature, ARRR. Don't mess with our files, i18n guys, ARRRRR."
164 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
168 # Process the accepted queue
169 function accepted() {
170 log "Processing queue/accepted"
171 rm -f "$accepted/REPORT"
172 dak process-accepted -pa -d "$accepted" > "$accepted/REPORT"
173 cat "$accepted/REPORT" | mail -s "Install for $(date +"%D - %R")" ftpmaster@ftp-master.debian.org
174 chgrp debadmin "$accepted/REPORT"
175 chmod 664 "$accepted/REPORT"
179 log "Checking for cruft in overrides"
182 log "Fixing symlinks in $ftpdir"
183 symlinks -d -r $ftpdir
187 log "Generating suite file lists for apt-ftparchive"
188 dak make-suite-file-list
191 function fingerprints() {
192 log "Updating fingerprints"
193 dak import-keyring -L /srv/keyring.debian.org/keyrings/debian-keyring.gpg
196 function overrides() {
197 log "Writing overrides into text files"
202 rm -f override.sid.all3
203 for i in main contrib non-free main.debian-installer; do cat override.sid.$i >> override.sid.all3; done
207 log "Generating package / file mapping"
208 dak make-pkg-file-mapping | bzip2 -9 > $base/ftp/indices/package-file.map.bz2
211 function packages() {
212 log "Generating Packages and Sources files"
214 apt-ftparchive generate apt.conf
218 log "Generating pdiff files"
219 dak generate-index-diffs
223 log "Generating Release files"
224 dak generate-releases
227 function dakcleanup() {
228 log "Cleanup old packages/files"
229 dak clean-suites -m 10000
234 # Needs to be rebuilt, as files have moved. Due to unaccepts, we need to
235 # update this before wanna-build is updated.
236 log "Regenerating wanna-build/buildd information"
237 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
238 symlinks -d /srv/incoming.debian.org/buildd > /dev/null
239 apt-ftparchive generate apt.conf.buildd
242 function buildd_dir() {
243 # Rebuilt the buildd dir to avoid long times of 403
244 log "Regenerating the buildd incoming dir"
245 STAMP=$(date "+%Y%m%d%H%M")
250 log "Running various scripts from $scriptsdir"
260 echo "Regenerating \"public\" mirror/ hardlink fun"
262 rsync -aH --link-dest ${ftpdir} --exclude Archive_Maintenance_In_Progress --delete --delete-after --ignore-errors ${ftpdir}/. .
266 log "Trigger daily wanna-build run"
267 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
271 log "Expiring old database dumps..."
273 $scriptsdir/expire_dumps -d . -p -f "dump_*"
276 function transitionsclean() {
277 log "Removing out of date transitions..."
279 dak transitions -c -a
283 # Send a report on NEW/BYHAND packages
284 log "Nagging ftpteam about NEW/BYHAND packages"
285 dak queue-report | mail -e -s "NEW and BYHAND on $(date +%D)" ftpmaster@ftp-master.debian.org
286 # and one on crufty packages
287 log "Sending information about crufty packages"
288 dak cruft-report > $webdir/cruft-report-daily.txt
289 dak cruft-report -s experimental >> $webdir/cruft-report-daily.txt
290 cat $webdir/cruft-report-daily.txt | mail -e -s "Debian archive cruft report for $(date +%D)" ftpmaster@ftp-master.debian.org
294 log "Updating DM html page"
295 $scriptsdir/dm-monitor >$webdir/dm-uploaders.html
299 log "Categorizing uncategorized bugs filed against ftp.debian.org"
304 # Push dak@merkel so it syncs the projectb there. Returns immediately, the sync runs detached
305 log "Trigger merkel/flotows projectb sync"
306 ssh -2 -o BatchMode=yes -o SetupTimeOut=30 -o ConnectTimeout=30 -i ~/.ssh/push_merkel_projectb dak@merkel.debian.org sleep 1
307 # Also trigger flotow, the ftpmaster test box
308 ssh -2 -o BatchMode=yes -o SetupTimeOut=30 -o ConnectTimeout=30 -i ~/.ssh/push_flotow_projectb dak@flotow.debconf.org sleep 1
312 # Push dak@merkel to tell it to sync the dd accessible parts. Returns immediately, the sync runs detached
313 log "Trigger merkels dd accessible parts sync"
314 ssh -2 -o BatchMode=yes -o SetupTimeOut=30 -o ConnectTimeout=30 -i ~/.ssh/push_merkel_ddaccess dak@merkel.debian.org sleep 1
317 function runparts() {
318 log "Using run-parts to run scripts in $base/scripts/distmnt"
319 run-parts --report $base/scripts/distmnt
323 log "Exporting package data foo for i18n project"
324 STAMP=$(date "+%Y%m%d%H%M")
325 mkdir -p ${scriptdir}/i18n/${STAMP}
326 cd ${scriptdir}/i18n/${STAMP}
327 dak control-suite -l stable > lenny
328 dak control-suite -l testing > squeeze
329 dak control-suite -l unstable > sid
330 echo "${STAMP}" > timestamp
331 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
335 ln -sfT ${scriptdir}/i18n/${STAMP} i18n
338 find ./i18n -mindepth 1 -maxdepth 1 -mtime +2 -not -name "${STAMP}" -type d -print0 | xargs --no-run-if-empty -0 rm -rf
342 log "Updating stats data"
344 $scriptsdir/update-ftpstats $base/log/* > $base/misc/ftpstats.data
345 R --slave --vanilla < $base/misc/ftpstats.R
346 dak stats arch-space > $webdir/arch-space
347 dak stats pkg-nums > $webdir/pkg-nums
350 function aptftpcleanup() {
351 log "Clean up apt-ftparchive's databases"
353 apt-ftparchive -q clean apt.conf
356 function compress() {
357 log "Compress old psql backups"
359 find -maxdepth 1 -mindepth 1 -type f -name 'dump_pre_*' -mtime +2 -print0 | xargs -0 --no-run-if-empty rm
361 find -maxdepth 1 -mindepth 1 -type f -name 'dump_*' \! -name '*.bz2' \! -name '*.gz' -mmin +720 |
362 while read dumpname; do
363 echo "Compressing $dumpname"
364 bzip2 -9fv "$dumpname"
366 find -maxdepth 1 -mindepth 1 -type f -name "dumpall_*" \! -name '*.bz2' \! -name '*.gz' -mmin +720 |
367 while read dumpname; do
368 echo "Compressing $dumpname"
369 bzip2 -9fv "$dumpname"
371 finddup -l -d $base/backup
374 function logstats() {
375 $masterdir/tools/logs.py "$1"
378 # save timestamp when we start
379 function savetimestamp() {
380 NOW=`date "+%Y.%m.%d-%H:%M:%S"`
381 echo ${NOW} > "${dbdir}/dinstallstart"
384 function maillogfile() {
385 cat "$LOGFILE" | mail -s "Log for dinstall run of ${NOW}" cron@ftp-master.debian.org
388 function renamelogfile() {
389 if [ -f "${dbdir}/dinstallstart" ]; then
390 NOW=$(cat "${dbdir}/dinstallstart")
392 mv "$LOGFILE" "$logdir/dinstall_${NOW}.log"
393 logstats "$logdir/dinstall_${NOW}.log"
394 bzip2 -9 "$logdir/dinstall_${NOW}.log"
396 error "Problem, I don't know when dinstall started, unable to do log statistics."
397 NOW=`date "+%Y.%m.%d-%H:%M:%S"`
399 mv "$LOGFILE" "$logdir/dinstall_${NOW}.log"
400 bzip2 -9 "$logdir/dinstall_${NOW}.log"
404 function testingsourcelist() {
405 dak ls -s testing -f heidi -r .| egrep 'source$' > ${webdir}/testing.list
408 # do a last run of process-unchecked before dinstall is on.
409 function process_unchecked() {
410 log "Processing the unchecked queue"
412 UNCHECKED_WITHOUT_LOCK="-p"
417 ########################################################################
418 ########################################################################
420 # Function to save which stage we are in, so we can restart an interrupted
421 # dinstall. Or even run actions in parallel, if we dare to, by simply
422 # backgrounding the call to this function. But that should only really be
423 # done for things we dont care much about.
425 # This should be called with the first argument being an array, with the
427 # - FUNC - the function name to call
428 # - ARGS - Possible arguments to hand to the function. Can be the empty string
429 # - TS - The timestamp name. Can be the empty string
430 # - ERR - if this is the string false, then the call will be surrounded by
431 # set +e ... set -e calls, so errors in the function do not exit
432 # dinstall. Can be the empty string, meaning true.
434 # MAKE SURE TO KEEP THIS THE LAST FUNCTION, AFTER ALL THE VARIOUS ONES
435 # ADDED FOR DINSTALL FEATURES!
440 if [ -f "${stagedir}/${FUNC}" ]; then
441 stamptime=$(/usr/bin/stat -c %Z "${stagedir}/${FUNC}")
443 difference=$(( $unixtime - $stamptime ))
444 if [ ${difference} -ge 14400 ]; then
445 log_error "Did already run ${FUNC}, stagefile exists, but that was ${difference} seconds ago. Please check."
447 log "Did already run ${FUNC}, not calling again..."
452 debug "Now calling function ${FUNC}. Arguments: ${ARGS}. Timestamp: ${TS}"
454 # Make sure we are always at the same place. If a function wants to be elsewhere,
455 # it has to cd first!
458 if [ -f "${LOCK_STOP}" ]; then
459 log "${LOCK_STOP} exists, exiting immediately"
463 if [ "${ERR}" = "false" ]; then
468 # No matter what happened in the function, we make sure we have set -e default state back
471 # Make sure we are always at the same place.
474 touch "${stagedir}/${FUNC}"
476 if [ -n "${TIME}" ]; then
480 if [ -f "${LOCK_STOP}" ]; then
481 log "${LOCK_STOP} exists, exiting immediately"
486 ########################################################################
489 LOGFILE="$logdir/dinstall.log"
491 exec >> "$LOGFILE" 2>&1
493 # usually we are not using debug logs. Set to 1 if you want them.
499 # where do we want mails to go? For example log entries made with error()
500 if [ "x$(hostname -s)x" != "xriesx" ]; then
501 # Not our ftpmaster host
502 MAILTO=${MAILTO:-"root"}
505 MAILTO=${MAILTO:-"ftpmaster@debian.org"}
508 # How many logfiles to keep
509 LOGROTATE=${LOGROTATE:-400}
511 # Marker for dinstall start
512 DINSTALLSTART="${lockdir}/dinstallstart"
513 # Marker for dinstall end
514 DINSTALLEND="${lockdir}/dinstallend"
516 # Timestamps start at -1. so first gets 0
518 touch "${DINSTALLSTART}"
521 # Tell everyone we are doing some work
522 NOTICE="$ftpdir/Archive_Maintenance_In_Progress"
524 # lock cron.unchecked (it immediately exits when this exists)
525 LOCK_DAILY="$lockdir/daily.lock"
527 # Lock cron.unchecked from doing work
528 LOCK_ACCEPTED="$lockdir/unchecked.lock"
530 # Lock process-new from doing work
531 LOCK_NEW="$lockdir/processnew.lock"
533 # This file is simply used to indicate to britney whether or not
534 # the Packages file updates completed sucessfully. It's not a lock
535 # from our point of view
536 LOCK_BRITNEY="$lockdir/britney.lock"
538 # If this file exists we exit immediately after the currently running
540 LOCK_STOP="$lockdir/archive.stop"
542 lockfile -l 3600 "${LOCK_DAILY}"
544 trap cleanup EXIT TERM HUP INT QUIT
546 touch "${LOCK_BRITNEY}"
582 TIME="External Updates"
612 lockfile "$LOCK_ACCEPTED"
616 FUNC="process_unchecked"
648 rm -f "$LOCK_ACCEPTED"
653 TIME="make-suite-file-list"
661 TIME="import-keyring"
677 TIME="pkg-file-mapping"
685 TIME="apt-ftparchive"
733 TIME="mirror hardlinks"
748 rm -f "${LOCK_DAILY}"
750 ts "locked part finished"
769 FUNC="transitionsclean"
770 TIME="transitionsclean"
802 TIME="merkel projectb push"
833 FUNC="testingsourcelist"
840 rm -f ${LOCK_BRITNEY}
852 TIME="apt-ftparchive cleanup"
860 TIME="merkel ddaccessible sync"
874 log "Daily cron scripts successful, all done"
876 exec > "$logdir/afterdinstall.log" 2>&1
887 # Now, at the very (successful) end of dinstall, make sure we remove
888 # our stage files, so the next dinstall run will do it all again.
890 touch "${DINSTALLEND}"