diff --git a/bin/addons/base/ir/__init__.py b/bin/addons/base/ir/__init__.py index 343b50a6998..2f322d1aee1 100644 --- a/bin/addons/base/ir/__init__.py +++ b/bin/addons/base/ir/__init__.py @@ -34,6 +34,7 @@ import ir_exports import workflow import ir_rule import wizard +import ir_config_parameter # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/bin/addons/base/maintenance/__init__.py b/bin/addons/base/maintenance/__init__.py index 329c61301d9..a6adfa1302a 100644 --- a/bin/addons/base/maintenance/__init__.py +++ b/bin/addons/base/maintenance/__init__.py @@ -20,6 +20,7 @@ ############################################################################## import maintenance +import dbuuid # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/bin/addons/base/maintenance/maintenance.py b/bin/addons/base/maintenance/maintenance.py index 389d915512f..f4f97a2c5f5 100644 --- a/bin/addons/base/maintenance/maintenance.py +++ b/bin/addons/base/maintenance/maintenance.py @@ -20,60 +20,30 @@ ############################################################################## from osv import osv, fields -import pooler import time import netsvc -from tools.misc import debug from tools.misc import ustr from tools.translate import _ import tools.maintenance as tm -class maintenance_contract_module(osv.osv): - _name ="maintenance.contract.module" - _description = "maintenance contract modules" - _columns = { - 'name' : fields.char('Name', size=128, required=True), - 'version': fields.char('Version', size=64,), - } - -maintenance_contract_module() - class maintenance_contract(osv.osv): _name = "maintenance.contract" _description = "Maintenance Contract" def _get_valid_contracts(self, cr, uid): return [contract for contract in self.browse(cr, uid, self.search(cr, uid, [])) if contract.state == 'valid'] - + def status(self, cr, uid): - covered_modules, uncovered_modules = set(), set() - - status = 'none' - for contract in self._get_valid_contracts(cr, uid): - covered_modules.update([m.name for m in contract.module_ids]) - - if covered_modules: - modobj = self.pool.get('ir.module.module') - modids = modobj.search(cr, uid, [('state', '=', 'installed')]) - uncovered_modules = set(m.name for m in modobj.browse(cr, uid, modids)) - covered_modules - status = ['full', 'partial'][len(uncovered_modules) > 0] - + contracts = self._get_valid_contracts(cr, uid) return { - 'status': status, - 'uncovered_modules': list(uncovered_modules), + 'status': "full" if contracts else "none" , + 'uncovered_modules': list(), } def send(self, cr, uid, tb, explanations, remarks=None): - status = self.status(cr, uid) - if status['status'] != 'full': - raise osv.except_osv(_('Error'), _("Your can't submit bug reports due to uncovered modules: %s") % (', '.join(status['uncovered_modules']),)) - - dbmsg = _('This error occurs on database %s') % (cr.dbname,) if not remarks: - remarks = dbmsg - else: - remarks += '\n\n-----\n' + dbmsg + remarks = "" valid_contracts = self._get_valid_contracts(cr, uid) @@ -81,8 +51,10 @@ class maintenance_contract(osv.osv): rc = None try: for contract in valid_contracts: - rc = tm.remote_contract(contract.name, contract.password) + rc = tm.remote_contract(cr, uid, contract.name) + if rc.id: + contract_name = contract.name break rc = None @@ -90,34 +62,25 @@ class maintenance_contract(osv.osv): raise osv.except_osv(_('Error'), _('Unable to find a valid contract')) origin = 'client' - crm_case_id = rc.submit(rc.id, tb, explanations, remarks or '', origin) + dbuuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') + crm_case_id = rc.submit({ + 'contract_name': contract_name, + 'tb': tb, + 'explanations': explanations, + 'remarks': remarks, + 'origin': origin, + 'dbname': cr.dbname, + 'dbuuid': dbuuid}) except tm.RemoteContractException, rce: netsvc.Logger().notifyChannel('maintenance', netsvc.LOG_INFO, rce) except osv.except_osv: raise except: - pass + pass # don't want to throw exceptions in exception handler - cid = rc and rc.name or valid_contracts[0].name - try: - # as backup, put it also in another database... - import urllib - args = urllib.urlencode({ - 'contract_id': cid, - 'crm_case_id': crm_case_id or 0, - 'explanation': explanations, - 'remark': remarks or '', - 'tb': tb, - }) - uo = urllib.urlopen('http://www.openerp.com/scripts/maintenance.php', args) - submit_result = uo.read() - debug(submit_result) - uo.close() - except: - if not crm_case_id: - # TODO schedule a retry (ir.cron) - return False + if not crm_case_id: + return False return True def _valid_get(self, cr, uid, ids, field_name, arg, context=None): @@ -127,16 +90,11 @@ class maintenance_contract(osv.osv): return res _columns = { - 'name' : fields.char('Contract ID', size=256, required=True, readonly=True), - 'password' : fields.char('Password', size=64, invisible=True, required=True, readonly=True), + 'name' : fields.char('Contract ID', size=384, required=True, readonly=True), 'date_start' : fields.date('Starting Date', readonly=True), 'date_stop' : fields.date('Ending Date', readonly=True), - 'module_ids' : fields.many2many('maintenance.contract.module', 'maintenance_contract_module_rel', 'contract_id', 'module_id', 'Covered Modules', readonly=True), 'state' : fields.function(_valid_get, method=True, string="State", type="selection", selection=[('valid', 'Valid'),('unvalid', 'Unvalid')], readonly=True), - 'kind' : fields.selection([('full', 'Full'),('partial', 'Partial')], 'Kind', required=True, readonly=True), - } - _defaults = { - 'password' : lambda obj,cr,uid,context={} : '', + 'kind' : fields.char('Kind', size=64, required=True, readonly=True), } _sql_constraints = [ ('uniq_name', 'unique(name)', "Your maintenance contract is already subscribed in the system !") @@ -149,8 +107,7 @@ class maintenance_contract_wizard(osv.osv_memory): _name = 'maintenance.contract.wizard' _columns = { - 'name' : fields.char('Contract ID', size=256, required=True ), - 'password' : fields.char('Password', size=64, required=True), + 'name' : fields.char('Contract ID', size=384, required=True ), 'state' : fields.selection([('draft', 'Draft'),('validated', 'Validated'),('unvalidated', 'Unvalidated')], 'States'), } @@ -159,46 +116,31 @@ class maintenance_contract_wizard(osv.osv_memory): } def action_validate(self, cr, uid, ids, context=None): + raise Exception("hahaha, this is a dirty exception to make you fail") if not ids: return False - - module_proxy = self.pool.get('ir.module.module') - module_ids = module_proxy.search(cr, uid, [('state', '=', 'installed')]) - modules = module_proxy.read(cr, uid, module_ids, ['name', 'installed_version']) - - contract = self.read(cr, uid, ids, ['name', 'password'])[0] + contract = self.read(cr, uid, ids, ['name'])[0] try: - contract_info = tm.remote_contract(contract['name'], contract['password'], modules) + contract_info = tm.remote_contract(cr, uid, contract['name']) except tm.RemoteContractException, rce: raise osv.except_osv(_('Error'), ustr(rce)) - is_ok = contract_info['status'] in ('partial', 'full') - if is_ok: - module_ids = [] - if contract_info['modules_with_contract']: - for name, version in contract_info['modules_with_contract']: - contract_module = self.pool.get('maintenance.contract.module') - res = contract_module.search(cr, uid, [('name', '=', name),('version', '=', version)]) - if not res: - id = contract_module.create(cr, uid, { 'name' : name, 'version' : version } ) - else: - id = res[0] - module_ids.append(id) + if contract_info['status'] == "valid": self.pool.get('maintenance.contract').create( cr, uid, { 'name' : contract['name'], - 'password' : contract['password'], 'date_start' : contract_info['date_from'], 'date_stop' : contract_info['date_to'], - 'kind' : contract_info['status'], - 'module_ids' : [(6,0,module_ids)], + 'kind' : contract_info['kind'], } ) - return self.write(cr, uid, ids, {'state' : ('unvalidated', 'validated')[is_ok] }, context=context) + return self.write(cr, uid, ids, + {'state' : ['validated' if contract_info['status'] == "valid" else 'unvalidated'] }, + context=context) maintenance_contract_wizard() diff --git a/bin/addons/base/maintenance/maintenance_view.xml b/bin/addons/base/maintenance/maintenance_view.xml index 836344a52df..fac95d705a3 100644 --- a/bin/addons/base/maintenance/maintenance_view.xml +++ b/bin/addons/base/maintenance/maintenance_view.xml @@ -27,13 +27,6 @@ - - - - - - - @@ -94,7 +87,6 @@ - diff --git a/bin/addons/base/security/ir.model.access.csv b/bin/addons/base/security/ir.model.access.csv index 62eb8ffe2b1..fea55ecc0bd 100644 --- a/bin/addons/base/security/ir.model.access.csv +++ b/bin/addons/base/security/ir.model.access.csv @@ -113,7 +113,6 @@ "access_res_bank_group_partner_manager","res_bank_group_partner_manager","model_res_bank","group_partner_manager",1,1,1,1 "access_res_bank_user","res_bank user","model_res_bank","group_user",1,0,0,0 "access_maintenance_group_user","maintenance_contract group_user","model_maintenance_contract","group_system",1,1,1,1 -"access_maintenance_contract_module","maintenance.contract.module","model_maintenance_contract_module","group_system",1,1,1,1 "access_multi_company_default user","multi_company_default all","model_multi_company_default",,1,0,0,0 "access_multi_company_default manager","multi_company_default Manager","model_multi_company_default","group_erp_manager",1,1,1,1 "access_ir_filter all","ir_filters all","model_ir_filters",,1,0,0,0 @@ -123,3 +122,4 @@ "access_res_widget","res.widget","model_res_widget","group_erp_manager",1,1,1,1 "access_res_widget_user","res.widget.user","model_res_widget",,1,0,0,0 "access_res_log_all","res.log","model_res_log",,1,1,1,1 +"access_ir_config_parameter","ir_config_parameter","model_ir_config_parameter",,1,0,0,0 diff --git a/bin/tools/config.py b/bin/tools/config.py index 2964870d427..3e776d83135 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -31,8 +31,8 @@ def check_ssl(): try: from OpenSSL import SSL import socket - - return hasattr(socket, 'ssl') + + return hasattr(socket, 'ssl') and hasattr(SSL, "Connection") except: return False @@ -91,6 +91,10 @@ class configmanager(object): 'static_http_url_prefix': None, 'secure_cert_file': 'server.cert', 'secure_pkey_file': 'server.pkey', + 'maintenance_server': 'http://tiny.my.odoo.com:8069/xmlrpc/', + 'maintenance_db': 'tiny_belgium', + 'maintenance_login': 'maintenance', + 'maintenance_password': 'maintenance', } self.misc = {} @@ -224,7 +228,7 @@ class configmanager(object): parser.add_option_group(security) def parse_config(self): - (opt, args) = self.parser.parse_args() + opt = self.parser.parse_args()[0] def die(cond, msg): if cond: @@ -317,7 +321,7 @@ class configmanager(object): # If an explicit TZ was provided in the config, make sure it is known try: import pytz - tz = pytz.timezone(self.options['timezone']) + pytz.timezone(self.options['timezone']) except pytz.UnknownTimeZoneError: die(True, "The specified timezone (%s) is invalid" % self.options['timezone']) except: @@ -374,7 +378,10 @@ class configmanager(object): fp.close() if is_win32: - import _winreg + try: + import _winreg + except ImportError: + _winreg = None x=_winreg.ConnectRegistry(None,_winreg.HKEY_LOCAL_MACHINE) y = _winreg.OpenKey(x, r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", 0,_winreg.KEY_ALL_ACCESS) _winreg.SetValueEx(y,"PGPASSFILE", 0, _winreg.REG_EXPAND_SZ, filename ) @@ -436,7 +443,7 @@ class configmanager(object): p = ConfigParser.ConfigParser() loglevelnames = dict(zip(self._LOGLEVELS.values(), self._LOGLEVELS.keys())) p.add_section('options') - for opt in self.options.keys(): + for opt in sorted(self.options.keys()): if opt in ('version', 'language', 'translate_out', 'translate_in', 'init', 'update'): continue if opt in ('log_level', 'assert_exit_level'): @@ -444,8 +451,8 @@ class configmanager(object): else: p.set('options', opt, self.options[opt]) - for sec in self.misc.keys(): - for opt in self.misc[sec].keys(): + for sec in sorted(self.misc.keys()): + for opt in sorted(self.misc[sec].keys()): p.set(sec,opt,self.misc[sec][opt]) # try to create the directories and write the file diff --git a/bin/tools/maintenance.py b/bin/tools/maintenance.py index 83cf5e3b8bd..6789ac5f8f8 100644 --- a/bin/tools/maintenance.py +++ b/bin/tools/maintenance.py @@ -20,50 +20,77 @@ ############################################################################## import xmlrpclib +import config +import logging +import pooler -class RemoteContractException(Exception): pass +_logger = logging.getLogger(__name__) -class remote_contract(object): - def __init__(self, contract_id, contract_password, modules=None): - self.__server = 'http://tiny.my.odoo.com:8069/xmlrpc/' - self.__db = "tiny_belgium" - self.__password = "maintenance" - self.__login = "maintenance" +class RemoteConnectionException(Exception): + pass + +class RemoteConnection: + + def __init__(self, server, db, login, password): + self._server = server.strip() + if not self._server.endswith("/"): + self._server += "/" + self._db = db + self._login = login + self._password = password - rpc = xmlrpclib.ServerProxy(self.__server + 'common') + rpc = xmlrpclib.ServerProxy(self._server + "xmlrpc/common") try: - self.__userid = rpc.login(self.__db, self.__login, self.__password) + self._userid = rpc.login(self._db, self._login, self._password) except: - raise RemoteContractException("Unable to contact the migration server") + raise RemoteConnectionException("Unable to contact the remote server") - if not self.__userid: - raise RemoteContractException("Unable to contact the migration server") - - self.__rpc = xmlrpclib.ServerProxy(self.__server + 'object') + if not self._userid: + raise RemoteConnectionException("Unable to contact the remote server") - - contract = { - 'name': contract_id, - 'password': contract_password, - } - if modules is None: - modules = [] - - info = self.check_contract(modules, contract) - for n in info: - setattr(self, n, info[n]) - - self.name = contract_id - self.contract_id = self.name - self.password = contract_password + self._rpc = xmlrpclib.ServerProxy(self._server + "xmlrpc/object") + def get_remote_object(self, object): + return RemoteObject(self, object) + +class RemoteObject(object): + + def __init__(self, connection, object): + self._c = connection + self._object = object + def __getattr__(self, fun): def remote_call(*args, **kwargs): - return self.__rpc.execute(self.__db, self.__userid, self.__password, 'maintenance.maintenance', fun, *args, **kwargs) + return self._c._rpc.execute(self._c._db, self._c._userid, + self._c._password, self._object, fun, *args, **kwargs) return remote_call - + def __getitem__(self, item): return getattr(self, item) + +class RemoteContractException(Exception): pass + +def remote_contract(cr, uid, contract_id): + pool = pooler.get_pool(cr.dbname) + dbuuid = pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') + + try: + ro = RemoteConnection(config.config.get("maintenance_server"), config.config.get("maintenance_db"), + config.config.get("maintenance_login"), config.config.get("maintenance_password") + ).get_remote_object('maintenance.maintenance') + except: + _logger.exception("Exception") + raise RemoteContractException("Unable to contact the migration server") + + info = ro.check_contract({ + "contract_name": contract_id, + "dbuuid": dbuuid, + "dbname": cr.dbname}) + for n in info: + setattr(ro, n, info[n]) + + return ro + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: