[X2go-Commits] python-x2go.git - master (branch) updated: 0.1.1.4-101-g2093439

X2go dev team git-admin at x2go.org
Wed Feb 8 17:16:16 CET 2012


The branch, master has been updated
       via  20934399dd3170bdbbb616eb3d634acd00b647d3 (commit)
      from  37cbc1fa5f77877a2a7c28f30947e0fe8027601e (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 20934399dd3170bdbbb616eb3d634acd00b647d3
Author: Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
Date:   Wed Feb 8 17:16:01 2012 +0100

    Provide client-side cache of shared local folders, detect server-side unsharing of client-side folders.

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

Summary of changes:
 debian/changelog                 |    2 +
 x2go/backends/control/_stdout.py |   39 ++++++++++++
 x2go/cache.py                    |   46 +++++++++++++-
 x2go/client.py                   |  124 ++++++++++++++++++++++++++++++++------
 x2go/guardian.py                 |    5 ++
 x2go/session.py                  |   86 ++++++++++++++++++++++----
 6 files changed, 268 insertions(+), 34 deletions(-)

The diff of changes is:
diff --git a/debian/changelog b/debian/changelog
index c2752f0..11d28ee 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -15,6 +15,8 @@ python-x2go (0.1.2.0-0~x2go1) UNRELEASED; urgency=low
     - Replace any non-code string ,,X2go'' by ,,X2Go''.
     - Add support for session port re-allocation on session resume (feature of
       x2goserver >= 3.1.0.0).
+    - Provide client-side cache of shared local folders, detect server-side
+      unsharing of client-side folders.
   * Depend on python-xlib.
 
  -- Mike Gabriel <mike.gabriel at das-netzwerkteam.de>  Sat, 28 Sep 2012 01:44:21 +0100
diff --git a/x2go/backends/control/_stdout.py b/x2go/backends/control/_stdout.py
index f3b3718..05b1c96 100644
--- a/x2go/backends/control/_stdout.py
+++ b/x2go/backends/control/_stdout.py
@@ -715,6 +715,45 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
 
             return _listdesktops
 
+    def list_mounts(self, session_name, raw=False, maxwait=20):
+        """\
+        List all mounts for a given session of the current user on the connected server.
+
+        @param session_name: name of a session to query a list of mounts for
+        @type session_name: C{str}
+        @param raw: if C{True}, the raw output of the server-side X2Go command 
+            C{x2godesktopsharing} is returned.
+        @type raw: C{bool}
+        @param maxwait: stop processing C{x2golistmounts} after C{<maxwait>} seconds
+        @type maxwait: C{int}
+
+        @return: a list of client-side mounts for X2Go session C{<session_name>} on the server
+        @rtype: C{list}
+
+        """
+        if raw:
+            (stdin, stdout, stderr) = self._x2go_exec_command("export HOSTNAME && x2golistmounts %s" % session_name)
+            return stdout.read(), stderr.read()
+
+        else:
+
+            # this _success loop will catch errors in case the x2golistmounts output is corrupt
+
+            timeout = gevent.Timeout(maxwait)
+            timeout.start()
+            try:
+                (stdin, stdout, stderr) = self._x2go_exec_command("export HOSTNAME && x2golistmounts %s" % session_name)
+                _stdout_read = stdout.read()
+                _listmounts = {session_name: [ line for line in _stdout_read.split('\n') if line ] }
+            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
+                raise x2go_exceptions.X2goTimeOutException('x2golistmounts command timed out')
+            finally:
+                timeout.cancel()
+
+            return _listmounts
+
     def list_sessions(self, raw=False):
         """\
         List all sessions of current user on the connected server.
diff --git a/x2go/cache.py b/x2go/cache.py
index 3c11def..a1d6c51 100644
--- a/x2go/cache.py
+++ b/x2go/cache.py
@@ -109,7 +109,7 @@ class X2goListSessionsCache(object):
 
         self.check_cache()
 
-    def update(self, profile_name, update_sessions=True, update_desktops=False):
+    def update(self, profile_name, update_sessions=True, update_desktops=False, update_mounts=False):
         """\
         Update L{X2goListSessionsCache} (i.e. session/desktops) for session profile C{profile_name}.
 
@@ -119,16 +119,40 @@ class X2goListSessionsCache(object):
         @type update_sessions: C{bool}
         @param update_desktops: cache recent desktop list from server
         @type update_desktops: C{bool}
+        @param update_mounts: cache list of client-side mounts on server
+        @type update_mounts: 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.x2go_listsessions_cache[profile_name] = {'sessions': None, 'desktops': None, 'mounts': {}, }
         if update_sessions:
             self._update_sessions(profile_name, control_session)
         if update_desktops:
             self._update_desktops(profile_name, control_session)
+        if update_mounts:
+            self._update_mounts(profile_name, control_session)
+
+    def _update_mounts(self, profile_name, control_session):
+        """\
+        Update mounts list of L{X2goListSessionsCache} for session profile C{profile_name}.
+
+        @param profile_name: name of profile to update
+        @type profile_name: C{str}
+
+        """
+
+        try:
+            if self.x2go_listsessions_cache[profile_name]['sessions']:
+                for session_name in self.x2go_listsessions_cache[profile_name]['sessions']:
+                    self.x2go_listsessions_cache[profile_name]['mounts'].update(control_session.list_mounts(session_name))
+        except x2go_exceptions.X2goControlSessionException, e:
+            try:
+                del self.x2go_listsessions_cache[profile_name]
+            except KeyError:
+                pass
+            raise e
 
     def _update_desktops(self, profile_name, control_session):
         """\
@@ -199,6 +223,24 @@ class X2goListSessionsCache(object):
         else:
             return None
 
+    def list_mounts(self, session_uuid):
+        """\
+        Retrieve a list of mounted client shares from the current cache content of
+        L{X2goListSessionsCache} for a given L{X2goSession} instance (specified by its 
+        unique session UUID).
+
+        @param session_uuid: unique identifier of session to query cache for
+        @type session_uuid: C{str}
+        @return: a list of strings representing mounted client shares
+        @rtype: C{list}
+
+        """
+        profile_name = self.client_instance.get_session_profile_name(session_uuid)
+        if self.is_cached(session_uuid=session_uuid):
+            return self.x2go_listsessions_cache[profile_name]['mounts']
+        else:
+            return None
+
     def is_cached(self, profile_name=None, session_uuid=None, cache_type=None):
         """\
         Check if session list is cached.
diff --git a/x2go/client.py b/x2go/client.py
index 5791584..095598c 100644
--- a/x2go/client.py
+++ b/x2go/client.py
@@ -194,6 +194,7 @@ class X2goClient(object):
                  use_listsessions_cache=False, 
                  auto_update_listsessions_cache=False,
                  auto_update_listdesktops_cache=False,
+                 auto_update_listmounts_cache=False,
                  auto_update_sessionregistry=False,
                  auto_register_sessions=False,
                  refresh_interval=5,
@@ -232,11 +233,13 @@ class X2goClient(object):
         @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_listmounts_cache: activate automatic updates of mount lists in (L{X2goListSessionsCache})
+        @type auto_update_listmounts_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
         @type auto_register_sessions: C{bool}
-        @param refresh_interval: refresh session list cache and session status every C{<refresh_interval>} seconds
+        @param refresh_interval: refresh session list cache and session status every C{refresh_interval} seconds
         @type refresh_interval: C{int}
         @param pulseaudio_installdir: install path of Pulseaudio binary
         @type pulseaudio_installdir: C{str}
@@ -314,6 +317,7 @@ class X2goClient(object):
         self.session_registry = X2goSessionRegistry(self, logger=self.logger)
         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_listmounts_cache=auto_update_listmounts_cache & use_listsessions_cache,
                                                     auto_update_sessionregistry=auto_update_sessionregistry,
                                                     auto_register_sessions=auto_register_sessions, 
                                                     refresh_interval=refresh_interval,
@@ -327,6 +331,7 @@ class X2goClient(object):
         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
+        self.auto_update_listmounts_cache = auto_update_listmounts_cache
 
     # user hooks for detecting/notifying what happened during application runtime
     def HOOK_session_startup_failed(self, profile_name='UNKNOWN'):
@@ -1095,8 +1100,8 @@ class X2goClient(object):
                         add_to_known_hosts=False,
                         force_password_auth=False):
         """\
-        Connect to a registered X2Go session with registry hash C{<session_uuid>}. 
-        This method basically wraps around paramiko.SSHClient.connect() for the 
+        Connect to a registered X2Go session with registry hash C{session_uuid}
+        This method basically wraps around paramiko.SSHClient.connect() for the
         corresponding session.
 
         @param session_uuid: the X2Go session's UUID registry hash
@@ -1661,7 +1666,7 @@ class X2goClient(object):
     __unshare_local_folder_from_session = unshare_local_folder
     __unshare_local_folder_from_profile = unshare_local_folder
 
-    def get_shared_folders(self, session_uuid=None, profile_name=None):
+    def get_shared_folders(self, session_uuid=None, profile_name=None, check_list_mounts=False):
         """\
         Get a list of local folders mounted within X2Go session with session hash <session_uuid>
         from this client.
