#!/usr/bin/env bash
#
# Copyright (C) 2000-2022 Kern Sibbald
# License: BSD 2-Clause; see file LICENSE-FOSS
#
# create btrfs volume and play with snapshots
#
# this test fail, it looks like btrfs is not working like before
# subvolume are not detected or maybe not tested the right way ...
#set -x
TestName="snapshot-btrfs-test"
JobName=Incremental
. scripts/functions

require_linux

${rscripts}/cleanup
${rscripts}/copy-test-confs

USE_SUDO=${USE_SUDO:-sudo}

if [ "$USE_SUDO" = sudo ]; then
    echo sudo=yes > $conf/bsnapshot.conf
fi

if ! which mkfs.btrfs > /dev/null; then
    print_debug "Install btrfs tools (mkfs.btrfs is not found)"
    exit 1
fi

if [ ! -f $cwd/btrfs.img ]; then
    dd of=$cwd/btrfs.img if=/dev/zero count=300 bs=1MB
    $USE_SUDO mkfs.btrfs $cwd/btrfs.img
fi

mkdir -p $cwd/btrfs
$USE_SUDO mount -o loop -t btrfs $cwd/btrfs.img $cwd/btrfs
if [ $? -ne 0 ]; then
    print_debug "ERROR: Unable to mount btrfs image"
    print_debug "Try to delete $cwd/btrfs.img and restart again"
    exit 1
fi

GID=`id -g`
$USE_SUDO chown $USER:$GID $cwd/btrfs

trap "$USE_SUDO umount $cwd/btrfs" EXIT 

echo "$cwd/btrfs" >${tmp}/file-list
cp -p $src/src/dird/{admin,backup}.c $cwd/btrfs
ln -sf $src/src/lib/{alist,base64}.c $cwd/btrfs

cd $cwd/btrfs
ln -sf ../README .

cd $cwd

make -C $cwd/build/src/tools install-bsnapshot

$bperl -e 'add_attribute("$conf/bacula-dir.conf", "Enable Snapshot", "yes", "FileSet")'
$bperl -e 'add_attribute("$conf/bacula-dir.conf", "Snapshot Retention", "300", "Client")'

change_jobname CompressedTest $JobName
start_test

cat <<END_OF_DATA >${tmp}/bconcmds
@output /dev/null
messages
@$out ${tmp}/log1.out
setdebug level=30 tags=snapshot fd trace=1
label storage=File volume=TestVolume001
run job=$JobName yes
status client
wait
messages
@output ${tmp}/list1
list files jobid=1
@$out ${tmp}/list1.snap_list
.jlist snapshot
@$out ${tmp}/list1.snap_listclient
snapshot listclient
@$out ${tmp}/list1.snap_update
snapshot update client snapshotid=1 comment="test1"
snapshot update client snapshotid=1 retention=3
@$out ${tmp}/list1.snap_list2
.jlist snapshot snapshotid=1
@$out ${tmp}/list1.snap_list22
.jlist snapshot snapshotid=3
@$out ${tmp}/list1.snap_prune
@sleep 4
snapshot prune client yes
@$out ${tmp}/list1.snap_list3
.jlist snapshot
@$out ${tmp}/list1.snap_listclient2
snapshot listclient
quit
END_OF_DATA

run_bacula

grep '{' $tmp/list1.snap_list | perl -MJSON -e '
$l = <>;
$j = JSON::decode_json($l) ;
exit (scalar(@{$j->{data}}) == 1);'

if [ $? != 1 ]; then
    print_debug "ERROR: Incorrect data in $tmp/list1.snap_list"
    estat=1
fi

nb=`grep deleted $tmp/list1.snap_prune | wc -l`
if [ $nb != 1 ]; then
    print_debug "ERROR: Should prune one snapshots"
    estat=1
fi

# snapshot updated
grep '{' $tmp/list1.snap_list2 | perl -MJSON -e '
$l = <>;
$j = JSON::decode_json($l) ;
exit (scalar(@{$j->{data}}) == 1 && $j->{data}->[0]->{comment} eq "test1" && $j->{data}->[0]->{retention} == 3);'

if [ $? != 1 ]; then
    print_debug "ERROR: Incorrect data in $tmp/list1.snap_list2"
    estat=1
fi

# One snapshot gone
grep '{' $tmp/list1.snap_list3 | perl -MJSON -e '
$l = <>;
$j = JSON::decode_json($l) ;
exit (scalar(@{$j->{data}}) == 0);'

if [ $? != 1 ]; then
    print_debug "ERROR: Incorrect data in $tmp/list1.snap_list3"
    estat=1
fi

check_for_zombie_jobs storage=File

cat <<END_OF_DATA >${tmp}/bconcmds
@# 
@# now do a restore
@#
@$out ${tmp}/log2.out
restore where=${tmp}/bacula-restores storage=File select all yes done
wait
status client
messages
quit
END_OF_DATA

run_bconsole

rmdir $cwd/btrfs/.snapshots &> /dev/null
$rscripts/diff.pl -s $cwd/btrfs -d $tmp/bacula-restores/$cwd/btrfs

if [ $? -ne 0 ]; then
    print_debug "ERROR: Found differences"
    estat=1
#    touch $tmp/stop.$$
#    while [ -f $tmp/stop.$$ ]; do
#        sleep 30
#    done
fi

grep .snapshots $tmp/list1
if [ $? -eq 0 ]; then
    print_debug "ERROR: Should not find .snapshots directory"
    estat=1
fi

f=`ls $working/*-fd.trace`
cp $f $working/job1.trace
cp /dev/null $f

grep -E "Adding $cwd/btrfs dev=[0-9]+ snap.=1 to the mount list" $working/job1.trace > /dev/null
if [ $? -ne 0 ]; then
    print_debug "ERROR: Should find $cwd/btrfs in the FD $working/job1.trace file"
    estat=1
fi

grep "Create Snapshot of $cwd/btrfs $JobName" $working/job1.trace > /dev/null
if [ $? -ne 0 ]; then
    print_debug "ERROR: Should find snapshot creation in FD $working/job1.trace file"
    estat=1
fi

grep "fname=$cwd/btrfs/admin.c snap=$cwd/btrfs/.snapshots/Incremental.*/admin.c link=$cwd/btrfs/admin.c" $working/job1.trace > /dev/null
if [ $? -ne 0 ]; then
    print_debug "ERROR: Should path convertion in FD $working/job1.trace trace file"
    estat=1
fi

$USE_SUDO btrfs subvolume create $cwd/btrfs/subvol
$USE_SUDO btrfs subvolume list $cwd/btrfs
$USE_SUDO chown $USER:$GID $cwd/btrfs/subvol
cp $cwd/build/README $cwd/btrfs/subvol

sed -i "s/Snapshot Retention/#Snapshot Retention/" $conf/bacula-dir.conf

cat <<END_OF_DATA >${tmp}/bconcmds
@$out ${tmp}/log3.out
reload
setdebug level=20 tags=snapshot fd trace=1
run level=full job=$JobName yes
wait
messages
@output ${tmp}/list3
list files jobid=3
@# 
@# now do a restore
@#
@$out ${tmp}/log4.out
restore where=${tmp}/bacula-restores4 storage=File select all yes done
wait
status client
messages
snapshot list
snapshot listclient
snapshot
6
7
snapshot list
sql
update Snapshot SET Retention=1;

snapshot prune client yes
snapshot list
snapshot listclient 
quit
END_OF_DATA

run_bconsole

echo pause
read a

cp $f $working/job3.trace

grep -E "Adding $cwd/btrfs dev=[0-9]+ snap.=1 to the mount list" $working/job3.trace > /dev/null
if [ $? -ne 0 ]; then
    print_debug "ERROR: Should find $cwd/btrfs in the FD $working/job3.trace file"
    estat=1
fi

grep "Create Snapshot of $cwd/btrfs $JobName" $working/job3.trace > /dev/null
if [ $? -ne 0 ]; then
    print_debug "ERROR: Should find snapshot creation in FD $working/job3.trace file"
    estat=1
fi

grep "fname=$cwd/btrfs/admin.c snap=$cwd/btrfs/.snapshots/Incremental.*/admin.c link=$cwd/btrfs/admin.c" $working/job3.trace > /dev/null
if [ $? -ne 0 ]; then
    print_debug "ERROR: Should find original and snapshot path in FD $working/job3.trace trace file"
    estat=1
fi

grep -E "Adding $cwd/btrfs/subvol dev=[0-9]+ snap.=1 to the mount list" $working/job3.trace > /dev/null
if [ $? -ne 0 ]; then
    print_debug "ERROR: Should find $cwd/btrfs/subvol in the FD $working/job3.trace file"
    estat=1
fi

grep "Create Snapshot of $cwd/btrfs/subvol $JobName" $working/job3.trace > /dev/null
if [ $? -ne 0 ]; then
    print_debug "ERROR: Should find snapshot creation in FD $working/job3.trace file"
    estat=1
fi

grep "fname=$cwd/btrfs/subvol/README snap=$cwd/btrfs/subvol/.snapshots/Incremental.*/README link=$cwd/btrfs/subvol/README" $working/job3.trace > /dev/null
if [ $? -ne 0 ]; then
    print_debug "ERROR: Should path convertion in FD $working/job3.trace trace file"
    estat=1
fi

rmdir $cwd/btrfs/subvol/.snapshots $cwd/btrfs/.snapshots
$rscripts/diff.pl -s $cwd/btrfs -d $tmp/bacula-restores4/$cwd/btrfs

if [ $? -ne 0 ]; then
    print_debug "ERROR: Found differences"
    estat=1
#    touch $tmp/stop.$$
#    while [ -f $tmp/stop.$$ ]; do
#        sleep 30
#    done
fi

$USE_SUDO btrfs subvolume delete $cwd/btrfs/subvol

stop_bacula

check_two_logs

end_test
