simplify pending counters, make werkzeug server threaded
This commit is contained in:
parent
951ae86520
commit
65dfff8eb0
@ -22,9 +22,7 @@ class PackageManager:
|
|||||||
# Load JSON configuration
|
# Load JSON configuration
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
self.online_packages = {}
|
self.online_packages = {}
|
||||||
self.pending = False
|
self.pending = 0
|
||||||
self.pending_to_download = 0
|
|
||||||
self.pending_downloaded = 0
|
|
||||||
|
|
||||||
def get_repo_resource(self, url, stream=False):
|
def get_repo_resource(self, url, stream=False):
|
||||||
return requests.get('{}/{}'.format(self.conf['repo']['url'], url), auth=(self.conf['repo']['user'], self.conf['repo']['pwd']), stream=stream)
|
return requests.get('{}/{}'.format(self.conf['repo']['url'], url), auth=(self.conf['repo']['user'], self.conf['repo']['pwd']), stream=stream)
|
||||||
@ -38,22 +36,21 @@ class PackageManager:
|
|||||||
pub_key.verify(packages_sig, packages, ec.ECDSA(hashes.SHA512()))
|
pub_key.verify(packages_sig, packages, ec.ECDSA(hashes.SHA512()))
|
||||||
self.online_packages = json.loads(packages)
|
self.online_packages = json.loads(packages)
|
||||||
|
|
||||||
def register_pending_installation(self):
|
def register_pending_installation(self, name):
|
||||||
# Registers pending installation. Fetch online packages here instead of install_pacakges() to fail early if the repo isn't reachable
|
# Registers pending installation. Fetch online packages here instead of install_pacakges() to fail early if the repo isn't reachable
|
||||||
self.fetch_online_packages()
|
self.fetch_online_packages()
|
||||||
self.pending = True
|
self.pending = 1
|
||||||
self.pending_to_download = 1
|
deps = [d for d in self.get_deps(name) if d not in self.conf['packages']]
|
||||||
self.pending_downloaded = 0
|
return sum(self.online_packages[d]['size'] for d in deps)
|
||||||
|
|
||||||
def install_package(self, name):
|
def install_package(self, name):
|
||||||
# Main installation function. Wrapper for download, registration and install script
|
# Main installation function. Wrapper for download, registration and install script
|
||||||
deps = d for d in self.get_deps(name) if d not in self.conf['packages']
|
deps = [d for d in self.get_deps(name) if d not in self.conf['packages']]
|
||||||
self.pending_to_download = sum(self.online_packages[d]['size'] for d in deps)
|
|
||||||
for dep in deps:
|
for dep in deps:
|
||||||
self.download_package(dep)
|
self.download_package(dep)
|
||||||
self.register_package(dep)
|
self.register_package(dep)
|
||||||
self.run_install_script(dep)
|
self.run_install_script(dep)
|
||||||
self.pending = False
|
self.pending = 0
|
||||||
|
|
||||||
def uninstall_package(self, name):
|
def uninstall_package(self, name):
|
||||||
# Main uninstallation function. Wrapper for uninstall script, filesystem purge and unregistration
|
# Main uninstallation function. Wrapper for uninstall script, filesystem purge and unregistration
|
||||||
@ -69,7 +66,7 @@ class PackageManager:
|
|||||||
with open(tmp_archive, 'wb') as f:
|
with open(tmp_archive, 'wb') as f:
|
||||||
for chunk in r.iter_content(chunk_size=65536):
|
for chunk in r.iter_content(chunk_size=65536):
|
||||||
if chunk:
|
if chunk:
|
||||||
self.pending_downloaded += f.write(chunk)
|
self.pending += f.write(chunk)
|
||||||
# Verify hash
|
# Verify hash
|
||||||
if self.online_packages[name]['sha512'] != hash_file(tmp_archive):
|
if self.online_packages[name]['sha512'] != hash_file(tmp_archive):
|
||||||
raise InvalidSignature(name)
|
raise InvalidSignature(name)
|
||||||
|
@ -141,13 +141,16 @@ class WSGIApp(object):
|
|||||||
|
|
||||||
def setup_apps_view(self, request):
|
def setup_apps_view(self, request):
|
||||||
# Application manager view.
|
# Application manager view.
|
||||||
self.pkgmgr.fetch_online_packages()
|
try:
|
||||||
|
self.pkgmgr.fetch_online_packages()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
all_apps = sorted(set([k for k,v in self.pkgmgr.online_packages.items() if 'host' in v] + list(self.conf['apps'].keys())))
|
all_apps = sorted(set([k for k,v in self.pkgmgr.online_packages.items() if 'host' in v] + list(self.conf['apps'].keys())))
|
||||||
return self.render_template('setup-apps.html', request, all_apps=all_apps, online_packages=self.pkgmgr.online_packages)
|
return self.render_template('setup-apps.html', request, all_apps=all_apps, online_packages=self.pkgmgr.online_packages)
|
||||||
|
|
||||||
def render_setup_apps_row(self, app, app_title, pending=False):
|
def render_setup_apps_row(self, app, app_title, total_size=None):
|
||||||
t = self.jinja_env.get_template('setup-apps-row.html')
|
t = self.jinja_env.get_template('setup-apps-row.html')
|
||||||
return t.render({'app': app, 'app_title': app_title, 'conf': self.conf, 'pending': pending})
|
return t.render({'app': app, 'app_title': app_title, 'conf': self.conf, 'total_size': total_size})
|
||||||
|
|
||||||
def update_host_action(self, request):
|
def update_host_action(self, request):
|
||||||
# Update domain and port, then restart nginx
|
# Update domain and port, then restart nginx
|
||||||
@ -285,19 +288,19 @@ class WSGIApp(object):
|
|||||||
return self.render_json({'error': request.session.lang.installation_in_progress()})
|
return self.render_json({'error': request.session.lang.installation_in_progress()})
|
||||||
try:
|
try:
|
||||||
app = request.form['app']
|
app = request.form['app']
|
||||||
self.pkgmgr.register_pending_installation()
|
total_size = self.pkgmgr.register_pending_installation(app)
|
||||||
except (BadRequest, InvalidValueException):
|
except (BadRequest, InvalidValueException):
|
||||||
return self.render_json({'error': request.session.lang.malformed_request()})
|
return self.render_json({'error': request.session.lang.malformed_request()})
|
||||||
except:
|
except:
|
||||||
return self.render_json({'error': request.session.lang.package_manager_error()})
|
return self.render_json({'error': request.session.lang.package_manager_error()})
|
||||||
app_title = self.pkgmgr.online_packages[app]['title']
|
app_title = self.pkgmgr.online_packages[app]['title']
|
||||||
response = self.render_json({'ok': self.render_setup_apps_row(app, app_title, True)})
|
response = self.render_json({'ok': self.render_setup_apps_row(app, app_title, round(total_size / 1048576, 1))})
|
||||||
response.call_on_close(lambda: pkgmgr.install_package(app))
|
response.call_on_close(lambda: self.pkgmgr.install_package(app))
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def get_install_progress_action(self, request):
|
def get_install_progress_action(self, request):
|
||||||
if self.pkgmgr.pending:
|
if self.pkgmgr.pending:
|
||||||
return self.render_json({'progress': '{0:.1f}'.format(self.pkgmgr.pending_downloaded / self.pkgmgr.pending_to_download)})
|
return self.render_json({'progress': round(self.pkgmgr.pending / 1048576, 1)})
|
||||||
self.conf.load()
|
self.conf.load()
|
||||||
app = request.form['app']
|
app = request.form['app']
|
||||||
app_title = self.conf['apps'][app]['title']
|
app_title = self.conf['apps'][app]['title']
|
||||||
|
@ -12,11 +12,11 @@ $(function() {
|
|||||||
.on('click', '.app-start', start_app)
|
.on('click', '.app-start', start_app)
|
||||||
.on('click', '.app-stop', stop_app)
|
.on('click', '.app-stop', stop_app)
|
||||||
.on('click', '.app-install', install_app)
|
.on('click', '.app-install', install_app)
|
||||||
.on('click', '.app-uninstall', install_app);
|
.on('click', '.app-uninstall', uninstall_app);
|
||||||
$('#update-password').on('submit', update_password);
|
$('#update-password').on('submit', update_password);
|
||||||
$('#reboot-vm').on('click', reboot_vm);
|
$('#reboot-vm').on('click', reboot_vm);
|
||||||
$('#shutdown-vm').on('click', shutdown_vm);
|
$('#shutdown-vm').on('click', shutdown_vm);
|
||||||
window.setTimeout(check_progress, 1000);
|
window.setInterval(check_progress, 1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
function update_host() {
|
function update_host() {
|
||||||
@ -146,7 +146,7 @@ function _do_app(action, ev) {
|
|||||||
$.post('/'+action+'-app', {'app': tr.data('app')}, function(data) {
|
$.post('/'+action+'-app', {'app': tr.data('app')}, function(data) {
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
td.attr('class','error').html(data.error);
|
td.attr('class','error').html(data.error);
|
||||||
} else {
|
} else if (action) {
|
||||||
tr.replaceWith(data.ok);
|
tr.replaceWith(data.ok);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -166,7 +166,7 @@ function install_app(ev) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function uninstall_app(ev) {
|
function uninstall_app(ev) {
|
||||||
if (confirm('Do you really want to uninstall this applition?')) {
|
if (confirm('Do you really want to uninstall this application?')) {
|
||||||
return _do_app('uninstall', ev);
|
return _do_app('uninstall', ev);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -176,7 +176,7 @@ function check_progress() {
|
|||||||
var progress = $('#install-progress');
|
var progress = $('#install-progress');
|
||||||
if (progress.length) {
|
if (progress.length) {
|
||||||
var tr = progress.closest('tr');
|
var tr = progress.closest('tr');
|
||||||
$.get('/get-install-progress', {'app': tr.data('app')}, function(data) {
|
$.post('/get-install-progress', {'app': tr.data('app')}, function(data) {
|
||||||
if (data.progress) {
|
if (data.progress) {
|
||||||
progress.text(data.progress);
|
progress.text(data.progress);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
<td>{{ app_title }}</td>
|
<td>{{ app_title }}</td>
|
||||||
<td class="center"><input type="checkbox" class="app-visible"{% if app not in conf['apps'] %} disabled{% elif conf['apps'][app]['visible'] %} checked{% endif %}></td>
|
<td class="center"><input type="checkbox" class="app-visible"{% if app not in conf['apps'] %} disabled{% elif conf['apps'][app]['visible'] %} checked{% endif %}></td>
|
||||||
<td class="center"><input type="checkbox" class="app-autostart"{% if app not in conf['apps'] %} disabled{% elif is_service_autostarted(app) %} checked{% endif %}></td>
|
<td class="center"><input type="checkbox" class="app-autostart"{% if app not in conf['apps'] %} disabled{% elif is_service_autostarted(app) %} checked{% endif %}></td>
|
||||||
<td>{% if pending %}Instalace (<span id="install-progress">0</span> %){% elif app not in conf['apps'] %} Není nainstalována{% elif is_service_started(app) %}<span class="info">Spuštěna</span>{% else %}<span class="error">Zastavena</span>{% endif %}</td>
|
<td>{% if total_size %}Instalace (<span id="install-progress">0</span> / {{ total_size }} MB){% elif app not in conf['apps'] %} Není nainstalována{% elif is_service_started(app) %}<span class="info">Spuštěna</span>{% else %}<span class="error">Zastavena</span>{% endif %}</td>
|
||||||
<td>{% if app not in conf['apps'] %}<a href="#" class="app-install">Instalovat</a>{% else %}{% if is_service_started(app) %}<a href="#" class="app-stop">Zastavit</a>{% else %}<a href="#" class="app-start">Spustit</a>{% endif %}, <a href="#" class="app-uninstall">Odinstalovat</a>{% endif %}</td>
|
<td>{% if total_size %}<div class="loader"></div>{% elif app not in conf['apps'] %}<a href="#" class="app-install">Instalovat</a>{% else %}{% if is_service_started(app) %}<a href="#" class="app-stop">Zastavit</a>{% else %}<a href="#" class="app-start">Spustit</a>{% endif %}, <a href="#" class="app-uninstall">Odinstalovat</a>{% endif %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -51,6 +51,9 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
{% if not online_packages %}
|
||||||
|
<p class="error">Připojení k distribučnímu serveru se nezdařilo. Zkontrolujte přístupové údaje a připojení k síti.</p>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setup-box">
|
<div class="setup-box">
|
||||||
|
@ -13,4 +13,4 @@ if __name__ == '__main__':
|
|||||||
from werkzeug.contrib.fixers import ProxyFix
|
from werkzeug.contrib.fixers import ProxyFix
|
||||||
from werkzeug.serving import run_simple
|
from werkzeug.serving import run_simple
|
||||||
|
|
||||||
run_simple('127.0.0.1', 8080, ProxyFix(application))
|
run_simple('127.0.0.1', 8080, ProxyFix(application), threaded=True)
|
||||||
|
@ -46,9 +46,9 @@ def pack(pkg_file):
|
|||||||
cwd = os.path.dirname(os.path.abspath(pkg_file))
|
cwd = os.path.dirname(os.path.abspath(pkg_file))
|
||||||
subprocess.run(['tar', '--transform', 's|^|srv/{}/|'.format(pkg_name), '-rpf', tar_path, 'install', 'install.sh', 'upgrade', 'upgrade.sh', 'uninstall', 'uninstall.sh'], cwd=cwd)
|
subprocess.run(['tar', '--transform', 's|^|srv/{}/|'.format(pkg_name), '-rpf', tar_path, 'install', 'install.sh', 'upgrade', 'upgrade.sh', 'uninstall', 'uninstall.sh'], cwd=cwd)
|
||||||
# Compress the tarball with xz (LZMA2)
|
# Compress the tarball with xz (LZMA2)
|
||||||
print('Compressing', tar_path, '({0:.2f} MB)'.format(os.path.getsize(tar_path)/1048576))
|
print('Compressing', tar_path, '({} MB)'.format(round(os.path.getsize(tar_path)/1048576, 2)))
|
||||||
subprocess.run(['xz', '-9', tar_path])
|
subprocess.run(['xz', '-9', tar_path])
|
||||||
print('Compressed ', xz_path, '({0:.2f} MB)'.format(os.path.getsize(xz_path)/1048576))
|
print('Compressed ', xz_path, '({} MB)'.format(round(os.path.getsize(xz_path)/1048576, 2)))
|
||||||
|
|
||||||
# Register package
|
# Register package
|
||||||
print('Registering package')
|
print('Registering package')
|
||||||
|
Loading…
Reference in New Issue
Block a user