[X2Go-Commits] python-x2go.git - build-baikal (branch) updated: 0.1.1.4-102-g2f1c22d

X2Go dev team git-admin at x2go.org
Wed Jan 8 15:26:48 CET 2014


The branch, build-baikal has been updated
       via  2f1c22df05d628d18458ded68c27100e8c76dbbc (commit)
      from  20934399dd3170bdbbb616eb3d634acd00b647d3 (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                  |    2 +
 x2go/backends/terminal/_stdout.py |    2 +-
 x2go/cache.py                     |   10 +++--
 x2go/client.py                    |   52 ++++++++++++++++---------
 x2go/registry.py                  |   77 ++++++++++++++++++++++++++++++++++---
 x2go/session.py                   |   57 ++++++++++++++++++++++-----
 6 files changed, 161 insertions(+), 39 deletions(-)

The diff of changes is:
diff --git a/debian/changelog b/debian/changelog
index 11d28ee..1f876f8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -17,6 +17,8 @@ python-x2go (0.1.2.0-0~x2go1) UNRELEASED; urgency=low
       x2goserver >= 3.1.0.0).
     - Provide client-side cache of shared local folders, detect server-side
       unsharing of client-side folders.
+    - Introduce concept of master sessions per profile to X2goClient class. Only
+      the master session can mount/unmount client-side shared 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/terminal/_stdout.py b/x2go/backends/terminal/_stdout.py
index 4ded9bc..d1db106 100644
--- a/x2go/backends/terminal/_stdout.py
+++ b/x2go/backends/terminal/_stdout.py
@@ -663,7 +663,7 @@ class X2goTerminalSessionSTDOUT(object):
                          '"%s"' % _CURRENT_LOCAL_USER,
                          _x2go_key_fname,
                          '%s__REVERSESSH_PORT__%s; ' % (local_path, self.session_info.sshfs_port),
-                         'rm -f %s %s.ident' % (_x2go_key_fname, _x2go_key_fname), 
+                         'rm -f %s %s.ident' % (_x2go_key_fname, _x2go_key_fname),
                        ]
 
         elif folder_type == 'spool':
diff --git a/x2go/cache.py b/x2go/cache.py
index a1d6c51..87d2bac 100644
--- a/x2go/cache.py
+++ b/x2go/cache.py
@@ -142,7 +142,6 @@ class X2goListSessionsCache(object):
         @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']:
@@ -251,11 +250,14 @@ class X2goListSessionsCache(object):
         @type session_uuid: C{str}
 
         """
-        if profile_name is None and session_uuid:
-            profile_name = self.client_instance.get_session_profile_name(session_uuid)
+        if profile_name is None and session_uuid and self.client_instance:
+            try:
+                profile_name = self.client_instance.get_session_profile_name(session_uuid)
+            except x2go_exceptions.X2goSessionRegistryException:
+                raise x2go_exceptions.X2goSessionCacheException("requested session UUID is not valid anymore")
         _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
+            return _is_cache_type_cached
diff --git a/x2go/client.py b/x2go/client.py
index 095598c..880c79d 100644
--- a/x2go/client.py
+++ b/x2go/client.py
@@ -1546,13 +1546,14 @@ class X2goClient(object):
 
         """
         if session_uuid is None and profile_name:
-            _connected = self._X2goClient__client_connected_sessions_of_profile_name(profile_name, return_objects=False)
-            if len(_connected) > 0:
-                session_uuid = _connected[0]
+            session_uuid = self._X2goClient__get_master_session(profile_name, return_object=False)
         if session_uuid:
-            return self.session_registry(session_uuid).is_folder_sharing_available()
+            try:
+                return self.session_registry(session_uuid).is_folder_sharing_available()
+            except x2go_exceptions.X2goSessionRegistryException:
+                return False
         else:
