Exemple #1
0
    def test_list_unfinished_jobs(self, mock_get_drac_client):
        mock_client = mock.Mock()
        mock_get_drac_client.return_value = mock_client
        mock_client.list_jobs.return_value = [self.job]

        jobs = drac_job.list_unfinished_jobs(self.node)

        mock_client.list_jobs.assert_called_once_with(only_unfinished=True)
        self.assertEqual([self.job], jobs)
Exemple #2
0
    def test_list_unfinished_jobs(self, mock_get_drac_client):
        mock_client = mock.Mock()
        mock_get_drac_client.return_value = mock_client
        mock_client.list_jobs.return_value = [self.job]

        jobs = drac_job.list_unfinished_jobs(self.node)

        mock_client.list_jobs.assert_called_once_with(only_unfinished=True)
        self.assertEqual([self.job], jobs)
Exemple #3
0
    def list_unfinished_jobs(self, task, **kwargs):
        """List unfinished config jobs of the node.

        :param task: a TaskManager instance containing the node to act on.
        :param kwargs: not used.
        :returns: a dictionary containing the ``unfinished_jobs`` key; this key
                  points to a list of dicts, with each dict representing a Job
                  object.
        :raises: DracOperationError on an error from python-dracclient.
        """
        jobs = drac_job.list_unfinished_jobs(task.node)
        # FIXME(mgould) Do this without calling private methods.
        return {'unfinished_jobs': [job._asdict() for job in jobs]}
Exemple #4
0
    def list_unfinished_jobs(self, task, **kwargs):
        """List unfinished config jobs of the node.

        :param task: a TaskManager instance containing the node to act on.
        :param kwargs: not used.
        :returns: a dictionary containing the ``unfinished_jobs`` key; this key
                  points to a list of dicts, with each dict representing a Job
                  object.
        :raises: DracOperationError on an error from python-dracclient.
        """
        jobs = drac_job.list_unfinished_jobs(task.node)
        # FIXME(mgould) Do this without calling private methods.
        return {'unfinished_jobs': [job._asdict() for job in jobs]}
Exemple #5
0
def set_boot_device(node, device, persistent=False):
    """Set the boot device for a node.

    Set the boot device to use on next boot of the node.

    :param node: an ironic node object.
    :param device: the boot device, one of
                   :mod:`ironic.common.boot_devices`.
    :param persistent: Boolean value. True if the boot device will
                       persist to all future boots, False if not.
                       Default: False.
    :raises: DracOperationError on an error from python-dracclient.
    """
    client = drac_common.get_drac_client(node)

    # If pending BIOS job or pending non-BIOS job found in job queue,
    # we need to clear that jobs before executing clear_job_queue or
    # known_good_state clean step of management interface.
    # Otherwise, pending BIOS config job can cause creating new config jobs
    # to fail and pending non-BIOS job can execute on reboot the node.
    validate_job_queue = True
    if node.driver_internal_info.get("clean_steps"):
        if node.driver_internal_info.get("clean_steps")[0].get(
                'step') in _CLEAR_JOBS_CLEAN_STEPS:
            unfinished_jobs = drac_job.list_unfinished_jobs(node)
            if unfinished_jobs:
                validate_job_queue = False
                client.delete_jobs(job_ids=[job.id for job in unfinished_jobs])

    if validate_job_queue:
        drac_job.validate_job_queue(node)

    try:
        drac_boot_devices = client.list_boot_devices()

        current_boot_device = _get_boot_device(node, drac_boot_devices)
        # If we are already booting from the right device, do nothing.
        if current_boot_device == {
                'boot_device': device,
                'persistent': persistent
        }:
            LOG.debug('DRAC already set to boot from %s', device)
            return

        persistent_boot_mode = _get_next_persistent_boot_mode(node)

        drac_boot_device = None
        for drac_device in drac_boot_devices[persistent_boot_mode]:
            for id_component in _BOOT_DEVICES_MAP[device]:
                if id_component in drac_device.id:
                    drac_boot_device = drac_device.id
                    break

            if drac_boot_device:
                break

        if drac_boot_device:
            if persistent:
                boot_list = persistent_boot_mode
            else:
                boot_list = _NON_PERSISTENT_BOOT_MODE

            client.change_boot_device_order(boot_list, drac_boot_device)
        else:
            # No DRAC boot device of the type requested by the argument
            # 'device' is present. This is normal for UEFI boot mode,
            # following deployment's writing of the operating system to
            # disk. It can also occur when a server has not been
            # powered on after a new boot device has been installed.
            #
            # If the boot order is flexibly programmable, use that to
            # attempt to detect and boot from a device of the requested
            # type during the next boot. That avoids the need for an
            # extra reboot. Otherwise, this function cannot satisfy the
            # request, because it was called with an invalid device.
            bios_settings = client.list_bios_settings(by_name=True)
            if _is_boot_order_flexibly_programmable(persistent, bios_settings):
                drac_boot_mode = bios_settings['BootMode'].current_value
                if drac_boot_mode not in _DRAC_BOOT_MODES:
                    message = _("DRAC reported unknown boot mode "
                                "'%(drac_boot_mode)s'") % {
                                    'drac_boot_mode': drac_boot_mode
                                }
                    LOG.error(
                        'DRAC driver failed to change boot device order '
                        'for node %(node_uuid)s. Reason: %(message)s.', {
                            'node_uuid': node.uuid,
                            'message': message
                        })
                    raise exception.DracOperationError(error=message)

                flexibly_program_settings = _flexibly_program_boot_order(
                    device, drac_boot_mode)
                client.set_bios_settings(flexibly_program_settings)
            else:
                raise exception.InvalidParameterValue(
                    _("set_boot_device called with invalid device "
                      "'%(device)s' for node %(node_id)s.") % {
                          'device': device,
                          'node_id': node.uuid
                      })

        job_id = client.commit_pending_bios_changes()
        job_entry = client.get_job(job_id)

        timeout = CONF.drac.boot_device_job_status_timeout
        end_time = time.time() + timeout

        LOG.debug(
            'Waiting for BIOS configuration job %(job_id)s '
            'to be scheduled for node %(node)s', {
                'job_id': job_id,
                'node': node.uuid
            })

        while job_entry.status != "Scheduled":
            if time.time() >= end_time:
                raise exception.DracOperationError(
                    error=_('Timed out waiting BIOS configuration for job '
                            '%(job)s to reach Scheduled state.  Job is still '
                            'in %(status)s state.') % {
                                'job': job_id,
                                'status': job_entry.status
                            })
            time.sleep(3)
            job_entry = client.get_job(job_id)

    except drac_exceptions.BaseClientException as exc:
        LOG.error(
            'DRAC driver failed to change boot device order for '
            'node %(node_uuid)s. Reason: %(error)s.', {
                'node_uuid': node.uuid,
                'error': exc
            })
        raise exception.DracOperationError(error=exc)