def ant_str_to_tuples(self, ant_str=all): ''' Get (fengine, pol_index) tuples corresponding to ant_str ''' if not (len(self.fengines) == self.n_ants): log_runtime_error(LOGGER, 'The number of fengines in our system (%d) does not match the number required (%d)'%(len(self.fengines), self.n_ants)) tuples = [] if ant_str==all: for ant_index in range(self.n_ants): for pol_index in range(len(self.config['pols'])): tuples.append((self.fengines[ant_index], pol_index)) else: #polarisation must be single character and in pol_map pol = ant_str[len(ant_str)-1] pol_index = self.config['pol_map'].get(pol) if pol_index == None: log_value_error(LOGGER, '%s not a valid polarisation label for %s'%(pol, self.descriptor)) #antenna index must be natural number smaller than the ants we have ant = ant_str[0:len(ant_str)-1] try: ant_index = int(ant) except ValueError: log_value_error(LOGGER, '%s cannot be converted to an integer'%(ant)) if ant_index < 0 or ant_index >= self.n_ants: log_runtime_error(LOGGER, '%d is not a valid antenna index in %s'%(ant_index, self.descriptor)) tuples.append((self.fengines[ant_index], pol_index)) return tuples
def return_hosts(self, hostnames, host_type='roach2', host_configuration='all'): ''' Return hosts to the pool ''' #check type if self.source == 'file': self.host_pool['%s'%host_type]['%s'%host_configuration].extend(hostnames) else: log_runtime_error(LOGGER, 'Don''t know how to return hosts via katcp yet ')
def create_fengine(self, ant_id): # index of host host_index = ant_id/self.f_per_host # index in FPGA engine_index = ant_id%self.f_per_host if len(self.fhosts) <= host_index: log_runtime_error(LOGGER, 'Trying to create an fengine with index greater than the number of host_links we have') host_link = self.fhosts[host_index] fengine = self.create_fengine_fpga(ant_id, host_link, engine_index) return fengine
def create_xengine(self, xengine_index): # index of host host_index = xengine_index/self.x_per_host # index in FPGA engine_index = xengine_index%self.x_per_host # number of existing xengines in system if len(self.xhosts) <= host_index: log_runtime_error(LOGGER, 'Trying to create an xengine with index greater than the number of host_links we have') # host it belongs in host_link = self.xhosts[host_index] xengine = self.create_xengine_fpga(host_link, engine_index) return xengine
def __init__(self, host_device, engine_id, host_instrument=None, config_file=None, descriptor='engine'): '''Constructor @param host_device: the device that hosts this engine @param engine_id: unique id for this engine type on host @param host_instrument: the Instrument it is part of @param config_file: configuration if engine is to be used not as part of Instrument @param descriptor: section in config to locate engine specific info at ''' if not isinstance(descriptor, str): log_runtime_error(LOGGER, 'descriptor provided is not a string') self.descriptor = descriptor self.instrument = None if host_instrument != None: #if a config file is provided, get config from there, otherwise use host Instrument's if not isinstance(host_instrument, instrument.Instrument): log_runtime_error(LOGGER, 'instrument provided is not an Instrument') else: self.instrument = host_instrument if not isinstance(host_device, host.Host): log_runtime_error(LOGGER, 'host provided is not an Host') self.host = host_device if not isinstance(engine_id, int): log_runtime_error(LOGGER, 'engine_id provided is not an int') self.id = engine_id self.config_portal = None #if no config file given if config_file == None: if self.instrument == None: log_runtime_error(LOGGER, 'No way to get config') # get config from instrument it is a part of self.config_portal = self.instrument.config_portal else: # create new configuration portal self.config_portal = configuration_katcp_client.ConfigurationKatcpClient(config_file=config_file) self.config = {} self._get_engine_config() #TODO SPEAD self.spead_transmitter = None LOGGER.info('Initialised %s', str(self))
def get_hosts(self, host_type='roach2', host_configuration='all', number=None, hostnames=None): ''' Request hosts for use @param hostnames: specific host names @param host_type: type of host if not specific @param number: number of type if not specific @return hostnames if available or empty list if not ''' if self.source == 'file': hosts = list() if hostnames==None: avail_hosts = self.hosts['%s'%host_type]['%s'%host_configuration] hosts.extend(avail_hosts[0:number]) avail_hosts = avail_hosts[number:len(avail_hosts)] self.hosts['%s'%host_type]['%s'%host_configuration] = avail_hosts return hosts else: log_runtime_error(LOGGER, 'Don''t know how to get specific hostnames yet') #TODO else: log_runtime_error(LOGGER, 'Don''t know how to get hosts via katcp yet')
def _get_engine_config(self): ''' COnfiguration info needed by all processing engines ''' #TODO check for descriptor section in config if not self.ping(): log_runtime_error(LOGGER, 'Host not pingable') if not self.host.is_running(): log_runtime_error(LOGGER, 'Need running host') # check firmware running on host same as specified in configuration host_config_file = self.config_portal.get_string(['%s'%self.descriptor, 'host_config_file']) file_info = self.host.get_config_file_info() if (host_config_file.find(file_info['name']) == -1): #TODO check date too log_runtime_error(LOGGER, 'Need to be running on host with configuration file matching the one specified in config') # get types of data it produces # each engine produces a single data product, other data products must be produced # by other engines product = self.config_portal.get_string(['%s'%self.descriptor, 'produces']) self.config['data_product'] = {} if product != 'Nothing': # find the default destination for the data it produces txport = self.config_portal.get_int(['%s'%product, 'txport']) txip_str = self.config_portal.get_string(['%s'%product, 'txip']) self.config['data_product']['name'] = '%s'%product self.config['data_product']['txport'] = txport self.config['data_product']['txip_str'] = txip_str
def __init__(self, config_host=None, katcp_port=None, config_file=None): '''Constructor @param config_host: host name of server containing daemon serving configuration information via katcp @param katcp_port: port number configuration daemon is listening on @param config_file: file containing configuration information (overrides katcp) ''' if config_file == None and (config_host == None or katcp_port == None): log_runtime_error(LOGGER, 'Need a configuration file name or katcp host location') self.source = None self.config_host = '' self.katcp_port = 0 if config_file != None: try: fptr = open(config_file, 'r') except: log_io_error(LOGGER, 'Configuration file \'%s\' cannot be opened.' % config_file) self.config = iniparse.INIConfig(fptr) fptr.close() self.source = 'file' else: self.config = None if (not isinstance(config_host, str)): log_runtime_error(LOGGER, 'config_host must be a string') self.config_host = config_host if (not isinstance(katcp_port, int)): log_runtime_error(LOGGER, 'katcp_port must be an int') self.katcp_port = katcp_port self.config = get_remote_config(self.config_host, self.katcp_port) self.source = 'katcp' self.get_config()
def get_string(self, target, fail_hard=True): '''Get configuration string @param target: list describing parameter @param fail_hard: throw exception on failure to locate target ''' if not isinstance(target, list): log_runtime_error(LOGGER, 'Configuration target must be a list in the form [section, name]') if len(target) != 2: log_runtime_error(LOGGER, 'Configuration target must be a list in the form [section, name]') # if a file then we have an iniparse structure if self.source == 'file': if not isinstance(target[0], str) or not isinstance(target[1], str): log_runtime_error(LOGGER, 'target must be strings in form [section, parameter]') section = self.config[target[0]] if isinstance(section, iniparse.config.Undefined): string = None msg = 'Asked for unknown section \'%s\''% (target[0]) if fail_hard==True: log_runtime_error(LOGGER, msg) else: LOGGER.warning(msg) else: string = section[target[1]] if isinstance(string, iniparse.config.Undefined): string = None msg = 'Asked for unknown parameter \'%s\' in section \'%s\''% (target[1], target[0]) if fail_hard==True: log_runtime_error(LOGGER, msg) else: LOGGER.warning(msg) # if katcp we have config in a dict elif self.source == 'katcp': log_runtime_error(LOGGER, 'Can''t get configuration via katcp yet') else: log_runtime_error(LOGGER, 'Unknown configuration source') return string
def get_remote_config(host, katcp_port): '''Connects to katcp daemon on remote host and gets config, constructing dictionary ''' log_runtime_error(LOGGER, 'Can''t get remote config yet')