Exemple #1
0
    def _asset(self, command):
        """ Asset info command for a given board and device.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the asset response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]

        try:
            # validate that asset is supported for the device
            self._get_device_by_id(device_id, const.DEVICE_SYSTEM)
            asset_data = vapor_ipmi.get_inventory(**self._ipmi_kwargs)
            asset_data['bmc_ip'] = self.bmc_ip

            if asset_data is not None:
                return Response(command=command, response_data=asset_data)

            logger.error('No response getting asset info for {}'.format(
                command.data))
            raise SynseException(
                'No response from BMC when retrieving asset information via IPMI.'
            )

        except Exception:
            raise SynseException(
                'Error getting IPMI asset info (device id: {})'.format(
                    device_id)), None, sys.exc_info()[2]
    def _read(self, command):
        """ Read the data off of a given board's device.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the read response.
        """
        # Get the command data out from the incoming command.
        device_id = command.data[_s_.DEVICE_ID]
        device_type_string = command.data[_s_.DEVICE_TYPE_STRING]

        try:
            # Validate device to ensure device id and type are ok.
            self._get_device_by_id(device_id, device_type_string)

            reading = self._read_sensor()

            if reading is not None:
                return Response(command=command, response_data=reading)

            # If we get here, there was no sensor device found, so we must raise.
            logger.exception(
                'No response for sensor reading for command: {}'.format(
                    command.data))
            raise SynseException('No sensor reading returned from I2C.')

        except Exception:
            logger.exception('Error reading lock')
            raise SynseException('Error reading lock (device id: {})'.format(
                device_id)), None, sys.exc_info()[2]
    def _scan_all(self, command):
        """ Get the scan information from a 'broadcast' (e.g. scan all) command.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the scan all response.
        """
        # get the command data out from the incoming command
        force = command.data.get(_s_.FORCE, False)

        if force:
            self._redfish_links = find_links(self.redfish_ip,
                                             self.redfish_port,
                                             **self._redfish_request_kwargs)
            self.board_record = self._get_board_record()

        boards = [] if self.board_record is None else [self.board_record]
        scan_results = {
            'racks': [{
                'rack_id': self.server_rack,
                'boards': boards
            }]
        }

        return Response(command=command, response_data=scan_results)
Exemple #4
0
    def _scan_all(self, command):
        """ Get the scan information from a 'broadcast' (e.g. scan all) command.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the scan all response.
        """
        # get the command data out from the incoming command
        force = command.data.get(_s_.FORCE, False)

        if force:
            self.board_record = self._get_board_record()

            if self.board_record is not None:
                # get FRU information for use in determining OEM support
                self.fru_info = self._get_fru_info()
                self.dcmi_supported = self._get_dcmi_power_capabilities()

        boards = [] if self.board_record is None else [self.board_record]
        scan_results = {
            'racks': [{
                'rack_id': self.bmc_rack,
                'boards': boards
            }]
        }

        return Response(command=command, response_data=scan_results)
    def _led(self, command):
        """ LED command for a given board and device.

        If an LED state is specified, this will attempt to set the LED state
        of the given device. Otherwise, it will just retrieve the currently
        configured LED state.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the LED response.
        """
        # get the command data from the incoming command:
        device_id = command.data[_s_.DEVICE_ID]
        led_state = command.data[_s_.LED_STATE]

        try:
            # check if the device raises an exception
            self._get_device_by_id(device_id, const.DEVICE_LED)

            links_list = [self._redfish_links['chassis']]

            if led_state is not None and led_state.lower(
            ) != _s_.LED_NO_OVERRIDE:
                if led_state.lower() in [_s_.LED_ON, _s_.LED_OFF]:
                    led_state = 'Off' if led_state.lower(
                    ) == _s_.LED_OFF else 'Lit'
                    response = vapor_redfish.set_led(
                        led_state=led_state,
                        links=links_list,
                        **self._redfish_request_kwargs)
                else:
                    logger.error(
                        'LED state unsupported for LED control operation: {}'.
                        format(led_state))
                    raise SynseException(
                        'Unsupported state change to Redfish server on LED operation.'
                    )
            else:
                response = vapor_redfish.get_led(
                    links=links_list, **self._redfish_request_kwargs)

            if response:
                return Response(command=command, response_data=response)

            logger.error('No response for LED control operation: {}'.format(
                command.data))
            raise SynseException(
                'No response from Redfish server on LED operation.')

        except ValueError as e:
            logger.error('Error with LED control: {}'.format(command.data))
            raise SynseException(
                'Error returned from Redfish server during LED operation via '
                'Redfish ({}).'.format(e))
Exemple #6
0
    def make_response(self, data):
        """ Make a Response object which contains a devicebus implementation's
        response to the given Command.

        Args:
            data (dict): a dictionary containing the response data.

        Returns:
            Response: a Response object wrapping the given data.
        """
        return Response(self, data)
    def _fan(self, command):
        """ Fan speed control command for a given board and device.

        Gets the fan speed for a given device. Since this is not NOT a Vapor
        Fan we can not control the fan speed, so any attempts to set the
        fan speed are met with a SynseException being raised.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the fan response.
        """
        device_id = command.data[_s_.DEVICE_ID]
        device_name = command.data[_s_.DEVICE_NAME]
        fan_speed = command.data[_s_.FAN_SPEED]

        try:
            if fan_speed is not None:
                raise SynseException(
                    'Setting of fan speed is not permitted for this device.')

            else:
                # check if the device raises an exception
                device = self._get_device_by_id(device_id,
                                                const.DEVICE_FAN_SPEED)
                if device['device_type'] != const.DEVICE_FAN_SPEED:
                    raise SynseException(
                        'Attempt to get fan speed for non-fan device.')

                links_list = [self._redfish_links['thermal']]

                response = vapor_redfish.get_thermal_sensor(
                    device_type='Fans',
                    device_name=device_name,
                    links=links_list,
                    **self._redfish_request_kwargs)

                if response:
                    return Response(command=command, response_data=response)

            logger.error('No response for fan control operation: {}'.format(
                command.data))
            raise SynseException(
                'No response from Redfish server on fan operation via Redfish.'
            )

        except ValueError as e:
            logger.error('Error with fan control: {}'.format(command.data))
            raise SynseException(
                'Error returned from Redfish server during fan operation via '
                'Redfish ({}).'.format(e))
    def _power(self, command):
        """ Power control command for a given board and device.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the power response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]
        power_action = command.data[_s_.POWER_ACTION]

        try:
            # validate device supports power control
            self._get_device_by_id(device_id, const.DEVICE_POWER)

            if power_action not in [
                    _s_.PWR_ON, _s_.PWR_OFF, _s_.PWR_CYCLE, _s_.PWR_STATUS
            ]:
                raise ValueError(
                    'Invalid Redfish power action {} for board {} device {}.'.
                    format(power_action, self.board_id, device_id))
            else:
                links_list = [
                    self._redfish_links['system'], self._redfish_links['power']
                ]
                if power_action == 'status':
                    response = vapor_redfish.get_power(
                        links=links_list, **self._redfish_request_kwargs)
                else:
                    response = vapor_redfish.set_power(
                        power_action,
                        links=links_list,
                        **self._redfish_request_kwargs)

            if response:
                return Response(command=command, response_data=response)

            # if we get here there is either no device found, or response received
            logger.error('Power control attempt returned no data: {}'.format(
                command.data))
            raise SynseException(
                'No response from Redfish server for power control action.')

        except ValueError as e:
            logger.error('Error controlling Redfish power: {}'.format(
                command.data))
            raise SynseException(
                'Error returned from Redfish server in controlling power '
                'via Redfish ({}).'.format(e))
    def _boot_target(self, command):
        """ Boot target command for a given board and device.

        If a boot target is specified, this will attempt to set the boot device.
        Otherwise, it will just retrieve the currently configured boot device.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the boot target response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]
        boot_target = command.data[_s_.BOOT_TARGET]

        try:
            # check if the device raises an exception
            self._get_device_by_id(device_id, const.DEVICE_SYSTEM)

            links_list = [self._redfish_links['system']]

            if boot_target in [None, 'status']:
                response = vapor_redfish.get_boot(
                    links=links_list, **self._redfish_request_kwargs)
            else:
                boot_target = _s_.BT_NO_OVERRIDE if boot_target not in [_s_.BT_PXE, _s_.BT_HDD] \
                    else boot_target

                response = vapor_redfish.set_boot(
                    target=boot_target,
                    links=links_list,
                    **self._redfish_request_kwargs)

            if response:
                return Response(command=command, response_data=response)

            logger.error('No response for boot target operation: {}'.format(
                command.data))
            raise SynseException(
                'No response from Redfish server on boot target operation via Redfish.'
            )

        except ValueError as e:
            logger.error(
                'Error getting or setting Redfish boot target: {}'.format(
                    command.data))
            raise SynseException(
                'Error returned from Redfish server during boot target operation via '
                'Redfish ({}).'.format(e))
    def _scan(self, command):
        """ Get the scan information for a given board.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the scan response.
        """
        boards = [] if self.board_record is None else [self.board_record]
        return Response(command=command, response_data={'boards': boards})
Exemple #11
0
    def _scan(self, command):
        """ Common scan functionality for all RS-485 devices.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the scan response.
        """
        boards = [] if self.board_record is None else [self.board_record]
        return Response(command=command, response_data={'boards': boards})
Exemple #12
0
    def _fan(self, command):
        """ Fan speed control command for a given board and device.

        Gets the fan speed for a given device. Since this is not NOT a Vapor
        Fan, we can not control the fan speed, so any attempts to set the
        fan speed are met with a SynseException being raised.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the fan response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]
        device_name = command.data[_s_.DEVICE_NAME]
        fan_speed = command.data[_s_.FAN_SPEED]

        try:
            if fan_speed is not None:
                raise SynseException(
                    'Setting of fan speed is not permitted for this device.')
            else:
                device = self._get_device_by_id(device_id,
                                                const.DEVICE_FAN_SPEED)
                reading = vapor_ipmi.read_sensor(sensor_name=device_name,
                                                 **self._ipmi_kwargs)
                response = dict()
                if device['device_type'] == const.DEVICE_FAN_SPEED:
                    response[const.UOM_FAN_SPEED] = reading['sensor_reading']
                else:
                    raise SynseException(
                        'Attempt to get fan speed for non-fan device.')

                response['health'] = reading['health']
                response['states'] = reading['states']

                if response is not None:
                    return Response(command=command, response_data=response)

            logger.error('No response for fan control operation: {}'.format(
                command.data))
            raise SynseException(
                'No response from BMC on fan operation via IPMI.')

        except Exception:
            raise SynseException(
                'Error with fan control (device id: {})'.format(
                    device_id)), None, sys.exc_info()[2]
