diff --git a/CODING_STYLE.TXT b/CODING_STYLE.TXT index 7bc8c6f..18780f4 100644 --- a/CODING_STYLE.TXT +++ b/CODING_STYLE.TXT @@ -25,19 +25,21 @@ Transform old shell scripts using unexpand command ++++ Comments -# Some comment -## Some important comment for the next function +Some command # comment +## Some comment on a new line ################################################# Some separation -++++ Todo comments +++++ Work comments -Whenever there is some idea to postpone, use #TODO: (exact match for searches) +Whenever there is some idea to postpone, use #TODO:dev-name: some remark +A marker must be left where on the line a dev is working (when the work isn't finished). Marker is #WIP:dev-name: some remark +dev-name is mandatory if more than one person is coding ++++ Variables All local variables are lowercase, separated by _ (ex: low_wait) All global variables full upercase, separated by _ (ex: EXEC_TIME) -All instance variables (verbose, silent, etc) have prefix _ and are full upercase, separated by _ (ex: _VERBOSE_INSTANCE) +All environment variables (verbose, silent, debug, etc) have prefix _ and are full upercase, separated by _ (ex: _PARANOIA_DEBUG) ++++ Functions diff --git a/osync.sh b/osync.sh index a37f890..b5ca3fb 100755 --- a/osync.sh +++ b/osync.sh @@ -4,7 +4,7 @@ PROGRAM="Osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(L) 2013-2015 by Orsiris \"Ozy\" de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.1-unstable -PROGRAM_BUILD=2015091002 +PROGRAM_BUILD=2015091003 ## type doesn't work on platforms other than linux (bash). If if doesn't work, always assume output is not a zero exitcode if ! type -p "$BASH" > /dev/null; then @@ -62,7 +62,7 @@ function Dummy { sleep .1 } -function _logger { +function _Logger { local value="${1}" # What to log echo -e "$value" >> "$LOG_FILE" @@ -72,7 +72,7 @@ function _logger { } function Logger { - local value="${1}" # What to log + local value="${1}" # Sentence to log (in double quotes) local level="${2}" # Log level: DEBUG, NOTICE, WARN, ERROR, CRITIAL # Special case in daemon mode we should timestamp instead of counting seconds @@ -83,22 +83,27 @@ function Logger { fi if [ "$level" == "CRITICAL" ]; then - _logger "$prefix\e[41m$value\e[0m" + _Logger "$prefix\e[41m$value\e[0m" ERROR_ALERT=1 + return elif [ "$level" == "ERROR" ]; then - _logger "$prefix\e[91m$value\e[0m" + _Logger "$prefix\e[91m$value\e[0m" ERROR_ALERT=1 + return elif [ "$level" == "WARN" ]; then - _logger "$prefix\e[93m$value\e[0m" + _Logger "$prefix\e[93m$value\e[0m" + return elif [ "$level" == "NOTICE" ]; then - _logger "$prefix$value" + _Logger "$prefix$value" + return elif [ "$level" == "DEBUG" ]; then if [ "$_DEBUG" == "yes" ]; then - _logger "$prefix$value" + _Logger "$prefix$value" + return fi else - _logger "\e[41mLogger function called without proper loglevel.\e[0m" - _logger "$prefix$value" + _Logger "\e[41mLogger function called without proper loglevel.\e[0m" + _Logger "$prefix$value" fi } @@ -918,13 +923,54 @@ function _LEGACY_CheckMasterSlaveDirs { fi } -function CheckMinimumSpace { +function _CheckDiskSpaceLocal { + local replica_path="${1}" + __CheckArguments 1 $# $FUNCNAME "$*" + + Logger "Checking minimum disk space in [$replica_path]." "NOTICE" + + local initiator_space=$(df -P "$replica_path" | tail -1 | awk '{print $4}') + if [ $initiator_space -lt $MINIMUM_SPACE ]; then + Logger "There is not enough free space on initiator [$initiator_space KB]." "WARN" + fi +} + +function _CheckDiskSpaceRemote { + local replica_path="${1}" + __CheckArguments 1 $# $FUNCNAME "$*" + + Logger "Checking minimum disk space on target [$replica_path]." "NOTICE" + + CheckConnectivity3rdPartyHosts + CheckConnectivityRemoteHost + + cmd="$SSH_CMD \"$COMMAND_SUDO df -P \\\"$replca_path\\\"\" > $RUN_DIR/osync_$FUNCNAME_$SCRIPT_PID 2>&1 &" + eval $cmd + WaitForTaskCompletion $! 0 1800 + if [ $? != 0 ]; then + Logger "Cannot get free space on target [$replica_path]." "ERROR" + Logger "Command output:\n$(cat $RUN_DIR/osync_$FUNCNAME_$SCRIPT_PID)" + else + local target_space=$(cat $RUN_DIR/osync_$FUNCNAME_$SCRIPT_PID | tail -1 | awk '{print $4}') + if [ $target_space -lt $MINIMUM_SPACE ]; then + Logger "There is not enough free space on target [$replica_path]." "WARN" + fi + fi +} + +function CheckDiskSpace { + _CheckDiskSpaceLocal "$INITIATOR_SYNC_DIR" + if [ "$REMOTE_SYNC" == "no" ]; then + _CheckDiskSpaceLocal "$TARGET_SYNC_DIR" + else + _CheckDiskSpaceRemote "$TARGET_SYNC_DIR" + fi +} + +function _LEGAGY_CheckMinimumSpace { Logger "Checking minimum disk space on initiator and target." "NOTICE" - INITIATOR_SPACE=$(df -P "$INITIATOR_SYNC_DIR" | tail -1 | awk '{print $4}') - if [ $INITIATOR_SPACE -lt $MINIMUM_SPACE ]; then - Logger "There is not enough free space on initiator [$INITIATOR_SPACE KB]." "ERROR" - fi + if [ "$REMOTE_SYNC" == "yes" ]; then CheckConnectivity3rdPartyHosts @@ -980,7 +1026,47 @@ function RsyncExcludeFrom { fi } +function _WriteLockFilesLocal { + local lockfile="${1}" + __CheckArguments 1 $# $FUNCNAME "$*" + + echo "$SCRIPT_PID@$SYNC_ID" > "$lockfile" #TODO: Determine best format for lockfile for v2 + if [ $? != 0 ]; then + Logger "Could not create lock file [$lockfile]." "CRITICAL" + exit 1 + else + Logger "Locked replica on [$lockfile]." "NOTICE" + fi +} + +function _WriteLockFilesRemote { + local lockfile="${1}" + __CheckArguments 1 $# $FUNCNAME "$*" + + CheckConnectivity3rdPartyHosts + CheckConnectivityRemoteHosts + + cmd="$SSH_CMD \"echo $SCRIPT_PID@$SYNC_ID | $COMMAND_SUDO tee \\\"$lock_file\\\" > /dev/null \"" & + eval $cmd + WaitForTaskCompletion $? 0 1800 + if [ $? != 0 ]; then + Logger "Could not set lock on remote target replica." "CRITICAL" + exit 1 + else + Logger "Locked remote target replica." "NOTICE" + fi +} + function WriteLockFiles { + _WriteLockFilesLocal "$INITIATOR_LOCKFILE" + if [ "$REMOTE_SYNC" != "yes" ]; then + _WriteLockFilesLocal "$TARGET_LOCKFILE" + else + _WriteLockFilesRemote "$TARGET_LOCKFILE" + fi +} + +function _LEGAGY_WriteLockFiles { echo $SCRIPT_PID > "$INITIATOR_LOCK" if [ $? != 0 ]; then Logger "Could not set lock on initiator replica." "CRITICAL" @@ -1012,12 +1098,50 @@ function WriteLockFiles { fi } +function _CheckLocksLocal { + local lockfile="${1}" + __CheckArguments 1 $# $FUNCNAME "$*" + + #WIP:deajan: Refactor here +} + +function _CheckLocksRemote { + local lockfile="${1}" + __CheckArguments 1 $# $FUNCNAME "$*" + + CheckConnectivity3rdPartyHosts + CheckConnectivityRemoteHosts + + #WIP:deajan: Refactor here +} + +function CheckLocks { + if [ $_NOLOCKS -eq 1 ]; then + return 0 + fi + + # Don't bother checking for locks when FORCE_UNLOCK is set + if [ $FORCE_UNLOCK -eq 1 ]; then + WriteLockFiles + if [ $? != 0 ]; then + exit 1 + fi + fi + _CheckLocksLocal "$INITIATOR_LOCKFILE" + if [ "$REMOTE_SYNC" != "yes" ]; then + _CheckLocksLocal "$TARGET_LOCKFILE" + else + _CheckLocksRemote "$TARGET_LOCKFILE" + fi +} + function LockDirectories { if [ $_NOLOCKS -eq 1 ]; then return 0 fi - if [ $force_unlock -eq 1 ]; then + # Don't bother checking for locks when FORCE_UNLOCK is set + if [ $FORCE_UNLOCK -eq 1 ]; then WriteLockFiles if [ $? != 0 ]; then exit 1 @@ -1026,8 +1150,8 @@ function LockDirectories { Logger "Checking for replica locks." "NOTICE" - if [ -f "$INITIATOR_LOCK" ]; then - initiator_lock_pid=$(cat $INITIATOR_LOCK) + if [ -f "$INITIATOR_LOCKFILE" ]; then + initiator_lock_pid=$(cat $INITIATOR_LOCKFILE) Logger "Master lock pid present: $initiator_lock_pid" "DEBUG" ps -p$initiator_lock_pid > /dev/null 2>&1 if [ $? != 0 ]; then @@ -1041,7 +1165,7 @@ function LockDirectories { if [ "$REMOTE_SYNC" == "yes" ]; then CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost - eval "$SSH_CMD \"if [ -f \\\"$TARGET_LOCK\\\" ]; then cat \\\"$TARGET_LOCK\\\"; fi\" > $RUN_DIR/osync_remote_target_lock_$SCRIPT_PID" & + eval "$SSH_CMD \"if [ -f \\\"$TARGET_LOCKFILE\\\" ]; then cat \\\"$TARGET_LOCKFILE\\\"; fi\" > $RUN_DIR/osync_remote_target_lock_$SCRIPT_PID" & child_pid=$! WaitForTaskCompletion $child_pid 0 1800 if [ -f $RUN_DIR/osync_remote_target_lock_$SCRIPT_PID ]; then @@ -1049,9 +1173,9 @@ function LockDirectories { target_lock_id=$(cat $RUN_DIR/osync_remote_target_lock_$SCRIPT_PID | cut -d'@' -f2) fi else - if [ -f "$TARGET_LOCK" ]; then - target_lock_pid=$(cat "$TARGET_LOCK" | cut -d'@' -f1) - target_lock_id=$(cat "$TARGET_LOCK" | cut -d'@' -f2) + if [ -f "$TARGET_LOCKFILE" ]; then + target_lock_pid=$(cat "$TARGET_LOCKFILE" | cut -d'@' -f1) + target_lock_id=$(cat "$TARGET_LOCKFILE" | cut -d'@' -f2) fi fi @@ -1839,8 +1963,8 @@ function Init { INITIATOR_STATE_DIR="$INITIATOR_SYNC_DIR$OSYNC_DIR/state" TARGET_STATE_DIR="$TARGET_SYNC_DIR$OSYNC_DIR/state" STATE_DIR="$OSYNC_DIR/state" - INITIATOR_LOCK="$INITIATOR_STATE_DIR/lock" - TARGET_LOCK="$TARGET_STATE_DIR/lock" + INITIATOR_LOCKFILE="$INITIATOR_STATE_DIR/lock" + TARGET_LOCKFILE="$TARGET_STATE_DIR/lock" ## Working directories to keep backups of updated / deleted files INITIATOR_BACKUP_DIR="$OSYNC_DIR/backups" @@ -2141,7 +2265,7 @@ fi stats=0 PARTIAL=0 -force_unlock=0 +FORCE_UNLOCK=0 no_maxtime=0 # Alert flags opts="" @@ -2183,7 +2307,7 @@ do opts=$opts" --partial" ;; --force-unlock) - force_unlock=1 + FORCE_UNLOCK=1 opts=$opts" --force-unlock" ;; --no-maxtime) @@ -2305,15 +2429,13 @@ then HARD_MAX_EXEC_TIME=0 fi CheckReplicaPaths - CheckMinimumSpace + CheckDiskSpace + RunBeforeHook + Main if [ $? == 0 ]; then - RunBeforeHook - Main - if [ $? == 0 ]; then - SoftDelete - fi - RunAfterHook + SoftDelete fi + RunAfterHook fi else Logger "Environment not suitable to run osync." "CRITICAL"