Merge lp:~therp-nl/openupgrade-server/7.0-deferred_steps into lp:openupgrade-server

Proposed by Stefan Rijnhart (Opener)
Status: Merged
Merged at revision: 4629
Proposed branch: lp:~therp-nl/openupgrade-server/7.0-deferred_steps
Merge into: lp:openupgrade-server
Diff against target: 181 lines (+74/-30)
4 files modified
openerp/addons/base/ir/ir_model.py (+13/-1)
openerp/modules/loading.py (+5/-5)
openerp/openupgrade/deferred_70.py (+55/-0)
openerp/openupgrade/openupgrade_loading.py (+1/-24)
To merge this branch: bzr merge lp:~therp-nl/openupgrade-server/7.0-deferred_steps
Reviewer Review Type Date Requested Status
Holger Brunn (Therp) code review Approve
Review via email: mp+177858@code.launchpad.net

Description of the change

Apparently, OpenERP 7.0 attempts to remove dropped columns and obsolete model's tables, triggered when an existing ir_model_data entry of the models 'ir.model' and 'ir.model.field' is not instanciated after a succesful module upgrade. That could be undesirable under certain circumstances, leading to data loss. Also, when whole models are missing there is the problem that the table cannot be retrieved anymore because this data is not in the database but only available from the instanciated model itself. This causes a lot of ugly errors in the log file. This branch logs the attempts to drop columns or tables but does not perform them.

Additionally, the deferred migration step is moved to a separate file and its call is optimized not to run at every pool initialization but only when at least some modules are being upgraded.

To post a comment you must log in.
Revision history for this message
Holger Brunn (Therp) (hbrunn) :
review: Approve (code review)
Revision history for this message
Sylvain LE GAL (GRAP) (sylvain-legal) wrote :

Hi.

1/ About the _drop_column & _drop_table calls. I agree with the concept but I will not be able to reproduce the call to these functions after a migration. Can you detail me when the problems occurs ? (an example of table or field that OpenERP try to delete).

2/ deferred migration move & conditional call : agreed.

Remark :
diff, line 20. "Not dropping the table of model ..." --> "Not dropping the table or view of model ..."

review: Needs Information
4623. By Stefan Rijnhart (Opener)

[MRG] Merged with target branch to resolve conflict

4624. By Stefan Rijnhart (Opener)

[IMP] Debug string, courtesy of Sylvain Le Gal

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Thanks for the suggestion, I just committed it.

About the dropping of columns and tables, this is triggered in the unlink method of ir.model.fields and ir.model respectively. I checked the logs from when I crafted this branch and all problematic models were related to deprecated modules that were not going to be reinstalled on 7.0 (such as our module to process a tax increase which occurred last year).

Revision history for this message
Sylvain LE GAL (GRAP) (sylvain-legal) wrote :

Ok.
If I unsterstood, I can not test this part of code if I don't have specific module ?

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Yes, although there were several of such modules in the database that we migrated (mostly wizard or reporting modules) so I expect this will be an issue in many migrations.

