1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
34 import os
35 import threading
36 import gevent
37 import copy
38
39
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
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
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
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
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
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
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
141 _running.append(xserver_name)
142 continue
143 return _running
144
145 @property
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
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
174
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
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
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
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