#!/usr/bin/env bash # gnuhealth-control # The GNU Health control center ############################################################################## # # GNU Health: The Free Health and Hospital Information System # Copyright (C) 2008-2022 Luis Falcon # Copyright (C) 2011-2022 GNU Solidario # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # ############################################################################## VERSION="4.0.2" TRYTON_URL="https://downloads-cdn.tryton.org" GNUHEALTH_URL="https://ftp.gnu.org/gnu/health" TRANSLATE_URL="https://hosted.weblate.org" TRYTON_MODULES="account account_invoice account_product company country \ currency party product stock stock_lot purchase account_invoice_stock \ stock_supply purchase_request" UPDATE_DOWNLOAD_DIR="$HOME/.gnuhealth_update" BACKUP_TEMP_DIR="$HOME/.backup_temp" PATCH_TRYTON=0 TRYTON_PATCHES="" BSDTAR="bsdtar" usage() { cat << EOF This is GNU Health control center ${VERSION} usage: `basename $0` command [options] Command: version : Show version update : Download and install the patches backup_attachments : Backup the attachments folder backup_database : Backup the database backup_environment : Backup the environment including config files, versions of GNU Health, Tryton and OS & pip freeze instpydeps : Install or update the latest dependencies getlang : Get and install / update the language pack code status : Show environment and GNU Health Tryton server status Options: --backdir : destination directory for the backup files --dry-run : Check, download and preview, but don't actually update process --database : database name to use with the backup_database command --datadir : directory containing attachments to backup EOF exit 0 } help() { cat << EOF The GNU Health Control Center (gnuhealth-control) is the main tool for administrative tasks of the GNU Health environment. It can perform backups and updates of the instance Updates ------- When gnuhealth-control is invoked with the update command, it will update GNU Health components within the same major number The following components will be checked and updated if necessary - Trytond : Tryton server version - GNU Health patchsets This will be valid for version with the same major and minor numbers, for example 2.8.x will look for the latest tryton updates and GNU Health updates associated to that release. GNU Health Control is available for release 2.8 and newer. You can get the latest version of GNU Health update at GNU ftp://ftp.gnu.org/gnu/health EOF usage exit 0 } message() { local UTC="$(date -u +'%Y-%m-%d %H:%M:%S')" case $1 in ERROR ) echo -e "\e[00;31m${UTC} [ERROR] $2\e[00m";; WARNING ) echo -e "\e[0;33m${UTC} [WARNING] $2\e[m" ;; INFO ) echo -e "\e[0;36m${UTC} [INFO] $2\e[m" ;; esac } get_current_values() { # Bail out if no GNU Health profile exists if [ -f $HOME/.gnuhealthrc ]; then GNUHEALTHRC_PATH=$HOME/.gnuhealthrc message "INFO" "Found gnuhealthrc at $GNUHEALTHRC_PATH" elif [ -f /etc/tryton/gnuhealthrc ]; then GNUHEALTHRC_PATH=/etc/tryton/gnuhealthrc message "INFO" "Found gnuhealthrc at $GNUHEALTHRC_PATH" else message "ERROR" "Could not find gnuhealthrc in $HOME/.gnuhealthrc or /etc/tryton/gnuhealthrc" bailout fi source $GNUHEALTHRC_PATH # Stop if it can not find the GNU Health version if [ -z "$GNUHEALTH_VERSION" ] then message "ERROR" "Could not find the GNU Health version env. variable" bailout fi # Stop if current GNU Health version < 3.0.0 local raw_ver=`echo $GNUHEALTH_VERSION | tr -d '.'` if [ $raw_ver -lt 300 ] then message "ERROR" "GNU Health version must be at least 3.0" bailout fi message "INFO" "Environment variables" message "INFO" "GNUHEALTH_VERSION = ${GNUHEALTH_VERSION}" message "INFO" "TRYTON VERSION = ${TRYTON_VERSION}" } do_backup_attachments() { local BACKDATE=`date -u +%Y-%m-%d_%H%M%S` local LOCKFILE="$HOME/.gnuhealth_backup_attachments.lock" local INFOFILE="$HOME/gnuhealth_backup_attachments.log" local BACKDIR="" local DATADIR="" shift # Remove the command and deal only with the options if [ $# -ne 4 ]; then echo -e "Usage : gnuhealth-control backup --backdir --datadir " exit fi for option in "$@" do case $option in --backdir ) BACKDIR=$2;; --datadir ) DATADIR=$2 ;; esac shift done if [ -f $LOCKFILE ]; then message "ERROR" "Backup in progress or stale lock file found ..." | tee -a $INFOFILE bailout fi if [ ! -e ${BACKDIR} ]; then message "INFO" "Backup directory does not exist yet; creating it." | tee -a $INFOFILE mkdir -p $BACKDIR || bailout fi echo $$ > $LOCKFILE # Backup start message "INFO" "Compressing GNU Health attachments directory" | tee -a $INFOFILE cd $DATADIR tar -cvzf $BACKDIR/gnuhealth_attachments_$BACKDATE.tar.gz * || bailout message "INFO" "Backup of Attachments Successful" | tee -a $INFOFILE #Remove lock file rm $LOCKFILE } do_backup_database() { local BACKDATE=`date -u +%Y-%m-%d_%H%M%S` local LOCKFILE="$HOME/.gnuhealth_backup_database.lock" local INFOFILE="$HOME/gnuhealth_backup_database.log" local BACKDIR="" local DB="" shift if [ $# -ne 4 ]; then echo -e "Usage : gnuhealth-control backup_database --backdir --database " exit fi for option in "$@" do case $option in --backdir ) BACKDIR=$2;; --database ) DB=$2 ;; esac shift done if [ -f $LOCKFILE ] then message "ERROR" "Backup in progress or stale lock file found ..." | tee -a $INFOFILE bailout fi if [ ! -e ${BACKDIR} ]; then message "INFO" "Backup directory does not exist yet; creating it." | tee -a $INFOFILE mkdir -p $BACKDIR || bailout fi echo $$ > $LOCKFILE # Backup start message "INFO" "START Database Backup" | tee -a $INFOFILE pg_dump -Fc $DB > $BACKDIR/backup\_$DB\_$BACKDATE.dump || bailout message "INFO" "Backup of Database Successful" | tee -a $INFOFILE #Remove lock file rm $LOCKFILE } do_backup_environment() { get_current_values local BACKDATE=`date -u +%Y-%m-%d_%H%M%S` local LOCKFILE="$HOME/.gnuhealth_backup_environment.lock" local INFOFILE="$HOME/gnuhealth_backup_environment.log" local BACKDIR="" local DB="" shift if [ $# -ne 4 ]; then echo -e "Usage : gnuhealth-control backup_environment --backdir --database " exit fi for option in "$@" do case $option in --backdir ) BACKDIR=$2;; --database ) DB=$2 ;; esac shift done if [ -f $LOCKFILE ] then message "ERROR" "Backup in progress or stale lock file found ..." | tee -a $INFOFILE bailout fi if [ ! -e ${BACKDIR} ]; then message "INFO" "Backup directory does not exist yet; creating it." | tee -a $INFOFILE mkdir -p $BACKDIR || bailout fi if [ -d $BACKUP_TEMP_DIR ]; then message "ERROR" "Update download directory exists. Bailing out" bailout fi mkdir -p $BACKUP_TEMP_DIR cd $BACKUP_TEMP_DIR # Get trytond-console commands' path if command -v trytond-console; then TRYTOND_CONSOLE_PATH=`command -v trytond-console` message "INFO" "Found trytond-console at $TRYTOND_CONSOLE_PATH" elif [ -f $HOME/gnuhealth/tryton/server/trytond-$TRYTON_VERSION/bin/trytond-console ]; then TRYTOND_CONSOLE_PATH=$HOME/gnuhealth/tryton/server/trytond-$TRYTON_VERSION/bin/trytond-console message "INFO" "Found trytond-console at $TRYTOND_CONSOLE_PATH" else message "ERROR" "Could not find trytond-console as system command or in ${$HOME/gnuhealth/tryton/server/trytond-$TRYTON_VERSION/bin/}" exit # bailout fi # Look for path of trytond config if [ "$TRYTOND_CONFIG" != "" ] && [ -f $TRYTOND_CONFIG ] ; then message "INFO" "Found trytond config at $TRYTOND_CONFIG" elif [ -f /etc/tryton/trytond.conf ]; then TRYTOND_CONFIG=/etc/tryton/trytond.conf message "INFO" "Found trytond config at $TRYTOND_CONFIG" else message "ERROR" "Could not find trytond.conf as environment variable TRYTOND_CONFIG or at /etc/tryton/trytond.conf" exit # bailout fi echo $$ > $LOCKFILE # Backup start message "INFO" "START Environment Backup" | tee -a $INFOFILE $TRYTOND_CONSOLE_PATH -d $DB -c $TRYTOND_CONFIG > trytond_modules.txt << EOF Module = pool.get('ir.module') modules = Module.search([('state', '=', 'activated')]) for module in modules: print(module.name) EOF pip3 freeze > pip_environment.txt cat /etc/os-release > os_version.txt echo $GNUHEALTH_VERSION > gnuhealth_version.txt echo $TRYTON_VERSION > trytond_version.txt cp $GNUHEALTHRC_PATH gnuhealthrc cp $TRYTOND_CONFIG . cp `dirname $TRYTOND_CONFIG`/gnuhealth_log.conf . || cp `dirname $TRYTOND_CONFIG`/trytond_log.conf . || message "WARNING" "Did not find log config" SYSTEMD_GNUHEALTH=`systemctl show -p FragmentPath gnuhealth` cp ${SYSTEMD_GNUHEALTH:13} . echo $TRYTOND_CONFIG > config_path.txt echo $GNUHEALTHRC_PATH > gnuhealthrc_path.txt echo ${SYSTEMD_GNUHEALTH:13} > systemd_path.txt tar -cvzf $BACKDIR/gnuhealth_environment_$BACKDATE.tar.gz . cd .. rm -rf $BACKUP_TEMP_DIR message "INFO" "Backup of Environment Successful" | tee -a $INFOFILE #Remove lock file rm $LOCKFILE } check_status() { TRYTOND_PIDS=`pgrep -f "^.*python.*trytond.*$"` if [ $? = 0 ] then message "INFO" "GNU Health / Tryton instance(s) with PID(s) :" echo $TRYTOND_PIDS else message "INFO" "No GNU Health instance seems to be running" fi } check_download_dir() { if [ -d $UPDATE_DOWNLOAD_DIR ]; then message "ERROR" "Update download directory exists. Bailing out" bailout fi } check_updates() { source $HOME/.gnuhealthrc UTIL_DIR="${GNUHEALTH_DIR}/tryton/server/util" local TRYTOND_PATCHLEVEL=`echo ${TRYTON_VERSION} | cut -d'.' -f3` TRYTON_MAJOR_MINOR=`echo $TRYTON_VERSION | cut -d'.' -f1-2` GNUHEALTH_MAJOR_MINOR=`echo $GNUHEALTH_VERSION | cut -d'.' -f1-2` GNUHEALTH_PATCHSET=`echo $GNUHEALTH_VERSION | cut -d'.' -f3` GCONTROL_PATCHSET=`echo $VERSION | cut -d'.' -f3` NEED_UPDATE_GCONTROL=0 NEED_UPDATE_TRYTOND=0 NEED_UPDATE_MODULES=0 NEED_UPDATE_PATCHSETS=0 NEED_PATCH_TRYTON=0 MOD_UPDATES="" NEED_DELETE=0 TO_DELETE="" message "INFO" "GNUHEALTH-CONTROL VERSION : ${VERSION}" # Retrieve the latest control center that is compatible with the current GNU Health version LATEST_GHCONTROL=`wget --quiet -O - ${GNUHEALTH_URL} | egrep -o gnuhealth-control-${GNUHEALTH_MAJOR_MINOR}.[0-9\.]+.tar.gz | sort -V | tail -1` local LATEST_GHCONTROL_PATCHSET=`echo ${LATEST_GHCONTROL} | cut -d'.' -f3` local GHCONTROL_PATCHSET=`echo $VERSION | cut -d'.' -f3` if (test ${LATEST_GHCONTROL}); then if (( ${GHCONTROL_PATCHSET} < ${LATEST_GHCONTROL_PATCHSET} )); then message "WARNING" "Current version ${VERSION} is outdated. A new version (${LATEST_GHCONTROL}) is available" NEED_UPDATE_GCONTROL=1 else message "INFO" "GNU Health control center is at the latest version ${VERSION}" fi else message "ERROR" "Error on getting the latest GNU Health Control Verion. Maybe a development release" fi message "INFO" "TRYTON SERVER : Checking latest patchlevel" LATEST_TRYTOND=`wget --quiet -O - ${TRYTON_URL}/${TRYTON_MAJOR_MINOR} | egrep -o trytond-${TRYTON_MAJOR_MINOR}.[0-9\.]+.tar.gz | sort -V | tail -1` local LATEST_TRYTOND_PATCHLEVEL=`echo ${LATEST_TRYTOND} | cut -d'.' -f3` # Check latest tryton server against local version if (( ${TRYTOND_PATCHLEVEL} < ${LATEST_TRYTOND_PATCHLEVEL} )); then message "WARNING" "TRYTON SERVER patchlevel ${TRYTOND_PATCHLEVEL} is outdated ! A newer version is available (${LATEST_TRYTOND})" NEED_DELETE=1 TO_DELETE="${TO_DELETE} ${GNUHEALTH_DIR}/tryton/server/trytond-${TRYTON_MAJOR_MINOR}.${TRYTOND_PATCHLEVEL}" NEED_UPDATE_TRYTOND=1 else message "INFO" "TRYTON SERVER patchlevel ${TRYTOND_PATCHLEVEL} is at the latest version" fi # Check latest tryton modules against local version cd ${GNUHEALTH_DIR}/tryton/server/modules for MODULE in ${TRYTON_MODULES}; do MOD=`ls -1d trytond_${MODULE}-*` message "INFO" "Checking MODULE ${MOD}" MODNAME=`echo $MOD | cut -d'-' -f1` MODULE_PATCHLEVEL=`echo $MOD | sed 's/^.*\.\([[:digit:]]*\)$/\1/'` LATEST_MODULE=`wget --quiet -O - ${TRYTON_URL}/${TRYTON_MAJOR_MINOR} | egrep -o ${MODNAME}-${TRYTON_MAJOR_MINOR}.[0-9\.]+.tar.gz | sort -V | tail -1` LATEST_MODULE_PATCHLEVEL=`echo ${LATEST_MODULE} | cut -d'.' -f3` if (( ${MODULE_PATCHLEVEL} < ${LATEST_MODULE_PATCHLEVEL} )); then message "WARNING" "${MODNAME} patchlevel ${MODULE_PATCHLEVEL} is outdated ! A newer version is available (${LATEST_MODULE})" NEED_UPDATE_MODULES=1 MOD_UPDATES="${MOD_UPDATES} ${LATEST_MODULE}" NEED_DELETE=1 TO_DELETE="${TO_DELETE} ${GNUHEALTH_DIR}/tryton/server/modules/${MODNAME}-${TRYTON_MAJOR_MINOR}.${MODULE_PATCHLEVEL}" else message "INFO" "${MODNAME} patchlevel ${MODULE_PATCHLEVEL} is at the latest version" fi done # Check latest GNU HEALTH PATCHSETS against local version message "INFO" "GNU HEALTH KERNEL : Checking latest PATCHSETS" PATCHSETS_NUM=`wget --quiet -O - ${GNUHEALTH_URL}/ | egrep -o gnuhealth_patchset-${GNUHEALTH_MAJOR_MINOR}\.[0-9\.]+.tar.gz | uniq | wc -l | tr -d ' '` if (( ${PATCHSETS_NUM} > 0 )); then message "INFO" "Number of Patchsets for this version : ${PATCHSETS_NUM}" LATEST_GNUHEALTH=`wget --quiet -O - ${GNUHEALTH_URL}/ | egrep -o gnuhealth_patchset-${GNUHEALTH_MAJOR_MINOR}\.[0-9\.]+.tar.gz | sort -V | tail -1` LATEST_GNUHEALTH_PATCHSET=`echo ${LATEST_GNUHEALTH} | cut -d'.' -f3` if (( ${GNUHEALTH_PATCHSET} < ${LATEST_GNUHEALTH_PATCHSET} )); then message "WARNING" "GNU HEALTH patchset ${GNUHEALTH_PATCHSET} is outdated ! A newer version is available (${LATEST_GNUHEALTH})" NEED_UPDATE_PATCHSETS=1 let PSET=GNUHEALTH_PATCHSET+1 for n in `seq $PSET $LATEST_GNUHEALTH_PATCHSET` do PATCHSETS="$PATCHSETS gnuhealth_patchset-${GNUHEALTH_MAJOR_MINOR}.$n.tar.gz" done else message "INFO" "GNU HEALTH patchset ${GNUHEALTH_PATCHSET} is at the latest version" fi else message "INFO" "** NO GNU HEALTH PATCHSETS FOUND FOR THIS VERSION **" fi # CHECK SECURITY ADVISORIES AND OTHER PATCHES NOT PRESENT IN THE STANDARD TRYTON KERNEL if (( ${PATCH_TRYTON} == 1 )); then message "INFO" "Checking Security Advisories and other patches not present in the standard tryton kernel" for n in ${TRYTON_PATCHES} do message "INFO" "Downloading patch for Tryton server : ${n}" wget --quiet --directory-prefix=${UPDATE_DOWNLOAD_DIR}/ ${GNUHEALTH_URL}/security/${n} || message "ERROR" "Could not get patch" message "INFO" "Checking elegibility of the patch" cd ${GNUHEALTH_DIR}/tryton/server/trytond-${TRYTON_VERSION}* patch --dry-run --silent -N -p1 < ${UPDATE_DOWNLOAD_DIR}/${n} if [ $? -eq 0 ]; then message "WARNING" "Patch ${n} needs to be applied" NEED_PATCH_TRYTON=1 else message "INFO" "Patch ${n} already applied or not elegible" fi done else message "WARNING" "PATCHING STANDARD TRYTON IS DISABLED. NO EXTRA SECURITY PATCHES OR FUNCTIONALITY WILL BE APPLIED" fi } install_updates() { if [ $NEED_UPDATE_GCONTROL -eq 1 ]; then message "INFO" "Downloading ${LATEST_GHCONTROL} ..." wget --quiet --directory-prefix=${UPDATE_DOWNLOAD_DIR}/ ${GNUHEALTH_URL}/${LATEST_GHCONTROL} || bailout message "INFO" "Uncompressing ${LATEST_GHCONTROL} ..." tar -xzf ${UPDATE_DOWNLOAD_DIR}/${LATEST_GHCONTROL} --directory ${UTIL_DIR}|| bailout message "INFO" "Sucessfully installed ${LATEST_GHCONTROL} " message "INFO" "Removing temporary download directory " rm -rf ${UPDATE_DOWNLOAD_DIR} || bailout message "INFO" "Please restart now the update with the new control center" exit 0 fi if [ $NEED_UPDATE_TRYTOND -eq 1 ]; then message "INFO" "Downloading TRYTON SERVER $LATEST_TRYTOND" wget --quiet --directory-prefix=${UPDATE_DOWNLOAD_DIR}/trytond ${TRYTON_URL}/${TRYTON_MAJOR_MINOR}/${LATEST_TRYTOND} || bailout message "INFO" "--> Uncompressing TRYTON SERVER $LATEST_TRYTOND" tar -xzf ${UPDATE_DOWNLOAD_DIR}/trytond/${LATEST_TRYTOND} --directory ${GNUHEALTH_DIR}/tryton/server || bailout fi if [ $NEED_UPDATE_MODULES -eq 1 ]; then for mod in ${MOD_UPDATES} do message "INFO" "Downloading $mod" wget --quiet --directory-prefix=${UPDATE_DOWNLOAD_DIR}/modules ${TRYTON_URL}/${TRYTON_MAJOR_MINOR}/${mod} || bailout message "INFO" "--> Uncompressing ${mod}" tar -xzf ${UPDATE_DOWNLOAD_DIR}/modules/${mod} --directory ${GNUHEALTH_DIR}/tryton/server/modules || bailout done fi if [ $NEED_UPDATE_PATCHSETS -eq 1 ]; then for patchset in ${PATCHSETS} do message "INFO" "Downloading $patchset" wget --quiet --directory-prefix=${UPDATE_DOWNLOAD_DIR}/patchsets ${GNUHEALTH_URL}/${patchset} || bailout message "INFO" "--> Applying PATCHSET $patchset" tar -xzf ${UPDATE_DOWNLOAD_DIR}/patchsets/${patchset} --directory ${HOME} || bailout done fi # APPLY SECURITY ADVISORIES AND OTHER PATCHES NOT PRESENT IN THE STANDARD TRYTON KERNEL if (( ${PATCH_TRYTON} == 1 )); then if (( ${NEED_PATCH_TRYTON} == 1 )); then message "INFO" "APPLY SECURITY ADVISORIES AND OTHER PATCHES NOT PRESENT IN THE STANDARD TRYTON KERNEL" for n in ${TRYTON_PATCHES} do message "INFO" "Checking elegibility of the patch" cd ${GNUHEALTH_DIR}/tryton/server/trytond-${TRYTON_VERSION} patch --dry-run --silent -N -p1 < ${UPDATE_DOWNLOAD_DIR}/${n} if [ $? -eq 0 ]; then message "WARNING" "Applying patch ${n} to Tryton kernel" patch -p1 < ${UPDATE_DOWNLOAD_DIR}/${n} || bailout message "INFO" "Tryton kernel sucessfully patched" else message "INFO" "Patch ${n} already applied or not elegible" fi done fi else message "WARNING" "PATCHING STANDARD TRYTON IS DISABLED. NO EXTRA SECURITY PATCHES OR FUNCTIONALITY WILL BE APPLIED" fi } remove_old() { if [ ${NEED_DELETE} -eq 1 ]; then message "WARNING" "Removing obsolete kernel and/or modules : ${TO_DELETE}" rm -rf ${TO_DELETE} fi } relink_mods() { source $HOME/.gnuhealthrc if [ ${NEED_DELETE} -eq 1 ]; then for mod in ${TRYTON_MODULES}; do local modname=`ls -1d trytond_${mod}-*` message "INFO" "Relinking : ${mod}" ln -sf ${GNUHEALTH_DIR}/tryton/server/modules/${modname} ${GNUHEALTH_DIR}/tryton/server/${TRYTOND}/trytond/modules/${mod} || bailout done message "INFO" "Relinking GNU Health modules ..." local HEALTH_MODS=`cd ${GNUHEALTH_DIR}/tryton/server/modules; ls -1d health*` for mod in ${HEALTH_MODS}; do message "INFO" "--> Relinking : ${mod}" ln -sf ${GNUHEALTH_DIR}/tryton/server/modules/${mod} ${GNUHEALTH_DIR}/tryton/server/${TRYTOND}/trytond/modules/ || bailout done message "INFO" "Relinking local modules and customizations ..." local LOCAL_MODS=`cd ${GNUHEALTH_DIR}/tryton/server/modules/local; ls -A` for mod in ${LOCAL_MODS}; do message "INFO" "--> Relinking : ${mod}" ln -sf ${GNUHEALTH_DIR}/tryton/server/modules/local/${mod} ${GNUHEALTH_DIR}/tryton/server/${TRYTOND}/trytond/modules/ || bailout done fi } do_update() { if [ $# -gt 1 ];then if [ $2 != "--dry-run" ];then message "ERROR" "Unrecognized update option" bailout fi fi check_download_dir get_current_values check_updates if [ $# -gt 1 ];then if [ $2 == "--dry-run" ];then cleanup exit 0 fi fi install_updates remove_old relink_mods cleanup } getlang() { if [ $# -eq 1 ]; then usage fi local lang_to_install=$2 local lang_file=${lang_to_install}.zip source $HOME/.gnuhealthrc || bailout local lang_download_dir=$(mktemp -d /tmp/gnuhealth-XXXX) message "INFO" "Going to modules directory..." cd ${GNUHEALTH_DIR}/tryton/server/modules || bailout message "INFO" "Retrieving language pack file for ${lang_to_install}" wget ${TRANSLATE_URL}/download-language/${lang_to_install}/gnu-health/?format=zip -O ${lang_download_dir}/${lang_file} || bailout message "INFO" "Installing / Updating language files for ${lang_to_install} ..." ${BSDTAR} --strip-components 3 -xzf ${lang_download_dir}/${lang_file} || bailout message "INFO" "Language pack ${lang_to_install} sucessfully installed / updated" message "INFO" "You now need to update the database modules" message "INFO" "Removing temporary directories" rm -rf ${lang_download_dir} cd } install_python_dependencies() { message "INFO" "Updating Python dependencies..." # PIP names on Debian/Arch Linux based distros: local PIP_NAMES="pip pip3 pip-python" PIP_NAME="" for NAME in ${PIP_NAMES}; do if [[ $(which ${NAME} 2>/dev/null) ]]; then PIP_NAME=${NAME} break fi done if [[ ! ${PIP_NAME} ]]; then message "ERROR" "PIP command not found. Please install it or check your PATH variable." bailout fi local PIP_CMD=$(which $PIP_NAME) local PIP_VERSION="$(${PIP_CMD} --version | awk '{print $2}')" local PIP_ARGS="install --upgrade --user" # Python packages local PIP_LXML="lxml" local PIP_RELATORIO="relatorio" local PIP_WRAPT="wrapt" local PIP_WERKZEUG="werkzeug<2" local PIP_DATEUTIL="python-dateutil" local PIP_PSYCOPG2="psycopg2-binary" local PIP_PYTZ="pytz" local PIP_LDAP="python-ldap" local PIP_VOBJECT="vobject" local PIP_QRCODE="qrcode" local PIP_PYBARCODE="python-barcode" local PIP_SIX="six" local PIP_PILLOW="Pillow" local PIP_CALDAV="caldav" local PIP_POLIB="polib" local PIP_SQL="python-sql" local PIP_STDNUM="python-stdnum" local PIP_SIMPLEEVAL="simpleeval" local PIP_CONFIGPARSER="configparser" local PIP_WEBDAV3="pywebdav3-gnuhealth" local PIP_BCRYPT="bcrypt" local PIP_NUMPY="numpy" local PIP_UNOCONV="unoconv" local PIP_MAGIC="python-magic" local PIP_BEREN="beren==0.7.0" local PIP_PENDULUM="pendulum" local PIP_MATPLOTLIB="matplotlib" local PIP_PASSLIB="passlib" local PIP_PYCOUNTRY="pycountry==20.7.3" local PIP_PROGRESSBAR="progressbar==2.2" local PIP_DEFUSEDXML="defusedxml" # Operating System specific package selection # Skip PYTHON-LDAP installation since it tries to install / compile it system-wide message "WARNING" "Skipping local PYTHON-LDAP installation. Please refer to the Wikibook to install it" local PIP_PKGS="$PIP_NUMPY $PIP_PYTZ $PIP_WRAPT $PIP_WERKZEUG $PIP_SIX $PIP_LXML $PIP_RELATORIO $PIP_DATEUTIL $PIP_PSYCOPG2 $PIP_VOBJECT \ $PIP_QRCODE $PIP_PYBARCODE $PIP_PILLOW $PIP_CALDAV $PIP_POLIB $PIP_SQL $PIP_STDNUM $PIP_SIMPLEEVAL $PIP_CONFIGPARSER \ $PIP_WEBDAV3 $PIP_BCRYPT $PIP_UNOCONV $PIP_MAGIC $PIP_PASSLIB $PIP_BEREN $PIP_PENDULUM $PIP_MATPLOTLIB $PIP_PASSLIB $PIP_PYCOUNTRY \ $PIP_PROGRESSBAR $PIP_DEFUSEDXML" message "INFO" "Installing python dependencies with pip-${PIP_VERSION} ..." for PKG in ${PIP_PKGS}; do message " >> ${PKG}" ${PIP_CMD} ${PIP_ARGS} ${PKG} || bailout message " >> OK" done } bailout() { message "ERROR" "Bailing out !" message "ERROR" "Removing lock files and temporary directories" rm -f $LOCKFILE rm -rf ${LANG_DOWNLOAD_DIR} exit 1 } cleanup() { # Delete temporary download directory rm -rf ${UPDATE_DOWNLOAD_DIR} || bailout exit 0 } parse_command_line() { if [ $# -eq 0 ]; then usage fi case $1 in version) echo $VERSION;; backup_attachments) do_backup_attachments $@;; backup_database) do_backup_database $@;; backup_environment) do_backup_environment $@;; update) do_update $@;; status) check_status;; getlang) getlang $@;; instpydeps) install_python_dependencies $@;; help) help;; *) echo $1: Unrecognized command; exit 1;; esac } parse_command_line $@