gastonfeng
10/23/2017 - 4:07 PM

install odoo from source

install odoo from source

#!/bin/bash
################################################################################################
# Fully automated script to install Odoo and Odoo SaaS Tool (tested on a fresh Ubuntu 14.04 LTS)
# * Install & configure last stable version of nginx
# * Install & configure last stable version of postgresql
# * Install & configure Odoo
# * Configure automated backup of Odoo databases
# * Optional: Install & configure Odoo SaaS Tool
# * Optional: Background installation: $ nohup ./odoo_install.sh > nohup.log 2>&1 </dev/null &
################################################################################################

 #### GENERAL SETTINGS : Edit the following settings as needed
 ## Gist url
 export GIST="bassn/996f8b168f0b1406dd54"   #update if you've forked this gist
 ## E-Mail
 export EMAIL_SERVER=stmp.example.com                                        
 export EMAIL_USER=mail@example.com
 export EMAIL_PASS=GiveMeYourPassBaby
 ## PostgreSQL
 export DB_PASS=`< /dev/urandom tr -dc A-Za-z0-9 | head -c${1:-32};echo;`    
 ## Odoo
 export ODOO_DOMAIN=odoo.example.com                                         
 export ODOO_DATABASE=odoo.example.com                                       
 export ODOO_USER=odoo
 export ODOO_BRANCH=8.0
 export ODOO_PASS=`< /dev/urandom tr -dc A-Za-z0-9 | head -c${1:-12};echo;`  
 ## SSL
 export SSL_CERT=/etc/ssl/certs/XXXX.crt                                    
 export SSL_KEY=/etc/ssl/private/XXXX.key                                   
 ## DB Backup 
 export DB_BACKUP="yes"         #set "no" if you do want to configure backup
 ## Odoo SaaS Tool 
 export ODOO_SAAS_TOOL="yes"    #set "no" if you do want odoo saas tool
 export SAAS_SERVER=server-1
 export SAAS_TEMPLATE=template-1
 ## Add your private Git
 export USE_PRIVATE_GIT="no"           #Set to "yes", if you want to clone a private Git
 export PRIVATE_GIT_REMOTE="https://MY_USER_NAME:MY_PASSWORD@bitbucket.org/MY_REMOTE_USER/MY_REMOTE_REPOSITORY.git"     #remote adress of your private Git
 export PRIVATE_GIT_LOCAL="/usr/local/src/odoo-addons/MY_LOCAL_ADDON_FOLDER"     #local folder of your private Git
 

 #### Detect type of system manager
 export SYSTEM=''
 pidof systemd && export SYSTEM='systemd' 
 [[ -z $SYSTEM ]] && whereis upstart | grep -q 'upstart: /' && export SYSTEM='upstart'
 [[ -z $SYSTEM ]] &&  export SYSTEM='supervisor'
 echo "SYSTEM=$SYSTEM"

 #### CHECK AND UPDATE LANGUAGE
 env | grep LANG
 export LANGUAGE=en_US:en && \
 export LANG=en_US.UTF-8 && \
 export LC_ALL=en_US.UTF-8 && \
 locale-gen en_US.UTF-8 && \
 dpkg-reconfigure locales
 locale

 #### DOWNLOADS...
 ### Packages
 apt-get update && \
 apt-get upgrade -y && \
 apt-get install -y git python-pip moreutils tree python-dev && \
 apt-get install -y emacs23-nox || apt-get install -y emacs24-nox  && \
 [[ "$SYSTEM" == "supervisor" ]] && apt-get install supervisor

 ### PostgreSQL
 wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
 echo 'deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main' >> /etc/apt/sources.list.d/pgdg.list &&\
 apt-get update &&\
 apt-get install postgresql postgresql-contrib -y && \
 echo "postgresql installed"
 
 ### Python
 pip install psycogreen &&\
 pip install rotate-backups &&\
 pip install oauthlib &&\
 pip install requests --upgrade 

 ### Deps for OCA website
 pip install ipwhois

 ### Deps for OCA Server tools
 apt-get install python-ldap &&
 pip install unidecode &&\
 pip install unidecode --upgrade

 ### Deps for addons-vauxoo
 pip install pandas

 ### Deps for Odoo Saas Tool
 pip install Boto 
 pip install FileChunkIO
 pip install pysftp

 ### Odoo Souce Code
 # If you change the following directories, you muss also ajust line 2 of file odoo-server.conf below
 cd /usr/local/src/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/odoo/odoo.git &&\
 mkdir /usr/local/src/odoo-addons -p && cd /usr/local/src/odoo-addons/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/web.git OCA/web/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/website.git OCA/website/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/account-financial-reporting.git OCA/account-financial-reporting/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/account-financial-tools.git OCA/account-financial-tools/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/partner-contact.git OCA/partner-contact/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/hr.git OCA/hr/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/pos.git OCA/pos/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/commission.git OCA/commission/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/server-tools.git OCA/server-tools/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/reporting-engine.git OCA/reporting-engine/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/rma.git OCA/rma/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/project.git OCA/project/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/contract.git OCA/contract/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/sale-workflow.git OCA/sale-workflow/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/sale-workflow.git OCA/purchase-workflow/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/bank-payment.git OCA/bank-payment/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/bank-statement-import.git OCA/bank-statement-import/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/OCA/bank-statement-reconcile.git OCA/bank-statement-reconcile/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/yelizariev/pos-addons.git yelizariev/pos-addons/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/yelizariev/access-addons.git yelizariev/access-addons/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/yelizariev/website-addons.git yelizariev/website-addons/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/yelizariev/addons-yelizariev.git yelizariev/addons-yelizariev/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/yelizariev/odoo-saas-tools.git yelizariev/odoo-saas-tools/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/iledarn/e-commerce.git iledarn/e-commerce/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/xpansa/hr.git xpansa/hr/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/odoomrp/odoomrp-wip.git odoomrp/odoomrp-wip/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/odoomrp/odoomrp-utils.git odoomrp/odoomrp-utils/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/Vauxoo/addons-vauxoo.git vauxoo/ &&\
 git clone -b ${ODOO_BRANCH} https://github.com/techreceptives/website_recaptcha.git techreceptives/ 
 if [[ "$USE_PRIVATE_GIT" == "yes" ]]        ###################################### IF
 then
 git clone -b ${ODOO_BRANCH} ${PRIVATE_GIT_REMOTE} ${PRIVATE_GIT_LOCAL}/
 export COMMA=","
 export PRIVATE_GIT_LOCAL="$PRIVATE_GIT_LOCAL$COMMA"
 else                                        ###################################### ELSE
 export PRIVATE_GIT_LOCAL=""
 fi                                          ###################################### END IF
 # further module collections
 mkdir -p z-others &&\ 
 mkdir -p z-others-p

 ### Odoo Deps
 ## python
 python --version                      # should be 2.7 or higher
 cd /usr/local/src/odoo &&\
 cp odoo.py odoo.py.orig &&\
 sed -i "s/'apt-get'/'apt-get', '-y'/" odoo.py &&\
 cat odoo.py | python &&\
 git checkout odoo.py
 echo "odoo.py checked out"

 ## wkhtmltopdf
 cd /usr/local/src
 lsb_release -a 
 uname -i
 # check version of your OS and download appropriate package
 # http://wkhtmltopdf.org/downloads.html
 apt-get install -y xfonts-base xfonts-75dpi
 apt-get -f install