@@ -1674,8 +1679,21 @@ class X2goClient(object):
             _associated = self._X2goClient__client_associated_sessions_of_profile_name(profile_name, return_objects=False)
             if len(_associated) > 0:
                 session_uuid = _associated[0]
-        if session_uuid:
-            return self.session_registry(session_uuid).get_shared_folders()
+
+        if session_uuid and profile_name is None:
+            profile_name = self.session_registry(session_uuid).get_profile_name()
+
+        if session_uuid and profile_name:
+
+            mounts = None
+            if check_list_mounts:
+                _mounts = self.list_mounts_by_profile_name(profile_name)
+                mounts = []
+                for mount_list in _mounts.values():
+                    mounts.extend(mount_list)
+
+            return self.session_registry(session_uuid).get_shared_folders(check_list_mounts=check_list_mounts, mounts=mounts)
+
     session_get_shared_folders = get_shared_folders
     profile_get_shared_folders = get_shared_folders
     __session_get_shared_folders = get_shared_folders
@@ -2136,7 +2154,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, cache_type=('sessions'))):
+            if self.use_listsessions_cache and (not self.listsessions_cache.is_cached(session_uuid=session_uuid, cache_type='sessions') or refresh_cache):
                 self.__update_cache_by_session_uuid(session_uuid)
             _session_list = self.listsessions_cache.list_sessions(session_uuid)
 
