Implement actual update function, lazy-load online_packages

This commit is contained in:
Disassembler 2019-10-17 08:11:10 +02:00
parent ecb09001d4
commit be36199640
No known key found for this signature in database
GPG Key ID: 524BD33A0EE29499
3 changed files with 40 additions and 37 deletions

View File

@ -56,7 +56,6 @@ def print_apps(packages):
def list_online():
pm = PkgMgr()
pm.fetch_online_packages()
apps = pm.online_packages['apps']
if apps:
print_apps(apps)

View File

@ -15,6 +15,10 @@ from . import lxcmgr
from . import svcmgr
from .paths import LXC_STORAGE_DIR, REPO_CACHE_DIR, REPO_CONF_FILE, REPO_LOCAL_FILE, REPO_LOCK, REPO_SIG_FILE
INSTALL_SCRIPT = 'install.sh'
UPDATE_SCRIPT = 'update.sh'
UNINSTALL_SCRIPT = 'uninstall.sh'
class Stage(Enum):
QUEUED = 1
DOWNLOAD = 2
@ -49,10 +53,20 @@ class PkgMgr:
def __init__(self):
self.repo_url = None
self.repo_auth = None
self.online_packages = None
self._online_packages = None
with open(REPO_LOCAL_FILE, 'r') as f:
self.installed_packages = json.load(f)
@property
def online_packages(self):
if not self._online_packages:
# Fetches and verifies online packages. Can raise InvalidSignature
packages = self.get_repo_resource('packages').content
packages_sig = self.get_repo_resource('packages.sig').content
crypto.verify_signature(REPO_SIG_FILE, packages, packages_sig)
self._online_packages = json.loads(packages)
return self._online_packages
def save_installed_packages(self):
with open(REPO_LOCAL_FILE, 'w') as f:
json.dump(self.installed_packages, f, sort_keys=True, indent=4)
@ -79,21 +93,26 @@ class PkgMgr:
raise RepoBadRequest(r.url)
return r
def fetch_online_packages(self):
# Fetches and verifies online packages. Can raise InvalidSignature
packages = self.get_repo_resource('packages').content
packages_sig = self.get_repo_resource('packages.sig').content
crypto.verify_signature(REPO_SIG_FILE, packages, packages_sig)
self.online_packages = json.loads(packages)
@flock.flock_ex(REPO_LOCK)
def install_app(self, app):
# Main installation function. Wrapper for download, registration and install script
if app.name in self.installed_packages['apps']:
app.stage = Stage.DONE
return
if not self.online_packages:
self.fetch_online_packages()
self.download_and_unpack_deps(app)
# Run setup scripts
app.stage = Stage.INSTALL
# Run uninstall script to clean previous failed installation
self.run_script(app.name, UNINSTALL_SCRIPT)
# Build containers and services
self.create_containers(self.online_packages['apps'][app.name]['containers'])
# Run install script and register the app
self.run_script(app.name, INSTALL_SCRIPT)
self.register_app(app.name, self.online_packages['apps'][app.name])
app.stage = Stage.DONE
def download_and_unpack_deps(self, app):
# Common download and unpack function for install and update
# Get all packages on which the app and its containers depend and which have not been installed yet
images = []
image_deps = [container['image'] for container in self.online_packages['apps'][app.name]['containers'].values()]
@ -116,16 +135,6 @@ class PkgMgr:
self.register_image(image, self.online_packages['images'][image])
self.purge_scripts(app.name)
self.unpack_scripts(app.name)
# Run setup scripts
app.stage = Stage.INSTALL
# Run uninstall script to clean previous failed installation
self.run_uninstall_script(app.name)
# Build containers and 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])
app.stage = Stage.DONE
def download_image(self, app, image):
# Download image archive and verify hash
@ -184,14 +193,6 @@ class PkgMgr:
subprocess.run(['tar', 'xJf', tmp_archive], cwd=os.path.join(REPO_CACHE_DIR, 'apps'), check=True)
os.unlink(tmp_archive)
def run_uninstall_script(self, app):
# Runs uninstall.sh for an app, if the script is present
self.run_script(app, 'uninstall.sh')
def run_install_script(self, app):
# Runs install.sh for a package, if the script is present
self.run_script(app, 'install.sh')
def run_script(self, app, script):
# Runs script for an app, if the script is present
script_dir = os.path.join(REPO_CACHE_DIR, 'apps', app)
@ -239,7 +240,7 @@ class PkgMgr:
app.stage = Stage.DONE
return
app.stage = Stage.UNINSTALL
self.run_uninstall_script(app.name)
self.run_script(app.name, UNINSTALL_SCRIPT)
self.destroy_containers(self.installed_packages['apps'][app.name]['containers'])
self.purge_scripts(app.name)
self.unregister_app(app.name)
@ -259,17 +260,20 @@ class PkgMgr:
self.purge_layer(layer)
@flock.flock_ex(REPO_LOCK)
def update_app(self, app, item):
def update_app(self, app):
# Main update function.
# TODO: Implement actual update
uninstall_app(app)
install_app(app, item)
self.download_and_unpack_deps(app)
# Run setup scripts
app.stage = Stage.UPDATE
# Build containers and services
self.create_containers(self.online_packages['apps'][app.name]['containers'])
# Run update script and register the app
self.run_script(app.name, UPDATE_SCRIPT)
self.register_app(app.name, self.online_packages['apps'][app.name])
app.stage = Stage.DONE
def has_update(self, app):
# Check if online repository list a newer version of app
if not self.online_packages:
self.fetch_online_packages()
if app not in self.online_packages['apps']:
# Application has been removed from online repo
return False

View File

@ -174,7 +174,7 @@ class WSGIApp:
# Application manager view.
repo_error = None
try:
self.appmgr.pkgmgr.fetch_online_packages()
self.appmgr.pkgmgr.fetch_online_packages() # TODO: fetch is now automatic in @property
except InvalidSignature:
repo_error = request.session.lang.invalid_packages_signature()
except Unauthorized: