From 5e0b9747121eab67c5a3ee3bb42a677e35da7fd6 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 10 Nov 2014 14:57:53 -0500 Subject: Add simple SqlSession implementation This allows us to store session data in the DB. This way session data can be shared by multiple servers behind a balancer. Signed-off-by: Simo Sorce Reviewed-by: Patrick Uiterwijk --- ipsilon/install/ipsilon-server-install | 12 ++++++ ipsilon/ipsilon | 2 + ipsilon/util/sessions.py | 74 ++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100755 ipsilon/util/sessions.py (limited to 'ipsilon') diff --git a/ipsilon/install/ipsilon-server-install b/ipsilon/install/ipsilon-server-install index c6d656d..df2a965 100755 --- a/ipsilon/install/ipsilon-server-install +++ b/ipsilon/install/ipsilon-server-install @@ -112,6 +112,18 @@ def install(plugins, args): 'datadir': args['data_dir'], 'dbname': 'transactions'}, 'secure': "False" if args['secure'] == "no" else "True", 'debugging': "True" if args['server_debugging'] else "False"} + # Testing database sessions + if 'session_type' in args: + confopts['sesstype'] = args['session_type'] + else: + confopts['sesstype'] = 'file' + if 'session_dburi' in args: + confopts['sessopt'] = 'dburi' + confopts['sessval'] = args['session_dburi'] + else: + confopts['sessopt'] = 'path' + confopts['sessval'] = os.path.join(args['data_dir'], 'sessions') + # Whetehr to disable security (for testing) if args['secure'] == 'no': confopts['secure'] = "False" confopts['sslrequiressl'] = "" diff --git a/ipsilon/ipsilon b/ipsilon/ipsilon index 681600d..094a09d 100755 --- a/ipsilon/ipsilon +++ b/ipsilon/ipsilon @@ -27,6 +27,7 @@ from ipsilon.util.data import AdminStore from ipsilon.util import page from ipsilon.root import Root from jinja2 import Environment, FileSystemLoader +import ipsilon.util.sessions def nuke_session_locks(): @@ -51,6 +52,7 @@ elif os.path.isfile('/etc/ipsilon/ipsilon.conf'): else: raise IOError("Configuration file not found") +cherrypy.lib.sessions.SqlSession = ipsilon.util.sessions.SqlSession cherrypy.config.update(cfgfile) nuke_session_locks() diff --git a/ipsilon/util/sessions.py b/ipsilon/util/sessions.py new file mode 100755 index 0000000..b724471 --- /dev/null +++ b/ipsilon/util/sessions.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# +# Copyright (C) 2014 Ipsilon project Contributors, for licensee see COPYING + +import base64 +from cherrypy.lib.sessions import Session +from ipsilon.util.data import SqlStore, SqlQuery +import threading +try: + import cPickle as pickle +except ImportError: + import pickle + + +SESSION_COLUMNS = ['id', 'data', 'expiration_time'] + + +class SqlSession(Session): + + dburi = None + _db = None + _proto = 2 + locks = {} + + @classmethod + def setup(cls, **kwargs): + """Initialization from cherrypy""" + + for k, v in kwargs.items(): + if k == 'storage_dburi': + cls.dburi = v + + cls._db = SqlStore(cls.dburi) + + def _exists(self): + q = SqlQuery(self._db, 'sessions', SESSION_COLUMNS) + result = q.select({'id': self.id}) + return True if result.fetchone() else False + + def _load(self): + q = SqlQuery(self._db, 'sessions', SESSION_COLUMNS) + result = q.select({'id': self.id}) + r = result.fetchone() + if r: + data = str(base64.b64decode(r[1])) + return pickle.loads(data) + + def _save(self, expiration_time): + q = None + try: + q = SqlQuery(self._db, 'sessions', SESSION_COLUMNS, trans=True) + q.delete({'id': self.id}) + data = pickle.dumps((self._data, expiration_time), self._proto) + q.insert((self.id, base64.b64encode(data), expiration_time)) + q.commit() + except Exception: # pylint: disable=broad-except + if q: + q.rollback() + raise + + def _delete(self): + q = SqlQuery(self._db, 'sessions', SESSION_COLUMNS) + q.delete({'id': self.id}) + + # copy what RamSession does for now + def acquire_lock(self): + """Acquire an exclusive lock on the currently-loaded session data.""" + self.locked = True + self.locks.setdefault(self.id, threading.RLock()).acquire() + + def release_lock(self): + """Release the lock on the currently-loaded session data.""" + self.locks[self.id].release() + self.locked = False -- cgit