#! /bin/bash
#
# This free software is released under GNU Affero GPL3
# author: Antonio M. Vigliotti - antoniomaria.vigliotti@gmail.com
# (C) 2018-2023 by SHS-AV s.r.l. - http://www.shs-av.com - info@shs-av.com
#
READLINK=$(which greadlink 2>/dev/null) || READLINK=$(which readlink 2>/dev/null)
export READLINK
# Based on template 2.0.0
THIS=$(basename "$0")
TDIR=$(readlink -f $(dirname $0))
[ $BASH_VERSINFO -lt 4 ] && echo "This script $0 requires bash 4.0+!" && exit 4
if [[ -z $HOME_DEVEL || ! -d $HOME_DEVEL ]]; then
  [[ -d $HOME/odoo/devel ]] && HOME_DEVEL="$HOME/odoo/devel" || HOME_DEVEL="$HOME/devel"
fi
[[ -x $TDIR/../bin/python3 ]] && PYTHON=$(readlink -f $TDIR/../bin/python3) || [[ -x $TDIR/python3 ]] && PYTHON="$TDIR/python3" || PYTHON=$(which python3 2>/dev/null) || PYTHON="python"
[[ -z $PYPATH ]] && PYPATH=$(echo -e "import os,sys\no=os.path\na=o.abspath\nj=o.join\nd=o.dirname\nb=o.basename\nf=o.isfile\np=o.isdir\nC=a('"$TDIR"')\nD='"$HOME_DEVEL"'\nif not p(D) and '/devel/' in C:\n D=C\n while b(D)!='devel':  D=d(D)\nN='venv_tools'\nU='setup.py'\nO='tools'\nH=o.expanduser('~')\nT=j(d(D),O)\nR=j(d(D),'pypi') if b(D)==N else j(D,'pypi')\nW=D if b(D)==N else j(D,'venv')\nS='site-packages'\nX='scripts'\ndef pt(P):\n P=a(P)\n if b(P) in (X,'tests','travis','_travis'):\n  P=d(P)\n if b(P)==b(d(P)) and f(j(P,'..',U)):\n  P=d(d(P))\n elif b(d(C))==O and f(j(P,U)):\n  P=d(P)\n return P\ndef ik(P):\n return P.startswith((H,D,K,W)) and p(P) and p(j(P,X)) and f(j(P,'__init__.py')) and f(j(P,'__main__.py'))\ndef ak(L,P):\n if P not in L:\n  L.append(P)\nL=[C]\nK=pt(C)\nfor B in ('z0lib','zerobug','odoo_score','clodoo','travis_emulator'):\n for P in [C]+sys.path+os.environ['PATH'].split(':')+[W,R,T]:\n  P=pt(P)\n  if B==b(P) and ik(P):\n   ak(L,P)\n   break\n  elif ik(j(P,B,B)):\n   ak(L,j(P,B,B))\n   break\n  elif ik(j(P,B)):\n   ak(L,j(P,B))\n   break\n  elif ik(j(P,S,B)):\n   ak(L,j(P,S,B))\n   break\nak(L,os.getcwd())\nprint(' '.join(L))\n"|$PYTHON)
[[ $TRAVIS_DEBUG_MODE -ge 8 ]] && echo "PYPATH=$PYPATH"
for d in $PYPATH /etc; do
  if [[ -e $d/z0librc ]]; then
    . $d/z0librc
    Z0LIBDIR=$(readlink -e $d)
    break
  fi
done
[[ -z "$Z0LIBDIR" ]] && echo "Library file z0librc not found in <$PYPATH>!" && exit 72
[[ $TRAVIS_DEBUG_MODE -ge 8 ]] && echo "Z0LIBDIR=$Z0LIBDIR"
ODOOLIBDIR=$(findpkg odoorc "$PYPATH" "clodoo")
[[ -z "$ODOOLIBDIR" ]] && echo "Library file odoorc not found!" && exit 72
. $ODOOLIBDIR
[[ $TRAVIS_DEBUG_MODE -ge 8 ]] && echo "ODOOLIBDIR=$ODOOLIBDIR"

