#!/bin/sh # # This script will try to upgrade an LXC Debian template # 1. Start the LXC container if available # 2. Run some script to upgrade the container # 3. Stop the container # This script can be call by a cronjob (eg. daily, weekly,…) # Vars {{{ readonly PROGNAME=$(basename "${0}") readonly PROGDIR=$(readlink -m $(dirname "${0}")) readonly ARGS="${*}" readonly NBARGS="${#}" [ -z "${DEBUG}" ] && DEBUG=1 ## Export DEBUG for sub-script export DEBUG readonly CT_ID_DEFAULT="199121" readonly SLEEP_DELAY_DEFAULT="5" ## Colors readonly PURPLE='\033[1;35m' readonly RED='\033[0;31m' readonly RESET='\033[0m' readonly COLOR_DEBUG="${PURPLE}" # }}} usage() { # {{{ cat <<- EOF usage: $PROGNAME [-d|-h|-i|-s] Start and upgrade an LXC container for Debian template EXAMPLES : - Upgrade default LXC container (${CT_ID_DEFAULT}) : ${PROGNAME} - Specify the container ID : ${PROGNAME} --id 666 OPTIONS : -d,--debug Enable debug messages. -h,--help Print this help message. -i,--id Choose a different LXC container ID (default ${CT_ID_DEFAULT}). -s,--sleep Set a different delay to test container between each different state (default: ${SLEEP_DELAY_DEFAULT}). EOF } # }}} debug_message() { # {{{ local_message="${1}" ## Print message if DEBUG is enable (=0) [ "${DEBUG}" -eq "0" ] && printf '\e[1;35m%-6b\e[m\n' "DEBUG − ${PROGNAME} : ${local_message}" return 0 } # }}} error_message() { # {{{ local_error_message="${1}" local_error_code="${2}" ## Print message if DEBUG is enable (=0) [ "${DEBUG}" -eq "0" ] && printf '%b\n' "ERROR − ${PROGNAME} : ${RED}${local_error_message}${RESET}" exit "${local_error_code:=66}" } # }}} define_vars() { # {{{ ## If ct_id wasn't defined (argument) {{{ if [ -z "${ct_id}" ]; then ## Use default value readonly ct_id="${CT_ID_DEFAULT}" fi ## }}} ## If sleep_delay wasn't defined (argument) {{{ if [ -z "${sleep_delay}" ]; then ## Use default value readonly sleep_delay="${SLEEP_DELAY_DEFAULT}" fi ## }}} } # }}} is_proxmox_absent() { # {{{ ## By default, Proxmox is absent on an host return_is_proxmox_absent="0" ## Check if the system runs on a PVE kernel if ! uname --kernel-release -- | grep --quiet -- "pve"; then return_is_proxmox_absent="0" debug_message "is_proxmox_absent − \ Proxmox is ${RED}absent${COLOR_DEBUG} on this host." else return_is_proxmox_absent="1" debug_message "is_proxmox_absent − \ Proxmox seems ${RED}present${COLOR_DEBUG} on this host." fi return "${return_is_proxmox_absent}" } # }}} is_lxc_container_absent() { # {{{ local_ct_id="${1}" ## By default, the LXC container is absent from the current host return_is_lxc_container_absent="0" ## Check if the system runs on a PVE kernel if ! /usr/sbin/pct list -- | grep --quiet "${local_ct_id}"; then return_is_lxc_container_absent="0" debug_message "is_lxc_container_absent − \ The LXC container (${RED}${local_ct_id}${COLOR_DEBUG}) is ${RED}absent${COLOR_DEBUG} from this host." else return_is_lxc_container_absent="1" debug_message "is_lxc_container_absent − \ The LXC container (${RED}${local_ct_id}${COLOR_DEBUG}) is ${RED}present${COLOR_DEBUG} on this host." fi return "${return_is_lxc_container_absent}" } # }}} is_lxc_container_state() { # {{{ local_ct_id="${1}" local_ct_state="${2}" ## Compare the status of the LXC container with argument if /usr/sbin/pct status "${local_ct_id}" -- | grep --quiet --word-regexp "${local_ct_state}"; then return_is_lxc_container_state="0" debug_message "is_lxc_container_state − \ The LXC container (${RED}${local_ct_id}${COLOR_DEBUG}) is in ${RED}${local_ct_state}${COLOR_DEBUG} state." else return_is_lxc_container_state="1" debug_message "is_lxc_container_state − \ The LXC container (${RED}${local_ct_id}${COLOR_DEBUG}) is not in ${RED}${local_ct_state}${COLOR_DEBUG} state." fi return "${return_is_lxc_container_state}" } # }}} start_lxc_container() { # {{{ local_ct_id="${1}" ## By default, the container is not running return_start_lxc_container="1" ## Start LXC container state /usr/sbin/pct start "${local_ct_id}" || exit 1 ## Wait a little for the container to start sleep "${sleep_delay}" ## Verify LXC container status if is_lxc_container_state "${local_ct_id}" "running"; then return_start_lxc_container="0" debug_message "start_lxc_container − \ LXC container ${RED}${local_ct_id}${COLOR_DEBUG} is now ${RED}running${COLOR_DEBUG}." else return_start_lxc_container="1" debug_message "start_lxc_container − \ LXC container ${RED}${local_ct_id}${COLOR_DEBUG} is still ${RED}stopped${COLOR_DEBUG}." fi return "${return_start_lxc_container}" } # }}} stop_lxc_container() { # {{{ local_ct_id="${1}" ## By default, the container is running return_stop_lxc_container="1" ## Stop LXC container state /usr/sbin/pct stop "${local_ct_id}" || exit 1 ## Wait a little for the container to stop sleep "${sleep_delay}" ## Verify LXC container status if is_lxc_container_state "${local_ct_id}" "stopped"; then return_stop_lxc_container="0" debug_message "stop_lxc_container − \ LXC container ${RED}${local_ct_id}${COLOR_DEBUG} is now ${RED}stopped${COLOR_DEBUG}." else return_stop_lxc_container="1" debug_message "stop_lxc_container − \ LXC container ${RED}${local_ct_id}${COLOR_DEBUG} is still ${RED}running${COLOR_DEBUG}." fi return "${return_stop_lxc_container}" } # }}} upgrade_container() { # {{{ local_ct_id="${1}" ## Keep output if DEBUG mode is activated if [ "${DEBUG}" -eq "0" ]; then /usr/sbin/pct exec "${local_ct_id:-/dev/null}" -- bash -c "wget https://git.ipr.univ-rennes1.fr/cellinfo/scripts/raw/master/proxmox/proxmox.template.debian.sh --output-document=/tmp/proxmox.template.debian.sh" || exit 2 /usr/sbin/pct exec "${local_ct_id:-/dev/null}" -- bash -c "chmod +x /tmp/proxmox.template.debian.sh" || exit 2 /usr/sbin/pct exec "${local_ct_id:-/dev/null}" -- bash -c "/tmp/proxmox.template.debian.sh" || exit 2 else /usr/sbin/pct exec "${local_ct_id:-/dev/null}" -- bash -c "wget --quiet https://git.ipr.univ-rennes1.fr/cellinfo/scripts/raw/master/proxmox/proxmox.template.debian.sh --output-document=/tmp/proxmox.template.debian.sh" || exit 2 /usr/sbin/pct exec "${local_ct_id:-/dev/null}" -- bash -c "chmod +x /tmp/proxmox.template.debian.sh" || exit 2 /usr/sbin/pct exec "${local_ct_id:-/dev/null}" -- bash -c "/tmp/proxmox.template.debian.sh" > /dev/null 2>&1 || exit 2 fi } # }}} main() { # {{{ ## If Proxmox is not yet available on this host {{{ ### Exit is_proxmox_absent \ && exit 0 ## }}} ## Define all vars define_vars ## If the LXC container ID is absent from this host {{{ ### Exit is_lxc_container_absent "${ct_id}" \ && exit 0 ## }}} ## If the LXC container ID is already running {{{ ### Exit with error message is_lxc_container_state "${ct_id}" "running" \ && error_message "LXC container (${ct_id}) is already running. \ Please power it off if you don't have any work in progress." "3" ## }}} ## If the LXC container ID is stopped {{{ ### Try to start the container is_lxc_container_state "${ct_id}" "stopped" \ && start_lxc_container "${ct_id}" ## }}} ## Try to upgrade the container {{{ ### And re-stop the container ### Then exit with success the script upgrade_container "${ct_id}" \ && stop_lxc_container "${ct_id}" \ && exit 0 ## }}} } # }}} # Manage arguments # {{{ # This code can't be in a function due to argument management if [ ! "${NBARGS}" -eq "0" ]; then manage_arg="0" ## If the first argument is not an option if ! printf -- '%s' "${1}" | grep -q -E -- "^-+"; then ## Print help message and exit printf '%b\n' "${RED}Invalid option: ${1}${RESET}" printf '%b\n' "---" usage exit 1 fi # Parse all options (start with a "-") one by one while printf -- '%s' "${1}" | grep -q -E -- "^-+"; do case "${1}" in -d|--debug ) ## debug DEBUG=0 ;; -h|--help ) ## help usage ## Exit after help informations exit 0 ;; -i|--id ) ## Use given CT ID ## Move to the next argument shift ## Define ct_id readonly ct_id="${1}" ;; -s|--sleep ) ## Use given sleeping delay ## Move to the next argument shift ## Define sleep_delay readonly sleep_delay="${1}" ;; * ) ## unknow option printf '%b\n' "${RED}Invalid option: ${1}${RESET}" printf '%b\n' "---" usage exit 1 ;; esac debug_message "Arguments management − \ ${RED}${1}${COLOR_DEBUG} option managed." ## Move to the next argument shift manage_arg=$((manage_arg+1)) done debug_message "Arguments management − \ ${RED}${manage_arg}${COLOR_DEBUG} argument(s) successfully managed." else debug_message "Arguments management − \ No arguments/options to manage." fi # }}} main exit 255