def _mock(*args, **kwargs):
     readings = [
         api.DeviceReading(
             rack='rack',
             board='board',
             device='device',
             reading=api.Reading(
                 timestamp='2018-10-18T16:43:18+00:00',
                 type='temperature',
                 int64_value=10,
             )
         ),
         api.DeviceReading(
             rack='rack',
             board='board',
             device='device',
             reading=api.Reading(
                 timestamp='2018-10-18T16:43:18+00:00',
                 type='humidity',
                 int64_value=30,
             )
         )
     ]
     for r in readings:
         yield r
예제 #2
0
def test_read_scheme_null_value():
    """Test that the read scheme matches the expected when there is no read value.
    """
    dev = make_device_response()

    reading = api.Reading(
        timestamp='november',
        type='temperature',
    )

    response_scheme = ReadResponse(dev, [reading])

    assert response_scheme.data == {
        'kind': 'thermistor',
        'data': [
            {
                'info': '',
                'type': 'temperature',
                'value': None,
                'timestamp': 'november',
                'unit': {
                    'name': 'celsius',
                    'symbol': 'C'
                }
            }
        ]
    }
예제 #3
0
def test_read_scheme_no_precision():
    """Test that the read scheme matches the expected when no precision is given
    for the device
    """
    dev = make_device_response()
    dev.output[0].precision = 0

    reading = api.Reading(
        timestamp='november',
        type='temperature',
        float64_value=10.98765432
    )

    response_scheme = ReadResponse(dev, [reading])

    assert response_scheme.data == {
        'kind': 'thermistor',
        'data': [
            {
                'info': '',
                'type': 'temperature',
                'value': 10.98765432,
                'timestamp': 'november',
                'unit': {
                    'name': 'celsius',
                    'symbol': 'C'
                }
            }
        ]
    }
예제 #4
0
def test_read_scheme_no_unit():
    """Test that the read scheme matches the expected when no unit is given
    for the device
    """
    dev = make_device_response()
    dev.output[0].unit.name = ''
    dev.output[0].unit.symbol = ''

    reading = api.Reading(
        timestamp='november',
        type='temperature',
        float64_value=10.98765432
    )

    response_scheme = ReadResponse(dev, [reading])

    assert response_scheme.data == {
        'kind': 'thermistor',
        'data': [
            {
                'info': '',
                'type': 'temperature',
                'value': 10.988,
                'timestamp': 'november',
                'unit': None
            }
        ]
    }
예제 #5
0
def test_read_scheme_with_precision_rounding_2():
    """Test that the read scheme matches the expected when the read value
    must be rounded to the specified precision.
    """
    dev = make_device_response()

    reading = api.Reading(
        timestamp='november',
        type='temperature',
        float64_value=10.98765432
    )

    response_scheme = ReadResponse(dev, [reading])

    assert response_scheme.data == {
        'kind': 'thermistor',
        'data': [
            {
                'info': '',
                'type': 'temperature',
                'value': 10.988,
                'timestamp': 'november',
                'unit': {
                    'name': 'celsius',
                    'symbol': 'C'
                }
            }
        ]
    }
예제 #6
0
def test_read_scheme_non_convertible_value():
    """Test that the read scheme matches the expected when the read value
    is non-convertible.

    In this case, it doesn't raise the error but log a warning.
    The error value is still processed and left for the plugin level to handle.
    """
    dev = make_device_response()

    reading = api.Reading(
        timestamp='november',
        type='temperature',
        string_value='101a'
    )

    response_scheme = ReadResponse(dev, [reading])

    assert response_scheme.data == {
        'kind': 'thermistor',
        'data': [
            {
                'info': '',
                'type': 'temperature',
                'value': '101a',
                'timestamp': 'november',
                'unit': {
                    'name': 'celsius',
                    'symbol': 'C'
                }
            }
        ]
    }
예제 #7
0
def test_read_scheme_wrong_type_value():
    """Test that the read scheme matches the expected when the read value
    has the wrong type.
    """
    with pytest.raises(TypeError):
        _ = api.Reading(
            timestamp='november',
            type='temperature',
            string_value=101
        )
 def _mock_read(*args, **kwargs):
     yield api.DeviceReading(
         rack='rack',
         board='board',
         device='device',
         reading=api.Reading(
             timestamp='2018-10-18T16:43:18+00:00',
             type='temperature',
             int64_value=10,
         )
     )
예제 #9
0
def test_read_scheme_with_no_matching_readings():
    """Test that the read scheme matches the expected when no matching
    readings are provided.
    """
    dev = make_device_response()

    reading = api.Reading(
        timestamp='november',
        type='humidity',
        int32_value=5
    )

    response_scheme = ReadResponse(dev, [reading])

    assert response_scheme.data == {
        'kind': 'thermistor',
        'data': []
    }
def test_read_cached_scheme():
    """Test that the read cached scheme matches the expected."""
    dev = api.Device(timestamp='october',
                     uid='12345',
                     kind='thermistor',
                     metadata=dict(model='test', manufacturer='vapor io'),
                     plugin='foo',
                     info='bar',
                     location=api.Location(rack='rack-1', board='vec'),
                     output=[
                         api.Output(name='foo.temperature',
                                    type='temperature',
                                    precision=3,
                                    unit=api.Unit(name='celsius', symbol='C'))
                     ])

    reading = api.DeviceReading(rack='rack-1',
                                board='vec',
                                device='12345',
                                reading=api.Reading(timestamp='november',
                                                    type='temperature',
                                                    int64_value=10))

    response_scheme = ReadCachedResponse(dev, reading)

    assert response_scheme.data == {
        'location': {
            'rack': 'rack-1',
            'board': 'vec',
            'device': '12345'
        },
        'kind': 'thermistor',
        'info': '',
        'type': 'temperature',
        'value': 10.0,
        'timestamp': 'november',
        'unit': {
            'name': 'celsius',
            'symbol': 'C'
        }
    }
예제 #11
0
def mockread(self, rack, board, device):
    """Mock method to monkeypatch the client read method."""
    return [
        api.Reading(timestamp='october', type='temperature', int64_value=10)
    ]
예제 #12
0
async def read(rack, board, device):
    """The handler for the Synse Server "read" API command.

    Args:
        rack (str): The rack which the device resides on.
        board (str): The board which the device resides on.
        device (str): The device to read.

    Returns:
        ReadResponse: The "read" response scheme model.
    """
    logger.debug(
        _('Read Command (args: {}, {}, {})').format(rack, board, device))

    # Lookup the known info for the specified device.
    plugin_name, dev = await cache.get_device_info(rack, board, device)
    logger.debug(
        _('Device {} is managed by plugin {}').format(device, plugin_name))

    # Get the plugin context for the device's specified protocol.
    _plugin = plugin.get_plugin(plugin_name)
    logger.debug(_('Got plugin: {}').format(_plugin))
    if not _plugin:
        raise errors.PluginNotFoundError(
            _('Unable to find plugin named "{}" to read').format(plugin_name))

    try:
        # Perform a gRPC read on the device's managing plugin
        read_data = _plugin.client.read(rack, board, device)
    except grpc.RpcError as ex:

        # FIXME (etd) - this isn't the nicest way of doing this check.
        # this string is returned from the SDK, and its not likely to change
        # anytime soon, so this is "safe" for now, but we should see if there
        # is a better way to check this other than comparing strings..
        if hasattr(ex, 'code') and hasattr(ex, 'details'):
            if grpc.StatusCode.NOT_FOUND == ex.code(
            ) and 'no readings found' in ex.details().lower():

                # FIXME (etd) - with SDK v1.0, is the below correct? We should not longer
                # have to pass the "null" string. I think an empty string should also not
                # indicate no readings.. it should be the NOT_FOUND error (or, at least
                # some kind of error).

                # Currently, in the SDK, there are three different behaviors for
                # devices that do not have readings. Either (a). "null" is returned,
                # (b). an empty string ("") is returned, or (c). a gRPC error is
                # returned with the NOT_FOUND status code. Cases (a) and (b) are
                # handled in the ReadResponse initialization (below). This block
                # handles case (c).
                #
                # The reason for the difference between (a) and (b) is just one
                # of implementation. The empty string is the default value for the
                # gRPC read response, but sometimes it is useful to have an explict
                # value set to make things easier to read.
                #
                # The difference between those and (c) is more distinct. (c) should
                # only happen when a configured device is not being read from at all.
                # Essentially, (c) is the fallback for when device-specific handlers
                # fail to read a configured device.
                #
                # To summarize:
                #   (a), (b)
                #       A device is configured and the plugin's device handlers
                #       can operate on the device. This indicates that the plugin
                #       is working, but the device could be failing or disconnected.
                #
                #   (c)
                #       A device is configured, but the plugin's device handler
                #       can not (or is not) able to operate on the device. This
                #       could indicate either a plugin configuration error or
                #       an error with the plugin logic itself.

                # Create empty readings for each of the device's readings.
                logger.warning(
                    _('Read for {}/{}/{} returned gRPC "no readings found". Will '
                      'apply None as reading value. Note that this response might '
                      'indicate plugin error/misconfiguration.').format(
                          rack, board, device))
                read_data = []
                for output in dev.output:
                    read_data.append(
                        api.Reading(
                            timestamp=utils.rfc3339now(),
                            type=output.type,
                        ))
            else:
                raise errors.FailedReadCommandError(str(ex)) from ex
        else:
            raise errors.FailedReadCommandError(str(ex)) from ex

    return ReadResponse(device=dev, readings=read_data)