Merge "Adds 'UefiTarget' as a boot option"

This commit is contained in:
Jenkins
2017-01-05 09:31:44 +00:00
committed by Gerrit Code Review
3 changed files with 140 additions and 19 deletions

View File

@@ -39,7 +39,7 @@ TODO : Add rest of the API's that exists in RIBCL. """
DEVICE_COMMON_TO_RIS = {'NETWORK': 'Pxe',
'CDROM': 'Cd',
'HDD': 'Hdd',
}
'ISCSI': 'UefiTarget'}
DEVICE_RIS_TO_COMMON = dict(
(v, k) for (k, v) in DEVICE_COMMON_TO_RIS.items())
@@ -1439,7 +1439,8 @@ class RISOperations(operations.IloOperations):
else:
return None
def _update_persistent_boot(self, device_type=[], persistent=False):
def _update_persistent_boot(self, device_type=[], persistent=False,
mac=None):
"""Changes the persistent boot device order in BIOS boot mode for host
Note: It uses first boot device from the device_type and ignores rest.
@@ -1447,13 +1448,13 @@ class RISOperations(operations.IloOperations):
:param device_type: ordered list of boot devices
:param persistent: Boolean flag to indicate if the device to be set as
a persistent boot device
:param mac: intiator mac address, mandotory for iSCSI uefi boot
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedError, if the command is not supported
on the server.
"""
tenure = 'Once'
new_device = device_type[0]
# If it is a standard device, we need to convert in RIS convention
if device_type[0].upper() in DEVICE_COMMON_TO_RIS:
new_device = DEVICE_COMMON_TO_RIS[device_type[0].upper()]
@@ -1461,21 +1462,50 @@ class RISOperations(operations.IloOperations):
if persistent:
tenure = 'Continuous'
systems_uri = "/rest/v1/Systems/1"
# Need to set this option first if device is 'UefiTarget'
if new_device is 'UefiTarget':
if not mac:
msg = ('Mac is needed for iscsi uefi boot')
raise exception.IloInvalidInputError(msg)
headers, bios_uri, bios_settings = self._check_bios_resource()
# Get the Boot resource and Mappings resource.
boot_settings = self._get_bios_boot_resource(bios_settings)
StructuredBootString = None
for boot_setting in boot_settings['BootSources']:
if(mac.upper() in boot_setting['UEFIDevicePath'] and
'iSCSI' in boot_setting['UEFIDevicePath']):
StructuredBootString = boot_setting['StructuredBootString']
break
if not StructuredBootString:
msg = ('MAC provided is Invalid "%s"' % mac)
raise exception.IloInvalidInputError(msg)
new_boot_settings = {}
new_boot_settings['Boot'] = {'UefiTargetBootSourceOverride':
StructuredBootString}
status, headers, response = self._rest_patch(systems_uri, None,
new_boot_settings)
if status >= 300:
msg = self._get_extended_error(response)
raise exception.IloError(msg)
new_boot_settings = {}
new_boot_settings['Boot'] = {'BootSourceOverrideEnabled': tenure,
'BootSourceOverrideTarget': new_device}
systems_uri = "/rest/v1/Systems/1"
status, headers, response = self._rest_patch(systems_uri, None,
new_boot_settings)
if status >= 300:
msg = self._get_extended_error(response)
raise exception.IloError(msg)
def update_persistent_boot(self, device_type=[]):
def update_persistent_boot(self, device_type=[], mac=None):
"""Changes the persistent boot device order for the host
:param device_type: ordered list of boot devices
:param mac: intiator mac address, mandatory for iSCSI uefi boot
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedError, if the command is not supported
on the server.
@@ -1483,20 +1513,22 @@ class RISOperations(operations.IloOperations):
# Check if the input is valid
for item in device_type:
if item.upper() not in DEVICE_COMMON_TO_RIS:
raise exception.IloInvalidInputError(
"Invalid input. Valid devices: NETWORK, HDD or CDROM.")
raise exception.IloInvalidInputError("Invalid input. Valid "
"devices: NETWORK, HDD,"
" ISCSI or CDROM.")
self._update_persistent_boot(device_type, persistent=True)
self._update_persistent_boot(device_type, persistent=True, mac=mac)
def set_one_time_boot(self, device):
def set_one_time_boot(self, device, mac=None):
"""Configures a single boot from a specific device.
:param device: Device to be set as a one time boot device
:param mac: intiator mac address, optional parameter
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedError, if the command is not supported
on the server.
"""
self._update_persistent_boot([device], persistent=False)
self._update_persistent_boot([device], persistent=False, mac=mac)
def get_one_time_boot(self):
"""Retrieves the current setting for the one time boot.

View File

