[IMP] Extract company menu from user and put it in the same level
[odoo/odoo.git] / bin / addons / quality_integration_server / base_quality_interrogation.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #    
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.     
19 #
20 ##############################################################################
21
22 import xmlrpclib
23 import ConfigParser
24 import optparse
25 import sys
26 import thread
27 import threading
28 import os
29 import time
30 import pickle
31 import base64
32 import socket
33
34 admin_passwd = 'admin'
35 waittime = 10
36 wait_count = 0
37 wait_limit = 12
38
39 def to_decode(s):
40     try:
41         return s.encode('utf-8')
42     except UnicodeError:
43         try:
44             return s.encode('latin')
45         except UnicodeError:
46             try:
47                 return s.decode('ascii')
48             except UnicodeError:
49                 return s
50
51 def start_server(root_path, port, netport, addons_path):
52     os.system('python2.5 %sopenerp-server.py  --pidfile=openerp.pid  --port=%s --net_port=%s --addons-path=%s' %(root_path, str(port),str(netport),addons_path))
53 def clean():
54     if os.path.isfile('openerp.pid'):
55         ps = open('openerp.pid')
56         if ps:
57             pid = int(ps.read())
58             ps.close()
59             if pid:
60                 os.kill(pid,9)
61
62 def execute(connector, method, *args):
63     global wait_count
64     res = False
65     try:
66         res = getattr(connector,method)(*args)
67     except socket.error,e:
68         if e.args[0] == 111:
69             if wait_count > wait_limit:
70                 print "Server is taking too long to start, it has exceeded the maximum limit of %d seconds."%(wait_limit)
71                 clean()
72                 sys.exit(1)
73             print 'Please wait %d sec to start server....'%(waittime)
74             wait_count += 1
75             time.sleep(waittime)
76             res = execute(connector, method, *args)
77         else:
78             raise e
79     wait_count = 0
80     return res
81
82 def login(uri, dbname, user, pwd):
83     conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common')
84     uid = execute(conn,'login',dbname, user, pwd)
85     return uid
86
87 def import_translate(uri, user, pwd, dbname, translate_in):
88     uid = login(uri, dbname, user, pwd)
89     if uid:
90         conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
91         wiz_id = execute(conn,'create',dbname, uid, pwd, 'module.lang.import')
92         for trans_in in translate_in:
93             lang,ext = os.path.splitext(trans_in.split('/')[-1])
94             state = 'init'
95             datas = {'form':{}}
96             while state!='end':
97                 res = execute(conn,'execute',dbname, uid, pwd, wiz_id, datas, state, {})
98                 if 'datas' in res:
99                     datas['form'].update( res['datas'].get('form',{}) )
100                 if res['type']=='form':
101                     for field in res['fields'].keys():
102                         datas['form'][field] = res['fields'][field].get('value', False)
103                     state = res['state'][-1][0]
104                     trans_obj = open(trans_in)
105                     datas['form'].update({
106                         'name': lang,
107                         'code': lang,
108                         'data' : base64.encodestring(trans_obj.read())
109                     })
110                     trans_obj.close()
111                 elif res['type']=='action':
112                     state = res['state']
113
114
115 def check_quality(uri, user, pwd, dbname, modules, quality_logs):
116     uid = login(uri, dbname, user, pwd)
117     quality_logs += 'quality-logs'
118     if uid:
119         conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
120         final = {}
121         for module in modules:
122             qualityresult = {}
123             test_detail = {}
124             quality_result = execute(conn,'execute', dbname, uid, pwd,'module.quality.check','check_quality',module)
125             detail_html = ''
126             html = '''<html><body><a name="TOP"></a>'''
127             html +="<h1> Module: %s </h1>"%(quality_result['name'])
128             html += "<h2> Final score: %s</h2>"%(quality_result['final_score'])
129             html += "<div id='tabs'>"
130             html += "<ul>"
131             for x,y,detail in quality_result['check_detail_ids']:
132                 test = detail.get('name')
133                 msg = detail.get('message','')
134                 score = round(float(detail.get('score',0)),2)
135                 html += "<li><a href=\"#%s\">%s</a></li>"%(test.replace(' ','-'),test)
136                 detail_html +='''<div id=\"%s\"><h3>%s (Score : %s)</h3><font color=red><h5>%s</h5></font>%s</div>'''%(test.replace(' ', '-'), test, score, msg, detail.get('detail', ''))
137                 test_detail[test] = (score,msg,detail.get('detail',''))
138             html += "</ul>"
139             html += "%s"%(detail_html)
140             html += "</div></body></html>"
141             if not os.path.isdir(quality_logs):
142                 os.mkdir(quality_logs)
143             fp = open('%s/%s.html'%(quality_logs,module),'wb')
144             fp.write(to_decode(html))
145             fp.close()
146             #final[quality_result['name']] = (quality_result['final_score'],html,test_detail)
147
148         #fp = open('quality_log.pck','wb')
149         #pck_obj = pickle.dump(final,fp)
150         #fp.close()
151         #print "LOG PATH%s"%(os.path.realpath('quality_log.pck'))
152         return True
153     else:
154         print 'Login Failed...'
155         clean()
156         sys.exit(1)
157
158
159
160 def wait(id,url=''):
161     progress=0.0
162     sock2 = xmlrpclib.ServerProxy(url+'/xmlrpc/db')
163     while not progress==1.0:
164         progress,users = execute(sock2,'get_progress',admin_passwd, id)
165     return True
166
167
168 def create_db(uri, dbname, user='admin', pwd='admin', lang='en_US'):
169     conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/db')
170     obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
171     wiz_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
172     login_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common')
173     db_list = execute(conn, 'list')
174     if dbname not in db_list:
175         id = execute(conn,'create',admin_passwd, dbname, True, lang)
176         wait(id,uri)
177     uid = login_conn.login(dbname, user, pwd)
178
179     wiz_id = execute(wiz_conn,'create', dbname, uid, user, 'base_setup.base_setup')
180
181     state = 'init'
182     datas = {'form':{}}
183
184     while state!='config':
185         res = execute(wiz_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
186         if state=='init':
187             datas['form'].update( res['datas'] )
188         if res['type']=='form':
189             for field in res['fields'].keys():
190                 datas['form'][field] = datas['form'].get(field,False)
191             state = res['state'][-1][0]
192             datas['form'].update({
193                 'profile': -1
194             })
195         elif res['type']=='state':
196             state = res['state']
197     res = execute(wiz_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
198     install_module(uri, dbname, ['base_module_quality'],user=user,pwd=pwd)
199     return True
200
201 def drop_db(uri, dbname):
202     conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/db')
203     db_list = execute(conn,'list')
204     if dbname in db_list:
205         execute(conn, 'drop', admin_passwd, dbname)
206     return True
207
208 def make_links(uri, uid, dbname, source, destination, module, user, pwd):
209     if module in ('base','quality_integration_server'):
210         return True
211     if not os.path.islink(destination + '/' + module):
212         if not os.path.isdir(destination + '/' + module):
213             for path in source:
214                 if os.path.isdir(path + '/' + module):
215                     os.symlink(path + '/' + module, destination + '/' + module)
216                     obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
217                     execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'update_list')
218                     module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','=',module)])
219                     if len(module_ids):
220                         data = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'read', module_ids[0],['name','dependencies_id'])
221                         dep_datas = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module.dependency', 'read', data['dependencies_id'],['name'])
222                         for dep_data in dep_datas:
223                             make_links(uri, uid, dbname, source, destination, dep_data['name'], user, pwd)
224                     return True
225     return False
226
227 def install_module(uri, dbname, modules, addons='', extra_addons='',  user='admin', pwd='admin'):
228     uid = login(uri, dbname, user, pwd)
229     if extra_addons:
230         extra_addons = extra_addons.split(',')
231     if uid:
232         if addons and extra_addons:
233             for module in modules:
234                 make_links(uri, uid, dbname, extra_addons, addons, module, user, pwd)
235
236         obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
237         wizard_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
238         module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','in',modules)])
239         execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'button_install', module_ids)
240         wiz_id = execute(wizard_conn, 'create', dbname, uid, pwd, 'module.upgrade.simple')
241         state = 'init'
242         datas = {}
243         #while state!='menu':
244         while state!='end':
245             res = execute(wizard_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
246             if state == 'init':
247                 state = 'start'
248             elif state == 'start':
249                 state = 'end'
250     return True
251
252 def upgrade_module(uri, dbname, modules, user='admin', pwd='admin'):
253     uid = login(uri, dbname, user, pwd)
254     if uid:
255         obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
256         wizard_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
257         module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','in',modules)])
258         execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'button_upgrade', module_ids)
259         wiz_id = execute(wizard_conn, 'create', dbname, uid, pwd, 'module.upgrade.simple')
260         state = 'init'
261         datas = {}
262         #while state!='menu':
263         while state!='end':
264             res = execute(wizard_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
265             if state == 'init':
266                 state = 'start'
267             elif state == 'start':
268                 state = 'end'
269
270     return True
271
272
273
274
275
276 usage = """%prog command [options]
277
278 Basic Commands:
279     start-server         Start Server
280     create-db            Create new database
281     drop-db              Drop database
282     install-module       Install module
283     upgrade-module       Upgrade module
284     install-translation  Install translation file
285     check-quality        Calculate quality and dump quality result into quality_log.pck using pickle
286 """
287 parser = optparse.OptionParser(usage)
288 parser.add_option("--modules", dest="modules",
289                      help="specify modules to install or check quality")
290 parser.add_option("--addons-path", dest="addons_path", help="specify the addons path")
291 parser.add_option("--quality-logs", dest="quality_logs", help="specify the path of quality logs files which has to stores")
292 parser.add_option("--root-path", dest="root_path", help="specify the root path")
293 parser.add_option("-p", "--port", dest="port", help="specify the TCP port", type="int")
294 parser.add_option("--net_port", dest="netport",help="specify the TCP port for netrpc")
295 parser.add_option("-d", "--database", dest="db_name", help="specify the database name")
296 parser.add_option("--login", dest="login", help="specify the User Login")
297 parser.add_option("--password", dest="pwd", help="specify the User Password")
298 parser.add_option("--translate-in", dest="translate_in",
299                      help="specify .po files to import translation terms")
300 parser.add_option("--extra-addons", dest="extra_addons",
301                      help="specify extra_addons and trunkCommunity modules path ")
302
303 (opt, args) = parser.parse_args()
304 if len(args) != 1:
305     parser.error("incorrect number of arguments")
306 command = args[0]
307 if command not in ('start-server','create-db','drop-db','install-module','upgrade-module','check-quality','install-translation'):
308     parser.error("incorrect command")
309
310 def die(cond, msg):
311     if cond:
312         print msg
313         sys.exit(1)
314
315 die(opt.modules and (not opt.db_name),
316         "the modules option cannot be used without the database (-d) option")
317
318 die(opt.translate_in and (not opt.db_name),
319         "the translate-in option cannot be used without the database (-d) option")
320
321 options = {
322     'addons-path' : opt.addons_path or 'addons',
323     'quality-logs' : opt.quality_logs or '',
324     'root-path' : opt.root_path or '',
325     'translate-in': [],
326     'port' : opt.port or 8069,
327     'netport':opt.netport or 8070,
328     'database': opt.db_name or 'terp',
329     'modules' : opt.modules or [],
330     'login' : opt.login or 'admin',
331     'pwd' : opt.pwd or '',
332     'extra-addons':opt.extra_addons or []
333 }
334
335 options['modules'] = opt.modules and map(lambda m: m.strip(), opt.modules.split(',')) or []
336 # Hint:i18n-import=purchase:ar_AR.po+sale:fr_FR.po,nl_BE.po
337 if opt.translate_in:
338     translate = opt.translate_in
339     for module_name,po_files in map(lambda x:tuple(x.split(':')),translate.split('+')):
340         for po_file in po_files.split(','):
341             if module_name == 'base':
342                 po_link = '%saddons/%s/i18n/%s'%(options['root-path'],module_name,po_file)
343             else:
344                 po_link = '%s/%s/i18n/%s'%(options['addons-path'], module_name, po_file)
345             options['translate-in'].append(po_link)
346
347 uri = 'http://localhost:' + str(options['port'])
348
349 server_thread = threading.Thread(target=start_server,
350                 args=(options['root-path'], options['port'],options['netport'], options['addons-path']))
351 try:
352     server_thread.start()
353     if command == 'create-db':
354         create_db(uri, options['database'], options['login'], options['pwd'])
355     if command == 'drop-db':
356         drop_db(uri, options['database'])
357     if command == 'install-module':
358         install_module(uri, options['database'], options['modules'],options['addons-path'],options['extra-addons'],options['login'], options['pwd'])
359     if command == 'upgrade-module':
360         upgrade_module(uri, options['database'], options['modules'], options['login'], options['pwd'])
361     if command == 'check-quality':
362         check_quality(uri, options['login'], options['pwd'], options['database'], options['modules'], options['quality-logs'])
363     if command == 'install-translation':
364         import_translate(uri, options['login'], options['pwd'], options['database'], options['translate-in'])
365     clean()
366     sys.exit(0)
367
368 except xmlrpclib.Fault, e:
369     print e.faultString
370     clean()
371     sys.exit(1)
372 except Exception, e:
373     print e
374     clean()
375     sys.exit(1)
376
377 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: