summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2014-11-10 14:57:53 -0500
committerPatrick Uiterwijk <puiterwijk@redhat.com>2014-11-12 23:46:52 +0100
commit5e0b9747121eab67c5a3ee3bb42a677e35da7fd6 (patch)
treec93728a60d98385637c9dc82f05fa46fdf858e8f
parent0087ad1e0824b4b1c49ce1468bfbb2e492ac7992 (diff)
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 <simo@redhat.com> Reviewed-by: Patrick Uiterwijk <puiterwijk@redhat.com>
-rwxr-xr-xipsilon/install/ipsilon-server-install12
-rwxr-xr-xipsilon/ipsilon2
-rwxr-xr-xipsilon/util/sessions.py74
-rwxr-xr-xquickrun.py3
-rw-r--r--templates/install/ipsilon.conf4
-rwxr-xr-xtests/helpers/common.py2
-rwxr-xr-xtests/pgdb.py2
7 files changed, 96 insertions, 3 deletions
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
diff --git a/quickrun.py b/quickrun.py
index 852f8b0..0546fcc 100755
--- a/quickrun.py
+++ b/quickrun.py
@@ -77,6 +77,9 @@ def config(workdir):
'admindb': admin_db,
'usersdb': users_db,
'transdb': trans_db,
+ 'sesstype': 'file',
+ 'sessopt': 'path',
+ 'sessval': os.path.join(workdir, 'sessions'),
'secure': 'False'})
conf = os.path.join(workdir, 'ipsilon.conf')
with open(conf, 'w+') as f:
diff --git a/templates/install/ipsilon.conf b/templates/install/ipsilon.conf
index 2e402a3..4b170ca 100644
--- a/templates/install/ipsilon.conf
+++ b/templates/install/ipsilon.conf
@@ -11,8 +11,8 @@ transactions.db = "${transdb}"
tools.sessions.on = True
tools.sessions.name = "${instance}_ipsilon_session_id"
-tools.sessions.storage_type = "file"
-tools.sessions.storage_path = "${datadir}/sessions"
+tools.sessions.storage_type = "${sesstype}"
+tools.sessions.storage_${sessopt} = "${sessval}"
tools.sessions.path = "/${instance}"
tools.sessions.timeout = 60
tools.sessions.httponly = ${secure}
diff --git a/tests/helpers/common.py b/tests/helpers/common.py
index a0adfae..e316718 100755
--- a/tests/helpers/common.py
+++ b/tests/helpers/common.py
@@ -138,7 +138,7 @@ class IpsilonTestBase(object):
env=env, preexec_fn=os.setsid)
self.processes.append(p)
p.wait()
- for d in ['adminconfig', 'userprefs', 'transactions']:
+ for d in ['adminconfig', 'userprefs', 'transactions', 'sessions']:
cmd = ['/usr/bin/createdb', '-h', addr, '-p', port, d]
subprocess.check_call(cmd, env=env)
diff --git a/tests/pgdb.py b/tests/pgdb.py
index 12f1cf2..14ffd36 100755
--- a/tests/pgdb.py
+++ b/tests/pgdb.py
@@ -37,6 +37,8 @@ idp_g = {'TEMPLATES': '${TESTDIR}/templates/install',
idp_a = {'hostname': '${ADDRESS}:${PORT}',
'database_url': 'postgresql://@127.0.0.10:45432/%(dbname)s',
+ 'session_type': 'sql',
+ 'session_dburi': 'postgresql://@127.0.0.10:45432/sessions',
'admin_user': '${TEST_USER}',
'system_user': '${TEST_USER}',
'instance': '${NAME}',