How to migrate Odoo from one version to another: the ultimate guide

A general how-to to help developers and other Odooers manage one of the most diffucult and recurring task of any Odoo instance: Odoo migration
June 1, 2024 by
How to migrate Odoo from one version to another: the ultimate guide
Raffaele Del Gatto
| No comments yet

Odoo migration is an almost inevitable process for those who want to continue having an updated Odoo system that keeps pace with the times, continues to be supported, and does not have security holes.

Over the years, I have faced countless migrations, and first and foremost, I can say that there is no truly standard methodology for migration. Or rather, there are a series of tools and good practices that are certainly common factors in all migrations, but different decisions, actions, and methodological lines are different from instance to instance.

There are some questions that accompany the initial analysis phase when approaching a migration: is the Odoo instance enterprise or community version? Is the instance on odoo.sh? How large is the database being migrated? Where are most of the data concentrated? How many integrations are there with external systems and how dependent are they on Odoo? How much does the temporary shutdown of Odoo impact the client's business, and how long can it be kept off for the migration process?

These are actually questions that should also be asked during the initial implementation phase, to understand (for example) how much sense it makes to centralize some processes in Odoo and how much to externalize them to other software, and to avoid having to face problems that will eventually come up and could even jeopardize the project.

Let's now look at the classic steps that concern the majority of Odoo migrations.

Odoo database migration

For migrating an Odoo database from one version to a higher version, there are mainly two tools: the Openupgrade tool from OCA, or the official script from Odoo SA provided for Enterprise customers. Therefore, in the case of a non-enterprise base instance, only the Openupgrade tool would be available.

We will now explain the two procedures.

How to migrate an Odoo database using Openupgrade, the tool from OCA.

Openupgrade is a tool developed by the Odoo Community Association (OCA) that helps users migrate their databases from one version of Odoo to another with ease. It is completely open source and its code can be viewed at the following GitHub repository: https://github.com/OCA/OpenUpgrade (while the official documentation is accessible at this link: https://oca.github.io/OpenUpgrade/index.html).

Below are the necessary steps to perform the migration:

1. First, you need to clone the repository inside the Odoo path of the target version to which you want to migrate. For example, if you want to migrate to version 16 and Odoo is located in the path /opt/odoo16/odoo, then you should clone the OpenUpgrade repository in that folder, referencing the 16.0 branch.

cd /opt/odoo16/odoo
git clone https://github.com/OCA/OpenUpgrade -b 16.0

Inside the OpenUpgrade folder we will find two main directories: openupgrade_framework, which contains the Odoo patches, and openupgrade_scripts which contains the actual migration analyses and scripts.

2. Run the updates contained in the requirements.txt file within the main folder of OpenUpgrade:

pip install -r requirements.txt

3. Launch the script pointing to the database you want to migrate and the target version of Odoo. It is good practice to test the migration multiple times on a backup of the original database until the procedure appears stable. The script should be run within the root folder of Odoo, as if launching an instance. For example, if we have our Odoo in /opt/odoo16/odoo the command will be:

python odoo-bin -d db_to_migrate --upgrade-path=/opt/odoo16/odoo/OpenUpgrade/openupgrade_scripts --update all --stop-after-init --load=base,web,openupgrade_framework

At this point, the migration process will start and we will see the log of the scripts running on the screen. It is important to note that migration does not always succeed on the first try, especially when the instance is heavily customized, there is a lot of data, or there are errors within it. If there are errors, they need to be analyzed and fixed, often through database queries. For example, there may be constraints introduced after certain versions, which could lead to errors if one of the fields in question has values that do not comply with the constraint. It will be necessary to act on the record to make it compatible.

The other option, for more complex errors, is to directly modify the OpenUpgrade scripts to correct the error based on our database. In both cases, given the heterogeneity of cases, it is mandatory to rely on qualified Odoo professionals who can understand and fix the error.

How to migrate an Odoo database using Odoo SA scripts

The other solution available only for enterprise clients is to use the tool provided by Odoo SA. This is the official page of the tool: https://upgrade.odoo.com.

For on-premise instances, the solutions are to either run the process via command line, or to use the form where you can upload the database dump and start the migration directly from the graphical interface. The second solution is available for instances with not large databases, with a maximum of 2GB of space.

As for the command line tool, we will explain below how to use it.

The basic command, as reported by the documentation, is this:

