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
62
63 import defaults
64 import log
65 import utils
66 import session
67 import x2go_exceptions
68
69
70 from x2go.backends.control import X2goControlSession as _X2goControlSession
71 from x2go.backends.terminal import X2goTerminalSession as _X2goTerminalSession
72 from x2go.backends.info import X2goServerSessionInfo as _X2goServerSessionInfo
73 from x2go.backends.info import X2goServerSessionList as _X2goServerSessionList
74 from x2go.backends.proxy import X2goProxy as _X2goProxy
75 from x2go.backends.settings import X2goClientSettings as _X2goClientSettings
76 from x2go.backends.printing import X2goClientPrinting as _X2goClientPrinting
77
78 from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
79 from defaults import LOCAL_HOME as _LOCAL_HOME
80 from defaults import X2GO_CLIENT_ROOTDIR as _X2GO_CLIENT_ROOTDIR
81 from defaults import X2GO_SESSIONS_ROOTDIR as _X2GO_SESSIONS_ROOTDIR
82 from defaults import X2GO_SSH_ROOTDIR as _X2GO_SSH_ROOTDIR
83
84 from defaults import SUPPORTED_SOUND, SUPPORTED_PRINTING, SUPPORTED_FOLDERSHARING, SUPPORTED_MIMEBOX
85
86 _X2GO_SESSION_PARAMS = ('use_sshproxy', 'profile_id', 'session_name',
87 'auto_start_or_resume', 'auto_connect',
88 'printing', 'allow_mimebox',
89 'mimebox_extensions', 'mimebox_action',
90 'allow_share_local_folders', 'share_local_folders',
91 'control_backend', 'terminal_backend', 'info_backend', 'list_backend', 'proxy_backend', 'settings_backend', 'printing_backend',
92 'client_rootdir', 'sessions_rootdir', 'ssh_rootdir',
93 'keep_controlsession_alive', 'add_to_known_hosts', 'known_hosts'
94 'connected', 'virgin', 'running', 'suspended', 'terminated', 'faulty'
95 'client_instance',
96 )
97 """A list of allowed X2Go pure session parameters (i.e. parameters that are passed on neither to an X2goControlSession, X2goSSHProxy nor an X2goControlSession object."""
98
99 _X2GO_TERMINAL_PARAMS = ('geometry', 'depth', 'link', 'pack', 'dpi',
100 'cache_type', 'kbtype', 'kblayout', 'kbvariant',
101 'session_type', 'snd_system', 'snd_port',
102 'cmd', 'set_session_title', 'session_title',
103 'rdp_server', 'rdp_options', 'applications',
104 'xdmcp_server',
105 'rootdir', 'loglevel', 'profile_name', 'profile_id',
106 'print_action', 'print_action_args',
107 'convert_encoding', 'client_encoding', 'server_encoding',
108 'proxy_options', 'published_applications', 'published_applications_no_submenus',
109 'logger',
110 'control_backend', 'terminal_backend', 'proxy_backend',
111 'profiles_backend', 'settings_backend', 'printing_backend',
112 )
113 """A list of allowed X2Go terminal session parameters."""
114 _X2GO_SSHPROXY_PARAMS = ('sshproxy_host', 'sshproxy_user', 'sshproxy_password',
115 'sshproxy_key_filename', 'sshproxy_pkey', 'sshproxy_tunnel',
116 )
117 """A list of allowed X2Go SSH proxy parameters."""
118
119
121 """\
122 Public API class for launching X2Go sessions. Recommended is to manage X2Go sessions from
123 within an L{X2goClient} instance. However, Python X2Go is designed in a way that it also
124 allows the management of singel L{X2goSession} instance.
125
126 Thus, you can use the L{X2goSession} class to manually set up X2Go sessions without
127 L{X2goClient} context (session registry, session list cache, auto-registration of new
128 sessions etc.).
129
130 """
131 - def __init__(self, server=None, port=22, control_session=None,
132 use_sshproxy=False,
133 profile_id=None, profile_name='UNKNOWN',
134 session_name=None,
135 auto_start_or_resume=False,
136 auto_connect=False,
137 printing=False,
138 allow_mimebox=False,
139 mimebox_extensions=[],
140 mimebox_action='OPEN',
141 allow_share_local_folders=False,
142 share_local_folders=[],
143 control_backend=_X2goControlSession,
144 terminal_backend=_X2goTerminalSession,
145 info_backend=_X2goServerSessionInfo,
146 list_backend=_X2goServerSessionList,
147 proxy_backend=_X2goProxy,
148 settings_backend=_X2goClientSettings,
149 printing_backend=_X2goClientPrinting,
150 client_rootdir=os.path.join(_LOCAL_HOME, _X2GO_CLIENT_ROOTDIR),
151 sessions_rootdir=os.path.join(_LOCAL_HOME, _X2GO_SESSIONS_ROOTDIR),
152 ssh_rootdir=os.path.join(_LOCAL_HOME, _X2GO_SSH_ROOTDIR),
153 keep_controlsession_alive=False,
154 add_to_known_hosts=False,
155 known_hosts=None,
156 logger=None, loglevel=log.loglevel_DEFAULT,
157 connected=False, activated=False, virgin=True, running=None, suspended=None, terminated=None, faulty=None,
158 client_instance=None,
159 **params):
160 """\
161 @param server: hostname of X2Go server
162 @type server: C{str}
163 @param control_session: an already initialized C{X2goControlSession*} instance
164 @type control_session: C{X2goControlSession*} instance
165 @param use_sshproxy: for communication with X2Go server use an SSH proxy host
166 @type use_sshproxy: C{bool}
167 @param profile_id: profile ID
168 @type profile_id: C{str}
169 @param profile_name: profile name
170 @type profile_name: C{str}
171 @param session_name: session name (if available)
172 @type session_name: C{str}
173 @param auto_start_or_resume: automatically start a new or resume latest session after connect
174 @type auto_start_or_resume: C{bool}
175 @param auto_connect: call a hook method that handles connecting the session profile automatically after a session for this profile has been registered
176 @type auto_connect: C{bool}
177 @param printing: enable X2Go printing
178 @type printing: C{bool}
179 @param allow_mimebox: enable X2Go MIME box support
180 @type allow_mimebox: C{bool}
181 @param mimebox_extensions: whitelist of allowed X2Go MIME box extensions
182 @type mimebox_extensions: C{list}
183 @param mimebox_action: action for incoming X2Go MIME box files
184 @type mimebox_action: C{X2goMimeBoxAction*} or C{str}
185 @param allow_share_local_folders: enable local folder sharing support
186 @type allow_share_local_folders: C{bool}
187 @param share_local_folders: list of local folders to share with the remote X2Go session
188 @type share_local_folders: C{list}
189 @param control_backend: X2Go control session backend to use
190 @type control_backend: C{class}
191 @param terminal_backend: X2Go terminal session backend to use
192 @type terminal_backend: C{class}
193 @param info_backend: X2Go session info backend to use
194 @type info_backend: C{class}
195 @param list_backend: X2Go session list backend to use
196 @type list_backend: C{class}
197 @param proxy_backend: X2Go proxy backend to use
198 @type proxy_backend: C{class}
199 @param settings_backend: X2Go client settings backend to use
200 @type settings_backend: C{class}
201 @param printing_backend: X2Go client printing backend to use
202 @type printing_backend: C{class}
203 @param client_rootdir: client base dir (default: ~/.x2goclient)
204 @type client_rootdir: C{str}
205 @param sessions_rootdir: sessions base dir (default: ~/.x2go)
206 @type sessions_rootdir: C{str}
207 @param ssh_rootdir: ssh base dir (default: ~/.ssh)
208 @type ssh_rootdir: C{str}
209 @param keep_controlsession_alive: On last L{X2goSession.disconnect()} keep the associated C{X2goControlSession*} instance alive?
210 @ŧype keep_controlsession_alive: C{bool}
211 @param add_to_known_hosts: Auto-accept server host validity?
212 @type add_to_known_hosts: C{bool}
213 @param known_hosts: the underlying Paramiko/SSH systems C{known_hosts} file
214 @type known_hosts: C{str}
215 @param connected: manipulate session state »connected« by giving a pre-set value
216 @type connected: C{bool}
217 @param activated: normal leave this untouched, an activated session is a session that is about to be used
218 @type activated: C{bool}
219 @param virgin: manipulate session state »virgin« by giving a pre-set value
220 @type virgin: C{bool}
221 @param running: manipulate session state »running« by giving a pre-set value
222 @type running: C{bool}
223 @param suspended: manipulate session state »suspended« by giving a pre-set value
224 @type suspended: C{bool}
225 @param terminated: manipulate session state »terminated« by giving a pre-set value
226 @type terminated: C{bool}
227 @param faulty: manipulate session state »faulty« by giving a pre-set value
228 @type faulty: C{bool}
229 @param client_instance: if available, the underlying L{X2goClient} instance
230 @type client_instance: C{X2goClient} instance
231 @param params: further control session, terminal session and SSH proxy class options
232 @type params: C{dict}
233
234 """
235 if logger is None:
236 self.logger = log.X2goLogger(loglevel=loglevel)
237 else:
238 self.logger = copy.deepcopy(logger)
239 self.logger.tag = __NAME__
240
241 self._keep = None
242
243 self.uuid = uuid.uuid1()
244 self.connected = connected
245
246 self.activated = activated
247 self.virgin = virgin
248 self.running = running
249 self.suspended = suspended
250 self.terminated = terminated
251 self.faulty = faulty
252 self.keep_controlsession_alive = keep_controlsession_alive
253
254 self.profile_id = profile_id
255 self.profile_name = profile_name
256 self.session_name = session_name
257 self.server = server
258 self.port = port
259
260 self._last_status = None
261
262 self.locked = False
263
264 self.auto_start_or_resume = auto_start_or_resume
265 self.auto_connect = auto_connect
266 self.printing = printing
267 self.allow_share_local_folders = allow_share_local_folders
268 self.share_local_folders = share_local_folders
269 self.allow_mimebox = allow_mimebox
270 self.mimebox_extensions = mimebox_extensions
271 self.mimebox_action = mimebox_action
272 self.control_backend = control_backend
273 self.terminal_backend = terminal_backend
274 self.info_backend = info_backend
275 self.list_backend = list_backend
276 self.proxy_backend = proxy_backend
277 self.settings_backend = settings_backend
278 self.printing_backend = printing_backend
279 self.client_rootdir = client_rootdir
280 self.sessions_rootdir = sessions_rootdir
281 self.ssh_rootdir = ssh_rootdir
282 self.control_session = control_session
283
284 if params.has_key('published_applications'):
285 self.published_applications = params['published_applications']
286 if self.published_applications:
287 params['cmd'] = 'PUBLISHED'
288 else:
289 self.published_applications = params['published_applications'] = False
290
291 if params.has_key('cmd') and params['cmd'] != 'PUBLISHED':
292 self.published_applications = params['published_applications'] = False
293 self.published_applications_menu = None
294
295 if self.session_name:
296 if not re.match('.*_stRPUBLISHED_.*',self.session_name):
297 self.published_applications = params['published_applications'] = False
298
299 self.control_params = {}
300 self.terminal_params = {}
301 self.sshproxy_params = {}
302 self.update_params(params)
303 self.shared_folders = []
304
305 self.session_environment = {}
306 self.server_features = []
307
308 try: del self.control_params['server']
309 except: pass
310
311 self.client_instance = client_instance
312
313 if self.logger.get_loglevel() & log.loglevel_DEBUG:
314 self.logger('X2Go control session parameters for profile %s:' % profile_name, loglevel=log.loglevel_DEBUG)
315 for p in self.control_params:
316 self.logger(' %s: %s' % (p, self.control_params[p]), log.loglevel_DEBUG)
317 self.logger('X2Go terminal session parameters for profile %s:' % profile_name, loglevel=log.loglevel_DEBUG)
318 for p in self.terminal_params:
319 self.logger(' %s: %s' % (p,self.terminal_params[p]), log.loglevel_DEBUG)
320 self.logger('X2Go sshproxy parameters for profile %s:' % profile_name, loglevel=log.loglevel_DEBUG)
321 for p in self.sshproxy_params:
322 self.logger(' %s: %s' % (p,self.sshproxy_params[p]), loglevel=log.loglevel_DEBUG)
323
324 self.add_to_known_hosts = add_to_known_hosts
325 self.known_hosts = known_hosts
326 self.use_sshproxy = use_sshproxy
327
328 self._current_status = {
329 'timestamp': time.time(),
330 'server': self.server,
331 'virgin': self.virgin,
332 'connected': self.connected,
333 'running': self.running,
334 'suspended': self.suspended,
335 'terminated': self.terminated,
336 'faulty': self.faulty,
337 }
338
339 self._SUPPORTED_SOUND = SUPPORTED_SOUND
340 self._SUPPORTED_PRINTING = SUPPORTED_PRINTING
341 self._SUPPORTED_MIMEBOX = SUPPORTED_MIMEBOX
342 self._SUPPORTED_FOLDERSHARING = SUPPORTED_FOLDERSHARING
343
344 self.master_session = None
345 self.init_control_session()
346 self.terminal_session = None
347
348 if self.is_connected():
349 self.retrieve_server_features()
350
352 """\
353 Return parent L{X2goClient} instance if avaiable.
354
355 return: L{X2goClient} instance this session is associated with
356 rtype: C{obj}
357
358 """
359 return self.client_instance
360 __get_client_instance = get_client_instance
361
363 """\
364 HOOK method: called if a control session (server connection) has unexpectedly encountered a failure.
365
366 """
367 if self.client_instance:
368 self.client_instance.HOOK_on_control_session_death(profile_name=self.profile_name)
369 else:
370 self.logger('HOOK_on_control_session_death: the control session of profile %s has died unexpectedly' % self.profile_name, loglevel=log.loglevel_WARN)
371
373 """\
374 HOOK method: called if the session demands to auto connect.
375
376 """
377 if self.client_instance:
378 self.client_instance.HOOK_profile_auto_connect(profile_name=self.profile_name)
379 else:
380 self.logger('HOOK_auto_connect: profile ,,%s\'\' wants to auto-connect to the X2Go server.' % self.profile_name, loglevel=log.loglevel_WARN)
381
383 """\
384 HOOK method: called if the startup of a session failed.
385
386 """
387 if self.client_instance:
388 self.client_instance.HOOK_session_startup_failed(profile_name=self.profile_name)
389 else:
390 self.logger('HOOK_session_startup_failed: session startup for session profile ,,%s\'\' failed.' % self.profile_name, loglevel=log.loglevel_WARN)
391
393 """\
394 HOOK method: called if a reverse port forwarding request has been denied.
395
396 @param server_port: remote server port (starting point of reverse forwarding tunnel)
397 @type server_port: C{str}
398
399 """
400 if self.client_instance:
401 self.client_instance.HOOK_rforward_request_denied(profile_name=self.profile_name, session_name=self.session_name, server_port=server_port)
402 else:
403 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)
404
406 """\
407 HOOK method: called if a port forwarding tunnel setup failed.
408
409 @param chain_host: hostname of chain host (forwarding tunnel end point)
410 @type chain_host: C{str}
411 @param chain_port: port of chain host (forwarding tunnel end point)
412 @type chain_port: C{str}
413
414 """
415
416 self.faulty = True
417
418 if self.client_instance:
419 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)
420 else:
421 self.logger('HOOK_forwarding_tunnel_setup_failed: Forwarding tunnel request to [%s]:%s for session %s (%s) was denied by remote X2go/SSH server. Session startup failed.' % (chain_host, chain_port, self.session_name, self.profile_name), loglevel=log.loglevel_WARN)
422
423
424 try:
425 self.terminate()
426 except x2go_exceptions.X2goSessionException:
427 pass
428
430 """\
431 HOOK method: called if X2Go client-side printing is not available.
432
433 """
434 if self.client_instance:
435 self.client_instance.HOOK_printing_not_available(profile_name=self.profile_name, session_name=self.session_name)
436 else:
437 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)
438
440 """\
441 HOOK method: called if the X2Go MIME box is not available.
442
443 """
444 if self.client_instance:
445 self.client_instance.HOOK_mimebox_not_available(profile_name=self.profile_name, session_name=self.session_name)
446 else:
447 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)
448
450 """\
451 HOOK method: called if X2Go client-side folder-sharing is not available.
452
453 """
454 if self.client_instance:
455 self.client_instance.HOOK_foldersharing_not_available(profile_name=self.profile_name, session_name=self.session_name)
456 else:
457 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)
458
460 """\
461 HOOK method: called if the X2Go server denies SSHFS access.
462
463 """
464 if self.client_instance:
465 self.client_instance.HOOK_sshfs_not_available(profile_name=self.profile_name, session_name=self.session_name)
466 else:
467 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)
468
470 """\
471 HOOK method: called if a host check is requested. This hook has to either return C{True} (default) or C{False}.
472
473 @param host: SSH server name to validate
474 @type host: C{str}
475 @param port: SSH server port to validate
476 @type port: C{int}
477 @param fingerprint: the server's fingerprint
478 @type fingerprint: C{str}
479 @param fingerprint_type: finger print type (like RSA, DSA, ...)
480 @type fingerprint_type: C{str}
481 @return: if host validity is verified, this hook method should return C{True}
482 @rtype: C{bool}
483
484 """
485 if self.client_instance:
486 return self.client_instance.HOOK_check_host_dialog(profile_name=self.profile_name, host=host, port=port, fingerprint=fingerprint, fingerprint_type=fingerprint_type)
487 else:
488 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)
489 return True
490
492 """\
493 Initialize a new control session (C{X2goControlSession*}).
494
495 """
496 if self.control_session is None:
497 self.logger('initializing X2goControlSession', loglevel=log.loglevel_DEBUG)
498 self.control_session = self.control_backend(profile_name=self.profile_name,
499 add_to_known_hosts=self.add_to_known_hosts,
500 known_hosts=self.known_hosts,
501 terminal_backend=self.terminal_backend,
502 info_backend=self.info_backend,
503 list_backend=self.list_backend,
504 proxy_backend=self.proxy_backend,
505 client_rootdir=self.client_rootdir,
506 sessions_rootdir=self.sessions_rootdir,
507 ssh_rootdir=self.ssh_rootdir,
508 logger=self.logger)
509 __init_control_session = init_control_session
510
512 """\
513 Is this session a/the master session of sessions.
514
515 The master session is the session has been launched first for a specific connection,
516 it also is _the_ session that controls the client-side shared folders.
517
518 If this L{X2goSession} instance is a standalone instance (without parent L{X2goClient})
519 this method will always return C{True}.
520
521 @return: returns C{True} if this session is a master session
522 @rtype: C{bool}
523
524 """
525 if self.master_session is None and self.client_instance is None:
526 return True
527 return bool(self.master_session)
528 __is_master_session = is_master_session
529
531 """\
532 Declare this as a master session of a connection channel.
533
534 This method gets called by the L{X2goSessionRegistry} while sessions are starting or resuming and it relies on
535 an already set-up terminal session.
536
537 @param wait: wait for <wait> seconds before sharing local folders via the new master session
538 of the corresponding session profile.
539 @type wait: C{int}
540 @param max_wait: wait for <max_wait> seconds for the terminal session to appear
541 @type max_wait: C{int}
542
543 """
544 self.logger('Using session %s as master session for profile %s.' % (self.get_session_name(), self.get_profile_name()), loglevel=log.loglevel_NOTICE)
545 self.master_session = True
546
547 i = 0
548 while i < max_wait:
549 i += 1
550 if self.has_terminal_session():
551 break
552 gevent.sleep(1)
553
554 if wait:
555 gevent.spawn_later(wait, self.share_all_local_folders)
556 else:
557 gevent.spawn(self.share_all_local_folders)
558 __set_master_session = set_master_session
559
569 __unset_master_session = unset_master_session
570
572 """\
573 Modify server name after L{X2goSession} has already been initialized.
574
575 @param server: new server name
576 @type server: C{str}
577
578 """
579 self.server = server
580 __set_server = set_server
581
583 """\
584 Modify server port after L{X2goSession} has already been initialized.
585
586 @param port: socket port of server to connect to
587 @type port: C{int}
588
589 """
590 self.port = port
591 __set_port = set_port
592
594 """\
595 Modify session profile name after L{X2goSession} has already been initialized.
596
597 @param profile_name: new session profile name
598 @type profile_name: C{str}
599
600 """
601 self.profile_name = profile_name
602 self.control_session.set_profile_name(profile_name)
603 __set_profile_name = set_profile_name
604
606 """\
607 Retrieve a specific profile parameter for this session.
608
609 @param option: name of a specific profile option to be queried.
610 @type option: C{str}
611
612 @return: value for profile option C{<option>}
613 @rtype: C{bool,str,int}
614
615 @raise X2goProfileException: if the session profile option is unknown
616
617 """
618 if option in _X2GO_SESSION_PARAMS + _X2GO_TERMINAL_PARAMS + _X2GO_SSHPROXY_PARAMS and hasattr(self, option):
619 return eval("self.%s" % option)
620 else:
621 raise x2go_exceptions.X2goProfileException('Unknown session profile option: %s.' % option)
622 __get_session_profile_option = get_session_profile_option
623
625 return self.__get_uuid()
626
628 result = 'X2goSession('
629 for p in dir(self):
630 if '__' in p or not p in self.__dict__ or type(p) is types.InstanceType: continue
631 result += p + '=' + str(self.__dict__[p]) + ', '
632 return result + ')'
633
635 return self.__get_uuid()
636
638 """\
639 Class destructor.
640
641 """
642 if self.has_control_session() and self.has_terminal_session():
643 self.get_control_session().dissociate(self.get_terminal_session())
644
645 if self.has_control_session():
646 if self.keep_controlsession_alive:
647
648
649 self.virgin = True
650 self.is_activated = False
651 self.connected = self.is_connected()
652 self.running = None
653 self.suspended = None
654 self.terminated = None
655 self._current_status = {
656 'timestamp': time.time(),
657 'server': self.server,
658 'virgin': self.virgin,
659 'connected': self.connected,
660 'running': self.running,
661 'suspended': self.suspended,
662 'terminated': self.terminated,
663 'faulty': self.faulty,
664 }
665 self._last_status = None
666 self.session_name = None
667
668 else:
669 self.get_control_session().__del__()
670 self.control_session = None
671
672 if self.has_terminal_session():
673 self.get_terminal_session().__del__()
674 self.terminal_session = None
675
677 """\
678 This method can be used to modify L{X2goSession} parameters after the
679 L{X2goSession} instance has already been initialized.
680
681 @param params: a Python dictionary with L{X2goSession} parameters
682 @type params: C{dict}
683
684 """
685 try: del params['server']
686 except KeyError: pass
687 try: del params['profile_name']
688 except KeyError: pass
689 try: del params['profile_id']
690 except KeyError: pass
691 try:
692 self.printing = params['printing']
693 del params['printing']
694 except KeyError: pass
695 try:
696 self.allow_share_local_folders = params['allow_share_local_folders']
697 del params['allow_share_local_folders']
698 except KeyError: pass
699 try:
700 self.share_local_folders = params['share_local_folders']
701 del params['share_local_folders']
702 except KeyError: pass
703 try:
704 self.allow_mimebox = params['allow_mimebox']
705 del params['allow_mimebox']
706 except KeyError: pass
707 try:
708 self.mimebox_extensions = params['mimebox_extensions']
709 del params['mimebox_extensions']
710 except KeyError: pass
711 try:
712 self.mimebox_action = params['mimebox_action']
713 del params['mimebox_action']
714 except KeyError: pass
715 try:
716 self.use_sshproxy = params['use_sshproxy']
717 del params['use_sshproxy']
718 except KeyError: pass
719 try:
720 self.auto_connect = params['auto_connect']
721 del params['auto_connect']
722 except KeyError: pass
723 try:
724 self.auto_start_or_resume = params['auto_start_or_resume']
725 del params['auto_start_or_resume']
726 except KeyError: pass
727
728 _terminal_params = copy.deepcopy(params)
729 _control_params = copy.deepcopy(params)
730 _sshproxy_params = copy.deepcopy(params)
731 for p in params.keys():
732 if p in session._X2GO_TERMINAL_PARAMS:
733 del _control_params[p]
734 del _sshproxy_params[p]
735 elif p in session._X2GO_SSHPROXY_PARAMS:
736 del _control_params[p]
737 del _terminal_params[p]
738 else:
739 del _sshproxy_params[p]
740 del _terminal_params[p]
741
742 self.control_params.update(_control_params)
743 self.terminal_params.update(_terminal_params)
744 self.sshproxy_params.update(_sshproxy_params)
745
747 """\
748 Retrieve session UUID hash for this L{X2goSession}.
749
750 @return: the session's UUID hash
751 @rtype: C{str}
752
753 """
754 return str(self.uuid)
755 __get_uuid = get_uuid
756
758 """\
759 After a session has been set up you can query the
760 username the sessions runs as.
761
762 @return: the remote username the X2Go session runs as
763 @rtype: C{str}
764
765 """
766
767 try:
768 return self.control_session.get_transport().get_username()
769 except AttributeError:
770 return self.control_params['username']
771 __get_username = get_username
772
774 """\
775 Check if a given user is valid server-side X2Go user.
776
777 @param username: username to check validity for
778 @type username: C{str}
779
780 @return: C{True} if the username is allowed to launch X2Go sessions
781 @rtype: C{bool}
782
783 """
784 if username is None:
785 username = self.__get_username()
786 return self.control_session.is_x2gouser(username)
787 __user_is_x2gouser = user_is_x2gouser
788
790 """\
791 After a session has been setup up you can query the
792 username's password from the session.
793
794 @return: the username's password
795 @rtype: C{str}
796
797 """
798 return self.control_session._session_password
799 __get_password = get_password
800
802 """\
803 After a session has been setup up you can query the
804 peername of the host this session is connected to (or
805 about to connect to).
806
807 @return: the address of the server the X2Go session is
808 connected to (as an C{(addr,port)} tuple)
809 @rtype: C{tuple}
810
811 """
812 return self.control_session.remote_peername()
813 __get_server_peername = get_server_peername
814 remote_peername = get_server_peername
815 __remote_peername = get_server_peername
816
818 """\
819 After a session has been setup up you can query the
820 hostname of the host this session is connected to (or
821 about to connect to).
822
823 @return: the hostname of the server the X2Go session is
824 connected to / about to connect to
825 @rtype: C{str}
826
827 """
828 self.server = self.control_session.get_hostname()
829 return self.server
830 __get_server_hostname = get_server_hostname
831
833 """\
834 After a session has been setup up you can query the
835 IP socket port used for connecting the remote X2Go server.
836
837 @return: the server-side IP socket port that is used by the X2Go session to
838 connect to the server
839 @rtype: C{str}
840
841 """
842 return self.control_session.get_port()
843 __get_server_port = get_server_port
844
846 """\
847 Retrieve the server-side X2Go session name for this session.
848
849 @return: X2Go session name
850 @rtype: C{str}
851
852 """
853 return self.session_name
854 __get_session_name = get_session_name
855
857 """\
858 Retrieve the server-side X2Go session info object for this session.
859
860 @return: X2Go session info
861 @rtype: C{obj}
862
863 """
864 if self.has_terminal_session():
865 self.terminal_session.get_session_info()
866 __get_session_info = get_session_info
867
869 """\
870 Retrieve the server-side command that is used to start a session
871 on the remote X2Go server.
872
873 @return: server-side session command
874 @rtype: C{str}
875
876 """
877 if self.has_terminal_session():
878 return self.terminal_session.get_session_cmd()
879 if self.terminal_params.has_key('cmd'):
880 return self.terminal_params['cmd']
881 return None
882 __get_session_cmd = get_session_cmd
883
885 """\
886 Retrieve the session type of a session (R, D, S or P).
887
888 - R: rootless session
889 - D: desktop session
890 - S: shadow session
891 - P: session in published applications mode
892
893 @return: session type
894 @rtype: C{str}
895
896 """
897 if self.has_terminal_session():
898 return self.terminal_session.get_session_type()
899 else:
900 return None
901 __get_session_type = get_session_type
902
904 """\
905 Retrieve the session window title of this
906 session.
907
908 @return: session window title
909 @rtype: C{str}
910
911 """
912 if self.has_terminal_session():
913 return self.terminal_session.session_title
914 else:
915 return 'X2GO-%s' % self.get_session_name()
916 __get_session_title = get_session_title
917
919 """\
920 Retrieve the control session (C{X2goControlSession*} backend) of this L{X2goSession}.
921
922 @return: the L{X2goSession}'s control session
923 @rtype: C{X2goControlSession*} instance
924
925 """
926 return self.control_session
927 __get_control_session = get_control_session
928
930 """\
931 Check if this L{X2goSession} instance has an associated control session.
932
933 @return: returns C{True} if this L{X2goSession} has a control session associated to itself
934 @rtype: C{bool}
935
936 """
937 return self.control_session is not None
938 __has_control_session = has_control_session
939
941 """\
942 Retrieve the terminal session (C{X2goTerminalSession*} backend) of this L{X2goSession}.
943
944 @return: the L{X2goSession}'s terminal session
945 @rtype: C{X2goControlTerminal*} instance
946
947 """
948 if self.terminal_session == 'PENDING':
949 return None
950 return self.terminal_session
951 __get_terminal_session = get_terminal_session
952
954 """\
955 Check if this L{X2goSession} instance has an associated terminal session.
956
957 @return: returns C{True} if this L{X2goSession} has a terminal session associated to itself
958 @rtype: C{bool}
959
960 """
961 return self.terminal_session not in (None, 'PENDING')
962 __has_terminal_session = has_terminal_session
963 is_associated = has_terminal_session
964 __is_associated = has_terminal_session
965
967 """\
968 Provide a host check mechanism. This method basically calls the L{HOOK_check_host_dialog()} method
969 which by itself calls the L{X2goClient.HOOK_check_host_dialog()} method. Make sure you
970 override any of these to enable user interaction on X2Go server validity checks.
971
972 @return: returns C{True} if an X2Go server host is valid for authentication
973 @rtype: C{bool}
974
975 """
976 if self.connected:
977 return True
978
979 _port = self.control_params['port']
980 (_valid, _host, _port, _fingerprint, _fingerprint_type) = self.control_session.check_host(self.server, port=_port)
981 return _valid or self.HOOK_check_host_dialog(host=_host, port=_port, fingerprint=_fingerprint, fingerprint_type=_fingerprint_type)
982 __check_host = check_host
983
985 """\
986 Check if a session is configured to use an intermediate SSH proxy server.
987
988 @return: returns C{True} if the session is configured to use an SSH proxy, C{False} otherwise.
989 @rtype: C{bool}
990
991 """
992 return self.use_sshproxy
993 __uses_sshproxy = uses_sshproxy
994
996 """\
997 Check if a session's SSH proxy (if used) is configured adequately to be able to auto-connect
998 to the SSH proxy server (e.g. by public key authentication).
999
1000 @return: returns C{True} if the session's SSH proxy can auto-connect, C{False} otherwise, C{None}
1001 if no SSH proxy is used for this session, C{None} is returned.
1002 @rtype: C{bool}
1003
1004 """
1005 if self.use_sshproxy:
1006 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'])):
1007 return True
1008 elif self.sshproxy_params.has_key('sshproxy_pkey') and self.sshproxy_params['sshproxy_pkey']:
1009 return True
1010 else:
1011 return False
1012 else:
1013 return None
1014 __can_sshproxy_auto_connect = can_sshproxy_auto_connect
1015
1017 """\
1018 Check if a session is configured adequately to be able to auto-connect to the X2go
1019 server (e.g. public key authentication).
1020
1021 @return: returns C{True} if the session can auto-connect, C{False} otherwise, C{None}
1022 if no control session has been set up yet.
1023 @rtype: C{bool}
1024
1025 """
1026 if self.control_session is None:
1027 return None
1028
1029
1030 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'])):
1031 _can_sshproxy_auto_connect = self.can_sshproxy_auto_connect()
1032 if _can_sshproxy_auto_connect is not None:
1033 return _can_sshproxy_auto_connect
1034 else:
1035 return True
1036
1037
1038 elif self.control_params.has_key('pkey') and self.control_params['pkey']:
1039 _can_sshproxy_auto_connect = self.can_sshproxy_auto_connect()
1040 if _can_sshproxy_auto_connect is not None:
1041 return _can_sshproxy_auto_connect
1042 else:
1043 return True
1044
1045 else:
1046 return False
1047 __can_auto_connect = can_auto_connect
1048
1050 """\
1051 Automatically connect this session.
1052
1053 @return: Return success (or failure) of connecting this sessions
1054 @rtype: C{bool}
1055
1056 """
1057 if not self.is_connected():
1058 if self.client_instance and redirect_to_client:
1059 return self.client_instance.session_auto_connect(self())
1060 else:
1061 if self.can_auto_connect() and self.auto_connect:
1062 gevent.spawn(self.connect)
1063 elif self.auto_connect:
1064 gevent.spawn(self.HOOK_auto_connect)
1065 __do_auto_connect = do_auto_connect
1066
1067 - def connect(self, username='', password='', add_to_known_hosts=False, force_password_auth=False,
1068 use_sshproxy=False, sshproxy_user='', sshproxy_password=''):
1069 """\
1070 Connects to the L{X2goSession}'s server host. This method basically wraps around
1071 the C{X2goControlSession*.connect()} method.
1072
1073 @param username: the username for the X2Go server that is going to be
1074 connected to (as a last minute way of changing the session username)
1075 @type username: C{str}
1076 @param password: the user's password for the X2Go server that is going to be
1077 connected to
1078 @type password: C{str}
1079 @param add_to_known_hosts: non-paramiko option, if C{True} paramiko.AutoAddPolicy()
1080 is used as missing-host-key-policy. If set to C{False} paramiko.RejectPolicy()
1081 is used
1082 @type add_to_known_hosts: C{bool}
1083 @param force_password_auth: disable SSH pub/priv key authentication mechanisms
1084 completely
1085 @type force_password_auth: C{bool}
1086 @param use_sshproxy: use an SSH proxy host for connecting the target X2Go server
1087 @type use_sshproxy: C{bool}
1088 @param sshproxy_user: username for authentication against the SSH proxy host
1089 @type sshproxy_user: C{str}
1090 @param sshproxy_password: password for authentication against the SSH proxy host
1091 @type sshproxy_password: C{str}
1092
1093 @return: returns C{True} is the connection to the X2Go server has been successful
1094 @rtype C{bool}
1095
1096 @raise X2goSessionException: on control session exceptions
1097 @raise X2goRemoteHomeException: if the remote home directory does not exist
1098 @raise Exception: any other exception during connecting is passed through
1099
1100 """
1101 if self.control_session and self.control_session.is_connected():
1102 self.logger('control session is already connected, skipping authentication', loglevel=log.loglevel_DEBUG)
1103 self.connected = True
1104 else:
1105 if username:
1106 self.control_params['username'] = username
1107 if add_to_known_hosts is not None:
1108 self.control_params['add_to_known_hosts'] = add_to_known_hosts
1109 if force_password_auth is not None:
1110 self.control_params['force_password_auth'] = force_password_auth
1111 if sshproxy_user:
1112 self.sshproxy_params['sshproxy_user'] = sshproxy_user
1113 if sshproxy_password:
1114 self.sshproxy_params['sshproxy_password'] = sshproxy_password
1115 self.control_params['password'] = password
1116
1117 _params = {}
1118 _params.update(self.control_params)
1119 _params.update(self.sshproxy_params)
1120
1121 if 'port' not in _params:
1122 _params['port'] = self.port
1123
1124 try:
1125 self.connected = self.control_session.connect(self.server,
1126 use_sshproxy=self.use_sshproxy,
1127 session_instance=self,
1128 **_params)
1129 except x2go_exceptions.X2goControlSessionException, e:
1130 raise x2go_exceptions.X2goSessionException(str(e))
1131 except x2go_exceptions.X2goRemoteHomeException, e:
1132 self.disconnect()
1133 raise e
1134 except:
1135
1136 self.control_params['password'] = ''
1137 if self.sshproxy_params and self.sshproxy_params.has_key('sshproxy_password'):
1138 del self.sshproxy_params['sshproxy_password']
1139 raise
1140 finally:
1141
1142 self.control_params['password'] = ''
1143 if self.sshproxy_params and self.sshproxy_params.has_key('sshproxy_password'):
1144 del self.sshproxy_params['sshproxy_password']
1145
1146 if not self.connected:
1147
1148 self.disconnect()
1149
1150 self.get_server_hostname()
1151
1152 if self.connected:
1153 self.update_status()
1154 self.retrieve_server_features()
1155 if self.auto_start_or_resume:
1156 gevent.spawn(self.do_auto_start_or_resume)
1157
1158 return self.connected
1159 __connect = connect
1160
1162 """\
1163 Disconnect this L{X2goSession} instance.
1164
1165 @return: returns C{True} if the disconnect operation has been successful
1166 @rtype: C{bool}
1167
1168 """
1169 self.connected = False
1170 self.running = None
1171 self.suspended = None
1172 self.terminated = None
1173 self.faults = None
1174 self.active = False
1175 self.unset_master_session()
1176 try:
1177 self.update_status(force_update=True)
1178 except x2go_exceptions.X2goControlSessionException:
1179 pass
1180 retval = self.control_session.disconnect()
1181 return retval
1182 __disconnect = disconnect
1183
1185 """\
1186 Query the X2Go server for a list of supported features.
1187
1188 """
1189 self.server_features = self.control_session.query_server_features()
1190 __retrieve_server_features = retrieve_server_features
1191
1193 """\
1194 Return a list of X2Go server-sides features (supported functionalities).
1195
1196 @return: a C{list} of X2Go feature names
1197 @rtype: C{list}
1198
1199 """
1200 return self.server_features
1201 __get_server_features = get_server_features
1202
1204 """\
1205 Check if C{feature} is a present feature of the connected X2Go server.
1206
1207 @param feature: an X2Go server feature as found in C{$SHAREDIR/x2go/feature.d/*}
1208 @type feature: C{str}
1209
1210 @return: returns C{True} if the feature is present
1211 @rtype: C{bool}
1212
1213 """
1214 return feature in self.get_server_features()
1215 __has_server_feature = has_server_feature
1216
1218 """\
1219 Modify session window title. If the session ID does not occur in the
1220 given title, it will be prepended, so that every X2Go session window
1221 always contains the X2Go session ID of that window.
1222
1223 @param title: new title for session window
1224 @type title: C{str}
1225
1226 """
1227 if self.terminal_session is not None:
1228 self.terminal_session.set_session_window_title(title=title)
1229 __set_session_window_title = set_session_window_title
1230
1232 """\
1233 Try to lift the session window above all other windows and bring
1234 it to focus.
1235
1236 """
1237 if self.terminal_session is not None:
1238 self.terminal_session.raise_session_window()
1239 __raise_session_window = raise_session_window
1240
1242 """\
1243 If X2Go client-side printing is enable within this X2Go session you can use
1244 this method to alter the way how incoming print spool jobs are handled/processed.
1245
1246 For further information, please refer to the documentation of the L{X2goClient.set_session_print_action()}
1247 method.
1248
1249 @param print_action: one of the named above print actions, either as string or class instance
1250 @type print_action: C{str} or C{instance}
1251 @param kwargs: additional information for the given print action (print
1252 action arguments), for possible print action arguments and their values see each individual
1253 print action class
1254 @type kwargs: C{dict}
1255
1256 """
1257 if type(print_action) is not types.StringType:
1258 return False
1259 self.terminal_session.set_print_action(print_action, **kwargs)
1260 __set_print_action = set_print_action
1261
1263 """\
1264 Find out if this X2Go session is still alive (that is: connected to the server).
1265
1266 @return: returns C{True} if the server connection is still alive
1267 @rtype: C{bool}
1268
1269 """
1270 self.connected = self.control_session.is_alive()
1271 if self.control_session.has_session_died():
1272 self.HOOK_on_control_session_death()
1273 if not self.connected:
1274 self._X2goSession__disconnect()
1275 return self.connected
1276 __is_alive = is_alive
1277
1278 - def clean_sessions(self, destroy_terminals=True, published_applications=False):
1279 """\
1280 Clean all running sessions for the authenticated user on the remote X2Go server.
1281
1282 @param destroy_terminals: destroy associated terminal sessions
1283 @type destroy_terminals: C{bool}
1284 @param published_applications: clean sessions that are published applications providers, too
1285 @type published_applications: C{bool}
1286
1287 """
1288 if self.is_alive():
1289
1290
1291 if self.has_terminal_session():
1292 self.unshare_all_local_folders(force_all=True)
1293
1294 self.control_session.clean_sessions(destroy_terminals=destroy_terminals, published_applications=published_applications)
1295 else:
1296 self._X2goSession__disconnect()
1297 __clean_sessions = clean_sessions
1298
1300 """\
1301 List all sessions on the remote X2Go server that are owned by the authenticated user
1302
1303 @param raw: if C{True} the output of this method equals
1304 the output of the server-side C{x2golistsessions} command
1305 @type raw: C{bool}
1306
1307 @return: a session list (as data object or list of strings when called with C{raw=True} option)
1308 @rtype: C{X2goServerSessionList*} instance or C{list}
1309
1310 """
1311 try:
1312 return self.control_session.list_sessions(raw=raw)
1313 except x2go_exceptions.X2goControlSessionException:
1314 self.HOOK_on_control_session_death()
1315 self._X2goSession__disconnect()
1316 return None
1317 __list_sessions = list_sessions
1318
1320 """\
1321 List X2Go desktops sessions available for desktop sharing on the remote X2Go server.
1322
1323 @param raw: if C{True} the output of this method equals
1324 the output of the server-side C{x2golistdesktops} command
1325 @type raw: C{bool}
1326
1327 @return: a list of strings representing available desktop sessions
1328 @rtype: C{list}
1329
1330 """
1331 try:
1332 return self.control_session.list_desktops(raw=raw)
1333 except x2go_exceptions.X2goControlSessionException:
1334 self.HOOK_on_control_session_death()
1335 self._X2goSession__disconnect()
1336 return None
1337 __list_desktops = list_desktops
1338
1340 """\
1341 Use the X2Go session registered under C{session_uuid} to
1342 retrieve its list of mounted client shares for that session.
1343
1344 @param raw: output the list of mounted client shares in X2go's
1345 raw C{x2golistmounts} format
1346 @type raw: C{bool}
1347
1348 @return: a list of strings representing mounted client shares for this session
1349 @rtype: C{list}
1350
1351 """
1352 try:
1353 return self.control_session.list_mounts(self.session_name, raw=raw)
1354 except x2go_exceptions.X2goControlSessionException:
1355 self.HOOK_on_control_session_death()
1356 self._X2goSession__disconnect()
1357 return None
1358 __list_mounts = list_mounts
1359
1360 - def update_status(self, session_list=None, force_update=False):
1361 """\
1362 Update the current session status. The L{X2goSession} instance uses an internal
1363 session status cache that allows to query the session status without the need
1364 of retrieving data from the remote X2Go server for each query.
1365
1366 The session status (if initialized properly with the L{X2goClient} constructor gets
1367 updated in regularly intervals.
1368
1369 In case you use the L{X2goSession} class in standalone instances (that is: without
1370 being embedded into an L{X2goSession} context) then run this method in regular
1371 intervals to make sure the L{X2goSession}'s internal status cache information
1372 is always up-to-date.
1373
1374 @param session_list: provide an C{X2goServerSessionList*} that refers to X2Go sessions we want to update.
1375 This option is mainly for reducing server/client traffic.
1376 @type session_list: C{X2goServerSessionList*} instance
1377 @param force_update: force a session status update, if if the last update is less then 1 second ago
1378 @type force_update: C{bool}
1379
1380 @raise Exception: any exception is passed through in case the session disconnected surprisingly
1381 or has been marked as faulty
1382
1383 """
1384 if not force_update and self._last_status is not None:
1385 _status_update_timedelta = time.time() - self._last_status['timestamp']
1386
1387
1388 if _status_update_timedelta < 1:
1389 self.logger('status update interval too short (%s), skipping status update this time...' % _status_update_timedelta, loglevel=log.loglevel_DEBUG)
1390 return False
1391
1392 e = None
1393 self._last_status = copy.deepcopy(self._current_status)
1394 if session_list is None:
1395 try:
1396 session_list = self.control_session.list_sessions()
1397 self.connected = True
1398 except x2go_exceptions.X2goControlSessionException, e:
1399 self.connected = False
1400 self.running = None
1401 self.suspended = None
1402 self.terminated = None
1403 self.faulty = None
1404
1405 if self.connected:
1406 try:
1407 _session_name = self.get_session_name()
1408 _session_info = session_list[_session_name]
1409 self.running = _session_info.is_running()
1410 self.suspended = _session_info.is_suspended()
1411 if not self.virgin:
1412 self.terminated = not (self.running or self.suspended)
1413 else:
1414 self.terminated = None
1415 except KeyError, e:
1416 self.running = False
1417 self.suspended = False
1418 if not self.virgin:
1419 self.terminated = True
1420 self.faulty = not (self.running or self.suspended or self.terminated or self.virgin)
1421
1422 self._current_status = {
1423 'timestamp': time.time(),
1424 'server': self.server,
1425 'virgin': self.virgin,
1426 'connected': self.connected,
1427 'running': self.running,
1428 'suspended': self.suspended,
1429 'terminated': self.terminated,
1430 'faulty': self.faulty,
1431 }
1432
1433 if (not self.connected or self.faulty) and e:
1434 raise e
1435
1436 return True
1437 __update_status = update_status
1438
1440 """\
1441 Returns true if this session runs in published applications mode.
1442
1443 @return: returns C{True} if this session is a provider session for published applications.
1444 @rtype: C{bool}
1445
1446 """
1447 if self.has_terminal_session() and self.is_running() :
1448 return self.terminal_session.is_published_applications_provider()
1449 return False
1450 __is_published_applications_provider = is_published_applications_provider
1451
1453 """\
1454 Returns true if this session is configured as desktop session.
1455
1456 @return: returns C{True} if this session is a desktop session.
1457 @rtype: C{bool}
1458
1459 """
1460 if self.has_terminal_session():
1461 return self.terminal_session.is_desktop_session()
1462 return False
1463 __is_desktop_session = is_desktop_session
1464
1466 """\
1467 Return a list of published menu items from the X2Go server
1468 for session type published applications.
1469
1470 @param lang: locale/language identifier
1471 @type lang: C{str}
1472 @param refresh: force reload of the menu tree from X2Go server
1473 @type refresh: C{bool}
1474 @param raw: retrieve a raw output of the server list of published applications
1475 @type raw: C{bool}
1476 @param very_raw: retrieve a very raw output of the server list of published applications (as-is output of x2gogetapps script)
1477 @type very_raw: C{bool}
1478
1479 @return: A C{list} of C{dict} elements. Each C{dict} elements has a
1480 C{desktop} key containing the text output of a .desktop file and
1481 an C{icon} key which contains the desktop icon data base64 encoded
1482 @rtype: C{list}
1483
1484 """
1485 if self.client_instance and hasattr(self.client_instance, 'lang'):
1486 lang = self.client_instance.lang
1487 return self.control_session.get_published_applications(lang=lang, refresh=refresh, raw=raw, very_raw=very_raw, max_no_submenus=max_no_submenus)
1488 __get_published_applications = get_published_applications
1489
1491 """\
1492 Execute an application while in published application mode.
1493
1494 @param exec_name: command to execute on server
1495 @type exec_name: C{str}
1496
1497 """
1498 if self.terminal_session is not None:
1499 self.logger('for %s executing published application: %s' % (self.profile_name, exec_name), loglevel=log.loglevel_NOTICE)
1500 self.terminal_session.exec_published_application(exec_name, timeout=timeout, env=self.session_environment)
1501 __exec_published_application = exec_published_application
1502
1503 - def do_auto_start_or_resume(self, newest=True, oldest=False, all_suspended=False, start=True, redirect_to_client=True):
1504 """\
1505 Automatically start or resume this session, if already associated with a server session. Otherwise
1506 resume a server-side available/suspended session (see options to declare which session to resume).
1507 If no session is available for resuming a new session will be launched.
1508
1509 Sessions in published applications mode are not resumed/started by this method.
1510
1511 @param newest: if resuming, only resume newest/youngest session
1512 @type newest: C{bool}
1513 @param oldest: if resuming, only resume oldest session
1514 @type oldest: C{bool}
1515 @param all_suspended: if resuming, resume all suspended sessions
1516 @type all_suspended: C{bool}
1517 @param start: is no session is to be resumed, start a new session
1518 @type start: C{bool}
1519 @param redirect_to_client: redirect this call to the L{X2goClient} instance (if available) to allow frontend interaction
1520 @type redirect_to_client: C{bool}
1521
1522 @return: returns success (or failure) of starting/resuming this sessions
1523 @rtype: C{bool}
1524
1525 """
1526 if self.client_instance and redirect_to_client:
1527 return self.client_instance.session_auto_start_or_resume(self())
1528 else:
1529 if self.session_name is not None and 'PUBLISHED' not in self.session_name:
1530 return self.resume()
1531 else:
1532 session_infos = self.list_sessions()
1533
1534
1535 for session_name in session_infos.keys():
1536 if session_infos[session_name].is_published_applications_provider():
1537 del session_infos[session_name]
1538
1539 if session_infos:
1540 if newest:
1541 return self.resume(session_name=utils.session_names_by_timestamp(session_infos)[-1])
1542 elif oldest:
1543 return self.resume(session_name=utils.session_names_by_timestamp(session_infos)[-1])
1544 elif all_suspended:
1545 for session_name in [ _sn for _sn in session_infos.keys() if session_infos[_sn].is_suspended() ]:
1546 return self.resume(session_name=session_name)
1547 else:
1548 if not self.published_applications:
1549 return self.start()
1550 __do_auto_start_or_resume = do_auto_start_or_resume
1551
1552 - def resume(self, session_name=None, session_list=None, cmd=None):
1553 """\
1554 Resume or continue a suspended / running X2Go session on the
1555 remote X2Go server.
1556
1557 @param session_name: the server-side name of an X2Go session
1558 @type session_name: C{str}
1559 @param session_list: a session list to avoid a server-side session list query
1560 @type session_list: C{dict}
1561 @param cmd: if starting a new session, manually hand over the command to be launched in
1562 the new session
1563 @type cmd: C{str}
1564
1565 @return: returns C{True} if resuming the session has been successful, C{False} otherwise
1566 @rtype: C{bool}
1567
1568 @raise Exception: any exception that occurs during published application menu retrieval is passed through
1569
1570 """
1571 self.terminal_session = 'PENDING'
1572 _new_session = False
1573 if self.session_name is None:
1574 self.session_name = session_name
1575
1576 if self.is_alive():
1577
1578 _control = self.control_session
1579
1580
1581
1582
1583
1584 if self.is_running():
1585 try:
1586 self.suspend()
1587 gevent.sleep(5)
1588 except x2go_exceptions.X2goSessionException:
1589 pass
1590
1591 try:
1592 if self.published_applications:
1593 self.published_applications_menu = gevent.spawn(self.get_published_applications)
1594 except:
1595
1596 raise
1597
1598 if cmd is not None:
1599 self.terminal_params['cmd'] = cmd
1600
1601 self.terminal_session = _control.resume(session_name=self.session_name,
1602 session_instance=self,
1603 session_list=session_list,
1604 logger=self.logger, **self.terminal_params)
1605
1606 if self.session_name is None:
1607 _new_session = True
1608 try:
1609 self.session_name = self.terminal_session.session_info.name
1610 except AttributeError:
1611
1612 self.HOOK_session_startup_failed()
1613 return False
1614
1615 if self.has_terminal_session() and not self.faulty:
1616
1617 self.terminal_session.session_info_protect()
1618
1619 if self.get_session_cmd() != 'PUBLISHED':
1620 self.published_applications = False
1621
1622 if self._SUPPORTED_SOUND and self.terminal_session.params.snd_system is not 'none':
1623 self.has_terminal_session() and not self.faulty and self.terminal_session.start_sound()
1624 else:
1625 self._SUPPORTED_SOUND = False
1626
1627 try:
1628 if (self._SUPPORTED_PRINTING and self.printing) or \
1629 (self._SUPPORTED_MIMEBOX and self.allow_mimebox) or \
1630 (self._SUPPORTED_FOLDERSHARING and self.allow_share_local_folders):
1631 self.has_terminal_session() and not self.faulty and self.terminal_session.start_sshfs()
1632 except x2go_exceptions.X2goUserException, e:
1633 self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
1634 self.HOOK_sshfs_not_available()
1635 self._SUPPORTED_PRINTING = False
1636 self._SUPPORTED_MIMEBOX = False
1637 self._SUPPORTED_FOLDERSHARING = False
1638
1639 if self._SUPPORTED_PRINTING and self.printing:
1640 try:
1641 self.has_terminal_session() and not self.faulty and gevent.spawn(self.terminal_session.start_printing)
1642 self.has_terminal_session() and not self.faulty and self.session_environment.update({'X2GO_SPOOLDIR': self.terminal_session.get_printing_spooldir(), })
1643 except x2go_exceptions.X2goUserException, e:
1644 self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
1645 self.HOOK_printing_not_available()
1646 self._SUPPORTED_PRINTING = False
1647
1648 if self._SUPPORTED_MIMEBOX and self.allow_mimebox:
1649 try:
1650 self.has_terminal_session() and not self.faulty and gevent.spawn(self.terminal_session.start_mimebox, mimebox_extensions=self.mimebox_extensions, mimebox_action=self.mimebox_action)
1651 self.has_terminal_session() and self.session_environment.update({'X2GO_MIMEBOX': self.terminal_session.get_mimebox_spooldir(), })
1652 except x2go_exceptions.X2goUserException, e:
1653 self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
1654 self.HOOK_mimebox_not_available()
1655 self._SUPPORTED_MIMEBOX = False
1656
1657
1658 if _new_session:
1659 self.has_terminal_session() and self.terminal_session.run_command(env=self.session_environment)
1660
1661 self.virgin = False
1662 self.suspended = False
1663 self.running = True
1664 self.terminated = False
1665 self.faulty = False
1666
1667
1668 if (not self.client_instance) and \
1669 self._SUPPORTED_FOLDERSHARING and \
1670 self.allow_share_local_folders:
1671 gevent.spawn(self.share_all_local_folders)
1672
1673 self.has_terminal_session() and self.terminal_session.session_info_unprotect()
1674 return True
1675
1676 else:
1677 self.terminal_session = None
1678 return False
1679
1680 return self.running
1681 else:
1682 self._X2goSession__disconnect()
1683 return False
1684
1685 __resume = resume
1686
1687 - def start(self, cmd=None):
1688 """\
1689 Start a new X2Go session on the remote X2Go server.
1690
1691 @param cmd: manually hand over the command that is to be launched in the new session
1692 @type cmd: C{str}
1693
1694 @return: returns C{True} if starting the session has been successful, C{False} otherwise
1695 @rtype: C{bool}
1696
1697 """
1698 self.session_name = None
1699 return self.resume(cmd=cmd)
1700 __start = start
1701
1702 - def share_desktop(self, desktop=None, user=None, display=None, share_mode=0, check_desktop_list=True):
1703 """\
1704 Share an already running X2Go session on the remote X2Go server locally. The shared session may be either
1705 owned by the same user or by a user that grants access to his/her desktop session by the local user.
1706
1707 @param desktop: desktop ID of a sharable desktop in format <user>@<display>
1708 @type desktop: C{str}
1709 @param user: user name and display number can be given separately, here give the
1710 name of the user who wants to share a session with you.
1711 @type user: C{str}
1712 @param display: user name and display number can be given separately, here give the
1713 number of the display that a user allows you to be shared with.
1714 @type display: C{str}
1715 @param share_mode: desktop sharing mode, 0 is VIEW-ONLY, 1 is FULL-ACCESS.
1716 @type share_mode: C{int}
1717 @param check_desktop_list: check if the given desktop is available on the X2Go server; handle with care as
1718 the server-side C{x2golistdesktops} command might block client I/O.
1719 @type check_desktop_list: C{bool}
1720
1721 @return: returns C{True} if starting the session has been successful, C{False} otherwise
1722 @rtype: C{bool}
1723
1724 @raise X2goDesktopSharingException: if the given desktop ID is not an available desktop session on the remote server
1725 @raise X2goSessionException: if the available desktop session appears to be dead, in fact
1726
1727 """
1728 self.terminal_session = 'PENDING'
1729
1730 _desktop = desktop or '%s@%s' % (user, display)
1731 if check_desktop_list:
1732 if not _desktop in self._X2goSession__list_desktops():
1733 _orig_desktop = _desktop
1734 _desktop = '%s.0' % _desktop
1735 if not _desktop in self._X2goSession__list_desktops():
1736 raise x2go_exceptions.X2goDesktopSharingException('No such desktop ID: %s' % _orig_desktop)
1737
1738 _session_owner = _desktop.split('@')[0]
1739
1740
1741 if self.is_alive():
1742 if self.get_username() != _session_owner:
1743 self.logger('waiting for user ,,%s\'\' to interactively grant you access to his/her desktop session...' % _session_owner, loglevel=log.loglevel_NOTICE)
1744 self.logger('THIS MAY TAKE A WHILE!', loglevel=log.loglevel_NOTICE)
1745
1746 _control = self.control_session
1747 try:
1748 self.terminal_session = _control.share_desktop(desktop=_desktop, share_mode=share_mode,
1749 logger=self.logger, **self.terminal_params)
1750 except ValueError:
1751
1752
1753 raise x2go_exceptions.X2goSessionException('the session on desktop %s is seemingly dead' % _desktop)
1754
1755 if self.has_terminal_session():
1756 self.session_name = self.terminal_session.session_info.name
1757
1758
1759
1760 self.terminal_session.run_command(env=self.session_environment)
1761
1762 self.virgin = False
1763 self.suspended = False
1764 self.running = True
1765 self.terminated = False
1766 self.faulty = False
1767
1768 return self.running
1769 else:
1770 self.terminal_session = None
1771
1772 else:
1773 self._X2goSession__disconnect()
1774
1775 return False
1776 __share_desktop = share_desktop
1777
1779 """\
1780 Suspend this X2Go session.
1781
1782 @return: returns C{True} if suspending the session has been successful, C{False} otherwise
1783 @rtype: C{bool}
1784
1785 @raise X2goSessionException: if the session could not be suspended
1786
1787 """
1788 if self.is_alive():
1789 if self.has_terminal_session():
1790
1791 self.running = False
1792 self.suspended = True
1793 self.terminated = False
1794 self.faulty = False
1795 self.active = False
1796
1797
1798 self.unshare_all_local_folders(force_all=True)
1799
1800 self.unset_master_session()
1801
1802 if self.terminal_session.suspend():
1803
1804 self.session_cleanup()
1805 del self.terminal_session
1806 self.terminal_session = None
1807 return True
1808
1809 elif self.has_control_session() and self.session_name:
1810 if self.control_session.suspend(session_name=self.session_name):
1811
1812 self.running = False
1813 self.suspended = True
1814 self.terminated = False
1815 self.faulty = False
1816 self.active = False
1817 self.session_cleanup()
1818 return True
1819
1820 else:
1821 raise x2go_exceptions.X2goSessionException('cannot suspend session')
1822
1823 else:
1824 self._X2goSession__disconnect()
1825
1826 return False
1827 __suspend = suspend
1828
1830 """\
1831 Terminate this X2Go session.
1832
1833 @return: returns C{True} if terminating the session has been successful, C{False} otherwise
1834 @rtype: C{bool}
1835
1836 @raise X2goSessionException: if the session could not be terminated
1837
1838 """
1839 if self.is_alive():
1840 if self.has_terminal_session():
1841
1842 self.running = False
1843 self.suspended = False
1844 self.terminated = True
1845 self.faulty = False
1846 self.active = False
1847
1848
1849 self.unshare_all_local_folders(force_all=True)
1850
1851 self.unset_master_session()
1852
1853 if self.terminal_session.terminate():
1854 self.session_cleanup()
1855 del self.terminal_session
1856 self.terminal_session = None
1857 return True
1858
1859 elif self.has_control_session() and self.session_name:
1860 if self.control_session.terminate(session_name=self.session_name):
1861
1862 self.running = False
1863 self.suspended = False
1864 self.terminated = True
1865 self.faulty = False
1866 self.active = False
1867 self.session_cleanup()
1868 return True
1869 else:
1870 raise x2go_exceptions.X2goSessionException('cannot terminate session')
1871
1872 else:
1873 self._X2goSession__disconnect()
1874
1875 return False
1876 __terminate = terminate
1877
1879 """\
1880 Retrieve the profile name of this L{X2goSession} instance.
1881
1882 @return: X2Go client profile name of the session
1883 @rtype: C{str}
1884
1885 """
1886 return self.profile_name
1887 __get_profile_name = get_profile_name
1888
1890 """\
1891 Retrieve the profile ID of this L{X2goSession} instance.
1892
1893 @return: the session profile's id
1894 @rtype: C{str}
1895
1896 """
1897 return self.profile_id
1898 __get_profile_id = get_profile_id
1899
1900
1901
1902
1903
1905 """\
1906 Test if this C{X2goSession} is
1907 in a healthy state.
1908
1909 @return: C{True} if session is ok, C{False} otherwise
1910 @rtype: C{bool}
1911
1912 """
1913 if self.has_terminal_session():
1914 return self.terminal_session.ok()
1915 return False
1916 __session_ok = session_ok
1917
1919 """\
1920 Extract color depth from session name.
1921
1922 @return: the session's color depth (as found in the session name)
1923 @rtype: C{str}
1924
1925 """
1926 return int(self.get_session_name().split('_')[2][2:])
1927 __color_depth_from_session_name = color_depth_from_session_name
1928
1930 """\
1931 Check if this session will display properly with the local screen's color depth.
1932
1933 @return: C{True} if the session will display on this client screen,
1934 C{False} otherwise. If no terminal session is yet registered with this session, C{None} is returned.
1935 @rtype: C{bool}
1936
1937 """
1938 return utils.is_color_depth_ok(depth_session=self.color_depth_from_session_name(), depth_local=utils.local_color_depth())
1939 __is_color_depth_ok = is_color_depth_ok
1940
1942 """\
1943 Test if the L{X2goSession}'s control session is connected to the
1944 remote X2Go server.
1945
1946 @return: C{True} if session is connected, C{False} otherwise
1947 @rtype: C{bool}
1948
1949 """
1950 self.connected = bool(self.control_session and self.control_session.is_connected())
1951 if not self.connected:
1952 self.running = None
1953 self.suspended = None
1954 self.terminated = None
1955 self.faulty = None
1956 return self.connected
1957 __is_connected = is_connected
1958
1960 """\
1961 Test if the L{X2goSession}'s terminal session is up and running.
1962
1963 @return: C{True} if session is running, C{False} otherwise
1964 @rtype: C{bool}
1965
1966 """
1967 if not update_status:
1968 return self.running
1969
1970 if self.is_connected():
1971 self.running = self.control_session.is_running(self.get_session_name())
1972 if self.running:
1973 self.suspended = False
1974 self.terminated = False
1975 self.faulty = False
1976 if self.virgin and not self.running:
1977 self.running = None
1978 return self.running
1979 __is_running = is_running
1980
1982 """\
1983 Test if the L{X2goSession}'s terminal session is in suspended state.
1984
1985 @return: C{True} if session is suspended, C{False} otherwise
1986 @rtype: C{bool}
1987
1988 """
1989 if not update_status:
1990 return self.suspended
1991
1992 if self.is_connected():
1993 self.suspended = self.control_session.is_suspended(self.get_session_name())
1994 if self.suspended:
1995 self.running = False
1996 self.terminated = False
1997 self.faulty = False
1998 if self.virgin and not self.suspended:
1999 self.suspended = None
2000 return self.suspended
2001 __is_suspended = is_suspended
2002
2004 """\
2005 Test if the L{X2goSession}'s terminal session has terminated.
2006
2007 @return: C{True} if session has terminated, C{False} otherwise
2008 @rtype: C{bool}
2009
2010 """
2011 if not update_status:
2012 return self.terminated
2013
2014 if self.is_connected():
2015 self.terminated = not self.virgin and self.control_session.has_terminated(self.get_session_name())
2016 if self.terminated:
2017 self.running = False
2018 self.suspended = False
2019 self.faulty = False
2020 if self.virgin and not self.terminated:
2021 self.terminated = None
2022 return self.terminated
2023 __has_terminated = has_terminated
2024
2026 """\
2027 Test if the remote session allows sharing of local folders with the session.
2028
2029 @return: returns C{True} if local folder sharing is available in the remote session
2030 @rtype: C{bool}
2031
2032 """
2033 if self._SUPPORTED_FOLDERSHARING and self.allow_share_local_folders:
2034 if self.is_connected():
2035 return self.control_session.is_sshfs_available()
2036 else:
2037 self.logger('session is not connected, cannot share local folders now', loglevel=log.loglevel_WARN)
2038 else:
2039 self.logger('local folder sharing is disabled for this session profile', loglevel=log.loglevel_WARN)
2040 return False
2041 __is_folder_sharing_available = is_folder_sharing_available
2042
2044 """\
2045 Share a local folder with this registered X2Go session.
2046
2047 @param local_path: the full path to an existing folder on the local
2048 file system
2049 @type local_path: C{str}
2050 @param folder_name: synonymous to C{local_path}
2051 @type folder_name: C{str}
2052
2053 @return: returns C{True} if the local folder has been successfully mounted within
2054 this X2Go session
2055 @rtype: C{bool}
2056
2057 @raise X2goSessionException: if this L{X2goSession} does not have an associated terminal session
2058
2059 """
2060
2061 if folder_name: local_path=folder_name
2062
2063 if self.has_terminal_session():
2064 if self.is_folder_sharing_available() and self.is_master_session():
2065 if self.terminal_session.share_local_folder(local_path=local_path):
2066 self.shared_folders.append(local_path)
2067 return True
2068 return False
2069 else:
2070 raise x2go_exceptions.X2goSessionException('this X2goSession object does not have any associated terminal')
2071 __share_local_folder = share_local_folder
2072
2074 """\
2075 Share all local folders configured to be mounted within this X2Go session.
2076
2077 @return: returns C{True} if all local folders could be successfully mounted
2078 inside this X2Go session
2079 @rtype: C{bool}
2080
2081 """
2082 _retval = False
2083 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():
2084 if self.is_master_session():
2085 if self.is_folder_sharing_available():
2086 if self.control_session.get_transport().reverse_tunnels[self.terminal_session.get_session_name()]['sshfs'][1] is not None:
2087 _retval = True
2088 for _folder in self.share_local_folders:
2089 try:
2090 _retval = self.share_local_folder(_folder) and _retval
2091 except x2go_exceptions.X2goUserException, e:
2092 self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
2093 else:
2094 self.HOOK_foldersharing_not_available()
2095 return _retval
2096 __share_all_local_folders = share_all_local_folders
2097
2099 """\
2100 Unshare all local folders mounted within this X2Go session.
2101
2102 @param force_all: Really unmount _all_ shared folders, including the print spool folder and
2103 the MIME box spool dir (not recommended).
2104 @type force_all: C{bool}
2105
2106 @return: returns C{True} if all local folders could be successfully unmounted
2107 inside this X2Go session
2108 @rtype: C{bool}
2109
2110 @raise X2goSessionException: if this L{X2goSession} does not have an associated terminal session
2111
2112 """
2113 if self.has_terminal_session():
2114 if self.is_folder_sharing_available() and self.is_master_session():
2115 if force_all:
2116 self.shared_folders = []
2117 return self.terminal_session.unshare_all_local_folders()
2118 else:
2119 retval = 0
2120 for _shared_folder in self.shared_folders:
2121 retval = retval | self.terminal_session.unshare_local_folder(_shared_folder)
2122 self.shared_folders = []
2123 return retval
2124 else:
2125 raise x2go_exceptions.X2goSessionException('this X2goSession object does not have any associated terminal')
2126 return False
2127 __unshare_all_local_folders = unshare_all_local_folders
2128
2130 """\
2131 Unshare a local folder that is mounted within this X2Go session.
2132
2133 @param local_path: the full path to an existing folder on the local
2134 file system that is mounted in this X2Go session and shall be
2135 unmounted
2136 @type local_path: C{str}
2137 @return: returns C{True} if all local folders could be successfully unmounted
2138 inside this X2Go session
2139 @rtype: C{bool}
2140
2141 @raise X2goSessionException: if this L{X2goSession} does not have an associated terminal session
2142
2143 """
2144 if self.has_terminal_session():
2145 if self.is_folder_sharing_available() and self.is_master_session() and local_path in self.shared_folders:
2146 self.shared_folders.remove(local_path)
2147 return self.terminal_session.unshare_local_folder(local_path=local_path)
2148 else:
2149 raise x2go_exceptions.X2goSessionException('this X2goSession object does not have any associated terminal')
2150 __unshare_local_folder = unshare_local_folder
2151
2153 """\
2154 Get a list of local folders mounted within this X2Go session from this client.
2155
2156 @param check_list_mounts: if set to C{True} the list of shared folders is referenced against
2157 the latest status of the server-side mount list.
2158 @type check_list_mounts: C{bool}
2159 @param mounts: a server-side dictionary of session name keys and lists of mounted shares (server-side mount points)
2160 @type mounts: C{dict}
2161
2162 @return: returns a C{list} of those local folder names that are mounted with this X2Go session.
2163 @rtype: C{list}
2164
2165 """
2166 if self.is_folder_sharing_available and self.is_master_session() and self.shared_folders and check_list_mounts:
2167
2168 unshared_folders = []
2169 if mounts is None:
2170 mounts = self.list_mounts()
2171
2172 for shared_folder in self.shared_folders:
2173
2174 _found = False
2175
2176 for mount in mounts:
2177 mount = mount.split('|')[1]
2178 if _X2GOCLIENT_OS == 'Windows':
2179 _driveletter, _path = os.path.splitdrive(shared_folder)
2180 _mount_point = '_windrive_%s%s' % (_driveletter[0], _path.replace('\\', '_'))
2181 _mount_point = _mount_point.replace(' ', '_')
2182
2183 if mount.lower().endswith(_mount_point.lower()):
2184 _found = True
2185 break
2186 else:
2187 _mount_point = shared_folder.replace('/', '_')
2188 _mount_point = _mount_point.replace(' ', '_')
2189 if mount.endswith(_mount_point):
2190 _found = True
2191 break
2192
2193 if not _found:
2194 unshared_folders.append(shared_folder)
2195
2196 for unshared_folder in unshared_folders:
2197 try:
2198 self.shared_folders.remove(unshared_folder)
2199 self.logger('Detected server-side unsharing of client-side folder for profile %s: %s:' % (self.get_profile_name(), shared_folder), loglevel=log.loglevel_INFO)
2200 except IndexError:
2201 pass
2202
2203 return self.shared_folders
2204 __get_shared_folders = get_shared_folders
2205
2207 """\
2208 Query session if it is locked by some command being processed.
2209
2210 @return: returns C{True} is the session is locked, C{False} if not; returns C{None}, if there is no
2211 control session yet.
2212 @rtype: C{bool}
2213
2214 """
2215 if self.control_session is not None:
2216 return self.control_session.locked or self.locked
2217 return None
2218 __is_locked = is_locked
2219
2238 __session_cleanup = session_cleanup
2239