-            self.logger('Cannot find a terminal session for profile ,,%s\'\' that can be used to query folder sharing capabilities' % profile_name, loglevel=log.loglevel_WARN)
+            self.logger('Cannot find a terminal session for profile ,,%s\'\' that can be used to query folder sharing capabilities' % profile_name, loglevel=log.loglevel_INFO)
             return False
     __is_folder_sharing_available = is_folder_sharing_available
     __profile_is_folder_sharing_available = is_folder_sharing_available
@@ -1584,11 +1585,12 @@ class X2goClient(object):
         if folder_name: local_path = folder_name
 
         if session_uuid is None and profile_name:
-            _associated = self._X2goClient__client_associated_sessions_of_profile_name(profile_name, return_objects=False)
-            if len(_associated) > 0:
-                session_uuid = _associated[0]
+            session_uuid = self._X2goClient__get_master_session(profile_name, return_object=False)
         if session_uuid:
-            return self.session_registry(session_uuid).share_local_folder(local_path=local_path)
+            try:
+                return self.session_registry(session_uuid).share_local_folder(local_path=local_path)
+            except x2go_exceptions.X2goSessionException:
+                return False
         else:
             self.logger('Cannot find a terminal session for profile ,,%s\'\' to share a local folder with' % profile_name, loglevel=log.loglevel_WARN)
             return False
@@ -1616,9 +1618,7 @@ class X2goClient(object):
 
         """
         if session_uuid is None and profile_name:
-            _associated = self._X2goClient__client_associated_sessions_of_profile_name(profile_name, return_objects=False)
-            if len(_associated) > 0:
-                session_uuid = _associated[0]
+            session_uuid = self._X2goClient__get_master_session(profile_name, return_object=False)
         if session_uuid:
             return self.session_registry(session_uuid).unshare_all_local_folders()
         else:
@@ -1653,9 +1653,7 @@ class X2goClient(object):
 
         """
         if session_uuid is None and profile_name:
-            _associated = self._X2goClient__client_associated_sessions_of_profile_name(profile_name, return_objects=False)
-            if len(_associated) > 0:
-                session_uuid = _associated[0]
+            session_uuid = self._X2goClient__get_master_session(profile_name, return_object=False)
         if session_uuid:
             return self.session_registry(session_uuid).unshare_local_folder(local_path=local_path)
         else:
@@ -1676,9 +1674,7 @@ class X2goClient(object):
 
         """
         if session_uuid is None and profile_name:
-            _associated = self._X2goClient__client_associated_sessions_of_profile_name(profile_name, return_objects=False)
-            if len(_associated) > 0:
-                session_uuid = _associated[0]
+            session_uuid = self._X2goClient__get_master_session(profile_name, return_object=False)
 
         if session_uuid and profile_name is None:
             profile_name = self.session_registry(session_uuid).get_profile_name()
@@ -1699,6 +1695,26 @@ class X2goClient(object):
     __session_get_shared_folders = get_shared_folders
     __profile_get_shared_folders = get_shared_folders
 
+    def get_master_session(self, profile_name, return_object=True, return_session_name=False):
+        """\
+        Retrieve the master session of a specific profile.
+
+        @param profile_name: the profile name that we query the master session of
+        @type profile_name: C{str}
+        @param return_object: return L{X2goSession} instance
+        @type return_object: C{bool}
+        @param return_session_name: return X2Go session name
+        @type return_session_name: C{bool}
+
+        @return: a session list (as UUID hashes, objects, profile names/IDs or session names)
+        @rtype: C{list}
+
+        """
+        return self.session_registry.master_session(profile_name, return_object=return_object, return_session_name=return_session_name)
+    profile_master_session = get_master_session
+    __get_master_session = get_master_session
+    __profile_master_session = profile_master_session
+
     ###
     ### Provide access to the X2goClient's session registry
     ### 
diff --git a/x2go/registry.py b/x2go/registry.py
index 35426f1..1771ae6 100644
--- a/x2go/registry.py
+++ b/x2go/registry.py
@@ -78,6 +78,7 @@ class X2goSessionRegistry(object):
 
         self.registry = {}
         self.control_sessions = {}
+        self.master_sessions = {}
 
         self._last_available_session_registration = None
         self._skip_auto_registration = False
@@ -263,6 +264,8 @@ class X2goSessionRegistry(object):
             _profile_name = self(_session_uuid).get_profile_name()
             _session_name = self(_session_uuid).get_session_name()
 
+            print _session_uuid, _session_name
+
             if self(_session_uuid).get_server_hostname() != _current_status['server']:
 
                 # if the server (hostname) has changed due to a configuration change we skip all notifications
@@ -279,12 +282,19 @@ class X2goSessionRegistry(object):
                 else:
                     # explicitly ask for the terminal_session object directly here, so we also get 'PENDING' terminal sessions here...
                     if self(_session_uuid).terminal_session:
+
+                        # declare as master session if appropriate
+                        if _profile_name not in self.master_sessions.keys():
+                            self.master_sessions[_profile_name] = self(_session_uuid)
+                            self(_session_uuid).set_master_session()
+
                         if _last_status['suspended']:
                             # from a suspended state
                             self.client_instance.HOOK_on_session_has_resumed_by_me(session_uuid=_session_uuid, profile_name=_profile_name, session_name=_session_name)
                         elif _last_status['virgin']:
                             # as a new session
                             self.client_instance.HOOK_on_session_has_started_by_me(session_uuid=_session_uuid, profile_name=_profile_name, session_name=_session_name)
+
                     else:
                         if _last_status['suspended']:
                             # from a suspended state
@@ -293,11 +303,26 @@ class X2goSessionRegistry(object):
                             # as a new session
                             self.client_instance.HOOK_on_session_has_started_by_other(session_uuid=_session_uuid, profile_name=_profile_name, session_name=_session_name)
 
-            elif _last_status['connected'] and (not _last_status['suspended'] and _current_status['suspended']) and not _current_status['faulty']:
+            elif _last_status['connected'] and (not _last_status['suspended'] and _current_status['suspended']) and not _current_status['faulty'] and _session_name:
+
+                # unregister as master session
+                if _profile_name in self.master_sessions.keys():
+                    self(_session_uuid).unset_master_session()
+                    if self.master_sessions[_profile_name] == self(_session_uuid):
+                        del self.master_sessions[_profile_name]
+
                 # session has been suspended
                 self(_session_uuid).session_cleanup()
                 self.client_instance.HOOK_on_session_has_been_suspended(session_uuid=_session_uuid, profile_name=_profile_name, session_name=_session_name)
-            elif _last_status['connected'] and (not _last_status['terminated'] and _current_status['terminated']) and not _current_status['faulty']:
+
+            elif _last_status['connected'] and (not _last_status['terminated'] and _current_status['terminated']) and not _current_status['faulty'] and _session_name:
+
+                # unregister as master session
+                if _profile_name in self.master_sessions.keys():
+                    self(_session_uuid).unset_master_session()
+                    if self.master_sessions[_profile_name] == self(_session_uuid):
+                        del self.master_sessions[_profile_name]
+
                 # session has terminated
                 self.client_instance.HOOK_on_session_has_terminated(session_uuid=_session_uuid, profile_name=_profile_name, session_name=_session_name)
                 try: self(_session_uuid).session_cleanup()
@@ -307,6 +332,12 @@ class X2goSessionRegistry(object):
                 if len(self.virgin_sessions_of_profile_name(profile_name)) > 1:
                     self.forget(_session_uuid)
 
+        for _profile_name in self.connected_profiles(return_profile_names=True):
+            _running_sessions = self.running_sessions_of_profile_name(_profile_name)
+            if _profile_name not in self.master_sessions.keys() and _running_sessions:
+                self.master_sessions[_profile_name] = _running_sessions[0]
+                _running_sessions[0].set_master_session()
+
         return True
 
     def register_available_server_sessions(self, profile_name, session_list=None, newly_connected=False):
@@ -443,7 +474,7 @@ class X2goSessionRegistry(object):
             control_session = self.control_sessions[profile_id]
 
         # when starting a new session, we will try to use unused registered virgin sessions
-        # depending on your application layout, there shoul either be one or no such virgin session at all
+        # depending on your application layout, there should either be one or no such virgin session at all
         _virgin_sessions = self.virgin_sessions_of_profile_name(profile_name, return_objects=True)
         if _virgin_sessions and not session_name:
 
@@ -496,6 +527,9 @@ class X2goSessionRegistry(object):
         if profile_id not in self.control_sessions.keys():
             self.control_sessions[profile_id] = s.get_control_session()
 
+        # make sure a new session is a non-master session unless promoted in update_status method
+        self(session_uuid).unset_master_session()
+
         return session_uuid
 
     def has_session_of_session_name(self, session_name):
@@ -618,7 +652,6 @@ class X2goSessionRegistry(object):
         @return: a session list (as UUID hashes, objects, profile names/IDs or session names)
         @rtype: C{list}
 
-
         """
         return self._sessionsWithState('virgin', return_objects=return_objects, return_profile_names=return_profile_names, return_profile_ids=return_profile_ids, return_session_names=return_session_names)
 
@@ -891,7 +924,7 @@ class X2goSessionRegistry(object):
         """
         return [ c for c in self.control_sessions.values() if c.is_connected() ]
 
-    def connected_profiles(self, use_paramiko=False):
+    def connected_profiles(self, use_paramiko=False, return_profile_ids=True, return_profile_names=False):
         """\
         Retrieve a list of all currently connected session profiles.
 
@@ -904,5 +937,37 @@ class X2goSessionRegistry(object):
         if use_paramiko:
             return [ p for p in self.control_sessions.keys() if self.control_sessions[p].is_connected() ]
         else:
-            return self.connected_sessions(return_profile_ids=True)
+            return self.connected_sessions(return_profile_ids=return_profile_ids, return_profile_names=return_profile_names)
+
+    def master_session(self, profile_name, return_object=True, return_session_name=False):
+        """\
+        Retrieve the master session of a specific profile.
 
+        @param profile_name: the profile name that we query the master session of
+        @type profile_name: C{str}
+        @param return_object: return L{X2goSession} instance
+        @type return_object: C{bool}
+        @param return_session_name: return X2Go session name
+        @type return_session_name: C{bool}
+
+        @return: a session list (as UUID hashes, objects, profile names/IDs or session names)
+        @rtype: C{list}
+
+        """
+        if profile_name not in self.connected_profiles(return_profile_names=True):
+            return None
+
+        if profile_name not in self.master_sessions.keys() or self.master_sessions[profile_name] is None:
+            return None
+
+        _session = self.master_sessions[profile_name]
+
+        if not _session.is_master_session():
+            self.master_sessions[profile_name] = None
+
+        if return_object:
+            return _session
+        elif return_session_name:
+            return _session.get_session_name()
+        else:
+            return _session.get_uuid()
diff --git a/x2go/session.py b/x2go/session.py
index 8167dd8..6c82eaa 100644
--- a/x2go/session.py
+++ b/x2go/session.py
@@ -276,6 +276,7 @@ class X2goSession(object):
         self._SUPPORTED_MIMEBOX = SUPPORTED_MIMEBOX
         self._SUPPORTED_FOLDERSHARING = SUPPORTED_FOLDERSHARING
 
+        self.master_session = None
         self.init_control_session()
         self.terminal_session = None
 
@@ -364,6 +365,42 @@ class X2goSession(object):
                                                         ssh_rootdir=self.ssh_rootdir,
                                                         logger=self.logger)
 