@@ -2172,7 +2190,7 @@ class X2goClient(object):
         @type profile_id: C{str}
         @param no_cache: do not get the session list from cache, query the X2Go server directly
         @type no_cache: C{bool}
-        @param raw: output the session list in X2go's raw C{x2golistsessions} format
+        @param raw: output the session list in X2go's raw C{x2golistdesktops} format
         @type raw: C{bool}
 
         """
@@ -2200,13 +2218,71 @@ class X2goClient(object):
         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'))):
+            if self.use_listsessions_cache and (not self.listsessions_cache.is_cached(session_uuid=session_uuid, cache_type='desktops') or refresh_cache):
                 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
     __list_desktops = list_desktops
 
+    def list_mounts_by_profile_name(self, profile_name,
+                                    no_cache=False, refresh_cache=False,
+                                    raw=False):
+        """
+        For a given profil C{profile_name} to
+        retrieve its list of mounted client shares for that session.
+
+        @param profile_name: a valid profile name
+        @type profile_name: C{str}
+        @param no_cache: do not get the session list from cache, query the X2Go server directly
+        @type no_cache: C{bool}
+        @param raw: output the session list in X2go's raw C{x2golistmounts} format
+        @type raw: C{bool}
+
+        """
+        sessions = [ s for s in self.client_running_sessions(return_objects=True) if s.get_profile_name() == profile_name ]
+
+        if raw:
+            _list_mounts = ""
+            for session in sessions:
+                _list_mounts += self.__list_mounts(session_uuid=session(), no_cache=no_cache, refresh_cache=refresh_cache, raw=True)
+        else:
+            _list_mounts = {}
+            for session in sessions:
+                _list_mounts.update(self.__list_mounts(session_uuid=session(), no_cache=no_cache, refresh_cache=refresh_cache, raw=False))
+        return _list_mounts
+
+    def list_mounts(self, session_uuid=None, 
+                    no_cache=False, refresh_cache=False,
+                    raw=False):
+        """\
+        Use the X2Go session registered under C{session_uuid} to
+        retrieve its list of mounted client shares for that session.
+
+        @param session_uuid: the X2Go session's UUID registry hash
+        @type session_uuid: C{str}
+        @param no_cache: do not get the session list from cache, query the X2Go server directly
+        @type no_cache: C{bool}
+        @param raw: output the session list in X2go's raw C{x2golistmounts} format
+        @type raw: C{bool}
+
+        """
+        if session_uuid is None:
+            raise x2go_exceptions.X2goClientException('must specify session UUID')
+
+        if raw:
+            return self.session_registry(session_uuid).list_mounts(raw=raw)
+
+        if not self.use_listsessions_cache or not self.auto_update_listmounts_cache or no_cache:
+            _mounts_list = self.session_registry(session_uuid).list_mounts()
+        else:
+            if self.use_listsessions_cache and (not self.listsessions_cache.is_cached(session_uuid=session_uuid, cache_type='mounts') or refresh_cache):
+                self.__update_cache_by_session_uuid(session_uuid, update_sessions=False, update_mounts=True)
+            _mounts_list = self.listsessions_cache.list_mounts(session_uuid)
+
+        return _mounts_list
+    __list_mounts = list_mounts
+
     ###
     ### Provide access to config file class objects
     ### 
@@ -2228,7 +2304,6 @@ class X2goClient(object):
     get_session_profiles = get_profiles
     """Alias for L{get_profiles()}."""
 
-
     @property
     def profile_names(self):
         """\
