Commit 2ed93a9c authored by Stavros Sachtouris's avatar Stavros Sachtouris Committed by Giorgos Korfiatis
Browse files

Launch the server in a different process

To achieve this, a new method "wait_session_to_load" is
implemented in the SessioHelper class, which blocks the execution
until a server session (any server session) is loaded.

The SessionHelper does not create a new session on instantiation.
Now the caller has to explicitly ask the helper to load a session
or create a new one.
parent f6e4a770
......@@ -81,11 +81,15 @@ class GUI(WebSocketBaseClient):
def run():
"""Prepare SessionHelper and GUI and run them in the proper order"""
helper = SessionHelper()
gui = GUI(helper.session)
LOG.info('Start SessionHelper session')
helper.start()
subprocess.Popen([
os.path.join(CURPATH, 'scripts/cli.py'), 'launch_server'])
LOG.info('Client blocks until session is ready')
session = SessionHelper().wait_session_to_load()
assert session, 'UI server failed to load...'
LOG.info('Server session is ready, setup the GUI session')
gui = GUI(session)
try:
LOG.info('Start GUI')
......@@ -93,8 +97,6 @@ def run():
except KeyboardInterrupt:
LOG.info('Shutdown GUI')
gui.clean_exit()
LOG.info('Shutdown SessionHelper server')
helper.shutdown()
if __name__ == '__main__':
logging.basicConfig(filename='agkyra.log', level=logging.DEBUG)
......
#!/usr/bin/env python
# Copyright (C) 2015 GRNET S.A.
#
# This program is free software: you can redistribute it and/or modify
......@@ -46,12 +48,14 @@ class SessionHelper(object):
LOG.debug('Connect to db')
self.db = sqlite3.connect(self.session_db)
self._init_db_relation()
self.session = self._load_active_session() or self._create_session()
# self.session = self._load_active_session() or self._create_session()
self.db.close()
# self.db.close()
def _init_db_relation(self):
"""Create the session relation"""
self.db.execute('BEGIN')
self.db.execute(
'CREATE TABLE IF NOT EXISTS %s ('
......@@ -59,7 +63,7 @@ class SessionHelper(object):
')' % self.session_relation)
self.db.commit()
def _load_active_session(self):
def load_active_session(self):
"""Load a session from db"""
r = self.db.execute('SELECT * FROM %s' % self.session_relation)
sessions = r.fetchall()
......@@ -71,7 +75,7 @@ class SessionHelper(object):
return dict(ui_id=last[0], address=last[1])
return None
def _create_session(self):
def create_session(self):
"""Create session credentials"""
ui_id = sha1(os.urandom(128)).hexdigest()
......@@ -84,6 +88,7 @@ class SessionHelper(object):
server_class=WSGIServer,
handler_class=WebSocketWSGIRequestHandler,
app=WebSocketWSGIApplication(handler_cls=WebSocketProtocol))
WebSocketProtocol.server = server
server.initialize_websockets_manager()
address = 'ws://%s:%s' % (LOCAL_ADDR, server.server_port)
self.server = server
......@@ -96,6 +101,19 @@ class SessionHelper(object):
return dict(ui_id=ui_id, address=address)
def wait_session_to_load(self, timeout=20, step=2):
"""Wait while the session is loading e.g. in another process
:returns: the session or None if timeout
"""
time_passed = 0
while time_passed < timeout:
self.session = self.load_active_session()
if self.session:
return self.session
time_passed += step
time.sleep(step)
return None
def start(self):
"""Start the helper server in a thread"""
if getattr(self, 'server', None):
......@@ -167,7 +185,7 @@ class WebSocketProtocol(WebSocket):
"""
ui_id = None
db, session_db, session_relation = None, None, None
session_db, session_relation = None, None
accepted = False
settings = dict(
token=None, url=None,
......@@ -180,13 +198,12 @@ class WebSocketProtocol(WebSocket):
essentials = ('url', 'token', 'container', 'directory')
def heartbeat(self):
if not self.db:
self.db = sqlite3.connect(self.session_db)
db = sqlite3.connect(self.session_db)
while True:
self.db.execute('BEGIN')
self.db.execute('UPDATE %s SET beat="%s" WHERE ui_id="%s"' % (
db.execute('BEGIN')
db.execute('UPDATE %s SET beat="%s" WHERE ui_id="%s"' % (
self.session_relation, time.time(), self.ui_id))
self.db.commit()
db.commit()
time.sleep(2)
def _get_default_sync(self):
......@@ -404,10 +421,11 @@ class WebSocketProtocol(WebSocket):
def clean_db(self):
"""Clean DB from session traces"""
LOG.debug('Remove session traces')
self.db = sqlite3.connect(self.session_db)
self.db.execute('BEGIN')
self.db.execute('DELETE FROM %s' % self.session_relation)
self.db.commit()
db = sqlite3.connect(self.session_db)
db.execute('BEGIN')
db.execute('DELETE FROM %s' % self.session_relation)
db.commit()
db.close()
def send_json(self, msg):
LOG.debug('send: %s' % msg)
......@@ -424,6 +442,7 @@ class WebSocketProtocol(WebSocket):
LOG.debug('Wait open syncs to complete')
self.syncer.wait_sync_threads()
self.close()
Thread(target=self.server.shutdown).start()
return
{
'start': self.start_sync,
......
......@@ -30,10 +30,11 @@ import logging
LOGFILE = os.path.join(AGKYRA_DIR, 'agkyra.log')
LOGGER = logging.getLogger('agkyra')
HANDLER = logging.FileHandler(LOGFILE)
FORMATTER = logging.Formatter("%(name)s %(levelname)s:%(asctime)s:%(message)s")
FORMATTER = logging.Formatter(
"[CLI]%(name)s %(levelname)s:%(asctime)s:%(message)s")
HANDLER.setFormatter(FORMATTER)
LOGGER.addHandler(HANDLER)
LOGGER.setLevel(logging.INFO)
LOGGER.setLevel(logging.DEBUG)
def main():
......@@ -43,4 +44,14 @@ def main():
if __name__ == "__main__":
main()
if sys.argv[1] in ('launch_server', ):
# This piece of code will stay here until the CLI can launch a server
# by itself
from agkyra.protocol import SessionHelper
LOGGER.debug('Please start the session helper')
helper = SessionHelper()
if not helper.load_active_session():
helper.create_session()
helper.server.serve_forever()
else:
main()
......@@ -33,7 +33,7 @@ HANDLER = logging.FileHandler(LOGFILE)
FORMATTER = logging.Formatter("%(name)s %(levelname)s:%(asctime)s:%(message)s")
HANDLER.setFormatter(FORMATTER)
LOGGER.addHandler(HANDLER)
LOGGER.setLevel(logging.INFO)
LOGGER.setLevel(logging.DEBUG)
def main():
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment