Skip to content

Instantly share code, notes, and snippets.

@iledarn
Last active August 20, 2016 14:26
Show Gist options
  • Save iledarn/c81c3504148996086109f4874c43b87c to your computer and use it in GitHub Desktop.
Save iledarn/c81c3504148996086109f4874c43b87c to your computer and use it in GitHub Desktop.

/openerp/addons/base/base.sql

4: SET LOCAL default_sequenceam = 'bdr';

Two odoo servers with replicated databases

We are resuming the previous part https://gist.github.com/iledarn/840b8b75df04742ee4bc1cb03f194cac where we have testhost1 and testhost2 with replicated database bdrdemo.

Connect and change owner of bdrdemo database to odoo. But first create user 'odoo' in postgresql From testhost1:

docker exec -i --user=root -t testhost1 /bin/bash
su - postgres
createuser -s odoo
psql -c "ALTER DATABASE bdrdemo OWNER TO odoo"

The same operations on testhost2:

docker exec -i --user=root -t testhost2 /bin/bash
su - postgres
createuser -s odoo
psql -c "ALTER DATABASE bdrdemo OWNER TO odoo"

Create odoo containers and link them to our postgresql containers.

docker run --name odoo1 --link testhost1:db -t odoo
docker run --name odoo2 --link testhost2:db -t odoo

Connect to the first odoo. Install emacs-nox and git there. We use emacs-nox to edit some files. And use git to work with github repositories as we need one module from there.

docker exec -i --user=root -t odoo1 /bin/bash
apt-get update
apt-get install -y emacs-nox
apt-get install -y git

The same operations on the second odoo:

docker exec -i --user=root -t odoo2 /bin/bash
apt-get update
apt-get install -y emacs-nox
apt-get install -y git

We must customize odoo in order to use it with bdr. First from odoo1: (we use Alt-g-g to goto line, Ctrl-x-s to save file and Ctrl-x-c to close)

emacs /usr/lib/python2.7/dist-packages/openerp/models.py

Go to line 2721 and put new line and put new line cr.execute("SET LOCAL default_sequenceam = 'bdr';") after it. Then go to line 2799. There we replace word 'UNIQUE' with 'PRIMARY KEY'. Then save and exit. BDR restricts UPDATE and DELETE operations with tables that have no PRIMARY KEY. https://wiki.postgresql.org/wiki/BDR_Command_Restrictions#Replication_of_UPDATE_or_DELETE_on_a_table_without_a_PRIMARY_KEY

The same operations from odoo2:

emacs /usr/lib/python2.7/dist-packages/openerp/models.py

2721: new line cr.execute("SET LOCAL default_sequenceam = 'bdr';") after. 2799: replace 'UNIQUE' to 'PRIMARY KEY'. Then save and exit.

We are using BDR global sequences http://bdr-project.org/docs/0.9.0/global-sequences.html

From odoo1:

emacs /usr/lib/python2.7/dist-packages/openerp/addons/base/ir/ir_sequence.py

21: There should be sql = "CREATE SEQUENCE %s USING bdr" % seq_name

22: cr.execute(sql) Then save and exit.

The same for the second odoo:

emacs /usr/lib/python2.7/dist-packages/openerp/addons/base/ir/ir_sequence.py

21: sql = "CREATE SEQUENCE %s USING bdr INCREMENT BY %%s START WITH %%s" % seq_name

From odoo1:

emacs /usr/lib/python2.7/dist-packages/openerp/modules/registry.py

234: cr.execute("""CREATE SEQUENCE base_registry_signaling USING bdr INCREMENT BY 1 START WITH 1""") 236: cr.execute("""CREATE SEQUENCE base_cache_signaling USING bdr INCREMENT BY 1 START WITH 1""")

The same from odoo2:

emacs /usr/lib/python2.7/dist-packages/openerp/modules/registry.py

234: cr.execute("""CREATE SEQUENCE base_registry_signaling USING bdr INCREMENT BY 1 START WITH 1""") 236: cr.execute("""CREATE SEQUENCE base_cache_signaling USING bdr INCREMENT BY 1 START WITH 1""")

Now we must edit and split base.sql file. Move insertion statements to the second file base2.sql. We do this in order to bdr use global sequences. From odoo1:

emacs /usr/lib/python2.7/dist-packages/openerp/addons/base/base.sql

