Merge "Fix persistent information when getting boot device"

This commit is contained in:
Zuul
2018-01-27 10:43:59 +00:00
committed by Gerrit Code Review
3 changed files with 100 additions and 18 deletions

View File

@@ -48,6 +48,10 @@ BOOT_DEVICE_MAP_ILO = {
BOOT_DEVICE_MAP_ILO_REV = {
v: k for k, v in BOOT_DEVICE_MAP_ILO.items()}
ILO_SYSTEM_PATH = "/rest/v1/Systems/1"
ILO_REQUEST_HEADERS = {"Content-Type": "application/json"}
def set_onetime_boot(task):
"""Set onetime boot to server hardware.
@@ -71,16 +75,15 @@ def set_onetime_boot(task):
server_hardware = task.node.driver_info.get('server_hardware_uri')
ilo_client = common.get_ilorest_client(server_hardware)
boot_device = BOOT_DEVICE_MAP_ILO.get(boot_device)
path = '/rest/v1/Systems/1'
body = {
"Boot": {
"BootSourceOverrideTarget": boot_device,
"BootSourceOverrideEnabled": "Once"
}
}
headers = {"Content-Type": "application/json"}
try:
ilo_client.patch(path=path, body=body, headers=headers)
ilo_client.patch(path=ILO_SYSTEM_PATH, body=body,
headers=ILO_REQUEST_HEADERS)
except Exception as e:
msg = (_("Error while trying to set onetime boot on Server Hardware: "
"%(sh_uri)s. Error: %(error)s") %
@@ -88,6 +91,26 @@ def set_onetime_boot(task):
raise exception.OneViewError(error=msg)
def _is_onetime_boot(task):
"""Check onetime boot from server hardware.
Check if the onetime boot option of an OneView server hardware
is set to 'Once' in iLO.
:param task: a task from TaskManager.
:returns: Boolean value. True if onetime boot is 'Once'
False otherwise.
:raises: AttributeError if Boot is None.
"""
server_hardware = task.node.driver_info.get('server_hardware_uri')
ilo_client = common.get_ilorest_client(server_hardware)
response = ilo_client.get(path=ILO_SYSTEM_PATH,
headers=ILO_REQUEST_HEADERS)
boot = response.dict.get('Boot')
onetime_boot = boot.get('BootSourceOverrideEnabled')
return onetime_boot == 'Once'
def set_boot_device(task):
"""Sets the boot device for a node.
@@ -279,7 +302,7 @@ class OneViewManagement(base.ManagementInterface):
boot_device = {
'boot_device': BOOT_DEVICE_MAP_ONEVIEW_REV.get(primary_device),
'persistent': True,
'persistent': not _is_onetime_boot(task)
}
return boot_device

View File

@@ -79,14 +79,12 @@ class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase):
client.server_profiles.get.return_value = server_profile
boot_device_map_ilo = management.BOOT_DEVICE_MAP_ILO
boot_device = boot_device_map_ilo.get(boot_devices.PXE)
path = '/rest/v1/Systems/1'
body = {
"Boot": {
"BootSourceOverrideTarget": boot_device,
"BootSourceOverrideEnabled": "Once"
}
}
headers = {"Content-Type": "application/json"}
with task_manager.acquire(self.context, self.node.uuid) as task:
driver_info = task.node.driver_info
profile_uri = driver_info.get('applied_server_profile_uri')
@@ -100,7 +98,10 @@ class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase):
update.assert_called_once_with(server_profile, profile_uri)
patch = ilo_client.patch
patch.assert_called_once_with(
path=path, body=body, headers=headers)
path=management.ILO_SYSTEM_PATH,
body=body,
headers=management.ILO_REQUEST_HEADERS
)
driver_internal_info = task.node.driver_internal_info
self.assertNotIn('next_boot_device', driver_internal_info)
@@ -155,14 +156,12 @@ class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase):
self, mock_iloclient, mock_get_ov_client):
ilo_client = mock_iloclient()
boot_device = management.BOOT_DEVICE_MAP_ILO.get(boot_devices.DISK)
path = '/rest/v1/Systems/1'
body = {
"Boot": {
"BootSourceOverrideTarget": boot_device,
"BootSourceOverrideEnabled": "Once"
}
}
headers = {"Content-Type": "application/json"}
with task_manager.acquire(self.context, self.node.uuid) as task:
driver_internal_info = task.node.driver_internal_info
next_boot_device = {'boot_device': 'disk', 'persistent': False}
@@ -170,8 +169,49 @@ class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase):
task.node.driver_internal_info = driver_internal_info
management.set_onetime_boot(task)
self.assertTrue(mock_iloclient.called)
ilo_client.patch.assert_called_with(
path=path, body=body, headers=headers)
ilo_client.patch.assert_called_once_with(
path=management.ILO_SYSTEM_PATH,
body=body,
headers=management.ILO_REQUEST_HEADERS
)
@mock.patch.object(common, 'get_ilorest_client')
def test__is_onetime_boot_true(
self, mock_iloclient, mock_get_ov_client):
class RestResponse(object):
@property
def dict(self):
return {'Boot': {'BootSourceOverrideEnabled': "Once"}}
ilo_client = mock_iloclient()
ilo_client.get.return_value = RestResponse()
with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertTrue(management._is_onetime_boot(task))
self.assertTrue(mock_iloclient.called)
ilo_client.get.assert_called_with(
path=management.ILO_SYSTEM_PATH,
headers=management.ILO_REQUEST_HEADERS
)
@mock.patch.object(common, 'get_ilorest_client')
def test__is_onetime_boot_false(
self, mock_iloclient, mock_get_ov_client):
class RestResponse(object):
@property
def dict(self):
return {'Boot': {'BootSourceOverrideEnabled': "Disabled"}}
ilo_client = mock_iloclient()
ilo_client.get.return_value = RestResponse()
with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertFalse(management._is_onetime_boot(task))
self.assertTrue(mock_iloclient.called)
ilo_client.get.assert_called_with(
path=management.ILO_SYSTEM_PATH,
headers=management.ILO_REQUEST_HEADERS
)
class OneViewManagementDriverTestCase(db_base.DbTestCase):
@@ -276,21 +316,26 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase):
)
@mock.patch.object(common, 'get_hponeview_client')
def test_get_boot_device(self, mock_get_ov_client):
client = mock_get_ov_client()
@mock.patch.object(common, 'get_ilorest_client')
def test_get_boot_device(self, mock_iloclient, mock_get_ov_client):
ilo_client = mock_iloclient()
oneview_client = mock_get_ov_client()
device_mapping = management.BOOT_DEVICE_MAP_ONEVIEW.items()
with task_manager.acquire(self.context, self.node.uuid) as task:
# For each known device on OneView, Ironic should return its
# counterpart value
for ironic_device, oneview_device in device_mapping:
profile = {'boot': {'order': [oneview_device]}}
client.server_profiles.get.return_value = profile
oneview_client.server_profiles.get.return_value = profile
expected = {'boot_device': ironic_device, 'persistent': True}
response = self.driver.management.get_boot_device(task)
self.assertEqual(expected, response)
self.assertTrue(client.server_profiles.get.called)
self.assertTrue(oneview_client.server_profiles.get.called)
self.assertTrue(ilo_client.get.called)
def test_get_boot_device_from_next_boot_device(self):
@mock.patch.object(common, 'get_ilorest_client')
def test_get_boot_device_from_next_boot_device(self, mock_iloclient):
ilo_client = mock_iloclient()
with task_manager.acquire(self.context, self.node.uuid) as task:
driver_internal_info = task.node.driver_internal_info
next_boot_device = {'boot_device': boot_devices.DISK,
@@ -303,10 +348,13 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase):
}
response = self.driver.management.get_boot_device(task)
self.assertEqual(expected_response, response)
self.assertFalse(ilo_client.get.called)
@mock.patch.object(common, 'get_hponeview_client')
def test_get_boot_device_fail(self, mock_get_ov_client):
@mock.patch.object(common, 'get_ilorest_client')
def test_get_boot_device_fail(self, mock_iloclient, mock_get_ov_client):
client = mock_get_ov_client()
ilo_client = mock_iloclient()
exc = client_exception.HPOneViewException()
client.server_profiles.get.side_effect = exc
with task_manager.acquire(self.context, self.node.uuid) as task:
@@ -316,14 +364,18 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase):
task
)
self.assertTrue(client.server_profiles.get.called)
self.assertFalse(ilo_client.get.called)
def test_get_boot_device_unknown_device(self):
@mock.patch.object(common, 'get_ilorest_client')
def test_get_boot_device_unknown_device(self, mock_iloclient):
ilo_client = mock_iloclient()
with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertRaises(
exception.InvalidParameterValue,
task.driver.management.get_boot_device,
task
)
self.assertFalse(ilo_client.get.called)
def test_get_sensors_data_not_implemented(self):
with task_manager.acquire(self.context, self.node.uuid) as task:

View File

@@ -0,0 +1,7 @@
---
fixes:
- |
The ``oneview`` management interface now correctly detects whether the
current boot device setting is persistent at the machine's iLO.
Previously it always returned ``True``.
See https://bugs.launchpad.net/ironic/+bug/1706725 for details.