VMMgr: Unify config, add pkg size
This commit is contained in:
parent
efdd1b1c68
commit
7abe6af068
@ -1,16 +1,15 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
from . import config
|
||||||
from . import tools
|
from . import tools
|
||||||
from . import validator
|
from . import validator
|
||||||
|
|
||||||
VERSION = '0.0.1'
|
VERSION = '0.0.1'
|
||||||
|
|
||||||
CONF_FILE = '/srv/vm/config.json'
|
|
||||||
ISSUE_FILE = '/etc/issue'
|
ISSUE_FILE = '/etc/issue'
|
||||||
NGINX_DIR = '/etc/nginx/conf.d'
|
NGINX_DIR = '/etc/nginx/conf.d'
|
||||||
ACME_CRON = '/etc/periodic/daily/acme-sh'
|
ACME_CRON = '/etc/periodic/daily/acme-sh'
|
||||||
@ -124,16 +123,10 @@ subjectAltName=DNS:{domain},DNS:*.{domain}"
|
|||||||
class VMMgr:
|
class VMMgr:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# Load JSON configuration
|
# Load JSON configuration
|
||||||
with open(CONF_FILE, 'r') as f:
|
self.conf = config.Config()
|
||||||
self.conf = json.load(f)
|
|
||||||
self.domain = self.conf['host']['domain']
|
self.domain = self.conf['host']['domain']
|
||||||
self.port = self.conf['host']['port']
|
self.port = self.conf['host']['port']
|
||||||
|
|
||||||
def save_conf(self):
|
|
||||||
# Save a sorted JSON configuration object with indentation
|
|
||||||
with open(CONF_FILE, 'w') as f:
|
|
||||||
json.dump(self.conf, f, sort_keys=True, indent=4)
|
|
||||||
|
|
||||||
def update_login(self, app, login, password):
|
def update_login(self, app, login, password):
|
||||||
# Update login and password for an app in the configuration
|
# Update login and password for an app in the configuration
|
||||||
if not validator.is_valid_app(app, self.conf):
|
if not validator.is_valid_app(app, self.conf):
|
||||||
@ -142,21 +135,21 @@ class VMMgr:
|
|||||||
self.conf['apps'][app]['login'] = login
|
self.conf['apps'][app]['login'] = login
|
||||||
if password is not None:
|
if password is not None:
|
||||||
self.conf['apps'][app]['password'] = password
|
self.conf['apps'][app]['password'] = password
|
||||||
self.save_conf()
|
self.conf.save()
|
||||||
|
|
||||||
def show_tiles(self, app):
|
def show_tiles(self, app):
|
||||||
# Update visibility for the app in the configuration
|
# Update visibility for the app in the configuration
|
||||||
if not validator.is_valid_app(app, self.conf):
|
if not validator.is_valid_app(app, self.conf):
|
||||||
raise validator.InvalidValueException('app', app)
|
raise validator.InvalidValueException('app', app)
|
||||||
self.conf['apps'][app]['visible'] = True
|
self.conf['apps'][app]['visible'] = True
|
||||||
self.save_conf()
|
self.conf.save()
|
||||||
|
|
||||||
def hide_tiles(self, app):
|
def hide_tiles(self, app):
|
||||||
# Update visibility for the app in the configuration
|
# Update visibility for the app in the configuration
|
||||||
if not validator.is_valid_app(app, self.conf):
|
if not validator.is_valid_app(app, self.conf):
|
||||||
raise validator.InvalidValueException('app', app)
|
raise validator.InvalidValueException('app', app)
|
||||||
self.conf['apps'][app]['visible'] = False
|
self.conf['apps'][app]['visible'] = False
|
||||||
self.save_conf()
|
self.conf.save()
|
||||||
|
|
||||||
def start_app(self, app):
|
def start_app(self, app):
|
||||||
# Start the actual app service
|
# Start the actual app service
|
||||||
@ -268,7 +261,7 @@ class VMMgr:
|
|||||||
raise validator.InvalidValueException('port', port)
|
raise validator.InvalidValueException('port', port)
|
||||||
self.domain = self.conf['host']['domain'] = domain
|
self.domain = self.conf['host']['domain'] = domain
|
||||||
self.port = self.conf['host']['port'] = port
|
self.port = self.conf['host']['port'] = port
|
||||||
self.save_conf()
|
self.conf.save()
|
||||||
# Restart all apps to trigger configuration refresh
|
# Restart all apps to trigger configuration refresh
|
||||||
for app in self.conf['apps']:
|
for app in self.conf['apps']:
|
||||||
if tools.is_service_started(app):
|
if tools.is_service_started(app):
|
||||||
@ -309,7 +302,7 @@ class VMMgr:
|
|||||||
# Update Google Maps API key
|
# Update Google Maps API key
|
||||||
self.conf['common']['gmaps-api-key'] = gmaps_api_key
|
self.conf['common']['gmaps-api-key'] = gmaps_api_key
|
||||||
# Save config to file
|
# Save config to file
|
||||||
self.save_conf()
|
self.conf.save()
|
||||||
for app in self.conf['apps']:
|
for app in self.conf['apps']:
|
||||||
# Restart currently running apps in order to update their config
|
# Restart currently running apps in order to update their config
|
||||||
if tools.is_service_started(app):
|
if tools.is_service_started(app):
|
||||||
@ -322,7 +315,7 @@ class VMMgr:
|
|||||||
# Update bcrypt-hashed password in config
|
# Update bcrypt-hashed password in config
|
||||||
self.conf['host']['adminpwd'] = tools.adminpwd_hash(newpassword)
|
self.conf['host']['adminpwd'] = tools.adminpwd_hash(newpassword)
|
||||||
# Save config to file
|
# Save config to file
|
||||||
self.save_conf()
|
self.conf.save()
|
||||||
|
|
||||||
def create_selfsigned(self):
|
def create_selfsigned(self):
|
||||||
# Create selfsigned certificate with wildcard alternative subject name
|
# Create selfsigned certificate with wildcard alternative subject name
|
||||||
|
17
basic/srv/vm/mgr/config.py
Normal file
17
basic/srv/vm/mgr/config.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
CONF_FILE = '/srv/vm/config.json'
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
def __init__(self):
|
||||||
|
with open(CONF_FILE, 'r') as f:
|
||||||
|
self.data = json.load(f)
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
with open(CONF_FILE, 'w') as f:
|
||||||
|
json.dump(self.data, f, sort_keys=True, indent=4)
|
||||||
|
|
||||||
|
def __getitem__(self, attr):
|
||||||
|
return self.data[attr]
|
@ -14,23 +14,18 @@ from cryptography.hazmat.primitives import hashes
|
|||||||
from cryptography.hazmat.primitives.asymmetric import ec
|
from cryptography.hazmat.primitives.asymmetric import ec
|
||||||
from cryptography.hazmat.primitives.serialization import load_pem_public_key
|
from cryptography.hazmat.primitives.serialization import load_pem_public_key
|
||||||
|
|
||||||
CONF_FILE = '/srv/vm/config.json'
|
from . import config
|
||||||
|
|
||||||
PUB_FILE = '/srv/vm/packages.pub'
|
PUB_FILE = '/srv/vm/packages.pub'
|
||||||
LXC_ROOT = '/var/lib/lxc'
|
LXC_ROOT = '/var/lib/lxc'
|
||||||
|
|
||||||
class PackageManager:
|
class PackageManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# Load JSON configuration
|
# Load JSON configuration
|
||||||
with open(CONF_FILE, 'r') as f:
|
self.conf = config.Config()
|
||||||
self.conf = json.load(f)
|
|
||||||
self.repo_url = self.conf['host']['repo']
|
self.repo_url = self.conf['host']['repo']
|
||||||
self.online_packages = {}
|
self.online_packages = {}
|
||||||
|
|
||||||
def save_conf(self):
|
|
||||||
# Save a sorted JSON configuration object with indentation
|
|
||||||
with open(CONF_FILE, 'w') as f:
|
|
||||||
json.dump(self.conf, f, sort_keys=True, indent=4)
|
|
||||||
|
|
||||||
def fetch_online_packages(self):
|
def fetch_online_packages(self):
|
||||||
# Fetches and verifies online packages. Can raise InvalidSignature
|
# Fetches and verifies online packages. Can raise InvalidSignature
|
||||||
packages = requests.get('{}/packages'.format(self.repo_url)).content
|
packages = requests.get('{}/packages'.format(self.repo_url)).content
|
||||||
@ -41,6 +36,7 @@ class PackageManager:
|
|||||||
self.online_packages = json.loads(packages)
|
self.online_packages = json.loads(packages)
|
||||||
|
|
||||||
def install_package(self, name):
|
def install_package(self, name):
|
||||||
|
# Main installation function. Wrapper for download, registration and setup
|
||||||
self.fetch_online_packages()
|
self.fetch_online_packages()
|
||||||
for dep in self.get_deps(name):
|
for dep in self.get_deps(name):
|
||||||
if dep not in self.conf['packages']:
|
if dep not in self.conf['packages']:
|
||||||
@ -64,10 +60,12 @@ class PackageManager:
|
|||||||
os.unlink(tmp_archive)
|
os.unlink(tmp_archive)
|
||||||
|
|
||||||
def register_package(self, name):
|
def register_package(self, name):
|
||||||
|
# Registers a package in local configuration
|
||||||
metadata = self.online_packages[name]
|
metadata = self.online_packages[name]
|
||||||
self.conf['packages'][name] = {
|
self.conf['packages'][name] = {
|
||||||
'version': metadata['version'],
|
'version': metadata['version'],
|
||||||
}
|
}
|
||||||
|
# If host definition is present, register the package as application
|
||||||
if 'host' in metadata:
|
if 'host' in metadata:
|
||||||
self.conf['apps'][name] = {
|
self.conf['apps'][name] = {
|
||||||
'title': metadata['title'],
|
'title': metadata['title'],
|
||||||
@ -76,9 +74,10 @@ class PackageManager:
|
|||||||
'password': 'N/A',
|
'password': 'N/A',
|
||||||
'visible': False
|
'visible': False
|
||||||
}
|
}
|
||||||
self.save_conf()
|
self.conf.save()
|
||||||
|
|
||||||
def setup_package(self):
|
def setup_package(self):
|
||||||
|
# Runs setup.sh for a package, if the script is present
|
||||||
setup_dir = os.path.join(LXC_ROOT, 'setup')
|
setup_dir = os.path.join(LXC_ROOT, 'setup')
|
||||||
setup_script = os.path.join(LXC_ROOT, 'setup.sh')
|
setup_script = os.path.join(LXC_ROOT, 'setup.sh')
|
||||||
if os.path.exists(setup_script):
|
if os.path.exists(setup_script):
|
||||||
@ -88,6 +87,7 @@ class PackageManager:
|
|||||||
shutil.rmtree(setup_dir)
|
shutil.rmtree(setup_dir)
|
||||||
|
|
||||||
def get_deps(self, name):
|
def get_deps(self, name):
|
||||||
|
# Flatten dependency tree for a package
|
||||||
deps = self.online_packages[name]['deps'].copy()
|
deps = self.online_packages[name]['deps'].copy()
|
||||||
for dep in deps:
|
for dep in deps:
|
||||||
deps[:0] = [d for d in self.get_deps(dep) if d not in deps]
|
deps[:0] = [d for d in self.get_deps(dep) if d not in deps]
|
||||||
|
@ -54,6 +54,7 @@ def pack(pkg_file):
|
|||||||
with open(packages_file, 'r') as f:
|
with open(packages_file, 'r') as f:
|
||||||
packages = json.load(f)
|
packages = json.load(f)
|
||||||
packages[pkg_name] = meta
|
packages[pkg_name] = meta
|
||||||
|
packages[pkg_name]['size'] = os.path.getsize(xz_path)
|
||||||
packages[pkg_name]['sha512'] = hash_file(xz_path)
|
packages[pkg_name]['sha512'] = hash_file(xz_path)
|
||||||
with open(packages_file, 'w') as f:
|
with open(packages_file, 'w') as f:
|
||||||
json.dump(packages, f, sort_keys=True, indent=4)
|
json.dump(packages, f, sort_keys=True, indent=4)
|
||||||
|
Loading…
Reference in New Issue
Block a user