# wget http://download.gna.org/wkhtmltopdf/0.12/0.12.2.1/wkhtmltox-0.12.2.1_linux-trusty-amd64.deb
 wget http://nightly.odoo.com/extra/wkhtmltox-0.12.1.2_linux-jessie-amd64.deb
 dpkg -i wkhtmltox-*.deb

 ## Less CSS via nodejs
 ## nodejs:
 # for 14.04+
 apt-get install -y npm
 ln -s /usr/bin/nodejs /usr/bin/node
 # for 13.10-
 # check https://www.odoo.com/documentation/8.0/setup/install.html
 ## less css
 npm install -g less less-plugin-clean-css
 #### ...DOWNLOADS done.

 #### Changes on Odoo Code
 cd /usr/local/src/odoo
 ## delete matches="..." at /web/database/manager
 sed -i 's/matches="[^"]*"//g' addons/web/static/src/xml/base.xml
 ## disable im_odoo_support
 sed -i "s/'auto_install': True/'auto_install': False/" addons/im_odoo_support/__openerp__.py

 #### CONFIGS
 ### System Config
 #from http://stackoverflow.com/questions/2914220/bash-templating-how-to-build-configuration-files-from-templates-with-bash
 export PERL_UPDATE_ENV="perl -p -e 's/\{\{([^}]+)\}\}/defined \$ENV{\$1} ? \$ENV{\$1} : \$&/eg' "
 [[ -z $SYSTEM ]] && echo "Don't forget to define SYSTEM variable"

 ### Odoo System User
 adduser --system --quiet --shell=/bin/bash --home=/opt/${ODOO_USER} --gecos '$OE_USER' --group ${ODOO_USER}
 ### Odoo DB User
 sudo su - postgres bash -c "psql -c \"CREATE USER ${ODOO_USER} WITH CREATEDB PASSWORD '${DB_PASS}';\""

 ### Odoo Config
 echo "Odoo Config"
 ## /var/log/odoo/
 mkdir -p /var/log/odoo/
 chown ${ODOO_USER}:${ODOO_USER} /var/log/odoo

 ## /temp import data
 mkdir -p /opt/${ODOO_USER}/.local/share/User/import/
 chown -R ${ODOO_USER}:${ODOO_USER} /opt/${ODOO_USER}/.local
 
 ## /etc/odoo/odoo-server.conf
 mkdir -p /etc/odoo && cd /etc/odoo/
 wget -q https://gist.githubusercontent.com/${GIST}/raw/odoo-server.conf -O odoo-server.conf
 eval "${PERL_UPDATE_ENV} < odoo-server.conf" | sponge odoo-server.conf
 chown ${ODOO_USER}:${ODOO_USER} odoo-server.conf
 chmod 600 odoo-server.conf


 #### NGINX
 #/etc/init.d/apache2 stop
 #apt-get remove apache2 -y && \
 wget --quiet -O - http://nginx.org/keys/nginx_signing.key | apt-key add - &&\
 echo 'deb http://nginx.org/packages/ubuntu/ trusty nginx' >> /etc/apt/sources.list.d/nginx.list &&\
 echo 'deb-src http://nginx.org/packages/ubuntu/ trusty nginx' >> /etc/apt/sources.list.d/nginx.list &&\
 apt-get update &&\
 apt-get install nginx -y && \
 echo "nginx installed"

 cd /etc/nginx && \
 mv nginx.conf nginx.conf.orig &&\
 wget -q https://gist.githubusercontent.com/${GIST}/raw/nginx.conf -O nginx.conf

 cd /etc/nginx && \
 wget -q https://gist.githubusercontent.com/${GIST}/raw/nginx_odoo_params -O odoo_params && \
 eval "${PERL_UPDATE_ENV} < odoo_params" | sponge odoo_params

 cd /etc/nginx && \
 wget -q https://gist.githubusercontent.com/${GIST}/raw/nginx_odoo_proxy_pass -O odoo_proxy_pass && \
 eval "${PERL_UPDATE_ENV} < odoo_proxy_pass" | sponge odoo_proxy_pass

 mkdir /etc/nginx/sites-available/ -p && \
 cd /etc/nginx/sites-available/ && \
 wget -q https://gist.githubusercontent.com/${GIST}/raw/nginx_odoo.conf -O odoo.conf && \
 eval "${PERL_UPDATE_ENV} < odoo.conf" | sponge odoo.conf
 mkdir /etc/nginx/sites-enabled/ -p && \
 cd /etc/nginx/sites-enabled/ && \
 ln -s ../sites-available/odoo.conf odoo.conf 
 
 #cd /etc/nginx/ && \
 cp -r /etc/nginx/conf.d/ /etc/nginx/conf.d.orig/  
 rm /etc/nginx/conf.d/default.conf && \
 rm /etc/nginx/conf.d/example_ssl.conf

 /etc/init.d/nginx restart

 #### START CONTROL
 ### CONTROL SCRIPTS - systemd
 if [[ "$SYSTEM" == "systemd" ]]            ###################################### IF
 then

 cd /lib/systemd/system/
 wget -q https://gist.githubusercontent.com/${GIST}/raw/odoo.service -O odoo.service
 eval "${PERL_UPDATE_ENV} < odoo.service" | sponge odoo.service
 ## START - systemd
 systemctl enable odoo.service 
 systemctl restart odoo.service 

 ### CONTROL SCRIPTS - upstart
 elif [[ "$SYSTEM" == "upstart" ]]          #################################### ELIF
 then

 cd /etc/init/
 wget -q https://gist.githubusercontent.com/${GIST}/raw/odoo-init.conf -O odoo.conf
 eval "${PERL_UPDATE_ENV} < odoo.conf" | sponge odoo.conf
 ## START - upstart
 start odoo     # alt: stop odoo  / restart odoo 

 ### CONTROL SCRIPTS - supervisor
 else                                       #################################### ELSE

 cd /etc/supervisor/conf.d/
 wget -q https://gist.githubusercontent.com/${GIST}/raw/odoo-supervisor.conf -O odoo.conf
 eval "${PERL_UPDATE_ENV} < odoo.conf" | sponge odoo.conf
 ## START - supervisor
 supervisorctl reread
 supervisorctl update
 supervisorctl restart odoo 

 fi                                         ################################   END IF

 echo "Do not forget to set server parameter report.url = 0.0.0.0:8069"

 ### CONTROL SCRIPTS - /etc/init.d/*
 # Such scripts are not recommended, because you will not get supervision features.
 # Use this link to find ones: https://gist.github.com/yelizariev/2abdd91d00dddc4e4fa4/d0ac3bd971e81213d17332647d9a74a580cfde6b
 

 #### ODOO DB BACKUP
 if [[ "$DB_BACKUP" == "yes" ]]             ###################################### IF
 then
 mkdir -p /opt/${ODOO_USER}/backups/
 chown ${ODOO_USER}:${ODOO_USER} /opt/${ODOO_USER}/backups/
 cd /usr/local/bin/
 wget -q https://gist.githubusercontent.com/${GIST}/raw/odoo-backup.py -O odoo-backup.py
 chmod +x odoo-backup.py
 echo "### check url for undestanding time parameters: https://github.com/xolox/python-rotate-backups" >> /etc/crontab
 echo -e "#6 6\t* * *\t${ODOO_USER} odoo-backup.py -d ${ODOO_DATABASE} -p /opt/${ODOO_USER}/backups/ --no-save-filestore --daily 8 --weekly 0 --monthly 0 --yearly 0" >> /etc/crontab
 echo -e "#4 4\t* * 7\t${ODOO_USER} odoo-backup.py -d ${ODOO_DATABASE} -p /opt/${ODOO_USER}/backups/" >> /etc/crontab
 ## to test run:
 # sudo su - ${ODOO_USER} -s /bin/bash -c  "odoo-backup.py -d ${ODOO_DATABASE} -p /opt/${ODOO_USER}/backups/"
 # e.g.
 # cd /usr/local/bin/ && sudo su - odoo -s /bin/bash -c  "odoo-backup.py -d ergodoo.com -p /opt/odoo/backups/"
 fi                                         ################################## END IF


 #### Odoo Saas Tool
 if [[ "$ODOO_SAAS_TOOL" == "yes" ]]        ###################################### IF
 then
 #emacs /etc/odoo/odoo-server.conf # change dbfilter to ^%h$ if needed
 echo $ODOO_PASS
 echo $ODOO_DOMAIN
 stop odoo
 sudo su - ${ODOO_USER} -s /bin/bash -c  "python /usr/local/src/odoo-addons/yelizariev/odoo-saas-tools/saas.py \
  --odoo-script=/usr/local/src/odoo/openerp-server \
  --odoo-config=/etc/odoo/odoo-server.conf \
  --portal-create --server-create --plan-create --run  \
  --admin-password=${ODOO_PASS} \
  --portal-db-name=${ODOO_DOMAIN} \
  --server-db-name=${SAAS_SERVER}.${ODOO_DOMAIN} \
  --plan-template-db-name=${SAAS_TEMPLATE}.${ODOO_DOMAIN} \
  --plan-clients=demo-%i.${ODOO_DOMAIN}"
 fi                                         ################################## END IF
 
 #### DEBUG
 ## show settings (admin password, addons path)
 head /etc/odoo/odoo-server.conf 
 ## show odoo version
 grep '^version_info ' /usr/local/src/odoo/openerp/release.py 
 ## Reminders
 echo "Do not forget PGTune: http://pgtune.leopard.in.ua/"
 ## log
 tail -f -n 100 /var/log/odoo/odoo-server.log 

 ## start from console (for ODOO_USER=odoo): 
 #  sudo su - odoo -s /bin/bash -c  "/usr/local/src/odoo/openerp-server -c /etc/odoo/odoo-server.conf"

 ## psql (use name of your database)
 # sudo -u odoo psql DATABASE

 ## some common issues:
 ## https://www.odoo.com/forum/help-1/question/dataerror-new-encoding-utf8-is-incompatible-with-the-encoding-of-the-template-database-sql-ascii-52124
 
 
