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)
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)
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]}
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]}
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)