+    def is_master_session(self):
+        """\
+        Is this session a/the master session of sessions.
+
+        The master session is the session has been launched first for a specific connection,
+        it also is _the_ session that controls the client-side shared folders.
+
+        @param server: new server name
+        @type server: C{str}
+
+        """
+        if self.master_session is None:
+            return True
+        return self.master_session
+
+    def set_master_session(self):
+        """\
+        Declare this as a master session of a connection channel.
+
+        @param server: new server name
+        @type server: C{str}
+
+        """
+        self.logger('Using session %s as master session for profile %s.' % (self.get_session_name(), self.get_profile_name()), loglevel=log.loglevel_NOTICE)
+        self.master_session = True
+
+    def unset_master_session(self):
+        """\
+        Declare this as a non-master session of a connection channel.
+
+        @param server: new server name
+        @type server: C{str}
+
+        """
+        self.master_session = False
+
     def set_server(self, server):
         """\
         Modify server name after L{X2goSession} has already been initialized.
@@ -432,6 +469,8 @@ class X2goSession(object):
                 self.get_control_session().__del__()
                 self.control_session = None
 
+        self.master_session = None
+
         if self.has_terminal_session():
             self.get_terminal_session().__del__()
             self.terminal_session = None
@@ -855,6 +894,7 @@ class X2goSession(object):
         self.suspended = None
         self.terminated = None
         self.faults = None
+        self.master_session = None
         try:
             self.update_status(force_update=True)
         except x2go_exceptions.X2goControlSessionException:
@@ -1493,8 +1533,11 @@ class X2goSession(object):
         if self._SUPPORTED_FOLDERSHARING and self.allow_share_local_folders:
             if self.is_connected():
                 return self.control_session.is_folder_sharing_available()
+            else:
+                self.logger('session is not connected, cannot share local folders now', loglevel=log.loglevel_WARN)
         else:
             self.logger('local folder sharing is disabled for this session profile', loglevel=log.loglevel_WARN)
+        return False
 
     def share_local_folder(self, local_path=None, folder_name=None):
         """\
@@ -1515,13 +1558,11 @@ class X2goSession(object):
         if folder_name: local_path=folder_name
 
         if self.has_terminal_session():
-            if self._SUPPORTED_FOLDERSHARING and self.allow_share_local_folders:
+            if self.is_folder_sharing_available() and self.is_master_session():
                 if self.terminal_session.share_local_folder(local_path=local_path):
                     self.shared_folders.append(local_path)
                     return True
                 return False
-            else:
-                self.logger('local folder sharing is disabled for this session profile', loglevel=log.loglevel_WARN)
         else:
             raise x2go_exceptions.X2goSessionException('this X2goSession object does not have any associated terminal')
     __share_local_folder = share_local_folder
@@ -1540,7 +1581,7 @@ class X2goSession(object):
 
         """
         if self.has_terminal_session():
-            if self._SUPPORTED_FOLDERSHARING and self.allow_share_local_folders:
+            if self.is_folder_sharing_available() and self.is_master_session():
                 if force_all:
                     self.shared_folders = []
                     return self.terminal_session.unshare_all_local_folders()
@@ -1550,8 +1591,6 @@ class X2goSession(object):
                         retval = retval | self.terminal_session.unshare_local_folder(_shared_folder)
                     self.shared_folders = []
                     return retval
-            else:
-                self.logger('local folder sharing is disabled for this session profile', loglevel=log.loglevel_WARN)
         else:
             raise x2go_exceptions.X2goSessionException('this X2goSession object does not have any associated terminal')
         return False
@@ -1571,11 +1610,9 @@ class X2goSession(object):
 
         """
         if self.has_terminal_session():
-            if self._SUPPORTED_FOLDERSHARING and self.allow_share_local_folders and local_path in self.shared_folders:
+            if self.is_folder_sharing_available() and self.is_master_session() and local_path in self.shared_folders:
                 self.shared_folders.remove(local_path)
                 return self.terminal_session.unshare_local_folder(local_path=local_path)
-            else:
-                self.logger('local folder sharing is disabled for this session profile', loglevel=log.loglevel_WARN)
         else:
             raise x2go_exceptions.X2goSessionException('this X2goSession object does not have any associated terminal')
     __unshare_local_folder = unshare_local_folder
@@ -1594,7 +1631,7 @@ class X2goSession(object):
         @rtype: C{list}
 
         """
-        if self.shared_folders and check_list_mounts:
+        if self.is_folder_sharing_available and self.is_master_session() and self.shared_folders and check_list_mounts:
 
             unshared_folders = []
             if mounts is 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