def upgrade_module(self): ir_module = self.env['ir.module.module'] # install/upgrade: double-check preconditions modules = ir_module.search([('state', 'in', ['to upgrade', 'to install'])]) if modules: cr.execute("""SELECT d.name FROM ir_module_module m JOIN ir_module_module_dependency d ON (m.id = d.module_id) LEFT JOIN ir_module_module m2 ON (d.name = m2.name) WHERE m.id in %s and (m2.state IS NULL or m2.state IN %s)""", (tuple(modules.ids), ('uninstalled',))) unmet_packages = [x[0] for x in cr.fetchall()] if unmet_packages: raise Warning(_('Unmet Dependency!'), _('Following modules are not installed or unknown: %s') % ('\n\n' + '\n'.join(unmet_packages))) modules.download() cr.commit() # save before re-creating cursor below # Change state, if not specified, set to done. self.write({'state': self.env.context.get('to_state', False) or 'done'}) pooler.restart_pool(cr.dbname, update_module=True) return { 'type': 'ir.actions.client', 'tag': 'reload', 'params': {'wait': True}, }
def upgrade_module(self, cr, uid, ids, context=None): ir_module = self.pool.get('ir.module.module') # install/upgrade: double-check preconditions ids = ir_module.search(cr, uid, [('state', 'in', ['to upgrade', 'to install'])]) if ids: cr.execute("""SELECT d.name FROM ir_module_module m JOIN ir_module_module_dependency d ON (m.id = d.module_id) LEFT JOIN ir_module_module m2 ON (d.name = m2.name) WHERE m.id in %s and (m2.state IS NULL or m2.state IN %s)""", (tuple(ids), ('uninstalled',))) unmet_packages = [x[0] for x in cr.fetchall()] if unmet_packages: raise osv.except_osv(_('Unmet dependency !'), _('Following modules are not installed or unknown: %s') % ('\n\n' + '\n'.join(unmet_packages))) ir_module.download(cr, uid, ids, context=context) cr.commit() # save before re-creating cursor below pooler.restart_pool(cr.dbname, update_module=True) ir_model_data = self.pool.get('ir.model.data') __, res_id = ir_model_data.get_object_reference(cr, uid, 'base', 'view_base_module_upgrade_install') return { 'view_type': 'form', 'view_mode': 'form', 'res_model': 'base.module.upgrade', 'views': [(res_id, 'form')], 'view_id': False, 'type': 'ir.actions.act_window', 'target': 'new', }
def upgrade_module(self, cr, uid, ids, context=None): ir_module = self.pool.get("ir.module.module") # install/upgrade: double-check preconditions module_ids = ir_module.search(cr, uid, [("state", "in", ["to upgrade", "to install"])]) if module_ids: cr.execute( """SELECT d.name FROM ir_module_module m JOIN ir_module_module_dependency d ON (m.id = d.module_id) LEFT JOIN ir_module_module m2 ON (d.name = m2.name) WHERE m.id in %s and (m2.state IS NULL or m2.state IN %s)""", (tuple(module_ids), ("uninstalled",)), ) unmet_packages = [x[0] for x in cr.fetchall()] if unmet_packages: raise osv.except_osv( _("Unmet Dependency!"), _("Following modules are not installed or unknown: %s") % ("\n\n" + "\n".join(unmet_packages)), ) ir_module.download(cr, uid, module_ids, context=context) cr.commit() # save before re-creating cursor below # Change state, if not specified, set to done. self.write(cr, uid, ids, {"state": context.get("to_state", False) or "done"}, context=context) pooler.restart_pool(cr.dbname, update_module=True) return {"type": "ir.actions.client", "tag": "reload", "params": {"wait": True}}
def exp_migrate_databases(self,databases): from openerp.osv.orm import except_orm from openerp.osv.osv import except_osv for db in databases: try: _logger.info('migrate database %s', db) tools.config['update']['base'] = True pooler.restart_pool(db, force_demo=False, update_module=True) except except_orm, inst: netsvc.abort_response(1, inst.name, 'warning', inst.value) except except_osv, inst: netsvc.abort_response(1, inst.name, 'warning', inst.value)
def exp_migrate_databases(self,databases): from openerp.osv.orm import except_orm from openerp.osv.osv import except_osv l = netsvc.Logger() for db in databases: try: l.notifyChannel('migration', netsvc.LOG_INFO, 'migrate database %s' % (db,)) tools.config['update']['base'] = True pooler.restart_pool(db, force_demo=False, update_module=True) except except_orm, inst: self.abortResponse(1, inst.name, 'warning', inst.value) except except_osv, inst: self.abortResponse(1, inst.name, inst.exc_type, inst.value)
def _initialize_db(serv, id, db_name, demo, lang, user_password): cr = None try: serv.actions[id]['progress'] = 0 cr = sql_db.db_connect(db_name).cursor() openerp.modules.db.initialize(cr) # TODO this should be removed as it is done by pooler.restart_pool. tools.config['lang'] = lang cr.commit() cr.close() pool = pooler.restart_pool(db_name, demo, serv.actions[id], update_module=True)[1] cr = sql_db.db_connect(db_name).cursor() if lang: modobj = pool.get('ir.module.module') mids = modobj.search(cr, SUPERUSER_ID, [('state', '=', 'installed')]) modobj.update_translations(cr, SUPERUSER_ID, mids, lang) # update admin's password and lang values = {'password': user_password, 'lang': lang} pool.get('res.users').write(cr, SUPERUSER_ID, [SUPERUSER_ID], values) cr.execute('SELECT login, password FROM res_users ORDER BY login') serv.actions[id].update(users=cr.dictfetchall(), clean=True) cr.commit() cr.close() except Exception, e: serv.actions[id].update(clean=False, exception=e) _logger.exception('CREATE DATABASE failed:') serv.actions[id]['traceback'] = traceback.format_exc() if cr: cr.close()
def _initialize_db(serv, id, db_name, demo, lang, user_password): cr = None try: serv.actions[id]['progress'] = 0 cr = sql_db.db_connect(db_name).cursor() openerp.modules.db.initialize(cr) # TODO this should be removed as it is done by pooler.restart_pool. tools.config['lang'] = lang cr.commit() cr.close() pool = pooler.restart_pool(db_name, demo, serv.actions[id], update_module=True)[1] cr = sql_db.db_connect(db_name).cursor() if lang: modobj = pool.get('ir.module.module') mids = modobj.search(cr, 1, [('state', '=', 'installed')]) modobj.update_translations(cr, 1, mids, lang) cr.execute('UPDATE res_users SET password=%s, context_lang=%s, active=True WHERE login=%s', ( user_password, lang, 'admin')) cr.execute('SELECT login, password, name ' \ ' FROM res_users ' \ ' ORDER BY login') serv.actions[id].update(users=cr.dictfetchall(), clean=True) cr.commit() cr.close() except Exception, e: serv.actions[id].update(clean=False, exception=e) _logger.exception('CREATE DATABASE failed:') serv.actions[id]['traceback'] = traceback.format_exc() if cr: cr.close()
def quirk_fiscalyear(self, cr, uid, ids, context=None): """ Install account module first and create a fiscal year, in order to prevent "No fiscal year defined" exception during an upgrade or reinstallation of the account module. Refer to account_fiscalyear.find(), which is called as a default function by the orm upon module upgrade. """ module_obj = self.pool.get('ir.module.module') pool = self.pool # Retrieve status of the account module account_module_id = module_obj.search( cr, uid, [('name', '=', 'account')], context=context)[0] state = module_obj.read( cr, uid, account_module_id, ['state'], context=context)['state'] if state != 'installed': # Cancel installation of other modules module_ids = module_obj.search( cr, uid, [('state', '=', 'to install')]) module_obj.write(cr, uid, module_ids, {'state': 'uninstalled'}) # Mark the module and its dependencies module_obj.button_install(cr, uid, [account_module_id]) # Install account module cr.commit() _db, pool = pooler.restart_pool(cr.dbname, update_module=True) # get or create today's fiscal year fy_obj = pool.get('account.fiscalyear') if not fy_obj.find(cr, uid, False, exception=False, context=context): fy_obj.create(cr, uid, { 'name': time.strftime('%Y'), 'code': time.strftime('%Y'), 'date_start': "%s-01-01" % time.strftime('%Y'), 'date_stop': "%s-12-31" % time.strftime('%Y'), })
def unlink(self, cr, user, ids, context=None): # Prevent manual deletion of module tables if context is None: context = {} if isinstance(ids, (int, long)): ids = [ids] if not context.get(MODULE_UNINSTALL_FLAG) and \ any(model.state != 'manual' for model in self.browse(cr, user, ids, context)): raise except_orm(_('Error'), _("Model '%s' contains module data and cannot be removed!") % (model.name,)) self._drop_table(cr, user, ids, context) res = super(ir_model, self).unlink(cr, user, ids, context) if not context.get(MODULE_UNINSTALL_FLAG): # only reload pool for normal unlink. For module uninstall the # reload is done independently in openerp.modules.loading pooler.restart_pool(cr.dbname) return res
def generate(self, cr, uid, ids, context=None): """ Main wizard step. Make sure that all modules are up-to-date, then reinitialize all installed modules. Equivalent of running the server with '-d <database> --init all' The goal of this is to fill the records table. TODO: update module list and versions, then update all modules? """ # Truncate the records table if (openupgrade_tools.table_exists(cr, 'openupgrade_attribute') and openupgrade_tools.table_exists(cr, 'openupgrade_record')): cr.execute( 'TRUNCATE openupgrade_attribute, openupgrade_record;' ) # Need to get all modules in state 'installed' module_obj = self.pool.get('ir.module.module') module_ids = module_obj.search( cr, uid, [('state', 'in', ['to install', 'to upgrade'])]) if module_ids: cr.commit() _db, pool = pooler.restart_pool(cr.dbname, update_module=True) # Did we succeed above? module_ids = module_obj.search( cr, uid, [('state', 'in', ['to install', 'to upgrade'])]) if module_ids: modules = module_obj.read( cr, uid, module_ids, ['name'], context=context) raise except_orm( "Cannot reliably generate records", ("Cannot seem to install or upgrade modules " + ', '.join([x['name'] for x in modules]))) # Now reinitialize all installed modules module_ids = module_obj.search( cr, uid, [('state', '=', 'installed')]) module_obj.write( cr, uid, module_ids, {'state': 'to install'}) cr.commit() _db, pool = pooler.restart_pool(cr.dbname, update_module=True) self.write(cr, uid, ids, {'state': 'ready'}) # and we are done return True
def generate(self, cr, uid, ids, context=None): """ Main wizard step. Make sure that all modules are up-to-date, then reinitialize all installed modules. Equivalent of running the server with '-d <database> --init all' The goal of this is to fill the records table. TODO: update module list and versions, then update all modules? """ # Truncate the records table if (openupgrade_tools.table_exists(cr, 'openupgrade_attribute') and openupgrade_tools.table_exists(cr, 'openupgrade_record')): cr.execute('TRUNCATE openupgrade_attribute, openupgrade_record;') # Need to get all modules in state 'installed' module_obj = self.pool.get('ir.module.module') module_ids = module_obj.search( cr, uid, [('state', 'in', ['to install', 'to upgrade'])]) if module_ids: cr.commit() _db, pool = pooler.restart_pool(cr.dbname, update_module=True) # Did we succeed above? module_ids = module_obj.search( cr, uid, [('state', 'in', ['to install', 'to upgrade'])]) if module_ids: modules = module_obj.read(cr, uid, module_ids, ['name'], context=context) raise except_orm("Cannot reliably generate records", ("Cannot seem to install or upgrade modules " + ', '.join([x['name'] for x in modules]))) # Now reinitialize all installed modules module_ids = module_obj.search(cr, uid, [('state', '=', 'installed')]) module_obj.write(cr, uid, module_ids, {'state': 'to install'}) self.quirk_payment_term_lines(cr, uid, context=context) cr.commit() _db, pool = pooler.restart_pool(cr.dbname, update_module=True) self.write(cr, uid, ids, {'state': 'ready'}) # and we are done return True
def execute(self, cr, uid, ids, context=None): modules = self.pool.get('ir.module.module') to_install = list(self.modules_to_install( cr, uid, ids, context=context)) _logger.info('Selecting addons %s to install', to_install) modules.state_update( cr, uid, modules.search(cr, uid, [('name','in',to_install)]), 'to install', ['uninstalled'], context=context) cr.commit() new_db, self.pool = pooler.restart_pool(cr.dbname, update_module=True)
def execute(self, cr, uid, ids, context=None): modules = self.pool.get('ir.module.module') to_install = list(self.modules_to_install( cr, uid, ids, context=context)) _logger.info('Selecting addons %s to install', to_install) modules.state_update( cr, uid, modules.search(cr, uid, [('name','in',to_install)]), 'to install', ['uninstalled'], context=context) cr.commit() #TOFIX: after remove this statement, installation wizard is fail new_db, self.pool = pooler.restart_pool(cr.dbname, update_module=True)
def execute(self, cr, uid, ids, context=None): modules = self.pool.get('ir.module.module') to_install = list(self.modules_to_install( cr, uid, ids, context=context)) _logger.info('Selecting addons %s to install', to_install) modules.state_update( cr, uid, modules.search(cr, uid, [('name','in',to_install)]), 'to install', ['uninstalled'], context=context) cr.commit() openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) new_db, self.pool = pooler.restart_pool(cr.dbname, update_module=True)
def upgrade_module(self, cr, uid, ids, context=None): ir_module = self.pool.get('ir.module.module') # install/upgrade: double-check preconditions ids = ir_module.search(cr, uid, [('state', 'in', ['to upgrade', 'to install'])]) if ids: cr.execute("""SELECT d.name FROM ir_module_module m JOIN ir_module_module_dependency d ON (m.id = d.module_id) LEFT JOIN ir_module_module m2 ON (d.name = m2.name) WHERE m.id in %s and (m2.state IS NULL or m2.state IN %s)""", (tuple(ids), ('uninstalled',))) unmet_packages = [x[0] for x in cr.fetchall()] if unmet_packages: raise osv.except_osv(_('Unmet Dependency!'), _('Following modules are not installed or unknown: %s') % ('\n\n' + '\n'.join(unmet_packages))) ir_module.download(cr, uid, ids, context=context) cr.commit() # save before re-creating cursor below pooler.restart_pool(cr.dbname, update_module=True) return {'type': 'ir.actions.act_window_close'}
def install_all(self, cr, uid, ids, context=None): """ Main wizard step. Set all installable modules to install and actually install them. """ module_obj = self.pool.get('ir.module.module') module_ids = module_obj.search( cr, uid, [('state', 'not in', ['installed', 'uninstallable', 'unknown'])]) if module_ids: module_obj.write(cr, uid, module_ids, {'state': 'to install'}) cr.commit() _db, pool = pooler.restart_pool(cr.dbname, update_module=True) self.write(cr, uid, ids, {'state': 'ready'}) return True
def install_all(self, cr, uid, ids, context=None): """ Main wizard step. Set all installable modules to install and actually install them. """ module_obj = self.pool.get('ir.module.module') module_ids = module_obj.search( cr, uid, [ ('state', 'not in', ['installed', 'uninstallable', 'unknown'])]) if module_ids: module_obj.write( cr, uid, module_ids, {'state': 'to install'}) cr.commit() _db, pool = pooler.restart_pool(cr.dbname, update_module=True) self.write(cr, uid, ids, {'state': 'ready'}) return True
def _button_immediate_function(self, cr, uid, ids, function, context=None): function(cr, uid, ids, context=context) cr.commit() _, pool = pooler.restart_pool(cr.dbname, update_module=True) config = pool.get('res.config').next(cr, uid, [], context=context) or {} if config.get('type') not in ('ir.actions.act_window_close',): return config # reload the client; open the first available root menu menu_obj = self.pool.get('ir.ui.menu') menu_ids = menu_obj.search(cr, uid, [('parent_id', '=', False)], context=context) return { 'type': 'ir.actions.client', 'tag': 'reload', 'params': {'menu_id': menu_ids and menu_ids[0] or False} }
def install_all(self, cr, uid, ids, context=None): """ Main wizard step. Set all installable modules to install and actually install them. Exclude testing modules. """ user_input = self.browse(cr, uid, ids, context=context)[0] module_obj = self.pool.get('ir.module.module') module_domain = self._get_module_domain(user_input.no_localization) module_ids = module_obj.search(cr, uid, module_domain, context=context) if module_ids: module_obj.write(cr, uid, module_ids, {'state': 'to install'}, context=context) cr.commit() _db, pool = pooler.restart_pool(cr.dbname, update_module=True) self.write(cr, uid, ids, {'state': 'ready'}, context) return self.redisplay_wizard_screen(cr, uid, ids, context=context)
def purge(self, cr, uid, ids, context=None): """ Uninstall modules upon manual confirmation, then reload the database. """ module_pool = self.pool['ir.module.module'] lines = self.browse(cr, uid, ids, context=context) module_names = [line.name for line in lines if not line.purged] module_ids = module_pool.search( cr, uid, [('name', 'in', module_names)], context=context) if not module_ids: return True self.logger.info('Purging modules %s', ', '.join(module_names)) module_pool.write( cr, uid, module_ids, {'state': 'to remove'}, context=context) cr.commit() _db, _pool = pooler.restart_pool(cr.dbname, update_module=True) module_pool.unlink(cr, uid, module_ids, context=context) return self.write(cr, uid, ids, {'purged': True}, context=context)
def install_all(self, cr, uid, ids, context=None): """ Main wizard step. Set all installable modules to install and actually install them. Exclude testing modules. """ module_obj = self.pool.get('ir.module.module') module_ids = module_obj.search( cr, uid, [ ('state', 'not in', ['installed', 'uninstallable', 'unknown']), ('category_id.name', '!=', 'Tests'), ('name', 'not in', BLACKLIST_MODULES), ], context=context) if module_ids: module_obj.write( cr, uid, module_ids, {'state': 'to install'}, context=context) cr.commit() _db, pool = pooler.restart_pool(cr.dbname, update_module=True) self.write(cr, uid, ids, {'state': 'ready'}, context=context) return True
def __call__(self, serv, id, db_name, demo, lang, user_password='******'): cr = None try: serv.actions[id]['progress'] = 0 cr = sql_db.db_connect(db_name).cursor() openerp.modules.db.initialize(cr) # TODO this should be removed as it is done by pooler.restart_pool. tools.config['lang'] = lang cr.commit() cr.close() pool = pooler.restart_pool(db_name, demo, serv.actions[id], update_module=True)[1] cr = sql_db.db_connect(db_name).cursor() if lang: modobj = pool.get('ir.module.module') mids = modobj.search(cr, 1, [('state', '=', 'installed')]) modobj.update_translations(cr, 1, mids, lang) cr.execute('UPDATE res_users SET password=%s, context_lang=%s, active=True WHERE login=%s', ( user_password, lang, 'admin')) cr.execute('SELECT login, password, name ' \ ' FROM res_users ' \ ' ORDER BY login') serv.actions[id]['users'] = cr.dictfetchall() serv.actions[id]['clean'] = True cr.commit() cr.close() except Exception, e: serv.actions[id]['clean'] = False serv.actions[id]['exception'] = e import traceback e_str = StringIO() traceback.print_exc(file=e_str) traceback_str = e_str.getvalue() e_str.close() netsvc.Logger().notifyChannel('web-services', netsvc.LOG_ERROR, 'CREATE DATABASE\n%s' % (traceback_str)) serv.actions[id]['traceback'] = traceback_str if cr: cr.close()
def purge(self, cr, uid, ids, context=None): """ Uninstall modules upon manual confirmation, then reload the database. """ module_pool = self.pool['ir.module.module'] lines = self.browse(cr, uid, ids, context=context) module_names = [line.name for line in lines if not line.purged] module_ids = module_pool.search(cr, uid, [('name', 'in', module_names)], context=context) if not module_ids: return True self.logger.info('Purging modules %s', ', '.join(module_names)) module_pool.write(cr, uid, module_ids, {'state': 'to remove'}, context=context) cr.commit() _db, _pool = pooler.restart_pool(cr.dbname, update_module=True) module_pool.unlink(cr, uid, module_ids, context=context) return self.write(cr, uid, ids, {'purged': True}, context=context)
def load_modules(db, force_demo=False, status=None, update_module=False): # TODO status['progress'] reporting is broken: used twice (and reset each # time to zero) in load_module_graph, not fine-grained enough. # It should be a method exposed by the pool. initialize_sys_path() open_openerp_namespace() force = [] if force_demo: force.append('demo') cr = db.cursor() try: if not openerp.modules.db.is_initialized(cr): _logger.info("init db") openerp.modules.db.initialize(cr) tools.config["init"]["all"] = 1 tools.config['update']['all'] = 1 if not tools.config['without_demo']: tools.config["demo"]['all'] = 1 # This is a brand new pool, just created in pooler.get_db_and_pool() pool = pooler.get_pool(cr.dbname) if 'base' in tools.config['update'] or 'all' in tools.config['update']: cr.execute("update ir_module_module set state=%s where name=%s and state=%s", ('to upgrade', 'base', 'installed')) # STEP 1: LOAD BASE (must be done before module dependencies can be computed for later steps) graph = openerp.modules.graph.Graph() graph.add_module(cr, 'base', force) if not graph: _logger.critical('module base cannot be loaded! (hint: verify addons-path)') raise osv.osv.except_osv(_('Could not load base module'), _('module base cannot be loaded! (hint: verify addons-path)')) # processed_modules: for cleanup step after install # loaded_modules: to avoid double loading report = pool._assertion_report loaded_modules, processed_modules = load_module_graph(cr, graph, status, perform_checks=update_module, report=report) if tools.config['load_language']: for lang in tools.config['load_language'].split(','): tools.load_language(cr, lang) # STEP 2: Mark other modules to be loaded/updated if update_module: modobj = pool.get('ir.module.module') if ('base' in tools.config['init']) or ('base' in tools.config['update']): _logger.info('updating modules list') modobj.update_list(cr, SUPERUSER_ID) _check_module_names(cr, itertools.chain(tools.config['init'].keys(), tools.config['update'].keys())) mods = [k for k in tools.config['init'] if tools.config['init'][k]] if mods: ids = modobj.search(cr, SUPERUSER_ID, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)]) if ids: modobj.button_install(cr, SUPERUSER_ID, ids) mods = [k for k in tools.config['update'] if tools.config['update'][k]] if mods: ids = modobj.search(cr, SUPERUSER_ID, ['&', ('state', '=', 'installed'), ('name', 'in', mods)]) if ids: modobj.button_upgrade(cr, SUPERUSER_ID, ids) cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base')) # STEP 3: Load marked modules (skipping base which was done in STEP 1) # IMPORTANT: this is done in two parts, first loading all installed or # partially installed modules (i.e. installed/to upgrade), to # offer a consistent system to the second part: installing # newly selected modules. # We include the modules 'to remove' in the first step, because # they are part of the "currently installed" modules. They will # be dropped in STEP 6 later, before restarting the loading # process. states_to_load = ['installed', 'to upgrade', 'to remove'] processed = load_marked_modules(cr, graph, states_to_load, force, status, report, loaded_modules, update_module) processed_modules.extend(processed) if update_module: states_to_load = ['to install'] processed = load_marked_modules(cr, graph, states_to_load, force, status, report, loaded_modules, update_module) processed_modules.extend(processed) # load custom models cr.execute('select model from ir_model where state=%s', ('manual',)) for model in cr.dictfetchall(): pool.get('ir.model').instanciate(cr, SUPERUSER_ID, model['model'], {}) # STEP 4: Finish and cleanup installations if processed_modules: cr.execute("""select model,name from ir_model where id NOT IN (select distinct model_id from ir_model_access)""") for (model, name) in cr.fetchall(): model_obj = pool.get(model) if model_obj and not model_obj.is_transient(): _logger.warning('The model %s has no access rules, consider adding one. E.g. access_%s,access_%s,model_%s,,1,1,1,1', model, model.replace('.', '_'), model.replace('.', '_'), model.replace('.', '_')) # Temporary warning while we remove access rights on osv_memory objects, as they have # been replaced by owner-only access rights cr.execute("""select distinct mod.model, mod.name from ir_model_access acc, ir_model mod where acc.model_id = mod.id""") for (model, name) in cr.fetchall(): model_obj = pool.get(model) if model_obj and model_obj.is_transient(): _logger.warning('The transient model %s (%s) should not have explicit access rules!', model, name) cr.execute("SELECT model from ir_model") for (model,) in cr.fetchall(): obj = pool.get(model) if obj: obj._check_removed_columns(cr, log=True) else: _logger.warning("Model %s is declared but cannot be loaded! (Perhaps a module was partially removed or renamed)", model) # Cleanup orphan records pool.get('ir.model.data')._process_end(cr, SUPERUSER_ID, processed_modules) for kind in ('init', 'demo', 'update'): tools.config[kind] = {} cr.commit() # STEP 5: Cleanup menus # Remove menu items that are not referenced by any of other # (child) menu item, ir_values, or ir_model_data. # TODO: This code could be a method of ir_ui_menu. Remove menu without actions of children if update_module: while True: cr.execute('''delete from ir_ui_menu where (id not IN (select parent_id from ir_ui_menu where parent_id is not null)) and (id not IN (select res_id from ir_values where model='ir.ui.menu')) and (id not IN (select res_id from ir_model_data where model='ir.ui.menu'))''') cr.commit() if not cr.rowcount: break else: _logger.info('removed %d unused menus', cr.rowcount) # STEP 6: Uninstall modules to remove if update_module: # Remove records referenced from ir_model_data for modules to be # removed (and removed the references from ir_model_data). cr.execute("SELECT id FROM ir_module_module WHERE state=%s", ('to remove',)) mod_ids_to_remove = [x[0] for x in cr.fetchall()] if mod_ids_to_remove: pool.get('ir.module.module').module_uninstall(cr, SUPERUSER_ID, mod_ids_to_remove) # Recursive reload, should only happen once, because there should be no # modules to remove next time cr.commit() _logger.info('Reloading registry once more after uninstalling modules') return pooler.restart_pool(cr.dbname, force_demo, status, update_module) if report.failures: _logger.error('At least one test failed when loading the modules.') else: _logger.info('Modules loaded.') # STEP 7: call _register_hook on every model for model in pool.models.values(): model._register_hook(cr) finally: cr.close()
def load_modules(db, force_demo=False, status=None, update_module=False): # TODO status['progress'] reporting is broken: used twice (and reset each # time to zero) in load_module_graph, not fine-grained enough. # It should be a method exposed by the pool. initialize_sys_path() open_openerp_namespace() force = [] if force_demo: force.append('demo') cr = db.cursor() try: if not openerp.modules.db.is_initialized(cr): _logger.info("init db") openerp.modules.db.initialize(cr) tools.config["init"]["all"] = 1 tools.config['update']['all'] = 1 if not tools.config['without_demo']: tools.config["demo"]['all'] = 1 # This is a brand new pool, just created in pooler.get_db_and_pool() pool = pooler.get_pool(cr.dbname) if 'base' in tools.config['update'] or 'all' in tools.config['update']: cr.execute( "update ir_module_module set state=%s where name=%s and state=%s", ('to upgrade', 'base', 'installed')) # STEP 1: LOAD BASE (must be done before module dependencies can be computed for later steps) graph = openerp.modules.graph.Graph() graph.add_module(cr, 'base', force) if not graph: _logger.critical( 'module base cannot be loaded! (hint: verify addons-path)') raise osv.osv.except_osv( _('Could not load base module'), _('module base cannot be loaded! (hint: verify addons-path)')) # processed_modules: for cleanup step after install # loaded_modules: to avoid double loading report = pool._assertion_report loaded_modules, processed_modules = load_module_graph( cr, graph, status, perform_checks=update_module, report=report) if tools.config['load_language']: for lang in tools.config['load_language'].split(','): tools.load_language(cr, lang) # STEP 2: Mark other modules to be loaded/updated if update_module: modobj = pool.get('ir.module.module') if ('base' in tools.config['init']) or ('base' in tools.config['update']): _logger.info('updating modules list') modobj.update_list(cr, SUPERUSER_ID) _check_module_names( cr, itertools.chain(tools.config['init'].keys(), tools.config['update'].keys())) mods = [k for k in tools.config['init'] if tools.config['init'][k]] if mods: ids = modobj.search( cr, SUPERUSER_ID, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)]) if ids: modobj.button_install(cr, SUPERUSER_ID, ids) mods = [ k for k in tools.config['update'] if tools.config['update'][k] ] if mods: ids = modobj.search( cr, SUPERUSER_ID, ['&', ('state', '=', 'installed'), ('name', 'in', mods)]) if ids: modobj.button_upgrade(cr, SUPERUSER_ID, ids) cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base')) # STEP 3: Load marked modules (skipping base which was done in STEP 1) # IMPORTANT: this is done in two parts, first loading all installed or # partially installed modules (i.e. installed/to upgrade), to # offer a consistent system to the second part: installing # newly selected modules. # We include the modules 'to remove' in the first step, because # they are part of the "currently installed" modules. They will # be dropped in STEP 6 later, before restarting the loading # process. states_to_load = ['installed', 'to upgrade', 'to remove'] processed = load_marked_modules(cr, graph, states_to_load, force, status, report, loaded_modules, update_module) processed_modules.extend(processed) if update_module: states_to_load = ['to install'] processed = load_marked_modules(cr, graph, states_to_load, force, status, report, loaded_modules, update_module) processed_modules.extend(processed) # load custom models cr.execute('select model from ir_model where state=%s', ('manual', )) for model in cr.dictfetchall(): pool.get('ir.model').instanciate(cr, SUPERUSER_ID, model['model'], {}) # STEP 4: Finish and cleanup installations if processed_modules: cr.execute( """select model,name from ir_model where id NOT IN (select distinct model_id from ir_model_access)""" ) for (model, name) in cr.fetchall(): model_obj = pool.get(model) if model_obj and not model_obj.is_transient(): _logger.warning( 'The model %s has no access rules, consider adding one. E.g. access_%s,access_%s,model_%s,,1,1,1,1', model, model.replace('.', '_'), model.replace('.', '_'), model.replace('.', '_')) # Temporary warning while we remove access rights on osv_memory objects, as they have # been replaced by owner-only access rights cr.execute( """select distinct mod.model, mod.name from ir_model_access acc, ir_model mod where acc.model_id = mod.id""" ) for (model, name) in cr.fetchall(): model_obj = pool.get(model) if model_obj and model_obj.is_transient(): _logger.warning( 'The transient model %s (%s) should not have explicit access rules!', model, name) cr.execute("SELECT model from ir_model") for (model, ) in cr.fetchall(): obj = pool.get(model) if obj: obj._check_removed_columns(cr, log=True) else: _logger.warning( "Model %s is declared but cannot be loaded! (Perhaps a module was partially removed or renamed)", model) # Cleanup orphan records pool.get('ir.model.data')._process_end(cr, SUPERUSER_ID, processed_modules) for kind in ('init', 'demo', 'update'): tools.config[kind] = {} cr.commit() # STEP 5: Cleanup menus # Remove menu items that are not referenced by any of other # (child) menu item, ir_values, or ir_model_data. # TODO: This code could be a method of ir_ui_menu. Remove menu without actions of children if update_module: while True: cr.execute('''delete from ir_ui_menu where (id not IN (select parent_id from ir_ui_menu where parent_id is not null)) and (id not IN (select res_id from ir_values where model='ir.ui.menu')) and (id not IN (select res_id from ir_model_data where model='ir.ui.menu'))''' ) cr.commit() if not cr.rowcount: break else: _logger.info('removed %d unused menus', cr.rowcount) # STEP 6: Uninstall modules to remove if update_module: # Remove records referenced from ir_model_data for modules to be # removed (and removed the references from ir_model_data). cr.execute("SELECT id FROM ir_module_module WHERE state=%s", ('to remove', )) mod_ids_to_remove = [x[0] for x in cr.fetchall()] if mod_ids_to_remove: pool.get('ir.module.module').module_uninstall( cr, SUPERUSER_ID, mod_ids_to_remove) # Recursive reload, should only happen once, because there should be no # modules to remove next time cr.commit() _logger.info( 'Reloading registry once more after uninstalling modules') return pooler.restart_pool(cr.dbname, force_demo, status, update_module) if report.failures: _logger.error('At least one test failed when loading the modules.') else: _logger.info('Modules loaded.') # STEP 7: call _register_hook on every model for model in pool.models.values(): model._register_hook(cr) finally: cr.close()