Add uninstallation
This commit is contained in:
parent
65dfff8eb0
commit
780e469f82
@ -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
|
# 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 = 1
|
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)
|
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_install_deps(name) if d not in self.conf['packages']]
|
||||||
for dep in deps:
|
for dep in deps:
|
||||||
self.download_package(dep)
|
self.download_package(dep)
|
||||||
self.register_package(dep)
|
self.register_package(dep)
|
||||||
@ -54,10 +55,12 @@ class PackageManager:
|
|||||||
|
|
||||||
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
|
||||||
# TODO: Get dependencies which can be uninstalled
|
deps = self.get_install_deps(name, False)[::-1]
|
||||||
self.run_uninstall_script(name)
|
for dep in deps:
|
||||||
self.purge_package(name)
|
if dep not in self.get_uninstall_deps():
|
||||||
self.unregister_package(name)
|
self.run_uninstall_script(dep)
|
||||||
|
self.purge_package(dep)
|
||||||
|
self.unregister_package(dep)
|
||||||
|
|
||||||
def download_package(self, name):
|
def download_package(self, name):
|
||||||
# Downloads, verifies, unpacks and sets up a package
|
# Downloads, verifies, unpacks and sets up a package
|
||||||
@ -78,7 +81,7 @@ class PackageManager:
|
|||||||
# Removes package and shared data from filesystem
|
# Removes package and shared data from filesystem
|
||||||
shutil.rmtree(os.path.join(LXC_ROOT, self.conf['packages'][name]['lxcpath']))
|
shutil.rmtree(os.path.join(LXC_ROOT, self.conf['packages'][name]['lxcpath']))
|
||||||
srv_dir = os.path.join('/srv/', name)
|
srv_dir = os.path.join('/srv/', name)
|
||||||
if os.path.exsit(srv_dir):
|
if os.path.exists(srv_dir):
|
||||||
shutil.rmtree(srv_dir)
|
shutil.rmtree(srv_dir)
|
||||||
|
|
||||||
def run_install_script(self, name):
|
def run_install_script(self, name):
|
||||||
@ -123,12 +126,21 @@ class PackageManager:
|
|||||||
del self.conf['apps'][name]
|
del self.conf['apps'][name]
|
||||||
self.conf.save()
|
self.conf.save()
|
||||||
|
|
||||||
def get_deps(self, name):
|
def get_install_deps(self, name, online=True):
|
||||||
# Flatten dependency tree for a package
|
# Flatten dependency tree for a package while preserving the dependency order
|
||||||
deps = self.online_packages[name]['deps'].copy()
|
packages = self.online_packages if online else self.conf['packages']
|
||||||
for dep in deps:
|
deps = packages[name]['deps'].copy()
|
||||||
deps[:0] = [d for d in self.get_deps(dep) if d not in deps]
|
for dep in deps[::-1]:
|
||||||
deps.append(name)
|
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
|
return deps
|
||||||
|
|
||||||
def hash_file(file_path):
|
def hash_file(file_path):
|
||||||
|
@ -274,6 +274,7 @@ class WSGIApp(object):
|
|||||||
# Stops application along with its dependencies
|
# Stops application along with its dependencies
|
||||||
try:
|
try:
|
||||||
app = request.form['app']
|
app = request.form['app']
|
||||||
|
if tools.is_service_started(app):
|
||||||
self.vmmgr.stop_app(app)
|
self.vmmgr.stop_app(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()})
|
||||||
@ -294,14 +295,14 @@ class WSGIApp(object):
|
|||||||
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, 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))
|
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):
|
||||||
|
# Gets pending installation status
|
||||||
if self.pkgmgr.pending:
|
if self.pkgmgr.pending:
|
||||||
return self.render_json({'progress': round(self.pkgmgr.pending / 1048576, 1)})
|
return self.render_json({'progress': '{:.1f}'.print(self.pkgmgr.pending / 1048576)})
|
||||||
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']
|
||||||
return self.render_json({'ok': self.render_setup_apps_row(app, app_title)})
|
return self.render_json({'ok': self.render_setup_apps_row(app, app_title)})
|
||||||
@ -310,16 +311,14 @@ class WSGIApp(object):
|
|||||||
# Uninstalls application
|
# Uninstalls application
|
||||||
try:
|
try:
|
||||||
app = request.form['app']
|
app = request.form['app']
|
||||||
|
app_title = self.conf['apps'][app]['title']
|
||||||
self.vmmgr.stop_app(app)
|
self.vmmgr.stop_app(app)
|
||||||
pkgmgr = PackageManager()
|
self.pkgmgr.uninstall_package(app)
|
||||||
pkgmgr.uninstall_package(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()})
|
raise
|
||||||
# Get title from old data, then reload config
|
# return self.render_json({'error': request.session.lang.package_manager_error()})
|
||||||
app_title = self.conf['apps'][app]['title']
|
|
||||||
self.conf.load()
|
|
||||||
return self.render_json({'ok': self.render_setup_apps_row(app, app_title)})
|
return self.render_json({'ok': self.render_setup_apps_row(app, app_title)})
|
||||||
|
|
||||||
def update_password_action(self, request):
|
def update_password_action(self, request):
|
||||||
|
@ -16,7 +16,7 @@ $(function() {
|
|||||||
$('#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.setInterval(check_progress, 1000);
|
window.setInterval(check_progress, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
function update_host() {
|
function update_host() {
|
||||||
|
@ -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, '({} 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])
|
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
|
# Register package
|
||||||
print('Registering package')
|
print('Registering package')
|
||||||
|
Loading…
Reference in New Issue
Block a user