New restart routine for executable files

Fix log in updater
New source option updater available
This commit is contained in:
Ozzie Isaacs 2021-02-06 09:42:27 +01:00
parent 6137fdeb33
commit e6fb460071
7 changed files with 112 additions and 41 deletions

View File

@ -48,6 +48,11 @@ try:
except ImportError:
flask_danceVersion = None
try:
from greenlet import __version__ as greenlet_Version
except ImportError:
greenlet_Version = None
from . import services
about = flask.Blueprint('about', __name__)
@ -77,7 +82,8 @@ _VERSIONS = OrderedDict(
python_LDAP = services.ldapVersion if bool(services.ldapVersion) else None,
Goodreads = u'installed' if bool(services.goodreads_support) else None,
jsonschema = services.SyncToken.__version__ if bool(services.SyncToken) else None,
flask_dance = flask_danceVersion
flask_dance = flask_danceVersion,
greenlet = greenlet_Version
)
_VERSIONS.update(uploader.get_versions())

View File

@ -56,7 +56,8 @@ log = logger.create()
feature_support = {
'ldap': bool(services.ldap),
'goodreads': bool(services.goodreads_support),
'kobo': bool(services.kobo)
'kobo': bool(services.kobo),
'updater': constants.UPDATER_AVAILABLE
}
try:
@ -1264,8 +1265,11 @@ def download_debug():
@login_required
@admin_required
def get_update_status():
log.info(u"Update status requested")
return updater_thread.get_available_updates(request.method, locale=get_locale())
if feature_support['updater']:
log.info(u"Update status requested")
return updater_thread.get_available_updates(request.method, locale=get_locale())
else:
return ''
@admi.route("/get_updater_status", methods=['GET', 'POST'])
@ -1273,35 +1277,37 @@ def get_update_status():
@admin_required
def get_updater_status():
status = {}
if request.method == "POST":
commit = request.form.to_dict()
if "start" in commit and commit['start'] == 'True':
text = {
"1": _(u'Requesting update package'),
"2": _(u'Downloading update package'),
"3": _(u'Unzipping update package'),
"4": _(u'Replacing files'),
"5": _(u'Database connections are closed'),
"6": _(u'Stopping server'),
"7": _(u'Update finished, please press okay and reload page'),
"8": _(u'Update failed:') + u' ' + _(u'HTTP Error'),
"9": _(u'Update failed:') + u' ' + _(u'Connection error'),
"10": _(u'Update failed:') + u' ' + _(u'Timeout while establishing connection'),
"11": _(u'Update failed:') + u' ' + _(u'General error'),
"12": _(u'Update failed:') + u' ' + _(u'Update File Could Not be Saved in Temp Dir')
}
status['text'] = text
updater_thread.status = 0
updater_thread.resume()
status['status'] = updater_thread.get_update_status()
elif request.method == "GET":
try:
status['status'] = updater_thread.get_update_status()
if status['status'] == -1:
status['status'] = 7
except Exception:
status['status'] = 11
return json.dumps(status)
if feature_support['updater']:
if request.method == "POST":
commit = request.form.to_dict()
if "start" in commit and commit['start'] == 'True':
text = {
"1": _(u'Requesting update package'),
"2": _(u'Downloading update package'),
"3": _(u'Unzipping update package'),
"4": _(u'Replacing files'),
"5": _(u'Database connections are closed'),
"6": _(u'Stopping server'),
"7": _(u'Update finished, please press okay and reload page'),
"8": _(u'Update failed:') + u' ' + _(u'HTTP Error'),
"9": _(u'Update failed:') + u' ' + _(u'Connection error'),
"10": _(u'Update failed:') + u' ' + _(u'Timeout while establishing connection'),
"11": _(u'Update failed:') + u' ' + _(u'General error'),
"12": _(u'Update failed:') + u' ' + _(u'Update File Could Not be Saved in Temp Dir')
}
status['text'] = text
updater_thread.status = 0
updater_thread.resume()
status['status'] = updater_thread.get_update_status()
elif request.method == "GET":
try:
status['status'] = updater_thread.get_update_status()
if status['status'] == -1:
status['status'] = 7
except Exception:
status['status'] = 11
return json.dumps(status)
return ''
@admi.route('/import_ldap_users')

