common 14.4 KB
Newer Older
J
Joerg Jaspert 已提交
1
# -*- mode:sh -*-
J
Joerg Jaspert 已提交
2 3 4 5
# log something (basically echo it together with a timestamp)
#
# Set $PROGRAM to a string to have it added to the output.
function log () {
J
Various  
Joerg Jaspert 已提交
6
    local prefix=${PROGRAM:-}
7
    echo "$(date +"%b %d %H:%M:%S") ${HOSTNAME} ${prefix}[$$]: $*"
J
Joerg Jaspert 已提交
8 9 10 11 12
}

# log the message using log() but then also send a mail
# to the address configured in MAILTO (if non-empty)
function log_error () {
J
Various  
Joerg Jaspert 已提交
13
    log "$@"
J
Joerg Jaspert 已提交
14
    if [[ -z ${MAILTO} ]]; then
15
        echo "$*" | mail -a "X-Debian: DAK" -e -s "[$PROGRAM@${HOSTNAME}] ERROR [$$]" -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" ${MAILTO}
J
Various  
Joerg Jaspert 已提交
16
    fi
J
Joerg Jaspert 已提交
17 18 19 20
}

# debug log, only output when DEBUG=1
function debug () {
J
Joerg Jaspert 已提交
21
    if [[ $DEBUG -eq 1 ]]; then
J
Joerg Jaspert 已提交
22 23 24
        log "$*"
    fi
}
J
Joerg Jaspert 已提交
25

26 27 28 29 30 31 32 33 34 35 36 37 38
# Get a tempfile, add it to the right variable to get rid of it,
# and return it
function gettempfile() {
    local MAKEDIR=${1:-false}
    local TMPARGS=""
    if [[ ${MAKEDIR} == true ]]; then
        TMPARGS="--directory"
    fi
    local TMPFILE=$( mktemp -p ${TMPDIR} ${TMPARGS} )
    TMPFILES="${TEMPFILES} ${TMPFILE}"
    echo "${TMPFILE}"
}