@@ -1426,6 +1426,15 @@ GET_BIOS_BOOT = """
"UEFIDevicePath": "PciRoot(0x0)/Pci(0x1C,0x4)/Pci(0x0,0x0)/MAC\
(C4346BB7EF30,0x0)/IPv4(0.0.0.0)"
},
{
"BootString": "Embedded LOM 1 Port 1 : HP Ethernet 1Gb 2-port\
361i Adapter - NIC (iSCSI IPv4) ",
"CorrelatableID": "PciRoot(0x0)/Pci(0x2,0x3)/Pci(0x0,0x0)",
"StructuredBootString": "NIC.LOM.1.1.iSCSI",
"UEFIDevicePath": "PciRoot(0x0)/Pci(0x2,0x3)/Pci(0x0,0x0)/MAC\
(C4346BB7EF30,0x1)/IPv4(0.0.0.0)/iSCSI(iqn.2016-07.org.de\
:storage,0x1,0x0,None,None,None,TCP)"
},
{
"BootString": "Embedded LOM 1 Port 1 : HP Ethernet 1Gb 4-port\
331i Adapter - NIC (PXE IPv6) ",
@@ -1479,6 +1488,7 @@ GET_BIOS_BOOT = """
"PersistentBootConfigOrder": [
"HD.Slot.1.1",
"HD.Slot.1.2",
"NIC.LOM.1.1.iSCSI",
"NIC.LOM.1.1.IPv4",
"NIC.LOM.1.1.IPv6",
"Generic.USB.1.1",
@@ -3490,6 +3500,7 @@ UEFI_BOOT_SOURCES_ERR = '''
UEFI_PERS_BOOT_DEVICES = ["HD.Slot.1.1",
"HD.Slot.1.2",
"NIC.LOM.1.1.iSCSI",
"NIC.LOM.1.1.IPv4",
"NIC.LOM.1.1.IPv6",
"Generic.USB.1.1",
@@ -3633,6 +3644,16 @@ UEFI_BootSources = '''
"UEFIDevicePath": "PciRoot(0x0)/Pci(0x1C,0x4)/Pci(0x0,0x0)/MAC\
(C4346BB7EF30,0x0)/IPv4(0.0.0.0)"
},
{
"BootString": "Embedded LOM 1 Port 1 : HP Ethernet 1Gb 2-port\
361i Adapter - NIC (iSCSI IPv4) ",
"CorrelatableID": "PciRoot(0x0)/Pci(0x2,0x3)/Pci(0x0,0x0)",
"StructuredBootString": "NIC.LOM.1.1.iSCSI",
"UEFIDevicePath": "PciRoot(0x0)/Pci(0x2,0x3)/Pci(0x0,0x0)/MAC\
(C4346BB7EF30,0x1)/IPv4(0.0.0.0)/iSCSI(iqn.2016-07.org.de\
:storage,0x1,0x0,None,None,None,TCP)"
},
{
"BootString": "Embedded LOM 1 Port 1 : HP Ethernet 1Gb 4-port\
331i Adapter - NIC (PXE IPv6) ",

View File

@@ -747,8 +747,14 @@ class IloRisTestCase(testtools.TestCase):
@mock.patch.object(ris.RISOperations, '_update_persistent_boot')
def test_set_one_time_boot_cdrom(self, update_persistent_boot_mock):
self.client.set_one_time_boot('cdrom')
update_persistent_boot_mock.assert_called_once_with(['cdrom'],
persistent=False)
update_persistent_boot_mock.assert_called_once_with(
['cdrom'], persistent=False, mac=None)
@mock.patch.object(ris.RISOperations, '_update_persistent_boot')
def test_set_one_time_boot_iscsi(self, update_persistent_boot_mock):
self.client.set_one_time_boot('ISCSI', '9cb654797870')
update_persistent_boot_mock.assert_called_once_with(
['ISCSI'], persistent=False, mac='9cb654797870')
@mock.patch.object(ris.RISOperations, '_get_host_details')
def test_get_persistent_boot_device_cdrom(self, get_host_details_mock):
@@ -862,8 +868,14 @@ class IloRisTestCase(testtools.TestCase):
@mock.patch.object(ris.RISOperations, '_update_persistent_boot')
def test_update_persistent_boot_cdrom(self, update_persistent_boot_mock):
self.client.update_persistent_boot(['cdrom'])
update_persistent_boot_mock.assert_called_once_with(['cdrom'],
persistent=True)
update_persistent_boot_mock.assert_called_once_with(
['cdrom'], mac=None, persistent=True)
@mock.patch.object(ris.RISOperations, '_update_persistent_boot')
def test_update_persistent_boot_iscsi(self, update_persistent_boot_mock):
self.client.update_persistent_boot(['ISCSI'], '9cb654797870')
update_persistent_boot_mock.assert_called_once_with(
['ISCSI'], mac='9cb654797870', persistent=True)
@mock.patch.object(ris.RISOperations, '_update_persistent_boot')
def test_update_persistent_boot_exc(self, update_persistent_boot_mock):
@@ -1614,7 +1626,8 @@ class TestRISOperationsPrivateMethods(testtools.TestCase):
'BootSourceOverrideTarget': 'Cd'}
rest_patch_mock.return_value = (200, ris_outputs.GET_HEADERS,
ris_outputs.REST_POST_RESPONSE)
self.client._update_persistent_boot(['cdrom'], persistent=False)
self.client._update_persistent_boot(['cdrom'], mac=None,
persistent=False)
rest_patch_mock.assert_called_once_with(systems_uri, None,
new_boot_settings)
@@ -1626,7 +1639,8 @@ class TestRISOperationsPrivateMethods(testtools.TestCase):
'BootSourceOverrideTarget': 'Cd'}
rest_patch_mock.return_value = (200, ris_outputs.GET_HEADERS,
ris_outputs.REST_POST_RESPONSE)
self.client._update_persistent_boot(['cdrom'], persistent=True)
self.client._update_persistent_boot(['cdrom'], mac=None,
persistent=True)
rest_patch_mock.assert_called_once_with(systems_uri, None,
new_boot_settings)
@@ -1638,10 +1652,64 @@ class TestRISOperationsPrivateMethods(testtools.TestCase):
'BootSourceOverrideTarget': 'UefiShell'}
rest_patch_mock.return_value = (200, ris_outputs.GET_HEADERS,
ris_outputs.REST_POST_RESPONSE)
self.client._update_persistent_boot(['UefiShell'], persistent=True)
self.client._update_persistent_boot(['UefiShell'], mac=None,
persistent=True)
rest_patch_mock.assert_called_once_with(systems_uri, None,
new_boot_settings)
@mock.patch.object(ris.RISOperations, '_get_bios_boot_resource')
@mock.patch.object(ris.RISOperations, '_check_bios_resource')
@mock.patch.object(ris.RISOperations, '_rest_patch')
def test__update_persistent_boot_for_iscsi_mac_valid(self, rest_patch_mock,
check_bios_mock,
boot_mock):
bios_uri = '/rest/v1/systems/1/bios'
bios_settings = json.loads(ris_outputs.GET_BIOS_SETTINGS)
check_bios_mock.return_value = (ris_outputs.GET_HEADERS,
bios_uri, bios_settings)
boot_settings = json.loads(ris_outputs.GET_BIOS_BOOT)
boot_mock.return_value = boot_settings
systems_uri = '/rest/v1/Systems/1'
new1_boot_settings = {}
new1_boot_settings['Boot'] = {'UefiTargetBootSourceOverride':
u'NIC.LOM.1.1.iSCSI'}
new2_boot_settings = {}
new2_boot_settings['Boot'] = {'BootSourceOverrideEnabled':
'Continuous', 'BootSourceOverrideTarget':
'UefiTarget'}
rest_patch_mock.return_value = (200, ris_outputs.GET_HEADERS,
ris_outputs.REST_POST_RESPONSE)
calls = [mock.call(systems_uri, None, new1_boot_settings),
mock.call(systems_uri, None, new2_boot_settings)]
self.client._update_persistent_boot(['ISCSI'], mac='C4346BB7EF30',
persistent=True)
check_bios_mock.assert_called_once_with()
boot_mock.assert_called_once_with(bios_settings)
rest_patch_mock.assert_has_calls(calls)
@mock.patch.object(ris.RISOperations, '_get_bios_boot_resource')
@mock.patch.object(ris.RISOperations, '_check_bios_resource')
def test__update_persistent_boot_for_iscsi_mac_invalid(self,
check_bios_mock,
boot_mock):
bios_uri = '/rest/v1/systems/1/bios'
bios_settings = json.loads(ris_outputs.GET_BIOS_SETTINGS)
check_bios_mock.return_value = (ris_outputs.GET_HEADERS,
bios_uri, bios_settings)
boot_settings = json.loads(ris_outputs.GET_BIOS_BOOT)
boot_mock.return_value = boot_settings
self.assertRaises(exception.IloInvalidInputError,
self.client._update_persistent_boot, ['ISCSI'],
mac='234343553', persistent=True)
check_bios_mock.assert_called_once_with()
boot_mock.assert_called_once_with(bios_settings)
def test__update_persistent_boot_for_iscsi_mac_none(self):
self.assertRaises(exception.IloInvalidInputError,
self.client._update_persistent_boot, ['ISCSI'],
mac=None, persistent=True)
@mock.patch.object(ris.RISOperations, '_rest_patch')
def test__update_persistent_boot_fail(self, rest_patch_mock):
systems_uri = "/rest/v1/Systems/1"
@@ -1652,7 +1720,7 @@ class TestRISOperationsPrivateMethods(testtools.TestCase):
ris_outputs.REST_POST_RESPONSE)
self.assertRaises(exception.IloError,
self.client._update_persistent_boot,
['FakeDevice'], persistent=True)
['FakeDevice'], mac=None, persistent=True)
rest_patch_mock.assert_called_once_with(systems_uri, None,
new_boot_settings)