automatic updates

Adds automatic updates to lbrynet-daemon, this will check if the
installed versions of LBRY applications as well as the lbrynet python
installation are up to date. If they aren’t, it downloads the new
versions, installs them, and restarts the daemon.
This commit is contained in:
Jack 2016-02-16 13:39:08 -05:00
parent 4dcfeca092
commit 20b516b5fa
3 changed files with 112 additions and 36 deletions

View file

@ -544,7 +544,7 @@ def launch_lbry_console():
action="store_true") action="store_true")
parser.add_argument("--data_dir", parser.add_argument("--data_dir",
help=("The full path to the directory in which lbrynet data and metadata will be stored. " help=("The full path to the directory in which lbrynet data and metadata will be stored. "
"Default: ~/.lbrynet"), "Default: ~/.lbrynet on linux, ~/Library/Application Support/lbrynet on OS X"),
type=str) type=str)
parser.add_argument("--lbrycrdd_path", parser.add_argument("--lbrycrdd_path",
help="The path to lbrycrdd, which will be launched if it isn't running, unless " help="The path to lbrycrdd, which will be launched if it isn't running, unless "
@ -573,7 +573,10 @@ def launch_lbry_console():
created_data_dir = False created_data_dir = False
if not args.data_dir: if not args.data_dir:
data_dir = os.path.join(os.path.expanduser("~"), ".lbrynet") if sys.platform == "darwin":
data_dir = os.path.join(os.path.expanduser("~"), "Library/Application Support/lbrynet")
else:
data_dir = os.path.join(os.path.expanduser("~"), ".lbrynet")
else: else:
data_dir = args.data_dir data_dir = args.data_dir
if not os.path.exists(data_dir): if not os.path.exists(data_dir):

View file

@ -29,17 +29,22 @@ import binascii
import webbrowser import webbrowser
import xmlrpclib import xmlrpclib
from decimal import Decimal from decimal import Decimal
import subprocess
from StringIO import StringIO
from zipfile import ZipFile
from urllib import urlopen
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
#TODO add login credentials in a conf file
#issues with delete: # TODO add login credentials in a conf file
#TODO when stream is stopped the generated file is deleted
#functions to add: # issues with delete:
#TODO send credits to address # TODO when stream is stopped the generated file is deleted
#TODO alert if your copy of a lbry file is out of date with the name record
# functions to add:
# TODO send credits to address
# TODO alert if your copy of a lbry file is out of date with the name record
class LBRYDaemon(xmlrpc.XMLRPC): class LBRYDaemon(xmlrpc.XMLRPC):
@ -54,7 +59,10 @@ class LBRYDaemon(xmlrpc.XMLRPC):
self.run_server = True self.run_server = True
self.session = None self.session = None
self.known_dht_nodes = KNOWN_DHT_NODES self.known_dht_nodes = KNOWN_DHT_NODES
self.db_dir = os.path.join(os.path.expanduser("~"), ".lbrynet") if sys.platform != "darwin":
self.db_dir = os.path.join(os.path.expanduser("~"), ".lbrynet")
else:
self.db_dir = os.path.join(os.path.expanduser("~"), "Library/Application Support/lbrynet")
self.blobfile_dir = os.path.join(self.db_dir, "blobfiles") self.blobfile_dir = os.path.join(self.db_dir, "blobfiles")
self.peer_port = 3333 self.peer_port = 3333
self.dht_node_port = 4444 self.dht_node_port = 4444
@ -102,14 +110,19 @@ class LBRYDaemon(xmlrpc.XMLRPC):
self.data_rate = MIN_BLOB_DATA_PAYMENT_RATE self.data_rate = MIN_BLOB_DATA_PAYMENT_RATE
self.max_key_fee = DEFAULT_MAX_KEY_FEE self.max_key_fee = DEFAULT_MAX_KEY_FEE
self.max_search_results = DEFAULT_MAX_SEARCH_RESULTS self.max_search_results = DEFAULT_MAX_SEARCH_RESULTS
self.restart_message = ""
self.search_timeout = 3.0 self.search_timeout = 3.0
self.query_handlers = {} self.query_handlers = {}
return defer.succeed(None) return defer.succeed(None)
def _disp_startup(): def _disp_startup():
print "Started LBRYnet daemon" if self.restart_message:
print "The daemon can be shut down by running 'stop-lbrynet-daemon' in a terminal" print self.restart_message
else:
print "Started LBRYnet daemon"
print "The daemon can be shut down by running 'stop-lbrynet-daemon' in a terminal"
return defer.succeed(None) return defer.succeed(None)
d = defer.Deferred() d = defer.Deferred()
@ -125,12 +138,79 @@ class LBRYDaemon(xmlrpc.XMLRPC):
d.addCallback(lambda _: self._setup_lbry_file_opener()) d.addCallback(lambda _: self._setup_lbry_file_opener())
d.addCallback(lambda _: self._setup_query_handlers()) d.addCallback(lambda _: self._setup_query_handlers())
d.addCallback(lambda _: self._setup_server()) d.addCallback(lambda _: self._setup_server())
if sys.platform == "darwin":
d.addCallback(lambda _: self._update())
d.addCallback(lambda _: self._setup_fetcher()) d.addCallback(lambda _: self._setup_fetcher())
d.addCallback(lambda _: _disp_startup()) d.addCallback(lambda _: _disp_startup())
d.callback(None) d.callback(None)
return defer.succeed(None) return defer.succeed(None)
def _update(self):
def _check_for_updater():
if os.path.isdir("/Applications/LBRY Updater.app"):
print "Found LBRY updater"
return defer.succeed(None)
print "LBRY updater not found, downloading and installing..."
url = urlopen("https://rawgit.com/jackrobison/lbrynet-app/master/LBRY%20Updater.app.zip")
zipped_app = ZipFile(StringIO(url.read()))
zipped_app.extractall("/Applications")
return defer.succeed(None)
def _update_lbrynet():
git_version = subprocess.check_output(
"git ls-remote https://github.com/lbryio/lbry.git | grep HEAD | cut -f 1",
shell=True)
if os.path.isfile(os.path.join(self.db_dir, "lbrynet_version.txt")):
f = open(os.path.join(self.db_dir, "lbrynet_version.txt"), 'r')
current_version = f.read()
f.close()
if git_version == current_version:
print "LBRYnet installation version " + current_version[:-1] + " is up to date"
return defer.succeed(None)
print "Update LBRYnet version " + current_version[:-1] + " --> " + git_version[:-1]
self.restart_message = "Updates available"
return defer.succeed(None)
def _update_lbrycrdd():
git_version = subprocess.check_output(
"git ls-remote https://github.com/jackrobison/lbrynet-app.git | grep HEAD | cut -f 1",
shell=True)
if os.path.isfile(os.path.join(self.wallet_dir, "lbry_app_version.txt")):
f = open(os.path.join(self.wallet_dir, "lbry_app_version.txt"), 'r')
current_version = f.read()
f.close()
if git_version == current_version:
print "LBRY installation version " + current_version[:-1] + " is up to date"
return defer.succeed(None)
print "Update LBRY version " + current_version[:-1] + " --> " + git_version[:-1]
self.restart_message = "Updates available"
return defer.succeed(None)
d = _check_for_updater()
d.addCallback(lambda _: _update_lbrynet())
d.addCallback(lambda _: _update_lbrycrdd())
d.addCallback(lambda _: os.system("open /Applications/LBRY\ Updater.app &>/dev/null") if self.restart_message
else defer.succeed(None))
d.addCallbacks(lambda _: self._restart() if self.restart_message else defer.succeed(None))
return defer.succeed(None)
def _restart(self):
def _disp_shutdown():
print 'Restarting lbrynet daemon'
return defer.succeed(None)
# LBRY Updater.app will restart the daemon
d = self._shutdown()
d.addCallback(lambda _: _disp_shutdown())
d.addCallback(lambda _: reactor.callLater(1.0, reactor.stop))
return d
def _start_server(self): def _start_server(self):
if self.peer_port is not None: if self.peer_port is not None:
@ -166,10 +246,10 @@ class LBRYDaemon(xmlrpc.XMLRPC):
def _setup_query_handlers(self): def _setup_query_handlers(self):
handlers = [ handlers = [
#CryptBlobInfoQueryHandlerFactory(self.lbry_file_metadata_manager, self.session.wallet, # CryptBlobInfoQueryHandlerFactory(self.lbry_file_metadata_manager, self.session.wallet,
# self._server_payment_rate_manager), # self._server_payment_rate_manager),
BlobAvailabilityHandlerFactory(self.session.blob_manager), BlobAvailabilityHandlerFactory(self.session.blob_manager),
#BlobRequestHandlerFactory(self.session.blob_manager, self.session.wallet, # BlobRequestHandlerFactory(self.session.blob_manager, self.session.wallet,
# self._server_payment_rate_manager), # self._server_payment_rate_manager),
self.session.wallet.get_wallet_info_query_handler_factory(), self.session.wallet.get_wallet_info_query_handler_factory(),
] ]
@ -287,8 +367,8 @@ class LBRYDaemon(xmlrpc.XMLRPC):
def _get_session(self): def _get_session(self):
def get_default_data_rate(): def get_default_data_rate():
d = self.settings.get_default_data_payment_rate() d = self.settings.get_default_data_payment_rate()
d.addCallback(lambda rate: {"default_data_payment_rate": d.addCallback(lambda rate: {"default_data_payment_rate": rate if rate is not None else
rate if rate is not None else MIN_BLOB_DATA_PAYMENT_RATE}) MIN_BLOB_DATA_PAYMENT_RATE})
return d return d
def get_wallet(): def get_wallet():
@ -358,18 +438,6 @@ class LBRYDaemon(xmlrpc.XMLRPC):
self.sd_identifier.add_stream_downloader_factory(LBRYFileStreamType, file_opener_factory) self.sd_identifier.add_stream_downloader_factory(LBRYFileStreamType, file_opener_factory)
return defer.succeed(None) return defer.succeed(None)
def _setup_lbry_file_manager(self):
self.lbry_file_metadata_manager = DBLBRYFileMetadataManager(self.db_dir)
d = self.lbry_file_metadata_manager.setup()
def set_lbry_file_manager():
self.lbry_file_manager = LBRYFileManager(self.session, self.lbry_file_metadata_manager, self.sd_identifier)
return self.lbry_file_manager.setup()
d.addCallback(lambda _: set_lbry_file_manager())
return d
def _setup_lbry_file_opener(self): def _setup_lbry_file_opener(self):
downloader_factory = LBRYFileOpenerFactory(self.session.peer_finder, self.session.rate_limiter, downloader_factory = LBRYFileOpenerFactory(self.session.peer_finder, self.session.rate_limiter,
@ -391,7 +459,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
d = self.session.wallet.get_stream_info_for_name(name) d = self.session.wallet.get_stream_info_for_name(name)
stream = GetStream(self.sd_identifier, self.session, self.session.wallet, self.lbry_file_manager, stream = GetStream(self.sd_identifier, self.session, self.session.wallet, self.lbry_file_manager,
max_key_fee=self.max_key_fee, data_rate=self.data_rate) max_key_fee=self.max_key_fee, data_rate=self.data_rate)
d.addCallback(_disp) d.addCallback(_disp)
d.addCallback(lambda stream_info: stream.start(stream_info)) d.addCallback(lambda stream_info: stream.start(stream_info))
d.addCallback(lambda _: self._path_from_name(name)) d.addCallback(lambda _: self._path_from_name(name))
@ -440,7 +508,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
print "[" + str(datetime.now()) + "] Search for lbry_file, returning: " + stream_hash print "[" + str(datetime.now()) + "] Search for lbry_file, returning: " + stream_hash
return defer.succeed(_get_lbry_file(path)) return defer.succeed(_get_lbry_file(path))
else: else:
print "[" + str(datetime.now()) + "] Search for lbry_file didn't return anything" print "[" + str(datetime.now()) + "] Search for lbry_file didn't return anything"
return defer.succeed(False) return defer.succeed(False)
d = self._resolve_name(name) d = self._resolve_name(name)
@ -471,7 +539,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
d = self._check_history(name) d = self._check_history(name)
d.addCallback(lambda lbry_file: {'stream_hash': lbry_file.stream_hash, d.addCallback(lambda lbry_file: {'stream_hash': lbry_file.stream_hash,
'path': os.path.join(self.download_directory, lbry_file.file_name)} 'path': os.path.join(self.download_directory, lbry_file.file_name)}
if lbry_file else defer.fail(UnknownNameError)) if lbry_file else defer.fail(UnknownNameError))
return d return d
def _path_from_lbry_file(self, lbry_file): def _path_from_lbry_file(self, lbry_file):
@ -508,7 +576,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
d.addCallback(self.sd_identifier.get_metadata_for_sd_blob) d.addCallback(self.sd_identifier.get_metadata_for_sd_blob)
d.addCallback(lambda metadata: metadata.validator.info_to_show()) d.addCallback(lambda metadata: metadata.validator.info_to_show())
d.addCallback(_to_dict) d.addCallback(_to_dict)
d.addCallback(lambda info: int(info['stream_size'])/1000000*self.data_rate) d.addCallback(lambda info: int(info['stream_size']) / 1000000 * self.data_rate)
d.addCallback(_add_key_fee) d.addCallback(_add_key_fee)
d.addErrback(lambda _: _add_key_fee(0.0)) d.addErrback(lambda _: _add_key_fee(0.0))
reactor.callLater(self.search_timeout, _check_est, d, name) reactor.callLater(self.search_timeout, _check_est, d, name)
@ -708,8 +776,10 @@ class LBRYDaemon(xmlrpc.XMLRPC):
def _disp_err(err): def _disp_err(err):
print str(err.getTraceback()) print str(err.getTraceback())
return err return err
d = defer.Deferred() d = defer.Deferred()
d.addCallback(lambda _: webbrowser.open("file://" + str(os.path.join(self.download_directory, "lbryio/view/page/gui.html")))) d.addCallback(lambda _: webbrowser.open(
"file://" + str(os.path.join(self.download_directory, "lbryio/view/page/gui.html"))))
d.addErrback(_disp_err) d.addErrback(_disp_err)
d.callback(None) d.callback(None)
@ -748,7 +818,8 @@ class LBRYDaemon(xmlrpc.XMLRPC):
if 'thumbnail' in meta.keys(): if 'thumbnail' in meta.keys():
t['img'] = meta['thumbnail'] t['img'] = meta['thumbnail']
else: else:
t['img'] = 'File://' + str(os.path.join(self.download_directory, "lbryio/web/img/Free-speech-flag.svg")) t['img'] = 'File://' + str(
os.path.join(self.download_directory, "lbryio/web/img/Free-speech-flag.svg"))
if 'name' in meta.keys(): if 'name' in meta.keys():
t['title'] = meta['name'] t['title'] = meta['name']
if 'description' in meta.keys(): if 'description' in meta.keys():
@ -770,7 +841,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
filtered_results = [n for n in filtered_results if 'txid' in n.keys()] filtered_results = [n for n in filtered_results if 'txid' in n.keys()]
resolved_results = [defer.DeferredList([_return_d(n), self._resolve_name_wc(n['name']), resolved_results = [defer.DeferredList([_return_d(n), self._resolve_name_wc(n['name']),
self._get_est_cost(n['name'])], consumeErrors=True) self._get_est_cost(n['name'])], consumeErrors=True)
for n in filtered_results] for n in filtered_results]
d = defer.DeferredList(resolved_results) d = defer.DeferredList(resolved_results)
d.addCallback(_clean) d.addCallback(_clean)
@ -915,6 +986,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
def main(): def main():
# shut down existing instance of lbrynet-daemon if there is one
try: try:
d = xmlrpclib.ServerProxy('http://localhost:7080') d = xmlrpclib.ServerProxy('http://localhost:7080')
d.stop() d.stop()
@ -926,5 +998,6 @@ def main():
reactor.listenTCP(7080, server.Site(daemon)) reactor.listenTCP(7080, server.Site(daemon))
reactor.run() reactor.run()
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View file

@ -21,7 +21,7 @@ echo "Downloading LBRYnet update"
git clone --depth 1 https://github.com/lbryio/lbry.git &>/dev/null git clone --depth 1 https://github.com/lbryio/lbry.git &>/dev/null
cd lbry cd lbry
echo "Updating LBRYnet" echo "Installing update"
sudo python setup.py install &>/dev/null sudo python setup.py install &>/dev/null
mkdir -p "$lbrynet_directory" mkdir -p "$lbrynet_directory"
echo $current_version > "${lbrynet_directory}/lbrynet_version.txt" echo $current_version > "${lbrynet_directory}/lbrynet_version.txt"