Hello,
regarding the backups of the gnuhealth-control command I modified this
bash script in a way that backups are differentiated into attachments,
database & environment. Before a potential commit I would work on
restore & tests but before doing this I would like to see what you think
about it.
Problems I see in the current state:
- All files & database are processed twice because there is
filesystem+database+filesystem&database
- All python & tryton modules are copied every time
- It fails if the database is not on the same system
- Restore can not be combined with changing the environment
- systemd .service file is not part of the backup
- It is not working for differing config file locations
Hopefully I could solve those problems with the new approach. It should
at least work for installations following the wikibooks documentation,
using the zypper package and modifications like my ansible scripts which
are based on the wikibooks documentation and keep the .gnuhealthrc at
$HOME but put config files at other locations.
The usage would be:
./gnuhealth-control backup_attachments --backdir <...> --datadir <...>
./gnuhealth-control backup_database --backdir <...> --database <...>
./gnuhealth-control backup_environment --backdir <...> --database <...>
Where ā./ā should be skipped on openSUSE package installation and "su
gnuhealth" + "cdutil" should be executed before if using the vanilla
installation
Besides Iām also interested in backup approaches people are using apart
from using gnuhealth-control if someone likes to share. I thought of
using rsnapshot (with SSH) for the attachments folder and doing the
database backup as postgres user or with sudo in order to include config
files as well.
Best
Gerald
On 31.03.22 15:12, Gerald Wiese wrote:
URL:
<https://savannah.gnu.org/task/?16142>
Summary: improve gnuhealth-control backup & restore
Project: GNU Health
Submitted by: gerald_wiese
Submitted on: Thu 31 Mar 2022 01:12:50 PM UTC
Should Start On: Thu 31 Mar 2022 12:00:00 AM UTC
Should be Finished on: Sun 01 May 2022 12:00:00 AM UTC
Category: None
Priority: 5 - Normal
Status: In Progress
Privacy: Public
Percent Complete: 0%
Assigned to: None
Open/Closed: Open
Release: None
Discussion Lock: Any
Module: health
_______________________________________________________
Details:
How to improve backups & restore in gnuhealth-control command?
Backup application for restore:
- attachments
- config files
- systemd service file
- .gnuhealthrc bash environment
- list of activated modules
Backup application for debugging if restore fails:
- OS version
- GH version
- Tryton version
- pip freeze
Backup PostgreSQL: A dump is saved but a backup as postgres/root could be more
appropriate in order to save config files as well that are not world-readable
Any further thoughts on this?
_______________________________________________________
Reply to this item at:
<https://savannah.gnu.org/task/?16142>
_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/
#!/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 <[email protected]>
# Copyright (C) 2011-2022 GNU Solidario <[email protected]>
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
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 <directory>
--datadir <directory>"
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 <directory>
--database <dbname>"
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
<directory> --database <dbname>"
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 $@