]> git.decadent.org.uk Git - dak.git/blob - config/debian/dinstall
Merge branch 'master' into content_generation, make changes based on Joerg's review
[dak.git] / config / debian / 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 # Rotate logfiles
32 function savelog() {
33     torotate="$1"
34     count=${2:-${LOGROTATE}}
35     while [ ${count} -gt 0 ]; do
36         prev=$(( count - 1 ))
37         if [ -e "${torotate}.${prev}" ]; then
38             mv "${torotate}.${prev}" "${torotate}.${count}"
39         fi
40         count=$prev
41     done
42     mv "${torotate}" "${torotate}.0"
43 }
44
45 # log something (basically echo it together with a timestamp)
46 #
47 # Set $PROGRAM to a string to have it added to the output.
48 function log () {
49         if [ -z "${PROGRAM}" ]; then
50                 echo "$(date +"%b %d %H:%M:%S") $(hostname -s) [$$] $@"
51         else
52                 echo "$(date +"%b %d %H:%M:%S") $(hostname -s) ${PROGRAM}[$$]: $@"
53         fi
54 }
55
56 # log the message using log() but then also send a mail
57 # to the address configured in MAILTO (if non-empty)
58 function error () {
59         log "$@"
60         if [ -z "${MAILTO}" ]; then
61                 echo "$@" | mail -e -s "[$PROGRAM@$(hostname -s)] ERROR [$$]" ${MAILTO}
62         fi
63 }
64
65 # debug log, only output when DEBUG=1
66 function debug () {
67         if [ $DEBUG -eq 1 ]; then
68                 log "$*"
69         fi
70 }
71
72 # Timestamp. Used for dinstall stat graphs
73 function ts() {
74         TS=$(($TS+1));
75         echo "Archive maintenance timestamp $TS ($1): $(date +%H:%M:%S)"
76 }
77
78 # Cleanup actions
79 function cleanup() {
80         savelog "$LOGFILE"
81 }
82
83 # Setup the notice file to tell bad mirrors they used the wrong time
84 function notice() {
85         rm -f "$NOTICE"
86         cat > "$NOTICE" <<EOF
87 Packages are currently being installed and indices rebuilt.
88 Maintenance is automatic, starting at 01|07|13|19:52 UTC,
89 and ending about an hour later.  This file is then removed.
90
91 You should not mirror the archive during this period.
92 EOF
93 }
94
95 # ushing merkels QA user, part one
96 function merkel1() {
97         log "Telling merkels QA user that we start dinstall"
98         ssh -2 -i ~dak/.ssh/push_merkel_qa  -o BatchMode=yes -o SetupTimeOut=90 -o ConnectTimeout=90 qa@merkel.debian.org sleep 1
99 }
100
101 # Create the postgres dump files
102 function pgdump_pre() {
103         log "Creating pre-daily-cron-job backup of projectb database..."
104         pg_dump projectb > $base/backup/dump_$(date +%Y.%m.%d-%H:%M:%S)
105 }
106
107 function pgdump_post() {
108         log "Creating post-daily-cron-job backup of projectb database..."
109         cd $base/backup
110         POSTDUMP=$base/backup/dump_$(date +%Y.%m.%d-%H:%M:%S)
111         pg_dump projectb > $POSTDUMP
112         ln -sf $POSTDUMP current
113 }
114
115 # Updating various files
116 function updates() {
117         log "Updating Bugs docu, Mirror list and mailing-lists.txt"
118         cd $configdir
119         $scriptsdir/update-bugdoctxt
120         $scriptsdir/update-mirrorlists
121         $scriptsdir/update-mailingliststxt
122         $scriptsdir/update-pseudopackages.sh
123 }
124
125 # Process (oldstable)-proposed-updates "NEW" queue
126 function punew_do() {
127         cd "${queuedir}/${1}"
128         date -u -R >> REPORT
129         dak process-new -a -C COMMENTS >> REPORT || true
130         echo >> REPORT
131 }
132 function punew() {
133         log "Doing automated p-u-new processing"
134         punew_do "$1"
135 }
136 function opunew() {
137         log "Doing automated o-p-u-new processing"
138         punew_do "$1"
139 }
140
141 # The first i18n one, syncing new descriptions
142 function i18n1() {
143         log "Synchronizing i18n package descriptions"
144     # First sync their newest data
145         cd ${scriptdir}/i18nsync
146         rsync -aq --delete --delete-after ddtp-sync:/does/not/matter . || true
147
148     # Now check if we still know about the packages for which they created the files
149     # is the timestamp signed by us?
150         if $(gpgv --keyring /srv/ftp.debian.org/s3kr1t/dot-gnupg/pubring.gpg timestamp.gpg timestamp); then
151         # now read it. As its signed by us we are sure the content is what we expect, no need
152         # to do more here. And we only test -d a directory on it anyway.
153                 TSTAMP=$(cat timestamp)
154         # do we have the dir still?
155                 if [ -d ${scriptdir}/i18n/${TSTAMP} ]; then
156             # Lets check!
157                         if ${scriptsdir}/ddtp-i18n-check.sh . ${scriptdir}/i18n/${TSTAMP}; then
158                 # Yay, worked, lets copy around
159                 for dir in squeeze sid; do
160                     if [ -d dists/${dir}/ ]; then
161                         cd dists/${dir}/main/i18n
162                         rsync -aq --delete --delete-after  . ${ftpdir}/dists/${dir}/main/i18n/.
163                     fi
164                     cd ${scriptdir}/i18nsync
165                 done
166             else
167                 echo "ARRRR, bad guys, wrong files, ARRR"
168                 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
169             fi
170                 else
171             echo "ARRRR, missing the timestamp ${TSTAMP} directory, not updating i18n, ARRR"
172             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
173         fi
174         else
175                 echo "ARRRRRRR, could not verify our timestamp signature, ARRR. Don't mess with our files, i18n guys, ARRRRR."
176         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
177         fi
178 }
179
180 # Process the accepted queue
181 function accepted() {
182         log "Processing queue/accepted"
183         cd "$accepted"
184         rm -f REPORT
185         dak process-accepted -pa *.changes | tee REPORT | \
186                 mail -s "Install for $(date +"%D - %R")" ftpmaster@ftp-master.debian.org
187         chgrp debadmin REPORT
188         chmod 664 REPORT
189 }
190
191 function cruft() {
192         log "Checking for cruft in overrides"
193         dak check-overrides
194
195         log "Fixing symlinks in $ftpdir"
196         symlinks -d -r $ftpdir
197 }
198
199 function msfl() {
200         log "Generating suite file lists for apt-ftparchive"
201         dak make-suite-file-list
202 }
203
204 function fingerprints() {
205         log "Updating fingerprints"
206         dak import-keyring -L /srv/keyring.debian.org/keyrings/debian-keyring.gpg
207 }
208
209 function overrides() {
210         log "Writing overrides into text files"
211         cd $overridedir
212         dak make-overrides
213
214     # FIXME
215         rm -f override.sid.all3
216         for i in main contrib non-free main.debian-installer; do cat override.sid.$i >> override.sid.all3; done
217 }
218
219 function mpfm() {
220         log "Generating package / file mapping"
221         dak make-pkg-file-mapping | bzip2 -9 > $base/ftp/indices/package-file.map.bz2
222 }
223
224 function packages() {
225         log "Generating Packages and Sources files"
226         cd $configdir
227         apt-ftparchive generate apt.conf
228 }
229
230 function pdiff() {
231         log "Generating pdiff files"
232         dak generate-index-diffs
233 }
234
235 function release() {
236         log "Generating Release files"
237         dak generate-releases
238 }
239
240 function cleanup() {
241         log "Cleanup old packages/files"
242         dak clean-suites
243         dak clean-queues
244 }
245
246 function buildd() {
247     # Needs to be rebuilt, as files have moved.  Due to unaccepts, we need to
248     # update this before wanna-build is updated.
249         log "Regenerating wanna-build/buildd information"
250         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
251         symlinks -d /srv/incoming.debian.org/buildd > /dev/null
252         apt-ftparchive generate apt.conf.buildd
253 }
254
255 function scripts() {
256         log "Running various scripts from $scriptsdir"
257         cd $scriptsdir
258         ./mkmaintainers
259         ./copyoverrides
260         ./mklslar
261         ./mkfilesindices
262         ./mkchecksums
263 }
264
265 function mirror() {
266         echo "Regenerating \"public\" mirror/ hardlink fun"
267         cd ${mirrordir}
268         rsync -aH --link-dest ${ftpdir} --delete --delete-after --ignore-errors ${ftpdir}/. .
269 }
270
271 function wb() {
272         log "Trigger daily wanna-build run"
273         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
274 }
275
276 function expire() {
277         log "Expiring old database dumps..."
278         cd $base/backup
279         $scriptsdir/expire_dumps -d . -p -f "dump_*"
280 }
281
282 function reports() {
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
291 }
292
293 function dm() {
294         log "Updating DM html page"
295         $scriptsdir/dm-monitor >$webdir/dm-uploaders.html
296 }
297
298 function bts() {
299         log "Categorizing uncategorized bugs filed against ftp.debian.org"
300         dak bts-categorize
301 }
302
303 function merkel2() {
304     # Push katie@merkel so it syncs the projectb there. Returns immediately, the sync runs detached
305         log "Trigger merkels projectb sync"
306         ssh -2 -o BatchMode=yes -o SetupTimeOut=30 -o ConnectTimeout=30 -i ~/.ssh/push_merkel_projectb katie@merkel.debian.org sleep 1
307 }
308
309 function runparts() {
310         log "Using run-parts to run scripts in $base/scripts/distmnt"
311         run-parts --report $base/scripts/distmnt
312 }
313
314 function i18n2() {
315         log "Exporting package data foo for i18n project"
316         STAMP=$(date "+%Y%m%d%H%M")
317         mkdir -p ${scriptdir}/i18n/${STAMP}
318         cd ${scriptdir}/i18n/${STAMP}
319         dak control-suite -l stable > lenny
320         dak control-suite -l testing > squeeze
321         dak control-suite -l unstable > sid
322         echo "${STAMP}" > timestamp
323         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
324         rm -f md5sum
325         md5sum * > md5sum
326         cd ${webdir}/
327         ln -sfT ${scriptdir}/i18n/${STAMP} i18n
328
329         cd ${scriptdir}
330         find ./i18n -mtime +2 -mindepth 1 -maxdepth 1 -not -name "${STAMP}" -type d -print0 | xargs --no-run-if-empty -0 rm -rf
331 }
332
333 function stats() {
334         log "Updating stats data"
335         cd $configdir
336         $scriptsdir/update-ftpstats $base/log/* > $base/misc/ftpstats.data
337         R --slave --vanilla < $base/misc/ftpstats.R
338 }
339
340 function aptftpcleanup() {
341         log "Clean up apt-ftparchive's databases"
342         cd $configdir
343         apt-ftparchive -q clean apt.conf
344 }
345
346 function compress() {
347         log "Compress old psql backups"
348         cd $base/backup/
349     find -maxdepth 1 -mindepth 1 -type f -name 'dump_*' \! -name '*.bz2' \! -name '*.gz' -mtime +1 |
350     while read dumpname; do
351         echo "Compressing $dumpname"
352         bzip2 -9v "$dumpname"
353     done
354 }
355
356 function logstats() {
357         $masterdir/tools/logs.py "$LOGFILE"
358 }
359
360 ########################################################################
361 ########################################################################
362
363 # Function to save which stage we are in, so we can restart an interrupted
364 # dinstall. Or even run actions in parallel, if we dare to, by simply
365 # backgrounding the call to this function. But that should only really be
366 # done for things we dont care much about.
367 #
368 # This should be called with the first argument being an array, with the
369 # members
370 #  - FUNC - the function name to call
371 #  - ARGS - Possible arguments to hand to the function. Can be the empty string
372 #  - TS   - The timestamp name. Can be the empty string
373 #  - ERR  - if this is the string false, then the call will be surrounded by
374 #           set +e ... set -e calls, so errors in the function do not exit
375 #           dinstall. Can be the empty string, meaning true.
376 #
377 # MAKE SURE TO KEEP THIS THE LAST FUNCTION, AFTER ALL THE VARIOUS ONES
378 # ADDED FOR DINSTALL FEATURES!
379 function stage() {
380         ARGS='GO[@]'
381         local "${!ARGS}"
382
383         if [ -f "${stagedir}/${FUNC}" ]; then
384                 stamptime=$(/usr/bin/stat -c %Z "${stagedir}/${FUNC}")
385                 unixtime=$(date +%s)
386                 difference=$(( $unixtime - $stamptime ))
387                 if [ ${difference} -ge 14400 ]; then
388                         error "Did already run ${FUNC}, stagefile exists, but that was ${difference} seconds ago. Please check."
389                 else
390                         log "Did already run ${FUNC}, not calling again..."
391                 fi
392                 return
393         fi
394
395         debug "Now calling function ${FUNC}. Arguments: ${ARGS}. Timestamp: ${TS}"
396
397         # Make sure we are always at the same place. If a function wants to be elsewhere,
398         # it has to cd first!
399         cd ${configdir}
400
401         if [ "${ERR}" = "false"]; then
402                 set +e
403         fi
404         ${FUNC} ${ARGS}
405
406         # No matter what happened in the function, we make sure we have set -e default state back
407         set -e
408
409         # Make sure we are always at the same place.
410         cd ${configdir}
411
412         touch "${stagedir}/${FUNC}"
413
414         if [ -n "${TIME}" ]; then
415                 ts "${TIME}"
416         fi
417 }
418
419 ########################################################################
420
421 # We need logs.
422 LOGFILE="$logdir/dinstall.log"
423
424 exec > "$LOGFILE" 2>&1
425
426 # usually we are not using debug logs. Set to 1 if you want them.
427 DEBUG=0
428
429 # our name
430 PROGRAM="dinstall"
431
432 # where do we want mails to go? For example log entries made with error()
433 if [ "x$(hostname -s)x" != "xriesx" ]; then
434     # Not our ftpmaster host
435     MAILTO=${MAILTO:-"root"}
436 else
437     # Yay, ftpmaster
438     MAILTO=${MAILTO:-"ftpmaster@debian.org"}
439 fi
440
441 # How many logfiles to keep
442 LOGROTATE=${LOGROTATE:-400}
443
444 # Timestamps start at -1. so first gets 0
445 TS=-1
446 ts "startup"
447
448 # Tell everyone we are doing some work
449 NOTICE="$ftpdir/Archive_Maintenance_In_Progress"
450
451 # lock cron.unchecked (it immediately exits when this exists)
452 LOCK_DAILY="$lockdir/daily.lock"
453
454 # Lock process-new and cron.unchecked from doing work
455 LOCK_ACCEPTED="$lockdir/unchecked.lock"
456
457 # This file is simply used to indicate to britney whether or not
458 # the Packages file updates completed sucessfully.  It's not a lock
459 # from our point of view
460 LOCK_BRITNEY="$lockdir/britney.lock"
461
462 lockfile -l 3600 "${LOCK_DAILY}"
463 trap cleanup EXIT ERR TERM HUP INT QUIT
464
465 touch "${LOCK_BRITNEY}"
466
467 GO=(
468         FUNC="notice"
469         TIME=""
470         ARGS=""
471         ERR="false"
472 )
473 stage $GO
474
475 GO=(
476         FUNC="merkel1"
477         TIME="init"
478         ARGS=""
479         ERR="false"
480 )
481 stage $GO
482
483 GO=(
484         FUNC="pgdump_pre"
485         TIME="pg_dump1"
486         ARGS=""
487         ERR=""
488 )
489 stage $GO
490
491 GO=(
492         FUNC="updates"
493         TIME="External Updates"
494         ARGS=""
495         ERR=""
496 )
497 stage $GO
498
499 GO=(
500         FUNC="punew"
501         TIME="p-u-new"
502         ARGS="p-u-new"
503         ERR=""
504 )
505 stage $GO
506
507 GO=(
508         FUNC="opunew"
509         TIME="o-p-u-new"
510         ARGS="o-p-u-new"
511         ERR=""
512 )
513 stage $GO
514
515 GO=(
516         FUNC="i18n1"
517         TIME="i18n 1"
518         ARGS=""
519         ERR="false"
520 )
521 stage $GO
522
523 lockfile "$LOCK_ACCEPTED"
524
525 GO=(
526         FUNC="accepted"
527         TIME="accepted"
528         ARGS=""
529         ERR=""
530 )
531 stage $GO
532
533 GO=(
534         FUNC="cruft"
535         TIME="cruft"
536         ARGS=""
537         ERR=""
538 )
539 stage $GO
540
541 rm -f $LOCKAC
542
543 GO=(
544         FUNC="msfl"
545         TIME="make-suite-file-list"
546         ARGS=""
547         ERR=""
548 )
549 stage $GO
550
551 GO=(
552         FUNC="fingerprints"
553         TIME="import-keyring"
554         ARGS=""
555         ERR="false"
556 )
557 stage $GO
558
559 GO=(
560         FUNC="overrides"
561         TIME="overrides"
562         ARGS=""
563         ERR=""
564 )
565 stage $GO
566
567 GO=(
568         FUNC="mpfm"
569         TIME="pkg-file-mapping"
570         ARGS=""
571         ERR="false"
572 )
573 stage $GO
574
575 GO=(
576         FUNC="packages"
577         TIME="apt-ftparchive"
578         ARGS=""
579         ERR=""
580 )
581 stage $GO
582
583 GO=(
584         FUNC="pdiff"
585         TIME="pdiff"
586         ARGS=""
587         ERR=""
588 )
589 stage $GO
590
591 GO=(
592         FUNC="release"
593         TIME="release files"
594         ARGS=""
595         ERR=""
596 )
597 stage $GO
598
599 GO=(
600         FUNC="cleanup"
601         TIME="cleanup"
602         ARGS=""
603         ERR=""
604 )
605 stage $GO
606
607 GO=(
608         FUNC="buildd"
609         TIME="buildd"
610         ARGS=""
611         ERR=""
612 )
613 stage $GO
614
615 GO=(
616         FUNC="scripts"
617         TIME="scripts"
618         ARGS=""
619         ERR=""
620 )
621 stage $GO
622
623 GO=(
624         FUNC="mirror"
625         TIME="mirror hardlinks"
626         ARGS=""
627         ERR=""
628 )
629 stage $GO
630
631 GO=(
632         FUNC="wb"
633         TIME="w-b"
634         ARGS=""
635         ERR=""
636 )
637 stage $GO
638
639 rm -f "${NOTICE}"
640 rm -f "${LOCK_DAILY}"
641
642 ts "locked part finished"
643
644 GO=(
645         FUNC="pgdump_post"
646         TIME="pg_dump2"
647         ARGS=""
648         ERR=""
649 )
650 stage $GO
651
652 GO=(
653         FUNC="expire"
654         TIME="expire_dumps"
655         ARGS=""
656         ERR=""
657 )
658 stage $GO
659
660 GO=(
661         FUNC="reports"
662         TIME="reports"
663         ARGS=""
664         ERR=""
665 )
666 stage $GO
667
668 GO=(
669         FUNC="dm"
670         TIME=""
671         ARGS=""
672         ERR=""
673 )
674 stage $GO
675
676 GO=(
677         FUNC="bts"
678         TIME=""
679         ARGS=""
680         ERR=""
681 )
682 stage $GO
683
684 GO=(
685         FUNC="merkel2"
686         TIME="merkel projectb push"
687         ARGS=""
688         ERR="false"
689 )
690 stage $GO
691
692 ulimit -m 90000 -d 90000 -s 10000 -v 200000
693
694 GO=(
695         FUNC="runparts"
696         TIME="run-parts"
697         ARGS=""
698         ERR="false"
699 )
700 stage $GO
701
702 GO=(
703         FUNC="i18n2"
704         TIME="i18n 2"
705         ARGS=""
706         ERR="false"
707 )
708 stage $GO
709
710 GO=(
711         FUNC="stats"
712         TIME="stats"
713         ARGS=""
714         ERR="false"
715 )
716 stage $GO
717
718 rm -f ${BRITNEYLOCK}
719
720 GO=(
721         FUNC="aptftpcleanup"
722         TIME="apt-ftparchive cleanup"
723         ARGS=""
724         ERR=""
725 )
726 stage $GO
727
728 GO=(
729         FUNC="compress"
730         TIME="compress"
731         ARGS=""
732         ERR=""
733 )
734 stage $GO
735
736 log "Daily cron scripts successful, all done"
737
738 exec > /dev/null 2>&1
739
740 GO=(
741         FUNC="logstats"
742         TIME=""
743         ARGS=""
744         ERR=""
745 )
746 stage $GO
747
748 cat "$LOGFILE" | mail -s "Log for dinstall run of ${NOW}" cron@ftp-master.debian.org
749
750 # Now, at the very (successful) end of dinstall, make sure we remove
751 # our stage files, so the next dinstall run will do it all again.
752 rm -f "${stagedir}/*"