remove UI_Manager
This commit is contained in:
parent
19aa1eebd5
commit
f1231bd8e5
2 changed files with 0 additions and 380 deletions
|
@ -33,7 +33,6 @@ from lbrynet.lbryfile.StreamDescriptor import save_sd_info
|
||||||
from lbrynet.lbryfile.EncryptedFileMetadataManager import DBEncryptedFileMetadataManager
|
from lbrynet.lbryfile.EncryptedFileMetadataManager import DBEncryptedFileMetadataManager
|
||||||
from lbrynet.lbryfile.StreamDescriptor import EncryptedFileStreamType
|
from lbrynet.lbryfile.StreamDescriptor import EncryptedFileStreamType
|
||||||
from lbrynet.lbryfilemanager.EncryptedFileManager import EncryptedFileManager
|
from lbrynet.lbryfilemanager.EncryptedFileManager import EncryptedFileManager
|
||||||
from lbrynet.lbrynet_daemon.UIManager import UIManager
|
|
||||||
from lbrynet.lbrynet_daemon.Downloader import GetStream
|
from lbrynet.lbrynet_daemon.Downloader import GetStream
|
||||||
from lbrynet.lbrynet_daemon.Publisher import Publisher
|
from lbrynet.lbrynet_daemon.Publisher import Publisher
|
||||||
from lbrynet.lbrynet_daemon.ExchangeRateManager import ExchangeRateManager
|
from lbrynet.lbrynet_daemon.ExchangeRateManager import ExchangeRateManager
|
||||||
|
@ -269,7 +268,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
self.looping_call_manager = LoopingCallManager(calls)
|
self.looping_call_manager = LoopingCallManager(calls)
|
||||||
self.sd_identifier = StreamDescriptorIdentifier()
|
self.sd_identifier = StreamDescriptorIdentifier()
|
||||||
self.stream_info_manager = DBEncryptedFileMetadataManager(self.db_dir)
|
self.stream_info_manager = DBEncryptedFileMetadataManager(self.db_dir)
|
||||||
self.lbry_ui_manager = UIManager(root)
|
|
||||||
self.lbry_file_manager = None
|
self.lbry_file_manager = None
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@ -307,11 +305,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
self.looping_call_manager.start(Checker.CONNECTION_STATUS, 30)
|
self.looping_call_manager.start(Checker.CONNECTION_STATUS, 30)
|
||||||
self.exchange_rate_manager.start()
|
self.exchange_rate_manager.start()
|
||||||
|
|
||||||
if conf.settings['host_ui']:
|
|
||||||
self.lbry_ui_manager.update_checker.start(1800, now=False)
|
|
||||||
yield self.lbry_ui_manager.setup()
|
|
||||||
if launch_ui:
|
|
||||||
self.lbry_ui_manager.launch()
|
|
||||||
yield self._initial_setup()
|
yield self._initial_setup()
|
||||||
yield threads.deferToThread(self._setup_data_directory)
|
yield threads.deferToThread(self._setup_data_directory)
|
||||||
yield self._check_db_migration()
|
yield self._check_db_migration()
|
||||||
|
@ -329,7 +322,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
def _get_platform(self):
|
def _get_platform(self):
|
||||||
if self.platform is None:
|
if self.platform is None:
|
||||||
self.platform = system_info.get_platform()
|
self.platform = system_info.get_platform()
|
||||||
self.platform["ui_version"] = self.lbry_ui_manager.loaded_git_version
|
|
||||||
return self.platform
|
return self.platform
|
||||||
|
|
||||||
def _initial_setup(self):
|
def _initial_setup(self):
|
||||||
|
@ -531,8 +523,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
self.looping_call_manager.shutdown()
|
self.looping_call_manager.shutdown()
|
||||||
if self.analytics_manager:
|
if self.analytics_manager:
|
||||||
self.analytics_manager.shutdown()
|
self.analytics_manager.shutdown()
|
||||||
if self.lbry_ui_manager.update_checker.running:
|
|
||||||
self.lbry_ui_manager.update_checker.stop()
|
|
||||||
|
|
||||||
self._clean_up_temp_files()
|
self._clean_up_temp_files()
|
||||||
|
|
||||||
|
@ -2225,28 +2215,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
d.addCallback(lambda _: self._render_response(True))
|
d.addCallback(lambda _: self._render_response(True))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
@AuthJSONRPCServer.auth_required
|
|
||||||
def jsonrpc_configure_ui(self, branch=None, path=None, check_requirements=True):
|
|
||||||
"""
|
|
||||||
Configure the UI being hosted
|
|
||||||
|
|
||||||
Args, optional:
|
|
||||||
'branch': a branch name on lbryio/lbry-web-ui
|
|
||||||
'path': path to a ui folder
|
|
||||||
"""
|
|
||||||
|
|
||||||
if path is not None:
|
|
||||||
d = self.lbry_ui_manager.setup(
|
|
||||||
user_specified=path, check_requirements=check_requirements)
|
|
||||||
elif branch is not None:
|
|
||||||
d = self.lbry_ui_manager.setup(branch=branch, check_requirements=check_requirements)
|
|
||||||
else:
|
|
||||||
d = self.lbry_ui_manager.setup(check_requirements=check_requirements)
|
|
||||||
|
|
||||||
d.addCallback(lambda r: self._render_response(r))
|
|
||||||
|
|
||||||
return d
|
|
||||||
|
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def jsonrpc_open(self, sd_hash):
|
def jsonrpc_open(self, sd_hash):
|
||||||
|
|
|
@ -1,348 +0,0 @@
|
||||||
import os
|
|
||||||
import logging
|
|
||||||
import shutil
|
|
||||||
import json
|
|
||||||
import webbrowser
|
|
||||||
from urllib2 import urlopen
|
|
||||||
from StringIO import StringIO
|
|
||||||
from zipfile import ZipFile
|
|
||||||
|
|
||||||
import pkg_resources
|
|
||||||
from twisted.internet import defer
|
|
||||||
from twisted.internet.task import LoopingCall
|
|
||||||
|
|
||||||
from lbrynet import conf
|
|
||||||
from lbrynet.lbrynet_daemon.Resources import NoCacheStaticFile
|
|
||||||
from lbrynet import __version__ as lbrynet_version
|
|
||||||
from lbryum.version import LBRYUM_VERSION as lbryum_version
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class UIManager(object):
|
|
||||||
def __init__(self, root):
|
|
||||||
self.ui_root = os.path.join(conf.settings['data_dir'], "lbry-ui")
|
|
||||||
self.active_dir = os.path.join(self.ui_root, "active")
|
|
||||||
self.update_dir = os.path.join(self.ui_root, "update")
|
|
||||||
|
|
||||||
if not os.path.isdir(self.ui_root):
|
|
||||||
os.mkdir(self.ui_root)
|
|
||||||
if not os.path.isdir(self.active_dir):
|
|
||||||
os.mkdir(self.active_dir)
|
|
||||||
if not os.path.isdir(self.update_dir):
|
|
||||||
os.mkdir(self.update_dir)
|
|
||||||
|
|
||||||
self.config = os.path.join(self.ui_root, "active.json")
|
|
||||||
self.update_requires = os.path.join(self.update_dir, "requirements.txt")
|
|
||||||
self.requirements = {}
|
|
||||||
self.check_requirements = True
|
|
||||||
self.ui_dir = self.active_dir
|
|
||||||
self.git_version = None
|
|
||||||
self.root = root
|
|
||||||
self.branch = None
|
|
||||||
self.update_checker = LoopingCall(self.setup)
|
|
||||||
|
|
||||||
if not os.path.isfile(os.path.join(self.config)):
|
|
||||||
self.loaded_git_version = None
|
|
||||||
self.loaded_branch = None
|
|
||||||
self.loaded_requirements = None
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
f = open(self.config, "r")
|
|
||||||
loaded_ui = json.loads(f.read())
|
|
||||||
f.close()
|
|
||||||
self.loaded_git_version = loaded_ui['commit']
|
|
||||||
self.loaded_branch = loaded_ui['branch']
|
|
||||||
self.loaded_requirements = loaded_ui['requirements']
|
|
||||||
except:
|
|
||||||
self.loaded_git_version = None
|
|
||||||
self.loaded_branch = None
|
|
||||||
self.loaded_requirements = None
|
|
||||||
|
|
||||||
def setup(self, branch=None, check_requirements=None, user_specified=None):
|
|
||||||
local_ui_path = user_specified or conf.settings['local_ui_path']
|
|
||||||
|
|
||||||
self.branch = branch or conf.settings['ui_branch']
|
|
||||||
self.check_requirements = (check_requirements if check_requirements is not None
|
|
||||||
else conf.settings['check_ui_requirements'])
|
|
||||||
|
|
||||||
# Note that this currently overrides any manual setting of UI.
|
|
||||||
# It might be worth considering changing that behavior but the expectation
|
|
||||||
# is generally that any manual setting of the UI will happen during development
|
|
||||||
# and not for folks checking out the QA / RC builds that bundle the UI.
|
|
||||||
if self._check_for_bundled_ui():
|
|
||||||
return defer.succeed(True)
|
|
||||||
|
|
||||||
if local_ui_path:
|
|
||||||
if os.path.isdir(local_ui_path):
|
|
||||||
log.info("Checking user specified UI directory: " + str(local_ui_path))
|
|
||||||
self.branch = "user-specified"
|
|
||||||
self.loaded_git_version = "user-specified"
|
|
||||||
d = self.migrate_ui(source=local_ui_path)
|
|
||||||
d.addCallback(lambda _: self._load_ui())
|
|
||||||
return d
|
|
||||||
else:
|
|
||||||
log.info("User specified UI directory doesn't exist, using " + self.branch)
|
|
||||||
elif self.loaded_branch == "user-specified":
|
|
||||||
log.info("Loading user provided UI")
|
|
||||||
d = defer.maybeDeferred(self._load_ui)
|
|
||||||
return d
|
|
||||||
else:
|
|
||||||
log.info("Checking for updates for UI branch: " + self.branch)
|
|
||||||
self._git_url = "https://s3.amazonaws.com/lbry-ui/{}/data.json".format(self.branch)
|
|
||||||
self._dist_url = "https://s3.amazonaws.com/lbry-ui/{}/dist.zip".format(self.branch)
|
|
||||||
|
|
||||||
d = self._up_to_date()
|
|
||||||
d.addCallback(lambda r: self._download_ui() if not r else self._load_ui())
|
|
||||||
return d
|
|
||||||
|
|
||||||
def _check_for_bundled_ui(self):
|
|
||||||
"""Try to load a bundled UI and return True if successful, False otherwise"""
|
|
||||||
try:
|
|
||||||
bundled_path = get_bundled_ui_path()
|
|
||||||
except Exception:
|
|
||||||
log.warning('Failed to get path for bundled UI', exc_info=True)
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
bundle_manager = BundledUIManager(self.root, self.active_dir, bundled_path)
|
|
||||||
loaded = bundle_manager.setup()
|
|
||||||
if loaded:
|
|
||||||
self.loaded_git_version = bundle_manager.version()
|
|
||||||
return loaded
|
|
||||||
|
|
||||||
def _up_to_date(self):
|
|
||||||
def _get_git_info():
|
|
||||||
try:
|
|
||||||
# TODO: should this be switched to the non-blocking getPage?
|
|
||||||
response = urlopen(self._git_url)
|
|
||||||
return defer.succeed(read_sha(response))
|
|
||||||
except Exception:
|
|
||||||
return defer.fail()
|
|
||||||
|
|
||||||
def _set_git(version):
|
|
||||||
self.git_version = version.replace('\n', '')
|
|
||||||
if self.git_version == self.loaded_git_version:
|
|
||||||
log.info("UI is up to date")
|
|
||||||
return defer.succeed(True)
|
|
||||||
else:
|
|
||||||
log.info("UI updates available, checking if installation meets requirements")
|
|
||||||
return defer.succeed(False)
|
|
||||||
|
|
||||||
def _use_existing():
|
|
||||||
log.info("Failed to check for new ui version, trying to use cached ui")
|
|
||||||
return defer.succeed(True)
|
|
||||||
|
|
||||||
d = _get_git_info()
|
|
||||||
d.addCallbacks(_set_git, lambda _: _use_existing)
|
|
||||||
return d
|
|
||||||
|
|
||||||
def migrate_ui(self, source=None):
|
|
||||||
if not source:
|
|
||||||
requires_file = self.update_requires
|
|
||||||
source_dir = self.update_dir
|
|
||||||
delete_source = True
|
|
||||||
else:
|
|
||||||
requires_file = os.path.join(source, "requirements.txt")
|
|
||||||
source_dir = source
|
|
||||||
delete_source = False
|
|
||||||
|
|
||||||
def _skip_requirements():
|
|
||||||
log.info("Skipping ui requirement check")
|
|
||||||
return defer.succeed(True)
|
|
||||||
|
|
||||||
def _check_requirements():
|
|
||||||
if not os.path.isfile(requires_file):
|
|
||||||
log.info("No requirements.txt file, rejecting request to migrate this UI")
|
|
||||||
return defer.succeed(False)
|
|
||||||
requirements = Requirements(requires_file)
|
|
||||||
passed_requirements = requirements.check(lbrynet_version, lbryum_version)
|
|
||||||
return defer.succeed(passed_requirements)
|
|
||||||
|
|
||||||
def _disp_failure():
|
|
||||||
log.info("Failed to satisfy requirements for branch '%s', update was not loaded",
|
|
||||||
self.branch)
|
|
||||||
return defer.succeed(False)
|
|
||||||
|
|
||||||
def _do_migrate():
|
|
||||||
replace_dir(self.active_dir, source_dir)
|
|
||||||
if delete_source:
|
|
||||||
shutil.rmtree(source_dir)
|
|
||||||
|
|
||||||
log.info("Loaded UI update")
|
|
||||||
|
|
||||||
f = open(self.config, "w")
|
|
||||||
loaded_ui = {
|
|
||||||
'commit': self.git_version,
|
|
||||||
'branch': self.branch,
|
|
||||||
'requirements': self.requirements
|
|
||||||
}
|
|
||||||
f.write(json.dumps(loaded_ui))
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
self.loaded_git_version = loaded_ui['commit']
|
|
||||||
self.loaded_branch = loaded_ui['branch']
|
|
||||||
self.loaded_requirements = loaded_ui['requirements']
|
|
||||||
return defer.succeed(True)
|
|
||||||
|
|
||||||
d = _check_requirements() if self.check_requirements else _skip_requirements()
|
|
||||||
d.addCallback(lambda r: _do_migrate() if r else _disp_failure())
|
|
||||||
return d
|
|
||||||
|
|
||||||
def _download_ui(self):
|
|
||||||
def _delete_update_dir():
|
|
||||||
if os.path.isdir(self.update_dir):
|
|
||||||
shutil.rmtree(self.update_dir)
|
|
||||||
return defer.succeed(None)
|
|
||||||
|
|
||||||
def _dl_ui():
|
|
||||||
url = urlopen(self._dist_url)
|
|
||||||
z = ZipFile(StringIO(url.read()))
|
|
||||||
names = [i for i in z.namelist() if '.DS_exStore' not in i and '__MACOSX' not in i]
|
|
||||||
z.extractall(self.update_dir, members=names)
|
|
||||||
log.info("Downloaded files for UI commit " + str(self.git_version).replace("\n", ""))
|
|
||||||
return self.branch
|
|
||||||
|
|
||||||
d = _delete_update_dir()
|
|
||||||
d.addCallback(lambda _: _dl_ui())
|
|
||||||
d.addCallback(lambda _: self.migrate_ui())
|
|
||||||
d.addCallback(lambda _: self._load_ui())
|
|
||||||
return d
|
|
||||||
|
|
||||||
def _load_ui(self):
|
|
||||||
return load_ui(self.root, self.active_dir)
|
|
||||||
|
|
||||||
def launch(self):
|
|
||||||
webbrowser.open(conf.settings.get_ui_address())
|
|
||||||
|
|
||||||
|
|
||||||
class BundledUIManager(object):
|
|
||||||
"""Copies the UI bundled with lbrynet, if available.
|
|
||||||
|
|
||||||
For the QA and nightly builds, we include a copy of the most
|
|
||||||
recent checkout of the development UI. For production builds
|
|
||||||
nothing is bundled.
|
|
||||||
|
|
||||||
n.b: For QA and nightly builds the update check is skipped.
|
|
||||||
"""
|
|
||||||
def __init__(self, root, active_dir, bundled_ui_path):
|
|
||||||
self.root = root
|
|
||||||
self.active_dir = active_dir
|
|
||||||
self.bundled_ui_path = bundled_ui_path
|
|
||||||
self.data_path = os.path.join(bundled_ui_path, 'data.json')
|
|
||||||
self._version = None
|
|
||||||
|
|
||||||
def version(self):
|
|
||||||
if not self._version:
|
|
||||||
self._version = open_and_read_sha(self.data_path)
|
|
||||||
return self._version
|
|
||||||
|
|
||||||
def bundle_is_available(self):
|
|
||||||
return os.path.exists(self.data_path)
|
|
||||||
|
|
||||||
def setup(self):
|
|
||||||
"""Load the bundled UI if possible and necessary
|
|
||||||
|
|
||||||
Returns True if there is a bundled UI, False otherwise
|
|
||||||
"""
|
|
||||||
if not self.bundle_is_available():
|
|
||||||
log.debug('No bundled UI is available')
|
|
||||||
return False
|
|
||||||
if not self.is_active_already_bundled_ui():
|
|
||||||
replace_dir(self.active_dir, self.bundled_ui_path)
|
|
||||||
log.info('Loading the bundled UI')
|
|
||||||
load_ui(self.root, self.active_dir)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def is_active_already_bundled_ui(self):
|
|
||||||
target_data_path = os.path.join(self.active_dir, 'data.json')
|
|
||||||
if os.path.exists(target_data_path):
|
|
||||||
target_version = open_and_read_sha(target_data_path)
|
|
||||||
if self.version() == target_version:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def get_bundled_ui_path():
|
|
||||||
return pkg_resources.resource_filename('lbrynet', 'resources/ui')
|
|
||||||
|
|
||||||
|
|
||||||
def are_same_version(data_a, data_b):
|
|
||||||
"""Compare two data files and return True if they are the same version"""
|
|
||||||
with open(data_a) as a:
|
|
||||||
with open(data_b) as b:
|
|
||||||
return read_sha(a) == read_sha(b)
|
|
||||||
|
|
||||||
|
|
||||||
def open_and_read_sha(filename):
|
|
||||||
with open(filename) as f:
|
|
||||||
return read_sha(f)
|
|
||||||
|
|
||||||
|
|
||||||
def read_sha(filelike):
|
|
||||||
data = json.load(filelike)
|
|
||||||
return data['sha']
|
|
||||||
|
|
||||||
|
|
||||||
def replace_dir(active_dir, source_dir):
|
|
||||||
if os.path.isdir(active_dir):
|
|
||||||
shutil.rmtree(active_dir)
|
|
||||||
shutil.copytree(source_dir, active_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def load_ui(root, active_dir):
|
|
||||||
for name in os.listdir(active_dir):
|
|
||||||
entry = os.path.join(active_dir, name)
|
|
||||||
if os.path.isdir(entry):
|
|
||||||
root.putChild(os.path.basename(entry), NoCacheStaticFile(entry))
|
|
||||||
|
|
||||||
|
|
||||||
class Requirements(object):
|
|
||||||
def __init__(self, requires_file):
|
|
||||||
self.requires_file = requires_file
|
|
||||||
|
|
||||||
def check(self, lbrynet_version, lbryum_version):
|
|
||||||
requirements = self._read()
|
|
||||||
expected = {'lbrynet': lbrynet_version, 'lbryum': lbryum_version}
|
|
||||||
return check_requirements(requirements, expected)
|
|
||||||
|
|
||||||
def _read(self):
|
|
||||||
requirements = {}
|
|
||||||
with open(self.requires_file, "r") as f:
|
|
||||||
for requirement in [line for line in f.read().split('\n') if line]:
|
|
||||||
t = requirement.split('=')
|
|
||||||
if len(t) == 3:
|
|
||||||
requirements[t[0]] = {'version': t[1], 'operator': '=='}
|
|
||||||
elif t[0][-1] == ">":
|
|
||||||
requirements[t[0][:-1]] = {'version': t[1], 'operator': '>='}
|
|
||||||
elif t[0][-1] == "<":
|
|
||||||
requirements[t[0][:-1]] = {'version': t[1], 'operator': '<='}
|
|
||||||
return requirements
|
|
||||||
|
|
||||||
|
|
||||||
def check_requirements(expected, actual):
|
|
||||||
passed_requirements = True
|
|
||||||
for name in expected:
|
|
||||||
if name in actual:
|
|
||||||
version = actual[name]
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
log_msg = "Local version %s of %s does not meet UI requirement for version %s"
|
|
||||||
if expected[name]['operator'] == '==':
|
|
||||||
if not expected[name]['version'] == version:
|
|
||||||
passed_requirements = False
|
|
||||||
log.info(log_msg, version, name, expected[name]['version'])
|
|
||||||
else:
|
|
||||||
log.info("Local version of %s meets ui requirement" % name)
|
|
||||||
if expected[name]['operator'] == '>=':
|
|
||||||
if not expected[name]['version'] <= version:
|
|
||||||
passed_requirements = False
|
|
||||||
log.info(log_msg, version, name, expected[name]['version'])
|
|
||||||
else:
|
|
||||||
log.info("Local version of %s meets ui requirement" % name)
|
|
||||||
if expected[name]['operator'] == '<=':
|
|
||||||
if not expected[name]['version'] >= version:
|
|
||||||
passed_requirements = False
|
|
||||||
log.info(log_msg, version, name, expected[name]['version'])
|
|
||||||
else:
|
|
||||||
log.info("Local version of %s meets ui requirement" % name)
|
|
||||||
return passed_requirements
|
|
Loading…
Reference in a new issue