[X2Go-Commits] python-x2go.git - release/0.4.0.x (branch) updated: 0.1.0.3-28-g1864f20

X2Go dev team git-admin at x2go.org
Tue Jan 7 16:17:12 CET 2014


The branch, release/0.4.0.x 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 -----------------------------------------------------------------
-----------------------------------------------------------------------

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