user			nginx;
worker_processes	auto;   

error_log               /var/log/nginx/error.log warn;
pid                     /var/run/nginx.pid;

events {
	worker_connections	2048;
	multi_accept        	on;
    	use                 	epoll;
}

worker_rlimit_nofile		40000;

http {
	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	### Basic Settings
	sendfile			on;
	tcp_nopush                      on;
	tcp_nodelay                     on;
	types_hash_max_size             2048;
	#server_tokens                  off;
	#server_names_hash_bucket_size  64;
	#server_name_in_redirect        off;
	proxy_headers_hash_max_size     1024; 
    	proxy_headers_hash_bucket_size  128;

    	### Timeout Settings
	keepalive_timeout            	90;
	proxy_connect_timeout       	1800;   
	proxy_send_timeout          	1800;   
	proxy_read_timeout          	1800;   
	#client_header_timeout	    	600;
	#client_body_timeout 	    	600;
	send_timeout                	1800;   

    	### SSL Cache Settings
    	ssl_session_cache           	shared:SSL:30m;
	ssl_session_timeout         	60m;		
	ssl_protocols               	SSLv3 TLSv1 TLSv1.1 TLSv1.2;
	ssl_ciphers                 	HIGH:!aNULL:!MD5;
	ssl_prefer_server_ciphers   	on;

    	### File Cache Settings
    	open_file_cache             	max=10000 inactive=15m;
	open_file_cache_valid       	30m;
    	open_file_cache_min_uses    	1;
    	open_file_cache_errors      	on;

	### Logging Settings
    	access_log                  	/var/log/nginx/access.log;   
	error_log                   	/var/log/nginx/error.log;

	### Gzip Settings
	gzip                        	on;
    	gzip_disable                	"MSIE [1-6]\.";     
	gzip_vary                   	on;
	gzip_proxied                	any;
	gzip_comp_level             	9;
	gzip_buffers                	16 8k;
	gzip_min_length             	2048;	    
	gzip_http_version           	1.1;
	#gzip_types                 	*;		
	gzip_types                  	text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

	### Virtual Host Configs
	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}


