[X2Go-Commits] python-x2go.git - build-baikal (branch) updated: bcb1bc06b3f2ceb51f4b8a14f18c04b91f171855
X2Go dev team
git-admin at x2go.org
Wed Jan 8 15:29:18 CET 2014
The branch, build-baikal has been updated
via bcb1bc06b3f2ceb51f4b8a14f18c04b91f171855 (commit)
from 61081683ba395feec7eb1b2ca0ccc8aa4e41e127 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
-----------------------------------------------------------------------
Summary of changes:
x2go/backends/control/stdout.py | 42 +++++++++++----
x2go/cache.py | 111 +++++++++++++++++++++++++++++++++++++++
x2go/cleanup.py | 12 ++---
x2go/client.py | 8 +--
x2go/guardian.py | 19 ++++---
x2go/session.py | 6 ++-
6 files changed, 168 insertions(+), 30 deletions(-)
create mode 100644 x2go/cache.py
The diff of changes is:
diff --git a/x2go/backends/control/stdout.py b/x2go/backends/control/stdout.py
index a38d55c..28bddb6 100644
--- a/x2go/backends/control/stdout.py
+++ b/x2go/backends/control/stdout.py
@@ -37,6 +37,7 @@ import x2go.log as log
import x2go.utils as utils
import x2go.x2go_exceptions as x2go_exceptions
import x2go.defaults as defaults
+import x2go.cache as cache
from x2go.backends.terminal import X2goTerminalSession as _X2goTerminalSession
from x2go.backends.info import X2goServerSessionInfo as _X2goServerSessionInfo
@@ -62,11 +63,14 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
_remote_home = None
_remote_group = {}
+ x2go_listsessions_cache = None
+
def __init__(self,
terminal_backend=_X2goTerminalSession,
info_backend=_X2goServerSessionInfo,
list_backend=_X2goServerSessionList,
proxy_backend=_X2goProxy,
+ use_listsessions_cache=True,
logger=None, loglevel=log.loglevel_DEFAULT,
*args, **kwargs):
"""\
@@ -85,6 +89,7 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
self._info_backend = info_backend
self._list_backend = list_backend
self._proxy_backend = proxy_backend
+ self.use_listsessions_cache = use_listsessions_cache
paramiko.SSHClient.__init__(self, *args, **kwargs)
def __del__(self):
@@ -263,6 +268,10 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
ssh_transport._x2go_session_marker = True
self._session_password = password
+ if self.use_listsessions_cache:
+ self.x2go_listsessions_cache = cache.X2goListSessionsCache(self, logger=self.logger)
+ self.x2go_listsessions_cache.start()
+
return (self.get_transport() is not None)
def disconnect(self):
@@ -270,6 +279,8 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
STILL UNDOCUMENTED
"""
+ self.x2go_listsessions_cache.stop_thread()
+ del self.x2go_listsessions_cache
t_names = self.associated_terminals.keys()
for t_obj in self.associated_terminals.values():
t_obj.suspend()
@@ -305,7 +316,7 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
raise x2go_exceptions.X2goSessionException('remote user %s is not member of X2go server group x2gousers' % self.get_transport().get_username())
if session_name is not None:
- session_info = self.list_sessions()[session_name]
+ session_info = self.list_sessions(refresh_cache=true)[session_name]
else:
session_info = None
@@ -342,7 +353,7 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
return _terminal or None
- def list_sessions(self, raw=False):
+ def list_sessions(self, raw=False, no_cache=False, refresh_cache=False):
"""\
List all sessions of current user on the connected server.
@@ -356,13 +367,23 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
@rtype: L{X2goServerSessionList} instance or str
"""
- (stdin, stdout, stderr) = self._x2go_exec_command("x2golistsessions")
-
if raw:
return stdout.read(), stderr.read()
- _stdout_read = stdout.read()
- return self._list_backend(_stdout_read, info_backend=self._info_backend).sessions
+ elif no_cache or refresh_cache or (self.use_listsessions_cache is False) or (self.x2go_listsessions_cache is None):
+
+ (stdin, stdout, stderr) = self._x2go_exec_command("x2golistsessions")
+
+ _stdout_read = stdout.read()
+ _listsessions = self._list_backend(_stdout_read, info_backend=self._info_backend).sessions
+ if refresh_cache and self.x2go_listsessions_cache is not None:
+ self.x2go_listsessions_cache.update_session_list(session_list=_listsessions)
+
+ return _listsessions
+
+ else:
+
+ return self.x2go_listsessions_cache.list_sessions()
def clean_sessions(self):
"""\
@@ -370,7 +391,7 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
connected user on the remote X2go server and terminate them.
"""
- session_infos = self.list_sessions()
+ session_infos = self.list_sessions(refresh_cache=True)
for session_info in session_infos.values():
self.terminate(session_name=session_info)
@@ -400,7 +421,7 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
@rtype: C{bool}
"""
- session_infos = self.list_sessions()
+ session_infos = self.list_sessions(refresh_cache=True)
if session_name in session_infos.keys():
return session_infos[session_name].is_running()
return False
@@ -414,7 +435,7 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
@rtype: C{bool}
"""
- session_infos = self.list_sessions()
+ session_infos = self.list_sessions(refresh_cache=True)
if session_name in session_infos.keys():
return session_infos[session_name].is_suspended()
return False
@@ -431,8 +452,7 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
@rtype: C{bool}
"""
- session_infos = self.list_sessions()
-
+ session_infos = self.list_sessions(refresh_cache=True)
if session_name not in session_infos.keys():
if session_name in self.terminated_terminals:
diff --git a/x2go/cache.py b/x2go/cache.py
new file mode 100644
index 0000000..147c5b4
--- /dev/null
+++ b/x2go/cache.py
@@ -0,0 +1,111 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2010 by Mike Gabriel <m.gabriel at das-netzwerkteam.de>
+#
+# Python X2go is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Python X2go is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+"""\
+X2goListSessionCache class - caching X2go session information.
+
+"""
+__NAME__ = 'x2gocache-pylib'
+
+# modules
+import gevent
+import threading
+import copy
+
+# Python X2go modules
+import log
+import x2go_exceptions
+
+class X2goListSessionsCache(threading.Thread):
+ """\
+ STILL UNDOCUMENTED
+
+ """
+
+ x2go_listsessions_cache = None
+
+ def __init__(self, control_session, refresh_interval=5, logger=None, loglevel=log.loglevel_DEFAULT):
+ """\
+ @param control: the L{X2goControlSession} that uses this L{X2goListSessionsCache}
+ @type control: C{instance}
+ @param refresh_interval: refresh interval of the list sessions cache in seconds
+ @type refresh_interval: C{int}
+ @param logger: you can pass an L{X2goLogger} object to the L{X2goSessionGuardian} constructor
+ @type logger: C{instance}
+ @param loglevel: if no L{X2goLogger} object has been supplied a new one will be
+ constructed with the given loglevel
+ @type loglevel: C{int}
+
+ """
+ if logger is None:
+ self.logger = log.X2goLogger(loglevel=loglevel)
+ else:
+ self.logger = copy.deepcopy(logger)
+ self.logger.tag = __NAME__
+
+ self.control_session = control_session
+ self.refresh_interval = refresh_interval
+ threading.Thread.__init__(self, target=self.refresh_cache)
+ self.daemon = True
+
+ def refresh_cache(self):
+ """\
+ The handler of this L{X2goListSessionsCache} thread.
+
+ """
+ seconds = 0
+ self._keepalive = True
+ while self._keepalive:
+ gevent.sleep(1)
+ seconds += 1
+ if seconds % self.refresh_interval == 0:
+ self.update_session_list()
+
+ def update_session_list(self, session_list=None):
+ """\
+ Retrieve a recent session list either from the control session's C{list_sessions()}
+ method or as an argument.
+
+ @param session_list: an L{X2goServerSessionList} backend instance
+ @type session_list C{instance}
+
+ """
+ if session_list is None:
+ try:
+ self.x2go_listsessions_cache = self.control_session.list_sessions(no_cache=True)
+ except x2go_exceptions.X2goSessionException:
+ pass
+ else:
+ self.x2go_listsessions_cache = session_list
+
+ def list_sessions(self):
+ """\
+ Retrieve the current cache content of L{X2goListSessionsCache}.
+
+ """
+ return self.x2go_listsessions_cache
+
+ def stop_thread(self):
+ """\
+ Stop this L{X2goListSessionsCache} thread.
+
+ """
+ self._keepalive = False
+
+
diff --git a/x2go/cleanup.py b/x2go/cleanup.py
index 72aa038..04949df 100644
--- a/x2go/cleanup.py
+++ b/x2go/cleanup.py
@@ -27,7 +27,7 @@ import guardian
import rforward
-def x2go_cleanup(e=None, session=None, threads=[]):
+def x2go_cleanup(e=None, terminal_session=None, threads=[]):
"""\
For every Python X2go application you write, please make sure to
capture the KeyboardInterrupt and the SystemExit exceptions and
@@ -49,16 +49,16 @@ def x2go_cleanup(e=None, session=None, threads=[]):
@param e: if L{x2go_cleanup} got called as we caught an exception this can be the C{Exception} that
we might process at the end of the clean-up (or if clean-up failed or was not appropriate)
@type e: C{exception}
- @param session: an L{X2goSession} object
- @type session: C{instance}
+ @param terminal_session: an L{X2goSession} object
+ @type terminal_session: C{instance}
@param threads: a list of threads to clean up
@type threads: C{list}
"""
- if session is None:
+ if terminal_session is None:
active_threads = threading.enumerate()
else:
- session.logger('cleaning up threads of session: %s' % session.session_info.name)
+ terminal_session.logger('cleaning up threads of terminal session: %s' % terminal_session.session_info.name)
active_threads = threads
# stop X2go reverse forwarding tunnels
@@ -66,7 +66,7 @@ def x2go_cleanup(e=None, session=None, threads=[]):
if type(t) == rforward.X2goRevFwTunnel:
t.stop_thread()
- # stop X2go paramiko transports used by X2goSession objects
+ # stop X2go paramiko transports used by X2goTerminalSession objects
for t in active_threads:
if type(t) == paramiko.Transport:
if hasattr(t, '_x2go_session_marker'):
diff --git a/x2go/client.py b/x2go/client.py
index 2b12c78..488468c 100644
--- a/x2go/client.py
+++ b/x2go/client.py
@@ -861,7 +861,7 @@ class X2goClient(object):
"""
if self._X2goClient__is_session_connected(session_uuid):
- session_list = self._X2goClient__list_sessions(session_uuid)
+ session_list = self._X2goClient__list_sessions(session_uuid, refresh_cache=True)
return [ key for key in session_list.keys() if session_list[key].status == 'R' ]
else:
raise X2goClientException('X2go session with UUID %s is not connected' % session_uuid)
@@ -890,7 +890,7 @@ class X2goClient(object):
"""
if self._X2goClient__is_session_connected(session_uuid):
- session_list = self._X2goClient__list_sessions(session_uuid)
+ session_list = self._X2goClient__list_sessions(session_uuid, refresh_cache=True)
return [ key for key in session_list.keys() if session_list[key].status == 'S' ]
else:
raise X2goClientException('X2go session with UUID %s is not connected' % session_uuid)
@@ -934,7 +934,7 @@ class X2goClient(object):
session.clean_sessions()
__clean_sessions = clean_sessions
- def list_sessions(self, session_uuid):
+ def list_sessions(self, session_uuid, no_cache=False, refresh_cache=False):
"""\
Use the X2go session registered under C{session_uuid} to
retrieve a list of running or suspended X2go sessions on the
@@ -950,7 +950,7 @@ class X2goClient(object):
"""
session = self.session_registry(session_uuid)
- return session.list_sessions()
+ return session.list_sessions(no_cache=no_cache, refresh_cache=refresh_cache)
__list_sessions = list_sessions
###
diff --git a/x2go/guardian.py b/x2go/guardian.py
index 4c2fa8d..7c483f6 100644
--- a/x2go/guardian.py
+++ b/x2go/guardian.py
@@ -56,10 +56,10 @@ class X2goSessionGuardian(threading.Thread):
"""
- def __init__(self, session, logger=None, loglevel=log.loglevel_DEFAULT):
+ def __init__(self, terminal_session, logger=None, loglevel=log.loglevel_DEFAULT):
"""\
- @param session: the L{X2goSession} that is controlled by this L{X2goSessionGuardian}
- @type session: C{instance}
+ @param terminal_session: the L{X2goTerminalSession} that is controlled by this L{X2goSessionGuardian}
+ @type terminal_session: C{instance}
@param logger: you can pass an L{X2goLogger} object to the L{X2goSessionGuardian} constructor
@type logger: C{instance}
@param loglevel: if no L{X2goLogger} object has been supplied a new one will be
@@ -73,8 +73,7 @@ class X2goSessionGuardian(threading.Thread):
self.logger = copy.deepcopy(logger)
self.logger.tag = __NAME__
- self.session = session
- self._keepalive = True
+ self.terminal_session = terminal_session
threading.Thread.__init__(self, target=self.guardian)
self.daemon = True
@@ -84,11 +83,17 @@ class X2goSessionGuardian(threading.Thread):
"""
global _sigterm_received
+
+ seconds = 0
+ self._keepalive = True
while not _sigterm_received and self._keepalive:
gevent.sleep(1)
- self.logger('X2go session guardian thread waking up, calling session cleanup for session: %s' % self.session.session_info.name, loglevel=log.loglevel_DEBUG)
+ seconds += 1
+
+ self.logger('X2go session guardian thread waking up after %s seconds' % seconds, loglevel=log.loglevel_DEBUG)
+ self.logger('calling terminal session cleanup for terminal session: %s' % self.terminal_session.session_info.name, loglevel=log.loglevel_DEBUG)
- x2go_cleanup(session=self.session, threads=self.active_threads)
+ x2go_cleanup(terminal_session=self.terminal_session, threads=self.active_threads)
def stop_thread(self):
"""\
diff --git a/x2go/session.py b/x2go/session.py
index 354069a..045245c 100644
--- a/x2go/session.py
+++ b/x2go/session.py
@@ -120,6 +120,7 @@ class X2goSession(object):
self.control_session = control_session
self.terminal_session = None
+ self.guardian_thread = None
self.logger('starting X2goSession', loglevel=log.loglevel_DEBUG)
if known_hosts:
self.control_session.load_host_keys(known_hosts)
@@ -283,8 +284,8 @@ class X2goSession(object):
def clean_sessions(self):
self.control_session.clean_sessions()
- def list_sessions(self):
- return self.control_session.list_sessions()
+ def list_sessions(self, no_cache=False, refresh_cache=False):
+ return self.control_session.list_sessions(no_cache=no_cache, refresh_cache=refresh_cache)
def resume(self, session_name=None):
"""\
@@ -297,6 +298,7 @@ class X2goSession(object):
"""
_control = self.control_session
_terminal = _control.resume(session_name=session_name, logger=self.logger, **self.terminal_params)
+ self.guardian_thread = _terminal.guardian_thread
self.terminal_session = _terminal
if _terminal is not None:
hooks/post-receive
--
python-x2go.git (Python X2Go Client API)
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "python-x2go.git" (Python X2Go Client API).
More information about the x2go-commits
mailing list