@@ -2401,7 +2476,6 @@ class X2goClient(object):
                     self.HOOK_on_control_session_death(profile_name)
     __update_sessionregistry_status_by_profile_name = update_sessionregistry_status_by_profile_name
 
-
     def update_sessionregistry_status_by_session_uuid(self, session_uuid):
         """\
         Update the session registry status of a specific L{X2goSession} instance with
@@ -2426,13 +2500,13 @@ class X2goClient(object):
     __update_sessionregistry_status_all_profiles = update_sessionregistry_status_all_profiles
 
 
-    def update_cache_by_profile_name(self, profile_name, cache_types=('sessions'), update_sessions=None, update_desktops=None):
+    def update_cache_by_profile_name(self, profile_name, cache_types=('sessions'), update_sessions=None, update_desktops=None, update_mounts=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})
+        @param cache_types: specify what cache type to update (available: C{sessions}, C{desktops}, C{mounts})
         @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.
@@ -2440,26 +2514,30 @@ class X2goClient(object):
         @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}
+        @param update_mounts: instead of giving a list of cache types, plainly say C{True} here, if 
+            you want to update mounted shares in the mount list cache.
+        @type update_mounts: 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
+            _update_mounts = ('mounts' in cache_types) or update_mounts
             try:
-                self.listsessions_cache.update(profile_name, update_sessions=_update_sessions, update_desktops=_update_desktops)
+                self.listsessions_cache.update(profile_name, update_sessions=_update_sessions, update_desktops=_update_desktops, update_mounts=_update_mounts, )
             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, cache_types=('sessions'), update_sessions=None, update_desktops=None):
+    def update_cache_by_session_uuid(self, session_uuid, cache_types=('sessions'), update_sessions=None, update_desktops=None, update_mounts=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})
+        @param cache_types: specify what cache type to update (available: C{sessions}, C{desktops}, C{mounts})
         @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.
@@ -2467,6 +2545,9 @@ class X2goClient(object):
         @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}
+        @param update_mounts: instead of giving a list of cache types, plainly say C{True} here, if 
+            you want to update mounted shares in the mount list cache.
+        @type update_mounts: C{bool}
 
         """
         profile_name = self.get_session_profile_name(session_uuid)
@@ -2474,14 +2555,15 @@ class X2goClient(object):
                                             cache_types=cache_types,
                                             update_sessions=update_sessions,
                                             update_desktops=update_desktops,
+                                            update_mounts=update_mounts,
                                            )
     __update_cache_by_session_uuid = update_cache_by_session_uuid
 
-    def update_cache_all_profiles(self, cache_types=('sessions'), update_sessions=None, update_desktops=None):
+    def update_cache_all_profiles(self, cache_types=('sessions'), update_sessions=None, update_desktops=None, update_mounts=None):
         """\
         Update the session list cache of all session profiles.
 
-        @param cache_types: specify what cache type to update (available: C{sessions}, C{desktops})
+        @param cache_types: specify what cache type to update (available: C{sessions}, C{desktops}, C{mounts})
         @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.
@@ -2489,6 +2571,9 @@ class X2goClient(object):
         @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}
+        @param update_mounts: instead of giving a list of cache types, plainly say C{True} here, if 
+            you want to update mounted shares in the mount list cache.
+        @type update_mounts: C{bool}
 
         """
         if self.listsessions_cache is not None:
@@ -2497,6 +2582,7 @@ class X2goClient(object):
                                                     cache_types=cache_types,
                                                     update_sessions=update_sessions,
                                                     update_desktops=update_desktops,
+                                                    update_mounts=update_mounts,
                                                    )
 
             # remove profiles that are not connected any more from cache object
@@ -2507,7 +2593,7 @@ class X2goClient(object):
     def register_available_server_sessions_by_profile_name(self, profile_name):
         """\
         Register available sessions that are found on the X2Go server the profile
-        of name C{<profile_name>} is connected to.
+        of name C{profile_name} is connected to.
 
         @param profile_name: the X2Go session profile name
         @type profile_name: C{str}
diff --git a/x2go/guardian.py b/x2go/guardian.py
index 77feeff..8d20dba 100644
--- a/x2go/guardian.py
+++ b/x2go/guardian.py
@@ -55,6 +55,7 @@ class X2goSessionGuardian(threading.Thread):
     def __init__(self, client_instance, 
                  auto_update_listsessions_cache=False, 
                  auto_update_listdesktops_cache=False, 
+                 auto_update_listmounts_cache=False, 
                  auto_update_sessionregistry=False,
                  auto_register_sessions=False,
                  refresh_interval=5,
@@ -64,6 +65,8 @@ class X2goSessionGuardian(threading.Thread):
         @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_listmounts_cache: let L{X2goSessionGuardian} refresh mount lists in the session list cache for all L{X2goSession} objects
+        @type auto_update_listmounts_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. 
@@ -87,6 +90,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_listmounts_cache = auto_update_listmounts_cache
         self.auto_update_sessionregistry = auto_update_sessionregistry
         self.auto_register_sessions = auto_register_sessions
         self.refresh_interval = refresh_interval
@@ -116,6 +120,7 @@ class X2goSessionGuardian(threading.Thread):
                 if self.auto_update_listsessions_cache:
                     self.client_instance.update_cache_all_profiles(update_sessions=self.auto_update_listsessions_cache, 
                                                                    update_desktops=self.auto_update_listdesktops_cache,
+                                                                   update_mounts=self.auto_update_listmounts_cache,
                                                                   )
 
                 if self.auto_update_sessionregistry and not self.auto_register_sessions:
diff --git a/x2go/session.py b/x2go/session.py
index 0c8eb2e..8167dd8 100644
--- a/x2go/session.py
+++ b/x2go/session.py
@@ -926,6 +926,13 @@ class X2goSession(object):
 
         """
         if self.is_alive():
+
+            # unmount shared folders
+            try:
+                self.unshare_all_local_folders()
+            except x2go_exceptions.X2goSessionException:
+                pass
+
             self.control_session.clean_sessions(destroy_terminals=destroy_terminals)
         else:
             self._X2goSession__disconnect()