#mail {
#	# See sample authentication script at:
#	# http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
# 
#	# auth_http localhost/auth.php;
#	# pop3_capabilities "TOP" "USER";
#	# imap_capabilities "IMAP4rev1" "UIDPLUS";
# 
#	server {
#		listen     localhost:110;
#		protocol   pop3;
#		proxy      on;
#	}
# 
#	server {
#		listen     localhost:143;
#		protocol   imap;
#		proxy      on;
#	}
#}
server {
    listen 80 ;
    listen [::]:80 ;
    ## Some domains to run in http without SSL
    server_name 
        XXXX_DOMAIN_A.net
        XXXX_DOMAIN_B.com
        ; 
    include odoo_params;

    ## non-ssl log files
    access_log    /var/log/nginx/odoo-access.log;
    error_log    /var/log/nginx/odoo-error.log;

    include odoo_proxy_pass;
}


server {
    listen 80 default_server;
    listen [::]:80 default_server;
    ## Other domains run in https with SSL
    #server_name {{ODOO_DOMAIN}};
    return 301 https://$host$request_uri;
}

server {
    listen 443;
    listen [::]:443;
    #server_name {{ODOO_DOMAIN}};

    include odoo_params;

    ## ssl certificate files
    ssl on;
    ssl_certificate        {{SSL_CERT}};
    ssl_certificate_key    {{SSL_KEY}};
    
    ## ssl log files
    access_log    /var/log/nginx/{{ODOO_USER}}-ssl-access.log;
    error_log    /var/log/nginx/{{ODOO_USER}}-ssl-error.log;

    # Let the OpenERP web service know that we’re using HTTPS, 
    # otherwise it will generate URL using http:// and not https://
    proxy_set_header X-Forwarded-Proto https;

    include odoo_proxy_pass;
    
    #the next line is only needed when we use explicite domain as server_name
    #add_header Strict-Transport-Security "max-age=2592000; includeSubDomains" always;   #max-age=31536000;
}


