def from_config_dict(cls, name, obj): """Build a Pool object from a config dict args: name: string, name of the pool obj: dict, config dict """ ############################ ### mandatory parameters ### ############################ ### monitor if obj['monitor'] not in monitors.registered: log_msg = 'unknown monitor "{}"'.format(obj['monitor']) LOG.error(log_msg) raise Error(log_msg) else: monitor_name = obj['monitor'] if 'monitor_params' in obj: if not obj['monitor_params']: log_msg = 'monitor_params should not be empty' LOG.error(log_msg) raise Error(log_msg) monitor_params = obj['monitor_params'] else: monitor_params = {} monitor = monitors.registered[monitor_name](**monitor_params) ### lb_method lb_method = obj['lb_method'] ### members members = {} # validate "members" key is present and not empty if not 'members' in obj or not obj['members']: log_msg = ('configuration dictionary must contain ' 'a non-empty "members" key') LOG.error(log_msg) raise Error(log_msg) for member_ip in obj['members']: member_name = obj['members'][member_ip]['name'] weight = obj['members'][member_ip]['weight'] region = None # if topology round robin method is used # set region on the pool member if lb_method == 'twrr': region = topology.get_region(member_ip, config.TOPOLOGY_MAP) if not region: log_msg = ('Unable to determine region for pool ' '{0} member {1}({2})'.format( name, member_ip, member_name)) LOG.error(log_msg) raise Error(log_msg) members[member_ip] = PoolMember(ip=member_ip, name=member_name, weight=weight, region=region) ########################### ### optional parameters ### ########################### pool_optional_params = {} ### fallback if 'fallback' in obj: pool_optional_params['fallback'] = obj['fallback'] ### max_addrs_returned if 'max_addrs_returned' in obj: pool_optional_params['max_addrs_returned'] = \ obj['max_addrs_returned'] # return Pool object return cls(name=name, monitor=monitor, lb_method=lb_method, members=members, **pool_optional_params)
def _any_response(self, params): """Generate a response to ANY/A query See polaris_health.state to_dist_dict() methods for the distribution state implementation details. """ qname = params['qname'].lower() # get a pool associated with the qname pool_name = self._state['globalnames'][qname]['pool_name'] pool = self._state['pools'][pool_name] # use the _default distribution table by default dist_table = pool['dist_tables']['_default'] ################## ### pool is UP ### ################## if pool['status']: # if using a topology based method, check if we have a distribution # table in the same region, if so - use it if pool['lb_method'] == 'twrr': # we'll log the time it takes to perfom a topology lookup t = time.time() # lookup the client's region, get_region() will # return None if the region cannot be determined region = topology.get_region(params['remote'], config.TOPOLOGY_MAP) # log the time taken to perform the lookup self.log.append( 'get_region() time taken: {:.6f}'.format(time.time() - t)) # log client's region self.log.append('client region: {}'.format(region)) # if we have a region table corresponding # to the client's region - use it if region in pool['dist_tables']: dist_table = pool['dist_tables'][region] #################### ### pool is DOWN ### #################### else: # if fallback is set to "refuse", refuse the query # (SOA response must return False as well) if pool['fallback'] == 'refuse': self.result = False return # otherwise(fallback is "any") use the _default distribution table # log the distribution table used self.log.append('dist table used: {}' .format(json.dumps(dist_table))) # determine how many records to return # which is the minimum of the dist table's num_unique_addrs and # the pool's max_addrs_returned if dist_table['num_unique_addrs'] <= pool['max_addrs_returned']: num_records_return = dist_table['num_unique_addrs'] else: num_records_return = pool['max_addrs_returned'] # if we don't have anything to return(all member weights may have # been set of 0), set the result to false if num_records_return == 0: self.result = False return ### add records to the response ### for i in range(num_records_return): # add record to the response self.add_record(qtype='A', # use the original qname from the parameters dict qname=params['qname'], content=dist_table['rotation'][dist_table['index']], ttl=self._state['globalnames'][qname]['ttl']) # increase index dist_table['index'] += 1 # set the index to 0 if we reached the end of the rotation list if dist_table['index'] >= len(dist_table['rotation']): dist_table['index'] = 0
def _any_response(self, params): """Generate a response to ANY/A query See polaris_health.state to_dist_dict() methods for the distribution state implementation details. """ qname = params['qname'].lower() # get a pool associated with the qname pool_name = self._state['globalnames'][qname]['pool_name'] pool = self._state['pools'][pool_name] # use the _default distribution table by default dist_table = pool['dist_tables']['_default'] ################## ### pool is UP ### ################## if pool['status']: # if using a topology based method, check if we have a distribution # table in the same region, if so - use it if pool['lb_method'] == 'twrr': # we'll log the time it takes to perfom a topology lookup t = time.time() # lookup the client's region, get_region() will # return None if the region cannot be determined region = topology.get_region(params['remote'], config.TOPOLOGY_MAP) # log the time taken to perform the lookup self.log.append( 'get_region() time taken: {:.6f}'.format(time.time() - t)) # log client's region self.log.append('client region: {}'.format(region)) # if we have a region table corresponding # to the client's region - use it if region in pool['dist_tables']: dist_table = pool['dist_tables'][region] #################### ### pool is DOWN ### #################### else: # if fallback is set to "refuse", refuse the query # (SOA response must return False as well) if pool['fallback'] == 'refuse': self.result = False return # otherwise(fallback is "any") use the _default distribution table # log the distribution table used self.log.append('dist table used: {}'.format(json.dumps(dist_table))) # determine how many records to return # which is the minimum of the dist table's num_unique_addrs and # the pool's max_addrs_returned if dist_table['num_unique_addrs'] <= pool['max_addrs_returned']: num_records_return = dist_table['num_unique_addrs'] else: num_records_return = pool['max_addrs_returned'] # if we don't have anything to return(all member weights may have # been set of 0), set the result to false if num_records_return == 0: self.result = False return ### add records to the response ### for i in range(num_records_return): # add record to the response self.add_record( qtype='A', # use the original qname from the parameters dict qname=params['qname'], content=dist_table['rotation'][dist_table['index']], ttl=self._state['globalnames'][qname]['ttl']) # increase index dist_table['index'] += 1 # set the index to 0 if we reached the end of the rotation list if dist_table['index'] >= len(dist_table['rotation']): dist_table['index'] = 0
def from_config_dict(cls, name, obj): """Build a Pool object from a config dict args: name: string, name of the pool obj: dict, config dict """ ############################ ### mandatory parameters ### ############################ ### monitor if obj['monitor'] not in monitors.registered: log_msg = 'unknown monitor "{}"'.format(obj['monitor']) LOG.error(log_msg) raise Error(log_msg) else: monitor_name = obj['monitor'] if 'monitor_params' in obj: if not obj['monitor_params']: log_msg = 'monitor_params should not be empty' LOG.error(log_msg) raise Error(log_msg) monitor_params = obj['monitor_params'] else: monitor_params = {} monitor = monitors.registered[monitor_name](**monitor_params) ### lb_method lb_method = obj['lb_method'] ### members members = {} # validate "members" key is present and not empty if not 'members' in obj or not obj['members']: log_msg = ('configuration dictionary must contain ' 'a non-empty "members" key') LOG.error(log_msg) raise Error(log_msg) for member_ip in obj['members']: member_name = obj['members'][member_ip]['name'] weight = obj['members'][member_ip]['weight'] region = None # if topology round robin method is used # set region on the pool member if lb_method == 'twrr': region = topology.get_region( member_ip, config.TOPOLOGY_MAP) if not region: log_msg = ('Unable to determine region for pool ' '{0} member {1}({2})'. format(name, member_ip, member_name)) LOG.error(log_msg) raise Error(log_msg) members[member_ip] = PoolMember(ip=member_ip, name=member_name, weight=weight, region=region) ########################### ### optional parameters ### ########################### pool_optional_params = {} ### fallback if 'fallback' in obj: pool_optional_params['fallback'] = obj['fallback'] ### max_addrs_returned if 'max_addrs_returned' in obj: pool_optional_params['max_addrs_returned'] = \ obj['max_addrs_returned'] # return Pool object return cls(name=name, monitor=monitor, lb_method=lb_method, members=members, **pool_optional_params)