[X2Go-Commits] python-x2go.git - release/0.4.0.x (branch) updated: 0.1.1.4-130-g0eff893
X2Go dev team
git-admin at x2go.org
Tue Jan 7 16:17:42 CET 2014
The branch, release/0.4.0.x has been updated
via 0eff893ffaa6c3358e4ca2184bebe5b471d529f0 (commit)
from f2e8361dc164f7ae5215745fe7d56ac9cf25fca0 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
-----------------------------------------------------------------------
Summary of changes:
debian/changelog | 1 +
x2go/backends/control/_stdout.py | 43 +++++++++++++++-
x2go/backends/info/_stdout.py | 5 ++
x2go/backends/terminal/_stdout.py | 103 ++++++++++++++++++++++++++++++-------
x2go/client.py | 56 +++++++++++++++++++-
x2go/defaults.py | 3 +-
x2go/registry.py | 35 ++++++++++++-
x2go/session.py | 94 ++++++++++++++++++++++++++++++---
x2go/utils.py | 10 ++--
9 files changed, 313 insertions(+), 37 deletions(-)
The diff of changes is:
diff --git a/debian/changelog b/debian/changelog
index 65571f2..8097dc9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -39,6 +39,7 @@ python-x2go (0.1.2.0-0~x2go1) UNRELEASED; urgency=low
- Amend list of default session options.
- Update list of unsupported session options.
- Retrieve feature list from X2Go server per session.
+ - Add published applications support.
* Depend on python-xlib.
-- Mike Gabriel <mike.gabriel at das-netzwerkteam.de> Sat, 28 Sep 2012 01:44:21 +0100
diff --git a/x2go/backends/control/_stdout.py b/x2go/backends/control/_stdout.py
index fc345d9..6b3dd1f 100644
--- a/x2go/backends/control/_stdout.py
+++ b/x2go/backends/control/_stdout.py
@@ -141,6 +141,8 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
self.sessions_rootdir = sessions_rootdir
self.ssh_rootdir = ssh_rootdir
+ self._published_applications_menu = None
+
paramiko.SSHClient.__init__(self, *args, **kwargs)
if self.add_to_known_hosts:
self.set_missing_host_key_policy(paramiko.AutoAddPolicy())
@@ -591,6 +593,39 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
return True
return False
+ def get_published_applications(self):
+ """\
+ Retrieve the menu tree of published applications from X2Go server.
+
+ """
+ if 'X2GO_PUBLISHED_APPLICATIONS' in self._x2go_server_features:
+ if self._published_applications_menu is None:
+ self.logger('querying server (%s) for list of published applications' % self.profile_name, loglevel=log.loglevel_NOTICE)
+ (stdin, stdout, stderr) = self._x2go_exec_command('which x2gogetapps >/dev/null && x2gogetapps')
+ _raw_menu_items = stdout.read().split('</desktop>\n')
+ _raw_menu_items = [ i.replace('<desktop>\n', '') for i in _raw_menu_items ]
+ _menu = []
+ for _raw_menu_item in _raw_menu_items:
+ if '<icon>\n' in _raw_menu_item and '</icon>' in _raw_menu_item:
+ _menu_item = _raw_menu_item.split('<icon>\n')[0] + _raw_menu_item.split('</icon>\n')[1]
+ _icon_base64 = _raw_menu_item.split('<icon>\n')[1].split('</icon>\n')[0].replace('\n', '')
+ else:
+ _menu_item = _raw_menu_item
+ _icon_base64 = None
+ if _menu_item:
+ _menu.append({ 'desktop': _menu_item, 'icon': _icon_base64, })
+ _menu_item = None
+ _icon_base64 = None
+
+ self._published_applications_menu = _menu
+ self.logger('published applications query for %s finished' % self.profile_name, loglevel=log.loglevel_NOTICE)
+ return self._published_applications_menu
+ else:
+ return self._published_applications_menu
+ else:
+ # FIXME: ignoring the absence of the published applications feature for now, handle it appropriately later
+ pass
+
def start(self, **kwargs):
"""\
Start a new X2Go session.
@@ -826,14 +861,18 @@ class X2goControlSessionSTDOUT(paramiko.SSHClient):
return _listsessions
- def clean_sessions(self, destroy_terminals=True):
+ def clean_sessions(self, destroy_terminals=True, published_applications=False):
"""\
Find X2Go terminals that have previously been started by the
connected user on the remote X2Go server and terminate them.
"""
session_list = self.list_sessions()
- for session_name in session_list.keys():
+ if published_applications:
+ session_names = session_list.keys()
+ else:
+ session_names = [ _sn for _sn in session_list.keys() if not session_list[_sn].is_published_applications_provider() ]
+ for session_name in session_names:
self.terminate(session_name=session_name, destroy_terminals=destroy_terminals)
def is_connected(self):
diff --git a/x2go/backends/info/_stdout.py b/x2go/backends/info/_stdout.py
index ae6046c..c316ec7 100644
--- a/x2go/backends/info/_stdout.py
+++ b/x2go/backends/info/_stdout.py
@@ -30,6 +30,7 @@ __NAME__ = 'x2goserversessioninfo-pylib'
# modules
import types
+import re
class X2goServerSessionInfoSTDOUT(object):
@@ -83,6 +84,10 @@ class X2goServerSessionInfoSTDOUT(object):
print x2go_output
raise e
+ def is_published_applications_provider(self):
+
+ return re.match('.*_stRPUBLISHED_.*', self.name)
+
def is_running(self):
return self.status == 'R'
diff --git a/x2go/backends/terminal/_stdout.py b/x2go/backends/terminal/_stdout.py
index 5179bdc..aee28b0 100644
--- a/x2go/backends/terminal/_stdout.py
+++ b/x2go/backends/terminal/_stdout.py
@@ -77,6 +77,10 @@ def _rewrite_cmd(cmd, params=None):
# place quot marks around cmd if not empty string
if cmd:
cmd = '"%s"' % cmd
+
+ if ((type(params) == X2goSessionParams) and params.published_applications and cmd == ''):
+ cmd = 'PUBLISHED'
+
return cmd
@@ -108,24 +112,33 @@ class X2goSessionParams(object):
"""
cmd = self.cmd
+ published = self.published_applications
- if cmd == 'RDP':
- self.session_type = 'R'
- elif cmd.startswith('rdesktop'):
- self.session_type = 'R'
- elif cmd == 'XDMCP':
- self.session_type = 'D'
- elif cmd in defaults.X2GO_DESKTOPSESSIONS.keys():
- self.session_type = 'D'
- elif os.path.basename(cmd) in defaults.X2GO_DESKTOPSESSIONS.values():
- self.session_type = 'D'
- elif self.session_type not in ("S", "shared", "shadow"):
- self.session_type = 'R'
+ if published and self.cmd in ('', 'PUBLISHED'):
+ self.session_type = 'P'
+ self.cmd = 'PUBLISHED'
+ else:
+ if cmd == 'RDP':
+ self.session_type = 'R'
+ elif cmd.startswith('rdesktop'):
+ self.session_type = 'R'
+ elif cmd == 'XDMCP':
+ self.session_type = 'D'
+ elif cmd in defaults.X2GO_DESKTOPSESSIONS.keys():
+ self.session_type = 'D'
+ elif os.path.basename(cmd) in defaults.X2GO_DESKTOPSESSIONS.values():
+ self.session_type = 'D'
+ elif self.session_type not in ("S", "shared", "shadow"):
+ self.session_type = 'R'
if self.session_type in ("D", "desktop"):
self.session_type = 'D'
elif self.session_type in ("S", "shared", "shadow"):
self.session_type = 'S'
+ elif self.session_type in ("R", "rootless"):
+ self.session_type = 'R'
+ elif self.session_type in ("P", "published", "published_applications"):
+ self.session_type = 'P'
def update(self, properties_to_be_updated={}):
"""\
@@ -174,6 +187,7 @@ class X2goTerminalSessionSTDOUT(object):
cache_type="unix-kde",
keyboard='', kblayout='null', kbtype='null/null',
session_type="application", snd_system='pulse', snd_port=4713, cmd=None,
+ published_applications=False,
set_session_title=False, session_title="", applications=[],
rdp_server=None, rdp_options=None,
xdmcp_server=None,
@@ -280,6 +294,9 @@ class X2goTerminalSessionSTDOUT(object):
self.params.cmd = str(cmd)
self.params.depth = str(depth)
+ self.params.published_applications = published_applications
+ self.published_applications = published_applications
+
self.params.rdp_server = str(rdp_server)
self.params.rdp_options = str(rdp_options)
self.params.xdmcp_server = str(xdmcp_server)
@@ -375,6 +392,13 @@ class X2goTerminalSessionSTDOUT(object):
"""
return self.session_info.name
+ def get_session_cmd(self):
+ """\
+ STILL UNDOCUMENTED
+
+ """
+ return self.params.cmd
+
def start_sound(self):
"""\
Initialize Paramiko/SSH reverse forwarding tunnel for X2Go sound.
@@ -870,6 +894,8 @@ class X2goTerminalSessionSTDOUT(object):
return True
elif 'XSHAD' in cmd:
return True
+ elif 'PUBLISHED' in cmd and 'X2GO_PUBLISHED_APPLICATIONS' in self.control_session.get_server_features():
+ return True
elif cmd and cmd.startswith('/'):
# check if full path is correct _and_ if application is in server path
test_cmd = 'test -x %s && which %s && echo OK' % (cmd, os.path.basename(cmd.split()[0]))
@@ -900,7 +926,7 @@ class X2goTerminalSessionSTDOUT(object):
@rtype: tuple of str
"""
- if not self.has_command(_rewrite_cmd(self.params.cmd)):
+ if not self.has_command(_rewrite_cmd(self.params.cmd, params=self.params)):
if self.client_instance:
self.client_instance.HOOK_no_such_command(profile_name=self.profile_name, session_name=self.session_info.name, cmd=self.params.cmd)
return False
@@ -947,6 +973,32 @@ class X2goTerminalSessionSTDOUT(object):
return stdout.read(), stderr.read()
+ def is_published_applications_provider(self):
+ """\
+ Returns true if this session runs in published applications mode.
+
+ @return: Returns C{True} is this session is a provider session for published applications.
+ @rtype: C{bool}
+
+ """
+ if self.session_info and self.is_running():
+ return self.session_info.is_published_applications_provider()
+ return False
+
+ def exec_published_application(self, exec_name):
+ """\
+ Executed a published application.
+
+ @param exec_name: application to be executed
+ @type exec_name: C{str}
+ """
+ cmd_line = [ "export DISPLAY=:%s && " % str(self.session_info.display),
+ "setsid %s" % exec_name,
+ "&> /dev/null & exit",
+ ]
+ self.logger('executing published application %s for %s with command line: %s' % (exec_name, self.profile_name, cmd_line), loglevel=log.loglevel_NOTICE)
+ (stdin, stdout, stderr) = self.control_session._x2go_exec_command(cmd_line)
+
def ok(self):
"""\
Returns C{True} if this X2Go session is up and running,
@@ -999,7 +1051,9 @@ class X2goTerminalSessionSTDOUT(object):
that can be passed to the class constructor.
"""
- if not self.has_command(_rewrite_cmd(self.params.cmd)):
+ self.params.rewrite_session_type()
+
+ if not self.has_command(_rewrite_cmd(self.params.cmd, params=self.params)):
if self.client_instance:
self.client_instance.HOOK_no_such_command(profile_name=self.profile_name, session_name=self.session_info.name, cmd=self.params.cmd)
return False
@@ -1069,9 +1123,13 @@ class X2goTerminalSessionSTDOUT(object):
self.proxy_subprocess = self.proxy.start_proxy()
self.active_threads.append(self.proxy)
- self.find_session_window()
- self.auto_session_window_title()
- #self.raise_session_window()
+ if self.params.session_type in ('D', 'S'):
+ self.find_session_window()
+ self.auto_session_window_title()
+ #self.raise_session_window()
+
+ if self.params.published_applications:
+ self.control_session.get_published_applications()
return self.ok()
@@ -1145,9 +1203,14 @@ class X2goTerminalSessionSTDOUT(object):
# on a session resume the user name comes in as a user ID. We have to translate this...
self.session_info.username = self.control_session.remote_username()
- self.find_session_window()
- self.auto_session_window_title()
- #self.raise_session_window()
+ if self.params.session_type in ('D', 'S'):
+ self.find_session_window()
+ self.auto_session_window_title()
+ #self.raise_session_window()
+
+ if self.is_published_applications_provider():
+ self.control_session.get_published_applications()
+ self.published_applications = True
return self.ok()
diff --git a/x2go/client.py b/x2go/client.py
index 4adfb01..4ff1e26 100644
--- a/x2go/client.py
+++ b/x2go/client.py
@@ -1991,6 +1991,55 @@ class X2goClient(object):
return self.session_registry.associated_sessions_of_profile_name(profile_name, return_objects=return_objects, return_session_names=return_session_names)
__client_associated_sessions_of_profile_name = client_associated_sessions_of_profile_name
+ def client_pubapp_sessions_of_profile_name(self, profile_name, return_objects=False, return_session_names=False):
+ """\
+ Retrieve X2Go sessions of profile name <profile_name> that provide published applications .
+
+ @param profile_name: profile name
+ @type profile_name: C{str}
+ @param return_objects: return as list of X2Go session objects
+ @type return_objects: C{bool}
+ @param return_session_names: return as list of session names
+ @type return_session_names: C{bool}
+ @return: list of application publishing sessions of profile name
+ @rtype: C{list}
+ """
+ return self.session_registry.pubapp_sessions_of_profile_name(profile_name, return_objects=return_objects, return_session_names=return_session_names)
+ __client_pubapp_sessions_of_profile_name = client_pubapp_sessions_of_profile_name
+
+
+ def client_running_sessions_of_profile_name(self, profile_name, return_objects=False, return_session_names=False):
+ """\
+ Retrieve running X2Go sessions of profile name <profile_name>.
+
+ @param profile_name: profile name
+ @type profile_name: C{str}
+ @param return_objects: return as list of X2Go session objects
+ @type return_objects: C{bool}
+ @param return_session_names: return as list of session names
+ @type return_session_names: C{bool}
+ @return: list of running sessions of profile name
+ @rtype: C{list}
+ """
+ return self.session_registry.running_sessions_of_profile_name(profile_name, return_objects=return_objects, return_session_names=return_session_names)
+ __client_running_sessions_of_profile_name = client_running_sessions_of_profile_name
+
+ def client_suspended_sessions_of_profile_name(self, profile_name, return_objects=False, return_session_names=False):
+ """\
+ Retrieve suspended X2Go sessions of profile name <profile_name>.
+
+ @param profile_name: profile name
+ @type profile_name: C{str}
+ @param return_objects: return as list of X2Go session objects
+ @type return_objects: C{bool}
+ @param return_session_names: return as list of session names
+ @type return_session_names: C{bool}
+ @return: list of suspended sessions of profile name
+ @rtype: C{list}
+ """
+ return self.session_registry.suspended_sessions_of_profile_name(profile_name, return_objects=return_objects, return_session_names=return_session_names)
+ __client_suspended_sessions_of_profile_name = client_suspended_sessions_of_profile_name
+
###
### Provide access to the X2Go server's sessions DB
###
@@ -2131,7 +2180,7 @@ class X2goClient(object):
### CLIENT OPERATIONS ON SESSIONS (listing sessions, terminating non-associated sessions etc.)
###
- def clean_sessions(self, session_uuid):
+ def clean_sessions(self, session_uuid, published_applications=None):
"""\
Find running X2Go sessions that have previously been started by the
connected user on the remote X2Go server and terminate them.
@@ -2147,7 +2196,10 @@ class X2goClient(object):
"""
_destroy_terminals = not ( self.auto_update_sessionregistry == True)
session = self.session_registry(session_uuid)
- session.clean_sessions(destroy_terminals=_destroy_terminals)
+ profile_name = session.get_profile_name()
+ if published_applications is None:
+ published_applications = self.session_profiles.get_profile_config(profile_name)['published']
+ session.clean_sessions(destroy_terminals=_destroy_terminals, published_applications=published_applications)
__clean_sessions = clean_sessions
def list_sessions(self, session_uuid=None,
diff --git a/x2go/defaults.py b/x2go/defaults.py
index 57e30a3..ce9190f 100644
--- a/x2go/defaults.py
+++ b/x2go/defaults.py
@@ -283,7 +283,7 @@ X2GO_SESSIONPROFILE_DEFAULTS = {
'sound': False, 'soundsystem': 'pulse', 'startsoundsystem': False, 'soundtunnel':True, 'defsndport':True, 'sndport':4713,
'name': 'NEW_PROFILE', 'icon': ':icons/128x128/x2gosession.png',
'host': '', 'user': CURRENT_LOCAL_USER, 'key': '', 'sshport': 22, 'krblogin': False,
- 'rootless': True, 'applications': X2GO_GENERIC_APPLICATIONS, 'command':'TERMINAL',
+ 'rootless': True, 'applications': X2GO_GENERIC_APPLICATIONS, 'command':'TERMINAL', 'published': False,
'rdpoptions': '-u X2GO_USER -p X2GO_PASSWORD', 'rdpserver': '',
'print': False,
'xdmcpserver': 'localhost',
@@ -406,3 +406,4 @@ X2GO_MIMEBOX_EXTENSIONS_BLACKLIST = [
# X2Go desktop sharing
X2GO_SHARE_VIEWONLY=0
X2GO_SHARE_FULLACCESS=1
+
diff --git a/x2go/registry.py b/x2go/registry.py
index 4fe08a0..0d06a03 100644
--- a/x2go/registry.py
+++ b/x2go/registry.py
@@ -283,6 +283,11 @@ class X2goSessionRegistry(object):
self.master_sessions[_profile_name] = self(_session_uuid)
self(_session_uuid).set_master_session()
+ elif self(_session_uuid).published_applications:
+ self(self.master_sessions[_profile_name]()).unset_master_session()
+ self.master_sessions[_profile_name] = self(_session_uuid)
+ self(_session_uuid).set_master_session()
+
if _last_status['suspended']:
# from a suspended state
self.client_instance.HOOK_on_session_has_resumed_by_me(session_uuid=_session_uuid, profile_name=_profile_name, session_name=_session_name)
@@ -327,9 +332,13 @@ class X2goSessionRegistry(object):
if len(self.virgin_sessions_of_profile_name(profile_name)) > 1:
self.forget(_session_uuid)
- for _profile_name in self.connected_profiles(return_profile_names=True):
+ for _profile_name in [ p for p in self.connected_profiles(return_profile_names=True) if p not in self.master_sessions.keys() ]:
_running_sessions = self.running_sessions_of_profile_name(_profile_name)
- if _profile_name not in self.master_sessions.keys() and _running_sessions:
+ _pubapp_sessions = [ _s for _s in self.pubapp_sessions_of_profile_name(_profile_name) if _s in _running_sessions ]
+ if _pubapp_sessions:
+ self.master_sessions[_profile_name] = _pubapp_sessions[0]
+ _pubapp_sessions[0].set_master_session()
+ elif _running_sessions:
self.master_sessions[_profile_name] = _running_sessions[0]
_running_sessions[0].set_master_session()
@@ -805,6 +814,28 @@ class X2goSessionRegistry(object):
else:
return self.associated_sessions() and [ s.get_uuid() for s in self.associated_sessions() if s.profile_name == profile_name ]
+ def pubapp_sessions_of_profile_name(self, profile_name, return_objects=True, return_session_names=False):
+ """\
+ For a given session profile name retrieve a list of sessions that can be providers for published application list.
+ If none of the C{return_*} options is specified a list of session UUID hashes will be returned.
+
+ @param profile_name: session profile name
+ @type profile_name: C{str}
+ @param return_objects: return as list of L{X2goSession} instances
+ @type return_objects: C{bool}
+ @param return_session_names: return as list of X2Go session names
+ @type return_session_names: C{bool}
+ @return: a session list (as UUID hashes, objects or session names)
+ @rtype: C{list}
+
+ """
+ if return_objects:
+ return self.associated_sessions() and [ s for s in self.associated_sessions() if s.published_applications ]
+ elif return_session_names:
+ return self.associated_sessions() and [ s.session_name for s in self.associated_sessions() if s.published_applications ]
+ else:
+ return self.associated_sessions() and [ s.get_uuid() for s in self.associated_sessions() if s.published_applications ]
+
def registered_sessions_of_profile_name(self, profile_name, return_objects=True, return_session_names=False):
"""\
For a given session profile name retrieve a list of sessions that are currently registered with this L{X2goClient} instance.
diff --git a/x2go/session.py b/x2go/session.py
index 4fe945c..fa83111 100644
--- a/x2go/session.py
+++ b/x2go/session.py
@@ -34,6 +34,7 @@ import types
import uuid
import time
import gevent
+import re
# Python X2Go modules
import log
@@ -66,7 +67,7 @@ _X2GO_SESSION_PARAMS = ('geometry', 'depth', 'link', 'pack',
'rootdir', 'loglevel', 'profile_name', 'profile_id',
'print_action', 'print_action_args',
'convert_encoding', 'client_encoding', 'server_encoding',
- 'proxy_options',
+ 'proxy_options', 'published_applications',
'logger',
'control_backend', 'terminal_backend', 'proxy_backend',
'profiles_backend', 'settings_backend', 'printing_backend',
@@ -230,6 +231,21 @@ class X2goSession(object):
self.ssh_rootdir = ssh_rootdir
self.control_session = control_session
+ if params.has_key('published_applications'):
+ self.published_applications = params['published_applications']
+ if self.published_applications:
+ params['cmd'] = 'PUBLISHED'
+ else:
+ self.published_applications = params['published_applications'] = False
+
+ if params.has_key('cmd') and params['cmd'] != 'PUBLISHED':
+ self.published_applications = params['published_applications'] = False
+ self.published_applications_menu = None
+
+ if self.session_name:
+ if not re.match('.*_stRPUBLISHED_.*',self.session_name):
+ self.published_applications = params['published_applications'] = False
+
self.control_params = {}
self.terminal_params = {}
self.sshproxy_params = {}
@@ -279,6 +295,10 @@ class X2goSession(object):
self.init_control_session()
self.terminal_session = None
+ if self.is_connected():
+ self.retrieve_server_features()
+
+
def HOOK_session_startup_failed(self):
"""\
HOOK method: called if the startup of a session failed.
@@ -683,6 +703,8 @@ class X2goSession(object):
@rtype: C{str}
"""
+ if self.has_terminal_session():
+ return self.terminal_session.get_session_cmd()
if self.terminal_params.has_key('cmd'):
return self.terminal_params['cmd']
return None
@@ -954,6 +976,18 @@ class X2goSession(object):
"""
return self.server_features
+ def has_server_feature(self, feature):
+ """\
+ Check if C{feature} is a present feature of the connected X2Go server.
+
+ @param feature: an X2Go server feature as found in C{$SHAREDIR/x2go/feature.d/*}
+ @type feature: C{str}
+ @return: C{True} if the feature is presend
+ @rtype: C{bool}
+
+ """
+ return feature in self.get_server_features()
+
def set_session_window_title(self, title=''):
"""\
Modify session window title. If the session ID does not occur in the
@@ -1011,7 +1045,7 @@ class X2goSession(object):
return self.connected
__is_alive = is_alive
- def clean_sessions(self, destroy_terminals=True):
+ def clean_sessions(self, destroy_terminals=True, published_applications=False):
"""\
Clean all running sessions for the authenticated user on the remote X2Go server.
@@ -1024,7 +1058,7 @@ class X2goSession(object):
except x2go_exceptions.X2goSessionException:
pass
- self.control_session.clean_sessions(destroy_terminals=destroy_terminals)
+ self.control_session.clean_sessions(destroy_terminals=destroy_terminals, published_applications=published_applications)
else:
self._X2goSession__disconnect()
__clean_sessions = clean_sessions
@@ -1138,14 +1172,13 @@ class X2goSession(object):
self.terminated = not (self.running or self.suspended)
else:
self.terminated = None
- except KeyError:
+ except KeyError, e:
self.running = False
self.suspended = False
if not self.virgin:
self.terminated = True
self.faulty = not (self.running or self.suspended or self.terminated or self.virgin)
-
self._current_status = {
'timestamp': time.time(),
'server': self.server,
@@ -1161,9 +1194,46 @@ class X2goSession(object):
raise e
return True
-
__update_status = update_status
+ def is_published_applications_provider(self):
+ """\
+ Returns true if this session runs in published applications mode.
+
+ @return: Returns C{True} is this session is a provider session for published applications.
+ @rtype: C{bool}
+
+ """
+ if self.is_running() and self.has_terminal_session():
+ return self.terminal_session.is_published_applications_provider()
+ return False
+
+ def get_published_applications(self):
+ """\
+ Return a list of published menu items from the X2Go server
+ for session type published applications.
+
+ @return: A C{list} of C{dict} elements. Each C{dict} elements has a
+ C{desktop} key containing the text output of a .desktop file and
+ an C{icon} key which contains the desktop icon data base64 encoded
+ @rtype: C{list}
+
+ """
+ return self.control_session.get_published_applications()
+
+ def exec_published_application(self, exec_name):
+ """\
+ Execute an application while in published application mode.
+
+ @param exec_name: command to execute on server
+ @type exec_name: C{str}
+
+ """
+ if self.terminal_session is not None:
+ self.logger('for %s executing published application: %s' % (self.profile_name, exec_name), loglevel=log.loglevel_NOTICE)
+ self.terminal_session.exec_published_application(exec_name)
+ __exec_published_application = exec_published_application
+
def resume(self, session_name=None):
"""\
Resume or continue a suspended / running X2Go session on the
@@ -1189,7 +1259,14 @@ class X2goSession(object):
# sockets, thus we plainly have to wait a while
if self.is_running():
self.suspend()
- gevent.sleep(10)
+ gevent.sleep(5)
+
+ try:
+ if self.published_applications:
+ self.published_applications_menu = self.get_published_applications()
+ except:
+ # FIXME: test the code to see what exceptions may occur here...
+ raise
self.terminal_session = _control.resume(session_name=self.session_name,
session_instance=self,
@@ -1209,6 +1286,9 @@ class X2goSession(object):
if _new_session:
self.terminal_session.run_command(env=self.session_environment)
+ if self.get_session_cmd() != 'PUBLISHED':
+ self.published_applications = False
+
if self._SUPPORTED_SOUND and self.terminal_session.params.snd_system is not 'none':
self.terminal_session and not self.faulty and self.terminal_session.start_sound()
else:
diff --git a/x2go/utils.py b/x2go/utils.py
index 8bec574..1b23cdc 100644
--- a/x2go/utils.py
+++ b/x2go/utils.py
@@ -166,6 +166,7 @@ def _convert_SessionProfileOptions_2_SessionParams(_options):
'sshproxytunnel': 'sshproxy_tunnel',
'sessiontitle': 'session_title',
'setsessiontitle': 'set_session_title',
+ 'published': 'published_applications',
}
_speed_dict = {
'0': 'modem',
@@ -505,9 +506,12 @@ def set_session_window_title(session_window, session_title):
"""
if _X2GOCLIENT_OS != 'Windows':
- session_window.set_wm_name(str(session_title))
- session_window.set_wm_icon_name(str(session_title))
- _X_DISPLAY.sync()
+ try:
+ session_window.set_wm_name(str(session_title))
+ session_window.set_wm_icon_name(str(session_title))
+ _X_DISPLAY.sync()
+ except Xlib.error.BadWindow:
+ pass
def raise_session_window(session_window):
"""\
hooks/post-receive
--
python-x2go.git (Python X2Go Client API)
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "python-x2go.git" (Python X2Go Client API).
More information about the x2go-commits
mailing list