Add uninstallation

This commit is contained in:
Disassembler 2018-10-26 21:52:06 +02:00
parent 65dfff8eb0
commit 780e469f82
Signed by: Disassembler
GPG Key ID: 524BD33A0EE29499
4 changed files with 37 additions and 26 deletions

View File

@ -40,12 +40,13 @@ class PackageManager:
# 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.pending = 1
deps = [d for d in self.get_deps(name) if d not in self.conf['packages']]
# Return total size for download
deps = [d for d in self.get_install_deps(name) if d not in self.conf['packages']]
return sum(self.online_packages[d]['size'] for d in deps)
def install_package(self, name):
# 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_install_deps(name) if d not in self.conf['packages']]
for dep in deps:
self.download_package(dep)
self.register_package(dep)
@ -54,10 +55,12 @@ class PackageManager:
def uninstall_package(self, name):
# Main uninstallation function. Wrapper for uninstall script, filesystem purge and unregistration
# TODO: Get dependencies which can be uninstalled
self.run_uninstall_script(name)
self.purge_package(name)
self.unregister_package(name)
deps = self.get_install_deps(name, False)[::-1]
for dep in deps:
if dep not in self.get_uninstall_deps():
self.run_uninstall_script(dep)
self.purge_package(dep)
self.unregister_package(dep)
def download_package(self, name):
# Downloads, verifies, unpacks and sets up a package
@ -78,7 +81,7 @@ class PackageManager:
# Removes package and shared data from filesystem
shutil.rmtree(os.path.join(LXC_ROOT, self.conf['packages'][name]['lxcpath']))
srv_dir = os.path.join('/srv/', name)
if os.path.exsit(srv_dir):
if os.path.exists(srv_dir):
shutil.rmtree(srv_dir)
def run_install_script(self, name):
@ -123,12 +126,21 @@ class PackageManager:
del self.conf['apps'][name]
self.conf.save()
def get_deps(self, name):
# Flatten dependency tree for a package
deps = self.online_packages[name]['deps'].copy()
for dep in deps:
deps[:0] = [d for d in self.get_deps(dep) if d not in deps]
deps.append(name)
def get_install_deps(self, name, online=True):
# Flatten dependency tree for a package while preserving the dependency order
packages = self.online_packages if online else self.conf['packages']
deps = packages[name]['deps'].copy()
for dep in deps[::-1]:
deps[:0] = [d for d in self.get_install_deps(dep, online)]
deps = list(dict.fromkeys(deps + [name]))
return deps
def get_uninstall_deps(self):
# Create reverse dependency tree for all installed packages
deps = {}
for pkg in self.conf['packages']:
for d in self.conf['packages'][pkg]['deps']:
deps.setdefault(d, []).append(pkg)
return deps
def hash_file(file_path):

View File

@ -274,7 +274,8 @@ class WSGIApp(object):
# Stops application along with its dependencies
try:
app = request.form['app']
self.vmmgr.stop_app(app)
if tools.is_service_started(app):
self.vmmgr.stop_app(app)
except (BadRequest, InvalidValueException):
return self.render_json({'error': request.session.lang.malformed_request()})
except:
@ -294,14 +295,14 @@ class WSGIApp(object):
except:
return self.render_json({'error': request.session.lang.package_manager_error()})
app_title = self.pkgmgr.online_packages[app]['title']
response = self.render_json({'ok': self.render_setup_apps_row(app, app_title, round(total_size / 1048576, 1))})
response = self.render_json({'ok': self.render_setup_apps_row(app, app_title, '{:.1f}'.print(total_size / 1048576))})
response.call_on_close(lambda: self.pkgmgr.install_package(app))
return response
def get_install_progress_action(self, request):
# Gets pending installation status
if self.pkgmgr.pending:
return self.render_json({'progress': round(self.pkgmgr.pending / 1048576, 1)})
self.conf.load()
return self.render_json({'progress': '{:.1f}'.print(self.pkgmgr.pending / 1048576)})
app = request.form['app']
app_title = self.conf['apps'][app]['title']
return self.render_json({'ok': self.render_setup_apps_row(app, app_title)})
@ -310,16 +311,14 @@ class WSGIApp(object):
# Uninstalls application
try:
app = request.form['app']
app_title = self.conf['apps'][app]['title']
self.vmmgr.stop_app(app)
pkgmgr = PackageManager()
pkgmgr.uninstall_package(app)
self.pkgmgr.uninstall_package(app)
except (BadRequest, InvalidValueException):
return self.render_json({'error': request.session.lang.malformed_request()})
except:
return self.render_json({'error': request.session.lang.package_manager_error()})
# Get title from old data, then reload config
app_title = self.conf['apps'][app]['title']
self.conf.load()
raise
# return self.render_json({'error': request.session.lang.package_manager_error()})
return self.render_json({'ok': self.render_setup_apps_row(app, app_title)})
def update_password_action(self, request):

View File

@ -16,7 +16,7 @@ $(function() {
$('#update-password').on('submit', update_password);
$('#reboot-vm').on('click', reboot_vm);
$('#shutdown-vm').on('click', shutdown_vm);
window.setInterval(check_progress, 1000);
window.setInterval(check_progress, 2000);
});
function update_host() {

View File

@ -46,9 +46,9 @@ def pack(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)
# Compress the tarball with xz (LZMA2)
print('Compressing', tar_path, '({} MB)'.format(round(os.path.getsize(tar_path)/1048576, 2)))
print('Compressing', tar_path, '({0:.2f} MB)'.format(os.path.getsize(tar_path)/1048576))
subprocess.run(['xz', '-9', tar_path])
print('Compressed ', xz_path, '({} MB)'.format(round(os.path.getsize(xz_path)/1048576, 2)))
print('Compressed ', xz_path, '({0:.2f} MB)'.format(os.path.getsize(xz_path)/1048576))
# Register package
print('Registering package')