python <(curl -s https://upgrade.odoo.com/upgrade) test -d <your db name> -t <target version>

The instruction python <(curl -s https://upgrade.odoo.com/upgrade) allows you to run the python instructions contained in the web address locally. Test is the type of migration we are performing, which if successful will return a database completely neutralized for testing. The -d instruction must be followed by the name of the odoo database to migrate present in our postgres server. Finally, we have -t, which must be followed by the target version to which we want to bring the database (e.g. -t 17.0). When it comes time to migrate for the live system, the 'test' parameter must be replaced with 'production', in order to have a non-neutralized database usable in a production instance.

When the command is executed, a token is generated that will uniquely identify the migration we are performing and can be used for various operations, as we will explain below.

In addition to the command to start the actual migration, the Odoo command tool provides several actions that can be listed by giving the command:

python <(curl -s https://upgrade.odoo.com/upgrade) --help

The options restore, status, and log serve to: download a successfully migrated database from the procedure; get the status of a specific migration; access the log of a specific migration. For each of these topics, we can use the --help option to know the parameters accepted by it:

python <(curl -s https://upgrade.odoo.com/upgrade) log --help
usage: python <(curl -s https://upgrade.odoo.com/upgrade) log
       [-h] -t TOKEN [-f FROM_BYTE]

optional arguments:
  -h, --help            show this help message and exit
  -t TOKEN, --token TOKEN
                        The token ID of the request
  -f FROM_BYTE, --from-byte FROM_BYTE
                        From which line start retrieving the log (0=from the
                        beginning)

In the example above, we can see the explanation on how to use the log argument. As you can see, the use of the unique token generated during the launch of the migration is fundamental (for all the types listed above).

python <(curl -s https://upgrade.odoo.com/upgrade) test --help
usage: python <(curl -s https://upgrade.odoo.com/upgrade) test
       [-h] [-d DBNAME] [-r RESTORE_NAME] [-i DUMP] [-c CONTRACT] -t TARGET
       [-e ENV] [--env-file ENV_FILE] [-x] [-s SSH_KEY] [-j CORE_COUNT]
       [-n DATA_SERVER_NAME] [-u DATA_SERVER_USER] [-p DATA_SERVER_PATH]

optional arguments:
  -h, --help            show this help message and exit
  -d DBNAME, --dbname DBNAME
                        The name of a database to dump and upgrade
  -r RESTORE_NAME, --restore-name RESTORE_NAME
                        The name of database into which the upgraded dump must
                        be restored
  -i DUMP, --dump DUMP  The database dump to upgrade (.sql, .dump, .sql.gz,
                        .zip or a psql dump directory with toc.dat file)
  -c CONTRACT, --contract CONTRACT
                        The contract number associated to the database (by
                        default taken from the DB if it already has one,
                        mandatory when sending a dump file with --dump)
  -t TARGET, --target TARGET
                        The upgraded database version
  -e ENV, --env ENV     Set an environment variable, in the format VAR=VAL
  --env-file ENV_FILE   Read in a file of environment variables, one per line,
                        in the format VAR=VAL
  -x, --no-restore      Download the upgraded database dump without restoring
                        it
  -s SSH_KEY, --ssh-key SSH_KEY
                        The ssh key to use for data transfer (default:
                        /tmp/1000_upgrade_ssh_key)
  -j CORE_COUNT, --core-count CORE_COUNT
                        The number of core to use to dump/restore a database
                        (default: 4)
  -n DATA_SERVER_NAME, --data-server-name DATA_SERVER_NAME
                        The server name where to download/upload dumps
                        (default: upgrade.odoo.com)
  -u DATA_SERVER_USER, --data-server-user DATA_SERVER_USER
                        The server user where to download/upload dumps
                        (default: odoo)
  -p DATA_SERVER_PATH, --data-server-path DATA_SERVER_PATH
                        The path on the server where to download/upload dumps
                        (default: /data)

Above, we see the options available for the migration process from test to production. There are several interesting options, such as the possibility of using a database dump instead of a restored database present in postgres, by calling the -i option instead of the -d option. Detailed information can then be provided on the number of cores to be used for the dump process through the -j option, or use the -x option to prevent Odoo SA's tool from not only returning the dump but also performing the restore on your postgres server at the end of a successfully completed migration.

In conclusion, we can see that the tool is very flexible and can be adapted to our specific needs. Finally, we note that the procedure is asynchronous, so once the database has been sent to the Odoo SA servers, we can turn off our machine and follow the procedure when and where we want, using the migration token.

In case of an error, we can try to manage and fix it through some queries in our database. If this is not enough, then we will necessarily have to open a ticket with Odoo's technical support service, indicating the license of the instance: unlike OpenUpgrade, the tool is proprietary and only Odoo SA technicians can modify the script for the specific case of our instance.

Restore the Odoo filestore

The procedures listed above are for migrating the database to a new version, but do not include the migration of the filestore. By default, Odoo generates a filestore for each specific database in the standard folder ~/.local/share/Odoo/filestore, unless declared otherwise in the Odoo configuration file.

Restoring the filestore for a migration is actually a very simple operation. Let's give a practical example. Let's say that our Odoo instance database is for version 14 and is called odoo_14, and we have migrated a database to version 16 by renaming it odoo_16.

In the folder /.local/share/Odoo/filestore we will definitely have the subfolder odoo_14, which will contain the entire filestore structure of our instance 14. In case we had launched instance 16 before restoring the filestore, we will already have a subfolder named odoo_16 (this does not compromise the restoration of the filestore, but if you want to test or migrate an instance with its filestore, we recommend putting this in the correct location before launching the instance).

In this case, simply copy the odoo_14 filestore, giving odoo_16 as the destination folder. So on Linux we will give the command:

cp -r odoo_14 odoo_16

Migration of modules and custom code

Obviously, the other aspect to consider during a migration is related to the modules installed in the system. First of all, it is necessary to map out to understand, beyond installed core and Enterprise modules, how many OCA modules we use, if we have purchased third-party modules, and if we eventually have one or more custom modules.

Core and Enterprise modules are generally excluded from the analysis in the migration process as these are already migrated, but it is good practice to have an idea of what has changed in terms of structure and functionality because various changes could have a significant impact on our custom modules. Think for example when, in Odoo version 13, the account.invoice class was completely eliminated to have everything inside account.move.

If we use one or more OCA modules, we must check that these have been migrated correctly. Usually, within the Issue section of the repository, we find pages dedicated to the migration of a specific version: see for example the account-invoicing page for the migration of the code to version 16 https://github.com/OCA/account-invoicing/issues/1250

Regarding OCA modules and repositories, some considerations must be made. Even if the OCA is an organization with its specific rules, different repositories are managed by local OCA associations, which can make specific decisions regarding the management of a given repository. For example, the Italian localization repository (https://github.com/OCA/l10n-italy) is migrated with all the functionalities only for even versions, as it became too burdensome to migrate the code to each new Odoo version (generally released every year).

In general, when a new Odoo version is released, it is unlikely that OCA modules have already been converted or that the conversion will be completed within a few months. However, keep in mind that the repositories and the OCA association are governed by healthy principles that characterize OpenSource communities. Therefore, if you do not find something converted that you need shortly, the invitation is to collaborate (https://odoo-community.org/get-involved/contribute) actively and propose yourself for the conversion of the module or eventually help for those already in progress.

As for third-party modules, you should go to the Odoo webstore to check that these have been converted to our target version, and if so, purchase the module again. If the module is not available, it is advisable to contact the developer. If this attempt is unsuccessful, you will have to develop your own module to restore the functionality that was previously provided by the third-party module.

Finally, our custom modules will need to be migrated to make them compatible with the target version. In this case, we can give some general advice that is valid for every migration.

First of all, check what the main technical differences are between the two versions, in order to successfully adapt your code: for example, from version 13 the decorators @api.one and @api.multi are no longer used. Some innovations are reported in the Odoo documentation changelog (https://github.com/odoo/documentation/blob/17.0/content/developer/reference/backend/orm/changelog.rs) but we believe that this does not exhaustively represent all the technical changes that have taken place in a specific version.

In addition, we must pay close attention when our modules extend/modify standard features of Odoo. It may happen that a class is suppressed or renamed, that views are renamed, or that their structure changes. Therefore, maximum attention and thorough testing of the module are required before releasing it on the new version.

Resolution of classic problems

You have migrated the database and the code, you have all the modules ready and at this point you want to test the Odoo instance on the new version. However, you realize that something is still not working and there are errors blocked on one or more views in the system, or there are problems with assets. The first advice is to delete the old assets from the system and regenerate them, which can be done with a query like this:

delete from ir_assets;

You do not necessarily have to do this for all assets. Sometimes it happens that in a new version some modules are no longer used, and it is therefore necessary to remove any traces of it that may cause conflicts. To delete assets linked to a specific module, the query becomes:

delete from ir_asset where path ilike '%your_module%';

If you notice that this module continues to give problems, if it is no longer used, it is advisable to bring it to an uninstalled state:

update ir_module_module set state='uninstalled' where name='your_module';

You must then delete (old) custom views from the module:

delete from ir_ui_view where arch_fs ilike '%your_module%';

If, instead, when opening some views you get errors of the type field missing, it is because there is still a view in which there are one or more fields that are no longer present in the new database. In this case, it is necessary to delete such views with a query like this:

delete from ir_ui_view where cast(arch_db as text) like '%missing_fields%';

Continue at this point to test all the views and repeat the procedure until you achieve a stable system.

If you encounter specific problems or have other considerations, we invite you to share your comments or email us directly.

How to migrate Odoo from one version to another: the ultimate guide
Raffaele Del Gatto June 1, 2024
Share this post
Tags
Archive
Sign in to leave a comment