[X2go-Commits] python-x2go.git - master (branch) updated: 0.1.0.3-28-g1864f20

X2go dev team git-admin at x2go.org
Tue Jun 21 19:50:13 CEST 2011


The branch, master has been updated
       via  1864f206b495fe38b2b9e6e2569de1b215279de0 (commit)
      from  40032c72120c5b58f9135488f3120902fce77e7a (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 -----------------------------------------------------------------
commit 1864f206b495fe38b2b9e6e2569de1b215279de0
Author: Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
Date:   Tue Jun 21 19:50:10 2011 +0200

    Make cache more configurable (session list updates, desktop list updates), add an auto_update_listdesktops_cache to X2goClient constructor argvs.

-----------------------------------------------------------------------

Summary of changes:
 debian/changelog                 |    6 ++-
 x2go/backends/control/_stdout.py |   41 ++++++++++++++++++-----
 x2go/cache.py                    |   30 +++++++++++++----
 x2go/client.py                   |   68 +++++++++++++++++++++++++++++++------
 x2go/guardian.py                 |    8 ++++-
 x2go/session.py                  |    5 +++
 6 files changed, 128 insertions(+), 30 deletions(-)

The diff of changes is:
diff --git a/debian/changelog b/debian/changelog
index b34e4bd..a3d162d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -8,10 +8,12 @@ python-x2go (0.1.1.0-0~x2go1) UNRELEASED; urgency=low
     - Add X2goSession status property ,,faulty''.
     - Make sure list session and list desktop commands always return.
     - Rely on X2goSessionListInfo backend to handle exceptions appropriately.
-    - Assure that rev forwarding tunnels use IPv4 (replace localhost with 127.0.0.1)
+    - Assure that rev forwarding tunnels use IPv4 (replace localhost with 127.0.0.1).
     - Explicitly tunnel over IPv4 for NX proxy.
+    - Make cache more configurable (session list updates, desktop list updates).
+    - Adds an auto_update_listdesktops_cache to X2goClient constructor argvs.
 
- -- Mike Gabriel <mike at mimino.das-netzwerkteam.de>  Tue, 21 Jun 2011 15:39:08 +0200
+ -- Mike Gabriel <mike at mimino.das-netzwerkteam.de>  Tue, 21 Jun 2011 19:48:12 +0200
 
 python-x2go (0.1.0.3-0~x2go1) unstable; urgency=low
 
diff --git a/x2go/backends/control/_stdout.py b/x2go/backends/control/_stdout.py
index d6ebe72..b953234 100644
--- a/x2go/backends/control/_stdout.py
+++ b/x2go/backends/control/_stdout.py
@@ -626,7 +626,7 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
 
         return self.start(**kwargs)
 
-    def list_desktops(self, raw=False):
+    def list_desktops(self, raw=False, maxwait=20):
         """\
         List all desktop-like sessions of current user (or of users that have 
         granted desktop sharing) on the connected server.
@@ -648,10 +648,19 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
             # this _success loop will catch errors in case the x2golistsessions output is corrupt
             # this should not be needed and is a workaround for the current X2go server implementation
 
-            (stdin, stdout, stderr) = self._x2go_exec_command("export HOSTNAME && x2golistdesktops")
-            _stdout_read = stdout.read()
-
-            _listdesktops = _stdout_read.split('\n')
+            timeout = gevent.Timeout(maxwait)
+            timeout.start()
+            try:
+                (stdin, stdout, stderr) = self._x2go_exec_command("export HOSTNAME && x2golistdesktops")
+                _stdout_read = stdout.read()
+                _listdesktops = _stdout_read.split('\n')
+            except gevent.timeout.Timeout:
+                # if we do not get a reply here after <maxwait> seconds we will raise a time out, we have to
+                # make sure that we catch this at places where we want to ignore timeouts (e.g. in the 
+                # desktop list cache)
+                raise x2go_exceptions.X2goTimeOutException('x2golistdesktop command timed out')
+            finally:
+                timeout.cancel()
 
             return _listdesktops
 
@@ -681,10 +690,24 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
             _success = False
             _count = 0
 
-            (stdin, stdout, stderr) = self._x2go_exec_command("export HOSTNAME && x2golistsessions")
-            _stdout_read = stdout.read()
-
-            _listsessions = self._list_backend(_stdout_read, info_backend=self._info_backend).sessions
+            # we will try this 20 times before giving up... we might simply catch the x2golistsessions
+            # output in the middle of creating a session in the database...
+            while not _success and _count < 20:
+                _count += 1
+                try:
+                    (stdin, stdout, stderr) = self._x2go_exec_command("export HOSTNAME && x2golistsessions")
+                    _stdout_read = stdout.read()
+                    _listsessions = self._list_backend(_stdout_read, info_backend=self._info_backend).sessions
+                    _success = True
+                except KeyError:
+                    gevent.sleep(1)
+                except IndexError:
+                    gevent.sleep(1)
+                except ValueError:
+                    gevent.sleep(1)
+
+            if _count >= 20:
+                raise x2go_exceptions.X2goControlSessionException('x2golistsessions command failed after we have tried 20 times')
 
             # update internal variables when list_sessions() is called
             for _session_name, _session_info in self.associated_terminals.items():
diff --git a/x2go/cache.py b/x2go/cache.py
index dda6faa..2a8643b 100644
--- a/x2go/cache.py
+++ b/x2go/cache.py
@@ -94,30 +94,41 @@ class X2goListSessionsCache(object):
             if profile_name not in self.client_instance.client_connected_profiles(return_profile_names=True):
                 del self.x2go_listsessions_cache[profile_name]
 
-    def update_all(self):
+    def update_all(self, update_sessions=True, update_desktops=False):
         """\
         Update L{X2goListSessionsCache} for all connected session profiles.
 
+        @param update_sessions: cache recent session lists from all connected servers
+        @type update_session: C{bool}
+        @param update_desktops: cache recent desktop lists from all connected servers
+        @type update_desktops: C{bool}
+
         """
         for profile_name in self.client_instance.client_connected_profiles(return_profile_names=True):
-            self.update(profile_name)
+            self.update(profile_name, update_sessions=update_sessions, update_desktops=update_desktops)
 
         self.check_cache()
 
-    def update(self, profile_name):
+    def update(self, profile_name, update_sessions=True, update_desktops=False):
         """\
         Update L{X2goListSessionsCache} (i.e. session/desktops) for session profile C{profile_name}.
 
         @param profile_name: name of profile to update
         @type profile_name: C{str}
+        @param update_sessions: cache recent session list from server
+        @type update_session: C{bool}
+        @param update_desktops: cache recent desktop list from server
+        @type update_desktops: C{bool}
 
         """
         self.last_listsessions_cache = copy.deepcopy(self.x2go_listsessions_cache)
         control_session = self.client_instance.client_control_session_of_profile_name(profile_name)
         if not self.x2go_listsessions_cache.has_key(profile_name):
             self.x2go_listsessions_cache[profile_name] = {'sessions': None, 'desktops': None, }
-        self._update_sessions(profile_name, control_session)
-        self._update_desktops(profile_name, control_session)
+        if update_sessions:
+            self._update_sessions(profile_name, control_session)
+        if update_desktops:
+            self._update_desktops(profile_name, control_session)
 
     def _update_desktops(self, profile_name, control_session):
         """\
@@ -188,7 +199,7 @@ class X2goListSessionsCache(object):
         else:
             return None
 
-    def is_cached(self, profile_name=None, session_uuid=None):
+    def is_cached(self, profile_name=None, session_uuid=None, cache_type=None):
         """\
         Check if session list is cached.
 
@@ -200,4 +211,9 @@ class X2goListSessionsCache(object):
         """
         if profile_name is None and session_uuid:
             profile_name = self.client_instance.get_session_profile_name(session_uuid)
-        return self.x2go_listsessions_cache.has_key(profile_name)
+        _is_profile_cached = self.x2go_listsessions_cache.has_key(profile_name)
+        _is_cache_type_cached = _is_profile_cached and self.x2go_listsessions_cache[profile_name].has_key(cache_type)
+        if cache_type is None:
+            return _is_profile_cached
+        else:
+            return _is_cache_type_cached
\ No newline at end of file
diff --git a/x2go/client.py b/x2go/client.py
index ae4dec1..fa87e4c 100644
--- a/x2go/client.py
+++ b/x2go/client.py
@@ -193,6 +193,7 @@ class X2goClient(object):
                  start_pulseaudio=False,
                  use_listsessions_cache=False, 
                  auto_update_listsessions_cache=False,
+                 auto_update_listdesktops_cache=False,
                  auto_update_sessionregistry=False,
                  auto_register_sessions=False,
                  refresh_interval=5,
@@ -225,10 +226,12 @@ class X2goClient(object):
         @type start_xserver: C{bool}
         @param start_pulseaudio: start Pulseaudio daemon when registering an L{X2goClient} instance
         @type start_pulseaudio: C{bool}
-        @param use_listsessions_cache: activate the X2go session list cache (L{X2goListSessionsCache})
+        @param use_listsessions_cache: activate the X2go session list cache in (L{X2goListSessionsCache})
         @type use_listsessions_cache: C{bool}
         @param auto_update_listsessions_cache: activate automatic updates of the X2go session list cache (L{X2goListSessionsCache})
         @type auto_update_listsessions_cache: C{bool}
+        @param auto_update_listdesktops_cache: activate automatic updates of desktop lists in (L{X2goListSessionsCache})
+        @type auto_update_listdesktops_cache: C{bool}
         @param auto_update_sessionregistry: activate automatic updates of the X2go session registry
         @type auto_update_sessionregistry: C{bool}
         @param auto_register_sessions: activate automatic X2go session registration
@@ -309,16 +312,20 @@ class X2goClient(object):
 
         self.auto_register_sessions = auto_register_sessions
         self.session_registry = X2goSessionRegistry(self, logger=self.logger)
-        self.session_guardian = X2goSessionGuardian(self, auto_update_listsessions_cache=auto_update_listsessions_cache & use_listsessions_cache, 
+        self.session_guardian = X2goSessionGuardian(self, auto_update_listsessions_cache=auto_update_listsessions_cache & use_listsessions_cache,
+                                                    auto_update_listdesktops_cache=auto_update_listdesktops_cache & use_listsessions_cache,
                                                     auto_update_sessionregistry=auto_update_sessionregistry,
                                                     auto_register_sessions=auto_register_sessions, 
                                                     refresh_interval=refresh_interval,
                                                     logger=self.logger
                                                    )
+
         if use_listsessions_cache:
             self.listsessions_cache = X2goListSessionsCache(self, logger=self.logger)
 
         self.use_listsessions_cache = use_listsessions_cache
+        self.auto_update_listsessions_cache = auto_update_listsessions_cache
+        self.auto_update_listdesktops_cache = auto_update_listdesktops_cache
 
     # user hooks for detecting/notifying what happened during application runtime
     def HOOK_no_known_xserver_found(self):
@@ -1869,7 +1876,7 @@ class X2goClient(object):
         if raw:
             return self.session_registry(session_uuid).list_sessions(raw=raw)
 
-        if not self.use_listsessions_cache or no_cache:
+        if not self.use_listsessions_cache or not self.auto_update_listsessions_cache or no_cache:
             _session_list = self.session_registry(session_uuid).list_sessions()
         elif refresh_cache:
             self.update_cache_by_session_uuid(session_uuid)
@@ -1877,7 +1884,7 @@ class X2goClient(object):
         else:
             # if there is no cache for this session_uuid available, make sure the cache gets updated
             # before reading from it...
-            if self.use_listsessions_cache and (not self.listsessions_cache.is_cached(session_uuid=session_uuid)):
+            if self.use_listsessions_cache and (not self.listsessions_cache.is_cached(session_uuid=session_uuid, cache_type=('sessions'))):
                 self.__update_cache_by_session_uuid(session_uuid)
             _session_list = self.listsessions_cache.list_sessions(session_uuid)
 
@@ -1938,9 +1945,11 @@ class X2goClient(object):
         if raw:
             return self.session_registry(session_uuid).list_desktops(raw=raw)
 
-        if not self.use_listsessions_cache or no_cache:
+        if not self.use_listsessions_cache or not self.auto_update_listdesktops_cache or no_cache:
             _desktop_list = self.session_registry(session_uuid).list_desktops()
         else:
+            if self.use_listsessions_cache and (not self.listsessions_cache.is_cached(session_uuid=session_uuid, cache_types=('desktops'))):
+                self.__update_cache_by_session_uuid(session_uuid, update_sessions=False, update_desktops=True)
             _desktop_list = self.listsessions_cache.list_desktops(session_uuid)
 
         return _desktop_list
@@ -2156,45 +2165,82 @@ class X2goClient(object):
     __update_sessionregistry_status_all_profiles = update_sessionregistry_status_all_profiles
 
 
-    def update_cache_by_profile_name(self, profile_name):
+    def update_cache_by_profile_name(self, profile_name, cache_types=('sessions'), update_sessions=None, update_desktops=None):
         """\
         Update the session list cache by profile name.
 
         @param profile_name: the X2go session profile name
         @type profile_name: C{str}
+        @param cache_types: specify what cache type to update (available: C{sessions}, C{desktops})
+        @type cache_types: C{tuple} or C{list}
+        @param update_sessions: instead of giving a list of cache types, plainly say C{True} here, if 
+            you want to update sessions in the session list cache.
+        @type update_session: C{bool}
+        @param update_desktops: instead of giving a list of cache types, plainly say C{True} here, if 
+            you want to update available desktops in the desktop list cache.
+        @type update_desktops: C{bool}
 
         """
         if self.listsessions_cache is not None:
+            _update_sessions = ('sessions' in cache_types) or update_sessions
+            _update_desktops = ('desktops' in cache_types) or update_desktops
             try:
-                self.listsessions_cache.update(profile_name)
+                self.listsessions_cache.update(profile_name, update_sessions=_update_sessions, update_desktops=_update_desktops)
             except x2go_exceptions.X2goControlSessionException:
                 if self.disconnect_profile(profile_name):
                     self.HOOK_on_control_session_death(profile_name)
     __update_cache_by_profile_name = update_cache_by_profile_name
 
-    def update_cache_by_session_uuid(self, session_uuid):
+    def update_cache_by_session_uuid(self, session_uuid, cache_types=('sessions'), update_sessions=None, update_desktops=None):
         """\
         Update the session list cache of a specific L{X2goSession} instance with
         session identifier <session_uuid>.
 
         @param session_uuid: the X2go session's UUID registry hash
         @type session_uuid: C{str}
+        @param cache_types: specify what cache type to update (available: C{sessions}, C{desktops})
+        @type cache_types: C{tuple} or C{list}
+        @param update_sessions: instead of giving a list of cache types, plainly say C{True} here, if 
+            you want to update sessions in the session list cache.
+        @type update_session: C{bool}
+        @param update_desktops: instead of giving a list of cache types, plainly say C{True} here, if 
+            you want to update available desktops in the desktop list cache.
+        @type update_desktops: C{bool}
 
         """
         profile_name = self.get_session_profile_name(session_uuid)
-        self.__update_cache_by_profile_name(profile_name)
+        self.__update_cache_by_profile_name(profile_name,
+                                            cache_types=cache_types,
+                                            update_sessions=update_sessions,
+                                            update_desktops=update_desktops,
+                                           )
     __update_cache_by_session_uuid = update_cache_by_session_uuid
 
-    def update_cache_all_profiles(self):
+    def update_cache_all_profiles(self, cache_types=('sessions'), update_sessions=None, update_desktops=None):
         """\
         Update the session list cache of all session profiles.
 
+        @param cache_types: specify what cache type to update (available: C{sessions}, C{desktops})
+        @type cache_types: C{tuple} or C{list}
+        @param update_sessions: instead of giving a list of cache types, plainly say C{True} here, if 
+            you want to update sessions in the session list cache.
+        @type update_session: C{bool}
+        @param update_desktops: instead of giving a list of cache types, plainly say C{True} here, if 
+            you want to update available desktops in the desktop list cache.
+        @type update_desktops: C{bool}
+
         """
         if self.listsessions_cache is not None:
             for profile_name in self.client_connected_profiles(return_profile_names=True):
-                self.__update_cache_by_profile_name(profile_name)
+                self.__update_cache_by_profile_name(profile_name,
+                                                    cache_types=cache_types,
+                                                    update_sessions=update_sessions,
+                                                    update_desktops=update_desktops,
+                                                   )
 
+            # remove profiles that are not connected any more from cache object
             self.listsessions_cache.check_cache()
+
     __update_cache_all_profiles = update_cache_all_profiles
 
     def register_available_server_sessions_by_profile_name(self, profile_name):
diff --git a/x2go/guardian.py b/x2go/guardian.py
index 36b0623..a5791e3 100644
--- a/x2go/guardian.py
+++ b/x2go/guardian.py
@@ -54,6 +54,7 @@ class X2goSessionGuardian(threading.Thread):
 
     def __init__(self, client_instance, 
                  auto_update_listsessions_cache=False, 
+                 auto_update_listdesktops_cache=False, 
                  auto_update_sessionregistry=False,
                  auto_register_sessions=False,
                  refresh_interval=5,
@@ -61,6 +62,8 @@ class X2goSessionGuardian(threading.Thread):
         """\
         @param auto_update_listsessions_cache: let L{X2goSessionGuardian} refresh the session list cache for all L{X2goSession} objects
         @type auto_update_listsessions_cache: C{bool}
+        @param auto_update_listdesktops_cache: let L{X2goSessionGuardian} refresh desktop lists in the session list cache for all L{X2goSession} objects
+        @type auto_update_listdesktops_cache: C{bool}
         @param auto_update_sessionregistry: if set to C{True} the session status will be updated in regular intervals
         @type auto_update_sessionregistry: C{bool}
         @param auto_register_sessions: register new sessions automatically once they appear in the X2go session (e.g. 
@@ -83,6 +86,7 @@ class X2goSessionGuardian(threading.Thread):
 
         self.client_instance = client_instance
         self.auto_update_listsessions_cache = auto_update_listsessions_cache
+        self.auto_update_listdesktops_cache = auto_update_listdesktops_cache
         self.auto_update_sessionregistry = auto_update_sessionregistry
         self.auto_register_sessions = auto_register_sessions
         self.refresh_interval = refresh_interval
@@ -110,7 +114,9 @@ class X2goSessionGuardian(threading.Thread):
 
 
                 if self.auto_update_listsessions_cache:
-                    self.client_instance.update_cache_all_profiles()
+                    self.client_instance.update_cache_all_profiles(update_sessions=self.auto_update_listsessions_cache, 
+                                                                   update_desktops=self.auto_update_listdesktops_cache,
+                                                                  )
 
                 if self.auto_update_sessionregistry and not self.auto_register_sessions:
                     self.client_instance.update_sessionregistry_status_all_profiles()
diff --git a/x2go/session.py b/x2go/session.py
index 52cb682..0767340 100644
--- a/x2go/session.py
+++ b/x2go/session.py
@@ -831,6 +831,11 @@ class X2goSession(object):
         """
         try:
             return self.control_session.list_desktops(raw=raw)
+        except X2goDesktopSharingException:
+            if raw:
+                return ('','')
+            else:
+                return []
         except X2goControlSessionException:
             self._X2goSession_disconnect()
             return 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