Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#!/bin/sh## netcf-transaction: save/restore current network interface configuration## chkconfig: - 09 91# description: This script can save the current state of network config, \# and later revert to that config, or commit the new config \# (by deleting the snapshot). At boot time, if there are \# uncommitted changes to the network config, they are \# reverted (and the discarded changes are archived in \# /var/lib/netcf/network-rollback-*).### BEGIN INIT INFO# Provides: netcf-transaction# Required-Start: $local_fs# Short-Description: save/restore network configuration files# Description: This script can save the current state of network config,# and later revert to that config, or commit the new config# (by deleting the snapshot). At boot time, if there are# uncommitted changes to the network config, they are# reverted (and the discarded changes are archived in# /var/lib/netcf/network-rollback-*).#### END INIT INFO# special exit code that means a command was issued that is invalid for the# current state (e.g. change-begin when there is already an open transaction)EINVALID_IN_THIS_STATE=199sysconfdir="/etc"localstatedir="/var"netconfdir="$sysconfdir"/sysconfig/network-scriptssnapshotdir="$localstatedir"/lib/netcf/network-snapshotrollbackdirbase="$localstatedir"/lib/netcf/network-rollback# Source function library.test ! -r "$sysconfdir"/rc.d/init.d/functions ||. "$sysconfdir"/rc.d/init.d/functions# take a snapshot of current network configuration scriptschange_begin (){if test -e "$snapshotdir"thenecho "There is already an open transaction ($snapshotdir exists)"return $EINVALID_IN_THIS_STATEfiif ! mkdir -p "$snapshotdir"thenecho "failed to create snapshot directory $snapshotdir"return 1fifor f in "$netconfdir"/ifcfg-* "$netconfdir"/route-* \"$netconfdir"/rule-*dotest ! -f "$f" && continueif ! cp -p "$f" "$snapshotdir"thenecho "failed to copy $f to $snapshotdir"return 1fidonedate >"$snapshotdir"/date}change_commit (){if test ! -d "$snapshotdir"thenecho "No pending transaction to commit"return $EINVALID_IN_THIS_STATEfiif ! rm -rf "$snapshotdir"thenecho "Failed to remove obsolete snapshot directory $snapshotdir"fi}# rollback network configuration to last snapshot (if one exists)change_rollback (){if test ! -d "$snapshotdir"thenecho "No pending transaction to rollback"return $EINVALID_IN_THIS_STATEfirollback_ret=0# eliminate all but the last 20 rollback savesLC_ALL=C ls -d "$rollbackdirbase"-* 2>/dev/null | head -n -20 |\while read rdoif ! rm -rf "$r"then# indicate an error, but continueecho "Failed to remove obsolete rollback directory $r"rollback_ret=1fidone# save a copy of the current config before rollback "just in case"rollbackdir=$rollbackdirbase-$(date +%Y.%m.%d-%H:%M:%S)if ! mkdir -p "$rollbackdir"thenecho "failed to create rollback directory $rollbackdir"return 1fifor f in "$netconfdir"/ifcfg-* "$netconfdir"/route-* \"$netconfdir"/rule-*dotest ! -f "$f" && continueif ! cp -p "$f" "$rollbackdir"thenecho "failed to copy $f to $rollbackdir"return 1fidone# There are 4 classes of files, each handled slightly differently to# minimize disruption in services:# 1) file in both, unmodified - just erase the snapshot copy# 2) file in both, modified - copy the snapshot version over# the current & erase copy# 3) file in current only - remove the file# 4) file in snapshot only - copy the snapshot file to current## We handle the 1st three cases in one loop going through all# current config files, and what is left over in snapshotdir is,# by definition, case 4.## (NB: we can't mv the files, because then the selinux labels# don't get reset properly.)for f in "$netconfdir"/ifcfg-* "$netconfdir"/route-* \"$netconfdir"/rule-*dotest ! -f "$f" && continuesnapshotf=$snapshotdir/${f##*/}if test -f "$snapshotf"then# Case (1) & (2) (only copies if they're different)if ! cmp -s "$snapshotf" "$f"thenif ! cp -pf "$snapshotf" "$f"thenecho "failed to restore $snapshotf to $f"return 1fifiif ! rm -f "$snapshotf"then# indicate an error, but continueecho "Failed to remove obsolete snapshot file $snapshotf"rollback_ret=1fielse# Case (3)if ! rm -f "$f"then# indicate an error, but continueecho "Failed to remove unwanted config file $f"rollback_ret=1fifidone# Case (4)for f in "$snapshotdir"/ifcfg-* "$snapshotdir"/route-* \"$snapshotdir"/rule-*dotest ! -f "$f" && continueif ! cp -pf "$f" "$netconfdir"thenecho "failed to restore $f to $netconfdir"return 1fidonetest -f "$snapshotdir"/date \&& echo Rolled back to network config state of $(cat "$snapshotdir"/date)if ! rm -rf "$snapshotdir"then# indicate an error, but continueecho "Failed to remove obsolete snapshot directory $snapshotdir"rollback_ret=1fireturn $rollback_ret}# usage [val]# Display usage string, then exit with VAL (defaults to 2).usage() {echo $"Usage: $0 {change-begin|change-commit|change-rollback|snapshot-dir|start|stop|status|restart|condrestart|try-restart|reload|force-reload}"exit ${1-2}}# See how we were called.if test $# != 1; thenusagefiretval=0case "$1" in# commands required in all Fedora initscriptsstart|restart|reload|force-reload|condrestart|try-restart)echo -n $"Running $prog $1: "change_rollback# ignore the "no pending transaction" errortest "$retval" != "$EINVALID_IN_THIS_STATE" && retval=$?echo;;stop|status)if test -d "$snapshotdir"thenecho $"There is an open transaction"elseecho $"No open transaction"fi;;--help)usage 0;;# specific to netcf-transactionchange-begin)change_beginretval=$?;;change-commit)change_commitretval=$?;;change-rollback)change_rollbackretval=$?;;snapshot-dir)echo $snapshotdir;;*)usage;;esacexit $retval