Exemple #13
0
    def _read(self, command):
        """ Read the data off of a given board's device.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the read response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]
        led_state = command.data.get(_s_.LED_STATE)
        color = command.data.get(_s_.LED_COLOR)
        if color is not None:
            color = int(color, 16)
        blink = command.data.get(_s_.LED_BLINK)

        # normalize the device_type_string - if it's of 'led-type', make it
        # vapor_led for board/device matching later otherwise, leave it
        # alone, which will reject erroneous reads
        device_type_string = command.data.get(_s_.DEVICE_TYPE_STRING,
                                              const.DEVICE_VAPOR_LED)

        if device_type_string in [const.DEVICE_LED, const.DEVICE_VAPOR_LED]:
            device_type_string = const.DEVICE_VAPOR_LED

        try:
            # validate device to ensure device id and type are ok
            self._get_device_by_id(device_id, device_type_string)

            reading = self._control_led(state=led_state,
                                        color=color,
                                        blink=blink)

            if reading is not None:
                return Response(command=command, response_data=reading)

            # if we get here, there was no sensor device found, so we
            # must raise
            logger.error('No response for LED status for command: {}'.format(
                command.data))
            raise SynseException('No LED status returned from I2C.')

        except Exception:
            raise SynseException(
                # NOTE: Writes go through this code path. Always did.
                'Error reading LED status (device id: {})'.format(
                    device_id)), None, sys.exc_info()[2]
Exemple #14
0
    def _scan_all(self, command):
        """ Common scan functionality for all I2C devices.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the scan all response.
        """
        boards = [] if self.board_record is None else [self.board_record]
        scan_results = {'racks': [{'rack_id': self.rack_id, 'boards': boards}]}

        return Response(command=command, response_data=scan_results)
Exemple #15
0
    def _lock_function(self, command):
        """ Read or write the lock state.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the lock response.
        """
        # Get the command data out from the incoming command.
        device_id = command.data[_s_.DEVICE_ID]
        device_type_string = command.data[_s_.DEVICE_TYPE_STRING]
        action = command.data[_s_.ACTION]

        try:
            # Validate device to ensure device id and type are ok.
            self._get_device_by_id(device_id, device_type_string)

            if action is None or action == 'status':
                reading = self._read_sensor()

            elif action == 'lock':
                i2c_common.lock_lock(self.lock_number)
                reading = self._return_lock_status(action)

            elif action == 'unlock':
                i2c_common.lock_unlock(self.lock_number)
                reading = self._return_lock_status(action)

            elif action == 'momentary_unlock':
                i2c_common.lock_momentary_unlock(self.lock_number)
                reading = self._return_lock_status(action)

            else:
                raise SynseException(
                    'Invalid action provided for lock control.')

            return Response(
                command=command,
                response_data=reading,
            )

        except Exception:
            logger.exception('Error reading lock. Raising SynseException.')
            raise SynseException('Error reading lock (device id: {})'.format(
                device_id)), None, sys.exc_info()[2]
    def _version(self, command):
        """ Get the version information for a given board.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the version response.
        """
        return Response(command=command,
                        response_data={
                            'api_version': __api_version__,
                            'synse_version': __version__,
                            'firmware_version': 'Synse Redfish Bridge v1.0'
                        })
Exemple #17
0
    def _read(self, command):
        """ Read the data off of a given board's device.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the read response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]
        device_type_string = command.data[_s_.DEVICE_TYPE_STRING]

        if device_type_string not in [
                const.DEVICE_VAPOR_FAN, const.DEVICE_FAN_SPEED
        ]:
            # this command is not for us
            raise SynseException('Incorrect device type "{}" for fan.'.format(
                device_type_string))

        # FIXME: override because main_blueprint doesn't distinguish between
        # 'fan_speed' and 'vapor_fan'
        device_type_string = const.DEVICE_VAPOR_FAN

        try:
            # validate device to ensure device id and type are ok
            self._get_device_by_id(device_id, device_type_string)

            reading = self._fan_control(action='status')

            if reading is not None:
                return Response(command=command, response_data=reading)

            # if we get here, there was no vapor_fan device found, so we must raise
            logger.error('No response for fan control for command: {}'.format(
                command.data))
            raise SynseException(
                'No fan control response returned from RS485.')

        except Exception:
            raise SynseException(
                'Error controlling fan controller (device id: {})'.format(
                    device_id)), None, sys.exc_info()[2]
    def _host_info(self, command):
        """ Get the host information for a given board.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the host info response.
        """
        return Response(
            command=command,
            response_data={
                'hostnames':
                self.hostnames,
                'ip_addresses':
                self.ip_addresses if self.ip_addresses else [self.redfish_ip]
            })