# DIST_CONF=$(findpkg ".z0tools.conf" "$PYPATH")
# TCONF="$HOME/.z0tools.conf"
CFG_init "ALL"
link_cfg_def
link_cfg $DIST_CONF $TCONF
[[ $TRAVIS_DEBUG_MODE -ge 8 ]] && echo "DIST_CONF=$DIST_CONF" && echo "TCONF=$TCONF"
get_pypi_param ALL
RED="\e[1;31m"
GREEN="\e[1;32m"
CLR="\e[0m"

__version__=2.0.3


evaluate_params() {
    local val prc minconn
    [[ $opt_branch =~ ^1[123456789] ]] && minconn=64 || minconn=32
    if [[ $opt_nopsql -ne 0 ]]; then
        ((AVAI_MEM=(CUR_MEM*3)/4))
    elif [[ $opt_huge -ne 0 ]]; then
        ((AVAI_MEM=(CUR_MEM+2)/3))
    else
        ((AVAI_MEM=(CUR_MEM+3)/4))
    fi
    ((REQ_WRKS=(NUSER+WRKS4CPU-1)/WRKS4CPU))
    ((MAX_WRKS=CUR_NCPU*2+opt_cw))
    ((REQ_CPU=((REQ_WRKS+opt_cw)+1)/2))
    [[ -n $QUEUE_JOB ]] && ((REQ_WRKS=REQ_WRKS+1))
    [[ $REQ_WRKS -gt $MAX_WRKS ]] && WK_WORKERS=$MAX_WRKS || WK_WORKERS=$REQ_WRKS
    [[ $no_workers -ne 0 ]] && WK_WORKERS=1
    [[ -n $QUEUE_JOB && $no_workers -ne 0 ]] && echo "Configuration mismatch: queue_job requires workers"
    ((MAX_HWRK=(MAX_WRKS+4)/5))
    ((MAX_LWRK=MAX_WRKS-MAX_HWRK))
    ((REQ_HWRK=(REQ_WRKS+4)/5))
    ((REQ_LWRK=REQ_WRKS-REQ_HWRK))
    ((HWRK=(WK_WORKERS+4)/5))
    ((LWRK=WK_WORKERS-HWRK))
    [[ $no_workers -eq 0 ]] && prc=2 || prc=$PRC4WRK
    ((REQ_AVAI_MEM=REQ_HWRK*MEM4HWRK*prc+REQ_LWRK*MEM4LWRK*prc))
    [[ $REQ_AVAI_MEM -gt $AVAI_MEM ]] && WK_AVAI_MEM=$AVAI_MEM || WK_AVAI_MEM=$REQ_AVAI_MEM
    [[ $no_workers -ne 0 ]] && ((MAX_HLIMIT=AVAI_MEM)) || (((MAX_HLIMIT=AVAI_MEM+2)/3))
    [[ $MAX_HLIMIT -lt $MEM4HWRK ]] && MAX_HLIMIT=$MEM4HWRK
    [[ $MAX_HLIMIT -lt $MIN_HLIMIT ]] && MAX_HLIMIT=$MIN_HLIMIT
    [[ $MAX_HLIMIT -gt $AVAI_MEM ]] && MAX_HLIMIT=$AVAI_MEM
    ((MAX_LLIMIT=AVAI_MEM*2/MAX_WRKS))
    ((val=MAX_HLIMIT*3/4))
    [[ $MAX_LLIMIT -gt $val ]] && MAX_LLIMIT=$val
    ((val=MAX_HLIMIT/2))
    [[ $MAX_LLIMIT -lt $val ]] && MAX_LLIMIT=$val
    [[ $no_workers -ne 0 ]] && ((REQ_HLIMIT=REQ_AVAI_MEM)) || (((REQ_HLIMIT=REQ_AVAI_MEM+2)/3))
    [[ $REQ_HLIMIT -lt $MEM4HWRK ]] && REQ_HLIMIT=$MEM4HWRK
    [[ $REQ_HLIMIT -lt $MIN_HLIMIT ]] && REQ_HLIMIT=$MIN_HLIMIT
    ((REQ_LLIMIT=REQ_AVAI_MEM*2/REQ_WRKS))
    ((val=REQ_HLIMIT*3/4))
    [[ $REQ_LLIMIT -gt $val ]] && REQ_LLIMIT=$val
    ((val=REQ_HLIMIT/2))
    [[ $REQ_LLIMIT -lt $val ]] && REQ_LLIMIT=$val
    if [[ $REQ_AVAI_MEM -gt $AVAI_MEM ]]; then
        [[ $no_workers -ne 0 ]] && ((WK_HLIMIT=AVAI_MEM)) || (((WK_HLIMIT=AVAI_MEM+2)/3))
        ((WK_LLIMIT=AVAI_MEM*2/WK_WORKERS))
    else
        [[ $no_workers -ne 0 ]] && ((WK_HLIMIT=REQ_AVAI_MEM)) || (((WK_HLIMIT=REQ_AVAI_MEM+2)/3))
        ((WK_LLIMIT=REQ_AVAI_MEM*2/WK_WORKERS))
    fi
    [[ $WK_HLIMIT -lt $MEM4HWRK ]] && WK_HLIMIT=$MEM4HWRK
    [[ $WK_HLIMIT -gt $AVAI_MEM ]] && WK_HLIMIT=$AVAI_MEM
    [[ $WK_HLIMIT -lt $MIN_HLIMIT ]] && WK_HLIMIT=$MIN_HLIMIT
    ((val=WK_HLIMIT*3/4))
    [[ $WK_LLIMIT -gt $val ]] && WK_LLIMIT=$val
    ((val=WK_HLIMIT/2))
    [[ $WK_LLIMIT -lt $val ]] && WK_LLIMIT=$val
    [[ $no_workers -eq 0 ]] && ((MAX_PG_DBCONN=(NUSER/16+1)*32)) || ((MAX_PG_DBCONN=(NUSER/16+1)*16))
    ((MAX_DBCONN=MAX_PG_DBCONN))
    [[ $MAX_PG_DBCONN -gt $CUR_PG_DBCONN ]] && ((MAX_DBCONN=CUR_PG_DBCONN))
    [[ $MAX_DBCONN -gt $max_dbconn ]] && MAX_DBCONN=$max_dbconn
    [[ $MAX_DBCONN -lt $minconn ]] && MAX_DBCONN=$minconn
    [[ $no_workers -eq 0 ]] && ((REQ_PG_DBCONN=(NUSER/16+1)*32)) || ((REQ_PG_DBCONN=(NUSER/16+1)*16))
    ((REQ_DBCONN=REQ_PG_DBCONN))
    [[ $REQ_PG_DBCONN -gt $CUR_PG_DBCONN ]] && ((REQ_DBCONN=CUR_PG_DBCONN))
    [[ $no_workers -eq 0 ]] && ((WK_PG_DBCONN=(NUSER/16+1)*32)) || ((WK_PG_DBCONN=(NUSER/16+1)*16))
    [[ $REQ_DBCONN -lt $minconn ]] && REQ_DBCONN=$minconn
    ((WK_DBCONN=WK_PG_DBCONN))
    [[ $WK_PG_DBCONN -gt $CUR_PG_DBCONN ]] && ((WK_DBCONN=CUR_PG_DBCONN))
    [[ $WK_PG_DBCONN -gt $CUR_PG_DBCONN ]] && WK_PG_DBCONN=$CUR_PG_DBCONN
    [[ $WK_DBCONN -lt $minconn ]] && WK_DBCONN=$minconn
    [[ $WK_WORKERS -lt 2 ]] && WK_WORKERS=0
    [[ $WK_WORKERS -gt 0 ]] && PROXY_MODE="True" || PROXY_MODE="False"
    [[ $WK_WORKERS -le 1 ]] && TIME_CPU=4800 || TIME_CPU=2400
    [[ $WK_WORKERS -le 1 ]] && TIME_REAL=9600 || TIME_REAL=4800
    [[ $opt_ltime -ne 0 ]] && ((TIME_CPU=TIME_CPU*2)) && ((TIME_REAL=TIME_REAL*2))
    ((MAX_NUSER=MAX_WRKS*WRKS4CPU))
    if [[ $opt_nopsql -ne 0 ]]; then
        ((RAM=REQ_AVAI_MEM/3*4))
    elif [[ $opt_huge -ne 0 ]]; then
        ((RAM=REQ_AVAI_MEM*3))
    else
        ((RAM=REQ_AVAI_MEM*4))
    fi
}

