Example #1
0
    def set_boot_mode(self, task, mode):
        """Set the boot mode for a node.

        Set the boot mode to use on next reboot of the node.

        :param task: A task from TaskManager.
        :param mode: The boot mode, one of
                     :mod:`ironic.common.boot_modes`.
        :raises: InvalidParameterValue on malformed parameter(s)
        :raises: MissingParameterValue on missing parameter(s)
        :raises: IBMCConnectionError when it fails to connect to iBMC
        :raises: IBMCError on an error from the iBMC
        """
        self.validate(task)
        system = utils.get_system(task.node)

        boot_device = system.boot.get('target')
        if not boot_device:
            error_msg = (_('Cannot change boot mode on node %(node)s '
                           'because its boot device is not set.') % {
                               'node': task.node.uuid
                           })
            LOG.error(error_msg)
            raise exception.IBMCError(error_msg)

        boot_override = system.boot.get('enabled')
        if not boot_override:
            error_msg = (_('Cannot change boot mode on node %(node)s '
                           'because its boot source override is not set.') % {
                               'node': task.node.uuid
                           })
            LOG.error(error_msg)
            raise exception.IBMCError(error_msg)

        try:
            system.set_system_boot_source(
                boot_device,
                enabled=boot_override,
                mode=mappings.BOOT_MODE_MAP_REV[mode])
        except requests.exceptions.RequestException as e:
            error_msg = (_('Setting boot mode to %(mode)s '
                           'failed for node %(node)s. Error : %(error)s') % {
                               'node': task.node.uuid,
                               'mode': mode,
                               'error': e
                           })
            LOG.error(error_msg)
            raise exception.IBMCError(error=error_msg)
Example #2
0
        def wrapper(*args, **kwargs):
            # NOTE(dtantsur): this code could be written simpler, but then unit
            # testing decorated functions is pretty hard, as we usually pass a
            # Mock object instead of TaskManager there.
            if len(args) > 1:
                is_task_mgr = isinstance(args[1], task_manager.TaskManager)
                task = args[1] if is_task_mgr else args[0]
            else:
                task = args[0]

            node = task.node

            try:
                return f(*args, **kwargs)
            except ibmc_error.IBMCConnectionError as e:
                error = (_('Failed to connect to iBMC for node %(node)s, '
                           'Error: %(error)s') % {
                               'node': node.uuid,
                               'error': e
                           })
                LOG.error(error)
                raise exception.IBMCConnectionError(node=node.uuid,
                                                    error=error)
            except ibmc_error.IBMCClientError as e:
                error = (_('Failed to %(action)s for node %(node)s, '
                           'Error %(error)s') % {
                               'node': node.uuid,
                               'action': action,
                               'error': e
                           })
                LOG.error(error)
                raise exception.IBMCError(node=node.uuid, error=error)
Example #3
0
    def set_boot_device(self, task, device, persistent=False):
        """Set the boot device for a node.

        :param task: A task from TaskManager.
        :param device: The boot device, one of
                       :mod:`ironic.common.boot_device`.
        :param persistent: Boolean value. True if the boot device will
                           persist to all future boots, False if not.
                           Default: False.
        :raises: InvalidParameterValue on malformed parameter(s)
        :raises: MissingParameterValue on missing parameter(s)
        :raises: IBMCConnectionError when it fails to connect to iBMC
        :raises: IBMCError on an error from the iBMC
        """
        self.validate(task)
        system = utils.get_system(task.node)

        try:
            system.set_system_boot_source(
                mappings.BOOT_DEVICE_MAP_REV[device],
                enabled=mappings.BOOT_DEVICE_PERSISTENT_MAP_REV[persistent])
        except requests.exceptions.RequestException as e:
            error_msg = (_('IBMC set boot device failed for node '
                           '%(node)s. Error: %(error)s') % {
                               'node': task.node.uuid,
                               'error': e
                           })
            LOG.error(error_msg)
            raise exception.IBMCError(error=error_msg)
Example #4
0
    def set_power_state(self, task, power_state, timeout=None):
        """Set the power state of the task's node.

        :param task: A TaskManager instance containing the node to act on.
        :param power_state: Any power state from :mod:`ironic.common.states`.
        :param timeout: Time to wait for the node to reach the requested state.
        :raises: InvalidParameterValue on malformed parameter(s)
        :raises: MissingParameterValue if a required parameter is missing.
        :raises: IBMCConnectionError when it fails to connect to iBMC
        :raises: IBMCError on an error from the iBMC
        """
        self.validate(task)
        system = utils.get_system(task.node)
        try:
            system.reset_system(
                mappings.SET_POWER_STATE_MAP_REV.get(power_state))
        except requests.exceptions.RequestException as e:
            error_msg = (_('IBMC set power state failed for node '
                           '%(node)s. Error: %(error)s') % {
                               'node': task.node.uuid,
                               'error': e
                           })
            LOG.error(error_msg)
            raise exception.IBMCError(error=error_msg)

        target_state = TARGET_STATE_MAP.get(power_state, power_state)
        cond_utils.node_wait_for_power_state(task,
                                             target_state,
                                             timeout=timeout)
Example #5
0
def _load_from_json(json, path, ignore_missing=False):
    """Load field from json.

    :param json: JSON object.
    :param path: Field path, string or string array. For example
        'Systems' will get field value from json.get('Systems'),
        ['Systems', 'data'] will get field value from
        json.get('Systems').get('data')
    :param ignore_missing: Ignore missing attribute
    :raises IBMCError: When no such attribute exists.
    :returns: Field value
    """
    if isinstance(path, six.string_types):
        path = [path]
    name = path[-1]
    body = json
    for path_item in path[:-1]:
        body = body.get(path_item) or {}

    if name not in body:
        if not ignore_missing:
            err_msg = _('Missing attribute %s, json: %s' %
                        ('/'.join(path), json))
            raise exception.IBMCError(error=err_msg)
        else:
            return None

    return body[name]
Example #6
0
    def reboot(self, task, timeout=None):
        """Perform a hard reboot of the task's node.

        :param task: A TaskManager instance containing the node to act on.
        :param timeout: Time to wait for the node to become powered on.
        :raises: InvalidParameterValue on malformed parameter(s)
        :raises: MissingParameterValue if a required parameter is missing.
        :raises: IBMCConnectionError when it fails to connect to iBMC
        :raises: IBMCError on an error from the iBMC
        """
        self.validate(task)
        system = utils.get_system(task.node)
        current_power_state = (mappings.GET_POWER_STATE_MAP.get(
            system.power_state))

        try:
            if current_power_state == states.POWER_ON:
                system.reset_system(
                    mappings.SET_POWER_STATE_MAP_REV.get(states.REBOOT))
            else:
                system.reset_system(
                    mappings.SET_POWER_STATE_MAP_REV.get(states.POWER_ON))
        except requests.exceptions.RequestException as e:
            error_msg = (_('IBMC reboot failed for node %(node)s. '
                           'Error: %(error)s') % {
                               'node': task.node.uuid,
                               'error': e
                           })
            LOG.error(error_msg)
            raise exception.IBMCError(error=error_msg)

        cond_utils.node_wait_for_power_state(task,
                                             states.POWER_ON,
                                             timeout=timeout)
Example #7
0
    def __init__(self, conn, id, address, systems_path):
        """A class representing iBMC System object.

        :param conn: IBMCConnector
        :param id: IBMC System identifier. If None, use first system.
        :param address: IBMC address
        :param systems_path: IBMC Systems path
        """
        self._conn = conn
        self._address = address
        self._systems_path = systems_path
        self._real_id = None
        self._json = None
        self._boot = None
        self._reset_path = None
        self._power_state = None
        self._bios_path = None

        if not id:
            r = self._conn.make_req('GET', self._systems_url())
            systems = _load_from_json(r.json(), 'Members')
            if not systems:
                raise exception.IBMCError(error='No system available')
            self._real_id = _load_from_json(systems[0], '@odata.id')
        else:
            self._real_id = id

        self.get()
Example #8
0
 def _get_resource_etag(self, url):
     r = self.make_req('GET', url)
     etag = r.headers.get('Etag') or r.headers.get('etag')
     if not etag:
         msg = 'Can not get resource[%s] etag' % url
         raise exception.IBMCError(msg)
     return etag
Example #9
0
    def _get_system():
        try:
            with SessionCache(driver_info) as conn:
                return conn.get_system(system_id)

        except requests.exceptions.RequestException as e:
            if (e.response is not None and e.response.status_code
                    and e.response.status_code == 404):
                # If it is a resource not found error, then log about
                #  the error, and re-raise a not-to-retry error
                LOG.error(
                    'The iBMC System "%(system)s" was not found for '
                    'node %(node)s. Error %(error)s', {
                        'system': system_id,
                        'node': node.uuid,
                        'error': e
                    })
                raise exception.IBMCError(error=e)
            else:
                # Every other exceptions raise from requests lib,
                #  we need to retry the request
                LOG.warning(
                    'For node %(node)s, got a connection error from '
                    'iBMC at address "%(address)s" when fetching '
                    'System "%(system)s". Error: %(error)s', {
                        'system': system_id,
                        'address': address,
                        'node': node.uuid,
                        'error': e
                    })
                raise exception.IBMCConnectionError(node=node.uuid, error=e)
Example #10
0
    def set_boot_mode(self, task, mode):
        """Set the boot mode for a node.

        Set the boot mode to use on next reboot of the node.

        :param task: A task from TaskManager.
        :param mode: The boot mode, one of
                     :mod:`ironic.common.boot_modes`.
        :raises: InvalidParameterValue on malformed parameter(s)
        :raises: MissingParameterValue on missing parameter(s)
        :raises: IBMCConnectionError when it fails to connect to iBMC
        :raises: IBMCError when iBMC responses an error information
        """
        ibmc = utils.parse_driver_info(task.node)
        with ibmc_client.connect(**ibmc) as conn:
            system = conn.system.get()
            boot_source_override = system.boot_source_override
            boot_device = boot_source_override.target
            boot_override = boot_source_override.enabled

            # Copied from redfish driver
            # TODO(Qianbiao.NG) what if boot device is "NONE"?
            if not boot_device:
                error_msg = (_('Cannot change boot mode on node %(node)s '
                               'because its boot device is not set.') % {
                                   'node': task.node.uuid
                               })
                LOG.error(error_msg)
                raise exception.IBMCError(error_msg)

            # TODO(Qianbiao.NG) what if boot override is "disabled"?
            if not boot_override:
                i18n = _('Cannot change boot mode on node %(node)s '
                         'because its boot source override is not set.')
                error_msg = i18n % {'node': task.node.uuid}
                LOG.error(error_msg)
                raise exception.IBMCError(error_msg)

            boot_mode = mappings.SET_BOOT_MODE_MAP[mode]
            conn.system.set_boot_source(boot_device,
                                        enabled=boot_override,
                                        mode=boot_mode)
Example #11
0
    def _make_req(self, method, url, json=None, headers=None):
        # If method is PATCH or PUT, get resource's etag first
        if method.lower() in ['patch', 'put']:
            etag = self._get_resource_etag(url)
            headers = headers or {}
            headers.update({'If-Match': etag})

        LOG.info('IBMC request: %(method)s, %(url)s', {
            'method': method,
            'url': url,
        })
        req = requests.Request(method, url, json=json, headers=headers)
        prepped = self._session.prepare_request(req)
        try:
            r = self._session.send(prepped, timeout=self._DEFAULT_TIMEOUT)
            r.raise_for_status()
            return r
        except requests.exceptions.RequestException as e:
            if (e.response is not None and e.response.status_code
                    and e.response.status_code >= 500):
                # If it's server error, then log about the error,
                # and re-raise a not-to-retry error
                msg = ('IBMC server error: method: [%s], url: [%s], %s' %
                       (method, url, e.response.text))
                raise exception.IBMCError(error=msg)
            else:
                try:
                    ext_info = _load_from_json(
                        e.response.json(), ['error', '@Message.ExtendedInfo'],
                        ignore_missing=True)
                    reason = (ext_info[0].get('Message')
                              if len(ext_info) else ext_info)
                except Exception:
                    reason = ''

                # Simply log about the exception, and re-raise to the
                #  outer try-catch, let it determine whether to retry
                #  the request
                msg = ('IBMC request error: method: [%s], url: [%s], '
                       'body: %s, headers: %s, reason: %s' %
                       (method, url, json, headers, reason))
                LOG.error(msg)
                raise e
Example #12
0
    def boot_up_seq(self, task, **kwargs):
        """List boot type order of the node.

        :param task: A TaskManager instance containing the node to act on.
        :param kwargs: Not used.
        :raises: InvalidParameterValue if kwargs does not contain 'method'.
        :raises: MissingParameterValue
        :returns: A dictionary, containing node boot up sequence,
                in ascending order.
        """
        self.validate(task)
        system = utils.get_system(task.node)
        try:
            boot_seq = system.boot_sequence
            return {'boot_up_sequence': boot_seq}
        except requests.exceptions.RequestException as e:
            error_msg = (_('IBMC get bootup sequence failed '
                           'for node %(node)s. Error: %(error)s') %
                         {'node': task.node.uuid, 'error': e})
            LOG.error(error_msg)
            raise exception.IBMCError(error=error_msg)
Example #13
0
    def inject_nmi(self, task):
        """Inject NMI, Non Maskable Interrupt.

        Inject NMI (Non Maskable Interrupt) for a node immediately.

        :param task: A TaskManager instance containing the node to act on.
        :raises: InvalidParameterValue on malformed parameter(s)
        :raises: MissingParameterValue on missing parameter(s)
        :raises: IBMCConnectionError when it fails to connect to iBMC
        :raises: IBMCError on an error from the Sushy library
        """
        self.validate(task)
        system = utils.get_system(task.node)
        try:
            system.reset_system(constants.RESET_NMI)
        except requests.exceptions.RequestException as e:
            error_msg = (_('IBMC inject NMI failed for node %(node)s. '
                           'Error: %(error)s') % {
                               'node': task.node.uuid,
                               'error': e
                           })
            LOG.error(error_msg)
            raise exception.IBMCError(error=error_msg)