2020-02-06 19:00:41 +01:00
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import argparse
import os
2020-02-19 23:13:46 +01:00
from pkg_resources import parse_version
2020-02-06 19:00:41 +01:00
2020-03-26 21:32:16 +01:00
from spoc import repo_local, repo_online, repo_publish
2020-02-19 23:13:46 +01:00
from spoc.app import App
2020-03-12 20:56:52 +01:00
from spoc.cli import ActionQueue, print_lock, readable_size
from spoc.config import LOCK_FILE
from spoc.flock import locked
2020-02-22 16:32:49 +01:00
from spoc.image import Image
2020-02-06 19:00:41 +01:00
2020-02-19 23:13:46 +01:00
def listing(list_type):
2020-03-26 20:29:27 +01:00
# Lists applications in particular state
2020-02-19 23:13:46 +01:00
if list_type == 'installed':
apps = repo_local.get_apps()
elif list_type == 'online':
apps = repo_online.get_apps()
elif list_type == 'updates':
online_apps = repo_online.get_apps()
2020-04-10 20:19:53 +02:00
apps = [a for a,d in repo_local.get_apps().items() if a in online_apps and parse_version(online_apps[a]['version']) > parse_version(d['version'])]
2020-02-19 23:13:46 +01:00
elif list_type == 'published':
apps = repo_publish.get_apps()
for app in apps:
print(app)
2020-02-06 19:00:41 +01:00
2020-03-12 20:56:52 +01:00
@locked(LOCK_FILE, print_lock)
2020-02-22 16:32:49 +01:00
def install(app_name):
2020-03-26 20:29:27 +01:00
# Install application from online repository
2020-02-22 16:32:49 +01:00
queue = ActionQueue()
required_images = []
for container in repo_online.get_app(app_name)['containers'].values():
required_images.extend(repo_online.get_image(container['image'])['layers'])
local_images = repo_local.get_images()
for layer in set(required_images):
if layer not in local_images:
queue.download_image(Image(layer, False))
2020-03-26 20:29:27 +01:00
queue.install_app(App(app_name, False, False))
2020-02-22 16:32:49 +01:00
queue.process()
2020-02-06 19:00:41 +01:00
2020-03-12 20:56:52 +01:00
@locked(LOCK_FILE, print_lock)
2020-02-22 16:32:49 +01:00
def update(app_name):
2020-03-26 20:29:27 +01:00
# Update application from online repository
queue = ActionQueue()
required_images = []
for container in repo_online.get_app(app_name)['containers'].values():
required_images.extend(repo_online.get_image(container['image'])['layers'])
local_images = repo_local.get_images()
for layer in set(required_images):
if layer not in local_images:
queue.download_image(Image(layer, False))
queue.update_app(App(app_name, False))
queue.process()
2020-02-06 19:00:41 +01:00
2020-03-12 20:56:52 +01:00
@locked(LOCK_FILE, print_lock)
2020-02-22 16:32:49 +01:00
def uninstall(app_name):
2020-03-26 20:29:27 +01:00
# Remove application and its containers from local repository
queue = ActionQueue()
queue.uninstall_app(App(app_name, False))
queue.process()
2020-02-06 19:00:41 +01:00
2020-02-22 16:32:49 +01:00
def start(app_name):
2020-03-26 20:29:27 +01:00
# Start all application containers
2020-04-03 15:14:06 +02:00
queue = ActionQueue()
queue.start_app(App(app_name))
queue.process()
2020-02-06 19:00:41 +01:00
2020-02-22 16:32:49 +01:00
def stop(app_name):
2020-03-26 20:29:27 +01:00
# Stop all application containers
2020-04-03 15:14:06 +02:00
queue = ActionQueue()
queue.stop_app(App(app_name))
queue.process()
2020-02-06 19:00:41 +01:00
2020-02-22 16:32:49 +01:00
def status(app_name):
2020-03-26 20:29:27 +01:00
# Print status of all application containers
2020-02-22 16:32:49 +01:00
for container,status in App(app_name).status():
print(f'{container}: {status}')
2020-02-06 19:00:41 +01:00
2020-02-19 23:13:46 +01:00
def publish(filename, force):
app_name = os.path.basename(os.path.dirname(os.path.abspath(filename)))
2020-02-06 19:00:41 +01:00
# Check if publishing is needed and attempt to publish the application
2020-02-19 23:13:46 +01:00
if force or app_name not in repo_publish.get_apps():
2020-04-03 23:46:35 +02:00
app = App(app_name, False, False)
2020-02-19 23:13:46 +01:00
print(f'Publishing application {app_name} from file {os.path.abspath(filename)}')
app.unpublish()
size, dlsize = app.publish(filename)
print(f'Application {app_name} compressed from {readable_size(size)} to {readable_size(dlsize)} and published successfully')
2020-02-06 19:00:41 +01:00
else:
2020-02-19 23:13:46 +01:00
print(f'Application {app_name} already published, skipping publish task')
2020-02-06 19:00:41 +01:00
2020-02-19 23:13:46 +01:00
def unpublish(app_name):
2020-03-26 20:29:27 +01:00
# Remove the application from publish repo
2020-03-26 19:47:15 +01:00
App(app_name, False, False).unpublish()
2020-02-06 19:00:41 +01:00
2020-03-26 20:09:10 +01:00
def autostart(app_name, value):
2020-03-26 20:29:27 +01:00
# Set if the application should be autostarted on boot
2020-03-26 19:30:37 +01:00
value = value.lower() in ('1', 'on', 'enable', 'true')
App(app_name, False).set_autostart(value)
2020-03-26 20:09:10 +01:00
def start_autostarted():
2020-03-26 20:29:27 +01:00
# Start all applications (resp. their containers) which are set to be autoostarted on boot
2020-04-10 20:19:53 +02:00
apps = [App(a) for a,d in repo_local.get_apps().items() if d['autostart']]
2020-03-26 20:09:10 +01:00
for app in apps:
app.start()
def stop_all():
2020-03-26 20:29:27 +01:00
# Stop all applications (resp. their containers)
2020-04-10 20:19:53 +02:00
apps = [App(a) for a,d in repo_local.get_apps().items()]
2020-03-26 20:09:10 +01:00
for app in apps:
app.stop()
2020-02-06 19:00:41 +01:00
parser = argparse.ArgumentParser(description='SPOC application manager')
parser.set_defaults(action=None)
subparsers = parser.add_subparsers()
parser_list = subparsers.add_parser('list')
2020-02-18 12:33:54 +01:00
parser_list.set_defaults(action=listing)
2020-02-19 23:13:46 +01:00
parser_list.add_argument('type', choices=('installed', 'online', 'updates', 'published'), default='installed', const='installed', nargs='?')
2020-02-06 19:00:41 +01:00
parser_install = subparsers.add_parser('install')
2020-02-18 12:33:54 +01:00
parser_install.set_defaults(action=install)
2020-02-06 19:00:41 +01:00
parser_install.add_argument('app')
2020-02-22 16:32:49 +01:00
parser_update = subparsers.add_parser('update')
parser_update.set_defaults(action=update)
parser_update.add_argument('app')
2020-02-06 19:00:41 +01:00
parser_uninstall = subparsers.add_parser('uninstall')
2020-02-18 12:33:54 +01:00
parser_uninstall.set_defaults(action=uninstall)
2020-02-06 19:00:41 +01:00
parser_uninstall.add_argument('app')
parser_start = subparsers.add_parser('start')
2020-02-18 12:33:54 +01:00
parser_start.set_defaults(action=start)
2020-02-06 19:00:41 +01:00
parser_start.add_argument('app')
parser_stop = subparsers.add_parser('stop')
2020-02-18 12:33:54 +01:00
parser_stop.set_defaults(action=stop)
2020-02-06 19:00:41 +01:00
parser_stop.add_argument('app')
parser_status = subparsers.add_parser('status')
2020-02-18 12:33:54 +01:00
parser_status.set_defaults(action=status)
2020-02-06 19:00:41 +01:00
parser_status.add_argument('app')
parser_publish = subparsers.add_parser('publish')
2020-02-18 12:33:54 +01:00
parser_publish.set_defaults(action=publish)
2020-02-06 19:00:41 +01:00
parser_publish.add_argument('-f', '--force', action='store_true', help='Force republish already published application')
2020-02-19 23:13:46 +01:00
parser_publish.add_argument('filename')
2020-02-06 19:00:41 +01:00
parser_unpublish = subparsers.add_parser('unpublish')
2020-02-18 12:33:54 +01:00
parser_unpublish.set_defaults(action=unpublish)
2020-02-06 19:00:41 +01:00
parser_unpublish.add_argument('app')
2020-03-26 19:30:37 +01:00
parser_autostart = subparsers.add_parser('autostart')
parser_autostart.set_defaults(action=autostart)
2020-03-26 20:09:10 +01:00
parser_autostart.add_argument('app')
2020-03-26 19:30:37 +01:00
parser_autostart.add_argument('value', choices=('1', 'on', 'enable', 'true', '0', 'off', 'disable', 'false'), help='Sets the applications to be automatically started after the host boots up')
2020-03-26 20:09:10 +01:00
parser_start_autostarted = subparsers.add_parser('start-autostarted')
parser_start_autostarted.set_defaults(action=start_autostarted)
parser_stop_all = subparsers.add_parser('stop-all')
parser_stop_all.set_defaults(action=stop_all)
2020-02-06 19:00:41 +01:00
args = parser.parse_args()
2020-02-18 12:33:54 +01:00
if args.action is listing:
2020-02-06 19:00:41 +01:00
listing(args.type)
2020-02-18 12:33:54 +01:00
elif args.action is install:
2020-02-06 19:00:41 +01:00
install(args.app)
2020-02-22 16:32:49 +01:00
elif args.action is update:
update(args.app)
2020-02-18 12:33:54 +01:00
elif args.action is uninstall:
2020-02-06 19:00:41 +01:00
uninstall(args.app)
2020-02-18 12:33:54 +01:00
elif args.action is start:
2020-02-06 19:00:41 +01:00
start(args.app)
2020-02-18 12:33:54 +01:00
elif args.action is stop:
2020-02-06 19:00:41 +01:00
stop(args.app)
2020-02-18 12:33:54 +01:00
elif args.action is status:
2020-02-06 19:00:41 +01:00
status(args.app)
2020-02-18 12:33:54 +01:00
elif args.action is publish:
2020-02-19 23:13:46 +01:00
publish(args.filename, args.force)
2020-02-18 12:33:54 +01:00
elif args.action is unpublish:
2020-02-06 19:00:41 +01:00
unpublish(args.app)
2020-03-26 19:30:37 +01:00
elif args.action is autostart:
2020-03-26 20:09:10 +01:00
autostart(args.app, args.value)
elif args.action is start_autostarted:
start_autostarted()
elif args.action is stop_all:
stop_all()
2020-02-06 19:00:41 +01:00
else:
parser.print_usage()