charset utf-8;
location = /favicon.ico {
    return 404;
}

## increase proxy buffer to handle some OpenERP web requests
proxy_buffers               16 64k;
proxy_buffer_size           128k;

## set headers
proxy_set_header            Host $host;
proxy_set_header            X-Real-IP       $remote_addr;
proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header            X-Forwarded-Proto $scheme;

#proxy_redirect             http:// https://;  
#proxy_read_timeout         600s;      #set centrally in nginx.conf             
client_max_body_size        200m;

#general proxy settings
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;

# by default, do not forward anything
proxy_redirect       off;
proxy_buffering      off;
    location /longpolling {
        proxy_pass http://127.0.0.1:8072;
    }
    location / {
        proxy_pass http://127.0.0.1:8069;
    }

    # cache some static data in memory for 90mins.
    # under heavy load this should relieve stress on the odoo web interface a bit.
    location ~* /web/static/ {
        proxy_cache_valid 200 90m;
        proxy_buffering    on;
        expires 864000;
        proxy_pass http://127.0.0.1:8069;
    }
    
#!/usr/bin/env python
### depends on https://github.com/xolox/python-rotate-backups -- check this url for understanding rotating parameters
import argparse

import os
import subprocess
import shutil
import zipfile
import datetime
import tempfile
from contextlib import contextmanager

### READ INPUT
parser = argparse.ArgumentParser(description='Odoo backup tool.')
parser.add_argument('-d', '--database', dest='database', nargs='+', help='database for backup')
parser.add_argument('--no-save-filestore', dest='save_filestore', action='store_false', help='skip filestore to save disk space')
parser.add_argument('--no-rotate', dest='rotate', action='store_false', help='skip backups rotating')
parser.add_argument('-p', '--path', dest='path', default='/tmp/', help='path to save backup')
parser.add_argument('-c', '--odoo-config', dest='odoo_config', default='/etc/odoo/odoo-server.conf', help='odoo config file')
parser.add_argument('--hourly', dest='hourly', default='24', help='how many hourly backups to preserve')
parser.add_argument('--daily', dest='daily', default='7', help='how many daily backups to preserve')
parser.add_argument('--weekly', dest='weekly', default='4', help='how many weekly backups to preserve')
parser.add_argument('--monthly', dest='monthly', default='12', help='how many monthly backups to preserve')
parser.add_argument('--yearly', dest='yearly', default='always', help='how many yearly backups to preserve')

#parser.add_argument('--odoo-source', dest='odoo_source', default='/usr/local/src/odoo/', help='odoo source dir')

args = parser.parse_args()

def get_odoo_config():
    import ConfigParser
    p = ConfigParser.ConfigParser()
    p.read(args.odoo_config)
    res = {}
    for (name,value) in p.items('options'):
        if value=='True' or value=='true':
            value = True
        if value=='False' or value=='false':
            value = False
        res[name] = value
    return res

odoo_config = get_odoo_config()


### EXECUTE


#@_set_pg_password_in_environment # see openerp/service/db.py
def dump_sql(db, dump_file):
    cmd = ['pg_dump', '--format=p', '--no-owner', '--file=' + dump_file]
    if odoo_config.get('db_user'):
        cmd.append('--username=' + odoo_config.get('db_user'))
    if odoo_config.get('db_host'):
        cmd.append('--host=' + odoo_config.get('db_host'))
    if odoo_config.get('db_port'):
        cmd.append('--port=' + str(odoo_config.get('db_port')))
    cmd.append(db)

    if exec_pg_command(*cmd):
        print ' '.join(cmd)
        raise Exception("Couldn't dump database")

