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

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


The branch, brokerclient 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