Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export SSID='your_ssid'
export WIFIPASS='your_pass'

# Variables for CIFS (Windows/Mac file sharing) archiving.
# If you want to use rsync or rclone, delete or comment out this section
# If you want to use rsync, rclone, or NFS, delete or comment out this section
# and uncomment the rsync or rclone section below.
export ARCHIVE_SYSTEM=cifs
export ARCHIVE_SERVER=your_archive_name_or_ip
Expand Down Expand Up @@ -48,6 +48,12 @@ export SHARE_PASSWORD='password'
# The following is optional
#export RCLONE_FLAGS=()

# Variables for NFS archiving
# Note: SHARE_NAME must be the exact export path on the NAS (e.g. /volume1/TeslaCam)
#export ARCHIVE_SYSTEM=nfs
#export ARCHIVE_SERVER=hostname_or_ip
#export SHARE_NAME='/volume1/TeslaCam'

# The DATA_DRIVE option (formerly USB_DRIVE) is used to specify that you want
# to store recordings on a different drive than the boot drive. If you don't
# plan on using an sd card at all (i.e. you are both booting from and storing
Expand Down
4 changes: 2 additions & 2 deletions run/archiveloop
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ then
exit 1
;;
esac
elif [ "${ARCHIVE_SYSTEM:-none}" = "cifs" ]
elif [ "${ARCHIVE_SYSTEM:-none}" = "cifs" ] || [ "${ARCHIVE_SYSTEM:-none}" = "nfs" ]
then
# For CIFS
# For CIFS and NFS
[[ -n "${SHARE_NAME:-}" && -f /backingfiles/cam_disk.bin ]] && export ARCHIVE_MOUNT=/mnt/archive
[[ -n "${MUSIC_SHARE_NAME:-}" && -f /backingfiles/music_disk.bin ]] && export MUSIC_ARCHIVE_MOUNT=/mnt/musicarchive
fi
Expand Down
46 changes: 46 additions & 0 deletions run/nfs_archive/archive-clips.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash -eu

function connectionmonitor {
while true
do
for _ in {1..5}
do
if timeout 6 /root/bin/archive-is-reachable.sh "$ARCHIVE_SERVER"
then
sleep 5
continue 2
fi
sleep 1
done
log "connection dead, killing archive-clips"
killall rsync || true
sleep 2
killall -9 rsync || true
kill -9 "$1" || true
return
done
}

connectionmonitor $$ &

rsynctmp=".teslausbtmp"
rm -rf "$ARCHIVE_MOUNT/${rsynctmp:?}" || true
mkdir -p "$ARCHIVE_MOUNT/$rsynctmp"

rm -f /tmp/archive-rsync-cmd.log /tmp/archive-error.log

while [ -n "${1+x}" ]
do
# Using --no-o --no-g to prevent permission errors on NFS root squashed shares
if ! (rsync -avhRL --no-o --no-g --remove-source-files --temp-dir="$rsynctmp" --no-perms --omit-dir-times --stats \
--log-file=/tmp/archive-rsync-cmd.log --ignore-missing-args \
--files-from="$2" "$1/" "$ARCHIVE_MOUNT" &> /tmp/rsynclog || [[ "$?" = "24" ]] )
then
cat /tmp/archive-rsync-cmd.log /tmp/rsynclog > /tmp/archive-error.log
exit 1
fi
shift 2
done

rm -rf "$ARCHIVE_MOUNT/${rsynctmp:?}" || true
kill %1 || true
4 changes: 4 additions & 0 deletions run/nfs_archive/archive-is-reachable.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash -eu

ARCHIVE_HOST_NAME="$1"
nc -z -w 5 "$ARCHIVE_HOST_NAME" 2049 > /dev/null 2>&1
9 changes: 9 additions & 0 deletions run/nfs_archive/connect-archive.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash -eu

function mount_if_set() {
local mount_point=$1
[ -z "$mount_point" ] || ensure_mountpoint_is_mounted_with_retry "$mount_point"
}

mount_if_set "${ARCHIVE_MOUNT:-}"
mount_if_set "${MUSIC_ARCHIVE_MOUNT:-}"
6 changes: 6 additions & 0 deletions run/nfs_archive/copy-music.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash -eu

ensure_music_file_is_mounted
/root/bin/copy-music.sh
trim_free_space "$MUSIC_MOUNT"
unmount_music_file
22 changes: 22 additions & 0 deletions run/nfs_archive/disconnect-archive.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash -eu

unmount_if_set() {
local mount_point=$1
if [ -n "$mount_point" ]
then
if findmnt --mountpoint "$mount_point" > /dev/null
then
if timeout 10 umount -f -l "$mount_point" >> "$LOG_FILE" 2>&1
then
log "Unmounted $mount_point."
else
log "Failed to unmount $mount_point."
fi
else
log "$mount_point already unmounted."
fi
fi
}

unmount_if_set "${ARCHIVE_MOUNT:-}" &
unmount_if_set "${MUSIC_ARCHIVE_MOUNT:-}" &
145 changes: 145 additions & 0 deletions run/nfs_archive/verify-and-configure-archive.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#!/bin/bash -eu

function log_progress () {
if declare -F setup_progress > /dev/null
then
setup_progress "verify-and-configure-archive: $*"
return
fi
echo "verify-and-configure-archive: $1"
}

