diff --git a/usr/lib/python3.8/spoc/app.py b/usr/lib/python3.8/spoc/app.py index dbf5cf7..b67c402 100644 --- a/usr/lib/python3.8/spoc/app.py +++ b/usr/lib/python3.8/spoc/app.py @@ -14,6 +14,8 @@ from .config import APPS_DIR, ONLINE_APPS_URL, PUB_APPS_DIR, TMP_APPS_DIR, LAYER from .container import Container from .image import Image +DEFINITION_MEMBERS = {'version', 'meta', 'autostart', 'containers'} + class App: def __init__(self, name, define_containers=True, load_from_repo=True): self.name = name @@ -26,20 +28,25 @@ class App: self.set_definition(repo_local.get_app(name), define_containers) def set_definition(self, definition, define_containers): - self.version = definition['version'] - self.meta = definition['meta'] - self.autostart = definition['autostart'] + # Set attributes given by definition + for key in DEFINITION_MEMBERS.intersection(definition): + setattr(self, key, definition[key]) + # Populate containers property with actual container objects self.containers = [Container(container, define_containers) for container in definition['containers']] def get_definition(self): - return { - 'version': self.version, - 'meta': self.meta.copy(), - 'autostart': self.autostart, - 'containers': [container.name for container in self.containers] - } + # Return shallow copy of image definition as dictionary + definition = {} + for key in DEFINITION_MEMBERS: + value = getattr(self, key) + if value: + definition[key] = copy.copy(value) + # Overwrite containers key with list of container names + definition['containers'] = [container.name for container in self.containers] + return definition def download(self, observer): + # Download the archive with application scripts and install data os.makedirs(TMP_APPS_DIR, 0o700, True) archive_url = urllib.parse.urljoin(ONLINE_APPS_URL, f'{self.name}.tar.xz') archive_path = os.path.join(TMP_APPS_DIR, f'{self.name}.tar.xz') @@ -48,6 +55,7 @@ class App: repo_online.download_archive(archive_url, archive_path, definition['hash'], observer) def unpack_downloaded(self, observer): + # Unpack downloaded archive with application scripts and install data archive_path = os.path.join(TMP_APPS_DIR, f'{self.name}.tar.xz') definition = repo_online.get_app(self.name) observer.units_total = definition['size'] @@ -66,6 +74,7 @@ class App: subprocess.run(script_path, cwd=cwd, env=env, check=True) def create_container(self, name, definition): + # Create container and enhance its definition (typically mounts) based on application requirements container = Container(name, False) container.set_definition(Image(definition['image']).get_definition()) if 'depends' in definition: @@ -78,6 +87,7 @@ class App: self.containers.append(container) def install(self): + # Install the application definition = repo_online.get_app(self.name) self.version = definition['version'] self.meta = definition['meta'] @@ -121,17 +131,26 @@ class App: pass def start(self): + # Start all application containers for container in self.containers: container.start() def stop(self): + # Stop all application containers for container in self.containers: container.stop() def status(self): + # Return status fo all application containers return {container.name:container.get_state() for container in sorted(self.containers)} + def set_autostart(self, autostart): + # Configure if the application should be automatically started after boot + self.autostart = autostart + repo_local.register_app(self.name, self.get_definition()) + def publish(self, filename): + # Create application archive and register to publish repository builddir = os.path.dirname(filename) os.makedirs(PUB_APPS_DIR, 0o755, True) files = repo_publish.TarSizeCounter() @@ -150,13 +169,10 @@ class App: return (definition['size'], definition['dlsize']) def unpublish(self): + # Remove the application from publish repository repo_publish.unregister_app(self.name) archive_path = os.path.join(PUB_APPS_DIR, f'{self.name}.tar.xz') try: os.unlink(archive_path) except FileNotFoundError: pass - - def set_autostart(self, autostart): - self.autostart = autostart - repo_local.register_app(self.name, self.get_definition()) diff --git a/usr/lib/python3.8/spoc/container.py b/usr/lib/python3.8/spoc/container.py index 10cf973..60135cc 100644 --- a/usr/lib/python3.8/spoc/container.py +++ b/usr/lib/python3.8/spoc/container.py @@ -53,6 +53,7 @@ class Container: self.set_definition(repo_local.get_container(name)) def set_definition(self, definition): + # Set attributes given by definition for key in DEFINITION_MEMBERS.intersection(definition): setattr(self, key, definition[key]) diff --git a/usr/lib/python3.8/spoc/image.py b/usr/lib/python3.8/spoc/image.py index 6475b17..28ecdc4 100644 --- a/usr/lib/python3.8/spoc/image.py +++ b/usr/lib/python3.8/spoc/image.py @@ -29,6 +29,7 @@ class Image: self.set_definition(repo_local.get_image(name)) def set_definition(self, definition): + # Set attributes given by definition for key in DEFINITION_MEMBERS.intersection(definition): setattr(self, key, definition[key]) @@ -50,6 +51,7 @@ class Image: repo_local.register_image(self.name, self.get_definition()) def delete(self): + # Remove the layer from local repository and filesystem repo_local.unregister_image(self.name) try: shutil.rmtree(self.layer_path) @@ -57,6 +59,7 @@ class Image: pass def download(self, observer): + # Download the archive with layer data os.makedirs(TMP_LAYERS_DIR, 0o700, True) archive_url = urllib.parse.urljoin(ONLINE_LAYERS_URL, f'{self.name}.tar.xz') archive_path = os.path.join(TMP_LAYERS_DIR, f'{self.name}.tar.xz') @@ -65,6 +68,7 @@ class Image: repo_online.download_archive(archive_url, archive_path, definition['hash'], observer) def unpack_downloaded(self, observer): + # Unpack downloaded archive with layer data archive_path = os.path.join(TMP_LAYERS_DIR, f'{self.name}.tar.xz') definition = repo_online.get_image(self.name) observer.units_total = definition['size'] @@ -73,6 +77,7 @@ class Image: repo_local.register_image(self.name, definition) def publish(self): + # Create layer archive and register to publish repository os.makedirs(PUB_LAYERS_DIR, 0o755, True) files = repo_publish.TarSizeCounter() archive_path = os.path.join(PUB_LAYERS_DIR, f'{self.name}.tar.xz') @@ -86,6 +91,7 @@ class Image: return (definition['size'], definition['dlsize']) def unpublish(self): + # Remove the layer from publish repository repo_publish.unregister_image(self.name) archive_path = os.path.join(PUB_LAYERS_DIR, f'{self.name}.tar.xz') try: