This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository x2gobroker. commit dcf76802471010339d3c3e886ea09bd89b7acd6e Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Mon Mar 30 13:27:05 2015 +0200 Various improvements / fixes for session selection via the load checker daemon. --- debian/changelog | 2 ++ x2gobroker/brokers/base_broker.py | 69 +++++++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/debian/changelog b/debian/changelog index b9f05bc..dc89706 100644 --- a/debian/changelog +++ b/debian/changelog @@ -264,6 +264,8 @@ x2gobroker (0.0.3.0-0x2go1) UNRELEASED; urgency=low and number of sessions as values. - Fix X2GoBroker.use_load_checker(): Obtain broker-* option via X2GoBroker.get_profile_broker(), not via X2GoBroker.get_profile(). + - Various improvements / fixes for session selection via the load checker + daemon. * 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 2bcf255..94c351e 100644 --- a/x2gobroker/brokers/base_broker.py +++ b/x2gobroker/brokers/base_broker.py @@ -1067,6 +1067,20 @@ class X2GoBroker(object): server_list = profile[u'host'] random.shuffle(server_list) + # if the load checker is in use for this profile, let's retrieve the available server loads here + # because: + # - it is fast... + # - if hosts are marked as "HOST-UNREACHABLE", we don't have to attempt + # using them as a remote agent (reduce delays at session + # startup/resumption) + # - the retrieved load factors can be re-used in X2GoBroker.select_session(). + load_factors = {} + if self.use_load_checker(profile_id): + load_factors = x2gobroker.loadchecker.check_load(self.backend_name, profile_id) + for h in [ _h for _h in load_factors.keys() if type(load_factors[_h]) != types.LongType ]: + if h in server_list: + server_list.remove(h) + for agent in exclude_agents: if agent['hostname'] in server_list: server_list.remove(agent['hostname']) @@ -1097,6 +1111,9 @@ class X2GoBroker(object): if not remote_agent: logger_broker.warning('base_broker.X2GoBroker.get_remote_agent(): failed to allocate any broker agent (query-mode: {query_mode}, remote_agent: {remote_agent})'.format(query_mode=agent_query_mode, remote_agent=remote_agent)) + else: + # ship the load_factors retrieved from the load checker service in the remote_agent dict + remote_agent[u'load_factors'] = load_factors elif agent_query_mode == u'LOCAL': # use a non-False value here, not used anywhere else... @@ -1310,7 +1327,7 @@ class X2GoBroker(object): server_name = server_list[0] server_port = profile['sshport'] - # try to retrieve contact to a remote broker agent + # try to retrieve a remote broker agent remote_agent = self.get_remote_agent(profile_id) # check for already running sessions for the given user (if any is given) @@ -1328,14 +1345,18 @@ class X2GoBroker(object): _save_server_list = None _save_busy_servers = None initial_server_list = copy.deepcopy(server_list) + while not selected_session and server_list: + if session_list: + matching_server_names = x2gobroker.utils.matching_hostnames(server_list, [ si.split('|')[3] for si in session_list ]) + if remote_agent == {}: # we failed to contact any remote agent, so it is very likely, that all servers are down... server_list = [] - elif session_list: + elif session_list and matching_server_names: # Obviously a remote broker agent reported an already running session # on the / on one the available X2Go Server host(s) @@ -1347,8 +1368,6 @@ class X2GoBroker(object): running_sessions = [] suspended_sessions = [] - matching_server_names = x2gobroker.utils.matching_hostnames(server_list, [ si.split('|')[3] for si in session_list ]) - for session_info in session_list: if session_info.split('|')[3] in matching_server_names: if session_info.split('|')[4] == 'R': @@ -1406,7 +1425,10 @@ class X2GoBroker(object): # status) if busy_servers is None: try: - success, busy_servers = x2gobroker.agent.find_busy_servers(username=username, remote_agent=remote_agent) + if remote_agent['load_factors']: + success, busy_servers = x2gobroker.agent.get_servers(username=username, remote_agent=remote_agent) + else: + success, busy_servers = x2gobroker.agent.find_busy_servers(username=username, remote_agent=remote_agent) except x2gobroker.x2gobroker_exceptions.X2GoBrokerAgentException: pass @@ -1444,7 +1466,8 @@ class X2GoBroker(object): server_list = server_list_normalized busy_servers = busy_servers_normalized - # the list of busy_servers only shows servers with session, but not those servers that are entirely idle... + # the list of busy_servers only shows servers with sessions, but not those servers that are entirely idle... + for server in server_list: if server not in busy_servers.keys(): busy_servers[server] = 0 @@ -1454,21 +1477,29 @@ class X2GoBroker(object): if busy_server not in server_list: del busy_servers[busy_server] + # dynamic load-balancing via load checker service + if remote_agent['load_factors']: - # dynamic load-balancing - if self.use_load_checker(profile_id): + load_factors = remote_agent['load_factors'] busy_servers_temp = copy.deepcopy(busy_servers) - load_factors = x2gobroker.loadchecker.checkload(self.backend_name, profile_id) - if load_factors: - for busy_server in busy_servers_temp.keys(): - # FIXME: this may need love later for peculiar multi-farm setups with non-FQDN hostnames in session profile configurations - if busy_server in load_factors.keys() and type(load_factors[busy_server]) == types.LongType: - # do the load-factor / relX2GoServerUsage calculation here... - busy_servers_temp[busy_server] = load_factors[busy_server] / busy_servers[busy_server] - else: - # ignore the load checker, results are garbage... - busy_servers_temp = None - break + + for busy_server in busy_servers_temp.keys(): + if busy_server in load_factors.keys() and type(load_factors[busy_server]) is not types.LongType: + # if a host cannot report its load, let's ignore it... + del busy_servers_temp[busy_server] + + elif busy_server in load_factors.keys() and ( type(load_factors[busy_server]) is types.LongType or busy_servers[busy_server] == 0): + + # when using the load checker service, then busy_servers contains the number of sessions per host + + # do the load-factor / numSessions calculation here... (avoid divison-by-zero by adding +1 to + # the number of sessions here) + busy_servers_temp[busy_server] = 1.0 / (load_factors[busy_server] / ( busy_servers[busy_server] +1)) + + else: + # ignore the load checker, results are garbage... + busy_servers_temp = None + break if busy_servers_temp is not None: busy_servers = copy.deepcopy(busy_servers_temp) -- Alioth's /srv/git/code.x2go.org/x2gobroker.git//..//_hooks_/post-receive-email on /srv/git/code.x2go.org/x2gobroker.git