Reorganize vm/lxc/app functions

This commit is contained in:
Disassembler 2019-02-19 16:05:21 +01:00
parent c213b0c0d8
commit 050b26f11f
No known key found for this signature in database
GPG Key ID: 524BD33A0EE29499
7 changed files with 102 additions and 119 deletions

View File

@ -2,7 +2,9 @@
# -*- coding: utf-8 -*-
import argparse
from vmmgr import Config, LXCMgr, VMMgr
from vmmgr import lxcmgr
from vmmgr.config import Config
from vmmgr.vmmgr import VMMgr
parser = argparse.ArgumentParser(description='VM application manager')
subparsers = parser.add_subparsers()
@ -38,9 +40,7 @@ parser_unregister_proxy.set_defaults(action='unregister-proxy')
parser_unregister_proxy.add_argument('app', help='Application name')
args = parser.parse_args()
conf = Config()
vmmgr = VMMgr(conf)
lxcmgr = LXCMgr(conf)
vmmgr = VMMgr(Config())
if args.action == 'register-app':
# Used by app install scripts
vmmgr.register_app(args.app, args.login, args.password)
@ -58,7 +58,7 @@ elif args.action == 'unregister-container':
lxcmgr.unregister_container()
elif args.action == 'register-proxy':
# Used in init scripts
lxcmgr.register_proxy(args.app, args.host)
vmmgr.register_proxy(args.app, args.host)
elif args.action == 'unregister-proxy':
# Used in init scripts
lxcmgr.unregister_proxy(args.app)
vmmgr.unregister_proxy(args.app)

View File

@ -1,15 +1 @@
# -*- coding: utf-8 -*-
from .appmgr import AppMgr
from .config import Config
from .lxcmgr import LXCMgr
from .vmmgr import VMMgr
from .wsgiapp import WSGIApp
__all__ = [
'AppMgr',
'Config',
'LXCMgr',
'VMMgr',
'WSGIApp'
]

View File

@ -114,15 +114,3 @@ class AppMgr:
except:
pass
return []
def update_common_settings(self, email, gmaps_api_key):
# Update common configuration values
self.conf['common']['email'] = email
self.conf['common']['gmaps-api-key'] = gmaps_api_key
self.conf.save()
def shutdown_vm(self):
subprocess.run(['/sbin/poweroff'])
def reboot_vm(self):
subprocess.run(['/sbin/reboot'])

View File

@ -6,22 +6,18 @@ import shutil
import subprocess
from . import templates
from .config import Config
from .paths import HOSTS_FILE, HOSTS_LOCK, LXC_ROOT, NGINX_DIR
class LXCMgr:
def __init__(self, conf):
# Load JSON configuration
self.conf = conf
def prepare_container(self):
def prepare_container():
# Extract the variables from values given via lxc.hook.pre-start hook
app = os.environ['LXC_NAME']
# Remove ephemeral layer data
self.clean_ephemeral_layer(app)
clean_ephemeral_layer(app)
# Configure host and common params used in the app
self.configure_app(app)
configure_app(app)
def clean_ephemeral_layer(self, app):
def clean_ephemeral_layer(app):
# Cleans containers ephemeral layer.
# This is done early in the container start process, so the inode of the delta0 directory must remain unchanged
layer = os.path.join(LXC_ROOT, app, 'delta0')
@ -29,25 +25,25 @@ class LXCMgr:
for item in os.scandir(layer):
shutil.rmtree(item.path) if item.is_dir() else os.unlink(item.path)
def register_container(self):
def register_container():
# Extract the variables from values given via lxc.hook.start-host hook
app = os.environ['LXC_NAME']
pid = os.environ['LXC_PID']
# Lease the first unused IP to the container
ip = self.update_hosts_lease(app, True)
ip = update_hosts_lease(app, True)
# Set IP in container based on PID given via lxc.hook.start-host hook
cmd = 'ip addr add {}/16 broadcast 172.17.255.255 dev eth0 && ip route add default via 172.17.0.1'.format(ip)
subprocess.run(['nsenter', '-a', '-t', pid, '--', '/bin/sh', '-c', cmd])
def unregister_container(self):
def unregister_container():
# Extract the variables from values given via lxc.hook.post-stop hook
app = os.environ['LXC_NAME']
# Release the container IP
self.update_hosts_lease(app, False)
update_hosts_lease(app, False)
# Remove ephemeral layer data
self.clean_ephemeral_layer(app)
clean_ephemeral_layer(app)
def update_hosts_lease(self, app, is_request):
def update_hosts_lease(app, is_request):
# This is a poor man's DHCP server which uses /etc/hosts as lease database
# Leases the first unused IP from range 172.17.0.0/16
# Uses file lock as interprocess mutex
@ -74,24 +70,14 @@ class LXCMgr:
f.write('{} {}\n'.format(lease[0], lease[1]))
return ip
def configure_app(self, app):
def configure_app(app):
# Supply common configuration for the application. Done as part of container preparation during service startup
script = os.path.join('/srv', app, 'update-conf.sh')
if os.path.exists(script):
conf = Config()
setup_env = os.environ.copy()
setup_env['DOMAIN'] = self.conf['host']['domain']
setup_env['PORT'] = self.conf['host']['port']
setup_env['EMAIL'] = self.conf['common']['email']
setup_env['GMAPS_API_KEY'] = self.conf['common']['gmaps-api-key']
setup_env['DOMAIN'] = conf['host']['domain']
setup_env['PORT'] = conf['host']['port']
setup_env['EMAIL'] = conf['common']['email']
setup_env['GMAPS_API_KEY'] = conf['common']['gmaps-api-key']
subprocess.run([script], env=setup_env, check=True)
def register_proxy(self, app, host):
# Setup proxy configuration and reload nginx
with open(os.path.join(NGINX_DIR, '{}.conf'.format(app)), 'w') as f:
f.write(templates.NGINX.format(app=app, host=host, domain=self.conf['host']['domain'], port=self.conf['host']['port']))
self.reload_nginx()
def unregister_proxy(self, app):
# Remove proxy configuration and reload nginx
os.unlink(os.path.join(NGINX_DIR, '{}.conf'.format(app)))
self.reload_nginx()