OPTOPTS=(h        b          C        c      D          K        H        L          M       m         n           N          p          S          t         V           v)
OPTDEST=(opt_help opt_branch opt_cpu  confn  max_dbconn opt_cw   opt_huge opt_lpport opt_mem opt_multi opt_dry_run no_workers opt_nopsql opt_sparse opt_ltime opt_version opt_verbose)
OPTACTI=("+"      "="        "="      "=>"   "="        "="      1        "="        "="     1         1           1          1          1          1         "*>"        "+")
OPTDEFL=(0        "12.0"     ""       ""     100        1        0        ""         ""      0         0           0          0          0          0         ""          -1)
OPTMETA=("help"   "branch"   "number" "file" "number"   "number" ""       "port"     "MB"    ""        ""          ""         ""         ""         ""        ""          "")
OPTHELP=("this help"\
 "branches: may be one or more of 6.1 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0 or 16.0"
 "# of cpu to evaluate (def current host)"
 "odoo configuration file"
 "max odoo db connection"
 "# of cron workers (def=1)"
 "huge database"
 "long polling port (def=8072)"
 "MB of memory to evaluate"
 "multi-instance odoo environment"
 "do nothing (dry-run)"
 "disable workers"
 "psql server run in separate machine"
 "multi sparse db"
 "long time processes"
 "show version"
 "verbose mode")
OPTARGS=(NUSER)

parseoptargs "$@"
if [[ "$opt_version" ]]; then
  echo "$__version__"
  exit $STS_SUCCESS
fi
[[ $opt_verbose -eq -1 ]] && opt_verbose=1
if [[ $opt_help -gt 0 ]]; then
  print_help "Update Odoo configuration file to best performance"\
  "(C) 2018-2023 by zeroincombenze(R)\nhttp://wiki.zeroincombenze.org/en/Linux/dev\nAuthor: antoniomaria.vigliotti@gmail.com"
  exit $STS_SUCCESS
fi
discover_multi
odoo_root=""
for p in $(echo ""|grep "^addons_path *=.*" $confn|tr -d " "|awk -F= '{print $2}'|tr "," " "); do
  [[ -x $p/../odoo-bin ]] && odoo_root=$p && break
done
[[ -z $odoo_root ]] && echo "No Odoo executable found!" && exit 1
odoo_vid=$(build_odoo_param FULLVER $odoo_root)
# [[ -z $odoo_branch ]] && odoo_branch=$odoo_ver
# [[ $(build_odoo_param MAJVER $odoo_branch) -ne $odooo_ver ]] && echo "Odoo version mismatch ($odoo_branch!=$odoo_ver)!" && exit 1


CUR_NUSER=$(echo ""|grep -E "^# .antoniov.*Workers are set for [0-9]+ users" $confn|grep --color=never -Eo "[0-9]+"|tail -n1)
[[ -z "$CUR_NUSER" ]] && CUR_NUSER=0
if [[ -n "$NUSER" && ! $NUSER =~ ^[0-9]+$ ]]; then
    echo "Invalid # of user supplied. Please issue a valid number or leave empty to get current value!!"
    exit 1
fi
# Odoo constants
MIN_HLIMIT=1792
if [[ $opt_sparse -ne 0 ]]; then
    WRKS4CPU=10
elif [[ $opt_huge -ne 0 ]]; then
    WRKS4CPU=8
else
    WRKS4CPU=6
fi
MEM4WRK=640
if [[ $opt_huge -ne 0 ]]; then
    ((MEM4HWRK=MEM4WRK*17/7))
    ((MEM4LWRK=MEM4WRK/2))
else
    ((MEM4HWRK=MEM4WRK*8/5))
    ((MEM4LWRK=MEM4WRK/4))
fi
if [[ $no_workers -eq 0 ]]; then
    PRC4WRK=64
elif [[ $opt_huge -eq 0 ]]; then
    PRC4WRK=8
elif [[ $opt_sparse -ne 0 ]]; then
    PRC4WRK=4
else
    PRC4WRK=6