def backup(db, dump_dir):
    odoo_data_dir = odoo_config.get('data_dir', '~/.local/share/Odoo/')
    filestore = os.path.join(odoo_data_dir, 'filestore', db)
    if args.save_filestore:
        os.symlink(filestore, os.path.join(dump_dir, 'filestore'))

    dump_file = os.path.join(dump_dir, 'dump.sql')
    dump_sql(db, dump_file)

    dump_archive  = "%(db)s_%(timestamp)s_%(mark)s.dump" % {
        'db': db,
        'timestamp': datetime.datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%SZ"),
        'mark': 'full' if args.save_filestore else 'quick',
    }
    with open(dump_archive, 'w') as stream:
        zip_dir(dump_dir, stream, include_dir=False)
    return dump_archive

def rotate(backup_dir):
    cmd = ['rotate-backups']
    for period in ('hourly', 'daily', 'weekly', 'monthly', 'yearly'):
        cmd.extend(['--%s' % period, getattr(args, period) ] )
    cmd.append(backup_dir)
    cmd.extend(['2>', '/dev/null'])
    os.system(' '.join(cmd))

def main():
    for db in args.database:
        backup_dir = os.path.join(args.path, db, 'full' if args.save_filestore else 'quick')
        if not os.path.exists(backup_dir):
            os.system('mkdir -p %s' % backup_dir)

        with tempdir() as dump_dir:
            dump_archive = backup(db, dump_dir)
            shutil.move(dump_archive, os.path.join(backup_dir, dump_archive))

        if args.rotate:
            rotate(backup_dir)

### TOOLS

def find_pg_tool(name):
    path = None
    #if config['pg_path'] and config['pg_path'] != 'None':
    #    path = config['pg_path']
    try:
        return which(name, path=path)
    except IOError:
        return None

def exec_pg_command(name, *args):
    prog = find_pg_tool(name)
    if not prog:
        raise Exception('Couldn\'t find %s' % name)
    args2 = (prog,) + args

    with open(os.devnull) as dn:
        return subprocess.call(args2, stdout=dn, stderr=subprocess.STDOUT)

def zip_dir(path, stream, include_dir=True):      # TODO add ignore list
    path = os.path.normpath(path)
    len_prefix = len(os.path.dirname(path)) if include_dir else len(path)
    if len_prefix:
        len_prefix += 1

    with zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zipf:
        for dirpath, dirnames, filenames in os.walk(path, followlinks=True):
            for fname in filenames:
                bname, ext = os.path.splitext(fname)
                ext = ext or bname
                if ext not in ['.pyc', '.pyo', '.swp', '.DS_Store']:
                    path = os.path.normpath(os.path.join(dirpath, fname))
                    if os.path.isfile(path):
                        zipf.write(path, path[len_prefix:])

@contextmanager
def tempdir():
    tmpdir = tempfile.mkdtemp()
    try:
        yield tmpdir
    finally:
        shutil.rmtree(tmpdir)

import sys
from os import access, defpath, pathsep, environ, F_OK, R_OK, W_OK, X_OK
from os.path import exists, dirname, split, join

windows = sys.platform.startswith('win')

defpath = environ.get('PATH', defpath).split(pathsep)

if windows:
    defpath.insert(0, '.') # can insert without checking, when duplicates are removed
    # given the quite usual mess in PATH on Windows, let's rather remove duplicates
    seen = set()
    defpath = [dir for dir in defpath if dir.lower() not in seen and not seen.add(dir.lower())]
    del seen

    defpathext = [''] + environ.get('PATHEXT',
        '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC').lower().split(pathsep)
else:
    defpathext = ['']