View File

@ -23,6 +23,7 @@ from collections import namedtuple
# if installed via pip this variable is set to true
HOME_CONFIG = False
UPDATER_AVAILABLE = True
# Base dir is parent of current file, necessary if called from different folder
if sys.version_info < (3, 0):

View File

@ -22,6 +22,7 @@ import os
import errno
import signal
import socket
import subprocess
try:
from gevent.pywsgi import WSGIServer
@ -136,6 +137,64 @@ class WebServer(object):
return sock, _readable_listen_address(*address)
def _get_args_for_reloading(self):
"""Determine how the script was executed, and return the args needed
to execute it again in a new process.
Code from https://github.com/pyload/pyload. Author GammaC0de, voulter
"""
rv = [sys.executable]
py_script = sys.argv[0]
args = sys.argv[1:]
# Need to look at main module to determine how it was executed.
__main__ = sys.modules["__main__"]
# The value of __package__ indicates how Python was called. It may
# not exist if a setuptools script is installed as an egg. It may be
# set incorrectly for entry points created with pip on Windows.
if getattr(__main__, "__package__", None) is None or (
os.name == "nt"
and __main__.__package__ == ""
and not os.path.exists(py_script)
and os.path.exists(f"{py_script}.exe")
):
# Executed a file, like "python app.py".
py_script = os.path.abspath(py_script)
if os.name == "nt":
# Windows entry points have ".exe" extension and should be
# called directly.
if not os.path.exists(py_script) and os.path.exists(f"{py_script}.exe"):
py_script += ".exe"
if (
os.path.splitext(sys.executable)[1] == ".exe"
and os.path.splitext(py_script)[1] == ".exe"
):
rv.pop(0)
rv.append(py_script)
else:
# Executed a module, like "python -m module".
if sys.argv[0] == "-m":
args = sys.argv
else:
if os.path.isfile(py_script):
# Rewritten by Python from "-m script" to "/path/to/script.py".
py_module = __main__.__package__
name = os.path.splitext(os.path.basename(py_script))[0]
if name != "__main__":
py_module += f".{name}"
else:
# Incorrectly rewritten by pydevd debugger from "-m script" to "script".
py_module = py_script
rv.extend(("-m", py_module.lstrip(".")))
rv.extend(args)
return rv
def _start_gevent(self):
ssl_args = self.ssl_args or {}
@ -199,11 +258,8 @@ class WebServer(object):
return True
log.info("Performing restart of Calibre-Web")
arguments = list(sys.argv)
arguments.insert(0, sys.executable)
if os.name == 'nt':
arguments = ["\"%s\"" % a for a in arguments]
os.execv(sys.executable, arguments)
args = self._get_args_for_reloading()
subprocess.call(args, close_fds=True)
return True
def _killServer(self, __, ___):

View File

@ -168,9 +168,11 @@
</tbody>
</table>
{% if feature_support['updater'] %}
<div class="hidden" id="update_error"> <span>{{update_error}}</span></div>
<div class="btn btn-primary" id="check_for_update">{{_('Check for Update')}}</div>
<div class="btn btn-primary hidden" id="perform_update" data-toggle="modal" data-target="#StatusDialog">{{_('Perform Update')}}</div>
{% endif %}
</div>
</div>
</div>

View File

@ -264,7 +264,7 @@ class Updater(threading.Thread):
# log_from_thread("Delete file " + item_path)
os.remove(item_path)
except OSError:
logger.debug("Could not remove: %s", item_path)
log.debug("Could not remove: %s", item_path)
shutil.rmtree(source, ignore_errors=True)
def is_venv(self):

View File

@ -1,7 +1,7 @@
# GDrive Integration
google-api-python-client>=1.7.11,<1.8.0
gevent>=1.2.1,<20.6.0
greenlet>=0.4.12,<0.4.17
gevent>20.6.0,<21.2.0
greenlet>=0.4.17,<1.1.0
httplib2>=0.9.2,<0.18.0
oauth2client>=4.0.0,<4.1.4
uritemplate>=3.0.0,<3.1.0