Don't instantiate vmmgr on every request. Only reload config.
This commit is contained in:
parent
7abe6af068
commit
867a5d4d69
@ -6,6 +6,9 @@ CONF_FILE = '/srv/vm/config.json'
|
|||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.load()
|
||||||
|
|
||||||
|
def load(self):
|
||||||
with open(CONF_FILE, 'r') as f:
|
with open(CONF_FILE, 'r') as f:
|
||||||
self.data = json.load(f)
|
self.data = json.load(f)
|
||||||
|
|
||||||
|
@ -20,7 +20,9 @@ SESSION_KEY = os.urandom(26)
|
|||||||
|
|
||||||
class WSGIApp(object):
|
class WSGIApp(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.vmmgr = VMMgr()
|
||||||
self.jinja_env = Environment(loader=FileSystemLoader('/srv/vm/templates'), autoescape=True, lstrip_blocks=True, trim_blocks=True)
|
self.jinja_env = Environment(loader=FileSystemLoader('/srv/vm/templates'), autoescape=True, lstrip_blocks=True, trim_blocks=True)
|
||||||
|
self.jinja_env.globals.update(is_app_visible=self.is_app_visible)
|
||||||
self.jinja_env.globals.update(is_service_autostarted=tools.is_service_autostarted)
|
self.jinja_env.globals.update(is_service_autostarted=tools.is_service_autostarted)
|
||||||
self.jinja_env.globals.update(is_service_started=tools.is_service_started)
|
self.jinja_env.globals.update(is_service_started=tools.is_service_started)
|
||||||
|
|
||||||
@ -29,8 +31,9 @@ class WSGIApp(object):
|
|||||||
|
|
||||||
def wsgi_app(self, environ, start_response):
|
def wsgi_app(self, environ, start_response):
|
||||||
request = Request(environ)
|
request = Request(environ)
|
||||||
|
# Reload VM Manager config in case it has changed
|
||||||
|
self.vmmgr.conf.load()
|
||||||
# Enhance request
|
# Enhance request
|
||||||
request.mgr = VMMgr()
|
|
||||||
request.session = WSGISession(request.cookies, SESSION_KEY)
|
request.session = WSGISession(request.cookies, SESSION_KEY)
|
||||||
request.session.lang = WSGILang()
|
request.session.lang = WSGILang()
|
||||||
# Dispatch request
|
# Dispatch request
|
||||||
@ -81,7 +84,7 @@ class WSGIApp(object):
|
|||||||
|
|
||||||
def render_template(self, template_name, request, **context):
|
def render_template(self, template_name, request, **context):
|
||||||
# Enhance context
|
# Enhance context
|
||||||
context['conf'] = request.mgr.conf
|
context['conf'] = self.vmmgr.conf
|
||||||
context['session'] = request.session
|
context['session'] = request.session
|
||||||
# Render template
|
# Render template
|
||||||
t = self.jinja_env.get_template(template_name)
|
t = self.jinja_env.get_template(template_name)
|
||||||
@ -95,7 +98,7 @@ class WSGIApp(object):
|
|||||||
|
|
||||||
def login_action(self, request):
|
def login_action(self, request):
|
||||||
password = request.form['password']
|
password = request.form['password']
|
||||||
if tools.adminpwd_verify(password, request.mgr.conf['host']['adminpwd']):
|
if tools.adminpwd_verify(password, self.vmmgr.conf['host']['adminpwd']):
|
||||||
request.session['admin'] = True
|
request.session['admin'] = True
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
else:
|
else:
|
||||||
@ -106,13 +109,22 @@ class WSGIApp(object):
|
|||||||
return redirect('/')
|
return redirect('/')
|
||||||
|
|
||||||
def portal_view(self, request):
|
def portal_view(self, request):
|
||||||
# Default view. If domain is set to the default dummy domain, redirects to first-run setup instead.
|
# Default portal view. If this is the first run, perform first-run setup.
|
||||||
|
if self.vmmgr.conf['host']['firstrun']:
|
||||||
|
# Set user as admin
|
||||||
|
request.session['admin'] = True
|
||||||
|
# Disable and save first-run flag
|
||||||
|
self.vmmgr.conf['host']['firstrun'] = False
|
||||||
|
self.vmmgr.conf.save()
|
||||||
|
# Redirect to host setup view
|
||||||
|
return redirect('/setup-host')
|
||||||
|
host = tools.compile_url(self.vmmgr.conf['host']['domain'], self.vmmgr.conf['host']['port'], None)
|
||||||
if request.session['admin']:
|
if request.session['admin']:
|
||||||
return self.render_template('portal-admin.html', request)
|
return self.render_template('portal-admin.html', request, host=host)
|
||||||
return self.render_template('portal-user.html', request)
|
return self.render_template('portal-user.html', request, host=host)
|
||||||
|
|
||||||
def setup_host_view(self, request):
|
def setup_host_view(self, request):
|
||||||
# First-run setup view.
|
# Host setup view.
|
||||||
ex_ipv4 = tools.get_external_ipv4()
|
ex_ipv4 = tools.get_external_ipv4()
|
||||||
ex_ipv6 = tools.get_external_ipv6()
|
ex_ipv6 = tools.get_external_ipv6()
|
||||||
in_ipv4 = tools.get_local_ipv4()
|
in_ipv4 = tools.get_local_ipv4()
|
||||||
@ -130,7 +142,7 @@ class WSGIApp(object):
|
|||||||
try:
|
try:
|
||||||
domain = request.form['domain']
|
domain = request.form['domain']
|
||||||
port = request.form['port']
|
port = request.form['port']
|
||||||
request.mgr.update_host(domain, port, False)
|
self.vmmgr.update_host(domain, port, False)
|
||||||
server_name = request.environ['HTTP_X_FORWARDED_SERVER_NAME']
|
server_name = request.environ['HTTP_X_FORWARDED_SERVER_NAME']
|
||||||
url = '{}/setup-host'.format(tools.compile_url(server_name, port))
|
url = '{}/setup-host'.format(tools.compile_url(server_name, port))
|
||||||
response = self.render_json({'ok': request.session.lang.host_updated(url, url)})
|
response = self.render_json({'ok': request.session.lang.host_updated(url, url)})
|
||||||
@ -146,8 +158,7 @@ class WSGIApp(object):
|
|||||||
|
|
||||||
def verify_dns_action(self, request):
|
def verify_dns_action(self, request):
|
||||||
# Check if all FQDNs for all applications are resolvable and point to current external IP
|
# Check if all FQDNs for all applications are resolvable and point to current external IP
|
||||||
mgr = request.mgr
|
domains = [self.vmmgr.domain]+['{}.{}'.format(self.vmmgr.conf['apps'][app]['host'], self.vmmgr.domain) for app in self.vmmgr.conf['apps']]
|
||||||
domains = [mgr.domain]+['{}.{}'.format(mgr.conf['apps'][app]['host'], mgr.domain) for app in mgr.conf['apps']]
|
|
||||||
ipv4 = tools.get_external_ipv4()
|
ipv4 = tools.get_external_ipv4()
|
||||||
ipv6 = tools.get_external_ipv6()
|
ipv6 = tools.get_external_ipv6()
|
||||||
for domain in domains:
|
for domain in domains:
|
||||||
@ -167,9 +178,8 @@ class WSGIApp(object):
|
|||||||
def verify_http_action(self, request, **kwargs):
|
def verify_http_action(self, request, **kwargs):
|
||||||
# Check if all applications are accessible from the internet using 3rd party ping service
|
# Check if all applications are accessible from the internet using 3rd party ping service
|
||||||
proto = kwargs['proto']
|
proto = kwargs['proto']
|
||||||
mgr = request.mgr
|
port = self.vmmgr.port if proto == 'https' else '80'
|
||||||
port = mgr.port if proto == 'https' else '80'
|
domains = [self.vmmgr.domain]+['{}.{}'.format(self.vmmgr.conf['apps'][app]['host'], self.vmmgr.domain) for app in self.vmmgr.conf['apps']]
|
||||||
domains = [mgr.domain]+['{}.{}'.format(mgr.conf['apps'][app]['host'], mgr.domain) for app in mgr.conf['apps']]
|
|
||||||
for domain in domains:
|
for domain in domains:
|
||||||
url = tools.compile_url(domain, port, proto)
|
url = tools.compile_url(domain, port, proto)
|
||||||
try:
|
try:
|
||||||
@ -191,22 +201,22 @@ class WSGIApp(object):
|
|||||||
return self.render_json({'error': request.session.lang.key_file_missing()})
|
return self.render_json({'error': request.session.lang.key_file_missing()})
|
||||||
request.files['public'].save('/tmp/public.pem')
|
request.files['public'].save('/tmp/public.pem')
|
||||||
request.files['private'].save('/tmp/private.pem')
|
request.files['private'].save('/tmp/private.pem')
|
||||||
request.mgr.install_cert('/tmp/public.pem', '/tmp/private.pem')
|
self.vmmgr.install_cert('/tmp/public.pem', '/tmp/private.pem')
|
||||||
os.unlink('/tmp/public.pem')
|
os.unlink('/tmp/public.pem')
|
||||||
os.unlink('/tmp/private.pem')
|
os.unlink('/tmp/private.pem')
|
||||||
else:
|
else:
|
||||||
request.mgr.request_cert()
|
self.vmmgr.request_cert()
|
||||||
except BadRequest:
|
except BadRequest:
|
||||||
return self.render_json({'error': request.session.lang.malformed_request()})
|
return self.render_json({'error': request.session.lang.malformed_request()})
|
||||||
except:
|
except:
|
||||||
return self.render_json({'error': request.session.lang.cert_request_error()})
|
return self.render_json({'error': request.session.lang.cert_request_error()})
|
||||||
url = tools.compile_url(request.mgr.domain, request.mgr.port)
|
url = tools.compile_url(self.vmmgr.domain, self.vmmgr.port)
|
||||||
return self.render_json({'ok': request.session.lang.cert_installed(url, url)})
|
return self.render_json({'ok': request.session.lang.cert_installed(url, url)})
|
||||||
|
|
||||||
def update_common_action(self, request):
|
def update_common_action(self, request):
|
||||||
# Update common settings shared between apps - admin e-mail address, Google Maps API key
|
# Update common settings shared between apps - admin e-mail address, Google Maps API key
|
||||||
try:
|
try:
|
||||||
request.mgr.update_common(request.form['email'], request.form['gmaps-api-key'])
|
self.vmmgr.update_common(request.form['email'], request.form['gmaps-api-key'])
|
||||||
except BadRequest:
|
except BadRequest:
|
||||||
return self.render_json({'error': request.session.lang.malformed_request()})
|
return self.render_json({'error': request.session.lang.malformed_request()})
|
||||||
return self.render_json({'ok': request.session.lang.common_updated()})
|
return self.render_json({'ok': request.session.lang.common_updated()})
|
||||||
@ -215,9 +225,9 @@ class WSGIApp(object):
|
|||||||
# Update application visibility on portal page
|
# Update application visibility on portal page
|
||||||
try:
|
try:
|
||||||
if request.form['value'] == 'true':
|
if request.form['value'] == 'true':
|
||||||
request.mgr.show_tiles(request.form['app'])
|
self.vmmgr.show_tiles(request.form['app'])
|
||||||
else:
|
else:
|
||||||
request.mgr.hide_tiles(request.form['app'])
|
self.vmmgr.hide_tiles(request.form['app'])
|
||||||
except (BadRequest, InvalidValueException):
|
except (BadRequest, InvalidValueException):
|
||||||
return self.render_json({'error': request.session.lang.malformed_request()})
|
return self.render_json({'error': request.session.lang.malformed_request()})
|
||||||
return self.render_json({'ok': 'ok'})
|
return self.render_json({'ok': 'ok'})
|
||||||
@ -226,9 +236,9 @@ class WSGIApp(object):
|
|||||||
# Update value determining if the app should be automatically started after VM boot
|
# Update value determining if the app should be automatically started after VM boot
|
||||||
try:
|
try:
|
||||||
if request.form['value'] == 'true':
|
if request.form['value'] == 'true':
|
||||||
request.mgr.enable_autostart(request.form['app'])
|
self.vmmgr.enable_autostart(request.form['app'])
|
||||||
else:
|
else:
|
||||||
request.mgr.disable_autostart(request.form['app'])
|
self.vmmgr.disable_autostart(request.form['app'])
|
||||||
except (BadRequest, InvalidValueException):
|
except (BadRequest, InvalidValueException):
|
||||||
return self.render_json({'error': request.session.lang.malformed_request()})
|
return self.render_json({'error': request.session.lang.malformed_request()})
|
||||||
return self.render_json({'ok': 'ok'})
|
return self.render_json({'ok': 'ok'})
|
||||||
@ -236,7 +246,7 @@ class WSGIApp(object):
|
|||||||
def start_app_action(self, request):
|
def start_app_action(self, request):
|
||||||
# Starts application along with its dependencies
|
# Starts application along with its dependencies
|
||||||
try:
|
try:
|
||||||
request.mgr.start_app(request.form['app'])
|
self.vmmgr.start_app(request.form['app'])
|
||||||
except (BadRequest, InvalidValueException):
|
except (BadRequest, InvalidValueException):
|
||||||
return self.render_json({'error': request.session.lang.malformed_request()})
|
return self.render_json({'error': request.session.lang.malformed_request()})
|
||||||
except:
|
except:
|
||||||
@ -246,7 +256,7 @@ class WSGIApp(object):
|
|||||||
def stop_app_action(self, request):
|
def stop_app_action(self, request):
|
||||||
# Stops application along with its dependencies
|
# Stops application along with its dependencies
|
||||||
try:
|
try:
|
||||||
request.mgr.stop_app(request.form['app'])
|
self.vmmgr.stop_app(request.form['app'])
|
||||||
except (BadRequest, InvalidValueException):
|
except (BadRequest, InvalidValueException):
|
||||||
return self.render_json({'error': request.session.lang.malformed_request()})
|
return self.render_json({'error': request.session.lang.malformed_request()})
|
||||||
except:
|
except:
|
||||||
@ -254,14 +264,14 @@ class WSGIApp(object):
|
|||||||
return self.render_json({'ok': request.session.lang.app_stopped()})
|
return self.render_json({'ok': request.session.lang.app_stopped()})
|
||||||
|
|
||||||
def update_password_action(self, request):
|
def update_password_action(self, request):
|
||||||
# Updates password for both HDD encryption (LUKS-on-LVM) and admin account to vmmgr
|
# Updates password for both HDD encryption (LUKS-on-LVM) and web interface admin account
|
||||||
try:
|
try:
|
||||||
if request.form['newpassword'] != request.form['newpassword2']:
|
if request.form['newpassword'] != request.form['newpassword2']:
|
||||||
return self.render_json({'error': request.session.lang.password_mismatch()})
|
return self.render_json({'error': request.session.lang.password_mismatch()})
|
||||||
if request.form['newpassword'] == '':
|
if request.form['newpassword'] == '':
|
||||||
return self.render_json({'error': request.session.lang.password_empty()})
|
return self.render_json({'error': request.session.lang.password_empty()})
|
||||||
# No need to explicitly validate old password, update_luks_password will raise exception if it's wrong
|
# No need to explicitly validate old password, update_luks_password will raise exception if it's wrong
|
||||||
request.mgr.update_password(request.form['oldpassword'], request.form['newpassword'])
|
self.vmmgr.update_password(request.form['oldpassword'], request.form['newpassword'])
|
||||||
except:
|
except:
|
||||||
return self.render_json({'error': request.session.lang.bad_password()})
|
return self.render_json({'error': request.session.lang.bad_password()})
|
||||||
return self.render_json({'ok': request.session.lang.password_changed()})
|
return self.render_json({'ok': request.session.lang.password_changed()})
|
||||||
@ -278,5 +288,8 @@ class WSGIApp(object):
|
|||||||
response.call_on_close(tools.shutdown_vm)
|
response.call_on_close(tools.shutdown_vm)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def is_app_visible(self, app):
|
||||||
|
return app in self.vmmgr.conf['apps'] and self.vmmgr.conf['apps'][app]['visible'] and tools.is_service_started(app)
|
||||||
|
|
||||||
class InvalidRecordException(Exception):
|
class InvalidRecordException(Exception):
|
||||||
pass
|
pass
|
||||||
|
Loading…
Reference in New Issue
Block a user