@@ -964,16 +971,30 @@ class X2goSession(object):
         """
         try:
             return self.control_session.list_desktops(raw=raw)
-        except x2go_exceptions.X2goDesktopSharingException:
-            if raw:
-                return ('','')
-            else:
-                return []
         except x2go_exceptions.X2goControlSessionException:
             self._X2goSession__disconnect()
             return None
     __list_desktops = list_desktops
 
+    def list_mounts(self, raw=False):
+        """\
+        Use the X2Go session registered under C{session_uuid} to
+        retrieve its list of mounted client shares for that session.
+
+        @param raw: output the list of mounted client shares in X2go's
+            raw C{x2golistmounts} format
+        @type raw: C{bool}
+
+        @return: a list of strings representing mounted client shares for this session
+        @rtype: C{list}
+
+        """
+        try:
+            return self.control_session.list_mounts(self.session_name, raw=raw)
+        except x2go_exceptions.X2goControlSessionException:
+            self._X2goSession__disconnect()
+            return None
+
     def update_status(self, session_list=None, force_update=False):
         """\
         Update the current session status. The L{X2goSession} instance uses an internal
@@ -1247,6 +1268,12 @@ class X2goSession(object):
         if self.is_alive():
             if self.has_terminal_session():
 
+                # unmount shared folders
+                try:
+                    self.unshare_all_local_folders()
+                except x2go_exceptions.X2goSessionException:
+                    pass
+
                 if self.terminal_session.suspend():
 
                     self.running = False
@@ -1286,6 +1313,12 @@ class X2goSession(object):
         if self.is_alive():
             if self.has_terminal_session():
 
+                # unmount shared folders
+                try:
+                    self.unshare_all_local_folders()
+                except x2go_exceptions.X2goSessionException:
+                    pass
+
                 if self.terminal_session.terminate():
                     self.running = False
                     self.suspended = False
@@ -1547,14 +1580,47 @@ class X2goSession(object):
             raise x2go_exceptions.X2goSessionException('this X2goSession object does not have any associated terminal')
     __unshare_local_folder = unshare_local_folder
 
-    def get_shared_folders(self):
+    def get_shared_folders(self, check_list_mounts=False, mounts=None):
         """\
         Get a list of local folders mounted within this X2Go session from this client.
 
-        @return: returns a C{list} of those folder names that are mounted with this X2Go session.
+        @param check_list_mounts: if set to C{True} the list of shared folders is referenced against
+            the latest status of the server-side mount list.
+        @type check_list_mounts: C{bool}
+        @param mounts: a server-side dictionary of session name keys and lists of mounted shares (server-side mount points)
+        @type mounts: C{dict}
+
+        @return: returns a C{list} of those local folder names that are mounted with this X2Go session.
         @rtype: C{list}
 
         """
+        if self.shared_folders and check_list_mounts:
+
+            unshared_folders = []
+            if mounts is None:
+                mounts = self.list_mounts()
+
+            for shared_folder in self.shared_folders:
+
+                _found = False
+
+                for mount in mounts:
+                    mount = mount.split('|')[1]
+                    _mount_point = shared_folder.replace('/', '_')
+                    if mount.endswith(_mount_point):
+                        _found = True
+                        break
+
+                if not _found:
+                    unshared_folders.append(shared_folder)
+
+            for unshared_folder in unshared_folders:
+                try:
+                    self.shared_folders.remove(unshared_folder)
+                    self.logger('Detected server-side unsharing of client-side folder for profile %s: %s:' % (self.get_profile_name(), shared_folder), loglevel=log.loglevel_INFO)
+                except IndexError:
+                    pass
+
         return self.shared_folders
     __get_shared_folders = get_shared_folders
 
@@ -1580,12 +1646,6 @@ class X2goSession(object):
         if self.has_terminal_session():
             self.terminal_session.release_proxy()
 
-        # unmount shared folders
-        try:
-            self.unshare_all_local_folders()
-        except x2go_exceptions.X2goSessionException:
-            pass
-
         # remove client-side session cache
         if self.terminated and self.has_terminal_session():
             self.terminal_session.post_terminate_cleanup()


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