From 537eba0f0ff95d8360ce8e65f1ab34e6b46daf12 Mon Sep 17 00:00:00 2001 From: j Date: Thu, 7 Aug 2014 11:46:23 +0200 Subject: [PATCH] install updates on startup, check for updates --- ctl | 7 +++-- oml/app.py | 1 + oml/commands.py | 17 +++++++++--- oml/downloads.py | 9 ++++++ oml/settings.py | 24 ++++++++-------- oml/update.py | 72 ++++++++++++++++++++++++++++++++---------------- 6 files changed, 89 insertions(+), 41 deletions(-) diff --git a/ctl b/ctl index e2eb6b6..a8882b5 100755 --- a/ctl +++ b/ctl @@ -44,6 +44,9 @@ if [ "$1" == "start" ]; then echo openmedialibrary already running exit 1 fi + if [ ! -d "$BASE/$NAME/.git" ]; then + python2 oml install_update + fi python2 oml server $PID rm -f $PID exit $? @@ -97,7 +100,7 @@ if [ "$1" == "update" ]; then echo Update $NAME.. cd "$BASE/$NAME" git pull - find . -name '*.pyc' -exec rm "{}" \; + find . -name "*.pyc" -exec rm "{}" \; "$0" setup "$0" update_static > /dev/null NEW=`"$0" version` @@ -105,7 +108,7 @@ if [ "$1" == "update" ]; then else python2 oml update fi - exit + exit $? fi if [ "$1" == "python" ]; then cd "$BASE/$NAME" diff --git a/oml/app.py b/oml/app.py index d1ebb06..becdce7 100644 --- a/oml/app.py +++ b/oml/app.py @@ -32,6 +32,7 @@ manager.add_command('db', MigrateCommand) manager.add_command('release', commands.Release) manager.add_command('debug', commands.Debug) manager.add_command('update', commands.Update) +manager.add_command('install_update', commands.InstallUpdate) manager.add_command('start', commands.Start) manager.add_command('stop', commands.Stop) manager.add_command('setup', commands.Setup) diff --git a/oml/commands.py b/oml/commands.py index fa46f4e..e06954e 100644 --- a/oml/commands.py +++ b/oml/commands.py @@ -5,6 +5,7 @@ from __future__ import division import subprocess from os.path import join, exists, dirname import os +import sys from flask.ext.script import Command, Option @@ -65,16 +66,24 @@ class Stop(Command): def run(self): pass +class InstallUpdate(Command): + """ + Update to latest development version + """ + def run(self): + import update + if not update.install(): + print "UPDATE FAILED" + sys.exit(1) + class Update(Command): """ Update to latest development version """ def run(self): import update - if update.update(): - print "OK" - else: - print "FAILED" + if not (update.download() and update.install()): + print "UPDATE FAILED" class PostUpdate(Command): """ diff --git a/oml/downloads.py b/oml/downloads.py index 7199626..e7d23a8 100644 --- a/oml/downloads.py +++ b/oml/downloads.py @@ -7,6 +7,8 @@ import time import logging import state +import settings +import update logger = logging.getLogger('oml.downloads') @@ -19,8 +21,15 @@ class Downloads(Thread): self.daemon = True self.start() + def download_updates(self): + now = int(time.mktime(time.gmtime())) + if now > settings.server.get('last_update_check', 0) + 24*60*60: + settings.server['last_update_check'] = now + update.download() + def download_next(self): import item.models + self.download_updates() for t in item.models.Transfer.query.filter( item.models.Transfer.added!=None, item.models.Transfer.progress<1).order_by(item.models.Transfer.added): diff --git a/oml/settings.py b/oml/settings.py index 1f332c7..f2a55e5 100644 --- a/oml/settings.py +++ b/oml/settings.py @@ -14,15 +14,15 @@ updates_path = os.path.normpath(os.path.join(base_dir, '..', 'updates')) oml_config_path = os.path.join(base_dir, 'config.json') -config_dir = os.path.normpath(os.path.join(base_dir, '..', 'config')) -if not os.path.exists(config_dir): - os.makedirs(config_dir) +config_path = os.path.normpath(os.path.join(base_dir, '..', 'config')) +if not os.path.exists(config_path): + os.makedirs(config_path) -db_path = os.path.join(config_dir, 'data.db') -icons_db_path = os.path.join(config_dir, 'icons.db') -key_path = os.path.join(config_dir, 'node.key') -ssl_cert_path = os.path.join(config_dir, 'node.ssl.crt') -ssl_key_path = os.path.join(config_dir, 'node.ssl.key') +db_path = os.path.join(config_path, 'data.db') +icons_db_path = os.path.join(config_path, 'icons.db') +key_path = os.path.join(config_path, 'node.key') +ssl_cert_path = os.path.join(config_path, 'node.ssl.crt') +ssl_key_path = os.path.join(config_path, 'node.ssl.key') db = SQLAlchemy() @@ -32,10 +32,10 @@ if os.path.exists(oml_config_path): else: config = {} -preferences = pdict(os.path.join(config_dir, 'preferences.json'), config['user']['preferences']) -ui = pdict(os.path.join(config_dir, 'ui.json'), config['user']['ui']) +preferences = pdict(os.path.join(config_path, 'preferences.json'), config['user']['preferences']) +ui = pdict(os.path.join(config_path, 'ui.json'), config['user']['ui']) -server = pdict(os.path.join(config_dir, 'server.json')) +server = pdict(os.path.join(config_path, 'server.json')) server_defaults = { 'port': 9842, 'address': '::1', @@ -51,7 +51,7 @@ for key in server_defaults: if key not in server: server[key] = server_defaults[key] -release = pdict(os.path.join(config_dir, 'release.json')) +release = pdict(os.path.join(config_path, 'release.json')) if os.path.exists(key_path): with open(key_path) as fd: diff --git a/oml/update.py b/oml/update.py index 35c16b8..a2e3c36 100644 --- a/oml/update.py +++ b/oml/update.py @@ -32,8 +32,8 @@ def verify(release): return False return True -def download(url, filename): - print 'download', filename +def download_module(url, filename): + print 'download', os.path.basename(filename) dirname = os.path.dirname(filename) if dirname and not os.path.exists(dirname): os.makedirs(dirname) @@ -44,7 +44,7 @@ def download(url, filename): f.write(data) data = u.read(4096) -def new_version(): +def check(): if settings.release: r = requests.get(RELEASE_URL) release_data = r.content @@ -53,7 +53,9 @@ def new_version(): new = release['modules']['openmedialibrary']['version'] return verify(release) and old < new -def update(): +def download(): + if not os.path.exists(os.path.join(settings.config_path, 'release.json')): + return True r = requests.get(RELEASE_URL) release_data = r.content release = json.loads(release_data) @@ -61,36 +63,60 @@ def update(): new = release['modules']['openmedialibrary']['version'] if verify(release) and old < new: ox.makedirs(settings.updates_path) + os.chdir(os.path.dirname(settings.base_dir)) + current_files = {'release.json'} + for module in release['modules']: + if release['modules'][module]['version'] > settings.release['modules'][module]['version']: + module_tar = os.path.join(settings.updates_path, release['modules'][module]['name']) + url = RELEASE_URL.replace('release.json', release['modules'][module]['name']) + if not os.path.exists(module_tar): + download_module(url, module_tar) + if ox.sha1sum(module_tar) != release['modules'][module]['sha1']: + os.unlink(module_tar) + return False + current_files.add(os.path.basename(module_tar)) with open(os.path.join(settings.updates_path, 'release.json'), 'w') as fd: fd.write(release_data) + for f in set(os.walk(settings.updates_path).next()[2])-current_files: + os.unlink(os.join(settings.updates_path, f)) + return True + return True + +def install(): + if not os.path.exists(os.path.join(settings.updates_path, 'release.json')): + return True + if not os.path.exists(os.path.join(settings.config_path, 'release.json')): + return True + with open(os.path.join(settings.updates_path, 'release.json')) as fd: + release = json.load(fd) + old = settings.release['modules']['openmedialibrary']['version'] + new = release['modules']['openmedialibrary']['version'] + if verify(release) and old < new: os.chdir(os.path.dirname(settings.base_dir)) for module in release['modules']: if release['modules'][module]['version'] > settings.release['modules'][module]['version']: - package_tar = os.path.join(settings.updates_path, release['modules'][module]['name']) - url = RELEASE_URL.replace('release.json', release['modules'][module]['name']) - download(url, package_tar) - if ox.sha1sum(package_tar) == release['modules'][module]['sha1']: - ox.makedirs('new') - os.chdir('new') - tar = tarfile.open(package_tar) + module_tar = os.path.join(settings.updates_path, release['modules'][module]['name']) + if os.path.exists(module_tar) and ox.sha1sum(module_tar) == release['modules'][module]['sha1']: + #tar fails if old platform is moved before extract + new = '%s_new' % module + ox.makedirs(new) + os.chdir(new) + tar = tarfile.open(module_tar) tar.extractall() tar.close() os.chdir(os.path.dirname(settings.base_dir)) shutil.move(module, '%s_old' % module) - shutil.move(os.path.join('new', module), module) + shutil.move(os.path.join(new, module), module) shutil.rmtree('%s_old' % module) - shutil.rmtree('new') + shutil.rmtree(new) else: return False - os.unlink(package_tar) - with open(os.path.join(settings.config_dir, 'release.json'), 'w') as fd: - fd.write(release_data) - cmd = ['./ctl', 'stop'] - subprocess.call(cmd) - cmd = ['./ctl', 'setup'] - subprocess.call(cmd) - cmd = ['./ctl', 'postupdate', '-o', old, '-n', new] - subprocess.call(cmd) - cmd = ['./ctl', 'start'] + shutil.copy(os.path.join(settings.updates_path, 'release.json'), os.path.join(settings.config_path, 'release.json')) + for cmd in [ + ['./ctl', 'stop'], + ['./ctl', 'setup'], + ['./ctl', 'postupdate', '-o', old, '-n', new] + ]: + subprocess.call(cmd) return True return True