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 # If we error out this one is called, *FOLLOWED* by cleanup above
48 ERRDATE=$(date "+%Y.%m.%d-%H:%M:%S")
49 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
52 ########################################################################
53 # the actual dinstall functions follow #
54 ########################################################################
56 # Setup the notice file to tell bad mirrors they used the wrong time
60 Packages are currently being installed and indices rebuilt.
61 Maintenance is automatic, starting at 01|07|13|19:52 UTC,
62 and ending about an hour later. This file is then removed.
64 You should not mirror the archive during this period.
68 # pushing merkels QA user, part one
70 log "Telling merkels QA user that we start dinstall"
71 ssh -2 -i ~dak/.ssh/push_merkel_qa -o BatchMode=yes -o SetupTimeOut=90 -o ConnectTimeout=90 qa@merkel.debian.org sleep 1
74 # Create the postgres dump files
75 function pgdump_pre() {
76 log "Creating pre-daily-cron-job backup of projectb database..."
77 pg_dump projectb > $base/backup/dump_pre_$(date +%Y.%m.%d-%H:%M:%S)
80 function pgdump_post() {
81 log "Creating post-daily-cron-job backup of projectb database..."
83 POSTDUMP=$(date +%Y.%m.%d-%H:%M:%S)
84 pg_dump projectb > $base/backup/dump_$POSTDUMP
85 pg_dumpall --globals-only > $base/backup/dumpall_$POSTDUMP
86 ln -sf $base/backup/dump_$POSTDUMP current
87 ln -sf $base/backup/dumpall_$POSTDUMP currentall
90 # Load the dak-dev projectb
93 echo "drop database projectb" | psql -p 5433 template1
94 cat currentall | psql -p 5433 template1
95 createdb -p 5433 -T template0 projectb
96 fgrep -v '\connect' current | psql -p 5433 projectb
99 # Updating various files
101 log "Updating Bugs docu, Mirror list and mailing-lists.txt"
103 $scriptsdir/update-bugdoctxt
104 $scriptsdir/update-mirrorlists
105 $scriptsdir/update-mailingliststxt
106 $scriptsdir/update-pseudopackages.sh
109 # Process (oldstable)-proposed-updates "NEW" queue
110 function punew_do() {
111 cd "${queuedir}/${1}"
113 dak process-new -a -C COMMENTS >> REPORT || true
117 log "Doing automated p-u-new processing"
121 log "Doing automated o-p-u-new processing"
125 # The first i18n one, syncing new descriptions
127 log "Synchronizing i18n package descriptions"
128 # First sync their newest data
129 cd ${scriptdir}/i18nsync
130 rsync -aq --delete --delete-after ddtp-sync:/does/not/matter . || true
132 # Now check if we still know about the packages for which they created the files
133 # is the timestamp signed by us?
134 if $(gpgv --keyring /srv/ftp.debian.org/s3kr1t/dot-gnupg/pubring.gpg timestamp.gpg timestamp); then
135 # now read it. As its signed by us we are sure the content is what we expect, no need
136 # to do more here. And we only test -d a directory on it anyway.
137 TSTAMP=$(cat timestamp)
138 # do we have the dir still?
139 if [ -d ${scriptdir}/i18n/${TSTAMP} ]; then
141 if ${scriptsdir}/ddtp-i18n-check.sh . ${scriptdir}/i18n/${TSTAMP}; then
142 # Yay, worked, lets copy around
143 for dir in squeeze sid; do
144 if [ -d dists/${dir}/ ]; then
145 cd dists/${dir}/main/i18n
146 rsync -aq --delete --delete-after . ${ftpdir}/dists/${dir}/main/i18n/.
148 cd ${scriptdir}/i18nsync
151 echo "ARRRR, bad guys, wrong files, ARRR"
152 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
155 echo "ARRRR, missing the timestamp ${TSTAMP} directory, not updating i18n, ARRR"
156 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
159 echo "ARRRRRRR, could not verify our timestamp signature, ARRR. Don't mess with our files, i18n guys, ARRRRR."
160 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
164 # Process the accepted queue
165 function accepted() {
166 log "Processing queue/accepted"
167 rm -f "$accepted/REPORT"
168 dak process-accepted -pa -d "$accepted" > "$accepted/REPORT"
169 cat "$accepted/REPORT" | mail -s "Install for $(date +"%D - %R")" ftpmaster@ftp-master.debian.org
170 chgrp debadmin "$accepted/REPORT"
171 chmod 664 "$accepted/REPORT"
175 log "Checking for cruft in overrides"
178 log "Fixing symlinks in $ftpdir"
179 symlinks -d -r $ftpdir
183 log "Generating suite file lists for apt-ftparchive"
184 dak make-suite-file-list
187 function fingerprints() {
188 log "Updating fingerprints"
189 dak import-keyring -L /srv/keyring.debian.org/keyrings/debian-keyring.gpg
192 function overrides() {
193 log "Writing overrides into text files"
198 rm -f override.sid.all3
199 for i in main contrib non-free main.debian-installer; do cat override.sid.$i >> override.sid.all3; done
203 log "Generating package / file mapping"
204 dak make-pkg-file-mapping | bzip2 -9 > $base/ftp/indices/package-file.map.bz2
207 function packages() {
208 log "Generating Packages and Sources files"
210 apt-ftparchive generate apt.conf
214 log "Generating pdiff files"
215 dak generate-index-diffs
219 log "Generating Release files"
220 dak generate-releases
223 function dakcleanup() {
224 log "Cleanup old packages/files"
225 dak clean-suites -m 10000
230 # Needs to be rebuilt, as files have moved. Due to unaccepts, we need to
231 # update this before wanna-build is updated.
232 log "Regenerating wanna-build/buildd information"
233 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
234 symlinks -d /srv/incoming.debian.org/buildd > /dev/null
235 apt-ftparchive generate apt.conf.buildd
238 function buildd_dir() {
239 # Rebuilt the buildd dir to avoid long times of 403
240 log "Regenerating the buildd incoming dir"
241 STAMP=$(date "+%Y%m%d%H%M")
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_*"
272 function transitionsclean() {
273 log "Removing out of date transitions..."
275 dak transitions -c -a
279 # Send a report on NEW/BYHAND packages
280 log "Nagging ftpteam about NEW/BYHAND packages"
281 dak queue-report | mail -e -s "NEW and BYHAND on $(date +%D)" ftpmaster@ftp-master.debian.org
282 # and one on crufty packages
283 log "Sending information about crufty packages"
284 dak cruft-report > $webdir/cruft-report-daily.txt
285 dak cruft-report -s experimental >> $webdir/cruft-report-daily.txt
286 cat $webdir/cruft-report-daily.txt | mail -e -s "Debian archive cruft report for $(date +%D)" ftpmaster@ftp-master.debian.org
290 log "Updating DM html page"
291 $scriptsdir/dm-monitor >$webdir/dm-uploaders.html
295 log "Categorizing uncategorized bugs filed against ftp.debian.org"
300 # Push dak@merkel so it syncs the projectb there. Returns immediately, the sync runs detached
301 log "Trigger merkel/flotows projectb sync"
302 ssh -2 -o BatchMode=yes -o SetupTimeOut=30 -o ConnectTimeout=30 -i ~/.ssh/push_merkel_projectb dak@merkel.debian.org sleep 1
303 # Also trigger flotow, the ftpmaster test box
304 ssh -2 -o BatchMode=yes -o SetupTimeOut=30 -o ConnectTimeout=30 -i ~/.ssh/push_flotow_projectb dak@flotow.debconf.org sleep 1
308 # Push dak@merkel to tell it to sync the dd accessible parts. Returns immediately, the sync runs detached
309 log "Trigger merkels dd accessible parts sync"
310 ssh -2 -o BatchMode=yes -o SetupTimeOut=30 -o ConnectTimeout=30 -i ~/.ssh/push_merkel_ddaccess dak@merkel.debian.org sleep 1
313 function runparts() {
314 log "Using run-parts to run scripts in $base/scripts/distmnt"
315 run-parts --report $base/scripts/distmnt
319 log "Exporting package data foo for i18n project"
320 STAMP=$(date "+%Y%m%d%H%M")
321 mkdir -p ${scriptdir}/i18n/${STAMP}
322 cd ${scriptdir}/i18n/${STAMP}
323 dak control-suite -l stable > lenny
324 dak control-suite -l testing > squeeze
325 dak control-suite -l unstable > sid
326 echo "${STAMP}" > timestamp
327 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
331 ln -sfT ${scriptdir}/i18n/${STAMP} i18n
334 find ./i18n -mindepth 1 -maxdepth 1 -mtime +2 -not -name "${STAMP}" -type d -print0 | xargs --no-run-if-empty -0 rm -rf
338 log "Updating stats data"
340 $scriptsdir/update-ftpstats $base/log/* > $base/misc/ftpstats.data
341 R --slave --vanilla < $base/misc/ftpstats.R
342 dak stats arch-space > $webdir/arch-space
343 dak stats pkg-nums > $webdir/pkg-nums
346 function aptftpcleanup() {
347 log "Clean up apt-ftparchive's databases"
349 apt-ftparchive -q clean apt.conf
352 function compress() {
353 log "Compress old psql backups"
355 find -maxdepth 1 -mindepth 1 -type f -name 'dump_pre_*' -mtime +2 -print0 | xargs -0 --no-run-if-empty rm
357 find -maxdepth 1 -mindepth 1 -type f -name 'dump_*' \! -name '*.bz2' \! -name '*.gz' -mmin +720 |
358 while read dumpname; do
359 echo "Compressing $dumpname"
360 bzip2 -9v "$dumpname"
362 find -maxdepth 1 -mindepth 1 -type f -name "dumpall_*" \! -name '*.bz2' \! -name '*.gz' -mmin +720 |
363 while read dumpname; do
364 echo "Compressing $dumpname"
365 bzip2 -9v "$dumpname"
367 finddup -l -d $base/backup
370 function logstats() {
371 $masterdir/tools/logs.py "$1"
374 # save timestamp when we start
375 function savetimestamp() {
376 NOW=`date "+%Y.%m.%d-%H:%M:%S"`
377 echo ${NOW} > "${dbdir}/dinstallstart"
380 function maillogfile() {
381 cat "$LOGFILE" | mail -s "Log for dinstall run of ${NOW}" cron@ftp-master.debian.org
384 function renamelogfile() {
385 if [ -f "${dbdir}/dinstallstart" ]; then
386 NOW=$(cat "${dbdir}/dinstallstart")
388 mv "$LOGFILE" "$logdir/dinstall_${NOW}.log"
389 logstats "$logdir/dinstall_${NOW}.log"
390 bzip2 -9 "$logdir/dinstall_${NOW}.log"
392 error "Problem, I don't know when dinstall started, unable to do log statistics."
393 NOW=`date "+%Y.%m.%d-%H:%M:%S"`
395 mv "$LOGFILE" "$logdir/dinstall_${NOW}.log"
396 bzip2 -9 "$logdir/dinstall_${NOW}.log"
400 function testingsourcelist() {
401 dak ls -s testing -f heidi -r .| egrep 'source$' > ${webdir}/testing.list
404 # do a last run of process-unchecked before dinstall is on.
405 function process_unchecked() {
406 log "Processing the unchecked queue"
408 UNCHECKED_WITHOUT_LOCK="-p"
413 ########################################################################
414 ########################################################################
416 # Function to save which stage we are in, so we can restart an interrupted
417 # dinstall. Or even run actions in parallel, if we dare to, by simply
418 # backgrounding the call to this function. But that should only really be
419 # done for things we dont care much about.
421 # This should be called with the first argument being an array, with the
423 # - FUNC - the function name to call
424 # - ARGS - Possible arguments to hand to the function. Can be the empty string
425 # - TS - The timestamp name. Can be the empty string
426 # - ERR - if this is the string false, then the call will be surrounded by
427 # set +e ... set -e calls, so errors in the function do not exit
428 # dinstall. Can be the empty string, meaning true.
430 # MAKE SURE TO KEEP THIS THE LAST FUNCTION, AFTER ALL THE VARIOUS ONES
431 # ADDED FOR DINSTALL FEATURES!
436 if [ -f "${stagedir}/${FUNC}" ]; then
437 stamptime=$(/usr/bin/stat -c %Z "${stagedir}/${FUNC}")
439 difference=$(( $unixtime - $stamptime ))
440 if [ ${difference} -ge 14400 ]; then
441 log_error "Did already run ${FUNC}, stagefile exists, but that was ${difference} seconds ago. Please check."
443 log "Did already run ${FUNC}, not calling again..."
448 debug "Now calling function ${FUNC}. Arguments: ${ARGS}. Timestamp: ${TS}"
450 # Make sure we are always at the same place. If a function wants to be elsewhere,
451 # it has to cd first!
454 if [ -f "${LOCK_STOP}" ]; then
455 log "${LOCK_STOP} exists, exiting immediately"
459 if [ "${ERR}" = "false" ]; then
464 # No matter what happened in the function, we make sure we have set -e default state back
467 # Make sure we are always at the same place.
470 touch "${stagedir}/${FUNC}"
472 if [ -n "${TIME}" ]; then
476 if [ -f "${LOCK_STOP}" ]; then
477 log "${LOCK_STOP} exists, exiting immediately"
482 ########################################################################
485 LOGFILE="$logdir/dinstall.log"
487 exec >> "$LOGFILE" 2>&1
489 # usually we are not using debug logs. Set to 1 if you want them.
495 # where do we want mails to go? For example log entries made with error()
496 if [ "x$(hostname -s)x" != "xriesx" ]; then
497 # Not our ftpmaster host
498 MAILTO=${MAILTO:-"root"}
501 MAILTO=${MAILTO:-"ftpmaster@debian.org"}
504 # How many logfiles to keep
505 LOGROTATE=${LOGROTATE:-400}
507 # Marker for dinstall start
508 DINSTALLSTART="${lockdir}/dinstallstart"
509 # Marker for dinstall end
510 DINSTALLEND="${lockdir}/dinstallend"
512 # Timestamps start at -1. so first gets 0
514 touch "${DINSTALLSTART}"
517 # Tell everyone we are doing some work
518 NOTICE="$ftpdir/Archive_Maintenance_In_Progress"
520 # lock cron.unchecked (it immediately exits when this exists)
521 LOCK_DAILY="$lockdir/daily.lock"
523 # Lock cron.unchecked from doing work
524 LOCK_ACCEPTED="$lockdir/unchecked.lock"
526 # Lock process-new from doing work
527 LOCK_NEW="$lockdir/processnew.lock"
529 # This file is simply used to indicate to britney whether or not
530 # the Packages file updates completed sucessfully. It's not a lock
531 # from our point of view
532 LOCK_BRITNEY="$lockdir/britney.lock"
534 # If this file exists we exit immediately after the currently running
536 LOCK_STOP="$lockdir/archive.stop"
538 lockfile -l 3600 "${LOCK_DAILY}"
540 trap cleanup EXIT TERM HUP INT QUIT
542 touch "${LOCK_BRITNEY}"
578 TIME="External Updates"
608 lockfile "$LOCK_ACCEPTED"
612 FUNC="process_unchecked"
644 rm -f "$LOCK_ACCEPTED"
649 TIME="make-suite-file-list"
657 TIME="import-keyring"
673 TIME="pkg-file-mapping"
681 TIME="apt-ftparchive"
729 TIME="mirror hardlinks"
744 rm -f "${LOCK_DAILY}"
746 ts "locked part finished"
765 FUNC="transitionsclean"
766 TIME="transitionsclean"
798 TIME="merkel projectb push"
829 FUNC="testingsourcelist"
836 rm -f ${LOCK_BRITNEY}
848 TIME="apt-ftparchive cleanup"
856 TIME="merkel ddaccessible sync"
870 log "Daily cron scripts successful, all done"
872 exec > "$logdir/afterdinstall.log" 2>&1
883 # Now, at the very (successful) end of dinstall, make sure we remove
884 # our stage files, so the next dinstall run will do it all again.
886 touch "${DINSTALLEND}"