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)
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.
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"
# TODO schedule a retry
return False
return True
-
-
def _valid_get(self, cr, uid, ids, field_name, arg, context=None):
res = {}
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']:
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)
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):
--- /dev/null
+# -*- 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:
+