def which_files(file, mode=F_OK | X_OK, path=None, pathext=None):
    """ Locate a file in a path supplied as a part of the file name,
        or the user's path, or a supplied path.
        The function yields full paths (not necessarily absolute paths),
        in which the given file name matches an existing file in a directory on the path.

        >>> def test_which(expected, *args, **argd):
        ...     result = list(which_files(*args, **argd))
        ...     assert result == expected, 'which_files: %s != %s' % (result, expected)
        ...
        ...     try:
        ...         result = [ which(*args, **argd) ]
        ...     except IOError:
        ...         result = []
        ...     assert result[:1] == expected[:1], 'which: %s != %s' % (result[:1], expected[:1])

        >>> if windows: cmd = environ['COMSPEC']
        >>> if windows: test_which([cmd], 'cmd')
        >>> if windows: test_which([cmd], 'cmd.exe')
        >>> if windows: test_which([cmd], 'cmd', path=dirname(cmd))
        >>> if windows: test_which([cmd], 'cmd', pathext='.exe')
        >>> if windows: test_which([cmd], cmd)
        >>> if windows: test_which([cmd], cmd, path='<nonexistent>')
        >>> if windows: test_which([cmd], cmd, pathext='<nonexistent>')
        >>> if windows: test_which([cmd], cmd[:-4])
        >>> if windows: test_which([cmd], cmd[:-4], path='<nonexistent>')

        >>> if windows: test_which([], 'cmd', path='<nonexistent>')
        >>> if windows: test_which([], 'cmd', pathext='<nonexistent>')
        >>> if windows: test_which([], '<nonexistent>/cmd')
        >>> if windows: test_which([], cmd[:-4], pathext='<nonexistent>')

        >>> if not windows: sh = '/bin/sh'
        >>> if not windows: test_which([sh], 'sh')
        >>> if not windows: test_which([sh], 'sh', path=dirname(sh))
        >>> if not windows: test_which([sh], 'sh', pathext='<nonexistent>')
        >>> if not windows: test_which([sh], sh)
        >>> if not windows: test_which([sh], sh, path='<nonexistent>')
        >>> if not windows: test_which([sh], sh, pathext='<nonexistent>')

        >>> if not windows: test_which([], 'sh', mode=W_OK)  # not running as root, are you?
        >>> if not windows: test_which([], 'sh', path='<nonexistent>')
        >>> if not windows: test_which([], '<nonexistent>/sh')
    """
    filepath, file = split(file)

    if filepath:
        path = (filepath,)
    elif path is None:
        path = defpath
    elif isinstance(path, str):
        path = path.split(pathsep)

    if pathext is None:
        pathext = defpathext
    elif isinstance(pathext, str):
        pathext = pathext.split(pathsep)

    if not '' in pathext:
        pathext.insert(0, '') # always check command without extension, even for custom pathext

    for dir in path:
        basepath = join(dir, file)
        for ext in pathext:
            fullpath = basepath + ext
            if exists(fullpath) and access(fullpath, mode):
                yield fullpath

def which(file, mode=F_OK | X_OK, path=None, pathext=None):
    """ Locate a file in a path supplied as a part of the file name,
        or the user's path, or a supplied path.
        The function returns full path (not necessarily absolute path),
        in which the given file name matches an existing file in a directory on the path,
        or raises IOError(errno.ENOENT).

        >>> # for doctest see which_files()
    """
    try:
        return iter(which_files(file, mode, path, pathext)).next()
    except StopIteration:
        try:
            from errno import ENOENT
        except ImportError:
            ENOENT = 2
        raise IOError(ENOENT, '%s not found' % (mode & X_OK and 'command' or 'file'), file)


if __name__ == '__main__':
    main()

description "odoo"
setuid {{ODOO_USER}}

start on startup
respawn
respawn limit 2 5

exec /usr/local/src/odoo/openerp-server --config=/etc/odoo/odoo-server.conf --logfile=/var/log/odoo/odoo-server.log
description "odoo-longpolling"
setuid {{ODOO_USER}}

start on startup
respawn
respawn limit 2 5

exec /usr/local/src/odoo/openerp-gevent --config=/etc/odoo/odoo-server.conf --logfile=/var/log/odoo/odoo-server-longpolling.log
[program:odoo-longpolling]
command=/usr/local/src/odoo/openerp-gevent --config=/etc/odoo/odoo-server.conf --logfile=/var/log/odoo/odoo-server-longpolling.log
autostart=true
autorestart=true
user={{ODOO_USER}}
directory=/opt/{{ODOO_USER}}/
environment = HOME="/opt/{{ODOO_USER}}/",USER="{{ODOO_USER}}"

[Unit]
Description=odoo-longpolling
Requires=postgresql.service
After=postgresql.service
Wants=nginx.service

[Install]
Alias=odoo.service

[Service]
Type=simple
PermissionsStartOnly=true
EnvironmentFile=-/etc/odoo/odoo-server.conf
User={{ODOO_USER}}
Group={{ODOO_USER}}
SyslogIdentifier=odoo-server
PIDFile=/run/odoo/odoo-server.pid
#ExecStartPre=/usr/bin/install -d -m755 -o odoo -g odoo /run/odoo
ExecStart=/usr/local/src/odoo/openerp-gevent --config=/etc/odoo/odoo-server.conf --logfile=/var/log/odoo/odoo-server-longpolling.log
#ExecStop=/bin/kill $MAINPID
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target


