#!/bin/bash #================================================= # LXD HELPERS #================================================= ynh_lxc_stop () { local container_to_stop=$1 # (We also use timeout 30 in front of the command because sometime lxc # commands can hang forever despite the --timeout >_>...) timeout 30 lxc stop --timeout 15 $container_to_stop 2>/dev/null # If the command times out, then add the option --force if [ $? -eq 124 ]; then timeout 30 lxc stop --timeout 15 $container_to_stop --force 2>/dev/null fi } # Run a command inside an LXC container # # usage: ynh_lxc_run_inside --name=name --command=command # | arg: -n, --name= - name of the LXC # | arg: -c, --command= - command to execute # # Requires YunoHost version *.*.* or higher. ynh_lxc_run_inside () { # Declare an array to define the options of this helper. local legacy_args=nc local -A args_array=([n]=name= [c]=command=) local name local command # Manage arguments with getopts ynh_handle_getopts_args "$@" lxc exec $name -- /bin/bash -c "$command" } _ynh_lxc_start_and_wait () { restart_container() { ynh_lxc_stop $1 lxc start "$1" } # Try to start the container 3 times. local max_try=3 local i=0 while [ $i -lt $max_try ] do i=$(( i +1 )) local failstart=0 # Wait for container to start, we are using systemd to check this, # for the sake of brevity. for j in $(seq 1 10); do if lxc exec "$1" -- systemctl isolate multi-user.target >/dev/null 2>/dev/null; then break fi if [ "$j" == "10" ]; then log_debug 'Failed to start the container ... restarting ...' failstart=1 restart_container "$1" fi sleep 1s done # Wait for container to access the internet for j in $(seq 1 10); do if lxc exec "$1" -- curl -s http://wikipedia.org > /dev/null 2>/dev/null; then break fi if [ "$j" == "10" ]; then log_debug 'Failed to access the internet ... restarting' failstart=1 restart_container "$1" fi sleep 1s done # Has started and has access to the internet if [ $failstart -eq 0 ] then break fi # Fail if the container failed to start if [ $i -eq $max_try ] && [ $failstart -eq 1 ] then log_error "The container miserably failed to start or to connect to the internet" lxc info --show-log $1 return 1 fi done LXC_IP=$(lxc exec $1 -- hostname -I | cut -d' ' -f1 | grep -E -o "\<[0-9.]{8,}\>") } ynh_lxc_swapfiles_clean () { # Restart it if needed if [ "$(lxc info $LXC_NAME | grep Status | awk '{print tolower($2)}')" != "running" ]; then lxc start $LXC_NAME _ynh_lxc_start_and_wait $LXC_NAME fi lxc exec $LXC_NAME -- bash -c 'for swapfile in $(ls /swap_* 2>/dev/null); do swapoff $swapfile; done' lxc exec $LXC_NAME -- bash -c 'for swapfile in $(ls /swap_* 2>/dev/null); do rm -f $swapfile; done' } ynh_lxc_snapshot_exists () { local snapname=$1 lxc list --format json \ | jq -e --arg LXC_NAME $LXC_NAME --arg snapname $snapname \ '.[] | select(.name==$LXC_NAME) | .snapshots[] | select(.name==$snapname)' \ >/dev/null } ynh_lxc_snapshot_load () { local snapname=$1 log_debug "Loading snapshot $snapname ..." # Remove swap files before restoring the snapshot. ynh_lxc_swapfiles_clean ynh_lxc_stop $LXC_NAME lxc restore $LXC_NAME $snapname lxc start $LXC_NAME _ynh_lxc_start_and_wait $LXC_NAME } ynh_lxc_reset () { # If the container exists if lxc info $LXC_NAME >/dev/null 2>/dev/null; then # Remove swap files before deletting the continer ynh_lxc_swapfiles_clean fi ynh_lxc_stop $LXC_NAME if lxc info $LXC_NAME >/dev/null 2>/dev/null; then local current_storage=$(lxc list $LXC_NAME --format json --columns b | jq '.[].expanded_devices.root.pool') swapoff "$(lxc storage get $current_storage source)/containers/$LXC_NAME/rootfs/swap" 2>/dev/null fi lxc delete $LXC_NAME --force 2>/dev/null }