39 40 41 42 43
# Function that only cleans tempfiles, but does not exit or otherwise
# care about any exit status
function cleantempfiles() {
    resolvetmpfiles
    for TEMPFILE in $TMPFILES; do
J
Joerg Jaspert 已提交
44
        if [[ -n ${TEMPFILE} ]] && [[ -f ${TEMPFILE} ]]; then
45
            rm -f "${TEMPFILE}"
J
Joerg Jaspert 已提交
46 47
        elif [[ -n ${TEMPFILE} ]] && [[ -d ${TEMPFILE} ]]; then
            if [[ ${TEMPFILE} != / ]] && [[ ${TEMPFILE} != /* ]]; then
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
                rm -rf "${TEMPFILE}"
            fi
        fi
    done
    TMPFILES=""
}

function resolvetmpfiles() {
    # If you don't understand this better not touch the script
    for TEMPFILE in $TEMPFILES; do
        TMPFILES="${TMPFILES} ${!TEMPFILE:-""}"
    done
    TEMPFILES=""
}

# Function cleanup
# No arguments
# Cleans up any known tempfile.
# Just ensure your script sets the variable
# TEMPFILES to the names of variables of tempfiles
# Or TMPFILES to the pathes of tempfiles
function cleanup() {
    ERRVAL=$?
    trap - ERR EXIT TERM HUP INT QUIT

    cleantempfiles

75
    return $ERRVAL
76 77 78 79
}
TEMPFILES=${TEMPFILES:-""}
TMPFILES=${TMPFILES:-""}

80 81 82 83
# Timestamp. Used for dinstall stat graphs
function ts() {
    echo "Archive maintenance timestamp ($1): $(date +%H:%M:%S)"
}
84 85 86 87

########################################################################
########################################################################

J
buildd  
Joerg Jaspert 已提交
88
function wbtrigger() {
89
    SSHOPT="-n -o BatchMode=yes -o ConnectTimeout=30 -o SetupTimeout=240"
J
buildd  
Joerg Jaspert 已提交
90
    if lockfile -r 3 -l 3600 "${LOCK_BUILDD}"; then
A
Ansgar Burchardt 已提交
91
        ssh -q -q ${SSHOPT} wbadm@buildd /srv/wanna-build/trigger.often
J
buildd  
Joerg Jaspert 已提交
92
    fi
J
Joerg Jaspert 已提交
93
    rm -f "${LOCK_BUILDD}"
J
buildd  
Joerg Jaspert 已提交
94 95
}

J
Joerg Jaspert 已提交
96 97
# used by cron.dinstall *and* cron.unchecked.
function make_buildd_dir () {
98
    # We generate straight into the static mirror location for incoming
J
Joerg Jaspert 已提交
99
    log "Preparing buildd area"
100
    dak manage-build-queues -a
101
    dak generate-packages-sources2 -a build-queues
J
silence  
Joerg Jaspert 已提交
102
    dak generate-releases -a build-queues >/dev/null
103

M
Mark Hymers 已提交
104
    # Stick a last modified date in the page footer
105
    echo "<p>Last updated: $(date -u)</p>" > ${incoming}/web/README.html
M
Mark Hymers 已提交
106

107 108
    write_project_trace "${incoming}/web/debian-buildd"

109
    # Tell the mirrors that we've updated
J
Joerg Jaspert 已提交
110
    log "Pushing static for incoming.d.o"
111
    sudo -u archvsync runmirrors -a buildd > ~dak/runmirrors-buildd.log 2>&1 &
112
    chronic timeout -k 600 480 /usr/local/bin/static-update-component incoming.debian.org < /dev/null
113
    wait
J
Joerg Jaspert 已提交
114
}
J
Joerg Jaspert 已提交
115

116 117
# Process (oldstable)-proposed-updates "NEW" queue
function punew_do() {
118
    local queue="$1"
119
    local qdir="$2"
120 121
    local to="${3}"

122
    date -u -R >> REPORT
123
    dak process-policy "${queue}" | tee -a REPORT | mail -a "X-Debian: DAK" -e -s "NEW changes in ${queue}" -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" "${to}"
124
    echo >> REPORT
125 126 127

    dak generate-packages-sources2 -s "${queue}"

128 129
    STAMP=${STAMP:-$(date "+%Y%m%d%H%M")}

130 131
    local exportdir="${qdir}/tree/${STAMP}"
    local targetdir="${qdir}/export"
132
    mkdir -p -- ${exportdir}
133
    dak export -q "${queue}" -d "${exportdir}" --all
J
Joerg Jaspert 已提交
134
    ln -sfT ${exportdir} ${targetdir}
135
    find "${qdir}/tree" -mindepth 1 -maxdepth 1 -not -name "${STAMP}" -type d -print0 | xargs --no-run-if-empty -0 rm -rf
136 137 138 139
}

# These versions used in dinstall
function punew() {
140
    log "Doing automated p-u-new processing"
141
    cd "${queuedir}/p-u-new"
142
    punew_do "$1" "${queuedir}/p-u-new" "debian-release@lists.debian.org"
143 144 145
}

function opunew() {
146
    log "Doing automated o-p-u-new processing"
147
    cd "${queuedir}/o-p-u-new"
148
    punew_do "$1" "${queuedir}/o-p-u-new" "debian-release@lists.debian.org"
149 150 151 152 153 154 155
}

function backports_policy() {
    local queue="backports-policy"
    local qdir="/srv/backports-master.debian.org/queue/policy"
    local to="backports-team@debian.org"

156
    log "Doing automated ${queue} processing"
157 158 159

    cd "${qdir}"
    punew_do "${queue}" "${qdir}" "${to}"
160 161
}

J
Joerg Jaspert 已提交
162 163 164 165
# Do the unchecked processing, in case we have files.
function do_unchecked () {
    cd $unchecked

J
Joerg Jaspert 已提交
166
    changes=$(find . -maxdepth 1 -mindepth 1 -type f \( -name \*.changes -o -name \*.dak-commands \) | sed -e "s,./,," | xargs)
J
Joerg Jaspert 已提交
167
    report=${queuedir}/REPORT
J
Joerg Jaspert 已提交
168
    timestamp=$(date "+%Y-%m-%d %H:%M")
169

J
Joerg Jaspert 已提交
170
    if [[ ! -z ${changes} ]]; then
J
Joerg Jaspert 已提交
171
        log "Processing files ${changes}"
172 173 174 175 176
        {
            echo "${timestamp}: ${changes}"
            dak process-upload -a -d "$unchecked"
            dak process-commands -d "$unchecked"
        } >> ${report}
J
Joerg Jaspert 已提交
177

178 179
        sync_debbugs
        do_buildd
J
Joerg Jaspert 已提交
180 181 182
    else
        log "Nothing to do"
        echo "Nothing to do" >> ${report}
183
    fi
J
Joerg Jaspert 已提交
184 185
}

186 187
# process NEW policy queue
function do_new () {
188
    log "Doing NEW processing"
189
    (dak process-policy new; dak process-policy byhand) | mail -a "X-Debian: DAK" -e -s "NEW and BYHAND processing" -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" ftpmaster@ftp-master.debian.org
190

191
    log "Processing Backports NEW"
192
    dak process-policy backports-new | mail -a "X-Debian: DAK" -e -s "NEW processing for backports-new" -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" backports-team@debian.org
193

194
    log "Cleanup NEW/Backports NEW"
195
    dak clean-suites -a new,backports-new
J
Joerg Jaspert 已提交
196 197
}

J
Joerg Jaspert 已提交
198 199
function sync_debbugs () {
    # sync with debbugs
J
Joerg Jaspert 已提交
200
    log "Sync debbugs version tracking information"
201
    echo "--" >> $report
J
meh  
Joerg Jaspert 已提交
202
    timestamp=$(date "+%Y-%m-%d-%H:%M")
J
Joerg Jaspert 已提交
203
    mkdir -p $queuedir/bts_version_track_archive/${timestamp}
204
    rsync -aq $queuedir/bts_version_track/ $queuedir/bts_version_track_archive/${timestamp}
J
Joerg Jaspert 已提交
205
    rmdir --ignore-fail-on-non-empty $queuedir/bts_version_track_archive/${timestamp} # remove if empty.
A
Ansgar Burchardt 已提交
206
    rsync -aq -e "ssh -o Batchmode=yes -o ConnectTimeout=30 -o SetupTimeout=30" --remove-source-files  $queuedir/bts_version_track/ bugs-sync:/srv/bugs.debian.org/versions/queue/ftp-master/ 2>/dev/null && touch $lockdir/synced_bts_version || true
J
Joerg Jaspert 已提交
207 208 209
    NOW=$(date +%s)
    TSTAMP=$(stat -c %Y $lockdir/synced_bts_version)
    DIFF=$(( NOW - TSTAMP ))
J
Joerg Jaspert 已提交
210
    if [[ $DIFF -ge 259200 ]]; then
J
Joerg Jaspert 已提交
211
        log_error "Kids, you tried your best and you failed miserably. The lesson is, never try. (Homer Simpson)"
J
Joerg Jaspert 已提交
212 213
    fi
}
J
Joerg Jaspert 已提交
214

215
function clean_debbugs () {
J
Joerg Jaspert 已提交
216
    log "Cleanup debbugs"
217 218 219 220 221 222
    # Delete files older than 60 days
    find $queuedir/bts_version_track_archive/ -mtime +60 -type f -delete
    # Delete empty directories
    find $queuedir/bts_version_track_archive/ -empty -type d -delete
}

J
Joerg Jaspert 已提交
223 224 225
function reports() {
    # Send a report on NEW/BYHAND packages
    log "Nagging ftpteam about NEW/BYHAND packages"
226 227
    dak queue-report | mail -a "X-Debian: DAK" -e -s "NEW and BYHAND on $(date +%D)" -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" ftpmaster@ftp-master.debian.org
    dak queue-report -d backports-new,backports-policy | mail -a "X-Debian: DAK" -e -s "NEW and POLICY on $(date +%D)" -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" backports-team@debian.org
J
Joerg Jaspert 已提交
228 229
    # and one on crufty packages
    log "Sending information about crufty packages"
230 231
    dak cruft-report -R > $webdir/cruft-report-daily.txt.new
    dak cruft-report -R -s experimental >> $webdir/cruft-report-daily.txt.new
232
    echo "Page generated on $(date -u)" >> $webdir/cruft-report-daily.txt.new
233
    mv $webdir/cruft-report-daily.txt.new $webdir/cruft-report-daily.txt
234
    mail -a "X-Debian: DAK" -e -s "Debian archive cruft report for $(date +%D)" -a "From: Debian FTP Masters <ftpmaster@ftp-master.debian.org>" ftpmaster@ftp-master.debian.org < $webdir/cruft-report-daily.txt
J
Joerg Jaspert 已提交
235
}
J
Joerg Jaspert 已提交
236 237 238 239 240 241

function pg_timestamp() {
    tsname=${1:-"unknown"}
    log "Saving postgres transaction id for ${tsname}"
    psql -tAc 'select txid_current();' > $base/backup/txid_${tsname}_$(date +%Y.%m.%d-%H:%M:%S)
}
242 243 244 245 246

function get_archiveroot() {
    local archivename="$1"
    local query="SELECT path FROM archive WHERE name='${archivename}'"
    local archiveroot="$(psql -tAc "${query}")"
J
Joerg Jaspert 已提交
247
    if [[ -z ${archiveroot} ]]; then
248 249 250 251 252
        echo "get_archiveroot: couldn't get archiveroot for '${archivename}'" >&2
        return 1
    fi
    echo "${archiveroot}"
}
253 254 255

# Prepare the trees for buildds, then push wanna-build
function do_buildd() {
256 257
    if lockfile -r3 ${LOCK_DAILY}; then
        TMPFILES="${TMPFILES} ${LOCK_DAILY}"
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
        make_buildd_dir
        wbtrigger
    fi
}

# Cleanup policy queues
function cleanpolicy() {
    dak clean-suites -a backports-policy,policy
}

# Scan new packages for contents
function scancontents() {
    dak contents -l 10000 scan-binary
    dak contents -l 1000 scan-source
}

function ddaccess() {
J
Joerg Jaspert 已提交
275 276
    # Tell our dd accessible mirror to sync itself up.
    log "Trigger dd accessible parts sync"
277 278 279
    ${scriptsdir}/sync-dd dd-sync dd-sync1 dd-sync2 sync
}

280 281 282 283 284
# Write ${path}/project/trace for given path
#   Note: use `write_project_trace` which sets version and date variables
function write_project_trace1() {
    local path="${1}"

285
    local tracedir="${path}/project/trace"
286
    local TRACEFILE="${tracedir}/${functionname}"
287
    local TRACEFILE_MASTER="${tracedir}/master"
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
    local HIERFILE="${tracedir}/_hierarchy"

    mkdir -p -- "${tracedir}"

    local DATE_SERIAL=$(date +"%Y%m%d01")
    local FILESOAPLUS1=$(awk '/serial/ { print $3+1 }' ${TRACEFILE} || echo ${DATE_SERIAL} )
    local SERIAL
    if [[ ${DATE_SERIAL} -gt ${FILESOAPLUS1}  ]]; then
        SERIAL="${DATE_SERIAL}"
    else
        SERIAL="${FILESOAPLUS1}"
    fi

    cat <<EOF > ${TRACEFILE}
${DATE}
Creator: dak ${CREATOR_VERSION}
Running on host: ${HOST}
Archive serial: ${SERIAL}
Date: ${RFC822DATE}
Architectures: ${archs%* } source
EOF

    cat <<EOF > ${HIERFILE}
${functionname} ${functionname} ${HOST} ${HOST}
EOF
    cp ${HIERFILE} ${HIERFILE}.mirror

    # Now make it accessible via one name, no matter on which host we run
    ln -sf $(basename ${TRACEFILE}) ${TRACEFILE_MASTER}
}
318

319 320 321 322 323 324 325 326 327 328 329 330 331 332
# Write ${path}/project/trace for given paths
function write_project_trace() {
    cd ${configdir}

    local CREATOR_VERSION="g$(git rev-parse --short HEAD)"
    local DATE=$(LC_ALL=POSIX LANG=POSIX date -u)
    local RFC822DATE=$(LC_ALL=POSIX LANG=POSIX date -u -R)
    local HOST=$(hostname -f)

    local path
    for path in "${@}"; do
        write_project_trace1 "${path}"
    done
}
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363

########################################################################
########################################################################
########################################################################
########################################################################

# Function to save which stage we are in, so we can restart an interrupted
# dinstall. Or even run actions in parallel, if we dare to, by simply
# backgrounding the call to this function. But that should only really be
# done for things we don't care much about.
#
# This should be called with the first argument being an array, with the
# members
#  - FUNC - the function name to call
#  - ARGS - Possible arguments to hand to the function. Can be the empty string
#  - TIME - The timestamp name. Can be the empty string
#  - ERR  - if this is the string false, then the call will be surrounded by
#           set +e ... set -e calls, so errors in the function do not exit
#           dinstall. Can be the empty string, meaning true.
#
# MAKE SURE TO KEEP THIS THE LAST FUNCTION, AFTER ALL THE VARIOUS ONES
# ADDED FOR DINSTALL FEATURES!
function stage() {
    ARGS='GO[@]'
    local "${!ARGS}"

    local error=${ERR:-"true"}

    ARGS=${ARGS:-""}

    log "########## ${PROGRAM} BEGIN: ${FUNC} ${ARGS} ##########"
364
    local STAGEFILE="${stagedir}/${FUNC}${ARGS:+_}${ARGS}"
365
    STAGEFILE=${STAGEFILE// /_}
J
Joerg Jaspert 已提交
366
    if [[ -f ${STAGEFILE} ]]; then
367 368
        local stamptime=$(/usr/bin/stat -c %Z "${STAGEFILE}")
        local unixtime=$(date +%s)
369
        local difference=$(( unixtime - stamptime ))
J
Joerg Jaspert 已提交
370
        if [[ ${difference} -ge 14400 ]]; then
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
            log_error "Did already run ${FUNC}, stagefile exists, but that was ${difference} seconds ago. Please check."
        else
            log "Did already run ${FUNC}, not calling again..."
        fi
        return
    fi

    debug "Now calling function ${FUNC}. Arguments: ${ARGS}. Timestamp: ${TIME}"

    # Make sure we are always at the same place. If a function wants
    # to be elsewhere, it has to cd first!
    cd ${configdir}

    # Now redirect the output into $STAGEFILE.log. In case it errors
    # out somewhere our errorhandler trap can then mail the contents
    # of $STAGEFILE.log only, instead of a whole ${PROGRAM} logfile.
    # Short error mails ftw!
    exec >> "${STAGEFILE}.log" 2>&1

J
Joerg Jaspert 已提交
390
    if [[ -f ${LOCK_STOP} ]]; then
391 392 393 394 395
        log "${LOCK_STOP} exists, exiting immediately"
        exit 42
    fi

    # Do we care about trouble in the function we call?
J
Joerg Jaspert 已提交
396
    if [[ ${error} == false ]]; then
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
        set +e
    fi
    ${FUNC} ${ARGS}

    # No matter what happened in the function, we make sure we have
    # set -e default state back
    set -e

    # Make sure we are always at the same place.
    cd ${configdir}

    # We always use the same umask. If a function wants to do
    # different, fine, but we reset.
    umask 022

    touch "${STAGEFILE}"

J
Joerg Jaspert 已提交
414
    if [[ -n ${TIME} ]]; then
415 416 417 418 419 420 421 422
        ts "${TIME}"
    fi

    # And the output goes back to the normal logfile
    exec >> "${LOGFILE}" 2>&1

    # Now we should make sure that we have a usable ${PROGRAM}.log, so
    # append the $STAGEFILE.log to it.
423 424 425 426 427
    if [[ ${TIMESTAMP} == true ]]; then
        /usr/bin/ts "%b %d %H:%M:%S ${HOSTNAME} ${PROGRAM}[$$]: ${FUNC} " < "${STAGEFILE}.log"
    else
        cat "${STAGEFILE}.log"
    fi
428 429 430 431
    rm -f "${STAGEFILE}.log"

    log "########## ${PROGRAM} END: ${FUNC} ##########"

J
Joerg Jaspert 已提交
432
    if [[ -f ${LOCK_STOP} ]]; then
433 434 435 436
        log "${LOCK_STOP} exists, exiting immediately"
        exit 42
    fi
}