#!/usr/bin/env bash
#
# Copyright (C) 2000-2021 Kern Sibbald
# Copyright (C) 2021-2023 Bacula Systems SA
# License: BSD 2-Clause; see file LICENSE-FOSS
#
# Run a simple backup of the Bacula build directory
#   then restore it. Use the Set Volume Read Only storage
#   daemon directive.
#
TestName="read-only-volume-test"
JobName=backup
. scripts/functions

scripts/cleanup
scripts/copy-confs


# TODO: Run the command with jobid=%j in a runscript
# TODO: Run the command with concurrent jobs and MaximumVolumeJobs = 1
# TODO: Check how the immutable flag is removed

# Zap out any schedule in default conf file so that
#  it doesn't start during our test
#
outf="$tmp/sed_tmp"
echo "s%  Schedule =%# Schedule =%g" >${outf}
cp $scripts/bacula-dir.conf $tmp/1
sed -f ${outf} $tmp/1 >$scripts/bacula-dir.conf

mkdir -p $tmp/add

$bperl -e "add_attribute('$conf/bacula-sd.conf', 'SetVolumeReadOnly', 'yes', 'Device')"
$bperl -e "add_attribute('$conf/bacula-sd.conf', 'MinimumVolumeProtectionTime', '10s', 'Device', 'FileChgr2-Dev1')"
$bperl -e "add_attribute('$conf/bacula-sd.conf', 'MinimumVolumeProtectionTime', '10s', 'Device', 'FileChgr2-Dev2')"
$bperl -e "add_attribute('$conf/bacula-dir.conf', 'MaximumVolumeBytes', '70MB', 'Pool')"
$bperl -e "add_attribute('$conf/bacula-dir.conf', 'MaximumVolumeJobs', '1', 'Pool')"
$bperl -e "add_attribute('$conf/bacula-dir.conf', 'VolumeRetention', '20s', 'Pool', 'Default')"
$bperl -e "add_attribute('$conf/bacula-dir.conf', 'LabelFormat', 'Default', 'Pool', 'Default')"
$bperl -e "add_attribute('$conf/bacula-dir.conf', 'ActionOnPurge', 'Truncate', 'Pool')"
$bperl -e "add_attribute('$conf/bacula-sd.conf', 'AlignedDevice', '$tmp/add', 'Device')"

cat <<EOF >> $conf/bacula-dir.conf
Pool {
  Name = Test1
  Pool Type = Backup 
  Recycle = yes                       # Bacula can automatically recycle Volumes
  AutoPrune = no                     # Prune expired volumes
  Volume Retention = 5s
  Maximum Volumes = 100               # Limit number of Volumes in Pool
  MaximumVolumeBytes = 50MB
  MaximumVolumeJobs = 1
  LabelFormat = Test1
  ActionOnPurge = Truncate
}

Job {
  Name = acljob
  Jobdefs = DefaultJob
  ClientRunBeforeJob = "sleep 5"
  RunScript {
    Console = "update volumeprotect jobid=%i"
    RunsOnClient = no
    RunsWhen = After
  }
}
Console {   
  Name = restricted-job
  Password = xxx
  JobAcl    =  acljob
  ClientAcl = $HOST-fd
  PoolAcl   = File
  CatalogAcl  = *all*
  FileSetAcl  = *all*
  CommandAcl  = *all*
  StorageAcl  = File1
  WhereAcl = *all*
  DirectoryAcl = *all*
  UserIdAcl = *all*
}

Job {
  Name = adm-update-protected
  Type = Admin
  Runscript {
   Console = "update volumeprotect"
   RunsOnClient = no
   RunsWhen = Before
  }
  JobDefs = DefaultJob
}
EOF

cat <<EOF > $tmp/bconsole.conf.job
Console {
  Name = restricted-job
  Password = xxx
}
Director {
  Name = $HOST-dir
  DIRport = $BASEPORT
  address = localhost
  Password = xxx
}
EOF

change_jobname BackupClient1 $JobName
start_test

cat <<END_OF_DATA >$tmp/bconcmds
@output /dev/null
messages
@$out $tmp/log1.out
setdebug level=50 tags=volume trace=1 storage=File1
setdebug level=50 tags=volume trace=1 dir
run job=$JobName yes
wait
messages
@exec "stat $tmp/Vol-0001"
@output $tmp/log4.out
@# info: List volumes after the first job
llist volume=Vol-0001
@# 
@# now do a restore
@#
@$out $tmp/log2.out  
restore where=$tmp/bacula-restores select all done
yes
wait
messages
purge volume=Vol-0001 yes
update volume=Vol-0002 volstatus=Used
run job=$JobName yes
wait
messages
run job=$JobName level=Full yes
wait
messages
run job=$JobName level=Full storage=File2 yes
wait
messages
@output $tmp/log3.out
@# info: List volumes at the end
@exec "stat $tmp/Vol-0001"
@exec "stat $tmp/Vol-0002"
llist volume
@$out $tmp/log1.out
setbandwidth limit=1000 client
run job=$JobName level=Full storage=File2 yes
@sleep 5
.status dir running
messages
update volumeprotect
setbandwidth limit=10000000 client
wait
messages
@output $tmp/vol1.out
llist volume
@$out $tmp/log5.out
run job=adm-update-protected yes
wait
messages
@output $tmp/vol5.out
llist volume=Vol-0014
@$out $tmp/vol6.out
run job=acljob yes
wait
messages
@output $tmp/vol6.out
llist volume=Vol-0010
llist volume=Vol-0011
@$out $tmp/vol7.out
run job=acljob level=full yes
@sleep 3
setbandwidth
1
5MB/s
yes
run job=acljob level=full yes
wait
messages
@$out $tmp/vol8.out
run job=$JobName level=Full storage=File2 pool=Default yes
wait
messages
@output $tmp/vol8.out
@# Check the small retention
llist volume=Default0016
llist volume=Default0017
@exec "stat $tmp/Default0016"
@exec "stat $tmp/Default0017"
@$out $tmp/vol9.out
run job=$JobName level=Full storage=File2 pool=Test1 yes
wait
messages
llist volume=Test10018
quit
END_OF_DATA

run_bacula

$bperl -e 'my @r = stat("$tmp/Vol-0001"); exit (($r[2] & 07777 & 0400) && $r[8] > $r[9] && $r[7] > 1000*1000*49);'
if [ $? -ne 1 ]; then
    print_debug "ERROR: problem with volume attribute"
    stat $tmp/Vol-0001
    estat=1
fi

$bperl -e 'check_protect("$tmp/log4.out", "Vol-0001", "Used", 1, 1)'
if [ $? != 0 ]; then
    estat=1
fi

$bperl -e 'check_protect("$tmp/log4.out", "Vol-0002", "Used", 1, 1, 365*24*60*60)'
if [ $? != 0 ]; then
    estat=1
fi

$bperl -e 'check_protect("$tmp/log4.out", "Vol-0004", "Used", 1, 1, 365*24*60*60)'
if [ $? != 0 ]; then
    estat=1
fi

$bperl -e 'check_protect("$tmp/log4.out", "Vol-0003", "Used", undef, 1)'
if [ $? != 0 ]; then
    estat=1
fi

$bperl -e 'check_protect("$tmp/log4.out", "Vol-0005", "Used", undef, 1)'
if [ $? != 0 ]; then
    estat=1
fi

$bperl -e 'check_protect("$tmp/log3.out", "Vol-0001", "Recycle")'
if [ $? != 0 ]; then
    estat=1
fi

$bperl -e 'check_protect("$tmp/log5.out", "Vol-0014", "Used", 1, 1, 365*24*60*60)'
if [ $? != 0 ]; then
    estat=1
fi

$bperl -e 'check_protect("$tmp/log1.out", "Vol-0014", "Used", 0, 1)'
if [ $? != 0 ]; then
    estat=1
fi
$bperl -e 'check_protect("$tmp/vol6.out", "Vol-0011", "Used", 1, 1, 365*24*60*60)'
if [ $? != 0 ]; then
    estat=1
fi
$bperl -e 'check_protect("$tmp/vol6.out", "Vol-0010", "Used", 1, 1, 365*24*60*60)'
if [ $? != 0 ]; then
    estat=1
fi
# We test the atime value in addition
$bperl -e 'check_protect("$tmp/vol8.out", "Default0016", "Used", 1, 1, 20)'
if [ $? != 0 ]; then
    estat=1
fi

# Here, the pool has 5s and the  device 10s, it should be 10s
$bperl -e 'check_protect("$tmp/vol9.out", "Test10018", "Used", 1, 1, 10)'
if [ $? != 0 ]; then
    estat=1
fi

cat <<END_OF_DATA >$tmp/bconcmds
@$out $tmp/vol9.out
time
@exec "stat $tmp/Test10018"
purge volume=Test10018 yes
truncate volume=Test10018 storage=File2 yes
@sleep 11
time
truncate volume=Test10018 storage=File2 yes
messages
quit
END_OF_DATA

run_bconsole

check_for_zombie_jobs storage=File1

stop_bacula

check_two_logs
check_restore_diff
end_test
