This is an automated email from the git hooks/post-receive script. x2go pushed a change to branch master in repository x2gobroker. from 9c1a745 asthetic fix for last commit new 886768a Make sure bind_address and bind_port are correctly detected from /etc/default/x2gobroker-daemon and /etc/x2go/broker/defaults.cfg. new f3bb32d Move split_host_address() code into x2gobroker.utils. new d427069 typo fix new e78ef5e Report to log what the broker agent replied to us. new 551e80f rebase with prev new 7e96a3a Provide support for load-balancing to hosts that are all reachable over the same IP address, but different TCP/IP ports (e.g. docker instances or hosts behind a reverse NATed IPv4 gateway). This ended up in a rewrite of the complete selection_session() method of the base broker code. The 6 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Summary of changes: bin/x2gobroker | 20 +---- debian/changelog | 9 ++ lib/x2gobroker-agent.pl | 2 +- x2gobroker/agent.py | 4 + x2gobroker/brokers/base_broker.py | 162 ++++++++++++++++++++-------------- x2gobroker/brokers/inifile_broker.py | 5 ++ x2gobroker/utils.py | 29 ++++++ 7 files changed, 149 insertions(+), 82 deletions(-) -- Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/x2gobroker.git
This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository x2gobroker. commit 886768adfb703f41270098a7593d418ea08bbf89 Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Thu Sep 11 14:17:22 2014 +0200 Make sure bind_address and bind_port are correctly detected from /etc/default/x2gobroker-daemon and /etc/x2go/broker/defaults.cfg. --- bin/x2gobroker | 5 +++-- debian/changelog | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/bin/x2gobroker b/bin/x2gobroker index 034f780..12ea764 100755 --- a/bin/x2gobroker +++ b/bin/x2gobroker @@ -253,9 +253,10 @@ if __name__ == "__main__": bind_address = cmdline_args.bind bind_port = 22 else: - bind_address = None + bind_address = "0.0.0.0" bind_port = int(cmdline_args.bind) - bind_address = bind_address.lstrip('[').rstrip(']') + bind_address = bind_address.lstrip('[').rstrip(']') + cmdline_args.bind = "[{address}]:{port}".format(address=bind_address, port=bind_port) urls = () settings = {} diff --git a/debian/changelog b/debian/changelog index 91ef098..141d2ee 100644 --- a/debian/changelog +++ b/debian/changelog @@ -148,6 +148,8 @@ x2gobroker (0.0.3.0-0x2go1) UNRELEASED; urgency=low - Rename LICENSE file to COPYING. - X2Go Broker Agent: Test if queried username exists on the system before performing the query. + - Make sure bind_address and bind_port are correctly detected from + /etc/default/x2gobroker-daemon and /etc/x2go/broker/defaults.cfg. * debian/control: + Provide separate bin:package for SSH brokerage: x2gobroker-ssh. + Replace LDAP support with session brokerage support in LONG_DESCRIPTION. -- Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/x2gobroker.git
This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository x2gobroker. commit e78ef5ec8bd2b34e9b6b9dd0c5715d3852d76f36 Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Thu Sep 11 22:35:17 2014 +0200 Report to log what the broker agent replied to us. --- debian/changelog | 1 + x2gobroker/agent.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/debian/changelog b/debian/changelog index e7d18e7..4e79add 100644 --- a/debian/changelog +++ b/debian/changelog @@ -151,6 +151,7 @@ x2gobroker (0.0.3.0-0x2go1) UNRELEASED; urgency=low - Make sure bind_address and bind_port are correctly detected from /etc/default/x2gobroker-daemon and /etc/x2go/broker/defaults.cfg. - Move split_host_address() code into x2gobroker.utils. + - Report to log what the broker agent replied to us. * debian/control: + Provide separate bin:package for SSH brokerage: x2gobroker-ssh. + Replace LDAP support with session brokerage support in LONG_DESCRIPTION. diff --git a/x2gobroker/agent.py b/x2gobroker/agent.py index 2b6a873..0a43633 100644 --- a/x2gobroker/agent.py +++ b/x2gobroker/agent.py @@ -134,6 +134,7 @@ def _call_local_broker_agent(username, task, cmdline_args=[]): except OSError: pass + logger_broker.info('Broker agent answered: {answer}'.format(answer="; ".join(result))) if result[0].startswith('OK'): return (True, [ r for r in result[1:] if r ]) @@ -196,6 +197,8 @@ def _call_remote_broker_agent(username, task, cmdline_args=[], remote_agent=None if err: logger_broker.warning('Remote agent command (host: {remote_agent}) reported an error: {err}'.format(remote_agent=remote_agent['hostname'], err=err)) client.close() + if result: + logger_broker.info('Broker agent answered: {answer}'.format(answer="; ".join(result))) if result and result[0].startswith('OK'): return (True, [ r for r in result[1:] if r ]) else: -- Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/x2gobroker.git
This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository x2gobroker. commit 551e80fbd467c6ca2a3932dd8f107df0dc1bd365 Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Thu Sep 11 22:36:11 2014 +0200 rebase with prev --- x2gobroker/agent.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x2gobroker/agent.py b/x2gobroker/agent.py index 0a43633..ebca7d6 100644 --- a/x2gobroker/agent.py +++ b/x2gobroker/agent.py @@ -134,7 +134,8 @@ def _call_local_broker_agent(username, task, cmdline_args=[]): except OSError: pass - logger_broker.info('Broker agent answered: {answer}'.format(answer="; ".join(result))) + if result: + logger_broker.info('Broker agent answered: {answer}'.format(answer="; ".join(result))) if result[0].startswith('OK'): return (True, [ r for r in result[1:] if r ]) -- Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/x2gobroker.git
This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository x2gobroker. commit d427069fce11e16af198c8c5f00e0a416c78f720 Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Thu Sep 11 22:16:40 2014 +0200 typo fix --- lib/x2gobroker-agent.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/x2gobroker-agent.pl b/lib/x2gobroker-agent.pl index 693178a..ec8ca58 100755 --- a/lib/x2gobroker-agent.pl +++ b/lib/x2gobroker-agent.pl @@ -152,7 +152,7 @@ if(!defined $uidNumber) } elsif($uidNumber < 1000) { - die "operation on system user: $username (with UID number: $uidNumber"); + die "operation on system user: $username (with UID number: $uidNumber)"; } if($mode eq 'listsessions' && which('x2golistsessions')) -- Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/x2gobroker.git
This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository x2gobroker. commit f3bb32d68de84542083ceec093ee0f1ce8cc1333 Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Thu Sep 11 20:59:46 2014 +0200 Move split_host_address() code into x2gobroker.utils. --- bin/x2gobroker | 19 ++----------------- debian/changelog | 1 + x2gobroker/utils.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/bin/x2gobroker b/bin/x2gobroker index 12ea764..f9c878f 100755 --- a/bin/x2gobroker +++ b/bin/x2gobroker @@ -95,7 +95,7 @@ except ImportError: from x2gobroker import __VERSION__ from x2gobroker import __AUTHOR__ from x2gobroker.loggers import logger_broker, logger_access, logger_error, tornado_log_request -from x2gobroker.utils import drop_privileges +from x2gobroker.utils import drop_privileges, split_host_address interactive_mode_warning = False # check effective UID the broker runs as and complain appropriately... @@ -240,22 +240,7 @@ if __name__ == "__main__": if not daemon_logdir.endswith('/'): daemon_logdir += '/' - # some people just give the port but prepend a colon, webpy does not like this, so we strip if off - cmdline_args.bind = cmdline_args.bind.lstrip('*') - cmdline_args.bind = cmdline_args.bind.lstrip(':') - - if ':' in cmdline_args.bind: - bind_address, bind_port = cmdline_args.bind.rsplit(':', 1) - try: - bind_port = int(bind_port) - except TypeError: - # obviously we split an IPv6 address - bind_address = cmdline_args.bind - bind_port = 22 - else: - bind_address = "0.0.0.0" - bind_port = int(cmdline_args.bind) - bind_address = bind_address.lstrip('[').rstrip(']') + bind_address, bind_port = x2gobroker.utils.split_host_address(cmdline_args.bind, default_address="0.0.0.0") cmdline_args.bind = "[{address}]:{port}".format(address=bind_address, port=bind_port) urls = () diff --git a/debian/changelog b/debian/changelog index 141d2ee..e7d18e7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -150,6 +150,7 @@ x2gobroker (0.0.3.0-0x2go1) UNRELEASED; urgency=low performing the query. - Make sure bind_address and bind_port are correctly detected from /etc/default/x2gobroker-daemon and /etc/x2go/broker/defaults.cfg. + - Move split_host_address() code into x2gobroker.utils. * debian/control: + Provide separate bin:package for SSH brokerage: x2gobroker-ssh. + Replace LDAP support with session brokerage support in LONG_DESCRIPTION. diff --git a/x2gobroker/utils.py b/x2gobroker/utils.py index 8baaed4..f296b03 100644 --- a/x2gobroker/utils.py +++ b/x2gobroker/utils.py @@ -192,3 +192,32 @@ def drop_privileges(uid, gid): # set the new user's home directory as $HOME os.environ['HOME'] = pwd.getpwnam(uid).pw_dir + +def split_host_address(host, default_address=None, default_port=22): + + # do some stripping first... + host = host.strip() + host = host.lstrip('*') + host = host.lstrip(':') + + if ':' in host: + bind_address, bind_port = host.rsplit(':', 1) + try: + bind_port = int(bind_port) + except TypeError: + # obviously we split an IPv6 address + bind_address = host + bind_port = 22 + else: + if default_address is not None: + bind_address = default_address + bind_port = int(host) + elif default_port is not None: + bind_address = host + bind_port = default_port + else: + bind_address = host + bind_port = 0 + bind_address = bind_address.lstrip('[').rstrip(']') + + return bind_address, bind_port -- Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/x2gobroker.git
This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository x2gobroker. commit 7e96a3af36a232fb7e4fbe6222e336b69ffe5794 Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Thu Sep 11 22:38:17 2014 +0200 Provide support for load-balancing to hosts that are all reachable over the same IP address, but different TCP/IP ports (e.g. docker instances or hosts behind a reverse NATed IPv4 gateway). This ended up in a rewrite of the complete selection_session() method of the base broker code. --- debian/changelog | 5 ++ x2gobroker/brokers/base_broker.py | 162 ++++++++++++++++++++-------------- x2gobroker/brokers/inifile_broker.py | 5 ++ 3 files changed, 108 insertions(+), 64 deletions(-) diff --git a/debian/changelog b/debian/changelog index 4e79add..4f207a1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -152,6 +152,11 @@ x2gobroker (0.0.3.0-0x2go1) UNRELEASED; urgency=low /etc/default/x2gobroker-daemon and /etc/x2go/broker/defaults.cfg. - Move split_host_address() code into x2gobroker.utils. - Report to log what the broker agent replied to us. + - Provide support for load-balancing to hosts that are all reachable + over the same IP address, but different TCP/IP ports (e.g. docker + instances or hosts behind a reverse NATed IPv4 gateway). This ended + up in a rewrite of the complete selection_session() method of the + base broker code. * debian/control: + Provide separate bin:package for SSH brokerage: x2gobroker-ssh. + Replace LDAP support with session brokerage support in LONG_DESCRIPTION. diff --git a/x2gobroker/brokers/base_broker.py b/x2gobroker/brokers/base_broker.py index e92c7d8..b72576d 100644 --- a/x2gobroker/brokers/base_broker.py +++ b/x2gobroker/brokers/base_broker.py @@ -1053,19 +1053,81 @@ class X2GoBroker(object): try: profile = self.get_profile(profile_id) except x2gobroker.x2gobroker_exceptions.X2GoBrokerProfileException: - return {} + return { 'server': 'no-server-available', 'port': 22, } # if we have more than one server, pick one server randomly for X2Go Broker Agent queries server_list = profile[u'host'] + if len(server_list) == 0: + return { 'server': 'no-server-available', 'port': profile['sshport'], } + + # if everything below fails, this will be the X2Go Server's hostname that + # we will connect to... + server_name = server_list[0] + server_port = profile['sshport'] + + # try to retrieve contact to a remote broker agent remote_agent = self.get_remote_agent(profile_id) if remote_agent: agent_query_mode = ( remote_agent == u'LOCAL') and u'LOCAL' or u'SSH' + # check for already running sessions for the given user (if any is given) + session_list = [] + if remote_agent and username: + try: + success, session_list = x2gobroker.agent.list_sessions(username=username, remote_agent=remote_agent) + except x2gobroker.x2gobroker_exceptions.X2GoBrokerAgentException: + session_list = [] + + session_info = None + if session_list: + + # Obviously a remote broker agent reported an already running session + # on the / on one the available X2Go Server host(s) + + # When resuming, always select the first session in the list, + # there should only be one running/suspended session by design + # of X2Go brokerage (this may change in the future) + try: + running_sessions = [] + suspended_sessions = [] + for session_info in session_list: + if session_info.split('|')[4] == 'R': + running_sessions.append(session_info) + if session_info.split('|')[4] == 'S': + suspended_sessions.append(session_info) + + # we prefer suspended sessions over resuming sessions if we find sessions with both + # states of activity + if suspended_sessions: + session_info = suspended_sessions[0] + elif running_sessions: + session_info = running_sessions[0] + x2gobroker.agent.suspend_session(username=username, session_name=session_info.split('|')[1], remote_agent=remote_agent) + # this is the turn-around in x2gocleansessions, so waiting as along as the daemon + # that will suspend the session + time.sleep(2) + session_info = session_info.replace('|R|', '|S|') + + # only use the server's official hostname (as set on the server) + # if we know about the real/physical address of the server + _session_server_name = session_info.split('|')[3] + if profile.has_key('host={server_name}'.format(server_name=_session_server_name)): + server_name = _session_server_name + + except IndexError: + # FIXME: if we get here, we have to deal with a broken session info + # entry in the X2Go session database. -> AWFUL!!! + pass + # detect best X2Go server for this user if load balancing is configured - if remote_agent and len(server_list) >= 2 and username: + elif remote_agent and len(server_list) >= 2 and username: - # query remote agent for session info + # No running / suspended session was found on any of the available + # X2Go Servers. Thus, we will try to detect the best server for this + # load balanced X2Go Server farm. + + # query remote agent on how busy our servers are... busy_servers = None try: success, busy_servers = x2gobroker.agent.find_busy_servers(username=username, remote_agent=remote_agent) @@ -1078,20 +1140,23 @@ class X2GoBroker(object): # when detecting the server load we have to support handling of differing subdomains (config # file vs. server load returned by x2gobroker agent). Best approach: all members of a multi-node - # server farm either (a) do not have a subdomain in their hostname or (b) the subdomain is - # is identical. + # server farm either + # + # (a) do not have a subdomain in their hostname or + # (b) have an identical subdomain in their hostnames # Example: # # ts01, ts02 - hostnames as returned by agent # ts01.intern, ts02.intern - hostnames configured in session profile option ,,host'' - # -> this will result in the subdomain .intern being stripped off from the hostnames before detecting - # the best server for this user + # -> this will result in the subdomain .intern being stripped off from the hostnames before + # detecting the best server for this user ### NORMALIZE (=reduce to hostname only) X2Go server names (as found in config) if possible server_list_normalized, subdomains_config = x2gobroker.utils.normalize_hostnames(server_list) - ### NORMALIZE X2Go server names (as returned by x2gobroker agent)--only if the hostnames in the config share the same subdomain + ### NORMALIZE X2Go server names (as returned by broker agent)--only if the hostnames in + # the config share the same subdomain if len(subdomains_config) == 1: busy_servers_normalized, subdomains_agent = x2gobroker.utils.normalize_hostnames(busy_servers) @@ -1110,74 +1175,43 @@ class X2GoBroker(object): logger_broker.debug('base_broker.X2GoBroker.select_session(): load balancer analysis: {server_load}'.format(server_load=unicode(busy_server_list))) - best_server = busy_server_list[0][1] + server_name = busy_server_list[0][1] else: logger_broker.warning('base_broker.X2GoBroker.select_session(): no broker agent could be contacted, this does not look good. We tried these agent hosts: {agent_hosts}'.format(agent_hosts=unicode(server_list))) - if server_list: best_server = server_list[0] - else: return { 'server': 'no-server-available', 'port': profile[u'sshport'], } - else: - if server_list: best_server = server_list[0] - else: return { 'server': 'no-server-available', 'port': profile[u'sshport'], } + # detect best X2Go server for this user if load balancing is configured + elif len(server_list) >= 2: + + # no remote broker agent or no username? Let's play roulette then... + server_name = random.choice(server_list) + + ### + ### by now we should know the proper host to connect to... + ### - # if we have an explicit IP address for best_server, let's use that instead... + # if we have an explicit TCP/IP port server_name, let's use that instead... try: - best_server = profile['host={hostname}'.format(hostname=best_server)] + server_port = profile['sshport={hostname}'.format(hostname=server_name)] + logger_broker.debug('base_broker.X2GoBroker.select_session(): use physical server port: {port}'.format(port=server_port)) + except KeyError: + pass + + # if we have an explicit TCP/IP address for server_name, let's use that instead... + try: + server_name = profile['host={hostname}'.format(hostname=server_name)] + logger_broker.debug('base_broker.X2GoBroker.select_session(): use physical server address: {address}'.format(address=server_name)) except KeyError: pass selected_session = { - 'server': best_server, - 'port': profile[u'sshport'], + 'server': server_name, + 'port': server_port, } - # find already running/suspended sessions and resume the first one found - if remote_agent and server_list and username: - - try: - success, session_list = x2gobroker.agent.list_sessions(username=username, remote_agent=remote_agent) - except x2gobroker.x2gobroker_exceptions.X2GoBrokerAgentException: - session_list = [] - - if session_list: - - # if resuming, always select the first session in the list, there should only be one suspended session - try: - running_sessions = [] - suspended_sessions = [] - for session_info in session_list: - if session_info.split('|')[4] == 'R': - running_sessions.append(session_info) - if session_info.split('|')[4] == 'S': - suspended_sessions.append(session_info) - - # we prefer suspended sessions for resuming if we find sessions with both states of activity - if suspended_sessions: - session_info = suspended_sessions[0] - else: - session_info = running_sessions[0] - x2gobroker.agent.suspend_session(username=username, session_name=session_info.split('|')[1], remote_agent=remote_agent) - # this is the turn-around in x2gocleansessions, so waiting as along as the daemon that will suspend the session - time.sleep(2) - session_info = session_info.replace('|R|', '|S|') - server_name = session_info.split('|')[3] - - # if we have an explicit IP address for server_name, let's use that instead... - try: - server_name = profile['host={hostname}'.format(hostname=server_name)] - except KeyError: - pass - - selected_session.update({ - 'server': server_name, - 'session_info': session_info, - }) - - except IndexError: - - # FIXME: if we get here, we have to deal with a broker session info entry in the X2Go session database - pass + # are we resuming a running/suspended session? + if session_info is not None: + selected_session['session_info'] = session_info # define a remote SSH proxy agent if an SSH proxy host is used with this session profile if profile.has_key(u'sshproxyhost') and profile[u'sshproxyhost']: diff --git a/x2gobroker/brokers/inifile_broker.py b/x2gobroker/brokers/inifile_broker.py index 81a69cb..18341bf 100644 --- a/x2gobroker/brokers/inifile_broker.py +++ b/x2gobroker/brokers/inifile_broker.py @@ -87,11 +87,14 @@ class X2GoBroker(base.X2GoBroker): del profile[key] if key == 'host': _hosts = copy.deepcopy(profile[key]) + try: _default_sshport = int(profile['sshport']) + except TypeError: _default_sshport = 22 profile[key] = [] for host in _hosts: if re.match('^.*\ \(.*\)$', host): _hostname = host.split(' ')[0] _address = host.split(' ')[1][1:-1] + _address, _port = x2gobroker.utils.split_host_address(_address, default_port=_default_sshport) # test if _address is a valid hostname, a valid DNS name or an IPv4/IPv6 address if (re.match('(?!-)[A-Z\d-]{1,63}(?<!-)$', _hostname, flags=re.IGNORECASE) or \ @@ -100,6 +103,8 @@ class X2GoBroker(base.X2GoBroker): netaddr.valid_ipv4(_address) or netaddr.valid_ipv6(_address)): profile["host={hostname}".format(hostname=_hostname)] = _address + if _port != _default_sshport: + profile["sshport={hostname}".format(hostname=_hostname)] = _port profile[key].append(_hostname) else: -- Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/x2gobroker.git