[IMP] add a method to retrieve the update from the maintenance server
authorChristophe Simonis <christophe@cobalt>
Fri, 2 Jan 2009 14:43:25 +0000 (15:43 +0100)
committerChristophe Simonis <christophe@cobalt>
Fri, 2 Jan 2009 14:43:25 +0000 (15:43 +0100)
bzr revid: christophe@cobalt-20090102144325-cevctmg0cv9cvviq

bin/addons/__init__.py
bin/addons/base/maintenance/maintenance.py
bin/service/web_services.py
bin/tools/maintenance.py [new file with mode: 0644]

index 25b4fce..7a69c3e 100644 (file)
@@ -38,6 +38,11 @@ from osv import fields
 import zipfile
 import release
 
+import re
+import base64
+from zipfile import PyZipFile, ZIP_DEFLATED
+import StringIO
+
 logger = netsvc.Logger()
 
 _ad = os.path.abspath(opj(tools.config['root_path'], 'addons'))     # default addons path (base)
@@ -172,6 +177,45 @@ def get_module_filetree(module, dir='.'):
     
     return tree
 
+
+def get_module_as_zip(modulename, b64enc=True, src=True):
+    
+    RE_exclude = re.compile('(?:^\..+\.swp$)|(?:\.py[oc]$)|(?:\.bak$)|(?:\.~.~$)', re.I)
+    
+    def _zippy(archive, path, src=True):
+        path = os.path.abspath(path)
+        base = os.path.basename(path)
+        for f in tools.osutil.listdir(path, True):
+            bf = os.path.basename(f)
+            if not RE_exclude.search(bf) and (src or bf == '__terp__.py' or not path.endswith('.py')):
+                archive.write(os.path.join(path, f), os.path.join(base, f))
+    
+    ap = get_module_path(str(modulename))
+    if not ap:
+        raise Exception('Unable to find path for module %s' % modulename)
+    
+    ap = ap.encode('utf8') 
+    if os.path.isfile(ap + '.zip'):
+        val = file(ap + '.zip', 'rb').read()
+    else:
+        archname = StringIO.StringIO('wb')
+        archive = PyZipFile(archname, "w", ZIP_DEFLATED)
+        archive.writepy(ap)
+        _zippy(archive, ap, src=src)
+        archive.close()
+        val = archname.getvalue()
+        archname.close()
+
+    ### debug
+    f = file('/tmp/mod.zip', 'wb')
+    f.write(val)
+    f.close()
+
+    if b64enc:
+        val = base64.encodestring(val)
+    return val
+
+
 def get_module_resource(module, *args):
     """Return the full path of a resource of the given module.
 
index 70d8724..86dc52d 100644 (file)
@@ -35,7 +35,7 @@ import math
 from pprint import pprint as pp
 
 from tools import config, debug
-import xmlrpclib
+from tools.maintenance import remote_contract
 
 class maintenance_contract_module(osv.osv):
     _name ="maintenance.contract.module"
@@ -91,8 +91,6 @@ class maintenance_contract(osv.osv):
             # TODO schedule a retry
             return False
         return True
-        
 
     def _valid_get(self, cr, uid, ids, field_name, arg, context=None):
         res = {}
@@ -142,12 +140,8 @@ class maintenance_contract_wizard(osv.osv_memory):
 
         contract = self.read(cr, uid, ids, ['name', 'password'])[0]
 
-        login, password, remote_db, remote_server, port = 'admin', 'admin', 'trunk', 'localhost', 8069
+        contract_info = remote_contact(contract['name'], contract['password'], modules)
 
-        rpc = xmlrpclib.ServerProxy('http://%s:%d/xmlrpc/common' % (remote_server, port))
-        ruid = rpc.login(remote_db, login, password)
-        rpc = xmlrpclib.ServerProxy('http://%s:%d/xmlrpc/object' % (remote_server, port))
-        contract_info = rpc.execute(remote_db, ruid, password, 'maintenance.maintenance', 'check_contract', modules, contract )
         is_ok = contract_info['status'] in ('partial', 'full')
         if is_ok:
             if contract_info['modules_with_contract']:
index 5ec9603..20531b2 100644 (file)
@@ -286,6 +286,7 @@ class common(netsvc.Service):
         self.exportMethod(self.login)
         self.exportMethod(self.logout)
         self.exportMethod(self.timezone_get)
+        self.exportMethod(self.get_migration_scripts)
 
     def ir_set(self, db, uid, password, keys, args, name, value, replace=True, isobject=False):
         security.check(db, uid, password)
@@ -349,6 +350,39 @@ GNU Public Licence.
 
     def timezone_get(self, db, login, password):
         return time.tzname[0]
+
+
+    def get_migration_scripts(self, password, contract_id, contract_password):
+        security.check_super(password)
+         
+        from tools.maintenance import remote_contract
+        rc = remote_contract(contract_id, contract_password)
+        if not rc.id:
+            raise Exception('This contract does not exist or is not active') 
+        if rc.status != 'full':
+            raise Exception('Can not get updates for a partial contract')
+
+        l = netsvc.Logger()
+        l.notifyChannel('migration', netsvc.LOG_INFO, 'starting migration with contract %s' % (rc.name,))
+
+        zips = rc.retrieve_updates(rc.id)
+        
+        from shutil import rmtree
+        for module in zips:
+            l.notifyChannel('migration', netsvc.LOG_INFO, 'upgrade module %s' % (module,))
+            mp = addons.get_module_path(module)
+            if mp:
+                if os.path.isdir(mp):
+                    rmtree(os.path.realpath(mp))
+                else:
+                    os.unlink(mp + '.zip')
+
+            mp = os.path.join(tools.config['addons_path'], module + '.zip')
+
+            zip = open(mp, 'w')
+            zip.write(base64.decodestring(zips[module]))
+            zip.close()
+        
 common()
 
 class objects_proxy(netsvc.Service):
diff --git a/bin/tools/maintenance.py b/bin/tools/maintenance.py
new file mode 100644 (file)
index 0000000..9548690
--- /dev/null
@@ -0,0 +1,62 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution  
+#    Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
+#    $Id$
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU 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 General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import xmlrpclib
+
+class remote_contract(object):
+    def __init__(self, contract_id, contract_password, modules=None):
+        self.__server = 'http://localhost:8069/xmlrpc/'
+        self.__db = "trunk"
+        self.__password = "admin"
+        self.__login = "admin"
+        
+        rpc = xmlrpclib.ServerProxy(self.__server + 'common')
+        self.__userid = rpc.login(self.__db, self.__login, self.__password)
+
+        self.__rpc = xmlrpclib.ServerProxy(self.__server + 'object')
+        
+
+        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
+        
+    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 remote_call
+
+    def __getitem__(self, item):
+        return getattr(self, item)
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+