mirror of
https://github.com/YunoHost/package_check.git
synced 2024-09-03 20:06:20 +02:00
When snap1 doesn't exist, `lxc-snapshot` will create a snapshot named `snap1` (instead of `snap2`). In this case we need to rename snap1 into snap2. However the condition check is wrong: after creating the snapshot, `snap1` will *always* exist – even if it didn't before. Thus the renaming never happens. Fix the issue by detecting the absence of snap2 (rather than snap1).
308 lines
10 KiB
Bash
Executable file
308 lines
10 KiB
Bash
Executable file
# #!/bin/bash
|
|
|
|
echo -e "Loads functions from launcher.sh"
|
|
|
|
#=================================================
|
|
# Globals variables
|
|
#=================================================
|
|
|
|
arg_ssh="-tt"
|
|
snapshot_path="/var/lib/lxcsnaps/$lxc_name"
|
|
current_snapshot=snap0
|
|
|
|
#=================================================
|
|
# TIMER
|
|
#=================================================
|
|
|
|
start_timer () {
|
|
# Set the beginning of the timer
|
|
starttime=$(date +%s)
|
|
}
|
|
|
|
stop_timer () {
|
|
# Ending the timer
|
|
# $1 = Type of querying
|
|
|
|
local finishtime=$(date +%s)
|
|
# Calculate the gap between the starting and the ending of the timer
|
|
local elapsedtime=$(echo $(( $finishtime - $starttime )))
|
|
# Extract the number of hour
|
|
local hours=$(echo $(( $elapsedtime / 3600 )))
|
|
local elapsedtime=$(echo $(( $elapsedtime - ( 3600 * $hours) )))
|
|
# Minutes
|
|
local minutes=$(echo $(( $elapsedtime / 60 )))
|
|
# And seconds
|
|
local seconds=$(echo $(( $elapsedtime - ( 60 * $minutes) )))
|
|
|
|
local phours=""
|
|
local pminutes=""
|
|
local pseconds=""
|
|
|
|
# Avoid null values
|
|
[ $hours -eq 0 ] || phours="$hours hour"
|
|
[ $minutes -eq 0 ] || pminutes="$minutes minute"
|
|
[ $seconds -eq 0 ] || pseconds="$seconds second"
|
|
|
|
# Add a 's' for plural values
|
|
[ $hours -eq 1 ] && phours="${phours}, " || test -z "$phours" || phours="${phours}s, "
|
|
[ $minutes -eq 1 ] && pminutes="${pminutes}, " || test -z "$pminutes" || pminutes="${pminutes}s, "
|
|
[ $seconds -gt 1 ] && pseconds="${pseconds}s"
|
|
|
|
if [ $1 -eq 2 ]; then
|
|
ECHO_FORMAT "Working time for this test: " "blue"
|
|
elif [ $1 -eq 3 ]; then
|
|
ECHO_FORMAT "Global working time for all tests: " "blue"
|
|
else
|
|
ECHO_FORMAT "Working time: " "blue"
|
|
fi
|
|
ECHO_FORMAT "${phours}${pminutes}${pseconds}.\n" "blue"
|
|
}
|
|
|
|
#=================================================
|
|
# RUNNING SNAPSHOT
|
|
#=================================================
|
|
|
|
create_temp_backup () {
|
|
# Create a temporary snapshot
|
|
|
|
# snap1 for subpath or snap2 for root install
|
|
snap_number=$1
|
|
|
|
start_timer
|
|
# Check all the witness files, to verify if them still here
|
|
check_witness_files >&2
|
|
|
|
# Stop the container, before its snapshot
|
|
sudo lxc-stop --name $lxc_name >&2
|
|
|
|
# Check if the snapshot already exist
|
|
if [ ! -e "$snapshot_path/snap$snap_number" ]
|
|
then
|
|
echo "snap$snap_number doesn't exist, its first creation can be take a little while." >&2
|
|
# Create the snapshot.
|
|
sudo lxc-snapshot --name $lxc_name >> "$test_result" 2>&1
|
|
|
|
# lxc always creates the first snapshot it can creates.
|
|
# So if snap1 doesn't exist and you try to create snap2, it will be named snap1.
|
|
if [ "$snap_number" == "2" ] && [ ! -e "$snapshot_path/snap2" ]
|
|
then
|
|
# Rename snap1 to snap2
|
|
sudo mv "$snapshot_path/snap1" "$snapshot_path/snap2"
|
|
fi
|
|
fi
|
|
|
|
# Update the snapshot with rsync to clone the current lxc state
|
|
sudo rsync --acls --archive --delete --executability --itemize-changes --xattrs "/var/lib/lxc/$lxc_name/rootfs/" "$snapshot_path/snap$snap_number/rootfs/" > /dev/null 2>> "$test_result"
|
|
|
|
# Set this snapshot as the current snapshot
|
|
current_snapshot=snap$snap_number
|
|
|
|
stop_timer 1 >&2
|
|
|
|
# Restart the container, after the snapshot
|
|
LXC_START "true" >&2
|
|
}
|
|
|
|
use_temp_snapshot () {
|
|
# Use a temporary snapshot, if it already exists
|
|
# $1 = Name of the snapshot to use
|
|
current_snapshot=$1
|
|
|
|
start_timer
|
|
# Fix the missing hostname in the hosts file...
|
|
echo "127.0.0.1 $lxc_name" | sudo tee --append "$snapshot_path/$current_snapshot/rootfs/etc/hosts" > /dev/null
|
|
|
|
# Restore this snapshot.
|
|
sudo rsync --acls --archive --delete --executability --itemize-changes --xattrs "$snapshot_path/$current_snapshot/rootfs/" "/var/lib/lxc/$lxc_name/rootfs/" > /dev/null 2>> "$test_result"
|
|
|
|
stop_timer 1
|
|
|
|
# Retrieve the app id in the log. To manage the app after
|
|
ynh_app_id=$(sudo tac "$yunohost_log" | grep --only-matching --max-count=1 "YNH_APP_INSTANCE_NAME=[^ ]*" | cut --delimiter='=' --fields=2)
|
|
|
|
# Fake the yunohost_result return code of the installation
|
|
yunohost_result=0
|
|
}
|
|
|
|
#=================================================
|
|
|
|
is_lxc_running () {
|
|
sudo lxc-info --name=$lxc_name | grep --quiet "RUNNING"
|
|
}
|
|
|
|
LXC_INIT () {
|
|
# Initialize LXC network
|
|
|
|
# Activate the bridge
|
|
echo "Initialize network for LXC."
|
|
sudo ifup $lxc_bridge --interfaces=/etc/network/interfaces.d/$lxc_bridge | tee --append "$test_result" 2>&1
|
|
|
|
# Activate iptables rules
|
|
echo "Activate iptables rules."
|
|
sudo iptables --append FORWARD --in-interface $lxc_bridge --out-interface $main_iface --jump ACCEPT | tee --append "$test_result" 2>&1
|
|
sudo iptables --append FORWARD --in-interface $main_iface --out-interface $lxc_bridge --jump ACCEPT | tee --append "$test_result" 2>&1
|
|
sudo iptables --table nat --append POSTROUTING --source $ip_range.0/24 --jump MASQUERADE | tee --append "$test_result" 2>&1
|
|
}
|
|
|
|
LXC_START () {
|
|
# Start the lxc container and execute the given command in it
|
|
# $1 = Command to execute in the container
|
|
|
|
start_timer
|
|
# Try to start the container 3 times.
|
|
local max_try=3
|
|
local i=0
|
|
for i in `seq 1 $max_try`
|
|
do
|
|
# Start the container and log the booting process in $script_dir/lxc_boot.log
|
|
# Try to start only if the container is not already started
|
|
if ! is_lxc_running; then
|
|
echo -n "Start the LXC container" | tee --append "$test_result"
|
|
sudo lxc-start --name=$lxc_name --daemon --logfile "$script_dir/lxc_boot.log" | tee --append "$test_result" 2>&1
|
|
local avoid_witness=0
|
|
else
|
|
echo -n "A LXC container is already running" | tee --append "$test_result"
|
|
local avoid_witness=1
|
|
fi
|
|
|
|
# Check during 20 seconds if the container has finished to start.
|
|
local j=0
|
|
for j in `seq 1 20`
|
|
do
|
|
echo -n .
|
|
# Try to connect with ssh to check if the container is ready to work.
|
|
if ssh $arg_ssh $lxc_name "exit 0" > /dev/null 2>&1; then
|
|
# Break the for loop if the container is ready.
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
echo ""
|
|
|
|
local failstart=0
|
|
# Check if the container is running
|
|
if ! is_lxc_running; then
|
|
ECHO_FORMAT "The LXC container didn't start...\n" "red" "bold"
|
|
failstart=1
|
|
if [ $i -ne $max_try ]; then
|
|
ECHO_FORMAT "Rebooting the container...\n" "red" "bold"
|
|
fi
|
|
LXC_STOP # Stop the LXC container
|
|
elif ! ssh $arg_ssh $lxc_name "sudo ping -q -c 2 security.debian.org > /dev/null 2>&1; exit \$?" >> "$test_result" 2>&1
|
|
then
|
|
# Try to ping security.debian.org to check the connectivity from the container
|
|
ECHO_FORMAT "The container failed to connect to internet...\n" "red" "bold"
|
|
failstart=1
|
|
if [ $i -ne $max_try ]; then
|
|
ECHO_FORMAT "Rebooting the container...\n" "red" "bold"
|
|
fi
|
|
LXC_STOP # Stop the LXC container
|
|
else
|
|
# Create files to check if the remove script does not remove them accidentally
|
|
[ $avoid_witness -eq 0 ] && set_witness_files
|
|
|
|
# Break the for loop if the container is ready.
|
|
break
|
|
fi
|
|
|
|
# Fail if the container failed to start
|
|
if [ $i -eq $max_try ] && [ $failstart -eq 1 ]
|
|
then
|
|
ECHO_FORMAT "The container failed to start $max_try times...\nIf this problem is persistent, try to fix it with lxc_check.sh.\n" "red" "bold"
|
|
ECHO_FORMAT "Boot log:\n" clog
|
|
cat "$script_dir/lxc_boot.log" | tee --append "$test_result"
|
|
stop_timer 1
|
|
return 1
|
|
fi
|
|
done
|
|
|
|
# Count the number of lines of the current yunohost log file.
|
|
COPY_LOG 1
|
|
|
|
# Copy the package into the container.
|
|
scp -rq "$package_path" "$lxc_name": >> "$test_result" 2>&1
|
|
|
|
# Execute the command given in argument in the container and log its results.
|
|
ssh $arg_ssh $lxc_name "$1 > /dev/null 2>> temp_yunohost-cli.log; exit \$?" >> "$test_result" 2>&1
|
|
# Store the return code of the command
|
|
local returncode=$?
|
|
|
|
# Retrieve the log of the previous command and copy its content in the temporary log
|
|
sudo cat "/var/lib/lxc/$lxc_name/rootfs/home/pchecker/temp_yunohost-cli.log" >> "$temp_log"
|
|
|
|
stop_timer 1
|
|
# Return the exit code of the ssh command
|
|
return $returncode
|
|
}
|
|
|
|
LXC_STOP () {
|
|
# Stop and restore the LXC container
|
|
|
|
start_timer
|
|
# Stop the LXC container
|
|
if is_lxc_running; then
|
|
echo "Stop the LXC container" | tee --append "$test_result"
|
|
sudo lxc-stop --name=$lxc_name | tee --append "$test_result" 2>&1
|
|
fi
|
|
|
|
# Fix the missing hostname in the hosts file
|
|
# If the hostname is missing in /etc/hosts inside the snapshot
|
|
if ! sudo grep --quiet "$lxc_name" "$snapshot_path/$current_snapshot/rootfs/etc/hosts"
|
|
then
|
|
# If the hostname was replaced by name of the snapshot, fix it
|
|
if sudo grep --quiet "$current_snapshot" "$snapshot_path/$current_snapshot/rootfs/etc/hosts"
|
|
then
|
|
# Replace snapX by the real hostname
|
|
sudo sed --in-place "s/$current_snapshot/$lxc_name/" "$snapshot_path/$current_snapshot/rootfs/etc/hosts"
|
|
else
|
|
# Otherwise, simply add the hostname
|
|
echo "127.0.0.1 $lxc_name" | sudo tee --append "$snapshot_path/$current_snapshot/rootfs/etc/hosts" > /dev/null
|
|
fi
|
|
fi
|
|
|
|
# Restore the snapshot.
|
|
echo "Restore the previous snapshot." | tee --append "$test_result"
|
|
sudo rsync --acls --archive --delete --executability --itemize-changes --xattrs "$snapshot_path/$current_snapshot/rootfs/" "/var/lib/lxc/$lxc_name/rootfs/" > /dev/null 2>> "$test_result"
|
|
stop_timer 1
|
|
}
|
|
|
|
LXC_TURNOFF () {
|
|
# Disable LXC network
|
|
|
|
echo "Disable iptables rules."
|
|
if sudo iptables --check FORWARD --in-interface $lxc_bridge --out-interface $main_iface --jump ACCEPT 2> /dev/null
|
|
then
|
|
sudo iptables --delete FORWARD --in-interface $lxc_bridge --out-interface $main_iface --jump ACCEPT >> "$test_result" 2>&1
|
|
fi
|
|
if sudo iptables --check FORWARD --in-interface $main_iface --out-interface $lxc_bridge --jump ACCEPT 2> /dev/null
|
|
then
|
|
sudo iptables --delete FORWARD --in-interface $main_iface --out-interface $lxc_bridge --jump ACCEPT | tee --append "$test_result" 2>&1
|
|
fi
|
|
if sudo iptables --table nat --check POSTROUTING --source $ip_range.0/24 --jump MASQUERADE 2> /dev/null
|
|
then
|
|
sudo iptables --table nat --delete POSTROUTING --source $ip_range.0/24 --jump MASQUERADE | tee --append "$test_result" 2>&1
|
|
fi
|
|
|
|
echo "Disable the network bridge."
|
|
if sudo ifquery $lxc_bridge --state > /dev/null
|
|
then
|
|
sudo ifdown --force $lxc_bridge | tee --append "$test_result" 2>&1
|
|
fi
|
|
|
|
# Set snap0 as the current snapshot
|
|
current_snapshot=snap0
|
|
}
|
|
|
|
LXC_CONNECT_INFO () {
|
|
# Print access information
|
|
|
|
echo "> To access the container:"
|
|
echo "To execute one command:"
|
|
echo -e "\e[1msudo lxc-attach -n $lxc_name -- command\e[0m"
|
|
|
|
echo "To establish a ssh connection:"
|
|
if [ $(cat "$script_dir/sub_scripts/setup_user") = "root" ]; then
|
|
echo -ne "\e[1msudo "
|
|
fi
|
|
echo -e "\e[1mssh $arg_ssh $lxc_name\e[0m"
|
|
}
|