Exemple #19
0
    def _led(self, command):
        """ LED command for a given board and device.

        If an LED state is specified, this will attempt to set the LED state
        of the given device. Otherwise, it will just retrieve the currently
        configured LED state.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the LED response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]
        led_state = command.data[_s_.LED_STATE]

        try:
            if led_state is not None:
                self._get_device_by_id(device_id, const.DEVICE_LED)
                led_state = 0 if led_state.lower() == _s_.LED_OFF else 1
                led_response = vapor_ipmi.set_identify(led_state=led_state,
                                                       **self._ipmi_kwargs)
                led_response['led_state'] = _s_.LED_OFF if led_response['led_state'] == 0 \
                    else _s_.LED_ON
            else:
                self._get_device_by_id(device_id, const.DEVICE_LED)
                led_response = vapor_ipmi.get_identify(**self._ipmi_kwargs)

            if led_response is not None:
                return Response(command=command, response_data=led_response)

            logger.error('No response for LED control operation: {}'.format(
                command.data))
            raise SynseException(
                'No response from BMC on LED operation via IPMI.')

        except Exception:
            raise SynseException(
                'Error with LED control (device id: {})'.format(
                    device_id)), None, sys.exc_info()[2]
Exemple #20
0
    def _read(self, command):
        """ Read the data off of a given board's device.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the read response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]
        device_type_string = command.data[_s_.DEVICE_TYPE_STRING]

        try:
            device = self._get_device_by_id(device_id, device_type_string)

            reading = vapor_ipmi.read_sensor(sensor_name=device['device_info'],
                                             **self._ipmi_kwargs)
            response = dict()

            uom = get_measure_for_device_type(device['device_type'])
            if uom is not None:
                response[uom] = reading['sensor_reading']

            response['health'] = reading['health']
            response['states'] = reading['states']

            if response is not None:
                return Response(command=command, response_data=response)

            # if we get here, there was no sensor device found, so we must raise
            logger.error(
                'No response for sensor reading for command: {}'.format(
                    command.data))
            raise SynseException('No sensor reading returned from BMC.')

        except Exception:
            raise SynseException(
                'Error reading IPMI sensor (device id: {})'.format(
                    device_id)), None, sys.exc_info()[2]
    def _asset(self, command):
        """ Asset info command for a given board and device.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the asset response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]

        try:
            # validate that asset is supported for the device
            self._get_device_by_id(device_id, const.DEVICE_SYSTEM)

            links_list = [
                self._redfish_links['chassis'], self._redfish_links['system'],
                self._redfish_links['bmc']
            ]

            response = vapor_redfish.get_asset(links=links_list,
                                               **self._redfish_request_kwargs)
            response['redfish_ip'] = self.redfish_ip

            if 'chassis_info' in response:
                return Response(command=command, response_data=response)

            logger.error('No response getting asset info for {}'.format(
                command.data))
            raise SynseException(
                'No response from Redfish server when retrieving asset '
                'information via Redfish.')
        except ValueError as e:
            logger.error('Error getting Redfish asset info: {}'.format(
                command.data))
            raise SynseException(
                'Error returned from Redfish server when retrieving asset info '
                'via Redfish ({}).'.format(e))
Exemple #22
0
    def _boot_target(self, command):
        """ Boot target command for a given board and device.

        If a boot target is specified, this will attempt to set the boot device.
        Otherwise, it will just retrieve the currently configured boot device.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the boot target response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]
        boot_target = command.data[_s_.BOOT_TARGET]

        try:
            if boot_target is None or boot_target == 'status':
                self._get_device_by_id(device_id, const.DEVICE_SYSTEM)
                boot_info = vapor_ipmi.get_boot(**self._ipmi_kwargs)
            else:
                boot_target = _s_.BT_NO_OVERRIDE if boot_target not in [_s_.BT_PXE, _s_.BT_HDD] \
                    else boot_target
                self._get_device_by_id(device_id, const.DEVICE_SYSTEM)
                boot_info = vapor_ipmi.set_boot(target=boot_target,
                                                **self._ipmi_kwargs)

            if boot_info is not None:
                return Response(command=command, response_data=boot_info)

            logger.error('No response for boot target operation: {}'.format(
                command.data))
            raise SynseException(
                'No response from BMC on boot target operation via IPMI.')

        except Exception:
            raise SynseException(
                'Error getting or setting IPMI boot target '
                '(device id: {})'.format(device_id)), None, sys.exc_info()[2]
Exemple #23
0
    def _chamber_led(self, command):
        """ Chamber LED control command.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the chamber LED response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]
        device_type_string = command.data[_s_.DEVICE_TYPE_STRING]

        try:
            # validate device to ensure device id and type are ok
            self._get_device_by_id(device_id, device_type_string)

            led_color = int(command.data[_s_.LED_COLOR], 16)

            reading = self._control_led(
                state=command.data[_s_.LED_STATE],
                blink=command.data[_s_.LED_BLINK_STATE],
                color=led_color)

            if reading is not None:
                return Response(command=command, response_data=reading)

            # if we get here, there was no sensor device found, so
            # we must raise
            logger.error('No response for LED control for command: {}'.format(
                command.data))
            raise SynseException('No LED control response from I2C.')

        except Exception:
            raise SynseException(
                'Error setting LED status (device id: {})'.format(
                    device_id)), None, sys.exc_info()[2]
    def _read(self, command):
        """ Read the data off of a given board's device.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the read response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]
        device_type_string = command.data[_s_.DEVICE_TYPE_STRING]
        response = dict()

        _device_type_string = device_type_string.lower()

        if _device_type_string == const.DEVICE_FAN_SPEED:
            device_type = 'Fans'
        elif _device_type_string == const.DEVICE_TEMPERATURE:
            device_type = 'Temperatures'
        elif _device_type_string == const.DEVICE_VOLTAGE:
            device_type = 'Voltages'
        elif _device_type_string == const.DEVICE_POWER_SUPPLY:
            device_type = 'PowerSupplies'
        else:
            logger.error(
                'Unsupported device type for Redfish device: {}'.format(
                    device_type_string))
            raise SynseException(
                '{} not a supported device type for Redfish.'.format(
                    device_type_string))

        try:
            # check if the device raises an exception
            device = self._get_device_by_id(device_id, device_type_string)
            device_name = device['device_info']

            if _device_type_string in [
                    const.DEVICE_FAN_SPEED, const.DEVICE_TEMPERATURE
            ]:
                links_list = [self._redfish_links['thermal']]
                response = vapor_redfish.get_thermal_sensor(
                    device_type=device_type,
                    device_name=device_name,
                    links=links_list,
                    **self._redfish_request_kwargs)
            elif _device_type_string in [
                    const.DEVICE_VOLTAGE, const.DEVICE_POWER_SUPPLY
            ]:
                links_list = [self._redfish_links['power']]
                response = vapor_redfish.get_power_sensor(
                    device_type=device_type,
                    device_name=device_name,
                    links=links_list,
                    **self._redfish_request_kwargs)

            if response:
                return Response(command=command, response_data=response)

            # if we get here, there was no sensor device found, so we must raise
            logger.error(
                'No response for sensor reading for command: {}'.format(
                    command.data))
            raise SynseException(
                'No sensor reading returned from Redfish server.')
        except ValueError as e:
            logger.error('Error reading Redfish sensor: {}'.format(e.message))
            logger.exception(e)
            raise SynseException('Error reading Redfish sensor: {}'.format(
                e.message))
Exemple #25
0
    def _power(self, command):
        """ Power control command for a given board and device.

        Args:
            command (Command): the command issued by the Synse endpoint
                containing the data and sequence for the request.

        Returns:
            Response: a Response object corresponding to the incoming Command
                object, containing the data from the power response.
        """
        # get the command data out from the incoming command
        device_id = command.data[_s_.DEVICE_ID]
        power_action = command.data[_s_.POWER_ACTION]

        try:
            if power_action not in [
                    _s_.PWR_ON, _s_.PWR_OFF, _s_.PWR_CYCLE, _s_.PWR_STATUS
            ]:
                raise ValueError(
                    'Invalid IPMI power action {} for board {} device {}.'.
                    format(power_action, self.board_id, device_id))
            # determine if there are OEM considerations
            # for reading power
            reading_method = None

            if self.dcmi_supported:
                reading_method = 'dcmi'

            if self.fru_info is not None:
                if self.fru_info['board_info'][
                        'manufacturer'] == 'Ciii USA Inc':
                    # flex OEM support should override dcmi support
                    reading_method = 'flex-victoria'

            # validate device supports power control
            self._get_device_by_id(device_id, const.DEVICE_POWER)

            power_status = vapor_ipmi.power(cmd=power_action,
                                            reading_method=reading_method,
                                            **self._ipmi_kwargs)

            # NB(ABC): disabled this but it could be re-enabled - if the DCMI Power Reading
            #    command is giving trouble elsewhere, we could re-enable this, but the checks
            #    done at startup should obviate the need for this logic for now.
            # check reading method, and if 'dcmi' and input_power is 'unknown', set reading_method
            # to 'None' in the future; 'unknown' indicates an exception occurred, which we do not
            # wish to repeat
            if reading_method == 'dcmi' and power_status[
                    'input_power'] == 'unknown':
                self.dcmi_supported = False

            if power_status is not None:
                return Response(command=command, response_data=power_status)

            # if we get here there is either no device found, or response received
            logger.error('Power control attempt returned no data: {}'.format(
                command.data))
            raise SynseException(
                'No response from BMC for power control action.')

        except Exception:
            raise SynseException(
                'Error for power control via IPMI (device id: {}).'.format(
                    device_id)), None, sys.exc_info()[2]