lib/update.operations
author Tero Marttila <terom@paivola.fi>
Sun, 22 Dec 2013 15:33:32 +0200
changeset 98 a3734856e0fa
parent 96 bed4765fc56f
child 99 934aab83b769
permissions -rw-r--r--
use hosts/dhcp/%** to create dhcp hosts configs
#!/bin/bash
## vim: set ft=sh :
#
# Operations on zonefiles/hosts/whatever

function link {
    local out="$1"
    local tgt="$2"

    if check_link "$out" "$tgt"; then
        log_update "Linking $out -> $tgt..."

        do_link "$out" "$tgt"

    else
        log_skip "Linking $out -> $tgt: not changed"
    fi
}

function copy {
    local out="$1"
    local src="$2"

    if check_update "$out" "$src"; then
        log_update "Copying $out <- $src..."

        do_update "$out" \
            cat "$src"
    else
        log_skip "Copying $out <- $src: not changed"
    fi
}

## Run check-command on given file, outputting results:
#
#   check    $src    $cmd $args...
#
function check {
    local src="$1"; shift
    local cmd="$1"; shift

    if cmd_test "$cmd" -q "$@"; then
        log_skip    "Check $src: OK"

    else
        log_error   "  Check $src: Failed"

        indent "    " "$cmd" "$@"

        exit 1
    fi
}

## Generate forward zone from hosts hosts using pvl.hosts-dns:
#
#   update_hosts_forward out/hosts/$hosts $hosts in/hosts/$hosts
function update_hosts_forward {
    local out="$1"; shift
    local domain="$1"; shift

    if check_update "$out" "$@"; then
        log_update "Generating forward hosts zone $out @ $domain <- $@..."
    
        do_update "$out" $OPT/bin/pvl.hosts-dns \
            --hosts-charset=$CHARSET \
            --forward-zone="$domain" \
             "$@"
    else
        log_skip "Generating forward hosts $out <- $@: not changed"
    fi
}

function update_hosts_dhcp {
    local out=$1; shift
    local domain="$1"; shift

    if check_update $out "$@"; then
        log_update "Generating DHCP hosts $out @ $domain <- $@..."

        do_update $out $OPT/bin/pvl.hosts-dhcp \
            --hosts-charset=$CHARSET \
            --hosts-domain=$domain \
            "$@"
    else
        log_skip "Generating DHCP hosts $out <- $@: not changed"
    fi
}

## Generate reverse zone from hosts hosts using pvl.hosts-dns:
#
#   update_hosts_reverse out/hosts/$reverse $reverse in/hosts/$hosts
function update_hosts_reverse {
    local out="$1"; shift
    local reverse="$1"; shift

    if check_update "$out" "$@"; then
        log_update "Generating reverse hosts zone $out <- $@..."
    
        do_update "$out" $OPT/bin/pvl.hosts-dns \
            --hosts-charset=$CHARSET \
            --reverse-zone="$reverse" \
            "$@"
    else
        log_skip "Generating reverse hosts $out <- $@: not changed"
    fi
}

## Update .serial number:
#
#   do_update_serial .../serials/$zone  $serial
#
function do_update_serial {
    local dst="$1"
    local serial="$2"

    echo $serial > $dst
}


## Generate new serial for zone using pvl.dns-serial, if the zone data has changed:
#
#   update_serial   .../serials/$zone   $serial     $deps...
#
# Supports SERIAL_FORCE/NOOP.
# Updates $SERIALS/$zone.serial.
function update_serial {
    local dst="$1"; shift
    local serial="$1"; shift

    local old=$(test -e "$dst" && cat "$dst" || echo '')
    
    # test
    if [ $SERIAL_FORCE ]; then
        log_force "Updating $dst: $old <- $serial: forced"

        do_update_serial "$dst" "$serial"

    elif ! check_update "$dst" "$@"; then
        log_skip "Updating $dst: $old <- $serial: not changed"

    elif [ $SERIAL_NOOP ]; then
        log_noop "Updating $dst: $old <- $serial: skipped"

    else
        log_update "Updating $dst: $old <- $serial"

        do_update_serial "$dst" "$serial"
    fi
}

## Generate zone file from source using pvl.dns-zone:
#
#   update_zone out/zones/$zone in/zones/$zone var/serials/$zone
function update_zone {
    local out="$1"; shift
    local src="$1"; shift
    local serial="$1"; shift
    local serial_opt=

    if [ -n "$serial" -a -f "$serial" ]; then
        serial_opt="--serial=$(cat "$serial")"
    elif [ $SERIAL_NOOP ]; then
        warn "$out: noop'd serial, omitting"
    else
        fail "$out: missing serial: $serial"
    fi

    if check_update "$out" "$src" "$serial" "$@"; then
        log_update "Generating $out <- $src..." 

        do_update "$out" $OPT/bin/pvl.dns-zone "$src" \
                --include-path=$SRV/var/zones   \
                $serial_opt
    else
        log_skip "Generating $out <- $src: not changed" 
    fi
}

## Generate dhcp confs from source using pvl.dhcp-conf:
function update_dhcp_conf {
    local out="$1"
    local src="$2"

    if check_update "$out" "$src"; then
        log_update "Generating $out <- $src..."
            
        do_update "$out" $OPT/bin/pvl.dhcp-conf "$src" \
            --include-path=$SRV/var/dhcp
    else
        log_skip "Generating $out <- $src: not changed"
    fi
}

## Test hosts zone for validity using pvl.hosts-check:
#
#   check_hosts     .../hosts
function check_hosts {
    local hosts=$1; shift 1
    
    # TODO
    check $hosts \
        $OPT/bin/pvl.hosts-check $hosts
}

## Test zone file for validity using named-checkzone:
#
#   check_zone      ..../$zone $origin
function check_zone {
    local zone=$1
    local origin=$2

    log_check "Checking $zone @ $origin..." 

    # checkzone is very specific about the order of arguments, -q must be first
    check $zone $NAMED_CHECKZONE $origin $zone
}

## Test DHCP configuration for validity using dhcpd -t:
#
#   check_dhcp      [$conf]
#
# Defaults to the global $DHCPD_CONF.
# Fails if the check fails.
function check_dhcp {
    local conf=${1:-$DHCPD_CONF}
    
    log_check "Checking DHCP $conf..." 

    if [ ! -e $DHCPD ]; then
        log_warn "check_dhcp: dhcpd not installed, skipping: $conf"
        return 0
    fi

    check $conf \
        $DHCPD -cf $conf -t
}

## Test DHCP configuration of given settings/dhcp using check_dhcp $DHCP_DATA/$host.conf:
#
#   check_dhcp_conf     $conf
#
function check_dhcp_conf {
    local conf=$1;

    check_dhcp $DHCP_DATA/$conf.conf
}

### Deploy
# set by do_reload_zone if zone data has actually been reloaded
RELOAD_ZONES=

## Run rndc reload
function do_reload_zones {
    # run
    indent "        rndc: " \
        $RNDC reload

    # set flag
    RELOAD_ZONES=y
}

## Load update zonefiles into bind:
#
#   reload_zones    
#
# Invokes `rndc reload`, showing its output.
function reload_zones {
    local msg="Reload zones"

    if [ $RELOAD_FORCE ]; then
        log_force  "$msg..."
        
        do_reload_zones

    elif [ $RELOAD_NOOP ]; then
        log_noop    "$msg: skipped"
    
    elif [ ! -e $RNDC ]; then
        log_warn "reload_zones: rndc not installed, skipping"

    elif [ ! -e $RNDC_KEY ]; then
        log_warn   "  $msg: rndc: key not found: $RNDC_KEY"

    elif [ ! -r $RNDC_KEY ]; then
        log_error   "  $msg: rndc: permission denied: $RNDC_KEY"

        return 1

    else
        log_update  "$msg..."

        # run
        do_reload_zones
    fi
}

## Reload DHCP by restarting it, if running:
#
#   do_reload_dhcp
#
# Does NOT restart dhcp if it is not running (status).
function do_reload_dhcp {
    if cmd_test $DHCPD_INIT status >/dev/null; then
        cmd $DHCPD_INIT restart
    else
        log_warn "dhcpd not running; did not restart"
    fi
}

## Reload dhcp hosts
#
#   reload_dhcp
#
# noop's if we haven't reloaded zones
function reload_dhcp {
    local msg="Reload DHCP hosts"

    if [ $RELOAD_FORCE ]; then
        log_force  "$msg..."
        
        do_reload_dhcp

    elif [ $RELOAD_NOOP ]; then
        log_noop    "$msg: skipped"
 
    elif [ ! -e $DHCPD ]; then
        log_warn "reload_dhcp: dhcpd not installed, skipping: $conf"
   
    else
        log_update  "$msg..."

        # run
        do_reload_dhcp
    fi
}

### Commit
## Commit changes to version control:
#
#   update_commit .../etc "commit message"
#
# Invokes `hg commit`, first showing the diff.
function update_commit {
    local repo="$1"
    local commit_msg="$COMMIT_MSG"

    local msg="Commit changes"

    # operate?
    if [ $COMMIT_FORCE ]; then
        log_force   "$msg: $commit_msg"

        [ $LOG_DIFF ] && indent "    " hg_diff $repo

        hg_commit "$repo" "$commit_msg"

    elif ! hg_modified "$repo"; then
        log_warn    "$msg: no changes"

    elif [ $COMMIT_SKIP ]; then
        log_noop    "$msg: skipped"
        
        # still show diff, though
        [ $LOG_DIFF ] && indent "    " hg_diff "$repo"
    else
        log_update  "$msg: $commit_msg"

        [ $LOG_DIFF ] && indent "    " hg_diff $repo

        hg_commit "$repo" "$commit_msg"
    fi
}