2 # Timestamp. Used for dinstall stat graphs
4 echo "Archive maintenance timestamp ($1): $(date +%H:%M:%S)"
8 function remove_daily_lock() {
13 function remove_all_locks() {
14 rm -f $LOCK_DAILY $LOCK_ACCEPTED $LOCK_NEW
17 # If we error out this one is called, *FOLLOWED* by cleanup above
19 ERRDATE=$(date "+%Y.%m.%d-%H:%M:%S")
21 subject="ATTENTION ATTENTION!"
22 if [ "${error}" = "false" ]; then
23 subject="${subject} (continued)"
25 subject="${subject} (interrupted)"
27 subject="${subject} dinstall error at ${ERRDATE} in ${STAGEFILE} - (Be quiet, Brain, or I'll stab you with a Q-tip)"
29 if [ -r "${STAGEFILE}.log" ]; then
30 cat "${STAGEFILE}.log"
32 echo "file ${STAGEFILE}.log does not exist, sorry"
33 fi | mail -s "${subject}" -a "X-Debian: DAK" cron@ftp-master.debian.org -- -F "Debian FTP Masters" -f ftpmaster@ftp-master.debian.org
36 ########################################################################
37 # the actual dinstall functions follow #
38 ########################################################################
40 # pushing merkels QA user, part one
42 log "Telling QA user that we start dinstall"
43 ssh -2 -i ~dak/.ssh/push_merkel_qa -o BatchMode=yes -o SetupTimeOut=90 -o ConnectTimeout=90 qa@qa.debian.org sleep 1
46 # Updating various files
48 log "Updating Bugs docu, Mirror list and mailing-lists.txt"
50 $scriptsdir/update-bugdoctxt
51 $scriptsdir/update-mirrorlists
52 $scriptsdir/update-mailingliststxt
53 $scriptsdir/update-pseudopackages.sh
56 # The first i18n one, syncing new descriptions
58 log "Synchronizing i18n package descriptions"
59 # First sync their newest data
60 cd ${scriptdir}/i18nsync
61 rsync -aq --delete --delete-after ddtp-sync:/does/not/matter . || true
63 # Now check if we still know about the packages for which they created the files
64 # is the timestamp signed by us?
65 if $(gpgv --keyring /srv/ftp-master.debian.org/s3kr1t/dot-gnupg/pubring.gpg timestamp.gpg timestamp); then
66 # now read it. As its signed by us we are sure the content is what we expect, no need
67 # to do more here. And we only test -d a directory on it anyway.
68 TSTAMP=$(cat timestamp)
69 # do we have the dir still?
70 if [ -d ${scriptdir}/i18n/${TSTAMP} ]; then
72 if ${scriptsdir}/ddtp-i18n-check.sh . ${scriptdir}/i18n/${TSTAMP}; then
73 # Yay, worked, lets copy around
74 for dir in wheezy sid; do
75 if [ -d dists/${dir}/ ]; then
76 cd dists/${dir}/main/i18n
77 rsync -aq --delete --delete-after --exclude Translation-en.bz2 --exclude Translation-*.diff/ . ${ftpdir}/dists/${dir}/main/i18n/.
79 cd ${scriptdir}/i18nsync
82 echo "ARRRR, bad guys, wrong files, ARRR"
83 echo "Arf, Arf, Arf, bad guys, wrong files, arf, arf, arf" | mail -a "X-Debian: DAK" -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 -- -F "Debian FTP Masters" -f ftpmaster@ftp-master.debian.org
86 echo "ARRRR, missing the timestamp ${TSTAMP} directory, not updating i18n, ARRR"
87 echo "Arf, Arf, Arf, missing the timestamp ${TSTAMP} directory, not updating i18n, arf, arf, arf" | mail -a "X-Debian: DAK" -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 -- -F "Debian FTP Masters" -f ftpmaster@ftp-master.debian.org
90 echo "ARRRRRRR, could not verify our timestamp signature, ARRR. Don't mess with our files, i18n guys, ARRRRR."
91 echo "Arf, Arf, Arf, could not verify our timestamp signature, arf. Don't mess with our files, i18n guys, arf, arf, arf" | mail -a "X-Debian: DAK" -s "You can't keep blaming yourself. Just blame yourself once, and move on." debian-l10n-devel@lists.alioth.debian.org -- -F "Debian FTP Masters" -f ftpmaster@ftp-master.debian.org
96 log "Checking for cruft in overrides"
100 function dominate() {
101 log "Removing obsolete source and binary associations"
105 function filelist() {
106 log "Generating file lists for apt-ftparchive"
107 dak generate-filelist
110 function fingerprints() {
111 log "Updating fingerprints"
112 dak import-keyring -L /srv/keyring.debian.org/keyrings/debian-keyring.gpg
115 dak import-keyring --generate-users "%s" /srv/keyring.debian.org/keyrings/debian-maintainers.gpg >"${OUTFILE}"
117 if [ -s "${OUTFILE}" ]; then
118 /usr/sbin/sendmail -odq -oi -t -f envelope@ftp-master.debian.org <<EOF
119 From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>
120 To: <debian-project@lists.debian.org>
121 Subject: Debian Maintainers Keyring changes
122 Content-Type: text/plain; charset=utf-8
126 The following changes to the debian-maintainers keyring have just been activated:
130 Debian distribution maintenance software,
131 on behalf of the Keyring maintainers
138 function overrides() {
139 log "Writing overrides into text files"
144 rm -f override.sid.all3
145 for i in main contrib non-free main.debian-installer; do cat override.sid.$i >> override.sid.all3; done
149 log "Generating package / file mapping"
150 dak make-pkg-file-mapping | bzip2 -9 > $base/ftp/indices/package-file.map.bz2
153 function packages() {
154 log "Generating Packages and Sources files"
155 dak generate-packages-sources2
156 dak contents generate
160 log "Generating pdiff files"
161 dak generate-index-diffs
165 # XXX: disable once we can remove i18n/Index (#649314)
166 log "Generating i18n/Index"
169 for dist in testing unstable experimental proposed-updates testing-proposed-updates; do
170 $scriptsdir/generate-i18n-Index $dist;
173 log "Generating Release files"
174 dak generate-releases
177 function dakcleanup() {
178 log "Cleanup old packages/files"
179 dak clean-suites -m 10000
183 function buildd_dir() {
184 # Rebuilt the buildd dir to avoid long times of 403
185 log "Regenerating the buildd incoming dir"
186 STAMP=$(date "+%Y%m%d%H%M")
195 log "Removing any core files ..."
196 find -type f -name core -print -delete
198 log "Checking symlinks ..."
201 log "Creating recursive directory listing ... "
203 TZ=UTC ls -lR | gzip -9c --rsyncable > ${FILENAME}.gz
206 function mkmaintainers() {
207 log 'Creating Maintainers index ... '
210 dak make-maintainers ${scriptdir}/masterfiles/pseudo-packages.maintainers
211 gzip -9v --rsyncable <Maintainers >Maintainers.gz
212 gzip -9v --rsyncable <Uploaders >Uploaders.gz
215 function copyoverrides() {
216 log 'Copying override files into public view ...'
218 for ofile in ${overridedir}/override.{squeeze,wheezy,sid}.{,extra.}{main,contrib,non-free}*; do
220 gzip -9cv --rsyncable ${ofile} > ${indices}/${bname}.gz
221 chmod g+w ${indices}/${bname}.gz
225 function mkfilesindices() {
228 cd $base/ftp/indices/files/components
232 log "Querying postgres"
233 local query='SELECT l.path, f.filename, a.arch_string FROM location l JOIN files f ON (f.location = l.id) LEFT OUTER JOIN (binaries b JOIN architecture a ON (b.architecture = a.id)) ON (f.id = b.file)'
234 psql -At -c "$query" | sed 's/|//;s,^/srv/ftp-master.debian.org/ftp,.,' | sort >$ARCHLIST
237 perl -ne 'print; while (m,/[^/]+$,) { $_=$`; print $_ . "\n" unless $d{$_}++; }'
240 perl -e '@nonpool=(); while (<>) { if (m,^\./pool/,) { print; } else { push @nonpool, $_; } } print for (@nonpool);'
243 log "Generating sources list"
245 sed -n 's/|$//p' $ARCHLIST
247 find ./dists -maxdepth 1 \! -type d
248 find ./dists \! -type d | grep "/source/"
249 ) | sort -u | gzip -9 > source.list.gz
251 log "Generating arch lists"
253 ARCHES=$( (<$ARCHLIST sed -n 's/^.*|//p'; echo amd64) | grep . | grep -v all | sort -u)
255 (sed -n "s/|$a$//p" $ARCHLIST
256 sed -n 's/|all$//p' $ARCHLIST
259 find ./dists -maxdepth 1 \! -type d
260 find ./dists \! -type d | grep -E "(proposed-updates.*_$a.changes$|/main/disks-$a/|/main/installer-$a/|/Contents-$a|/binary-$a/)"
261 ) | sort -u | gzip -9 > arch-$a.list.gz
264 log "Generating suite lists"
268 query="$(printf 'SELECT DISTINCT l.path, f.filename FROM (SELECT sa.source AS source FROM src_associations sa WHERE sa.suite = %d UNION SELECT b.source AS source FROM bin_associations ba JOIN binaries b ON (ba.bin = b.id) WHERE ba.suite = %d) s JOIN dsc_files df ON (s.source = df.source) JOIN files f ON (df.file = f.id) JOIN location l ON (f.location = l.id)' $1 $1)"
269 psql -F' ' -A -t -c "$query"
271 query="$(printf 'SELECT l.path, f.filename FROM bin_associations ba JOIN binaries b ON (ba.bin = b.id) JOIN files f ON (b.file = f.id) JOIN location l ON (f.location = l.id) WHERE ba.suite = %d' $1)"
272 psql -F' ' -A -t -c "$query"
275 psql -F' ' -At -c "SELECT id, suite_name FROM suite" |
276 while read id suite; do
277 [ -e $base/ftp/dists/$suite ] || continue
280 distname=$(cd dists; readlink $suite || echo $suite)
281 find ./dists/$distname \! -type d
282 for distdir in ./dists/*; do
283 [ "$(readlink $distdir)" != "$distname" ] || echo $distdir
286 suite_list $id | tr -d ' ' | sed 's,^/srv/ftp-master.debian.org/ftp,.,'
287 ) | sort -u | gzip -9 > suite-${suite}.list.gz
290 log "Finding everything on the ftp site to generate sundries"
291 (cd $base/ftp; find . \! -type d \! -name 'Archive_Maintenance_In_Progress' | sort) >$ARCHLIST
294 zcat *.list.gz | cat - *.list | sort -u |
295 diff - $ARCHLIST | sed -n 's/^> //p' > sundries.list
297 log "Generating files list"
300 (echo ./project/trace; zcat arch-$a.list.gz source.list.gz) |
301 cat - sundries.list dists.list project.list docs.list indices.list |
302 sort -u | poolfirst > ../arch-$a.files
306 for dist in sid wheezy; do
307 find ./dists/$dist/main/i18n/ \! -type d | sort -u | gzip -9 > $base/ftp/indices/files/components/translation-$dist.list.gz
311 (cat ../arch-i386.files ../arch-amd64.files; zcat suite-proposed-updates.list.gz ; zcat translation-sid.list.gz ; zcat translation-wheezy.list.gz) |
312 sort -u | poolfirst > ../typical.files
319 function mkchecksums() {
320 dsynclist=$dbdir/dsync.list
321 md5list=$indices/md5sums
323 log -n "Creating md5 / dsync index file ... "
326 ${bindir}/dsync-flist -q generate $dsynclist --exclude $dsynclist --md5
327 ${bindir}/dsync-flist -q md5sums $dsynclist | gzip -9n > ${md5list}.gz
328 ${bindir}/dsync-flist -q link-dups $dsynclist || true
332 log "Regenerating \"public\" mirror/ hardlink fun"
333 DATE_SERIAL=$(date +"%Y%m%d01")
334 FILESOAPLUS1=$(awk '/serial/ { print $3+1 }' ${TRACEFILE} )
335 if [ "$DATE_SERIAL" -gt "$FILESOAPLUS1" ]; then
336 SERIAL="$DATE_SERIAL"
338 SERIAL="$FILESOAPLUS1"
340 date -u > ${TRACEFILE}
341 echo "Using dak v1" >> ${TRACEFILE}
342 echo "Running on host: $(hostname -f)" >> ${TRACEFILE}
343 echo "Archive serial: ${SERIAL}" >> ${TRACEFILE}
345 rsync -aH --link-dest ${ftpdir} --delete --delete-after --delete-excluded --exclude Packages.*.new --exclude Sources.*.new --ignore-errors ${ftpdir}/. .
349 log "Expiring old database dumps..."
351 $scriptsdir/expire_dumps -d . -p -f "dump_*"
354 function transitionsclean() {
355 log "Removing out of date transitions..."
357 dak transitions -c -a
361 log "Updating DM html page"
362 $scriptsdir/dm-monitor >$webdir/dm-uploaders.html
366 log "Categorizing uncategorized bugs filed against ftp.debian.org"
370 function ddaccess() {
371 # Tell our dd accessible mirror to sync itself up. Including ftp dir.
372 log "Trigger dd accessible parts sync including ftp dir"
373 ssh -o Batchmode=yes -o ConnectTimeout=30 -o SetupTimeout=30 -2 -i ${base}/s3kr1t/pushddmirror dak@ries.debian.org pool
376 function mirrorpush() {
377 log "Checking the public archive copy"
378 cd ${mirrordir}/dists
381 for release in $(find . -name "InRelease"); do
382 echo "Processing: ${release}"
383 subdir=${release%/InRelease}
384 while read SHASUM SIZE NAME; do
385 if ! [ -f "${subdir}/${NAME}" ]; then
386 bname=$(basename ${NAME})
387 if [[ "${bname}" =~ ^(Packages|Sources|Translation-[a-zA-Z_]+)$ ]]; then
388 # We don't keep unpacked files, don't check for their existance.
389 # We might want to go and check their unpacked shasum, but right now
390 # I don't care. I believe it should be enough if all the packed shasums
394 broken=$(( broken + 1 ))
395 echo "File ${subdir}/${NAME} is missing"
399 # We do have symlinks in the tree (see the contents files currently).
400 # So we use "readlink -f" to check the size of the target, as thats basically
401 # what gen-releases does
402 fsize=$(stat -c %s $(readlink -f "${subdir}/${NAME}"))
403 if [ ${fsize} -ne ${SIZE} ]; then
404 broken=$(( broken + 1 ))
405 echo "File ${subdir}/${NAME} has size ${fsize}, expected is ${SIZE}"
409 fshasum=$(sha1sum $(readlink -f "${subdir}/${NAME}"))
410 fshasum=${fshasum%% *}
411 if [ "${fshasum}" != "${SHASUM}" ]; then
412 broken=$(( broken + 1 ))
413 echo "File ${subdir}/${NAME} has checksum ${fshasum}, expected is ${SHASUM}"
416 done < <(sed '1,/SHA1:/d' "${release}" | sed '/SHA256:/,$d')
419 if [ $broken -gt 0 ]; then
420 log_error "Trouble with the public mirror, found ${broken} errors"
424 log "Starting the mirrorpush"
425 date -u > /srv/ftp.debian.org/web/mirrorstart
426 echo "Using dak v1" >> /srv/ftp.debian.org/web/mirrorstart
427 echo "Running on host $(hostname -f)" >> /srv/ftp.debian.org/web/mirrorstart
428 sudo -H -u archvsync /home/archvsync/runmirrors > ~dak/runmirrors.log 2>&1 &
432 log "Exporting package data foo for i18n project"
433 STAMP=$(date "+%Y%m%d%H%M")
434 mkdir -p ${scriptdir}/i18n/${STAMP}
435 cd ${scriptdir}/i18n/${STAMP}
436 for suite in stable testing unstable; do
437 codename=$(dak admin s show ${suite}|grep '^Codename')
438 codename=${codename##* }
439 echo "Codename is ${codename}"
440 dak control-suite -l ${suite} >${codename}
442 echo "${STAMP}" > timestamp
443 gpg --secret-keyring /srv/ftp-master.debian.org/s3kr1t/dot-gnupg/secring.gpg --keyring /srv/ftp-master.debian.org/s3kr1t/dot-gnupg/pubring.gpg --no-options --batch --no-tty --armour --default-key 55BE302B --detach-sign -o timestamp.gpg timestamp
447 ln -sfT ${scriptdir}/i18n/${STAMP} i18n
450 find ./i18n -mindepth 1 -maxdepth 1 -mtime +2 -not -name "${STAMP}" -type d -print0 | xargs --no-run-if-empty -0 rm -rf
454 log "Updating stats data"
456 $scriptsdir/update-ftpstats $base/log/* > $base/misc/ftpstats.data
457 R --slave --vanilla < $base/misc/ftpstats.R
458 dak stats arch-space > $webdir/arch-space
459 dak stats pkg-nums > $webdir/pkg-nums
462 function aptftpcleanup() {
463 log "Clean up apt-ftparchive's databases"
465 apt-ftparchive -q clean apt.conf
468 function cleantransactions() {
469 log "Cleanup transaction ids older than 3 months"
471 find -maxdepth 1 -mindepth 1 -type f -name 'txid_*' -mtime +90 -print0 | xargs -0 --no-run-if-empty rm
474 function logstats() {
475 $masterdir/tools/logs.py "$1"
478 # save timestamp when we start
479 function savetimestamp() {
480 NOW=`date "+%Y.%m.%d-%H:%M:%S"`
481 echo ${NOW} > "${dbdir}/dinstallstart"
484 function maillogfile() {
485 cat "$LOGFILE" | mail -a "X-Debian: DAK" -s "Log for dinstall run of ${NOW}" cron@ftp-master.debian.org -- -F "Debian FTP Masters" -f ftpmaster@ftp-master.debian.org
488 function renamelogfile() {
489 if [ -f "${dbdir}/dinstallstart" ]; then
490 NOW=$(cat "${dbdir}/dinstallstart")
492 mv "$LOGFILE" "$logdir/dinstall_${NOW}.log"
493 logstats "$logdir/dinstall_${NOW}.log"
494 bzip2 -9 "$logdir/dinstall_${NOW}.log"
496 error "Problem, I don't know when dinstall started, unable to do log statistics."
497 NOW=`date "+%Y.%m.%d-%H:%M:%S"`
499 mv "$LOGFILE" "$logdir/dinstall_${NOW}.log"
500 bzip2 -9 "$logdir/dinstall_${NOW}.log"
504 function testingsourcelist() {
505 dak ls -s testing -f heidi -r .| egrep 'source$' > ${webdir}/testing.list
508 # do a last run of process-unchecked before dinstall is on.
509 function process_unchecked() {
510 log "Processing the unchecked queue"
511 UNCHECKED_WITHOUT_LOCK="-p"
516 # do a run of newstage only before dinstall is on.
517 function newstage() {
518 log "Processing the newstage queue"
519 UNCHECKED_WITHOUT_LOCK="-p"
523 # Function to update a "statefile" telling people what we are doing
526 # This should be called with the argument(s)
527 # - Status name we want to show.
530 RIGHTNOW="$(date -u +"%a %b %d %T %Z %Y (%s)")"
531 cat >"${DINSTALLSTATE}" <<EOF
532 Dinstall start: ${DINSTALLBEGIN}
534 Action start: ${RIGHTNOW}
538 # extract changelogs and stuff
539 function changelogs() {
540 log "Extracting changelogs"
541 dak make-changelog -e
542 mkdir -p ${exportpublic}/changelogs
543 cd ${exportpublic}/changelogs
544 rsync -aHW --delete --delete-after --ignore-errors ${exportdir}/changelogs/. .
545 sudo -H -u archvsync /home/archvsync/runmirrors metaftpdo > ~dak/runmirrors-metadata.log 2>&1 &
548 function gitpdiff() {
549 # Might be that we want to change this to have more than one git repository.
550 # Advantage of one is that we do not need much space in terms of storage in git itself,
551 # git gc is pretty good on our input.
552 # But it might be faster. Well, lets test.
553 log "Adjusting the git tree for pdiffs"
556 # The regex needs the architectures seperated with \|
557 garchs=$(dak admin a list|sed -e ':q;N;s/\n/\\|/g;t q')
559 # First, get all the files we want to work on. ../dists/ is a symlink to the real dists/ we
561 # Also, we only want contents, packages and sources.
562 for file in $(find ../dists/ -regex ".*/\(Contents-\($archs\)\|\(Packages\|Sources\)\).gz"); do
571 # Second, add all there is into git
574 # Maybe we want to make this the same for tag and commit? But well, shouldn't matter
576 TAGD=$(date +%Y-%m-%d-%H-%M)
577 git commit -m "Commit of ${COMD}"