[options]
addons_path = /usr/local/src/odoo/addons,/usr/local/src/odoo/openerp/addons,/usr/local/src/odoo-addons,{{PRIVATE_GIT_LOCAL}}/usr/local/src/odoo-addons/OCA/account-financial-reporting,/usr/local/src/odoo-addons/OCA/account-financial-tools,/usr/local/src/odoo-addons/OCA/partner-contact,/usr/local/src/odoo-addons/OCA/hr,/usr/local/src/odoo-addons/OCA/pos,/usr/local/src/odoo-addons/OCA/commission,/usr/local/src/odoo-addons/OCA/web,/usr/local/src/odoo-addons/OCA/project,/usr/local/src/odoo-addons/OCA/website,/usr/local/src/odoo-addons/OCA/server-tools,/usr/local/src/odoo-addons/OCA/reporting-engine,/usr/local/src/odoo-addons/OCA/rma,/usr/local/src/odoo-addons/OCA/contract,/usr/local/src/odoo-addons/OCA/sale-workflow,/usr/local/src/odoo-addons/OCA/purchase-workflow,/usr/local/src/odoo-addons/OCA/bank-payment,/usr/local/src/odoo-addons/OCA/bank-statement-import,/usr/local/src/odoo-addons/OCA/bank-statement-reconcile,/usr/local/src/odoo-addons/yelizariev/pos-addons,/usr/local/src/odoo-addons/yelizariev/access-addons,/usr/local/src/odoo-addons/yelizariev/website-addons,/usr/local/src/odoo-addons/yelizariev/addons-yelizariev,/usr/local/src/odoo-addons/yelizariev/odoo-saas-tools,/usr/local/src/odoo-addons/iledarn/e-commerce,/usr/local/src/odoo-addons/vauxoo,/usr/local/src/odoo-addons/xpansa/hr,/usr/local/src/odoo-addons/odoomrp/odoomrp-wip,/usr/local/src/odoo-addons/odoomrp/odoomrp-utils,/usr/local/src/odoo-addons/techreceptives,/usr/local/src/odoo-addons/z-others,/usr/local/src/odoo-addons/z-others-p 
admin_passwd = {{DB_PASS}}
auto_reload = False
csv_internal_sep = ,
data_dir=/opt/{{ODOO_USER}}/.local/share/Odoo
#dbfilter  = .*   ;will show database selector if there are more than one database
dbfilter = ^%h$  ;select database automatically by domain. E.g. http://portal.example.com will show "portal.example.com" database
#dbfilter = ^%d$  ;select database automatically by first subdomain (www is ignored). E.g. http://my.portal.example.com and http://www.my.portal.example.com will show database "my" 
db_user = {{ODOO_USER}}
db_template = template1
db_host = False
db_maxconn = 64
db_name = False
db_password = {{DB_PASS}}
db_port = False
debug_mode = False
demo = {}
email_from = False
#import_partial = /opt/{{ODOO_USER}}/.local/share/User/import/odoo.import.temp   ;needed for long-running data imports
import_partial = 
limit_memory_hard = 25000000000
limit_memory_soft = 24000000000
limit_request = 8192
limit_time_cpu = 10800
limit_time_real = 14400
list_db = True

# uncomment below to activate debug logs
#log_handler = ['["[\':DEBUG\']"]']
#log_level = debug

# should be set in run command (i.e. via --logfile)
#logfile = /var/log/odoo/odoo-server.log

login_message = False
logrotate = True
longpolling_port = 8072
max_cron_threads = 3
netrpc = False
netrpc_interface = 
netrpc_port = 8070
osv_memory_age_limit = 12.0
osv_memory_count_limit = False
pg_path = None
pidfile = False
proxy_mode = True
reportgz = False
secure_cert_file = {{SSL_CERT}}
secure_pkey_file = {{SSL_KEY}}
server_wide_modules = None
smtp_password = {{EMAIL_PASS}} ;False
smtp_port = 465  ;25
smtp_server = {{EMAIL_SERVER}}   ;localhost
smtp_ssl = True                  ;False
smtp_user = {{EMAIL_USER}}       ;False
static_http_document_root = None
static_http_enable = False
static_http_url_prefix = None
syslog = False
test_commit = False
test_enable = False
test_file = False
test_report_directory = False
timezone = False
translate_modules = ['all']
unaccent = False
without_demo = False
workers = 9
xmlrpc = True
xmlrpc_interface = 
xmlrpc_port = 8069
xmlrpcs = True
xmlrpcs_interface = 
xmlrpcs_port = 8071
[program:odoo]
command=/usr/local/src/odoo/openerp-server --config=/etc/odoo/odoo-server.conf --logfile=/var/log/odoo/odoo-server.log
autostart=true
autorestart=true
user={{ODOO_USER}}
directory=/opt/{{ODOO_USER}}/
environment = HOME="/opt/{{ODOO_USER}}/",USER="{{ODOO_USER}}"
[Unit]
Description=odoo
Requires=postgresql.service
After=postgresql.service
Wants=nginx.service

[Install]
Alias=odoo.service

[Service]
Type=simple
PermissionsStartOnly=true
EnvironmentFile=-/etc/odoo/odoo-server.conf
User={{ODOO_USER}}
Group={{ODOO_USER}}
SyslogIdentifier=odoo-server
PIDFile=/run/odoo/odoo-server.pid
#ExecStartPre=/usr/bin/install -d -m755 -o odoo -g odoo /run/odoo
ExecStart=/usr/local/src/odoo/openerp-server --config=/etc/odoo/odoo-server.conf --logfile=/var/log/odoo/odoo-server.log
#ExecStop=/bin/kill $MAINPID
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target