From 577a2a1a1137ccc5d3e8c7185449d99168e51d90 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Fri, 2 Jan 2009 15:43:25 +0100 Subject: [PATCH] [IMP] add a method to retrieve the update from the maintenance server bzr revid: christophe@cobalt-20090102144325-cevctmg0cv9cvviq --- bin/addons/__init__.py | 44 +++++++++++++++ bin/addons/base/maintenance/maintenance.py | 10 +--- bin/service/web_services.py | 34 ++++++++++++ bin/tools/maintenance.py | 62 ++++++++++++++++++++++ 4 files changed, 142 insertions(+), 8 deletions(-) create mode 100644 bin/tools/maintenance.py diff --git a/bin/addons/__init__.py b/bin/addons/__init__.py index 25b4fce9976..7a69c3ec131 100644 --- a/bin/addons/__init__.py +++ b/bin/addons/__init__.py @@ -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. diff --git a/bin/addons/base/maintenance/maintenance.py b/bin/addons/base/maintenance/maintenance.py index 70d872495b4..86dc52de5e7 100644 --- a/bin/addons/base/maintenance/maintenance.py +++ b/bin/addons/base/maintenance/maintenance.py @@ -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']: diff --git a/bin/service/web_services.py b/bin/service/web_services.py index 5ec9603dde5..20531b23327 100644 --- a/bin/service/web_services.py +++ b/bin/service/web_services.py @@ -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 index 00000000000..9548690beaa --- /dev/null +++ b/bin/tools/maintenance.py @@ -0,0 +1,62 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2008 Tiny SPRL (). 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 . +# +############################################################################## + +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: +