terom@60: #!/bin/bash terom@52: ## vim: set ft=sh : terom@52: # terom@52: # Operations on zonefiles/hosts/whatever terom@52: terom@82: function link { terom@85: local out="$1" terom@85: local tgt="$2" terom@62: terom@85: if check_link "$out" "$tgt"; then terom@62: log_update "Linking $out -> $tgt..." terom@62: terom@85: do_link "$out" "$tgt" terom@62: terom@62: else terom@62: log_skip "Linking $out -> $tgt: not changed" terom@62: fi terom@62: } terom@62: terom@82: function copy { terom@85: local out="$1" terom@85: local src="$2" terom@64: terom@85: if check_update "$out" "$src"; then terom@64: log_update "Copying $out <- $src..." terom@64: terom@85: do_update "$out" \ terom@85: cat "$src" terom@64: else terom@64: log_skip "Copying $out <- $src: not changed" terom@64: fi terom@64: } terom@62: terom@66: ## Run check-command on given file, outputting results: terom@66: # terom@82: # check $src $cmd $args... terom@66: # terom@82: function check { terom@85: local src="$1"; shift terom@85: local cmd="$1"; shift terom@66: terom@85: if cmd_test "$cmd" -q "$@"; then terom@66: log_skip "Check $src: OK" terom@66: terom@66: else terom@66: log_error " Check $src: Failed" terom@66: terom@85: indent " " "$cmd" "$@" terom@66: terom@66: exit 1 terom@66: fi terom@66: } terom@66: terom@82: ## Generate forward zone from hosts hosts using pvl.hosts-dns: terom@52: # terom@84: # update_hosts_forward out/hosts/$hosts $hosts in/hosts/$hosts terom@82: function update_hosts_forward { terom@85: local out="$1"; shift terom@85: local domain="$1"; shift terom@92: terom@93: if check_update "$out" "$@"; then terom@93: log_update "Generating forward hosts zone $out @ $domain <- $@..." terom@82: terom@85: do_update "$out" $OPT/bin/pvl.hosts-dns \ terom@84: --hosts-charset=$CHARSET \ terom@85: --forward-zone="$domain" \ terom@93: "$@" terom@82: else terom@93: log_skip "Generating forward hosts $out <- $@: not changed" terom@82: fi terom@82: } terom@52: terom@82: function update_hosts_dhcp { terom@84: local out=$1; shift terom@98: local domain="$1"; shift terom@82: terom@98: if check_update $out "$@"; then terom@98: log_update "Generating DHCP hosts $out @ $domain <- $@..." terom@82: terom@84: do_update $out $OPT/bin/pvl.hosts-dhcp \ terom@84: --hosts-charset=$CHARSET \ terom@98: --hosts-domain=$domain \ terom@98: "$@" terom@52: else terom@98: log_skip "Generating DHCP hosts $out <- $@: not changed" terom@52: fi terom@52: } terom@52: terom@84: ## Generate reverse zone from hosts hosts using pvl.hosts-dns: terom@84: # terom@84: # update_hosts_reverse out/hosts/$reverse $reverse in/hosts/$hosts terom@84: function update_hosts_reverse { terom@85: local out="$1"; shift terom@85: local reverse="$1"; shift terom@84: terom@93: if check_update "$out" "$@"; then terom@93: log_update "Generating reverse hosts zone $out <- $@..." terom@84: terom@85: do_update "$out" $OPT/bin/pvl.hosts-dns \ terom@84: --hosts-charset=$CHARSET \ terom@85: --reverse-zone="$reverse" \ terom@93: "$@" terom@84: else terom@93: log_skip "Generating reverse hosts $out <- $@: not changed" terom@84: fi terom@84: } terom@84: terom@61: ## Update .serial number: terom@61: # terom@95: # do_update_serial .../serials/$zone $serial terom@61: # terom@61: function do_update_serial { terom@95: local dst="$1" terom@95: local serial="$2" terom@61: terom@95: echo $serial > $dst terom@61: } terom@61: terom@61: terom@82: ## Generate new serial for zone using pvl.dns-serial, if the zone data has changed: terom@52: # terom@95: # update_serial .../serials/$zone $serial $deps... terom@52: # terom@52: # Supports SERIAL_FORCE/NOOP. terom@52: # Updates $SERIALS/$zone.serial. terom@52: function update_serial { terom@95: local dst="$1"; shift terom@85: local serial="$1"; shift terom@95: terom@95: local old=$(test -e "$dst" && cat "$dst" || echo '') terom@52: terom@52: # test terom@52: if [ $SERIAL_FORCE ]; then terom@95: log_force "Updating $dst: $old <- $serial: forced" terom@52: terom@95: do_update_serial "$dst" "$serial" terom@52: terom@95: elif ! check_update "$dst" "$@"; then terom@95: log_skip "Updating $dst: $old <- $serial: not changed" terom@52: terom@52: elif [ $SERIAL_NOOP ]; then terom@95: log_noop "Updating $dst: $old <- $serial: skipped" terom@52: terom@52: else terom@95: log_update "Updating $dst: $old <- $serial" terom@52: terom@95: do_update_serial "$dst" "$serial" terom@52: fi terom@52: } terom@52: terom@85: ## Generate zone file from source using pvl.dns-zone: terom@52: # terom@85: # update_zone out/zones/$zone in/zones/$zone var/serials/$zone terom@85: function update_zone { terom@95: local out="$1"; shift terom@95: local src="$1"; shift terom@95: local serial="$1"; shift terom@88: local serial_opt= terom@88: terom@88: if [ -n "$serial" -a -f "$serial" ]; then terom@88: serial_opt="--serial=$(cat "$serial")" terom@88: elif [ $SERIAL_NOOP ]; then terom@88: warn "$out: noop'd serial, omitting" terom@88: else terom@88: fail "$out: missing serial: $serial" terom@88: fi terom@52: terom@95: if check_update "$out" "$src" "$serial" "$@"; then terom@52: log_update "Generating $out <- $src..." terom@52: terom@85: do_update "$out" $OPT/bin/pvl.dns-zone "$src" \ terom@90: --include-path=$SRV/var/zones \ terom@88: $serial_opt terom@52: else terom@52: log_skip "Generating $out <- $src: not changed" terom@52: fi terom@52: } terom@52: terom@91: ## Generate dhcp confs from source using pvl.dhcp-conf: terom@91: function update_dhcp_conf { terom@91: local out="$1" terom@91: local src="$2" terom@91: terom@91: if check_update "$out" "$src"; then terom@91: log_update "Generating $out <- $src..." terom@91: terom@91: do_update "$out" $OPT/bin/pvl.dhcp-conf "$src" \ terom@91: --include-path=$SRV/var/dhcp terom@91: else terom@91: log_skip "Generating $out <- $src: not changed" terom@91: fi terom@91: } terom@91: terom@82: ## Test hosts zone for validity using pvl.hosts-check: terom@52: # terom@82: # check_hosts .../hosts terom@52: function check_hosts { terom@52: local hosts=$1; shift 1 terom@82: terom@82: # TODO terom@82: check $hosts \ terom@82: $OPT/bin/pvl.hosts-check $hosts terom@52: } terom@52: terom@52: ## Test zone file for validity using named-checkzone: terom@52: # terom@82: # check_zone ..../$zone $origin terom@52: function check_zone { terom@82: local zone=$1 terom@82: local origin=$2 terom@52: terom@90: log_check "Checking $zone @ $origin..." terom@90: terom@82: # checkzone is very specific about the order of arguments, -q must be first terom@82: check $zone $NAMED_CHECKZONE $origin $zone terom@52: } terom@52: terom@62: ## Test DHCP configuration for validity using dhcpd -t: terom@62: # terom@62: # check_dhcp [$conf] terom@62: # terom@62: # Defaults to the global $DHCPD_CONF. terom@62: # Fails if the check fails. terom@62: function check_dhcp { terom@62: local conf=${1:-$DHCPD_CONF} terom@90: terom@90: log_check "Checking DHCP $conf..." terom@62: terom@68: if [ ! -e $DHCPD ]; then terom@68: log_warn "check_dhcp: dhcpd not installed, skipping: $conf" terom@68: return 0 terom@68: fi terom@68: terom@82: check $conf \ terom@66: $DHCPD -cf $conf -t terom@62: } terom@62: terom@63: ## Test DHCP configuration of given settings/dhcp using check_dhcp $DHCP_DATA/$host.conf: terom@62: # terom@63: # check_dhcp_conf $conf terom@63: # terom@63: function check_dhcp_conf { terom@66: local conf=$1; terom@62: terom@63: check_dhcp $DHCP_DATA/$conf.conf terom@62: } terom@62: terom@82: ### Deploy terom@94: # set by do_reload_zone if zone data has actually been reloaded terom@94: RELOAD_ZONES= terom@94: terom@82: ## Run rndc reload terom@66: function do_reload_zones { terom@59: # run terom@59: indent " rndc: " \ terom@59: $RNDC reload terom@66: terom@66: # set flag terom@66: RELOAD_ZONES=y terom@59: } terom@59: terom@52: ## Load update zonefiles into bind: terom@52: # terom@61: # reload_zones terom@52: # terom@52: # Invokes `rndc reload`, showing its output. terom@61: function reload_zones { terom@52: local msg="Reload zones" terom@52: terom@61: if [ $RELOAD_FORCE ]; then terom@59: log_force "$msg..." terom@59: terom@66: do_reload_zones terom@59: terom@61: elif [ $RELOAD_NOOP ]; then terom@59: log_noop "$msg: skipped" terom@52: terom@68: elif [ ! -e $RNDC ]; then terom@68: log_warn "reload_zones: rndc not installed, skipping" terom@68: terom@68: elif [ ! -e $RNDC_KEY ]; then terom@68: log_warn " $msg: rndc: key not found: $RNDC_KEY" terom@68: terom@52: elif [ ! -r $RNDC_KEY ]; then terom@52: log_error " $msg: rndc: permission denied: $RNDC_KEY" terom@52: terom@59: return 1 terom@59: terom@52: else terom@52: log_update "$msg..." terom@52: terom@52: # run terom@66: do_reload_zones terom@66: fi terom@66: } terom@66: terom@66: ## Reload DHCP by restarting it, if running: terom@66: # terom@66: # do_reload_dhcp terom@66: # terom@66: # Does NOT restart dhcp if it is not running (status). terom@66: function do_reload_dhcp { terom@66: if cmd_test $DHCPD_INIT status >/dev/null; then terom@66: cmd $DHCPD_INIT restart terom@66: else terom@66: log_warn "dhcpd not running; did not restart" terom@66: fi terom@66: } terom@66: terom@66: ## Reload dhcp hosts terom@66: # terom@66: # reload_dhcp terom@66: # terom@66: # noop's if we haven't reloaded zones terom@66: function reload_dhcp { terom@66: local msg="Reload DHCP hosts" terom@66: terom@66: if [ $RELOAD_FORCE ]; then terom@66: log_force "$msg..." terom@66: terom@66: do_reload_dhcp terom@66: terom@66: elif [ $RELOAD_NOOP ]; then terom@66: log_noop "$msg: skipped" terom@68: terom@68: elif [ ! -e $DHCPD ]; then terom@68: log_warn "reload_dhcp: dhcpd not installed, skipping: $conf" terom@68: terom@66: else terom@66: log_update "$msg..." terom@66: terom@66: # run terom@66: do_reload_dhcp terom@52: fi terom@52: } terom@61: terom@82: ### Commit terom@82: ## Commit changes to version control: terom@52: # terom@96: # update_commit .../etc "commit message" terom@52: # terom@82: # Invokes `hg commit`, first showing the diff. terom@95: function update_commit { terom@96: local repo="$1" terom@52: local commit_msg="$COMMIT_MSG" terom@52: terom@82: local msg="Commit changes" terom@52: terom@52: # operate? terom@52: if [ $COMMIT_FORCE ]; then terom@95: log_force "$msg: $commit_msg" terom@52: terom@96: [ $LOG_DIFF ] && indent " " hg_diff $repo terom@52: terom@96: hg_commit "$repo" "$commit_msg" terom@96: terom@96: elif ! hg_modified "$repo"; then terom@89: log_warn "$msg: no changes" terom@52: terom@52: elif [ $COMMIT_SKIP ]; then terom@52: log_noop "$msg: skipped" terom@57: terom@57: # still show diff, though terom@96: [ $LOG_DIFF ] && indent " " hg_diff "$repo" terom@52: else terom@95: log_update "$msg: $commit_msg" terom@52: terom@96: [ $LOG_DIFF ] && indent " " hg_diff $repo terom@96: terom@96: hg_commit "$repo" "$commit_msg" terom@52: fi terom@52: }