1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 """\
21 X2GoSession class - a public API of Python X2Go, handling standalone X2Go
22 sessions.
23
24 This class is normally embedded into the context of an L{X2GoClient}
25 instance, but it is also possible to address L{X2GoSession}s directly via this
26 class.
27
28 To launch a session manually from the Python interactive shell, perform these
29 simple steps::
30
31 $ python
32 Python 2.6.6 (r266:84292, Dec 26 2010, 22:31:48)
33 [GCC 4.4.5] on linux2
34 Type "help", "copyright", "credits" or "license" for more information.
35 >>> import x2go
36 >>> import gevent
37 Xlib.protocol.request.QueryExtension
38 >>> s = x2go.session.X2GoSession()
39 >>> s.set_server('<my.x2go.server>')
40 >>> s.set_port(<ssh-port>)
41 >>> s.connect('<my-login>', '<my-password>')
42 [<pidno>] (x2gocontrolsession-pylib) NOTICE: connecting to [<my.x2go.server>]:<ssh-port>
43 [<pidno>] (x2gosession-pylib) NOTICE: SSH host key verification for host [<my.x2go.server>]:<ssh-port> with SSH-RSA fingerprint ,,<ssh-fingerprint>'' initiated. We are seeing this X2Go server for the first time.
44 [<pidno>] (x2gosession-pylib) WARN: HOOK_check_host_dialog: host check requested for [<my.x2go.server>]:<ssh-port> with SSH-RSA fingerprint: ,,<ssh-fingerprint>''. Automatically adding host as known host.
45 True
46 >>> s.start(cmd="LXDE")
47 True
48 >>> while True: gevent.sleep(1)
49
50 """
51
52 __NAME__ = 'x2gosession-pylib'
53
54 import os
55 import copy
56 import types
57 import uuid
58 import time
59 import gevent
60 import re
61 import threading
62 import base64
63
64
65 import paramiko
66
67
68 import defaults
69 import log
70 import utils
71 import session
72 import x2go_exceptions
73
74 from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
75 from defaults import LOCAL_HOME as _LOCAL_HOME
76 from defaults import X2GO_CLIENT_ROOTDIR as _X2GO_CLIENT_ROOTDIR
77 from defaults import X2GO_SESSIONS_ROOTDIR as _X2GO_SESSIONS_ROOTDIR
78 from defaults import X2GO_SSH_ROOTDIR as _X2GO_SSH_ROOTDIR
79
80 from defaults import BACKENDS as _BACKENDS
81
82 from defaults import SUPPORTED_SOUND, SUPPORTED_PRINTING, SUPPORTED_FOLDERSHARING, SUPPORTED_MIMEBOX, SUPPORTED_TELEKINESIS
83
84 _X2GO_SESSION_PARAMS = ('use_sshproxy', 'sshproxy_reuse_authinfo',
85 'profile_id', 'session_name',
86 'auto_start_or_resume', 'auto_connect',
87 'printing', 'allow_mimebox',
88 'mimebox_extensions', 'mimebox_action',
89 'allow_share_local_folders', 'share_local_folders', 'restore_shared_local_folders',
90 'control_backend', 'terminal_backend', 'info_backend', 'list_backend', 'proxy_backend', 'settings_backend', 'printing_backend',
91 'client_rootdir', 'sessions_rootdir', 'ssh_rootdir',
92 'keep_controlsession_alive', 'add_to_known_hosts', 'known_hosts', 'forward_sshagent',
93 'connected', 'virgin', 'running', 'suspended', 'terminated', 'faulty'
94 'client_instance',
95 )
96 """A list of allowed X2Go pure session parameters (i.e. parameters that are passed on neither to an X2GoControlSession, X2GoSSHProxy nor an X2GoControlSession object."""
97
98 _X2GO_TERMINAL_PARAMS = ('geometry', 'depth', 'link', 'pack', 'dpi',
99 'cache_type', 'kbtype', 'kblayout', 'kbvariant', 'clipboard',
100 'session_type', 'snd_system', 'snd_port',
101 'cmd', 'set_session_title', 'session_title',
102 'rdp_server', 'rdp_options', 'applications',
103 'xdmcp_server',
104 'rootdir', 'loglevel', 'profile_name', 'profile_id',
105 'print_action', 'print_action_args',
106 'convert_encoding', 'client_encoding', 'server_encoding',
107 'proxy_options', 'published_applications', 'published_applications_no_submenus',
108 'logger',
109 'control_backend', 'terminal_backend', 'proxy_backend',
110 'profiles_backend', 'settings_backend', 'printing_backend',
111 )
112 """A list of allowed X2Go terminal session parameters."""
113 _X2GO_SSHPROXY_PARAMS = ('sshproxy_host', 'sshproxy_port', 'sshproxy_user', 'sshproxy_password',
114 'sshproxy_key_filename', 'sshproxy_pkey', 'sshproxy_passphrase',
115 'sshproxy_look_for_keys', 'sshproxy_allow_agent',
116 'sshproxy_tunnel',
117 )
118 """A list of allowed X2Go SSH proxy parameters."""
119
120
122 """\
123 Public API class for launching X2Go sessions. Recommended is to manage X2Go sessions from
124 within an L{X2GoClient} instance. However, Python X2Go is designed in a way that it also
125 allows the management of singel L{X2GoSession} instance.
126
127 Thus, you can use the L{X2GoSession} class to manually set up X2Go sessions without
128 L{X2GoClient} context (session registry, session list cache, auto-registration of new
129 sessions etc.).
130
131 """
132 - def __init__(self, server=None, port=22, control_session=None,
133 use_sshproxy=False,
134 sshproxy_reuse_authinfo=False,
135 profile_id=None, profile_name='UNKNOWN',
136 session_name=None,
137 auto_start_or_resume=False,
138 auto_connect=False,
139 printing=False,
140 allow_mimebox=False,
141 mimebox_extensions=[],
142 mimebox_action='OPEN',
143 allow_share_local_folders=False,
144 share_local_folders=[],
145 restore_shared_local_folders=False,
146 control_backend=_BACKENDS['X2GoControlSession']['default'],
147 terminal_backend=_BACKENDS['X2GoTerminalSession']['default'],
148 info_backend=_BACKENDS['X2GoServerSessionInfo']['default'],
149 list_backend=_BACKENDS['X2GoServerSessionList']['default'],
150 proxy_backend=_BACKENDS['X2GoProxy']['default'],
151 settings_backend=_BACKENDS['X2GoClientSettings']['default'],
152 printing_backend=_BACKENDS['X2GoClientPrinting']['default'],
153 client_rootdir=os.path.join(_LOCAL_HOME, _X2GO_CLIENT_ROOTDIR),
154 sessions_rootdir=os.path.join(_LOCAL_HOME, _X2GO_SESSIONS_ROOTDIR),
155 ssh_rootdir=os.path.join(_LOCAL_HOME, _X2GO_SSH_ROOTDIR),
156 keep_controlsession_alive=False,
157 add_to_known_hosts=False,
158 known_hosts=None,
159 forward_sshagent=False,
160 logger=None, loglevel=log.loglevel_DEFAULT,
161 connected=False, activated=False, virgin=True, running=None, suspended=None, terminated=None, faulty=None,
162 client_instance=None,
163 **params):
164 """\
165 @param server: hostname of X2Go server
166 @type server: C{str}
167 @param control_session: an already initialized C{X2GoControlSession*} instance
168 @type control_session: C{X2GoControlSession*} instance
169 @param use_sshproxy: for communication with X2Go server use an SSH proxy host
170 @type use_sshproxy: C{bool}
171 @param sshproxy_reuse_authinfo: for proxy authentication re-use the X2Go session's password / key file
172 @type sshproxy_reuse_authinfo: C{bool}
173 @param profile_id: profile ID
174 @type profile_id: C{str}
175 @param profile_name: profile name
176 @type profile_name: C{str}
177 @param session_name: session name (if available)
178 @type session_name: C{str}
179 @param auto_start_or_resume: automatically start a new or resume latest session after connect
180 @type auto_start_or_resume: C{bool}
181 @param auto_connect: call a hook method that handles connecting the session profile automatically after a session for this profile has been registered
182 @type auto_connect: C{bool}
183 @param printing: enable X2Go printing
184 @type printing: C{bool}
185 @param allow_mimebox: enable X2Go MIME box support
186 @type allow_mimebox: C{bool}
187 @param mimebox_extensions: whitelist of allowed X2Go MIME box extensions
188 @type mimebox_extensions: C{list}
189 @param mimebox_action: action for incoming X2Go MIME box files
190 @type mimebox_action: C{X2GoMimeBoxAction*} or C{str}
191 @param allow_share_local_folders: enable local folder sharing support
192 @type allow_share_local_folders: C{bool}
193 @param share_local_folders: list of local folders to share with the remote X2Go session
194 @type share_local_folders: C{list}
195 @param restore_shared_local_folders: store actual list of shared local folders after session has been suspended or terminated
196 @type restore_shared_local_folders: C{bool}
197 @param control_backend: X2Go control session backend to use
198 @type control_backend: C{str}
199 @param terminal_backend: X2Go terminal session backend to use
200 @type terminal_backend: C{str}
201 @param info_backend: X2Go session info backend to use
202 @type info_backend: C{str}
203 @param list_backend: X2Go session list backend to use
204 @type list_backend: C{str}
205 @param proxy_backend: X2Go proxy backend to use
206 @type proxy_backend: C{str}
207 @param settings_backend: X2Go client settings backend to use
208 @type settings_backend: C{str}
209 @param printing_backend: X2Go client printing backend to use
210 @type printing_backend: C{str}
211 @param client_rootdir: client base dir (default: ~/.x2goclient)
212 @type client_rootdir: C{str}
213 @param sessions_rootdir: sessions base dir (default: ~/.x2go)
214 @type sessions_rootdir: C{str}
215 @param ssh_rootdir: ssh base dir (default: ~/.ssh)
216 @type ssh_rootdir: C{str}
217 @param keep_controlsession_alive: On last L{X2GoSession.disconnect()} keep the associated C{X2GoControlSession*} instance alive?
218 @ŧype keep_controlsession_alive: C{bool}
219 @param add_to_known_hosts: Auto-accept server host validity?
220 @type add_to_known_hosts: C{bool}
221 @param known_hosts: the underlying Paramiko/SSH systems C{known_hosts} file
222 @type known_hosts: C{str}
223 @param forward_sshagent: forward SSH agent authentication requests to the SSH agent on the X2Go client-side
224 @type forward_sshagent: C{bool}
225 @param connected: manipulate session state »connected« by giving a pre-set value
226 @type connected: C{bool}
227 @param activated: normal leave this untouched, an activated session is a session that is about to be used
228 @type activated: C{bool}
229 @param virgin: manipulate session state »virgin« by giving a pre-set value
230 @type virgin: C{bool}
231 @param running: manipulate session state »running« by giving a pre-set value
232 @type running: C{bool}
233 @param suspended: manipulate session state »suspended« by giving a pre-set value
234 @type suspended: C{bool}
235 @param terminated: manipulate session state »terminated« by giving a pre-set value
236 @type terminated: C{bool}
237 @param faulty: manipulate session state »faulty« by giving a pre-set value
238 @type faulty: C{bool}
239 @param client_instance: if available, the underlying L{X2GoClient} instance
240 @type client_instance: C{X2GoClient} instance
241 @param params: further control session, terminal session and SSH proxy class options
242 @type params: C{dict}
243
244 """
245 if logger is None:
246 self.logger = log.X2GoLogger(loglevel=loglevel)
247 else:
248 self.logger = copy.deepcopy(logger)
249 self.logger.tag = __NAME__
250
251 self._keep = None
252
253 self.uuid = uuid.uuid1()
254 self.connected = connected
255
256 self.activated = activated
257 self.virgin = virgin
258 self.running = running
259 self.suspended = suspended
260 self.terminated = terminated
261 self.faulty = faulty
262 self.keep_controlsession_alive = keep_controlsession_alive
263
264 self.profile_id = profile_id
265 self.profile_name = profile_name
266 self.session_name = session_name
267 self.server = server
268 self.port = port
269
270 self._last_status = None
271
272 self.auto_start_or_resume = auto_start_or_resume
273 self.auto_connect = auto_connect
274 self.printing = printing
275 self.allow_share_local_folders = allow_share_local_folders
276 self.share_local_folders = share_local_folders
277 self.restore_shared_local_folders = restore_shared_local_folders
278 self.allow_mimebox = allow_mimebox
279 self.mimebox_extensions = mimebox_extensions
280 self.mimebox_action = mimebox_action
281 self.control_backend = utils._get_backend_class(control_backend, "X2GoControlSession")
282 self.terminal_backend = utils._get_backend_class(terminal_backend, "X2GoTerminalSession")
283 self.info_backend = utils._get_backend_class(info_backend, "X2GoServerSessionInfo")
284 self.list_backend = utils._get_backend_class(list_backend, "X2GoServerSessionList")
285 self.proxy_backend = utils._get_backend_class(proxy_backend, "X2GoProxy")
286 self.settings_backend = utils._get_backend_class(settings_backend, "X2GoClientSettings")
287 self.printing_backend = utils._get_backend_class(printing_backend, "X2GoClientPrinting")
288 self.client_rootdir = client_rootdir
289 self.sessions_rootdir = sessions_rootdir
290 self.ssh_rootdir = ssh_rootdir
291 self.control_session = control_session
292
293 if params.has_key('published_applications'):
294 self.published_applications = params['published_applications']
295 if self.published_applications:
296 params['cmd'] = 'PUBLISHED'
297 else:
298 self.published_applications = params['published_applications'] = False
299
300 if params.has_key('cmd') and params['cmd'] != 'PUBLISHED':
301 self.published_applications = params['published_applications'] = False
302 self.published_applications_menu = None
303
304 if self.session_name:
305 if not re.match('.*_stRPUBLISHED_.*',self.session_name):
306 self.published_applications = params['published_applications'] = False
307
308 self.use_sshproxy = use_sshproxy
309 self.sshproxy_reuse_authinfo = sshproxy_reuse_authinfo
310
311 self.control_params = {}
312 self.terminal_params = {}
313 self.sshproxy_params = {}
314 self.update_params(params)
315 self.shared_folders = {}
316
317 self.session_environment = {}
318 self.server_features = []
319
320 try: del self.control_params['server']
321 except: pass
322
323 self.client_instance = client_instance
324
325 if self.logger.get_loglevel() & log.loglevel_DEBUG:
326 self.logger('X2Go control session parameters for profile %s:' % profile_name, loglevel=log.loglevel_DEBUG)
327 for p in [ _p for _p in self.control_params if not _p.endswith('pkey') ]:
328 self.logger(' %s: %s' % (p, self.control_params[p]), log.loglevel_DEBUG)
329 self.logger('X2Go terminal session parameters for profile %s:' % profile_name, loglevel=log.loglevel_DEBUG)
330 for p in self.terminal_params:
331 self.logger(' %s: %s' % (p,self.terminal_params[p]), log.loglevel_DEBUG)
332 self.logger('X2Go sshproxy parameters for profile %s:' % profile_name, loglevel=log.loglevel_DEBUG)
333 for p in self.sshproxy_params:
334 self.logger(' %s: %s' % (p,self.sshproxy_params[p]), loglevel=log.loglevel_DEBUG)
335
336 self.add_to_known_hosts = add_to_known_hosts
337 self.known_hosts = known_hosts
338 self.forward_sshagent = forward_sshagent
339
340 self._current_status = {
341 'timestamp': time.time(),
342 'server': self.server,
343 'virgin': self.virgin,
344 'connected': self.connected,
345 'running': self.running,
346 'suspended': self.suspended,
347 'terminated': self.terminated,
348 'faulty': self.faulty,
349 }
350
351 self._SUPPORTED_SOUND = SUPPORTED_SOUND
352 self._SUPPORTED_PRINTING = SUPPORTED_PRINTING
353 self._SUPPORTED_MIMEBOX = SUPPORTED_MIMEBOX
354 self._SUPPORTED_TELEKINESIS = SUPPORTED_TELEKINESIS
355 self._SUPPORTED_FOLDERSHARING = SUPPORTED_FOLDERSHARING
356
357 self.master_session = None
358 self.init_control_session()
359 self.terminal_session = None
360
361 if self.is_connected():
362 self.retrieve_server_features()
363
364 self._progress_status = 0
365 self._lock = threading.Lock()
366
367 self._restore_exported_folders = {}
368 if self.client_instance and self.restore_shared_local_folders:
369 self._restore_exported_folders = self.client_instance.get_profile_config(self.profile_name, 'export')
370
372 return self.__get_uuid()
373
375 result = 'X2GoSession('
376 for p in dir(self):
377 if '__' in p or not p in self.__dict__ or type(p) is types.InstanceType: continue
378 result += p + '=' + str(self.__dict__[p]) + ','
379 result = result.strip(',')
380 return result + ')'
381
383 return self.__get_uuid()
384
386 """\
387 Class destructor.
388
389 """
390 if self.has_control_session() and self.has_terminal_session():
391 self.get_control_session().dissociate(self.get_terminal_session())
392
393 if self.has_control_session():
394 if self.keep_controlsession_alive:
395
396
397 self.virgin = True
398 self.activated = False
399 self.connected = self.is_connected()
400 self.running = None
401 self.suspended = None
402 self.terminated = None
403 self._current_status = {
404 'timestamp': time.time(),
405 'server': self.server,
406 'virgin': self.virgin,
407 'connected': self.connected,
408 'running': self.running,
409 'suspended': self.suspended,
410 'terminated': self.terminated,
411 'faulty': self.faulty,
412 }
413 self._last_status = None
414 self.session_name = None
415
416 else:
417 self.get_control_session().__del__()
418 self.control_session = None
419
420 if self.has_terminal_session():
421 self.get_terminal_session().__del__()
422 self.terminal_session = None
423
425 """\
426 Return parent L{X2GoClient} instance if avaiable.
427
428 return: L{X2GoClient} instance this session is associated with
429 rtype: C{obj}
430
431 """
432 return self.client_instance
433 __get_client_instance = get_client_instance
434
436 """\
437 HOOK method: called if a control session (server connection) has unexpectedly encountered a failure.
438
439 """
440 if self.client_instance:
441 self.client_instance.HOOK_on_control_session_death(profile_name=self.profile_name)
442 else:
443 self.logger('HOOK_on_control_session_death: the control session of profile %s has died unexpectedly' % self.profile_name, loglevel=log.loglevel_WARN)
444
446 """\
447 HOOK method: called SFTP client support is unavailable for the session.
448
449 """
450 if self.client_instance:
451 self.client_instance.HOOK_on_failing_SFTP_client(profile_name=self.profile_name)
452 else:
453 self.logger('HOOK_on_failing_SFTP_client: new session for profile: %s will lack SFTP client support. Check your server setup. Avoid echoing ~/.bashrc files on server.' % self.profile_name, loglevel=log.loglevel_ERROR)
454
456 """\
457 HOOK method: called if the session demands to auto connect.
458
459 """
460 if self.client_instance:
461 self.client_instance.HOOK_profile_auto_connect(profile_name=self.profile_name)
462 else:
463 self.logger('HOOK_auto_connect: profile ,,%s\'\' wants to auto-connect to the X2Go server.' % self.profile_name, loglevel=log.loglevel_WARN)
464
466 """\
467 HOOK method: called if the startup of a session failed.
468
469 """
470 if self.client_instance:
471 self.client_instance.HOOK_session_startup_failed(profile_name=self.profile_name)
472 else:
473 self.logger('HOOK_session_startup_failed: session startup for session profile ,,%s\'\' failed.' % self.profile_name, loglevel=log.loglevel_WARN)
474
476 """\
477 HOOK method: called if the startup of a shadow session was denied by the other user.
478
479 """
480 if self.client_instance:
481 self.client_instance.HOOK_desktop_sharing_denied(profile_name=self.profile_name)
482 else:
483 self.logger('HOOK_desktop_sharing_denied: desktop sharing for session profile ,,%s\'\' was denied by the other user.' % self.profile_name, loglevel=log.loglevel_WARN)
484
486 """\
487 HOOK method: called if the x2golistdesktops command generates a timeout due to long execution time.
488
489 """
490 if self.client_instance:
491 self.client_instance.HOOK_list_desktops_timeout(profile_name=self.profile_name)
492 else:
493 self.logger('HOOK_list_desktops_timeout: the server-side x2golistdesktops command for session profile %s took too long to return results. This can happen from time to time, please try again.' % self.profile_name, loglevel=log.loglevel_WARN)
494
496 """\
497 HOOK method: called if it is tried to connect to a shared desktop that's not available (anymore).
498
499 """
500 if self.client_instance:
501 self.client_instance.HOOK_no_such_desktop(profile_name=self.profile_name, desktop=desktop)
502 else:
503 self.logger('HOOK_no_such_desktop: the desktop %s (via session profile %s) is not available for sharing (anymore).' % (desktop, self.profile_name), loglevel=log.loglevel_WARN)
504
506 """\
507 HOOK method: called if a reverse port forwarding request has been denied.
508
509 @param server_port: remote server port (starting point of reverse forwarding tunnel)
510 @type server_port: C{str}
511
512 """
513 if self.client_instance:
514 self.client_instance.HOOK_rforward_request_denied(profile_name=self.profile_name, session_name=self.session_name, server_port=server_port)
515 else:
516 self.logger('HOOK_rforward_request_denied: TCP port (reverse) forwarding request for session %s to server port %s has been denied by server %s. This is a common issue with SSH, it might help to restart the server\'s SSH daemon.' % (self.session_name, server_port, self.profile_name), loglevel=log.loglevel_WARN)
517
519 """\
520 HOOK method: called if a port forwarding tunnel setup failed.
521
522 @param chain_host: hostname of chain host (forwarding tunnel end point)
523 @type chain_host: C{str}
524 @param chain_port: port of chain host (forwarding tunnel end point)
525 @type chain_port: C{str}
526 @param subsystem: information on the subsystem that provoked this hook call
527 @type subsystem: C{str}
528
529 """
530 if type(subsystem) in (types.StringType, types.UnicodeType):
531 _subsystem = '(%s) ' % subsystem
532 else:
533 _subsystem = ''
534
535 if subsystem.endswith('Proxy'):
536 self.faulty = True
537
538 if self.client_instance:
539 self.client_instance.HOOK_forwarding_tunnel_setup_failed(profile_name=self.profile_name, session_name=self.session_name, chain_host=chain_host, chain_port=chain_port, subsystem=subsystem)
540 else:
541 self.logger('HOOK_forwarding_tunnel_setup_failed: Forwarding tunnel request to [%s]:%s for session %s (%s) was denied by remote X2Go/SSH server. Subsystem (%s) startup failed.' % (chain_host, chain_port, self.session_name, self.profile_name, _subsystem), loglevel=log.loglevel_WARN)
542
544 """\
545 HOOK method: called if X2Go client-side printing is not available.
546
547 """
548 if self.client_instance:
549 self.client_instance.HOOK_printing_not_available(profile_name=self.profile_name, session_name=self.session_name)
550 else:
551 self.logger('HOOK_printing_not_available: X2Go\'s client-side printing feature is not available with this session (%s) of profile %s.' % (self.session_name, self.profile_name), loglevel=log.loglevel_WARN)
552
554 """\
555 HOOK method: called if the X2Go MIME box is not available.
556
557 """
558 if self.client_instance:
559 self.client_instance.HOOK_mimebox_not_available(profile_name=self.profile_name, session_name=self.session_name)
560 else:
561 self.logger('HOOK_mimebox_not_available: X2Go\'s MIME box feature is not available with this session (%s) of profile %s.' % (self.session_name, self.profile_name), loglevel=log.loglevel_WARN)
562
564 """\
565 HOOK method: called if X2Go client-side folder-sharing is not available.
566
567 """
568 if self.client_instance:
569 self.client_instance.HOOK_foldersharing_not_available(profile_name=self.profile_name, session_name=self.session_name)
570 else:
571 self.logger('HOOK_foldersharing_not_available: X2Go\'s client-side folder sharing feature is not available with this session (%s) of profile %s.' % (self.session_name, self.profile_name), loglevel=log.loglevel_WARN)
572
574 """\
575 HOOK method: called if the X2Go server denies SSHFS access.
576
577 """
578 if self.client_instance:
579 self.client_instance.HOOK_sshfs_not_available(profile_name=self.profile_name, session_name=self.session_name)
580 else:
581 self.logger('HOOK_sshfs_not_available: the remote X2Go server (%s) denies SSHFS access for session %s. This will result in client-side folder sharing, printing and the MIME box feature being unavailable' % (self.profile_name, self.session_name), loglevel=log.loglevel_WARN)
582
584 """\
585 HOOK method: called if a host check is requested. This hook has to either return C{True} (default) or C{False}.
586
587 @param host: SSH server name to validate
588 @type host: C{str}
589 @param port: SSH server port to validate
590 @type port: C{int}
591 @param fingerprint: the server's fingerprint
592 @type fingerprint: C{str}
593 @param fingerprint_type: finger print type (like RSA, DSA, ...)
594 @type fingerprint_type: C{str}
595 @return: if host validity is verified, this hook method should return C{True}
596 @rtype: C{bool}
597
598 """
599 if self.client_instance:
600 return self.client_instance.HOOK_check_host_dialog(profile_name=self.profile_name, host=host, port=port, fingerprint=fingerprint, fingerprint_type=fingerprint_type)
601 else:
602 self.logger('HOOK_check_host_dialog: host check requested for [%s]:%s with %s fingerprint: ,,%s\'\'. Automatically adding host as known host.' % (host, port, fingerprint_type, fingerprint), loglevel=log.loglevel_WARN)
603 return True
604
606 """\
607 Initialize a new control session (C{X2GoControlSession*}).
608
609 """
610 low_latency = self.terminal_params.has_key('link') and self.terminal_params['link'].lower() in ('modem', 'isdn')
611
612 if self.control_session is None:
613 self.logger('initializing X2GoControlSession', loglevel=log.loglevel_DEBUG)
614 self.control_session = self.control_backend(profile_name=self.profile_name,
615 add_to_known_hosts=self.add_to_known_hosts,
616 known_hosts=self.known_hosts,
617 forward_sshagent=self.forward_sshagent,
618 terminal_backend=self.terminal_backend,
619 info_backend=self.info_backend,
620 list_backend=self.list_backend,
621 proxy_backend=self.proxy_backend,
622 client_rootdir=self.client_rootdir,
623 sessions_rootdir=self.sessions_rootdir,
624 ssh_rootdir=self.ssh_rootdir,
625 low_latency=low_latency,
626 logger=self.logger)
627 else:
628 self.control_session.low_latency = low_latency
629 __init_control_session = init_control_session
630
632 """\
633 Is this session a/the master session of sessions.
634
635 The master session is the session has been launched first for a specific connection,
636 it also is _the_ session that controls the client-side shared folders.
637
638 If this L{X2GoSession} instance is a standalone instance (without parent L{X2GoClient})
639 this method will always return C{True}.
640
641 @return: returns C{True} if this session is a master session
642 @rtype: C{bool}
643
644 """
645 if self.master_session is None and self.client_instance is None:
646 return True
647 return bool(self.master_session)
648 __is_master_session = is_master_session
649
651 """\
652 Declare this as a master session of a connection channel.
653
654 This method gets called by the L{X2GoSessionRegistry} while sessions are starting or resuming and it relies on
655 an already set-up terminal session.
656
657 @param wait: wait for <wait> seconds before sharing local folders via the new master session
658 of the corresponding session profile.
659 @type wait: C{int}
660 @param max_wait: wait for <max_wait> seconds for the terminal session to appear
661 @type max_wait: C{int}
662
663 """
664 self.logger('Using session %s as master session for profile %s.' % (self.get_session_name(), self.get_profile_name()), loglevel=log.loglevel_NOTICE)
665 self.master_session = True
666
667
668 if self.client_instance:
669 _exports = self.client_instance.get_profile_config(self.profile_name, 'export')
670 self.share_local_folders = [ sf for sf in _exports.keys() if _exports[sf] ]
671
672 i = 0
673 while i < max_wait:
674 i += 1
675 if self.has_terminal_session():
676 break
677 gevent.sleep(1)
678
679 if wait:
680 gevent.spawn_later(wait, self.share_all_local_folders, update_exported_folders=False)
681 else:
682 gevent.spawn(self.share_all_local_folders, update_exported_folders=False)
683 __set_master_session = set_master_session
684
694 __unset_master_session = unset_master_session
695
697 """\
698 Modify server name after L{X2GoSession} has already been initialized.
699
700 @param server: new server name
701 @type server: C{str}
702
703 """
704 self.server = server
705 __set_server = set_server
706
708 """\
709 Modify server port after L{X2GoSession} has already been initialized.
710
711 @param port: socket port of server to connect to
712 @type port: C{int}
713
714 """
715 self.port = port
716 __set_port = set_port
717
719 """\
720 Modify session profile name after L{X2GoSession} has already been initialized.
721
722 @param profile_name: new session profile name
723 @type profile_name: C{str}
724
725 """
726 self.profile_name = profile_name
727 self.control_session.set_profile_name(profile_name)
728 __set_profile_name = set_profile_name
729
731 """\
732 Retrieve a specific profile parameter for this session.
733
734 @param option: name of a specific profile option to be queried.
735 @type option: C{str}
736
737 @return: value for profile option C{<option>}
738 @rtype: C{bool,str,int}
739
740 @raise X2GoProfileException: if the session profile option is unknown
741
742 """
743 if option in _X2GO_SESSION_PARAMS + _X2GO_TERMINAL_PARAMS + _X2GO_SSHPROXY_PARAMS and hasattr(self, option):
744 return eval("self.%s" % option)
745 else:
746 raise x2go_exceptions.X2GoProfileException('Unknown session profile option: %s.' % option)
747 __get_session_profile_option = get_session_profile_option
748
750 """\
751 This method can be used to modify L{X2GoSession} parameters after the
752 L{X2GoSession} instance has already been initialized.
753
754 @param params: a Python dictionary with L{X2GoSession} parameters
755 @type params: C{dict}
756
757 """
758 try: del params['server']
759 except KeyError: pass
760 try: del params['profile_name']
761 except KeyError: pass
762 try: del params['profile_id']
763 except KeyError: pass
764 try:
765 self.printing = params['printing']
766 del params['printing']
767 except KeyError: pass
768 try:
769 self.allow_share_local_folders = params['allow_share_local_folders']
770 del params['allow_share_local_folders']
771 except KeyError: pass
772 try:
773 self.share_local_folders = params['share_local_folders']
774 del params['share_local_folders']
775 except KeyError: pass
776 try:
777 self.restore_shared_local_folders = params['restore_shared_local_folders']
778 del params['restore_shared_local_folders']
779 except KeyError: pass
780 try:
781 self.allow_mimebox = params['allow_mimebox']
782 del params['allow_mimebox']
783 except KeyError: pass
784 try:
785 self.mimebox_extensions = params['mimebox_extensions']
786 del params['mimebox_extensions']
787 except KeyError: pass
788 try:
789 self.mimebox_action = params['mimebox_action']
790 del params['mimebox_action']
791 except KeyError: pass
792 try:
793 self.use_sshproxy = params['use_sshproxy']
794 del params['use_sshproxy']
795 except KeyError: pass
796 try:
797 self.sshproxy_reuse_authinfo = params['sshproxy_reuse_authinfo']
798 del params['sshproxy_reuse_authinfo']
799 except KeyError: pass
800 try:
801 self.auto_connect = params['auto_connect']
802 del params['auto_connect']
803 except KeyError: pass
804 try:
805 self.forward_sshagent = params['forward_sshagent']
806 del params['forward_sshagent']
807 except KeyError: pass
808 try:
809 self.auto_start_or_resume = params['auto_start_or_resume']
810 del params['auto_start_or_resume']
811 except KeyError: pass
812
813 if self.sshproxy_reuse_authinfo:
814 if params.has_key('key_filename'):
815 params['sshproxy_key_filename'] = params['key_filename']
816 if params.has_key('pkey'):
817 params['sshproxy_pkey'] = params['pkey']
818 if params.has_key('password'):
819 params['sshproxy_password'] = params['password']
820
821 _terminal_params = copy.deepcopy(params)
822 _control_params = copy.deepcopy(params)
823 _sshproxy_params = copy.deepcopy(params)
824 for p in params.keys():
825 if p in session._X2GO_TERMINAL_PARAMS:
826 del _control_params[p]
827 del _sshproxy_params[p]
828 elif p in session._X2GO_SSHPROXY_PARAMS:
829 del _control_params[p]
830 del _terminal_params[p]
831 else:
832 del _sshproxy_params[p]
833 del _terminal_params[p]
834
835 self.control_params.update(_control_params)
836 self.terminal_params.update(_terminal_params)
837 self.sshproxy_params.update(_sshproxy_params)
838
840 """\
841 Retrieve session UUID hash for this L{X2GoSession}.
842
843 @return: the session's UUID hash
844 @rtype: C{str}
845
846 """
847 return str(self.uuid)
848 __get_uuid = get_uuid
849
851 """\
852 After a session has been set up you can query the
853 username the session runs as.
854
855 @return: the remote username the X2Go session runs as
856 @rtype: C{str}
857
858 """
859
860 try:
861 return self.control_session.get_transport().get_username()
862 except AttributeError:
863 return self.control_params['username']
864 __get_username = get_username
865
867 """\
868 After a session has been set up you can query the
869 remote user's home directory path.
870
871 @return: the remote home directory path
872 @rtype: C{str}
873
874 """
875
876 if self.is_connected():
877 return self.control_session._x2go_remote_home
878 else:
879 return None
880 __get_remote_home = get_remote_home
881
883 """\
884 Check if a given user is valid server-side X2Go user.
885
886 @param username: username to check validity for
887 @type username: C{str}
888
889 @return: C{True} if the username is allowed to launch X2Go sessions
890 @rtype: C{bool}
891
892 """
893 if username is None:
894 username = self.__get_username()
895 return self.control_session.is_x2gouser(username)
896 __user_is_x2gouser = user_is_x2gouser
897
899 """\
900 After a session has been setup up you can query the
901 username's password from the session.
902
903 @return: the username's password
904 @rtype: C{str}
905
906 """
907 return base64.base64decode(self.control_session._session_password)
908 __get_password = get_password
909
911 """\
912 After a session has been setup up you can query the
913 peername of the host this session is connected to (or
914 about to connect to).
915
916 @return: the address of the server the X2Go session is
917 connected to (as an C{(addr,port)} tuple)
918 @rtype: C{tuple}
919
920 """
921 return self.control_session.remote_peername()
922 __get_server_peername = get_server_peername
923 remote_peername = get_server_peername
924 __remote_peername = get_server_peername
925
927 """\
928 After a session has been setup up you can query the
929 hostname of the host this session is connected to (or
930 about to connect to).
931
932 @return: the hostname of the server the X2Go session is
933 connected to / about to connect to
934 @rtype: C{str}
935
936 """
937 self.server = self.control_session.get_hostname()
938 return self.server
939 __get_server_hostname = get_server_hostname
940
942 """\
943 After a session has been setup up you can query the
944 IP socket port used for connecting the remote X2Go server.
945
946 @return: the server-side IP socket port that is used by the X2Go session to
947 connect to the server
948 @rtype: C{str}
949
950 """
951 return self.control_session.get_port()
952 __get_server_port = get_server_port
953
955 """\
956 Retrieve the server-side X2Go session name for this session.
957
958 @return: X2Go session name
959 @rtype: C{str}
960
961 """
962 return self.session_name
963 __get_session_name = get_session_name
964
966 """\
967 Manipulate the L{X2GoSession}'s session name.
968
969 @param session_name: the new session name to be set
970 @type session_name: C{str}
971
972 """
973 self.session_name = session_name
974 __set_session_name = set_session_name
975
977 """\
978 Retrieve the server-side X2Go session info object for this session.
979
980 @return: X2Go session info
981 @rtype: C{obj}
982
983 """
984 if self.has_terminal_session():
985 self.terminal_session.get_session_info()
986 __get_session_info = get_session_info
987
989 """\
990 Retrieve the server-side command that is used to start a session
991 on the remote X2Go server.
992
993 @return: server-side session command
994 @rtype: C{str}
995
996 """
997 if self.has_terminal_session():
998 return self.terminal_session.get_session_cmd()
999 if self.terminal_params.has_key('cmd'):
1000 return self.terminal_params['cmd']
1001 return None
1002 __get_session_cmd = get_session_cmd
1003
1005 """\
1006 Retrieve the session type of a session (R, D, S or P).
1007
1008 - R: rootless session
1009 - D: desktop session
1010 - S: shadow session
1011 - P: session in published applications mode
1012
1013 @return: session type
1014 @rtype: C{str}
1015
1016 """
1017 if self.has_terminal_session():
1018 return self.terminal_session.get_session_type()
1019 else:
1020 return None
1021 __get_session_type = get_session_type
1022
1024 """\
1025 Retrieve the session window title of this
1026 session.
1027
1028 @return: session window title
1029 @rtype: C{str}
1030
1031 """
1032 if self.has_terminal_session():
1033 return self.terminal_session.session_title
1034 else:
1035 return 'X2GO-%s' % self.get_session_name()
1036 __get_session_title = get_session_title
1037
1039 """\
1040 Retrieve the control session (C{X2GoControlSession*} backend) of this L{X2GoSession}.
1041
1042 @return: the L{X2GoSession}'s control session
1043 @rtype: C{X2GoControlSession*} instance
1044
1045 """
1046 return self.control_session
1047 __get_control_session = get_control_session
1048
1050 """\
1051 Check if this L{X2GoSession} instance has an associated control session.
1052
1053 @return: returns C{True} if this L{X2GoSession} has a control session associated to itself
1054 @rtype: C{bool}
1055
1056 """
1057 return self.control_session is not None
1058 __has_control_session = has_control_session
1059
1061 """\
1062 Retrieve the terminal session (C{X2GoTerminalSession*} backend) of this L{X2GoSession}.
1063
1064 @return: the L{X2GoSession}'s terminal session
1065 @rtype: C{X2GoControlTerminal*} instance
1066
1067 """
1068 if self.terminal_session == 'PENDING':
1069 return None
1070 return self.terminal_session
1071 __get_terminal_session = get_terminal_session
1072
1074 """\
1075 Check if this L{X2GoSession} instance has an associated terminal session.
1076
1077 @return: returns C{True} if this L{X2GoSession} has a terminal session associated to itself
1078 @rtype: C{bool}
1079
1080 """
1081 return self.terminal_session not in (None, 'PENDING')
1082 __has_terminal_session = has_terminal_session
1083 is_associated = has_terminal_session
1084 __is_associated = has_terminal_session
1085
1087 """\
1088 Provide a host check mechanism. This method basically calls the L{HOOK_check_host_dialog()} method
1089 which by itself calls the L{X2GoClient.HOOK_check_host_dialog()} method. Make sure you
1090 override any of these to enable user interaction on X2Go server validity checks.
1091
1092 @return: returns C{True} if an X2Go server host is valid for authentication
1093 @rtype: C{bool}
1094
1095 """
1096 if self.connected:
1097 return True
1098
1099 _port = self.control_params['port']
1100 (_valid, _host, _port, _fingerprint, _fingerprint_type) = self.control_session.check_host(self.server, port=_port)
1101 return _valid or self.HOOK_check_host_dialog(host=_host, port=_port, fingerprint=_fingerprint, fingerprint_type=_fingerprint_type)
1102 __check_host = check_host
1103
1105 """\
1106 Check if a session is configured to use an intermediate SSH proxy server.
1107
1108 @return: returns C{True} if the session is configured to use an SSH proxy, C{False} otherwise.
1109 @rtype: C{bool}
1110
1111 """
1112 return self.use_sshproxy
1113 __uses_sshproxy = uses_sshproxy
1114
1116 """\
1117 Check if a session is configured to re-use the X2Go session's password / key for
1118 proxy authentication, as well.
1119
1120 @return: returns C{True} if the session is configured to re-use session password / key for proxy authentication
1121 @rtype: C{bool}
1122
1123 """
1124 return self.sshproxy_reuse_authinfo
1125 __reuses_sshproxy_authinfo = reuses_sshproxy_authinfo
1126
1128 """\
1129 Check if a session's SSH proxy (if used) is configured adequately to be able to auto-connect
1130 to the SSH proxy server (e.g. by public key authentication).
1131
1132 @return: returns C{True} if the session's SSH proxy can auto-connect, C{False} otherwise, C{None}
1133 if no SSH proxy is used for this session, C{None} is returned.
1134 @rtype: C{bool}
1135
1136 """
1137 if self.use_sshproxy:
1138 if self.sshproxy_params.has_key('sshproxy_key_filename') and self.sshproxy_params['sshproxy_key_filename'] and os.path.exists(os.path.normpath(self.sshproxy_params['sshproxy_key_filename'])):
1139 return True
1140 elif self.sshproxy_reuse_authinfo and self.control_params.has_key('key_filename') and self.control_params['key_filename'] and os.path.exists(os.path.normpath(self.control_params['key_filename'])):
1141 return True
1142 elif self.sshproxy_params.has_key('sshproxy_pkey') and self.sshproxy_params['sshproxy_pkey']:
1143 return True
1144 elif self.sshproxy_reuse_authinfo and self.control_params.has_key('pkey') and self.control_params['pkey']:
1145 return True
1146 elif self.sshproxy_params.has_key('sshproxy_look_for_keys') and self.sshproxy_params['sshproxy_look_for_keys'] and (os.path.exists(os.path.expanduser('~/.ssh/id_rsa')) or os.path.exists(os.path.expanduser('~/.ssh/id_dsa'))):
1147 return True
1148 elif self.sshproxy_params.has_key('sshproxy_allow_agent') and self.sshproxy_params['sshproxy_allow_agent'] and paramiko.Agent().get_keys():
1149 return True
1150 else:
1151 return False
1152 else:
1153 return None
1154 __can_sshproxy_auto_connect = can_sshproxy_auto_connect
1155
1157 """\
1158 Check if a session is configured adequately to be able to auto-connect to the X2Go
1159 server (e.g. public key authentication).
1160
1161 @return: returns C{True} if the session can auto-connect, C{False} otherwise, C{None}
1162 if no control session has been set up yet.
1163 @rtype: C{bool}
1164
1165 """
1166 if self.control_session is None:
1167 return None
1168
1169 _can_sshproxy_auto_connect = self.can_sshproxy_auto_connect()
1170
1171
1172 if self.control_params.has_key('key_filename') and self.control_params['key_filename'] and os.path.exists(os.path.normpath(self.control_params['key_filename'])):
1173 return (_can_sshproxy_auto_connect is None) or _can_sshproxy_auto_connect
1174
1175
1176 elif self.control_params.has_key('pkey') and self.control_params['pkey']:
1177 return (_can_sshproxy_auto_connect is None) or _can_sshproxy_auto_connect
1178
1179
1180 elif self.control_params.has_key('look_for_keys') and self.control_params['look_for_keys'] and (os.path.exists(os.path.expanduser('~/.ssh/id_rsa')) or os.path.exists(os.path.expanduser('~/.ssh/id_dsa'))):
1181 return (_can_sshproxy_auto_connect is None) or _can_sshproxy_auto_connect
1182
1183
1184 elif self.control_params.has_key('allow_agent') and self.control_params['allow_agent'] and paramiko.Agent().get_keys():
1185 return (_can_sshproxy_auto_connect is None) or _can_sshproxy_auto_connect
1186
1187 else:
1188 return False
1189 __can_auto_connect = can_auto_connect
1190
1192 """\
1193 Automatically connect this session.
1194
1195 @return: Return success (or failure) of connecting this sessions
1196 @rtype: C{bool}
1197
1198 """
1199 if not self.is_connected():
1200 if self.client_instance and redirect_to_client:
1201 return self.client_instance.session_auto_connect(self())
1202 else:
1203 if self.can_auto_connect() and self.auto_connect:
1204 gevent.spawn(self.connect)
1205 elif self.auto_connect:
1206 gevent.spawn(self.HOOK_auto_connect)
1207 __do_auto_connect = do_auto_connect
1208
1209 - def connect(self, username=None, password=None, passphrase=None, add_to_known_hosts=None,
1210 force_password_auth=None, look_for_keys=None, allow_agent=None,
1211 use_sshproxy=None, sshproxy_user=None, sshproxy_password=None, sshproxy_passphrase=None,
1212 sshproxy_force_password_auth=None, sshproxy_reuse_authinfo=None, ):
1213 """\
1214 Connects to the L{X2GoSession}'s server host. This method basically wraps around
1215 the C{X2GoControlSession*.connect()} method.
1216
1217 @param username: the username for the X2Go server that is going to be
1218 connected to (as a last minute way of changing the session username)
1219 @type username: C{str}
1220 @param password: the user's password for the X2Go server that is going to be
1221 connected to
1222 @type password: C{str}
1223 @param passphrase: a passphrase to use for unlocking
1224 a private key in case the password is already needed for two-factor
1225 authentication
1226 @type passphrase: C{str}
1227 @param add_to_known_hosts: non-paramiko option, if C{True} paramiko.AutoAddPolicy()
1228 is used as missing-host-key-policy. If set to C{False} paramiko.RejectPolicy()
1229 is used
1230 @type add_to_known_hosts: C{bool}
1231 @param force_password_auth: disable SSH pub/priv key authentication mechanisms
1232 completely
1233 @type force_password_auth: C{bool}
1234 @param look_for_keys: set to C{True} to enable searching for discoverable
1235 private key files in C{~/.ssh/}
1236 @type look_for_keys: C{bool}
1237 @param allow_agent: set to C{True} to enable connecting to a local SSH agent
1238 for acquiring authentication information
1239 @type allow_agent: C{bool}
1240 @param use_sshproxy: use an SSH proxy host for connecting the target X2Go server
1241 @type use_sshproxy: C{bool}
1242 @param sshproxy_reuse_authinfo: for proxy authentication re-use the X2Go session's password / key file
1243 @type sshproxy_reuse_authinfo: C{bool}
1244 @param sshproxy_user: username for authentication against the SSH proxy host
1245 @type sshproxy_user: C{str}
1246 @param sshproxy_password: password for authentication against the SSH proxy host
1247 @type sshproxy_password: C{str}
1248 @param sshproxy_passphrase: a passphrase to use for unlocking
1249 a private key needed for the SSH proxy host in case the sshproxy_password is already needed for
1250 two-factor authentication
1251 @type sshproxy_passphrase: C{str}
1252 @param sshproxy_force_password_auth: enforce password authentication even is a key(file) is present
1253 @type sshproxy_force_password_auth: C{bool}
1254
1255 @return: returns C{True} is the connection to the X2Go server has been successful
1256 @rtype C{bool}
1257
1258 @raise X2GoSessionException: on control session exceptions
1259 @raise X2GoRemoteHomeException: if the remote home directory does not exist
1260 @raise Exception: any other exception during connecting is passed through
1261
1262 """
1263 if self.control_session and self.control_session.is_connected():
1264 self.logger('control session is already connected, skipping authentication', loglevel=log.loglevel_DEBUG)
1265 self.connected = True
1266 else:
1267
1268 if use_sshproxy is not None:
1269 self.use_sshproxy = use_sshproxy
1270
1271 if sshproxy_reuse_authinfo is not None:
1272 self.sshproxy_reuse_authinfo = sshproxy_reuse_authinfo
1273
1274 if username:
1275 self.control_params['username'] = username
1276 if add_to_known_hosts is not None:
1277 self.control_params['add_to_known_hosts'] = add_to_known_hosts
1278 if force_password_auth is not None:
1279 self.control_params['force_password_auth'] = force_password_auth
1280 if look_for_keys is not None:
1281 self.control_params['look_for_keys'] = look_for_keys
1282 if allow_agent is not None:
1283 self.control_params['allow_agent'] = allow_agent
1284
1285 if sshproxy_user:
1286 self.sshproxy_params['sshproxy_user'] = sshproxy_user
1287 if sshproxy_password:
1288 self.sshproxy_params['sshproxy_password'] = sshproxy_password
1289 if sshproxy_passphrase:
1290 self.sshproxy_params['sshproxy_passphrase'] = sshproxy_passphrase
1291 if sshproxy_force_password_auth is not None:
1292 self.sshproxy_params['sshproxy_force_password_auth'] = sshproxy_force_password_auth
1293
1294 self.control_params['password'] = password
1295 if passphrase:
1296 self.control_params['passphrase'] = passphrase
1297
1298 if self.sshproxy_reuse_authinfo:
1299 if self.control_params.has_key('key_filename'):
1300 self.sshproxy_params['sshproxy_key_filename'] = self.control_params['key_filename']
1301 if self.control_params.has_key('pkey'):
1302 self.sshproxy_params['sshproxy_pkey'] = self.control_params['pkey']
1303 if self.control_params.has_key('password'):
1304 self.sshproxy_params['sshproxy_password'] = self.control_params['password']
1305 if self.control_params.has_key('passphrase'):
1306 self.sshproxy_params['sshproxy_passphrase'] = self.control_params['passphrase']
1307
1308 _params = {}
1309 _params.update(self.control_params)
1310 _params.update(self.sshproxy_params)
1311
1312 if 'port' not in _params:
1313 _params['port'] = self.port
1314
1315 try:
1316 self.connected = self.control_session.connect(self.server,
1317 use_sshproxy=self.use_sshproxy,
1318 session_instance=self,
1319 forward_sshagent=self.forward_sshagent,
1320 **_params)
1321 except x2go_exceptions.X2GoControlSessionException, e:
1322 raise x2go_exceptions.X2GoSessionException(str(e))
1323 except x2go_exceptions.X2GoRemoteHomeException, e:
1324 self.disconnect()
1325 raise e
1326 except:
1327
1328 self.control_params['password'] = ''
1329 if self.control_params and self.control_params.has_key('passphrase'):
1330 del self.control_params['passphrase']
1331 if self.sshproxy_params and self.sshproxy_params.has_key('sshproxy_password'):
1332 self.sshproxy_params['sshproxy_password'] = ''
1333 if self.sshproxy_params and self.sshproxy_params.has_key('sshproxy_passphrase'):
1334 del self.sshproxy_params['sshproxy_passphrase']
1335 raise
1336 finally:
1337
1338 self.control_params['password'] = ''
1339 if self.control_params and self.control_params.has_key('passphrase'):
1340 del self.control_params['passphrase']
1341 if self.sshproxy_params and self.sshproxy_params.has_key('sshproxy_password'):
1342 self.sshproxy_params['sshproxy_password'] = ''
1343 if self.sshproxy_params and self.sshproxy_params.has_key('sshproxy_passphrase'):
1344 del self.sshproxy_params['sshproxy_passphrase']
1345
1346 if not self.connected:
1347
1348 self.disconnect()
1349
1350 self.get_server_hostname()
1351
1352 if self.connected:
1353 self.update_status()
1354 self.retrieve_server_features()
1355 if self.auto_start_or_resume:
1356 gevent.spawn(self.do_auto_start_or_resume)
1357
1358 return self.connected
1359 __connect = connect
1360
1362 """\
1363 Disconnect this L{X2GoSession} instance.
1364
1365 @return: returns C{True} if the disconnect operation has been successful
1366 @rtype: C{bool}
1367
1368 """
1369 self.connected = False
1370 self.running = None
1371 self.suspended = None
1372 self.terminated = None
1373 self.faults = None
1374 self.active = False
1375 if self._lock.locked():
1376 self._lock.release()
1377 self.unset_master_session()
1378 try:
1379 self.update_status(force_update=True)
1380 except x2go_exceptions.X2GoControlSessionException:
1381 pass
1382 retval = self.control_session.disconnect()
1383 return retval
1384 __disconnect = disconnect
1385
1393 __retrieve_server_features = retrieve_server_features
1394
1396 """\
1397 Return a list of X2Go server-sides features (supported functionalities).
1398
1399 @return: a C{list} of X2Go feature names
1400 @rtype: C{list}
1401
1402 """
1403 return self.server_features
1404 __get_server_features = get_server_features
1405
1407 """\
1408 Check if C{feature} is a present feature of the connected X2Go server.
1409
1410 @param feature: an X2Go server feature as found in C{$SHAREDIR/x2go/feature.d/*}
1411 @type feature: C{str}
1412
1413 @return: returns C{True} if the feature is present
1414 @rtype: C{bool}
1415
1416 """
1417 return feature in self.get_server_features()
1418 __has_server_feature = has_server_feature
1419
1421 """\
1422 Modify session window title. If the session ID does not occur in the
1423 given title, it will be prepended, so that every X2Go session window
1424 always contains the X2Go session ID of that window.
1425
1426 @param title: new title for session window
1427 @type title: C{str}
1428
1429 """
1430 if self.terminal_session is not None:
1431 self.terminal_session.set_session_window_title(title=title)
1432 __set_session_window_title = set_session_window_title
1433
1435 """\
1436 Try to lift the session window above all other windows and bring
1437 it to focus.
1438
1439 """
1440 if self.terminal_session is not None:
1441 self.terminal_session.raise_session_window()
1442 __raise_session_window = raise_session_window
1443
1445 """\
1446 If X2Go client-side printing is enable within this X2Go session you can use
1447 this method to alter the way how incoming print spool jobs are handled/processed.
1448
1449 For further information, please refer to the documentation of the L{X2GoClient.set_session_print_action()}
1450 method.
1451
1452 @param print_action: one of the named above print actions, either as string or class instance
1453 @type print_action: C{str} or C{instance}
1454 @param kwargs: additional information for the given print action (print
1455 action arguments), for possible print action arguments and their values see each individual
1456 print action class
1457 @type kwargs: C{dict}
1458
1459 """
1460 if type(print_action) is not types.StringType:
1461 return False
1462 self.terminal_session.set_print_action(print_action, **kwargs)
1463 __set_print_action = set_print_action
1464
1466 """\
1467 Find out if this X2Go session is still alive (that is: connected to the server).
1468
1469 @return: returns C{True} if the server connection is still alive
1470 @rtype: C{bool}
1471
1472 """
1473 self.connected = self.control_session.is_alive()
1474 if self.control_session.has_session_died():
1475 self.HOOK_on_control_session_death()
1476 if not self.connected:
1477 self._X2GoSession__disconnect()
1478 return self.connected
1479 __is_alive = is_alive
1480
1481 - def clean_sessions(self, destroy_terminals=True, published_applications=False):
1482 """\
1483 Clean all running sessions for the authenticated user on the remote X2Go server.
1484
1485 @param destroy_terminals: destroy associated terminal sessions
1486 @type destroy_terminals: C{bool}
1487 @param published_applications: clean sessions that are published applications providers, too
1488 @type published_applications: C{bool}
1489
1490 """
1491 if self.is_alive():
1492
1493
1494 if self.has_terminal_session():
1495 self.unshare_all_local_folders(force_all=True)
1496
1497 self.control_session.clean_sessions(destroy_terminals=destroy_terminals, published_applications=published_applications)
1498 else:
1499 self._X2GoSession__disconnect()
1500 __clean_sessions = clean_sessions
1501
1503 """\
1504 List all sessions on the remote X2Go server that are owned by the authenticated user
1505
1506 @param raw: if C{True} the output of this method equals
1507 the output of the server-side C{x2golistsessions} command
1508 @type raw: C{bool}
1509
1510 @return: a session list (as data object or list of strings when called with C{raw=True} option)
1511 @rtype: C{X2GoServerSessionList*} instance or C{list}
1512
1513 """
1514 try:
1515 return self.control_session.list_sessions(raw=raw)
1516 except x2go_exceptions.X2GoControlSessionException:
1517 if self.connected: self.HOOK_on_control_session_death()
1518 self._X2GoSession__disconnect()
1519 return None
1520 __list_sessions = list_sessions
1521
1523 """\
1524 List X2Go desktops sessions available for desktop sharing on the remote X2Go server.
1525
1526 @param raw: if C{True} the output of this method equals
1527 the output of the server-side C{x2golistdesktops} command
1528 @type raw: C{bool}
1529
1530 @return: a list of strings representing available desktop sessions
1531 @rtype: C{list}
1532
1533 """
1534 try:
1535 return self.control_session.list_desktops(raw=raw)
1536 except x2go_exceptions.X2GoTimeoutException:
1537 if self.is_alive(): self.HOOK_list_desktop_timeout()
1538 return []
1539 except x2go_exceptions.X2GoControlSessionException:
1540 if self.connected: self.HOOK_on_control_session_death()
1541 self._X2GoSession__disconnect()
1542 return None
1543 __list_desktops = list_desktops
1544
1546 """\
1547 Use the X2Go session registered under C{session_uuid} to
1548 retrieve its list of mounted client shares for that session.
1549
1550 @param raw: output the list of mounted client shares in X2Go's
1551 raw C{x2golistmounts} format
1552 @type raw: C{bool}
1553
1554 @return: a list of strings representing mounted client shares for this session
1555 @rtype: C{list}
1556
1557 """
1558 try:
1559 return self.control_session.list_mounts(self.session_name, raw=raw)
1560 except x2go_exceptions.X2GoControlSessionException:
1561 if self.connected: self.HOOK_on_control_session_death()
1562 self._X2GoSession__disconnect()
1563 return None
1564 __list_mounts = list_mounts
1565
1566 - def update_status(self, session_list=None, force_update=False):
1567 """\
1568 Update the current session status. The L{X2GoSession} instance uses an internal
1569 session status cache that allows to query the session status without the need
1570 of retrieving data from the remote X2Go server for each query.
1571
1572 The session status (if initialized properly with the L{X2GoClient} constructor gets
1573 updated in regularly intervals.
1574
1575 In case you use the L{X2GoSession} class in standalone instances (that is: without
1576 being embedded into an L{X2GoSession} context) then run this method in regular
1577 intervals to make sure the L{X2GoSession}'s internal status cache information
1578 is always up-to-date.
1579
1580 @param session_list: provide an C{X2GoServerSessionList*} that refers to X2Go sessions we want to update.
1581 This option is mainly for reducing server/client traffic.
1582 @type session_list: C{X2GoServerSessionList*} instance
1583 @param force_update: force a session status update, if if the last update is less then 1 second ago
1584 @type force_update: C{bool}
1585
1586 @raise Exception: any exception is passed through in case the session disconnected surprisingly
1587 or has been marked as faulty
1588
1589 """
1590 if not force_update and self._last_status is not None:
1591 _status_update_timedelta = time.time() - self._last_status['timestamp']
1592
1593
1594 if _status_update_timedelta < 1:
1595 self.logger('status update interval too short (%s), skipping status update this time...' % _status_update_timedelta, loglevel=log.loglevel_DEBUG)
1596 return False
1597
1598 e = None
1599 self._last_status = copy.deepcopy(self._current_status)
1600 if session_list is None:
1601 try:
1602 session_list = self.control_session.list_sessions()
1603 self.connected = True
1604 except x2go_exceptions.X2GoControlSessionException, e:
1605 self.connected = False
1606 self.running = None
1607 self.suspended = None
1608 self.terminated = None
1609 self.faulty = None
1610
1611 if self.connected:
1612 try:
1613 _session_name = self.get_session_name()
1614 _session_info = session_list[_session_name]
1615 self.running = _session_info.is_running()
1616 self.suspended = _session_info.is_suspended()
1617 if not self.virgin:
1618 self.terminated = not (self.running or self.suspended)
1619 else:
1620 self.terminated = None
1621 except KeyError, e:
1622 self.running = False
1623 self.suspended = False
1624 if not self.virgin:
1625 self.terminated = True
1626 self.faulty = not (self.running or self.suspended or self.terminated or self.virgin)
1627
1628 self._current_status = {
1629 'timestamp': time.time(),
1630 'server': self.server,
1631 'virgin': self.virgin,
1632 'connected': self.connected,
1633 'running': self.running,
1634 'suspended': self.suspended,
1635 'terminated': self.terminated,
1636 'faulty': self.faulty,
1637 }
1638
1639 if (not self.connected or self.faulty) and e:
1640 raise e
1641
1642 return True
1643 __update_status = update_status
1644
1646 """\
1647 Returns true if this session runs in published applications mode.
1648
1649 @return: returns C{True} if this session is a provider session for published applications.
1650 @rtype: C{bool}
1651
1652 """
1653 if self.has_terminal_session() and self.is_running() :
1654 return self.terminal_session.is_published_applications_provider()
1655 return False
1656 __is_published_applications_provider = is_published_applications_provider
1657
1659 """\
1660 Return a list of published menu items from the X2Go server
1661 for session type published applications.
1662
1663 @param lang: locale/language identifier
1664 @type lang: C{str}
1665 @param refresh: force reload of the menu tree from X2Go server
1666 @type refresh: C{bool}
1667 @param raw: retrieve a raw output of the server list of published applications
1668 @type raw: C{bool}
1669 @param very_raw: retrieve a very raw output of the server list of published applications (as-is output of x2gogetapps script)
1670 @type very_raw: C{bool}
1671
1672 @return: A C{list} of C{dict} elements. Each C{dict} elements has a
1673 C{desktop} key containing the text output of a .desktop file and
1674 an C{icon} key which contains the desktop icon data base64 encoded
1675 @rtype: C{list}
1676
1677 """
1678 if self.client_instance and hasattr(self.client_instance, 'lang'):
1679 lang = self.client_instance.lang
1680 return self.control_session.get_published_applications(lang=lang, refresh=refresh, raw=raw, very_raw=very_raw, max_no_submenus=max_no_submenus)
1681 __get_published_applications = get_published_applications
1682
1684 """\
1685 Execute an application while in published application mode.
1686
1687 @param exec_name: command to execute on server
1688 @type exec_name: C{str}
1689
1690 """
1691 if self.terminal_session is not None:
1692 self.logger('for %s executing published application: %s' % (self.profile_name, exec_name), loglevel=log.loglevel_NOTICE)
1693 self.terminal_session.exec_published_application(exec_name, timeout=timeout, env=self.session_environment)
1694 __exec_published_application = exec_published_application
1695
1696 - def do_auto_start_or_resume(self, newest=True, oldest=False, all_suspended=False, start=True, redirect_to_client=True):
1697 """\
1698 Automatically start or resume this session, if already associated with a server session. Otherwise
1699 resume a server-side available/suspended session (see options to declare which session to resume).
1700 If no session is available for resuming a new session will be launched.
1701
1702 Sessions in published applications mode are not resumed/started by this method.
1703
1704 @param newest: if resuming, only resume newest/youngest session
1705 @type newest: C{bool}
1706 @param oldest: if resuming, only resume oldest session
1707 @type oldest: C{bool}
1708 @param all_suspended: if resuming, resume all suspended sessions
1709 @type all_suspended: C{bool}
1710 @param start: is no session is to be resumed, start a new session
1711 @type start: C{bool}
1712 @param redirect_to_client: redirect this call to the L{X2GoClient} instance (if available) to allow frontend interaction
1713 @type redirect_to_client: C{bool}
1714
1715 @return: returns success (or failure) of starting/resuming this sessions
1716 @rtype: C{bool}
1717
1718 """
1719 if self.client_instance and redirect_to_client:
1720 return self.client_instance.session_auto_start_or_resume(self())
1721 else:
1722 if self.session_name is not None and 'PUBLISHED' not in self.session_name:
1723 return self.resume()
1724 else:
1725 session_infos = self.list_sessions()
1726
1727
1728 for session_name in session_infos.keys():
1729 if session_infos[session_name].is_published_applications_provider():
1730 del session_infos[session_name]
1731
1732 if session_infos:
1733 sorted_session_names = utils.session_names_by_timestamp(session_infos)
1734 if newest:
1735 if sorted_session_names[0].find('RDP') == -1:
1736 return self.resume(session_name=sorted_session_names[-1])
1737 elif oldest:
1738 if sorted_session_names[-1].find('RDP') == -1:
1739 return self.resume(session_name=sorted_session_names[0])
1740 elif all_suspended:
1741 for session_name in [ _sn for _sn in session_infos.keys() if session_infos[_sn].is_suspended() ]:
1742 return self.resume(session_name=session_name)
1743 else:
1744 if not self.published_applications:
1745 return self.start()
1746 __do_auto_start_or_resume = do_auto_start_or_resume
1747
1749 """\
1750 Reset session startup/resumption progress status.
1751
1752 """
1753 self._progress_status = 0
1754
1756 """\
1757 Retrieve session startup/resumption progress status.
1758
1759 @return: returns an C{int} value between 0 and 100 reflecting the session startup/resumption status
1760 @rtype: C{int}
1761
1762 """
1763 return self._progress_status
1764
1765 - def resume(self, session_name=None, session_list=None, cmd=None, progress_event=None):
1766 """\
1767 Resume or continue a suspended / running X2Go session on the
1768 remote X2Go server.
1769
1770 @param session_name: the server-side name of an X2Go session
1771 @type session_name: C{str}
1772 @param session_list: a session list to avoid a server-side session list query
1773 @type session_list: C{dict}
1774 @param cmd: if starting a new session, manually hand over the command to be launched in
1775 the new session
1776 @type cmd: C{str}
1777 @param progress_event: a C{thread.Event} object that notifies a status object like the one in
1778 L{utils.ProgressStatus}.
1779 @type progress_event: C{obj}
1780
1781 @return: returns C{True} if resuming the session has been successful, C{False} otherwise
1782 @rtype: C{bool}
1783
1784 @raise Exception: any exception that occurs during published application menu retrieval is passed through
1785
1786 """
1787 self._lock.acquire()
1788 try:
1789 _retval = self._resume(session_name=session_name, session_list=session_list, cmd=cmd, progress_event=progress_event)
1790 except:
1791 if self._lock.locked():
1792 self._lock.release()
1793 raise
1794 finally:
1795 if self._lock.locked():
1796 self._lock.release()
1797 return _retval
1798
1799 - def _resume(self, session_name=None, session_list=None, cmd=None, progress_event=None):
1800 """\
1801 Resume or continue a suspended / running X2Go session on the
1802 remote X2Go server.
1803
1804 @param session_name: the server-side name of an X2Go session
1805 @type session_name: C{str}
1806 @param session_list: a session list to avoid a server-side session list query
1807 @type session_list: C{dict}
1808 @param cmd: if starting a new session, manually hand over the command to be launched in
1809 the new session
1810 @type cmd: C{str}
1811 @param progress_event: a C{thread.Event} object that notifies a status object like the one in
1812 L{utils.ProgressStatus}.
1813 @type progress_event: C{obj}
1814
1815 @return: returns C{True} if resuming the session has been successful, C{False} otherwise
1816 @rtype: C{bool}
1817
1818 @raise Exception: any exception that occurs during published application menu retrieval is passed through
1819
1820 """
1821 if self.terminal_session is None:
1822 self.terminal_session = 'PENDING'
1823
1824
1825 self.reset_progress_status()
1826 _dummy_event = threading.Event()
1827 if type(progress_event) != type(_dummy_event):
1828 progress_event = _dummy_event
1829
1830 self._progress_status = 1
1831 progress_event.set()
1832
1833 _new_session = False
1834 if self.session_name is None:
1835 self.session_name = session_name
1836
1837 self._progress_status = 2
1838 progress_event.set()
1839
1840 if self.is_alive():
1841
1842 self._progress_status = 5
1843 progress_event.set()
1844
1845 _control = self.control_session
1846
1847 self._progress_status = 7
1848 progress_event.set()
1849
1850
1851
1852
1853
1854 try:
1855 _control.test_sftpclient()
1856 except x2go_exceptions.X2GoSFTPClientException:
1857 self.HOOK_on_failing_SFTP_client()
1858 self.terminal_session = None
1859 self._progress_status = -1
1860 progress_event.set()
1861 return False
1862
1863 if self.is_running():
1864 try:
1865
1866 self._suspend()
1867 self.terminal_session = 'PENDING'
1868
1869 self._progress_status = 10
1870 progress_event.set()
1871
1872 if self._lock.locked():
1873 self._lock.release()
1874 gevent.sleep(5)
1875 self._lock.acquire()
1876
1877 self._progress_status = 15
1878 progress_event.set()
1879
1880 except x2go_exceptions.X2GoSessionException:
1881 pass
1882
1883
1884 self._progress_status = 20
1885 progress_event.set()
1886
1887 try:
1888 if self.published_applications:
1889 self.published_applications_menu = gevent.spawn(self.get_published_applications)
1890 except:
1891
1892
1893 self._progress_status = -1
1894 progress_event.set()
1895 raise
1896
1897 if cmd is not None:
1898 self.terminal_params['cmd'] = cmd
1899
1900 try:
1901 self.terminal_session = _control.resume(session_name=self.session_name,
1902 session_instance=self,
1903 session_list=session_list,
1904 logger=self.logger, **self.terminal_params)
1905 except x2go_exceptions.X2GoControlSessionException, e:
1906 self.logger('%s' % str(e), loglevel=log.loglevel_ERROR)
1907 self.HOOK_on_control_session_death()
1908 self._X2GoSession__disconnect()
1909 return False
1910
1911 self._progress_status = 25
1912 progress_event.set()
1913
1914 if self.session_name is None:
1915 _new_session = True
1916 try:
1917 self.session_name = self.terminal_session.session_info.name
1918 except AttributeError:
1919
1920 self.HOOK_session_startup_failed()
1921
1922 self._progress_status = -1
1923 progress_event.set()
1924
1925 return False
1926
1927 self._progress_status = 30
1928 progress_event.set()
1929
1930 if self.has_terminal_session() and not self.faulty:
1931
1932 self.terminal_session.session_info_protect()
1933
1934 if self.get_session_cmd() != 'PUBLISHED':
1935 self.published_applications = False
1936
1937 self._progress_status = 35
1938 progress_event.set()
1939
1940 if self._SUPPORTED_SOUND and self.terminal_session.params.snd_system is not 'none':
1941 self.has_terminal_session() and not self.faulty and self.terminal_session.start_sound()
1942 else:
1943 self._SUPPORTED_SOUND = False
1944
1945 self._progress_status = 40
1946 progress_event.set()
1947
1948 if self._SUPPORTED_TELEKINESIS and self.has_terminal_session() and not self.faulty:
1949 gevent.spawn(self.terminal_session.start_telekinesis)
1950
1951 self._progress_status = 50
1952 progress_event.set()
1953
1954 try:
1955 if (self._SUPPORTED_PRINTING and self.printing) or \
1956 (self._SUPPORTED_MIMEBOX and self.allow_mimebox) or \
1957 (self._SUPPORTED_FOLDERSHARING and self.allow_share_local_folders):
1958 self.has_terminal_session() and not self.faulty and self.terminal_session.start_sshfs()
1959 except x2go_exceptions.X2GoUserException, e:
1960 self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
1961 self.HOOK_sshfs_not_available()
1962 self._SUPPORTED_PRINTING = False
1963 self._SUPPORTED_MIMEBOX = False
1964 self._SUPPORTED_FOLDERSHARING = False
1965
1966 self._progress_status = 60
1967 progress_event.set()
1968
1969 if self._SUPPORTED_PRINTING and self.printing:
1970 try:
1971 self.has_terminal_session() and not self.faulty and self.terminal_session.start_printing()
1972 self.has_terminal_session() and not self.faulty and self.session_environment.update({'X2GO_SPOOLDIR': self.terminal_session.get_printing_spooldir(), })
1973 except (x2go_exceptions.X2GoUserException, x2go_exceptions.X2GoSFTPClientException), e:
1974 self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
1975 self.HOOK_printing_not_available()
1976 self._SUPPORTED_PRINTING = False
1977 except x2go_exceptions.X2GoControlSessionException, e:
1978 self.logger('%s' % str(e), loglevel=log.loglevel_ERROR)
1979 self.HOOK_on_control_session_death()
1980 self._X2GoSession__disconnect()
1981 return False
1982
1983 self._progress_status = 70
1984 progress_event.set()
1985
1986 if self._SUPPORTED_MIMEBOX and self.allow_mimebox:
1987 try:
1988 self.has_terminal_session() and not self.faulty and self.terminal_session.start_mimebox(mimebox_extensions=self.mimebox_extensions, mimebox_action=self.mimebox_action)
1989 self.has_terminal_session() and self.session_environment.update({'X2GO_MIMEBOX': self.terminal_session.get_mimebox_spooldir(), })
1990 except (x2go_exceptions.X2GoUserException, x2go_exceptions.X2GoSFTPClientException), e:
1991 self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
1992 self.HOOK_mimebox_not_available()
1993 self._SUPPORTED_MIMEBOX = False
1994 except x2go_exceptions.X2GoControlSessionException, e:
1995 self.logger('%s' % str(e), loglevel=log.loglevel_ERROR)
1996 self.HOOK_on_control_session_death()
1997 self._X2GoSession__disconnect()
1998 return False
1999
2000 self._progress_status = 80
2001 progress_event.set()
2002
2003
2004 if _new_session:
2005 try:
2006 self.has_terminal_session() and self.terminal_session.run_command(env=self.session_environment)
2007 except x2go_exceptions.X2GoControlSessionException, e:
2008 self.logger('%s' % str(e), loglevel=log.loglevel_ERROR)
2009 self.HOOK_on_control_session_death()
2010 self._X2GoSession__disconnect()
2011 return False
2012
2013 self.virgin = False
2014 self.suspended = False
2015 self.running = True
2016 self.terminated = False
2017 self.faulty = False
2018
2019 self._progress_status = 90
2020 progress_event.set()
2021
2022
2023 if (not self.client_instance) and \
2024 self._SUPPORTED_FOLDERSHARING and \
2025 self.allow_share_local_folders:
2026 gevent.spawn(self.share_all_local_folders)
2027
2028 self._progress_status = 100
2029 progress_event.set()
2030
2031 self.has_terminal_session() and self.terminal_session.session_info_unprotect()
2032 return True
2033
2034 else:
2035 self.terminal_session = None
2036
2037 self._progress_status = -1
2038 progress_event.set()
2039
2040 return False
2041
2042 else:
2043
2044 self._progress_status = -1
2045 progress_event.set()
2046
2047 self._X2GoSession__disconnect()
2048 return False
2049 __resume = resume
2050
2051 - def start(self, cmd=None, progress_event=None):
2052 """\
2053 Start a new X2Go session on the remote X2Go server.
2054
2055 @param cmd: manually hand over the command that is to be launched in the new session
2056 @type cmd: C{str}
2057 @param progress_event: a C{thread.Event} object that notifies a status object like the one in
2058 L{utils.ProgressStatus}.
2059 @type progress_event: C{obj}
2060
2061 @return: returns C{True} if starting the session has been successful, C{False} otherwise
2062 @rtype: C{bool}
2063
2064 """
2065 self.session_name = None
2066 return self.resume(cmd=cmd, progress_event=progress_event)
2067 __start = start
2068
2069 - def share_desktop(self, desktop=None, user=None, display=None, share_mode=0, check_desktop_list=True, progress_event=None):
2070 """\
2071 Share an already running X2Go session on the remote X2Go server locally. The shared session may be either
2072 owned by the same user or by a user that grants access to his/her desktop session by the local user.
2073
2074 @param desktop: desktop ID of a sharable desktop in format <user>@<display>
2075 @type desktop: C{str}
2076 @param user: user name and display number can be given separately, here give the
2077 name of the user who wants to share a session with you.
2078 @type user: C{str}
2079 @param display: user name and display number can be given separately, here give the
2080 number of the display that a user allows you to be shared with.
2081 @type display: C{str}
2082 @param share_mode: desktop sharing mode, 0 is VIEW-ONLY, 1 is FULL-ACCESS.
2083 @type share_mode: C{int}
2084 @param check_desktop_list: check if the given desktop is available on the X2Go server; handle with care as
2085 the server-side C{x2golistdesktops} command might block client I/O.
2086 @type check_desktop_list: C{bool}
2087 @param progress_event: a C{thread.Event} object that notifies a status object like the one in
2088 L{utils.ProgressStatus}.
2089 @type progress_event: C{obj}
2090
2091 @return: returns C{True} if starting the session has been successful, C{False} otherwise
2092 @rtype: C{bool}
2093
2094 @raise X2GoDesktopSharingException: if a given desktop ID does not specify an available desktop session
2095 @raise X2GoSessionException: if the available desktop session appears to be dead, in fact
2096
2097 """
2098 self._lock.acquire()
2099 try:
2100 _retval = self._share_desktop(desktop=desktop, user=user, display=display, share_mode=share_mode, check_desktop_list=check_desktop_list, progress_event=progress_event)
2101 except:
2102 if self._lock.locked():
2103 self._lock.release()
2104 raise
2105 finally:
2106 if self._lock.locked():
2107 self._lock.release()
2108 return _retval
2109
2110 - def _share_desktop(self, desktop=None, user=None, display=None, share_mode=0, check_desktop_list=True, progress_event=None):
2111 """\
2112 Share an already running X2Go session on the remote X2Go server locally. The shared session may be either
2113 owned by the same user or by a user that grants access to his/her desktop session by the local user.
2114
2115 @param desktop: desktop ID of a sharable desktop in format <user>@<display>
2116 @type desktop: C{str}
2117 @param user: user name and display number can be given separately, here give the
2118 name of the user who wants to share a session with you.
2119 @type user: C{str}
2120 @param display: user name and display number can be given separately, here give the
2121 number of the display that a user allows you to be shared with.
2122 @type display: C{str}
2123 @param share_mode: desktop sharing mode, 0 is VIEW-ONLY, 1 is FULL-ACCESS.
2124 @type share_mode: C{int}
2125 @param check_desktop_list: check if the given desktop is available on the X2Go server; handle with care as
2126 the server-side C{x2golistdesktops} command might block client I/O.
2127 @type check_desktop_list: C{bool}
2128 @param progress_event: a C{thread.Event} object that notifies a status object like the one in
2129 L{utils.ProgressStatus}.
2130 @type progress_event: C{obj}
2131
2132 @return: returns C{True} if starting the session has been successful, C{False} otherwise
2133 @rtype: C{bool}
2134
2135 @raise X2GoDesktopSharingException: if a given desktop ID does not specify an available desktop session
2136 @raise X2GoSessionException: if the available desktop session appears to be dead, in fact
2137
2138 """
2139 self.terminal_session = 'PENDING'
2140
2141
2142 self.reset_progress_status()
2143 _dummy_event = threading.Event()
2144 if type(progress_event) != type(_dummy_event):
2145 progress_event = _dummy_event
2146
2147 self._progress_status = 5
2148 progress_event.set()
2149
2150 _desktop = desktop or '%s@%s' % (user, display)
2151 if check_desktop_list:
2152 desktop_list = self._X2GoSession__list_desktops()
2153 if not _desktop in desktop_list:
2154 _orig_desktop = _desktop
2155 _desktop = '%s.0' % _desktop
2156 if not _desktop in desktop_list:
2157 self.HOOK_no_such_desktop(desktop=_orig_desktop)
2158 self._progress_status = -1
2159 progress_event.set()
2160 return False
2161
2162 self._progress_status = 33
2163 progress_event.set()
2164
2165 _session_owner = _desktop.split('@')[0]
2166
2167 if self.is_alive():
2168 if self.get_username() != _session_owner:
2169 self.logger('waiting for user ,,%s\'\' to interactively grant you access to his/her desktop session...' % _session_owner, loglevel=log.loglevel_NOTICE)
2170 self.logger('THIS MAY TAKE A WHILE!', loglevel=log.loglevel_NOTICE)
2171
2172 self._progress_status = 50
2173 progress_event.set()
2174
2175 _control = self.control_session
2176 try:
2177 self.terminal_session = _control.share_desktop(desktop=_desktop, share_mode=share_mode,
2178 logger=self.logger, **self.terminal_params)
2179
2180 self._progress_status = 80
2181 progress_event.set()
2182
2183 except ValueError:
2184
2185
2186
2187 self._progress_status = -1
2188 progress_event.set()
2189
2190 raise x2go_exceptions.X2GoSessionException('the session on desktop %s is seemingly dead' % _desktop)
2191
2192 except x2go_exceptions.X2GoDesktopSharingDenied:
2193
2194 self._progress_status = -1
2195 progress_event.set()
2196
2197 self.HOOK_desktop_sharing_denied()
2198 return False
2199
2200 self._progress_status = 90
2201 progress_event.set()
2202
2203 if self.has_terminal_session():
2204 self.session_name = self.terminal_session.session_info.name
2205
2206
2207
2208 try:
2209 self.terminal_session.run_command(env=self.session_environment)
2210 except x2go_exceptions.X2GoControlSessionException, e:
2211 self.logger('%s' % str(e), loglevel=log.loglevel_ERROR)
2212 self.HOOK_on_control_session_death()
2213 self._X2GoSession__disconnect()
2214 return False
2215
2216 self.virgin = False
2217 self.suspended = False
2218 self.running = True
2219 self.terminated = False
2220 self.faulty = False
2221
2222 self._progress_status = 100
2223 progress_event.set()
2224
2225 return self.running
2226 else:
2227 self.terminal_session = None
2228
2229 self._progress_status = -1
2230 progress_event.set()
2231
2232 else:
2233
2234 self._progress_status = -1
2235 progress_event.set()
2236
2237 self._X2GoSession__disconnect()
2238
2239 return False
2240 __share_desktop = share_desktop
2241
2243 """\
2244 Test if this X2Go session is a desktop session.
2245
2246 @return: C{True} if this session is of session type desktop ('D').
2247 @rtype: C{bool}
2248
2249 """
2250 if self.has_terminal_session():
2251 return self.terminal_session.is_desktop_session()
2252 __is_desktop_session = is_desktop_session
2253
2255 """\
2256 Test if this X2Go session is a rootless session.
2257
2258 @return: C{True} if this session is of session type rootless ('R').
2259 @rtype: C{bool}
2260
2261 """
2262 if self.has_terminal_session():
2263 return self.terminal_session.is_rootless_session()
2264 __is_rootless_session = is_rootless_session
2265
2267 """\
2268 Test if this X2Go session is a desktop sharing (aka shadow) session.
2269
2270 @return: C{True} if this session is of session type shadow ('S').
2271 @rtype: C{bool}
2272
2273 """
2274 if self.has_terminal_session():
2275 return self.terminal_session.is_shadow_session()
2276 __is_shadow_session = is_shadow_session
2277
2279 """\
2280 Test if this X2Go session is a published applications session.
2281
2282 @return: C{True} if this session is of session type published applications ('P').
2283 @rtype: C{bool}
2284
2285 """
2286 if self.has_terminal_session():
2287 return self.terminal_session.is_pubapp_session()
2288 __is_pubapp_session = is_pubapp_session
2289
2291 """\
2292 Suspend this X2Go session.
2293
2294 @return: returns C{True} if suspending the session has been successful, C{False} otherwise
2295 @rtype: C{bool}
2296
2297 @raise X2GoSessionException: if the session could not be suspended
2298
2299 """
2300 self._lock.acquire()
2301 try:
2302 _retval = self._suspend()
2303 except:
2304 if self._lock.locked():
2305 self._lock.release()
2306 raise
2307 finally:
2308 if self._lock.locked():
2309 self._lock.release()
2310 return _retval
2311
2313 """\
2314 Suspend this X2Go session.
2315
2316 @return: returns C{True} if suspending the session has been successful, C{False} otherwise
2317 @rtype: C{bool}
2318
2319 @raise X2GoSessionException: if the session could not be suspended
2320
2321 """
2322 if self.is_alive():
2323 if self.has_terminal_session():
2324
2325 self.running = False
2326 self.suspended = True
2327 self.terminated = False
2328 self.faulty = False
2329 self.active = False
2330
2331
2332 self.unshare_all_local_folders(force_all=True, update_exported_folders=False)
2333
2334 self.unset_master_session()
2335
2336 if self.has_terminal_session():
2337 if self.terminal_session.suspend():
2338 self.session_cleanup()
2339 del self.terminal_session
2340 self.terminal_session = None
2341 return True
2342
2343 elif self.has_control_session() and self.session_name:
2344 if self.control_session.suspend(session_name=self.session_name):
2345
2346 self.running = False
2347 self.suspended = True
2348 self.terminated = False
2349 self.faulty = False
2350 self.active = False
2351 self.session_cleanup()
2352 return True
2353
2354 else:
2355 raise x2go_exceptions.X2GoSessionException('cannot suspend session')
2356
2357 else:
2358 self._X2GoSession__disconnect()
2359
2360 return False
2361 __suspend = suspend
2362
2364 """\
2365 Terminate this X2Go session.
2366
2367 @return: returns C{True} if terminating the session has been successful, C{False} otherwise
2368 @rtype: C{bool}
2369
2370 @raise X2GoSessionException: if the session could not be terminated
2371
2372 """
2373 self._lock.acquire()
2374 try:
2375 _retval = self._terminate()
2376 except:
2377 if self._lock.locked():
2378 self._lock.release()
2379 raise
2380 finally:
2381 if self._lock.locked():
2382 self._lock.release()
2383 return _retval
2384
2386 """\
2387 Terminate this X2Go session.
2388
2389 @return: returns C{True} if terminating the session has been successful, C{False} otherwise
2390 @rtype: C{bool}
2391
2392 @raise X2GoSessionException: if the session could not be terminated
2393
2394 """
2395 if self.is_alive():
2396 if self.has_terminal_session():
2397
2398 self.running = False
2399 self.suspended = False
2400 self.terminated = True
2401 self.faulty = False
2402 self.active = False
2403
2404
2405 self.unshare_all_local_folders(force_all=True, update_exported_folders=False)
2406
2407 self.unset_master_session()
2408
2409 if self.has_terminal_session():
2410 if self.terminal_session.terminate():
2411 self.session_cleanup()
2412 del self.terminal_session
2413 self.terminal_session = None
2414 return True
2415
2416 elif self.has_control_session() and self.session_name:
2417 if self.control_session.terminate(session_name=self.session_name):
2418
2419 self.running = False
2420 self.suspended = False
2421 self.terminated = True
2422 self.faulty = False
2423 self.active = False
2424 self.session_cleanup()
2425 return True
2426 else:
2427 raise x2go_exceptions.X2GoSessionException('cannot terminate session')
2428
2429 else:
2430 self._X2GoSession__disconnect()
2431
2432 return False
2433 __terminate = terminate
2434
2436 """\
2437 Retrieve the profile name of this L{X2GoSession} instance.
2438
2439 @return: X2Go client profile name of the session
2440 @rtype: C{str}
2441
2442 """
2443 return self.profile_name
2444 __get_profile_name = get_profile_name
2445
2447 """\
2448 Retrieve the profile ID of this L{X2GoSession} instance.
2449
2450 @return: the session profile's id
2451 @rtype: C{str}
2452
2453 """
2454 return self.profile_id
2455 __get_profile_id = get_profile_id
2456
2457
2458
2459
2460
2462 """\
2463 Test if this C{X2GoSession} is
2464 in a healthy state.
2465
2466 @return: C{True} if session is ok, C{False} otherwise
2467 @rtype: C{bool}
2468
2469 """
2470 if self.has_terminal_session():
2471 return self.terminal_session.ok()
2472 return False
2473 __session_ok = session_ok
2474
2476 """\
2477 Extract color depth from session name.
2478
2479 @return: the session's color depth (as found in the session name)
2480 @rtype: C{str}
2481
2482 """
2483 try:
2484 return int(self.get_session_name().split('_')[2][2:])
2485 except:
2486 return None
2487 __color_depth_from_session_name = color_depth_from_session_name
2488
2490 """\
2491 Check if this session will display properly with the local screen's color depth.
2492
2493 @return: C{True} if the session will display on this client screen,
2494 C{False} otherwise. If no terminal session is yet registered with this session, C{None} is returned.
2495 @rtype: C{bool}
2496
2497 """
2498 _depth_local = utils.local_color_depth()
2499 _depth_session = self.color_depth_from_session_name()
2500 if type(_depth_session) == types.IntType:
2501 return utils.is_color_depth_ok(depth_session=_depth_session, depth_local=_depth_local)
2502
2503
2504
2505 return True
2506 __is_color_depth_ok = is_color_depth_ok
2507
2509 """\
2510 Test if the L{X2GoSession}'s control session is connected to the
2511 remote X2Go server.
2512
2513 @return: C{True} if session is connected, C{False} otherwise
2514 @rtype: C{bool}
2515
2516 """
2517 self.connected = bool(self.control_session and self.control_session.is_connected())
2518 if not self.connected:
2519 self.running = None
2520 self.suspended = None
2521 self.terminated = None
2522 self.faulty = None
2523 return self.connected
2524 __is_connected = is_connected
2525
2527 """\
2528 Test if the L{X2GoSession}'s terminal session is up and running.
2529
2530 @return: C{True} if session is running, C{False} otherwise
2531 @rtype: C{bool}
2532
2533 """
2534 if not update_status:
2535 return self.running
2536
2537 if self.is_connected():
2538 self.running = self.control_session.is_running(self.get_session_name())
2539 if self.running:
2540 self.suspended = False
2541 self.terminated = False
2542 self.faulty = False
2543 if self.virgin and not self.running:
2544 self.running = None
2545 return self.running
2546 __is_running = is_running
2547
2549 """\
2550 Test if the L{X2GoSession}'s terminal session is in suspended state.
2551
2552 @return: C{True} if session is suspended, C{False} otherwise
2553 @rtype: C{bool}
2554
2555 """
2556 if not update_status:
2557 return self.suspended
2558
2559 if self.is_connected():
2560 self.suspended = self.control_session.is_suspended(self.get_session_name())
2561 if self.suspended:
2562 self.running = False
2563 self.terminated = False
2564 self.faulty = False
2565 if self.virgin and not self.suspended:
2566 self.suspended = None
2567 return self.suspended
2568 __is_suspended = is_suspended
2569
2571 """\
2572 Test if the L{X2GoSession}'s terminal session has terminated.
2573
2574 @return: C{True} if session has terminated, C{False} otherwise
2575 @rtype: C{bool}
2576
2577 """
2578 if not update_status:
2579 return self.terminated
2580
2581 if self.is_connected():
2582 self.terminated = not self.virgin and self.control_session.has_terminated(self.get_session_name())
2583 if self.terminated:
2584 self.running = False
2585 self.suspended = False
2586 self.faulty = False
2587 if self.virgin and not self.terminated:
2588 self.terminated = None
2589 return self.terminated
2590 __has_terminated = has_terminated
2591
2593 """\
2594 Test if the remote session allows sharing of local folders with the session.
2595
2596 @return: returns C{True} if local folder sharing is available in the remote session
2597 @rtype: C{bool}
2598
2599 """
2600 if self._SUPPORTED_FOLDERSHARING and self.allow_share_local_folders:
2601 if self.is_connected():
2602 return self.control_session.is_sshfs_available()
2603 else:
2604 self.logger('session is not connected, cannot share local folders now', loglevel=log.loglevel_WARN)
2605 else:
2606 self.logger('local folder sharing is disabled for this session profile', loglevel=log.loglevel_WARN)
2607 return False
2608 __is_folder_sharing_available = is_folder_sharing_available
2609
2611
2612
2613 if self.client_instance and self.restore_shared_local_folders:
2614 _exported_folders = copy.deepcopy(self._restore_exported_folders)
2615 for folder in [ sf for sf in self.shared_folders.keys() if self.shared_folders[sf]['status'] in ('new', 'mounted') ]:
2616 _exported_folders.update({ unicode(folder): True })
2617 for folder in _exported_folders.keys():
2618 if folder in [ sf for sf in self.shared_folders.keys() if self.shared_folders[sf]['status'] == 'unmounted' ]:
2619 _exported_folders.update({ unicode(folder): False })
2620 self._restore_exported_folders = _exported_folders
2621
2622 - def share_local_folder(self, local_path=None, folder_name=None, update_exported_folders=True):
2623 """\
2624 Share a local folder with this registered X2Go session.
2625
2626 @param local_path: the full path to an existing folder on the local
2627 file system
2628 @type local_path: C{str}
2629 @param folder_name: synonymous to C{local_path}
2630 @type folder_name: C{str}
2631 @param update_exported_folders: do an update of the session profile option ,,export'' after the operation
2632 @type update_exported_folders: C{bool}
2633
2634 @return: returns C{True} if the local folder has been successfully mounted within
2635 this X2Go session
2636 @rtype: C{bool}
2637
2638 @raise X2GoSessionException: if this L{X2GoSession} does not have an associated terminal session
2639
2640 """
2641
2642 if folder_name: local_path=folder_name
2643
2644 local_path = unicode(local_path)
2645
2646 retval = False
2647 if self.has_terminal_session():
2648 if self.is_folder_sharing_available() and self.is_master_session():
2649
2650
2651 if self.shared_folders.has_key(local_path):
2652 self.shared_folders[local_path]['status'] = 'mounted'
2653 else:
2654 self.shared_folders.update({ local_path: { 'status': 'new', 'mountpoint': '', }, })
2655 try:
2656 if self.terminal_session.share_local_folder(local_path=local_path):
2657 if update_exported_folders:
2658 self._update_restore_exported_folders()
2659 retval = True
2660 else:
2661
2662 if self.shared_folders[local_path]['status'] == 'new':
2663 del self.shared_folders[local_path]
2664 else:
2665 self.shared_folders[local_path]['status'] = 'unmounted'
2666
2667
2668 if self.client_instance and self.restore_shared_local_folders:
2669 if local_path in self._restore_exported_folders.keys():
2670 self._restore_exported_folders[local_path] = False
2671
2672 except x2go_exceptions.X2GoControlSessionException:
2673 if self.connected: self.HOOK_on_control_session_death()
2674 self._X2GoSession__disconnect()
2675 return retval
2676
2677
2678 if update_exported_folders and self.client_instance and self.restore_shared_local_folders:
2679 self._update_restore_exported_folders()
2680 self.client_instance.set_profile_config(self.profile_name, 'export', self._restore_exported_folders)
2681
2682 else:
2683 raise x2go_exceptions.X2GoSessionException('this X2GoSession object does not have any associated terminal')
2684 return retval
2685
2686 __share_local_folder = share_local_folder
2687
2689 """\
2690 Share all local folders configured to be mounted within this X2Go session.
2691
2692 @param update_exported_folders: do an update of the session profile option ,,export'' after the operation
2693 @type update_exported_folders: C{bool}
2694
2695 @return: returns C{True} if all local folders could be successfully mounted
2696 inside this X2Go session
2697 @rtype: C{bool}
2698
2699 """
2700 retval = False
2701 if self.is_running() and not self.faulty and self._SUPPORTED_FOLDERSHARING and self.share_local_folders and self.allow_share_local_folders and self.has_terminal_session():
2702 if self.is_master_session():
2703 if self.is_folder_sharing_available():
2704 retval = True
2705 for _folder in self.share_local_folders:
2706 try:
2707 retval = self.share_local_folder(_folder, update_exported_folders=False) and retval
2708 except x2go_exceptions.X2GoUserException, e:
2709 retval = False
2710 self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
2711 except x2go_exceptions.X2GoControlSessionException, e:
2712 retval = False
2713 self.logger('%s' % str(e), loglevel=log.loglevel_ERROR)
2714 self.HOOK_on_control_session_death()
2715 self._X2GoSession__disconnect()
2716 break
2717
2718 if update_exported_folders:
2719 self._update_restore_exported_folders()
2720 self.client_instance.set_profile_config(self.profile_name, 'export', self._restore_exported_folders)
2721 else:
2722 self.HOOK_foldersharing_not_available()
2723 return retval
2724 __share_all_local_folders = share_all_local_folders
2725
2727 """\
2728 Unshare a local folder that is mounted within this X2Go session.
2729
2730 @param local_path: the full path to an existing folder on the local
2731 file system that is mounted in this X2Go session and shall be
2732 unmounted
2733 @type local_path: C{str}
2734 @param update_exported_folders: do an update of the session profile option ,,export'' after the operation
2735 @type update_exported_folders: C{bool}
2736
2737 @return: returns C{True} if all local folders could be successfully unmounted
2738 inside this X2Go session
2739 @rtype: C{bool}
2740
2741 @raise X2GoSessionException: if this L{X2GoSession} does not have an associated terminal session
2742
2743 """
2744 retval = False
2745
2746 local_path = unicode(local_path)
2747
2748 if self.has_terminal_session():
2749 if self.is_folder_sharing_available() and self.is_master_session() and local_path in self.shared_folders.keys():
2750
2751
2752 self.shared_folders[local_path]['status'] = 'unmounted'
2753 if self.terminal_session.unshare_local_folder(local_path=local_path):
2754 retval = True
2755 else:
2756
2757 self.shared_folders[local_path]['status'] = 'mounted'
2758
2759
2760 if update_exported_folders and self.client_instance and self.restore_shared_local_folders:
2761 self._update_restore_exported_folders()
2762 self.client_instance.set_profile_config(self.profile_name, 'export', self._restore_exported_folders)
2763
2764 else:
2765 raise x2go_exceptions.X2GoSessionException('this X2GoSession object does not have any associated terminal')
2766
2767 return retval
2768 __unshare_local_folder = unshare_local_folder
2769
2771 """\
2772 Unshare all local folders mounted within this X2Go session.
2773
2774 @param force_all: Really unmount _all_ shared folders, including the print spool folder and
2775 the MIME box spool dir (not recommended).
2776 @type force_all: C{bool}
2777 @param update_exported_folders: do an update of the session profile option ,,export'' after the operation
2778 @type update_exported_folders: C{bool}
2779
2780 @return: returns C{True} if all local folders could be successfully unmounted
2781 inside this X2Go session
2782 @rtype: C{bool}
2783
2784 @raise X2GoSessionException: if this L{X2GoSession} does not have an associated terminal session
2785
2786 """
2787 if self.has_terminal_session():
2788 if self.is_folder_sharing_available() and self.is_master_session():
2789
2790 if force_all:
2791 retval = self.terminal_session.unshare_all_local_folders()
2792 if retval:
2793 self.shared_folders = {}
2794 return retval
2795 else:
2796 retval = True
2797 _shared_folders = copy.deepcopy(self.shared_folders)
2798 for _folder in _shared_folders.keys():
2799 retval = self.unshare_local_folder(_folder, update_exported_folders=False) and retval
2800 if update_exported_folders:
2801 self._update_restore_exported_folders()
2802 self.client_instance.set_profile_config(self.profile_name, 'export', self._restore_exported_folders)
2803 return retval
2804 else:
2805 raise x2go_exceptions.X2GoSessionException('this X2GoSession object does not have any associated terminal')
2806 return False
2807 __unshare_all_local_folders = unshare_all_local_folders
2808
2810 """\
2811 Get a list of local folders mounted within this X2Go session from this client.
2812
2813 @param check_list_mounts: if set to C{True} the list of shared folders is referenced against
2814 the latest status of the server-side mount list.
2815 @type check_list_mounts: C{bool}
2816 @param mounts: a server-side dictionary of session name keys and lists of mounted shares (server-side mount points)
2817 @type mounts: C{dict}
2818
2819 @return: returns a C{list} of those local folder names that are mounted with this X2Go session.
2820 @rtype: C{list}
2821
2822 """
2823 if self.is_folder_sharing_available and self.is_master_session() and self.shared_folders and check_list_mounts:
2824
2825 unshared_folders = []
2826 if mounts is None:
2827 mounts = self.list_mounts()
2828 _defacto_mounts = [ unicode(m.split('|')[1].split('/')[-1]) for m in mounts ]
2829
2830 for shared_folder in self.shared_folders.keys():
2831
2832 if _X2GOCLIENT_OS == 'Windows':
2833 _driveletter, _path = os.path.splitdrive(shared_folder)
2834 _mount_point = '_windrive_%s%s' % (_driveletter[0], _path.replace('\\', '_'))
2835 _mount_point = _mount_point.replace(' ', '_')
2836
2837 else:
2838 _mount_point = shared_folder.replace('/', '_')
2839 _mount_point = _mount_point.replace(' ', '_')
2840
2841 self.shared_folders[shared_folder]['status'] = 'mounted'
2842 self.shared_folders[shared_folder]['mountpoint'] = unicode(_mount_point)
2843
2844 for m in _defacto_mounts:
2845 for sf in self.shared_folders.keys():
2846 if self.shared_folders[sf]['mountpoint'] == m:
2847 self.shared_folders[sf]['status'] = 'mounted'
2848 break
2849
2850 unshared_folders = False
2851
2852 for sf in self.shared_folders.keys():
2853 m = self.shared_folders[sf]['mountpoint']
2854 if m and m not in _defacto_mounts:
2855 try:
2856 if self.shared_folders[sf]['status'] == 'mounted':
2857 self.shared_folders[sf]['status'] = 'unmounted'
2858 self.logger('Detected server-side unsharing of client-side folder for profile %s: %s:' % (self.get_profile_name(), sf), loglevel=log.loglevel_INFO)
2859 unshared_folders = True
2860 except IndexError:
2861 pass
2862
2863 if unshared_folders:
2864 self._update_restore_exported_folders()
2865
2866 return [ unicode(sf) for sf in self.shared_folders if self.shared_folders[sf]['status'] in ('new', 'mounted') ]
2867 __get_shared_folders = get_shared_folders
2868
2887 __session_cleanup = session_cleanup
2888
2890 """\
2891 Test if the session is lock at the moment. This normally occurs
2892 if there is some action running that will result in a session status
2893 change.
2894
2895 @return: returns C{True} if the session is locked
2896 @rtype: C{bool}
2897
2898 """
2899 self._lock.locked()
2900