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

Source Code for Module x2go.xserver

  1  # -*- coding: utf-8 -*- 
  2   
  3  # Copyright (C) 2010-2011 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 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 General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU 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  # This code was initially written by: 
 21  #       2010 Dick Kniep <dick.kniep@lindix.nl> 
 22  # 
 23  # Other contributors: 
 24  #       none so far 
 25   
 26  __NAME__ = 'x2goxserver-pylib' 
 27   
 28  from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS 
 29  if _X2GOCLIENT_OS == 'Windows': 
 30      import wmi 
 31      import win32process 
 32   
 33  # modules 
 34  import os 
 35  import threading 
 36  import gevent 
 37  import copy 
 38   
 39  # Python X2go modules 
 40  import log 
 41  from defaults import X2GO_XCONFIG_CONFIGFILES as _X2GO_XCONFIG_CONFIGFILES 
 42  from defaults import X2GO_CLIENTXCONFIG_DEFAULTS as _X2GO_CLIENTXCONFIG_DEFAULTS 
 43  import inifiles 
44 45 46 -class X2goClientXConfig(inifiles.X2goIniFile):
47 """\ 48 Configuration file based XServer startup settings for X2goClient instances. 49 50 This class is needed for Windows systems and (maybe soon) for Unix desktops using Wayland. 51 52 """ 53 defaultValues = _X2GO_CLIENTXCONFIG_DEFAULTS 54
55 - def __init__(self, config_files=_X2GO_XCONFIG_CONFIGFILES, defaults=None, logger=None, loglevel=log.loglevel_DEFAULT):
56 """\ 57 Constructs an L{X2goClientXConfig} instance. This is normally done by an L{X2goClient} instance. 58 You can retrieve this L{X2goClientXConfig} instance with the C{X2goClient.get_client_xconfig()} 59 method. 60 61 On construction the L{X2goClientXConfig} instance is filled with values from the configuration files:: 62 63 /etc/x2goclient/xconfig 64 ~/.x2goclient/xconfig 65 66 The files are read in the specified order and config options of both files are merged. Options 67 set in the user configuration file (C{~/.x2goclient/xconfig}) override global options set in 68 C{/etc/x2goclient/xconfig}. 69 70 @param config_files: a list of configuration file names 71 @type config_files: C{list} 72 @param defaults: a Python dictionary with configuration file defaults (use on your own risk) 73 @type defaults: C{dict} 74 @param logger: you can pass an L{X2goLogger} object to the L{X2goClientXConfig} constructor 75 @type logger: C{instance} 76 @param loglevel: if no L{X2goLogger} object has been supplied a new one will be 77 constructed with the given loglevel 78 @type loglevel: C{int} 79 80 """ 81 if _X2GOCLIENT_OS not in ("Windows"): 82 import exceptions 83 class OSNotSupportedException(exceptions.StandardError): pass 84 raise OSNotSupportedException('classes of x2go.xserver module are for Windows only') 85 86 inifiles.X2goIniFile.__init__(self, config_files, defaults=defaults, logger=logger, loglevel=loglevel)
87
88 - def get_xserver_config(self, xserver_name):
89 """\ 90 Retrieve the XServer configuration (from the xconfig file) for the given XServer application. 91 92 @param xserver_name: name of the XServer application 93 @type xserver_name: C{str} 94 95 @return: A Python dictionary containing the XServer's configuration settings 96 @rtype: C{list} 97 98 """ 99 _xserver_config = {} 100 for option in self.iniConfig.options(xserver_name): 101 _xserver_config[option] = self.get(xserver_name, option, key_type=self.get_type(xserver_name, option)) 102 return _xserver_config
103 104 @property
105 - def known_xservers(self):
106 """\ 107 Renders a list of XServers that are known to Python X2go. 108 109 """ 110 return self.get_value('XServers', 'known_xservers')
111 112 @property
113 - def installed_xservers(self):
114 """\ 115 Among the known XServers renders a list of XServers that are actually 116 installed on the system. 117 118 """ 119 _installed = [] 120 for xserver_name in self.known_xservers: 121 if os.path.exists(os.path.normpath(self.get_xserver_config(xserver_name)['test_installed'])): 122 _installed.append(xserver_name) 123 return _installed
124 125 @property
126 - def running_xservers(self):
127 """\ 128 Tries to render a list of running XServer processes from the system's process list. 129 130 """ 131 _running = [] 132 _wmi = wmi.WMI() 133 _p_names = [] 134 for process in _wmi.Win32_Process(): 135 _p_names.append(process.Name) 136 137 for xserver_name in self.installed_xservers: 138 process_name = self.get_xserver_config(xserver_name)['process_name'] 139 if process_name in _p_names: 140 # XServer is already running 141 _running.append(xserver_name) 142 continue 143 return _running
144 145 @property
146 - def xserver_launch_possible(self):
147 """\ 148 Detect if there is an XServer (that is known to Python X2go) installed on the system. 149 Equals C{True} if we have found an installed XServer that we can launch. 150 151 """ 152 return bool(self.installed_xservers)
153 154 @property
155 - def xserver_launch_needed(self):
156 """\ 157 Detect if an XServer launch is really needed (or if we use an already running XServer instance). 158 Equals C{True} if we have to launch an XServer before we can start/resume 159 X2go sessions. 160 161 """ 162 return not bool(self.running_xservers)
163 164 @property
165 - def preferred_xserver(self):
166 """\ 167 Renders a list of preferred XServer names (most preferred on top). 168 169 """ 170 if self.xserver_launch_possible and self.xserver_launch_needed: 171 return (self.installed_xservers[0], self.get_xserver_config(self.installed_xservers[0])) 172 else: 173 return None
174
175 176 -class X2goXServer(threading.Thread):
177 """ 178 This class is responsible for starting/stopping an external XServer application. 179 180 X2go applications require a running XServer on the client system. This class will 181 manage/handle the XServer while your X2go application is running. 182 183 """ 184
185 - def __init__(self, xserver_name, xserver_config, logger=None, loglevel=log.loglevel_DEFAULT):
186 """\ 187 Initialize an XServer thread. 188 189 @param xserver_name: name of the XServer to start (refer to the xconfig file for available names) 190 @type xserver_name: C{str} 191 @param xserver_config: XServer configuration node (as derived from L{X2goClientXConfig.get_xserver_config()} 192 @type xserver_config: C{dict} 193 @param logger: you can pass an L{X2goLogger} object to the L{X2goClientXConfig} constructor 194 @type logger: C{instance} 195 @param loglevel: if no L{X2goLogger} object has been supplied a new one will be 196 constructed with the given loglevel 197 @type loglevel: C{int} 198 199 """ 200 if _X2GOCLIENT_OS not in ("Windows"): 201 import exceptions 202 class OSNotSupportedException(exceptions.StandardError): pass 203 raise OSNotSupportedException('classes of x2go.xserver module are for Windows only') 204 205 if logger is None: 206 self.logger = log.X2goLogger(loglevel=loglevel) 207 else: 208 self.logger = copy.deepcopy(logger) 209 self.logger.tag = __NAME__ 210 211 self._keepalive = None 212 213 self.xserver_name = xserver_name 214 self.xserver_config = xserver_config 215 if self.xserver_config.has_key('display'): 216 self.logger('settings DISPLAY environment variable to %s' % self.xserver_config['display'], loglevel=log.loglevel_NOTICE) 217 os.environ.update({'DISPLAY': str(self.xserver_config['display'])}) 218 threading.Thread.__init__(self) 219 self.daemon = True 220 self.start()
221
222 - def run(self):
223 """\ 224 Start this L{X2goXServer} thread. This will launch the configured XServer application. 225 226 """ 227 self._keepalive = True 228 cmd_line = [self.xserver_config['run_command']] 229 cmd_line.extend(self.xserver_config['parameters']) 230 self.logger('starting XServer ,,%s\'\' with command line: %s' % (self.xserver_name, ' '.join(cmd_line)), loglevel=log.loglevel_DEBUG) 231 232 if _X2GOCLIENT_OS == 'Windows': 233 si = win32process.STARTUPINFO() 234 p_info = win32process.CreateProcess(None, 235 ' '.join(cmd_line), 236 None, 237 None, 238 0, 239 win32process.NORMAL_PRIORITY_CLASS, 240 None, 241 None, 242 si, 243 ) 244 (hProcess, hThread, processId, threadId) = p_info 245 246 while self._keepalive: 247 gevent.sleep(1) 248 249 self.logger('terminating running XServer ,,%s\'\'' % self.xserver_name, loglevel=log.loglevel_DEBUG) 250 251 if _X2GOCLIENT_OS == 'Windows': 252 try: 253 win32process.TerminateProcess(hProcess, 0) 254 except win32process.error: 255 pass
256
257 - def stop_thread(self):
258 """\ 259 A call to this method will stop the XServer application and do a cleanup afterwards. 260 261 """ 262 self.logger('stop_thread() method has been called', loglevel=log.loglevel_DEBUG) 263 self._keepalive = False
264