DRAC: Fix a bug for clear_job_queue clean step with non-BIOS pending job
If we create pending non-bios config job(E.g create/delete virtual disk) with "At next reboot" option and execute "clear_job_queue" clean step, then that job gets deleted after job execution instead of getting deleted before job execution. Change-Id: Ibeae18798a25e33fa070f1120ce0cc0981f66850 Story: #2006580 Task: #36695
This commit is contained in:
parent
9fa39045da
commit
4be3fcef26
@ -81,8 +81,8 @@ _NON_PERSISTENT_BOOT_MODE = 'OneTime'
|
||||
# Clear job id's constant
|
||||
_CLEAR_JOB_IDS = 'JID_CLEARALL_FORCE'
|
||||
|
||||
# BIOS pending job constant
|
||||
_BIOS_JOB_NAME = 'BIOS.Setup.1-1'
|
||||
# Clean steps constant
|
||||
_CLEAR_JOBS_CLEAN_STEPS = ['clear_job_queue', 'known_good_state']
|
||||
|
||||
|
||||
def _get_boot_device(node, drac_boot_devices=None):
|
||||
@ -190,19 +190,24 @@ def set_boot_device(node, device, persistent=False):
|
||||
Default: False.
|
||||
:raises: DracOperationError on an error from python-dracclient.
|
||||
"""
|
||||
|
||||
client = drac_common.get_drac_client(node)
|
||||
|
||||
# If pending BIOS job found in job queue, we need to clear that job
|
||||
# before executing cleaning step of management interface.
|
||||
# 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.
|
||||
unfinished_jobs = drac_job.list_unfinished_jobs(node)
|
||||
if unfinished_jobs:
|
||||
unfinished_bios_jobs = [job.id for job in unfinished_jobs if
|
||||
_BIOS_JOB_NAME in job.name]
|
||||
if unfinished_bios_jobs:
|
||||
client.delete_jobs(job_ids=unfinished_bios_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()
|
||||
|
@ -250,7 +250,10 @@ class DracManagementInternalMethodsTestCase(test_utils.BaseDracTest):
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_job, 'list_unfinished_jobs', spec_set=True,
|
||||
autospec=True)
|
||||
def test_set_boot_device(self, mock_list_unfinished_jobs,
|
||||
@mock.patch.object(drac_job, 'validate_job_queue', spec_set=True,
|
||||
autospec=True)
|
||||
def test_set_boot_device(self, mock_validate_job_queue,
|
||||
mock_list_unfinished_jobs,
|
||||
mock__get_boot_device,
|
||||
mock__get_next_persistent_boot_mode,
|
||||
mock_get_drac_client):
|
||||
@ -267,11 +270,14 @@ class DracManagementInternalMethodsTestCase(test_utils.BaseDracTest):
|
||||
'persistent': True}
|
||||
mock__get_boot_device.return_value = boot_device
|
||||
mock__get_next_persistent_boot_mode.return_value = 'IPL'
|
||||
self.node.driver_internal_info['clean_steps'] = []
|
||||
|
||||
boot_device = drac_mgmt.set_boot_device(
|
||||
self.node, ironic.common.boot_devices.PXE, persistent=False)
|
||||
|
||||
mock_list_unfinished_jobs.assert_called_once_with(self.node)
|
||||
self.assertEqual(0, mock_list_unfinished_jobs.call_count)
|
||||
self.assertEqual(0, mock_client.delete_jobs.call_count)
|
||||
mock_validate_job_queue.assert_called_once_with(self.node)
|
||||
mock_client.change_boot_device_order.assert_called_once_with(
|
||||
'OneTime', 'BIOS.Setup.1-1#BootSeq#NIC.Embedded.1-1-1')
|
||||
self.assertEqual(0, mock_client.set_bios_settings.call_count)
|
||||
@ -495,15 +501,18 @@ class DracManagementInternalMethodsTestCase(test_utils.BaseDracTest):
|
||||
self.assertEqual(0, mock_client.set_bios_settings.call_count)
|
||||
self.assertEqual(0, mock_client.commit_pending_bios_changes.call_count)
|
||||
|
||||
@mock.patch.object(drac_job, 'validate_job_queue', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_job, 'list_unfinished_jobs', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_mgmt, '_get_boot_device', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_mgmt, '_get_next_persistent_boot_mode',
|
||||
spec_set=True, autospec=True)
|
||||
def test_set_boot_device_with_list_unfinished_jobs(
|
||||
def test_set_boot_device_with_list_unfinished_jobs_without_clean_step(
|
||||
self, mock__get_next_persistent_boot_mode, mock__get_boot_device,
|
||||
mock_list_unfinished_jobs, mock_get_drac_client):
|
||||
mock_list_unfinished_jobs, mock_validate_job_queue,
|
||||
mock_get_drac_client):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
|
||||
@ -525,21 +534,27 @@ class DracManagementInternalMethodsTestCase(test_utils.BaseDracTest):
|
||||
mock__get_boot_device.return_value = boot_device
|
||||
mock__get_next_persistent_boot_mode.return_value = 'IPL'
|
||||
|
||||
self.node.driver_internal_info['clean_steps'] = []
|
||||
|
||||
drac_mgmt.set_boot_device(self.node, ironic.common.boot_devices.DISK,
|
||||
persistent=True)
|
||||
mock_list_unfinished_jobs.assert_called_once_with(self.node)
|
||||
mock_client.delete_jobs.assert_called_once_with(
|
||||
job_ids=['JID_602553293345'])
|
||||
self.assertEqual(0, mock_list_unfinished_jobs.call_count)
|
||||
self.assertEqual(0, mock_client.delete_jobs.call_count)
|
||||
|
||||
mock_validate_job_queue.assert_called_once_with(self.node)
|
||||
|
||||
@mock.patch.object(drac_job, 'validate_job_queue', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_job, 'list_unfinished_jobs', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_mgmt, '_get_boot_device', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_mgmt, '_get_next_persistent_boot_mode',
|
||||
spec_set=True, autospec=True)
|
||||
def test_set_boot_device_with_multiple_unfinished_jobs(
|
||||
def test_set_boot_device_with_multiple_unfinished_jobs_without_clean_step(
|
||||
self, mock__get_next_persistent_boot_mode, mock__get_boot_device,
|
||||
mock_list_unfinished_jobs, mock_get_drac_client):
|
||||
mock_list_unfinished_jobs, mock_validate_job_queue,
|
||||
mock_get_drac_client):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
|
||||
@ -571,11 +586,115 @@ class DracManagementInternalMethodsTestCase(test_utils.BaseDracTest):
|
||||
mock__get_boot_device.return_value = boot_device
|
||||
mock__get_next_persistent_boot_mode.return_value = 'IPL'
|
||||
|
||||
self.node.driver_internal_info['clean_steps'] = []
|
||||
drac_mgmt.set_boot_device(self.node, ironic.common.boot_devices.DISK,
|
||||
persistent=True)
|
||||
self.assertEqual(0, mock_list_unfinished_jobs.call_count)
|
||||
self.assertEqual(0, mock_client.delete_jobs.call_count)
|
||||
|
||||
mock_validate_job_queue.assert_called_once_with(self.node)
|
||||
|
||||
@mock.patch.object(drac_mgmt, '_get_next_persistent_boot_mode',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(drac_mgmt, '_get_boot_device', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_job, 'list_unfinished_jobs', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_job, 'validate_job_queue', spec_set=True,
|
||||
autospec=True)
|
||||
def test_set_boot_device_with_list_unfinished_jobs_with_clean_step(
|
||||
self, mock_validate_job_queue,
|
||||
mock_list_unfinished_jobs,
|
||||
mock__get_boot_device,
|
||||
mock__get_next_persistent_boot_mode,
|
||||
mock_get_drac_client):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
mock_client.list_boot_devices.return_value = self.boot_devices['IPL']
|
||||
|
||||
boot_device = {'boot_device': ironic.common.boot_devices.DISK,
|
||||
'persistent': True}
|
||||
mock__get_boot_device.return_value = boot_device
|
||||
mock__get_next_persistent_boot_mode.return_value = 'IPL'
|
||||
|
||||
mock_job = mock.Mock()
|
||||
mock_job.status = "Scheduled"
|
||||
mock_client.get_job.return_value = mock_job
|
||||
|
||||
bios_job_dict = {
|
||||
'id': 'JID_602553293345',
|
||||
'name': 'ConfigBIOS:BIOS.Setup.1-1',
|
||||
'start_time': 'TIME_NOW',
|
||||
'until_time': 'TIME_NA',
|
||||
'message': 'Task successfully scheduled.',
|
||||
'status': 'Scheduled',
|
||||
'percent_complete': 0}
|
||||
bios_job = test_utils.make_job(bios_job_dict)
|
||||
mock_list_unfinished_jobs.return_value = [bios_job]
|
||||
|
||||
self.node.driver_internal_info['clean_steps'] = [{
|
||||
u'interface': u'management', u'step': u'clear_job_queue'}]
|
||||
boot_device = drac_mgmt.set_boot_device(
|
||||
self.node, ironic.common.boot_devices.PXE, persistent=False)
|
||||
mock_list_unfinished_jobs.assert_called_once_with(self.node)
|
||||
mock_client.delete_jobs.assert_called_once_with(
|
||||
job_ids=['JID_602553293345'])
|
||||
|
||||
self.assertEqual(0, mock_validate_job_queue.call_count)
|
||||
|
||||
@mock.patch.object(drac_job, 'validate_job_queue', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_job, 'list_unfinished_jobs', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_mgmt, '_get_boot_device', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_mgmt, '_get_next_persistent_boot_mode',
|
||||
spec_set=True, autospec=True)
|
||||
def test_set_boot_device_with_multiple_unfinished_jobs_with_clean_step(
|
||||
self, mock__get_next_persistent_boot_mode, mock__get_boot_device,
|
||||
mock_list_unfinished_jobs, mock_validate_job_queue,
|
||||
mock_get_drac_client):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
|
||||
job_dict = {
|
||||
'id': 'JID_602553293345',
|
||||
'name': 'Config:RAID:RAID.Integrated.1-1',
|
||||
'start_time': 'TIME_NOW',
|
||||
'until_time': 'TIME_NA',
|
||||
'message': 'Task successfully scheduled.',
|
||||
'status': 'Scheduled',
|
||||
'percent_complete': 0}
|
||||
job = test_utils.make_job(job_dict)
|
||||
|
||||
bios_job_dict = {
|
||||
'id': 'JID_602553293346',
|
||||
'name': 'ConfigBIOS:BIOS.Setup.1-1',
|
||||
'start_time': 'TIME_NOW',
|
||||
'until_time': 'TIME_NA',
|
||||
'message': 'Task successfully scheduled.',
|
||||
'status': 'Scheduled',
|
||||
'percent_complete': 0}
|
||||
bios_job = test_utils.make_job(bios_job_dict)
|
||||
|
||||
mock_list_unfinished_jobs.return_value = [job, bios_job]
|
||||
mock_client.list_boot_devices.return_value = self.boot_devices['IPL']
|
||||
boot_device = {'boot_device': ironic.common.boot_devices.DISK,
|
||||
'persistent': True}
|
||||
|
||||
mock__get_boot_device.return_value = boot_device
|
||||
mock__get_next_persistent_boot_mode.return_value = 'IPL'
|
||||
|
||||
self.node.driver_internal_info['clean_steps'] = [{
|
||||
u'interface': u'management', u'step': u'clear_job_queue'}]
|
||||
|
||||
drac_mgmt.set_boot_device(self.node, ironic.common.boot_devices.DISK,
|
||||
persistent=True)
|
||||
mock_list_unfinished_jobs.assert_called_once_with(self.node)
|
||||
mock_client.delete_jobs.assert_called_once_with(
|
||||
job_ids=['JID_602553293346'])
|
||||
job_ids=['JID_602553293345', 'JID_602553293346'])
|
||||
|
||||
self.assertEqual(0, mock_validate_job_queue.call_count)
|
||||
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Fixes a bug in the ``idrac`` hardware type where executing
|
||||
the ``clear_job_queue`` clean step, pending non-BIOS config jobs
|
||||
(E.g. create/delete virtual disk) were not being deleted before
|
||||
job execution.
|
||||
|
||||
See bug `2006580 https://storyboard.openstack.org/#!/story/2006580`
|
||||
for details
|
Loading…
x
Reference in New Issue
Block a user