You can reproduce by installing this module in the 6.1 database, then upgrade the database without the module in your addons-path (the module is not available for 7.0): https://apps.openerp.com/apps/6.1/trp_update_tax/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openerp/addons/base/ir/ir_model.py'
2--- openerp/addons/base/ir/ir_model.py 2013-05-07 07:08:52 +0000
3+++ openerp/addons/base/ir/ir_model.py 2013-09-13 19:42:27 +0000
4@@ -35,7 +35,7 @@
5 from openerp.tools.translate import _
6 from openerp.osv.orm import except_orm, browse_record
7
8-from openerp.openupgrade import openupgrade_log
9+from openerp.openupgrade import openupgrade_log, openupgrade
10
11 _logger = logging.getLogger(__name__)
12
13@@ -147,6 +147,12 @@
14
15 def _drop_table(self, cr, uid, ids, context=None):
16 for model in self.browse(cr, uid, ids, context):
17+ # OpenUpgrade: do not run the new table cleanup
18+ openupgrade.message(
19+ cr, 'Unknown', False, False,
20+ "Not dropping the table or view of model %s", model.model)
21+ continue
22+
23 model_pool = self.pool.get(model.model)
24 cr.execute('select relkind from pg_class where relname=%s', (model_pool._table,))
25 result = cr.fetchone()
26@@ -302,6 +308,12 @@
27
28 def _drop_column(self, cr, uid, ids, context=None):
29 for field in self.browse(cr, uid, ids, context):
30+ # OpenUpgrade: do not run the new column cleanup
31+ openupgrade.message(
32+ cr, 'Unknown', False, False,
33+ "Not dropping the column of field %s of model %s", field.name, field.model)
34+ continue
35+
36 model = self.pool.get(field.model)
37 cr.execute('select relkind from pg_class where relname=%s', (model._table,))
38 result = cr.fetchone()
39
40=== modified file 'openerp/modules/loading.py'
41--- openerp/modules/loading.py 2013-07-23 20:00:30 +0000
42+++ openerp/modules/loading.py 2013-09-13 19:42:27 +0000
43@@ -44,7 +44,7 @@
44 from openerp.modules.module import initialize_sys_path, \
45 load_openerp_module, init_module_models, adapt_version
46
47-from openerp.openupgrade import openupgrade_loading
48+from openerp.openupgrade import openupgrade_loading, deferred_70
49 _logger = logging.getLogger(__name__)
50
51 def open_openerp_namespace():
52@@ -419,6 +419,10 @@
53 # Cleanup orphan records
54 pool.get('ir.model.data')._process_end(cr, SUPERUSER_ID, processed_modules)
55
56+ # OpenUpgrade: call deferred migration steps
57+ if update_module:
58+ deferred_70.migrate_deferred(cr, pool)
59+
60 for kind in ('init', 'demo', 'update'):
61 tools.config[kind] = {}
62
63@@ -444,10 +448,6 @@
64 else:
65 _logger.info('removed %d unused menus', cr.rowcount)
66
67- # STEP 5 1/2 (OpenUpgrade): deferred call to sync commercial partner fields
68- if update_module:
69- openupgrade_loading.sync_commercial_fields(cr, pool)
70-
71 # STEP 6: Uninstall modules to remove
72 if update_module:
73 # Remove records referenced from ir_model_data for modules to be
74
75=== added file 'openerp/openupgrade/deferred_70.py'
76--- openerp/openupgrade/deferred_70.py 1970-01-01 00:00:00 +0000
77+++ openerp/openupgrade/deferred_70.py 2013-09-13 19:42:27 +0000
78@@ -0,0 +1,55 @@
79+# -*- coding: utf-8 -*-
80+##############################################################################
81+#
82+# OpenERP, Open Source Management Solution
83+# This module copyright (C) 2013 Therp BV (<http://therp.nl>)
84+#
85+# This program is free software: you can redistribute it and/or modify
86+# it under the terms of the GNU Affero General Public License as
87+# published by the Free Software Foundation, either version 3 of the
88+# License, or (at your option) any later version.
89+#
90+# This program is distributed in the hope that it will be useful,
91+# but WITHOUT ANY WARRANTY; without even the implied warranty of
92+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
93+# GNU Affero General Public License for more details.
94+#
95+# You should have received a copy of the GNU Affero General Public License
96+# along with this program. If not, see <http://www.gnu.org/licenses/>.
97+#
98+##############################################################################
99+
100+"""
101+This module contains a set of functions that should be called at the end of the
102+migration. A migration may be run several times after corrections in the code
103+or the configuration, and there is no way for OpenERP to detect a succesful
104+result. Therefore, the functions in this module should be robust against
105+being run multiple times on the same database.
106+"""
107+
108+import logging
109+from openerp import SUPERUSER_ID
110+
111+logger = logging.getLogger("OpenUpgrade")
112+
113+def sync_commercial_fields(cr, pool):
114+ """
115+ Take care of propagating the commercial fields
116+ in the new partner model.
117+ """
118+ partner_obj = pool.get('res.partner')
119+ partner_ids = partner_obj.search(
120+ cr, SUPERUSER_ID,
121+ [], 0, False, False, {'active_test': False})
122+ logger.info("Syncing commercial fields between %s partners",
123+ len(partner_ids))
124+ for partner_id in partner_ids:
125+ vals = partner_obj.read(
126+ cr, SUPERUSER_ID, partner_id, [], load='_classic_write')
127+ partner_obj._fields_sync(
128+ cr, SUPERUSER_ID,
129+ partner_obj.browse(cr, SUPERUSER_ID, partner_id),
130+ vals)
131+
132+def migrate_deferred(cr, pool):
133+ sync_commercial_fields(cr, pool)
134
135=== modified file 'openerp/openupgrade/openupgrade_loading.py'
136--- openerp/openupgrade/openupgrade_loading.py 2013-08-02 12:43:11 +0000
137+++ openerp/openupgrade/openupgrade_loading.py 2013-09-13 19:42:27 +0000
138@@ -19,9 +19,8 @@
139 #
140 ##############################################################################
141
142-import logging
143 import types
144-from openerp import release, SUPERUSER_ID
145+from openerp import release
146 from openerp.osv.orm import TransientModel
147 from openerp.osv import fields
148 from openerp.openupgrade.openupgrade import table_exists
149@@ -30,8 +29,6 @@
150 # A collection of functions used in
151 # openerp/modules/loading.py
152
153-logger = logging.getLogger("OpenUpgrade")
154-
155 def add_module_dependencies(cr, module_list):
156 """
157 Select (new) dependencies from the modules in the list
158@@ -186,23 +183,3 @@
159 (key, value, record_id)
160 )
161 old_field[key] = value
162-
163-def sync_commercial_fields(cr, pool):
164- """
165- Take care of propagating the commercial fields
166- in the new partner model. To be called after the
167- upgrade process has finished.
168- """
169- partner_obj = pool.get('res.partner')
170- partner_ids = partner_obj.search(
171- cr, SUPERUSER_ID,
172- [], 0, False, False, {'active_test': False})
173- logger.info("Syncing commercial fields between %s partners",
174- len(partner_ids))
175- for partner_id in partner_ids:
176- vals = partner_obj.read(
177- cr, SUPERUSER_ID, partner_id, [], load='_classic_write')
178- partner_obj._fields_sync(
179- cr, SUPERUSER_ID,
180- partner_obj.browse(cr, SUPERUSER_ID, partner_id),
181- vals)

Subscribers

People subscribed via source and target branches