[X2Go-Commits] [python-x2go] 01/03: Provide session profile backend for a http broker.
git-admin at x2go.org
git-admin at x2go.org
Tue Mar 18 01:11:40 CET 2014
This is an automated email from the git hooks/post-receive script.
x2go pushed a commit to branch master
in repository python-x2go.
commit f5f6f6db53dff875a642583da56c0ada78a47231
Author: Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
Date: Tue Mar 4 13:58:21 2014 +0100
Provide session profile backend for a http broker.
---
debian/changelog | 2 +
x2go/backends/control/plain.py | 5 +
x2go/backends/profiles/base.py | 210 +++++++++++++++++++++++++++++----
x2go/backends/profiles/file.py | 16 +++
x2go/backends/profiles/httpbroker.py | 215 +++++++++++++++++++++++++++++++---
x2go/client.py | 40 +++++--
x2go/defaults.py | 2 +-
x2go/inifiles.py | 4 +-
x2go/registry.py | 1 +
x2go/utils.py | 27 +++--
10 files changed, 461 insertions(+), 61 deletions(-)
diff --git a/debian/changelog b/debian/changelog
index 0c28057..3d7ff02 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,8 @@ python-x2go (0.5.0.0-0x2go1) UNRELEASED; urgency=low
not really used by third-party products, if at all).
- Fix setting default values in X2GoClientXConfig class.
- Default to xdg-open as default PDF viewer command.
+ - Provide basic session profile backend for a http broker.
+ - Make session profile backends more unicode robust.
-- Mike Gabriel <mike.gabriel at das-netzwerkteam.de> Sun, 05 Jan 2014 16:35:57 +0100
diff --git a/x2go/backends/control/plain.py b/x2go/backends/control/plain.py
index bb0ec98..fa756df 100644
--- a/x2go/backends/control/plain.py
+++ b/x2go/backends/control/plain.py
@@ -51,6 +51,7 @@ import x2go.defaults as defaults
import x2go.checkhosts as checkhosts
from x2go.defaults import BACKENDS as _BACKENDS
+from x2go.defaults import CURRENT_LOCAL_USER as _current_user
import x2go._paramiko
x2go._paramiko.monkey_patch_paramiko()
@@ -817,6 +818,10 @@ class X2GoControlSession(paramiko.SSHClient):
"""
_fake_hostname = None
+ if not username:
+ self.logger('no username specified, cannot connect without username', loglevel=log.loglevel_ERROR)
+ raise paramiko.AuthenticationException('no username specified, cannot connect without username')
+
if type(password) not in (types.StringType, types.UnicodeType):
password = ''
if type(sshproxy_password) not in (types.StringType, types.UnicodeType):
diff --git a/x2go/backends/profiles/base.py b/x2go/backends/profiles/base.py
index 6985f9a..641e5e4 100644
--- a/x2go/backends/profiles/base.py
+++ b/x2go/backends/profiles/base.py
@@ -36,7 +36,7 @@ from x2go.defaults import X2GO_DESKTOPSESSIONS as _X2GO_DESKTOPSESSIONS
import x2go.log as log
import x2go.utils as utils
-from x2go.x2go_exceptions import X2GoNotImplementedYetException
+from x2go.x2go_exceptions import X2GoProfileException
class X2GoSessionProfiles():
@@ -74,7 +74,7 @@ class X2GoSessionProfiles():
if utils._checkSessionProfileDefaults(session_profile_defaults):
self.defaultSessionProfile = session_profile_defaults
- self.session_profiles = self.populate_session_profiles()
+ self.populate_session_profiles()
def __call__(self, profile_id_or_name):
"""\
@@ -90,6 +90,29 @@ class X2GoSessionProfiles():
_profile_id = self.check_profile_id_or_name(self, profile_id_or_name)
return self.get_profile_config(profile_id=_profile_id)
+ def init_profile_cache(self, profile_id_or_name):
+ """\
+ Some session profile backends (e.g. the broker backends cache
+ dynamic session profile data). On new connections, it is
+ recommented to (re-)initialize these caches.
+
+ @param profile_id_or_name: profile ID or profile name
+ @type profile_id_or_name: C{str}
+
+ """
+ profile_id = self.check_profile_id_or_name(profile_id_or_name)
+
+ # allow backend specific clean-up
+ self._init_profile_cache(profile_id)
+
+ def _init_profile_cache(self, profile_id):
+ """\
+ Inherit from this class to (re-)initialize profile ID based
+ cache storage.
+
+ """
+ pass
+
def populate_session_profiles(self):
"""\
Load a session profile set from the configuration storage
@@ -99,7 +122,7 @@ class X2GoSessionProfiles():
@rtype: C{dict}
"""
- return self. _populate_session_profiles()
+ self.session_profiles = self. _populate_session_profiles()
def _populate_session_profiles(self):
"""\
@@ -126,6 +149,7 @@ class X2GoSessionProfiles():
"""
_profile_id = self.check_profile_id_or_name(profile_id_or_name)
+
if not self._profile_metatypes.has_key(_profile_id) or force:
_config = self.get_profile_config(_profile_id)
if _config['host']:
@@ -151,10 +175,74 @@ class X2GoSessionProfiles():
_metatype = 'RDP/direct'
else:
_metatype = 'not supported'
- self._profile_metatypes[_profile_id] = _metatype
+ self._profile_metatypes[_profile_id] = unicode(_metatype)
else:
return self._profile_metatypes[_profile_id]
+ def is_mutable(self, profile_id_or_name):
+ """\
+ Check if a given profile name (or ID) is mutable or not.
+
+ @param profile_id_or_name: profile name or profile ID
+ @type profile_id_or_name: C{str}
+
+ @return: C{True} if the session profile of the specified name/ID is mutable
+ @rtype: C{bool}
+
+ """
+ try:
+ profile_id = self.check_profile_id_or_name(profile_id_or_name)
+ return self._is_mutable(profile_id)
+ except X2GoProfileException:
+ return None
+
+ def _is_mutable(self, profile_id):
+ """\
+ Inherit from this base class and provide your own decision making
+ code here if a given profile ID is mutable or not.
+
+ @param profile_id: profile ID
+ @type profile_id: C{str}
+
+ @return: C{True} if the session profile of the specified ID is mutable
+ @rtype: C{bool}
+
+ """
+ return False
+
+ def supports_mutable_profiles(self):
+ """\
+ Check if the current session profile backend supports
+ mutable session profiles.
+
+ @return: list of mutable profiles
+ @rtype: C{list)
+
+ """
+ return self._supports_mutable_profiles()
+
+ def _supports_mutable_profiles(self):
+ """\
+ Inherit from this base class and provide your own decision making
+ code here if a your session profile backend supports mutable
+ session profiles or not.
+
+ @return: list of mutable profiles
+ @rtype: C{list)
+
+ """
+ return False
+
+ def mutable_profile_ids(self):
+ """\
+ List all mutable session profiles.
+
+ @return: List up all session profile IDs of mutable session profiles.
+ @rtype: C{bool}
+
+ """
+ return [ p for p in self.profile_ids if self._is_mutable(p) ]
+
def write(self):
"""\
Store session profile data to the storage backend.
@@ -220,28 +308,31 @@ class X2GoSessionProfiles():
_profile_id = profile_id or self.check_profile_id_or_name(profile_id_or_name)
_profile_config = {}
for option in self._get_profile_options(_profile_id):
- _profile_config[option] = self._get_profile_parameter(_profile_id, option, key_type=self.get_profile_option_type(option))
+ value = self._get_profile_parameter(_profile_id, option, key_type=self.get_profile_option_type(option))
- if parameter is not None:
- if parameter in _profile_config.keys():
+ if option == 'export':
+ _strvalue = value.replace(',', ';').strip().strip('"').strip().strip(';').strip()
+ value = {}
+ if _strvalue:
+ _export_paths = _strvalue.split(';')
+ for _path in _export_paths:
+ if not re.match('.*:(0|1)$', _path): _path = '%s:1' % _path
+ _auto_export_path = re.match('.*:1$', _path) and True or False
+ _export_path = ':'.join(_path.split(':')[:-1])
+ value[_export_path] = _auto_export_path
- value = _profile_config[parameter]
+ if type(value) is types.StringType:
+ value = unicode(value)
- if parameter == 'export':
- _strvalue = value.replace(',', ';').strip().strip('"').strip().strip(';').strip()
- value = {}
- if _strvalue:
- _export_paths = _strvalue.split(';')
- for _path in _export_paths:
- if not re.match('.*:(0|1)$', _path): _path = '%s:1' % _path
- _auto_export_path = re.match('.*:1$', _path) and True or False
- _export_path = ':'.join(_path.split(':')[:-1])
- value[_export_path] = _auto_export_path
+ _profile_config[option] = value
+ if parameter is not None:
+ if parameter in _profile_config.keys():
+ value = _profile_config[parameter]
return value
-
else:
raise X2GoProfileException('no such session profile parameter: %s' % parameter)
+
return _profile_config
def default_profile_config(self):
@@ -303,7 +394,7 @@ class X2GoSessionProfiles():
@rtype: C{bool}
"""
- return profile_id in self.profile_ids
+ return unicode(profile_id) in self.profile_ids
@property
def profile_names(self):
@@ -326,7 +417,7 @@ class X2GoSessionProfiles():
@rtype: C{bool}
"""
- return profile_name in self.profile_names
+ return unicode(profile_name) in self.profile_names
def to_profile_id(self, profile_name):
"""\
@@ -341,7 +432,7 @@ class X2GoSessionProfiles():
"""
_profile_ids = [ p for p in self.profile_ids if self.to_profile_name(p) == profile_name ]
if len(_profile_ids) == 1:
- return _profile_ids[0]
+ return unicode(_profile_ids[0])
elif len(_profile_ids) == 0:
return None
else:
@@ -360,9 +451,9 @@ class X2GoSessionProfiles():
"""
_profile_config = self.get_profile_config(profile_id=profile_id)
if _profile_config.has_key('name'):
- return _profile_config['name']
+ return unicode(_profile_config['name'])
else:
- return ''
+ return u''
def add_profile(self, profile_id=None, force_add=False, **kwargs):
"""\
@@ -396,7 +487,7 @@ class X2GoSessionProfiles():
self._cached_profile_ids = []
self._cached_profile_names = []
- return profile_id
+ return unicode(profile_id)
def delete_profile(self, profile_id_or_name):
"""\
@@ -440,11 +531,14 @@ class X2GoSessionProfiles():
except X2GoProfileException:
profile_id = profile_id_or_name
+ if not self.is_mutable(profile_id):
+ raise X2GoProfileException("session profile cannot be modified, it is marked as immutable")
+
if option == 'name':
profile_name = value
current_profile_name = self.get_value(profile_id, option)
if not profile_name:
- raise X2GoProfileException('profile name for profile id %s may not be empty' % profile_id)
+ raise X2GoProfileException('profile name for profile id %s must not be empty' % profile_id)
else:
self._cached_profile_names = []
if profile_name != current_profile_name and profile_name in self.profile_names:
@@ -462,6 +556,10 @@ class X2GoSessionProfiles():
_config = self.get_profile_config(profile_id=profile_id)
if _config.has_key('host') and _config['host'] != value:
self._profiles_need_profile_id_renewal.append(profile_id)
+ if type(value) is types.TupleType:
+ value = list(value)
+ if type(value) is not types.ListType:
+ value = value.split(',')
self._update_value(profile_id, option, value)
@@ -495,6 +593,8 @@ class X2GoSessionProfiles():
_profile_id = profile_id_or_name
else:
raise X2GoProfileException('No session profile with id or name ,,%s\'\' exists.' % profile_id_or_name)
+ if _profile_id is not None:
+ _profile_id = unicode(_profile_id)
return _profile_id
def to_session_params(self, profile_id_or_name=None, profile_id=None):
@@ -557,3 +657,61 @@ class X2GoSessionProfiles():
"""
return []
+ def get_server_hostname(self, profile_id):
+ """\
+ Retrieve host name of the X2Go Server configured in a session profile.
+
+ @param profile_id: the profile's unique ID
+ @type profile_id: C{str}
+
+ @return: the host name of the X2Go Server configured by the session profile
+ of the given profile ID
+ @rtype: C{list}
+
+ """
+ return self._get_server_hostname(profile_id)
+
+ def _get_server_hostname(self, profile_id):
+ """\
+ Inherit from this class and provide a way for actually obtaining
+ a the server host name for a given profile ID.
+
+ @param profile_id: the profile's unique ID
+ @type profile_id: C{str}
+
+ @return: the host name of the X2Go Server configured by the session profile
+ of the given profile ID
+ @rtype: C{list}
+
+ """
+ return [u'localhost']
+
+ def get_server_port(self, profile_id):
+ """\
+ Retrieve SSH port of the X2Go Server configured in a session profile.
+
+ @param profile_id: the profile's unique ID
+ @type profile_id: C{str}
+
+ @return: the SSH port of the X2Go Server configured by the session profile
+ of the given profile ID
+ @rtype: C{list}
+
+ """
+ return self._get_server_port(profile_id)
+
+ def _get_server_hostname(self, profile_id):
+ """\
+ Inherit from this class and provide a way for actually obtaining
+ a the server SSH port for a given profile ID.
+
+ @param profile_id: the profile's unique ID
+ @type profile_id: C{str}
+
+ @return: the SSH port of the X2Go Server configured by the session profile
+ of the given profile ID
+ @rtype: C{list}
+
+ """
+ return 22
+
diff --git a/x2go/backends/profiles/file.py b/x2go/backends/profiles/file.py
index 9e7edcf..0f08336 100644
--- a/x2go/backends/profiles/file.py
+++ b/x2go/backends/profiles/file.py
@@ -26,6 +26,8 @@ applications.
"""
__NAME__ = 'x2gosessionprofiles-pylib'
+import types
+
# Python X2Go modules
from x2go.defaults import X2GO_SESSIONPROFILES_CONFIGFILES as _X2GO_SESSIONPROFILES_CONFIGFILES
import x2go.backends.profiles.base as base
@@ -90,6 +92,12 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles, inifiles.X2GoIniFile):
self.get_profile_metatype(session_profile)
return session_profiles
+ def _is_mutable(self, profile_id):
+ return True
+
+ def _supports_mutable_profiles(self):
+ return True
+
def _write(self):
self._write_user_config = self.write_user_config
return inifiles.X2GoIniFile.write(self)
@@ -98,6 +106,8 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles, inifiles.X2GoIniFile):
self.iniConfig.remove_section(profile_id)
def _update_value(self, profile_id, option, value):
+ if option == 'host':
+ value = ','.join(value)
inifiles.X2GoIniFile.update_value(self, profile_id, option, value)
def _get_profile_parameter(self, profile_id, option, key_type):
@@ -108,3 +118,9 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles, inifiles.X2GoIniFile):
def _get_profile_ids(self):
return [ s for s in self.iniConfig.sections() if s != "none" ]
+
+ def _get_server_hostname(self, profile_id):
+ return self.get_profile_config(profile_id)['host']
+
+ def _get_server_port(self, profile_id):
+ return self.get_profile_config(profile_id)['sshport']
diff --git a/x2go/backends/profiles/httpbroker.py b/x2go/backends/profiles/httpbroker.py
index 0d27cb4..569e851 100644
--- a/x2go/backends/profiles/httpbroker.py
+++ b/x2go/backends/profiles/httpbroker.py
@@ -26,8 +26,16 @@ applications.
"""
__NAME__ = 'x2gosessionprofiles-pylib'
+import re
+import requests
+import copy
+import types
+try: import simplejson as json
+except ImportError: import json
+
# Python X2Go modules
-from x2go.defaults import X2GO_SESSIONPROFILE_DEFAULTS
+from x2go.defaults import X2GO_SESSIONPROFILE_DEFAULTS as _X2GO_SESSIONPROFILE_DEFAULTS
+from x2go.defaults import CURRENT_LOCAL_USER as _CURRENT_LOCAL_USER
import x2go.backends.profiles.base as base
import x2go.log as log
@@ -35,14 +43,27 @@ from x2go.x2go_exceptions import X2GoNotImplementedYetException
class X2GoSessionProfiles(base.X2GoSessionProfiles):
- defaultSessionProfile = X2GO_SESSIONPROFILE_DEFAULTS
+ defaultSessionProfile = _X2GO_SESSIONPROFILE_DEFAULTS
- def __init__(self, session_profile_defaults=None, logger=None, loglevel=log.loglevel_DEFAULT):
+ def __init__(self, session_profile_defaults=None,
+ broker_url="http://localhost:8080/json/",
+ broker_username=None,
+ broker_password=None,
+ broker_noauth=False,
+ logger=None, loglevel=log.loglevel_DEFAULT,
+ **kwargs):
"""\
Retrieve X2Go session profiles from a HTTP(S) session broker.
@param session_profile_defaults: a default session profile
@type session_profile_defaults: C{dict}
+ @param broker_url: URL for accessing the X2Go Session Broker
+ @type broker_url: C{str}
+ @param broker_password: use this password for authentication against the X2Go Session Broker (avoid
+ password string in the C{broker_URL} parameter is highly recommended)
+ @type broker_password: C{str}
+ @param broker_noauth: the X2Go Session Broker accepts connections without authentication
+ @type broker_noauth: C{bool}
@param logger: you can pass an L{X2GoLogger} object to the
L{X2GoSessionProfilesHTTPSBROKER} constructor
@type logger: L{X2GoLogger} instance
@@ -51,7 +72,139 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles):
@type loglevel: C{int}
"""
+ self.broker_noauth = broker_noauth
+ if broker_url.upper() != "HTTP":
+ match = re.match('^(?P<protocol>(http(|s)))://(|(?P<user>[a-zA-Z0-9_\.-]+)(|:(?P<password>.*))@)(?P<hostname>[a-zA-Z0-9\.-]+)(|:(?P<port>[0-9]+))($|/(?P<path>.*)$)', broker_url)
+ p = match.groupdict()
+ if p['user']:
+ self.broker_username = p['user']
+ else:
+ self.broker_username = broker_username
+ if not self.broker_noauth:
+ if p['password']:
+ self.broker_password = p['password']
+ else:
+ self.broker_password = broker_password
+ else:
+ self.broker_password = None
+
+ # fine-tune the URL
+ p['path'] = "/{path}".format(**p)
+ if p['port'] is not None:
+ p['port'] = ":{port}".format(**p)
+
+ self.broker_url = "{protocol}://{hostname}{port}{path}".format(**p)
+
+ else:
+ self.broker_username = broker_username
+ self.broker_password = broker_password
+ self.broker_url = broker_url
+
base.X2GoSessionProfiles.__init__(self, session_profile_defaults=session_profile_defaults, logger=logger, loglevel=loglevel)
+ if self.broker_url != "HTTP":
+ self.logger("Using session broker at URL: %s" % self.broker_url, log.loglevel_NOTICE)
+
+ self._broker_profile_cache = {}
+ self._mutable_profile_ids = None
+ self._broker_auth_successful = None
+
+ self._broker_type = "http"
+
+ def get_broker_noauth(self):
+ return self.broker_noauth
+
+ def get_broker_username(self):
+ return self.broker_username
+
+ def get_broker_url(self):
+ return self.broker_url
+
+ def set_broker_url(self, broker_url):
+ self.broker_url = broker_url
+
+ def get_broker_type(self):
+ return self._broker_type
+
+ def broker_simpleauth(self, broker_username, broker_password):
+ if self.broker_url is not None:
+ request_data = {
+ 'user': broker_username or '',
+ 'password': broker_password or '',
+ }
+ r = requests.post(self.broker_url, data=request_data)
+ if r.status_code == 200:
+ self.broker_username = broker_username or ''
+ self.broker_password = broker_password or ''
+ self._broker_auth_successful = True
+ return True
+ self._broker_auth_successful = False
+ return False
+
+ def broker_disconnect(self):
+ _profile_ids = copy.deepcopy(self.profile_ids)
+
+ # forget nearly everything...
+ for profile_id in _profile_ids:
+ self.init_profile_cache(profile_id)
+ try: del self._profile_metatypes[profile_id]
+ except KeyError: pass
+ try: self._profiles_need_profile_id_renewal.remove(profile_id)
+ except ValueError: pass
+ try: self._cached_profile_names.remove(self.to_profile_name(profile_id))
+ except ValueError: pass
+ try: self._cached_profile_ids.remove(profile_id)
+ except ValueError: pass
+ del self.session_profiles[profile_id]
+ self._mutable_profile_ids = None
+ self._broker_auth_successful = False
+ self.broker_password = None
+
+ def is_broker_authenticated(self):
+ if self._broker_auth_successful is None:
+ # do a test auth against the given broker URL
+ self.broker_simpleauth(self.broker_username, self.broker_password)
+ return self._broker_auth_successful
+
+ def broker_listprofiles(self):
+ if self.broker_url is not None:
+ request_data = {
+ 'task': 'listprofiles',
+ 'user': self.broker_username,
+ 'password': self.broker_password,
+ }
+ r = requests.post(self.broker_url, data=request_data)
+ if r.status_code == 200 and r.headers['content-type'].startswith("text/json"):
+ payload = json.loads(r.text)
+ if payload.has_key('mutable_profile_ids'):
+ self._mutable_profile_ids = payload['mutable_profile_ids']
+ self._broker_auth_successful = True
+ return payload['profiles'] if payload['task'] == 'listprofiles' else {}
+ self._broker_auth_successful = False
+ return {}
+
+ def broker_selectsession(self, profile_id):
+ if self.broker_url is not None:
+ if not self._broker_profile_cache.has_key(profile_id) or not self._broker_profile_cache[profile_id]:
+ request_data = {
+ 'task': 'selectsession',
+ 'profile-id': profile_id,
+ 'user': self.broker_username,
+ 'password': self.broker_password,
+ }
+ r = requests.post(self.broker_url, data=request_data)
+ if r.status_code == 200 and r.headers['content-type'].startswith("text/json"):
+ payload = json.loads(r.text)
+ self._broker_profile_cache[profile_id] = payload['selected_session'] if payload['task'] == 'selectsession' else {}
+ self._broker_auth_successful = True
+ else:
+ self._broker_auth_successful = False
+ self._broker_profile_cache[profile_id]
+ return self._broker_profile_cache[profile_id]
+ return {}
+
+ def _init_profile_cache(self, profile_id):
+ if self._broker_profile_cache.has_key(unicode(profile_id)):
+ del self._broker_profile_cache[unicode(profile_id)]
def _populate_session_profiles(self):
"""\
@@ -62,31 +215,61 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles):
@rtype: C{dict}
"""
- session_profiles = LOAD
+ if self.broker_noauth or \
+ self.broker_username and self.broker_password:
- for session_profile in session_profiles:
- for key, default_value in self.defaultSessionProfile.iteritems():
- if not self.iniConfig.has_option(session_profile, key):
- self._storeValue(session_profile, key, default_value)
- # update cached meta type session profile information
- self.get_profile_metatype(session_profile)
+ session_profiles = self.broker_listprofiles()
+ _session_profiles = copy.deepcopy(session_profiles)
+
+ for session_profile in _session_profiles:
+ session_profile = unicode(session_profile)
+ for key, default_value in self.defaultSessionProfile.iteritems():
+ key = unicode(key)
+ if type(default_value) is types.StringType:
+ default_value = unicode(default_value)
+ if not session_profiles[session_profile].has_key(key):
+ session_profiles[session_profile][key] = default_value
+
+ else:
+ session_profiles = {}
return session_profiles
+ def _is_mutable(self, profile_id):
+ if type(self._mutable_profile_ids) is types.ListType and profile_id in self._mutable_profile_ids:
+ return True
+ return False
+
+ def _supports_mutable_profiles(self):
+ if type(self._mutable_profile_ids) is types.ListType:
+ return True
+ return False
+
def _write(self):
- print "BROKER CLIENT: WRITING SESSION PROFILES IS NOT SUPPORTED"
+ print "not suported, yet"
def _delete_profile(self, profile_id):
- print "BROKER CLIENT: DELETING SESSION PROFILES IS NOT SUPPORTED"
+ del self.session_profiles[unicode(profile_id)]
def _update_value(self, profile_id, option, value):
- print "BROKER CLIENT: MODIFYING SESSION PROFILES IS NOT SUPPORTED"
+ if type(value) is types.StringType:
+ value = unicode(value)
+ self.session_profiles[unicode(profile_id)][unicode(option)] = value
def _get_profile_parameter(self, profile_id, option, key_type):
- print "TODO"
+ return key_type(self.session_profiles[unicode(profile_id)][unicode(option)])
def _get_profile_options(self, profile_id):
- print "TODO"
+ return self.session_profiles[unicode(profile_id)].keys()
def _get_profile_ids(self):
- print "TODO"
+ self.session_profiles.keys()
+ return self.session_profiles.keys()
+
+ def _get_server_hostname(self, profile_id):
+ selected_session = self.broker_selectsession(profile_id)
+ return selected_session['server']
+
+ def _get_server_port(self, profile_id):
+ selected_session = self.broker_selectsession(profile_id)
+ return int(selected_session['port'])
diff --git a/x2go/client.py b/x2go/client.py
index debba28..b1fa978 100644
--- a/x2go/client.py
+++ b/x2go/client.py
@@ -182,6 +182,9 @@ class X2GoClient(object):
profiles_backend=_BACKENDS['X2GoSessionProfiles']['default'],
settings_backend=_BACKENDS['X2GoClientSettings']['default'],
printing_backend=_BACKENDS['X2GoClientPrinting']['default'],
+ broker_url=None,
+ broker_password=None,
+ broker_noauth=False,
client_rootdir=None,
sessions_rootdir=None,
ssh_rootdir=None,
@@ -215,6 +218,12 @@ class X2GoClient(object):
@type settings_backend: C{str}
@param printing_backend: X2Go client printing backend to use
@type printing_backend: C{str}
+ @param broker_url: URL pointing to the X2Go Session Broker
+ @type broker_url: C{str}
+ @param broker_password: use this password for authentication against the X2Go Session Broker
+ @type broker_password: C{str}
+ @param broker_noauth: accessing the X2Go Session Broker works without credentials
+ @type broker_noauth: C{bool}
@param client_rootdir: client base dir (default: ~/.x2goclient)
@type client_rootdir: C{str}
@param sessions_rootdir: sessions base dir (default: ~/.x2go)
@@ -268,6 +277,11 @@ class X2GoClient(object):
self.info_backend = utils._get_backend_class(info_backend, "X2GoServerSessionInfo")
self.list_backend = utils._get_backend_class(list_backend, "X2GoServerSessionList")
self.proxy_backend = utils._get_backend_class(proxy_backend, "X2GoProxy")
+ if broker_url is not None:
+ if broker_url.lower().startswith('ssh'):
+ profiles_backend = 'sshbroker'
+ elif broker_url.lower().startswith('http'):
+ profiles_backend = 'httpbroker'
self.profiles_backend = utils._get_backend_class(profiles_backend, "X2GoSessionProfiles")
self.settings_backend = utils._get_backend_class(settings_backend, "X2GoClientSettings")
self.printing_backend = utils._get_backend_class(printing_backend, "X2GoClientPrinting")
@@ -288,7 +302,7 @@ class X2GoClient(object):
_settings_config_file = os.path.join(self.client_rootdir, _X2GO_SETTINGS_FILENAME)
_printing_config_file = os.path.join(self.client_rootdir, _X2GO_PRINTING_FILENAME)
_xconfig_config_file = os.path.join(self.client_rootdir, _X2GO_XCONFIG_FILENAME)
- self.session_profiles = self.profiles_backend(config_files=[_sessions_config_file], logger=self.logger)
+ self.session_profiles = self.profiles_backend(config_files=[_sessions_config_file], logger=self.logger, broker_url=broker_url, broker_password=broker_password, broker_noauth=broker_noauth)
self.client_settings = self.settings_backend(config_files=[_settings_config_file], logger=self.logger)
self.client_printing = self.printing_backend(config_files=[_printing_config_file], client_instance=self, logger=self.logger)
else:
@@ -864,18 +878,27 @@ class X2GoClient(object):
@rtype: C{str}
"""
+ _p = None
# detect profile name and profile id properly
if profile_id and self.session_profiles.has_profile_id(profile_id):
_p = profile_id
elif profile_name and self.session_profiles.has_profile_name(profile_name):
_p = profile_name
- else:
- _p = None
-
+ elif profile_id:
+ try:
+ _p = self.session_profiles.check_profile_id_or_name(profile_id)
+ except x2go_exceptions.X2GoProfileException:
+ pass
+ elif profile_name:
+ try:
+ _p = self.session_profiles.check_profile_id_or_name(profile_name)
+ except x2go_exceptions.X2GoProfileException:
+ pass
if _p:
-
_profile_id = self.session_profiles.check_profile_id_or_name(_p)
_profile_name = self.session_profiles.to_profile_name(_profile_id)
+ else:
+ _profile_id = None
# test if session_name has already been registered. If yes, return it immediately.
if type(session_name) is types.StringType:
@@ -886,8 +909,10 @@ class X2GoClient(object):
if known_hosts is None:
known_hosts = os.path.join(_LOCAL_HOME, self.ssh_rootdir, 'known_hosts')
+ if _profile_id:
- if _p:
+ # initialize session profile cache
+ self.session_profiles.init_profile_cache(_profile_id)
_params = self.session_profiles.to_session_params(profile_id=_profile_id)
del _params['profile_name']
@@ -897,7 +922,8 @@ class X2GoClient(object):
if k in kwargs.keys():
_params[k] = kwargs[k]
- server = _params['server']
+ server = self.session_profiles.get_server_hostname(_profile_id)
+ _params['port'] = self.session_profiles.get_server_port(_profile_id)
del _params['server']
_params['client_instance'] = self
diff --git a/x2go/defaults.py b/x2go/defaults.py
index 59373f4..ee785a5 100644
--- a/x2go/defaults.py
+++ b/x2go/defaults.py
@@ -296,7 +296,7 @@ X2GO_SESSIONPROFILE_DEFAULTS = {
'usekbd': True, 'layout': 'us', 'type': 'pc105/us', 'variant': '',
'sound': False, 'soundsystem': 'pulse', 'startsoundsystem': False, 'soundtunnel':True, 'defsndport':True, 'sndport':4713,
'name': 'NEW_PROFILE', 'icon': ':icons/128x128/x2gosession.png',
- 'host': 'server.mydomain', 'user': CURRENT_LOCAL_USER, 'key': '', 'sshport': 22, 'krblogin': False, 'forwardsshagent': False,
+ 'host': ['server.mydomain'], 'user': CURRENT_LOCAL_USER, 'key': '', 'sshport': 22, 'krblogin': False, 'forwardsshagent': False,
'rootless': True, 'applications': X2GO_GENERIC_APPLICATIONS, 'command':'TERMINAL', 'published': False,
'directrdp': False, 'directrdpsettings': '', 'rdpclient': 'rdesktop', 'rdpport': 3389,
'rdpoptions': '-u X2GO_USER -p X2GO_PASSWORD', 'rdpserver': '',
diff --git a/x2go/inifiles.py b/x2go/inifiles.py
index e363bee..1bc10d4 100644
--- a/x2go/inifiles.py
+++ b/x2go/inifiles.py
@@ -52,7 +52,6 @@ class X2GoIniFile(object):
always contain the same fields.
"""
- user_config_file = None
def __init__(self, config_files, defaults=None, logger=None, loglevel=log.loglevel_DEFAULT):
"""\
@@ -70,6 +69,7 @@ class X2GoIniFile(object):
@type loglevel: C{int}
"""
+ self.user_config_file = None
self._write_user_config = True
# make sure a None type gets turned into list type
@@ -102,8 +102,8 @@ class X2GoIniFile(object):
if not os.path.exists(file_name):
utils.touch_file(file_name)
_create_file = True
+ self.user_config_file = file_name
break
-
self.load()
if _create_file:
diff --git a/x2go/registry.py b/x2go/registry.py
index 66ad62f..ffe0708 100644
--- a/x2go/registry.py
+++ b/x2go/registry.py
@@ -560,6 +560,7 @@ class X2GoSessionRegistry(object):
try: del _params['profile_id']
except: pass
+ print _params['port']
s = session.X2GoSession(server=server, control_session=control_session,
profile_id=profile_id, profile_name=profile_name,
session_name=session_name,
diff --git a/x2go/utils.py b/x2go/utils.py
index 13b2fe6..7f182ed 100644
--- a/x2go/utils.py
+++ b/x2go/utils.py
@@ -272,18 +272,27 @@ def _convert_SessionProfileOptions_2_SessionParams(options):
_export = _params['export']
del _params['export']
- # fix for wrong export field usage in PyHoca-GUI/CLI and python-x2go before 20110923
- _export = _export.replace(",", ";")
+ if type(_export) is types.DictType:
- _export = _export.strip().strip('"').strip().strip(';').strip()
- _export_list = [ f for f in _export.split(';') if f ]
+ # since Python X2Go 0.5.0.0
+ _params['share_local_folders'] = _export.keys()
+
+ else:
+
+ # before Python X2Go 0.5.0.0 (analysing the INI file's format for the export field)
- _params['share_local_folders'] = []
- for _shared_folder in _export_list:
# fix for wrong export field usage in PyHoca-GUI/CLI and python-x2go before 20110923
- if not ":" in _shared_folder: _shared_folder = "%s:1" % _shared_folder
- if _shared_folder.split(":")[-1] == "1":
- _params['share_local_folders'].append(":".join(_shared_folder.split(":")[:-1]))
+ _export = _export.replace(",", ";")
+
+ _export = _export.strip().strip('"').strip().strip(';').strip()
+ _export_list = [ f for f in _export.split(';') if f ]
+
+ _params['share_local_folders'] = []
+ for _shared_folder in _export_list:
+ # fix for wrong export field usage in PyHoca-GUI/CLI and python-x2go before 20110923
+ if not ":" in _shared_folder: _shared_folder = "%s:1" % _shared_folder
+ if _shared_folder.split(":")[-1] == "1":
+ _params['share_local_folders'].append(":".join(_shared_folder.split(":")[:-1]))
if options['fullscreen']:
_params['geometry'] = 'fullscreen'
--
Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/python-x2go.git
More information about the x2go-commits
mailing list