]> git.decadent.org.uk Git - dak.git/blob - config/debian/cron.dinstall
import latest bpo changes before merging its code around
[dak.git] / config / debian / cron.dinstall
1 #!/bin/bash
2 # No way I try to deal with a crippled sh just for POSIX foo.
3
4 # Copyright (C) 2009 Joerg Jaspert <joerg@debian.org>
5 #
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.
9 #
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.
14 #
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.
18
19 # exit on errors
20 set -e
21 # make sure to only use defined variables
22 set -u
23
24 # import the general variable set.
25 export SCRIPTVARS=/srv/ftp.debian.org/dak/config/debian/vars
26 . $SCRIPTVARS
27
28 ########################################################################
29 # Functions                                                            #
30 ########################################################################
31 # common functions are "outsourced"
32 . "${configdir}/common"
33
34 # Timestamp. Used for dinstall stat graphs
35 function ts() {
36         TS=$(($TS+1));
37         echo "Archive maintenance timestamp $TS ($1): $(date +%H:%M:%S)"
38 }
39
40 # Cleanup actions
41 function cleanup() {
42         rm -f ${LOCK_DAILY}
43         rm -f ${LOCK_ACCEPTED}
44 }
45
46 ########################################################################
47 # the actual dinstall functions follow                                 #
48 ########################################################################
49
50 # Setup the notice file to tell bad mirrors they used the wrong time
51 function notice() {
52     rm -f "$NOTICE"
53     cat > "$NOTICE" <<EOF
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.
57
58 You should not mirror the archive during this period.
59 EOF
60 }
61
62 # pushing merkels QA user, part one
63 function merkel1() {
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
66 }
67
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)
72 }
73
74 function pgdump_post() {
75     log "Creating post-daily-cron-job backup of projectb database..."
76     cd $base/backup
77     POSTDUMP=$base/backup/dump_$(date +%Y.%m.%d-%H:%M:%S)
78     pg_dump projectb > $POSTDUMP
79     ln -sf $POSTDUMP current
80 }
81
82 # Updating various files
83 function updates() {
84     log "Updating Bugs docu, Mirror list and mailing-lists.txt"
85     cd $configdir
86     $scriptsdir/update-bugdoctxt
87     $scriptsdir/update-mirrorlists
88     $scriptsdir/update-mailingliststxt
89     $scriptsdir/update-pseudopackages.sh
90 }
91
92 # Process (oldstable)-proposed-updates "NEW" queue
93 function punew_do() {
94     cd "${queuedir}/${1}"
95     date -u -R >> REPORT
96     dak process-new -a -C COMMENTS >> REPORT || true
97     echo >> REPORT
98 }
99 function punew() {
100     log "Doing automated p-u-new processing"
101     punew_do "$1"
102 }
103 function opunew() {
104     log "Doing automated o-p-u-new processing"
105     punew_do "$1"
106 }
107
108 # The first i18n one, syncing new descriptions
109 function i18n1() {
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
114
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
123             # Lets check!
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/.
130                     fi
131                     cd ${scriptdir}/i18nsync
132                 done
133             else
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
136             fi
137         else
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
140         fi
141     else
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
144     fi
145 }
146
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"
155 }
156
157 function cruft() {
158     log "Checking for cruft in overrides"
159     dak check-overrides
160
161     log "Fixing symlinks in $ftpdir"
162     symlinks -d -r $ftpdir
163 }
164
165 function msfl() {
166     log "Generating suite file lists for apt-ftparchive"
167     dak make-suite-file-list
168 }
169
170 function fingerprints() {
171     log "Updating fingerprints"
172     dak import-keyring -L /srv/keyring.debian.org/keyrings/debian-keyring.gpg
173 }
174
175 function overrides() {
176     log "Writing overrides into text files"
177     cd $overridedir
178     dak make-overrides
179
180     # FIXME
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
183 }
184
185 function mpfm() {
186     log "Generating package / file mapping"
187     dak make-pkg-file-mapping | bzip2 -9 > $base/ftp/indices/package-file.map.bz2
188 }
189
190 function packages() {
191     log "Generating Packages and Sources files"
192     cd $configdir
193     apt-ftparchive generate apt.conf
194 }
195
196 function pdiff() {
197     log "Generating pdiff files"
198     dak generate-index-diffs
199 }
200
201 function release() {
202     log "Generating Release files"
203     dak generate-releases
204 }
205
206 function dakcleanup() {
207     log "Cleanup old packages/files"
208     dak clean-suites
209     dak clean-queues
210 }
211
212 function buildd() {
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
219 }
220
221 function scripts() {
222     log "Running various scripts from $scriptsdir"
223     cd $scriptsdir
224     ./mkmaintainers
225     ./copyoverrides
226     ./mklslar
227     ./mkfilesindices
228     ./mkchecksums
229 }
230
231 function mirror() {
232     echo "Regenerating \"public\" mirror/ hardlink fun"
233     cd ${mirrordir}
234     rsync -aH --link-dest ${ftpdir} --delete --delete-after --ignore-errors ${ftpdir}/. .
235 }
236
237 function wb() {
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
240 }
241
242 function expire() {
243     log "Expiring old database dumps..."
244     cd $base/backup
245     $scriptsdir/expire_dumps -d . -p -f "dump_*"
246 }
247
248 function reports() {
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
257 }
258
259 function dm() {
260     log "Updating DM html page"
261     $scriptsdir/dm-monitor >$webdir/dm-uploaders.html
262 }
263
264 function bts() {
265     log "Categorizing uncategorized bugs filed against ftp.debian.org"
266     dak bts-categorize
267 }
268
269 function merkel2() {
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
273 }
274
275 function runparts() {
276     log "Using run-parts to run scripts in $base/scripts/distmnt"
277     run-parts --report $base/scripts/distmnt
278 }
279
280 function i18n2() {
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
290     rm -f md5sum
291     md5sum * > md5sum
292     cd ${webdir}/
293     ln -sfT ${scriptdir}/i18n/${STAMP} i18n
294
295     cd ${scriptdir}
296     find ./i18n -mindepth 1 -maxdepth 1 -mtime +2 -not -name "${STAMP}" -type d -print0 | xargs --no-run-if-empty -0 rm -rf
297 }
298
299 function stats() {
300     log "Updating stats data"
301     cd $configdir
302     $scriptsdir/update-ftpstats $base/log/* > $base/misc/ftpstats.data
303     R --slave --vanilla < $base/misc/ftpstats.R
304 }
305
306 function aptftpcleanup() {
307     log "Clean up apt-ftparchive's databases"
308     cd $configdir
309     apt-ftparchive -q clean apt.conf
310 }
311
312 function compress() {
313     log "Compress old psql backups"
314     cd $base/backup/
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"
319     done
320 }
321
322 function logstats() {
323     $masterdir/tools/logs.py "$1"
324 }
325
326 # save timestamp when we start
327 function savetimestamp() {
328         NOW=`date "+%Y.%m.%d-%H:%M:%S"`
329         echo ${NOW} > "${dbdir}/dinstallstart"
330 }
331
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"
338         else
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"
343         fi
344 }
345
346 ########################################################################
347 ########################################################################
348
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.
353 #
354 # This should be called with the first argument being an array, with the
355 # members
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.
362 #
363 # MAKE SURE TO KEEP THIS THE LAST FUNCTION, AFTER ALL THE VARIOUS ONES
364 # ADDED FOR DINSTALL FEATURES!
365 function stage() {
366     ARGS='GO[@]'
367     local "${!ARGS}"
368
369     if [ -f "${stagedir}/${FUNC}" ]; then
370         stamptime=$(/usr/bin/stat -c %Z "${stagedir}/${FUNC}")
371         unixtime=$(date +%s)
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."
375         else
376             log "Did already run ${FUNC}, not calling again..."
377         fi
378         return
379     fi
380
381     debug "Now calling function ${FUNC}. Arguments: ${ARGS}. Timestamp: ${TS}"
382
383     # Make sure we are always at the same place. If a function wants to be elsewhere,
384     # it has to cd first!
385     cd ${configdir}
386
387         if [ -f "${LOCK_STOP}" ]; then
388                 log "${LOCK_STOP} exists, exiting immediately"
389                 exit 42
390         fi
391
392     if [ "${ERR}" = "false" ]; then
393         set +e
394     fi
395     ${FUNC} ${ARGS}
396
397     # No matter what happened in the function, we make sure we have set -e default state back
398     set -e
399
400     # Make sure we are always at the same place.
401     cd ${configdir}
402
403     touch "${stagedir}/${FUNC}"
404
405     if [ -n "${TIME}" ]; then
406         ts "${TIME}"
407     fi
408
409         if [ -f "${LOCK_STOP}" ]; then
410                 log "${LOCK_STOP} exists, exiting immediately"
411                 exit 42
412         fi
413 }
414
415 ########################################################################
416
417 # We need logs.
418 LOGFILE="$logdir/dinstall.log"
419
420 exec >> "$LOGFILE" 2>&1
421
422 # usually we are not using debug logs. Set to 1 if you want them.
423 DEBUG=0
424
425 # our name
426 PROGRAM="dinstall"
427
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"}
432 else
433     # Yay, ftpmaster
434     MAILTO=${MAILTO:-"ftpmaster@debian.org"}
435 fi
436
437 # How many logfiles to keep
438 LOGROTATE=${LOGROTATE:-400}
439
440 # Marker for dinstall start
441 DINSTALLSTART="${lockdir}/dinstallstart"
442 # Marker for dinstall end
443 DINSTALLEND="${lockdir}/dinstallend"
444
445 # Timestamps start at -1. so first gets 0
446 TS=-1
447 touch "${DINSTALLSTART}"
448 ts "startup"
449
450 # Tell everyone we are doing some work
451 NOTICE="$ftpdir/Archive_Maintenance_In_Progress"
452
453 # lock cron.unchecked (it immediately exits when this exists)
454 LOCK_DAILY="$lockdir/daily.lock"
455
456 # Lock process-new and cron.unchecked from doing work
457 LOCK_ACCEPTED="$lockdir/unchecked.lock"
458
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"
463
464 # If this file exists we exit immediately after the currently running
465 # function is done
466 LOCK_STOP="$lockdir/archive.stop"
467
468 lockfile -l 3600 "${LOCK_DAILY}"
469 trap cleanup EXIT ERR TERM HUP INT QUIT
470
471 touch "${LOCK_BRITNEY}"
472
473 GO=(
474     FUNC="savetimestamp"
475     TIME=""
476     ARGS=""
477     ERR="false"
478 )
479 stage $GO
480
481 GO=(
482     FUNC="notice"
483     TIME=""
484     ARGS=""
485     ERR="false"
486 )
487 stage $GO
488
489 GO=(
490     FUNC="merkel1"
491     TIME="init"
492     ARGS=""
493     ERR="false"
494 )
495 stage $GO
496
497 GO=(
498     FUNC="pgdump_pre"
499     TIME="pg_dump1"
500     ARGS=""
501     ERR=""
502 )
503 stage $GO
504
505 GO=(
506     FUNC="updates"
507     TIME="External Updates"
508     ARGS=""
509     ERR="false"
510 )
511 stage $GO
512
513 GO=(
514     FUNC="punew"
515     TIME="p-u-new"
516     ARGS="p-u-new"
517     ERR=""
518 )
519 stage $GO
520
521 GO=(
522     FUNC="opunew"
523     TIME="o-p-u-new"
524     ARGS="o-p-u-new"
525     ERR=""
526 )
527 stage $GO
528
529 GO=(
530     FUNC="i18n1"
531     TIME="i18n 1"
532     ARGS=""
533     ERR="false"
534 )
535 stage $GO
536
537 lockfile "$LOCK_ACCEPTED"
538
539 GO=(
540     FUNC="accepted"
541     TIME="accepted"
542     ARGS=""
543     ERR=""
544 )
545 stage $GO
546
547 GO=(
548     FUNC="cruft"
549     TIME="cruft"
550     ARGS=""
551     ERR=""
552 )
553 stage $GO
554
555 rm -f "$LOCK_ACCEPTED"
556
557 GO=(
558     FUNC="msfl"
559     TIME="make-suite-file-list"
560     ARGS=""
561     ERR=""
562 )
563 stage $GO
564
565 GO=(
566     FUNC="fingerprints"
567     TIME="import-keyring"
568     ARGS=""
569     ERR="false"
570 )
571 stage $GO
572
573 GO=(
574     FUNC="overrides"
575     TIME="overrides"
576     ARGS=""
577     ERR=""
578 )
579 stage $GO
580
581 GO=(
582     FUNC="mpfm"
583     TIME="pkg-file-mapping"
584     ARGS=""
585     ERR="false"
586 )
587 stage $GO
588
589 GO=(
590     FUNC="packages"
591     TIME="apt-ftparchive"
592     ARGS=""
593     ERR=""
594 )
595 stage $GO
596
597 GO=(
598     FUNC="pdiff"
599     TIME="pdiff"
600     ARGS=""
601     ERR=""
602 )
603 stage $GO
604
605 GO=(
606     FUNC="release"
607     TIME="release files"
608     ARGS=""
609     ERR=""
610 )
611 stage $GO
612
613 GO=(
614     FUNC="dakcleanup"
615     TIME="cleanup"
616     ARGS=""
617     ERR=""
618 )
619 stage $GO
620
621 GO=(
622     FUNC="buildd"
623     TIME="buildd"
624     ARGS=""
625     ERR=""
626 )
627 stage $GO
628
629 GO=(
630     FUNC="scripts"
631     TIME="scripts"
632     ARGS=""
633     ERR=""
634 )
635 stage $GO
636
637 GO=(
638     FUNC="mirror"
639     TIME="mirror hardlinks"
640     ARGS=""
641     ERR=""
642 )
643 stage $GO
644
645 GO=(
646     FUNC="wb"
647     TIME="w-b"
648     ARGS=""
649     ERR=""
650 )
651 stage $GO
652
653 rm -f "${NOTICE}"
654 rm -f "${LOCK_DAILY}"
655
656 ts "locked part finished"
657
658 GO=(
659     FUNC="pgdump_post"
660     TIME="pg_dump2"
661     ARGS=""
662     ERR=""
663 )
664 stage $GO
665
666 GO=(
667     FUNC="expire"
668     TIME="expire_dumps"
669     ARGS=""
670     ERR=""
671 )
672 stage $GO
673
674 GO=(
675     FUNC="reports"
676     TIME="reports"
677     ARGS=""
678     ERR=""
679 )
680 stage $GO
681
682 GO=(
683     FUNC="dm"
684     TIME=""
685     ARGS=""
686     ERR=""
687 )
688 stage $GO
689
690 GO=(
691     FUNC="bts"
692     TIME=""
693     ARGS=""
694     ERR=""
695 )
696 stage $GO
697
698 GO=(
699     FUNC="merkel2"
700     TIME="merkel projectb push"
701     ARGS=""
702     ERR="false"
703 )
704 stage $GO
705
706 ulimit -m 90000 -d 90000 -s 10000 -v 200000
707
708 GO=(
709     FUNC="runparts"
710     TIME="run-parts"
711     ARGS=""
712     ERR="false"
713 )
714 stage $GO
715
716 GO=(
717     FUNC="i18n2"
718     TIME="i18n 2"
719     ARGS=""
720     ERR="false"
721 )
722 stage $GO
723
724 GO=(
725     FUNC="stats"
726     TIME="stats"
727     ARGS=""
728     ERR="false"
729 )
730 stage $GO
731
732 rm -f ${LOCK_BRITNEY}
733
734 GO=(
735     FUNC="aptftpcleanup"
736     TIME="apt-ftparchive cleanup"
737     ARGS=""
738     ERR=""
739 )
740 stage $GO
741
742 GO=(
743     FUNC="compress"
744     TIME="compress"
745     ARGS=""
746     ERR=""
747 )
748 stage $GO
749
750 log "Daily cron scripts successful, all done"
751
752 exec > "$logdir/afterdinstall.log" 2>&1
753
754 cat "$LOGFILE" | mail -s "Log for dinstall run of ${NOW}" cron@ftp-master.debian.org
755
756 GO=(
757     FUNC="renamelogfile"
758     TIME=""
759     ARGS=""
760     ERR="false"
761 )
762 stage $GO
763
764
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.
767 rm -f ${stagedir}/*
768 touch "${DINSTALLEND}"