4: SET LOCAL default_sequenceam = 'bdr'; Cut lines from 192 to the end of the file and put them into base2.sql new file. Comment select setval(.. lines

The same from odoo2:

emacs /usr/lib/python2.7/dist-packages/openerp/addons/base/base.sql

4: SET LOCAL default_sequenceam = 'bdr'; Cut lines from 192 to the end of the file and put them into base2.sql new file. Comment select setval(.. lines

From odoo1:

emacs /usr/lib/python2.7/dist-packages/openerp/modules/db.py

Paste the following two lines before L38:

import time
time.sleep(10)

Copy lines from 26 to 37 and paste them after line 40. Change 'base.sql' to 'base2.sql' on L41.

Do the same operations on odoo2:

emacs /usr/lib/python2.7/dist-packages/openerp/modules/db.py

We need to install a module to store all attachment files in database. This way all attachements will be synchronized too. It is one of the possible solution to syncronize files. E.g. we may use also rsync utility.

On odoo1:

cd /usr/local/src/
git clone https://github.com/yelizariev/addons-yelizariev.git
emacs /etc/odoo/openerp-server.conf

Add /usr/local/src/addons-yelizariev into addons_path then save and exit.

The same on odoo2:

cd /usr/local/src/
git clone https://github.com/yelizariev/addons-yelizariev.git
emacs /etc/odoo/openerp-server.conf

Now we should restart our odoo containers. We stop them both and then start only odoo1. So we can initiate database there and install ir_attachment_force_storage module. Note that postgresql containers running, we don't stop them.

docker stop odoo1
docker stop odoo2
docker start -a odoo1

Connect to odoo1. We need to know its IP.

docker exec -i --user=root -t odoo1 /bin/bash
ip addr

My odoo1 IP was 172.17.0.8. Go the your browser and put http://172.17.0.8:8069/web/database/manager url there. Log in inro bdrdemo and install ir_attachment_force storage module there.

Now we can start our second odoo.

docker start -a odoo2

Then connect to it from another terminal:

docker exec -i --user=root -t odoo2 /bin/bash
ip addr

Then in browser http://172.17.0.9:8069/web/database/manager Note that not initdb process started for the second odoo. bdrdemo database was replicated on second postgresql server.

Limitations

  • we can install modules i.e. create new tables only with two postgresql servers online
  • when we install new modules on one odoo, the second odoo should be restarted after it
  • due to the global sequences voting we can create records on tables only with two postgresql servers online

If we were using more than two servers (bdr nodes) then we could eliminate the last limitation.

Here you can see video tutorial on this instruction (2 Parts):

There was an error with global sequnces that didn't occure second time in other database.

/openerp/addons/base/ir/ir_sequence.py

21: sql = "CREATE SEQUENCE %s INCREMENT BY %%s START WITH %%s" % seq_name

21: sql = "CREATE SEQUENCE %s START WITH %%s USING bdr" % seq_name

22: cr.execute(sql, (number_increment, number_next))

22: cr.execute(sql, (number_next,))

For 8.0: edit ir_sequence._create_sequence

138: sql = "CREATE SEQUENCE ir_sequence_%03d INCREMENT BY %%s START WITH %%s" % id

138: sql = "CREATE SEQUENCE ir_sequence_%03d START WITH %%s USING bdr" % id

139: cr.execute(sql, (number_increment, number_next))

139: cr.execute(sql, (number_next,))

106: 'implementation': 'standard',

106: 'implementation': 'no_gap',

openerp/models.py

2722: cr.execute("SET LOCAL default_sequenceam = 'bdr'")

2799: cr.execute('CREATE TABLE "%s" ("%s" INTEGER NOT NULL, "%s" INTEGER NOT NULL, PRIMARY KEY("%s","%s"))' % (m2m_tbl, col1, col2, col1, col2))

/openerp/modules/registry.py

  @classmethod
  def setup_multi_process_signaling(cls, cr):
      if not openerp.multi_process:
          return None, None

      # Inter-process signaling:
      # The `base_registry_signaling` sequence indicates the whole registry
      # must be reloaded.
      # The `base_cache_signaling sequence` indicates all caches must be
      # invalidated (i.e. cleared).
      cr.execute("""SELECT sequence_name FROM information_schema.sequences WHERE sequence_name='base_registry_signaling'""")
      if not cr.fetchall():
          cr.execute("""CREATE SEQUENCE base_registry_signaling INCREMENT BY 1 START WITH 1""")
          cr.execute("""SELECT nextval('base_registry_signaling')""")
          cr.execute("""CREATE SEQUENCE base_cache_signaling INCREMENT BY 1 START WITH 1""")
          cr.execute("""SELECT nextval('base_cache_signaling')""")

      cr.execute("""
                  SELECT base_registry_signaling.last_value,
                         base_cache_signaling.last_value
                  FROM base_registry_signaling, base_cache_signaling""")
      r, c = cr.fetchone()
      _logger.debug("Multiprocess load registry signaling: [Registry: # %s] "\
                  "[Cache: # %s]",
                  r, c)
      return r, c


233 (232 in 8.0): cr.execute("""CREATE SEQUENCE base_registry_signaling INCREMENT BY 1 START WITH 1""")
233 (232 in 8.0): cr.execute("""CREATE SEQUENCE base_registry_signaling START WITH 1 USING bdr""")

235 (234 in 8.0): cr.execute("""CREATE SEQUENCE base_cache_signaling INCREMENT BY 1 START WITH 1""")
235 (234 in 8.0): cr.execute("""CREATE SEQUENCE base_cache_signaling START WITH 1 USING bdr""")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment