Ejemplo n.º 1
0
 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')
Ejemplo n.º 2
0
 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')
Ejemplo n.º 3
0
    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())
Ejemplo n.º 4
0
    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())
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
 def test_invalid(self):
     """Passing a non-existent interface raises :exc:`ValueError`"""
     with self.assertRaises(ValueError):
         get_interface_address('not_an_interface_name')
Ejemplo n.º 7
0
 def test_none(self):
     """Passing None returns None"""
     self.assertIsNone(get_interface_address(None))
Ejemplo n.º 8
0
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