This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository x2gobroker. commit a9bc46b1a69ad769aa04f7bd9d24efd795d9d73e Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Wed Dec 10 11:52:08 2014 +0100 Fix remote agent detection if one ore more X2Go Servers are offline and hostname does not match host address (plus unit test). --- debian/changelog | 2 ++ x2gobroker/agent.py | 21 ++++++------ x2gobroker/brokers/base_broker.py | 20 +++++++---- x2gobroker/tests/test_broker_agent.py | 59 ++++++++++++++++++++++++++++++--- 4 files changed, 81 insertions(+), 21 deletions(-) diff --git a/debian/changelog b/debian/changelog index d040e38..ad3eb5e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -215,6 +215,8 @@ x2gobroker (0.0.3.0-0x2go1) UNRELEASED; urgency=low deploying SSH keys. - Allow resuming sessions from servers even if one offline server has left bogus in the session DB (plus unit tests). + - Fix remote agent detection if one ore more X2Go Servers are offline and + hostname does not match host address (plus unit test). * 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 8f7ae9e..56c66fd 100644 --- a/x2gobroker/agent.py +++ b/x2gobroker/agent.py @@ -164,17 +164,17 @@ def _call_remote_broker_agent(username, task, cmdline_args=[], remote_agent=None """ if remote_agent is None: - logger_error.error('With the SSH agent-query-mode a remote agent host (hostname, port) has to be specified!') + logger_error.error('With the SSH agent-query-mode a remote agent host (hostname, hostaddr, port) has to be specified!') elif not remote_agent.has_key('host_key_policy'): remote_agent['host_key_policy'] = paramiko.WarningPolicy() - remote_hostname = remote_agent[u'hostname'] + remote_hostaddr = remote_agent[u'hostaddr'] if remote_agent.has_key(u'port'): remote_port = int(remote_agent[u'port']) else: remote_port = 22 - if x2gobroker.utils.portscan(remote_hostname, remote_port): + if x2gobroker.utils.portscan(remote_hostaddr, remote_port): cmd_line = [ '{x2gobroker_agent_binary}'.format(x2gobroker_agent_binary=x2gobroker.defaults.X2GOBROKER_AGENT_CMD), '{username}'.format(username=username), @@ -192,7 +192,7 @@ def _call_remote_broker_agent(username, task, cmdline_args=[], remote_agent=None if os.path.exists(os.path.expanduser("~/.ssh/known_hosts")): client.load_host_keys(os.path.expanduser("~/.ssh/known_hosts")) client.set_missing_host_key_policy(remote_agent['host_key_policy']) - client.connect(remote_hostname, remote_port, remote_username, look_for_keys=True, allow_agent=True) + client.connect(remote_hostaddr, remote_port, remote_username, look_for_keys=True, allow_agent=True) result = [] ssh_transport = client.get_transport() @@ -213,11 +213,11 @@ def _call_remote_broker_agent(username, task, cmdline_args=[], remote_agent=None else: return (False, []) except paramiko.AuthenticationException: - raise x2gobroker.x2gobroker_exceptions.X2GoBrokerAgentException('Authentication to remote X2Go Broker Agent Host failed (user: {user}, hostname: {hostname}, port: {port}) failed'.format(user=remote_username, hostname=remote_hostname, port=remote_port)) + raise x2gobroker.x2gobroker_exceptions.X2GoBrokerAgentException('Authentication to remote X2Go Broker Agent Host failed (user: {user}, hostname: {hostname}, host address: {hostaddr}, port: {port}) failed'.format(user=remote_username, hostname=remote_hostname, hostaddr=remote_hostaddr, port=remote_port)) except (paramiko.SSHException, paramiko.BadHostKeyException, socket.error): - raise x2gobroker.x2gobroker_exceptions.X2GoBrokerAgentException('Query to remote X2Go Broker Agent (user: {user}, hostname: {hostname}, port: {port}) failed'.format(user=remote_username, hostname=remote_hostname, port=remote_port)) + raise x2gobroker.x2gobroker_exceptions.X2GoBrokerAgentException('Query to remote X2Go Broker Agent (user: {user}, hostname: {hostname}, host address: {hostaddr}, port: {port}) failed'.format(user=remote_username, hostname=remote_hostname, hostaddr=remote_hostaddr, port=remote_port)) else: - raise x2gobroker.x2gobroker_exceptions.X2GoBrokerAgentException('Could not ping remote X2Go Broker Agent host ({remote_hostname})'.format(remote_hostname=remote_hostname)) + raise x2gobroker.x2gobroker_exceptions.X2GoBrokerAgentException('Could not ping remote X2Go Broker Agent host: {hostname} ({hostaddr})'.format(hostname=remote_hostname, hostaddr=remote_hostaddr)) def ping(remote_agent=None, **kwargs): @@ -233,7 +233,7 @@ def ping(remote_agent=None, **kwargs): return _call_local_broker_agent(username)[0] else: return remote_agent is not None and \ - x2gobroker.utils.portscan(remote_agent['hostname'], remote_agent['port']) and \ + (x2gobroker.utils.portscan(remote_agent['hostname'], remote_agent['port']) or x2gobroker.utils.portscan(remote_agent['hostname'], remote_agent['port'])) and \ _call_remote_broker_agent(username, task='ping', remote_agent=remote_agent)[0] tasks['ping'] = ping @@ -364,13 +364,14 @@ def delete_authorized_key(username, pubkey_hash, authorized_keys_file='%h/.x2go/ """ # this is for the logger output if remote_agent in ('LOCAL', None): - _hostname = 'LOCAL' + _hostname = _hostaddr = 'LOCAL' else: _hostname = remote_agent['hostname'] + _hostaddr = remote_agent['hostaddr'] if delay_deletion > 0: delayed_execution(delete_authorized_key, delay=delay_deletion, username=username, pubkey_hash=pubkey_hash, authorized_keys_file=authorized_keys_file, remote_agent=remote_agent, ) - logger_broker.debug('Scheduled deletion of authorized key in {delay}s: user={user}, host={host}'.format(delay=delay_deletion, user=username, host=_hostname)) + logger_broker.debug('Scheduled deletion of authorized key in {delay}s: user={user}, hostname={hostname}, hostaddr={hostaddr}'.format(delay=delay_deletion, user=username, hostname=_hostname, hostaddr=_hostaddr)) else: return call_broker_agent(username, task='delauthkey', cmdline_args=[pubkey_hash, authorized_keys_file, ], remote_agent=remote_agent, **kwargs) tasks['delauthkey'] = delete_authorized_key diff --git a/x2gobroker/brokers/base_broker.py b/x2gobroker/brokers/base_broker.py index 4a6cb00..ebcf4af 100644 --- a/x2gobroker/brokers/base_broker.py +++ b/x2gobroker/brokers/base_broker.py @@ -1008,14 +1008,18 @@ class X2GoBroker(object): while server_list: - remote_agent_server = server_list[-1] + remote_agent_hostname = server_list[-1] + remote_agent_hostaddr = remote_agent_hostname remote_agent_port = profile[u'sshport'] - if profile.has_key('sshport={ras}'.format(ras=remote_agent_server)): - remote_agent_port = profile["sshport={ras}".format(ras=remote_agent_server)] - if profile.has_key('host={ras}'.format(ras=remote_agent_server)): - remote_agent_server = profile["host={ras}".format(ras=remote_agent_server)] + if profile.has_key('sshport={hostname}'.format(hostname=remote_agent_hostname)): + remote_agent_port = profile["sshport={hostname}".format(hostname=remote_agent_hostname)] + if profile.has_key('host={hostname}'.format(hostname=remote_agent_hostname)): + remote_agent_hostaddr = profile["host={hostname}".format(hostname=remote_agent_hostname)] - remote_agent = {u'hostname': remote_agent_server, u'port': remote_agent_port, } + remote_agent = { + u'hostname': remote_agent_hostname, + u'hostaddr': remote_agent_hostaddr, + u'port': remote_agent_port, } try: if x2gobroker.agent.ping(remote_agent=remote_agent): @@ -1397,6 +1401,7 @@ class X2GoBroker(object): if profile.has_key(u'sshproxyhost') and profile[u'sshproxyhost']: remote_sshproxy_agent = { u'hostname': profile[u'sshproxyhost'], + u'hostaddr': profile[u'sshproxyhost'], u'port': "22" } if profile.has_key(u'sshproxyport') and profile[u'sshproxyport']: @@ -1410,7 +1415,8 @@ class X2GoBroker(object): # let's use the chosen server_name if remote_agent is reachable via SSH if type(remote_agent) is types.DictType: remote_agent = { - u'hostname': selected_session[u'server'], + u'hostname': server_name, + u'hostaddr': server_addr, u'port': selected_session[u'port'], } diff --git a/x2gobroker/tests/test_broker_agent.py b/x2gobroker/tests/test_broker_agent.py index a7cc26c..e9ead47 100644 --- a/x2gobroker/tests/test_broker_agent.py +++ b/x2gobroker/tests/test_broker_agent.py @@ -206,7 +206,7 @@ broker-agent-query-mode = SSH i = 0 while i < 10: _remoteagent5 = inifile_backend.get_remote_agent('testprofile5') - self.assertTrue( _remoteagent5 == {u'hostname': '10.0.2.4', u'port': 22} or _remoteagent5 == {u'hostname': '10.0.2.5', u'port': 22} ) + self.assertTrue( _remoteagent5 == {u'hostname': 'host1.mydomain', u'hostaddr': '10.0.2.4', u'port': 22} or _remoteagent5 == {u'hostname': 'host2.mydomain', u'hostaddr': '10.0.2.5', u'port': 22} ) _session5 = inifile_backend.select_session('testprofile5', 'foo5N') self.assertTrue( _session5 == {'port': 22, 'server': '10.0.2.4', } or _session5 == {'port': 22, 'server': '10.0.2.5', } ) i += 1 @@ -220,7 +220,7 @@ broker-agent-query-mode = SSH self.assertTrue( _profile6['host'][0] in ('host1.mydomain', 'host2.mydomain') ) self.assertTrue( not _profile6.has_key('status') ) _remoteagent6 = inifile_backend.get_remote_agent('testprofile6') - self.assertTrue( _remoteagent6 == {u'hostname': '10.0.2.4', u'port': 23467} or _remoteagent6 == {u'hostname': '10.0.2.5', u'port': 23467} ) + self.assertTrue( _remoteagent6 == {u'hostname': 'host1.mydomain', u'hostaddr': '10.0.2.4', u'port': 23467} or _remoteagent6 == {u'hostname': 'host2.mydomain', u'hostaddr': '10.0.2.5', u'port': 23467} ) _session6 = inifile_backend.select_session('testprofile6', 'foo6N') self.assertTrue( _session6 == {'port': 23467, 'server': '10.0.2.4', } or _session6 == {'port': 23467, 'server': '10.0.2.5', } ) @@ -232,7 +232,7 @@ broker-agent-query-mode = SSH i = 0 while i < 10: _remoteagent7 = inifile_backend.get_remote_agent('testprofile7') - self.assertTrue( _remoteagent7 == {u'hostname': 'docker-server', u'port': 22001} or _remoteagent7 == {u'hostname': 'docker-server', u'port': 22002} ) + self.assertTrue( _remoteagent7 == {u'hostname': 'docker-vm-1', u'hostaddr': 'docker-server', u'port': 22001} or _remoteagent7 == {u'hostname': 'docker-vm-2', u'hostaddr': 'docker-server', u'port': 22002} ) _session7 = inifile_backend.select_session('testprofile7', 'foo7N') self.assertTrue( _session7 == {'port': 22001, 'server': 'docker-server', } or _session7 == {'port': 22001, 'server': 'docker-server', } ) i += 1 @@ -245,7 +245,7 @@ broker-agent-query-mode = SSH i = 0 while i < 10: _remoteagent8 = inifile_backend.get_remote_agent('testprofile8') - self.assertTrue( _remoteagent8 == {u'hostname': 'docker-server', u'port': 22000} or _remoteagent8 == {u'hostname': 'docker-server', u'port': 22001} or _remoteagent8 == {u'hostname': 'docker-server', u'port': 22002} ) + self.assertTrue( _remoteagent8 == {u'hostname': 'docker-vm-0', u'hostaddr': 'docker-server', u'port': 22000} or _remoteagent8 == {u'hostname': 'docker-vm-1', u'hostaddr': 'docker-server', u'port': 22001} or _remoteagent8 == {u'hostname': 'docker-vm-2', u'hostaddr': 'docker-server', u'port': 22002} ) _session8 = inifile_backend.select_session('testprofile8', 'foo8N') self.assertTrue( _session8 == {'port': 22000, 'server': 'docker-server', } or _session8 == {'port': 22001, 'server': 'docker-server', } or _session8 == {'port': 22001, 'server': 'docker-server', } ) i += 1 @@ -433,6 +433,57 @@ broker-autologin = true x2gobroker.utils.portscan = _save_portscan time.sleep = _save_time_sleep + def test_get_remote_agent_with_offline_servers(self): + + _save_local_broker_agent_call = x2gobroker.agent._call_local_broker_agent + _save_remote_broker_agent_call = x2gobroker.agent._call_remote_broker_agent + _save_portscan = x2gobroker.utils.portscan + + def _call_testsuite_broker_agent(username, task, cmdline_args=[], remote_agent=None): + + if task == 'ping': + return True, [] + + return False, [] + + def _fake_portscan(addr, port=22): + if addr == 'host3.internal': + return False + if addr.startswith('downhost'): + return False + return True + + def _fake_time_sleep(sec): + pass + + x2gobroker.agent._call_local_broker_agent = _call_testsuite_broker_agent + x2gobroker.agent._call_remote_broker_agent = _call_testsuite_broker_agent + x2gobroker.utils.portscan = _fake_portscan + time.sleep = _fake_time_sleep + + _session_profiles = """ +[DEFAULT] +command = MATE +user = foo +broker-agent-query-mode = NONE + +[testprofile1] +name = testprofile1 +host = downhost1.internal (10.0.2.11), host2.internal (10.0.2.12), host3.internal (10.0.2.13) +broker-agent-query-mode = SSH +broker-portscan-x2goservers = true + +""" + tf = tempfile.NamedTemporaryFile() + print >> tf, _session_profiles + tf.seek(0) + inifile_backend = inifile.X2GoBroker(profile_config_file=tf.name) + + i = 0 + while i < 50: + remote_agent = inifile_backend.get_remote_agent('testprofile1') + self.assertTrue ( remote_agent['hostaddr'] != '10.0.2.11') + i += 1 def test_suite(): from unittest import TestSuite, makeSuite -- Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/x2gobroker.git