View File

@ -21,7 +21,7 @@ class VMMgr:
def register_app(self, app, login, password):
# Register newly installed application, its metadata and credentials
with open('/var/lib/lxcpkgs/{app}/meta'.format(app)) as f:
with open('/var/lib/lxcpkgs/{}/meta'.format(app)) as f:
meta = json.load(f)
self.conf['apps'][app] = {**meta,
'login': login if login else 'N/A',
@ -34,6 +34,17 @@ class VMMgr:
except:
pass
def register_proxy(self, app, host):
# Setup proxy configuration and reload nginx
with open(os.path.join(NGINX_DIR, '{}.conf'.format(app)), 'w') as f:
f.write(templates.NGINX.format(app=app, host=host, domain=self.conf['host']['domain'], port=self.conf['host']['port']))
self.reload_nginx()
def unregister_proxy(self, app):
# Remove proxy configuration and reload nginx
os.unlink(os.path.join(NGINX_DIR, '{}.conf'.format(app)))
self.reload_nginx()
def update_host(self, domain, port):
# Update domain and port and rebuild all configuration. Web interface calls restart_nginx() in WSGI close handler
self.domain = self.conf['host']['domain'] = domain
@ -58,6 +69,12 @@ class VMMgr:
with open(ISSUE_FILE, 'w') as f:
f.write(templates.ISSUE.format(url=net.compile_url(self.domain, self.port), ip=net.compile_url(net.get_local_ip(), self.port)))
def update_common_settings(self, email, gmaps_api_key):
# Update common configuration values
self.conf['common']['email'] = email
self.conf['common']['gmaps-api-key'] = gmaps_api_key
self.conf.save()
def update_password(self, oldpassword, newpassword):
# Update LUKS password and adminpwd for WSGI application
pwinput = '{}\n{}'.format(oldpassword, newpassword).encode()
@ -135,3 +152,9 @@ class VMMgr:
os.chmod(crypto.CERT_KEY_FILE, 0o640)
# Reload nginx
self.reload_nginx()
def shutdown_vm(self):
subprocess.run(['/sbin/poweroff'])
def reboot_vm(self):
subprocess.run(['/sbin/reboot'])

View File

@ -308,7 +308,7 @@ class WSGIApp:
if not validator.is_valid_email(email):
request.session['msg'] = 'common:error:{}'.format(request.session.lang.invalid_email(email))
else:
self.appmgr.update_common_settings(email, request.form['gmaps-api-key'])
self.vmmgr.update_common_settings(email, request.form['gmaps-api-key'])
request.session['msg'] = 'common:info:{}'.format(request.session.lang.common_updated())
return redirect('/setup-apps')
@ -380,13 +380,13 @@ class WSGIApp:
def reboot_vm_action(self, request):
# Reboots VM
response = self.render_json({'ok': request.session.lang.reboot_initiated()})
response.call_on_close(self.appmgr.reboot_vm)
response.call_on_close(self.vmmgr.reboot_vm)
return response
def shutdown_vm_action(self, request):
# Shuts down VM
response = self.render_json({'ok': request.session.lang.shutdown_initiated()})
response.call_on_close(self.appmgr.shutdown_vm)
response.call_on_close(self.vmmgr.shutdown_vm)
return response
def reload_config_action(self, request):

View File

@ -1,7 +1,7 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from vmmgr import WSGIApp
from vmmgr.wsgiapp import WSGIApp
application = WSGIApp()