def test_no_ipv4(self): """An interface with no IPv4 entries raises :exc:`ValueError`""" with mock.patch('netifaces.ifaddresses', return_value={ netifaces.AF_LINK: [{'addr': 'de:ad:be:ef:ca:fe', 'broadcast': 'ff:ff:ff:ff:ff:ff'}] }): with self.assertRaises(ValueError): get_interface_address('wlan1')
def test_valid(self): with mock.patch('netifaces.ifaddresses', return_value={ netifaces.AF_LINK: [{'addr': 'de:ad:be:ef:ca:fe', 'broadcast': 'ff:ff:ff:ff:ff:ff'}], netifaces.AF_INET: [{'addr': '192.168.1.1', 'broadcast': '192.168.1.255', 'netmask': '255.255.255.0'}] }) as m: self.assertEqual('192.168.1.1', get_interface_address('eth1')) m.assert_called_with('eth1')
def __init__(self, host: str, port: int, loop: asyncio.AbstractEventLoop, endpoints: List[Endpoint], flag_interface: Optional[str], flags_ibv: bool, chunk_store: katdal.chunkstore.ChunkStore, chunk_params: spead_write.ChunkParams, telstate: katsdptelstate.TelescopeState, input_name: str, output_name: str, rename_src: Mapping[str, str], s3_endpoint_url: Optional[str], max_workers: int, buffer_dumps: int) -> None: super().__init__(host, port, loop=loop) self._chunk_store = chunk_store self._telstate = telstate # track the status of each capture block we have seen to date self._capture_block_state = {} # type: Dict[str, State] self._input_name = input_name self._output_name = output_name # rechunker group for each CBID self._flag_streams = {} # type: Dict[str, RechunkerGroup] self._executor = ThreadPoolExecutor(max_workers=max_workers) self.sensors.add( Sensor(Status, "status", "The current status of the flag writer process.")) self.sensors.add( Sensor( str, "capture-block-state", "JSON dict with the state of each capture block seen in this session.", default='{}', initial_status=Sensor.Status.NOMINAL)) for sensor in spead_write.io_sensors(): self.sensors.add(sensor) self.sensors.add(spead_write.device_status_sensor()) telstate_input = telstate.view(input_name) in_chunks = spead_write.chunks_from_telstate(telstate_input) DATA_LOST = 1 << FLAG_NAMES.index('data_lost') self._arrays = [ spead_write.make_array('flags', in_chunks, DATA_LOST, np.uint8, chunk_params) ] dump_size = sum(array.nbytes for array in self._arrays) self._executor_queue_space = QueueSpace(buffer_dumps * dump_size, loop=self.loop) spead_write.write_telstate(telstate, input_name, output_name, rename_src, s3_endpoint_url) rx = spead_write.make_receiver( endpoints, self._arrays, katsdpservices.get_interface_address(flag_interface), flags_ibv) self._writer = FlagWriter(self.sensors, rx, self) self._capture_task = loop.create_task(self._do_capture())
def __init__(self, host: str, port: int, loop: asyncio.AbstractEventLoop, endpoints: List[Endpoint], interface: Optional[str], ibv: bool, chunk_store: katdal.chunkstore.ChunkStore, chunk_params: spead_write.ChunkParams, telstate: katsdptelstate.TelescopeState, input_name: str, output_name: str, rename_src: Mapping[str, str], s3_endpoint_url: Optional[str], max_workers: int, buffer_dumps: int) -> None: super().__init__(host, port, loop=loop) self._endpoints = endpoints self._interface_address = katsdpservices.get_interface_address( interface) self._ibv = ibv self._chunk_store = chunk_store self._input_name = input_name self._output_name = output_name self._telstate = telstate self._rx = None # type: Optional[spead2.recv.asyncio.Stream] self._max_workers = max_workers telstate_input = telstate.view(input_name) in_chunks = spead_write.chunks_from_telstate(telstate_input) DATA_LOST = 1 << FLAG_NAMES.index('data_lost') self._arrays = [ spead_write.make_array('correlator_data', in_chunks, 0, np.complex64, chunk_params), spead_write.make_array('flags', in_chunks, DATA_LOST, np.uint8, chunk_params), spead_write.make_array('weights', in_chunks, 0, np.uint8, chunk_params), spead_write.make_array('weights_channel', in_chunks[:2], 0, np.float32, chunk_params) ] dump_size = sum(array.nbytes for array in self._arrays) self._buffer_size = buffer_dumps * dump_size spead_write.write_telstate(telstate, input_name, output_name, rename_src, s3_endpoint_url) self._capture_task = None # type: Optional[asyncio.Task] self._n_substreams = len(in_chunks[1]) self.sensors.add( Sensor(Status, 'status', 'The current status of the capture process', default=Status.IDLE, initial_status=Sensor.Status.NOMINAL, status_func=_status_status)) for sensor in spead_write.io_sensors(): self.sensors.add(sensor) self.sensors.add(spead_write.device_status_sensor())
async def data_to_spead(self, telstate, l0_endpoints, spead_rate=5e8, max_scans=None, interface=None): """Iterates through file and transmits data as a SPEAD stream. Parameters ---------- telstate : :class:`katsdptelstate.TelescopeState` Telescope State l0_endpoints : sequence of :class:`katsdptelstate.endpoint.Endpoint` Endpoints for SPEAD stream spead_rate : float SPEAD data transmission rate (bytes per second) max_scans : int, optional Maximum number of scans to transmit interface : str, optional Name of the interface on which to transmit data, if it is multicast. """ if self.n_substreams % len(l0_endpoints) != 0: raise ValueError( 'Number of endpoints must divide into number of substreams') logging.info('TX: Initializing...') # configure SPEAD - may need to rate-limit transmission for laptops etc. config = spead2.send.StreamConfig(max_packet_size=8872, rate=spead_rate, max_heaps=self.n_substreams) if interface: interface_address = katsdpservices.get_interface_address(interface) else: interface_address = '' tx = spead2.send.asyncio.UdpStream( spead2.ThreadPool(), [(l0_endpoint.host, l0_endpoint.port) for l0_endpoint in l0_endpoints], config, interface_address=interface_address) # if the maximum number of scans to transmit has not been # specified, set to total number of scans if max_scans is None or max_scans > self.num_scans: max_scans = self.num_scans # transmit data timestamp by timestamp and update telescope state await self.tx_data(telstate, tx, max_scans)
def test_invalid(self): """Passing a non-existent interface raises :exc:`ValueError`""" with self.assertRaises(ValueError): get_interface_address('not_an_interface_name')
def test_none(self): """Passing None returns None""" self.assertIsNone(get_interface_address(None))
def create_session_config(args: argparse.Namespace) -> SessionConfig: """Creates a SessionConfig object for a :class:`CaptureServer`. Note that this function makes blocking calls to telstate. The returned config has no filename. Parameters ---------- args Command-line arguments. See :class:`CaptureServer`. """ config = SessionConfig('') # Real filename supplied later config.max_packet = args.max_packet config.buffer_size = args.buffer_size if args.interface is not None: config.interface_address = katsdpservices.get_interface_address( args.interface) config.ibv = args.ibv if args.affinity: config.disk_affinity = args.affinity[0] config.network_affinity = args.affinity[1] if args.direct_io: config.direct = True # Load external config from telstate telstate = utils.cbf_telstate_view(args.telstate, args.stream_name) _config_from_telstate(telstate, config, 'channels', 'n_chans') _config_from_telstate(telstate, config, 'channels_per_heap', 'n_chans_per_substream') for name in [ 'ticks_between_spectra', 'spectra_per_heap', 'sync_time', 'bandwidth', 'center_freq', 'scale_factor_timestamp' ]: _config_from_telstate(telstate, config, name) # Set up batching to get 32MB per slice config.heaps_per_slice_time = max( 1, 2**25 // (config.channels * config.spectra_per_heap * 2)) # 256MB of buffer config.ring_slots = 8 # Check that the requested channel range is valid. all_channels = Range(0, config.channels) if args.channels is None: args.channels = all_channels channels_per_endpoint = config.channels // len(args.cbf_spead) if not args.channels.isaligned(channels_per_endpoint): raise ValueError('--channels is not aligned to multiples of {}'.format( channels_per_endpoint)) if not args.channels.issubset(all_channels): raise ValueError( '--channels does not fit inside range {}'.format(all_channels)) # Update for selected channel range channel_shift = (args.channels.start + args.channels.stop - config.channels) / 2 config.center_freq += channel_shift * config.bandwidth / config.channels config.bandwidth = config.bandwidth * len(args.channels) / config.channels config.channels = len(args.channels) config.channel_offset = args.channels.start endpoint_range = np.s_[args.channels.start // channels_per_endpoint:args.channels.stop // channels_per_endpoint] endpoints = args.cbf_spead[endpoint_range] for endpoint in endpoints: config.add_endpoint(socket.gethostbyname(endpoint.host), endpoint.port) config.endpoints_str = endpoints_to_str(endpoints) if args.stats is not None: config.set_stats_endpoint(args.stats.host, args.stats.port) config.stats_int_time = args.stats_int_time if args.stats_interface is not None: config.stats_interface_address = \ katsdpservices.get_interface_address(args.stats_interface) return config