fi
# Detected or simulated
QUEUE_JOB=$(echo ""|grep "^server_wide_modules =.*" $confn|grep --color=never -Eo "queue_job")
CUR_LPPORT=$(echo ""|grep "^longpolling_port *=.*" $confn|awk -F= '{print $2}'|grep --color=never -Eo "[0-9]+")
[[ -n $opt_lpport ]] && WK_LPPORT=$opt_lpport || WK_LPPORT=$CUR_LPPORT
[[ -z $WK_LPPORT || $WK_LPPORT == "0" ]] && WK_LPPORT=$(build_odoo_param LPPORT $odoo_vid)
[[ -z "$WK_LPPORT" ]] && WK_LPPORT=8072
[[ -z "$NUSER" && $CUR_NUSER -ne 0 ]] && NUSER=$CUR_NUSER
[[ -z "$NUSER" ]] && NUSER=16
[[ $NUSER -lt 2 ]] && NUSER=2
[[ -n "$opt_cpu" ]] && CUR_NCPU=$opt_cpu || CUR_NCPU="$(lscpu|grep "^CPU.s.:"|awk -F: '{print $2}')"
CUR_NCPU=${CUR_NCPU// /}
[[ -n "$opt_mem" ]] && CUR_MEM=$opt_mem || CUR_MEM=$(free -m|grep "Mem:"|awk '{print $2}')
CUR_PG_DBCONN=$(pg_db_active -s)
[[ -z "$CUR_PG_DBCONN" ]] && CUR_PG_DBCONN=100
[[ $opt_cw -lt 1 ]] && opt_cw=1
[[ $opt_cw -gt 2 ]] && opt_cw=2
CUR_PROXY_MODE=$(echo ""|grep "^proxy_mode *=.*" $confn|awk -F= '{print $2}')
[[ -z "$CUR_PROXY_MODE" ]] && CUR_PROXY_MODE="False"
cur_time_cpu=$(echo ""|grep "^limit_time_cpu *=.*" $confn|grep --color=never -Eo "[0-9]+")
[[ -z "$cur_time_cpu" ]] && cur_time_cpu=60
cur_time_real=$(echo ""|grep "^limit_time_real *=.*" $confn|grep --color=never -Eo "[0-9]+")
[[ -z "$cur_time_real" ]] && cur_time_real=120
CUR_HWRK=$(echo "2147483648"|grep "^limit_memory_hard *=.*" $confn|grep --color=never -Eo "[0-9]+")
((CUR_HLIMIT=(CUR_HWRK+1048575)/1048576))
CUR_LWRK=$(echo "1610612736"|grep "^limit_memory_soft *=.*" $confn|grep --color=never -Eo "[0-9]+")
((CUR_LLIMIT=(CUR_LWRK+1048575)/1048576))
CUR_WRKS=$(echo ""|grep "^workers *=.*" $confn|grep --color=never -Eo "[0-9]+")
[[ -z "$CUR_WRKS" ]] && CUR_WRKS=0
CUR_DBCONN=$(echo ""|grep "^db_maxconn *=.*" $confn|grep --color=never -Eo "[0-9]+")
[[ -z "$CUR_DBCONN" ]] && CUR_DBCONN=64
CUR_LOGROTATE=$(echo ""|grep "^logrotate *=.*" $confn|awk -F= '{print $2}')
[[ -z "$CUR_LOGROTATE" ]] && CUR_LOGROTATE="False"
[[ $NUSER -eq 0 || $no_workers -ne 0 ]] && LOGROTATE="True" || LOGROTATE="False"
#
evaluate_params
#
[[ $CUR_NCPU -lt $REQ_CPU ]] && STS_NCPU="  <-- <CPU>"
[[ $WK_AVAI_MEM -lt $REQ_AVAI_MEM ]] && STS_MEM="<-- <RAM>"
[[ $CUR_PG_DBCONN -lt $REQ_PG_DBCONN ]] && STS_DBC="   <-- <CONN>"
[[ $WK_HLIMIT -gt $AVAI_MEM ]] && STS_HL="<-- <MEM>"
#
printf "                      Detected      Max Required  Applied\n"
printf "# concurrent users.:  %8d %8d %8d\n" $CUR_NUSER $MAX_NUSER $NUSER
printf "# CPU..............:  %8d          %8d           %s\n" $CUR_NCPU $REQ_CPU "$STS_NCPU"
printf "Available memory...:  %8d %8d %8d %8d MB %s\n" $CUR_MEM $AVAI_MEM $REQ_AVAI_MEM $WK_AVAI_MEM "$STS_MEM"
printf "High limit memory..:  %8d %8d %8d %8d MB %s\n" $CUR_HLIMIT $MAX_HLIMIT $REQ_HLIMIT $WK_HLIMIT "$STS_HL"
printf "Low limit memory...:  %8d %8d %8d %8d MB\n" $CUR_LLIMIT $MAX_LLIMIT $REQ_LLIMIT $WK_LLIMIT
printf "# workers..........:  %8d %8d %8d %8d\n" $CUR_WRKS $MAX_WRKS $REQ_WRKS $WK_WORKERS
printf "# hard workers.....:           %8d %8d %8d\n" $MAX_HWRK $REQ_HWRK $HWRK
printf "# soft workers.....:           %8d %8d %8d\n" $MAX_LWRK $REQ_LWRK $LWRK
printf "# DB connections...:  %8d %8d %8d %8d\n" $CUR_DBCONN $MAX_DBCONN $REQ_DBCONN $WK_DBCONN
printf "# psql connections.:  %8d %8d %8d %8d  %s\n" $CUR_PG_DBCONN $MAX_PG_DBCONN $REQ_PG_DBCONN $WK_PG_DBCONN "$STS_DBC"
printf "longpolling_port...:  %8d                   %8d\n" $CUR_LPPORT $WK_LPPORT
printf "Proxy mode.........:  %8.8s                   %8.8s\n" $CUR_PROXY_MODE $PROXY_MODE
printf "Log rotate.........:  %8.8s                   %8.8s\n" $CUR_LOGROTATE $LOGROTATE
printf "limit time CPU.....:  %8d                   %8d\n" $cur_time_cpu $TIME_CPU
printf "limit time real....:  %8d                   %8d\n" $cur_time_real $TIME_REAL
if [[ $opt_nopsql -eq 0 ]]; then
((PSQL_MEM=(CUR_MEM*3)/4))
printf "Memory reserved to postgresql server...........: %8d\n" $PSQL_MEM
fi
if [[ $CUR_NCPU -lt $REQ_CPU ]]; then
    echo "*<CPU>* Warning! You should increase the # of CPU to $REQ_CPU! ***"
fi
if [[ $WK_AVAI_MEM -lt $REQ_AVAI_MEM ]]; then
    echo "*<RAM>* Warning! You should increase the physical memory to $RAM! ***"
fi
if [[ $WK_HLIMIT -gt $AVAI_MEM ]]; then
    echo "*<MEM>* Warning! System could crash with big data! ***"
fi
if [[ $CUR_PG_DBCONN -lt $REQ_PG_DBCONN ]]; then
   echo "*<CONN>* Warning! You should increase postgresql max connections to $REQ_PG_DBCONN! ***"
fi

((MEM_HARD=WK_HLIMIT*1024*1024))
((MEM_SOFT=WK_LLIMIT*1024*1024))
if [[ -n "$confn" ]]; then
    echo "Update file $confn ..."
    grep -E "^# .*Workers are set for [0-9]+ users" $confn
    if [ $? -ne 0 ]; then
        run_traced "sed \"/^workers *=.*/i # [antoniov: $(date +%Y-%m-%d)] Workers are set for $NUSER users\" -i $confn"
    else
        run_traced "sed -re \"s/^# .*Workers are set for [0-9]+ users/# [antoniov: $(date +%Y-%m-%d)] Workers are set for $NUSER users/\" -i $confn"
    fi
    run_traced "sed -e \"s/^limit_memory_hard *=.*/limit_memory_hard = $MEM_HARD/\" -i $confn"
    run_traced "sed -e \"s/^limit_memory_soft *=.*/limit_memory_soft = $MEM_SOFT/\" -i $confn"
    run_traced "sed -e \"s/^workers *=.*/workers = $WK_WORKERS/\" -i $confn"
    run_traced "sed -e \"s/^db_maxconn *=.*/db_maxconn = $WK_DBCONN/\" -i $confn"
    run_traced "sed -e \"s/^proxy_mode *=.*/proxy_mode = $PROXY_MODE/\" -i $confn"
    run_traced "sed -e \"s/^longpolling_port *=.*/longpolling_port = $WK_LPPORT/\" -i $confn"
    run_traced "sed -e \"s/^limit_time_cpu *=.*/limit_time_cpu = $TIME_CPU/\" -i $confn"
    run_traced "sed -e \"s/^limit_time_real *=.*/limit_time_real = $TIME_REAL/\" -i $confn"
    run_traced "sed -e \"s/^logrotate *=.*/logrotate = $LOGROTATE/\" -i $confn"
    echo "You should restart odoo with a command like this one"
    echo "sudo systemctl restart odoo"
fi
