This is an automated email from the git hooks/post-receive script. x2go pushed a change to branch master in repository x2gobroker. from 2ab71c5 LoadCheckerServiceHandler(): Add line breaks in per-profile output. Return nothing if the load checker service is unreachable. new 5456c12 agent.py: Let get_servers() return a dictionary with hostnames as keys and number of sessions as values. new db17a98 rename checkload() -> check_load in agent.py/loadchecker.py, handle reported errors in loadchecker.check_load() new 9226a59 agent.py: Return meaningful errors in check_load() function within the returned data structure new 53aa3c3 Fix X2GoBroker.use_load_checker(): Obtain broker-* option via X2GoBroker.get_profile_broker(), not via X2GoBroker.get_profile(). new dcf7680 Various improvements / fixes for session selection via the load checker daemon. The 5 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: debian/changelog | 6 +++ x2gobroker/agent.py | 20 +++++++--- x2gobroker/brokers/base_broker.py | 75 ++++++++++++++++++++++++++----------- x2gobroker/loadchecker.py | 41 +++++++++++++------- 4 files changed, 102 insertions(+), 40 deletions(-) -- Alioth's /srv/git/code.x2go.org/x2gobroker.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 5456c1237a1904ae433c4f0d41c65f84d8923e9d Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Mon Mar 30 13:19:18 2015 +0200 agent.py: Let get_servers() return a dictionary with hostnames as keys and number of sessions as values. --- debian/changelog | 2 ++ x2gobroker/agent.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 2c82fe3..deb891f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -260,6 +260,8 @@ x2gobroker (0.0.3.0-0x2go1) UNRELEASED; urgency=low cycle summary. - LoadCheckerServiceHandler(): Add line breaks in per-profile output. Return nothing if the load checker service is unreachable. + - agent.py: Let get_servers() return a dictionary with hostnames as keys + and number of sessions as values. * 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 92ed427..aa73a87 100644 --- a/x2gobroker/agent.py +++ b/x2gobroker/agent.py @@ -526,7 +526,17 @@ def get_servers(username, remote_agent=None, logger=None, **kwargs): if logger is None: logger = logger_broker - return call_broker_agent(username, task='getservers', remote_agent=remote_agent, logger=logger, **kwargs) + result = {} + success, lines = call_broker_agent(username, task='getservers', remote_agent=remote_agent, logger=logger, **kwargs) + if success: + for line in lines: + try: + if " " in line: + server, num_sessions = line.split(" ", 1) + result[server] = int(num_sessions) + except ValueError: + pass + return success, result tasks['getservers'] = get_servers -- Alioth's /srv/git/code.x2go.org/x2gobroker.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 db17a98b723fb5bcc62b00f904903bb5abac4ba5 Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Mon Mar 30 13:22:05 2015 +0200 rename checkload() -> check_load in agent.py/loadchecker.py, handle reported errors in loadchecker.check_load() --- x2gobroker/agent.py | 4 ++-- x2gobroker/loadchecker.py | 41 +++++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/x2gobroker/agent.py b/x2gobroker/agent.py index aa73a87..203b66c 100644 --- a/x2gobroker/agent.py +++ b/x2gobroker/agent.py @@ -400,7 +400,7 @@ def find_busy_servers(username, remote_agent=None, logger=None, **kwargs): tasks['findbusyservers'] = find_busy_servers -def checkload(remote_agent=None, logger=None, **kwargs): +def check_load(remote_agent=None, logger=None, **kwargs): """\ Query X2Go Broker Agent for a summary of system load specific parameters. @@ -440,7 +440,7 @@ def checkload(remote_agent=None, logger=None, **kwargs): pass return load_factor -tasks['checkload'] = checkload +tasks['checkload'] = check_load def add_authorized_key(username, pubkey_hash, authorized_keys_file='%h/.x2go/authorized_keys', remote_agent=None, logger=None, **kwargs): """\ diff --git a/x2gobroker/loadchecker.py b/x2gobroker/loadchecker.py index 61ada88..435e53e 100644 --- a/x2gobroker/loadchecker.py +++ b/x2gobroker/loadchecker.py @@ -29,49 +29,62 @@ import x2gobroker.config from x2gobroker.loggers import logger_broker -def checkload(backend, profile_id, hostname=None): +def check_load(backend, profile_id, hostname=None): s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - logger_broker.debug('loadchecker.checkload(): connecting to load checker service socket {socket}'.format(socket=x2gobroker.defaults.X2GOBROKER_LOADCHECKER_SOCKET)) + logger_broker.debug('loadchecker.check_load(): connecting to load checker service socket {socket}'.format(socket=x2gobroker.defaults.X2GOBROKER_LOADCHECKER_SOCKET)) try: s.connect(x2gobroker.defaults.X2GOBROKER_LOADCHECKER_SOCKET) except socket.error, e: - logger_broker.error('loadchecker.checkload(): failure when connecting to the load checker service socket {socket}: {errmsg}'.format(socket=x2gobroker.defaults.X2GOBROKER_LOADCHECKER_SOCKET, errmsg=str(e))) + logger_broker.error('loadchecker.check_load(): failure when connecting to the load checker service socket {socket}: {errmsg}'.format(socket=x2gobroker.defaults.X2GOBROKER_LOADCHECKER_SOCKET, errmsg=str(e))) if hostname is not None: load_factor = 'LOAD-UNAVAILABLE' - logger_broker.debug('loadchecker.checkload(): sending backend={backend}, profile_id={profile_id}, hostname={hostname} to load checker service'.format(backend=backend, profile_id=profile_id, hostname=hostname)) + logger_broker.debug('loadchecker.check_load(): sending backend={backend}, profile_id={profile_id}, hostname={hostname} to load checker service'.format(backend=backend, profile_id=profile_id, hostname=hostname)) try: s.send('{backend}\r{profile_id}\r{hostname}\n'.format(backend=backend, profile_id=profile_id, hostname=hostname)) load_factor = s.recv(1024) s.close() except socket.error, e: - logger_broker.error('loadchecker.checkload(): failure when sending data to the load checker service socket {socket}: {errmsg}'.format(socket=x2gobroker.defaults.X2GOBROKER_LOADCHECKER_SOCKET, errmsg=str(e))) + logger_broker.error('loadchecker.check_load(): failure when sending data to the load checker service socket {socket}: {errmsg}'.format(socket=x2gobroker.defaults.X2GOBROKER_LOADCHECKER_SOCKET, errmsg=str(e))) if load_factor.startswith('LOAD-UNAVAILABLE'): - logger_broker.warning('loadchecker.checkload(): load unavailable for backend={backend}, profile_id={profile_id}, hostname={hostname}'.format(backend=backend, profile_id=profile_id, hostname=hostname)) - return None + logger_broker.warning('loadchecker.check_load(): load unavailable for backend={backend}, profile_id={profile_id}, hostname={hostname}'.format(backend=backend, profile_id=profile_id, hostname=hostname)) + return 'LOAD-UNAVAILABLE' + + try: + load_factor = long(load_factor) + except ValueError: + logger_broker.warning('loadchecker.check_load(): load data for backend={backend}, profile_id={profile_id}, hostname={hostname} contained bogus (»{lf}«)'.format(backend=backend, profile_id=profile_id, hostname=hostname, lf=load_factor)) + return 'LOAD-DATA-BOGUS' - logger_broker.info('loadchecker.checkload(): load factor for backend={backend}, profile_id={profile_id}, hostname={hostname} is: {lf}'.format(backend=backend, profile_id=profile_id, hostname=hostname, lf=load_factor)) + logger_broker.info('loadchecker.check_load(): load factor for backend={backend}, profile_id={profile_id}, hostname={hostname} is: {lf}'.format(backend=backend, profile_id=profile_id, hostname=hostname, lf=load_factor)) return load_factor else: raw_output = "" - logger_broker.debug('loadchecker.checkload(): sending backend={backend}, profile_id={profile_id} to load checker service'.format(backend=backend, profile_id=profile_id, hostname=hostname)) + logger_broker.debug('loadchecker.check_load(): sending backend={backend}, profile_id={profile_id} to load checker service'.format(backend=backend, profile_id=profile_id, hostname=hostname)) try: s.send('{backend}\r{profile_id}\r\n'.format(backend=backend, profile_id=profile_id)) raw_output = s.recv(1024) s.close() except socket.error, e: - logger_broker.error('loadchecker.checkload(): failure when sending data to the load checker service socket {socket}: {errmsg}'.format(socket=x2gobroker.defaults.X2GOBROKER_LOADCHECKER_SOCKET, errmsg=str(e))) + logger_broker.error('loadchecker.check_load(): failure when sending data to the load checker service socket {socket}: {errmsg}'.format(socket=x2gobroker.defaults.X2GOBROKER_LOADCHECKER_SOCKET, errmsg=str(e))) load_factors = {} items = raw_output.split('\n') for item in items: if ":" in item: key, val = item.split(':', 1) - load_factors[key] = val - - logger_broker.info('loadchecker.checkload(): load metrics for backend={backend}, profile_id={profile_id} are: {lf}'.format(backend=backend, profile_id=profile_id, hostname=hostname, lf=load_factors)) + try: + if val not in ('HOST-UNREACHABLE', 'LOAD-UNAVAILABLE', 'LOAD-DATA-BOGUS'): + load_factors[key] = long(val) + else: + load_factors[key] = val + except ValueError: + logger_broker.warning('loadchecker.check_load(): load data for backend={backend}, profile_id={profile_id}, hostname={hostname} contained bogus (»{lf}«)'.format(backend=backend, profile_id=profile_id, hostname=hostname, lf=val)) + load_factors[key] = 'LOAD-DATA-BOGUS' + + logger_broker.info('loadchecker.check_load(): load metrics for backend={backend}, profile_id={profile_id} are: {lf}'.format(backend=backend, profile_id=profile_id, hostname=hostname, lf=load_factors)) return load_factors @@ -176,7 +189,7 @@ class LoadChecker(threading.Thread): self.server_load[backend][profile_id] = {} remote_agents = self.brokers[backend].get_all_remote_agents(profile_id) for remote_agent in remote_agents: - _load_factor = x2gobroker.agent.checkload(remote_agent, logger=self.logger) + _load_factor = x2gobroker.agent.check_load(remote_agent, logger=self.logger) num_queries += 1 if _load_factor is None: if self.logger: self.logger.info('LoadChecker.loadchecker(): backend={backend}, profile_id={profile_id}, hostname={hostname}, load factor not available'.format(backend=backend, profile_id=profile_id, hostname=remote_agent[u'hostname'])) -- Alioth's /srv/git/code.x2go.org/x2gobroker.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 9226a5906ef898d9b56a1dad3890395ed98e5fd8 Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Mon Mar 30 13:23:20 2015 +0200 agent.py: Return meaningful errors in check_load() function within the returned data structure --- x2gobroker/agent.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x2gobroker/agent.py b/x2gobroker/agent.py index 203b66c..b5c6b06 100644 --- a/x2gobroker/agent.py +++ b/x2gobroker/agent.py @@ -422,7 +422,7 @@ def check_load(remote_agent=None, logger=None, **kwargs): _success, _load_params = call_broker_agent('foo', task='checkload', remote_agent=remote_agent, logger=logger, **kwargs) except x2gobroker.x2gobroker_exceptions.X2GoBrokerAgentException, e: logger.error('querying remote agent on host {hostname} failed: {errmsg}'.format(hostname=remote_agent[u'hostname'], errmsg=str(e))) - return None + return "HOST-UNREACHABLE" p = {} for _param in _load_params: @@ -437,7 +437,7 @@ def check_load(remote_agent=None, logger=None, **kwargs): load_factor = long( ( (p['memAvail']/1000) * p['numCPU'] * p['typeCPU'] * 100 ) / p['loadavgXX'] ) except KeyError: - pass + return "LOAD-DATA-BOGUS" return load_factor tasks['checkload'] = check_load -- Alioth's /srv/git/code.x2go.org/x2gobroker.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 53aa3c3cffc0792dec0f9a80f392f806acf931cb Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Mon Mar 30 13:26:16 2015 +0200 Fix X2GoBroker.use_load_checker(): Obtain broker-* option via X2GoBroker.get_profile_broker(), not via X2GoBroker.get_profile(). --- debian/changelog | 2 ++ x2gobroker/brokers/base_broker.py | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index deb891f..b9f05bc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -262,6 +262,8 @@ x2gobroker (0.0.3.0-0x2go1) UNRELEASED; urgency=low nothing if the load checker service is unreachable. - agent.py: Let get_servers() return a dictionary with hostnames as keys and number of sessions as values. + - Fix X2GoBroker.use_load_checker(): Obtain broker-* option via + X2GoBroker.get_profile_broker(), not via X2GoBroker.get_profile(). * 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 bec6d03..2bcf255 100644 --- a/x2gobroker/brokers/base_broker.py +++ b/x2gobroker/brokers/base_broker.py @@ -748,12 +748,14 @@ class X2GoBroker(object): # it is enabled for the broker backend... if self.get_use_load_checker(): - _profile = self.get_profile(profile_id) + _profile_broker = self.get_profile_broker(profile_id) # it is not explicitly disabled per session profile definition - if _profile and _profile.has_key(u'broker-use-load-checker') and _profile['broker-use-load-checker'] is False: + if _profile_broker and _profile_broker.has_key(u'broker-use-load-checker') and _profile_broker['broker-use-load-checker'] not in ('1', 'true'): return False + _profile = self.get_profile(profile_id) + # more than one host is defined in the session profile if len(_profile[u'host']) < 2: return False -- Alioth's /srv/git/code.x2go.org/x2gobroker.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 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