# -*- coding: utf-8 -*- from os.path import join, exists, dirname import os import shutil import signal import subprocess import sys import settings from utils import run, get root_dir = dirname(settings.base_dir) HIDDEN = ['install_update', 'install_launcher', 'uninstall_launcher'] def r(*cmd): return subprocess.call(cmd) def version(module): if os.path.exists(join(root_dir, module, '.git')): os.chdir(join(root_dir, module)) version = get('git', 'log', '-1', '--format=%cd', '--date=iso').split(' ')[0].replace('-', '') version += '-' + get('git', 'rev-list', 'HEAD', '--count').strip() version += '-' + get('git', 'describe', '--always').strip() os.chdir(root_dir) else: if 'modules' in settings.release and module in settings.release['modules']: version = settings.release['modules'][module]['version'] else: version = -1 return version def command_version(*args): """ Print current version """ print(version('openmedialibrary')) def command_debug(*args): """ Start in debug mode """ pass def command_start(*args): """ Start Open Media Libary """ pass def command_stop(*args): """ Stop Open Media Libary """ if sys.platform == 'win32': from utils import check_pid if args: pid = args[0] else: pid = os.path.join(settings.data_path, 'openmedialibrary.pid') try: with open(pid) as fd: pid = int(fd.read()) except: return if check_pid(pid): os.kill(pid, signal.SIGTERM) def command_restart(*args): """ Restart Open Media Libary """ if sys.platform == 'win32': from urllib.request import urlopen from urllib.parse import urlencode url = 'http://{address}:{port}/api/'.format(**settings.server) data = urlencode({'action': 'quit', 'data': '{}'}).encode() try: urlopen(url, data, timeout=2) except: pass from utils import check_pid, ctl pidfile = os.path.join(settings.data_path, 'openmedialibrary.pid') try: with open(pidfile) as fd: pid = int(fd.read()) except: pid = None if pid and check_pid(pid): os.kill(pid, signal.SIGTERM) ctl('server', pidfile) def command_install_launcher(*args): """ Install launcher """ import integration integration.install_launcher() def command_uninstall_launcher(*args): """ Uninstall launcher """ import integration integration.uninstall_launcher() def command_install_update(*args): """ Install available updates """ pass def command_update(*args): """ Update to latest development version """ import update print('Downloading...') if not update.download(): print('Download failed') return print('Installing...') if not update.install(): print("Installation failed") def command_postupdate(*args): """ Called after update with -o old -n new """ o, old, n, new = args if o != '-o' or n != '-n': print('usage: -o oldversion -n newversion') sys.exit(1) if old <= '20140521-65-e14c686' and new > '20140521-65-e14c686': if not os.path.exists(settings.db_path): r('./ctl', 'setup') import setup setup.upgrade_db(old, new) def command_setup(*args): """ Setup new node """ import setup setup.create_db() def command_update_static(*args): """ Update static files """ import setup import utils setup.create_db() old_oxjs = os.path.join(settings.static_path, 'oxjs') oxjs = os.path.join(settings.base_dir, '..', 'oxjs') if os.path.exists(old_oxjs) and not os.path.exists(oxjs): shutil.move(old_oxjs, oxjs) if not os.path.exists(oxjs): r('git', 'clone', '--depth', '1', 'https://code.0x2620.org/0x2620/oxjs.git', oxjs) elif os.path.exists(os.path.join(oxjs, '.git')): os.system('cd "%s" && git pull' % oxjs) r('python3', os.path.join(oxjs, 'tools', 'build', 'build.py'), '-nogeo') utils.update_static() reader = os.path.join(settings.base_dir, '..', 'reader') if not os.path.exists(reader): r('git', 'clone', '--depth', '1', 'https://code.0x2620.org/0x2620/openmedialibrary_reader.git', reader) elif os.path.exists(os.path.join(reader, '.git')): os.system('cd "%s" && git pull' % reader) def command_release(*args): """ Release new version """ print('checking...') import base64 import ed25519 import hashlib import json import OpenSSL.crypto from OpenSSL.crypto import load_privatekey, FILETYPE_PEM import os release_name = args[0] if args else 'release' os.chdir(root_dir) with open(os.path.expanduser('~/.openmedialibrary_release.key'), 'rb') as fd: SIG_KEY=ed25519.SigningKey(fd.read()) SIG_ENCODING='base64' with open(os.path.expanduser('~/.openmedialibrary_tls_release.key'), 'rb') as fd: tls_key = load_privatekey(FILETYPE_PEM, fd.read()) def sign(release): value = [] for module in sorted(release['modules']): value += ['%s/%s' % (release['modules'][module]['version'], release['modules'][module]['sha1'])] value = '\n'.join(value).encode() sig = SIG_KEY.sign(value, encoding=SIG_ENCODING).decode() release['signature'] = sig digest = 'sha1' tls_sig = OpenSSL.crypto.sign(tls_key, value, digest) release['signature_%s'%digest] = base64.b64encode(tls_sig).decode() import update if not update.verify(release): print('verifiying signature failed!') return False return True def sha1sum(path): h = hashlib.sha1() with open(path, 'rb') as fd: for chunk in iter(lambda: fd.read(128*h.block_size), b''): h.update(chunk) return h.hexdigest() MODULES = ['platform', 'openmedialibrary', 'oxjs', 'reader'] PLATFORM_MODULES = { 'platform_linux32': 'linux32', 'platform_linux64': 'linux64', 'platform_linux_armv7l': 'linux_armv7l', 'platform_linux_aarch64': 'linux_aarch64', 'platform_darwin64': 'darwin64', 'platform_win32': 'win32', } MODULES += list(PLATFORM_MODULES) VERSIONS = {module:version(module) for module in MODULES} EXCLUDE = [ '--exclude', '.git', '--exclude', '.bzr', '--exclude', 'pip_cache', '--exclude', '.*.swp', '--exclude', '._*', '--exclude', '.DS_Store', '--exclude', 'Geo/png' ] #run('./ctl', 'update_static') for module in MODULES: tar = join('updates', '%s-%s.tar.bz2' % (module, VERSIONS[module])) if not exists(tar): cmd = ['tar', 'cvjf', tar] + EXCLUDE if module in ('openmedialibrary', ): cmd += ['--exclude', '*.pyc'] if module == 'openmedialibrary': cmd += ['--exclude', 'gunicorn.pid'] if module == 'oxjs': cmd += ['--exclude', 'oxjs/examples'] if module == 'platform_win32': cmd += ['--exclude', 'build', '--exclude', 'dist'] cmd += [module + '/'] run(*cmd) release = {} release['modules'] = {module: { 'name': '%s-%s.tar.bz2' % (module, VERSIONS[module]), 'version': VERSIONS[module], 'sha1': sha1sum(join('updates', '%s-%s.tar.bz2' % (module, VERSIONS[module]))) } for module in MODULES} for module in PLATFORM_MODULES: release['modules'][module]['platform'] = PLATFORM_MODULES[module] if sign(release): with open('updates/%s.json' % release_name, 'w') as fd: json.dump(release, fd, indent=2, sort_keys=True) print('signed latest release in updates/%s.json' % release_name) def command_shell(*args): ''' Runs a Python shell inside the application context. ''' context = None banner = 'Open Media Library' import db with db.session(): # Try BPython try: from bpython import embed embed(banner=banner, locals_=context) return except ImportError: pass # Try IPython try: try: # 0.10.x from IPython.Shell import IPShellEmbed ipshell = IPShellEmbed(banner=banner) ipshell(global_ns=dict(), local_ns=context) except ImportError: # 0.12+ from IPython.terminal.ipapp import TerminalIPythonApp app = TerminalIPythonApp.instance() app.extensions = ['autoreload'] app.exec_lines = ['%autoreload 2'] app.display_banner = False print(banner) app.initialize(argv=[]) app.start() return except ImportError: pass import code # Use basic python shell code.interact(banner, local=context) def command_dump_json(*args): """ Dump items to json """ if not args: print('usage: ./ctl json_dump dump.json') sys.exit(1) import db import state with db.session(): library = state.user().library library.export_json(args[0]) def main(): actions = globals() commands = [c[8:] for c in actions if c.startswith('command_')] command = sys.argv[1] if len(sys.argv) > 1 else None if command and command in commands: globals()["command_%s"%command](*sys.argv[2:]) else: print("usage: ./ctl [action]") indent = max([len(command) for command in commands]) + 4 for command in sorted(commands): if command in HIDDEN: continue space = ' ' * (indent - len(command)) info = actions["command_%s"%command].__doc__.split('\n') info = [' %s%s' % (' ' * indent, i.strip()) for i in info] info = '\n'.join(info).strip() print((" %s%s%s" % (command, space, info))) sys.exit(1)