Destroy containers on install to cleanup previous

This commit is contained in:
Disassembler 2019-09-24 19:45:25 +02:00
parent 7591cf2d47
commit 6045349f9c
No known key found for this signature in database
GPG Key ID: 524BD33A0EE29499
4 changed files with 33 additions and 31 deletions

View File

@ -118,10 +118,12 @@ def install_app(app):
def update_app(app):
pm = PkgMgr()
app = App(app)
run_install_action(pm.update_app, app)
def uninstall_app(app):
pm = PkgMgr()
app = App(app)
run_install_action(pm.uninstall_app, app)
args = parser.parse_args()

View File

@ -109,6 +109,7 @@ class PkgMgr:
self.download_scripts(app)
# Purge old data to clean previous failed installation and unpack downloaded archives
app.stage = Stage.UNPACK
self.destroy_containers(self.online_packages['apps'][app.name]['containers'])
for image in images:
self.purge_image(image)
self.unpack_image(image)
@ -120,8 +121,7 @@ class PkgMgr:
# Run uninstall script to clean previous failed installation
self.run_uninstall_script(app.name)
# Build containers and services
self.create_containers(app.name)
# TODO: Create services
self.create_containers(self.online_packages['apps'][app.name]['containers'])
# Run install script and register the app
self.run_install_script(app.name)
self.register_app(app.name, self.online_packages['apps'][app.name])
@ -209,38 +209,38 @@ class PkgMgr:
del self.installed_packages['apps'][app]
self.save_installed_packages()
def create_containers(self, app):
def create_containers(self, containers):
# Create LXC containers from image and app metadata
for container in self.online_packages['apps'][app]['containers']:
image = self.online_packages['apps'][app]['containers'][container]['image']
for container in containers:
image = containers[container]['image']
image = self.online_packages['images'][image].copy()
if 'mounts' in self.online_packages['apps'][app]['containers'][container]:
image['mounts'] = self.online_packages['apps'][app]['containers'][container]['mounts']
if 'depends' in self.online_packages['apps'][app]['containers'][container]:
image['depends'] = self.online_packages['apps'][app]['containers'][container]['depends']
if 'mounts' in containers[container]:
image['mounts'] = containers[container]['mounts']
if 'depends' in containers[container]:
image['depends'] = containers[container]['depends']
lxcmgr.create_container(container, image)
svcmgr.create_service(app, container, image)
svcmgr.create_service(container, image)
def destroy_containers(self, containers):
# Destroy LXC containers
for container in containers:
svcmgr.delete_service(container)
lxcmgr.destroy_container(container)
@flock.flock_ex(REPO_LOCK)
def uninstall_app(self, app):
# Main uninstallation function. Wrapper for uninstall script and filesystem purge
if app not in self.installed_packages['apps']:
if app.name not in self.installed_packages['apps']:
app.stage = Stage.DONE
return
app.stage = Stage.UNINSTALL
self.run_uninstall_script(app)
self.destroy_containers(app)
self.purge_scripts(app)
self.unregister_app(app)
self.run_uninstall_script(app.name)
self.destroy_containers(self.installed_packages['apps'][app.name]['containers'])
self.purge_scripts(app.name)
self.unregister_app(app.name)
self.purge_unused_layers()
app.stage = Stage.DONE
def destroy_containers(self, app):
# Destroy LXC containers
for container in self.installed_packages['apps'][app]['containers']:
svcmgr.delete_service(container)
lxcmgr.destroy_container(container)
def purge_unused_layers(self):
# Remove layers which are no longer used by any installed application
layers = set(os.list(LXC_STORAGE_DIR))

View File

@ -6,14 +6,14 @@ import subprocess
from .paths import AUTOSTART_SVC_DIR, SERVICE_DIR, STARTED_SVC_DIR
from .templates import SERVICE
def create_service(app, container, image):
def create_service(container, image):
depends = ' '.join(image['depends']) if 'depends' in image else ''
# Add ready check to start_post
# This could arguably be better done via some template engine, but introducing one for 2 template files seems like overkill
start_post = '\nstart_post() {{\n timeout -t 60 lxc-attach {} -- sh -c \'until {}; do sleep 0.1; done\'\n}}\n'.format(container, image['ready']) if 'ready' in image else ''
service_file = os.path.join(SERVICE_DIR, container)
with open(service_file, 'w') as f:
f.write(SERVICE.format(app=app, container=container, depends=depends, start_post=start_post))
f.write(SERVICE.format(container=container, depends=depends, start_post=start_post))
os.chmod(service_file, 0o755)
update_services()
@ -24,9 +24,9 @@ def delete_service(service):
update_service_autostart(service, False)
try:
os.unlink(os.path.join(SERVICE_DIR, service))
update_services()
except FileNotFoundError:
pass
update_services()
def update_services():
subprocess.run(['/sbin/rc-update', '-u'], check=True)
@ -39,14 +39,14 @@ def stop_service(service):
if is_service_started(service):
subprocess.run(['/sbin/service', service, 'stop'], check=True)
def is_service_started(self, app):
def is_service_started(service):
# Check OpenRC service status without calling any binary
return os.path.exists(os.path.join(STARTED_SVC_DIR, app))
return os.path.exists(os.path.join(STARTED_SVC_DIR, service))
def is_service_autostarted(self, app):
def is_service_autostarted(service):
# Check OpenRC service enablement
return os.path.exists(os.path.join(AUTOSTART_SVC_DIR, app))
return os.path.exists(os.path.join(AUTOSTART_SVC_DIR, service))
def update_service_autostart(self, service, enabled):
# Add/remove the app to OpenRC default runlevel
def update_service_autostart(service, enabled):
# Add/remove the service to/from OpenRC default runlevel
subprocess.run(['/sbin/rc-update', 'add' if enabled else 'del', service])

View File

@ -51,7 +51,7 @@ lxc.include = /usr/share/lxc/config/userns.conf
SERVICE = """#!/sbin/openrc-run
description="{app} {container} LXC container"
description="{container} LXC container"
depend() {{
need cgroups {depends}