From fd65d126806f5a3b31cdb3f21e10dfb054aa8694 Mon Sep 17 00:00:00 2001 From: "nicolas.bessi@camptocamp.com" <> Date: Fri, 22 Oct 2010 15:34:02 +0200 Subject: [PATCH 01/60] [FIX] RC2 fix of image embeeding, possibilit to have tmp file name in same milisecond, imporvement of multi header support when cusomizing report, fix of translation getter retunr scr if no translation available bzr revid: nicolas.bessi@camptocamp.com-20101022133402-bme1hmy4mtd7maa8 --- addons/report_webkit/report_helper.py | 2 +- addons/report_webkit/webkit_report.py | 34 ++++++++++++++++----------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/addons/report_webkit/report_helper.py b/addons/report_webkit/report_helper.py index 80896fa4ba2..db0c1c372fc 100644 --- a/addons/report_webkit/report_helper.py +++ b/addons/report_webkit/report_helper.py @@ -51,7 +51,7 @@ class WebKitHelper(object): height = 'width="%spx"'%(height) else : height = ' ' - toreturn = ''%( + toreturn = ''%( width, height, type, diff --git a/addons/report_webkit/webkit_report.py b/addons/report_webkit/webkit_report.py index 3dd768128fb..5bdea865cde 100644 --- a/addons/report_webkit/webkit_report.py +++ b/addons/report_webkit/webkit_report.py @@ -84,8 +84,10 @@ class WebKitParser(report_sxw): _('path to Wkhtmltopdf is not absolute'), 'for path %s'%(path) ) - def generate_pdf(self, comm_path, report_xml, header, footer, html_list): + def generate_pdf(self, comm_path, report_xml, header, footer, html_list, webkit_header=False): """Call webkit in order to generate pdf""" + if not webkit_header: + webkit_header = report_xml.webkit_header tmp_dir = tempfile.gettempdir() out = report_xml.name+str(time.time())+'.pdf' out = os.path.join(tmp_dir, out.replace(' ','')) @@ -120,20 +122,22 @@ class WebKitParser(report_sxw): file_to_del.append(foot_file.name) command.append("--footer-html '%s'"%(foot_file.name)) - if report_xml.webkit_header.margin_top : - command.append('--margin-top %s'%(report_xml.webkit_header.margin_top)) - if report_xml.webkit_header.margin_bottom : - command.append('--margin-bottom %s'%(report_xml.webkit_header.margin_bottom)) - if report_xml.webkit_header.margin_left : - command.append('--margin-left %s'%(report_xml.webkit_header.margin_left)) - if report_xml.webkit_header.margin_right : - command.append('--margin-right %s'%(report_xml.webkit_header.margin_right)) - if report_xml.webkit_header.orientation : - command.append("--orientation '%s'"%(report_xml.webkit_header.orientation)) - if report_xml.webkit_header.format : - command.append(" --page-size '%s'"%(report_xml.webkit_header.format)) + if webkit_header.margin_top : + command.append('--margin-top %s'%(webkit_header.margin_top)) + if webkit_header.margin_bottom : + command.append('--margin-bottom %s'%(webkit_header.margin_bottom)) + if webkit_header.margin_left : + command.append('--margin-left %s'%(webkit_header.margin_left)) + if webkit_header.margin_right : + command.append('--margin-right %s'%(webkit_header.margin_right)) + if webkit_header.orientation : + command.append("--orientation '%s'"%(webkit_header.orientation)) + if webkit_header.format : + command.append(" --page-size '%s'"%(webkit_header.format)) + count = 0 for html in html_list : - html_file = file(os.path.join(tmp_dir, str(time.time()) + '.body.html'), 'w') + html_file = file(os.path.join(tmp_dir, str(time.time()) + str(count) +'.body.html'), 'w') + count += 1 html_file.write(html) html_file.close() file_to_del.append(html_file.name) @@ -168,6 +172,8 @@ class WebKitParser(report_sxw): """Translate String.""" ir_translation = self.pool.get('ir.translation') res = ir_translation._get_source(self.parser_instance.cr, self.parser_instance.uid, self.name, 'report', self.localcontext.get('lang', 'en_US'), src) + if not res : + return src return res def formatLang(self, value, digits=None, date=False, date_time=False, grouping=True, monetary=False): From cdaef22f14104878cf21aba391c444cfe83e1abb Mon Sep 17 00:00:00 2001 From: "nicolas.bessi@camptocamp.com" <> Date: Mon, 15 Nov 2010 11:17:59 +0100 Subject: [PATCH 02/60] [IMP] better debug-error message$ bzr revid: nicolas.bessi@camptocamp.com-20101115101759-vt2b1j03c9upbubn --- addons/report_webkit/webkit_report.py | 82 +++++++++++++++------------ 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/addons/report_webkit/webkit_report.py b/addons/report_webkit/webkit_report.py index cce410a9dc6..e05c8e5c437 100644 --- a/addons/report_webkit/webkit_report.py +++ b/addons/report_webkit/webkit_report.py @@ -35,7 +35,7 @@ import report import tempfile import time from mako.template import Template - +from mako import exceptions import netsvc import pooler from report_helper import WebKitHelper @@ -278,45 +278,57 @@ class WebKitParser(report_sxw): #default_filters=['unicode', 'entity'] can be used to set global filter body_mako_tpl = Template(template ,input_encoding='utf-8') helper = WebKitHelper(cursor, uid, report_xml.id, context) - html = body_mako_tpl.render( helper=helper, - css=css, - _=self.translate_call, - **self.parser_instance.localcontext - ) + try : + html = body_mako_tpl.render( helper=helper, + css=css, + _=self.translate_call, + **self.parser_instance.localcontext + ) + except : + raise Exception(exceptions.html_error_template().render()) head_mako_tpl = Template(header, input_encoding='utf-8') - head = head_mako_tpl.render( - company=company, - time=time, - helper=helper, - css=css, - formatLang=self.formatLang, - setLang=self.setLang, - _=self.translate_call, - _debug=False - ) + try : + head = head_mako_tpl.render( + company=company, + time=time, + helper=helper, + css=css, + formatLang=self.formatLang, + setLang=self.setLang, + _=self.translate_call, + _debug=False + ) + except : + raise Exception(exceptions.html_error_template().render()) foot = False if footer : foot_mako_tpl = Template(footer ,input_encoding='utf-8') - foot = foot_mako_tpl.render( - company=company, - time=time, - helper=helper, - css=css, - formatLang=self.formatLang, - setLang=self.setLang, - _=self.translate_call, - ) + try : + foot = foot_mako_tpl.render( + company=company, + time=time, + helper=helper, + css=css, + formatLang=self.formatLang, + setLang=self.setLang, + _=self.translate_call, + ) + except: + raise Exception(exceptions.html_error_template().render()) if report_xml.webkit_debug : - deb = head_mako_tpl.render( - company=company, - time=time, - helper=helper, - css=css, - _debug=html, - formatLang=self.formatLang, - setLang=self.setLang, - _=self.translate_call, - ) + try : + deb = head_mako_tpl.render( + company=company, + time=time, + helper=helper, + css=css, + _debug=html, + formatLang=self.formatLang, + setLang=self.setLang, + _=self.translate_call, + ) + except : + raise Exception(exceptions.html_error_template().render()) return (deb, 'html') bin = self.get_lib(cursor, uid, company.id) pdf = self.generate_pdf(bin, report_xml, head, foot, [html]) From b8551a5fcca83d88f798e480290fa7b1c9f17280 Mon Sep 17 00:00:00 2001 From: nvi-openerp Date: Wed, 17 Nov 2010 18:17:54 +0100 Subject: [PATCH 03/60] [IMP] wip bzr revid: nicolas.vanhoren@openerp.com-20101117171754-ay58hnzhsq56iq3s --- bin/addons/base/ir/__init__.py | 1 + bin/addons/base/maintenance/__init__.py | 1 + bin/addons/base/maintenance/maintenance.py | 120 +++++------------- .../base/maintenance/maintenance_view.xml | 8 -- bin/addons/base/security/ir.model.access.csv | 2 +- bin/tools/config.py | 23 ++-- bin/tools/maintenance.py | 89 ++++++++----- 7 files changed, 107 insertions(+), 137 deletions(-) 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: From d5debf686f752cbb417a3150eba48aaf10baaf1a Mon Sep 17 00:00:00 2001 From: nvi-openerp Date: Thu, 18 Nov 2010 10:34:12 +0100 Subject: [PATCH 04/60] [IMP] wip bzr revid: nicolas.vanhoren@openerp.com-20101118093412-czjcmcqupngfqjnt --- .bzrignore | 3 + bin/addons/base/ir/ir_config_parameter.py | 81 ++++++++++++++++++++++ bin/addons/base/maintenance/dbuuid.py | 45 ++++++++++++ bin/addons/base/maintenance/maintenance.py | 12 ++-- bin/tools/maintenance.py | 2 +- 5 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 bin/addons/base/ir/ir_config_parameter.py create mode 100644 bin/addons/base/maintenance/dbuuid.py diff --git a/.bzrignore b/.bzrignore index 5581ee20f94..f67a6e2c6b6 100644 --- a/.bzrignore +++ b/.bzrignore @@ -18,3 +18,6 @@ bin/python2.6 build/ bin/yolk bin/pil*.py +.project +.pydevproject +.settings diff --git a/bin/addons/base/ir/ir_config_parameter.py b/bin/addons/base/ir/ir_config_parameter.py new file mode 100644 index 00000000000..a7502490ea4 --- /dev/null +++ b/bin/addons/base/ir/ir_config_parameter.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +""" +A module to store some configuration parameters relative to a whole database. +""" + +from osv import osv,fields + +class ir_config_parameter(osv.osv): + """ An osv to old configuration parameters for a given database. + + To be short, it's just a global dictionnary of strings stored in a table. """ + + _name = 'ir.config_parameter' + + _columns = { + # The key of the configuration parameter. + 'key': fields.char('Key', size=256, required=True, select=1), + # The value of the configuration parameter. + 'value': fields.text('Value', required=True), + } + + _sql_constraints = [ + ('key_uniq', 'unique (key)', 'Key must be unique.') + ] + + def get_param(self, cr, uid, key, context=None): + """ Get the value of a parameter. + + @param key: The key of the parameter. + @type key: string + @return: The value of the parameter, False if it does not exist. + @rtype: string + """ + ids = self.search(cr, uid, [('key','=',key)], context=context) + if not ids: + return False + param = self.browse(cr, uid, ids[0], context=context) + value = param.value + return value + + def set_param(self, cr, uid, key, value, context=None): + """ Set the value of a parameter. + + @param key: The key of the parameter. + @type key: string + @param value: The value of the parameter. + @type value: string + @return: Return the previous value of the parameter of False if it did + not existed. + @rtype: string + """ + ids = self.search(cr, uid, [('key','=',key)], context=context) + if ids: + param = self.browse(cr, uid, ids[0], context=context) + old = param.value + self.write(cr, uid, ids, {'value': value}, context=context) + return old + else: + self.create(cr, uid, {'key': key, 'value': value}, context=context) + return False + +ir_config_parameter() diff --git a/bin/addons/base/maintenance/dbuuid.py b/bin/addons/base/maintenance/dbuuid.py new file mode 100644 index 00000000000..1cbb10fab1b --- /dev/null +++ b/bin/addons/base/maintenance/dbuuid.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +""" +A module to handle a database UUID. That uuid will be stored in the osv +"ir.config_parameter" with key "database.uuid". +""" + +from osv import osv +import uuid + +class uuid_saver(osv.osv_memory): + """ An empty osv memory to init the uuid of the database the first it is + used. """ + + _name = 'maintenance.database_uuid_saver' + + def init(self, cr): + """ Checks that the database uuid was already created and create it if + it not the case. """ + params = self.pool.get('ir.config_parameter') + uniq = params.get_param(cr, 1, 'database.uuid') + if not uniq: + uniq = str(uuid.uuid1()) + params.set_param(cr, 1, 'database.uuid', uniq) + +uuid_saver() + diff --git a/bin/addons/base/maintenance/maintenance.py b/bin/addons/base/maintenance/maintenance.py index f4f97a2c5f5..a6e10c71e3c 100644 --- a/bin/addons/base/maintenance/maintenance.py +++ b/bin/addons/base/maintenance/maintenance.py @@ -22,11 +22,13 @@ from osv import osv, fields import time import netsvc - from tools.misc import ustr from tools.translate import _ import tools.maintenance as tm +_nlogger = netsvc.Logger() +_CHAN = __name__.split()[-1] + class maintenance_contract(osv.osv): _name = "maintenance.contract" _description = "Maintenance Contract" @@ -35,6 +37,7 @@ class maintenance_contract(osv.osv): return [contract for contract in self.browse(cr, uid, self.search(cr, uid, [])) if contract.state == 'valid'] def status(self, cr, uid): + """ Method called by the client to check availability of maintenance contract. """ contracts = self._get_valid_contracts(cr, uid) return { 'status': "full" if contracts else "none" , @@ -42,6 +45,7 @@ class maintenance_contract(osv.osv): } def send(self, cr, uid, tb, explanations, remarks=None): + """ Method called by the client to send a problem to the maintenance server. """ if not remarks: remarks = "" @@ -63,7 +67,7 @@ class maintenance_contract(osv.osv): origin = 'client' dbuuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') - crm_case_id = rc.submit({ + crm_case_id = rc.submit_6({ 'contract_name': contract_name, 'tb': tb, 'explanations': explanations, @@ -73,11 +77,11 @@ class maintenance_contract(osv.osv): 'dbuuid': dbuuid}) except tm.RemoteContractException, rce: - netsvc.Logger().notifyChannel('maintenance', netsvc.LOG_INFO, rce) + _nlogger.notifyChannel(_CHAN, netsvc.LOG_INFO, rce) except osv.except_osv: raise except: - pass # don't want to throw exceptions in exception handler + pass # we don't want to throw exceptions in an exception handler if not crm_case_id: return False diff --git a/bin/tools/maintenance.py b/bin/tools/maintenance.py index 6789ac5f8f8..f0488b957ac 100644 --- a/bin/tools/maintenance.py +++ b/bin/tools/maintenance.py @@ -82,7 +82,7 @@ def remote_contract(cr, uid, contract_id): _logger.exception("Exception") raise RemoteContractException("Unable to contact the migration server") - info = ro.check_contract({ + info = ro.check_contract_6({ "contract_name": contract_id, "dbuuid": dbuuid, "dbname": cr.dbname}) From 469f0c3f5b80246aaa424779d5f5ac8136200e41 Mon Sep 17 00:00:00 2001 From: nvi-openerp Date: Thu, 18 Nov 2010 14:24:31 +0100 Subject: [PATCH 05/60] [IMP] wip bzr revid: nicolas.vanhoren@openerp.com-20101118132431-275gq1i1vjg52yoy --- bin/addons/base/maintenance/maintenance.py | 1 + bin/tools/maintenance.py | 3 -- bin/tools/ping.py | 40 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 bin/tools/ping.py diff --git a/bin/addons/base/maintenance/maintenance.py b/bin/addons/base/maintenance/maintenance.py index a6e10c71e3c..b8e8e4dd6c7 100644 --- a/bin/addons/base/maintenance/maintenance.py +++ b/bin/addons/base/maintenance/maintenance.py @@ -31,6 +31,7 @@ _CHAN = __name__.split()[-1] class maintenance_contract(osv.osv): _name = "maintenance.contract" + _description = "Maintenance Contract" def _get_valid_contracts(self, cr, uid): diff --git a/bin/tools/maintenance.py b/bin/tools/maintenance.py index f0488b957ac..f8f8e9f11d3 100644 --- a/bin/tools/maintenance.py +++ b/bin/tools/maintenance.py @@ -21,10 +21,8 @@ import xmlrpclib import config -import logging import pooler -_logger = logging.getLogger(__name__) class RemoteConnectionException(Exception): pass @@ -79,7 +77,6 @@ def remote_contract(cr, uid, contract_id): 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_6({ diff --git a/bin/tools/ping.py b/bin/tools/ping.py new file mode 100644 index 00000000000..34efaad309a --- /dev/null +++ b/bin/tools/ping.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import urllib +import pooler + +def send_ping(cr, uid): + pooler.get_pool(cr.dbname) + + args = urllib.urlencode({ + 'arg0': "coucou", + }) + uo = urllib.urlopen('http://localhost/phonehome/phonehome.php', args) + try: + submit_result = uo.read() + finally: + uo.close() + + return "" + + + From 5b2a35641cbac9c984df77d54c34fef0ae16e41b Mon Sep 17 00:00:00 2001 From: nvi-openerp Date: Thu, 18 Nov 2010 14:42:56 +0100 Subject: [PATCH 06/60] [IMP] wip bzr revid: nicolas.vanhoren@openerp.com-20101118134256-p0tlk3kbpw1njqu8 --- bin/addons/base/maintenance/maintenance.py | 4 ++++ bin/tools/config.py | 6 ++++++ bin/tools/ping.py | 7 ++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/bin/addons/base/maintenance/maintenance.py b/bin/addons/base/maintenance/maintenance.py index b8e8e4dd6c7..0ddf8486e9f 100644 --- a/bin/addons/base/maintenance/maintenance.py +++ b/bin/addons/base/maintenance/maintenance.py @@ -25,6 +25,7 @@ import netsvc from tools.misc import ustr from tools.translate import _ import tools.maintenance as tm +import tools.ping _nlogger = netsvc.Logger() _CHAN = __name__.split()[-1] @@ -93,6 +94,9 @@ class maintenance_contract(osv.osv): for contract in self.browse(cr, uid, ids, context=context): res[contract.id] = ("unvalid", "valid")[contract.date_stop >= time.strftime('%Y-%m-%d')] return res + + def send_ping(self, cr, uid, context={}): + tools.ping.send_ping(cr, uid) _columns = { 'name' : fields.char('Contract ID', size=384, required=True, readonly=True), diff --git a/bin/tools/config.py b/bin/tools/config.py index 3e776d83135..50a127bc1b1 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -95,7 +95,11 @@ class configmanager(object): 'maintenance_db': 'tiny_belgium', 'maintenance_login': 'maintenance', 'maintenance_password': 'maintenance', + 'ping_url': 'http://tiny.my.odoo.com:8069/phonehome.php', } + + self.blacklist_for_save = set(['maintenance_server', 'maintenance_db', + 'maintenance_login', 'maintenance_password', "ping_url"]) self.misc = {} self.config_file = fname @@ -446,6 +450,8 @@ class configmanager(object): for opt in sorted(self.options.keys()): if opt in ('version', 'language', 'translate_out', 'translate_in', 'init', 'update'): continue + if opt in self.blacklist_for_save: + continue if opt in ('log_level', 'assert_exit_level'): p.set('options', opt, loglevelnames.get(self.options[opt], self.options[opt])) else: diff --git a/bin/tools/ping.py b/bin/tools/ping.py index 34efaad309a..dd45456fd02 100644 --- a/bin/tools/ping.py +++ b/bin/tools/ping.py @@ -21,20 +21,21 @@ import urllib import pooler +import config def send_ping(cr, uid): - pooler.get_pool(cr.dbname) + pool = pooler.get_pool(cr.dbname) args = urllib.urlencode({ 'arg0': "coucou", }) - uo = urllib.urlopen('http://localhost/phonehome/phonehome.php', args) + uo = urllib.urlopen(config.config.get("ping_url"), args) try: submit_result = uo.read() finally: uo.close() - return "" + return submit_result From 16e9bde2c82cd7d6b75748689589fb649f3dc837 Mon Sep 17 00:00:00 2001 From: nvi-openerp Date: Fri, 19 Nov 2010 09:15:50 +0100 Subject: [PATCH 07/60] [IMP] wip bzr revid: nicolas.vanhoren@openerp.com-20101119081550-0ftgvc1vurkumejl --- bin/addons/base/__openerp__.py | 1 + bin/addons/base/maintenance/maintenance.py | 101 ++++++++++-------- .../base/maintenance/maintenance_data.xml | 19 ++++ .../base/maintenance/maintenance_security.xml | 6 -- .../base/maintenance/maintenance_view.xml | 77 ++++--------- bin/tools/ping.py | 23 +++- 6 files changed, 113 insertions(+), 114 deletions(-) create mode 100644 bin/addons/base/maintenance/maintenance_data.xml delete mode 100644 bin/addons/base/maintenance/maintenance_security.xml diff --git a/bin/addons/base/__openerp__.py b/bin/addons/base/__openerp__.py index 492c397754d..73b428d805c 100644 --- a/bin/addons/base/__openerp__.py +++ b/bin/addons/base/__openerp__.py @@ -76,6 +76,7 @@ 'security/ir.model.access.csv', 'res/res_widget_view.xml', 'res/res_widget_data.xml', + 'maintenance/maintenance_data.xml', ], 'demo_xml': [ 'base_demo.xml', diff --git a/bin/addons/base/maintenance/maintenance.py b/bin/addons/base/maintenance/maintenance.py index 0ddf8486e9f..a109dea8021 100644 --- a/bin/addons/base/maintenance/maintenance.py +++ b/bin/addons/base/maintenance/maintenance.py @@ -26,6 +26,7 @@ from tools.misc import ustr from tools.translate import _ import tools.maintenance as tm import tools.ping +import datetime _nlogger = netsvc.Logger() _CHAN = __name__.split()[-1] @@ -95,63 +96,69 @@ class maintenance_contract(osv.osv): res[contract.id] = ("unvalid", "valid")[contract.date_stop >= time.strftime('%Y-%m-%d')] return res - def send_ping(self, cr, uid, context={}): - tools.ping.send_ping(cr, uid) + def check_validity(self, cr, uid, ids, context={}): + contract_id = ids[0] + contract = self.browse(cr, uid, contract_id) + valid = contract.state == "valid" + + self.send_ping(cr, uid, ids, cron_mode=False, context=context) + + contract = self.browse(cr, uid, contract_id) + valid2 = contract.state == "valid" + if not valid and not valid2: + raise osv.except_osv("Contract validation error", + "Please check your maintenance contract name and validity.") + + def send_ping(self, cr, uid, ids, cron_mode=True, context={}): + try: + result = tools.ping.send_ping(cr, uid) + except: + if cron_mode: + pass # if ping fails that's bad but we don't want it to interfere + else: + raise osv.except_osv("Error", "Error during communication with the maintenance server.") + + contracts = result["validity_dates"] + for contract in contracts: + c_id = self.search(cr, uid, [("name","=",contract)])[0] + date_from = contracts[contract][0] + date_to = contracts[contract][1] + valid = datetime.date.today() >= datetime.datetime.strptime(date_from, '%Y-%m-%d').date() \ + and datetime.date.today() <= datetime.datetime.strptime(date_to, '%Y-%m-%d').date() + self.write(cr, uid, c_id, { + "date_start": date_from, + "date_stop": date_to, + "state": "valid" if valid else "unvalid", + }) + + if cron_mode: + cronosv = self.pool.get("ir.cron") + sched_id = cronosv.search(cr, uid, [("name","=","Maintenance Update Scheduler")])[0] + cronosv.write(cr, uid, sched_id, { + "interval_type": result["interval_type"], + "interval_number": result["interval_number"], + }) + + return True _columns = { - 'name' : fields.char('Contract ID', size=384, required=True, readonly=True), + 'name' : fields.char('Contract ID', size=384, required=True), 'date_start' : fields.date('Starting Date', readonly=True), 'date_stop' : fields.date('Ending Date', readonly=True), - 'state' : fields.function(_valid_get, method=True, string="State", type="selection", selection=[('valid', 'Valid'),('unvalid', 'Unvalid')], readonly=True), - 'kind' : fields.char('Kind', size=64, required=True, readonly=True), + 'state' : fields.function(_valid_get, method=True, string="State", type="selection", + selection=[('valid', 'Valid'),('unvalid', 'Unvalid')], readonly=True), + 'kind' : fields.char('Kind', size=64, readonly=True), } + + _defaults = { + 'state': 'unvalid', + } + _sql_constraints = [ ('uniq_name', 'unique(name)', "Your maintenance contract is already subscribed in the system !") ] maintenance_contract() - -class maintenance_contract_wizard(osv.osv_memory): - _name = 'maintenance.contract.wizard' - - _columns = { - 'name' : fields.char('Contract ID', size=384, required=True ), - 'state' : fields.selection([('draft', 'Draft'),('validated', 'Validated'),('unvalidated', 'Unvalidated')], 'States'), - } - - _defaults = { - 'state' : lambda *a: 'draft', - } - - 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 - contract = self.read(cr, uid, ids, ['name'])[0] - - try: - contract_info = tm.remote_contract(cr, uid, contract['name']) - except tm.RemoteContractException, rce: - raise osv.except_osv(_('Error'), ustr(rce)) - - if contract_info['status'] == "valid": - - self.pool.get('maintenance.contract').create( - cr, - uid, { - 'name' : contract['name'], - 'date_start' : contract_info['date_from'], - 'date_stop' : contract_info['date_to'], - 'kind' : contract_info['kind'], - } - ) - - return self.write(cr, uid, ids, - {'state' : ['validated' if contract_info['status'] == "valid" else 'unvalidated'] }, - context=context) - -maintenance_contract_wizard() - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/bin/addons/base/maintenance/maintenance_data.xml b/bin/addons/base/maintenance/maintenance_data.xml new file mode 100644 index 00000000000..981a806bf0e --- /dev/null +++ b/bin/addons/base/maintenance/maintenance_data.xml @@ -0,0 +1,19 @@ + + + + + + Maintenance Update Scheduler + + + 1 + weeks + -1 + + + + + + + + \ No newline at end of file diff --git a/bin/addons/base/maintenance/maintenance_security.xml b/bin/addons/base/maintenance/maintenance_security.xml deleted file mode 100644 index 04b7d6dc2cf..00000000000 --- a/bin/addons/base/maintenance/maintenance_security.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/bin/addons/base/maintenance/maintenance_view.xml b/bin/addons/base/maintenance/maintenance_view.xml index fac95d705a3..5c3adbfc988 100644 --- a/bin/addons/base/maintenance/maintenance_view.xml +++ b/bin/addons/base/maintenance/maintenance_view.xml @@ -22,12 +22,25 @@ form
- - - - - - + + + + + + + + + + + + + +