Package x2go :: Module cache
[frames] | no frames]

Source Code for Module x2go.cache

  1  # -*- coding: utf-8 -*- 
  2   
  3  # Copyright (C) 2010-2015 by Mike Gabriel <mike.gabriel@das-netzwerkteam.de> 
  4  # 
  5  # Python X2Go is free software; you can redistribute it and/or modify 
  6  # it under the terms of the GNU Affero General Public License as published by 
  7  # the Free Software Foundation; either version 3 of the License, or 
  8  # (at your option) any later version. 
  9  # 
 10  # Python X2Go is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  # GNU Affero General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU Affero General Public License 
 16  # along with this program; if not, write to the 
 17  # Free Software Foundation, Inc., 
 18  # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 
 19   
 20  """\ 
 21  X2GoListSessionCache class - caching X2Go session information. 
 22   
 23  """ 
 24  __NAME__ = 'x2gocache-pylib' 
 25   
 26  # modules 
 27  import copy 
 28  import gevent 
 29   
 30  # Python X2Go modules 
 31  import log 
 32  import x2go_exceptions 
 33   
34 -class X2GoListSessionsCache(object):
35 """\ 36 For non-blocking operations in client applications using Python X2Go, it is 37 recommended to enable the L{X2GoListSessionsCache}. This can be done by calling 38 the constructor of the L{X2GoClient} class. 39 40 The session list and desktop cache gets updated in regular intervals by a threaded 41 L{X2GoSessionGuardian} instance. For the session list and desktop list update, the 42 X2Go server commands C{x2golistsessions} and C{x2godesktopsessions} are called and 43 the command's stdout is cached in the session list cache. 44 45 Whenever your client application needs access to either the server's session list 46 or the server's desktop list the session cache is queried instead. This assures that 47 the server's session/desktop list is available without delay, even on slow internet 48 connections. 49 50 """ 51 x2go_listsessions_cache = {} 52
53 - def __init__(self, client_instance, logger=None, loglevel=log.loglevel_DEFAULT):
54 """\ 55 @param client_instance: the L{X2GoClient} instance that uses this L{X2GoListSessionsCache} 56 @type client_instance: C{obj} 57 @param logger: you can pass an L{X2GoLogger} object to the L{X2GoListSessionsCache} constructor 58 @type logger: C{obj} 59 @param loglevel: if no L{X2GoLogger} object has been supplied a new one will be 60 constructed with the given loglevel 61 @type loglevel: C{int} 62 63 """ 64 self.x2go_listsessions_cache = {} 65 self.last_listsessions_cache = {} 66 self.protected = False 67 68 if logger is None: 69 self.logger = log.X2GoLogger(loglevel=loglevel) 70 else: 71 self.logger = copy.deepcopy(logger) 72 self.logger.tag = __NAME__ 73 74 self.client_instance = client_instance
75
76 - def delete(self, profile_name):
77 """\ 78 Remove session list from cache for a given profile. 79 80 @param profile_name: name of profile to operate on 81 @type profile_name: C{str} 82 83 """ 84 while self.protected: 85 gevent.sleep(.1) 86 try: del self.x2go_listsessions_cache[profile_name] 87 except KeyError: pass
88
89 - def check_cache(self):
90 """\ 91 Check if session list cache elements are still valid (i.e. if all corresponding 92 session profiles are still connected). If not so, remove invalid cache entries from 93 the session list cache. 94 95 """ 96 for profile_name in self.x2go_listsessions_cache.keys(): 97 if profile_name not in self.client_instance.client_connected_profiles(return_profile_names=True): 98 del self.x2go_listsessions_cache[profile_name]
99
100 - def update_all(self, update_sessions=True, update_desktops=False):
101 """\ 102 Update L{X2GoListSessionsCache} for all connected session profiles. 103 104 @param update_sessions: cache recent session lists from all connected servers 105 @type update_sessions: C{bool} 106 @param update_desktops: cache recent desktop lists from all connected servers 107 @type update_desktops: C{bool} 108 109 """ 110 for profile_name in self.client_instance.client_connected_profiles(return_profile_names=True): 111 self.update(profile_name, update_sessions=update_sessions, update_desktops=update_desktops) 112 113 self.check_cache()
114
115 - def update(self, profile_name, update_sessions=True, update_desktops=False, update_mounts=False):
116 """\ 117 Update L{X2GoListSessionsCache} (i.e. session/desktops) for session profile C{profile_name}. 118 119 @param profile_name: name of profile to update 120 @type profile_name: C{str} 121 @param update_sessions: cache recent session list from server 122 @type update_sessions: C{bool} 123 @param update_desktops: cache recent desktop list from server 124 @type update_desktops: C{bool} 125 @param update_mounts: cache list of client-side mounts on server 126 @type update_mounts: C{bool} 127 128 """ 129 self.protected = True 130 self.last_listsessions_cache = copy.deepcopy(self.x2go_listsessions_cache) 131 control_session = self.client_instance.client_control_session_of_profile_name(profile_name) 132 if not self.x2go_listsessions_cache.has_key(profile_name): 133 self.x2go_listsessions_cache[profile_name] = {'sessions': None, 'desktops': None, 'mounts': {}, } 134 if update_sessions: 135 self._update_sessions(profile_name, control_session) 136 if update_desktops: 137 self._update_desktops(profile_name, control_session) 138 if update_mounts: 139 self._update_mounts(profile_name, control_session) 140 self.protected = False
141
142 - def _update_mounts(self, profile_name, control_session):
143 """\ 144 Update mounts list of L{X2GoListSessionsCache} for session profile C{profile_name}. 145 146 @param profile_name: name of profile to update 147 @type profile_name: C{str} 148 149 @raise X2GoControlSessionException: if the control session's C{list_mounts} method fails 150 """ 151 try: 152 self.x2go_listsessions_cache[profile_name]['mounts'] = {} 153 if self.x2go_listsessions_cache[profile_name]['sessions']: 154 for session_name in self.x2go_listsessions_cache[profile_name]['sessions']: 155 session = self.client_instance.get_session_of_session_name(session_name, return_object=True, match_profile_name=profile_name) 156 if session is not None and session.is_running(): 157 if control_session is not None and not control_session.has_session_died(): 158 self.x2go_listsessions_cache[profile_name]['mounts'].update(control_session.list_mounts(session_name)) 159 except (x2go_exceptions.X2GoControlSessionException, AttributeError), e: 160 if profile_name in self.x2go_listsessions_cache.keys(): 161 del self.x2go_listsessions_cache[profile_name] 162 self.protected = False 163 raise x2go_exceptions.X2GoControlSessionException(str(e)) 164 except x2go_exceptions.X2GoTimeOutException: 165 pass 166 except KeyError: 167 pass
168
169 - def _update_desktops(self, profile_name, control_session):
170 """\ 171 Update session lists of L{X2GoListSessionsCache} for session profile C{profile_name}. 172 173 @param profile_name: name of profile to update 174 @type profile_name: C{str} 175 @param control_session: X2Go control session instance 176 @type control_session: C{obj} 177 178 @raise X2GoControlSessionException: if the control session's C{list_desktop} method fails 179 """ 180 try: 181 if control_session is not None and not control_session.has_session_died(): 182 self.x2go_listsessions_cache[profile_name]['desktops'] = control_session.list_desktops() 183 except (x2go_exceptions.X2GoControlSessionException, AttributeError), e: 184 if profile_name in self.x2go_listsessions_cache.keys(): 185 del self.x2go_listsessions_cache[profile_name] 186 self.protected = False 187 raise x2go_exceptions.X2GoControlSessionException(str(e)) 188 except x2go_exceptions.X2GoTimeOutException: 189 pass 190 except KeyError: 191 pass
192
193 - def _update_sessions(self, profile_name, control_session):
194 """\ 195 Update desktop list of L{X2GoListSessionsCache} for session profile C{profile_name}. 196 197 @param profile_name: name of profile to update 198 @type profile_name: C{str} 199 200 @raise X2GoControlSessionException: if the control session's C{list_sessions} method fails 201 """ 202 try: 203 if control_session is not None and not control_session.has_session_died(): 204 self.x2go_listsessions_cache[profile_name]['sessions'] = control_session.list_sessions() 205 except (x2go_exceptions.X2GoControlSessionException, AttributeError), e: 206 if profile_name in self.x2go_listsessions_cache.keys(): 207 del self.x2go_listsessions_cache[profile_name] 208 self.protected = False 209 raise x2go_exceptions.X2GoControlSessionException(str(e)) 210 except KeyError: 211 pass
212
213 - def list_sessions(self, session_uuid):
214 """\ 215 Retrieve a session list from the current cache content of L{X2GoListSessionsCache} 216 for a given L{X2GoSession} instance (specified by its unique session UUID). 217 218 @param session_uuid: unique identifier of session to query cache for 219 @type session_uuid: C{str} 220 221 @return: a data object containing available session information 222 @rtype: C{X2GoServerSessionList*} instance (or C{None}) 223 224 """ 225 profile_name = self.client_instance.get_session_profile_name(session_uuid) 226 if self.is_cached(session_uuid=session_uuid): 227 return self.x2go_listsessions_cache[profile_name]['sessions'] 228 else: 229 return None
230
231 - def list_desktops(self, session_uuid):
232 """\ 233 Retrieve a list of available desktop sessions from the current cache content of 234 L{X2GoListSessionsCache} for a given L{X2GoSession} instance (specified by its 235 unique session UUID). 236 237 @param session_uuid: unique identifier of session to query cache for 238 @type session_uuid: C{str} 239 240 @return: a list of strings representing X2Go desktop sessions available for sharing 241 @rtype: C{list} (or C{None}) 242 243 """ 244 profile_name = self.client_instance.get_session_profile_name(session_uuid) 245 if self.is_cached(session_uuid=session_uuid): 246 return self.x2go_listsessions_cache[profile_name]['desktops'] 247 else: 248 return None
249
250 - def list_mounts(self, session_uuid):
251 """\ 252 Retrieve a list of mounted client shares from the current cache content of 253 L{X2GoListSessionsCache} for a given L{X2GoSession} instance (specified by its 254 unique session UUID). 255 256 @param session_uuid: unique identifier of session to query cache for 257 @type session_uuid: C{str} 258 259 @return: a list of strings representing mounted client shares 260 @rtype: C{list} (or C{None}) 261 262 """ 263 profile_name = self.client_instance.get_session_profile_name(session_uuid) 264 if self.is_cached(session_uuid=session_uuid): 265 return self.x2go_listsessions_cache[profile_name]['mounts'] 266 else: 267 return None
268
269 - def is_cached(self, profile_name=None, session_uuid=None, cache_type=None):
270 """\ 271 Check if session information is cached. 272 273 @param profile_name: name of profile to update 274 @type profile_name: C{str} 275 @param session_uuid: unique identifier of session to query cache for 276 @type session_uuid: C{str} 277 278 @return: C{True} if session information is cached 279 @rtype: C{bool} 280 281 """ 282 if profile_name is None and session_uuid and self.client_instance: 283 try: 284 profile_name = self.client_instance.get_session_profile_name(session_uuid) 285 except x2go_exceptions.X2GoSessionRegistryException: 286 raise x2go_exceptions.X2GoSessionCacheException("requested session UUID is not valid anymore") 287 _is_profile_cached = self.x2go_listsessions_cache.has_key(profile_name) 288 _is_cache_type_cached = _is_profile_cached and self.x2go_listsessions_cache[profile_name].has_key(cache_type) 289 if cache_type is None: 290 return _is_profile_cached 291 else: 292 return _is_cache_type_cached
293