openmedialibrary/oml/update.py

171 lines
6.5 KiB
Python
Raw Normal View History

2014-08-05 09:47:16 +00:00
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
2014-09-02 22:32:44 +00:00
2014-08-05 09:47:16 +00:00
from contextlib import closing
import json
import os
import tarfile
2014-09-02 22:32:44 +00:00
import urllib.request, urllib.error, urllib.parse
2014-08-05 09:47:16 +00:00
import shutil
import subprocess
import ed25519
import ox
2014-08-22 17:46:45 +00:00
from oxtornado import actions
2014-08-05 09:47:16 +00:00
import settings
2014-08-22 17:46:45 +00:00
2014-08-05 09:47:16 +00:00
ENCODING='base64'
2014-08-05 10:12:55 +00:00
RELEASE_URL = 'http://downloads.openmedialibrary.com/release.json'
2014-08-05 09:47:16 +00:00
def verify(release):
vk = ed25519.VerifyingKey(settings.OML_UPDATE_KEY, encoding=ENCODING)
value = []
for module in sorted(release['modules']):
value += [str('%s/%s' % (release['modules'][module]['version'], release['modules'][module]['sha1']))]
value = '\n'.join(value)
2014-10-31 17:53:10 +00:00
value = value.encode()
sig = release['signature'].encode()
2014-08-05 09:47:16 +00:00
try:
vk.verify(sig, value, encoding=ENCODING)
except ed25519.BadSignatureError:
return False
return True
2014-08-07 10:12:03 +00:00
def get(url, filename=None):
2014-09-02 22:32:44 +00:00
request = urllib.request.Request(url, headers={
2014-08-07 10:12:03 +00:00
'User-Agent': settings.USER_AGENT
})
2014-09-02 22:32:44 +00:00
with closing(urllib.request.urlopen(request)) as u:
2014-08-07 10:12:03 +00:00
if not filename:
data = u.read()
return data
else:
dirname = os.path.dirname(filename)
if dirname and not os.path.exists(dirname):
os.makedirs(dirname)
2014-10-31 17:47:48 +00:00
with open(filename, 'wb') as fd:
2014-08-05 09:47:16 +00:00
data = u.read(4096)
2014-08-07 10:12:03 +00:00
while data:
fd.write(data)
data = u.read(4096)
2014-08-05 09:47:16 +00:00
def check():
2014-08-05 09:47:16 +00:00
if settings.release:
2014-08-07 10:12:03 +00:00
release_data = get(RELEASE_URL)
2014-10-31 17:47:48 +00:00
release = json.loads(release_data.decode('utf-8'))
2014-08-05 09:47:16 +00:00
old = settings.release['modules']['openmedialibrary']['version']
new = release['modules']['openmedialibrary']['version']
return verify(release) and old < new
return False
2014-08-05 09:47:16 +00:00
def download():
if not os.path.exists(os.path.join(settings.config_path, 'release.json')):
return True
2014-08-07 10:12:03 +00:00
release_data = get(RELEASE_URL)
2014-10-31 17:47:48 +00:00
release = json.loads(release_data.decode('utf-8'))
2014-09-05 23:56:37 +00:00
if verify(release):
2014-08-05 10:10:42 +00:00
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):
2014-09-02 22:32:44 +00:00
print('download', os.path.basename(module_tar))
2014-08-07 10:12:03 +00:00
get(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))
2014-10-31 17:47:48 +00:00
with open(os.path.join(settings.updates_path, 'release.json'), 'wb') as fd:
2014-08-05 09:47:16 +00:00
fd.write(release_data)
for f in set(os.walk(settings.updates_path).next()[2])-current_files:
2014-08-11 17:11:07 +00:00
os.unlink(os.path.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:
2014-08-05 10:10:42 +00:00
os.chdir(os.path.dirname(settings.base_dir))
2014-08-05 09:47:16 +00:00
for module in release['modules']:
2014-08-05 09:51:17 +00:00
if release['modules'][module]['version'] > settings.release['modules'][module]['version']:
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)
2014-08-05 09:51:17 +00:00
tar.extractall()
tar.close()
2014-08-05 10:10:42 +00:00
os.chdir(os.path.dirname(settings.base_dir))
shutil.move(module, '%s_old' % module)
shutil.move(os.path.join(new, module), module)
2014-08-05 09:51:17 +00:00
shutil.rmtree('%s_old' % module)
shutil.rmtree(new)
2014-08-05 09:51:17 +00:00
else:
2014-09-05 23:56:37 +00:00
os.unlink(module_tar)
2014-08-05 09:51:17 +00:00
return False
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)
2014-08-05 09:47:16 +00:00
return True
return True
2014-08-22 17:46:45 +00:00
def getVersion(data):
'''
check if new version is available
'''
response = {
'current': settings.MINOR_VERSION,
'upgrade': False,
}
2014-09-01 12:01:41 +00:00
if settings.MINOR_VERSION == 'git':
cmd = ['git', 'rev-parse', '@']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, close_fds=True)
stdout, stderr = p.communicate()
current = stdout.strip()
cmd = ['git', 'ls-remote', 'origin', '-h', 'refs/heads/master']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, close_fds=True)
stdout, stderr = p.communicate()
new = stdout.strip()[:40]
response['update'] = current != new
else:
if not os.path.exists(os.path.join(settings.updates_path, 'release.json')):
return response
if not os.path.exists(os.path.join(settings.config_path, 'release.json')):
return response
with open(os.path.join(settings.updates_path, 'release.json')) as fd:
release = json.load(fd)
current = settings.release['modules']['openmedialibrary']['version']
response['current'] = current
new = release['modules']['openmedialibrary']['version']
response['new'] = new
response['update'] = current < new
2014-08-22 17:46:45 +00:00
return response
actions.register(getVersion, cache=False)
def restart(data):
'''
restart (and upgrade if upgrades are available)
'''
subprocess.Popen(['./ctl', 'restart'], close_fds=True)
return {}
actions.register(restart, cache=False)