function check_archive_server_reachable () {
log_progress "Verifying that the archive server $ARCHIVE_SERVER is reachable..."
local serverunreachable=false
local default_interface
default_interface=$(route | grep "^default" | awk '{print $NF}')

# Check NFS Port 2049
hping3 -c 1 -S -p 2049 "$ARCHIVE_SERVER" 1>/dev/null 2>&1 ||
hping3 -c 1 -S -p 2049 -I "$default_interface" "$ARCHIVE_SERVER" 1>/dev/null 2>&1 ||
serverunreachable=true

if [ "$serverunreachable" = true ]
then
log_progress "STOP: The archive server $ARCHIVE_SERVER is unreachable on port 2049. Try specifying its IP address instead."
exit 1
fi

log_progress "The archive server is reachable."
}

function check_archive_mountable () {
local test_mount_location="/tmp/archivetestmount"
local share_path="$1"
local mode="$2"

log_progress "Verifying that the archive share is mountable..."

if [ ! -e "$test_mount_location" ]
then
mkdir "$test_mount_location"
fi

local mounted=false

# NFS Mount Command
# Forced vers=3 for wider NAS compatibility (Unifi, Synology, etc)
# proto=tcp and nolock help with stability over wifi
local commandline="mount -t nfs '$ARCHIVE_SERVER:$share_path' '$test_mount_location' -o 'rw,noauto,nolock,proto=tcp,vers=3'"

log_progress "Trying NFS mount command-line:"
log_progress "$commandline"

if eval "$commandline"
then
mounted=true
fi

if [ "$mounted" = false ]
then
log_progress "STOP: unable to mount archive share via NFS"
exit 1
else
log_progress "The archive share is mountable."
if [ "$mode" = "rw" ]
then
if ! touch "$test_mount_location/testfile"
then
log_progress "STOP: archive share is not writeable. Check permissions on NAS."
umount "$test_mount_location"
exit 1
fi
rm "$test_mount_location/testfile"
fi
fi

umount "$test_mount_location"
}

function install_required_packages () {
log_progress "Installing/updating required packages if needed"
apt-get -y --force-yes install hping3 nfs-common
if ! command -v nc > /dev/null
then
apt-get -y --force-yes install netcat || apt-get -y --force-yes install netcat-openbsd
fi
log_progress "Done"
}

install_required_packages

check_archive_server_reachable

if [ -e /backingfiles/cam_disk.bin ]
then
check_archive_mountable "$SHARE_NAME" rw
fi

if [ -n "${MUSIC_SHARE_NAME:+x}" ]
then
if [ "$MUSIC_SIZE" = "0" ]
then
log_progress "STOP: MUSIC_SHARE_NAME specified but no music drive size specified"
exit 1
fi
check_archive_mountable "$MUSIC_SHARE_NAME" ro
fi

function configure_archive () {
log_progress "Configuring the archive..."

local archive_path="/mnt/archive"
local music_archive_path="/mnt/musicarchive"

if [ ! -e "$archive_path" ] && [ -e /backingfiles/cam_disk.bin ]
then
mkdir "$archive_path"
fi

# Remove existing NFS entries to prevent duplicates
sed -i "/^.* nfs .*$/ d" /etc/fstab

if [ -e /backingfiles/cam_disk.bin ]
then
echo "$ARCHIVE_SERVER:$SHARE_NAME $archive_path nfs rw,noauto,nolock,proto=tcp,vers=3 0 0" >> /etc/fstab
elif [ -d "$archive_path" ]
then
rmdir "$archive_path" || log_progress "failed to remove $archive_path"
fi

if [ -n "${MUSIC_SHARE_NAME:+x}" ]
then
if [ ! -e "$music_archive_path" ]
then
mkdir "$music_archive_path"
fi
echo "$ARCHIVE_SERVER:$MUSIC_SHARE_NAME $music_archive_path nfs ro,noauto,nolock,proto=tcp,vers=3 0 0" >> /etc/fstab
elif [ -d "$music_archive_path" ]
then
rmdir "$music_archive_path" || log_progress "failed to remove $music_archive_path"
fi
log_progress "Configured the archive."
}

configure_archive
13 changes: 12 additions & 1 deletion setup/pi/configure.sh
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ function check_archive_configs () {
check_variable "ARCHIVE_SERVER"
check_rsync
;;
nfs)
if [ -e /backingfiles/cam_disk.bin ]
then
check_variable "SHARE_NAME"
fi
check_variable "ARCHIVE_SERVER"
check_rsync
;;
none)
export ARCHIVE_SERVER=localhost
;;
Expand All @@ -163,6 +171,9 @@ function get_archive_module () {
cifs)
echo "run/cifs_archive"
;;
nfs)
echo "run/nfs_archive"
;;
none)
echo "run/none_archive"
;;
Expand Down Expand Up @@ -365,7 +376,7 @@ function install_archive_scripts () {
copy_script "$archive_module"/connect-archive.sh "$install_path"
copy_script "$archive_module"/disconnect-archive.sh "$install_path"
copy_script "$archive_module"/archive-is-reachable.sh "$install_path"
if [ -n "${MUSIC_SHARE_NAME:+x}" ] && grep cifs <<< "$archive_module"
if [ -n "${MUSIC_SHARE_NAME:+x}" ] && grep -E "cifs|nfs" <<< "$archive_module"
then
copy_script "$archive_module"/copy-music.sh "$install_path"
fi
Expand Down
8 changes: 8 additions & 0 deletions setup/pi/setup-teslausb
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,14 @@ function diagnose {
else
echo "ERROR: CIFS archiving selected, but archive not defined in fstab"
fi
elif [ "${ARCHIVE_SYSTEM:-none}" = "nfs" ]
then
if grep -q '/mnt/archive' /etc/fstab
then
echo "NFS archiving selected"
else
echo "ERROR: NFS archiving selected, but archive not defined in fstab"
fi
elif [ "${ARCHIVE_SYSTEM:-none}" = "rclone" ]
then
if [ ! -e "/root/.config/rclone/rclone.conf" ]
Expand Down