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