Merge "Adds 'UefiTarget' as a boot option"
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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) ",
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user